refactor(notice): unify showNotice usage

This commit is contained in:
Slinetrac
2025-11-02 14:22:36 +08:00
Unverified
parent 4683fc7bf1
commit 9b455d740d
51 changed files with 328 additions and 168 deletions

View File

@@ -26,7 +26,7 @@ import { useNavigate } from "react-router";
import { useAppData } from "@/providers/app-data-context"; import { useAppData } from "@/providers/app-data-context";
import { openWebUrl, updateProfile } from "@/services/cmds"; import { openWebUrl, updateProfile } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import parseTraffic from "@/utils/parse-traffic"; import parseTraffic from "@/utils/parse-traffic";
import { EnhancedCard } from "./enhanced-card"; import { EnhancedCard } from "./enhanced-card";
@@ -297,7 +297,7 @@ export const HomeProfileCard = ({
// 刷新首页数据 // 刷新首页数据
refreshAll(); refreshAll();
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString(), 3000); showNotice("error", createRawNotice(err.message || err.toString()), 3000);
} finally { } finally {
setUpdating(false); setUpdating(false);
} }

View File

@@ -21,7 +21,7 @@ import ProxyControlSwitches from "@/components/shared/ProxyControlSwitches";
import { useSystemProxyState } from "@/hooks/use-system-proxy-state"; import { useSystemProxyState } from "@/hooks/use-system-proxy-state";
import { useSystemState } from "@/hooks/use-system-state"; import { useSystemState } from "@/hooks/use-system-state";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
const LOCAL_STORAGE_TAB_KEY = "clash-verge-proxy-active-tab"; const LOCAL_STORAGE_TAB_KEY = "clash-verge-proxy-active-tab";
@@ -148,7 +148,7 @@ export const ProxyTunCard: FC = () => {
const { enable_tun_mode } = verge ?? {}; const { enable_tun_mode } = verge ?? {};
const handleError = (err: Error) => { const handleError = (err: Error) => {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
}; };
const handleTabChange = (tab: string) => { const handleTabChange = (tab: string) => {

View File

@@ -24,7 +24,7 @@ import { useSystemState } from "@/hooks/use-system-state";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { useServiceInstaller } from "@/hooks/useServiceInstaller"; import { useServiceInstaller } from "@/hooks/useServiceInstaller";
import { getSystemInfo } from "@/services/cmds"; import { getSystemInfo } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { checkUpdateSafe as checkUpdate } from "@/services/update"; import { checkUpdateSafe as checkUpdate } from "@/services/update";
import { version as appVersion } from "@root/package.json"; import { version as appVersion } from "@root/package.json";
@@ -174,13 +174,15 @@ export const SystemInfoCard = () => {
try { try {
const info = await checkUpdate(); const info = await checkUpdate();
if (!info?.available) { if (!info?.available) {
showNotice("success", t("Currently on the Latest Version")); showNotice("success", {
i18nKey: "Currently on the Latest Version",
});
} else { } else {
showNotice("info", t("Update Available"), 2000); showNotice("info", { i18nKey: "Update Available" }, 2000);
goToSettings(); goToSettings();
} }
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}); });

View File

@@ -25,7 +25,7 @@ import { useTranslation } from "react-i18next";
import MonacoEditor from "react-monaco-editor"; import MonacoEditor from "react-monaco-editor";
import pac from "types-pac/pac.d.ts?raw"; import pac from "types-pac/pac.d.ts?raw";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { useThemeMode } from "@/services/states"; import { useThemeMode } from "@/services/states";
import debounce from "@/utils/debounce"; import debounce from "@/utils/debounce";
import getSystem from "@/utils/get-system"; import getSystem from "@/utils/get-system";
@@ -133,7 +133,7 @@ export const EditorViewer = <T extends Language>(props: Props<T>) => {
currData.current = value; currData.current = value;
onChange?.(prevData.current, currData.current); onChange?.(prevData.current, currData.current);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}); });
@@ -144,7 +144,7 @@ export const EditorViewer = <T extends Language>(props: Props<T>) => {
} }
onClose(); onClose();
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}); });
@@ -152,7 +152,7 @@ export const EditorViewer = <T extends Language>(props: Props<T>) => {
try { try {
onClose(); onClose();
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}); });

View File

@@ -55,7 +55,7 @@ import {
readProfileFile, readProfileFile,
saveProfileFile, saveProfileFile,
} from "@/services/cmds"; } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { useThemeMode } from "@/services/states"; import { useThemeMode } from "@/services/states";
import getSystem from "@/utils/get-system"; import getSystem from "@/utils/get-system";
@@ -384,12 +384,14 @@ export const GroupsEditorViewer = (props: Props) => {
} }
await saveProfileFile(property, nextData); await saveProfileFile(property, nextData);
showNotice("success", t("components.profile.notifications.saved")); showNotice("success", {
i18nKey: "components.profile.notifications.saved",
});
setPrevData(nextData); setPrevData(nextData);
onSave?.(prevData, nextData); onSave?.(prevData, nextData);
onClose(); onClose();
} catch (err: any) { } catch (err: any) {
showNotice("error", err.toString()); showNotice("error", createRawNotice(err.toString()));
} }
}); });
@@ -920,7 +922,10 @@ export const GroupsEditorViewer = (props: Props) => {
} }
setPrependSeq([formIns.getValues(), ...prependSeq]); setPrependSeq([formIns.getValues(), ...prependSeq]);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice(
"error",
createRawNotice(err.message || err.toString()),
);
} }
}} }}
> >
@@ -946,7 +951,10 @@ export const GroupsEditorViewer = (props: Props) => {
} }
setAppendSeq([...appendSeq, formIns.getValues()]); setAppendSeq([...appendSeq, formIns.getValues()]);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice(
"error",
createRawNotice(err.message || err.toString()),
);
} }
}} }}
> >

View File

@@ -34,7 +34,7 @@ import {
saveProfileFile, saveProfileFile,
getNextUpdateTime, getNextUpdateTime,
} from "@/services/cmds"; } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { useLoadingCache, useSetLoadingCache } from "@/services/states"; import { useLoadingCache, useSetLoadingCache } from "@/services/states";
import parseTraffic from "@/utils/parse-traffic"; import parseTraffic from "@/utils/parse-traffic";
@@ -321,7 +321,7 @@ export const ProfileItem = (props: Props) => {
try { try {
await viewProfile(itemData.uid); await viewProfile(itemData.uid);
} catch (err: any) { } catch (err: any) {
showNotice("error", err?.message || err.toString()); showNotice("error", createRawNotice(err?.message || err.toString()));
} }
}); });

View File

