From 82d76113f28ebccaa29b98379c49e2bfedebf45a Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Fri, 11 Sep 2026 10:02:03 +0800 Subject: [PATCH] refactor(frontend): drop dead code in traffic and ws pipelines Removes zero-consumer surface verified by repo-wide grep: the reference-count render machinery, the never-called clearData chain, unread snapshot fields (rangeMinutes, reason), dead refresh callbacks on the connection hooks, the write-only wsRef sync, and the worker's unreachable DEFAULT_CONFIG placeholder (now definite assignment under the init-first client contract). No behavior change; the compressed sampler path, samplerStats diagnostics, and lastTimestamp perf contract stay. Net -120 lines across six files. --- .../home/enhanced-traffic-stats.tsx | 11 ---- src/hooks/use-connection-data.ts | 19 ------ src/hooks/use-mihomo-ws-subscription.ts | 20 +----- src/hooks/use-traffic-monitor.ts | 64 +++---------------- src/services/traffic-monitor-worker.ts | 43 ++++--------- src/types/global.d.ts | 13 ---- 6 files changed, 25 insertions(+), 145 deletions(-) diff --git a/src/components/home/enhanced-traffic-stats.tsx b/src/components/home/enhanced-traffic-stats.tsx index 7bea75d22..39d68a850 100644 --- a/src/components/home/enhanced-traffic-stats.tsx +++ b/src/components/home/enhanced-traffic-stats.tsx @@ -39,17 +39,6 @@ interface StatCardProps { onClick?: () => void } -// 全局变量类型定义 -declare global { - interface Window { - animationFrameId?: number - lastTrafficData?: { - up: number - down: number - } - } -} - // 统计卡片组件 - 使用memo优化 const CompactStatCard = memo( ({ icon, title, value, unit, color, onClick }: StatCardProps) => { diff --git a/src/hooks/use-connection-data.ts b/src/hooks/use-connection-data.ts index 510cbef26..d74cde2fe 100644 --- a/src/hooks/use-connection-data.ts +++ b/src/hooks/use-connection-data.ts @@ -258,7 +258,6 @@ const clearPendingMessage = () => { interface SocketSupervisor { start: () => void stopIfIdle: () => void - reconnect: () => Promise } const createSocketSupervisor = (options: { @@ -349,7 +348,6 @@ const createSocketSupervisor = (options: { clearReconnectTimer() void closeSocket() }, - reconnect, } } @@ -405,15 +403,6 @@ const subscribeConnectionSummary = (listener: ConnectionListener) => { } } -const refreshConnectionData = () => { - clearPendingMessage() - void connectionSupervisor.reconnect() -} - -const refreshConnectionSummary = () => { - void summarySupervisor.reconnect() -} - const clearClosedConnectionData = () => { if (connectionData.closedConnections.length === 0) return connectionData = { @@ -436,16 +425,12 @@ export const useConnectionData = (options?: { enabled?: boolean }) => { getConnectionSnapshot, ) const response = useMemo(() => ({ data }), [data]) - const refreshGetClashConnection = useCallback(() => { - refreshConnectionData() - }, []) const clearClosedConnections = useCallback(() => { clearClosedConnectionData() }, []) return { response, - refreshGetClashConnection, clearClosedConnections, } } @@ -463,12 +448,8 @@ export const useConnectionSummaryData = (options?: { enabled?: boolean }) => { getConnectionSummarySnapshot, ) const response = useMemo(() => ({ data }), [data]) - const refreshGetClashConnectionSummary = useCallback(() => { - refreshConnectionSummary() - }, []) return { response, - refreshGetClashConnectionSummary, } } diff --git a/src/hooks/use-mihomo-ws-subscription.ts b/src/hooks/use-mihomo-ws-subscription.ts index 9cf4debaf..c0a4cea09 100644 --- a/src/hooks/use-mihomo-ws-subscription.ts +++ b/src/hooks/use-mihomo-ws-subscription.ts @@ -1,5 +1,5 @@ import { useLocalStorage } from 'foxact/use-local-storage' -import { type MutableRefObject, useCallback, useEffect, useRef } from 'react' +import { useCallback, useEffect, useRef } from 'react' import { type Message, type MihomoWebSocket } from 'tauri-plugin-mihomo-api' import { @@ -22,7 +22,6 @@ interface SharedSubscriptionEntry { ws: MihomoWebSocket | null reconnectTimer: ReturnType | null connecting: boolean - refHolders: Set> owners: Set activeOwner: SharedSubscriptionOwner | null closed: boolean @@ -42,12 +41,6 @@ const writeSubscriptionSnapshot = (key: string, data: T) => { void setCacheData([key], data) } -const syncSharedWsRefs = (entry: SharedSubscriptionEntry) => { - entry.refHolders.forEach((ref) => { - ref.current = entry.ws - }) -} - const pickActiveOwner = (entry: SharedSubscriptionEntry) => { if (entry.activeOwner?.isMounted()) return entry.activeOwner @@ -67,7 +60,6 @@ const closeSharedSocket = async (entry: SharedSubscriptionEntry) => { if (!ws) return entry.ws = null - syncSharedWsRefs(entry) await ws.close() } @@ -79,7 +71,6 @@ const createSharedSubscriptionEntry = ( ws: null, reconnectTimer: null, connecting: false, - refHolders: new Set(), owners: new Set(), activeOwner: null, closed: false, @@ -121,7 +112,6 @@ const createSharedSubscriptionEntry = ( }) entry.ws = ws - syncSharedWsRefs(entry) clearReconnectTimer() } catch (ignoreError) { if (!entry.closed && !entry.ws) { @@ -207,8 +197,6 @@ export const useMihomoWsSubscription = ( const responseCacheKey = subscriptionCacheKey ?? lastSubscriptionCacheKeyRef.current - const wsRef = useRef(null) - const resolveNextData = useCallback( ( data: T | ((current?: T) => T | undefined) | undefined, @@ -246,8 +234,6 @@ export const useMihomoWsSubscription = ( } entry.refs += 1 - entry.refHolders.add(wsRef) - wsRef.current = entry.ws let throttleCleanup: (() => void) | undefined let wrappedNext: NextFn @@ -331,8 +317,6 @@ export const useMihomoWsSubscription = ( return () => { isMounted = false - entry.refHolders.delete(wsRef) - wsRef.current = null entry.owners.delete(owner) owner.cleanup?.() @@ -376,5 +360,5 @@ export const useMihomoWsSubscription = ( [responseCacheKey], ) - return { response, refresh, setData, wsRef } + return { response, refresh, setData } } diff --git a/src/hooks/use-traffic-monitor.ts b/src/hooks/use-traffic-monitor.ts index c4d0b7a45..97fe30f7c 100644 --- a/src/hooks/use-traffic-monitor.ts +++ b/src/hooks/use-traffic-monitor.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useReducer, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { Traffic } from 'tauri-plugin-mihomo-api' import { useVisibility } from '@/hooks/use-visibility' @@ -8,33 +8,17 @@ import { TrafficDataSampler, isSameTrafficData } from '@/utils/traffic-sampler' // 引用计数管理器 class ReferenceCounter { private count = 0 - private callbacks = new Set<() => void>() - - private notify() { - this.callbacks.forEach((cb) => { - cb() - }) - } increment(): () => void { this.count++ debugLog(`[ReferenceCounter] 引用计数增加: ${this.count}`) - this.notify() - return () => { this.count-- debugLog(`[ReferenceCounter] 引用计数减少: ${this.count}`) - - this.notify() } } - onCountChange(callback: () => void) { - this.callbacks.add(callback) - return () => this.callbacks.delete(callback) - } - getCount(): number { return this.count } @@ -96,10 +80,10 @@ class InlineTrafficMonitor { if (this.throttleTimer !== null) return const slice = this.sampler.getDataForTimeRange(this.currentRange) if (!isSameTrafficData(this.lastBroadcast, slice)) { - this.emitSnapshot('interval') + this.emitSnapshot() } }, 1000) - this.emitSnapshot('init') + this.emitSnapshot() break } case 'append': { @@ -112,24 +96,18 @@ class InlineTrafficMonitor { this.lastTimestamp = timestamp this.sampler.addDataPoint(dataPoint) - this.scheduleSnapshot('append-throttle') - break - } - case 'clear': { - this.sampler.clear() - this.lastTimestamp = undefined - this.emitSnapshot('clear') + this.scheduleSnapshot() break } case 'setRange': { if (this.currentRange !== message.minutes) { this.currentRange = message.minutes - this.emitSnapshot('range-change') + this.emitSnapshot() } break } case 'requestSnapshot': { - this.emitSnapshot('request') + this.emitSnapshot() break } default: @@ -137,25 +115,23 @@ class InlineTrafficMonitor { } } - private emitSnapshot(reason: ITrafficWorkerSnapshotMessage['reason']) { + private emitSnapshot() { const dataPoints = this.sampler.getDataForTimeRange(this.currentRange) this.emit({ type: 'snapshot', dataPoints, samplerStats: this.sampler.getStats(), - rangeMinutes: this.currentRange, lastTimestamp: this.lastTimestamp, - reason, }) this.lastBroadcast = dataPoints } - private scheduleSnapshot(reason: ITrafficWorkerSnapshotMessage['reason']) { + private scheduleSnapshot() { if (this.throttleTimer !== null) return this.throttleTimer = setTimeout(() => { this.throttleTimer = null - this.emitSnapshot(reason) + this.emitSnapshot() }, this.config.snapshotIntervalMs) } } @@ -331,11 +307,6 @@ class TrafficWorkerClient { }) } - clearData() { - this.ensureStarted() - this.post({ type: 'clear' }) - } - setRange(minutes: number) { this.currentRange = minutes this.post({ type: 'setRange', minutes }) @@ -382,7 +353,6 @@ export const useTrafficMonitorEnhanced = (options?: { dataPoints: [], samplerStats: EMPTY_STATS, }) - const [, forceRefCountRender] = useReducer((value) => value + 1, 0) const clientRef = useRef(getWorkerClient()) const currentRangeRef = useRef(WORKER_CONFIG.defaultRangeMinutes) @@ -396,9 +366,6 @@ export const useTrafficMonitorEnhanced = (options?: { const client = getWorkerClient() clientRef.current = client - const stopWatchRefCount = refCounter.onCountChange(() => - forceRefCountRender(), - ) const cleanup = refCounter.increment() client.start(currentRangeRef.current) @@ -415,7 +382,6 @@ export const useTrafficMonitorEnhanced = (options?: { return () => { unsubscribe?.() - stopWatchRefCount() cleanup() if (refCounter.getCount() === 0) { client.stop() @@ -449,21 +415,13 @@ export const useTrafficMonitorEnhanced = (options?: { [enabled], ) - // 清空数据 - const clearData = useCallback(() => { - if (!enabled) return - clientRef.current?.clearData() - }, [enabled]) - return { graphData: { dataPoints: enabled ? latestSnapshot.dataPoints : EMPTY_DATA, requestRange, appendData, - clearData, }, samplerStats: latestSnapshot.samplerStats, - referenceCount: refCounter.getCount(), } } @@ -471,12 +429,10 @@ export const useTrafficMonitorEnhanced = (options?: { * 图表数据Hook */ export const useTrafficGraphDataEnhanced = () => { - const { graphData, samplerStats, referenceCount } = - useTrafficMonitorEnhanced() + const { graphData, samplerStats } = useTrafficMonitorEnhanced() return { ...graphData, samplerStats, - referenceCount, } } diff --git a/src/services/traffic-monitor-worker.ts b/src/services/traffic-monitor-worker.ts index 6d51607be..eaf2b7c20 100644 --- a/src/services/traffic-monitor-worker.ts +++ b/src/services/traffic-monitor-worker.ts @@ -1,16 +1,5 @@ import { TrafficDataSampler, isSameTrafficData } from '../utils/traffic-sampler' -const DEFAULT_CONFIG: ISamplingConfig & { - snapshotIntervalMs: number - defaultRangeMinutes: number -} = { - rawDataMinutes: 10, - compressedDataMinutes: 60, - compressionRatio: 5, - snapshotIntervalMs: 250, - defaultRangeMinutes: 10, -} - interface WorkerScope { postMessage: (message: unknown) => void onmessage: ((event: MessageEvent) => void) | null @@ -22,14 +11,16 @@ interface WorkerScope { const ctx: WorkerScope = self as unknown as WorkerScope -let config = { ...DEFAULT_CONFIG } -let sampler = new TrafficDataSampler(config) -let currentRangeMinutes = config.defaultRangeMinutes +// 'init' is the first message posted by the client, so these are always +// assigned before first use. +let config!: ITrafficWorkerInitMessage['config'] +let sampler!: TrafficDataSampler +let currentRangeMinutes!: number let throttleTimer: ReturnType | null = null let lastTimestamp: number | undefined let lastBroadcast: ITrafficDataPoint[] = [] -const broadcastSnapshot = (reason: ITrafficWorkerSnapshotMessage['reason']) => { +const broadcastSnapshot = () => { const dataPoints = sampler.getDataForTimeRange(currentRangeMinutes) const samplerStats = sampler.getStats() @@ -37,20 +28,18 @@ const broadcastSnapshot = (reason: ITrafficWorkerSnapshotMessage['reason']) => { type: 'snapshot', dataPoints, samplerStats, - rangeMinutes: currentRangeMinutes, lastTimestamp, - reason, } ctx.postMessage(message) lastBroadcast = dataPoints } -const scheduleSnapshot = (reason: ITrafficWorkerSnapshotMessage['reason']) => { +const scheduleSnapshot = () => { if (throttleTimer !== null) return throttleTimer = ctx.setTimeout(() => { throttleTimer = null - broadcastSnapshot(reason) + broadcastSnapshot() }, config.snapshotIntervalMs) } @@ -68,10 +57,10 @@ ctx.onmessage = (event: MessageEvent) => { if (throttleTimer !== null) return const slice = sampler.getDataForTimeRange(currentRangeMinutes) if (!isSameTrafficData(lastBroadcast, slice)) { - broadcastSnapshot('interval') + broadcastSnapshot() } }, 1000) - broadcastSnapshot('init') + broadcastSnapshot() break } case 'append': { @@ -84,24 +73,18 @@ ctx.onmessage = (event: MessageEvent) => { lastTimestamp = timestamp sampler.addDataPoint(dataPoint) - scheduleSnapshot('append-throttle') - break - } - case 'clear': { - sampler.clear() - lastTimestamp = undefined - broadcastSnapshot('clear') + scheduleSnapshot() break } case 'setRange': { if (currentRangeMinutes !== message.minutes) { currentRangeMinutes = message.minutes - broadcastSnapshot('range-change') + broadcastSnapshot() } break } case 'requestSnapshot': { - broadcastSnapshot('request') + broadcastSnapshot() break } default: diff --git a/src/types/global.d.ts b/src/types/global.d.ts index 10871c074..33ee5c50b 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -1005,10 +1005,6 @@ interface ITrafficWorkerAppendMessage { } } -interface ITrafficWorkerClearMessage { - type: 'clear' -} - interface ITrafficWorkerSetRangeMessage { type: 'setRange' minutes: number @@ -1021,7 +1017,6 @@ interface ITrafficWorkerRequestSnapshotMessage { type TrafficWorkerRequestMessage = | ITrafficWorkerInitMessage | ITrafficWorkerAppendMessage - | ITrafficWorkerClearMessage | ITrafficWorkerSetRangeMessage | ITrafficWorkerRequestSnapshotMessage @@ -1029,15 +1024,7 @@ interface ITrafficWorkerSnapshotMessage { type: 'snapshot' dataPoints: ITrafficDataPoint[] samplerStats: ISamplerStats - rangeMinutes: number lastTimestamp?: number - reason: - | 'init' - | 'interval' - | 'range-change' - | 'request' - | 'append-throttle' - | 'clear' } interface ITrafficWorkerLogMessage {