refactor: home components
This commit is contained in:
@@ -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(
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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();
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user