Commit Graph
1091 Commits
Author SHA1 Message Date
Tunglies 45afb1c15a fix(frontend): reduce long-running memory pressure in connections (#7227)
* fix(connections): stabilize table memory usage

Render the connections table and list from stable row view models, and replace the TanStack row/cell instantiation path with a lightweight virtualized table body.

The leak was isolated to the frontend table render path: websocket data without the table stayed flat, while the normal table path kept producing large per-snapshot object graphs under active/closed churn.

Introduced-by: bf06cbc87d (introduced the TanStack table path)

Related-hot-path: 068678135 (made default ordering/filtering hot enough for long-running /connections sessions to amplify retained heap/RSS)

Related-retention-path: 7fc238c27b (moved Home stats to the full connection websocket subscription, so Home could keep connection snapshots alive for totals/count)

Keep UI behavior intact: column visibility, column order, resizing, sorting, connection details, the closed-connection cap, and the 500ms refresh cadence remain.

* fix(connections): lazily release connection snapshots

Keep the full active/closed connection snapshot scoped to /connections by using a short React Query gcTime for the full subscription.

Home now subscribes to a lightweight connection summary for totals and active count, so leaving /connections no longer keeps the full active/closed arrays and closed history alive for the dashboard.

Only the selected Active or Closed mode feeds filtering, sorting, row-view derivation, and table/list rendering. Switching modes remounts the row subtree and closes detail/column-manager state without changing the capped closed-history behavior.

* fix(connections): decouple collection from rendering

Move the high-frequency connection websocket path out of React Query and into a module-level external store consumed with useSyncExternalStore.

The store keeps one normalized active snapshot plus the capped closed history, continues collecting across route changes, and only notifies mounted subscribers. Home reads the same store through a lightweight summary snapshot, so leaving /connections no longer renders the table/list while connection history is still preserved.

This replaces the short-gc release behavior that made Active/Closed history disappear after navigating away, and bounds retained data to current active connections plus the closed cap instead of React Query cache objects.

* fix(connections): keep collection store authoritative

Remove the temporary per-subscription gcTime override added for /connections. The connection monitor now owns active/closed retention outside React Query, so route changes should stop rendering without clearing collected history.

This leaves the shared Mihomo websocket hook on its original 30s cache behavior for logs, traffic, and memory while /connections uses the external store introduced in the previous commit.

* perf(connections): coalesce snapshots before parsing

Keep only the latest raw websocket message during the 500ms throttle window and parse it when the store flushes. High-churn connection bursts no longer allocate parsed object graphs for snapshots that will be overwritten before React can observe them.

Also compare incoming metadata through the same normalization used for retained records, so optional undefined fields do not prevent metadata reference reuse.

* perf(connections): trim render allocations

Reuse existing row view objects before formatting derived strings when the retained connection object reference is unchanged. Stable closed-history rows no longer allocate throwaway display strings on every snapshot.

Measure the table scroll viewport on mount and resize instead of assuming a 1200px body, so virtual rendering starts from the real visible row count. Keep table state across Active/Closed switches and share the relative-time cell between table and list rows.

* perf(connections): tighten shared time updates

Refresh the shared relative-time clock before the first subscriber render and switch the listener registry back to a Set, avoiding stale labels after returning to /connections and keeping subscriber churn O(1).

Also sort table time rows by the existing numeric startTime field, drop the redundant row-view startTime equality check, and remove one unnecessary table prop guard.

* perf(connections): skip table-wide row projection

Stop materializing ConnectionRowView objects for the whole filtered dataset in table layout. The page now keeps raw connection records for the table path and only formats visible cells inside the virtualized table body, while list layout keeps the cached row-view path.

This removes the steady 500ms allocation pass that was still walking every filtered connection before table rendering. Detail lookup now reads the current filtered raw record directly, and the table clamps scroll state when switching between datasets of different lengths.

* perf(connections): skip unnecessary filter clone when table not searching

In table mode, avoid creating a filtered copy when search is empty: only apply search/sort work for non-empty query while retaining the same default order behavior. Also replace  parsing in order comparators with numeric startTime to avoid per-tick Date object churn and use SearchBox state to detect an empty search.

In table layout without search input, use upstream connection snapshot directly for rendering instead of cloning/sorting every interval tick. This removes a persistent per-update array allocation path while keeping list-mode sort/search behavior unchanged.

* perf(connections): bound closed merge without full transient arrays

Cap closed-history promotion while iterating previous active set without building a temporary large closed array. This preserves the 500-item limit while avoiding 100k-scale transient allocations when many connections close between snapshots.

* fix(changelog): address memory leak caused by frontend

* perf(connections): cache visible table cell snapshots

Add a bounded row snapshot cache for the virtualized table so repeated paints and optional column sorting reuse stable formatted strings instead of rebuilding host/source/rule/chains/traffic text on every refresh. The cache is capped to avoid retaining large active sets.

Also skip full connection-data snapshot merging when only summary listeners are mounted, keeping Home on the summary-only path without changing Connections history while the page is subscribed.

* chore: update Changelog

* chore: update Changelog
2026-06-07 13:08:15 +08:00
Tunglies fa27d3eae5 Revert "feat(cvd): add device-bound subscription protocol"
This reverts commit 2cb9c13ab6.
2026-06-02 21:02:19 +08:00
wonfen 2cb9c13ab6 feat(cvd): add device-bound subscription protocol 2026-06-02 13:43:54 +08:00
Tunglies 3444d594ac perf(profile): optimize profile batch update and worker config 2026-05-29 20:18:40 +08:00
Siyuan LiangandTunglies 22c516f550 feat(sysinfo): return structured system info (#7122)
* feat(sysinfo): return structured system info

* refactor: simplify SystemInfo conversion and enhance Platform struct

---------

Co-authored-by: Tunglies <77394545+Tunglies@users.noreply.github.com>
2026-05-26 08:40:42 +00:00
Tunglies 2a397d7ef6 fix(settings): load network interfaces in allow LAN dialog 2026-05-24 15:41:15 +08:00
Tunglies 21878ea936 Refactor timer management and remove delay_timer dependency (#7075)
* Refactor timer management and remove delay_timer dependency

The delay_timer spawned tokio threads of cores, which not controled by expected.

* refactor: improve logging messages in Timer implementation

* fix(timer): prevent potential panic by using saturating_mul for interval calculations

* refactor timer scheduler

* chore: translate timer logs to english

* fix timer clippy warnings

* fix profile auto update refresh

* fix duplicate profile update notification

* fix: prevent potential panic in lightweight timer setup

* fix profile update listener cleanup

* Revert "fix duplicate profile update notification"

This reverts commit 4aafa94d3e.
2026-05-22 04:30:48 +00:00
Tunglies 54d130a0c4 fix lint violations 2026-05-21 18:49:12 +08:00
wonfen 15de400f2f fix: align backup dialogs with in-app modal behavior 2026-05-20 10:24:11 +08:00
wonfen e11b74206d feat: add warning tooltip for proxy chain 2026-05-18 07:53:29 +08:00
Tunglies fc2ff69bdb fix(proxy): stabilize proxy group sticky scroll #6982
Close #6982
2026-05-16 02:48:51 +08:00
Tunglies a60ef75061 perf: lazy load monaco editor 2026-05-14 02:31:20 +08:00
Tunglies 753dad7c40 fix: move connection columns control 2026-05-10 13:21:06 +08:00
Tunglies 1d28cf7b5a style: improve update notes readability 2026-05-07 14:03:37 +08:00
Tunglies 8c1c143b5e fix: render GitHub alert syntax in update notes 2026-05-07 13:44:07 +08:00
wonfen db0fee7894 feat: add sticky scroll for proxy groups 2026-05-03 03:55:50 +08:00
renovate[bot]Tungliesrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
8fe79aee66 chore(deps): update github actions (#6861)
* fix(ui): reduce idle traffic graph redraws

* fix(sysproxy): preserve global proxy apply order #6760, #6832, #6790, #6793, #6801

* chore(deps): update github actions

---------

Co-authored-by: Tunglies <77394545+Tunglies@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-30 13:04:55 +00:00
Tunglies 6e0647f7b2 perf: narrow app data subscriptions 2026-04-29 10:18:03 +08:00
Tunglies b85b435e00 refactor: structure config validation outcomes
- Replace boolean/string validation results with structured ValidationOutcome values across config validation, profile switching, DNS validation, and script validation. Callers can now distinguish valid, invalid, skipped, and busy states, with invalid results carrying an error kind and message.

- Route core config updates through structured outcomes and checked forced updates. Generation and validation failures now discard runtime drafts and surface validation failures instead of relying on empty success messages.

- Preserve existing frontend ergonomics by keeping boolean service wrappers where callers only need success, while direct DNS and script validation consumers receive ValidationOutcome. Failed profile editor saves reload the backend-restored file content and synchronize Monaco models so reopened editors show the restored state.
2026-04-25 13:31:08 +08:00
Tunglies 549f21961c perf: reduce frontend subscription and raf churn 2026-04-25 01:12:45 +08:00
Tunglies d9ae7578ce perf: reduce traffic update allocations 2026-04-25 00:17:47 +08:00
Tunglies e0b9f8a48b perf(frontend): optimize traffic graph rendering 2026-04-24 22:27:05 +08:00
Tunglies 1eb194d0f9 fix(core): streamline core change process and ensure version mutation after upgrade 2026-04-22 00:55:16 +08:00
Tunglies bf2fccac1f fix(ui): prevent proxy update when disabled #6849 2026-04-19 23:11:07 +08:00
Tunglies 72394eb9b7 feat(ui): add QR code sharing for remote profiles
Add "Share QR Code" context menu item to remote profile cards.
2026-04-19 22:20:17 +08:00
Tunglies d203121abe perf(ui): reduce CPU and memory pressure on hot frontend paths
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
2026-04-19 19:33:23 +08:00
Tunglies b1eb011050 refactor(ui): extract useProxyDelayState hook and tighten types
- Extract shared delay state logic from ProxyItem and ProxyItemMini
  into `useProxyDelayState` hook (src/hooks/use-proxy-delay-state.ts);
  JSX display thresholds preserved per-component.
- Deduplicate rAF/setTimeout/Promise scheduling in DelayManager via
  a private `scheduleOnNextFrame` helper.
- Drop no-op `useMemo(() => MODES, [])` in proxies page.
- Replace `any` on `setClashLog` prev params and layout-traffic sx
  objects with proper types (`pre!`, `Pick<BoxProps|...>`).
2026-04-19 17:25:57 +08:00
Tunglies 0e6d1d2476 fix(ui): unify delay color handling in ProxyItem and TestItem components #6829 2026-04-17 21:29:35 +08:00
Tunglies 3ff53ab975 fix(ui): restore memory usage centering in sidebar after MUI v9 migration
The MUI v9 migration moved boxStyle layout props into sx, but the memory
usage Box had a separate sx that overwrote it. Merge boxStyle.sx like the
upload/download rows already do.
2026-04-16 10:35:10 +08:00
renovate[bot]Tungliesrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
71dc5f0bdb chore(deps): update npm dependencies to v9 (major) (#6819)
* fix: replace DeleteOutline with DeleteOutlined icon in BackupHistoryViewer

* chore(deps): update npm dependencies to v9

* refactor: bump @mui to v9

---------

Co-authored-by: Tunglies <77394545+Tunglies@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-15 14:12:06 +00:00
Tunglies 2e505f26ae feat(proxy-groups): integrate useQuery for fetching proxies data 2026-04-15 15:07:04 +08:00
9e5da1a851 feat(tray): 恢复并重构托盘显示速率功能 (#6487)
* feat(tray): 恢复并重构托盘显示速率功能

* docs(changelog): add tray speed feature entry for v2.4.7

* refactor(tray): 将托盘速率显示限制为仅 macOS

* chore(style): 统一托盘速率设置相关代码风格

* refactor(tray): 统一 speed 任务调度并移除循环内配置轮询

* chore(tauri): enable createUpdaterArtifacts for updater support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor(tray): refine macOS tray speed formatting and two-line alignment

* refactor(tray): move to utils

* refactor(tray): improve macOS speed display formatting, alignment, and structure

* chore: 降级 Node.js 版本至 21.7.1

* refactor(tray): 优化 macOS 托盘速率流与显示逻辑

* refactor(tray): 将速率任务重构为独立控制器并切换至 /traffic 流

* refactor(tray): 缩短速率宽度

* refactor(tray): 收敛测速流抽象并修正停止清理时序

* docs(changelog): 更新变更日志

* refactor(tray): simplify speed formatting logic and remove redundant functions

* refactor(tray): optimize speed display logic and reduce redundant attribute initialization

* refactor(tray): enhance traffic event parsing and improve stale event handling

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Tunglies <77394545+Tunglies@users.noreply.github.com>
2026-04-09 14:40:32 +00:00
Tunglies bff78d96b4 chore: migrate formatter from prettier to biome 2026-04-07 01:32:14 +08:00
Tunglies 437fef1c30 fix: eliminate error flash on startup by distinguishing loading from error state
- Change TQ_MIHOMO retryDelay from fixed 2000ms to exponential backoff
  (200ms → 400ms → 800ms, cap 3s) so core-dependent queries retry faster
- Expose isCoreDataPending from AppDataProvider to distinguish between
  data still loading vs actual errors
- ClashModeCard: show placeholder instead of "communication error" while
  core data is pending
- CurrentProxyCard: show empty space instead of "no active node" while
  core data is pending
2026-04-06 02:14:33 +08:00
Tunglies b8fbabae04 fix: frontend memory leaks — Monaco dispose, TQ cache eviction, useEffect cleanup
- Dispose Monaco editor instances on dialog close to prevent cycle leak
- Replace gcTime: Infinity with finite TTLs and evict orphaned subscription queryKeys
- Add missing useEffect cleanup for timers, move setTimeout out of useMemo
2026-04-05 23:10:45 +08:00
Tunglies d6d15652ca refactor: migrate react-virtuoso to @tanstack/react-virtual 2026-04-03 17:13:13 +08:00
Tunglies a73fafaf9f refactor: migrate SWR to TanStack Query v5 (#6713)
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.
2026-04-03 08:15:51 +00:00
wonfen 51578c03b0 fix: URL test url 2026-04-03 12:13:04 +08:00
Tunglies 7a06a5a069 fix: remove dead localStorage writes and hardcoded key
- Remove unused `dns_settings_enabled` localStorage writes in
  setting-clash.tsx — state is sourced from verge config, these
  writes were never read anywhere.
- Replace hardcoded `'last_check_update'` localStorage read in
  system-info-card.tsx with exported `readLastCheckTime()` from
  the useUpdate hook, keeping the key in a single source of truth.
2026-03-29 02:06:08 +08:00
Tunglies 99bbd7ee5a fix(home): unify last check update timestamp across settings and home page (#6605)
The settings page "Check for updates" did not update the homepage
"last check update time" because each page managed the timestamp
independently. Centralizes the timestamp in the useUpdate hook
via SWR + localStorage so both pages share a single data source.

Closes https://github.com/clash-verge-rev/clash-verge-rev/issues/6605#issuecomment-4147144987
2026-03-29 01:56:34 +08:00
Tunglies c3aba3fc79 fix(profile): refresh profile data after timer auto-update completes
The profile-update-completed event handler was missing a mutate('getProfiles')
call, causing the "X time ago" display to show stale timestamps after
backend timer auto-updates.
2026-03-28 02:37:59 +08:00
Tunglies ca8e350694 fix(proxy): resolve system proxy toggle stuck and state desync (#6614) (#6657)
* fix(proxy): resolve system proxy toggle stuck and state desync (#6614)

Backend: replace hand-rolled AtomicBool lock in update_sysproxy() with
tokio::sync::Mutex so concurrent calls wait instead of being silently
dropped, ensuring the latest config is always applied.

Move blocking OS calls (networksetup on macOS) to spawn_blocking so
they no longer stall the tokio worker thread pool.

Frontend: release SwitchRow pendingRef in .finally() so the UI always
re-syncs with the actual OS proxy state, and rollback checked on error.

Closes #6614

* fix(changelog): add note for macOS proxy toggle freeze issue
2026-03-27 15:40:03 +00:00
Tunglies 607ef5a8a9 fix(home): update last check timestamp on manual update check (#6605)
The onCheckUpdate handler never persisted the timestamp to localStorage
or dispatched it to component state, so clicking "Last Check Update"
would report the result but leave the displayed time stale.
2026-03-27 22:10:20 +08:00
wonfen 56141e6dfa feat: use optimistic updates for system proxy toggle 2026-03-17 12:50:44 +08:00
wonfen 68ca01cfea refactor: streamline proxy availability checks and remove redundant methods 2026-03-17 09:25:16 +08:00
wonfen 2043b24e4b feat: use actual OS proxy status 2026-03-17 09:25:16 +08:00
wysha-objectandSlinetrac 4ceb7e6043 feat: Allow toggling pause of traffic stats animation on blur (#6463)
* feat: Allow toggling pause of traffic stats animation on blur

* fix: React Hook useCallback has a missing dependency

* chore: i18n

---------

Co-authored-by: Slinetrac <realakayuki@gmail.com>
2026-03-16 08:17:12 +00:00
renovate[bot]renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>Slinetrac
13538914be chore(deps): update dependency @eslint-react/eslint-plugin to v3 (#6522)
* chore(deps): update dependency @eslint-react/eslint-plugin to v3

* chore: remove deprecated rules

* chore: remove eslint from pre-push

* chore: update lint-staged config

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Slinetrac <realakayuki@gmail.com>
2026-03-16 05:40:15 +00:00
Slinetrac c672a6fef3 refactor: lint (#6511)
* refactor: lint

* chore: remove eslint-plugin/config-prettier
2026-03-15 07:40:11 +00:00
Slinetrac 837508c02c feat(monaco): reintroduce meta-json-schema (#6509)
* refactor(editor): make EditorViewer controlled and unify document state handling

* fix(monaco-yaml): add patchCreateWebWorker

* feat(monaco): reintroduce meta-json-schema

* fix(editor): reset document state on target change
2026-03-15 06:04:59 +00:00