import { ArrowUpwardRounded, ArrowDownwardRounded, MemoryRounded, LinkRounded, CloudUploadRounded, CloudDownloadRounded, } from "@mui/icons-material"; import { Typography, Paper, alpha, useTheme, PaletteColor, Grid, Box, } from "@mui/material"; import { useRef, useCallback, memo, useMemo } from "react"; import { ReactNode } from "react"; import { useTranslation } from "react-i18next"; import useSWR from "swr"; import { EnhancedCanvasTrafficGraph, type EnhancedCanvasTrafficGraphRef, } from "./enhanced-canvas-traffic-graph"; import { TrafficErrorBoundary } from "@/components/common/traffic-error-boundary"; import { useTrafficDataEnhanced } from "@/hooks/use-traffic-monitor"; import { useVerge } from "@/hooks/use-verge"; import { useVisibility } from "@/hooks/use-visibility"; import { useAppData } from "@/providers/app-data-provider"; import { isDebugEnabled, gc } from "@/services/cmds"; import parseTraffic from "@/utils/parse-traffic"; interface StatCardProps { icon: ReactNode; title: string; value: string | number; unit: string; color: "primary" | "secondary" | "error" | "warning" | "info" | "success"; onClick?: () => void; } // 全局变量类型定义 declare global { interface Window { animationFrameId?: number; lastTrafficData?: { up: number; down: number; }; } } // 统计卡片组件 - 使用memo优化 const CompactStatCard = memo( ({ icon, title, value, unit, color, onClick }: StatCardProps) => { const theme = useTheme(); // 获取调色板颜色 - 使用useMemo避免重复计算 const colorValue = useMemo(() => { const palette = theme.palette; if ( color in palette && palette[color as keyof typeof palette] && "main" in (palette[color as keyof typeof palette] as PaletteColor) ) { return (palette[color as keyof typeof palette] as PaletteColor).main; } return palette.primary.main; }, [theme.palette, color]); return ( {/* 图标容器 */} {icon} {/* 文本内容 */} {title} {value} {unit} ); }, ); // 添加显示名称 CompactStatCard.displayName = "CompactStatCard"; export const EnhancedTrafficStats = () => { const { t } = useTranslation(); const theme = useTheme(); const { verge } = useVerge(); const trafficRef = useRef(null); const pageVisible = useVisibility(); // 使用AppDataProvider const { connections } = useAppData(); // 使用增强版的统一流量数据Hook const { traffic, memory, isLoading, isDataFresh, hasValidData } = useTrafficDataEnhanced(); // 是否显示流量图表 const trafficGraph = verge?.traffic_graph ?? true; // 检查是否支持调试 // TODO: merge this hook with layout-traffic.tsx const { data: isDebug } = useSWR( `clash-verge-rev-internal://isDebugEnabled`, () => isDebugEnabled(), { // default value before is fetched fallbackData: false, }, ); // Canvas组件现在直接从全局Hook获取数据,无需手动添加数据点 // 执行垃圾回收 const handleGarbageCollection = useCallback(async () => { if (isDebug) { try { await gc(); console.log("[Debug] 垃圾回收已执行"); } catch (err) { console.error("[Debug] 垃圾回收失败:", err); } } }, [isDebug]); // 使用useMemo计算解析后的流量数据 const parsedData = useMemo(() => { const [up, upUnit] = parseTraffic(traffic?.raw?.up_rate || 0); const [down, downUnit] = parseTraffic(traffic?.raw?.down_rate || 0); const [inuse, inuseUnit] = parseTraffic(memory?.raw?.inuse || 0); const [uploadTotal, uploadTotalUnit] = parseTraffic( connections.uploadTotal, ); const [downloadTotal, downloadTotalUnit] = parseTraffic( connections.downloadTotal, ); return { up, upUnit, down, downUnit, inuse, inuseUnit, uploadTotal, uploadTotalUnit, downloadTotal, downloadTotalUnit, connectionsCount: connections.count, }; }, [traffic, memory, connections]); // 渲染流量图表 - 使用useMemo缓存渲染结果 const trafficGraphComponent = useMemo(() => { if (!trafficGraph || !pageVisible) return null; return ( trafficRef.current?.toggleStyle()} >
{isDebug && (
DEBUG: {trafficRef.current ? "图表已初始化" : "图表未初始化"}
状态: {isDataFresh ? "active" : "inactive"}
数据新鲜度: {traffic?.is_fresh ? "Fresh" : "Stale"}
{new Date().toISOString().slice(11, 19)}
)}
); }, [trafficGraph, pageVisible, theme.palette.divider, isDebug]); // 使用useMemo计算统计卡片配置 const statCards = useMemo( () => [ { icon: , title: t("Upload Speed"), value: parsedData.up, unit: `${parsedData.upUnit}/s`, color: "secondary" as const, }, { icon: , title: t("Download Speed"), value: parsedData.down, unit: `${parsedData.downUnit}/s`, color: "primary" as const, }, { icon: , title: t("Active Connections"), value: parsedData.connectionsCount, unit: "", color: "success" as const, }, { icon: , title: t("Uploaded"), value: parsedData.uploadTotal, unit: parsedData.uploadTotalUnit, color: "secondary" as const, }, { icon: , title: t("Downloaded"), value: parsedData.downloadTotal, unit: parsedData.downloadTotalUnit, color: "primary" as const, }, { icon: , title: t("Memory Usage"), value: parsedData.inuse, unit: parsedData.inuseUnit, color: "error" as const, onClick: isDebug ? handleGarbageCollection : undefined, }, ], [t, parsedData, isDebug, handleGarbageCollection], ); return ( { console.error("[EnhancedTrafficStats] 组件错误:", error, errorInfo); }} > {trafficGraph && ( {/* 流量图表区域 */} {trafficGraphComponent} )} {/* 统计卡片区域 */} {statCards.map((card, index) => ( ))} {/* 数据状态指示器(调试用)*/} {isDebug && ( 数据状态: {isDataFresh ? "新鲜" : "过期"} | 有效数据:{" "} {hasValidData ? "是" : "否"} | 加载中: {isLoading ? "是" : "否"} )} ); };