From fc84dc561ca7bb6508ee1171311c7232175520b6 Mon Sep 17 00:00:00 2001 From: Sline Date: Fri, 19 Dec 2025 18:04:23 +0800 Subject: [PATCH] feat(notice): persist toast position preference (#5621) * feat(notice): persist toast position preference * docs: Changelog.md --- Changelog.md | 1 + src-tauri/src/config/verge.rs | 6 +++ src/components/base/NoticeManager.tsx | 53 ++++++++++++++++--- src/components/setting/mods/layout-viewer.tsx | 36 +++++++++++++ src/locales/ar/settings.json | 7 +++ src/locales/de/settings.json | 7 +++ src/locales/en/settings.json | 7 +++ src/locales/es/settings.json | 7 +++ src/locales/fa/settings.json | 7 +++ src/locales/id/settings.json | 7 +++ src/locales/jp/settings.json | 7 +++ src/locales/ko/settings.json | 7 +++ src/locales/ru/settings.json | 7 +++ src/locales/tr/settings.json | 7 +++ src/locales/tt/settings.json | 7 +++ src/locales/zh/settings.json | 7 +++ src/locales/zhtw/settings.json | 7 +++ src/pages/_layout.tsx | 2 +- src/types/generated/i18n-keys.ts | 5 ++ src/types/generated/i18n-resources.ts | 7 +++ src/types/global.d.ts | 1 + 21 files changed, 195 insertions(+), 7 deletions(-) diff --git a/Changelog.md b/Changelog.md index 085296fc8..476895eb7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ - 允许代理页面允许高级过滤搜索 - 备份设置页面新增导入备份按钮 +- 允许修改通知弹窗位置(「界面设置」->「通知位置」) diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs index ad43af331..5c50529cc 100644 --- a/src-tauri/src/config/verge.rs +++ b/src-tauri/src/config/verge.rs @@ -66,6 +66,10 @@ pub struct IVerge { #[serde(skip_serializing_if = "Option::is_none")] pub menu_order: Option>, + /// toast / notice position on screen + #[serde(skip_serializing_if = "Option::is_none")] + pub notice_position: Option, + /// sysproxy tray icon pub sysproxy_tray_icon: Option, @@ -391,6 +395,7 @@ impl IVerge { #[cfg(target_os = "macos")] tray_icon: Some("monochrome".into()), menu_icon: Some("monochrome".into()), + notice_position: Some("top-right".into()), common_tray_icon: Some(false), sysproxy_tray_icon: Some(false), tun_tray_icon: Some(false), @@ -475,6 +480,7 @@ impl IVerge { patch!(tray_icon); patch!(menu_icon); patch!(menu_order); + patch!(notice_position); patch!(common_tray_icon); patch!(sysproxy_tray_icon); patch!(tun_tray_icon); diff --git a/src/components/base/NoticeManager.tsx b/src/components/base/NoticeManager.tsx index 8bd59c7e2..d573268d0 100644 --- a/src/components/base/NoticeManager.tsx +++ b/src/components/base/NoticeManager.tsx @@ -1,6 +1,12 @@ import { CloseRounded } from "@mui/icons-material"; -import { Snackbar, Alert, IconButton, Box } from "@mui/material"; -import React, { useSyncExternalStore } from "react"; +import { + Snackbar, + Alert, + IconButton, + Box, + type SnackbarOrigin, +} from "@mui/material"; +import React, { useMemo, useSyncExternalStore } from "react"; import { useTranslation } from "react-i18next"; import { @@ -10,8 +16,41 @@ import { } from "@/services/notice-service"; import type { TranslationKey } from "@/types/generated/i18n-keys"; -export const NoticeManager: React.FC = () => { +type NoticePosition = NonNullable; + +const VALID_POSITIONS: NoticePosition[] = [ + "top-left", + "top-right", + "bottom-left", + "bottom-right", +]; + +const resolvePosition = (position?: NoticePosition | null): NoticePosition => { + if (position && VALID_POSITIONS.includes(position)) { + return position; + } + return "top-right"; +}; + +const getAnchorOrigin = (position: NoticePosition): SnackbarOrigin => { + const [vertical, horizontal] = position.split("-") as [ + SnackbarOrigin["vertical"], + SnackbarOrigin["horizontal"], + ]; + return { vertical, horizontal }; +}; + +interface NoticeManagerProps { + position?: NoticePosition | null; +} + +export const NoticeManager: React.FC = ({ position }) => { const { t } = useTranslation(); + const resolvedPosition = useMemo(() => resolvePosition(position), [position]); + const anchorOrigin = useMemo( + () => getAnchorOrigin(resolvedPosition), + [resolvedPosition], + ); const currentNotices = useSyncExternalStore( subscribeNotices, getSnapshotNotices, @@ -25,8 +64,10 @@ export const NoticeManager: React.FC = () => { { ((_, ref) => { + + + e.target.value} + onChange={(value) => onChangeData({ notice_position: value })} + onGuard={(value) => patchVerge({ notice_position: value })} + > + + + + { > {/* 左侧底部窗口控制按钮 */} - +