mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-28 07:14:40 +08:00
refactor: home components
This commit is contained in:
@@ -31,7 +31,7 @@ export const ClashModeCard = () => {
|
||||
);
|
||||
}
|
||||
return t("Core communication error");
|
||||
}, [currentMode]);
|
||||
}, [currentMode, t]);
|
||||
|
||||
// 模式图标映射
|
||||
const modeIcons = useMemo(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user