Commit Graph
46 Commits
Author SHA1 Message Date
Tunglies 40fd1d5012 refactor: frontend cleanup (#8447)
* docs(agents): add frontend liveness constraints

Add six liveness rules to the frontend guardrails covering dead state,
unused exposed surface, unreachable fallback paths, duplicate side
effects per interaction, unreachable mounts and unbounded resource
lifecycles. These target defect classes that the existing CI gates
(knip, eslint, arch:check) cannot detect mechanically.

* refactor(frontend): remove dead states, refs and unreachable branches

Drop state that can only hold its initial value (profiles page disabled
flag, traffic graph currentFPS), a write-only window controls ref with
its unconsumed imperative handle, a no-op appendData ref method, an
unreachable gradient branch, an invisible fadeIn shell, constant-true
subexpressions in the system info card, an empty click handler and a
pointless useMemo.

* refactor(frontend): drop unused params, props and api surface

Remove the never-read _revalidate argument of mutateVerge and its 16
call-site placeholders, seven never-passed props of the split chip
editor, the unconsumed refreshDecorated context member, the now-orphaned
toggleFullscreen control, the unused translate argument of the notice
message handler, the reserved-but-unset ServiceConfig.timeout field and
unreachable branches in parseNoticeExtras.

* refactor(types): remove dead provider view types superseded by bindings

Drop the handwritten IProxyProviderItem and IRuleProviderItem
interfaces: IProxyProviderItem is a stale duplicate of the generated
ProxyProviderView contract, and neither has any references left in
the tree.

Keep IProxyItem and IProxyGroupItem: IConfigData still declares
'proxy-groups'?: IProxyGroupItem[], which builds on IProxyItem.

* fix(rules): refresh once per visibility trigger

The mount effect fired refreshRules and refreshRuleProviders
unconditionally and again under the page-visible flag, double-firing
both queries on mount and on every hide-to-show transition. Gate the
refresh on visibility once so each trigger performs exactly one
revalidation.

* fix(setting): write auto launch patch once per toggle

GuardState applies the optimistic onChange write before onGuard runs,
so repeating the same onChangeData patch inside the guard handler
duplicated every cache write and subscriber notification for the auto
launch switch.

* fix(setting): build viewer form defaults from a single source

sysproxy, misc and tunnels viewers duplicated their form default
literals in useState and open(), and the two copies in misc-viewer had
already diverged (app log max size, app log max count, auto log clean).
Extract a buildInitialValues factory per viewer and unify on the open()
values, which are the only ones users could ever see.

* fix(setting): mount only reachable proxy control viewers

ProxyControlSwitches unconditionally mounted both SysproxyViewer and
TunViewer while its switch rows are mutually exclusive, so every
instance carried a dialog that could never open, each firing
getEmbeddedServerPort or a clash query subscription on mount. Mount
each viewer under the same condition as the switch row that opens it.

SettingSystem also mounted its own SysproxyViewer and TunViewer whose
refs were never opened there; the reachable entries are the
ProxyControlSwitches rows, so the dead pair is removed. Viewer mounts
across the app drop from eight (setting-system: two own + two per
instance, proxy-tun-card: two) to three (one per rendered switch
variant).

* fix(delay): write pending state once per node in batch checks

checkListDelay pre-marked every node as checking, help() re-marked it
when picked up and measureDelay marked it a third time on entry, so
each batch run queued three identical pending updates per node. Keep
the pre-mark (immediate feedback for queued nodes) and drop the
redundant marks along the chain.

* fix(services): make retries viable and align polling freshness window

Share no abort signal across retry attempts: after a timeout abort the
old signal stays dead and every later fetch rejects immediately, so
retries only burned backoff time. Also drop the system state query's
staleTime: the wrapper maps it to SWR's dedupingInterval, which
swallowed every other 3s poll tick while it exceeded the interval.

* refactor(traffic): drop unreachable inline monitor fallback

The inline traffic monitor duplicated the worker's message loop,
snapshot throttling and aging logic but only runs when Worker is
undefined or its constructor throws, which no supported Tauri webview
or browser hits. Keep the worker as the single implementation and
remove the mode switch and the pending-message queue that could only
ever buffer the init message.

* refactor(shared): replace the traffic error boundary with ErrorBoundary

TrafficErrorBoundary maintained a second boundary system beside
BaseErrorBoundary: a report builder that only console.logged constants
in the Tauri webview, an onError that re-logged what componentDidCatch
already logged, and a fallback wrapper with a single consumer. Fold
both mount points into react-error-boundary (the primitive behind
BaseErrorBoundary) with local fallbacks that keep the panel styling,
message text and retry reset, log each error once, and drop the retry
attempt cap and the stack-details collapse along with it.

* refactor(hooks): drop the write-only error channel and key-rotating refresh

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.

* refactor(hooks): trim dead surface from proxy selection

Drop the connection-cleanup option nobody ever disabled (behavior now
unconditional), the returned changeProxy no consumer called and the two
one-caller argument adapters; both call sites use the shared select
entry directly.

* refactor(services): drop the bespoke retry engine from the query wrapper

The custom onErrorRetry existed only to honor a function-form
retryDelay, which exactly one caller (the app data provider) used for
exponential backoff. Fall back to SWR's built-in error retry and
express that caller's cadence with constant options.
2026-11-03 10:48:45 +00:00
Tunglies 69b76cc6a9 refactor(frontend): contract flow (#8131)
* feat(contract): export wire contract from backend and generate frontend types

Adds a zero-dependency `frontend-contract` bin that serializes the real
NoticeStatus variants and FrontendEvent payloads, scripts/gen-contract.mjs
which emits the committed src/services/contract.ts, and a CI job that
regenerates it and fails on a non-empty diff. events.ts now derives its
event map from the generated contract instead of hand-typed shapes.

* feat(events): route all backend events through a single event bus and store

Adds src/services/bus (the only listen/emit site: one handler per contract
event plus the frontend-internal test-all event) and the React
context/reducer app store. Migrates the five scattered subscriptions
(layout events, pending failures, proxy refresh, profile update/timer,
test-all), deletes the old glue (events.ts, use-listen, use-layout-events,
LoadingCacheProvider), moves run state into the store, and adds an
architecture gate script wired into CI. Behavior is unchanged; the
run-state query's poll/focus safety net is preserved by the store
provider.

* refactor(notice): make the notice table exhaustive and drop dead wire entries

D5 cleanup, frontend and backend in one commit: removes the six
config_validate::* statuses that never receive a backend send and the
set_config::ok send (enum variants, golden list 41→34, send point in
restart_clash_core), their frontend handlers, and the five i18n keys only
those handlers used. The notice table is now typed as a Record over the
generated NoticeStatus union, so a status without a frontend entry fails
to compile. The info status (sent by the silent updater for breaking
change notices, previously dropped with a console warning) now shows an
info toast — the one deliberate behavior delta.

* feat(mutate): single funnel for user-intent commands and invoke gate

Adds src/services/mutate.ts: one path for optimistic apply, services-layer
invoke, Busy handling, failure rollback, and the error toast, with busy
bookkeeping mirrored into the app store. The patch hooks (verge, clash,
profiles) now route through it. Moves the remaining direct invokes
(unlock ×3, DNS ×4) into cmds.ts and turns on the invoke-only-in-services
architecture gate in CI.

* refactor(settings): route settings-domain commands through the mutate funnel

Ports port saving, webdav/local backup operations, core change/restart/
upgrade, service install/uninstall/repair flows, the system-proxy toggle
queue, the DNS override toggle, and app lifecycle commands onto the single
funnel. Bespoke flows keep their own error handling via errorNotice:false;
simple flows gain the funnel's default error toast and revalidation.

* refactor(profiles): route profile operations through the mutate funnel

Ports profile create/import/reorder/delete/update/patch/save-file and
enhance calls onto the funnel; retry and editor flows keep their own
error handling with errorNotice:false. Per-uid ids keep the update
worker pool concurrent under the funnel's in-flight dedupe.

* refactor(proxies): route proxy/home/misc commands through the mutate funnel

Ports mode switching (page and home card), chain runtime updates, node
selection with tray sync, selection recording, provider updates and
syncs, and lightweight-mode entry onto the funnel; every site keeps its
existing optimistic/revert and error-handling behavior.

* docs: add frontend architecture guardrails for src

Layering rules for the contract flow: generated contract as the only
wire-typing source, event bus as the only listen/emit site, pure-reducer
store for event-derived state, the mutate funnel for user intent, and
invoke only in the services layer — each backed by the CI gates.

* fix(events): close run-state race and restore single error toasts

Self-review findings: the bus now re-reads the run-state snapshot in
onSubscribed so an event racing the store's initial read cannot leave a
stale snapshot (the ordering the old layout listener guaranteed), and the
patch hooks pass errorNotice:false so GuardState/page handlers remain the
only error toast, matching the pre-migration behavior.

* fix(frontend): preserve queued intents and fresh runtime snapshots

* refactor(frontend): trim unused mutation and busy state APIs

* docs(frontend): focus guardrails on architecture ownership
2026-10-07 07:38:55 +00: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
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
Slinetrac c672a6fef3 refactor: lint (#6511)
* refactor: lint

* chore: remove eslint-plugin/config-prettier
2026-03-15 07:40:11 +00:00
Slinetrac a981be80ef refactor(base): expand barrel exports and standardize imports 2026-01-06 15:02:10 +08:00
歳納七夏 2417d064e1 feat: allow disabling proxy groups in tray icon (#5946)
* feat: allow disabling proxy groups in tray icon

* feat: allow disabling proxy groups in tray icon (update i11n)

* feat: allow disabling proxy groups in tray icon (fix)

* feat: allow disabling proxy groups in tray icon (less nesting)

* feat: allow disabling proxy groups in tray icon (changelog)
2025-12-26 16:29:05 +08:00
Slinetrac 23e551e384 feat(tray): add optional inline outbound modes in tray menu #5881
Closes #5881
2025-12-21 10:33:19 +08:00
CactusandSlinetrac 57b17ab8d3 feat: add navigation collapse functionality to layout (#5815)
* feat(layout): add collapsible navbar toggle in UI settings

* refactor(layout): adjust collapsed navbar styles

* docs: Changelog.md

---------

Co-authored-by: Slinetrac <realakayuki@gmail.com>
2025-12-19 18:15:20 +08:00
Sline fc84dc561c feat(notice): persist toast position preference (#5621)
* feat(notice): persist toast position preference

* docs: Changelog.md
2025-12-19 18:04:23 +08:00
Slinetrac bae65a523a chore: rename files to kebab-case and update imports 2025-12-09 13:52:42 +08:00
Sline 2a2de29224 feat: tray menu enhance (#5412)
* feat(tray): move outbound modes into a dedicated submenu

* refactor: Enable 'Show Proxy Groups Inline' by default

* refactor(tray): move `copyEnv` to `more` submenu
2025-11-12 14:10:20 +08:00
Tunglies 33f575ed4d refactor: update icon handling in tray methods to accept IVerge reference and improve logging #5379 (#5387)
* refactor: update icon handling in tray methods to accept IVerge reference and improve logging #5379

* refactor: simplify icon retrieval logic in Tray implementation
2025-11-10 19:06:37 +08:00
Slinerenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>rozan
c8aa72186e chore: i18n (#5276)
* chore: notice i18n

* feat: add script to clean up unused i18n keys

* chore: cleanup i18n keys

* refactor(i18n/proxies): migrate proxies UI to structured locale keys

* chore: i18n for rule module

* chore: i18n for profile module

* chore: i18n for connections module

* chore: i18n for settings module

* chore: i18n for verge settings

* chore: i18n for theme settings

* chore: i18n for theme

* chore(i18n): components.home.*

* chore(i18n): remove unused i18n keys

* chore(i18n): components.profile.*

* chore(i18n): components.connection

* chore(i18n): pages.logs.*

* chore(i18n): pages.*.provider

* chore(i18n): components.settings.externalCors.*

* chore(i18n): components.settings.clash.*

* chore(i18n): components.settings.liteMode.*

* chore(i18n): components.settings.backup.*

* chore(i18n): components.settings.clash.port.*

* chore(i18n): components.settings.misc.*

* chore(i18n): components.settings.update.*

* chore(i18n): components.settings.sysproxy.*

* chore(i18n): components.settings.sysproxy.*

* chore(i18n): pages.profiles.notices/components.providers.notices

* refactor(notice): unify showNotice usage

* refactor(notice): add typed showNotice shortcuts, centralize defaults, and simplify subscriptions

* refactor: unify showNotice usage

* refactor(notice): unify showNotice API

* refactor(notice): unify showNotice usage

* chore(i18n): components.test.*

* chore(i18n): components.settings.dns.*

* chore(i18n): components.home.clashInfo.*

* chore(i18n): components.home.systemInfo.*

* chore(i18n): components.home.ipInfo/traffic.*

* chore(i18n): navigation.*

* refactor(i18n): remove pages.* namespace and migrate route texts under module-level page keys

* chore(i18n): common.*

* chore(i18n): common.*

* fix: change error handling in patch_profiles_config to return false when a switch is in progress

* fix: improve error handling in patch_profiles_config to prevent requests during profile switching

* fix: change error handling in patch_profiles_config to return false when a switch is in progress

fix: ensure CURRENT_SWITCHING_PROFILE is reset after config updates in perform_config_update and patch_profiles_config

* chore(i18n): restructure root-level locale keys into namespaces

* chore(i18n): add missing i18n keys

* docs: i18n guide

* chore: adjust i18n

* refactor(i18n): align UI actions and status labels with common keys

* refactor(i18n): unify two-name locale namespaces

* refactor(i18n/components): unify locale keys and update component references

* chore(i18n): add shared and entities namespaces to all locale files

* refactor(i18n): consolidate shared and entity namespaces across features

* chore(deps): update npm dependencies to ^7.3.5 (#5310)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* refactor(i18n): migrate shared editor modes and consolidate entities namespaces

* tmp

* refactor(i18n): flatten locales and move theme/validation strings

* docs: CONTRIBUTING_i18n.md

* refactor(i18n): restructure feedback and profile namespaces for better organization

* refactor(i18n): unify settings locale structure and update references

* refactor(i18n): reorganize locale keys for home, proxies, rules, connections, logs, unlock, and tests

* refactor(i18n/feedback/layout): unify shared toasts & normalize layout namespace

* refactor(i18n): centralize common UI strings in shared

* refactor(i18n): flatten headers and unify locale schema

* refactor(i18n): consolidate duplicate per-feature translations into shared namespace

* refactor(i18n): split locales into per-namespace files

* style: lint

* refactor(i18n): unify unlock UI translations under tests namespace

* feat(i18n): add type-checked translation keys

* style: eslint import order

* feat(i18n): replace ad-hoc loader with rust-i18n backend bundles

* chore(prebuild): remove locale-copy step

* fix(i18n, notice): propagate runtime params and update cleanup script path

* fix(i18n,notice): make locale formatting idempotent and guard early notice translations

* fix(i18n): resolve locale aliases and match OS codes correctly

* fix(unlock): use i18next-compatible double-brace interpolation in failure notice

* fix(i18n): route unlock error notices through translation keys

* fix(i18n): i18n types

* feat(i18n): localize upgrade notice for Clash core viewer

* fix(notice): ensure runtime overrides apply to prefix translations

* chore(i18n): replace literal notices with translation keys

* chore(i18n): types

* chore(i18n): regen typings before formatting to keep keys in sync

* chore(i18n): simply labels

* chore(i18n): adjust translation

* chore: remove eslint-plugin-i18next

* chore(i18n): add/refine Korean translations across frontend scopes and Rust backend (#5341)

* chore(i18n): translate settings.json (missed in previous pass) (#5343)

* chore(i18n): add/refine Korean translations across frontend scopes and Rust backend

* chore(i18n): add/refine Korean translations across frontend scopes and Rust backend

* fix(i18n-tauri): quote placeholder-leading value in ko.yml to prevent rust_i18n parse panic

* chore(i18n): translate settings.json (forgot to include previously)

---------

Co-authored-by: rozan <34974262+thelojan@users.noreply.github.com>
2025-11-08 19:40:38 +08:00
Tunglies 2af0af0837 refactor(tray): comment out enable_tray_icon references for future removal #5161
Since network speed display in Tray on menu has been removed
2025-10-28 14:37:57 +08:00
Sline 8657cedca0 feat: add configurable hover jump navigator delay (#5178)
* fix: hover options

* feat: add configurable hover jump navigator delay

- Added `hover_jump_navigator_delay` to Verge config defaults, patch flow, and response payload for persistent app-wide settings.
- Made proxy navigator respect configurable delay via `DEFAULT_HOVER_DELAY` and new `hoverDelay` prop.
- Threaded stored delay through proxy list so hover scrolling uses Verge-configured value.
- Added "Hover Jump Navigator Delay" control in Layout settings with clamped numeric input, tooltip, and toggle-aware disabling.
- Localized new labels in English, Simplified Chinese, and Traditional Chinese.
- Extended frontend Verge config type to include delay field for type-safe access.

* docs: UPDATELOG.md
2025-10-23 13:14:01 +08:00
Sline 0b4403b67b refactor: frontend (#5068)
* refactor: setting components

* refactor: frontend

* fix: settings router
2025-10-15 18:57:44 +08:00
Sline f541464ff4 feat: tray enhance (#5058)
* feat: proxy group sorting for tray

* feat(tray): add inline proxy groups toggle
2025-10-14 17:03:37 +08:00
Tunglies bfd1274a8c feat: Implement custom window controls and titlebar management (#4919)
- Added WindowControls component for managing window actions (minimize, maximize, close) based on the operating system.
- Integrated window decoration toggle functionality to allow users to prefer system titlebar.
- Updated layout styles to accommodate new titlebar and window controls.
- Refactored layout components to utilize new window management hooks.
- Enhanced layout viewer to include a switch for enabling/disabling window decorations.
- Improved overall window management by introducing useWindow and useWindowDecorations hooks for better state handling.
2025-10-08 20:23:26 +08:00
Tunglies 8a4f2de887 Revert "Refactor components to remove forwardRef and simplify props handling"
This reverts commit 1cd013fb94.
2025-09-30 18:13:02 +08:00
Tunglies 1cd013fb94 Refactor components to remove forwardRef and simplify props handling
- Updated multiple components to remove the use of forwardRef, simplifying the props structure.
- Adjusted imports and component definitions accordingly.
- Ensured consistent handling of refs and props across various viewer components.
- Improved readability and maintainability of the codebase.
2025-09-30 14:26:40 +08:00
Tunglies e414b49879 Refactor imports across multiple components for consistency and clarity
- Reorganized import statements in various components to ensure consistent ordering and grouping.
- Removed unnecessary imports and added missing ones where applicable.
- Improved readability and maintainability of the codebase by standardizing import styles.
2025-09-19 00:01:04 +08:00
Tunglies 627119bb22 Refactor imports and improve code organization across multiple components and hooks
- Consolidated and reordered imports in various files for better readability and maintainability.
- Removed unused imports and ensured consistent import styles.
- Enhanced the structure of components by grouping related imports together.
- Updated the layout and organization of hooks to streamline functionality.
- Improved the overall code quality by following best practices in import management.
2025-09-18 23:34:38 +08:00
Tunglies e7461fccab refactor: remove unused macOS tray speed display and improve tray icon handling (#3862)
* refactor: remove unused macOS tray speed display and improve tray icon handling

* refactor: disable macOS specific logging during core initialization

* feat: add linux elevator function to determine privilege escalation command
2025-06-22 16:28:06 +08:00
rebecca554owen 4f474e1098 feat: add proxy auto scroll toggle setting (#3674)
* feat: add proxy auto scroll toggle setting

* refactor: rename enable_proxy_auto_scroll to enable_hover_jump_navigator

* 参考 Unified Delay 调整式样
2025-06-11 13:21:24 +08:00
Tunglies 09969d95de feat: add rustfmt configuration and CI workflow for code formatting
refactor: streamline formatting workflow by removing unused taplo steps and clarifying directory change

refactor: remove unnecessary directory change step in formatting workflow
2025-06-06 22:13:11 +08:00
wonfen b37b121afb chore: disable tray speed by default 2025-05-11 19:25:32 +08:00
wonfen 8296675574 refactor: notification system 2025-05-04 22:17:08 +08:00
Tunglies 1a7c076e07 feat: add option to enable/disable tray icon display on MacOS 2025-03-23 16:37:27 +08:00
0XE 7ea7ca1415 fix: issues #2838 (#2886) 2025-03-04 20:46:17 +08:00
huzibaca 29ec4dc546 feat: maoos tray speed can be closed 2025-01-13 20:48:25 +08:00
huzibaca dffd663d7a Fix: Custom tray icon not working
1. Contains potential deadlock
2024-09-20 16:26:23 +08:00
huzibaca 6cc81fe6b8 chore: update 2024-09-02 19:33:17 +08:00
dongchengjie 0a8935686a chore: add descriptions for Miscellaneous 2024-06-28 15:54:27 +08:00
dongchengjie 753395965a chore: tooltips and locales 2024-06-26 05:33:06 +08:00
dongchengjie dc31269a06 typo: inconsistent style in layout-viewer 2024-05-27 16:37:48 +08:00
MystiPanda 21176d2fd3 feat: support monochrome tray icon 2024-05-15 14:50:10 +08:00
MystiPanda 4a37e49798 feat: support ico format for tray icon (#911) 2024-04-22 20:43:15 +08:00
MystiPanda daf726ebbf feat: Try to cache remote images
#603
2024-03-15 16:43:39 +08:00
MystiPanda 739161849a feat: Add option to control menu icon 2024-03-10 19:54:47 +08:00
AmnesiashandMystiPanda 3a0429d049 refactor: Upgrade to the new UI (#521)
Co-authored-by: MystiPanda <mystipanda@proton.me>
2024-03-09 21:37:21 +08:00
MystiPanda 56011d37d4 feat: allow disable group icon 2024-02-24 12:38:17 +08:00
MystiPanda c2852c8a82 refactor: Optimize implementation of Custom tray icon 2024-02-24 11:25:22 +08:00
MystiPanda 6f546a424e feat: Support Custom Tray Icon 2024-02-24 00:52:21 +08:00
MystiPanda 5b7e29b8ad refactor: rm theme blur 2024-01-15 17:13:55 +08:00
GyDi 15cf9be90d feat: support clash meta memory usage display 2023-08-05 19:40:23 +08:00