@@ -14,7 +14,7 @@ import { useTranslation } from "react-i18next";
import { EditorViewer } from "@/components/profile/editor-viewer"; import { EditorViewer } from "@/components/profile/editor-viewer";
import { viewProfile, readProfileFile, saveProfileFile } from "@/services/cmds"; import { viewProfile, readProfileFile, saveProfileFile } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { LogViewer } from "./log-viewer"; import { LogViewer } from "./log-viewer";
import { ProfileBox } from "./profile-box"; import { ProfileBox } from "./profile-box";
@@ -48,7 +48,7 @@ export const ProfileMore = (props: Props) => {
try { try {
await viewProfile(id); await viewProfile(id);
} catch (err: any) { } catch (err: any) {
showNotice("error", err?.message || err.toString()); showNotice("error", createRawNotice(err?.message || err.toString()));
} }
}); });

View File

@@ -17,7 +17,7 @@ import { useTranslation } from "react-i18next";
import { BaseDialog, Switch } from "@/components/base"; import { BaseDialog, Switch } from "@/components/base";
import { useProfiles } from "@/hooks/use-profiles"; import { useProfiles } from "@/hooks/use-profiles";
import { createProfile, patchProfile } from "@/services/cmds"; import { createProfile, patchProfile } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { version } from "@root/package.json"; import { version } from "@root/package.json";
import { FileInput } from "./file-input"; import { FileInput } from "./file-input";
@@ -187,7 +187,7 @@ export function ProfileViewer({ onChange, ref }: ProfileViewerProps) {
onChange(isActivating); onChange(isActivating);
}, 0); }, 0);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} finally { } finally {
setLoading(false); setLoading(false);
} }

View File

@@ -42,7 +42,7 @@ import { Virtuoso } from "react-virtuoso";
import { ProxyItem } from "@/components/profile/proxy-item"; import { ProxyItem } from "@/components/profile/proxy-item";
import { readProfileFile, saveProfileFile } from "@/services/cmds"; import { readProfileFile, saveProfileFile } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { useThemeMode } from "@/services/states"; import { useThemeMode } from "@/services/states";
import getSystem from "@/utils/get-system"; import getSystem from "@/utils/get-system";
import parseUri from "@/utils/uri-parser"; import parseUri from "@/utils/uri-parser";
@@ -263,11 +263,13 @@ export const ProxiesEditorViewer = (props: Props) => {
const handleSave = useLockFn(async () => { const handleSave = useLockFn(async () => {
try { try {
await saveProfileFile(property, currData); await saveProfileFile(property, currData);
showNotice("success", t("components.profile.notifications.saved")); showNotice("success", {
i18nKey: "components.profile.notifications.saved",
});
onSave?.(prevData, currData); onSave?.(prevData, currData);
onClose(); onClose();
} catch (err: any) { } catch (err: any) {
showNotice("error", err.toString()); showNotice("error", createRawNotice(err.toString()));
} }
}); });

View File

@@ -45,7 +45,7 @@ import { Virtuoso } from "react-virtuoso";
import { Switch } from "@/components/base"; import { Switch } from "@/components/base";
import { RuleItem } from "@/components/profile/rule-item"; import { RuleItem } from "@/components/profile/rule-item";
import { readProfileFile, saveProfileFile } from "@/services/cmds"; import { readProfileFile, saveProfileFile } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { useThemeMode } from "@/services/states"; import { useThemeMode } from "@/services/states";
import getSystem from "@/utils/get-system"; import getSystem from "@/utils/get-system";
@@ -351,7 +351,10 @@ export const RulesEditorViewer = (props: Props) => {
), ),
); );
} catch (e: any) { } catch (e: any) {
showNotice("error", e?.message || e?.toString() || "YAML dump error"); showNotice(
"error",
createRawNotice(e?.message || e?.toString() || "YAML dump error"),
);
} }
}; };
let idleId: number | undefined; let idleId: number | undefined;
@@ -479,11 +482,13 @@ export const RulesEditorViewer = (props: Props) => {
const handleSave = useLockFn(async () => { const handleSave = useLockFn(async () => {
try { try {
await saveProfileFile(property, currData); await saveProfileFile(property, currData);
showNotice("success", t("components.profile.notifications.saved")); showNotice("success", {
i18nKey: "components.profile.notifications.saved",
});
onSave?.(prevData, currData); onSave?.(prevData, currData);
onClose(); onClose();
} catch (err: any) { } catch (err: any) {
showNotice("error", err.toString()); showNotice("error", createRawNotice(err.toString()));
} }
}); });
@@ -626,7 +631,10 @@ export const RulesEditorViewer = (props: Props) => {
if (prependSeq.includes(raw)) return; if (prependSeq.includes(raw)) return;
setPrependSeq([raw, ...prependSeq]); setPrependSeq([raw, ...prependSeq]);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice(
"error",
createRawNotice(err.message || err.toString()),
);
} }
}} }}
> >
@@ -644,7 +652,10 @@ export const RulesEditorViewer = (props: Props) => {
if (appendSeq.includes(raw)) return; if (appendSeq.includes(raw)) return;
setAppendSeq([...appendSeq, raw]); setAppendSeq([...appendSeq, raw]);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice(
"error",
createRawNotice(err.message || err.toString()),
);
} }
}} }}
> >

View File

