perf: improve Clash mode switch responsiveness on home card

This commit is contained in:
wonfen 2025-03-23 04:54:18 +08:00
parent 7cb0c8173a
commit 15fd8b17c3
3 changed files with 38 additions and 39 deletions

View File

@ -9,24 +9,27 @@
2.2.1 相对于 2.2.0(已下架不在提供) 2.2.1 相对于 2.2.0(已下架不在提供)
修复了: 修复了:
1. **首页** 1. **首页**
- 修复 Direct 模式首页无法渲染。 - 修复 Direct 模式首页无法渲染
- 修复 首页启用轻量模式导致 ClashVergeRev 从托盘退出。 - 修复 首页启用轻量模式导致 ClashVergeRev 从托盘退出
- 增加 首页文本过长自动截断
- 修复 系统代理标识判断不准的问题 - 修复 系统代理标识判断不准的问题
- 修复 系统代理地址错误的问题 - 修复 系统代理地址错误的问题
- 代理模式“多余的切换动画”
2. **系统** 2. **系统**
- 增加 在 ClashVergeRev 对 Mihomo 进行操作时,总是尝试确保两者运行。
- 修复 MacOS 无法使用快捷键粘贴/选择/复制订阅地址。 - 修复 MacOS 无法使用快捷键粘贴/选择/复制订阅地址。
- 修复 代理端口设置同步问题。 - 修复 代理端口设置同步问题。
- 修复 Linux 无法与 Mihomo 核心 和 ClashVergeRev 服务通信。 - 修复 Linux 无法与 Mihomo 核心 和 ClashVergeRev 服务通信
- 增加 服务器模式下启动mihomo内核的时候查找并停止其他已经存在的内核进程防止内核假死等问题带来的通信失败。
3. **界面** 3. **界面**
- 修复 连接详情卡没有跟随主题色 - 修复 连接详情卡没有跟随主题色
新增了: 新增了:
1. **轻量模式** 1. **首页**
- 首页文本过长自动截断
2. **轻量模式**
- 新增托盘进入轻量模式支持 - 新增托盘进入轻量模式支持
- 新增进入轻量模式快捷键支持 - 新增进入轻量模式快捷键支持
3. **系统**
- 在 ClashVergeRev 对 Mihomo 进行操作时,总是尝试确保两者运行
- 服务器模式下启动mihomo内核的时候查找并停止其他已经存在的内核进程防止内核假死等问题带来的通信失败
--- ---

View File

@ -10,7 +10,7 @@ import {
MultipleStopRounded, MultipleStopRounded,
DirectionsRounded, DirectionsRounded,
} from "@mui/icons-material"; } from "@mui/icons-material";
import { useState, useEffect, useMemo } from "react"; import { useMemo } from "react";
export const ClashModeCard = () => { export const ClashModeCard = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -20,21 +20,19 @@ export const ClashModeCard = () => {
const { data: clashConfig, mutate: mutateClash } = useSWR( const { data: clashConfig, mutate: mutateClash } = useSWR(
"getClashConfig", "getClashConfig",
getClashConfig, getClashConfig,
{ revalidateOnFocus: false } {
revalidateOnFocus: false,
revalidateIfStale: true,
dedupingInterval: 1000,
errorRetryInterval: 5000
}
); );
// 支持的模式列表 // 支持的模式列表
const modeList = useMemo(() => ["rule", "global", "direct"] as const, []); const modeList = useMemo(() => ["rule", "global", "direct"] as const, []);
// 本地状态记录当前模式 // 直接使用API返回的模式不维护本地状态
const [localMode, setLocalMode] = useState<string>("rule"); const currentMode = clashConfig?.mode?.toLowerCase();
// 当从API获取到当前模式时更新本地状态
useEffect(() => {
if (clashConfig?.mode) {
setLocalMode(clashConfig.mode.toLowerCase());
}
}, [clashConfig]);
// 模式图标映射 // 模式图标映射
const modeIcons = useMemo(() => ({ const modeIcons = useMemo(() => ({
@ -45,10 +43,7 @@ export const ClashModeCard = () => {
// 切换模式的处理函数 // 切换模式的处理函数
const onChangeMode = useLockFn(async (mode: string) => { const onChangeMode = useLockFn(async (mode: string) => {
if (mode === localMode) return; if (mode === currentMode) return;
setLocalMode(mode);
if (verge?.auto_close_connection) { if (verge?.auto_close_connection) {
closeAllConnections(); closeAllConnections();
} }
@ -58,9 +53,6 @@ export const ClashModeCard = () => {
mutateClash(); mutateClash();
} catch (error) { } catch (error) {
console.error("Failed to change mode:", error); console.error("Failed to change mode:", error);
if (clashConfig?.mode) {
setLocalMode(clashConfig.mode.toLowerCase());
}
} }
}); });
@ -73,8 +65,8 @@ export const ClashModeCard = () => {
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
gap: 1, gap: 1,
bgcolor: mode === localMode ? "primary.main" : "background.paper", bgcolor: mode === currentMode ? "primary.main" : "background.paper",
color: mode === localMode ? "primary.contrastText" : "text.primary", color: mode === currentMode ? "primary.contrastText" : "text.primary",
borderRadius: 1.5, borderRadius: 1.5,
transition: "all 0.2s ease-in-out", transition: "all 0.2s ease-in-out",
position: "relative", position: "relative",
@ -86,7 +78,7 @@ export const ClashModeCard = () => {
"&:active": { "&:active": {
transform: "translateY(1px)", transform: "translateY(1px)",
}, },
"&::after": mode === localMode "&::after": mode === currentMode
? { ? {
content: '""', content: '""',
position: "absolute", position: "absolute",
@ -132,7 +124,7 @@ export const ClashModeCard = () => {
{modeList.map((mode) => ( {modeList.map((mode) => (
<Paper <Paper
key={mode} key={mode}
elevation={mode === localMode ? 2 : 0} elevation={mode === currentMode ? 2 : 0}
onClick={() => onChangeMode(mode)} onClick={() => onChangeMode(mode)}
sx={buttonStyles(mode)} sx={buttonStyles(mode)}
> >
@ -141,7 +133,7 @@ export const ClashModeCard = () => {
variant="body2" variant="body2"
sx={{ sx={{
textTransform: "capitalize", textTransform: "capitalize",
fontWeight: mode === localMode ? 600 : 400, fontWeight: mode === currentMode ? 600 : 400,
}} }}
> >
{t(mode)} {t(mode)}
@ -161,15 +153,13 @@ export const ClashModeCard = () => {
overflow: "visible", overflow: "visible",
}} }}
> >
<Fade in={true} timeout={200}> <Typography
<Typography variant="caption"
variant="caption" component="div"
component="div" sx={descriptionStyles}
sx={descriptionStyles} >
> {t(`${currentMode} Mode Description`)}
{t(`${localMode} Mode Description`)} </Typography>
</Typography>
</Fade>
</Box> </Box>
</Box> </Box>
); );

View File

@ -16,6 +16,12 @@ const ProxyPage = () => {
const { data: clashConfig, mutate: mutateClash } = useSWR( const { data: clashConfig, mutate: mutateClash } = useSWR(
"getClashConfig", "getClashConfig",
getClashConfig, getClashConfig,
{
revalidateOnFocus: false,
revalidateIfStale: true,
dedupingInterval: 1000,
errorRetryInterval: 5000
}
); );
const { verge } = useVerge(); const { verge } = useVerge();