refactor: home components

This commit is contained in:
Slinetrac
2025-10-14 21:57:33 +08:00
parent 8dbe3f8c48
commit 06dc7a6ef4
4 changed files with 79 additions and 38 deletions

View File

@@ -31,7 +31,7 @@ export const ClashModeCard = () => {
); );
} }
return t("Core communication error"); return t("Core communication error");
}, [currentMode]); }, [currentMode, t]);
// 模式图标映射 // 模式图标映射
const modeIcons = useMemo( const modeIcons = useMemo(

View File

@@ -6,6 +6,7 @@ import {
useEffect, useEffect,
useImperativeHandle, useImperativeHandle,
useMemo, useMemo,
useReducer,
useRef, useRef,
useState, useState,
} from "react"; } from "react";
@@ -80,6 +81,11 @@ interface EnhancedCanvasTrafficGraphProps {
ref?: Ref<EnhancedCanvasTrafficGraphRef>; ref?: Ref<EnhancedCanvasTrafficGraphRef>;
} }
const displayDataReducer = (
_: ITrafficDataPoint[],
payload: ITrafficDataPoint[],
): ITrafficDataPoint[] => payload;
/** /**
* 稳定版Canvas流量图表组件 * 稳定版Canvas流量图表组件
* 修复闪烁问题,添加时间轴显示 * 修复闪烁问题,添加时间轴显示
@@ -118,7 +124,11 @@ export const EnhancedCanvasTrafficGraph = memo(
const isInitializedRef = useRef<boolean>(false); const isInitializedRef = useRef<boolean>(false);
// 当前显示的数据缓存 // 当前显示的数据缓存
const [displayData, setDisplayData] = useState<ITrafficDataPoint[]>([]); const [displayData, dispatchDisplayData] = useReducer(
displayDataReducer,
[],
);
const debounceTimeoutRef = useRef<number | null>(null);
// 主题颜色配置 // 主题颜色配置
const colors = useMemo( const colors = useMemo(
@@ -133,26 +143,27 @@ export const EnhancedCanvasTrafficGraph = memo(
); );
// 更新显示数据(防抖处理) // 更新显示数据(防抖处理)
const updateDisplayDataDebounced = useMemo(() => { const updateDisplayData = useCallback((newData: ITrafficDataPoint[]) => {
let timeoutId: number; if (debounceTimeoutRef.current !== null) {
return (newData: ITrafficDataPoint[]) => { window.clearTimeout(debounceTimeoutRef.current);
clearTimeout(timeoutId); }
timeoutId = window.setTimeout(() => { debounceTimeoutRef.current = window.setTimeout(() => {
setDisplayData(newData); dispatchDisplayData(newData);
}, 50); // 50ms防抖 }, 50); // 50ms防抖
};
}, []); }, []);
// 监听数据变化 // 监听数据变化
useEffect(() => { useEffect(() => {
const timeRangeData = getDataForTimeRange(timeRange); const timeRangeData = getDataForTimeRange(timeRange);
updateDisplayDataDebounced(timeRangeData); updateDisplayData(timeRangeData);
}, [
dataPoints, return () => {
timeRange, if (debounceTimeoutRef.current !== null) {
getDataForTimeRange, window.clearTimeout(debounceTimeoutRef.current);
updateDisplayDataDebounced, debounceTimeoutRef.current = null;
]); }
};
}, [dataPoints, timeRange, getDataForTimeRange, updateDisplayData]);
// Y轴坐标计算 - 基于刻度范围的线性映射 // Y轴坐标计算 - 基于刻度范围的线性映射
const calculateY = useCallback( const calculateY = useCallback(

View File

@@ -278,7 +278,7 @@ export const EnhancedTrafficStats = () => {
</Grid> </Grid>
)} )}
{/* 统计卡片区域 */} {/* 统计卡片区域 */}
{statCards.map((card, _index) => ( {statCards.map((card) => (
<Grid key={card.title} size={4}> <Grid key={card.title} size={4}>
<CompactStatCard {...(card as StatCardProps)} /> <CompactStatCard {...(card as StatCardProps)} />
</Grid> </Grid>

View File

@@ -16,7 +16,7 @@ import {
} from "@mui/material"; } from "@mui/material";
import { check as checkUpdate } from "@tauri-apps/plugin-updater"; import { check as checkUpdate } from "@tauri-apps/plugin-updater";
import { useLockFn } from "ahooks"; import { useLockFn } from "ahooks";
import { useCallback, useEffect, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useReducer } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import useSWR from "swr"; import useSWR from "swr";
@@ -30,6 +30,29 @@ import { version as appVersion } from "@root/package.json";
import { EnhancedCard } from "./enhanced-card"; import { EnhancedCard } from "./enhanced-card";
interface SystemState {
osInfo: string;
lastCheckUpdate: string;
}
type SystemStateAction =
| { type: "set-os-info"; payload: string }
| { type: "set-last-check-update"; payload: string };
const systemStateReducer = (
state: SystemState,
action: SystemStateAction,
): SystemState => {
switch (action.type) {
case "set-os-info":
return { ...state, osInfo: action.payload };
case "set-last-check-update":
return { ...state, lastCheckUpdate: action.payload };
default:
return state;
}
};
export const SystemInfoCard = () => { export const SystemInfoCard = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { verge, patchVerge } = useVerge(); const { verge, patchVerge } = useVerge();
@@ -38,13 +61,15 @@ export const SystemInfoCard = () => {
const { installServiceAndRestartCore } = useServiceInstaller(); const { installServiceAndRestartCore } = useServiceInstaller();
// 系统信息状态 // 系统信息状态
const [systemState, setSystemState] = useState({ const [systemState, dispatchSystemState] = useReducer(systemStateReducer, {
osInfo: "", osInfo: "",
lastCheckUpdate: "-", lastCheckUpdate: "-",
}); });
// 初始化系统信息 // 初始化系统信息
useEffect(() => { useEffect(() => {
let timeoutId: number | undefined;
getSystemInfo() getSystemInfo()
.then((info) => { .then((info) => {
const lines = info.split("\n"); const lines = info.split("\n");
@@ -59,10 +84,10 @@ export const SystemInfoCard = () => {
sysVersion = sysVersion.substring(sysName.length).trim(); sysVersion = sysVersion.substring(sysName.length).trim();
} }
setSystemState((prev) => ({ dispatchSystemState({
...prev, type: "set-os-info",
osInfo: `${sysName} ${sysVersion}`, payload: `${sysName} ${sysVersion}`,
})); });
} }
}) })
.catch(console.error); .catch(console.error);
@@ -73,10 +98,10 @@ export const SystemInfoCard = () => {
try { try {
const timestamp = parseInt(lastCheck, 10); const timestamp = parseInt(lastCheck, 10);
if (!isNaN(timestamp)) { if (!isNaN(timestamp)) {
setSystemState((prev) => ({ dispatchSystemState({
...prev, type: "set-last-check-update",
lastCheckUpdate: new Date(timestamp).toLocaleString(), payload: new Date(timestamp).toLocaleString(),
})); });
} }
} catch (e) { } catch (e) {
console.error("Error parsing last check update time", e); console.error("Error parsing last check update time", e);
@@ -85,18 +110,23 @@ export const SystemInfoCard = () => {
// 如果启用了自动检查更新但没有记录,设置当前时间并延迟检查 // 如果启用了自动检查更新但没有记录,设置当前时间并延迟检查
const now = Date.now(); const now = Date.now();
localStorage.setItem("last_check_update", now.toString()); localStorage.setItem("last_check_update", now.toString());
setSystemState((prev) => ({ dispatchSystemState({
...prev, type: "set-last-check-update",
lastCheckUpdate: new Date(now).toLocaleString(), payload: new Date(now).toLocaleString(),
})); });
setTimeout(() => { timeoutId = window.setTimeout(() => {
if (verge?.auto_check_update) { if (verge?.auto_check_update) {
checkUpdate().catch(console.error); checkUpdate().catch(console.error);
} }
}, 5000); }, 5000);
} }
}, [verge?.auto_check_update]); return () => {
if (timeoutId !== undefined) {
window.clearTimeout(timeoutId);
}
};
}, [verge?.auto_check_update, dispatchSystemState]);
// 自动检查更新逻辑 // 自动检查更新逻辑
useSWR( useSWR(
@@ -104,10 +134,10 @@ export const SystemInfoCard = () => {
async () => { async () => {
const now = Date.now(); const now = Date.now();
localStorage.setItem("last_check_update", now.toString()); localStorage.setItem("last_check_update", now.toString());
setSystemState((prev) => ({ dispatchSystemState({
...prev, type: "set-last-check-update",
lastCheckUpdate: new Date(now).toLocaleString(), payload: new Date(now).toLocaleString(),
})); });
return await checkUpdate(); return await checkUpdate();
}, },
{ {