From f763fcb244caab8476a79d44f8f40f049ad256bb Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Sat, 13 Jun 2026 14:47:29 +0800 Subject: [PATCH] fix: fallback clash mode from runtime config --- Changelog.md | 1 + src/components/home/clash-mode-card.tsx | 68 +++++++++++-------------- 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/Changelog.md b/Changelog.md index b47fd7c7b..99e39fe0e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ - Linux 托盘可能与其他 tauri 程序托盘冲突导致图标异常 - 修复前端连接页面导致的内存泄漏 - macOS 12(Monterey) 首页 IP 卡兼容性 +- 代理卡可能显示的通信错误,但实际可用
✨ 新增功能 diff --git a/src/components/home/clash-mode-card.tsx b/src/components/home/clash-mode-card.tsx index 94225672b..a9d0ad9de 100644 --- a/src/components/home/clash-mode-card.tsx +++ b/src/components/home/clash-mode-card.tsx @@ -5,10 +5,11 @@ import { } from '@mui/icons-material' import { Box, Paper, Stack, Typography } from '@mui/material' import { useLockFn } from 'ahooks' -import { useMemo } from 'react' +import { type ReactNode } from 'react' import { useTranslation } from 'react-i18next' import { closeAllConnections } from 'tauri-plugin-mihomo-api' +import { useRuntimeConfig } from '@/hooks/use-clash' import { useVerge } from '@/hooks/use-verge' import { useAppRefreshers, @@ -24,6 +25,11 @@ type ClashMode = (typeof CLASH_MODES)[number] const isClashMode = (mode: string): mode is ClashMode => (CLASH_MODES as readonly string[]).includes(mode) +const toClashMode = (mode?: string | null) => { + const normalized = mode?.toLowerCase() + return normalized && isClashMode(normalized) ? normalized : undefined +} + const MODE_META: Record< ClashMode, { label: TranslationKey; description: TranslationKey } @@ -42,6 +48,12 @@ const MODE_META: Record< }, } +const MODE_ICONS: Record = { + rule: , + global: , + direct: , +} + export const ClashModeCard = () => { const { t } = useTranslation() const { verge } = useVerge() @@ -49,39 +61,21 @@ export const ClashModeCard = () => { const { isCoreDataPending } = useCoreDataStatus() const { refreshClashConfig } = useAppRefreshers() - // 支持的模式列表 - const modeList = CLASH_MODES + const controllerMode = toClashMode(clashConfig?.mode) + const { data: runtimeConfig, isPending: isRuntimeConfigPending } = + useRuntimeConfig(!controllerMode) + const runtimeMode = toClashMode(runtimeConfig?.mode) + const currentMode = controllerMode ?? runtimeMode - // 直接使用API返回的模式,不维护本地状态 - const currentMode = clashConfig?.mode?.toLowerCase() - const currentModeKey = - typeof currentMode === 'string' && isClashMode(currentMode) - ? currentMode - : undefined - - const modeDescription = useMemo(() => { - if (currentModeKey) { - return t(MODE_META[currentModeKey].description) - } - if (isCoreDataPending) { - return '\u00A0' - } - return t('home.components.clashMode.errors.communication') - }, [currentModeKey, isCoreDataPending, t]) - - // 模式图标映射 - const modeIcons = useMemo( - () => ({ - rule: , - global: , - direct: , - }), - [], - ) + const modeDescription = currentMode + ? t(MODE_META[currentMode].description) + : isCoreDataPending || isRuntimeConfigPending + ? '\u00A0' + : t('home.components.clashMode.errors.communication') // 切换模式的处理函数 const onChangeMode = useLockFn(async (mode: ClashMode) => { - if (mode === currentModeKey) return + if (mode === currentMode) return if (verge?.auto_close_connection) { closeAllConnections() } @@ -104,8 +98,8 @@ export const ClashModeCard = () => { alignItems: 'center', justifyContent: 'center', gap: 1, - bgcolor: mode === currentModeKey ? 'primary.main' : 'background.paper', - color: mode === currentModeKey ? 'primary.contrastText' : 'text.primary', + bgcolor: mode === currentMode ? 'primary.main' : 'background.paper', + color: mode === currentMode ? 'primary.contrastText' : 'text.primary', borderRadius: 1.5, transition: 'all 0.2s ease-in-out', position: 'relative', @@ -118,7 +112,7 @@ export const ClashModeCard = () => { transform: 'translateY(1px)', }, '&::after': - mode === currentModeKey + mode === currentMode ? { content: '""', position: 'absolute', @@ -161,19 +155,19 @@ export const ClashModeCard = () => { zIndex: 2, }} > - {modeList.map((mode) => ( + {CLASH_MODES.map((mode) => ( onChangeMode(mode)} sx={buttonStyles(mode)} > - {modeIcons[mode]} + {MODE_ICONS[mode]} {t(MODE_META[mode].label)}