mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-15 13:50:47 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84027cbae1 | ||
|
|
5343040ef3 | ||
|
|
75cd7dd4b9 | ||
|
|
fb6ffd8e09 | ||
|
|
aca9e61f39 | ||
|
|
56078098a4 | ||
|
|
1f197965e0 | ||
|
|
183f0f6c42 | ||
|
|
76624c7d83 | ||
|
|
ab47c56ec5 | ||
|
|
ad35ed96c8 | ||
|
|
97bd51cf5f | ||
|
|
f4a110cfd7 | ||
|
|
e9ed06adfd | ||
|
|
bc5eaf34fe | ||
|
|
3e8b891dd0 | ||
|
|
3f2ea4bc64 | ||
|
|
ae81b37c1d | ||
|
|
b4349afb1b | ||
|
|
0cffe8e3f7 | ||
|
|
7a1f4f9abe | ||
|
|
5768b01786 | ||
|
|
7e9079467f | ||
|
|
615e96922e | ||
|
|
8b94c452fb | ||
|
|
66dd510acc | ||
|
|
96e044566c | ||
|
|
726ad84d7f | ||
|
|
4fc422f880 | ||
|
|
1938024ab3 | ||
|
|
05b1de6fd5 | ||
|
|
0bf8807b50 | ||
|
|
23668ee74e | ||
|
|
6bc5c5a808 | ||
|
|
330004dc72 | ||
|
|
a900d6d742 | ||
|
|
bfea70eec9 | ||
|
|
13babbf330 | ||
|
|
0a6fe382ac | ||
|
|
dd6dea9dfc | ||
|
|
11434fba68 | ||
|
|
10bf90c92a | ||
|
|
5193fe4bab | ||
|
|
4df4995623 | ||
|
|
f5f4ecf46a | ||
|
|
69b65d06a4 | ||
|
|
e6bf4e836d | ||
|
|
01d67eb239 | ||
|
|
3514cfbd44 | ||
|
|
cade35fe10 | ||
|
|
2c6df77f5a | ||
|
|
0276ae91b5 | ||
|
|
60fee2accb | ||
|
|
03e2632294 | ||
|
|
194fe59458 | ||
|
|
e400111f8a | ||
|
|
8bc7607783 |
@@ -1,8 +1,5 @@
|
||||
pnpm install
|
||||
pnpm check $INPUT_TARGET
|
||||
sed -i "s/#openssl/openssl={version=\"0.10\",features=[\"vendored\"]}/g" src-tauri/Cargo.toml
|
||||
if [ "$INPUT_TARGET" = "x86_64-unknown-linux-gnu" ]; then
|
||||
pnpm build --target $INPUT_TARGET
|
||||
else
|
||||
pnpm build --target $INPUT_TARGET -b deb
|
||||
fi
|
||||
|
||||
cargo tauri build --target $INPUT_TARGET
|
||||
|
||||
@@ -5,6 +5,8 @@ tar -Jxvf ./node-v20.10.0-linux-x64.tar.xz
|
||||
export PATH=$(pwd)/node-v20.10.0-linux-x64/bin:$PATH
|
||||
npm install pnpm -g
|
||||
|
||||
cargo install --git https://github.com/tauri-apps/tauri --branch 1.x tauri-cli
|
||||
|
||||
rustup target add "$INPUT_TARGET"
|
||||
|
||||
if [ "$INPUT_TARGET" = "x86_64-unknown-linux-gnu" ]; then
|
||||
|
||||
+27
-23
@@ -43,15 +43,17 @@ jobs:
|
||||
with:
|
||||
workspaces: src-tauri
|
||||
|
||||
- name: Install Tauri CLI
|
||||
run: cargo install --git https://github.com/tauri-apps/tauri --branch 1.x tauri-cli
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 9
|
||||
run_install: false
|
||||
|
||||
- name: Pnpm install and check
|
||||
@@ -62,16 +64,23 @@ jobs:
|
||||
- name: Tauri build
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
with:
|
||||
tagName: alpha
|
||||
releaseName: "Clash Verge Rev Alpha"
|
||||
releaseBody: "More new features are now supported."
|
||||
releaseDraft: false
|
||||
prerelease: true
|
||||
tauriScript: pnpm
|
||||
tauriScript: cargo tauri
|
||||
args: --target ${{ matrix.target }}
|
||||
|
||||
- name: Portable Bundle
|
||||
@@ -101,6 +110,7 @@ jobs:
|
||||
- name: Build for Linux
|
||||
uses: ./.github/build-for-linux
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
with:
|
||||
@@ -114,7 +124,6 @@ jobs:
|
||||
echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
|
||||
|
||||
- name: Upload Release
|
||||
if: startsWith(matrix.target, 'x86_64')
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: alpha
|
||||
@@ -122,17 +131,9 @@ jobs:
|
||||
body: "More new features are now supported."
|
||||
prerelease: true
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
files: src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage*
|
||||
|
||||
- name: Upload Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: alpha
|
||||
name: "Clash Verge Rev Alpha"
|
||||
body: "More new features are now supported."
|
||||
prerelease: true
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
files: src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
|
||||
files: |
|
||||
src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
|
||||
src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm
|
||||
|
||||
alpha-for-fixed-webview2:
|
||||
strategy:
|
||||
@@ -161,15 +162,17 @@ jobs:
|
||||
with:
|
||||
workspaces: src-tauri
|
||||
|
||||
- name: Install Tauri CLI
|
||||
run: cargo install --git https://github.com/tauri-apps/tauri --branch 1.x tauri-cli
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 9
|
||||
run_install: false
|
||||
|
||||
- name: Pnpm install and check
|
||||
@@ -188,11 +191,12 @@ jobs:
|
||||
id: build
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
with:
|
||||
tauriScript: pnpm
|
||||
tauriScript: cargo tauri
|
||||
args: --target ${{ matrix.target }}
|
||||
|
||||
- name: Rename
|
||||
@@ -245,12 +249,12 @@ jobs:
|
||||
- MacOS apple M芯片: aarch64.dmg
|
||||
|
||||
### Linux
|
||||
- Linux 64位: amd64.AppImage/amd64.deb
|
||||
- Linux 32位: i386.deb
|
||||
- Linux arm64架构: arm64.deb
|
||||
- Linux armv7架构: armhf.deb
|
||||
- Linux 64位: amd64.deb/amd64.rpm
|
||||
- Linux 32位: i386.deb/i386.rpm
|
||||
- Linux arm64架构: arm64.deb/aarch64.rpm
|
||||
- Linux armv7架构: armhf.deb/armhfp.rpm
|
||||
|
||||
### Windows (Win7 用户请查看下面FAQ手动替换内核使用)
|
||||
### Windows (Win7 用户请查看下面FAQ中的解决方案)
|
||||
#### 正常版本(推荐)
|
||||
- 64位: x64-setup.exe
|
||||
- 32位: x86-setup.exe
|
||||
|
||||
@@ -45,10 +45,9 @@ jobs:
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 9
|
||||
run_install: false
|
||||
|
||||
- name: Pnpm install and check
|
||||
@@ -59,9 +58,16 @@ jobs:
|
||||
- name: Tauri build
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
with:
|
||||
tagName: v__VERSION__
|
||||
releaseName: "Clash Verge Rev v__VERSION__"
|
||||
@@ -96,6 +102,7 @@ jobs:
|
||||
- name: Build for Linux
|
||||
uses: ./.github/build-for-linux
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
with:
|
||||
@@ -108,23 +115,15 @@ jobs:
|
||||
echo "VERSION=$(cat package.json | jq '.version' | tr -d '"')" >> $GITHUB_ENV
|
||||
|
||||
- name: Upload Release
|
||||
if: startsWith(matrix.target, 'x86_64')
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: v${{env.VERSION}}
|
||||
name: "Clash Verge Rev v${{env.VERSION}}"
|
||||
body: "More new features are now supported."
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
files: src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage*
|
||||
|
||||
- name: Upload Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: v${{env.VERSION}}
|
||||
name: "Clash Verge Rev v${{env.VERSION}}"
|
||||
body: "More new features are now supported."
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
files: src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
|
||||
files: |
|
||||
src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
|
||||
src-tauri/target/${{ matrix.target }}/release/bundle/rpm/*.rpm
|
||||
|
||||
release-for-fixed-webview2:
|
||||
strategy:
|
||||
@@ -158,10 +157,9 @@ jobs:
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 9
|
||||
run_install: false
|
||||
|
||||
- name: Pnpm install and check
|
||||
@@ -180,6 +178,7 @@ jobs:
|
||||
id: build
|
||||
uses: tauri-apps/tauri-action@v0
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||
@@ -219,10 +218,9 @@ jobs:
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 9
|
||||
run_install: false
|
||||
|
||||
- name: Pnpm install
|
||||
@@ -245,10 +243,9 @@ jobs:
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 9
|
||||
run_install: false
|
||||
|
||||
- name: Pnpm install
|
||||
|
||||
@@ -7,17 +7,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 9
|
||||
run_install: false
|
||||
|
||||
- name: Pnpm install
|
||||
@@ -39,10 +38,9 @@ jobs:
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 9
|
||||
run_install: false
|
||||
|
||||
- name: Pnpm install
|
||||
|
||||
+32
-1
@@ -1,4 +1,35 @@
|
||||
## v1.6.3
|
||||
## v1.6.6
|
||||
|
||||
### Features
|
||||
|
||||
- MacOS 应用签名
|
||||
- 删除 AppImage
|
||||
- 应用更新对话框添加下载按钮
|
||||
- 设置系统代理绕过时保留默认值
|
||||
- 系统代理绕过设置输入格式检查
|
||||
|
||||
### Bugs Fixes
|
||||
|
||||
- MacOS 代理组图标无法显示
|
||||
- RPM 包依赖缺失
|
||||
|
||||
---
|
||||
|
||||
## v1.6.5
|
||||
|
||||
### Features
|
||||
|
||||
- 添加 RPM 包支持
|
||||
- 优化细节
|
||||
|
||||
### Bugs Fixes
|
||||
|
||||
- MacOS 10.15 编辑器空白的问题
|
||||
- MacOS 低版本启动白屏的问题
|
||||
|
||||
---
|
||||
|
||||
## v1.6.4
|
||||
|
||||
### Features
|
||||
|
||||
|
||||
+27
-25
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "clash-verge",
|
||||
"version": "1.6.3",
|
||||
"version": "1.6.6",
|
||||
"license": "GPL-3.0-only",
|
||||
"scripts": {
|
||||
"dev": "tauri dev",
|
||||
@@ -24,47 +24,47 @@
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@juggle/resize-observer": "^3.4.0",
|
||||
"@mui/icons-material": "^5.15.16",
|
||||
"@mui/icons-material": "^5.15.19",
|
||||
"@mui/lab": "5.0.0-alpha.149",
|
||||
"@mui/material": "^5.15.16",
|
||||
"@mui/x-data-grid": "^6.19.11",
|
||||
"@tauri-apps/api": "^1.5.4",
|
||||
"@mui/material": "^5.15.19",
|
||||
"@mui/x-data-grid": "^6.20.1",
|
||||
"@tauri-apps/api": "^1.5.6",
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"ahooks": "^3.7.11",
|
||||
"axios": "^1.6.8",
|
||||
"axios-tauri-api-adapter": "^0.2.1",
|
||||
"ahooks": "^3.8.0",
|
||||
"axios": "^1.7.2",
|
||||
"dayjs": "1.11.5",
|
||||
"i18next": "^23.11.3",
|
||||
"foxact": "^0.2.35",
|
||||
"i18next": "^23.11.5",
|
||||
"lodash-es": "^4.17.21",
|
||||
"meta-json-schema": "1.18.5-alpha",
|
||||
"monaco-editor": "^0.48.0",
|
||||
"monaco-yaml": "^5.1.1",
|
||||
"types-pac": "^1.0.2",
|
||||
"meta-json-schema": "1.18.5-alpha4",
|
||||
"monaco-editor": "^0.49.0",
|
||||
"monaco-yaml": "^5.2.0",
|
||||
"nanoid": "^5.0.7",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-error-boundary": "^3.1.4",
|
||||
"react-hook-form": "^7.51.4",
|
||||
"react-hook-form": "^7.51.5",
|
||||
"react-i18next": "^13.5.0",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-router-dom": "^6.23.0",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"react-virtuoso": "^4.7.10",
|
||||
"recoil": "^0.7.7",
|
||||
"react-virtuoso": "^4.7.11",
|
||||
"swr": "^1.3.0",
|
||||
"tar": "^6.2.1"
|
||||
"tar": "^6.2.1",
|
||||
"types-pac": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@actions/github": "^5.1.1",
|
||||
"@tauri-apps/cli": "^1.5.13",
|
||||
"@tauri-apps/cli": "^1.5.14",
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/react": "^18.3.1",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/react-transition-group": "^4.4.10",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"adm-zip": "^0.5.12",
|
||||
"@vitejs/plugin-legacy": "^5.4.1",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"adm-zip": "^0.5.14",
|
||||
"cross-env": "^7.0.3",
|
||||
"fs-extra": "^11.2.0",
|
||||
"https-proxy-agent": "^5.0.1",
|
||||
@@ -72,9 +72,10 @@
|
||||
"node-fetch": "^3.3.2",
|
||||
"prettier": "^2.8.8",
|
||||
"pretty-quick": "^3.3.1",
|
||||
"sass": "^1.77.0",
|
||||
"sass": "^1.77.5",
|
||||
"terser": "^5.31.1",
|
||||
"typescript": "^5.4.5",
|
||||
"vite": "^5.2.11",
|
||||
"vite": "^5.2.13",
|
||||
"vite-plugin-monaco-editor": "^1.1.0",
|
||||
"vite-plugin-svgr": "^4.2.0"
|
||||
},
|
||||
@@ -83,5 +84,6 @@
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
},
|
||||
"packageManager": "pnpm@9.1.4"
|
||||
}
|
||||
|
||||
Generated
+2370
-718
File diff suppressed because it is too large
Load Diff
@@ -41,6 +41,7 @@ async function resolveUpdater() {
|
||||
"windows-x86_64": { signature: "", url: "" },
|
||||
"windows-aarch64": { signature: "", url: "" },
|
||||
"windows-x86": { signature: "", url: "" },
|
||||
"windows-i686": { signature: "", url: "" },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -60,11 +61,13 @@ async function resolveUpdater() {
|
||||
// win32 url
|
||||
if (name.endsWith("x86_fixed_webview2-setup.nsis.zip")) {
|
||||
updateData.platforms["windows-x86"].url = browser_download_url;
|
||||
updateData.platforms["windows-i686"].url = browser_download_url;
|
||||
}
|
||||
// win32 signature
|
||||
if (name.endsWith("x86_fixed_webview2-setup.nsis.zip.sig")) {
|
||||
const sig = await getSignature(browser_download_url);
|
||||
updateData.platforms["windows-x86"].signature = sig;
|
||||
updateData.platforms["windows-i686"].signature = sig;
|
||||
}
|
||||
|
||||
// win arm url
|
||||
|
||||
+12
-15
@@ -46,11 +46,13 @@ async function resolveUpdater() {
|
||||
"darwin-x86_64": { signature: "", url: "" },
|
||||
"linux-x86_64": { signature: "", url: "" },
|
||||
"linux-x86": { signature: "", url: "" },
|
||||
"linux-i686": { signature: "", url: "" },
|
||||
"linux-aarch64": { signature: "", url: "" },
|
||||
"linux-armv7": { signature: "", url: "" },
|
||||
"windows-x86_64": { signature: "", url: "" },
|
||||
"windows-aarch64": { signature: "", url: "" },
|
||||
"windows-x86": { signature: "", url: "" },
|
||||
"windows-i686": { signature: "", url: "" },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -72,11 +74,13 @@ async function resolveUpdater() {
|
||||
// win32 url
|
||||
if (name.endsWith("x64-setup.nsis.zip")) {
|
||||
updateData.platforms["windows-x86"].url = browser_download_url;
|
||||
updateData.platforms["windows-i686"].url = browser_download_url;
|
||||
}
|
||||
// win32 signature
|
||||
if (name.endsWith("x64-setup.nsis.zip.sig")) {
|
||||
const sig = await getSignature(browser_download_url);
|
||||
updateData.platforms["windows-x86"].signature = sig;
|
||||
updateData.platforms["windows-i686"].signature = sig;
|
||||
}
|
||||
|
||||
// win arm url
|
||||
@@ -106,29 +110,22 @@ async function resolveUpdater() {
|
||||
// darwin url (aarch)
|
||||
if (name.endsWith("aarch64.app.tar.gz")) {
|
||||
updateData.platforms["darwin-aarch64"].url = browser_download_url;
|
||||
// 使linux可以检查更新
|
||||
updateData.platforms.linux.url = browser_download_url;
|
||||
updateData.platforms["linux-x86_64"].url = browser_download_url;
|
||||
updateData.platforms["linux-x86"].url = browser_download_url;
|
||||
updateData.platforms["linux-i686"].url = browser_download_url;
|
||||
updateData.platforms["linux-aarch64"].url = browser_download_url;
|
||||
updateData.platforms["linux-armv7"].url = browser_download_url;
|
||||
}
|
||||
// darwin signature (aarch)
|
||||
if (name.endsWith("aarch64.app.tar.gz.sig")) {
|
||||
const sig = await getSignature(browser_download_url);
|
||||
updateData.platforms["darwin-aarch64"].signature = sig;
|
||||
}
|
||||
|
||||
// linux x64 url
|
||||
if (name.endsWith("amd64.AppImage.tar.gz")) {
|
||||
updateData.platforms.linux.url = browser_download_url;
|
||||
updateData.platforms["linux-x86_64"].url = browser_download_url;
|
||||
updateData.platforms["linux-x86"].url = browser_download_url;
|
||||
// 暂时使用x64版本的url和sig,使得可以检查更新,但aarch64版本还不支持构建appimage
|
||||
updateData.platforms["linux-aarch64"].url = browser_download_url;
|
||||
updateData.platforms["linux-armv7"].url = browser_download_url;
|
||||
}
|
||||
// linux x64 signature
|
||||
if (name.endsWith("amd64.AppImage.tar.gz.sig")) {
|
||||
const sig = await getSignature(browser_download_url);
|
||||
updateData.platforms.linux.signature = sig;
|
||||
updateData.platforms["linux-x86_64"].signature = sig;
|
||||
updateData.platforms["linux-x86"].url = browser_download_url;
|
||||
// 暂时使用x64版本的url和sig,使得可以检查更新,但aarch64版本还不支持构建appimage
|
||||
updateData.platforms["linux-i686"].url = browser_download_url;
|
||||
updateData.platforms["linux-aarch64"].signature = sig;
|
||||
updateData.platforms["linux-armv7"].signature = sig;
|
||||
}
|
||||
|
||||
Generated
+507
-486
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "clash-verge"
|
||||
version = "1.6.3"
|
||||
version = "1.6.6"
|
||||
description = "clash verge"
|
||||
authors = ["zzzgydi", "wonfen", "MystiPanda"]
|
||||
license = "GPL-3.0-only"
|
||||
@@ -10,13 +10,13 @@ edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1", features = [] }
|
||||
tauri-build = { git="https://github.com/tauri-apps/tauri",branch = "1.x", features = [] }
|
||||
|
||||
[dependencies]
|
||||
warp = "0.3"
|
||||
anyhow = "1.0"
|
||||
dirs = "5.0"
|
||||
open = "5.0"
|
||||
open = "5.1"
|
||||
log = "0.4"
|
||||
dunce = "1.0"
|
||||
log4rs = "1"
|
||||
@@ -26,9 +26,9 @@ sysinfo = "0.30"
|
||||
boa_engine = "0.18"
|
||||
serde_json = "1.0"
|
||||
serde_yaml = "0.9"
|
||||
once_cell = "1.18"
|
||||
once_cell = "1.19"
|
||||
port_scanner = "0.1.5"
|
||||
delay_timer = "0.11.5"
|
||||
delay_timer = "0.11"
|
||||
parking_lot = "0.12"
|
||||
percent-encoding = "2.3.1"
|
||||
window-shadows = { version = "0.2" }
|
||||
@@ -37,8 +37,7 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
|
||||
sysproxy = { git="https://github.com/zzzgydi/sysproxy-rs", branch = "main" }
|
||||
auto-launch = { git="https://github.com/zzzgydi/auto-launch", branch = "main" }
|
||||
tauri = { version = "1.6", features = [ "http-all", "fs-read-file", "fs-exists", "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "icon-ico", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] }
|
||||
|
||||
tauri = { git="https://github.com/tauri-apps/tauri",branch = "1.x", features = [ "fs-read-file", "fs-exists", "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "icon-ico", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] }
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
runas = "=1.2.0"
|
||||
deelevate = "0.2.0"
|
||||
|
||||
@@ -327,7 +327,7 @@ pub fn copy_icon_file(path: String, name: String) -> CmdResult<String> {
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
} else {
|
||||
return Err("file not found".to_string());
|
||||
Err("file not found".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
mod clash;
|
||||
#[allow(clippy::module_inception)]
|
||||
mod config;
|
||||
mod draft;
|
||||
mod prfitem;
|
||||
|
||||
@@ -103,7 +103,9 @@ impl PrfOption {
|
||||
a.user_agent = b.user_agent.or(a.user_agent);
|
||||
a.with_proxy = b.with_proxy.or(a.with_proxy);
|
||||
a.self_proxy = b.self_proxy.or(a.self_proxy);
|
||||
a.danger_accept_invalid_certs = b.danger_accept_invalid_certs.or(a.danger_accept_invalid_certs);
|
||||
a.danger_accept_invalid_certs = b
|
||||
.danger_accept_invalid_certs
|
||||
.or(a.danger_accept_invalid_certs);
|
||||
a.update_interval = b.update_interval.or(a.update_interval);
|
||||
Some(a)
|
||||
}
|
||||
@@ -182,7 +184,8 @@ impl PrfItem {
|
||||
let opt_ref = option.as_ref();
|
||||
let with_proxy = opt_ref.map_or(false, |o| o.with_proxy.unwrap_or(false));
|
||||
let self_proxy = opt_ref.map_or(false, |o| o.self_proxy.unwrap_or(false));
|
||||
let accept_invalid_certs = opt_ref.map_or(false, |o| o.danger_accept_invalid_certs.unwrap_or(false));
|
||||
let accept_invalid_certs =
|
||||
opt_ref.map_or(false, |o| o.danger_accept_invalid_certs.unwrap_or(false));
|
||||
let user_agent = opt_ref.and_then(|o| o.user_agent.clone());
|
||||
let update_interval = opt_ref.and_then(|o| o.update_interval);
|
||||
|
||||
@@ -300,7 +303,7 @@ impl PrfItem {
|
||||
Some(value) => {
|
||||
let str_value = value.to_str().unwrap_or("");
|
||||
Some(str_value.to_string())
|
||||
},
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
|
||||
@@ -116,12 +116,12 @@ impl CoreManager {
|
||||
// 服务模式启动失败就直接运行sidecar
|
||||
log::debug!(target: "app", "try to run core in service mode");
|
||||
|
||||
match (|| async {
|
||||
let res = async {
|
||||
service::check_service().await?;
|
||||
service::run_core_by_service(&config_path).await
|
||||
})()
|
||||
.await
|
||||
{
|
||||
}
|
||||
.await;
|
||||
match res {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(err) => {
|
||||
// 修改这个值,免得stop出错
|
||||
|
||||
@@ -43,7 +43,7 @@ impl Hotkey {
|
||||
}
|
||||
}
|
||||
}
|
||||
*self.current.lock() = hotkeys.clone();
|
||||
self.current.lock().clone_from(hotkeys);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -142,7 +142,7 @@ impl Hotkey {
|
||||
});
|
||||
|
||||
new_map.iter().for_each(|(&key, &func)| {
|
||||
if old_map.get(key).is_none() {
|
||||
if !old_map.contains_key(key) {
|
||||
add_list.push((key, func));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -22,7 +22,8 @@ pub fn grant_permission(core: String) -> anyhow::Result<()> {
|
||||
#[cfg(target_os = "linux")]
|
||||
let output = {
|
||||
let path = path.replace(' ', "\\ "); // 避免路径中有空格
|
||||
let shell = format!("setcap cap_net_bind_service,cap_net_admin,cap_dac_override=+ep {path}");
|
||||
let shell =
|
||||
format!("setcap cap_net_bind_service,cap_net_admin,cap_dac_override=+ep {path}");
|
||||
|
||||
let sudo = match Command::new("which").arg("pkexec").output() {
|
||||
Ok(output) => {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
pub mod clash_api;
|
||||
#[allow(clippy::module_inception)]
|
||||
mod core;
|
||||
pub mod handle;
|
||||
pub mod hotkey;
|
||||
pub mod logger;
|
||||
pub mod manager;
|
||||
pub mod service;
|
||||
pub mod sysopt;
|
||||
pub mod timer;
|
||||
pub mod tray;
|
||||
pub mod service;
|
||||
pub mod win_uwp;
|
||||
|
||||
pub use self::core::*;
|
||||
|
||||
@@ -41,6 +41,34 @@ static DEFAULT_BYPASS: &str = "localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,172
|
||||
static DEFAULT_BYPASS: &str =
|
||||
"127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,localhost,*.local,*.crashlytics.com,<local>";
|
||||
|
||||
fn get_bypass() -> String {
|
||||
let bypass = DEFAULT_BYPASS.to_string();
|
||||
|
||||
let res = {
|
||||
let verge = Config::verge();
|
||||
let verge = verge.latest();
|
||||
verge.system_proxy_bypass.clone()
|
||||
};
|
||||
let custom_bypass = match res {
|
||||
Some(bypass) => bypass,
|
||||
None => "".to_string(),
|
||||
};
|
||||
#[cfg(target_os = "windows")]
|
||||
let bypass = if custom_bypass.is_empty() {
|
||||
bypass
|
||||
} else {
|
||||
format!("{};{}", bypass, custom_bypass)
|
||||
};
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let bypass = if custom_bypass.is_empty() {
|
||||
bypass
|
||||
} else {
|
||||
format!("{},{}", bypass, custom_bypass)
|
||||
};
|
||||
|
||||
bypass
|
||||
}
|
||||
|
||||
impl Sysopt {
|
||||
pub fn global() -> &'static Sysopt {
|
||||
static SYSOPT: OnceCell<Sysopt> = OnceCell::new();
|
||||
@@ -63,12 +91,11 @@ impl Sysopt {
|
||||
.unwrap_or(Config::clash().data().get_mixed_port());
|
||||
let pac_port = IVerge::get_singleton_port();
|
||||
|
||||
let (enable, bypass, pac) = {
|
||||
let (enable, pac) = {
|
||||
let verge = Config::verge();
|
||||
let verge = verge.latest();
|
||||
(
|
||||
verge.enable_system_proxy.unwrap_or(false),
|
||||
verge.system_proxy_bypass.clone(),
|
||||
verge.proxy_auto_config.unwrap_or(false),
|
||||
)
|
||||
};
|
||||
@@ -76,16 +103,7 @@ impl Sysopt {
|
||||
enable,
|
||||
host: String::from("127.0.0.1"),
|
||||
port,
|
||||
bypass: match bypass {
|
||||
Some(bypass) => {
|
||||
if bypass.is_empty() {
|
||||
DEFAULT_BYPASS.into()
|
||||
} else {
|
||||
bypass
|
||||
}
|
||||
}
|
||||
None => DEFAULT_BYPASS.into(),
|
||||
},
|
||||
bypass: get_bypass(),
|
||||
};
|
||||
let mut auto = Autoproxy {
|
||||
enable,
|
||||
@@ -127,28 +145,26 @@ impl Sysopt {
|
||||
let mut cur_autoproxy = self.cur_autoproxy.lock();
|
||||
let old_autoproxy = self.old_autoproxy.lock();
|
||||
|
||||
let (enable, bypass, pac) = {
|
||||
let (enable, pac) = {
|
||||
let verge = Config::verge();
|
||||
let verge = verge.latest();
|
||||
(
|
||||
verge.enable_system_proxy.unwrap_or(false),
|
||||
verge.system_proxy_bypass.clone(),
|
||||
verge.proxy_auto_config.unwrap_or(false),
|
||||
)
|
||||
};
|
||||
if pac {
|
||||
if cur_autoproxy.is_none() || old_autoproxy.is_none() {
|
||||
drop(cur_autoproxy);
|
||||
drop(old_autoproxy);
|
||||
return self.init_sysproxy();
|
||||
}
|
||||
} else {
|
||||
if cur_sysproxy.is_none() || old_sysproxy.is_none() {
|
||||
drop(cur_sysproxy);
|
||||
drop(old_sysproxy);
|
||||
return self.init_sysproxy();
|
||||
}
|
||||
if pac && (cur_autoproxy.is_none() || old_autoproxy.is_none()) {
|
||||
drop(cur_autoproxy);
|
||||
drop(old_autoproxy);
|
||||
return self.init_sysproxy();
|
||||
}
|
||||
|
||||
if !pac && (cur_sysproxy.is_none() || old_sysproxy.is_none()) {
|
||||
drop(cur_sysproxy);
|
||||
drop(old_sysproxy);
|
||||
return self.init_sysproxy();
|
||||
}
|
||||
|
||||
let port = Config::verge()
|
||||
.latest()
|
||||
.verge_mixed_port
|
||||
@@ -156,16 +172,7 @@ impl Sysopt {
|
||||
let pac_port = IVerge::get_singleton_port();
|
||||
|
||||
let mut sysproxy = cur_sysproxy.take().unwrap();
|
||||
sysproxy.bypass = match bypass {
|
||||
Some(bypass) => {
|
||||
if bypass.is_empty() {
|
||||
DEFAULT_BYPASS.into()
|
||||
} else {
|
||||
bypass
|
||||
}
|
||||
}
|
||||
None => DEFAULT_BYPASS.into(),
|
||||
};
|
||||
sysproxy.bypass = get_bypass();
|
||||
sysproxy.port = port;
|
||||
|
||||
let mut autoproxy = cur_autoproxy.take().unwrap();
|
||||
@@ -349,14 +356,13 @@ impl Sysopt {
|
||||
loop {
|
||||
sleep(Duration::from_secs(wait_secs)).await;
|
||||
|
||||
let (enable, guard, guard_duration, bypass, pac) = {
|
||||
let (enable, guard, guard_duration, pac) = {
|
||||
let verge = Config::verge();
|
||||
let verge = verge.latest();
|
||||
(
|
||||
verge.enable_system_proxy.unwrap_or(false),
|
||||
verge.enable_proxy_guard.unwrap_or(false),
|
||||
verge.proxy_guard_duration.unwrap_or(10),
|
||||
verge.system_proxy_bypass.clone(),
|
||||
verge.proxy_auto_config.unwrap_or(false),
|
||||
)
|
||||
};
|
||||
@@ -389,16 +395,7 @@ impl Sysopt {
|
||||
enable: true,
|
||||
host: "127.0.0.1".into(),
|
||||
port,
|
||||
bypass: match bypass {
|
||||
Some(bypass) => {
|
||||
if bypass.is_empty() {
|
||||
DEFAULT_BYPASS.into()
|
||||
} else {
|
||||
bypass
|
||||
}
|
||||
}
|
||||
None => DEFAULT_BYPASS.into(),
|
||||
},
|
||||
bypass: get_bypass(),
|
||||
};
|
||||
|
||||
log_err!(sysproxy.set_system_proxy());
|
||||
|
||||
@@ -88,7 +88,7 @@ impl Tray {
|
||||
),
|
||||
))
|
||||
.add_native_item(SystemTrayMenuItem::Separator)
|
||||
.add_item(CustomMenuItem::new("quit", t!("Quit", "退出")).accelerator("CmdOrControl+Q"))
|
||||
.add_item(CustomMenuItem::new("quit", t!("Quit", "退出")))
|
||||
}
|
||||
|
||||
pub fn update_systray(app_handle: &AppHandle) -> Result<()> {
|
||||
|
||||
@@ -88,13 +88,13 @@ impl ChainItem {
|
||||
impl ChainSupport {
|
||||
pub fn is_support(&self, core: Option<&String>) -> bool {
|
||||
match core {
|
||||
Some(core) => match (self, core.as_str()) {
|
||||
(ChainSupport::All, _) => true,
|
||||
(ChainSupport::Clash, "clash") => true,
|
||||
(ChainSupport::ClashMeta, "clash-meta") => true,
|
||||
(ChainSupport::ClashMetaAlpha, "clash-meta-alpha") => true,
|
||||
_ => false,
|
||||
},
|
||||
Some(core) => matches!(
|
||||
(self, core.as_str()),
|
||||
(ChainSupport::All, _)
|
||||
| (ChainSupport::Clash, "clash")
|
||||
| (ChainSupport::ClashMeta, "clash-meta")
|
||||
| (ChainSupport::ClashMetaAlpha, "clash-meta-alpha")
|
||||
),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,11 +60,7 @@ pub fn use_sort(config: Mapping) -> Mapping {
|
||||
|
||||
let supported_keys: HashSet<&str> = HANDLE_FIELDS.into_iter().chain(DEFAULT_FIELDS).collect();
|
||||
|
||||
let config_keys: HashSet<&str> = config
|
||||
.keys()
|
||||
.filter_map(|e| e.as_str())
|
||||
.into_iter()
|
||||
.collect();
|
||||
let config_keys: HashSet<&str> = config.keys().filter_map(|e| e.as_str()).collect();
|
||||
|
||||
config_keys.difference(&supported_keys).for_each(|&key| {
|
||||
let key = Value::from(key);
|
||||
|
||||
@@ -12,7 +12,7 @@ const MERGE_FIELDS: [&str; 6] = [
|
||||
|
||||
fn deep_merge(a: &mut Value, b: &Value) {
|
||||
match (a, b) {
|
||||
(&mut Value::Mapping(ref mut a), &Value::Mapping(ref b)) => {
|
||||
(&mut Value::Mapping(ref mut a), Value::Mapping(b)) => {
|
||||
for (k, v) in b {
|
||||
deep_merge(a.entry(k.clone()).or_insert(Value::Null), v);
|
||||
}
|
||||
|
||||
@@ -136,17 +136,15 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||
.map(|(_, c)| c)
|
||||
.for_each(|item| {
|
||||
log::debug!(target: "app", "run builtin script {}", item.uid);
|
||||
|
||||
match item.data {
|
||||
ChainType::Script(script) => match use_script(script, config.to_owned()) {
|
||||
if let ChainType::Script(script) = item.data {
|
||||
match use_script(script, config.to_owned()) {
|
||||
Ok((res_config, _)) => {
|
||||
config = res_config;
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!(target: "app", "builtin script error `{err}`");
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -155,7 +153,7 @@ pub fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||
config = use_sort(config);
|
||||
|
||||
let mut exists_set = HashSet::new();
|
||||
exists_set.extend(exists_keys.into_iter());
|
||||
exists_set.extend(exists_keys);
|
||||
exists_keys = exists_set.into_iter().collect();
|
||||
|
||||
(config, exists_keys, result_map)
|
||||
|
||||
@@ -16,7 +16,7 @@ pub fn use_script(script: String, config: Mapping) -> Result<(Mapping, Vec<(Stri
|
||||
2,
|
||||
NativeFunction::from_closure(
|
||||
move |_: &JsValue, args: &[JsValue], context: &mut Context| {
|
||||
let level = args.get(0).unwrap().to_string(context)?;
|
||||
let level = args.first().unwrap().to_string(context)?;
|
||||
let level = level.to_std_string().unwrap();
|
||||
let data = args.get(1).unwrap().to_string(context)?;
|
||||
let data = data.to_std_string().unwrap();
|
||||
|
||||
+20
-10
@@ -106,7 +106,7 @@ pub fn toggle_tun_mode() {
|
||||
pub async fn patch_clash(patch: Mapping) -> Result<()> {
|
||||
Config::clash().draft().patch_config(patch.clone());
|
||||
|
||||
match {
|
||||
let res = {
|
||||
let redir_port = patch.get("redir-port");
|
||||
let tproxy_port = patch.get("tproxy-port");
|
||||
let mixed_port = patch.get("mixed-port");
|
||||
@@ -156,7 +156,8 @@ pub async fn patch_clash(patch: Mapping) -> Result<()> {
|
||||
Config::runtime().latest().patch_config(patch);
|
||||
|
||||
<Result<()>>::Ok(())
|
||||
} {
|
||||
};
|
||||
match res {
|
||||
Ok(()) => {
|
||||
Config::clash().apply();
|
||||
Config::clash().data().save_config()?;
|
||||
@@ -193,7 +194,7 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
|
||||
let tproxy_enabled = patch.verge_tproxy_enabled;
|
||||
let socks_enabled = patch.verge_socks_enabled;
|
||||
let http_enabled = patch.verge_http_enabled;
|
||||
match {
|
||||
let res = {
|
||||
let service_mode = patch.enable_service_mode;
|
||||
|
||||
if service_mode.is_some() {
|
||||
@@ -255,7 +256,8 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
|
||||
}
|
||||
|
||||
<Result<()>>::Ok(())
|
||||
} {
|
||||
};
|
||||
match res {
|
||||
Ok(()) => {
|
||||
Config::verge().apply();
|
||||
Config::verge().data().save_file()?;
|
||||
@@ -385,11 +387,19 @@ pub async fn test_delay(url: String) -> Result<u32> {
|
||||
.get(url).header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0");
|
||||
let start = Instant::now();
|
||||
|
||||
let response = request.send().await?;
|
||||
if response.status().is_success() {
|
||||
let delay = start.elapsed().as_millis() as u32;
|
||||
Ok(delay)
|
||||
} else {
|
||||
Ok(10000u32)
|
||||
let response = request.send().await;
|
||||
match response {
|
||||
Ok(response) => {
|
||||
log::trace!(target: "app", "test_delay response: {:#?}", response);
|
||||
if response.status().is_success() {
|
||||
Ok(start.elapsed().as_millis() as u32)
|
||||
} else {
|
||||
Ok(10000u32)
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::trace!(target: "app", "test_delay error: {:#?}", err);
|
||||
Err(err.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ pub fn delete_log() -> Result<()> {
|
||||
}
|
||||
|
||||
let service_log_dir = log_dir.join("service");
|
||||
for file in fs::read_dir(&service_log_dir)?.flatten() {
|
||||
for file in fs::read_dir(service_log_dir)?.flatten() {
|
||||
let _ = process_file(file);
|
||||
}
|
||||
|
||||
@@ -318,11 +318,11 @@ pub fn startup_script() -> Result<()> {
|
||||
Some(dir) => {
|
||||
let _ = Command::new(shell)
|
||||
.current_dir(dir.to_path_buf())
|
||||
.args(&[path])
|
||||
.args([path])
|
||||
.output()?;
|
||||
}
|
||||
None => {
|
||||
let _ = Command::new(shell).args(&[path]).output()?;
|
||||
let _ = Command::new(shell).args([path]).output()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,9 +99,12 @@ pub fn resolve_setup(app: &mut App) {
|
||||
|
||||
let argvs: Vec<String> = std::env::args().collect();
|
||||
if argvs.len() > 1 {
|
||||
tauri::async_runtime::block_on(async {
|
||||
resolve_scheme(argvs[1].to_owned()).await;
|
||||
});
|
||||
let param = argvs[1].as_str();
|
||||
if param.starts_with("clash:") {
|
||||
tauri::async_runtime::block_on(async {
|
||||
resolve_scheme(argvs[1].to_owned()).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +208,6 @@ pub fn create_window(app_handle: &AppHandle) {
|
||||
}
|
||||
Err(_) => {
|
||||
log::error!("failed to create window");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,12 +28,14 @@ pub fn check_singleton() -> Result<()> {
|
||||
let argvs: Vec<String> = std::env::args().collect();
|
||||
if argvs.len() > 1 {
|
||||
let param = argvs[1].as_str();
|
||||
reqwest::get(format!(
|
||||
"http://127.0.0.1:{port}/commands/scheme?param={param}"
|
||||
))
|
||||
.await?
|
||||
.text()
|
||||
.await?;
|
||||
if param.starts_with("clash:") {
|
||||
reqwest::get(format!(
|
||||
"http://127.0.0.1:{port}/commands/scheme?param={param}"
|
||||
))
|
||||
.await?
|
||||
.text()
|
||||
.await?;
|
||||
}
|
||||
} else {
|
||||
reqwest::get(format!("http://127.0.0.1:{port}/commands/visible"))
|
||||
.await?
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||
"package": {
|
||||
"productName": "Clash Verge",
|
||||
"version": "1.6.3"
|
||||
"version": "1.6.6"
|
||||
},
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
@@ -38,10 +38,6 @@
|
||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEQyOEMyRjBCQkVGOUJEREYKUldUZnZmbStDeStNMHU5Mmo1N24xQXZwSVRYbXA2NUpzZE5oVzlqeS9Bc0t6RVV4MmtwVjBZaHgK"
|
||||
},
|
||||
"allowlist": {
|
||||
"http": {
|
||||
"all": true,
|
||||
"scope": ["http://**", "http://**"]
|
||||
},
|
||||
"shell": {
|
||||
"all": true
|
||||
},
|
||||
@@ -79,7 +75,7 @@
|
||||
},
|
||||
"windows": [],
|
||||
"security": {
|
||||
"csp": "script-src 'unsafe-eval' 'self'; default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; img-src asset: http: https: data: 'self';"
|
||||
"csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: asset: 'unsafe-eval' 'unsafe-inline' 'self';"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,20 @@
|
||||
},
|
||||
"bundle": {
|
||||
"identifier": "io.github.clash-verge-rev.clash-verge-rev",
|
||||
"targets": ["deb", "appimage", "updater"],
|
||||
"targets": ["deb", "rpm"],
|
||||
"deb": {
|
||||
"depends": ["openssl"],
|
||||
"desktopTemplate": "./template/clash-verge.desktop"
|
||||
"desktopTemplate": "./template/clash-verge.desktop",
|
||||
"provides": ["clash-verge", "clash-meta"],
|
||||
"conflicts": ["clash-verge", "clash-meta"],
|
||||
"replaces": ["clash-verge", "clash-meta"]
|
||||
},
|
||||
"rpm": {
|
||||
"depends": ["openssl"],
|
||||
"desktopTemplate": "./template/clash-verge.desktop",
|
||||
"provides": ["clash-verge", "clash-meta"],
|
||||
"conflicts": ["clash-verge", "clash-meta"],
|
||||
"obsoletes": ["clash-verge", "clash-meta"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,10 +323,15 @@ Var AppStartMenuFolder
|
||||
!define MUI_FINISHPAGE_SHOWREADME_TEXT "$(createDesktop)"
|
||||
!define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateDesktopShortcut
|
||||
; Show run app after installation.
|
||||
!define MUI_FINISHPAGE_RUN "$INSTDIR\${MAINBINARYNAME}.exe"
|
||||
!define MUI_FINISHPAGE_RUN
|
||||
!define MUI_FINISHPAGE_RUN_FUNCTION RunMainBinary
|
||||
!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
Function RunMainBinary
|
||||
nsis_tauri_utils::RunAsUser "$INSTDIR\${MAINBINARYNAME}.exe" ""
|
||||
FunctionEnd
|
||||
|
||||
; Uninstaller Pages
|
||||
; 1. Confirm uninstall page
|
||||
Var DeleteAppDataCheckbox
|
||||
@@ -729,7 +734,7 @@ Function .onInstSuccess
|
||||
${GetOptions} $CMDLINE "/R" $R0
|
||||
IfErrors run_done 0
|
||||
${GetOptions} $CMDLINE "/ARGS" $R0
|
||||
Exec '"$INSTDIR\${MAINBINARYNAME}.exe" $R0'
|
||||
nsis_tauri_utils::RunAsUser "$INSTDIR\${MAINBINARYNAME}.exe" "$R0"
|
||||
run_done:
|
||||
FunctionEnd
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="48" height="48"><path d="M16.125 1c-1.153.067-2.477.71-3.264 1.527-.71.744-1.272 1.85-1.043 2.918 1.253.033 2.511-.626 3.264-1.459.703-.779 1.236-1.866 1.043-2.986zm.068 4.443c-1.809 0-2.565 1.112-3.818 1.112-1.289 0-2.467-1.041-4.027-1.041C6.226 5.514 3 7.48 3 12.11 3 16.324 6.818 21 8.973 21c1.309.013 1.626-.823 3.402-.832 1.778-.013 2.162.843 3.473.832 1.476-.011 2.628-1.633 3.47-2.918.604-.92.853-1.39 1.32-2.43-3.472-.88-4.163-6.48 0-7.638-.785-1.341-3.08-2.57-4.445-2.57z"/></svg>
|
||||
|
After Width: | Height: | Size: 556 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" width="48" height="48"><path d="M15 3C8.373 3 3 8.373 3 15c0 5.623 3.872 10.328 9.092 11.63a1.751 1.751 0 0 1-.092-.583v-2.051h-1.508c-.821 0-1.551-.353-1.905-1.009-.393-.729-.461-1.844-1.435-2.526-.289-.227-.069-.486.264-.451.615.174 1.125.596 1.605 1.222.478.627.703.769 1.596.769.433 0 1.081-.025 1.691-.121.328-.833.895-1.6 1.588-1.962-3.996-.411-5.903-2.399-5.903-5.098 0-1.162.495-2.286 1.336-3.233-.276-.94-.623-2.857.106-3.587 1.798 0 2.885 1.166 3.146 1.481A8.993 8.993 0 0 1 15.495 9c1.036 0 2.024.174 2.922.483C18.675 9.17 19.763 8 21.565 8c.732.731.381 2.656.102 3.594.836.945 1.328 2.066 1.328 3.226 0 2.697-1.904 4.684-5.894 5.097C18.199 20.49 19 22.1 19 23.313v2.734c0 .104-.023.179-.035.268C23.641 24.676 27 20.236 27 15c0-6.627-5.373-12-12-12z"/></svg>
|
||||
|
After Width: | Height: | Size: 829 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48"><path fill="#FFC107" d="M43.611 20.083H42V20H24v8h11.303c-1.649 4.657-6.08 8-11.303 8-6.627 0-12-5.373-12-12s5.373-12 12-12c3.059 0 5.842 1.154 7.961 3.039l5.657-5.657C34.046 6.053 29.268 4 24 4 12.955 4 4 12.955 4 24s8.955 20 20 20 20-8.955 20-20c0-1.341-.138-2.65-.389-3.917z"/><path fill="#FF3D00" d="M6.306 14.691l6.571 4.819C14.655 15.108 18.961 12 24 12c3.059 0 5.842 1.154 7.961 3.039l5.657-5.657C34.046 6.053 29.268 4 24 4 16.318 4 9.656 8.337 6.306 14.691z"/><path fill="#4CAF50" d="M24 44c5.166 0 9.86-1.977 13.409-5.192l-6.19-5.238A11.91 11.91 0 0 1 24 36c-5.202 0-9.619-3.317-11.283-7.946l-6.522 5.025C9.505 39.556 16.227 44 24 44z"/><path fill="#1976D2" d="M43.611 20.083H42V20H24v8h11.303a12.04 12.04 0 0 1-4.087 5.571l.003-.002 6.19 5.238C36.971 39.205 44 34 44 24c0-1.341-.138-2.65-.389-3.917z"/></svg>
|
||||
|
After Width: | Height: | Size: 901 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48"><path fill="#FF3D00" d="M43.2 33.9c-.4 2.1-2.1 3.7-4.2 4-3.3.5-8.8 1.1-15 1.1-6.1 0-11.6-.6-15-1.1-2.1-.3-3.8-1.9-4.2-4-.4-2.3-.8-5.7-.8-9.9s.4-7.6.8-9.9c.4-2.1 2.1-3.7 4.2-4C12.3 9.6 17.8 9 24 9c6.2 0 11.6.6 15 1.1 2.1.3 3.8 1.9 4.2 4 .4 2.3.9 5.7.9 9.9-.1 4.2-.5 7.6-.9 9.9z"/><path fill="#FFF" d="M20 31V17l12 7z"/></svg>
|
||||
|
After Width: | Height: | Size: 407 B |
@@ -0,0 +1,38 @@
|
||||
import React from "react";
|
||||
import { Box, styled } from "@mui/material";
|
||||
|
||||
type Props = {
|
||||
label: string;
|
||||
fontSize?: string;
|
||||
width?: string;
|
||||
padding?: string;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
export const BaseFieldset: React.FC<Props> = (props: Props) => {
|
||||
const Fieldset = styled(Box)(() => ({
|
||||
position: "relative",
|
||||
border: "1px solid #bbb",
|
||||
borderRadius: "5px",
|
||||
width: props.width ?? "auto",
|
||||
padding: props.padding ?? "15px",
|
||||
}));
|
||||
|
||||
const Label = styled("legend")(({ theme }) => ({
|
||||
position: "absolute",
|
||||
top: "-10px",
|
||||
left: props.padding ?? "15px",
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
backgroundImage:
|
||||
"linear-gradient(rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.16))",
|
||||
color: theme.palette.text.primary,
|
||||
fontSize: props.fontSize ?? "1em",
|
||||
}));
|
||||
|
||||
return (
|
||||
<Fieldset component="fieldset">
|
||||
<Label>{props.label}</Label>
|
||||
{props.children}
|
||||
</Fieldset>
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Box, SvgIcon, TextField, Theme, styled } from "@mui/material";
|
||||
import { Box, SvgIcon, TextField, styled } from "@mui/material";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import { ChangeEvent, useState } from "react";
|
||||
import { ChangeEvent, useEffect, useRef, useState } from "react";
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import matchCaseIcon from "@/assets/image/component/match_case.svg?react";
|
||||
@@ -22,6 +22,7 @@ type SearchProps = {
|
||||
|
||||
export const BaseSearchBox = styled((props: SearchProps) => {
|
||||
const { t } = useTranslation();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [matchCase, setMatchCase] = useState(true);
|
||||
const [matchWholeWord, setMatchWholeWord] = useState(false);
|
||||
const [useRegularExpression, setUseRegularExpression] = useState(false);
|
||||
@@ -36,6 +37,14 @@ export const BaseSearchBox = styled((props: SearchProps) => {
|
||||
inheritViewBox: true,
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!inputRef.current) return;
|
||||
|
||||
onChange({
|
||||
target: inputRef.current,
|
||||
} as ChangeEvent<HTMLInputElement>);
|
||||
}, [matchCase, matchWholeWord, useRegularExpression]);
|
||||
|
||||
const onChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
props.onSearch(
|
||||
(content) => doSearch([content], e.target?.value ?? "").length > 0,
|
||||
@@ -80,6 +89,7 @@ export const BaseSearchBox = styled((props: SearchProps) => {
|
||||
return (
|
||||
<Tooltip title={errorMessage} placement="bottom-start">
|
||||
<TextField
|
||||
inputRef={inputRef}
|
||||
hiddenLabel
|
||||
fullWidth
|
||||
size="small"
|
||||
|
||||
@@ -19,6 +19,7 @@ const Tag = styled("span")(({ theme }) => ({
|
||||
border: "1px solid",
|
||||
borderRadius: 4,
|
||||
borderColor: alpha(theme.palette.text.secondary, 0.35),
|
||||
marginTop: "4px",
|
||||
marginRight: "4px",
|
||||
}));
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ export const LayoutControl = () => {
|
||||
<ButtonGroup
|
||||
variant="text"
|
||||
sx={{
|
||||
zIndex: 1000,
|
||||
height: "100%",
|
||||
".MuiButtonGroup-grouped": {
|
||||
borderRadius: "0px",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { alpha, createTheme, Shadows, Theme } from "@mui/material";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import { atomThemeMode } from "@/services/states";
|
||||
import { useSetThemeMode, useThemeMode } from "@/services/states";
|
||||
import { defaultTheme, defaultDarkTheme } from "@/pages/_theme";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
|
||||
@@ -12,7 +11,8 @@ import { useVerge } from "@/hooks/use-verge";
|
||||
export const useCustomTheme = () => {
|
||||
const { verge } = useVerge();
|
||||
const { theme_mode, theme_setting } = verge ?? {};
|
||||
const [mode, setMode] = useRecoilState(atomThemeMode);
|
||||
const mode = useThemeMode();
|
||||
const setMode = useSetThemeMode();
|
||||
|
||||
useEffect(() => {
|
||||
const themeMode = ["light", "dark", "system"].includes(theme_mode!)
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import dayjs from "dayjs";
|
||||
import { useEffect } from "react";
|
||||
import { useRecoilValue, useSetRecoilState } from "recoil";
|
||||
import { getClashLogs } from "@/services/cmds";
|
||||
import { useClashInfo } from "@/hooks/use-clash";
|
||||
import { atomEnableLog, atomLogData } from "@/services/states";
|
||||
import { useEnableLog, useSetLogData } from "@/services/states";
|
||||
import { useWebsocket } from "@/hooks/use-websocket";
|
||||
|
||||
const MAX_LOG_NUM = 1000;
|
||||
@@ -12,8 +11,8 @@ const MAX_LOG_NUM = 1000;
|
||||
export const useLogSetup = () => {
|
||||
const { clashInfo } = useClashInfo();
|
||||
|
||||
const enableLog = useRecoilValue(atomEnableLog);
|
||||
const setLogData = useSetRecoilState(atomLogData);
|
||||
const [enableLog] = useEnableLog();
|
||||
const setLogData = useSetLogData();
|
||||
|
||||
const { connect, disconnect } = useWebsocket((event) => {
|
||||
const data = JSON.parse(event.data) as ILogItem;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ReactNode, useEffect, useRef } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useRecoilValue } from "recoil";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
Button,
|
||||
@@ -9,7 +8,7 @@ import {
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
} from "@mui/material";
|
||||
import { atomThemeMode } from "@/services/states";
|
||||
import { useThemeMode } from "@/services/states";
|
||||
import { readProfileFile, saveProfileFile } from "@/services/cmds";
|
||||
import { Notice } from "@/components/base";
|
||||
import { nanoid } from "nanoid";
|
||||
@@ -90,7 +89,7 @@ export const EditorViewer = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const editorRef = useRef<any>();
|
||||
const instanceRef = useRef<editor.IStandaloneCodeEditor | null>(null);
|
||||
const themeMode = useRecoilValue(atomThemeMode);
|
||||
const themeMode = useThemeMode();
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
@@ -131,7 +130,7 @@ export const EditorViewer = (props: Props) => {
|
||||
padding: {
|
||||
top: 33, // 顶部padding防止遮挡snippets
|
||||
},
|
||||
fontFamily: `Fira Code, Roboto Mono, Roboto, Source Code Pro, Menlo, Monaco, Consolas, Courier New, monospace, "Apple Color Emoji"${
|
||||
fontFamily: `Fira Code, JetBrains Mono, Roboto Mono, "Source Code Pro", Consolas, Menlo, Monaco, monospace, "Courier New", "Apple Color Emoji"${
|
||||
getSystem() === "windows" ? ", twemoji mozilla" : ""
|
||||
}`,
|
||||
fontLigatures: true, // 连字符
|
||||
|
||||
@@ -2,7 +2,6 @@ import dayjs from "dayjs";
|
||||
import { mutate } from "swr";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
@@ -17,7 +16,7 @@ import {
|
||||
CircularProgress,
|
||||
} from "@mui/material";
|
||||
import { RefreshRounded, DragIndicator } from "@mui/icons-material";
|
||||
import { atomLoadingCache } from "@/services/states";
|
||||
import { useLoadingCache, useSetLoadingCache } from "@/services/states";
|
||||
import { updateProfile, deleteProfile, viewProfile } from "@/services/cmds";
|
||||
import { Notice } from "@/components/base";
|
||||
import { EditorViewer } from "@/components/profile/editor-viewer";
|
||||
@@ -47,7 +46,8 @@ export const ProfileItem = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const [anchorEl, setAnchorEl] = useState<any>(null);
|
||||
const [position, setPosition] = useState({ left: 0, top: 0 });
|
||||
const [loadingCache, setLoadingCache] = useRecoilState(atomLoadingCache);
|
||||
const loadingCache = useLoadingCache();
|
||||
const setLoadingCache = useSetLoadingCache();
|
||||
|
||||
const { uid, name = "Profile", extra, updated = 0 } = itemData;
|
||||
|
||||
@@ -278,6 +278,7 @@ export const ProfileItem = (props: Props) => {
|
||||
{/* only if has url can it be updated */}
|
||||
{hasUrl && (
|
||||
<IconButton
|
||||
title={t("Refresh")}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
p: "3px",
|
||||
|
||||
@@ -69,7 +69,7 @@ export const ProviderButton = () => {
|
||||
sx={{ textTransform: "capitalize" }}
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
{t("Provider")}
|
||||
{t("Proxy Provider")}
|
||||
</Button>
|
||||
|
||||
<BaseDialog
|
||||
@@ -171,7 +171,7 @@ export const ProviderButton = () => {
|
||||
<IconButton
|
||||
size="small"
|
||||
color="inherit"
|
||||
title="Update Provider"
|
||||
title={`${t("Update")}${t("Proxy Provider")}`}
|
||||
onClick={() => handleUpdate(key, index)}
|
||||
sx={{
|
||||
animation: updating[index]
|
||||
|
||||
@@ -17,8 +17,7 @@ import { ProxyItem } from "./proxy-item";
|
||||
import { ProxyItemMini } from "./proxy-item-mini";
|
||||
import type { IRenderItem } from "./use-render-list";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { atomThemeMode } from "@/services/states";
|
||||
import { useThemeMode } from "@/services/states";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { convertFileSrc } from "@tauri-apps/api/tauri";
|
||||
import { downloadIconCache } from "@/services/cmds";
|
||||
@@ -38,7 +37,7 @@ export const ProxyRender = (props: RenderProps) => {
|
||||
const { type, group, headState, proxy, proxyCol } = item;
|
||||
const { verge } = useVerge();
|
||||
const enable_group_icon = verge?.enable_group_icon ?? true;
|
||||
const [mode] = useRecoilState(atomThemeMode);
|
||||
const mode = useThemeMode();
|
||||
const isDark = mode === "light" ? false : true;
|
||||
const itembackgroundcolor = isDark ? "#282A36" : "#ffffff";
|
||||
const [iconCachePath, setIconCachePath] = useState("");
|
||||
|
||||
@@ -67,7 +67,7 @@ export const ProviderButton = () => {
|
||||
sx={{ textTransform: "capitalize" }}
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
{t("Provider")}
|
||||
{t("Rule Provider")}
|
||||
</Button>
|
||||
|
||||
<BaseDialog
|
||||
@@ -145,7 +145,7 @@ export const ProviderButton = () => {
|
||||
<IconButton
|
||||
size="small"
|
||||
color="inherit"
|
||||
title="Update Provider"
|
||||
title={`${t("Update")}${t("Rule Provider")}`}
|
||||
onClick={() => handleUpdate(key, index)}
|
||||
sx={{
|
||||
animation: updating[index]
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { List, Button, Select, MenuItem } from "@mui/material";
|
||||
import {
|
||||
List,
|
||||
Button,
|
||||
Select,
|
||||
MenuItem,
|
||||
styled,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
} from "@mui/material";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
||||
import { SettingItem } from "./setting-comp";
|
||||
import { GuardState } from "./guard-state";
|
||||
import { open as openDialog } from "@tauri-apps/api/dialog";
|
||||
import { convertFileSrc } from "@tauri-apps/api/tauri";
|
||||
@@ -77,7 +84,8 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
onCancel={() => setOpen(false)}
|
||||
>
|
||||
<List>
|
||||
<SettingItem label={t("Traffic Graph")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Traffic Graph")} />
|
||||
<GuardState
|
||||
value={verge?.traffic_graph ?? true}
|
||||
valueProps="checked"
|
||||
@@ -88,9 +96,10 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
>
|
||||
<Switch edge="end" />
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
<SettingItem label={t("Memory Usage")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Memory Usage")} />
|
||||
<GuardState
|
||||
value={verge?.enable_memory_usage ?? true}
|
||||
valueProps="checked"
|
||||
@@ -101,9 +110,10 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
>
|
||||
<Switch edge="end" />
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
<SettingItem label={t("Proxy Group Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Proxy Group Icon")} />
|
||||
<GuardState
|
||||
value={verge?.enable_group_icon ?? true}
|
||||
valueProps="checked"
|
||||
@@ -114,9 +124,10 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
>
|
||||
<Switch edge="end" />
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
<SettingItem label={t("Menu Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Menu Icon")} />
|
||||
<GuardState
|
||||
value={verge?.menu_icon ?? "monochrome"}
|
||||
onCatch={onError}
|
||||
@@ -130,9 +141,11 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
<MenuItem value="disable">{t("Disable")}</MenuItem>
|
||||
</Select>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
{OS === "macos" && (
|
||||
<SettingItem label={t("Tray Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Tray Icon")} />
|
||||
<GuardState
|
||||
value={verge?.tray_icon ?? "monochrome"}
|
||||
onCatch={onError}
|
||||
@@ -148,10 +161,11 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
<MenuItem value="colorful">{t("Colorful")}</MenuItem>
|
||||
</Select>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
)}
|
||||
|
||||
<SettingItem label={t("Common Tray Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Common Tray Icon")} />
|
||||
<GuardState
|
||||
value={verge?.common_tray_icon}
|
||||
onCatch={onError}
|
||||
@@ -194,9 +208,10 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
{verge?.common_tray_icon ? t("Clear") : t("Browse")}
|
||||
</Button>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
<SettingItem label={t("System Proxy Tray Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("System Proxy Tray Icon")} />
|
||||
<GuardState
|
||||
value={verge?.sysproxy_tray_icon}
|
||||
onCatch={onError}
|
||||
@@ -239,9 +254,10 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
{verge?.sysproxy_tray_icon ? t("Clear") : t("Browse")}
|
||||
</Button>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
<SettingItem label={t("Tun Tray Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Tun Tray Icon")} />
|
||||
<GuardState
|
||||
value={verge?.tun_tray_icon}
|
||||
onCatch={onError}
|
||||
@@ -282,8 +298,12 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
{verge?.tun_tray_icon ? t("Clear") : t("Browse")}
|
||||
</Button>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
</List>
|
||||
</BaseDialog>
|
||||
);
|
||||
});
|
||||
|
||||
const Item = styled(ListItem)(() => ({
|
||||
padding: "5px 2px",
|
||||
}));
|
||||
|
||||
@@ -1,34 +1,59 @@
|
||||
import React, { ReactNode } from "react";
|
||||
import React, { ReactNode, useState } from "react";
|
||||
import {
|
||||
Box,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemText,
|
||||
ListSubheader,
|
||||
} from "@mui/material";
|
||||
import { ChevronRightRounded } from "@mui/icons-material";
|
||||
import CircularProgress from "@mui/material/CircularProgress";
|
||||
import isAsyncFunction from "@/utils/is-async-function";
|
||||
|
||||
interface ItemProps {
|
||||
label: ReactNode;
|
||||
extra?: ReactNode;
|
||||
children?: ReactNode;
|
||||
secondary?: ReactNode;
|
||||
onClick?: () => void | Promise<any>;
|
||||
}
|
||||
|
||||
export const SettingItem: React.FC<ItemProps> = (props) => {
|
||||
const { label, extra, children, secondary } = props;
|
||||
const { label, extra, children, secondary, onClick } = props;
|
||||
const clickable = !!onClick;
|
||||
|
||||
const primary = !extra ? (
|
||||
const primary = (
|
||||
<Box sx={{ display: "flex", alignItems: "center", fontSize: "14px" }}>
|
||||
<span>{label}</span>
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{ display: "flex", alignItems: "center", fontSize: "14px" }}>
|
||||
<span>{label}</span>
|
||||
{extra}
|
||||
{extra ? extra : null}
|
||||
</Box>
|
||||
);
|
||||
|
||||
return (
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const handleClick = () => {
|
||||
if (onClick) {
|
||||
if (isAsyncFunction(onClick)) {
|
||||
setIsLoading(true);
|
||||
onClick()!.finally(() => setIsLoading(false));
|
||||
} else {
|
||||
onClick();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return clickable ? (
|
||||
<ListItem disablePadding>
|
||||
<ListItemButton onClick={handleClick} disabled={isLoading}>
|
||||
<ListItemText primary={primary} secondary={secondary} />
|
||||
{isLoading ? (
|
||||
<CircularProgress color="inherit" size={20} />
|
||||
) : (
|
||||
<ChevronRightRounded />
|
||||
)}
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
) : (
|
||||
<ListItem sx={{ pt: "5px", pb: "5px" }}>
|
||||
<ListItemText primary={primary} secondary={secondary} />
|
||||
{children}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { forwardRef, useImperativeHandle, useState } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Box, IconButton, Tooltip } from "@mui/material";
|
||||
import { InfoRounded } from "@mui/icons-material";
|
||||
import {
|
||||
Box,
|
||||
InputAdornment,
|
||||
List,
|
||||
ListItem,
|
||||
@@ -17,12 +18,22 @@ import { getSystemProxy, getAutotemProxy } from "@/services/cmds";
|
||||
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
||||
import { Edit } from "@mui/icons-material";
|
||||
import { EditorViewer } from "@/components/profile/editor-viewer";
|
||||
import { BaseFieldset } from "@/components/base/base-fieldset";
|
||||
import getSystem from "@/utils/get-system";
|
||||
const DEFAULT_PAC = `function FindProxyForURL(url, host) {
|
||||
return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;";
|
||||
}`;
|
||||
|
||||
export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
const { t } = useTranslation();
|
||||
let validReg;
|
||||
if (getSystem() === "windows") {
|
||||
validReg =
|
||||
/^(\*?\w+(\.\w+)*|\d{1,3}(\.\d{1,3}){0,2}\.\*|\d{1,3}(\.\d{1,3}){3})(;(\*?\w+(\.\w+)*|\d{1,3}(\.\d{1,3}){0,2}\.\*|\d{1,3}(\.\d{1,3}){3}))*$/;
|
||||
} else {
|
||||
validReg =
|
||||
/^((\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}|(\d{1,3}\.){3}\d{1,3}(\/\d{1,2})?|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+(\/\d{1,3})?)(,((\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}|(\d{1,3}\.){3}\d{1,3}(\/\d{1,2})?|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+(\/\d{1,3})?))*$/;
|
||||
}
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [editorOpen, setEditorOpen] = useState(false);
|
||||
@@ -90,7 +101,10 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
if (value.pac_content !== pac_file_content) {
|
||||
patch.pac_file_content = value.pac_content;
|
||||
}
|
||||
|
||||
if (value.bypass && !validReg.test(value.bypass)) {
|
||||
Notice.error(t("Invalid Bypass Format"));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await patchVerge(patch);
|
||||
setOpen(false);
|
||||
@@ -103,7 +117,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
<BaseDialog
|
||||
open={open}
|
||||
title={t("System Proxy Setting")}
|
||||
contentSx={{ width: 450, maxHeight: 300 }}
|
||||
contentSx={{ width: 450, maxHeight: 565 }}
|
||||
okBtn={t("Save")}
|
||||
cancelBtn={t("Cancel")}
|
||||
onClose={() => setOpen(false)}
|
||||
@@ -111,6 +125,36 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
onOk={onSave}
|
||||
>
|
||||
<List>
|
||||
<BaseFieldset label={t("Current System Proxy")} padding="15px 10px">
|
||||
<FlexBox>
|
||||
<Typography className="label">{t("Enable status")}</Typography>
|
||||
<Typography className="value">
|
||||
{value.pac
|
||||
? autoproxy?.enable
|
||||
? t("Enabled")
|
||||
: t("Disabled")
|
||||
: sysproxy?.enable
|
||||
? t("Enabled")
|
||||
: t("Disabled")}
|
||||
</Typography>
|
||||
</FlexBox>
|
||||
{!value.pac && (
|
||||
<>
|
||||
<FlexBox>
|
||||
<Typography className="label">{t("Server Addr")}</Typography>
|
||||
<Typography className="value">
|
||||
{sysproxy?.server ? sysproxy.server : t("Not available")}
|
||||
</Typography>
|
||||
</FlexBox>
|
||||
</>
|
||||
)}
|
||||
{value.pac && (
|
||||
<FlexBox>
|
||||
<Typography className="label">{t("PAC URL")}</Typography>
|
||||
<Typography className="value">{autoproxy?.url || "-"}</Typography>
|
||||
</FlexBox>
|
||||
)}
|
||||
</BaseFieldset>
|
||||
<ListItem sx={{ padding: "5px 2px" }}>
|
||||
<ListItemText primary={t("Use PAC Mode")} />
|
||||
<Switch
|
||||
@@ -120,8 +164,17 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
onChange={(_, e) => setValue((v) => ({ ...v, pac: e }))}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem sx={{ padding: "5px 2px" }}>
|
||||
<ListItemText primary={t("Proxy Guard")} />
|
||||
<Tooltip title={t("Proxy Guard Info")}>
|
||||
<IconButton color="inherit" size="small">
|
||||
<InfoRounded
|
||||
fontSize="inherit"
|
||||
style={{ cursor: "pointer", opacity: 0.75 }}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Switch
|
||||
edge="end"
|
||||
disabled={!enabled}
|
||||
@@ -150,27 +203,32 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
</ListItem>
|
||||
{!value.pac && (
|
||||
<>
|
||||
<ListItem sx={{ padding: "5px 2px", alignItems: "start" }}>
|
||||
<ListItemText
|
||||
primary={t("Proxy Bypass")}
|
||||
sx={{ padding: "3px 0" }}
|
||||
/>
|
||||
</ListItem>
|
||||
<ListItem sx={{ padding: "5px 2px" }}>
|
||||
<ListItemText primary={t("Proxy Bypass")} />
|
||||
<TextField
|
||||
error={value.bypass ? !validReg.test(value.bypass) : false}
|
||||
disabled={!enabled}
|
||||
size="small"
|
||||
autoComplete="off"
|
||||
multiline
|
||||
rows={4}
|
||||
sx={{ width: "100%" }}
|
||||
value={value.bypass}
|
||||
onChange={(e) => {
|
||||
setValue((v) => ({ ...v, bypass: e.target.value }));
|
||||
}}
|
||||
/>
|
||||
<ListItemText primary={t("Bypass")} />
|
||||
<FlexBox>
|
||||
<TextField
|
||||
disabled={!enabled}
|
||||
disabled={true}
|
||||
size="small"
|
||||
autoComplete="off"
|
||||
multiline
|
||||
rows={4}
|
||||
sx={{ width: "100%" }}
|
||||
value={value.bypass}
|
||||
placeholder={sysproxy?.bypass || `-`}
|
||||
onChange={(e) =>
|
||||
setValue((v) => ({ ...v, bypass: e.target.value }))
|
||||
}
|
||||
value={sysproxy?.bypass || "-"}
|
||||
/>
|
||||
</ListItem>
|
||||
</FlexBox>
|
||||
</>
|
||||
)}
|
||||
{value.pac && (
|
||||
@@ -210,52 +268,6 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
</>
|
||||
)}
|
||||
</List>
|
||||
|
||||
<Box sx={{ mt: 2.5 }}>
|
||||
<Typography variant="body1" sx={{ fontSize: "18px", mb: 1 }}>
|
||||
{t("Current System Proxy")}
|
||||
</Typography>
|
||||
|
||||
<FlexBox>
|
||||
<Typography className="label">{t("Enable status")}</Typography>
|
||||
<Typography className="value">
|
||||
{value.pac
|
||||
? (!!autoproxy?.enable).toString()
|
||||
: (!!sysproxy?.enable).toString()}
|
||||
</Typography>
|
||||
</FlexBox>
|
||||
{!value.pac && (
|
||||
<>
|
||||
<FlexBox>
|
||||
<Typography className="label">{t("Server Addr")}</Typography>
|
||||
<Typography className="value">
|
||||
{sysproxy?.server || "-"}
|
||||
</Typography>
|
||||
</FlexBox>
|
||||
|
||||
<FlexBox>
|
||||
<Typography className="label">{t("Bypass")}</Typography>
|
||||
</FlexBox>
|
||||
<FlexBox>
|
||||
<TextField
|
||||
disabled={true}
|
||||
size="small"
|
||||
autoComplete="off"
|
||||
multiline
|
||||
rows={4}
|
||||
sx={{ width: "100%" }}
|
||||
value={sysproxy?.bypass || "-"}
|
||||
/>
|
||||
</FlexBox>
|
||||
</>
|
||||
)}
|
||||
{value.pac && (
|
||||
<FlexBox>
|
||||
<Typography className="label">{t("PAC URL")}</Typography>
|
||||
<Typography className="value">{autoproxy?.url || "-"}</Typography>
|
||||
</FlexBox>
|
||||
)}
|
||||
</Box>
|
||||
</BaseDialog>
|
||||
);
|
||||
});
|
||||
@@ -266,6 +278,6 @@ const FlexBox = styled("div")`
|
||||
|
||||
.label {
|
||||
flex: none;
|
||||
width: 85px;
|
||||
//width: 85px;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -81,7 +81,7 @@ export const ThemeViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
title={t("Theme Setting")}
|
||||
okBtn={t("Save")}
|
||||
cancelBtn={t("Cancel")}
|
||||
contentSx={{ width: 400, maxHeight: 300, overflow: "auto", pb: 0 }}
|
||||
contentSx={{ width: 400, maxHeight: 505, overflow: "auto", pb: 0 }}
|
||||
onClose={() => setOpen(false)}
|
||||
onCancel={() => setOpen(false)}
|
||||
onOk={onSave}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import useSWR from "swr";
|
||||
import { forwardRef, useImperativeHandle, useState, useMemo } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { Box, LinearProgress } from "@mui/material";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { Box, LinearProgress, Button } from "@mui/material";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { relaunch } from "@tauri-apps/api/process";
|
||||
import { checkUpdate, installUpdate } from "@tauri-apps/api/updater";
|
||||
import { BaseDialog, DialogRef, Notice } from "@/components/base";
|
||||
import { atomUpdateState } from "@/services/states";
|
||||
import { useUpdateState, useSetUpdateState } from "@/services/states";
|
||||
import { listen, Event, UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { portableFlag } from "@/pages/_layout";
|
||||
import { open as openUrl } from "@tauri-apps/api/shell";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
|
||||
let eventListener: UnlistenFn | null = null;
|
||||
@@ -18,7 +18,9 @@ export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const [updateState, setUpdateState] = useRecoilState(atomUpdateState);
|
||||
|
||||
const updateState = useUpdateState();
|
||||
const setUpdateState = useSetUpdateState();
|
||||
|
||||
const { data: updateInfo } = useSWR("checkUpdate", checkUpdate, {
|
||||
errorRetryCount: 2,
|
||||
@@ -75,7 +77,24 @@ export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
return (
|
||||
<BaseDialog
|
||||
open={open}
|
||||
title={`New Version v${updateInfo?.manifest?.version}`}
|
||||
title={
|
||||
<Box display="flex" justifyContent="space-between">
|
||||
{`New Version v${updateInfo?.manifest?.version}`}
|
||||
<Box>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
openUrl(
|
||||
`https://github.com/clash-verge-rev/clash-verge-rev/releases/tag/v${updateInfo?.manifest?.version}`
|
||||
);
|
||||
}}
|
||||
>
|
||||
{t("Go to Release Page")}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
}
|
||||
contentSx={{ minWidth: 360, maxWidth: 400, height: "50vh" }}
|
||||
okBtn={t("Update")}
|
||||
cancelBtn={t("Cancel")}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
EditRounded,
|
||||
OpenInNewRounded,
|
||||
} from "@mui/icons-material";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface Props {
|
||||
value?: string;
|
||||
@@ -35,6 +36,7 @@ export const WebUIItem = (props: Props) => {
|
||||
|
||||
const [editing, setEditing] = useState(false);
|
||||
const [editValue, setEditValue] = useState(value);
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (editing || onlyEdit) {
|
||||
return (
|
||||
@@ -45,12 +47,12 @@ export const WebUIItem = (props: Props) => {
|
||||
size="small"
|
||||
value={editValue}
|
||||
onChange={(e) => setEditValue(e.target.value)}
|
||||
placeholder={`Support %host %port %secret`}
|
||||
placeholder={t("Support %host, %port, %secret")}
|
||||
autoComplete="off"
|
||||
/>
|
||||
<IconButton
|
||||
size="small"
|
||||
title="Save"
|
||||
title={t("Save")}
|
||||
color="inherit"
|
||||
onClick={() => {
|
||||
onChange(editValue);
|
||||
@@ -61,7 +63,7 @@ export const WebUIItem = (props: Props) => {
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size="small"
|
||||
title="Cancel"
|
||||
title={t("Cancel")}
|
||||
color="inherit"
|
||||
onClick={() => {
|
||||
onCancel?.();
|
||||
@@ -100,7 +102,7 @@ export const WebUIItem = (props: Props) => {
|
||||
/>
|
||||
<IconButton
|
||||
size="small"
|
||||
title="Open URL"
|
||||
title={t("Open URL")}
|
||||
color="inherit"
|
||||
onClick={() => onOpenUrl?.(value)}
|
||||
>
|
||||
@@ -108,7 +110,7 @@ export const WebUIItem = (props: Props) => {
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size="small"
|
||||
title="Edit"
|
||||
title={t("Edit")}
|
||||
color="inherit"
|
||||
onClick={() => {
|
||||
setEditing(true);
|
||||
@@ -119,7 +121,7 @@ export const WebUIItem = (props: Props) => {
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size="small"
|
||||
title="Delete"
|
||||
title={t("Delete")}
|
||||
color="inherit"
|
||||
onClick={onDelete}
|
||||
>
|
||||
|
||||
@@ -105,10 +105,10 @@ export const WebUIViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
>
|
||||
{!editing && webUIList.length === 0 && (
|
||||
<BaseEmpty
|
||||
text="Empty List"
|
||||
text="Empty"
|
||||
extra={
|
||||
<Typography mt={2} sx={{ fontSize: "12px" }}>
|
||||
Replace host, port, secret with "%host" "%port" "%secret"
|
||||
{t("Replace host, port, secret with %host, %port, %secret")}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
IconButton,
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import { ArrowForward, Settings, Shuffle } from "@mui/icons-material";
|
||||
import { Settings, Shuffle } from "@mui/icons-material";
|
||||
import { DialogRef, Notice, Switch } from "@/components/base";
|
||||
import { useClash } from "@/hooks/use-clash";
|
||||
import { GuardState } from "./mods/guard-state";
|
||||
@@ -51,14 +51,14 @@ const SettingClash = ({ onError }: Props) => {
|
||||
const onChangeVerge = (patch: Partial<IVergeConfig>) => {
|
||||
mutateVerge({ ...verge, ...patch }, false);
|
||||
};
|
||||
const onUpdateGeo = useLockFn(async () => {
|
||||
const onUpdateGeo = async () => {
|
||||
try {
|
||||
await updateGeoData();
|
||||
Notice.success(t("GeoData Updated"));
|
||||
} catch (err: any) {
|
||||
Notice.error(err?.response.data.message || err.toString());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingList title={t("Clash Setting")}>
|
||||
@@ -120,7 +120,10 @@ const SettingClash = ({ onError }: Props) => {
|
||||
color={enable_random_port ? "primary" : "inherit"}
|
||||
size="small"
|
||||
onClick={() => {
|
||||
Notice.success(t("Restart Application to Apply Modifications"), 1000);
|
||||
Notice.success(
|
||||
t("Restart Application to Apply Modifications"),
|
||||
1000
|
||||
);
|
||||
onChangeVerge({ enable_random_port: !enable_random_port });
|
||||
patchVerge({ enable_random_port: !enable_random_port });
|
||||
}}
|
||||
@@ -146,27 +149,12 @@ const SettingClash = ({ onError }: Props) => {
|
||||
/>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem label={t("External")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={() => ctrlRef.current?.open()}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem
|
||||
onClick={() => ctrlRef.current?.open()}
|
||||
label={t("External")}
|
||||
/>
|
||||
|
||||
<SettingItem label={t("Web UI")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={() => webRef.current?.open()}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem onClick={() => webRef.current?.open()} label={t("Web UI")} />
|
||||
|
||||
<SettingItem
|
||||
label={t("Clash Core")}
|
||||
@@ -187,28 +175,10 @@ const SettingClash = ({ onError }: Props) => {
|
||||
</SettingItem>
|
||||
|
||||
{isWIN && (
|
||||
<SettingItem label={t("Open UWP tool")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={invoke_uwp_tool}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem onClick={invoke_uwp_tool} label={t("Open UWP tool")} />
|
||||
)}
|
||||
|
||||
<SettingItem label={t("Update GeoData")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={onUpdateGeo}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem onClick={onUpdateGeo} label={t("Update GeoData")} />
|
||||
</SettingList>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -123,16 +123,26 @@ const SettingSystem = ({ onError }: Props) => {
|
||||
<SettingItem
|
||||
label={t("System Proxy")}
|
||||
extra={
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
onClick={() => sysproxyRef.current?.open()}
|
||||
>
|
||||
<Settings
|
||||
fontSize="inherit"
|
||||
style={{ cursor: "pointer", opacity: 0.75 }}
|
||||
/>
|
||||
</IconButton>
|
||||
<>
|
||||
<Tooltip title={t("System Proxy Info")} placement="top">
|
||||
<IconButton color="inherit" size="small">
|
||||
<InfoRounded
|
||||
fontSize="inherit"
|
||||
style={{ cursor: "pointer", opacity: 0.75 }}
|
||||
/>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
onClick={() => sysproxyRef.current?.open()}
|
||||
>
|
||||
<Settings
|
||||
fontSize="inherit"
|
||||
style={{ cursor: "pointer", opacity: 0.75 }}
|
||||
/>
|
||||
</IconButton>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<GuardState
|
||||
|
||||
@@ -2,14 +2,7 @@ import { useRef } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { open } from "@tauri-apps/api/dialog";
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
MenuItem,
|
||||
Select,
|
||||
Input,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { Button, MenuItem, Select, Input, Typography } from "@mui/material";
|
||||
import {
|
||||
exitApp,
|
||||
openAppDir,
|
||||
@@ -17,7 +10,6 @@ import {
|
||||
openLogsDir,
|
||||
openDevTools,
|
||||
} from "@/services/cmds";
|
||||
import { ArrowForward } from "@mui/icons-material";
|
||||
import { checkUpdate } from "@tauri-apps/api/updater";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { version } from "@root/package.json";
|
||||
@@ -63,7 +55,7 @@ const SettingVerge = ({ onError }: Props) => {
|
||||
mutateVerge({ ...verge, ...patch }, false);
|
||||
};
|
||||
|
||||
const onCheckUpdate = useLockFn(async () => {
|
||||
const onCheckUpdate = async () => {
|
||||
try {
|
||||
const info = await checkUpdate();
|
||||
if (!info?.shouldUpdate) {
|
||||
@@ -74,7 +66,7 @@ const SettingVerge = ({ onError }: Props) => {
|
||||
} catch (err: any) {
|
||||
Notice.error(err.message || err.toString());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingList title={t("Verge Setting")}>
|
||||
@@ -213,128 +205,48 @@ const SettingVerge = ({ onError }: Props) => {
|
||||
></Input>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
<SettingItem label={t("Theme Setting")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={() => themeRef.current?.open()}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem label={t("Layout Setting")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={() => layoutRef.current?.open()}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem
|
||||
onClick={() => themeRef.current?.open()}
|
||||
label={t("Theme Setting")}
|
||||
/>
|
||||
|
||||
<SettingItem label={t("Miscellaneous")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={() => miscRef.current?.open()}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem
|
||||
onClick={() => layoutRef.current?.open()}
|
||||
label={t("Layout Setting")}
|
||||
/>
|
||||
|
||||
<SettingItem label={t("Hotkey Setting")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={() => hotkeyRef.current?.open()}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem
|
||||
onClick={() => miscRef.current?.open()}
|
||||
label={t("Miscellaneous")}
|
||||
/>
|
||||
|
||||
<SettingItem label={t("Runtime Config")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={() => configRef.current?.open()}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem
|
||||
onClick={() => hotkeyRef.current?.open()}
|
||||
label={t("Hotkey Setting")}
|
||||
/>
|
||||
|
||||
<SettingItem label={t("Open App Dir")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={openAppDir}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem
|
||||
onClick={() => configRef.current?.open()}
|
||||
label={t("Runtime Config")}
|
||||
/>
|
||||
|
||||
<SettingItem label={t("Open Core Dir")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={openCoreDir}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem onClick={openAppDir} label={t("Open App Dir")} />
|
||||
|
||||
<SettingItem label={t("Open Logs Dir")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={openLogsDir}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem onClick={openCoreDir} label={t("Open Core Dir")} />
|
||||
|
||||
<SettingItem label={t("Check for Updates")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={onCheckUpdate}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem onClick={openLogsDir} label={t("Open Logs Dir")} />
|
||||
|
||||
<SettingItem label={t("Open Dev Tools")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={openDevTools}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem onClick={onCheckUpdate} label={t("Check for Updates")} />
|
||||
|
||||
<SettingItem label={t("Exit")}>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ my: "2px" }}
|
||||
onClick={() => {
|
||||
exitApp();
|
||||
}}
|
||||
>
|
||||
<ArrowForward />
|
||||
</IconButton>
|
||||
</SettingItem>
|
||||
<SettingItem onClick={openDevTools} label={t("Open Dev Tools")} />
|
||||
|
||||
<SettingItem
|
||||
onClick={() => {
|
||||
exitApp();
|
||||
}}
|
||||
label={t("Exit")}
|
||||
/>
|
||||
|
||||
<SettingItem label={t("Verge Version")}>
|
||||
<Typography sx={{ py: "7px", pr: 1 }}>v{version}</Typography>
|
||||
|
||||
@@ -175,7 +175,7 @@ export const TestItem = (props: Props) => {
|
||||
":hover": { bgcolor: alpha(palette.primary.main, 0.15) },
|
||||
})}
|
||||
>
|
||||
Check
|
||||
{t("Test")}
|
||||
</Widget>
|
||||
)}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ export const TestViewer = forwardRef<TestViewerRef, Props>((props, ref) => {
|
||||
}
|
||||
return x;
|
||||
});
|
||||
await patchVerge({ ...verge, test_list: newList });
|
||||
await patchVerge({ test_list: newList });
|
||||
};
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
|
||||
@@ -9,27 +9,6 @@
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Clash Verge</title>
|
||||
<script>
|
||||
(function () {
|
||||
var _matchMedia = window.matchMedia;
|
||||
window.matchMedia = function () {
|
||||
var v = _matchMedia.apply(null, arguments);
|
||||
if (!v.addEventListener) {
|
||||
v.addEventListener = function () {
|
||||
if (arguments.length < 2 || arguments[0] !== "change") {
|
||||
console.error("Cannot proxy addEventListener:", arguments);
|
||||
return;
|
||||
}
|
||||
if (arguments.length > 2) {
|
||||
console.warn("Proxy addEventListener:", arguments);
|
||||
}
|
||||
v.addListener(arguments[1]);
|
||||
};
|
||||
}
|
||||
return v;
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
+175
-167
@@ -1,60 +1,33 @@
|
||||
{
|
||||
"Back": "Back",
|
||||
"Close": "Close",
|
||||
"Cancel": "Cancel",
|
||||
"Confirm": "Confirm",
|
||||
|
||||
"New": "New",
|
||||
"Edit": "Edit",
|
||||
"Save": "Save",
|
||||
"Delete": "Delete",
|
||||
"Enable": "Enable",
|
||||
"Disable": "Disable",
|
||||
|
||||
"Label-Proxies": "Proxies",
|
||||
"Label-Test": "Test",
|
||||
"Label-Profiles": "Profiles",
|
||||
"Label-Connections": "Connections",
|
||||
"Label-Logs": "Logs",
|
||||
"Label-Rules": "Rules",
|
||||
"Label-Logs": "Logs",
|
||||
"Label-Test": "Test",
|
||||
"Label-Settings": "Settings",
|
||||
|
||||
"Connections": "Connections",
|
||||
"Logs": "Logs",
|
||||
"Clear": "Clear",
|
||||
"Proxies": "Proxies",
|
||||
"Proxy Groups": "Proxy Groups",
|
||||
"Test": "Test",
|
||||
"Proxy Provider": "Proxy Provider",
|
||||
"Update All": "Update All",
|
||||
"Update At": "Update At",
|
||||
"rule": "rule",
|
||||
"global": "global",
|
||||
"direct": "direct",
|
||||
"script": "script",
|
||||
|
||||
"Create Test": "Create Test",
|
||||
"Edit Test": "Edit Test",
|
||||
"Edit": "Edit",
|
||||
"Icon": "Icon",
|
||||
"Test URL": "Test URL",
|
||||
"Test All": "Test All",
|
||||
|
||||
"Paste": "Paste",
|
||||
"Profiles": "Profiles",
|
||||
"Profile URL": "Profile URL",
|
||||
"Import": "Import",
|
||||
"New": "New",
|
||||
"Create Profile": "Create Profile",
|
||||
"Edit Profile": "Edit Profile",
|
||||
"Choose File": "Choose File",
|
||||
"Close": "Close",
|
||||
"Close All": "Close All",
|
||||
"Home": "Home",
|
||||
"Select": "Select",
|
||||
"Edit Info": "Edit Info",
|
||||
"Edit File": "Edit File",
|
||||
"Open File": "Open File",
|
||||
"Update": "Update",
|
||||
"Update(Proxy)": "Update(Proxy)",
|
||||
"Delete": "Delete",
|
||||
"Enable": "Enable",
|
||||
"Disable": "Disable",
|
||||
"Refresh": "Refresh",
|
||||
"To Top": "To Top",
|
||||
"To End": "To End",
|
||||
"Update All Profiles": "Update All Profiles",
|
||||
"View Runtime Config": "View Runtime Config",
|
||||
"Reactivate Profiles": "Reactivate Profiles",
|
||||
"Confirm deletion": "Confirm deletion",
|
||||
"This operation is not reversible": "This operation is not reversible",
|
||||
"Script Console": "Script Console",
|
||||
|
||||
"Location": "Location",
|
||||
"Delay check": "Delay check",
|
||||
"Sort by default": "Sort by default",
|
||||
@@ -64,13 +37,46 @@
|
||||
"Delay check to cancel fixed": "Delay check to cancel fixed",
|
||||
"Proxy basic": "Proxy basic",
|
||||
"Proxy detail": "Proxy detail",
|
||||
"Filter": "Filter",
|
||||
"Filter conditions": "Filter conditions",
|
||||
"Refresh profiles": "Refresh profiles",
|
||||
"Rules": "Rules",
|
||||
"Update All": "Update All",
|
||||
"Update At": "Update At",
|
||||
|
||||
"Profiles": "Profiles",
|
||||
"Update All Profiles": "Update All Profiles",
|
||||
"View Runtime Config": "View Runtime Config",
|
||||
"Reactivate Profiles": "Reactivate Profiles",
|
||||
"Paste": "Paste",
|
||||
"Profile URL": "Profile URL",
|
||||
"Import": "Import",
|
||||
"Create Profile": "Create Profile",
|
||||
"Edit Profile": "Edit Profile",
|
||||
"Type": "Type",
|
||||
"Name": "Name",
|
||||
"Descriptions": "Descriptions",
|
||||
"Subscription URL": "Subscription URL",
|
||||
"Update Interval": "Update Interval",
|
||||
"Choose File": "Choose File",
|
||||
"Use System Proxy": "Use System Proxy",
|
||||
"Use Clash Proxy": "Use Clash Proxy",
|
||||
"Accept Invalid Certs (Danger)": "Allows Invalid Certificates (Danger)",
|
||||
"Refresh": "Refresh",
|
||||
"Home": "Home",
|
||||
"Select": "Select",
|
||||
"Edit Info": "Edit Info",
|
||||
"Edit File": "Edit File",
|
||||
"Open File": "Open File",
|
||||
"Update": "Update",
|
||||
"Update(Proxy)": "Update(Proxy)",
|
||||
"Confirm deletion": "Confirm deletion",
|
||||
"This operation is not reversible": "This operation is not reversible",
|
||||
"Script Console": "Script Console",
|
||||
"To Top": "To Top",
|
||||
"To End": "To End",
|
||||
|
||||
"Connections": "Connections",
|
||||
"Table View": "Table View",
|
||||
"List View": "List View",
|
||||
"Close All": "Close All",
|
||||
"Default": "Default",
|
||||
"Download Speed": "Download Speed",
|
||||
"Upload Speed": "Upload Speed",
|
||||
"Host": "Host",
|
||||
"Downloaded": "Downloaded",
|
||||
"Uploaded": "Uploaded",
|
||||
@@ -84,88 +90,98 @@
|
||||
"Destination IP": "Destination IP",
|
||||
"Close Connection": "Close Connection",
|
||||
|
||||
"Type": "Type",
|
||||
"Name": "Name",
|
||||
"Descriptions": "Descriptions",
|
||||
"Subscription URL": "Subscription URL",
|
||||
"Update Interval": "Update Interval",
|
||||
"Use System Proxy": "Use System Proxy",
|
||||
"Use Clash Proxy": "Use Clash Proxy",
|
||||
"Accept Invalid Certs (Danger)": "Allows Invalid Certificates (Danger)",
|
||||
"Rules": "Rules",
|
||||
"Rule Provider": "Rule Provider",
|
||||
|
||||
"Logs": "Logs",
|
||||
"Pause": "Pause",
|
||||
"Clear": "Clear",
|
||||
|
||||
"Test": "Test",
|
||||
"Test All": "Test All",
|
||||
"Create Test": "Create Test",
|
||||
"Edit Test": "Edit Test",
|
||||
"Icon": "Icon",
|
||||
"Test URL": "Test URL",
|
||||
|
||||
"Settings": "Settings",
|
||||
"Clash Setting": "Clash Setting",
|
||||
"System Setting": "System Setting",
|
||||
"Verge Setting": "Verge Setting",
|
||||
"Tun Mode": "Tun Mode",
|
||||
"Reset to Default": "Reset to Default",
|
||||
"Tun Mode Info": "The Tun mode requires granting core-related permissions. Please enable service mode before using it",
|
||||
"Stack": "Tun Stack",
|
||||
"System and Mixed Can Only be Used in Service Mode": "System and Mixed Can Only be Used in Service Mode",
|
||||
"Device": "Device Name",
|
||||
"Auto Route": "Auto Route",
|
||||
"Strict Route": "Strict Route",
|
||||
"Auto Detect Interface": "Auto Detect Interface",
|
||||
"DNS Hijack": "DNS Hijack",
|
||||
"MTU": "Max Transmission Unit",
|
||||
"Service Mode": "Service Mode",
|
||||
"Current State": "Current State",
|
||||
"pending": "pending",
|
||||
"installed": "installed",
|
||||
"uninstall": "uninstalled",
|
||||
"active": "active",
|
||||
"unknown": "unknown",
|
||||
"Information: Please make sure that the Clash Verge Service is installed and enabled": "Information: Please make sure that the Clash Verge Service is installed and enabled",
|
||||
"Install": "Install",
|
||||
"Uninstall": "Uninstall",
|
||||
"Disable Service Mode": "Disable Service Mode",
|
||||
"System Proxy": "System Proxy",
|
||||
"System Proxy Info": "Enable to modify the operating system's proxy settings. If enabling fails, modify the operating system's proxy settings manually",
|
||||
"System Proxy Setting": "System Proxy Setting",
|
||||
"Current System Proxy": "Current System Proxy",
|
||||
"Enable status": "Enable Status:",
|
||||
"Enabled": "Enabled",
|
||||
"Disabled": "Disabled",
|
||||
"Server Addr": "Server Addr: ",
|
||||
"Not available": "Not available",
|
||||
"Proxy Guard": "Proxy Guard",
|
||||
"Proxy Guard Info": "Enable to prevent other software from modifying the operating system's proxy settings",
|
||||
"Guard Duration": "Guard Duration",
|
||||
"Proxy Bypass": "Proxy Bypass Settings: ",
|
||||
"Bypass": "Bypass: ",
|
||||
"Use PAC Mode": "Use PAC Mode",
|
||||
"PAC Script Content": "PAC Script Content",
|
||||
"PAC URL": "PAC URL: ",
|
||||
"Auto Launch": "Auto Launch",
|
||||
"Silent Start": "Silent Start",
|
||||
|
||||
"Clash Setting": "Clash Setting",
|
||||
"Allow Lan": "Allow Lan",
|
||||
"IPv6": "IPv6",
|
||||
"Log Level": "Log Level",
|
||||
"Port Config": "Port Config",
|
||||
"Random Port": "Random Port",
|
||||
"Restart Application to Apply Modifications": "Restart Application to Apply Modifications",
|
||||
"External": "External",
|
||||
"External Controller": "External Controller",
|
||||
"Core Secret": "Core Secret",
|
||||
"Recommended": "Recommended",
|
||||
"Open URL": "Open URL",
|
||||
"Replace host, port, secret with %host, %port, %secret": "Replace host, port, secret with %host, %port, %secret",
|
||||
"Support %host, %port, %secret": "Support %host, %port, %secret",
|
||||
"Clash Core": "Clash Core",
|
||||
"Grant": "Grant",
|
||||
"Upgrade": "Upgrade",
|
||||
"Restart": "Restart",
|
||||
"Tun mode requires": "Tun mode requires",
|
||||
"Tun Mode": "Tun Mode",
|
||||
"Service Mode": "Service Mode",
|
||||
"Auto Launch": "Auto Launch",
|
||||
"Silent Start": "Silent Start",
|
||||
"System Proxy": "System Proxy",
|
||||
"System Proxy Setting": "System Proxy Setting",
|
||||
"Grant": "Grant",
|
||||
"Open UWP tool": "Open UWP tool",
|
||||
"Update GeoData": "Update GeoData",
|
||||
"Use PAC Mode": "Use PAC Mode",
|
||||
"PAC URL": "PAC URL",
|
||||
"PAC Script Content": "PAC Script Content",
|
||||
"Proxy Guard": "Proxy Guard",
|
||||
"Guard Duration": "Guard Duration",
|
||||
"Proxy Bypass": "Proxy Bypass",
|
||||
"Current System Proxy": "Current System Proxy",
|
||||
"Enable status": "Enable status",
|
||||
"Server Addr": "Server Addr",
|
||||
"Bypass": "Bypass",
|
||||
|
||||
"Verge Setting": "Verge Setting",
|
||||
"Language": "Language",
|
||||
"Theme Mode": "Theme Mode",
|
||||
"theme.light": "Light",
|
||||
"theme.dark": "Dark",
|
||||
"theme.system": "System",
|
||||
"Tray Click Event": "Tray Click Event",
|
||||
"Show Main Window": "Show Main Window",
|
||||
"Copy Env Type": "Copy Env Type",
|
||||
"Start Page": "Start Page",
|
||||
"Startup Script": "Startup Script",
|
||||
"Browse": "Browse",
|
||||
"Show Main Window": "Show Main Window",
|
||||
"Theme Setting": "Theme Setting",
|
||||
"Layout Setting": "Layout Setting",
|
||||
"Miscellaneous": "Miscellaneous",
|
||||
"Hotkey Setting": "Hotkey Setting",
|
||||
"Traffic Graph": "Traffic Graph",
|
||||
"Memory Usage": "Memory Usage",
|
||||
"Proxy Group Icon": "Proxy Group Icon",
|
||||
"Tray Icon": "Tray Icon",
|
||||
"Menu Icon": "Menu Icon",
|
||||
"Monochrome": "Monochrome",
|
||||
"Colorful": "Colorful",
|
||||
"Common Tray Icon": "Common Tray Icon",
|
||||
"System Proxy Tray Icon": "System Proxy Tray Icon",
|
||||
"Tun Tray Icon": "Tun Tray Icon",
|
||||
"Language": "Language",
|
||||
"Open App Dir": "Open App Dir",
|
||||
"Open Core Dir": "Open Core Dir",
|
||||
"Open Logs Dir": "Open Logs Dir",
|
||||
"Check for Updates": "Check for Updates",
|
||||
"Open Dev Tools": "Open Dev Tools",
|
||||
"Verge Version": "Verge Version",
|
||||
"theme.light": "Light",
|
||||
"theme.dark": "Dark",
|
||||
"theme.system": "System",
|
||||
"Clash Field": "Clash Field",
|
||||
"Runtime Config": "Runtime Config",
|
||||
"ReadOnly": "ReadOnly",
|
||||
"ReadOnlyMessage": "Cannot edit in read-only editor",
|
||||
"Restart": "Restart",
|
||||
"Upgrade": "Upgrade",
|
||||
|
||||
"Primary Color": "Primary Color",
|
||||
"Secondary Color": "Secondary Color",
|
||||
"Primary Text": "Primary Text",
|
||||
@@ -176,82 +192,74 @@
|
||||
"Success Color": "Success Color",
|
||||
"Font Family": "Font Family",
|
||||
"CSS Injection": "CSS Injection",
|
||||
|
||||
"Back": "Back",
|
||||
"Save": "Save",
|
||||
"Cancel": "Cancel",
|
||||
"Exit": "Exit",
|
||||
"Confirm": "Confirm",
|
||||
|
||||
"Default": "Default",
|
||||
"Download Speed": "Download Speed",
|
||||
"Upload Speed": "Upload Speed",
|
||||
|
||||
"Layout Setting": "Layout Setting",
|
||||
"Traffic Graph": "Traffic Graph",
|
||||
"Memory Usage": "Memory Usage",
|
||||
"Proxy Group Icon": "Proxy Group Icon",
|
||||
"Menu Icon": "Menu Icon",
|
||||
"Monochrome": "Monochrome",
|
||||
"Colorful": "Colorful",
|
||||
"Tray Icon": "Tray Icon",
|
||||
"Common Tray Icon": "Common Tray Icon",
|
||||
"System Proxy Tray Icon": "System Proxy Tray Icon",
|
||||
"Tun Tray Icon": "Tun Tray Icon",
|
||||
"Miscellaneous": "Miscellaneous",
|
||||
"App Log Level": "App Log Level",
|
||||
"Auto Close Connections": "Auto Close Connections",
|
||||
"Auto Check Update": "Auto Check Update",
|
||||
"Enable Builtin Enhanced": "Enable Builtin Enhanced",
|
||||
"Proxy Layout Column": "Proxy Layout Column",
|
||||
"Auto Log Clean": "Auto Log Clean",
|
||||
"Never Clean": "Never Clean",
|
||||
"Retain 7 Days": "Retain 7 Days",
|
||||
"Retain 30 Days": "Retain 30 Days",
|
||||
"Retain 90 Days": "Retain 90 Days",
|
||||
"Default Latency Test": "Default Latency Test",
|
||||
"Default Latency Timeout": "Default Latency Timeout",
|
||||
"Hotkey Setting": "Hotkey Setting",
|
||||
"open_or_close_dashboard": "Open/Close Dashboard",
|
||||
"clash_mode_rule": "Rule Mode",
|
||||
"clash_mode_global": "Global Mode",
|
||||
"clash_mode_direct": "Direct Mode",
|
||||
"toggle_system_proxy": "Enable/Disable System Proxy",
|
||||
"toggle_tun_mode": "Enable/Disable Tun Mode",
|
||||
|
||||
"App Log Level": "App Log Level",
|
||||
"Auto Close Connections": "Auto Close Connections",
|
||||
"Auto Check Update": "Auto Check Update",
|
||||
"Enable Builtin Enhanced": "Enable Builtin Enhanced",
|
||||
"Proxy Layout Column": "Proxy Layout Column",
|
||||
"Default Latency Test": "Default Latency Test",
|
||||
"Default Latency Timeout": "Default Latency Timeout",
|
||||
|
||||
"Auto Log Clean": "Auto Log Clean",
|
||||
"Never Clean": "Never Clean",
|
||||
"Retain 7 Days": "Retain 7 Days",
|
||||
"Retain 30 Days": "Retain 30 Days",
|
||||
"Retain 90 Days": "Retain 90 Days",
|
||||
|
||||
"Stack": "Tun Stack",
|
||||
"Device": "Device Name",
|
||||
"Auto Route": "Auto Route",
|
||||
"Strict Route": "Strict Route",
|
||||
"Auto Detect Interface": "Auto Detect Interface",
|
||||
"DNS Hijack": "DNS Hijack",
|
||||
"MTU": "Max Transmission Unit",
|
||||
"Reset to Default": "Reset to Default",
|
||||
|
||||
"Current State": "Current State",
|
||||
"pending": "pending",
|
||||
"installed": "installed",
|
||||
"uninstall": "uninstalled",
|
||||
"active": "active",
|
||||
"unknown": "unknown",
|
||||
"Disable Service Mode": "Disable Service Mode",
|
||||
"Install": "Install",
|
||||
"Uninstall": "Uninstall",
|
||||
|
||||
"Runtime Config": "Runtime Config",
|
||||
"Open App Dir": "Open App Dir",
|
||||
"Open Core Dir": "Open Core Dir",
|
||||
"Open Logs Dir": "Open Logs Dir",
|
||||
"Check for Updates": "Check for Updates",
|
||||
"Go to Release Page": "Go to Release Page",
|
||||
"Portable Updater Error": "The portable version does not support in-app updates. Please manually download and replace it",
|
||||
"Tun Mode Info": "The Tun mode requires granting core-related permissions. Please enable service mode before using it",
|
||||
"System and Mixed Can Only be Used in Service Mode": "System and Mixed Can Only be Used in Service Mode",
|
||||
"Information: Please make sure that the Clash Verge Service is installed and enabled": "Information: Please make sure that the Clash Verge Service is installed and enabled",
|
||||
"Open Dev Tools": "Open Dev Tools",
|
||||
"Exit": "Exit",
|
||||
"Verge Version": "Verge Version",
|
||||
|
||||
"ReadOnly": "ReadOnly",
|
||||
"ReadOnlyMessage": "Cannot edit in read-only editor",
|
||||
"Filter": "Filter",
|
||||
"Filter conditions": "Filter conditions",
|
||||
"Match Case": "Match Case",
|
||||
"Match Whole Word": "Match Whole Word",
|
||||
"Use Regular Expression": "Use Regular Expression",
|
||||
|
||||
"External Controller Address Modified": "External Controller Address Modified",
|
||||
"Clash Port Modified": "Clash Port Modified",
|
||||
"Currently on the Latest Version": "Currently on the Latest Version",
|
||||
"Only YAML Files Supported": "Only YAML Files Supported",
|
||||
"Port Conflict": "Port Conflict",
|
||||
"Proxy Daemon Duration Cannot be Less than 1 Second": "Proxy Daemon Duration Cannot be Less than 1 Second",
|
||||
"Profile Imported Successfully": "Profile Imported Successfully",
|
||||
"Clash Config Updated": "Clash Config Updated",
|
||||
"Profile Switched": "Profile Switched",
|
||||
"Profile Reactivated": "Profile Reactivated",
|
||||
"Clash Config Updated": "Clash Config Updated",
|
||||
"Only YAML Files Supported": "Only YAML Files Supported",
|
||||
"Settings Applied": "Settings Applied",
|
||||
"Service Installed Successfully": "Service Installed Successfully",
|
||||
"Service Uninstalled Successfully": "Service Uninstalled Successfully",
|
||||
"GeoData Updated": "GeoData Updated",
|
||||
"Proxy Daemon Duration Cannot be Less than 1 Second": "Proxy Daemon Duration Cannot be Less than 1 Second",
|
||||
"Invalid Bypass Format": "Invalid Bypass Format",
|
||||
"Clash Port Modified": "Clash Port Modified",
|
||||
"Port Conflict": "Port Conflict",
|
||||
"Restart Application to Apply Modifications": "Restart Application to Apply Modifications",
|
||||
"External Controller Address Modified": "External Controller Address Modified",
|
||||
"Permissions Granted Successfully for _clash Core": "Permissions Granted Successfully for {{core}} Core",
|
||||
"Profile Imported Successfully": "Profile Imported Successfully",
|
||||
"Core Version Updated": "Core Version Updated",
|
||||
"Clash Core Restarted": "Clash Core Restarted",
|
||||
"Switched to _clash Core": "Switched to {{core}} Core",
|
||||
"Core Version Updated": "Core Version Updated"
|
||||
"GeoData Updated": "GeoData Updated",
|
||||
"Currently on the Latest Version": "Currently on the Latest Version"
|
||||
}
|
||||
|
||||
+175
-167
@@ -1,60 +1,33 @@
|
||||
{
|
||||
"Back": "بازگشت",
|
||||
"Close": "بستن",
|
||||
"Cancel": "لغو",
|
||||
"Confirm": "تأیید",
|
||||
|
||||
"New": "جدید",
|
||||
"Edit": "ویرایش",
|
||||
"Save": "ذخیره",
|
||||
"Delete": "حذف",
|
||||
"Enable": "فعال کردن",
|
||||
"Disable": "غیرفعال کردن",
|
||||
|
||||
"Label-Proxies": "پراکسیها",
|
||||
"Label-Test": "آزمون",
|
||||
"Label-Profiles": "پروفایلها",
|
||||
"Label-Connections": "اتصالات",
|
||||
"Label-Logs": "لاگها",
|
||||
"Label-Rules": "قوانین",
|
||||
"Label-Logs": "لاگها",
|
||||
"Label-Test": "آزمون",
|
||||
"Label-Settings": "تنظیمات",
|
||||
|
||||
"Connections": "اتصالات",
|
||||
"Logs": "لاگها",
|
||||
"Clear": "پاک کردن",
|
||||
"Proxies": "پراکسیها",
|
||||
"Proxy Groups": "گروههای پراکسی",
|
||||
"Test": "آزمون",
|
||||
"Proxy Provider": "تأمینکننده پروکسی",
|
||||
"Update All": "بهروزرسانی همه",
|
||||
"Update At": "بهروزرسانی در",
|
||||
"rule": "قانون",
|
||||
"global": "جهانی",
|
||||
"direct": "مستقیم",
|
||||
"script": "اسکریپت",
|
||||
|
||||
"Create Test": "ایجاد آزمون",
|
||||
"Edit Test": "ویرایش آزمون",
|
||||
"Edit": "ویرایش",
|
||||
"Icon": "آیکون",
|
||||
"Test URL": "آدرس آزمون",
|
||||
"Test All": "آزمون همه",
|
||||
|
||||
"Paste": "چسباندن",
|
||||
"Profiles": "پروفایلها",
|
||||
"Profile URL": "آدرس پروفایل",
|
||||
"Import": "وارد کردن",
|
||||
"New": "جدید",
|
||||
"Create Profile": "ایجاد پروفایل",
|
||||
"Edit Profile": "ویرایش پروفایل",
|
||||
"Choose File": "انتخاب فایل",
|
||||
"Close": "بستن",
|
||||
"Close All": "بستن همه",
|
||||
"Home": "خانه",
|
||||
"Select": "انتخاب",
|
||||
"Edit Info": "ویرایش اطلاعات",
|
||||
"Edit File": "ویرایش فایل",
|
||||
"Open File": "باز کردن فایل",
|
||||
"Update": "بهروزرسانی",
|
||||
"Update(Proxy)": "بهروزرسانی (پراکسی)",
|
||||
"Delete": "حذف",
|
||||
"Enable": "فعال کردن",
|
||||
"Disable": "غیرفعال کردن",
|
||||
"Refresh": "بازنشانی",
|
||||
"To Top": "به بالا",
|
||||
"To End": "به پایان",
|
||||
"Update All Profiles": "بهروزرسانی همه پروفایلها",
|
||||
"View Runtime Config": "مشاهده پیکربندی زمان اجرا",
|
||||
"Reactivate Profiles": "فعالسازی مجدد پروفایلها",
|
||||
"Confirm deletion": "تأیید حذف",
|
||||
"This operation is not reversible": "این عملیات قابل برگشت نیست",
|
||||
"Script Console": "کنسول اسکریپت",
|
||||
|
||||
"Location": "موقعیت",
|
||||
"Delay check": "بررسی تأخیر",
|
||||
"Sort by default": "مرتبسازی بر اساس پیشفرض",
|
||||
@@ -64,13 +37,46 @@
|
||||
"Delay check to cancel fixed": "بررسی تأخیر برای لغو ثابت",
|
||||
"Proxy basic": "پراکسی پایه",
|
||||
"Proxy detail": "جزئیات پراکسی",
|
||||
"Filter": "فیلتر",
|
||||
"Filter conditions": "شرایط فیلتر",
|
||||
"Refresh profiles": "بازنشانی پروفایلها",
|
||||
"Rules": "قوانین",
|
||||
"Update All": "بهروزرسانی همه",
|
||||
"Update At": "بهروزرسانی در",
|
||||
|
||||
"Profiles": "پروفایلها",
|
||||
"Update All Profiles": "بهروزرسانی همه پروفایلها",
|
||||
"View Runtime Config": "مشاهده پیکربندی زمان اجرا",
|
||||
"Reactivate Profiles": "فعالسازی مجدد پروفایلها",
|
||||
"Paste": "چسباندن",
|
||||
"Profile URL": "آدرس پروفایل",
|
||||
"Import": "وارد کردن",
|
||||
"Create Profile": "ایجاد پروفایل",
|
||||
"Edit Profile": "ویرایش پروفایل",
|
||||
"Type": "نوع",
|
||||
"Name": "نام",
|
||||
"Descriptions": "توضیحات",
|
||||
"Subscription URL": "آدرس اشتراک",
|
||||
"Update Interval": "فاصله زمانی بهروزرسانی",
|
||||
"Choose File": "انتخاب فایل",
|
||||
"Use System Proxy": "استفاده از پراکسی سیستم",
|
||||
"Use Clash Proxy": "استفاده از پراکسی Clash",
|
||||
"Accept Invalid Certs (Danger)": "پذیرش گواهینامههای نامعتبر (خطرناک)",
|
||||
"Refresh": "بازنشانی",
|
||||
"Home": "خانه",
|
||||
"Select": "انتخاب",
|
||||
"Edit Info": "ویرایش اطلاعات",
|
||||
"Edit File": "ویرایش فایل",
|
||||
"Open File": "باز کردن فایل",
|
||||
"Update": "بهروزرسانی",
|
||||
"Update(Proxy)": "بهروزرسانی (پراکسی)",
|
||||
"Confirm deletion": "تأیید حذف",
|
||||
"This operation is not reversible": "این عملیات قابل برگشت نیست",
|
||||
"Script Console": "کنسول اسکریپت",
|
||||
"To Top": "به بالا",
|
||||
"To End": "به پایان",
|
||||
|
||||
"Connections": "اتصالات",
|
||||
"Table View": "نمای جدولی",
|
||||
"List View": "نمای لیستی",
|
||||
"Close All": "بستن همه",
|
||||
"Default": "پیشفرض",
|
||||
"Download Speed": "سرعت دانلود",
|
||||
"Upload Speed": "سرعت بارگذاری",
|
||||
"Host": "میزبان",
|
||||
"Downloaded": "دانلود شده",
|
||||
"Uploaded": "بارگذاری شده",
|
||||
@@ -84,88 +90,98 @@
|
||||
"Destination IP": "آدرس IP مقصد",
|
||||
"Close Connection": "بستن اتصال",
|
||||
|
||||
"Type": "نوع",
|
||||
"Name": "نام",
|
||||
"Descriptions": "توضیحات",
|
||||
"Subscription URL": "آدرس اشتراک",
|
||||
"Update Interval": "فاصله زمانی بهروزرسانی",
|
||||
"Use System Proxy": "استفاده از پراکسی سیستم",
|
||||
"Use Clash Proxy": "استفاده از پراکسی Clash",
|
||||
"Accept Invalid Certs (Danger)": "پذیرش گواهینامههای نامعتبر (خطرناک)",
|
||||
"Rules": "قوانین",
|
||||
"Rule Provider": "تأمینکننده قانون",
|
||||
|
||||
"Logs": "لاگها",
|
||||
"Pause": "توقف",
|
||||
"Clear": "پاک کردن",
|
||||
|
||||
"Test": "آزمون",
|
||||
"Test All": "آزمون همه",
|
||||
"Create Test": "ایجاد آزمون",
|
||||
"Edit Test": "ویرایش آزمون",
|
||||
"Icon": "آیکون",
|
||||
"Test URL": "آدرس آزمون",
|
||||
|
||||
"Settings": "تنظیمات",
|
||||
"Clash Setting": "تنظیمات Clash",
|
||||
"System Setting": "تنظیمات سیستم",
|
||||
"Verge Setting": "تنظیمات Verge",
|
||||
"Tun Mode": "حالت Tun",
|
||||
"Reset to Default": "بازنشانی به پیشفرض",
|
||||
"Tun Mode Info": "حالت Tun نیاز به اعطای مجوزهای مربوط به هسته دارد. لطفاً قبل از استفاده، حالت سرویس را فعال کنید",
|
||||
"Stack": "انباشته Tun",
|
||||
"System and Mixed Can Only be Used in Service Mode": "سیستم و ترکیبی تنها میتوانند در حالت سرویس استفاده شوند",
|
||||
"Device": "نام دستگاه",
|
||||
"Auto Route": "مسیر خودکار",
|
||||
"Strict Route": "مسیر دقیق",
|
||||
"Auto Detect Interface": "تشخیص خودکار رابط",
|
||||
"DNS Hijack": "ربایش DNS",
|
||||
"MTU": "واحد حداکثر انتقال",
|
||||
"Service Mode": "حالت سرویس",
|
||||
"Current State": "وضعیت فعلی",
|
||||
"pending": "در انتظار",
|
||||
"installed": "نصب شده",
|
||||
"uninstall": "حذف شده",
|
||||
"active": "فعال",
|
||||
"unknown": "ناشناخته",
|
||||
"Information: Please make sure that the Clash Verge Service is installed and enabled": "اطلاعات: لطفاً مطمئن شوید که سرویس Clash Verge نصب و فعال شده است",
|
||||
"Install": "نصب",
|
||||
"Uninstall": "حذف نصب",
|
||||
"Disable Service Mode": "غیرفعال کردن حالت سرویس",
|
||||
"System Proxy": "پراکسی سیستم",
|
||||
"System Proxy Info": "به امکانات تنظیم پروکسی سیستم عامل دسترسی پیدا کنید. اگر فعالسازی ناموفق بود، پروکسی سیستم عامل را بهصورت دستی تغییر دهید",
|
||||
"System Proxy Setting": "تنظیمات پراکسی سیستم",
|
||||
"Current System Proxy": "پراکسی سیستم فعلی",
|
||||
"Enable status": "وضعیت فعال",
|
||||
"Enabled": "توانایی فعال شد",
|
||||
"Disabled": "غیرفعال شد",
|
||||
"Server Addr": "آدرس سرور: ",
|
||||
"Not available": "غیر فعال شد",
|
||||
"Proxy Guard": "محافظ پراکسی",
|
||||
"Proxy Guard Info": "امکان جلوگیری از نرمافزارهای دیگر از تغییر تنظیمات پروکسی سیستم عامل را فعال کنید",
|
||||
"Guard Duration": "مدت محافظت",
|
||||
"Proxy Bypass": "دور زدن پراکسی: ",
|
||||
"Bypass": "دور زدن: ",
|
||||
"Use PAC Mode": "استفاده از حالت PAC",
|
||||
"PAC Script Content": "محتوای اسکریپت PAC",
|
||||
"PAC URL": "PAC URL: ",
|
||||
"Auto Launch": "راهاندازی خودکار",
|
||||
"Silent Start": "شروع بیصدا",
|
||||
|
||||
"Clash Setting": "تنظیمات Clash",
|
||||
"Allow Lan": "اجازه LAN",
|
||||
"IPv6": "IPv6",
|
||||
"Log Level": "سطح لاگ",
|
||||
"Port Config": "پیکربندی پورت",
|
||||
"Random Port": "پورت تصادفی",
|
||||
"Restart Application to Apply Modifications": "راهاندازی مجدد برنامه برای اعمال تغییرات",
|
||||
"External": "خارجی",
|
||||
"External Controller": "کنترلکننده خارجی",
|
||||
"Core Secret": "رمز اصلی",
|
||||
"Recommended": "توصیه شده",
|
||||
"Open URL": "باز کردن آدرس اینترنتی",
|
||||
"Replace host, port, secret with %host, %port, %secret": "جایگزین کردن میزبان، پورت و رمز با %host، %port، %secret",
|
||||
"Support %host, %port, %secret": "پشتیبانی از %host، %port و %secret",
|
||||
"Clash Core": "هسته Clash",
|
||||
"Grant": "اعطا",
|
||||
"Upgrade": "ارتقاء",
|
||||
"Restart": "راهاندازی مجدد",
|
||||
"Tun mode requires": "Tun mode نیاز دارد",
|
||||
"Tun Mode": "حالت Tun",
|
||||
"Service Mode": "حالت سرویس",
|
||||
"Auto Launch": "راهاندازی خودکار",
|
||||
"Silent Start": "شروع بیصدا",
|
||||
"System Proxy": "پراکسی سیستم",
|
||||
"System Proxy Setting": "تنظیمات پراکسی سیستم",
|
||||
"Grant": "اعطا",
|
||||
"Open UWP tool": "باز کردن ابزار UWP",
|
||||
"Update GeoData": "بهروزرسانی GeoData",
|
||||
"Use PAC Mode": "استفاده از حالت PAC",
|
||||
"PAC URL": "PAC URL",
|
||||
"PAC Script Content": "محتوای اسکریپت PAC",
|
||||
"Proxy Guard": "محافظ پراکسی",
|
||||
"Guard Duration": "مدت محافظت",
|
||||
"Proxy Bypass": "دور زدن پراکسی",
|
||||
"Current System Proxy": "پراکسی سیستم فعلی",
|
||||
"Enable status": "وضعیت فعال",
|
||||
"Server Addr": "آدرس سرور",
|
||||
"Bypass": "دور زدن",
|
||||
|
||||
"Verge Setting": "تنظیمات Verge",
|
||||
"Language": "زبان",
|
||||
"Theme Mode": "حالت تم",
|
||||
"theme.light": "روشن",
|
||||
"theme.dark": "تاریک",
|
||||
"theme.system": "سیستم",
|
||||
"Tray Click Event": "رویداد کلیک در سینی سیستم",
|
||||
"Show Main Window": "نمایش پنجره اصلی",
|
||||
"Copy Env Type": "کپی نوع محیط",
|
||||
"Start Page": "صفحه شروع",
|
||||
"Startup Script": "اسکریپت راهاندازی",
|
||||
"Browse": "مرور کردن",
|
||||
"Show Main Window": "نمایش پنجره اصلی",
|
||||
"Theme Setting": "تنظیمات تم",
|
||||
"Layout Setting": "تنظیمات چیدمان",
|
||||
"Miscellaneous": "متفرقه",
|
||||
"Hotkey Setting": "تنظیمات کلیدهای میانبر",
|
||||
"Traffic Graph": "نمودار ترافیک",
|
||||
"Memory Usage": "استفاده از حافظه",
|
||||
"Proxy Group Icon": "آیکون گروه پراکسی",
|
||||
"Tray Icon": "آیکون سینی سیستم",
|
||||
"Menu Icon": "آیکون منو",
|
||||
"Monochrome": "تک رنگ",
|
||||
"Colorful": "رنگارنگ",
|
||||
"Common Tray Icon": "آیکون مشترک سینی سیستم",
|
||||
"System Proxy Tray Icon": "آیکون سینی پراکسی سیستم",
|
||||
"Tun Tray Icon": "آیکون سینی Tun",
|
||||
"Language": "زبان",
|
||||
"Open App Dir": "باز کردن پوشه برنامه",
|
||||
"Open Core Dir": "باز کردن پوشه هسته",
|
||||
"Open Logs Dir": "باز کردن پوشه لاگها",
|
||||
"Check for Updates": "بررسی برای بهروزرسانیها",
|
||||
"Open Dev Tools": "باز کردن ابزارهای توسعهدهنده",
|
||||
"Verge Version": "نسخه Verge",
|
||||
"theme.light": "روشن",
|
||||
"theme.dark": "تاریک",
|
||||
"theme.system": "سیستم",
|
||||
"Clash Field": "زمینه Clash",
|
||||
"Runtime Config": "پیکربندی زمان اجرا",
|
||||
"ReadOnly": "فقط خواندنی",
|
||||
"ReadOnlyMessage": "نمیتوان در ویرایشگر فقط خواندنی ویرایش کرد",
|
||||
"Restart": "راهاندازی مجدد",
|
||||
"Upgrade": "ارتقاء",
|
||||
|
||||
"Primary Color": "رنگ اصلی",
|
||||
"Secondary Color": "رنگ ثانویه",
|
||||
"Primary Text": "متن اصلی",
|
||||
@@ -176,82 +192,74 @@
|
||||
"Success Color": "رنگ موفقیت",
|
||||
"Font Family": "خانواده فونت",
|
||||
"CSS Injection": "تزریق CSS",
|
||||
|
||||
"Back": "بازگشت",
|
||||
"Save": "ذخیره",
|
||||
"Cancel": "لغو",
|
||||
"Exit": "خروج",
|
||||
"Confirm": "تأیید",
|
||||
|
||||
"Default": "پیشفرض",
|
||||
"Download Speed": "سرعت دانلود",
|
||||
"Upload Speed": "سرعت بارگذاری",
|
||||
|
||||
"Layout Setting": "تنظیمات چیدمان",
|
||||
"Traffic Graph": "نمودار ترافیک",
|
||||
"Memory Usage": "استفاده از حافظه",
|
||||
"Proxy Group Icon": "آیکون گروه پراکسی",
|
||||
"Menu Icon": "آیکون منو",
|
||||
"Monochrome": "تک رنگ",
|
||||
"Colorful": "رنگارنگ",
|
||||
"Tray Icon": "آیکون سینی سیستم",
|
||||
"Common Tray Icon": "آیکون مشترک سینی سیستم",
|
||||
"System Proxy Tray Icon": "آیکون سینی پراکسی سیستم",
|
||||
"Tun Tray Icon": "آیکون سینی Tun",
|
||||
"Miscellaneous": "متفرقه",
|
||||
"App Log Level": "سطح لاگ برنامه",
|
||||
"Auto Close Connections": "بستن خودکار اتصالات",
|
||||
"Auto Check Update": "بررسی خودکار بهروزرسانی",
|
||||
"Enable Builtin Enhanced": "فعال کردن تقویت داخلی",
|
||||
"Proxy Layout Column": "ستون چیدمان پراکسی",
|
||||
"Auto Log Clean": "پاکسازی خودکار لاگ",
|
||||
"Never Clean": "هرگز پاک نکن",
|
||||
"Retain 7 Days": "نگهداری به مدت 7 روز",
|
||||
"Retain 30 Days": "نگهداری به مدت 30 روز",
|
||||
"Retain 90 Days": "نگهداری به مدت 90 روز",
|
||||
"Default Latency Test": "آزمون تأخیر پیشفرض",
|
||||
"Default Latency Timeout": "زمان انتظار تأخیر پیشفرض",
|
||||
"Hotkey Setting": "تنظیمات کلیدهای میانبر",
|
||||
"open_or_close_dashboard": "باز/بستن داشبورد",
|
||||
"clash_mode_rule": "حالت قانون",
|
||||
"clash_mode_global": "حالت جهانی",
|
||||
"clash_mode_direct": "حالت مستقیم",
|
||||
"toggle_system_proxy": "فعال/غیرفعال کردن پراکسی سیستم",
|
||||
"toggle_tun_mode": "فعال/غیرفعال کردن حالت Tun",
|
||||
|
||||
"App Log Level": "سطح لاگ برنامه",
|
||||
"Auto Close Connections": "بستن خودکار اتصالات",
|
||||
"Auto Check Update": "بررسی خودکار بهروزرسانی",
|
||||
"Enable Builtin Enhanced": "فعال کردن تقویت داخلی",
|
||||
"Proxy Layout Column": "ستون چیدمان پراکسی",
|
||||
"Default Latency Test": "آزمون تأخیر پیشفرض",
|
||||
"Default Latency Timeout": "زمان انتظار تأخیر پیشفرض",
|
||||
|
||||
"Auto Log Clean": "پاکسازی خودکار لاگ",
|
||||
"Never Clean": "هرگز پاک نکن",
|
||||
"Retain 7 Days": "نگهداری به مدت 7 روز",
|
||||
"Retain 30 Days": "نگهداری به مدت 30 روز",
|
||||
"Retain 90 Days": "نگهداری به مدت 90 روز",
|
||||
|
||||
"Stack": "انباشته Tun",
|
||||
"Device": "نام دستگاه",
|
||||
"Auto Route": "مسیر خودکار",
|
||||
"Strict Route": "مسیر دقیق",
|
||||
"Auto Detect Interface": "تشخیص خودکار رابط",
|
||||
"DNS Hijack": "ربایش DNS",
|
||||
"MTU": "واحد حداکثر انتقال",
|
||||
"Reset to Default": "بازنشانی به پیشفرض",
|
||||
|
||||
"Current State": "وضعیت فعلی",
|
||||
"pending": "در انتظار",
|
||||
"installed": "نصب شده",
|
||||
"uninstall": "حذف شده",
|
||||
"active": "فعال",
|
||||
"unknown": "ناشناخته",
|
||||
"Disable Service Mode": "غیرفعال کردن حالت سرویس",
|
||||
"Install": "نصب",
|
||||
"Uninstall": "حذف نصب",
|
||||
|
||||
"Runtime Config": "پیکربندی زمان اجرا",
|
||||
"Open App Dir": "باز کردن پوشه برنامه",
|
||||
"Open Core Dir": "باز کردن پوشه هسته",
|
||||
"Open Logs Dir": "باز کردن پوشه لاگها",
|
||||
"Check for Updates": "بررسی برای بهروزرسانیها",
|
||||
"Go to Release Page": "رفتن به صفحه انتشار",
|
||||
"Portable Updater Error": "نسخه پرتابل از بهروزرسانی درون برنامهای پشتیبانی نمیکند. لطفاً به صورت دستی دانلود و جایگزین کنید",
|
||||
"Tun Mode Info": "حالت Tun نیاز به اعطای مجوزهای مربوط به هسته دارد. لطفاً قبل از استفاده، حالت سرویس را فعال کنید",
|
||||
"System and Mixed Can Only be Used in Service Mode": "سیستم و ترکیبی تنها میتوانند در حالت سرویس استفاده شوند",
|
||||
"Information: Please make sure that the Clash Verge Service is installed and enabled": "اطلاعات: لطفاً مطمئن شوید که سرویس Clash Verge نصب و فعال شده است",
|
||||
"Open Dev Tools": "باز کردن ابزارهای توسعهدهنده",
|
||||
"Exit": "خروج",
|
||||
"Verge Version": "نسخه Verge",
|
||||
|
||||
"ReadOnly": "فقط خواندنی",
|
||||
"ReadOnlyMessage": "نمیتوان در ویرایشگر فقط خواندنی ویرایش کرد",
|
||||
"Filter": "فیلتر",
|
||||
"Filter conditions": "شرایط فیلتر",
|
||||
"Match Case": "تطبیق حروف کوچک و بزرگ",
|
||||
"Match Whole Word": "تطبیق کل کلمه",
|
||||
"Use Regular Expression": "استفاده از عبارت منظم",
|
||||
|
||||
"External Controller Address Modified": "آدرس کنترلکننده خارجی تغییر یافت",
|
||||
"Clash Port Modified": "پورت Clash تغییر یافت",
|
||||
"Currently on the Latest Version": "در حال حاضر در آخرین نسخه",
|
||||
"Only YAML Files Supported": "فقط فایلهای YAML پشتیبانی میشوند",
|
||||
"Port Conflict": "تعارض پورت",
|
||||
"Proxy Daemon Duration Cannot be Less than 1 Second": "مدت زمان دیمن پراکسی نمیتواند کمتر از 1 ثانیه باشد",
|
||||
"Profile Imported Successfully": "پروفایل با موفقیت وارد شد",
|
||||
"Clash Config Updated": "پیکربندی Clash بهروزرسانی شد",
|
||||
"Profile Switched": "پروفایل تغییر یافت",
|
||||
"Profile Reactivated": "پروفایل مجدداً فعال شد",
|
||||
"Clash Config Updated": "پیکربندی Clash بهروزرسانی شد",
|
||||
"Only YAML Files Supported": "فقط فایلهای YAML پشتیبانی میشوند",
|
||||
"Settings Applied": "تنظیمات اعمال شد",
|
||||
"Service Installed Successfully": "سرویس با موفقیت نصب شد",
|
||||
"Service Uninstalled Successfully": "سرویس با موفقیت حذف نصب شد",
|
||||
"GeoData Updated": "GeoData بهروزرسانی شد",
|
||||
"Proxy Daemon Duration Cannot be Less than 1 Second": "مدت زمان دیمن پراکسی نمیتواند کمتر از 1 ثانیه باشد",
|
||||
"Invalid Bypass Format": "فرمت عبور نامعتبر است",
|
||||
"Clash Port Modified": "پورت Clash تغییر یافت",
|
||||
"Port Conflict": "تعارض پورت",
|
||||
"Restart Application to Apply Modifications": "راهاندازی مجدد برنامه برای اعمال تغییرات",
|
||||
"External Controller Address Modified": "آدرس کنترلکننده خارجی تغییر یافت",
|
||||
"Permissions Granted Successfully for _clash Core": "مجوزها با موفقیت برای هسته {{core}} اعطا شد",
|
||||
"Profile Imported Successfully": "پروفایل با موفقیت وارد شد",
|
||||
"Core Version Updated": "نسخه هسته بهروزرسانی شد",
|
||||
"Clash Core Restarted": "هسته Clash مجدداً راهاندازی شد",
|
||||
"Switched to _clash Core": "تغییر به هسته {{core}}",
|
||||
"Core Version Updated": "نسخه هسته بهروزرسانی شد"
|
||||
"GeoData Updated": "GeoData بهروزرسانی شد",
|
||||
"Currently on the Latest Version": "در حال حاضر در آخرین نسخه"
|
||||
}
|
||||
|
||||
+175
-167
@@ -1,60 +1,33 @@
|
||||
{
|
||||
"Back": "Назад",
|
||||
"Close": "Закрыть",
|
||||
"Cancel": "Отмена",
|
||||
"Confirm": "Подтвердить",
|
||||
|
||||
"New": "Новый",
|
||||
"Edit": "Редактировать",
|
||||
"Save": "Сохранить",
|
||||
"Delete": "Удалить",
|
||||
"Enable": "Включить",
|
||||
"Disable": "Отключить",
|
||||
|
||||
"Label-Proxies": "Прокси",
|
||||
"Label-Test": "Тест",
|
||||
"Label-Profiles": "Профили",
|
||||
"Label-Connections": "Соединения",
|
||||
"Label-Logs": "Логи",
|
||||
"Label-Rules": "Правила",
|
||||
"Label-Logs": "Логи",
|
||||
"Label-Test": "Тест",
|
||||
"Label-Settings": "Настройки",
|
||||
|
||||
"Connections": "Соединения",
|
||||
"Logs": "Логи",
|
||||
"Clear": "Очистить",
|
||||
"Proxies": "Прокси",
|
||||
"Proxy Groups": "Группы прокси",
|
||||
"Test": "Тест",
|
||||
"Proxy Provider": "Провайдер прокси",
|
||||
"Update All": "Обновить все",
|
||||
"Update At": "Обновлено в",
|
||||
"rule": "правила",
|
||||
"global": "глобальный",
|
||||
"direct": "прямой",
|
||||
"script": "скриптовый",
|
||||
|
||||
"Create Test": "Создать тест",
|
||||
"Edit Test": "Редактировать тест",
|
||||
"Edit": "Редактировать",
|
||||
"Icon": "Икона",
|
||||
"Test URL": "Тестовый URL",
|
||||
"Test All": "Тест Все",
|
||||
|
||||
"Paste": "Вставить",
|
||||
"Profiles": "Профили",
|
||||
"Profile URL": "URL профиля",
|
||||
"Import": "Импорт",
|
||||
"New": "Новый",
|
||||
"Create Profile": "Создать профиль",
|
||||
"Edit Profile": "Изменить профиль",
|
||||
"Choose File": "Выбрать файл",
|
||||
"Close": "Закрыть",
|
||||
"Close All": "Закрыть всё",
|
||||
"Home": "Главная",
|
||||
"Select": "Выбрать",
|
||||
"Edit Info": "Изменить информацию",
|
||||
"Edit File": "Изменить файл",
|
||||
"Open File": "Открыть файл",
|
||||
"Update": "Обновить",
|
||||
"Update(Proxy)": "Обновить (прокси)",
|
||||
"Delete": "Удалить",
|
||||
"Enable": "Включить",
|
||||
"Disable": "Отключить",
|
||||
"Refresh": "Обновить",
|
||||
"To Top": "Наверх",
|
||||
"To End": "Вниз",
|
||||
"Update All Profiles": "Обновить все профили",
|
||||
"View Runtime Config": "Просмотреть используемый конфиг",
|
||||
"Reactivate Profiles": "Реактивировать профили",
|
||||
"Confirm deletion": "Подтвердите удаление",
|
||||
"This operation is not reversible": "Эта операция необратима",
|
||||
"Script Console": "Консоль скрипта",
|
||||
|
||||
"Location": "Местоположение",
|
||||
"Delay check": "Проверка задержки",
|
||||
"Sort by default": "Сортировать по умолчанию",
|
||||
@@ -64,13 +37,46 @@
|
||||
"Delay check to cancel fixed": "Проверка задержки для отмены фиксированного",
|
||||
"Proxy basic": "Резюме о прокси",
|
||||
"Proxy detail": "Подробности о прокси",
|
||||
"Filter": "Фильтр",
|
||||
"Filter conditions": "Условия фильтрации",
|
||||
"Refresh profiles": "Обновить профили",
|
||||
"Rules": "Правила",
|
||||
"Update All": "Обновить все",
|
||||
"Update At": "Обновлено в",
|
||||
|
||||
"Profiles": "Профили",
|
||||
"Update All Profiles": "Обновить все профили",
|
||||
"View Runtime Config": "Просмотреть используемый конфиг",
|
||||
"Reactivate Profiles": "Реактивировать профили",
|
||||
"Paste": "Вставить",
|
||||
"Profile URL": "URL профиля",
|
||||
"Import": "Импорт",
|
||||
"Create Profile": "Создать профиль",
|
||||
"Edit Profile": "Изменить профиль",
|
||||
"Type": "Тип",
|
||||
"Name": "Название",
|
||||
"Descriptions": "Описания",
|
||||
"Subscription URL": "URL подписки",
|
||||
"Update Interval": "Интервал обновления",
|
||||
"Choose File": "Выбрать файл",
|
||||
"Use System Proxy": "Использовать системный прокси для обновления",
|
||||
"Use Clash Proxy": "Использовать прокси Clash для обновления",
|
||||
"Accept Invalid Certs (Danger)": "Принимать недействительные сертификаты (Опасно)",
|
||||
"Refresh": "Обновить",
|
||||
"Home": "Главная",
|
||||
"Select": "Выбрать",
|
||||
"Edit Info": "Изменить информацию",
|
||||
"Edit File": "Изменить файл",
|
||||
"Open File": "Открыть файл",
|
||||
"Update": "Обновить",
|
||||
"Update(Proxy)": "Обновить (прокси)",
|
||||
"Confirm deletion": "Подтвердите удаление",
|
||||
"This operation is not reversible": "Эта операция необратима",
|
||||
"Script Console": "Консоль скрипта",
|
||||
"To Top": "Наверх",
|
||||
"To End": "Вниз",
|
||||
|
||||
"Connections": "Соединения",
|
||||
"Table View": "Tablichnyy vid",
|
||||
"List View": "Spiskovyy vid",
|
||||
"Close All": "Закрыть всё",
|
||||
"Default": "По умолчанию",
|
||||
"Download Speed": "Скорость загрузки",
|
||||
"Upload Speed": "Скорость загрузки",
|
||||
"Host": "Хост",
|
||||
"Downloaded": "Скачано",
|
||||
"Uploaded": "Загружено",
|
||||
@@ -84,88 +90,98 @@
|
||||
"Destination IP": "IP-адрес назначения",
|
||||
"Close Connection": "Закрыть соединение",
|
||||
|
||||
"Type": "Тип",
|
||||
"Name": "Название",
|
||||
"Descriptions": "Описания",
|
||||
"Subscription URL": "URL подписки",
|
||||
"Update Interval": "Интервал обновления",
|
||||
"Use System Proxy": "Использовать системный прокси для обновления",
|
||||
"Use Clash Proxy": "Использовать прокси Clash для обновления",
|
||||
"Accept Invalid Certs (Danger)": "Принимать недействительные сертификаты (Опасно)",
|
||||
"Rules": "Правила",
|
||||
"Rule Provider": "Провайдер правило",
|
||||
|
||||
"Logs": "Логи",
|
||||
"Pause": "Пауза",
|
||||
"Clear": "Очистить",
|
||||
|
||||
"Test": "Тест",
|
||||
"Test All": "Тест Все",
|
||||
"Create Test": "Создать тест",
|
||||
"Edit Test": "Редактировать тест",
|
||||
"Icon": "Икона",
|
||||
"Test URL": "Тестовый URL",
|
||||
|
||||
"Settings": "Настройки",
|
||||
"Clash Setting": "Настройки Clash",
|
||||
"System Setting": "Настройки системы",
|
||||
"Verge Setting": "Настройки Verge",
|
||||
"Tun Mode": "Режим туннеля",
|
||||
"Reset to Default": "Сбросить настройки по умолчанию",
|
||||
"Tun Mode Info": "Режим туннеля требует предоставления разрешений, связанных с ядрам. Пожалуйста, включите сервисный режим перед его использованием",
|
||||
"Stack": "Стек",
|
||||
"System and Mixed Can Only be Used in Service Mode": "Система и смешанные могут использоваться только в сервисном режиме",
|
||||
"Device": "Имя устройства",
|
||||
"Auto Route": "Автоматическая маршрутизация",
|
||||
"Strict Route": "Строгий маршрут",
|
||||
"Auto Detect Interface": "Автоопределение интерфейса",
|
||||
"DNS Hijack": "DNS-перехват",
|
||||
"MTU": "Максимальная единица передачи",
|
||||
"Service Mode": "Режим сервиса",
|
||||
"Current State": "Текущее состояние",
|
||||
"pending": "Ожидающий",
|
||||
"installed": "Установленный",
|
||||
"uninstall": "Не установленный",
|
||||
"active": "Активированный",
|
||||
"unknown": "неизвестный",
|
||||
"Information: Please make sure that the Clash Verge Service is installed and enabled": "Информация: Пожалуйста, убедитесь, что сервис Clash Verge Service установлен и включен",
|
||||
"Install": "Установить",
|
||||
"Uninstall": "Удалить",
|
||||
"Disable Service Mode": "Отключить режим обслуживания",
|
||||
"System Proxy": "Системный прокси",
|
||||
"System Proxy Info": "Разрешить изменение настроек прокси-сервера операционной системы. Если разрешение не удастся, измените настройки прокси-сервера операционной системы вручную",
|
||||
"System Proxy Setting": "Настройка системного прокси",
|
||||
"Current System Proxy": "Текущий системный прокси",
|
||||
"Enable status": "Статус включения",
|
||||
"Enabled": "Включено",
|
||||
"Disabled": "Отключено",
|
||||
"Server Addr": "Адрес сервера: ",
|
||||
"Not available": "Недоступно",
|
||||
"Proxy Guard": "Защита прокси",
|
||||
"Proxy Guard Info": "Включите эту функцию чтобы предотвратить изменение настроек прокси-сервера операционной системы другим программным обеспечением",
|
||||
"Guard Duration": "Период защиты",
|
||||
"Proxy Bypass": "Игнорирование прокси: ",
|
||||
"Bypass": "Игнорирование: ",
|
||||
"Use PAC Mode": "Используйте режим PAC",
|
||||
"PAC Script Content": "Содержание сценария PAC",
|
||||
"PAC URL": "Адрес PAC: ",
|
||||
"Auto Launch": "Автозапуск",
|
||||
"Silent Start": "Тихий запуск",
|
||||
|
||||
"Clash Setting": "Настройки Clash",
|
||||
"Allow Lan": "Разрешить локальную сеть",
|
||||
"IPv6": "IPv6",
|
||||
"Log Level": "Уровень логов",
|
||||
"Port Config": "Настройка порта",
|
||||
"Random Port": "Случайный порт",
|
||||
"Restart Application to Apply Modifications": "Чтобы изменения вступили в силу, необходимо перезапустить приложение",
|
||||
"External": "Внешний",
|
||||
"External Controller": "Адрес прослушивания внешнего контроллера",
|
||||
"Core Secret": "Секрет",
|
||||
"Recommended": "Рекомендуется",
|
||||
"Open URL": "Открыть URL",
|
||||
"Replace host, port, secret with %host, %port, %secret": "Замените хост, порт, секрет на %host, %port, %secret",
|
||||
"Support %host, %port, %secret": "Поддержка %host, %port, %secret",
|
||||
"Clash Core": "Ядра Clash",
|
||||
"Grant": "Предоставить",
|
||||
"Upgrade": "Обновлять",
|
||||
"Restart": "Перезапуск",
|
||||
"Tun mode requires": "Требуется Режим туннеля",
|
||||
"Tun Mode": "Режим туннеля",
|
||||
"Service Mode": "Режим сервиса",
|
||||
"Auto Launch": "Автозапуск",
|
||||
"Silent Start": "Тихий запуск",
|
||||
"System Proxy": "Системный прокси",
|
||||
"System Proxy Setting": "Настройка системного прокси",
|
||||
"Grant": "Предоставить",
|
||||
"Open UWP tool": "Открыть UWP инструмент",
|
||||
"Update GeoData": "Обновление GeoData",
|
||||
"Use PAC Mode": "Используйте режим PAC.",
|
||||
"PAC URL": "Адрес PAC",
|
||||
"PAC Script Content": "Содержание сценария PAC",
|
||||
"Proxy Guard": "Защита прокси",
|
||||
"Guard Duration": "Период защиты",
|
||||
"Proxy Bypass": "Игнорирование прокси",
|
||||
"Current System Proxy": "Текущий системный прокси",
|
||||
"Enable status": "Статус включения",
|
||||
"Server Addr": "Адрес сервера",
|
||||
"Bypass": "Игнорирование",
|
||||
|
||||
"Verge Setting": "Настройки Verge",
|
||||
"Language": "Язык",
|
||||
"Theme Mode": "Режим темы",
|
||||
"theme.light": "Светлая",
|
||||
"theme.dark": "Тёмная",
|
||||
"theme.system": "Системная",
|
||||
"Tray Click Event": "Событие щелчка в лотке",
|
||||
"Show Main Window": "Показать главное окно",
|
||||
"Copy Env Type": "Скопировать тип Env",
|
||||
"Start Page": "Главная страница",
|
||||
"Startup Script": "Скрипт запуска",
|
||||
"Browse": "Просмотреть",
|
||||
"Show Main Window": "Показать главное окно",
|
||||
"Theme Setting": "Настройки темы",
|
||||
"Layout Setting": "Настройки раскладки",
|
||||
"Miscellaneous": "Настройки Прочие",
|
||||
"Hotkey Setting": "Настройки клавиатурных сокращений",
|
||||
"Traffic Graph": "График трафика",
|
||||
"Memory Usage": "Использование памяти",
|
||||
"Proxy Group Icon": "Иконка Группы прокси",
|
||||
"Tray Icon": "Иконка лотка",
|
||||
"Menu Icon": "Иконка меню",
|
||||
"Monochrome": "Монохромный",
|
||||
"Colorful": "Полноцветный",
|
||||
"Common Tray Icon": "Общий значок в лотке",
|
||||
"System Proxy Tray Icon": "Значок системного прокси в лотке",
|
||||
"Tun Tray Icon": "Значок туннеля в лотке",
|
||||
"Language": "Язык",
|
||||
"Open App Dir": "Открыть папку приложения",
|
||||
"Open Core Dir": "Открыть папку ядра",
|
||||
"Open Logs Dir": "Открыть папку логов",
|
||||
"Check for Updates": "Проверить обновления",
|
||||
"Open Dev Tools": "Открыть инструменты разработчика",
|
||||
"Verge Version": "Версия Verge",
|
||||
"theme.light": "Светлая",
|
||||
"theme.dark": "Тёмная",
|
||||
"theme.system": "Системная",
|
||||
"Clash Field": "Используемые настройки Clash",
|
||||
"Runtime Config": "Используемый конфиг",
|
||||
"ReadOnly": "Только для чтения",
|
||||
"ReadOnlyMessage": "Невозможно редактировать в режиме только для чтения",
|
||||
"Restart": "Перезапуск",
|
||||
"Upgrade": "Обновлять",
|
||||
|
||||
"Primary Color": "Основной цвет",
|
||||
"Secondary Color": "Вторичный цвет",
|
||||
"Primary Text Color": "Основной текст",
|
||||
@@ -176,82 +192,74 @@
|
||||
"Success Color": "Цвет успеха",
|
||||
"Font Family": "Семейство шрифтов",
|
||||
"CSS Injection": "Внедрение CSS",
|
||||
|
||||
"Back": "Назад",
|
||||
"Save": "Сохранить",
|
||||
"Cancel": "Отмена",
|
||||
"Exit": "Выход",
|
||||
"Confirm": "Подтвердить",
|
||||
|
||||
"Default": "По умолчанию",
|
||||
"Download Speed": "Скорость загрузки",
|
||||
"Upload Speed": "Скорость загрузки",
|
||||
|
||||
"Layout Setting": "Настройки раскладки",
|
||||
"Traffic Graph": "График трафика",
|
||||
"Memory Usage": "Использование памяти",
|
||||
"Proxy Group Icon": "Иконка Группы прокси",
|
||||
"Menu Icon": "Иконка меню",
|
||||
"Monochrome": "Монохромный",
|
||||
"Colorful": "Полноцветный",
|
||||
"Tray Icon": "Иконка лотка",
|
||||
"Common Tray Icon": "Общий значок в лотке",
|
||||
"System Proxy Tray Icon": "Значок системного прокси в лотке",
|
||||
"Tun Tray Icon": "Значок туннеля в лотке",
|
||||
"Miscellaneous": "Настройки Прочие",
|
||||
"App Log Level": "Уровень журнала приложения",
|
||||
"Auto Close Connections": "Автоматическое закрытие соединений",
|
||||
"Auto Check Update": "Автоматическая проверка обновлений",
|
||||
"Enable Builtin Enhanced": "Включить встроенные улучшения",
|
||||
"Proxy Layout Column": "Количество столбцов в макете прокси",
|
||||
"Auto Log Clean": "Автоматическая очистка журналов",
|
||||
"Never Clean": "Никогда не очищать",
|
||||
"Retain 7 Days": "Сохранять 7 дней",
|
||||
"Retain 30 Days": "Сохранять 30 дней",
|
||||
"Retain 90 Days": "Сохранять 90 дней",
|
||||
"Default Latency Test": "Ссылка на тестирование задержки по умолчанию",
|
||||
"Default Latency Timeout": "Таймаут задержки по умолчанию",
|
||||
"Hotkey Setting": "Настройки клавиатурных сокращений",
|
||||
"open_or_close_dashboard": "Открыть/Закрыть панель управления",
|
||||
"clash_mode_rule": "Режим правил",
|
||||
"clash_mode_global": "Глобальный режим",
|
||||
"clash_mode_direct": "Прямой режим",
|
||||
"toggle_system_proxy": "Включить/Отключить системный прокси",
|
||||
"toggle_tun_mode": "Включить/Отключить режим туннеля",
|
||||
|
||||
"App Log Level": "Уровень журнала приложения",
|
||||
"Auto Close Connections": "Автоматическое закрытие соединений",
|
||||
"Auto Check Update": "Автоматическая проверка обновлений",
|
||||
"Enable Builtin Enhanced": "Включить встроенные улучшения",
|
||||
"Proxy Layout Column": "Количество столбцов в макете прокси",
|
||||
"Default Latency Test": "Ссылка на тестирование задержки по умолчанию",
|
||||
"Default Latency Timeout": "Таймаут задержки по умолчанию",
|
||||
|
||||
"Auto Log Clean": "Автоматическая очистка журналов",
|
||||
"Never Clean": "Никогда не очищать",
|
||||
"Retain 7 Days": "Сохранять 7 дней",
|
||||
"Retain 30 Days": "Сохранять 30 дней",
|
||||
"Retain 90 Days": "Сохранять 90 дней",
|
||||
|
||||
"Stack": "Стек",
|
||||
"Device": "Имя устройства",
|
||||
"Auto Route": "Автоматическая маршрутизация",
|
||||
"Strict Route": "Строгий маршрут",
|
||||
"Auto Detect Interface": "Автоопределение интерфейса",
|
||||
"DNS Hijack": "DNS-перехват",
|
||||
"MTU": "Максимальная единица передачи",
|
||||
"Reset to Default": "Сбросить настройки по умолчанию",
|
||||
|
||||
"Current State": "Текущее состояние",
|
||||
"pending": "Ожидающий",
|
||||
"installed": "Установленный",
|
||||
"uninstall": "Не установленный",
|
||||
"active": "Активированный",
|
||||
"unknown": "неизвестный",
|
||||
"Disable Service Mode": "Отключить режим обслуживания",
|
||||
"Install": "Установить",
|
||||
"Uninstall": "Удалить",
|
||||
|
||||
"Runtime Config": "Используемый конфиг",
|
||||
"Open App Dir": "Открыть папку приложения",
|
||||
"Open Core Dir": "Открыть папку ядра",
|
||||
"Open Logs Dir": "Открыть папку логов",
|
||||
"Check for Updates": "Проверить обновления",
|
||||
"Go to Release Page": "Перейти на страницу релизов",
|
||||
"Portable Updater Error": "Портативная версия не поддерживает обновление внутри приложения, пожалуйста, скачайте и замените вручную",
|
||||
"Tun Mode Info": "Режим туннеля требует предоставления разрешений, связанных с ядрам. Пожалуйста, включите сервисный режим перед его использованием",
|
||||
"System and Mixed Can Only be Used in Service Mode": "Система и смешанные могут использоваться только в сервисном режиме",
|
||||
"Information: Please make sure that the Clash Verge Service is installed and enabled": "Информация: Пожалуйста, убедитесь, что сервис Clash Verge Service установлен и включен",
|
||||
"Open Dev Tools": "Открыть инструменты разработчика",
|
||||
"Exit": "Выход",
|
||||
"Verge Version": "Версия Verge",
|
||||
|
||||
"ReadOnly": "Только для чтения",
|
||||
"ReadOnlyMessage": "Невозможно редактировать в режиме только для чтения",
|
||||
"Filter": "Фильтр",
|
||||
"Filter conditions": "Условия фильтрации",
|
||||
"Match Case": "Учитывать регистр",
|
||||
"Match Whole Word": "Полное совпадение слова",
|
||||
"Use Regular Expression": "Использовать регулярные выражения",
|
||||
|
||||
"External Controller Address Modified": "Изменен адрес внешнего контроллера",
|
||||
"Clash Port Modified": "Clash порт изменен",
|
||||
"Currently on the Latest Version": "В настоящее время используется последняя версия",
|
||||
"Only YAML Files Supported": "Поддерживаются только файлы YAML",
|
||||
"Port Conflict": "Конфликт портов",
|
||||
"Proxy Daemon Duration Cannot be Less than 1 Second": "Продолжительность работы прокси-демона не может быть меньше 1 секунды",
|
||||
"Profile Imported Successfully": "Профиль успешно импортирован",
|
||||
"Clash Config Updated": "Clash конфигурация Обновлена",
|
||||
"Profile Switched": "Профиль изменен",
|
||||
"Profile Reactivated": "Профиль повторно активирован",
|
||||
"Clash Config Updated": "Clash конфигурация Обновлена",
|
||||
"Only YAML Files Supported": "Поддерживаются только файлы YAML",
|
||||
"Settings Applied": "Применены настройки",
|
||||
"Service Installed Successfully": "Служба успешно установлена",
|
||||
"Service Uninstalled Successfully": "Служба успешно удалена",
|
||||
"GeoData Updated": "GeoData Обновлена",
|
||||
"Proxy Daemon Duration Cannot be Less than 1 Second": "Продолжительность работы прокси-демона не может быть меньше 1 секунды",
|
||||
"Invalid Bypass Format": "Неверный формат обхода",
|
||||
"Clash Port Modified": "Clash порт изменен",
|
||||
"Port Conflict": "Конфликт портов",
|
||||
"Restart Application to Apply Modifications": "Чтобы изменения вступили в силу, необходимо перезапустить приложение",
|
||||
"External Controller Address Modified": "Изменен адрес внешнего контроллера",
|
||||
"Permissions Granted Successfully for _clash Core": "Разрешения успешно предоставлены для ядра {{core}}",
|
||||
"Profile Imported Successfully": "Профиль успешно импортирован",
|
||||
"Core Version Updated": "Обновлена версия ядра",
|
||||
"Clash Core Restarted": "Clash ядра перезапущено",
|
||||
"Switched to _clash Core": "Переключено на ядра {{core}}",
|
||||
"Core Version Updated": "Обновлена версия ядра"
|
||||
"GeoData Updated": "GeoData Обновлена",
|
||||
"Currently on the Latest Version": "В настоящее время используется последняя версия"
|
||||
}
|
||||
|
||||
+175
-167
@@ -1,60 +1,33 @@
|
||||
{
|
||||
"Back": "返回",
|
||||
"Close": "关闭",
|
||||
"Cancel": "取消",
|
||||
"Confirm": "确认",
|
||||
|
||||
"New": "新建",
|
||||
"Edit": "编辑",
|
||||
"Save": "保存",
|
||||
"Delete": "删除",
|
||||
"Enable": "启用",
|
||||
"Disable": "禁用",
|
||||
|
||||
"Label-Proxies": "代 理",
|
||||
"Label-Test": "测 试",
|
||||
"Label-Profiles": "订 阅",
|
||||
"Label-Connections": "连 接",
|
||||
"Label-Logs": "日 志",
|
||||
"Label-Rules": "规 则",
|
||||
"Label-Logs": "日 志",
|
||||
"Label-Test": "测 试",
|
||||
"Label-Settings": "设 置",
|
||||
|
||||
"Connections": "连接",
|
||||
"Logs": "日志",
|
||||
"Clear": "清除",
|
||||
"Proxies": "代理",
|
||||
"Proxy Groups": "代理组",
|
||||
"Test": "测试",
|
||||
"Proxy Provider": "代理集合",
|
||||
"Update All": "更新全部",
|
||||
"Update At": "更新于",
|
||||
"rule": "规则",
|
||||
"global": "全局",
|
||||
"direct": "直连",
|
||||
"script": "脚本",
|
||||
|
||||
"Create Test": "新建测试",
|
||||
"Edit Test": "编辑测试",
|
||||
"Edit": "编辑",
|
||||
"Icon": "图标",
|
||||
"Test URL": "测试地址",
|
||||
"Test All": "测试全部",
|
||||
|
||||
"Paste": "粘贴",
|
||||
"Profiles": "订阅",
|
||||
"Profile URL": "订阅文件链接",
|
||||
"Import": "导入",
|
||||
"New": "新建",
|
||||
"Create Profile": "新建配置",
|
||||
"Edit Profile": "编辑配置",
|
||||
"Choose File": "选择文件",
|
||||
"Close": "关闭",
|
||||
"Close All": "关闭全部",
|
||||
"Home": "首页",
|
||||
"Select": "使用",
|
||||
"Edit Info": "编辑信息",
|
||||
"Edit File": "编辑文件",
|
||||
"Open File": "打开文件",
|
||||
"Update": "更新",
|
||||
"Update(Proxy)": "更新(代理)",
|
||||
"Delete": "删除",
|
||||
"Enable": "启用",
|
||||
"Disable": "禁用",
|
||||
"Refresh": "刷新",
|
||||
"To Top": "移到最前",
|
||||
"To End": "移到末尾",
|
||||
"Update All Profiles": "更新所有订阅",
|
||||
"View Runtime Config": "查看运行时订阅",
|
||||
"Reactivate Profiles": "重新激活订阅",
|
||||
"Confirm deletion": "确认删除",
|
||||
"This operation is not reversible": "此操作不可逆",
|
||||
"Script Console": "脚本控制台输出",
|
||||
|
||||
"Location": "当前节点",
|
||||
"Delay check": "延迟测试",
|
||||
"Sort by default": "默认排序",
|
||||
@@ -64,13 +37,46 @@
|
||||
"Delay check to cancel fixed": "进行延迟测试,以取消固定",
|
||||
"Proxy basic": "隐藏节点细节",
|
||||
"Proxy detail": "展示节点细节",
|
||||
"Filter": "过滤节点",
|
||||
"Filter conditions": "过滤条件",
|
||||
"Refresh profiles": "刷新订阅",
|
||||
"Rules": "规则",
|
||||
"Update All": "更新全部",
|
||||
"Update At": "更新于",
|
||||
|
||||
"Profiles": "订阅",
|
||||
"Update All Profiles": "更新所有订阅",
|
||||
"View Runtime Config": "查看运行时订阅",
|
||||
"Reactivate Profiles": "重新激活订阅",
|
||||
"Paste": "粘贴",
|
||||
"Profile URL": "订阅文件链接",
|
||||
"Import": "导入",
|
||||
"Create Profile": "新建配置",
|
||||
"Edit Profile": "编辑配置",
|
||||
"Type": "类型",
|
||||
"Name": "名称",
|
||||
"Descriptions": "描述",
|
||||
"Subscription URL": "订阅链接",
|
||||
"Update Interval": "更新间隔",
|
||||
"Choose File": "选择文件",
|
||||
"Use System Proxy": "使用系统代理更新",
|
||||
"Use Clash Proxy": "使用 Clash 代理更新",
|
||||
"Accept Invalid Certs (Danger)": "允许无效证书 (危险)",
|
||||
"Refresh": "刷新",
|
||||
"Home": "首页",
|
||||
"Select": "使用",
|
||||
"Edit Info": "编辑信息",
|
||||
"Edit File": "编辑文件",
|
||||
"Open File": "打开文件",
|
||||
"Update": "更新",
|
||||
"Update(Proxy)": "更新(代理)",
|
||||
"Confirm deletion": "确认删除",
|
||||
"This operation is not reversible": "此操作不可逆",
|
||||
"Script Console": "脚本控制台输出",
|
||||
"To Top": "移到最前",
|
||||
"To End": "移到末尾",
|
||||
|
||||
"Connections": "连接",
|
||||
"Table View": "表格视图",
|
||||
"List View": "列表视图",
|
||||
"Close All": "关闭全部",
|
||||
"Default": "默认",
|
||||
"Download Speed": "下载速度",
|
||||
"Upload Speed": "上传速度",
|
||||
"Host": "主机",
|
||||
"Downloaded": "下载量",
|
||||
"Uploaded": "上传量",
|
||||
@@ -84,88 +90,98 @@
|
||||
"Destination IP": "目标地址",
|
||||
"Close Connection": "关闭连接",
|
||||
|
||||
"Type": "类型",
|
||||
"Name": "名称",
|
||||
"Descriptions": "描述",
|
||||
"Subscription URL": "订阅链接",
|
||||
"Update Interval": "更新间隔",
|
||||
"Use System Proxy": "使用系统代理更新",
|
||||
"Use Clash Proxy": "使用 Clash 代理更新",
|
||||
"Accept Invalid Certs (Danger)": "允许无效证书 (危险)",
|
||||
"Rules": "规则",
|
||||
"Rule Provider": "规则集合",
|
||||
|
||||
"Logs": "日志",
|
||||
"Pause": "暂停",
|
||||
"Clear": "清除",
|
||||
|
||||
"Test": "测试",
|
||||
"Test All": "测试全部",
|
||||
"Create Test": "新建测试",
|
||||
"Edit Test": "编辑测试",
|
||||
"Icon": "图标",
|
||||
"Test URL": "测试地址",
|
||||
|
||||
"Settings": "设置",
|
||||
"Clash Setting": "Clash 设置",
|
||||
"System Setting": "系统设置",
|
||||
"Verge Setting": "Verge 设置",
|
||||
"Tun Mode": "Tun 模式",
|
||||
"Reset to Default": "重置为默认值",
|
||||
"Tun Mode Info": "Tun模式需要授予内核相关权限,使用前请先开启服务模式",
|
||||
"Stack": "Tun 模式堆栈",
|
||||
"System and Mixed Can Only be Used in Service Mode": "System 和 Mixed 只能在服务模式下使用",
|
||||
"Device": "Tun 网卡名称",
|
||||
"Auto Route": "自动设置全局路由",
|
||||
"Strict Route": "严格路由",
|
||||
"Auto Detect Interface": "自动选择流量出口接口",
|
||||
"DNS Hijack": "DNS 劫持",
|
||||
"MTU": "最大传输单元",
|
||||
"Service Mode": "服务模式",
|
||||
"Current State": "当前状态",
|
||||
"pending": "等待中",
|
||||
"installed": "已安装",
|
||||
"uninstall": "未安装",
|
||||
"active": "已激活",
|
||||
"unknown": "未知",
|
||||
"Information: Please make sure that the Clash Verge Service is installed and enabled": "提示信息: 请确保 Clash Verge Service 已安装并启用",
|
||||
"Install": "安装",
|
||||
"Uninstall": "卸载",
|
||||
"Disable Service Mode": "禁用服务模式",
|
||||
"System Proxy": "系统代理",
|
||||
"System Proxy Info": "打开此开关修改操作系统的代理设置,如果开启失败,可手动修改操作系统的代理设置",
|
||||
"System Proxy Setting": "系统代理设置",
|
||||
"Current System Proxy": "当前系统代理",
|
||||
"Enable status": "开启状态:",
|
||||
"Enabled": "已启用",
|
||||
"Disabled": "未启用",
|
||||
"Server Addr": "服务地址:",
|
||||
"Not available": "不可用",
|
||||
"Proxy Guard": "系统代理守卫",
|
||||
"Proxy Guard Info": "开启以防止其他软件修改操作系统的代理设置",
|
||||
"Guard Duration": "代理守卫间隔",
|
||||
"Proxy Bypass": "代理绕过设置:",
|
||||
"Bypass": "当前绕过:",
|
||||
"Use PAC Mode": "使用PAC模式",
|
||||
"PAC Script Content": "PAC脚本内容",
|
||||
"PAC URL": "PAC地址:",
|
||||
"Auto Launch": "开机自启",
|
||||
"Silent Start": "静默启动",
|
||||
|
||||
"Clash Setting": "Clash 设置",
|
||||
"Allow Lan": "局域网连接",
|
||||
"IPv6": "IPv6",
|
||||
"Log Level": "日志等级",
|
||||
"Port Config": "端口设置",
|
||||
"Random Port": "随机端口",
|
||||
"Restart Application to Apply Modifications": "重启应用程序以应用修改",
|
||||
"External": "外部控制",
|
||||
"External Controller": "外部控制器监听地址",
|
||||
"Core Secret": "API 访问密钥",
|
||||
"Recommended": "建议设置",
|
||||
"Open URL": "打开链接",
|
||||
"Replace host, port, secret with %host, %port, %secret": "使用 %host, %port, %secret 表示 主机, 端口, 访问密钥",
|
||||
"Support %host, %port, %secret": "支持 %host, %port, %secret",
|
||||
"Clash Core": "Clash 内核",
|
||||
"Grant": "授权",
|
||||
"Upgrade": "升级内核",
|
||||
"Restart": "重启内核",
|
||||
"Tun mode requires": "如需启用 Tun 模式需要授权",
|
||||
"Tun Mode": "Tun 模式",
|
||||
"Service Mode": "服务模式",
|
||||
"Auto Launch": "开机自启",
|
||||
"Silent Start": "静默启动",
|
||||
"System Proxy": "系统代理",
|
||||
"System Proxy Setting": "系统代理设置",
|
||||
"Grant": "授权",
|
||||
"Open UWP tool": "UWP 工具",
|
||||
"Update GeoData": "更新 GeoData",
|
||||
"Use PAC Mode": "使用PAC模式",
|
||||
"PAC URL": "PAC 地址",
|
||||
"PAC Script Content": "PAC 脚本内容",
|
||||
"Proxy Guard": "系统代理守卫",
|
||||
"Guard Duration": "代理守卫间隔",
|
||||
"Proxy Bypass": "代理绕过",
|
||||
"Current System Proxy": "当前系统代理",
|
||||
"Enable status": "开启状态:",
|
||||
"Server Addr": "服务地址:",
|
||||
"Bypass": "当前绕过:",
|
||||
|
||||
"Verge Setting": "Verge 设置",
|
||||
"Language": "语言设置",
|
||||
"Theme Mode": "主题模式",
|
||||
"theme.light": "浅色",
|
||||
"theme.dark": "深色",
|
||||
"theme.system": "系统",
|
||||
"Tray Click Event": "托盘点击事件",
|
||||
"Show Main Window": "显示主窗口",
|
||||
"Copy Env Type": "复制环境变量类型",
|
||||
"Start Page": "启动页面",
|
||||
"Startup Script": "启动脚本",
|
||||
"Browse": "浏览",
|
||||
"Show Main Window": "显示主窗口",
|
||||
"Theme Setting": "主题设置",
|
||||
"Layout Setting": "界面设置",
|
||||
"Miscellaneous": "杂项设置",
|
||||
"Hotkey Setting": "热键设置",
|
||||
"Traffic Graph": "流量图显",
|
||||
"Memory Usage": "内存使用",
|
||||
"Proxy Group Icon": "代理组图标",
|
||||
"Tray Icon": "托盘图标",
|
||||
"Menu Icon": "菜单图标",
|
||||
"Monochrome": "单色图标",
|
||||
"Colorful": "彩色图标",
|
||||
"Common Tray Icon": "常规托盘图标",
|
||||
"System Proxy Tray Icon": "系统代理托盘图标",
|
||||
"Tun Tray Icon": "Tun 模式托盘图标",
|
||||
"Language": "语言设置",
|
||||
"Open App Dir": "应用目录",
|
||||
"Open Core Dir": "内核目录",
|
||||
"Open Logs Dir": "日志目录",
|
||||
"Check for Updates": "检查更新",
|
||||
"Open Dev Tools": "打开开发者工具",
|
||||
"Verge Version": "Verge 版本",
|
||||
"theme.light": "浅色",
|
||||
"theme.dark": "深色",
|
||||
"theme.system": "系统",
|
||||
"Clash Field": "Clash 字段",
|
||||
"Runtime Config": "当前配置",
|
||||
"ReadOnly": "只读",
|
||||
"ReadOnlyMessage": "无法在只读模式下编辑",
|
||||
"Restart": "重启内核",
|
||||
"Upgrade": "升级内核",
|
||||
|
||||
"Primary Color": "主要颜色",
|
||||
"Secondary Color": "次要颜色",
|
||||
"Primary Text": "文本主要颜色",
|
||||
@@ -176,82 +192,74 @@
|
||||
"Success Color": "成功颜色",
|
||||
"Font Family": "字体系列",
|
||||
"CSS Injection": "CSS 注入",
|
||||
|
||||
"Back": "返回",
|
||||
"Save": "保存",
|
||||
"Cancel": "取消",
|
||||
"Exit": "退出",
|
||||
"Confirm": "确认",
|
||||
|
||||
"Default": "默认",
|
||||
"Download Speed": "下载速度",
|
||||
"Upload Speed": "上传速度",
|
||||
|
||||
"Layout Setting": "界面设置",
|
||||
"Traffic Graph": "流量图显",
|
||||
"Memory Usage": "内存使用",
|
||||
"Proxy Group Icon": "代理组图标",
|
||||
"Menu Icon": "菜单图标",
|
||||
"Monochrome": "单色图标",
|
||||
"Colorful": "彩色图标",
|
||||
"Tray Icon": "托盘图标",
|
||||
"Common Tray Icon": "常规托盘图标",
|
||||
"System Proxy Tray Icon": "系统代理托盘图标",
|
||||
"Tun Tray Icon": "Tun 模式托盘图标",
|
||||
"Miscellaneous": "杂项设置",
|
||||
"App Log Level": "App日志等级",
|
||||
"Auto Close Connections": "自动关闭连接",
|
||||
"Auto Check Update": "自动检查更新",
|
||||
"Enable Builtin Enhanced": "内置增强功能",
|
||||
"Proxy Layout Column": "代理页布局列数",
|
||||
"Auto Log Clean": "自动清理日志",
|
||||
"Never Clean": "不清理",
|
||||
"Retain 7 Days": "保留7天",
|
||||
"Retain 30 Days": "保留30天",
|
||||
"Retain 90 Days": "保留90天",
|
||||
"Default Latency Test": "默认测试链接",
|
||||
"Default Latency Timeout": "测试超时时间",
|
||||
"Hotkey Setting": "热键设置",
|
||||
"open_or_close_dashboard": "打开/关闭面板",
|
||||
"clash_mode_rule": "规则模式",
|
||||
"clash_mode_global": "全局模式",
|
||||
"clash_mode_direct": "直连模式",
|
||||
"toggle_system_proxy": "打开/关闭系统代理",
|
||||
"toggle_tun_mode": "打开/关闭 Tun 模式",
|
||||
|
||||
"App Log Level": "App日志等级",
|
||||
"Auto Close Connections": "自动关闭连接",
|
||||
"Auto Check Update": "自动检查更新",
|
||||
"Enable Builtin Enhanced": "开启内建增强功能",
|
||||
"Proxy Layout Column": "代理页布局列数",
|
||||
"Default Latency Test": "默认测试链接",
|
||||
"Default Latency Timeout": "测试超时时间",
|
||||
|
||||
"Auto Log Clean": "自动清理日志",
|
||||
"Never Clean": "不清理",
|
||||
"Retain 7 Days": "保留7天",
|
||||
"Retain 30 Days": "保留30天",
|
||||
"Retain 90 Days": "保留90天",
|
||||
|
||||
"Stack": "Tun 模式堆栈",
|
||||
"Device": "Tun 网卡名称",
|
||||
"Auto Route": "自动设置全局路由",
|
||||
"Strict Route": "严格路由",
|
||||
"Auto Detect Interface": "自动选择流量出口接口",
|
||||
"DNS Hijack": "DNS 劫持",
|
||||
"MTU": "最大传输单元",
|
||||
"Reset to Default": "重置为默认值",
|
||||
|
||||
"Current State": "当前状态",
|
||||
"pending": "等待中",
|
||||
"installed": "已安装",
|
||||
"uninstall": "未安装",
|
||||
"active": "已激活",
|
||||
"unknown": "未知",
|
||||
"Disable Service Mode": "禁用服务模式",
|
||||
"Install": "安装",
|
||||
"Uninstall": "卸载",
|
||||
|
||||
"Runtime Config": "当前配置",
|
||||
"Open App Dir": "应用目录",
|
||||
"Open Core Dir": "内核目录",
|
||||
"Open Logs Dir": "日志目录",
|
||||
"Check for Updates": "检查更新",
|
||||
"Go to Release Page": "前往发布页",
|
||||
"Portable Updater Error": "便携版不支持应用内更新,请手动下载替换",
|
||||
"Tun Mode Info": "Tun模式需要授予内核相关权限,使用前请先开启服务模式",
|
||||
"System and Mixed Can Only be Used in Service Mode": "System 和 Mixed 只能在服务模式下使用",
|
||||
"Information: Please make sure that the Clash Verge Service is installed and enabled": "提示信息: 请确保 Clash Verge Service 已安装并启用",
|
||||
"Open Dev Tools": "打开开发者工具",
|
||||
"Exit": "退出",
|
||||
"Verge Version": "Verge 版本",
|
||||
|
||||
"ReadOnly": "只读",
|
||||
"ReadOnlyMessage": "无法在只读模式下编辑",
|
||||
"Filter": "过滤节点",
|
||||
"Filter conditions": "过滤条件",
|
||||
"Match Case": "区分大小写",
|
||||
"Match Whole Word": "全字匹配",
|
||||
"Use Regular Expression": "使用正则表达式",
|
||||
|
||||
"External Controller Address Modified": "外部控制器监听地址已修改",
|
||||
"Clash Port Modified": "Clash 端口已修改",
|
||||
"Currently on the Latest Version": "当前已是最新版本",
|
||||
"Only YAML Files Supported": "仅支持 YAML 文件",
|
||||
"Port Conflict": "端口冲突",
|
||||
"Proxy Daemon Duration Cannot be Less than 1 Second": "代理守护间隔时间不得低于1秒",
|
||||
"Profile Imported Successfully": "导入订阅成功",
|
||||
"Clash Config Updated": "Clash 配置已更新",
|
||||
"Profile Switched": "订阅已切换",
|
||||
"Profile Reactivated": "订阅已激活",
|
||||
"Clash Config Updated": "Clash 配置已更新",
|
||||
"Only YAML Files Supported": "仅支持 YAML 文件",
|
||||
"Settings Applied": "设置已应用",
|
||||
"Service Installed Successfully": "已成功安装服务",
|
||||
"Service Uninstalled Successfully": "已成功卸载服务",
|
||||
"GeoData Updated": "已更新 GeoData",
|
||||
"Proxy Daemon Duration Cannot be Less than 1 Second": "代理守护间隔时间不得低于1秒",
|
||||
"Invalid Bypass Format": "无效的代理绕过格式",
|
||||
"Clash Port Modified": "Clash 端口已修改",
|
||||
"Port Conflict": "端口冲突",
|
||||
"Restart Application to Apply Modifications": "重启应用程序以应用修改",
|
||||
"External Controller Address Modified": "外部控制器监听地址已修改",
|
||||
"Permissions Granted Successfully for _clash Core": "{{core}} 内核授权成功",
|
||||
"Profile Imported Successfully": "导入订阅成功",
|
||||
"Core Version Updated": "内核版本已更新",
|
||||
"Clash Core Restarted": "已重启 Clash 内核",
|
||||
"Switched to _clash Core": "已切换至 {{core}} 内核",
|
||||
"Core Version Updated": "内核版本已更新"
|
||||
"GeoData Updated": "已更新 GeoData",
|
||||
"Currently on the Latest Version": "当前已是最新版本"
|
||||
}
|
||||
|
||||
+17
-4
@@ -9,11 +9,17 @@ if (!window.ResizeObserver) {
|
||||
|
||||
import React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { ComposeContextProvider } from "foxact/compose-context-provider";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import { BaseErrorBoundary } from "./components/base";
|
||||
import Layout from "./pages/_layout";
|
||||
import "./services/i18n";
|
||||
import {
|
||||
LoadingCacheProvider,
|
||||
LogDataProvider,
|
||||
ThemeModeProvider,
|
||||
UpdateStateProvider,
|
||||
} from "./services/states";
|
||||
|
||||
const mainElementId = "root";
|
||||
const container = document.getElementById(mainElementId);
|
||||
@@ -31,20 +37,27 @@ document.addEventListener("keydown", (event) => {
|
||||
}
|
||||
if (
|
||||
(event.ctrlKey || event.metaKey) &&
|
||||
["F", "H", "P", "R", "U"].includes(event.key.toUpperCase())
|
||||
["F", "H", "P", "Q", "R", "U"].includes(event.key.toUpperCase())
|
||||
) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
const contexts = [
|
||||
<ThemeModeProvider />,
|
||||
<LogDataProvider />,
|
||||
<LoadingCacheProvider />,
|
||||
<UpdateStateProvider />,
|
||||
];
|
||||
|
||||
createRoot(container).render(
|
||||
<React.StrictMode>
|
||||
<RecoilRoot>
|
||||
<ComposeContextProvider contexts={contexts}>
|
||||
<BaseErrorBoundary>
|
||||
<BrowserRouter>
|
||||
<Layout />
|
||||
</BrowserRouter>
|
||||
</BaseErrorBoundary>
|
||||
</RecoilRoot>
|
||||
</ComposeContextProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
@@ -14,8 +14,7 @@ import { useVerge } from "@/hooks/use-verge";
|
||||
import LogoSvg from "@/assets/image/logo.svg?react";
|
||||
import iconLight from "@/assets/image/icon_light.svg?react";
|
||||
import iconDark from "@/assets/image/icon_dark.svg?react";
|
||||
import { atomThemeMode } from "@/services/states";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { useThemeMode } from "@/services/states";
|
||||
import { Notice } from "@/components/base";
|
||||
import { LayoutItem } from "@/components/layout/layout-item";
|
||||
import { LayoutControl } from "@/components/layout/layout-control";
|
||||
@@ -36,7 +35,7 @@ dayjs.extend(relativeTime);
|
||||
const OS = getSystem();
|
||||
|
||||
const Layout = () => {
|
||||
const [mode] = useRecoilState(atomThemeMode);
|
||||
const mode = useThemeMode();
|
||||
const isDark = mode === "light" ? false : true;
|
||||
const { t } = useTranslation();
|
||||
const { theme } = useCustomTheme();
|
||||
|
||||
@@ -4,14 +4,14 @@ const OS = getSystem();
|
||||
// default theme setting
|
||||
export const defaultTheme = {
|
||||
primary_color: "#007AFF",
|
||||
secondary_color: "#fc9b76",
|
||||
secondary_color: "#FC9B76",
|
||||
primary_text: "#000000",
|
||||
secondary_text: "#3c3c4399",
|
||||
secondary_text: "#3C3C4399",
|
||||
info_color: "#007AFF",
|
||||
error_color: "#FF3B30",
|
||||
warning_color: "#FF9500",
|
||||
success_color: "#06943D",
|
||||
background_color: "#f5f5f5",
|
||||
background_color: "#F5F5F5",
|
||||
font_family: `-apple-system, BlinkMacSystemFont,"Microsoft YaHei UI", "Microsoft YaHei", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji"${
|
||||
OS === "windows" ? ", twemoji mozilla" : ""
|
||||
}`,
|
||||
@@ -22,9 +22,9 @@ export const defaultDarkTheme = {
|
||||
...defaultTheme,
|
||||
primary_color: "#0A84FF",
|
||||
secondary_color: "#FF9F0A",
|
||||
primary_text: "#ffffff",
|
||||
background_color: "#2e303d",
|
||||
secondary_text: "#ebebf599",
|
||||
primary_text: "#FFFFFF",
|
||||
background_color: "#2E303D",
|
||||
secondary_text: "#EBEBF599",
|
||||
info_color: "#0A84FF",
|
||||
error_color: "#FF453A",
|
||||
warning_color: "#FF9F0A",
|
||||
|
||||
+14
-19
@@ -1,20 +1,11 @@
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
IconButton,
|
||||
MenuItem,
|
||||
Select,
|
||||
SelectProps,
|
||||
styled,
|
||||
} from "@mui/material";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { Box, Button, IconButton, MenuItem } from "@mui/material";
|
||||
import { Virtuoso } from "react-virtuoso";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TableChartRounded, TableRowsRounded } from "@mui/icons-material";
|
||||
import { closeAllConnections } from "@/services/api";
|
||||
import { atomConnectionSetting } from "@/services/states";
|
||||
import { useConnectionSetting } from "@/services/states";
|
||||
import { useClashInfo } from "@/hooks/use-clash";
|
||||
import { BaseEmpty, BasePage } from "@/components/base";
|
||||
import { useWebsocket } from "@/hooks/use-websocket";
|
||||
@@ -34,7 +25,7 @@ const initConn = { uploadTotal: 0, downloadTotal: 0, connections: [] };
|
||||
type OrderFunc = (list: IConnectionsItem[]) => IConnectionsItem[];
|
||||
|
||||
const ConnectionsPage = () => {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
const { clashInfo } = useClashInfo();
|
||||
const { theme } = useCustomTheme();
|
||||
const isDark = theme.palette.mode === "dark";
|
||||
@@ -42,7 +33,7 @@ const ConnectionsPage = () => {
|
||||
const [curOrderOpt, setOrderOpt] = useState("Default");
|
||||
const [connData, setConnData] = useState<IConnections>(initConn);
|
||||
|
||||
const [setting, setSetting] = useRecoilState(atomConnectionSetting);
|
||||
const [setting, setSetting] = useConnectionSetting();
|
||||
|
||||
const isTableLayout = setting.layout === "table";
|
||||
|
||||
@@ -130,7 +121,7 @@ const ConnectionsPage = () => {
|
||||
return (
|
||||
<BasePage
|
||||
full
|
||||
title={t("Connections")}
|
||||
title={<span style={{ whiteSpace: "nowrap" }}>{t("Connections")}</span>}
|
||||
contentStyle={{ height: "100%" }}
|
||||
header={
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
|
||||
@@ -145,21 +136,25 @@ const ConnectionsPage = () => {
|
||||
size="small"
|
||||
onClick={() =>
|
||||
setSetting((o) =>
|
||||
o.layout === "list"
|
||||
o?.layout !== "table"
|
||||
? { ...o, layout: "table" }
|
||||
: { ...o, layout: "list" }
|
||||
)
|
||||
}
|
||||
>
|
||||
{isTableLayout ? (
|
||||
<TableChartRounded fontSize="inherit" />
|
||||
<span title={t("List View")}>
|
||||
<TableRowsRounded fontSize="inherit" />
|
||||
</span>
|
||||
) : (
|
||||
<TableRowsRounded fontSize="inherit" />
|
||||
<span title={t("Table View")}>
|
||||
<TableChartRounded fontSize="inherit" />
|
||||
</span>
|
||||
)}
|
||||
</IconButton>
|
||||
|
||||
<Button size="small" variant="contained" onClick={onCloseAll}>
|
||||
{t("Close All")}
|
||||
<span style={{ whiteSpace: "nowrap" }}>{t("Close All")}</span>
|
||||
</Button>
|
||||
</Box>
|
||||
}
|
||||
@@ -209,7 +204,7 @@ const ConnectionsPage = () => {
|
||||
) : (
|
||||
<Virtuoso
|
||||
data={filterConn}
|
||||
itemContent={(index, item) => (
|
||||
itemContent={(_, item) => (
|
||||
<ConnectionItem
|
||||
value={item}
|
||||
onShowDetail={() => detailRef.current?.open(item)}
|
||||
|
||||
+5
-4
@@ -1,5 +1,4 @@
|
||||
import { useMemo, useState } from "react";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { Box, Button, IconButton, MenuItem } from "@mui/material";
|
||||
import { Virtuoso } from "react-virtuoso";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -7,7 +6,7 @@ import {
|
||||
PlayCircleOutlineRounded,
|
||||
PauseCircleOutlineRounded,
|
||||
} from "@mui/icons-material";
|
||||
import { atomEnableLog, atomLogData } from "@/services/states";
|
||||
import { useEnableLog, useLogData, useSetLogData } from "@/services/states";
|
||||
import { BaseEmpty, BasePage } from "@/components/base";
|
||||
import LogItem from "@/components/log/log-item";
|
||||
import { useCustomTheme } from "@/components/layout/use-custom-theme";
|
||||
@@ -16,8 +15,9 @@ import { BaseStyledSelect } from "@/components/base/base-styled-select";
|
||||
|
||||
const LogPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const [logData, setLogData] = useRecoilState(atomLogData);
|
||||
const [enableLog, setEnableLog] = useRecoilState(atomEnableLog);
|
||||
const logData = useLogData();
|
||||
const setLogData = useSetLogData();
|
||||
const [enableLog, setEnableLog] = useEnableLog();
|
||||
const { theme } = useCustomTheme();
|
||||
const isDark = theme.palette.mode === "dark";
|
||||
const [logState, setLogState] = useState("all");
|
||||
@@ -39,6 +39,7 @@ const LogPage = () => {
|
||||
header={
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
|
||||
<IconButton
|
||||
title={t("Pause")}
|
||||
size="small"
|
||||
color="inherit"
|
||||
onClick={() => setEnableLog((e) => !e)}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import useSWR, { mutate } from "swr";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useSetRecoilState } from "recoil";
|
||||
import { Box, Button, Grid, IconButton, Stack, Divider } from "@mui/material";
|
||||
import {
|
||||
DndContext,
|
||||
@@ -35,7 +34,7 @@ import {
|
||||
reorderProfile,
|
||||
createProfile,
|
||||
} from "@/services/cmds";
|
||||
import { atomLoadingCache } from "@/services/states";
|
||||
import { useSetLoadingCache, useThemeMode } from "@/services/states";
|
||||
import { closeAllConnections } from "@/services/api";
|
||||
import { BasePage, DialogRef, Notice } from "@/components/base";
|
||||
import {
|
||||
@@ -47,8 +46,6 @@ import { ProfileMore } from "@/components/profile/profile-more";
|
||||
import { useProfiles } from "@/hooks/use-profiles";
|
||||
import { ConfigViewer } from "@/components/setting/mods/config-viewer";
|
||||
import { throttle } from "lodash-es";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { atomThemeMode } from "@/services/states";
|
||||
import { BaseStyledTextField } from "@/components/base/base-styled-text-field";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { readTextFile } from "@tauri-apps/api/fs";
|
||||
@@ -239,7 +236,7 @@ const ProfilePage = () => {
|
||||
});
|
||||
|
||||
// 更新所有订阅
|
||||
const setLoadingCache = useSetRecoilState(atomLoadingCache);
|
||||
const setLoadingCache = useSetLoadingCache();
|
||||
const onUpdateAll = useLockFn(async () => {
|
||||
const throttleMutate = throttle(mutateProfiles, 2000, {
|
||||
trailing: true,
|
||||
@@ -271,7 +268,7 @@ const ProfilePage = () => {
|
||||
const text = await readText();
|
||||
if (text) setUrl(text);
|
||||
};
|
||||
const [mode] = useRecoilState(atomThemeMode);
|
||||
const mode = useThemeMode();
|
||||
const islight = mode === "light" ? true : false;
|
||||
const dividercolor = islight
|
||||
? "rgba(0, 0, 0, 0.06)"
|
||||
|
||||
@@ -7,8 +7,7 @@ import { openWebUrl } from "@/services/cmds";
|
||||
import SettingVerge from "@/components/setting/setting-verge";
|
||||
import SettingClash from "@/components/setting/setting-clash";
|
||||
import SettingSystem from "@/components/setting/setting-system";
|
||||
import { atomThemeMode } from "@/services/states";
|
||||
import { useRecoilState } from "recoil";
|
||||
import { useThemeMode } from "@/services/states";
|
||||
|
||||
const SettingPage = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -25,7 +24,7 @@ const SettingPage = () => {
|
||||
return openWebUrl("https://clash-verge-rev.github.io/guide/log.html");
|
||||
});
|
||||
|
||||
const [mode] = useRecoilState(atomThemeMode);
|
||||
const mode = useThemeMode();
|
||||
const isDark = mode === "light" ? false : true;
|
||||
|
||||
return (
|
||||
|
||||
+15
-3
@@ -22,6 +22,12 @@ import { TestItem } from "@/components/test/test-item";
|
||||
import { emit } from "@tauri-apps/api/event";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
// test icons
|
||||
import apple from "@/assets/image/test/apple.svg?raw";
|
||||
import github from "@/assets/image/test/github.svg?raw";
|
||||
import google from "@/assets/image/test/google.svg?raw";
|
||||
import youtube from "@/assets/image/test/youtube.svg?raw";
|
||||
|
||||
const TestPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const sensors = useSensors(
|
||||
@@ -38,19 +44,25 @@ const TestPage = () => {
|
||||
uid: nanoid(),
|
||||
name: "Apple",
|
||||
url: "https://www.apple.com",
|
||||
icon: "https://www.apple.com/favicon.ico",
|
||||
icon: apple,
|
||||
},
|
||||
{
|
||||
uid: nanoid(),
|
||||
name: "GitHub",
|
||||
url: "https://www.github.com",
|
||||
icon: `<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#000000"/></svg>`,
|
||||
icon: github,
|
||||
},
|
||||
{
|
||||
uid: nanoid(),
|
||||
name: "Google",
|
||||
url: "https://www.google.com",
|
||||
icon: `<svg enable-background="new 0 0 48 48" height="48" viewBox="0 0 48 48" width="48" xmlns="http://www.w3.org/2000/svg"><path d="m43.611 20.083h-1.611v-.083h-18v8h11.303c-1.649 4.657-6.08 8-11.303 8-6.627 0-12-5.373-12-12s5.373-12 12-12c3.059 0 5.842 1.154 7.961 3.039l5.657-5.657c-3.572-3.329-8.35-5.382-13.618-5.382-11.045 0-20 8.955-20 20s8.955 20 20 20 20-8.955 20-20c0-1.341-.138-2.65-.389-3.917z" fill="#ffc107"/><path d="m6.306 14.691 6.571 4.819c1.778-4.402 6.084-7.51 11.123-7.51 3.059 0 5.842 1.154 7.961 3.039l5.657-5.657c-3.572-3.329-8.35-5.382-13.618-5.382-7.682 0-14.344 4.337-17.694 10.691z" fill="#ff3d00"/><path d="m24 44c5.166 0 9.86-1.977 13.409-5.192l-6.19-5.238c-2.008 1.521-4.504 2.43-7.219 2.43-5.202 0-9.619-3.317-11.283-7.946l-6.522 5.025c3.31 6.477 10.032 10.921 17.805 10.921z" fill="#4caf50"/><path d="m43.611 20.083h-1.611v-.083h-18v8h11.303c-.792 2.237-2.231 4.166-4.087 5.571.001-.001.002-.001.003-.002l6.19 5.238c-.438.398 6.591-4.807 6.591-14.807 0-1.341-.138-2.65-.389-3.917z" fill="#1976d2"/></svg>`,
|
||||
icon: google,
|
||||
},
|
||||
{
|
||||
uid: nanoid(),
|
||||
name: "Youtube",
|
||||
url: "https://www.youtube.com",
|
||||
icon: youtube,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
(function () {
|
||||
if (typeof window.RegExp === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
const originalRegExp = window.RegExp;
|
||||
|
||||
window.RegExp = function (pattern, flags) {
|
||||
if (pattern instanceof originalRegExp && flags === undefined) {
|
||||
flags = pattern.flags;
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
if (!originalRegExp.prototype.hasOwnProperty("unicodeSets")) {
|
||||
if (flags.includes("v")) {
|
||||
flags = flags.replace("v", "u");
|
||||
}
|
||||
}
|
||||
|
||||
if (!originalRegExp.prototype.hasOwnProperty("hasIndices")) {
|
||||
if (flags.includes("d")) {
|
||||
flags = flags.replace("d", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new originalRegExp(pattern, flags);
|
||||
};
|
||||
window.RegExp.prototype = originalRegExp.prototype;
|
||||
})();
|
||||
@@ -0,0 +1,16 @@
|
||||
(function () {
|
||||
if (typeof window.WeakRef !== "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
window.WeakRef = (function (weakMap) {
|
||||
function WeakRef(target) {
|
||||
weakMap.set(this, target);
|
||||
}
|
||||
WeakRef.prototype.deref = function () {
|
||||
return weakMap.get(this);
|
||||
};
|
||||
|
||||
return WeakRef;
|
||||
})(new WeakMap());
|
||||
})();
|
||||
@@ -0,0 +1,36 @@
|
||||
(function () {
|
||||
if (window.matchMedia && window.matchMedia("all").addEventListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
const originalMatchMedia = window.matchMedia;
|
||||
|
||||
window.matchMedia = function (query) {
|
||||
const mediaQueryList = originalMatchMedia(query);
|
||||
|
||||
if (!mediaQueryList.addEventListener) {
|
||||
mediaQueryList.addEventListener = function (eventType, listener) {
|
||||
if (eventType !== "change" || typeof listener !== "function") {
|
||||
console.error("Invalid arguments for addEventListener:", arguments);
|
||||
return;
|
||||
}
|
||||
mediaQueryList.addListener(listener);
|
||||
};
|
||||
}
|
||||
|
||||
if (!mediaQueryList.removeEventListener) {
|
||||
mediaQueryList.removeEventListener = function (eventType, listener) {
|
||||
if (eventType !== "change" || typeof listener !== "function") {
|
||||
console.error(
|
||||
"Invalid arguments for removeEventListener:",
|
||||
arguments
|
||||
);
|
||||
return;
|
||||
}
|
||||
mediaQueryList.removeListener(listener);
|
||||
};
|
||||
}
|
||||
|
||||
return mediaQueryList;
|
||||
};
|
||||
})();
|
||||
@@ -1,4 +1,3 @@
|
||||
import axiosTauriApiAdapter from "axios-tauri-api-adapter";
|
||||
import axios, { AxiosInstance } from "axios";
|
||||
import { getClashInfo } from "./cmds";
|
||||
|
||||
@@ -26,7 +25,6 @@ export const getAxios = async (force: boolean = false) => {
|
||||
} catch {}
|
||||
|
||||
axiosIns = axios.create({
|
||||
adapter: axiosTauriApiAdapter,
|
||||
baseURL: `http://${server}`,
|
||||
headers: secret ? { Authorization: `Bearer ${secret}` } : {},
|
||||
timeout: 15000,
|
||||
|
||||
+38
-60
@@ -1,73 +1,51 @@
|
||||
import { atom } from "recoil";
|
||||
import { createContextState } from "foxact/create-context-state";
|
||||
import { useLocalStorage } from "foxact/use-local-storage";
|
||||
|
||||
export const atomThemeMode = atom<"light" | "dark">({
|
||||
key: "atomThemeMode",
|
||||
default: "light",
|
||||
});
|
||||
const [ThemeModeProvider, useThemeMode, useSetThemeMode] = createContextState<
|
||||
"light" | "dark"
|
||||
>("light");
|
||||
|
||||
export const atomLogData = atom<ILogItem[]>({
|
||||
key: "atomLogData",
|
||||
default: [],
|
||||
});
|
||||
const [LogDataProvider, useLogData, useSetLogData] = createContextState<
|
||||
ILogItem[]
|
||||
>([]);
|
||||
|
||||
export const atomEnableLog = atom<boolean>({
|
||||
key: "atomEnableLog",
|
||||
effects: [
|
||||
({ setSelf, onSet }) => {
|
||||
const key = "enable-log";
|
||||
|
||||
try {
|
||||
setSelf(localStorage.getItem(key) !== "false");
|
||||
} catch {}
|
||||
|
||||
onSet((newValue, _, isReset) => {
|
||||
try {
|
||||
if (isReset) {
|
||||
localStorage.removeItem(key);
|
||||
} else {
|
||||
localStorage.setItem(key, newValue.toString());
|
||||
}
|
||||
} catch {}
|
||||
});
|
||||
},
|
||||
],
|
||||
});
|
||||
export const useEnableLog = () => useLocalStorage("enable-log", true);
|
||||
|
||||
interface IConnectionSetting {
|
||||
layout: "table" | "list";
|
||||
}
|
||||
|
||||
export const atomConnectionSetting = atom<IConnectionSetting>({
|
||||
key: "atomConnectionSetting",
|
||||
effects: [
|
||||
({ setSelf, onSet }) => {
|
||||
const key = "connections-setting";
|
||||
const defaultConnectionSetting: IConnectionSetting = { layout: "table" };
|
||||
|
||||
try {
|
||||
const value = localStorage.getItem(key);
|
||||
const data = value == null ? { layout: "table" } : JSON.parse(value);
|
||||
setSelf(data);
|
||||
} catch {
|
||||
setSelf({ layout: "table" });
|
||||
}
|
||||
|
||||
onSet((newValue) => {
|
||||
try {
|
||||
localStorage.setItem(key, JSON.stringify(newValue));
|
||||
} catch {}
|
||||
});
|
||||
},
|
||||
],
|
||||
});
|
||||
export const useConnectionSetting = () =>
|
||||
useLocalStorage<IConnectionSetting>(
|
||||
"connections-setting",
|
||||
defaultConnectionSetting,
|
||||
{
|
||||
serializer: JSON.stringify,
|
||||
deserializer: JSON.parse,
|
||||
}
|
||||
);
|
||||
|
||||
// save the state of each profile item loading
|
||||
export const atomLoadingCache = atom<Record<string, boolean>>({
|
||||
key: "atomLoadingCache",
|
||||
default: {},
|
||||
});
|
||||
const [LoadingCacheProvider, useLoadingCache, useSetLoadingCache] =
|
||||
createContextState<Record<string, boolean>>({});
|
||||
|
||||
// save update state
|
||||
export const atomUpdateState = atom<boolean>({
|
||||
key: "atomUpdateState",
|
||||
default: false,
|
||||
});
|
||||
const [UpdateStateProvider, useUpdateState, useSetUpdateState] =
|
||||
createContextState<boolean>(false);
|
||||
|
||||
export {
|
||||
ThemeModeProvider,
|
||||
useThemeMode,
|
||||
useSetThemeMode,
|
||||
LogDataProvider,
|
||||
useLogData,
|
||||
useSetLogData,
|
||||
LoadingCacheProvider,
|
||||
useLoadingCache,
|
||||
useSetLoadingCache,
|
||||
UpdateStateProvider,
|
||||
useUpdateState,
|
||||
useSetUpdateState,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export default function isAsyncFunction(fn: Function): boolean {
|
||||
return fn.constructor.name === "AsyncFunction";
|
||||
}
|
||||
+13
-1
@@ -2,15 +2,27 @@ import { defineConfig } from "vite";
|
||||
import path from "path";
|
||||
import svgr from "vite-plugin-svgr";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import legacy from "@vitejs/plugin-legacy";
|
||||
import monacoEditor from "vite-plugin-monaco-editor";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
root: "src",
|
||||
server: { port: 3000 },
|
||||
plugins: [
|
||||
svgr(),
|
||||
react(),
|
||||
legacy({
|
||||
renderLegacyChunks: false,
|
||||
modernTargets: ["edge>=109", "safari>=13"],
|
||||
modernPolyfills: true,
|
||||
additionalModernPolyfills: [
|
||||
"core-js/modules/es.object.has-own.js",
|
||||
"core-js/modules/web.structured-clone.js",
|
||||
path.resolve("./src/polyfills/matchMedia.js"),
|
||||
path.resolve("./src/polyfills/WeakRef.js"),
|
||||
path.resolve("./src/polyfills/RegExp.js"),
|
||||
],
|
||||
}),
|
||||
monacoEditor({
|
||||
languageWorkers: ["editorWorkerService", "typescript", "css"],
|
||||
customWorkers: [
|
||||
|
||||
Reference in New Issue
Block a user