@@ -67,13 +67,13 @@ export const ProviderButton = () => {
await refreshProxyProviders(); await refreshProxyProviders();
showNotice("success", { showNotice("success", {
i18nKey: "components.notices.providers.updateSuccess", i18nKey: "components.providers.notices.updateSuccess",
params: { name }, params: { name },
}); });
} catch (err: any) { } catch (err: any) {
const message = err?.message || err?.toString?.() || String(err); const message = err?.message || err?.toString?.() || String(err);
showNotice("error", { showNotice("error", {
i18nKey: "components.notices.providers.updateFailed", i18nKey: "components.providers.notices.updateFailed",
params: { name, message }, params: { name, message },
}); });
} finally { } finally {
@@ -89,7 +89,7 @@ export const ProviderButton = () => {
const allProviders = Object.keys(proxyProviders || {}); const allProviders = Object.keys(proxyProviders || {});
if (allProviders.length === 0) { if (allProviders.length === 0) {
showNotice("info", { showNotice("info", {
i18nKey: "components.notices.providers.none", i18nKey: "components.providers.notices.none",
}); });
return; return;
} }
@@ -121,12 +121,12 @@ export const ProviderButton = () => {
await refreshProxyProviders(); await refreshProxyProviders();
showNotice("success", { showNotice("success", {
i18nKey: "components.notices.providers.allUpdated", i18nKey: "components.providers.notices.allUpdated",
}); });
} catch (err: any) { } catch (err: any) {
const message = err?.message || err?.toString?.() || String(err); const message = err?.message || err?.toString?.() || String(err);
showNotice("error", { showNotice("error", {
i18nKey: "components.notices.providers.genericError", i18nKey: "components.providers.notices.genericError",
params: { message }, params: { message },
}); });
} finally { } finally {

View File

@@ -21,7 +21,7 @@ import { closeAllConnections, upgradeCore } from "tauri-plugin-mihomo-api";
import { BaseDialog, DialogRef } from "@/components/base"; import { BaseDialog, DialogRef } from "@/components/base";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { changeClashCore, restartCore } from "@/services/cmds"; import { changeClashCore, restartCore } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
const VALID_CORE = [ const VALID_CORE = [
{ name: "Mihomo", core: "verge-mihomo", chip: "Release Version" }, { name: "Mihomo", core: "verge-mihomo", chip: "Release Version" },
@@ -54,7 +54,7 @@ export function ClashCoreViewer({ ref }: { ref?: Ref<DialogRef> }) {
const errorMsg = await changeClashCore(core); const errorMsg = await changeClashCore(core);
if (errorMsg) { if (errorMsg) {
showNotice("error", errorMsg); showNotice("error", createRawNotice(errorMsg));
setChangingCore(null); setChangingCore(null);
return; return;
} }
@@ -67,7 +67,7 @@ export function ClashCoreViewer({ ref }: { ref?: Ref<DialogRef> }) {
}, 500); }, 500);
} catch (err: any) { } catch (err: any) {
setChangingCore(null); setChangingCore(null);
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}); });
@@ -75,11 +75,11 @@ export function ClashCoreViewer({ ref }: { ref?: Ref<DialogRef> }) {
try { try {
setRestarting(true); setRestarting(true);
await restartCore(); await restartCore();
showNotice("success", t(`Clash Core Restarted`)); showNotice("success", { i18nKey: "Clash Core Restarted" });
setRestarting(false); setRestarting(false);
} catch (err: any) { } catch (err: any) {
setRestarting(false); setRestarting(false);
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}); });
@@ -88,14 +88,14 @@ export function ClashCoreViewer({ ref }: { ref?: Ref<DialogRef> }) {
setUpgrading(true); setUpgrading(true);
await upgradeCore(); await upgradeCore();
setUpgrading(false); setUpgrading(false);
showNotice("success", t(`Core Version Updated`)); showNotice("success", { i18nKey: "Core Version Updated" });
} catch (err: any) { } catch (err: any) {
setUpgrading(false); setUpgrading(false);
const errMsg = err.response?.data?.message || err.toString(); const errMsg = err.response?.data?.message || err.toString();
const showMsg = errMsg.includes("already using latest version") const showMsg = errMsg.includes("already using latest version")
? "Already Using Latest Core Version" ? "Already Using Latest Core Version"
: errMsg; : errMsg;
showNotice("error", t(showMsg)); showNotice("error", { i18nKey: showMsg, fallback: showMsg });
} }
}); });

View File

@@ -18,7 +18,7 @@ import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch } from "@/components/base"; import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { useClashInfo } from "@/hooks/use-clash"; import { useClashInfo } from "@/hooks/use-clash";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { showNotice } from "@/services/noticeService"; import { createPrefixedNotice, showNotice } from "@/services/noticeService";
export function ControllerViewer({ ref }: { ref?: Ref<DialogRef> }) { export function ControllerViewer({ ref }: { ref?: Ref<DialogRef> }) {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -56,20 +56,18 @@ export function ControllerViewer({ ref }: { ref?: Ref<DialogRef> }) {
// 如果启用了外部控制器,则保存控制器地址和密钥 // 如果启用了外部控制器,则保存控制器地址和密钥
if (enableController) { if (enableController) {
if (!controller.trim()) { if (!controller.trim()) {
showNotice( showNotice("error", {
"error", i18nKey:
t(
"components.settings.externalController.messages.addressRequired", "components.settings.externalController.messages.addressRequired",
), });
);
return; return;
} }
if (!secret.trim()) { if (!secret.trim()) {
showNotice( showNotice("error", {
"error", i18nKey:
t("components.settings.externalController.messages.secretRequired"), "components.settings.externalController.messages.secretRequired",
); });
return; return;
} }
@@ -79,12 +77,15 @@ export function ControllerViewer({ ref }: { ref?: Ref<DialogRef> }) {
await patchInfo({ "external-controller": "" }); await patchInfo({ "external-controller": "" });
} }
showNotice("success", t("Configuration saved successfully")); showNotice("success", { i18nKey: "Configuration saved successfully" });
setOpen(false); setOpen(false);
} catch (err: any) { } catch (err: any) {
const message = err?.message || err?.toString?.();
showNotice( showNotice(
"error", "error",
err.message || t("Failed to save configuration"), message
? createPrefixedNotice(t("Failed to save configuration"), message)
: { i18nKey: "Failed to save configuration" },
4000, 4000,
); );
} finally { } finally {
@@ -101,10 +102,9 @@ export function ControllerViewer({ ref }: { ref?: Ref<DialogRef> }) {
setTimeout(() => setCopySuccess(null)); setTimeout(() => setCopySuccess(null));
} catch (err) { } catch (err) {
console.warn("[ControllerViewer] copy to clipboard failed:", err); console.warn("[ControllerViewer] copy to clipboard failed:", err);
showNotice( showNotice("error", {
"error", i18nKey: "components.settings.externalController.messages.copyFailed",
t("components.settings.externalController.messages.copyFailed"), });
);
} }
}, },
); );

View File

@@ -29,7 +29,11 @@ import MonacoEditor from "react-monaco-editor";
import { BaseDialog, DialogRef, Switch } from "@/components/base"; import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { useClash } from "@/hooks/use-clash"; import { useClash } from "@/hooks/use-clash";
import { showNotice } from "@/services/noticeService"; import {
createPrefixedNotice,
createRawNotice,
showNotice,
} from "@/services/noticeService";
import { useThemeMode } from "@/services/states"; import { useThemeMode } from "@/services/states";
import getSystem from "@/utils/get-system"; import getSystem from "@/utils/get-system";
@@ -424,9 +428,9 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
skipYamlSyncRef.current = true; skipYamlSyncRef.current = true;
updateValuesFromConfig(parsedYaml); updateValuesFromConfig(parsedYaml);
} catch { } catch {
showNotice("error", t("Invalid YAML format")); showNotice("error", { i18nKey: "Invalid YAML format" });
} }
}, [yamlContent, t, updateValuesFromConfig]); }, [yamlContent, updateValuesFromConfig]);
useEffect(() => { useEffect(() => {
if (skipYamlSyncRef.current) { if (skipYamlSyncRef.current) {
@@ -549,7 +553,10 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
showNotice( showNotice(
"error", "error",
t("DNS configuration error") + ": " + cleanErrorMsg, createPrefixedNotice(
`${t("DNS configuration error")}:`,
cleanErrorMsg,
),
); );
return; return;
} }
@@ -561,9 +568,9 @@ export function DnsViewer({ ref }: { ref?: Ref<DialogRef> }) {
} }
setOpen(false); setOpen(false);
showNotice("success", t("DNS settings saved")); showNotice("success", { i18nKey: "DNS settings saved" });
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}); });

