mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 08:45:41 +08:00
refactor: notification system
This commit is contained in:
@@ -14,7 +14,6 @@ import LogoSvg from "@/assets/image/logo.svg?react";
|
||||
import iconLight from "@/assets/image/icon_light.svg?react";
|
||||
import iconDark from "@/assets/image/icon_dark.svg?react";
|
||||
import { useThemeMode, useEnableLog } from "@/services/states";
|
||||
import { Notice } from "@/components/base";
|
||||
import { LayoutItem } from "@/components/layout/layout-item";
|
||||
import { LayoutControl } from "@/components/layout/layout-control";
|
||||
import { LayoutTraffic } from "@/components/layout/layout-traffic";
|
||||
@@ -31,6 +30,8 @@ import { listen } from "@tauri-apps/api/event";
|
||||
import { useClashInfo } from "@/hooks/use-clash";
|
||||
import { initGlobalLogService } from "@/services/global-log-service";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { showNotice } from "@/services/noticeService";
|
||||
import { NoticeManager } from "@/components/base/NoticeManager";
|
||||
|
||||
const appWindow = getCurrentWebviewWindow();
|
||||
export let portableFlag = false;
|
||||
@@ -46,92 +47,95 @@ const handleNoticeMessage = (
|
||||
t: (key: string) => string,
|
||||
navigate: (path: string, options?: any) => void,
|
||||
) => {
|
||||
console.log("[通知监听] 收到消息:", status, msg);
|
||||
console.log("[通知监听 V2] 收到消息:", status, msg);
|
||||
|
||||
switch (status) {
|
||||
case "import_sub_url::ok":
|
||||
navigate("/profile", { state: { current: msg } });
|
||||
Notice.success(t("Import Subscription Successful"));
|
||||
showNotice('success', t("Import Subscription Successful"));
|
||||
break;
|
||||
case "import_sub_url::error":
|
||||
navigate("/profile");
|
||||
Notice.error(msg);
|
||||
showNotice('error', msg);
|
||||
break;
|
||||
case "set_config::error":
|
||||
Notice.error(msg);
|
||||
showNotice('error', msg);
|
||||
break;
|
||||
case "update_with_clash_proxy":
|
||||
Notice.success(`${t("Update with Clash proxy successfully")} ${msg}`);
|
||||
showNotice('success', `${t("Update with Clash proxy successfully")} ${msg}`);
|
||||
break;
|
||||
case "update_retry_with_clash":
|
||||
Notice.info(t("Update failed, retrying with Clash proxy..."));
|
||||
showNotice('info', t("Update failed, retrying with Clash proxy..."));
|
||||
break;
|
||||
case "update_failed_even_with_clash":
|
||||
Notice.error(`${t("Update failed even with Clash proxy")}: ${msg}`);
|
||||
showNotice('error', `${t("Update failed even with Clash proxy")}: ${msg}`);
|
||||
break;
|
||||
case "update_failed":
|
||||
Notice.error(msg);
|
||||
showNotice('error', msg);
|
||||
break;
|
||||
case "config_validate::boot_error":
|
||||
Notice.error(`${t("Boot Config Validation Failed")} ${msg}`);
|
||||
showNotice('error', `${t("Boot Config Validation Failed")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::core_change":
|
||||
Notice.error(`${t("Core Change Config Validation Failed")} ${msg}`);
|
||||
showNotice('error', `${t("Core Change Config Validation Failed")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::error":
|
||||
Notice.error(`${t("Config Validation Failed")} ${msg}`);
|
||||
showNotice('error', `${t("Config Validation Failed")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::process_terminated":
|
||||
Notice.error(t("Config Validation Process Terminated"));
|
||||
showNotice('error', t("Config Validation Process Terminated"));
|
||||
break;
|
||||
case "config_validate::stdout_error":
|
||||
Notice.error(`${t("Config Validation Failed")} ${msg}`);
|
||||
showNotice('error', `${t("Config Validation Failed")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::script_error":
|
||||
Notice.error(`${t("Script File Error")} ${msg}`);
|
||||
showNotice('error', `${t("Script File Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::script_syntax_error":
|
||||
Notice.error(`${t("Script Syntax Error")} ${msg}`);
|
||||
showNotice('error', `${t("Script Syntax Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::script_missing_main":
|
||||
Notice.error(`${t("Script Missing Main")} ${msg}`);
|
||||
showNotice('error', `${t("Script Missing Main")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::file_not_found":
|
||||
Notice.error(`${t("File Not Found")} ${msg}`);
|
||||
showNotice('error', `${t("File Not Found")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::yaml_syntax_error":
|
||||
Notice.error(`${t("YAML Syntax Error")} ${msg}`);
|
||||
showNotice('error', `${t("YAML Syntax Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::yaml_read_error":
|
||||
Notice.error(`${t("YAML Read Error")} ${msg}`);
|
||||
showNotice('error', `${t("YAML Read Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::yaml_mapping_error":
|
||||
Notice.error(`${t("YAML Mapping Error")} ${msg}`);
|
||||
showNotice('error', `${t("YAML Mapping Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::yaml_key_error":
|
||||
Notice.error(`${t("YAML Key Error")} ${msg}`);
|
||||
showNotice('error', `${t("YAML Key Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::yaml_error":
|
||||
Notice.error(`${t("YAML Error")} ${msg}`);
|
||||
showNotice('error', `${t("YAML Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::merge_syntax_error":
|
||||
Notice.error(`${t("Merge File Syntax Error")} ${msg}`);
|
||||
showNotice('error', `${t("Merge File Syntax Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::merge_mapping_error":
|
||||
Notice.error(`${t("Merge File Mapping Error")} ${msg}`);
|
||||
showNotice('error', `${t("Merge File Mapping Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::merge_key_error":
|
||||
Notice.error(`${t("Merge File Key Error")} ${msg}`);
|
||||
showNotice('error', `${t("Merge File Key Error")} ${msg}`);
|
||||
break;
|
||||
case "config_validate::merge_error":
|
||||
Notice.error(`${t("Merge File Error")} ${msg}`);
|
||||
showNotice('error', `${t("Merge File Error")} ${msg}`);
|
||||
break;
|
||||
case "config_core::change_success":
|
||||
Notice.success(`${t("Core Changed Successfully")}: ${msg}`);
|
||||
showNotice('success', `${t("Core Changed Successfully")}: ${msg}`);
|
||||
break;
|
||||
case "config_core::change_error":
|
||||
Notice.error(`${t("Failed to Change Core")}: ${msg}`);
|
||||
showNotice('error', `${t("Failed to Change Core")}: ${msg}`);
|
||||
break;
|
||||
default: // Optional: Log unhandled statuses
|
||||
console.warn(`[通知监听 V2] 未处理的状态: ${status}`);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -276,6 +280,8 @@ const Layout = () => {
|
||||
return (
|
||||
<SWRConfig value={{ errorRetryCount: 3 }}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<NoticeManager />
|
||||
|
||||
<Paper
|
||||
square
|
||||
elevation={0}
|
||||
|
||||
@@ -36,7 +36,7 @@ import {
|
||||
} from "@/services/cmds";
|
||||
import { useSetLoadingCache, useThemeMode } from "@/services/states";
|
||||
import { closeAllConnections } from "@/services/api";
|
||||
import { BasePage, DialogRef, Notice } from "@/components/base";
|
||||
import { BasePage, DialogRef } from "@/components/base";
|
||||
import {
|
||||
ProfileViewer,
|
||||
ProfileViewerRef,
|
||||
@@ -53,6 +53,7 @@ import { useLocation } from "react-router-dom";
|
||||
import { useListen } from "@/hooks/use-listen";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { TauriEvent } from "@tauri-apps/api/event";
|
||||
import { showNotice } from "@/services/noticeService";
|
||||
|
||||
const ProfilePage = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -79,7 +80,7 @@ const ProfilePage = () => {
|
||||
|
||||
for (let file of paths) {
|
||||
if (!file.endsWith(".yaml") && !file.endsWith(".yml")) {
|
||||
Notice.error(t("Only YAML Files Supported"));
|
||||
showNotice('error', t("Only YAML Files Supported"));
|
||||
continue;
|
||||
}
|
||||
const item = {
|
||||
@@ -144,14 +145,14 @@ const ProfilePage = () => {
|
||||
try {
|
||||
// 尝试正常导入
|
||||
await importProfile(url);
|
||||
Notice.success(t("Profile Imported Successfully"));
|
||||
showNotice('success', t("Profile Imported Successfully"));
|
||||
setUrl("");
|
||||
mutateProfiles();
|
||||
await onEnhance(false);
|
||||
} catch (err: any) {
|
||||
// 首次导入失败,尝试使用自身代理
|
||||
const errmsg = err.message || err.toString();
|
||||
Notice.info(t("Import failed, retrying with Clash proxy..."));
|
||||
showNotice('info', t("Import failed, retrying with Clash proxy..."));
|
||||
|
||||
try {
|
||||
// 使用自身代理尝试导入
|
||||
@@ -161,16 +162,14 @@ const ProfilePage = () => {
|
||||
});
|
||||
|
||||
// 回退导入成功
|
||||
Notice.success(t("Profile Imported with Clash proxy"));
|
||||
showNotice('success', t("Profile Imported with Clash proxy"));
|
||||
setUrl("");
|
||||
mutateProfiles();
|
||||
await onEnhance(false);
|
||||
} catch (retryErr: any) {
|
||||
// 回退导入也失败
|
||||
const retryErrmsg = retryErr?.message || retryErr.toString();
|
||||
Notice.error(
|
||||
`${t("Import failed even with Clash proxy")}: ${retryErrmsg}`,
|
||||
);
|
||||
showNotice('error', `${t("Import failed even with Clash proxy")}: ${retryErrmsg}`);
|
||||
}
|
||||
} finally {
|
||||
setDisabled(false);
|
||||
@@ -200,10 +199,10 @@ const ProfilePage = () => {
|
||||
closeAllConnections();
|
||||
await activateSelected();
|
||||
if (notifySuccess && success) {
|
||||
Notice.success(t("Profile Switched"), 1000);
|
||||
showNotice('success', t("Profile Switched"), 1000);
|
||||
}
|
||||
} catch (err: any) {
|
||||
Notice.error(err?.message || err.toString(), 4000);
|
||||
showNotice('error', err?.message || err.toString(), 4000);
|
||||
} finally {
|
||||
clearTimeout(reset);
|
||||
setActivatings([]);
|
||||
@@ -229,10 +228,10 @@ const ProfilePage = () => {
|
||||
await enhanceProfiles();
|
||||
mutateLogs();
|
||||
if (notifySuccess) {
|
||||
Notice.success(t("Profile Reactivated"), 1000);
|
||||
showNotice('success', t("Profile Reactivated"), 1000);
|
||||
}
|
||||
} catch (err: any) {
|
||||
Notice.error(err.message || err.toString(), 3000);
|
||||
showNotice('error', err.message || err.toString(), 3000);
|
||||
} finally {
|
||||
setActivatings([]);
|
||||
}
|
||||
@@ -247,7 +246,7 @@ const ProfilePage = () => {
|
||||
mutateLogs();
|
||||
current && (await onEnhance(false));
|
||||
} catch (err: any) {
|
||||
Notice.error(err?.message || err.toString());
|
||||
showNotice('error', err?.message || err.toString());
|
||||
} finally {
|
||||
setActivatings([]);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Box, ButtonGroup, IconButton, Select, MenuItem } from "@mui/material";
|
||||
import Grid from "@mui/material/Grid2";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { BasePage, Notice } from "@/components/base";
|
||||
import { BasePage } from "@/components/base";
|
||||
import { GitHub, HelpOutlineRounded, Telegram } from "@mui/icons-material";
|
||||
import { openWebUrl } from "@/services/cmds";
|
||||
import SettingVergeBasic from "@/components/setting/setting-verge-basic";
|
||||
@@ -10,12 +10,13 @@ import SettingVergeAdvanced from "@/components/setting/setting-verge-advanced";
|
||||
import SettingClash from "@/components/setting/setting-clash";
|
||||
import SettingSystem from "@/components/setting/setting-system";
|
||||
import { useThemeMode } from "@/services/states";
|
||||
import { showNotice } from "@/services/noticeService";
|
||||
|
||||
const SettingPage = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const onError = (err: any) => {
|
||||
Notice.error(err?.message || err.toString());
|
||||
showNotice('error', err?.message || err.toString());
|
||||
};
|
||||
|
||||
const toGithubRepo = useLockFn(() => {
|
||||
|
||||
Reference in New Issue
Block a user