feat: daemon support, general improvement, and preparation for Windows release

This commit is contained in:
zhom
2026-02-01 20:55:09 +04:00
parent e9f4edd120
commit 4a59459eb2
58 changed files with 9763 additions and 296 deletions
+14 -1
View File
@@ -295,13 +295,26 @@ export function useBrowserDownload() {
eta: etaText,
},
{
onCancel: () => dismissToast(toastId),
onCancel: () => {
invoke("cancel_download", {
browserStr: progress.browser,
version: progress.version,
}).catch((err) =>
console.error("Failed to cancel download:", err),
);
dismissToast(toastId);
},
},
);
} else if (progress.stage === "extracting") {
showDownloadToast(browserName, progress.version, "extracting");
} else if (progress.stage === "verifying") {
showDownloadToast(browserName, progress.version, "verifying");
} else if (progress.stage === "cancelled") {
dismissToast(
`download-${browserName.toLowerCase()}-${progress.version}`,
);
setDownloadProgress(null);
} else if (progress.stage === "completed") {
// On completion, refresh the downloaded versions for this browser and also refresh camoufox,
// since the Create dialog implicitly uses camoufox on the anti-detect tab
+81
View File
@@ -0,0 +1,81 @@
import { invoke } from "@tauri-apps/api/core";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import {
getLanguageWithFallback,
SUPPORTED_LANGUAGES,
type SupportedLanguage,
} from "@/i18n";
interface AppSettings {
language?: string | null;
[key: string]: unknown;
}
export function useLanguage() {
const { i18n } = useTranslation();
const [isLoading, setIsLoading] = useState(true);
const [currentLanguage, setCurrentLanguage] = useState<string>("en");
const loadLanguage = useCallback(async () => {
try {
const settings = await invoke<AppSettings>("get_app_settings");
let language = settings.language;
if (!language) {
const systemLanguage = await invoke<string>("get_system_language");
language = getLanguageWithFallback(systemLanguage);
}
if (
language &&
SUPPORTED_LANGUAGES.some((lang) => lang.code === language)
) {
await i18n.changeLanguage(language);
setCurrentLanguage(language);
}
} catch (error) {
console.error("Failed to load language setting:", error);
} finally {
setIsLoading(false);
}
}, [i18n]);
const changeLanguage = useCallback(
async (language: SupportedLanguage | null) => {
try {
const settings = await invoke<AppSettings>("get_app_settings");
const updatedSettings = {
...settings,
language,
};
await invoke("save_app_settings", { settings: updatedSettings });
if (language) {
await i18n.changeLanguage(language);
setCurrentLanguage(language);
} else {
const systemLanguage = await invoke<string>("get_system_language");
const fallbackLanguage = getLanguageWithFallback(systemLanguage);
await i18n.changeLanguage(fallbackLanguage);
setCurrentLanguage(fallbackLanguage);
}
} catch (error) {
console.error("Failed to change language:", error);
throw error;
}
},
[i18n],
);
useEffect(() => {
void loadLanguage();
}, [loadLanguage]);
return {
currentLanguage,
changeLanguage,
isLoading,
supportedLanguages: SUPPORTED_LANGUAGES,
};
}
+10 -2
View File
@@ -13,8 +13,16 @@ export function useWayfernTerms(): UseWayfernTermsReturn {
const checkTerms = useCallback(async () => {
try {
const accepted = await invoke<boolean>("check_wayfern_terms_accepted");
setTermsAccepted(accepted);
const [accepted, downloaded] = await Promise.all([
invoke<boolean>("check_wayfern_terms_accepted"),
invoke<boolean>("check_wayfern_downloaded"),
]);
// Only require terms when Wayfern is downloaded and terms not accepted
if (!downloaded) {
setTermsAccepted(true);
} else {
setTermsAccepted(accepted);
}
} catch (error) {
console.error("Failed to check terms acceptance:", error);
setTermsAccepted(false);