View File

@@ -140,10 +140,12 @@ export const HeaderConfiguration = forwardRef<ClashHeaderConfigingRef>(
manual: true, manual: true,
onSuccess: () => { onSuccess: () => {
setOpen(false); setOpen(false);
showNotice("success", t("Configuration saved successfully")); showNotice("success", {
i18nKey: "Configuration saved successfully",
});
}, },
onError: () => { onError: () => {
showNotice("error", t("Failed to save configuration")); showNotice("error", { i18nKey: "Failed to save configuration" });
}, },
}, },
); );

View File

@@ -5,7 +5,7 @@ import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch } from "@/components/base"; import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { HotkeyInput } from "./hotkey-input"; import { HotkeyInput } from "./hotkey-input";
@@ -82,7 +82,7 @@ export const HotkeyViewer = forwardRef<DialogRef>((props, ref) => {
}); });
setOpen(false); setOpen(false);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}); });

View File

@@ -23,7 +23,7 @@ import { DEFAULT_HOVER_DELAY } from "@/components/proxy/proxy-group-navigator";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { useWindowDecorations } from "@/hooks/use-window"; import { useWindowDecorations } from "@/hooks/use-window";
import { copyIconFile, getAppDir } from "@/services/cmds"; import { copyIconFile, getAppDir } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import getSystem from "@/utils/get-system"; import getSystem from "@/utils/get-system";
import { GuardState } from "./guard-state"; import { GuardState } from "./guard-state";
@@ -104,7 +104,7 @@ export const LayoutViewer = forwardRef<DialogRef>((_, ref) => {
const onSwitchFormat = (_e: any, value: boolean) => value; const onSwitchFormat = (_e: any, value: boolean) => value;
const onError = (err: any) => { const onError = (err: any) => {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
}; };
const onChangeData = (patch: Partial<IVergeConfig>) => { const onChangeData = (patch: Partial<IVergeConfig>) => {
mutateVerge({ ...verge, ...patch }, false); mutateVerge({ ...verge, ...patch }, false);

View File

@@ -15,7 +15,7 @@ import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { TooltipIcon } from "@/components/base/base-tooltip-icon"; import { TooltipIcon } from "@/components/base/base-tooltip-icon";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { entry_lightweight_mode } from "@/services/cmds"; import { entry_lightweight_mode } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
export function LiteModeViewer({ ref }: { ref?: Ref<DialogRef> }) { export function LiteModeViewer({ ref }: { ref?: Ref<DialogRef> }) {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -46,7 +46,7 @@ export function LiteModeViewer({ ref }: { ref?: Ref<DialogRef> }) {
}); });
setOpen(false); setOpen(false);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}); });

View File

@@ -14,7 +14,7 @@ import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch } from "@/components/base"; import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { TooltipIcon } from "@/components/base/base-tooltip-icon"; import { TooltipIcon } from "@/components/base/base-tooltip-icon";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
export const MiscViewer = forwardRef<DialogRef>((props, ref) => { export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -70,7 +70,7 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
}); });
setOpen(false); setOpen(false);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.toString()); showNotice("error", createRawNotice(err.toString()));
} }
}); });

View File

@@ -109,8 +109,6 @@ const AddressDisplay = ({
label: string; label: string;
content: string; content: string;
}) => { }) => {
const { t } = useTranslation();
return ( return (
<Box <Box
sx={{ sx={{
@@ -135,7 +133,7 @@ const AddressDisplay = ({
size="small" size="small"
onClick={async () => { onClick={async () => {
await writeText(content); await writeText(content);
showNotice("success", t("Copy Success")); showNotice("success", { i18nKey: "Copy Success" });
}} }}
> >
<ContentCopyRounded sx={{ fontSize: "18px" }} /> <ContentCopyRounded sx={{ fontSize: "18px" }} />

View File

@@ -36,7 +36,7 @@ import {
getSystemProxy, getSystemProxy,
patchVergeConfig, patchVergeConfig,
} from "@/services/cmds"; } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import getSystem from "@/utils/get-system"; import getSystem from "@/utils/get-system";
const sleep = (ms: number) => const sleep = (ms: number) =>
@@ -161,7 +161,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
]); ]);
} }
} catch (err: any) { } catch (err: any) {
showNotice("error", err.toString()); showNotice("error", createRawNotice(err.toString()));
} }
}; };
@@ -410,7 +410,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
} catch (err: any) { } catch (err: any) {
console.error("配置保存失败:", err); console.error("配置保存失败:", err);
mutateVerge(); mutateVerge();
showNotice("error", err.toString()); showNotice("error", createRawNotice(err.toString()));
// setOpen(true); // setOpen(true);
} }
}); });

View File

@@ -16,7 +16,7 @@ import { BaseDialog, DialogRef } from "@/components/base";
import { EditorViewer } from "@/components/profile/editor-viewer"; import { EditorViewer } from "@/components/profile/editor-viewer";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { defaultDarkTheme, defaultTheme } from "@/pages/_theme"; import { defaultDarkTheme, defaultTheme } from "@/pages/_theme";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
export function ThemeViewer(props: { ref?: React.Ref<DialogRef> }) { export function ThemeViewer(props: { ref?: React.Ref<DialogRef> }) {
const { ref } = props; const { ref } = props;
@@ -51,7 +51,7 @@ export function ThemeViewer(props: { ref?: React.Ref<DialogRef> }) {
await patchVerge({ theme_setting: theme }); await patchVerge({ theme_setting: theme });
setOpen(false); setOpen(false);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.toString()); showNotice("error", createRawNotice(err.toString()));
} }
}); });

View File

@@ -15,7 +15,7 @@ import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch } from "@/components/base"; import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { useClash } from "@/hooks/use-clash"; import { useClash } from "@/hooks/use-clash";
import { enhanceProfiles } from "@/services/cmds"; import { enhanceProfiles } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import getSystem from "@/utils/get-system"; import getSystem from "@/utils/get-system";
import { StackModeSwitch } from "./stack-mode-switch"; import { StackModeSwitch } from "./stack-mode-switch";
@@ -80,13 +80,15 @@ export function TunViewer({ ref }: { ref?: Ref<DialogRef> }) {
); );
try { try {
await enhanceProfiles(); await enhanceProfiles();
showNotice("success", t("components.settings.tun.messages.applied")); showNotice("success", {
i18nKey: "components.settings.tun.messages.applied",
});
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
setOpen(false); setOpen(false);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}); });

