Compare commits

..
Author SHA1 Message Date
Tunglies 97453a9077 perf(tray): build menu in one main-thread dispatch
Every tauri menu API call from a non-main thread blocks on a synchronous
round-trip to the app event loop. Building the tray menu with proxy
groups enabled issued one such round-trip per menu item (200+ for a
typical subscription) while holding the menu update lock, and the cost
grows when the event loop is busy with webview work.

Gather the async inputs (verge/clash/profiles snapshots and the proxy
view) on the caller's task, then construct every menu item inside a
single run_on_main_thread closure and hand the finished menu back;
set_menu and the per-group refresh keep their original call sites.
Measured on a standalone tauri bench (5 groups x 40 nodes): a rebuild
drops from ~6.2ms to ~1.6ms on an idle event loop and from ~11.4ms to
~1.6ms with the loop busy. refresh_proxy_items already used this shape;
the rebuild path now matches it.
2026-10-20 23:46:43 +08:00
41 changed files with 1105 additions and 782 deletions
+2 -2
View File
@@ -5,10 +5,10 @@
"features": {
"ghcr.io/devcontainers/features/node:2": {
"version": "24.22.0",
"pnpmVersion": "12.14.0"
"pnpmVersion": "12.11.2"
},
"ghcr.io/devcontainers/features/rust:1": {
"version": "1.99.1",
"version": "1.99.0",
"profile": "default"
},
"ghcr.io/devcontainers/features/git:1": {},
+19 -5
View File
@@ -21,7 +21,7 @@ This is a **dispatcher agent** that routes your request to the appropriate speci
- **Creating new workflows**: Routes to `create` prompt
- **Updating existing workflows**: Routes to `update` prompt
- **Debugging workflows**: Routes to `debug` prompt
- **Diagnosis, patching, and active debugging**: Routes to `debug-agentic-workflow` for the local-first strategy, evidence triage and live gates
- **Upgrading workflows**: Routes to `upgrade-agentic-workflows` prompt
- **Creating report-generating workflows**: Routes to `report` prompt — consult this whenever the workflow posts status updates, audits, analyses, or any structured output as issues, discussions, or comments
- **Creating shared components**: Routes to `create-shared-agentic-workflow` prompt
@@ -31,6 +31,7 @@ This is a **dispatcher agent** that routes your request to the appropriate speci
- **CLI commands and triggering workflows**: Routes to `cli-commands` guide — consult this whenever the user asks how to run, compile, debug, or manage workflows from the command line, or when they need the MCP tool equivalent of a `gh aw` command
- **Reducing token consumption / cost optimization**: Routes to `token-optimization` guide — consult this whenever the user asks how to reduce token usage, lower costs, speed up workflows, or measure the impact of prompt changes with experiments
- **Choosing workflow architectures and design patterns**: Routes to `patterns` guide — consult this whenever the user asks for strategy, architecture, operating models, or pattern selection for agentic workflows
- **Git-backed work queues**: Routes to `work-queue` instructions for producers, dispatchers, workers, observers, deployment and recovery
Workflows may optionally include:
@@ -47,7 +48,8 @@ Workflows may optionally include:
## Problems This Solves
- **Workflow Creation**: Design secure, validated agentic workflows with proper triggers, tools, and permissions
- **Workflow Debugging**: Analyze logs, identify missing tools, investigate failures, and fix configuration issues
- **Diagnosis and Patching**: Analyze evidence and produce regression-backed fixes without requiring live runs
- **Active Debugging**: Run bounded edit/test/run/audit loops where permitted, stopping on dispatch 403 responses
- **Version Upgrades**: Migrate workflows to new gh-aw versions, apply codemods, fix breaking changes
- **Component Design**: Create reusable shared workflow components that wrap MCP servers
@@ -83,11 +85,14 @@ When you interact with this agent, it will:
- "Update the PR reviewer to use discussions instead of issues"
- "Improve the prompt for the weekly-research workflow"
### Debug Workflow
### Diagnose, Patch, or Debug a Workflow
**Load when**: User needs to investigate, audit, debug, or understand a workflow, troubleshoot issues, analyze logs, or fix errors
**Prompt file**: `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/debug-agentic-workflow.md`
The shared strategy distinguishes diagnosis/patching from permitted active debug
loops using explicit live gates and includes existing-run evidence triage.
**Use cases**:
- "Why is this workflow failing?"
- "Analyze the logs for workflow X"
@@ -180,6 +185,15 @@ When you interact with this agent, it will:
## Instructions
### Work Queue
For queue design, deployment, inspection or recovery, load
`https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/work-queue.md`.
Also load it after the primary create/update/debug/upgrade prompt whenever a
workflow uses `tools.work-queue`. Load linked developer docs and specifications
only when needed; do not substitute lightweight WorkQueueOps backlog guidance
for the Git-backed protocol.
When a user interacts with you:
1. **Identify the task type** from the user's request
@@ -196,7 +210,7 @@ gh aw init
# Generate the lock file for a workflow
gh aw compile [workflow-name]
# Trigger a workflow on demand (preferred over gh workflow run)
# Only where permitted and human-validated under debug-agentic-workflow.md:
gh aw run <workflow-name> # interactive input collection
gh aw run <workflow-name> --ref main # run on a specific branch
@@ -229,5 +243,5 @@ gh aw compile --validate
- Follow security best practices: minimal permissions, explicit network access, no template injection
- **Network configuration**: Use ecosystem identifiers (`node`, `python`, `go`, etc.) or explicit FQDNs in `network.allowed`. Bare shorthands like `npm` or `pypi` are **not** valid. See `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/network.md` for the full list of valid ecosystem identifiers and domain patterns.
- **Single-file output**: When creating a workflow, produce exactly **one** workflow `.md` file. Do not create separate documentation files (architecture docs, runbooks, usage guides, etc.). If documentation is needed, add a brief `## Usage` section inside the workflow file itself.
- **Triggering runs**: Always use `gh aw run <workflow-name>` to trigger a workflow on demand — not `gh workflow run <file>.lock.yml`. `gh aw run` handles workflow resolution by short name, input parsing and validation, and correct run-tracking for agentic workflows. Use `--ref <branch>` to run on a specific branch.
- **Triggering runs**: Only where permitted and human-validated under `debug-agentic-workflow.md`, prefer `gh aw run <workflow-name>` over `gh workflow run <file>.lock.yml` for workflow resolution, input validation and run-tracking. Use the reviewed remote ref; explicit no-dispatch rules override user requests.
- **CLI commands reference**: For a complete guide on all `gh aw` commands and their MCP tool equivalents (for restricted environments), see `https://raw.githubusercontent.com/github/gh-aw/main/.github/aw/cli-commands.md`
+3 -3
View File
@@ -5,10 +5,10 @@
"version": "v9.0.0",
"sha": "3a2844b7e9c422d3c10d287c895573f7108da1b3"
},
"github/gh-aw-actions/setup@v0.89.21": {
"github/gh-aw-actions/setup@v0.92.0": {
"repo": "github/gh-aw-actions/setup",
"version": "v0.89.21",
"sha": "924af5fdc64061cfbf66fb584c8b07e2ac230c60"
"version": "v0.92.0",
"sha": "458b269006dcf88e3b5496b6fbecabe4b9a0f954"
}
},
"containers": {
+11 -2
View File
@@ -1,6 +1,6 @@
---
name: agentic-workflows
description: Route gh-aw workflow design/create/debug/upgrade requests to the right prompts.
description: Route gh-aw design, creation, diagnosis, patching, active debugging, and upgrade requests to the right strategies.
---
# Agentic Workflows Router
@@ -19,6 +19,7 @@ Load these files from `github/gh-aw` (they are not available locally).
- `.github/aw/agent-runtime-instructions.md`
- `.github/aw/agentic-chat.md`
- `.github/aw/agentic-workflows-mcp.md`
- `.github/aw/analyzing-runs.md`
- `.github/aw/asciicharts.md`
- `.github/aw/campaign.md`
- `.github/aw/charts-trending.md`
@@ -31,6 +32,8 @@ Load these files from `github/gh-aw` (they are not available locally).
- `.github/aw/create-agentic-workflow.md`
- `.github/aw/create-shared-agentic-workflow.md`
- `.github/aw/debug-agentic-workflow.md`
- `.github/aw/debug-model-engine-misconfiguration.md`
- `.github/aw/debug-security-review.md`
- `.github/aw/dependabot.md`
- `.github/aw/deployment-status.md`
- `.github/aw/designer-mappings.md`
@@ -46,6 +49,7 @@ Load these files from `github/gh-aw` (they are not available locally).
- `.github/aw/instructions.md`
- `.github/aw/intent.md`
- `.github/aw/jobs.md`
- `.github/aw/ledger.md`
- `.github/aw/linter-workflows.md`
- `.github/aw/llms.md`
- `.github/aw/loop.md`
@@ -87,6 +91,7 @@ Load these files from `github/gh-aw` (they are not available locally).
- `.github/aw/update-agentic-workflow.md`
- `.github/aw/upgrade-agentic-workflows.md`
- `.github/aw/visual-regression.md`
- `.github/aw/work-queue.md`
- `.github/aw/workflow-constraints.md`
- `.github/aw/workflow-editing.md`
- `.github/aw/workflow-patterns.md`
@@ -96,7 +101,8 @@ After loading the matching workflow prompt or skill, follow it directly:
- Create new workflows: `.github/aw/create-agentic-workflow.md`
- Configure or add declarative engines: `.github/aw/configure-agentic-engine.md`
- Update existing workflows: `.github/aw/update-agentic-workflow.md`
- Debug, audit, or investigate workflows: `.github/aw/debug-agentic-workflow.md`
- Diagnose, patch, audit, or actively debug workflows: `.github/aw/debug-agentic-workflow.md` (local-first strategy, evidence triage and live gates)
- AWF model/endpoint 400s, silent cross-family sub-agent failures, `model: auto` failures, install-step 404s after a version pin, or questions about version fields: go directly to [Model and engine misconfiguration](../../aw/debug-agentic-workflow.md#model-and-engine-misconfiguration) before suggesting model changes.
- Upgrade workflows and fix deprecations: `.github/aw/upgrade-agentic-workflows.md`
- Create shared components or MCP wrappers: `.github/aw/create-shared-agentic-workflow.md`
- Create report-generating workflows: `.github/aw/report.md`
@@ -105,8 +111,11 @@ After loading the matching workflow prompt or skill, follow it directly:
- Render compact markdown charts: `.github/aw/asciicharts.md`
- Map CLI commands to MCP usage: `.github/aw/cli-commands.md`
- Choose workflow architecture and patterns: `.github/aw/patterns.md`
- Design, deploy, inspect or recover a Git-backed work queue: `.github/aw/work-queue.md`
- Optimize token usage and cost: `.github/aw/token-optimization.md`
- Design long-running multi-agent research workflows: `.github/aw/multi-agent-research.md`
- Add skills or agent plugins requested by the user (`skills:` / `plugins:` frontmatter, never on-the-fly installs): `.github/aw/skills.md`
When the task involves OTEL, OTLP, traces, observability backends, or telemetry-driven analysis, also read and follow `skills/otel-queries/SKILL.md` after loading the matching workflow prompt or skill.
When creating, updating, diagnosing or upgrading a workflow that uses `tools.work-queue`, also load `.github/aw/work-queue.md` after the primary prompt. Load deployment docs, operator reference or specification only when that task needs them.
+5 -5
View File
@@ -154,7 +154,7 @@ jobs:
- name: Install Rust Stable
uses: dtolnay/rust-toolchain@master
with:
toolchain: '1.99.1'
toolchain: '1.99.0'
targets: ${{ matrix.target }}
- name: Add Rust Target
@@ -206,7 +206,7 @@ jobs:
- name: Add Rust Target
run: |
rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }}
rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }}
rustup target list --installed
echo "Rust target ${{ matrix.target }} installed."
@@ -257,7 +257,7 @@ jobs:
- name: Install Rust Stable
uses: dtolnay/rust-toolchain@master
with:
toolchain: '1.99.1'
toolchain: '1.99.0'
targets: ${{ matrix.target }}
- name: Add Rust Target
@@ -347,7 +347,7 @@ jobs:
- name: Add Rust Target
run: |
rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }}
rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }}
rustup target list --installed
echo "Rust target ${{ matrix.target }} installed."
@@ -454,7 +454,7 @@ jobs:
- name: Add Rust Target
run: |
rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }}
rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }}
rustup target list --installed
echo "Rust target ${{ matrix.target }} installed."
+1 -1
View File
@@ -31,6 +31,6 @@ jobs:
with:
persist-credentials: false
- name: Install gh-aw extension
uses: github/gh-aw-actions/setup-cli@924af5fdc64061cfbf66fb584c8b07e2ac230c60 # v0.89.21
uses: github/gh-aw-actions/setup-cli@458b269006dcf88e3b5496b6fbecabe4b9a0f954 # v0.92.0
with:
version: v0.89.15
+2 -2
View File
@@ -74,7 +74,7 @@ jobs:
- name: Install Rust Stable
if: github.event.inputs[matrix.input] == 'true'
uses: dtolnay/rust-toolchain@1.99.1
uses: dtolnay/rust-toolchain@1.99.0
- name: Rust Cache
uses: Swatinem/rust-cache@v2
@@ -129,7 +129,7 @@ jobs:
if: github.event.inputs[matrix.input] == 'true'
run: |
# Ensure cross target is installed for the pinned toolchain; fallback without explicit toolchain if needed
rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }}
rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }}
rustup target list --installed
echo "Rust target ${{ matrix.target }} installed."
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -8,7 +8,7 @@ on:
roles: all
skip-roles: [admin, maintainer, write]
skip-bots: [dependabot, renovate]
pull_request_target:
pull_request:
# reopened is intentionally excluded: reopens carry no new implementation
# evidence (the rerun-stability policy handles them), and a manual
# workflow_dispatch remains available when a re-review is wanted.
@@ -26,6 +26,7 @@ max-daily-ai-credits: 5000
permissions:
issues: read
pull-requests: read
copilot-requests: none
pre-agent-steps:
- name: Make Copilot quota exhaustion non-blocking
+6 -6
View File
@@ -204,7 +204,7 @@ jobs:
- name: Install Rust Stable
uses: dtolnay/rust-toolchain@master
with:
toolchain: '1.99.1'
toolchain: '1.99.0'
targets: ${{ matrix.target }}
- name: Add Rust Target
@@ -244,7 +244,7 @@ jobs:
- name: Add Rust Target
run: |
rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }}
rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }}
rustup target list --installed
echo "Rust target ${{ matrix.target }} installed."
@@ -311,7 +311,7 @@ jobs:
- name: Install Rust Stable
uses: dtolnay/rust-toolchain@master
with:
toolchain: '1.99.1'
toolchain: '1.99.0'
targets: ${{ matrix.target }}
- name: Add Rust Target
@@ -389,7 +389,7 @@ jobs:
- name: Add Rust Target
run: |
rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }}
rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }}
rustup target list --installed
echo "Rust target ${{ matrix.target }} installed."
@@ -446,7 +446,7 @@ jobs:
- name: Install Rust Stable
uses: dtolnay/rust-toolchain@master
with:
toolchain: '1.99.1'
toolchain: '1.99.0'
targets: ${{ matrix.target }}
- name: Add Rust Target
@@ -487,7 +487,7 @@ jobs:
- name: Add Rust Target
run: |
rustup target add ${{ matrix.target }} --toolchain 1.99.1 || rustup target add ${{ matrix.target }}
rustup target add ${{ matrix.target }} --toolchain 1.99.0 || rustup target add ${{ matrix.target }}
rustup target list --installed
echo "Rust target ${{ matrix.target }} installed."
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: '1.99.1'
toolchain: '1.99.0'
targets: x86_64-pc-windows-msvc
- name: Install Node
+2 -2
View File
@@ -1,3 +1,3 @@
nodejs 24.22.0
pnpm 12.14.0
rust 1.99.1
pnpm 12.11.2
rust 1.99.0
Generated
+30 -33
View File
@@ -1138,7 +1138,7 @@ dependencies = [
"serde",
"serde_json",
"serde_yaml_ng",
"sha2 0.11.1",
"sha2 0.11.0",
"smartstring",
"socket2",
"specta",
@@ -1175,7 +1175,7 @@ dependencies = [
"windows-service",
"windows-sys 0.61.2",
"winreg 0.56.0",
"zip 9.0.4",
"zip 9.0.1",
]
[[package]]
@@ -1247,7 +1247,7 @@ dependencies = [
"once_cell",
"serde",
"serde_json",
"sha2 0.11.1",
"sha2 0.11.0",
"strum",
"strum_macros",
"sysproxy",
@@ -1462,12 +1462,9 @@ dependencies = [
[[package]]
name = "constant_time_eq"
version = "0.6.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9eb6feb175df65d0a3ccd3e73484e940d0ac664e8034f0519fd49a93db3071d9"
dependencies = [
"rustversion",
]
checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
[[package]]
name = "cookie"
@@ -3954,9 +3951,9 @@ checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c"
[[package]]
name = "libc"
version = "0.2.191"
version = "0.2.190"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
[[package]]
name = "libdbus-sys"
@@ -4051,11 +4048,11 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
[[package]]
name = "lzma-rust2"
version = "0.22.0"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7277c9742229dc25243236d578b6471a798c554512c6f6a04365ec2e87c2a3bb"
checksum = "fde178a3caf126c440fa15628147772d8ee590a39477d711353fbe2e58a73a5b"
dependencies = [
"sha2 0.11.1",
"sha2 0.11.0",
]
[[package]]
@@ -5346,9 +5343,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppmd-rust"
version = "1.5.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "196a7c80b9a7652aba7cc070827516c2abe4ccdf53d128e1944003cf5726cff1"
checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24"
[[package]]
name = "ppv-lite86"
@@ -6070,9 +6067,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.23.46"
version = "0.23.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf"
checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634"
dependencies = [
"aws-lc-rs",
"log",
@@ -6413,9 +6410,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.154"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
@@ -6600,9 +6597,9 @@ dependencies = [
[[package]]
name = "sha2"
version = "0.11.1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47d7069beb7d6ac7b9acd1039986e73443f24234f41074da099d6f994ac9ad19"
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
dependencies = [
"cfg-if",
"cpufeatures 0.3.0",
@@ -8076,9 +8073,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.53.3"
version = "1.53.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce3335fa71841cda333a58d7615b03901380ecf09d59b3296d21f8bbac0dde4e"
checksum = "e95f91fcc7a621e8b030f6aa23c71fe9838ae2fb4d8118b75602a328f5144044"
dependencies = [
"bytes",
"libc",
@@ -8138,9 +8135,9 @@ dependencies = [
[[package]]
name = "tokio-util"
version = "0.7.20"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b"
checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52"
dependencies = [
"bytes",
"futures-core",
@@ -10153,9 +10150,9 @@ dependencies = [
[[package]]
name = "zip"
version = "9.0.4"
version = "9.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a954114b47a54df49f83d2722814e86b23d4bb1b54a1b90fb7d92b41619ddc22"
checksum = "e49ade69c4434c55dd651d36fe05f38e0578db948b773cbc01c48c4b5e560692"
dependencies = [
"aes",
"bzip2",
@@ -10205,27 +10202,27 @@ dependencies = [
[[package]]
name = "zstd"
version = "0.14.3"
version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3ae9bf90af6e40197bef767eeefc46ad6397420fe873830bd85e5fbbfb3c70"
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "8.2.0"
version = "7.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded520f16b29e1a9b771c722221b2b0a0398c2316d9bb3c42b458a5414d7434b"
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "2.1.2+zstd.1.5.7"
version = "2.0.16+zstd.1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "481ada9c543b2323cbb7bbdbb5249177fbf0188ed959ed2c15e4b22421c84ed3"
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
dependencies = [
"cc",
"pkg-config",
+2 -2
View File
@@ -67,7 +67,7 @@ parking_lot = { version = "0.12.5", features = ["hardware-lock-elision"] }
anyhow = "1.0.104"
chrono = "0.4.45"
criterion = { version = "0.8.2", features = ["async_tokio"] }
tokio = { version = "1.53.3", features = [
tokio = { version = "1.53.2", features = [
"rt-multi-thread",
"macros",
"time",
@@ -88,7 +88,7 @@ rust_iso3166 = "0.2.0"
smartstring = { version = "1.0.1" }
serde = { version = "1.0.229" }
serde_json = { version = "1.0.154" }
serde_json = { version = "1.0.151" }
serde_yaml_ng = { version = "0.10.0" }
bitflags = { version = "2.13.2" }
socket2 = "0.6.5"
-1
View File
@@ -22,7 +22,6 @@
<details>
<summary><strong> 🚀 优化改进 </strong></summary>
- 优化「链式代理」:开启前需确认网速影响提示,空面板新增「关闭」按钮
**🖥️ Windows**
@@ -15,7 +15,7 @@ serde = { workspace = true, features = ["derive"] }
sysinfo = { version = "0.39.6", features = ["network", "system"] }
[target.'cfg(not(windows))'.dependencies]
libc = "0.2.191"
libc = "0.2.190"
[target.'cfg(windows)'.dependencies]
deelevate = { workspace = true }
+6 -6
View File
@@ -75,11 +75,11 @@
"monaco-yaml": "^5.5.1",
"nanoid": "^6.0.1",
"qrcode.react": "^4.2.0",
"react": "19.3.1",
"react-dom": "19.3.1",
"react": "19.3.0",
"react-dom": "19.3.0",
"react-error-boundary": "6.1.6",
"react-hook-form": "^7.88.0",
"react-i18next": "17.1.0",
"react-i18next": "17.0.15",
"react-markdown": "10.1.0",
"react-router": "^8.4.0",
"rehype-raw": "^7.0.0",
@@ -123,7 +123,7 @@
"https-proxy-agent": "^9.1.0",
"husky": "^9.1.7",
"jiti": "^2.7.0",
"knip": "6.42.0",
"knip": "6.39.0",
"lint-staged": "^17.5.1",
"sass": "^1.104.1",
"tar": "^7.5.22",
@@ -133,7 +133,7 @@
"vite": "^8.3.0",
"vite-plugin-svgr": "^5.2.0",
"vitest": "^5.0.1",
"webdriverio": "10.1.0",
"webdriverio": "10.0.0",
"ws": "8.22.0"
},
"lint-staged": {
@@ -146,5 +146,5 @@
]
},
"type": "module",
"packageManager": "pnpm@12.14.0"
"packageManager": "pnpm@12.11.2"
}
+589 -389
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,3 +1,3 @@
[toolchain]
channel = "1.99.1"
channel = "1.99.0"
components = ["rustfmt", "clippy"]
+5 -5
View File
@@ -79,13 +79,13 @@ tauri-plugin-fs = "2.6.0"
tauri-plugin-process = "2.4.0"
tauri-plugin-deep-link = "2.6.1"
tauri-plugin-window-state = "2.5.0"
zip = "9.0.4"
zip = "9.0.1"
flate2 = "1.1.10"
reqwest_dav = "0.3.3"
aes-gcm = { version = "0.11.1" }
base64 = "0.23.1"
minisign-verify = "0.3.0"
sha2 = "0.11.1"
sha2 = "0.11"
getrandom = "0.4.3"
futures = "0.3.34"
gethostname = "1.1.0"
@@ -103,17 +103,17 @@ clash_verge_service_ipc = { git = "https://github.com/clash-verge-rev/clash-verg
] }
arc-swap = "1.9.2"
tokio-rustls = "0.26.6"
rustls = { version = "0.23.46", features = ["ring"] }
rustls = { version = "0.23.45", features = ["ring"] }
webpki-roots = "1.0.9"
dark-light = "3.0.0"
bytes = "1.12.1"
tokio-util = { version = "0.7.20", features = ["time"] }
tokio-util = { version = "0.7.19", features = ["time"] }
specta = { version = "=2.0.0-rc.25", features = ["derive", "function", "serde_json"] }
tauri-specta = { version = "=2.0.0-rc.25", features = ["derive", "typescript"] }
specta-typescript = "=0.0.12"
[target.'cfg(unix)'.dependencies]
libc = "0.2.191"
libc = "0.2.190"
[target.'cfg(target_os = "linux")'.dependencies]
# Upstream has no session-end signal support on Linux; see crates/clash-verge-signal.
+67 -59
View File
@@ -1,4 +1,4 @@
use crate::config::{IProfilePreview, IVerge};
use crate::config::{IProfilePreview, IProfiles, IVerge};
use crate::core::lightweight;
use crate::core::proxy_view::{ProxyGroupView, ProxyMemberRef, ProxyNodeSource, ProxyViewProviderState, ProxyViewV1};
use crate::core::tray::menu_def::TrayAction;
@@ -42,7 +42,8 @@ const TRAY_CLICK_DEBOUNCE_MS: u64 = 300;
pub const TRAY_ID: &str = "clash-verge-rev-tray";
#[derive(Clone, Copy)]
struct TrayMenuOptions {
struct TrayMenuOptions<'a> {
mode: Option<&'a str>,
is_lightweight_mode: bool,
include_proxy_groups: bool,
}
@@ -223,9 +224,8 @@ impl Tray {
};
let verge = Config::verge().await.latest_arc();
let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false);
let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false);
let tun_mode_available = crate::core::runstate::RUN_STATE.state().tun_capable();
let system_proxy = verge.enable_system_proxy.unwrap_or(false);
let tun_mode = verge.enable_tun_mode.unwrap_or(false);
let mode = {
Config::clash()
.await
@@ -236,30 +236,59 @@ impl Tray {
.unwrap_or("rule")
.to_owned()
};
let profiles_config = Config::profiles().await;
let profiles_arc = profiles_config.latest_arc();
let profiles_preview = profiles_arc.profiles_preview().unwrap_or_default();
let is_lightweight_mode = is_in_lightweight_mode();
let (menu, latency_items) = create_tray_menu(
app_handle,
Some(mode.as_str()),
*system_proxy,
*tun_mode,
tun_mode_available,
profiles_preview,
TrayMenuOptions {
is_lightweight_mode,
include_proxy_groups,
},
)
.await?;
tray.set_menu(Some(menu))?;
let groups: Vec<_> = latency_items.keys().cloned().collect();
*self.latency_items.lock() = latency_items;
for group in groups {
self.refresh_latency_item(&group);
}
// Proxy data must remain optional so a stopped Core cannot roll back unrelated settings.
let fetch_proxy_groups =
include_proxy_groups && verge.tray_proxy_groups_display_mode.as_deref() != Some("disable");
let proxy_view = if fetch_proxy_groups {
tokio::time::timeout(
Duration::from_millis(1000),
cmd::proxy::proxy_view(Some(Duration::from_millis(750))),
)
.await
.ok()
.and_then(Result::ok)
} else {
None
};
let verge = if fetch_proxy_groups {
Config::verge().await.latest_arc()
} else {
verge
};
let profiles = Config::profiles().await.latest_arc();
let (tx, rx) = tokio::sync::oneshot::channel();
let dispatch_handle = app_handle.clone();
app_handle
.run_on_main_thread(move || {
let _ = tx.send((|| -> Result<()> {
let (menu, latency_items) = build_tray_menu(
&dispatch_handle,
system_proxy,
tun_mode,
TrayMenuOptions {
mode: Some(mode.as_str()),
is_lightweight_mode,
include_proxy_groups,
},
&verge,
&profiles,
proxy_view,
)?;
tray.set_menu(Some(menu))?;
let groups: Vec<_> = latency_items.keys().cloned().collect();
*Self::global().latency_items.lock() = latency_items;
for group in &groups {
Self::global().refresh_latency_item_on_main_thread(group);
}
Ok(())
})());
})
.map_err(|e| anyhow::anyhow!("Failed to dispatch tray menu update: {e}"))?;
rx.await
.map_err(|_| anyhow::anyhow!("Tray menu update returned no result"))??;
logging!(debug, Type::Tray, "托盘菜单更新成功");
Ok(())
@@ -790,39 +819,17 @@ fn create_proxy_menu_item(
Ok((proxies_submenu, inline_proxy_items))
}
async fn create_tray_menu(
fn build_tray_menu(
app_handle: &AppHandle,
mode: Option<&str>,
system_proxy_enabled: bool,
tun_mode_enabled: bool,
tun_mode_available: bool,
profiles_preview: Vec<IProfilePreview<'_>>,
options: TrayMenuOptions,
options: TrayMenuOptions<'_>,
verge_settings: &IVerge,
profiles_config: &IProfiles,
proxy_view: Option<ProxyViewV1>,
) -> Result<(tauri::menu::Menu<Wry>, HashMap<std::string::String, LatencyMenuItem>)> {
let current_proxy_mode = mode.unwrap_or("");
let mut verge_settings = Config::verge().await.latest_arc();
let fetch_proxy_groups =
options.include_proxy_groups && verge_settings.tray_proxy_groups_display_mode.as_deref() != Some("disable");
// Proxy data must remain optional so a stopped Core cannot roll back unrelated settings.
let proxy_view = if fetch_proxy_groups {
tokio::time::timeout(
Duration::from_millis(1000),
cmd::proxy::proxy_view(Some(Duration::from_millis(750))),
)
.await
.ok()
.and_then(Result::ok)
} else {
None
};
if fetch_proxy_groups {
verge_settings = Config::verge().await.latest_arc();
}
let profiles_config = Config::profiles().await.latest_arc();
let current_proxy_mode = options.mode.unwrap_or("");
let tun_mode_available = crate::core::runstate::RUN_STATE.state().tun_capable();
let tray_proxy_groups_display_mode = verge_settings
.tray_proxy_groups_display_mode
@@ -836,7 +843,8 @@ async fn create_tray_menu(
let hotkeys = create_hotkeys(&verge_settings.hotkeys);
let profile_menu_items: Vec<CheckMenuItem<Wry>> = create_profile_menu_item(app_handle, profiles_preview)?;
let profile_menu_items: Vec<CheckMenuItem<Wry>> =
create_profile_menu_item(app_handle, profiles_config.profiles_preview().unwrap_or_default())?;
let texts = MenuTexts::new();
let profile_menu_items_refs: Vec<&dyn IsMenuItem<Wry>> = profile_menu_items
@@ -917,8 +925,8 @@ async fn create_tray_menu(
proxy_view,
&mut latency_items,
&texts,
&verge_settings,
&profiles_config,
verge_settings,
profiles_config,
);
match tray_proxy_groups_display_mode {
-7
View File
@@ -75,7 +75,6 @@ interface ProxyChainProps {
onMarkUnsavedChanges?: () => void
mode?: string
selectedGroup?: string | null
onExitChainMode: () => void
}
interface ProxyChainItemProps {
@@ -332,7 +331,6 @@ export const ProxyChain = ({
onMarkUnsavedChanges,
mode,
selectedGroup,
onExitChainMode,
}: ProxyChainProps) => {
const theme = useTheme()
const { t } = useTranslation()
@@ -698,18 +696,13 @@ export const ProxyChain = ({
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: 2,
height: '100%',
color: theme.palette.text.secondary,
}}
>
<Typography>{t('proxies.page.chain.empty')}</Typography>
<Button size="small" variant="outlined" onClick={onExitChainMode}>
{t('shared.actions.close')}
</Button>
</Box>
) : (
<DragDropProvider
@@ -77,7 +77,6 @@ interface GroupSelectMenuProps {
interface ProxyGroupsChainProps {
mode: string
chainConfigData?: string | null
onExitChainMode: () => void
availableGroups: any[]
activeSelectedGroup: string | null
showScrollTop: boolean
@@ -306,7 +305,6 @@ export function ProxyGroupsChain(props: ProxyGroupsChainProps) {
const {
mode,
chainConfigData,
onExitChainMode,
availableGroups,
activeSelectedGroup,
showScrollTop,
@@ -523,7 +521,6 @@ export function ProxyGroupsChain(props: ProxyGroupsChainProps) {
chainConfigData={chainConfigData}
mode={mode}
selectedGroup={activeSelectedGroup}
onExitChainMode={onExitChainMode}
/>
</Box>
</Box>
+3 -10
View File
@@ -71,7 +71,6 @@ interface Props {
mode: string
isChainMode?: boolean
chainConfigData?: string | null
onExitChainMode: () => void
}
function useEmptyRenderList() {
@@ -200,9 +199,8 @@ function useProxyRenderState(
function ChainProxyGroups(props: {
mode: string
chainConfigData?: string | null
onExitChainMode: () => void
}) {
const { mode, chainConfigData, onExitChainMode } = props
const { mode, chainConfigData } = props
const { proxyView } = useProxiesData()
const [selectedGroup, setSelectedGroup] = useState<string | null>(null)
@@ -357,7 +355,6 @@ function ChainProxyGroups(props: {
<ProxyGroupsChain
mode={mode}
chainConfigData={chainConfigData}
onExitChainMode={onExitChainMode}
availableGroups={availableGroups}
activeSelectedGroup={activeSelectedGroup}
showScrollTop={showScrollTop}
@@ -629,7 +626,7 @@ function NormalProxyGroups(props: { mode: string }) {
}
export const ProxyGroups = (props: Props) => {
const { mode, isChainMode = false, chainConfigData, onExitChainMode } = props
const { mode, isChainMode = false, chainConfigData } = props
const { profiles, isLoading: isProfilesLoading } = useProfiles()
const { isProxyViewPending } = useProxiesData()
const { isRunningModePending } = useSystemData()
@@ -651,11 +648,7 @@ export const ProxyGroups = (props: Props) => {
return <ProxyEmptyState reason={listState.reason} />
case 'render':
return isChainMode ? (
<ChainProxyGroups
mode={mode}
chainConfigData={chainConfigData}
onExitChainMode={onExitChainMode}
/>
<ChainProxyGroups mode={mode} chainConfigData={chainConfigData} />
) : (
<NormalProxyGroups mode={mode} />
)
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "Chain Proxy Config",
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"confirmEnable": "I understand, enable",
"keepDisabled": "Keep disabled",
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "Proxy-Kette konfigurieren",
"warning": "Eine Proxy-Kette verringert die Netzwerkgeschwindigkeit deutlich. Wenn Sie keinen klaren Bedarf haben oder diese Konfiguration nicht verstehen, lassen Sie sie deaktiviert.",
"confirmEnable": "Verstanden, aktivieren",
"keepDisabled": "Deaktiviert lassen",
"empty": "Eine Proxy-Kette verringert die Netzwerkgeschwindigkeit deutlich. Wenn Sie keinen klaren Bedarf haben oder diese Konfiguration nicht verstehen, lassen Sie sie deaktiviert.",
"instruction": "Klicken Sie die Knoten nacheinander an, um sie zur Proxy-Kette hinzuzufügen",
"minimumNodes": "Eine Proxy-Kette braucht mindestens 2 Knoten",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "Chain Proxy Config",
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"confirmEnable": "I understand, enable",
"keepDisabled": "Keep disabled",
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "Chain Proxy Config",
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"confirmEnable": "I understand, enable",
"keepDisabled": "Keep disabled",
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "Chain Proxy Config",
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"confirmEnable": "I understand, enable",
"keepDisabled": "Keep disabled",
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "Chain Proxy Config",
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"confirmEnable": "I understand, enable",
"keepDisabled": "Keep disabled",
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "Chain Proxy Config",
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"confirmEnable": "I understand, enable",
"keepDisabled": "Keep disabled",
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "체인 프록시 구성",
"warning": "체인 프록시는 네트워크 속도를 크게 저하시킬 수 있습니다. 명확한 업무상 필요가 없거나 이 구성을 이해하지 못한다면 비활성화 상태로 두세요.",
"confirmEnable": "이해했습니다, 활성화",
"keepDisabled": "비활성화 유지",
"empty": "체인 프록시는 네트워크 속도를 크게 저하시킬 수 있습니다. 명확한 업무상 필요가 없거나 이 구성을 이해하지 못한다면 비활성화 상태로 두세요.",
"instruction": "프록시 체인에 추가하려면 순서대로 노드를 클릭하세요",
"minimumNodes": "체인 프록시는 최소 2개의 노드가 필요합니다",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "Configuração do proxy em cadeia",
"warning": "O proxy em cadeia reduz significativamente a velocidade da rede. Se você não tem uma necessidade clara ou não entende esta configuração, mantenha-o desativado.",
"confirmEnable": "Entendi, ativar",
"keepDisabled": "Manter desativado",
"empty": "O proxy em cadeia reduz significativamente a velocidade da rede. Se você não tem uma necessidade clara ou não entende esta configuração, mantenha-o desativado.",
"instruction": "Clique nos nós em ordem para adicioná-los à cadeia de proxy",
"minimumNodes": "O proxy em cadeia requer pelo menos 2 nós",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "Цепочка прокси",
"warning": "Цепочка прокси может значительно снизить скорость сети. Если у вас нет явной рабочей необходимости или вы не понимаете эту настройку, оставьте ее отключенной.",
"confirmEnable": "Понятно, включить",
"keepDisabled": "Оставить выключенным",
"empty": "Цепочка прокси может значительно снизить скорость сети. Если у вас нет явной рабочей необходимости или вы не понимаете эту настройку, оставьте ее отключенной.",
"instruction": "Нажимайте на узлы по порядку, чтобы добавить их в цепочку",
"minimumNodes": "Для цепочки требуется минимум 2 узла",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "Zincir Vekil Yapılandırması",
"warning": "Zincir vekil ağ hızını belirgin biçimde düşürür. Açık bir ihtiyacınız yoksa ya da bu yapılandırmayı bilmiyorsanız devre dışı bırakın.",
"confirmEnable": "Anladım, etkinleştir",
"keepDisabled": "Devre dışı kalsın",
"empty": "Zincir vekil ağ hızını belirgin biçimde düşürür. Açık bir ihtiyacınız yoksa ya da bu yapılandırmayı bilmiyorsanız devre dışı bırakın.",
"instruction": "Vekil zincirine eklemek için düğümlere sırayla tıklayın",
"minimumNodes": "Zincir vekil en az 2 düğüm gerektirir",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "Chain Proxy Config",
"warning": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"confirmEnable": "I understand, enable",
"keepDisabled": "Keep disabled",
"empty": "Chain proxy will significantly reduce network speed. If you do not have a clear business need, or do not understand this configuration, keep it disabled.",
"instruction": "Click nodes in order to add to proxy chain",
"minimumNodes": "Chain proxy requires at least 2 nodes",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "代理链配置",
"warning": "链式代理会显著降低网速。如果您没有明确的业务需求,或不了解此项配置,请保持关闭",
"confirmEnable": "我明白,开启",
"keepDisabled": "保持关闭",
"empty": "链式代理会显著降低网速。如果您没有明确的业务需求,或不了解此项配置,请保持关闭",
"instruction": "顺序点击节点添加到代理链中",
"minimumNodes": "链式代理至少需要 2 个节点",
-2
View File
@@ -70,8 +70,6 @@
"chain": {
"header": "鏈式代理設定",
"warning": "鏈式代理會顯著降低網速。如果您沒有明確的業務需求,或不了解此項設定,請保持關閉",
"confirmEnable": "我明白,開啟",
"keepDisabled": "保持關閉",
"empty": "鏈式代理會顯著降低網速。如果您沒有明確的業務需求,或不了解此項設定,請保持關閉",
"instruction": "依序點擊節點新增到鏈式代理中",
"minimumNodes": "鏈式代理至少需要 2 個節點",
+24 -43
View File
@@ -1,10 +1,10 @@
import { LanOutlined, LanRounded, WarningRounded } from '@mui/icons-material'
import { Box, Button, ButtonGroup, Typography } from '@mui/material'
import { Box, Button, ButtonGroup } from '@mui/material'
import { useLockFn } from 'ahooks'
import { useCallback, useEffect, useReducer, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { BaseDialog, BasePage, TooltipIcon } from '@/components/base'
import { BasePage, TooltipIcon } from '@/components/base'
import { ProviderButton } from '@/components/proxy/provider-button'
import { ProxyGroups } from '@/components/proxy/proxy-groups'
import {
@@ -38,7 +38,6 @@ const ProxyPage = () => {
return false
}
})
const [chainConfirmOpen, setChainConfirmOpen] = useState(false)
const [chainConfigData, dispatchChainConfigData] = useReducer(
(_: string | null, action: string | null) => action,
@@ -69,34 +68,32 @@ const ProxyPage = () => {
}
})
const applyChainMode = (enabled: boolean) => {
setIsChainMode(enabled)
localStorage.setItem('proxy-chain-mode-enabled', enabled.toString())
}
const onToggleChainMode = useLockFn(async () => {
const newChainMode = !isChainMode
const onExitChainMode = useLockFn(async () => {
// 退出链式代理模式时,清除链式代理配置
try {
debugLog('Exiting chain mode, clearing chain configuration')
const result = await mutate(() => updateProxyChainConfigInRuntime(null), {
id: 'update-proxy-chain-runtime',
errorNotice: false,
})
if (!result.ok) return
debugLog('Chain configuration cleared successfully')
} catch (error) {
console.error('Failed to clear chain configuration:', error)
showNotice.error(error)
return
if (!newChainMode) {
// 退出链式代理模式时,清除链式代理配置
try {
debugLog('Exiting chain mode, clearing chain configuration')
const result = await mutate(
() => updateProxyChainConfigInRuntime(null),
{
id: 'update-proxy-chain-runtime',
errorNotice: false,
},
)
if (!result.ok) return
debugLog('Chain configuration cleared successfully')
} catch (error) {
console.error('Failed to clear chain configuration:', error)
showNotice.error(error)
return
}
}
applyChainMode(false)
setIsChainMode(newChainMode)
localStorage.setItem('proxy-chain-mode-enabled', newChainMode.toString())
})
const onToggleChainMode = () => {
if (isChainMode) onExitChainMode().catch(() => {})
else setChainConfirmOpen(true)
}
// 当开启链式代理模式时,获取配置数据
useEffect(() => {
if (!isChainMode) {
@@ -205,23 +202,7 @@ const ProxyPage = () => {
mode={curMode ?? 'rule'}
isChainMode={isChainMode}
chainConfigData={chainConfigData}
onExitChainMode={onExitChainMode}
/>
<BaseDialog
open={chainConfirmOpen}
title={t('proxies.page.actions.toggleChain')}
okBtn={t('proxies.page.chain.confirmEnable')}
cancelBtn={t('proxies.page.chain.keepDisabled')}
contentSx={{ width: { xs: 320, sm: 420 } }}
onCancel={() => setChainConfirmOpen(false)}
onClose={() => setChainConfirmOpen(false)}
onOk={() => {
setChainConfirmOpen(false)
applyChainMode(true)
}}
>
<Typography variant="body2">{chainWarning}</Typography>
</BaseDialog>
</BasePage>
)
}
-2
View File
@@ -322,8 +322,6 @@ export const translationKeys = [
'proxies.page.empty.actions.openLogs',
'proxies.page.chain.header',
'proxies.page.chain.warning',
'proxies.page.chain.confirmEnable',
'proxies.page.chain.keepDisabled',
'proxies.page.chain.empty',
'proxies.page.chain.instruction',
'proxies.page.chain.minimumNodes',
-2
View File
@@ -525,7 +525,6 @@ export interface TranslationResources {
toggleChain: string
}
chain: {
confirmEnable: string
connectFailed: string
disconnectFailed: string
duplicateNode: string
@@ -534,7 +533,6 @@ export interface TranslationResources {
exitNode: string
header: string
instruction: string
keepDisabled: string
minimumNodes: string
minimumNodesHint: string
warning: string