mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-06-06 23:13:58 +02:00
refactor: sync
This commit is contained in:
+13
-1
@@ -23,6 +23,7 @@ import { ProfileSyncDialog } from "@/components/profile-sync-dialog";
|
||||
import { ProxyAssignmentDialog } from "@/components/proxy-assignment-dialog";
|
||||
import { ProxyManagementDialog } from "@/components/proxy-management-dialog";
|
||||
import { SettingsDialog } from "@/components/settings-dialog";
|
||||
import { SyncAllDialog } from "@/components/sync-all-dialog";
|
||||
import { SyncConfigDialog } from "@/components/sync-config-dialog";
|
||||
import { WayfernTermsDialog } from "@/components/wayfern-terms-dialog";
|
||||
import { useAppUpdateNotifications } from "@/hooks/use-app-update-notifications";
|
||||
@@ -143,6 +144,7 @@ export default function Home() {
|
||||
useState(false);
|
||||
const [isBulkDeleting, setIsBulkDeleting] = useState(false);
|
||||
const [syncConfigDialogOpen, setSyncConfigDialogOpen] = useState(false);
|
||||
const [syncAllDialogOpen, setSyncAllDialogOpen] = useState(false);
|
||||
const [profileSyncDialogOpen, setProfileSyncDialogOpen] = useState(false);
|
||||
const [currentProfileForSync, setCurrentProfileForSync] =
|
||||
useState<BrowserProfile | null>(null);
|
||||
@@ -1118,7 +1120,17 @@ export default function Home() {
|
||||
|
||||
<SyncConfigDialog
|
||||
isOpen={syncConfigDialogOpen}
|
||||
onClose={() => setSyncConfigDialogOpen(false)}
|
||||
onClose={(loginOccurred) => {
|
||||
setSyncConfigDialogOpen(false);
|
||||
if (loginOccurred) {
|
||||
setSyncAllDialogOpen(true);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<SyncAllDialog
|
||||
isOpen={syncAllDialogOpen}
|
||||
onClose={() => setSyncAllDialogOpen(false)}
|
||||
/>
|
||||
|
||||
<ProfileSyncDialog
|
||||
|
||||
@@ -555,9 +555,7 @@ export function CreateProfileDialog({
|
||||
})()}
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-medium">
|
||||
Chromium (Wayfern)
|
||||
</div>
|
||||
<div className="font-medium">Wayfern</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
Anti-Detect Browser
|
||||
</div>
|
||||
@@ -580,9 +578,7 @@ export function CreateProfileDialog({
|
||||
})()}
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="font-medium">
|
||||
Firefox (Camoufox)
|
||||
</div>
|
||||
<div className="font-medium">Camoufox</div>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
Anti-Detect Browser
|
||||
</div>
|
||||
|
||||
@@ -1595,7 +1595,10 @@ export function ProfilesDataTable({
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Created on {osName} - view only</p>
|
||||
<p>
|
||||
This profile was created on {osName} and is not supported on
|
||||
this system
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
@@ -1608,7 +1611,12 @@ export function ProfilesDataTable({
|
||||
: "another OS";
|
||||
return (
|
||||
<NonHoverableTooltip
|
||||
content={<p>Created on {osName} - view only</p>}
|
||||
content={
|
||||
<p>
|
||||
This profile was created on {osName} and is not supported on
|
||||
this system
|
||||
</p>
|
||||
}
|
||||
sideOffset={4}
|
||||
horizontalOffset={8}
|
||||
>
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
"use client";
|
||||
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { LoadingButton } from "@/components/loading-button";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { showErrorToast, showSuccessToast } from "@/lib/toast-utils";
|
||||
|
||||
interface UnsyncedEntityCounts {
|
||||
proxies: number;
|
||||
groups: number;
|
||||
vpns: number;
|
||||
}
|
||||
|
||||
interface SyncAllDialogProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function SyncAllDialog({ isOpen, onClose }: SyncAllDialogProps) {
|
||||
const { t } = useTranslation();
|
||||
const [counts, setCounts] = useState<UnsyncedEntityCounts | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isEnabling, setIsEnabling] = useState(false);
|
||||
|
||||
const loadCounts = useCallback(async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const result = await invoke<UnsyncedEntityCounts>(
|
||||
"get_unsynced_entity_counts",
|
||||
);
|
||||
setCounts(result);
|
||||
} catch (error) {
|
||||
console.error("Failed to get unsynced entity counts:", error);
|
||||
setCounts(null);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
void loadCounts();
|
||||
}
|
||||
}, [isOpen, loadCounts]);
|
||||
|
||||
const handleEnableAll = useCallback(async () => {
|
||||
setIsEnabling(true);
|
||||
try {
|
||||
await invoke("enable_sync_for_all_entities");
|
||||
showSuccessToast(t("syncAll.success"));
|
||||
onClose();
|
||||
} catch (error) {
|
||||
console.error("Failed to enable sync for all entities:", error);
|
||||
showErrorToast(String(error));
|
||||
} finally {
|
||||
setIsEnabling(false);
|
||||
}
|
||||
}, [onClose, t]);
|
||||
|
||||
const totalCount =
|
||||
(counts?.proxies ?? 0) + (counts?.groups ?? 0) + (counts?.vpns ?? 0);
|
||||
|
||||
// Don't show if there's nothing to sync
|
||||
if (!isLoading && totalCount === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parts: string[] = [];
|
||||
if (counts?.proxies && counts.proxies > 0) {
|
||||
parts.push(t("syncAll.proxies", { count: counts.proxies }));
|
||||
}
|
||||
if (counts?.groups && counts.groups > 0) {
|
||||
parts.push(t("syncAll.groups", { count: counts.groups }));
|
||||
}
|
||||
if (counts?.vpns && counts.vpns > 0) {
|
||||
parts.push(t("syncAll.vpns", { count: counts.vpns }));
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen && totalCount > 0} onOpenChange={onClose}>
|
||||
<DialogContent className="max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t("syncAll.title")}</DialogTitle>
|
||||
<DialogDescription>{t("syncAll.description")}</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
{isLoading ? (
|
||||
<div className="flex justify-center py-8">
|
||||
<div className="w-6 h-6 rounded-full border-2 border-current animate-spin border-t-transparent" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="py-4">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{t("syncAll.itemsList", { items: parts.join(", ") })}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<DialogFooter className="flex gap-2">
|
||||
<Button variant="outline" onClick={onClose} disabled={isEnabling}>
|
||||
{t("syncAll.skip")}
|
||||
</Button>
|
||||
<LoadingButton
|
||||
onClick={handleEnableAll}
|
||||
isLoading={isEnabling}
|
||||
disabled={isLoading}
|
||||
>
|
||||
{t("syncAll.enableAll")}
|
||||
</LoadingButton>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import type { SyncSettings } from "@/types";
|
||||
|
||||
interface SyncConfigDialogProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
onClose: (loginOccurred?: boolean) => void;
|
||||
}
|
||||
|
||||
export function SyncConfigDialog({ isOpen, onClose }: SyncConfigDialogProps) {
|
||||
@@ -179,8 +179,8 @@ export function SyncConfigDialog({ isOpen, onClose }: SyncConfigDialogProps) {
|
||||
} catch (e) {
|
||||
console.error("Failed to restart sync service:", e);
|
||||
}
|
||||
// Auto-close dialog after successful login
|
||||
onClose();
|
||||
// Auto-close dialog after successful login, signal that login occurred
|
||||
onClose(true);
|
||||
} catch (error) {
|
||||
console.error("OTP verification failed:", error);
|
||||
showErrorToast(String(error));
|
||||
|
||||
@@ -273,6 +273,17 @@ export function useBrowserDownload() {
|
||||
const progress = event.payload;
|
||||
setDownloadProgress(progress);
|
||||
|
||||
if (
|
||||
progress.stage === "downloading" ||
|
||||
progress.stage === "extracting" ||
|
||||
progress.stage === "verifying"
|
||||
) {
|
||||
setDownloadingBrowsers((prev) => {
|
||||
if (prev.has(progress.browser)) return prev;
|
||||
return new Set(prev).add(progress.browser);
|
||||
});
|
||||
}
|
||||
|
||||
const browserName = getBrowserDisplayName(progress.browser);
|
||||
|
||||
if (progress.stage === "downloading") {
|
||||
@@ -311,11 +322,21 @@ export function useBrowserDownload() {
|
||||
} else if (progress.stage === "verifying") {
|
||||
showDownloadToast(browserName, progress.version, "verifying");
|
||||
} else if (progress.stage === "cancelled") {
|
||||
setDownloadingBrowsers((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.delete(progress.browser);
|
||||
return next;
|
||||
});
|
||||
dismissToast(
|
||||
`download-${browserName.toLowerCase()}-${progress.version}`,
|
||||
);
|
||||
setDownloadProgress(null);
|
||||
} else if (progress.stage === "completed") {
|
||||
setDownloadingBrowsers((prev) => {
|
||||
const next = new Set(prev);
|
||||
next.delete(progress.browser);
|
||||
return next;
|
||||
});
|
||||
// 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
|
||||
try {
|
||||
|
||||
@@ -174,7 +174,7 @@ export function useBrowserState(
|
||||
|
||||
if (isCrossOsProfile(profile) && profile.host_os) {
|
||||
const osName = getOSDisplayName(profile.host_os);
|
||||
return `Created on ${osName}. Can only be launched on ${osName}.`;
|
||||
return `This profile was created on ${osName} and is not supported on this system`;
|
||||
}
|
||||
|
||||
const isRunning = runningProfiles.has(profile.id);
|
||||
|
||||
@@ -166,8 +166,8 @@
|
||||
"antiDetect": {
|
||||
"title": "Anti-Detect Browser",
|
||||
"description": "Choose a browser with anti-detection capabilities",
|
||||
"chromium": "Chromium (Wayfern)",
|
||||
"firefox": "Firefox (Camoufox)",
|
||||
"chromium": "Wayfern",
|
||||
"firefox": "Camoufox",
|
||||
"badge": "Anti-Detect Browser"
|
||||
},
|
||||
"regular": {
|
||||
@@ -483,11 +483,25 @@
|
||||
"wayfern": "Wayfern"
|
||||
},
|
||||
"fingerprint": {
|
||||
"crossOsWarning": "Spoofing a different operating system is harder — system-level APIs are more difficult to mask, making it easier for websites to detect inconsistencies. No anti-detect browser can perfectly spoof every detail across operating systems."
|
||||
"crossOsWarning": "Spoofing fingerprint for a different operating system is less reliable because it is impossible to perfectly mimic all underlying components. Use with caution."
|
||||
},
|
||||
"syncAll": {
|
||||
"title": "Enable Sync for Existing Items",
|
||||
"description": "You have items that are not being synced. Would you like to enable sync for all of them?",
|
||||
"itemsList": "Items not synced: {{items}}",
|
||||
"proxies": "{{count}} proxy",
|
||||
"proxies_plural": "{{count}} proxies",
|
||||
"groups": "{{count}} group",
|
||||
"groups_plural": "{{count}} groups",
|
||||
"vpns": "{{count}} VPN",
|
||||
"vpns_plural": "{{count}} VPNs",
|
||||
"enableAll": "Enable All",
|
||||
"skip": "Skip",
|
||||
"success": "Sync enabled for all items"
|
||||
},
|
||||
"crossOs": {
|
||||
"viewOnly": "Created on {{os}} - view only",
|
||||
"cannotLaunch": "Created on {{os}}. Can only be launched on {{os}}.",
|
||||
"viewOnly": "This profile was created on {{os}} and is not supported on this system",
|
||||
"cannotLaunch": "This profile was created on {{os}} and is not supported on this system",
|
||||
"cannotModify": "Cannot modify sync settings for a cross-OS profile"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,8 +166,8 @@
|
||||
"antiDetect": {
|
||||
"title": "Navegador Anti-Detección",
|
||||
"description": "Elige un navegador con capacidades anti-detección",
|
||||
"chromium": "Chromium (Wayfern)",
|
||||
"firefox": "Firefox (Camoufox)",
|
||||
"chromium": "Wayfern",
|
||||
"firefox": "Camoufox",
|
||||
"badge": "Navegador Anti-Detección"
|
||||
},
|
||||
"regular": {
|
||||
@@ -483,11 +483,25 @@
|
||||
"wayfern": "Wayfern"
|
||||
},
|
||||
"fingerprint": {
|
||||
"crossOsWarning": "Suplantar un sistema operativo diferente es más difícil: las API a nivel de sistema son más difíciles de enmascarar, lo que facilita que los sitios web detecten inconsistencias. Ningún navegador antidetección puede suplantar perfectamente cada detalle entre sistemas operativos."
|
||||
"crossOsWarning": "La suplantación de huella digital para un sistema operativo diferente es menos fiable porque es imposible imitar perfectamente todos los componentes subyacentes. Usar con precaución."
|
||||
},
|
||||
"syncAll": {
|
||||
"title": "Activar sincronización para elementos existentes",
|
||||
"description": "Tienes elementos que no se están sincronizando. ¿Te gustaría activar la sincronización para todos?",
|
||||
"itemsList": "Elementos no sincronizados: {{items}}",
|
||||
"proxies": "{{count}} proxy",
|
||||
"proxies_plural": "{{count}} proxies",
|
||||
"groups": "{{count}} grupo",
|
||||
"groups_plural": "{{count}} grupos",
|
||||
"vpns": "{{count}} VPN",
|
||||
"vpns_plural": "{{count}} VPNs",
|
||||
"enableAll": "Activar todos",
|
||||
"skip": "Omitir",
|
||||
"success": "Sincronización activada para todos los elementos"
|
||||
},
|
||||
"crossOs": {
|
||||
"viewOnly": "Creado en {{os}} - solo lectura",
|
||||
"cannotLaunch": "Creado en {{os}}. Solo se puede iniciar en {{os}}.",
|
||||
"viewOnly": "Este perfil fue creado en {{os}} y no es compatible con este sistema",
|
||||
"cannotLaunch": "Este perfil fue creado en {{os}} y no es compatible con este sistema",
|
||||
"cannotModify": "No se pueden modificar los ajustes de sincronización de un perfil de otro sistema operativo"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,8 +166,8 @@
|
||||
"antiDetect": {
|
||||
"title": "Navigateur anti-détection",
|
||||
"description": "Choisissez un navigateur avec des capacités anti-détection",
|
||||
"chromium": "Chromium (Wayfern)",
|
||||
"firefox": "Firefox (Camoufox)",
|
||||
"chromium": "Wayfern",
|
||||
"firefox": "Camoufox",
|
||||
"badge": "Navigateur anti-détection"
|
||||
},
|
||||
"regular": {
|
||||
@@ -483,11 +483,25 @@
|
||||
"wayfern": "Wayfern"
|
||||
},
|
||||
"fingerprint": {
|
||||
"crossOsWarning": "Usurper un système d'exploitation différent est plus difficile : les API au niveau du système sont plus difficiles à masquer, ce qui permet aux sites web de détecter plus facilement les incohérences. Aucun navigateur anti-détection ne peut parfaitement usurper chaque détail d'un système d'exploitation à l'autre."
|
||||
"crossOsWarning": "L'usurpation d'empreinte pour un système d'exploitation différent est moins fiable car il est impossible d'imiter parfaitement tous les composants sous-jacents. À utiliser avec précaution."
|
||||
},
|
||||
"syncAll": {
|
||||
"title": "Activer la synchronisation pour les éléments existants",
|
||||
"description": "Vous avez des éléments qui ne sont pas synchronisés. Voulez-vous activer la synchronisation pour tous ?",
|
||||
"itemsList": "Éléments non synchronisés : {{items}}",
|
||||
"proxies": "{{count}} proxy",
|
||||
"proxies_plural": "{{count}} proxies",
|
||||
"groups": "{{count}} groupe",
|
||||
"groups_plural": "{{count}} groupes",
|
||||
"vpns": "{{count}} VPN",
|
||||
"vpns_plural": "{{count}} VPNs",
|
||||
"enableAll": "Tout activer",
|
||||
"skip": "Ignorer",
|
||||
"success": "Synchronisation activée pour tous les éléments"
|
||||
},
|
||||
"crossOs": {
|
||||
"viewOnly": "Créé sur {{os}} - lecture seule",
|
||||
"cannotLaunch": "Créé sur {{os}}. Ne peut être lancé que sur {{os}}.",
|
||||
"viewOnly": "Ce profil a été créé sur {{os}} et n'est pas pris en charge sur ce système",
|
||||
"cannotLaunch": "Ce profil a été créé sur {{os}} et n'est pas pris en charge sur ce système",
|
||||
"cannotModify": "Impossible de modifier les paramètres de synchronisation d'un profil d'un autre système d'exploitation"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,8 +166,8 @@
|
||||
"antiDetect": {
|
||||
"title": "アンチ検出ブラウザ",
|
||||
"description": "アンチ検出機能を持つブラウザを選択",
|
||||
"chromium": "Chromium (Wayfern)",
|
||||
"firefox": "Firefox (Camoufox)",
|
||||
"chromium": "Wayfern",
|
||||
"firefox": "Camoufox",
|
||||
"badge": "アンチ検出ブラウザ"
|
||||
},
|
||||
"regular": {
|
||||
@@ -483,11 +483,25 @@
|
||||
"wayfern": "Wayfern"
|
||||
},
|
||||
"fingerprint": {
|
||||
"crossOsWarning": "異なるオペレーティングシステムの偽装はより困難です。システムレベルのAPIはマスクしにくく、ウェブサイトが矛盾を検出しやすくなります。どのアンチディテクトブラウザも、異なるOS間のすべての詳細を完璧に偽装することはできません。"
|
||||
"crossOsWarning": "異なるオペレーティングシステムのフィンガープリント偽装は、すべての基盤コンポーネントを完璧に模倣することが不可能なため、信頼性が低くなります。注意してご使用ください。"
|
||||
},
|
||||
"syncAll": {
|
||||
"title": "既存アイテムの同期を有効にする",
|
||||
"description": "同期されていないアイテムがあります。すべての同期を有効にしますか?",
|
||||
"itemsList": "未同期アイテム: {{items}}",
|
||||
"proxies": "{{count}}個のプロキシ",
|
||||
"proxies_plural": "{{count}}個のプロキシ",
|
||||
"groups": "{{count}}個のグループ",
|
||||
"groups_plural": "{{count}}個のグループ",
|
||||
"vpns": "{{count}}個のVPN",
|
||||
"vpns_plural": "{{count}}個のVPN",
|
||||
"enableAll": "すべて有効にする",
|
||||
"skip": "スキップ",
|
||||
"success": "すべてのアイテムの同期が有効になりました"
|
||||
},
|
||||
"crossOs": {
|
||||
"viewOnly": "{{os}}で作成 - 閲覧のみ",
|
||||
"cannotLaunch": "{{os}}で作成されました。{{os}}でのみ起動できます。",
|
||||
"viewOnly": "このプロファイルは{{os}}で作成されたもので、このシステムではサポートされていません",
|
||||
"cannotLaunch": "このプロファイルは{{os}}で作成されたもので、このシステムではサポートされていません",
|
||||
"cannotModify": "他のOSのプロファイルの同期設定は変更できません"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,8 +166,8 @@
|
||||
"antiDetect": {
|
||||
"title": "Navegador Anti-Detecção",
|
||||
"description": "Escolha um navegador com capacidades anti-detecção",
|
||||
"chromium": "Chromium (Wayfern)",
|
||||
"firefox": "Firefox (Camoufox)",
|
||||
"chromium": "Wayfern",
|
||||
"firefox": "Camoufox",
|
||||
"badge": "Navegador Anti-Detecção"
|
||||
},
|
||||
"regular": {
|
||||
@@ -483,11 +483,25 @@
|
||||
"wayfern": "Wayfern"
|
||||
},
|
||||
"fingerprint": {
|
||||
"crossOsWarning": "Falsificar um sistema operacional diferente é mais difícil: as APIs de nível de sistema são mais difíceis de mascarar, facilitando a detecção de inconsistências pelos sites. Nenhum navegador antidetecção consegue falsificar perfeitamente todos os detalhes entre sistemas operacionais."
|
||||
"crossOsWarning": "A falsificação de impressão digital para um sistema operacional diferente é menos confiável porque é impossível imitar perfeitamente todos os componentes subjacentes. Use com cautela."
|
||||
},
|
||||
"syncAll": {
|
||||
"title": "Ativar sincronização para itens existentes",
|
||||
"description": "Você tem itens que não estão sendo sincronizados. Gostaria de ativar a sincronização para todos?",
|
||||
"itemsList": "Itens não sincronizados: {{items}}",
|
||||
"proxies": "{{count}} proxy",
|
||||
"proxies_plural": "{{count}} proxies",
|
||||
"groups": "{{count}} grupo",
|
||||
"groups_plural": "{{count}} grupos",
|
||||
"vpns": "{{count}} VPN",
|
||||
"vpns_plural": "{{count}} VPNs",
|
||||
"enableAll": "Ativar todos",
|
||||
"skip": "Pular",
|
||||
"success": "Sincronização ativada para todos os itens"
|
||||
},
|
||||
"crossOs": {
|
||||
"viewOnly": "Criado em {{os}} - somente leitura",
|
||||
"cannotLaunch": "Criado em {{os}}. Só pode ser iniciado em {{os}}.",
|
||||
"viewOnly": "Este perfil foi criado em {{os}} e não é compatível com este sistema",
|
||||
"cannotLaunch": "Este perfil foi criado em {{os}} e não é compatível com este sistema",
|
||||
"cannotModify": "Não é possível modificar as configurações de sincronização de um perfil de outro sistema operacional"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,8 +166,8 @@
|
||||
"antiDetect": {
|
||||
"title": "Антидетект браузер",
|
||||
"description": "Выберите браузер с возможностями защиты от обнаружения",
|
||||
"chromium": "Chromium (Wayfern)",
|
||||
"firefox": "Firefox (Camoufox)",
|
||||
"chromium": "Wayfern",
|
||||
"firefox": "Camoufox",
|
||||
"badge": "Антидетект браузер"
|
||||
},
|
||||
"regular": {
|
||||
@@ -483,11 +483,25 @@
|
||||
"wayfern": "Wayfern"
|
||||
},
|
||||
"fingerprint": {
|
||||
"crossOsWarning": "Подмена другой операционной системы сложнее — системные API труднее замаскировать, что упрощает обнаружение несоответствий веб-сайтами. Ни один антидетект-браузер не может идеально подменить все детали при смене операционной системы."
|
||||
"crossOsWarning": "Подмена отпечатка для другой операционной системы менее надёжна, так как невозможно идеально имитировать все базовые компоненты. Используйте с осторожностью."
|
||||
},
|
||||
"syncAll": {
|
||||
"title": "Включить синхронизацию для существующих элементов",
|
||||
"description": "У вас есть элементы, которые не синхронизируются. Хотите включить синхронизацию для всех?",
|
||||
"itemsList": "Несинхронизированные элементы: {{items}}",
|
||||
"proxies": "{{count}} прокси",
|
||||
"proxies_plural": "{{count}} прокси",
|
||||
"groups": "{{count}} группа",
|
||||
"groups_plural": "{{count}} групп",
|
||||
"vpns": "{{count}} VPN",
|
||||
"vpns_plural": "{{count}} VPN",
|
||||
"enableAll": "Включить все",
|
||||
"skip": "Пропустить",
|
||||
"success": "Синхронизация включена для всех элементов"
|
||||
},
|
||||
"crossOs": {
|
||||
"viewOnly": "Создан на {{os}} - только просмотр",
|
||||
"cannotLaunch": "Создан на {{os}}. Может быть запущен только на {{os}}.",
|
||||
"viewOnly": "Этот профиль был создан на {{os}} и не поддерживается в этой системе",
|
||||
"cannotLaunch": "Этот профиль был создан на {{os}} и не поддерживается в этой системе",
|
||||
"cannotModify": "Невозможно изменить настройки синхронизации профиля другой ОС"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,8 +166,8 @@
|
||||
"antiDetect": {
|
||||
"title": "防检测浏览器",
|
||||
"description": "选择具有防检测功能的浏览器",
|
||||
"chromium": "Chromium (Wayfern)",
|
||||
"firefox": "Firefox (Camoufox)",
|
||||
"chromium": "Wayfern",
|
||||
"firefox": "Camoufox",
|
||||
"badge": "防检测浏览器"
|
||||
},
|
||||
"regular": {
|
||||
@@ -483,11 +483,25 @@
|
||||
"wayfern": "Wayfern"
|
||||
},
|
||||
"fingerprint": {
|
||||
"crossOsWarning": "伪装不同的操作系统更加困难——系统级API更难以掩盖,使网站更容易检测到不一致之处。没有任何反检测浏览器能够完美伪装跨操作系统的所有细节。"
|
||||
"crossOsWarning": "伪装不同操作系统的指纹不太可靠,因为不可能完美模拟所有底层组件。请谨慎使用。"
|
||||
},
|
||||
"syncAll": {
|
||||
"title": "为现有项目启用同步",
|
||||
"description": "您有未同步的项目。是否要为所有项目启用同步?",
|
||||
"itemsList": "未同步项目: {{items}}",
|
||||
"proxies": "{{count}} 个代理",
|
||||
"proxies_plural": "{{count}} 个代理",
|
||||
"groups": "{{count}} 个分组",
|
||||
"groups_plural": "{{count}} 个分组",
|
||||
"vpns": "{{count}} 个 VPN",
|
||||
"vpns_plural": "{{count}} 个 VPN",
|
||||
"enableAll": "全部启用",
|
||||
"skip": "跳过",
|
||||
"success": "已为所有项目启用同步"
|
||||
},
|
||||
"crossOs": {
|
||||
"viewOnly": "在 {{os}} 上创建 - 仅查看",
|
||||
"cannotLaunch": "在 {{os}} 上创建。只能在 {{os}} 上启动。",
|
||||
"viewOnly": "此配置文件在 {{os}} 上创建,不受此系统支持",
|
||||
"cannotLaunch": "此配置文件在 {{os}} 上创建,不受此系统支持",
|
||||
"cannotModify": "无法修改跨操作系统配置文件的同步设置"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@ export function getBrowserDisplayName(browserType: string): string {
|
||||
zen: "Zen Browser",
|
||||
brave: "Brave",
|
||||
chromium: "Chromium",
|
||||
camoufox: "Firefox (Camoufox)",
|
||||
wayfern: "Chromium (Wayfern)",
|
||||
camoufox: "Camoufox",
|
||||
wayfern: "Wayfern",
|
||||
};
|
||||
|
||||
return browserNames[browserType] || browserType;
|
||||
|
||||
Reference in New Issue
Block a user