View File

@@ -12,7 +12,7 @@ import useSWR from "swr";
import { BaseDialog, DialogRef } from "@/components/base"; import { BaseDialog, DialogRef } from "@/components/base";
import { useListen } from "@/hooks/use-listen"; import { useListen } from "@/hooks/use-listen";
import { portableFlag } from "@/pages/_layout"; import { portableFlag } from "@/pages/_layout";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { useSetUpdateState, useUpdateState } from "@/services/states"; import { useSetUpdateState, useUpdateState } from "@/services/states";
import { checkUpdateSafe as checkUpdate } from "@/services/update"; import { checkUpdateSafe as checkUpdate } from "@/services/update";
@@ -95,7 +95,7 @@ export function UpdateViewer({ ref }: { ref?: Ref<DialogRef> }) {
await updateInfo.downloadAndInstall(); await updateInfo.downloadAndInstall();
await relaunch(); await relaunch();
} catch (err: any) { } catch (err: any) {
showNotice("error", err?.message || err.toString()); showNotice("error", createRawNotice(err?.message || err.toString()));
} finally { } finally {
setUpdateState(false); setUpdateState(false);
if (progressListener) { if (progressListener) {

View File

@@ -8,7 +8,7 @@ import { BaseDialog, BaseEmpty, DialogRef } from "@/components/base";
import { useClashInfo } from "@/hooks/use-clash"; import { useClashInfo } from "@/hooks/use-clash";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { openWebUrl } from "@/services/cmds"; import { openWebUrl } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { WebUIItem } from "./web-ui-item"; import { WebUIItem } from "./web-ui-item";
@@ -92,7 +92,7 @@ export function WebUIViewer({ ref }: { ref?: Ref<DialogRef> }) {
await openWebUrl(url); await openWebUrl(url);
} catch (e: any) { } catch (e: any) {
showNotice("error", e.message || e.toString()); showNotice("error", createRawNotice(e.message || e.toString()));
} }
}); });

View File

@@ -11,7 +11,7 @@ import { TooltipIcon } from "@/components/base/base-tooltip-icon";
import { useClash } from "@/hooks/use-clash"; import { useClash } from "@/hooks/use-clash";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { invoke_uwp_tool } from "@/services/cmds"; import { invoke_uwp_tool } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { useClashLog } from "@/services/states"; import { useClashLog } from "@/services/states";
import getSystem from "@/utils/get-system"; import getSystem from "@/utils/get-system";
@@ -72,7 +72,7 @@ const SettingClash = ({ onError }: Props) => {
t("components.settings.clash.messages.geoDataUpdated"), t("components.settings.clash.messages.geoDataUpdated"),
); );
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}; };
@@ -89,7 +89,7 @@ const SettingClash = ({ onError }: Props) => {
} catch (err: any) { } catch (err: any) {
setDnsSettingsEnabled(!enable); setDnsSettingsEnabled(!enable);
localStorage.setItem("dns_settings_enabled", String(!enable)); localStorage.setItem("dns_settings_enabled", String(!enable));
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
await patchVerge({ enable_dns_settings: !enable }).catch(() => {}); await patchVerge({ enable_dns_settings: !enable }).catch(() => {});
throw err; throw err;
} }

View File

@@ -13,7 +13,7 @@ import {
openDevTools, openDevTools,
openLogsDir, openLogsDir,
} from "@/services/cmds"; } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { checkUpdateSafe as checkUpdate } from "@/services/update"; import { checkUpdateSafe as checkUpdate } from "@/services/update";
import { version } from "@root/package.json"; import { version } from "@root/package.json";
@@ -55,7 +55,7 @@ const SettingVergeAdvanced = ({ onError: _ }: Props) => {
updateRef.current?.open(); updateRef.current?.open();
} }
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}; };

View File

@@ -21,7 +21,7 @@ import { useSystemState } from "@/hooks/use-system-state";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { useServiceInstaller } from "@/hooks/useServiceInstaller"; import { useServiceInstaller } from "@/hooks/useServiceInstaller";
import { useServiceUninstaller } from "@/hooks/useServiceUninstaller"; import { useServiceUninstaller } from "@/hooks/useServiceUninstaller";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
interface ProxySwitchProps { interface ProxySwitchProps {
label?: string; label?: string;
@@ -126,8 +126,8 @@ const ProxyControlSwitches = ({
const { enable_tun_mode, enable_system_proxy } = verge ?? {}; const { enable_tun_mode, enable_system_proxy } = verge ?? {};
const showErrorNotice = useCallback( const showErrorNotice = useCallback(
(msg: string) => showNotice("error", t(msg)), (msg: string) => showNotice("error", { i18nKey: msg }),
[t], [],
); );
const handleTunToggle = async (value: boolean) => { const handleTunToggle = async (value: boolean) => {
@@ -145,7 +145,10 @@ const ProxyControlSwitches = ({
await installServiceAndRestartCore(); await installServiceAndRestartCore();
await mutateSystemState(); await mutateSystemState();
} catch (err) { } catch (err) {
showNotice("error", (err as Error).message || String(err)); showNotice(
"error",
createRawNotice((err as Error).message || String(err)),
);
} }
}); });
@@ -157,7 +160,10 @@ const ProxyControlSwitches = ({
await uninstallServiceAndRestartCore(); await uninstallServiceAndRestartCore();
await mutateSystemState(); await mutateSystemState();
} catch (err) { } catch (err) {
showNotice("error", (err as Error).message || String(err)); showNotice(
"error",
createRawNotice((err as Error).message || String(err)),
);
} }
}); });

View File

@@ -12,7 +12,7 @@ import { BaseLoading } from "@/components/base";
import { useListen } from "@/hooks/use-listen"; import { useListen } from "@/hooks/use-listen";
import { cmdTestDelay, downloadIconCache } from "@/services/cmds"; import { cmdTestDelay, downloadIconCache } from "@/services/cmds";
import delayManager from "@/services/delay"; import delayManager from "@/services/delay";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { TestBox } from "./test-box"; import { TestBox } from "./test-box";
@@ -82,7 +82,7 @@ export const TestItem = ({
try { try {
removeTest(uid); removeTest(uid);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
} }
}); });

View File

