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");
}, [currentMode]);
}, [currentMode, t]);
// 模式图标映射
const modeIcons = useMemo(

View File

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

View File

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

View File

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