diff --git a/src/pages/connections.tsx b/src/pages/connections.tsx index a56195f6..874ab4a8 100644 --- a/src/pages/connections.tsx +++ b/src/pages/connections.tsx @@ -3,7 +3,12 @@ import { useLockFn } from "ahooks"; import { Box, Button, IconButton, MenuItem } from "@mui/material"; import { Virtuoso } from "react-virtuoso"; import { useTranslation } from "react-i18next"; -import { TableChartRounded, TableRowsRounded } from "@mui/icons-material"; +import { + TableChartRounded, + TableRowsRounded, + PlayCircleOutlineRounded, + PauseCircleOutlineRounded, +} from "@mui/icons-material"; import { closeAllConnections } from "@/services/api"; import { useConnectionSetting } from "@/services/states"; import { useClashInfo } from "@/hooks/use-clash"; @@ -58,6 +63,9 @@ const ConnectionsPage = () => { list.sort((a, b) => b.curDownload! - a.curDownload!), }; + const [isPaused, setIsPaused] = useState(false); + const [frozenData, setFrozenData] = useState(null); + const { data: connData = initConn } = useSWRSubscription< IConnections, any, @@ -70,9 +78,7 @@ const ConnectionsPage = () => { `ws://${server}/connections?token=${encodeURIComponent(secret)}`, { onmessage(event) { - // meta v1.15.0 出现 data.connections 为 null 的情况 const data = JSON.parse(event.data) as IConnections; - // 尽量与前一次 connections 的展示顺序保持一致 next(null, (old = initConn) => { const oldConn = old.connections; const maxLen = data.connections?.length; @@ -117,9 +123,13 @@ const ConnectionsPage = () => { }, ); + const displayData = useMemo(() => { + return isPaused ? (frozenData ?? connData) : connData; + }, [isPaused, frozenData, connData]); + const [filterConn, download, upload] = useMemo(() => { const orderFunc = orderOpts[curOrderOpt]; - let connections = connData.connections.filter((conn) => + let connections = displayData.connections.filter((conn) => match(conn.metadata.host || conn.metadata.destinationIP || ""), ); @@ -132,7 +142,7 @@ const ConnectionsPage = () => { upload += x.upload; }); return [connections, download, upload]; - }, [connData, match, curOrderOpt]); + }, [displayData, match, curOrderOpt]); const onCloseAll = useLockFn(closeAllConnections); @@ -142,6 +152,17 @@ const ConnectionsPage = () => { setMatch(() => match); }, []); + const handlePauseToggle = useCallback(() => { + setIsPaused((prev) => { + if (!prev) { + setFrozenData(connData); + } else { + setFrozenData(null); + } + return !prev; + }); + }, [connData]); + return ( { display: "flex", flexDirection: "column", overflow: "auto", - // margin: "0 10px", - // backgroundColor: isDark ? "#282a36" : "#ffffff", borderRadius: "8px", }} header={ @@ -175,16 +194,23 @@ const ConnectionsPage = () => { } > {isTableLayout ? ( - - - + ) : ( - - - + + )} + + + {isPaused ? ( + + ) : ( + )} - @@ -200,7 +226,6 @@ const ConnectionsPage = () => { display: "flex", alignItems: "center", userSelect: "text", - // backgroundColor: isDark ? "#282a36" : "#ffffff", position: "sticky", top: 0, zIndex: 2, @@ -232,7 +257,6 @@ const ConnectionsPage = () => {