@@ -7,7 +7,7 @@ import { useTranslation } from "react-i18next";
import { BaseDialog } from "@/components/base"; import { BaseDialog } from "@/components/base";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
interface Props { interface Props {
onChange: (uid: string, patch?: Partial<IVergeTestItem>) => void; onChange: (uid: string, patch?: Partial<IVergeTestItem>) => void;
@@ -101,7 +101,7 @@ export const TestViewer = forwardRef<TestViewerRef, Props>((props, ref) => {
setLoading(false); setLoading(false);
setTimeout(() => formIns.reset(), 500); setTimeout(() => formIns.reset(), 500);
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString()); showNotice("error", createRawNotice(err.message || err.toString()));
setLoading(false); setLoading(false);
} }
}), }),

View File

@@ -67,14 +67,16 @@ export function useSystemState() {
disablingTunMode = true; disablingTunMode = true;
patchVerge({ enable_tun_mode: false }) patchVerge({ enable_tun_mode: false })
.then(() => { .then(() => {
showNotice( showNotice("info", {
"info", i18nKey:
t("TUN Mode automatically disabled due to service unavailable"), "TUN Mode automatically disabled due to service unavailable",
); });
}) })
.catch((err) => { .catch((err) => {
console.error("[useVerge] 自动关闭TUN模式失败:", err); console.error("[useVerge] 自动关闭TUN模式失败:", err);
showNotice("error", t("Failed to disable TUN Mode automatically")); showNotice("error", {
i18nKey: "Failed to disable TUN Mode automatically",
});
}) })
.finally(() => { .finally(() => {
const tid = setTimeout(() => { const tid = setTimeout(() => {

View File

@@ -1,8 +1,7 @@
import { t } from "i18next";
import { useCallback } from "react"; import { useCallback } from "react";
import { installService, restartCore } from "@/services/cmds"; import { installService, restartCore } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { useSystemState } from "./use-system-state"; import { useSystemState } from "./use-system-state";
@@ -12,14 +11,14 @@ const executeWithErrorHandling = async (
successMessage?: string, successMessage?: string,
) => { ) => {
try { try {
showNotice("info", t(loadingMessage)); showNotice("info", { i18nKey: loadingMessage });
await operation(); await operation();
if (successMessage) { if (successMessage) {
showNotice("success", t(successMessage)); showNotice("success", { i18nKey: successMessage });
} }
} catch (err) { } catch (err) {
const msg = (err as Error)?.message || String(err); const msg = (err as Error)?.message || String(err);
showNotice("error", msg); showNotice("error", createRawNotice(msg));
throw err; throw err;
} }
}; };

View File

@@ -1,8 +1,7 @@
import { t } from "i18next";
import { useCallback } from "react"; import { useCallback } from "react";
import { restartCore, stopCore, uninstallService } from "@/services/cmds"; import { restartCore, stopCore, uninstallService } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { useSystemState } from "./use-system-state"; import { useSystemState } from "./use-system-state";
@@ -12,14 +11,14 @@ const executeWithErrorHandling = async (
successMessage?: string, successMessage?: string,
) => { ) => {
try { try {
showNotice("info", t(loadingMessage)); showNotice("info", { i18nKey: loadingMessage });
await operation(); await operation();
if (successMessage) { if (successMessage) {
showNotice("success", t(successMessage)); showNotice("success", { i18nKey: successMessage });
} }
} catch (err) { } catch (err) {
const msg = (err as Error)?.message || String(err); const msg = (err as Error)?.message || String(err);
showNotice("error", msg); showNotice("error", createRawNotice(msg));
throw err; throw err;
} }
}; };

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "تصور", "visualization": "تصور",
"advanced": "متقدم" "advanced": "متقدم"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "Visualisierung", "visualization": "Visualisierung",
"advanced": "Erweitert" "advanced": "Erweitert"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "Visualization", "visualization": "Visualization",
"advanced": "Advanced" "advanced": "Advanced"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "Visualización", "visualization": "Visualización",
"advanced": "Avanzado" "advanced": "Avanzado"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "تجسم", "visualization": "تجسم",
"advanced": "پیشرفته" "advanced": "پیشرفته"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "Visualisasi", "visualization": "Visualisasi",
"advanced": "Lanjutan" "advanced": "Lanjutan"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "可視化", "visualization": "可視化",
"advanced": "詳細設定" "advanced": "詳細設定"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "시각화", "visualization": "시각화",
"advanced": "고급" "advanced": "고급"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "Визуализация", "visualization": "Визуализация",
"advanced": "Дополнительно" "advanced": "Дополнительно"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "Görselleştirme", "visualization": "Görselleştirme",
"advanced": "Gelişmiş" "advanced": "Gelişmiş"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "Визуализация", "visualization": "Визуализация",
"advanced": "Өстәмә" "advanced": "Өстәмә"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "可视化", "visualization": "可视化",
"advanced": "高级" "advanced": "高级"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1081,6 +1081,10 @@
"editorModes": { "editorModes": {
"visualization": "視覺化", "visualization": "視覺化",
"advanced": "進階" "advanced": "進階"
},
"notices": {
"raw": "{{message}}",
"prefixedRaw": "{{prefix}} {{message}}"
} }
} }
} }

View File

@@ -1,4 +1,8 @@
import { showNotice } from "@/services/noticeService"; import {
createPrefixedNotice,
createRawNotice,
showNotice,
} from "@/services/noticeService";
type NavigateFunction = (path: string, options?: any) => void; type NavigateFunction = (path: string, options?: any) => void;
type TranslateFunction = (key: string) => string; type TranslateFunction = (key: string) => string;
@@ -12,69 +16,97 @@ export const handleNoticeMessage = (
const handlers: Record<string, () => void> = { const handlers: Record<string, () => void> = {
"import_sub_url::ok": () => { "import_sub_url::ok": () => {
navigate("/profile", { state: { current: msg } }); navigate("/profile", { state: { current: msg } });
showNotice("success", t("Import Subscription Successful")); showNotice("success", { i18nKey: "Import Subscription Successful" });
}, },
"import_sub_url::error": () => { "import_sub_url::error": () => {
navigate("/profile"); navigate("/profile");
showNotice("error", msg); showNotice("error", createRawNotice(msg));
}, },
"set_config::error": () => showNotice("error", msg), "set_config::error": () => showNotice("error", createRawNotice(msg)),
update_with_clash_proxy: () => update_with_clash_proxy: () =>
showNotice( showNotice(
"success", "success",
`${t("Update with Clash proxy successfully")} ${msg}`, createPrefixedNotice(t("Update with Clash proxy successfully"), msg),
), ),
update_retry_with_clash: () => update_retry_with_clash: () =>
showNotice("info", t("Update failed, retrying with Clash proxy...")), showNotice("info", {
i18nKey: "Update failed, retrying with Clash proxy...",
}),
update_failed_even_with_clash: () => update_failed_even_with_clash: () =>
showNotice( showNotice(
"error", "error",
`${t("Update failed even with Clash proxy")}: ${msg}`, createPrefixedNotice(
`${t("Update failed even with Clash proxy")}:`,
msg,
),
), ),
update_failed: () => showNotice("error", msg), update_failed: () => showNotice("error", createRawNotice(msg)),
"config_validate::boot_error": () => "config_validate::boot_error": () =>
showNotice("error", `${t("Boot Config Validation Failed")} ${msg}`), showNotice(
"error",
createPrefixedNotice(t("Boot Config Validation Failed"), msg),
),
"config_validate::core_change": () => "config_validate::core_change": () =>
showNotice( showNotice(
"error", "error",
`${t("Core Change Config Validation Failed")} ${msg}`, createPrefixedNotice(t("Core Change Config Validation Failed"), msg),
), ),
"config_validate::error": () => "config_validate::error": () =>
showNotice("error", `${t("Config Validation Failed")} ${msg}`), showNotice(
"error",
createPrefixedNotice(t("Config Validation Failed"), msg),
),
"config_validate::process_terminated": () => "config_validate::process_terminated": () =>
showNotice("error", t("Config Validation Process Terminated")), showNotice("error", {
i18nKey: "Config Validation Process Terminated",
}),
"config_validate::stdout_error": () => "config_validate::stdout_error": () =>
showNotice("error", `${t("Config Validation Failed")} ${msg}`), showNotice(
"error",
createPrefixedNotice(t("Config Validation Failed"), msg),
),
"config_validate::script_error": () => "config_validate::script_error": () =>
showNotice("error", `${t("Script File Error")} ${msg}`), showNotice("error", createPrefixedNotice(t("Script File Error"), msg)),
"config_validate::script_syntax_error": () => "config_validate::script_syntax_error": () =>
showNotice("error", `${t("Script Syntax Error")} ${msg}`), showNotice("error", createPrefixedNotice(t("Script Syntax Error"), msg)),
"config_validate::script_missing_main": () => "config_validate::script_missing_main": () =>
showNotice("error", `${t("Script Missing Main")} ${msg}`), showNotice("error", createPrefixedNotice(t("Script Missing Main"), msg)),
"config_validate::file_not_found": () => "config_validate::file_not_found": () =>
showNotice("error", `${t("File Not Found")} ${msg}`), showNotice("error", createPrefixedNotice(t("File Not Found"), msg)),
"config_validate::yaml_syntax_error": () => "config_validate::yaml_syntax_error": () =>
showNotice("error", `${t("YAML Syntax Error")} ${msg}`), showNotice("error", createPrefixedNotice(t("YAML Syntax Error"), msg)),
"config_validate::yaml_read_error": () => "config_validate::yaml_read_error": () =>
showNotice("error", `${t("YAML Read Error")} ${msg}`), showNotice("error", createPrefixedNotice(t("YAML Read Error"), msg)),
"config_validate::yaml_mapping_error": () => "config_validate::yaml_mapping_error": () =>
showNotice("error", `${t("YAML Mapping Error")} ${msg}`), showNotice("error", createPrefixedNotice(t("YAML Mapping Error"), msg)),
"config_validate::yaml_key_error": () => "config_validate::yaml_key_error": () =>
showNotice("error", `${t("YAML Key Error")} ${msg}`), showNotice("error", createPrefixedNotice(t("YAML Key Error"), msg)),
"config_validate::yaml_error": () => "config_validate::yaml_error": () =>
showNotice("error", `${t("YAML Error")} ${msg}`), showNotice("error", createPrefixedNotice(t("YAML Error"), msg)),
"config_validate::merge_syntax_error": () => "config_validate::merge_syntax_error": () =>
showNotice("error", `${t("Merge File Syntax Error")} ${msg}`), showNotice(
"error",
createPrefixedNotice(t("Merge File Syntax Error"), msg),
),
"config_validate::merge_mapping_error": () => "config_validate::merge_mapping_error": () =>
showNotice("error", `${t("Merge File Mapping Error")} ${msg}`), showNotice(
"error",
createPrefixedNotice(t("Merge File Mapping Error"), msg),
),
"config_validate::merge_key_error": () => "config_validate::merge_key_error": () =>
showNotice("error", `${t("Merge File Key Error")} ${msg}`), showNotice("error", createPrefixedNotice(t("Merge File Key Error"), msg)),
"config_validate::merge_error": () => "config_validate::merge_error": () =>
showNotice("error", `${t("Merge File Error")} ${msg}`), showNotice("error", createPrefixedNotice(t("Merge File Error"), msg)),
"config_core::change_success": () => "config_core::change_success": () =>
showNotice("success", `${t("Core Changed Successfully")}: ${msg}`), showNotice(
"success",
createPrefixedNotice(`${t("Core Changed Successfully")}:`, msg),
),
"config_core::change_error": () => "config_core::change_error": () =>
showNotice("error", `${t("Failed to Change Core")}: ${msg}`), showNotice(
"error",
createPrefixedNotice(`${t("Failed to Change Core")}:`, msg),
),
}; };
const handler = handlers[status]; const handler = handlers[status];

View File

@@ -58,7 +58,11 @@ import {
reorderProfile, reorderProfile,
updateProfile, updateProfile,
} from "@/services/cmds"; } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import {
createPrefixedNotice,
createRawNotice,
showNotice,
} from "@/services/noticeService";
import { useSetLoadingCache, useThemeMode } from "@/services/states"; import { useSetLoadingCache, useThemeMode } from "@/services/states";
// 记录profile切换状态 // 记录profile切换状态
@@ -147,7 +151,10 @@ const ProfilePage = () => {
setActivatings((prev) => prev.filter((id) => id !== previousSwitching)); setActivatings((prev) => prev.filter((id) => id !== previousSwitching));
showNotice( showNotice(
"info", "info",
`${t("pages.profiles.notifications.switchInterrupted")}: ${previousSwitching}${newProfile}`, createPrefixedNotice(
t("pages.profiles.notifications.switchInterrupted"),
`${previousSwitching}${newProfile}`,
),
3000, 3000,
); );
}, },
@@ -191,7 +198,9 @@ const ProfilePage = () => {
for (const file of paths) { for (const file of paths) {
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) { if (!file.endsWith(".yaml") && !file.endsWith(".yml")) {
showNotice("error", t("pages.profiles.errors.onlyYaml")); showNotice("error", {
i18nKey: "pages.profiles.errors.onlyYaml",
});
continue; continue;
} }
const item = { const item = {
@@ -283,13 +292,15 @@ const ProfilePage = () => {
if (!url) return; if (!url) return;
// 校验url是否为http/https // 校验url是否为http/https
if (!/^https?:\/\//i.test(url)) { if (!/^https?:\/\//i.test(url)) {
showNotice("error", t("pages.profiles.errors.invalidUrl")); showNotice("error", {
i18nKey: "pages.profiles.errors.invalidUrl",
});
return; return;
} }
setLoading(true); setLoading(true);
const handleImportSuccess = async (noticeKey: string) => { const handleImportSuccess = async (noticeKey: string) => {
showNotice("success", t(noticeKey)); showNotice("success", { i18nKey: noticeKey });
setUrl(""); setUrl("");
await performRobustRefresh(); await performRobustRefresh();
}; };
@@ -301,7 +312,9 @@ const ProfilePage = () => {
} catch (initialErr) { } catch (initialErr) {
console.warn("[订阅导入] 首次导入失败:", initialErr); console.warn("[订阅导入] 首次导入失败:", initialErr);
showNotice("info", t("pages.profiles.notifications.importRetry")); showNotice("info", {
i18nKey: "pages.profiles.notifications.importRetry",
});
try { try {
// 使用自身代理尝试导入 // 使用自身代理尝试导入
await importProfile(url, { await importProfile(url, {
@@ -524,7 +537,11 @@ const ProfilePage = () => {
} }
console.error(`[Profile] 切换失败:`, err); console.error(`[Profile] 切换失败:`, err);
showNotice("error", err?.message || err.toString(), 4000); showNotice(
"error",
createRawNotice(err?.message || err.toString()),
4000,
);
} finally { } finally {
// 只有当前profile仍然是正在切换的profile且序列号匹配时才清理状态 // 只有当前profile仍然是正在切换的profile且序列号匹配时才清理状态
if ( if (
@@ -597,7 +614,7 @@ const ProfilePage = () => {
); );
} }
} catch (err: any) { } catch (err: any) {
showNotice("error", err.message || err.toString(), 3000); showNotice("error", createRawNotice(err.message || err.toString()), 3000);
} finally { } finally {
// 保留正在切换的profile清除其他状态 // 保留正在切换的profile清除其他状态
setActivatings((prev) => setActivatings((prev) =>
@@ -617,7 +634,7 @@ const ProfilePage = () => {
await onEnhance(false); await onEnhance(false);
} }
} catch (err: any) { } catch (err: any) {
showNotice("error", err?.message || err.toString()); showNotice("error", createRawNotice(err?.message || err.toString()));
} finally { } finally {
setActivatings([]); setActivatings([]);
} }
@@ -733,9 +750,11 @@ const ProfilePage = () => {
setSelectedProfiles(new Set()); setSelectedProfiles(new Set());
setBatchMode(false); setBatchMode(false);
showNotice("success", t("pages.profiles.notifications.batchDeleted")); showNotice("success", {
i18nKey: "pages.profiles.notifications.batchDeleted",
});
} catch (err: any) { } catch (err: any) {
showNotice("error", err?.message || err.toString()); showNotice("error", createRawNotice(err?.message || err.toString()));
} finally { } finally {
setActivatings([]); setActivatings([]);
} }

View File

@@ -9,14 +9,14 @@ import SettingSystem from "@/components/setting/setting-system";
import SettingVergeAdvanced from "@/components/setting/setting-verge-advanced"; import SettingVergeAdvanced from "@/components/setting/setting-verge-advanced";
import SettingVergeBasic from "@/components/setting/setting-verge-basic"; import SettingVergeBasic from "@/components/setting/setting-verge-basic";
import { openWebUrl } from "@/services/cmds"; import { openWebUrl } from "@/services/cmds";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
import { useThemeMode } from "@/services/states"; import { useThemeMode } from "@/services/states";
const SettingPage = () => { const SettingPage = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const onError = (err: any) => { const onError = (err: any) => {
showNotice("error", err?.message || err.toString()); showNotice("error", createRawNotice(err?.message || err.toString()));
}; };
const toGithubRepo = useLockFn(() => { const toGithubRepo = useLockFn(() => {

View File

@@ -2,7 +2,7 @@ import { invoke } from "@tauri-apps/api/core";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { getProxies, getProxyProviders } from "tauri-plugin-mihomo-api"; import { getProxies, getProxyProviders } from "tauri-plugin-mihomo-api";
import { showNotice } from "@/services/noticeService"; import { createRawNotice, showNotice } from "@/services/noticeService";
export async function copyClashEnv() { export async function copyClashEnv() {
return invoke<void>("copy_clash_env"); return invoke<void>("copy_clash_env");
@@ -315,19 +315,19 @@ export async function getAppDir() {
export async function openAppDir() { export async function openAppDir() {
return invoke<void>("open_app_dir").catch((err) => return invoke<void>("open_app_dir").catch((err) =>
showNotice("error", err?.message || err.toString()), showNotice("error", createRawNotice(err?.message || err.toString())),
); );
} }
export async function openCoreDir() { export async function openCoreDir() {
return invoke<void>("open_core_dir").catch((err) => return invoke<void>("open_core_dir").catch((err) =>
showNotice("error", err?.message || err.toString()), showNotice("error", createRawNotice(err?.message || err.toString())),
); );
} }
export async function openLogsDir() { export async function openLogsDir() {
return invoke<void>("open_logs_dir").catch((err) => return invoke<void>("open_logs_dir").catch((err) =>
showNotice("error", err?.message || err.toString()), showNotice("error", createRawNotice(err?.message || err.toString())),
); );
} }
@@ -335,7 +335,7 @@ export const openWebUrl = async (url: string) => {
try { try {
await invoke("open_web_url", { url }); await invoke("open_web_url", { url });
} catch (err: any) { } catch (err: any) {
showNotice("error", err.toString()); showNotice("error", createRawNotice(err.toString()));
} }
}; };
@@ -377,7 +377,7 @@ export async function cmdTestDelay(url: string) {
export async function invoke_uwp_tool() { export async function invoke_uwp_tool() {
return invoke<void>("invoke_uwp_tool").catch((err) => return invoke<void>("invoke_uwp_tool").catch((err) =>
showNotice("error", err?.message || err.toString(), 1500), showNotice("error", createRawNotice(err?.message || err.toString()), 1500),
); );
} }

View File

@@ -98,6 +98,25 @@ export function showTranslatedNotice(
); );
} }
export const createRawNotice = (
message: string,
fallback?: string,
): NoticeTranslationDescriptor => ({
i18nKey: "common.notices.raw",
params: { message },
fallback: fallback ?? message,
});
export const createPrefixedNotice = (
prefix: string,
message: string,
fallback?: string,
): NoticeTranslationDescriptor => ({
i18nKey: "common.notices.prefixedRaw",
params: { prefix, message },
fallback: fallback ?? `${prefix} ${message}`,
});
// Hides a specific notification by its ID. // Hides a specific notification by its ID.
export function hideNotice(id: number) { export function hideNotice(id: number) {