The mihomo ws subscription's next callback accepted an error half that
baseNext silently discarded while traffic, memory and log consumers
kept constructing fallback payloads for it. Refresh minted a fresh
SWR key per call via a localStorage timestamp, abandoning old keys in
the cache forever. Reduce next to its data half and reset the snapshot
under a stable key instead.
Consolidate ordinary query snapshots on SWR and make Profiles own its query key, cache mutation, and invalidation policy.
Impact:
- remove the generic synchronous query Map while keeping dedicated Mihomo WebSocket snapshots
- eliminate duplicate Profiles refreshes while preserving retries and the 800 ms event throttle
- preserve preload-backed Verge updates and system proxy rollback behavior
- scope uptime polling to the Home Clash info card instead of the app lifetime
- leave RunState, Connections, Traffic, backend, and IPC contracts unchanged
- reduce frontend code by 72 net lines without adding dependencies
WebSocket hooks (use-connection-data, use-log-data)
- Single-pass merge for connection snapshots; reuse previous row reference
when upload/download are unchanged so downstream memos can bail out
- Single-allocation cap on closedConnections (no double concat+slice)
- Single-allocation clamp in appendLogs
- Cache dayjs().format result within each 50ms log flush window
Connection table (connection-table.tsx)
- Decouple 5s relative-time tick from columnDefs via shared module-level
tickStore + memoised RelativeTimeCell so the tick no longer rebuilds
the table
- RowComponent memo with custom comparator (relies on stable row reference)
- Lift sx objects to module scope
- Stable onShowDetail via ref
App data provider (app-data-provider, app-data-context)
- Split monolithic context into six sub-contexts (Proxies/Rules/ClashConfig/
System/Uptime/Refreshers); 3s uptime ticks no longer invalidate unrelated
consumers
- useAppData adapter aggregates sub-contexts; consumer files unchanged
- useStableFn helper stabilises all refresh* callback identities
- Extract useCtx helper to remove repeated null-check boilerplate
Canvas traffic graph (enhanced-canvas-traffic-graph, use-traffic-monitor)
- Lift Y-axis scale (max/min) to drawGraph layer; calculateY allocations
per frame: ~600 -> 1
- Document visibility gate stops RAF and the setNow interval when the
window is hidden; appendData unaffected
- Reuse the existing visibilitychange listener instead of adding a second
one; isDocumentVisibleRef guards animate() inside the frame
- Convert forEach arrow shorthands to block bodies
- Drop unnecessary state-setter deps from a useCallback
Proxy groups (proxy-groups, proxy-render, use-render-list)
- Narrow proxyColItemsMemo dep: headState -> headState.showType
- Per-group fingerprint cache + prevListRef in use-render-list; steady-state
refetch ticks become O(0) and the list reference stays stable when nothing
changed
- useStableCallback wraps handleCheckAll / handleLocation
Replace swr with @tanstack/react-query v5 across all hooks, providers,
and components. Introduce singleton QueryClient, WS subscription pattern
via useQuery+useEffect, and enforce component-layer cache access contract.
Preserve SWR cache in onConnected to avoid replacing accumulated logs
with kernel buffer on reconnect. Add KeepAlive for the logs page so
its DOM stays mounted across route changes, removing the visible blank
window when navigating back.
* feat: migrate logs API from REST to IPC streaming
- Replace REST API `/logs` calls with IPC streaming implementation
- Add new `src-tauri/src/ipc/logs.rs` with `LogsMonitor` for real-time log streaming
- Implement duplicate stream prevention with level tracking
- Add frontend-backend communication via Tauri commands for log management
- Remove WebSocket compatibility, maintain IPC-only mode
- Fix duplicate monitoring task startup when toggling log service
- Add proper task lifecycle management with JoinHandle cleanup
* refactor: remove dead code from logs.rs to fix clippy warnings
- Remove unused `timestamp` field from LogItem struct
- Remove unused `client` field from LogsMonitor struct
- Remove unused methods: `is_fresh`, `get_current_monitoring_level`, `get_current_logs`
- Simplify LogsMonitor initialization by removing client dependency
- All clippy warnings with -D warnings now resolved
* refactor: extract duplicate fmt_bytes function to utils module
- Create new utils/format.rs module with fmt_bytes function
- Remove duplicate fmt_bytes implementations from traffic.rs and memory.rs
- Update imports to use shared utils::format::fmt_bytes
- Add comprehensive unit tests for fmt_bytes function
- Ensure DRY principle compliance and code maintainability