Compare commits

..

131 Commits
7.3.0 ... 7.6.1

Author SHA1 Message Date
2dust
6b4076be10 up 7.6.1 2025-01-12 19:36:19 +08:00
alphax-hue3682
d7a04a15ae Update Persian translate (#6487) 2025-01-12 19:33:57 +08:00
2dust
2ae43f8bdb Revert "Remove rules custom Icon"
This reverts commit d3ebc17a10.
2025-01-12 19:33:23 +08:00
2dust
d3ebc17a10 Remove rules custom Icon 2025-01-12 14:35:59 +08:00
2dust
7a8680711e Improvements and Adjustments 2025-01-12 14:30:49 +08:00
2dust
649e89e7af Added Copy Terminal proxy command to clipboard in tray menu
https://github.com/2dust/v2rayN/issues/6482
2025-01-12 11:07:34 +08:00
2dust
cb94d64395 Bug fix 2025-01-11 19:35:32 +08:00
2dust
2440dc2440 Remove deprecated DefIEProxyExceptions 2025-01-11 19:34:04 +08:00
Little丶Dreams
364a24c580 CloneServerStatItem 时检查indexId和toIndexId是否相同 (#6478) 2025-01-11 14:44:09 +08:00
2dust
8f3e0dbd82 up 7.6.0 2025-01-11 11:48:57 +08:00
alphax-hue3682
596234df26 Update Persian translate (#6465)
* Update ResUI.fa-Ir.resx

e0ae101ff4

* Update ResUI.fa-Ir.resx
2025-01-11 11:30:06 +08:00
2dust
c38aec50dc Delete unused resources 2025-01-11 11:28:35 +08:00
2dust
40915b5f98 Adjust theme options for windows 2025-01-11 11:23:40 +08:00
2dust
a176613119 Bug fix for ProcUtils 2025-01-11 10:44:34 +08:00
2dust
6c6de1ae7f Improvements and Adjustments 2025-01-10 20:12:42 +08:00
2dust
edbd168dcf Add theme options for desktop 2025-01-10 15:53:06 +08:00
2dust
127858d582 Adjust UI for desktop 2025-01-10 14:23:03 +08:00
2dust
baf90cfbdd Sing-box cache file specified path
https://github.com/2dust/v2rayN/issues/6460
2025-01-10 10:00:00 +08:00
2dust
1a5eeb9401 Adjust UI for desktop 2025-01-09 21:03:17 +08:00
2dust
e0ae101ff4 Adjust UI for desktop 2025-01-09 15:14:03 +08:00
Long Yixing
8b4a07dfe8 Modify the macos build script (#6461)
No longer generate AppIcon.icns
2025-01-09 10:21:07 +08:00
2dust
db934e70cb The icon of the system proxy can be customized
https://github.com/2dust/v2rayN/issues/6459
2025-01-08 20:35:33 +08:00
2dust
b770048f05 The exported routing rules are compatible with the import function of v2rayNG 2025-01-08 17:57:23 +08:00
2dust
27c53be209 up 7.5.6 2025-01-08 14:16:30 +08:00
2dust
d93c12b354 Add more options to xray fragment 2025-01-08 13:52:21 +08:00
2dust
98d4a47efb Fix Mux for XUDP
https://github.com/2dust/v2rayN/issues/6446
2025-01-07 20:16:05 +08:00
2dust
8ab04c65b5 Update README.md 2025-01-07 14:33:15 +08:00
2dust
1b2dab1388 Bug fix
https://github.com/2dust/v2rayN/issues/6448
2025-01-07 11:28:46 +08:00
2dust
4f8dae7fa0 Add the mixed option in Stack in Tun mode settings
https://github.com/2dust/v2rayN/issues/6441
2025-01-06 20:46:07 +08:00
Harry Huang
cdc23e32c4 Fix zh-Hans and zh-Hant translation style (#6443)
* Fix zh-Hans i10n translation style

* Fix zh-Hant i10n translation style
2025-01-06 19:05:43 +08:00
2dust
20457e9e63 up 7.5.5 2025-01-05 19:10:57 +08:00
2dust
e63042af84 Bug fix for fontsize 2025-01-05 19:10:12 +08:00
2dust
c35b4d3c1b up 7.5.4 2025-01-05 17:58:55 +08:00
2dust
64a83a5d64 down PackageReference 2025-01-05 17:58:23 +08:00
2dust
01039d0b47 up 7.5.3 2025-01-05 17:31:32 +08:00
2dust
7c1e5a3cba Fixed possible crash issues 2025-01-05 17:12:51 +08:00
2dust
038161527f Buf fix for CurrentFontSize 2025-01-05 17:11:32 +08:00
2dust
b12b7a17e6 Fix possible issues with load balancing 2025-01-05 16:31:32 +08:00
2dust
37cf23d5fe up PackageReference 2025-01-05 15:01:15 +08:00
2dust
ed7fb4f6e3 Code clean 2025-01-05 14:50:31 +08:00
2dust
5d4bd2fee6 Fix possible issues with load balancing
https://github.com/2dust/v2rayN/issues/6429
2025-01-05 14:49:53 +08:00
2dust
aae5906311 Fix GetListNetworkServices 2025-01-05 12:24:14 +08:00
2dust
4a7bafd011 Fix Linux restore backup function
Fixed the issue that the guiNConfig.json file cannot be restored in the backup and restore function
2025-01-05 10:22:18 +08:00
2dust
626ebfe65d Improved ModifyFontSize 2025-01-04 20:42:42 +08:00
2dust
3cc75cd46d up 7.5.2 2025-01-04 19:07:16 +08:00
2dust
f809ee7b20 Adjust the macos package icon
https://github.com/2dust/v2rayN/issues/6404
2025-01-04 19:06:26 +08:00
2dust
1295d8191c Fix DNS
https://github.com/2dust/v2rayN/issues/6416
2025-01-04 17:47:54 +08:00
2dust
bc2adbfa77 Add restart to Linux restore backup function 2025-01-04 17:03:12 +08:00
2dust
9583dff176 Added the function of restarting the main app to AmazTool 2025-01-04 17:01:57 +08:00
2dust
5732b84a7b Refactor KillProcess 2025-01-04 15:06:30 +08:00
2dust
c0d27504ac Refactor ProcessStart RebootAsAdmin 2025-01-03 20:56:51 +08:00
2dust
3db1dd7bbb Add a title to SaveLog 2025-01-03 15:02:31 +08:00
2dust
5392766c5e Improved KillProcess 2025-01-03 15:01:30 +08:00
2dust
730b7dea37 Adjust upgrade waiting time 2025-01-03 09:50:21 +08:00
2dust
02a13ce028 Add logging to KillProcess
https://github.com/2dust/v2rayN/issues/6386
2025-01-02 13:54:17 +08:00
2dust
7884853098 Improved backup and restore
Overwrite the configuration file directly in the main program
2025-01-02 13:36:26 +08:00
2dust
e122ea8146 Optimize VerticalAlignment="Center" 2025-01-02 12:20:43 +08:00
2dust
f500d2b9f4 up 7.5.1 2025-01-01 16:25:53 +08:00
2dust
79e53bf1f5 Improve macos system proxy code 2025-01-01 14:24:23 +08:00
2dust
31de7ec094 Bug fix SetLinuxChmod 2025-01-01 12:27:49 +08:00
2dust
2e4501187c Window title display adjustment
https://github.com/2dust/v2rayN/issues/6389
2025-01-01 10:38:55 +08:00
2dust
4430c9bd74 Remove the last rule from the Whitelist
https://github.com/2dust/v2rayN/issues/6378
2024-12-31 20:37:14 +08:00
2dust
cf8be85ff7 Remove the display of run as an administrator in Linux and macos 2024-12-31 16:30:27 +08:00
2dust
0759be1223 Fix rule required
https://github.com/2dust/v2rayN/issues/6378
2024-12-31 15:32:31 +08:00
2dust
21f8ddcf9f macos adds system proxy for USB
https://github.com/2dust/v2rayN/issues/6381
2024-12-31 14:55:35 +08:00
2dust
37cba5ee34 Fix export rule order issue
https://github.com/2dust/v2rayN/issues/6377
2024-12-31 14:15:09 +08:00
OnceUponATimeInAmerica
ff642fd1ac Add full support for (one-click) Iran regional preset by using Chocolate4U's github repos for iran routing rules (#6384) 2024-12-31 13:51:06 +08:00
2dust
647f1d9c8b up 7.5.0 2024-12-30 19:56:33 +08:00
2dust
d886195ee3 Adjust upgrade waiting time 2024-12-30 19:55:32 +08:00
2dust
e2b8f4f89a If Process.start contains spaces, add quotes 2024-12-30 19:33:39 +08:00
2dust
1dcfe661e9 Modify the build script
When NotStoreConfigHere.txt file exists, the configs not stored in the current folder
2024-12-30 18:16:07 +08:00
2dust
d6dd110781 Adjust open the storage location 2024-12-30 11:10:27 +08:00
2dust
a0f956c885 Add command shortcut keys for macos
https://github.com/2dust/v2rayN/issues/6375
2024-12-30 11:02:09 +08:00
Long Yixing
88bcafed97 Modify the build macos script (#6374) 2024-12-30 09:24:22 +08:00
2dust
6e4f15ab52 Update README.md 2024-12-27 10:12:38 +08:00
Wydy
20cae1ff4d Update pac (#6356) 2024-12-27 09:48:28 +08:00
2dust
dcf621b822 Modify the build script 2024-12-26 17:19:42 +08:00
2dust
eafa20032b Modify the build windows script 2024-12-25 17:06:03 +08:00
2dust
7375e1a490 Modify the build macos script 2024-12-25 16:48:23 +08:00
2dust
199d87ba84 Modify the build linux script and add release package deb 2024-12-25 16:11:02 +08:00
2dust
b43975ebfc Add v2rayN.png for desktop 2024-12-25 16:06:11 +08:00
2dust
fe7314c978 up 7.4.2 2024-12-24 10:55:25 +08:00
2dust
d4eb8e59a6 update build 2024-12-23 17:39:50 +08:00
2dust
8ee00907b7 update build 2024-12-23 17:34:06 +08:00
2dust
25fddc3c71 Code clean for desktop 2024-12-23 14:28:33 +08:00
2dust
c78b733850 Revert "update build macos"
This reverts commit a57c83125e.
2024-12-23 13:59:55 +08:00
2dust
a57c83125e update build macos 2024-12-23 12:12:03 +08:00
2dust
247b59985f update build 2024-12-23 11:31:56 +08:00
2dust
7470b8b6d3 Try to fix
https://github.com/2dust/v2rayN/issues/6073
2024-12-23 10:38:37 +08:00
2dust
776d37b7aa Optimize port display 2024-12-23 10:37:43 +08:00
alphax-hue3682
8f532f8468 Update persian translate (#6325) 2024-12-23 10:00:51 +08:00
2dust
472963fe2d Add a second local listening port
https://github.com/2dust/v2rayN/issues/6321
2024-12-22 20:03:20 +08:00
2dust
6a9b62ab9a Improve Ctrl+V for Windows 2024-12-22 12:02:00 +08:00
2dust
9ac8aa2969 up PackageReference 2024-12-22 12:00:50 +08:00
2dust
838bd2c794 up 7.4.1 2024-12-19 16:18:45 +08:00
2dust
b2bbe432e0 Fix
https://github.com/2dust/v2rayN/issues/6309
2024-12-19 16:07:45 +08:00
2dust
b3d8042452 The lower limit of the font size from 10 to 8 2024-12-19 13:53:40 +08:00
2dust
0c758a7fdc Optimize UI for macos 2024-12-19 13:36:45 +08:00
2dust
85cb1d1c92 Bug fix system proxy for macos 2024-12-19 13:20:12 +08:00
2dust
2cd2e8894d Add system proxy exception function for macos 2024-12-19 11:40:16 +08:00
2dust
abb58379b3 Add IsNonWindows instead of IsLinux or IsOSX 2024-12-19 11:24:52 +08:00
2dust
4f48e8b190 Optimize UI 2024-12-19 10:23:46 +08:00
2dust
2b5cbb5e74 UnauthorizedAccessException to Exception 2024-12-18 15:27:00 +08:00
2dust
23dd140921 up 7.4.0 2024-12-18 14:47:27 +08:00
2dust
8c8d7bda64 StartupPath optional LocalApplicationData for linux 2024-12-18 10:27:58 +08:00
2dust
a6e246948a Linux system proxy adds kde version processing 2024-12-17 11:05:12 +08:00
2dust
c49ba735a0 Optimize code 2024-12-16 21:05:36 +08:00
2dust
1a33c598e8 Disable mux when using xhttp 2024-12-16 21:01:03 +08:00
2dust
a4bbdb49de proxy api.ip.sb
https://github.com/2dust/v2rayN/issues/6280
2024-12-16 19:59:46 +08:00
2dust
cf3846fbfd Update README.md 2024-12-16 19:47:27 +08:00
2dust
d46943eedf Optimize UI 2024-12-16 14:28:22 +08:00
2dust
3bc17bd50a Add host for xray ws
https://github.com/XTLS/Xray-core/pull/4142
2024-12-16 14:22:31 +08:00
2dust
48a159f4c8 Need SkiaSharp V2.88 2024-12-15 16:15:58 +08:00
2dust
3d1bcffdc5 up 7.3.2 2024-12-15 15:14:25 +08:00
2dust
45fa0f94d2 up PackageReference 2024-12-15 15:13:37 +08:00
2dust
ed16b7de4a Fix
https://github.com/2dust/v2rayN/issues/6258
2024-12-15 14:41:48 +08:00
2dust
f2ec03c7ec Bug fix
https://github.com/2dust/v2rayN/issues/6263
2024-12-15 14:41:29 +08:00
2dust
11db87f1e6 Remove unused resources 2024-12-15 14:27:00 +08:00
phoenix6936
a1feaf33e0 Update persian translation (#6245)
* Update persian translation

* Update ResUI.fa-Ir.resx
2024-12-15 11:24:13 +08:00
2dust
53a99e3f79 Remove part System.Reflection 2024-12-08 11:11:06 +08:00
2dust
e7f04f55c2 Remove QueryableExtension 2024-12-08 11:10:15 +08:00
2dust
6653ea12b7 Add Language: Hungarian
https://github.com/2dust/v2rayN/issues/6252
2024-12-07 21:25:53 +08:00
2dust
a28cef5b98 Fixed the issue of save window size when exit
https://github.com/2dust/v2rayN/issues/6251
2024-12-07 21:13:57 +08:00
2dust
78a28fbdb3 up 7.3.1 2024-12-07 16:30:32 +08:00
2dust
bf8bbbdcb0 Code clean 2024-12-07 16:29:58 +08:00
2dust
83ad83b135 Optimize save config files 2024-12-07 14:07:51 +08:00
2dust
dbd4f55981 Add system proxy exception function for linux
https://github.com/2dust/v2rayN/issues/6214
2024-12-06 19:12:32 +08:00
2dust
5f5d7172ee Optimize system proxy exceptions 2024-12-06 16:38:23 +08:00
2dust
fbd4557b44 WebProxy uses socks5 instead of http 2024-12-06 14:01:11 +08:00
phoenix6936
5d55a55754 Update persian translate (#6237)
* Update persian translate

* Update ResUI.fa-Ir.resx
2024-12-06 10:01:11 +08:00
phoenix6936
84032aec33 Update persian translation (#6227)
* Update persian translation

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx
2024-12-06 09:38:56 +08:00
150 changed files with 10198 additions and 2826 deletions

77
.github/workflows/build-linux.yml vendored Normal file
View File

@@ -0,0 +1,77 @@
name: release Linux
on:
workflow_dispatch:
inputs:
release_tag:
required: false
type: string
push:
branches:
- master
env:
OutputArch: "linux-64"
OutputArchArm: "linux-arm64"
OutputPath64: "${{ github.workspace }}/v2rayN/Release/linux-64"
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/linux-arm64"
jobs:
build:
strategy:
matrix:
configuration: [Release]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build
run: |
cd v2rayN
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-x64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPath64
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-arm64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPathArm64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-x64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPath64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-arm64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPathArm64
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: v2rayN-linux
path: |
${{ github.workspace }}/v2rayN/Release/linux*
# release debian package
- name: Package debian
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-debian.sh
./package-debian.sh $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }}
./package-debian.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}
- name: Upload deb to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.deb
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
# release zip archive
- name: Package release zip archive
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-release-zip.sh
./package-release-zip.sh $OutputArch $OutputPath64
./package-release-zip.sh $OutputArchArm $OutputPathArm64
- name: Upload zip archive to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.zip
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true

View File

@@ -1,10 +1,20 @@
name: release macos name: release macOS
on: on:
workflow_dispatch:
inputs:
release_tag:
required: false
type: string
push: push:
branches: [ "master" ] branches:
pull_request: - master
branches: [ "master" ]
env:
OutputArch: "macos-64"
OutputArchArm: "macos-arm64"
OutputPath64: "${{ github.workspace }}/v2rayN/Release/macos-64"
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/macos-arm64"
jobs: jobs:
build: build:
@@ -19,14 +29,50 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Build - name: Build
run: cd v2rayN && run: |
./build-osx.sh cd v2rayN
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-x64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPath64
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-arm64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPathArm64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-x64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPath64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-arm64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPathArm64
- name: Upload build artifacts - name: Upload build artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: v2rayN-osx name: v2rayN-macos
path: | path: |
./v2rayN/v2rayN-osx.zip ${{ github.workspace }}/v2rayN/Release/macos*
# release osx package
- name: Package osx
if: github.event.inputs.release_tag != ''
run: |
brew install create-dmg
chmod 755 package-osx.sh
./package-osx.sh $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }}
./package-osx.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}
- name: Upload dmg to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.dmg
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
# release zip archive
- name: Package release zip archive
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-release-zip.sh
./package-release-zip.sh $OutputArch $OutputPath64
./package-release-zip.sh $OutputArchArm $OutputPathArm64
- name: Upload zip archive to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.zip
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true

68
.github/workflows/build-windows.yml vendored Normal file
View File

@@ -0,0 +1,68 @@
name: release Windows
on:
workflow_dispatch:
inputs:
release_tag:
required: false
type: string
push:
branches:
- master
env:
OutputArch: "windows-64"
OutputArchArm: "windows-arm64"
OutputPath64: "${{ github.workspace }}/v2rayN/Release/windows-64"
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/windows-arm64"
OutputPath64Sc: "${{ github.workspace }}/v2rayN/Release/windows-64-SelfContained"
jobs:
build:
strategy:
matrix:
configuration: [Release]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build
run: |
cd v2rayN
dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-x64 --self-contained false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPath64
dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-arm64 --self-contained false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPathArm64
dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-x64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPath64Sc
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPath64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPathArm64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -p:EnableWindowsTargeting=true -o $OutputPath64Sc
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: v2rayN-windows
path: |
${{ github.workspace }}/v2rayN/Release/windows*
# release zip archive
- name: Package release zip archive
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-release-zip.sh
./package-release-zip.sh $OutputArch $OutputPath64
./package-release-zip.sh "windows-64-With-Core" $OutputPath64
./package-release-zip.sh $OutputArchArm $OutputPathArm64
./package-release-zip.sh "windows-64-SelfContained" $OutputPath64Sc
./package-release-zip.sh "windows-64-SelfContained-With-Core" $OutputPath64Sc
- name: Upload zip archive to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.zip
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true

View File

@@ -1,60 +0,0 @@
name: release
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
strategy:
matrix:
configuration: [Release]
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
# - name: 删除工作流运行
# uses: Mattraks/delete-workflow-runs@v2
# with:
# token: ${{ github.token }}
# repository: ${{ github.repository }}
# retain_days: 0
# keep_minimum_runs: 1
- name: Build
run: cd v2rayN &&
./build.ps1
# - name: Package
# shell: pwsh
# run: |
# 7z a -mx9 ..\v2rayN.7z $env:Wap_Project_Directory
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: v2rayN
path: |
./v2rayN/v2rayN.zip
# - name: Release
# uses: softprops/action-gh-release@v1
# env:
# GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
# with:
# prerelease: ${{ contains(github.ref, '-') }}
# draft: false
# files: |
# .\v2rayN\v2rayN.zip
# body: |
# [![](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/netch_channel) [![](https://img.shields.io/badge/Telegram-Group-green)](https://t.me/netch_group)
# ## Changelogs
# * This is an automated deployment of GitHub Actions, the change log should be updated manually soon
# ## 更新日志
# * 这是 GitHub Actions 自动化部署,更新日志应该很快会手动更新

View File

@@ -1,5 +1,5 @@
# v2rayN # v2rayN
A GUI client for Windows and Linux, support [Xray core](https://github.com/XTLS/Xray-core) and [sing-box-core](https://github.com/SagerNet/sing-box/releases) and [others](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores) A GUI client for Windows, Linux and macOS, support [Xray core](https://github.com/XTLS/Xray-core) and [sing-box-core](https://github.com/SagerNet/sing-box/releases) and [others](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/2dust/v2rayN)](https://github.com/2dust/v2rayN/commits/master) [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/2dust/v2rayN)](https://github.com/2dust/v2rayN/commits/master)
@@ -13,12 +13,17 @@ Check [Release files introduction](https://github.com/2dust/v2rayN/wiki/Release-
### Windows ### Windows
- Run `v2rayN.exe` - Run `v2rayN.exe`
### Linux ### Linux
- `chmod +x v2rayN` Run `./v2rayN` - `chmod +x v2rayN` Run `./v2rayN` under user permissions
``` ```
Debian 9+ Debian 9+
Ubuntu 16.04+ Ubuntu 16.04+
Fedora 30+ Fedora 30+
``` ```
### macOS
- `chmod +x v2rayN` Run `./v2rayN` under user permissions
```
macOS 11+
```
## Requirements ## Requirements
- [Microsoft .NET 8.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) - [Microsoft .NET 8.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)

53
package-debian.sh Normal file
View File

@@ -0,0 +1,53 @@
#!/bin/bash
Arch="$1"
OutputPath="$2"
Version="$3"
PackagePath="v2rayN-Package-${Arch}"
mkdir -p "${PackagePath}/DEBIAN"
mkdir -p "${PackagePath}/opt"
cp -rf $OutputPath "${PackagePath}/opt/v2rayN"
echo "When this file exists, app will not store configs under this folder" > "${PackagePath}/opt/v2rayN/NotStoreConfigHere.txt"
if [ $Arch = "linux-64" ]; then
Arch2="amd64"
else
Arch2="arm64"
fi
echo $Arch2
# basic
cat >"${PackagePath}/DEBIAN/control" <<-EOF
Package: v2rayN
Version: $Version
Architecture: $Arch2
Maintainer: https://github.com/2dust/v2rayN
Description: A GUI client for Windows and Linux, support Xray core and sing-box-core and others
EOF
cat >"${PackagePath}/DEBIAN/postinst" <<-EOF
if [ ! -s /usr/share/applications/v2rayN.desktop ]; then
cat >/usr/share/applications/v2rayN.desktop<<-END
[Desktop Entry]
Name=v2rayN
Comment=A GUI client for Windows and Linux, support Xray core and sing-box-core and others
Exec=/opt/v2rayN/v2rayN
Icon=/opt/v2rayN/v2rayN.png
Terminal=false
Type=Application
Categories=Network;Application;
END
fi
update-desktop-database
EOF
sudo chmod 0755 "${PackagePath}/DEBIAN/postinst"
sudo chmod 0755 "${PackagePath}/opt/v2rayN/v2rayN"
sudo chmod 0755 "${PackagePath}/opt/v2rayN/AmazTool"
# desktop && PATH
sudo dpkg-deb -Zxz --build $PackagePath
sudo mv "${PackagePath}.deb" "v2rayN-${Arch}.deb"

53
package-osx.sh Executable file
View File

@@ -0,0 +1,53 @@
#!/bin/bash
Arch="$1"
OutputPath="$2"
Version="$3"
PackagePath="v2rayN-Package-${Arch}"
mkdir -p "$PackagePath/v2rayN.app/Contents/Resources"
cp -rf "$OutputPath" "$PackagePath/v2rayN.app/Contents/MacOS"
cp -f "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.icns" "$PackagePath/v2rayN.app/Contents/Resources/AppIcon.icns"
echo "When this file exists, app will not store configs under this folder" > "$PackagePath/v2rayN.app/Contents/MacOS/NotStoreConfigHere.txt"
chmod +x "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN"
cat >"$PackagePath/v2rayN.app/Contents/Info.plist" <<-EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>v2rayN</string>
<key>CFBundleExecutable</key>
<string>v2rayN</string>
<key>CFBundleIconFile</key>
<string>AppIcon</string>
<key>CFBundleIconName</key>
<string>AppIcon</string>
<key>CFBundleIdentifier</key>
<string>2dust.v2rayN</string>
<key>CFBundleName</key>
<string>v2rayN</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${Version}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>
EOF
create-dmg \
--volname "v2rayN Installer" \
--window-size 700 420 \
--icon-size 100 \
--icon "v2rayN.app" 160 185 \
--hide-extension "v2rayN.app" \
--app-drop-link 500 185 \
"v2rayN-${Arch}.dmg" \
"$PackagePath/v2rayN.app"

15
package-release-zip.sh Normal file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
Arch="$1"
OutputPath="$2"
OutputArch="v2rayN-${Arch}"
FileName="v2rayN-${Arch}.zip"
wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName"
ZipPath64="./$OutputArch"
mkdir $ZipPath64
cp -rf $OutputPath "$ZipPath64/$OutputArch"
7z a -tZip $FileName "$ZipPath64/$OutputArch" -mx1

View File

@@ -5,8 +5,8 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright> <Copyright>Copyright © 2017-2025 (GPLv3)</Copyright>
<FileVersion>1.3.0</FileVersion> <FileVersion>1.3.1</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -15,8 +15,15 @@
return; return;
} }
var fileName = Uri.UnescapeDataString(string.Join(" ", args)); var argData = Uri.UnescapeDataString(string.Join(" ", args));
UpgradeApp.Upgrade(fileName); if (argData.Equals("rebootas"))
{
Thread.Sleep(1000);
Utils.StartV2RayN();
return;
}
UpgradeApp.Upgrade(argData);
} }
} }
} }

View File

@@ -10,7 +10,7 @@ namespace AmazTool
{ {
Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}"); Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
Waiting(9); Waiting(5);
if (!File.Exists(fileName)) if (!File.Exists(fileName))
{ {
@@ -21,11 +21,11 @@ namespace AmazTool
Console.WriteLine(Resx.Resource.TryTerminateProcess); Console.WriteLine(Resx.Resource.TryTerminateProcess);
try try
{ {
var existing = Process.GetProcessesByName(V2rayN); var existing = Process.GetProcessesByName(Utils.V2rayN);
foreach (var pp in existing) foreach (var pp in existing)
{ {
var path = pp.MainModule?.FileName ?? ""; var path = pp.MainModule?.FileName ?? "";
if (path.StartsWith(GetPath(V2rayN))) if (path.StartsWith(Utils.GetPath(Utils.V2rayN)))
{ {
pp?.Kill(); pp?.Kill();
pp?.WaitForExit(1000); pp?.WaitForExit(1000);
@@ -42,7 +42,7 @@ namespace AmazTool
StringBuilder sb = new(); StringBuilder sb = new();
try try
{ {
string thisAppOldFile = $"{GetExePath()}.tmp"; string thisAppOldFile = $"{Utils.GetExePath()}.tmp";
File.Delete(thisAppOldFile); File.Delete(thisAppOldFile);
string splitKey = "/"; string splitKey = "/";
@@ -62,12 +62,12 @@ namespace AmazTool
if (lst.Length == 1) continue; if (lst.Length == 1) continue;
string fullName = string.Join(splitKey, lst[1..lst.Length]); string fullName = string.Join(splitKey, lst[1..lst.Length]);
if (string.Equals(GetExePath(), GetPath(fullName), StringComparison.OrdinalIgnoreCase)) if (string.Equals(Utils.GetExePath(), Utils.GetPath(fullName), StringComparison.OrdinalIgnoreCase))
{ {
File.Move(GetExePath(), thisAppOldFile); File.Move(Utils.GetExePath(), thisAppOldFile);
} }
string entryOutputPath = GetPath(fullName); string entryOutputPath = Utils.GetPath(fullName);
Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!); Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!);
entry.ExtractToFile(entryOutputPath, true); entry.ExtractToFile(entryOutputPath, true);
@@ -91,40 +91,12 @@ namespace AmazTool
} }
Console.WriteLine(Resx.Resource.Restartv2rayN); Console.WriteLine(Resx.Resource.Restartv2rayN);
Waiting(9); Waiting(2);
Process process = new()
{ Utils.StartV2RayN();
StartInfo = new()
{
UseShellExecute = true,
FileName = V2rayN,
WorkingDirectory = StartupPath()
}
};
process.Start();
} }
private static string GetExePath() public static void Waiting(int second)
{
return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
}
private static string StartupPath()
{
return AppDomain.CurrentDomain.BaseDirectory;
}
private static string GetPath(string fileName)
{
string startupPath = StartupPath();
if (string.IsNullOrEmpty(fileName))
{
return startupPath;
}
return Path.Combine(startupPath, fileName);
}
private static void Waiting(int second)
{ {
for (var i = second; i > 0; i--) for (var i = second; i > 0; i--)
{ {
@@ -132,7 +104,5 @@ namespace AmazTool
Thread.Sleep(1000); Thread.Sleep(1000);
} }
} }
private static string V2rayN => "v2rayN";
} }
} }

43
v2rayN/AmazTool/Utils.cs Normal file
View File

@@ -0,0 +1,43 @@
using System.Diagnostics;
namespace AmazTool
{
internal class Utils
{
public static string GetExePath()
{
return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
}
public static string StartupPath()
{
return AppDomain.CurrentDomain.BaseDirectory;
}
public static string GetPath(string fileName)
{
string startupPath = StartupPath();
if (string.IsNullOrEmpty(fileName))
{
return startupPath;
}
return Path.Combine(startupPath, fileName);
}
public static string V2rayN => "v2rayN";
public static void StartV2RayN()
{
Process process = new()
{
StartInfo = new()
{
UseShellExecute = true,
FileName = V2rayN,
WorkingDirectory = StartupPath()
}
};
process.Start();
}
}
}

View File

@@ -6,6 +6,8 @@ namespace ServiceLib.Common
{ {
public static class FileManager public static class FileManager
{ {
private static readonly string _tag = "FileManager";
public static bool ByteArrayToFile(string fileName, byte[] content) public static bool ByteArrayToFile(string fileName, byte[] content)
{ {
try try
@@ -15,7 +17,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return false; return false;
} }
@@ -30,7 +32,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }
@@ -46,7 +48,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }
@@ -60,7 +62,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }
@@ -79,7 +81,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
throw; throw;
} }
} }
@@ -105,13 +107,13 @@ namespace ServiceLib.Common
} }
catch (IOException ex) catch (IOException ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
return false; return false;
} }
return true; return true;
@@ -130,7 +132,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
return null; return null;
} }
} }
@@ -148,7 +150,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
return false; return false;
} }
return true; return true;

View File

@@ -10,7 +10,7 @@ namespace ServiceLib.Common
{ {
private static readonly Lazy<HttpClientHelper> _instance = new(() => private static readonly Lazy<HttpClientHelper> _instance = new(() =>
{ {
HttpClientHandler handler = new() { UseCookies = false }; SocketsHttpHandler handler = new() { UseCookies = false };
HttpClientHelper helper = new(new HttpClient(handler)); HttpClientHelper helper = new(new HttpClient(handler));
return helper; return helper;
}); });

View File

@@ -6,6 +6,8 @@ namespace ServiceLib.Common
{ {
public class JsonUtils public class JsonUtils
{ {
private static readonly string _tag = "JsonUtils";
/// <summary> /// <summary>
/// DeepCopy /// DeepCopy
/// </summary> /// </summary>
@@ -70,8 +72,9 @@ namespace ServiceLib.Common
/// </summary> /// </summary>
/// <param name="obj"></param> /// <param name="obj"></param>
/// <param name="indented"></param> /// <param name="indented"></param>
/// <param name="nullValue"></param>
/// <returns></returns> /// <returns></returns>
public static string Serialize(object? obj, bool indented = true) public static string Serialize(object? obj, bool indented = true, bool nullValue = false)
{ {
var result = string.Empty; var result = string.Empty;
try try
@@ -82,14 +85,38 @@ namespace ServiceLib.Common
} }
var options = new JsonSerializerOptions var options = new JsonSerializerOptions
{ {
WriteIndented = indented ? true : false, WriteIndented = indented,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull
}; };
result = JsonSerializer.Serialize(obj, options); result = JsonSerializer.Serialize(obj, options);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
}
return result;
}
/// <summary>
/// Serialize Object to Json string
/// </summary>
/// <param name="obj"></param>
/// <param name="options"></param>
/// <returns></returns>
public static string Serialize(object? obj, JsonSerializerOptions options)
{
var result = string.Empty;
try
{
if (obj == null)
{
return result;
}
result = JsonSerializer.Serialize(obj, options);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
} }
return result; return result;
} }
@@ -100,38 +127,5 @@ namespace ServiceLib.Common
/// <param name="obj"></param> /// <param name="obj"></param>
/// <returns></returns> /// <returns></returns>
public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj); public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj);
/// <summary>
/// Save as json file
/// </summary>
/// <param name="obj"></param>
/// <param name="filePath"></param>
/// <param name="nullValue"></param>
/// <returns></returns>
public static int ToFile(object? obj, string? filePath, bool nullValue = true)
{
if (filePath is null)
{
return -1;
}
try
{
using var file = File.Create(filePath);
var options = new JsonSerializerOptions
{
WriteIndented = true,
DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull
};
JsonSerializer.Serialize(file, obj, options);
return 0;
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
return -1;
}
}
} }
} }

View File

@@ -0,0 +1,139 @@
using System.Diagnostics;
namespace ServiceLib.Common;
public static class ProcUtils
{
private static readonly string _tag = "ProcUtils";
public static void ProcessStart(string? fileName, string arguments = "")
{
ProcessStart(fileName, arguments, null);
}
public static int? ProcessStart(string? fileName, string arguments, string? dir)
{
if (fileName.IsNullOrEmpty())
{
return null;
}
try
{
if (fileName.Contains(' ')) fileName = fileName.AppendQuotes();
if (arguments.Contains(' ')) arguments = arguments.AppendQuotes();
Process process = new()
{
StartInfo = new ProcessStartInfo
{
UseShellExecute = true,
FileName = fileName,
Arguments = arguments,
WorkingDirectory = dir
}
};
process.Start();
return process.Id;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return null;
}
public static void RebootAsAdmin(bool blAdmin = true)
{
try
{
ProcessStartInfo startInfo = new()
{
UseShellExecute = true,
Arguments = Global.RebootAs,
WorkingDirectory = Utils.StartupPath(),
FileName = Utils.GetExePath().AppendQuotes(),
Verb = blAdmin ? "runas" : null,
};
Process.Start(startInfo);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public static async Task ProcessKill(int pid)
{
try
{
await ProcessKill(Process.GetProcessById(pid), false);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public static async Task ProcessKill(Process? proc, bool review)
{
if (proc is null)
{
return;
}
GetProcessKeyInfo(proc, review, out var procId, out var fileName, out var processName);
try { proc?.Kill(true); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
try { proc?.Kill(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
try { proc?.Close(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
try { proc?.Dispose(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
await Task.Delay(300);
await ProcessKillByKeyInfo(review, procId, fileName, processName);
}
private static void GetProcessKeyInfo(Process? proc, bool review, out int? procId, out string? fileName, out string? processName)
{
procId = null;
fileName = null;
processName = null;
if (!review) return;
try
{
procId = proc?.Id;
fileName = proc?.MainModule?.FileName;
processName = proc?.ProcessName;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
private static async Task ProcessKillByKeyInfo(bool review, int? procId, string? fileName, string? processName)
{
if (review && procId != null && fileName != null)
{
try
{
var lstProc = Process.GetProcessesByName(processName);
foreach (var proc2 in lstProc)
{
if (proc2.Id == procId)
{
Logging.SaveLog($"{_tag}, KillProcess not completing the job, procId");
await ProcessKill(proc2, false);
}
if (proc2.MainModule != null && proc2.MainModule?.FileName == fileName)
{
Logging.SaveLog($"{_tag}, KillProcess not completing the job, fileName");
}
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
}
}

View File

@@ -1,50 +0,0 @@
using System.Linq.Expressions;
using System.Reflection;
namespace ServiceLib.Common
{
public static class QueryableExtension
{
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> query, string propertyName)
{
return _OrderBy<T>(query, propertyName, false);
}
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> query, string propertyName)
{
return _OrderBy<T>(query, propertyName, true);
}
private static IOrderedQueryable<T> _OrderBy<T>(IQueryable<T> query, string propertyName, bool isDesc)
{
var methodname = (isDesc) ? "OrderByDescendingInternal" : "OrderByInternal";
var memberProp = typeof(T).GetProperty(propertyName);
var method = typeof(QueryableExtension).GetMethod(methodname)
.MakeGenericMethod(typeof(T), memberProp.PropertyType);
return (IOrderedQueryable<T>)method.Invoke(null, new object[] { query, memberProp });
}
public static IOrderedQueryable<T> OrderByInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty)
{//public
return query.OrderBy(_GetLambda<T, TProp>(memberProperty));
}
public static IOrderedQueryable<T> OrderByDescendingInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty)
{//public
return query.OrderByDescending(_GetLambda<T, TProp>(memberProperty));
}
private static Expression<Func<T, TProp>> _GetLambda<T, TProp>(PropertyInfo memberProperty)
{
if (memberProperty.PropertyType != typeof(TProp)) throw new Exception();
var thisArg = Expression.Parameter(typeof(T));
var lambda = Expression.Lambda<Func<T, TProp>>(Expression.Property(thisArg, memberProperty), thisArg);
return lambda;
}
}
}

View File

@@ -73,5 +73,19 @@ namespace ServiceLib.Common
{ {
return _dbAsync.Table<T>(); return _dbAsync.Table<T>();
} }
public async Task DisposeDbConnectionAsync()
{
await Task.Factory.StartNew(() =>
{
_db?.Close();
_db?.Dispose();
_db = null;
_dbAsync?.GetConnection()?.Close();
_dbAsync?.GetConnection()?.Dispose();
_dbAsync = null;
});
}
} }
} }

View File

@@ -15,6 +15,8 @@ namespace ServiceLib.Common
{ {
public class Utils public class Utils
{ {
private static readonly string _tag = "Utils";
#region #region
/// <summary> /// <summary>
@@ -36,7 +38,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return result; return result;
@@ -57,7 +59,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return null; return null;
@@ -92,7 +94,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return string.Empty; return string.Empty;
@@ -117,7 +119,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return null; return null;
@@ -139,7 +141,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return null; return null;
@@ -159,7 +161,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("Base64Encode", ex); Logging.SaveLog(_tag, ex);
} }
return string.Empty; return string.Empty;
@@ -193,7 +195,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("Base64Decode", ex); Logging.SaveLog(_tag, ex);
} }
return string.Empty; return string.Empty;
@@ -483,7 +485,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return false; return false;
@@ -515,10 +517,10 @@ namespace ServiceLib.Common
#region #region
public static bool UpgradeAppExists(out string fileName) public static bool UpgradeAppExists(out string upgradeFileName)
{ {
fileName = Path.Combine(Utils.StartupPath(), GetExeName("AmazTool")); upgradeFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, GetExeName("AmazTool"));
return File.Exists(fileName); return File.Exists(upgradeFileName);
} }
/// <summary> /// <summary>
@@ -529,19 +531,13 @@ namespace ServiceLib.Common
{ {
try try
{ {
if (blFull) return blFull
{ ? $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture}"
return : $"{Global.AppName}/{GetVersionInfo()}";
$"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture} - {File.GetLastWriteTime(GetExePath()):yyyy/MM/dd}";
}
else
{
return $"{Global.AppName}/{GetVersionInfo()}";
}
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return Global.AppName; return Global.AppName;
@@ -555,11 +551,16 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
return "0.0"; return "0.0";
} }
} }
public static string GetRuntimeInfo()
{
return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion}";
}
/// <summary> /// <summary>
/// 取得GUID /// 取得GUID
/// </summary> /// </summary>
@@ -579,7 +580,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return string.Empty; return string.Empty;
@@ -590,23 +591,6 @@ namespace ServiceLib.Common
return Guid.TryParse(strSrc, out _); return Guid.TryParse(strSrc, out _);
} }
public static void ProcessStart(string? fileName, string arguments = "")
{
try
{
if (fileName.IsNullOrEmpty())
{
return;
}
Process.Start(new ProcessStartInfo(fileName, arguments) { UseShellExecute = true });
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
}
public static Dictionary<string, string> GetSystemHosts() public static Dictionary<string, string> GetSystemHosts()
{ {
var systemHosts = new Dictionary<string, string>(); var systemHosts = new Dictionary<string, string>();
@@ -629,7 +613,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return systemHosts; return systemHosts;
@@ -677,6 +661,33 @@ namespace ServiceLib.Common
#region TempPath #region TempPath
public static bool HasWritePermission()
{
try
{
//When this file exists, it is equivalent to having no permission to read and write
if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "NotStoreConfigHere.txt")))
{
return false;
}
var tempPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "guiTemps");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
var fileName = Path.Combine(tempPath, GetGuid());
File.Create(fileName).Close();
File.Delete(fileName);
}
catch (Exception)
{
return false;
}
return true;
}
public static string GetPath(string fileName) public static string GetPath(string fileName)
{ {
var startupPath = StartupPath(); var startupPath = StartupPath();
@@ -695,6 +706,11 @@ namespace ServiceLib.Common
public static string StartupPath() public static string StartupPath()
{ {
if (Utils.IsNonWindows() && Environment.GetEnvironmentVariable("V2RAYN_LOCAL_APPLICATION_DATA") == "1")
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "v2rayN");
}
return AppDomain.CurrentDomain.BaseDirectory; return AppDomain.CurrentDomain.BaseDirectory;
} }
@@ -818,6 +834,8 @@ namespace ServiceLib.Common
public static bool IsOSX() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX); public static bool IsOSX() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
public static bool IsNonWindows() => !RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public static string GetExeName(string name) public static string GetExeName(string name)
{ {
return IsWindows() ? $"{name}.exe" : name; return IsWindows() ? $"{name}.exe" : name;
@@ -829,18 +847,19 @@ namespace ServiceLib.Common
{ {
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
} }
else return false;
{ //else
var id = GetLinuxUserId().Result ?? "1000"; //{
if (int.TryParse(id, out var userId)) // var id = GetLinuxUserId().Result ?? "1000";
{ // if (int.TryParse(id, out var userId))
return userId == 0; // {
} // return userId == 0;
else // }
{ // else
return false; // {
} // return false;
} // }
//}
} }
private static async Task<string?> GetLinuxUserId() private static async Task<string?> GetLinuxUserId()
@@ -852,6 +871,8 @@ namespace ServiceLib.Common
public static async Task<string?> SetLinuxChmod(string? fileName) public static async Task<string?> SetLinuxChmod(string? fileName)
{ {
if (fileName.IsNullOrEmpty()) return null; if (fileName.IsNullOrEmpty()) return null;
if (fileName.Contains(' ')) fileName = fileName.AppendQuotes();
//File.SetUnixFileMode(fileName, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
var arg = new List<string>() { "-c", $"chmod +x {fileName}" }; var arg = new List<string>() { "-c", $"chmod +x {fileName}" };
return await GetCliWrapOutput("/bin/bash", arg); return await GetCliWrapOutput("/bin/bash", arg);
} }
@@ -870,6 +891,12 @@ namespace ServiceLib.Common
: Environment.GetEnvironmentVariable("HOME"); : Environment.GetEnvironmentVariable("HOME");
} }
public static async Task<string?> GetListNetworkServices()
{
var arg = new List<string>() { "-c", $"networksetup -listallnetworkservices" };
return await GetCliWrapOutput("/bin/bash", arg);
}
#endregion Platform #endregion Platform
} }
} }

View File

@@ -4,6 +4,8 @@ namespace ServiceLib.Common
{ {
internal static class WindowsUtils internal static class WindowsUtils
{ {
private static readonly string _tag = "WindowsUtils";
public static string? RegReadValue(string path, string name, string def) public static string? RegReadValue(string path, string name, string def)
{ {
RegistryKey? regKey = null; RegistryKey? regKey = null;
@@ -15,7 +17,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
finally finally
{ {
@@ -41,7 +43,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
finally finally
{ {

View File

@@ -6,6 +6,8 @@ namespace ServiceLib.Common
{ {
public class YamlUtils public class YamlUtils
{ {
private static readonly string _tag = "YamlUtils";
#region YAML #region YAML
/// <summary> /// <summary>
@@ -26,7 +28,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("FromYaml", ex); Logging.SaveLog(_tag, ex);
return deserializer.Deserialize<T>(""); return deserializer.Deserialize<T>("");
} }
} }
@@ -53,7 +55,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return result; return result;
} }
@@ -71,7 +73,7 @@ namespace ServiceLib.Common
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("PreprocessYaml", ex); Logging.SaveLog(_tag, ex);
return null; return null;
} }
} }

View File

@@ -4,6 +4,7 @@
{ {
socks = 0, socks = 0,
socks2, socks2,
socks3,
pac, pac,
api, api,
api2, api2,

View File

@@ -6,6 +6,7 @@
SendMsgView, SendMsgView,
SendSnackMsg, SendSnackMsg,
RefreshProfiles, RefreshProfiles,
StopSpeedtest StopSpeedtest,
AppExit
} }
} }

View File

@@ -4,5 +4,6 @@
{ {
Default = 0, Default = 0,
Russia = 1, Russia = 1,
Iran = 2,
} }
} }

View File

@@ -0,0 +1,13 @@
namespace ServiceLib.Enums
{
public enum ETheme
{
FollowSystem,
Dark,
Light,
Aquatic,
Desert,
Dusk,
NightSky
}
}

View File

@@ -63,20 +63,23 @@
public const string HttpProtocol = "http://"; public const string HttpProtocol = "http://";
public const string HttpsProtocol = "https://"; public const string HttpsProtocol = "https://";
public const string SocksProtocol = "socks://"; public const string SocksProtocol = "socks://";
public const string Socks5Protocol = "socks5://";
public const string UserEMail = "t@t.tt"; public const string UserEMail = "t@t.tt";
public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run"; public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
public const string AutoRunName = "v2rayNAutoRun"; public const string AutoRunName = "v2rayNAutoRun";
public const string CustomIconName = "v2rayN.ico"; public const string CustomIconName = "v2rayN.ico";
public const string IEProxyExceptions = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*"; public const string SystemProxyExceptionsWindows = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
public const string SystemProxyExceptionsLinux = "localhost,127.0.0.0/8,::1";
public const string RoutingRuleComma = "<COMMA>"; public const string RoutingRuleComma = "<COMMA>";
public const string GrpcGunMode = "gun"; public const string GrpcGunMode = "gun";
public const string GrpcMultiMode = "multi"; public const string GrpcMultiMode = "multi";
public const int MaxPort = 65536; public const int MaxPort = 65536;
public const string DelayUnit = ""; public const string DelayUnit = "";
public const string SpeedUnit = ""; public const string SpeedUnit = "";
public const int MinFontSize = 10; public const int MinFontSize = 8;
public const string RebootAs = "rebootas"; public const string RebootAs = "rebootas";
public const string AvaAssets = "avares://v2rayN/Assets/";
public static readonly List<string> IEProxyProtocols = new() { public static readonly List<string> IEProxyProtocols = new() {
"{ip}:{http_port}", "{ip}:{http_port}",
@@ -122,21 +125,25 @@
public static readonly List<string> GeoFilesSources = new() { public static readonly List<string> GeoFilesSources = new() {
"", "",
@"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/{0}.dat", @"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/{0}.dat",
@"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-v2ray-rules@release/{0}.dat",
}; };
public static readonly List<string> SingboxRulesetSources = new() { public static readonly List<string> SingboxRulesetSources = new() {
"", "",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-rules-dat@release/sing-box/rule-set-{0}/{1}.srs", @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-rules-dat@release/sing-box/rule-set-{0}/{1}.srs",
@"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-sing-box-rules@rule-set/{1}.srs",
}; };
public static readonly List<string> RoutingRulesSources = new() { public static readonly List<string> RoutingRulesSources = new() {
"", "",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/template.json", @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/template.json",
@"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/template.json",
}; };
public static readonly List<string> DNSTemplateSources = new() { public static readonly List<string> DNSTemplateSources = new() {
"", "",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/", @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/",
@"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/",
}; };
public static readonly Dictionary<string, string> UserAgentTexts = new() public static readonly Dictionary<string, string> UserAgentTexts = new()
@@ -195,15 +202,15 @@
public static readonly List<string> SingboxDomainStrategy4Out = new() { "ipv4_only", "prefer_ipv4", "prefer_ipv6", "ipv6_only", "" }; public static readonly List<string> SingboxDomainStrategy4Out = new() { "ipv4_only", "prefer_ipv4", "prefer_ipv6", "ipv6_only", "" };
public static readonly List<string> DomainDNSAddress = ["223.5.5.5", "223.6.6.6", "localhost"]; public static readonly List<string> DomainDNSAddress = ["223.5.5.5", "223.6.6.6", "localhost"];
public static readonly List<string> SingboxDomainDNSAddress = ["223.5.5.5", "223.6.6.6", "dhcp://auto"]; public static readonly List<string> SingboxDomainDNSAddress = ["223.5.5.5", "223.6.6.6", "dhcp://auto"];
public static readonly List<string> Languages = new() { "zh-Hans", "zh-Hant", "en", "fa-Ir", "ru" }; public static readonly List<string> Languages = new() { "zh-Hans", "zh-Hant", "en", "fa-Ir", "ru", "hu" };
public static readonly List<string> Alpns = new() { "h3", "h2", "http/1.1", "h3,h2", "h2,http/1.1", "h3,h2,http/1.1", "" }; public static readonly List<string> Alpns = new() { "h3", "h2", "http/1.1", "h3,h2", "h2,http/1.1", "h3,h2,http/1.1", "" };
public static readonly List<string> LogLevels = new() { "debug", "info", "warning", "error", "none" }; public static readonly List<string> LogLevels = new() { "debug", "info", "warning", "error", "none" };
public static readonly List<string> InboundTags = new() { "socks", "socks2" }; public static readonly List<string> InboundTags = new() { "socks", "socks2", "socks3" };
public static readonly List<string> RuleProtocols = new() { "http", "tls", "bittorrent" }; public static readonly List<string> RuleProtocols = new() { "http", "tls", "bittorrent" };
public static readonly List<string> RuleNetworks = new() { "", "tcp", "udp", "tcp,udp" }; public static readonly List<string> RuleNetworks = new() { "", "tcp", "udp", "tcp,udp" };
public static readonly List<string> destOverrideProtocols = ["http", "tls", "quic", "fakedns", "fakedns+others"]; public static readonly List<string> destOverrideProtocols = ["http", "tls", "quic", "fakedns", "fakedns+others"];
public static readonly List<string> TunMtus = new() { "1280", "1408", "1500", "9000" }; public static readonly List<string> TunMtus = new() { "1280", "1408", "1500", "9000" };
public static readonly List<string> TunStacks = new() { "gvisor", "system" }; public static readonly List<string> TunStacks = new() { "gvisor", "system", "mixed" };
public static readonly List<string> PresetMsgFilters = new() { "proxy", "direct", "block", "" }; public static readonly List<string> PresetMsgFilters = new() { "proxy", "direct", "block", "" };
public static readonly List<string> SingboxMuxs = new() { "h2mux", "smux", "yamux", "" }; public static readonly List<string> SingboxMuxs = new() { "h2mux", "smux", "yamux", "" };
public static readonly List<string> TuicCongestionControls = new() { "cubic", "new_reno", "bbr" }; public static readonly List<string> TuicCongestionControls = new() { "cubic", "new_reno", "bbr" };

View File

@@ -46,6 +46,11 @@
public bool InitApp() public bool InitApp()
{ {
if (Utils.IsNonWindows() && Utils.HasWritePermission() == false)
{
Environment.SetEnvironmentVariable("V2RAYN_LOCAL_APPLICATION_DATA", "1", EnvironmentVariableTarget.Process);
}
Logging.Setup(); Logging.Setup();
var config = ConfigHandler.LoadConfig(); var config = ConfigHandler.LoadConfig();
if (config == null) if (config == null)
@@ -72,8 +77,7 @@
public bool InitComponents() public bool InitComponents()
{ {
Logging.SaveLog($"v2rayN start up | {Utils.GetVersion()} | {Utils.GetExePath()}"); Logging.SaveLog($"v2rayN start up | {Utils.GetRuntimeInfo()}");
Logging.SaveLog($"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
Logging.LoggingEnabled(_config.GuiItem.EnableLog); Logging.LoggingEnabled(_config.GuiItem.EnableLog);
Logging.ClearLogs(); Logging.ClearLogs();
@@ -102,7 +106,13 @@
if (Utils.IsWindows()) if (Utils.IsWindows())
{ {
_processJob ??= new(); _processJob ??= new();
_processJob?.AddProcess(processHandle); try
{
_processJob?.AddProcess(processHandle);
}
catch
{
}
} }
} }

View File

@@ -5,6 +5,8 @@ namespace ServiceLib.Handler
{ {
public static class AutoStartupHandler public static class AutoStartupHandler
{ {
private static readonly string _tag = "AutoStartupHandler";
public static async Task<bool> UpdateTask(Config config) public static async Task<bool> UpdateTask(Config config)
{ {
if (Utils.IsWindows()) if (Utils.IsWindows())
@@ -62,7 +64,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }
@@ -123,7 +125,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }
@@ -143,7 +145,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }

View File

@@ -9,6 +9,7 @@ namespace ServiceLib.Handler
private Dictionary<string, ProxiesItem>? _proxies; private Dictionary<string, ProxiesItem>? _proxies;
public Dictionary<string, object> ProfileContent { get; set; } public Dictionary<string, object> ProfileContent { get; set; }
private static readonly string _tag = "ClashApiHandler";
public async Task<Tuple<ClashProxies, ClashProviders>?> GetClashProxiesAsync(Config config) public async Task<Tuple<ClashProxies, ClashProviders>?> GetClashProxiesAsync(Config config)
{ {
@@ -109,7 +110,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("GetClashProxyGroups", ex); Logging.SaveLog(_tag, ex);
return null; return null;
} }
} }
@@ -125,7 +126,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }
@@ -153,7 +154,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }
@@ -169,7 +170,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return null; return null;
@@ -184,7 +185,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }

View File

@@ -9,7 +9,7 @@ namespace ServiceLib.Handler
public class ConfigHandler public class ConfigHandler
{ {
private static readonly string _configRes = Global.ConfigFileName; private static readonly string _configRes = Global.ConfigFileName;
private static readonly object _objLock = new(); private static readonly string _tag = "ConfigHandler";
#region ConfigHandler #region ConfigHandler
@@ -67,10 +67,9 @@ namespace ServiceLib.Handler
} }
config.RoutingBasicItem ??= new(); config.RoutingBasicItem ??= new();
if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy)) if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy))
{ {
config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies.First();//"IPIfNonMatch"; config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies.First();
} }
config.KcpItem ??= new KcpItem config.KcpItem ??= new KcpItem
@@ -120,10 +119,6 @@ namespace ServiceLib.Handler
} }
config.ConstItem ??= new ConstItem(); config.ConstItem ??= new ConstItem();
if (Utils.IsNullOrEmpty(config.ConstItem.DefIEProxyExceptions))
{
config.ConstItem.DefIEProxyExceptions = Global.IEProxyExceptions;
}
config.SpeedTestItem ??= new(); config.SpeedTestItem ??= new();
if (config.SpeedTestItem.SpeedTestTimeout < 10) if (config.SpeedTestItem.SpeedTestTimeout < 10)
@@ -161,6 +156,17 @@ namespace ServiceLib.Handler
config.SystemProxyItem ??= new(); config.SystemProxyItem ??= new();
config.WebDavItem ??= new(); config.WebDavItem ??= new();
config.CheckUpdateItem ??= new(); config.CheckUpdateItem ??= new();
config.Fragment4RayItem ??= new()
{
Packets = "tlshello",
Length = "100-200",
Interval = "10-20"
};
if (config.SystemProxyItem.SystemProxyExceptions.IsNullOrEmpty())
{
config.SystemProxyItem.SystemProxyExceptions = Utils.IsWindows() ? Global.SystemProxyExceptionsWindows : Global.SystemProxyExceptionsLinux;
}
return config; return config;
} }
@@ -172,30 +178,26 @@ namespace ServiceLib.Handler
/// <returns></returns> /// <returns></returns>
public static async Task<int> SaveConfig(Config config) public static async Task<int> SaveConfig(Config config)
{ {
lock (_objLock) try
{ {
try //save temp file
{ var resPath = Utils.GetConfigPath(_configRes);
//save temp file var tempPath = $"{resPath}_temp";
var resPath = Utils.GetConfigPath(_configRes);
var tempPath = $"{resPath}_temp";
if (JsonUtils.ToFile(config, tempPath) != 0)
{
return -1;
}
if (File.Exists(resPath)) var content = JsonUtils.Serialize(config, true, true);
{ if (content.IsNullOrEmpty())
File.Delete(resPath);
}
//rename
File.Move(tempPath, resPath);
}
catch (Exception ex)
{ {
Logging.SaveLog("ToJsonFile", ex);
return -1; return -1;
} }
await File.WriteAllTextAsync(tempPath, content);
//rename
File.Move(tempPath, resPath, true);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
return -1;
} }
return 0; return 0;
@@ -500,7 +502,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
return -1; return -1;
} }
@@ -766,69 +768,66 @@ namespace ServiceLib.Handler
}).ToList(); }).ToList();
Enum.TryParse(colName, true, out EServerColName name); Enum.TryParse(colName, true, out EServerColName name);
var propertyName = string.Empty;
switch (name)
{
case EServerColName.ConfigType:
case EServerColName.Remarks:
case EServerColName.Address:
case EServerColName.Port:
case EServerColName.Network:
case EServerColName.StreamSecurity:
propertyName = name.ToString();
break;
case EServerColName.DelayVal:
propertyName = "Delay";
break;
case EServerColName.SpeedVal:
propertyName = "Speed";
break;
case EServerColName.SubRemarks:
propertyName = "Subid";
break;
default:
return -1;
}
var items = lstProfile.AsQueryable();
if (asc) if (asc)
{ {
lstProfile = items.OrderBy(propertyName).ToList(); lstProfile = name switch
{
EServerColName.ConfigType => lstProfile.OrderBy(t => t.ConfigType).ToList(),
EServerColName.Remarks => lstProfile.OrderBy(t => t.Remarks).ToList(),
EServerColName.Address => lstProfile.OrderBy(t => t.Address).ToList(),
EServerColName.Port => lstProfile.OrderBy(t => t.Port).ToList(),
EServerColName.Network => lstProfile.OrderBy(t => t.Network).ToList(),
EServerColName.StreamSecurity => lstProfile.OrderBy(t => t.StreamSecurity).ToList(),
EServerColName.DelayVal => lstProfile.OrderBy(t => t.Delay).ToList(),
EServerColName.SpeedVal => lstProfile.OrderBy(t => t.Speed).ToList(),
EServerColName.SubRemarks => lstProfile.OrderBy(t => t.Subid).ToList(),
_ => lstProfile
};
} }
else else
{ {
lstProfile = items.OrderByDescending(propertyName).ToList(); lstProfile = name switch
{
EServerColName.ConfigType => lstProfile.OrderByDescending(t => t.ConfigType).ToList(),
EServerColName.Remarks => lstProfile.OrderByDescending(t => t.Remarks).ToList(),
EServerColName.Address => lstProfile.OrderByDescending(t => t.Address).ToList(),
EServerColName.Port => lstProfile.OrderByDescending(t => t.Port).ToList(),
EServerColName.Network => lstProfile.OrderByDescending(t => t.Network).ToList(),
EServerColName.StreamSecurity => lstProfile.OrderByDescending(t => t.StreamSecurity).ToList(),
EServerColName.DelayVal => lstProfile.OrderByDescending(t => t.Delay).ToList(),
EServerColName.SpeedVal => lstProfile.OrderByDescending(t => t.Speed).ToList(),
EServerColName.SubRemarks => lstProfile.OrderByDescending(t => t.Subid).ToList(),
_ => lstProfile
};
} }
for (int i = 0; i < lstProfile.Count; i++)
for (var i = 0; i < lstProfile.Count; i++)
{ {
ProfileExHandler.Instance.SetSort(lstProfile[i].IndexId, (i + 1) * 10); ProfileExHandler.Instance.SetSort(lstProfile[i].IndexId, (i + 1) * 10);
} }
if (name == EServerColName.DelayVal) switch (name)
{ {
var maxSort = lstProfile.Max(t => t.Sort) + 10; case EServerColName.DelayVal:
foreach (var item in lstProfile)
{
if (item.Delay <= 0)
{ {
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort); var maxSort = lstProfile.Max(t => t.Sort) + 10;
foreach (var item in lstProfile.Where(item => item.Delay <= 0))
{
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort);
}
break;
} }
} case EServerColName.SpeedVal:
}
if (name == EServerColName.SpeedVal)
{
var maxSort = lstProfile.Max(t => t.Sort) + 10;
foreach (var item in lstProfile)
{
if (item.Speed <= 0)
{ {
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort); var maxSort = lstProfile.Max(t => t.Sort) + 10;
foreach (var item in lstProfile.Where(item => item.Speed <= 0))
{
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort);
}
break;
} }
}
} }
return 0; return 0;
@@ -990,7 +989,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("Remove Item", ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
@@ -1871,6 +1870,16 @@ namespace ServiceLib.Handler
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json")); await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json"));
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json")); await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json"));
return true;
case EPresetType.Iran:
config.ConstItem.GeoSourceUrl = Global.GeoFilesSources[2];
config.ConstItem.SrsSourceUrl = Global.SingboxRulesetSources[2];
config.ConstItem.RouteRulesTemplateSourceUrl = Global.RoutingRulesSources[2];
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[2] + "v2ray.json"));
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[2] + "sing_box.json"));
return true; return true;
} }

View File

@@ -5,6 +5,8 @@
/// </summary> /// </summary>
public class CoreConfigHandler public class CoreConfigHandler
{ {
private static readonly string _tag = "CoreConfigHandler";
public static async Task<RetResult> GenerateClientConfig(ProfileItem node, string? fileName) public static async Task<RetResult> GenerateClientConfig(ProfileItem node, string? fileName)
{ {
var config = AppHandler.Instance.Config; var config = AppHandler.Instance.Config;
@@ -82,7 +84,7 @@
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("GenerateClientCustomConfig", ex); Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }

View File

@@ -15,6 +15,7 @@ namespace ServiceLib.Handler
private Process? _processPre; private Process? _processPre;
private int _linuxSudoPid = -1; private int _linuxSudoPid = -1;
private Action<bool, string>? _updateFunc; private Action<bool, string>? _updateFunc;
private const string _tag = "CoreHandler";
public async Task Init(Config config, Action<bool, string> updateFunc) public async Task Init(Config config, Action<bool, string> updateFunc)
{ {
@@ -24,16 +25,16 @@ namespace ServiceLib.Handler
Environment.SetEnvironmentVariable("V2RAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process); Environment.SetEnvironmentVariable("V2RAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("XRAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process); Environment.SetEnvironmentVariable("XRAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
if (Utils.IsLinux() || Utils.IsOSX()) if (Utils.IsNonWindows())
{ {
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(); var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
foreach (var it in coreInfo) foreach (var it in coreInfo)
{ {
if (it.CoreType == ECoreType.v2rayN) if (it.CoreType == ECoreType.v2rayN)
{ {
if (Utils.UpgradeAppExists(out var fileName)) if (Utils.UpgradeAppExists(out var upgradeFileName))
{ {
await Utils.SetLinuxChmod(fileName); await Utils.SetLinuxChmod(upgradeFileName);
} }
continue; continue;
} }
@@ -54,7 +55,7 @@ namespace ServiceLib.Handler
{ {
if (node == null) if (node == null)
{ {
ShowMsg(false, ResUI.CheckServerSettings); UpdateFunc(false, ResUI.CheckServerSettings);
return; return;
} }
@@ -62,13 +63,13 @@ namespace ServiceLib.Handler
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName); var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
if (result.Success != true) if (result.Success != true)
{ {
ShowMsg(true, result.Msg); UpdateFunc(true, result.Msg);
return; return;
} }
ShowMsg(true, $"{node.GetSummary()}"); UpdateFunc(true, $"{node.GetSummary()}");
ShowMsg(false, $"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}"); UpdateFunc(false, $"{Utils.GetRuntimeInfo()}");
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"))); UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
await CoreStop(); await CoreStop();
await Task.Delay(100); await Task.Delay(100);
await CoreStart(node); await CoreStart(node);
@@ -80,15 +81,23 @@ namespace ServiceLib.Handler
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray; var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray;
var configPath = Utils.GetConfigPath(Global.CoreSpeedtestConfigFileName); var configPath = Utils.GetConfigPath(Global.CoreSpeedtestConfigFileName);
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType); var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
ShowMsg(false, result.Msg); UpdateFunc(false, result.Msg);
if (result.Success != true) if (result.Success != true)
{ {
return -1; return -1;
} }
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"))); UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
ShowMsg(false, configPath); UpdateFunc(false, configPath);
return await CoreStartSpeedtest(configPath, coreType);
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true, false);
if (proc is null)
{
return -1;
}
return proc.Id;
} }
public async Task CoreStop() public async Task CoreStop()
@@ -97,12 +106,14 @@ namespace ServiceLib.Handler
{ {
if (_process != null) if (_process != null)
{ {
_process = await KillProcess(_process); await ProcUtils.ProcessKill(_process, true);
_process = null;
} }
if (_processPre != null) if (_processPre != null)
{ {
_processPre = await KillProcess(_processPre); await ProcUtils.ProcessKill(_processPre, true);
_processPre = null;
} }
if (_linuxSudoPid > 0) if (_linuxSudoPid > 0)
@@ -113,45 +124,12 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
}
}
public async Task CoreStopPid(int pid)
{
try
{
await KillProcess(Process.GetProcessById(pid));
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
} }
} }
#region Private #region Private
private string CoreFindExe(CoreInfo coreInfo)
{
var fileName = string.Empty;
foreach (var name in coreInfo.CoreExes)
{
var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());
if (File.Exists(vName))
{
fileName = vName;
break;
}
}
if (Utils.IsNullOrEmpty(fileName))
{
var msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.CoreType.ToString()), string.Join(", ", coreInfo.CoreExes.ToArray()), coreInfo.Url);
Logging.SaveLog(msg);
ShowMsg(false, msg);
}
return fileName;
}
private async Task CoreStart(ProfileItem node) private async Task CoreStart(ProfileItem node)
{ {
var coreType = _config.RunningCoreType = AppHandler.Instance.GetCoreType(node, node.ConfigType); var coreType = _config.RunningCoreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
@@ -191,28 +169,7 @@ namespace ServiceLib.Handler
} }
} }
private async Task<int> CoreStartSpeedtest(string configPath, ECoreType coreType) private void UpdateFunc(bool notify, string msg)
{
try
{
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true, false);
if (proc is null)
{
return -1;
}
return proc.Id;
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
ShowMsg(false, ex.Message);
return -1;
}
}
private void ShowMsg(bool notify, string msg)
{ {
_updateFunc?.Invoke(notify, msg); _updateFunc?.Invoke(notify, msg);
} }
@@ -221,7 +178,7 @@ namespace ServiceLib.Handler
{ {
return _config.TunModeItem.EnableTun return _config.TunModeItem.EnableTun
&& eCoreType == ECoreType.sing_box && eCoreType == ECoreType.sing_box
&& (Utils.IsLinux() || Utils.IsOSX()) && (Utils.IsNonWindows())
//&& _config.TunModeItem.LinuxSudoPwd.IsNotEmpty() //&& _config.TunModeItem.LinuxSudoPwd.IsNotEmpty()
; ;
} }
@@ -230,11 +187,12 @@ namespace ServiceLib.Handler
#region Process #region Process
private async Task<Process?> RunProcess(CoreInfo coreInfo, string configPath, bool displayLog, bool mayNeedSudo) private async Task<Process?> RunProcess(CoreInfo? coreInfo, string configPath, bool displayLog, bool mayNeedSudo)
{ {
var fileName = CoreFindExe(coreInfo); var fileName = CoreInfoHandler.Instance.GetCoreExecFile(coreInfo, out var msg);
if (Utils.IsNullOrEmpty(fileName)) if (Utils.IsNullOrEmpty(fileName))
{ {
UpdateFunc(false, msg);
return null; return null;
} }
@@ -269,12 +227,12 @@ namespace ServiceLib.Handler
proc.OutputDataReceived += (sender, e) => proc.OutputDataReceived += (sender, e) =>
{ {
if (Utils.IsNullOrEmpty(e.Data)) return; if (Utils.IsNullOrEmpty(e.Data)) return;
ShowMsg(false, e.Data + Environment.NewLine); UpdateFunc(false, e.Data + Environment.NewLine);
}; };
proc.ErrorDataReceived += (sender, e) => proc.ErrorDataReceived += (sender, e) =>
{ {
if (Utils.IsNullOrEmpty(e.Data)) return; if (Utils.IsNullOrEmpty(e.Data)) return;
ShowMsg(false, e.Data + Environment.NewLine); UpdateFunc(false, e.Data + Environment.NewLine);
if (!startUpSuccessful) if (!startUpSuccessful)
{ {
@@ -300,6 +258,7 @@ namespace ServiceLib.Handler
proc.BeginErrorReadLine(); proc.BeginErrorReadLine();
} }
AppHandler.Instance.AddProcess(proc.Handle);
if (proc.WaitForExit(1000)) if (proc.WaitForExit(1000))
{ {
proc.CancelErrorRead(); proc.CancelErrorRead();
@@ -315,26 +274,12 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
ShowMsg(true, ex.Message); UpdateFunc(true, ex.Message);
return null; return null;
} }
} }
private async Task<Process?> KillProcess(Process? proc)
{
if (proc is null)
{
return null;
}
try { proc?.Kill(true); } catch { }
try { proc?.Close(); } catch { }
try { proc?.Dispose(); } catch { }
await Task.Delay(100);
return null;
}
#endregion Process #endregion Process
#region Linux #region Linux

View File

@@ -29,6 +29,27 @@
return _coreInfo ?? []; return _coreInfo ?? [];
} }
public string GetCoreExecFile(CoreInfo? coreInfo, out string msg)
{
var fileName = string.Empty;
msg = string.Empty;
foreach (var name in coreInfo?.CoreExes)
{
var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());
if (File.Exists(vName))
{
fileName = vName;
break;
}
}
if (fileName.IsNullOrEmpty())
{
msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.CoreType.ToString()), string.Join(", ", coreInfo.CoreExes.ToArray()), coreInfo.Url);
Logging.SaveLog(msg);
}
return fileName;
}
private void InitCoreInfo() private void InitCoreInfo()
{ {
_coreInfo = []; _coreInfo = [];

View File

@@ -2,6 +2,8 @@
{ {
public class FmtHandler public class FmtHandler
{ {
private static readonly string _tag = "FmtHandler";
public static string? GetShareUri(ProfileItem item) public static string? GetShareUri(ProfileItem item)
{ {
try try
@@ -23,7 +25,7 @@
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
return ""; return "";
} }
} }
@@ -81,7 +83,7 @@
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
msg = ResUI.Incorrectconfiguration; msg = ResUI.Incorrectconfiguration;
return null; return null;
} }

View File

@@ -10,6 +10,7 @@ namespace ServiceLib.Handler
private ConcurrentBag<ProfileExItem> _lstProfileEx = []; private ConcurrentBag<ProfileExItem> _lstProfileEx = [];
private Queue<string> _queIndexIds = new(); private Queue<string> _queIndexIds = new();
public static ProfileExHandler Instance => _instance.Value; public static ProfileExHandler Instance => _instance.Value;
private static readonly string _tag = "ProfileExHandler";
public ProfileExHandler() public ProfileExHandler()
{ {
@@ -87,7 +88,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("ProfileExHandler", ex); Logging.SaveLog(_tag, ex);
} }
} }
} }
@@ -119,7 +120,7 @@ namespace ServiceLib.Handler
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }

View File

@@ -12,7 +12,7 @@
private StatisticsXrayService? _statisticsXray; private StatisticsXrayService? _statisticsXray;
private StatisticsSingboxService? _statisticsSingbox; private StatisticsSingboxService? _statisticsSingbox;
private static readonly string _tag = "StatisticsHandler";
public List<ServerStatItem> ServerStat => _lstServerStat; public List<ServerStatItem> ServerStat => _lstServerStat;
public async Task Init(Config config, Action<ServerSpeedItem> updateFunc) public async Task Init(Config config, Action<ServerSpeedItem> updateFunc)
@@ -39,7 +39,7 @@
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }
@@ -61,7 +61,7 @@
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }
@@ -72,6 +72,11 @@
return; return;
} }
if(indexId == toIndexId)
{
return;
}
var stat = _lstServerStat.FirstOrDefault(t => t.IndexId == indexId); var stat = _lstServerStat.FirstOrDefault(t => t.IndexId == indexId);
if (stat == null) if (stat == null)
{ {

View File

@@ -2,9 +2,9 @@
{ {
public class ProxySettingLinux public class ProxySettingLinux
{ {
public static async Task SetProxy(string host, int port) public static async Task SetProxy(string host, int port, string exceptions)
{ {
var lstCmd = GetSetCmds(host, port); var lstCmd = GetSetCmds(host, port, exceptions);
await ExecCmd(lstCmd); await ExecCmd(lstCmd);
} }
@@ -29,25 +29,39 @@
} }
} }
private static List<CmdItem> GetSetCmds(string host, int port) private static List<CmdItem> GetSetCmds(string host, int port, string exceptions)
{ {
var isKde = IsKde(out var configDir); var isKde = IsKde(out var configDir);
List<string> lstType = ["", "http", "https", "socks", "ftp"]; List<string> lstType = ["", "http", "https", "socks", "ftp"];
List<CmdItem> lstCmd = []; List<CmdItem> lstCmd = [];
//GNOME
foreach (var type in lstType)
{
lstCmd.AddRange(GetSetCmd4Gnome(type, host, port));
}
if (exceptions.IsNotEmpty())
{
lstCmd.AddRange(GetSetCmd4Gnome("exceptions", exceptions, 0));
}
if (isKde) if (isKde)
{ {
foreach (var type in lstType) foreach (var type in lstType)
{ {
lstCmd.AddRange(GetSetCmd4Kde(type, host, port, configDir)); lstCmd.AddRange(GetSetCmd4Kde(type, host, port, configDir));
} }
} if (exceptions.IsNotEmpty())
else
{
foreach (var type in lstType)
{ {
lstCmd.AddRange(GetSetCmd4Gnome(type, host, port)); lstCmd.AddRange(GetSetCmd4Kde("exceptions", exceptions, 0, configDir));
} }
// Notify system to reload
lstCmd.Add(new CmdItem()
{
Cmd = "dbus-send",
Arguments = ["--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''"]
});
} }
return lstCmd; return lstCmd;
} }
@@ -57,44 +71,58 @@
var isKde = IsKde(out var configDir); var isKde = IsKde(out var configDir);
List<CmdItem> lstCmd = []; List<CmdItem> lstCmd = [];
//GNOME
lstCmd.Add(new CmdItem()
{
Cmd = "gsettings",
Arguments = ["set", "org.gnome.system.proxy", "mode", "none"]
});
if (isKde) if (isKde)
{ {
lstCmd.Add(new CmdItem() lstCmd.Add(new CmdItem()
{ {
Cmd = "kwriteconfig5", Cmd = GetKdeVersion(),
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "0"] Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "0"]
}); });
}
else // Notify system to reload
{
lstCmd.Add(new CmdItem() lstCmd.Add(new CmdItem()
{ {
Cmd = "gsettings", Cmd = "dbus-send",
Arguments = ["set", "org.gnome.system.proxy", "mode", "none"] Arguments = ["--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''"]
}); });
} }
return lstCmd; return lstCmd;
} }
private static List<CmdItem> GetSetCmd4Kde(string type, string host, int port, string configDir) private static List<CmdItem> GetSetCmd4Kde(string type, string host, int port, string configDir)
{ {
List<CmdItem> lstCmd = []; List<CmdItem> lstCmd = [];
var cmd = GetKdeVersion();
if (type.IsNullOrEmpty()) if (type.IsNullOrEmpty())
{ {
lstCmd.Add(new() lstCmd.Add(new()
{ {
Cmd = "kwriteconfig5", Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "1"] Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "1"]
}); });
} }
else if (type == "exceptions")
{
lstCmd.Add(new()
{
Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "NoProxyFor", host]
});
}
else else
{ {
var type2 = type.Equals("https") ? "http" : type; var type2 = type.Equals("https") ? "http" : type;
lstCmd.Add(new CmdItem() lstCmd.Add(new CmdItem()
{ {
Cmd = "kwriteconfig5", Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", $"{type}Proxy", $"{type2}://{host}:{port}"] Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", $"{type}Proxy", $"{type2}://{host}:{port}"]
}); });
} }
@@ -114,6 +142,14 @@
Arguments = ["set", "org.gnome.system.proxy", "mode", "manual"] Arguments = ["set", "org.gnome.system.proxy", "mode", "manual"]
}); });
} }
else if (type == "exceptions")
{
lstCmd.Add(new()
{
Cmd = "gsettings",
Arguments = ["set", $"org.gnome.system.proxy", "ignore-hosts", JsonUtils.Serialize(host.Split(','), false)]
});
}
else else
{ {
lstCmd.Add(new() lstCmd.Add(new()
@@ -136,7 +172,11 @@
{ {
configDir = "/home"; configDir = "/home";
var desktop = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP"); var desktop = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP");
var isKde = string.Equals(desktop, "KDE", StringComparison.OrdinalIgnoreCase); var desktop2 = Environment.GetEnvironmentVariable("XDG_SESSION_DESKTOP");
var isKde = string.Equals(desktop, "KDE", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop, "plasma", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop2, "KDE", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop2, "plasma", StringComparison.OrdinalIgnoreCase);
if (isKde) if (isKde)
{ {
var homeDir = Environment.GetEnvironmentVariable("HOME"); var homeDir = Environment.GetEnvironmentVariable("HOME");
@@ -148,5 +188,15 @@
return isKde; return isKde;
} }
private static string GetKdeVersion()
{
var ver = Environment.GetEnvironmentVariable("KDE_SESSION_VERSION") ?? "0";
return ver switch
{
"6" => "kwriteconfig6",
_ => "kwriteconfig5"
};
}
} }
} }

View File

@@ -2,29 +2,27 @@
{ {
public class ProxySettingOSX public class ProxySettingOSX
{ {
/*
* 仅测试了MacOS 13.7.1 x86 版本,其他版本有待确认
*/
/// <summary> /// <summary>
/// 应用接口类型 /// 应用接口类型
/// </summary> /// </summary>
private static readonly List<string> LstInterface = ["Ethernet", "Wi-Fi", "Thunderbolt Bridge"]; private static readonly List<string> LstInterface = ["Ethernet", "Wi-Fi", "Thunderbolt Bridge", "USB 10/100/1000 LAN"];
/// <summary> /// <summary>
/// 代理类型,对应 http,https,socks /// 代理类型,对应 http,https,socks
/// </summary> /// </summary>
private static readonly List<string> LstTypes = ["setwebproxy", "setsecurewebproxy", "setsocksfirewallproxy"]; private static readonly List<string> LstTypes = ["setwebproxy", "setsecurewebproxy", "setsocksfirewallproxy"];
public static async Task SetProxy(string host, int port) public static async Task SetProxy(string host, int port, string exceptions)
{ {
var lstCmd = GetSetCmds(host, port); var lstInterface = await GetListNetworkServices();
var lstCmd = GetSetCmds(lstInterface, host, port, exceptions);
await ExecCmd(lstCmd); await ExecCmd(lstCmd);
} }
public static async Task UnsetProxy() public static async Task UnsetProxy()
{ {
var lstCmd = GetUnsetCmds(); var lstInterface = await GetListNetworkServices();
var lstCmd = GetUnsetCmds(lstInterface);
await ExecCmd(lstCmd); await ExecCmd(lstCmd);
} }
@@ -42,17 +40,27 @@
} }
} }
private static List<CmdItem> GetSetCmds(string host, int port) private static List<CmdItem> GetSetCmds(List<string> lstInterface, string host, int port, string exceptions)
{ {
List<CmdItem> lstCmd = []; List<CmdItem> lstCmd = [];
foreach (var interf in LstInterface) foreach (var interf in lstInterface)
{ {
foreach (var type in LstTypes) foreach (var type in LstTypes)
{ {
lstCmd.Add(new CmdItem() lstCmd.Add(new CmdItem()
{ {
Cmd = "networksetup", Cmd = "networksetup",
Arguments = [$"-{type}", interf, host, (type.Contains("socks") ? (port - 1) : port).ToString()] Arguments = [$"-{type}", interf, host, port.ToString()]
});
}
if (exceptions.IsNotEmpty())
{
List<string> args = [$"-setproxybypassdomains", interf];
args.AddRange(exceptions.Split(','));
lstCmd.Add(new CmdItem()
{
Cmd = "networksetup",
Arguments = args
}); });
} }
} }
@@ -60,10 +68,10 @@
return lstCmd; return lstCmd;
} }
private static List<CmdItem> GetUnsetCmds() private static List<CmdItem> GetUnsetCmds(List<string> lstInterface)
{ {
List<CmdItem> lstCmd = []; List<CmdItem> lstCmd = [];
foreach (var interf in LstInterface) foreach (var interf in lstInterface)
{ {
foreach (var type in LstTypes) foreach (var type in LstTypes)
{ {
@@ -77,5 +85,17 @@
return lstCmd; return lstCmd;
} }
public static async Task<List<string>> GetListNetworkServices()
{
var services = await Utils.GetListNetworkServices();
if (services.IsNullOrEmpty())
{
return LstInterface;
}
var lst = services.Split(Environment.NewLine).Where(t => t.Length > 0 && t.Contains('*') == false);
return lst.ToList();
}
} }
} }

View File

@@ -72,7 +72,6 @@ namespace ServiceLib.Handler.SysProxy
catch (Exception ex) catch (Exception ex)
{ {
SetProxyFallback(strProxy, exceptions, type); SetProxyFallback(strProxy, exceptions, type);
//Logging.SaveLog(ex.Message, ex);
return false; return false;
} }
} }

View File

@@ -2,6 +2,8 @@
{ {
public static class SysProxyHandler public static class SysProxyHandler
{ {
private static readonly string _tag = "SysProxyHandler";
public static async Task<bool> UpdateSysProxy(Config config, bool forceDisable) public static async Task<bool> UpdateSysProxy(Config config, bool forceDisable)
{ {
var type = config.SystemProxyItem.SysProxyType; var type = config.SystemProxyItem.SysProxyType;
@@ -14,6 +16,7 @@
try try
{ {
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks); var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
var exceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
if (port <= 0) if (port <= 0)
{ {
return false; return false;
@@ -27,11 +30,11 @@
break; break;
} }
case ESysProxyType.ForcedChange when Utils.IsLinux(): case ESysProxyType.ForcedChange when Utils.IsLinux():
await ProxySettingLinux.SetProxy(Global.Loopback, port); await ProxySettingLinux.SetProxy(Global.Loopback, port, exceptions);
break; break;
case ESysProxyType.ForcedChange when Utils.IsOSX(): case ESysProxyType.ForcedChange when Utils.IsOSX():
await ProxySettingOSX.SetProxy(Global.Loopback, port); await ProxySettingOSX.SetProxy(Global.Loopback, port, exceptions);
break; break;
case ESysProxyType.ForcedClear when Utils.IsWindows(): case ESysProxyType.ForcedClear when Utils.IsWindows():
@@ -58,14 +61,14 @@
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return true; return true;
} }
private static void GetWindowsProxyString(Config config, int port, out string strProxy, out string strExceptions) private static void GetWindowsProxyString(Config config, int port, out string strProxy, out string strExceptions)
{ {
strExceptions = $"{config.ConstItem.DefIEProxyExceptions};{config.SystemProxyItem.SystemProxyExceptions}"; strExceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
if (config.SystemProxyItem.NotProxyLocalAddress) if (config.SystemProxyItem.NotProxyLocalAddress)
{ {
strExceptions = $"<local>;{strExceptions}"; strExceptions = $"<local>;{strExceptions}";

View File

@@ -13,7 +13,7 @@ namespace ServiceLib.Handler
private string? _lastDescription; private string? _lastDescription;
private string _webDir = Global.AppName + "_backup"; private string _webDir = Global.AppName + "_backup";
private readonly string _webFileName = "backup.zip"; private readonly string _webFileName = "backup.zip";
private string _logTitle = "WebDav--"; private readonly string _tag = "WebDav--";
public WebDavHandler() public WebDavHandler()
{ {
@@ -81,13 +81,13 @@ namespace ServiceLib.Handler
private void SaveLog(string desc) private void SaveLog(string desc)
{ {
_lastDescription = desc; _lastDescription = desc;
Logging.SaveLog(_logTitle + desc); Logging.SaveLog(_tag + desc);
} }
private void SaveLog(Exception ex) private void SaveLog(Exception ex)
{ {
_lastDescription = ex.Message; _lastDescription = ex.Message;
Logging.SaveLog(_logTitle, ex); Logging.SaveLog(_tag, ex);
} }
public async Task<bool> CheckConnection() public async Task<bool> CheckConnection()

View File

@@ -47,6 +47,7 @@
public SystemProxyItem SystemProxyItem { get; set; } public SystemProxyItem SystemProxyItem { get; set; }
public WebDavItem WebDavItem { get; set; } public WebDavItem WebDavItem { get; set; }
public CheckUpdateItem CheckUpdateItem { get; set; } public CheckUpdateItem CheckUpdateItem { get; set; }
public Fragment4RayItem? Fragment4RayItem { get; set; }
public List<InItem> Inbound { get; set; } public List<InItem> Inbound { get; set; }
public List<KeyEventItem> GlobalHotkeys { get; set; } public List<KeyEventItem> GlobalHotkeys { get; set; }
public List<CoreTypeItem> CoreTypeItem { get; set; } public List<CoreTypeItem> CoreTypeItem { get; set; }

View File

@@ -24,21 +24,16 @@
public class InItem public class InItem
{ {
public int LocalPort { get; set; } public int LocalPort { get; set; }
public string Protocol { get; set; } public string Protocol { get; set; }
public bool UdpEnabled { get; set; } public bool UdpEnabled { get; set; }
public bool SniffingEnabled { get; set; } = true; public bool SniffingEnabled { get; set; } = true;
public List<string>? DestOverride { get; set; } = ["http", "tls"]; public List<string>? DestOverride { get; set; } = ["http", "tls"];
public bool RouteOnly { get; set; } public bool RouteOnly { get; set; }
public bool AllowLANConn { get; set; } public bool AllowLANConn { get; set; }
public bool NewPort4LAN { get; set; } public bool NewPort4LAN { get; set; }
public string User { get; set; } public string User { get; set; }
public string Pass { get; set; } public string Pass { get; set; }
public bool SecondLocalPortEnabled { get; set; }
} }
[Serializable] [Serializable]
@@ -107,9 +102,8 @@
public double MainGirdHeight1 { get; set; } public double MainGirdHeight1 { get; set; }
public double MainGirdHeight2 { get; set; } public double MainGirdHeight2 { get; set; }
public EGirdOrientation MainGirdOrientation { get; set; } = EGirdOrientation.Vertical; public EGirdOrientation MainGirdOrientation { get; set; } = EGirdOrientation.Vertical;
public bool ColorModeDark { get; set; }
public bool FollowSystemTheme { get; set; }
public string? ColorPrimaryName { get; set; } public string? ColorPrimaryName { get; set; }
public string? CurrentTheme { get; set; }
public string CurrentLanguage { get; set; } public string CurrentLanguage { get; set; }
public string CurrentFontFamily { get; set; } public string CurrentFontFamily { get; set; }
public int CurrentFontSize { get; set; } public int CurrentFontSize { get; set; }
@@ -124,8 +118,7 @@
[Serializable] [Serializable]
public class ConstItem public class ConstItem
{ {
public string DefIEProxyExceptions { get; set; } public string? SubConvertUrl { get; set; }
public string SubConvertUrl { get; set; } = string.Empty;
public string? GeoSourceUrl { get; set; } public string? GeoSourceUrl { get; set; }
public string? SrsSourceUrl { get; set; } public string? SrsSourceUrl { get; set; }
public string? RouteRulesTemplateSourceUrl { get; set; } public string? RouteRulesTemplateSourceUrl { get; set; }
@@ -251,4 +244,12 @@
public bool CheckPreReleaseUpdate { get; set; } public bool CheckPreReleaseUpdate { get; set; }
public List<string>? SelectedCoreTypes { get; set; } public List<string>? SelectedCoreTypes { get; set; }
} }
[Serializable]
public class Fragment4RayItem
{
public string? Packets { get; set; }
public string? Length { get; set; }
public string? Interval { get; set; }
}
} }

View File

@@ -324,7 +324,8 @@ namespace ServiceLib.Models
public class WsSettings4Ray public class WsSettings4Ray
{ {
public string path { get; set; } public string? path { get; set; }
public string? host { get; set; }
public Headers4Ray headers { get; set; } public Headers4Ray headers { get; set; }
} }
@@ -349,21 +350,9 @@ namespace ServiceLib.Models
public string? path { get; set; } public string? path { get; set; }
public string? host { get; set; } public string? host { get; set; }
public string? mode { get; set; } public string? mode { get; set; }
public object? scMaxEachPostBytes { get; set; }
public object? scMaxConcurrentPosts { get; set; }
public object? scMinPostsIntervalMs { get; set; }
//public Xmux4Ray? xmux { get; set; }
public object? extra { get; set; } public object? extra { get; set; }
} }
//public class Xmux4Ray
//{
// public object? maxConcurrency { get; set; }
// public object? maxConnections { get; set; }
// public object? cMaxReuseTimes { get; set; }
// public object? cMaxLifetimeMs { get; set; }
//}
public class HttpSettings4Ray public class HttpSettings4Ray
{ {
public string? path { get; set; } public string? path { get; set; }

View File

@@ -843,6 +843,15 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Copy proxy command to clipboard 的本地化字符串。
/// </summary>
public static string menuCopyProxyCmdToClipboard {
get {
return ResourceManager.GetString("menuCopyProxyCmdToClipboard", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Clone selected server 的本地化字符串。 /// 查找类似 Clone selected server 的本地化字符串。
/// </summary> /// </summary>
@@ -942,15 +951,6 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Import old config (guiNConfig) 的本地化字符串。
/// </summary>
public static string menuImportOldGuiConfig {
get {
return ResourceManager.GetString("menuImportOldGuiConfig", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Import Rules From Clipboard 的本地化字符串。 /// 查找类似 Import Rules From Clipboard 的本地化字符串。
/// </summary> /// </summary>
@@ -1248,6 +1248,15 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Iran 的本地化字符串。
/// </summary>
public static string menuRegionalPresetsIran {
get {
return ResourceManager.GetString("menuRegionalPresetsIran", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Russia 的本地化字符串。 /// 查找类似 Russia 的本地化字符串。
/// </summary> /// </summary>
@@ -1339,7 +1348,7 @@ namespace ServiceLib.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Import Advanced Rules 的本地化字符串。 /// 查找类似 Import Rules 的本地化字符串。
/// </summary> /// </summary>
public static string menuRoutingAdvancedImportRules { public static string menuRoutingAdvancedImportRules {
get { get {
@@ -1527,15 +1536,6 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Save Interface Layout 的本地化字符串。
/// </summary>
public static string menuStorageUI {
get {
return ResourceManager.GetString("menuStorageUI", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Add 的本地化字符串。 /// 查找类似 Add 的本地化字符串。
/// </summary> /// </summary>
@@ -2347,15 +2347,6 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Enable advanced function 的本地化字符串。
/// </summary>
public static string TbenableRoutingAdvanced {
get {
return ResourceManager.GetString("TbenableRoutingAdvanced", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Enable Tun 的本地化字符串。 /// 查找类似 Enable Tun 的本地化字符串。
/// </summary> /// </summary>
@@ -2599,6 +2590,15 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 socks: local port, socks2: second local port, socks3: LAN port 的本地化字符串。
/// </summary>
public static string TbRoutingInboundTagTips {
get {
return ResourceManager.GetString("TbRoutingInboundTagTips", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Domain 的本地化字符串。 /// 查找类似 Domain 的本地化字符串。
/// </summary> /// </summary>
@@ -2797,15 +2797,6 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Dark Mode 的本地化字符串。
/// </summary>
public static string TbSettingsColorMode {
get {
return ResourceManager.GetString("TbSettingsColorMode", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Core: basic settings 的本地化字符串。 /// 查找类似 Core: basic settings 的本地化字符串。
/// </summary> /// </summary>
@@ -2914,6 +2905,15 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Sniffing type 的本地化字符串。
/// </summary>
public static string TbSettingsDestOverride {
get {
return ResourceManager.GetString("TbSettingsDestOverride", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Outbound DNS address 的本地化字符串。 /// 查找类似 Outbound DNS address 的本地化字符串。
/// </summary> /// </summary>
@@ -3059,11 +3059,11 @@ namespace ServiceLib.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Follow System Theme 的本地化字符串。 /// 查找类似 Exception. Do not use proxy server for addresses,with a comma (,) 的本地化字符串。
/// </summary> /// </summary>
public static string TbSettingsFollowSystemTheme { public static string TbSettingsExceptionTip2 {
get { get {
return ResourceManager.GetString("TbSettingsFollowSystemTheme", resourceCulture); return ResourceManager.GetString("TbSettingsExceptionTip2", resourceCulture);
} }
} }
@@ -3292,6 +3292,15 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Enable second mixed port 的本地化字符串。
/// </summary>
public static string TbSettingsSecondLocalPortEnabled {
get {
return ResourceManager.GetString("TbSettingsSecondLocalPortEnabled", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Set Win10 UWP Loopback 的本地化字符串。 /// 查找类似 Set Win10 UWP Loopback 的本地化字符串。
/// </summary> /// </summary>
@@ -3320,7 +3329,7 @@ namespace ServiceLib.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Pac port = +2; Xray API port = +3; mihomo API port = +4; 的本地化字符串。 /// 查找类似 Pac port = +3; Xray API port = +4; mihomo API port = +5; 的本地化字符串。
/// </summary> /// </summary>
public static string TbSettingsSocksPortTip { public static string TbSettingsSocksPortTip {
get { get {
@@ -3418,6 +3427,15 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Theme 的本地化字符串。
/// </summary>
public static string TbSettingsTheme {
get {
return ResourceManager.GetString("TbSettingsTheme", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Enable Security Protocol TLS v1.3 (subscription/update) 的本地化字符串。 /// 查找类似 Enable Security Protocol TLS v1.3 (subscription/update) 的本地化字符串。
/// </summary> /// </summary>

View File

@@ -118,7 +118,7 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="BatchExportURLSuccessfully" xml:space="preserve"> <data name="BatchExportURLSuccessfully" xml:space="preserve">
<value>Batch export share URL to clipboard successfully</value> <value>ارسال دسته ای آدرس اینترنتی اشتراک گذاری به کلیپ بورد با موفقیت.</value>
</data> </data>
<data name="CheckServerSettings" xml:space="preserve"> <data name="CheckServerSettings" xml:space="preserve">
<value>لطفا ابتدا تنظیمات سرور را بررسی کنید</value> <value>لطفا ابتدا تنظیمات سرور را بررسی کنید</value>
@@ -136,7 +136,7 @@
<value>دانلود</value> <value>دانلود</value>
</data> </data>
<data name="DownloadYesNo" xml:space="preserve"> <data name="DownloadYesNo" xml:space="preserve">
<value>Whether to download? {0}</value> <value>آیا برای دانلود؟ {0}</value>
</data> </data>
<data name="FailedConversionConfiguration" xml:space="preserve"> <data name="FailedConversionConfiguration" xml:space="preserve">
<value>تبدیل فایل پیکربندی انجام نشد</value> <value>تبدیل فایل پیکربندی انجام نشد</value>
@@ -226,7 +226,7 @@
<value>هیچ اشتراک معتبری تنظیم نشده است</value> <value>هیچ اشتراک معتبری تنظیم نشده است</value>
</data> </data>
<data name="MsgParsingSuccessfully" xml:space="preserve"> <data name="MsgParsingSuccessfully" xml:space="preserve">
<value>Resolve {0} successfully</value> <value>حل {0} با موفقیت</value>
</data> </data>
<data name="MsgStartGettingSubscriptions" xml:space="preserve"> <data name="MsgStartGettingSubscriptions" xml:space="preserve">
<value>شروع به دریافت اشتراک شد</value> <value>شروع به دریافت اشتراک شد</value>
@@ -253,19 +253,19 @@
<value>هسته با موفقیت بروزرسانی شد! راه اندازی مجدد سرویس...</value> <value>هسته با موفقیت بروزرسانی شد! راه اندازی مجدد سرویس...</value>
</data> </data>
<data name="NonvmessOrssProtocol" xml:space="preserve"> <data name="NonvmessOrssProtocol" xml:space="preserve">
<value>Non-VMess or ss protocol</value> <value>پروتکل غیر VMess یا ss</value>
</data> </data>
<data name="NotFoundCore" xml:space="preserve"> <data name="NotFoundCore" xml:space="preserve">
<value>The Core file (file name: {1}) was not found under the folder ({0}), please download and put it in the folder, download address: {2}</value> <value>فایل Core (نام فایل: {1}) در زیر پوشه ({0}) یافت نشد، لطفاً آن را دانلود کرده و در پوشه قرار دهید، آدرس دانلود: {2}</value>
</data> </data>
<data name="NoValidQRcodeFound" xml:space="preserve"> <data name="NoValidQRcodeFound" xml:space="preserve">
<value>Scan completed, no valid QR code found</value> <value>اسکن کامل شد، QRcode معتبری یافت نشد</value>
</data> </data>
<data name="OperationFailed" xml:space="preserve"> <data name="OperationFailed" xml:space="preserve">
<value> عملیات انجام نشد، لطفا بررسی کنید و دوباره امتحان کنید</value> <value> عملیات انجام نشد، لطفا بررسی کنید و دوباره امتحان کنید</value>
</data> </data>
<data name="PleaseFillRemarks" xml:space="preserve"> <data name="PleaseFillRemarks" xml:space="preserve">
<value>Please Fill Remarks</value> <value>لطفا ملاحظات را پر کنید</value>
</data> </data>
<data name="PleaseSelectEncryption" xml:space="preserve"> <data name="PleaseSelectEncryption" xml:space="preserve">
<value>لطفاً روش رمزگذاری را انتخاب کنید</value> <value>لطفاً روش رمزگذاری را انتخاب کنید</value>
@@ -277,16 +277,16 @@
<value>لطفا ابتدا سرور را انتخاب کنید</value> <value>لطفا ابتدا سرور را انتخاب کنید</value>
</data> </data>
<data name="RemoveDuplicateServerResult" xml:space="preserve"> <data name="RemoveDuplicateServerResult" xml:space="preserve">
<value>Servers deduplication completed. Old: {0}, New: {1}.</value> <value>حذف مجدد سرورها تکمیل شد. قدیمی: {0}، جدید: {1}.</value>
</data> </data>
<data name="RemoveServer" xml:space="preserve"> <data name="RemoveServer" xml:space="preserve">
<value>آیا مطمئن هستید که سرور را حذف می کنید؟</value> <value>آیا مطمئن هستید که سرور را حذف می کنید؟</value>
</data> </data>
<data name="SaveClientConfigurationIn" xml:space="preserve"> <data name="SaveClientConfigurationIn" xml:space="preserve">
<value>The client configuration file is saved at: {0}</value> <value>فایل پیکربندی کلاینت در این آدرس ذخیره می شود: {0}</value>
</data> </data>
<data name="StartService" xml:space="preserve"> <data name="StartService" xml:space="preserve">
<value>Start service ({0})...</value> <value>شروع سرویس ({0})...</value>
</data> </data>
<data name="SuccessfulConfiguration" xml:space="preserve"> <data name="SuccessfulConfiguration" xml:space="preserve">
<value>پیکربندی با موفقیت انجام شد <value>پیکربندی با موفقیت انجام شد
@@ -317,19 +317,19 @@
<value>{0},یکی از مورد نیاز.</value> <value>{0},یکی از مورد نیاز.</value>
</data> </data>
<data name="LvRemarks" xml:space="preserve"> <data name="LvRemarks" xml:space="preserve">
<value>Remarks</value> <value>ملاحظات</value>
</data> </data>
<data name="LvUrl" xml:space="preserve"> <data name="LvUrl" xml:space="preserve">
<value>Url(Optional)</value> <value>آدرس اینترنتی (اختیاری)</value>
</data> </data>
<data name="LvCount" xml:space="preserve"> <data name="LvCount" xml:space="preserve">
<value>Count</value> <value>شمارش</value>
</data> </data>
<data name="MsgNeedUrl" xml:space="preserve"> <data name="MsgNeedUrl" xml:space="preserve">
<value>Please fill in the address (Url)</value> <value>لطفا آدرس (آدرس اینترنتی) را وارد کنید</value>
</data> </data>
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve"> <data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
<value>Do you want to append rules? Choose yes to append, choose otherwise to replace</value> <value>آیا می خواهید قوانین را اضافه کنید؟ برای ضمیمه بله را انتخاب کنید، در غیر این صورت جایگزین کنید</value>
</data> </data>
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve"> <data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
<value>دانلود GeoFile: {0} با موفقیت</value> <value>دانلود GeoFile: {0} با موفقیت</value>
@@ -386,10 +386,10 @@
<value>*Kcp seed</value> <value>*Kcp seed</value>
</data> </data>
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve"> <data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
<value>Global hotkey {0} registered failed, reason {1}</value> <value>کلید میانبر جهانی {0} ثبت نشد، دلیل کلید میانبر جهانی {0} ثبت ناموفق بود، دلیل {1}{1}</value>
</data> </data>
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve"> <data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
<value>Global hotkey {0} registered successfully</value> <value>کلید میانبر جهانی {0} با موفقیت ثبت شد</value>
</data> </data>
<data name="UngroupedServers" xml:space="preserve"> <data name="UngroupedServers" xml:space="preserve">
<value>گروه بندی نشده</value> <value>گروه بندی نشده</value>
@@ -398,7 +398,7 @@
<value>همه سرورها</value> <value>همه سرورها</value>
</data> </data>
<data name="FillServerAddressCustom" xml:space="preserve"> <data name="FillServerAddressCustom" xml:space="preserve">
<value>Please browse to import server configuration</value> <value>لطفاً برای وارد کردن پیکربندی سرور مرور کنید</value>
</data> </data>
<data name="Speedtesting" xml:space="preserve"> <data name="Speedtesting" xml:space="preserve">
<value>درحال تست کردن...</value> <value>درحال تست کردن...</value>
@@ -481,9 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve"> <data name="TbSettingsColor" xml:space="preserve">
<value>رنگ</value> <value>رنگ</value>
</data> </data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>حالت تاریک</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve"> <data name="TbSettingsLanguage" xml:space="preserve">
<value>زبان</value> <value>زبان</value>
</data> </data>
@@ -593,7 +590,7 @@
<value>آدرس</value> <value>آدرس</value>
</data> </data>
<data name="TbAllowInsecure" xml:space="preserve"> <data name="TbAllowInsecure" xml:space="preserve">
<value>اجازه ناامن</value> <value>اعطای مجوز ناامن</value>
</data> </data>
<data name="TbAlpn" xml:space="preserve"> <data name="TbAlpn" xml:space="preserve">
<value>Alpn</value> <value>Alpn</value>
@@ -602,10 +599,10 @@
<value>AlterId</value> <value>AlterId</value>
</data> </data>
<data name="TbFingerprint" xml:space="preserve"> <data name="TbFingerprint" xml:space="preserve">
<value>Fingerprint</value> <value>اثرانگشت</value>
</data> </data>
<data name="TbHeaderType" xml:space="preserve"> <data name="TbHeaderType" xml:space="preserve">
<value>Camouflage type</value> <value>نوع Camouflage</value>
</data> </data>
<data name="TbId" xml:space="preserve"> <data name="TbId" xml:space="preserve">
<value>UUID(id)</value> <value>UUID(id)</value>
@@ -620,13 +617,13 @@
<value>پورت</value> <value>پورت</value>
</data> </data>
<data name="TbRemarks" xml:space="preserve"> <data name="TbRemarks" xml:space="preserve">
<value>Alias (remarks)</value> <value>نام مستعار (ملاحظات)</value>
</data> </data>
<data name="TbRequestHost" xml:space="preserve"> <data name="TbRequestHost" xml:space="preserve">
<value>Camouflage domain(host)</value> <value>Camouflage domain(host)</value>
</data> </data>
<data name="TbSecurity" xml:space="preserve"> <data name="TbSecurity" xml:space="preserve">
<value>Encryption method (security)</value> <value>روش رمزگذاری (امنیتی)</value>
</data> </data>
<data name="TbSNI" xml:space="preserve"> <data name="TbSNI" xml:space="preserve">
<value>SNI</value> <value>SNI</value>
@@ -635,7 +632,7 @@
<value>TLS</value> <value>TLS</value>
</data> </data>
<data name="TipNetwork" xml:space="preserve"> <data name="TipNetwork" xml:space="preserve">
<value>*Default value tcp</value> <value>*مقدار پیش فرض tcp</value>
</data> </data>
<data name="TbCoreType" xml:space="preserve"> <data name="TbCoreType" xml:space="preserve">
<value>نوع هسته</value> <value>نوع هسته</value>
@@ -644,7 +641,7 @@
<value>جریان</value> <value>جریان</value>
</data> </data>
<data name="TbGUID" xml:space="preserve"> <data name="TbGUID" xml:space="preserve">
<value>Generate</value> <value>ساختن</value>
</data> </data>
<data name="TbId3" xml:space="preserve"> <data name="TbId3" xml:space="preserve">
<value>رمزعبور</value> <value>رمزعبور</value>
@@ -668,10 +665,10 @@
<value>txtPreSocksPort</value> <value>txtPreSocksPort</value>
</data> </data>
<data name="TipPreSocksPort" xml:space="preserve"> <data name="TipPreSocksPort" xml:space="preserve">
<value>* After setting this value, an socks service will be started using Xray/sing-box(Tun) to provide functions such as speed display</value> <value>* پس از تنظیم این مقدار، یک سرویس جوراب با استفاده از Xray/sing-box (Tun) برای ارائه عملکردهایی مانند نمایش سرعت شروع می شود.</value>
</data> </data>
<data name="TbBrowse" xml:space="preserve"> <data name="TbBrowse" xml:space="preserve">
<value>Browse</value> <value>مرور کردن</value>
</data> </data>
<data name="TbEdit" xml:space="preserve"> <data name="TbEdit" xml:space="preserve">
<value>ویرایش</value> <value>ویرایش</value>
@@ -683,7 +680,7 @@
<value>اتصالات از LAN را مجاز کنید</value> <value>اتصالات از LAN را مجاز کنید</value>
</data> </data>
<data name="TbSettingsAutoHideStartup" xml:space="preserve"> <data name="TbSettingsAutoHideStartup" xml:space="preserve">
<value>Auto hide startup</value> <value>راه اندازی مخفی کردن خودکار</value>
</data> </data>
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve"> <data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
<value>فاصله به روز رسانی خودکار و Geo (ساعت)</value> <value>فاصله به روز رسانی خودکار و Geo (ساعت)</value>
@@ -692,7 +689,7 @@
<value>هسته: تنظیمات اولیه</value> <value>هسته: تنظیمات اولیه</value>
</data> </data>
<data name="TbSettingsCoreDns" xml:space="preserve"> <data name="TbSettingsCoreDns" xml:space="preserve">
<value>V2ray DNS settings</value> <value>تنظیمات V2ray DNS</value>
</data> </data>
<data name="TbSettingsCoreKcp" xml:space="preserve"> <data name="TbSettingsCoreKcp" xml:space="preserve">
<value>هسته: تنظیمات KCP</value> <value>هسته: تنظیمات KCP</value>
@@ -701,7 +698,7 @@
<value>تنظیمات CoreType</value> <value>تنظیمات CoreType</value>
</data> </data>
<data name="TbSettingsDefAllowInsecure" xml:space="preserve"> <data name="TbSettingsDefAllowInsecure" xml:space="preserve">
<value>اجازه ناامن</value> <value>اعطای مجوز ناامن</value>
</data> </data>
<data name="TbSettingsDomainStrategy4Freedom" xml:space="preserve"> <data name="TbSettingsDomainStrategy4Freedom" xml:space="preserve">
<value>Outbound Freedom domainStrategy</value> <value>Outbound Freedom domainStrategy</value>
@@ -716,7 +713,7 @@
<value>استثنا</value> <value>استثنا</value>
</data> </data>
<data name="TbSettingsExceptionTip" xml:space="preserve"> <data name="TbSettingsExceptionTip" xml:space="preserve">
<value>Exception. Do not use proxy server for addresses beginning with,Use semicolon (;)</value> <value>استثنا: از سرور پروکسی برای آدرس هایی که با شروع می شوند استفاده نکنید، از نقطه ویرگول (;) استفاده کنید.</value>
</data> </data>
<data name="TbSettingsHttpPort" xml:space="preserve"> <data name="TbSettingsHttpPort" xml:space="preserve">
<value>پورت Http</value> <value>پورت Http</value>
@@ -725,7 +722,7 @@
<value>هنگام به‌روزرسانی هسته، فایل‌های Geo را نادیده بگیرید</value> <value>هنگام به‌روزرسانی هسته، فایل‌های Geo را نادیده بگیرید</value>
</data> </data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve"> <data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>Keep older when deduplication</value> <value>هنگام کپی برداری، نگه داری قدیمی تر ها</value>
</data> </data>
<data name="TbSettingsLogEnabled" xml:space="preserve"> <data name="TbSettingsLogEnabled" xml:space="preserve">
<value>ثبت گزارش های محلی</value> <value>ثبت گزارش های محلی</value>
@@ -734,25 +731,25 @@
<value>سطح ثبت رویداد</value> <value>سطح ثبت رویداد</value>
</data> </data>
<data name="TbSettingsMuxEnabled" xml:space="preserve"> <data name="TbSettingsMuxEnabled" xml:space="preserve">
<value>Turn on Mux Multiplexing</value> <value>فعال کردن Mux Multiplexing</value>
</data> </data>
<data name="TbSettingsN" xml:space="preserve"> <data name="TbSettingsN" xml:space="preserve">
<value>تنظیمات v2rayN</value> <value>تنظیمات v2rayN</value>
</data> </data>
<data name="TbSettingsPass" xml:space="preserve"> <data name="TbSettingsPass" xml:space="preserve">
<value>Auth pass</value> <value>مجوز احراز هویت</value>
</data> </data>
<data name="TbSettingsRemoteDNS" xml:space="preserve"> <data name="TbSettingsRemoteDNS" xml:space="preserve">
<value>سفارشی DNS (multiple, separated by commas (,))</value> <value>سفارشی DNS (multiple, separated by commas (,))</value>
</data> </data>
<data name="TbSettingsSetUWP" xml:space="preserve"> <data name="TbSettingsSetUWP" xml:space="preserve">
<value>Set Win10 UWP Loopback</value> <value>تنظیم کردن Win10 UWP Loopback</value>
</data> </data>
<data name="TbSettingsSniffingEnabled" xml:space="preserve"> <data name="TbSettingsSniffingEnabled" xml:space="preserve">
<value>Turn on Sniffing</value> <value>فعال کردن Sniffing</value>
</data> </data>
<data name="TbSettingsSocksPort" xml:space="preserve"> <data name="TbSettingsSocksPort" xml:space="preserve">
<value>Mixed Port</value> <value>پورت Mixed</value>
</data> </data>
<data name="TbSettingsStartBoot" xml:space="preserve"> <data name="TbSettingsStartBoot" xml:space="preserve">
<value>درهنگام راه ائدازی شروع شود</value> <value>درهنگام راه ائدازی شروع شود</value>
@@ -761,22 +758,22 @@
<value>فعال کردن آمار (نیاز به راه اندازی مجدد)</value> <value>فعال کردن آمار (نیاز به راه اندازی مجدد)</value>
</data> </data>
<data name="TbSettingsSubConvert" xml:space="preserve"> <data name="TbSettingsSubConvert" xml:space="preserve">
<value>Subscription conversion Url</value> <value>آدرس اینترنتی تبدیل اشتراک</value>
</data> </data>
<data name="TbSettingsSystemproxy" xml:space="preserve"> <data name="TbSettingsSystemproxy" xml:space="preserve">
<value>تنظیمات پراکسی سیستم</value> <value>تنظیمات پراکسی سیستم</value>
</data> </data>
<data name="TbSettingsTLS13" xml:space="preserve"> <data name="TbSettingsTLS13" xml:space="preserve">
<value>Enable Security Protocol TLS v1.3 (subscription/update)</value> <value>فعال کردن پروتکل امنیتی TLS نسخه 1.3 (اشتراک/به‌روزرسانی)</value>
</data> </data>
<data name="TbSettingsTrayMenuServersLimit" xml:space="preserve"> <data name="TbSettingsTrayMenuServersLimit" xml:space="preserve">
<value>Tray right-click menu servers display limit</value> <value>محدودیت نمایش سرورهای منوی سینی کلیک راست</value>
</data> </data>
<data name="TbSettingsUdpEnabled" xml:space="preserve"> <data name="TbSettingsUdpEnabled" xml:space="preserve">
<value>UDP را فعال شود</value> <value>فعال سازی UDP</value>
</data> </data>
<data name="TbSettingsUser" xml:space="preserve"> <data name="TbSettingsUser" xml:space="preserve">
<value>Auth user</value> <value>تایید کاربر</value>
</data> </data>
<data name="TbClearSystemProxy" xml:space="preserve"> <data name="TbClearSystemProxy" xml:space="preserve">
<value>پاک کردن پروکسی سیستم</value> <value>پاک کردن پروکسی سیستم</value>
@@ -821,16 +818,16 @@
<value>پایین (D)</value> <value>پایین (D)</value>
</data> </data>
<data name="menuMoveTop" xml:space="preserve"> <data name="menuMoveTop" xml:space="preserve">
<value>Move to top (T)</value> <value>حرکت به بالا (T)</value>
</data> </data>
<data name="menuMoveUp" xml:space="preserve"> <data name="menuMoveUp" xml:space="preserve">
<value>Up (U)</value> <value>بالا (U)</value>
</data> </data>
<data name="MsgFilterTitle" xml:space="preserve"> <data name="MsgFilterTitle" xml:space="preserve">
<value>Filter, support regular</value> <value>فیلتر، پشتیبانی منظم</value>
</data> </data>
<data name="menuWebsiteItem" xml:space="preserve"> <data name="menuWebsiteItem" xml:space="preserve">
<value>{0} Website</value> <value>{0} وب سایت</value>
</data> </data>
<data name="menuRoutingAdvanced" xml:space="preserve"> <data name="menuRoutingAdvanced" xml:space="preserve">
<value>عملکرد پیشرفته</value> <value>عملکرد پیشرفته</value>
@@ -839,13 +836,13 @@
<value>اضافه کردن</value> <value>اضافه کردن</value>
</data> </data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve"> <data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>وارد کردن قوانین پیشرفته</value> <value>وارد کردن مجموعه قوانین</value>
</data> </data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve"> <data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>حذف انتخاب شده</value> <value>حذف انتخاب شده</value>
</data> </data>
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve"> <data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
<value>Set as active rule</value> <value>تنظیم کردن به عنوان قانون فعال</value>
</data> </data>
<data name="TbdomainMatcher" xml:space="preserve"> <data name="TbdomainMatcher" xml:space="preserve">
<value>تطبیق دامنه</value> <value>تطبیق دامنه</value>
@@ -853,23 +850,20 @@
<data name="TbdomainStrategy" xml:space="preserve"> <data name="TbdomainStrategy" xml:space="preserve">
<value>استراتژی دامنه</value> <value>استراتژی دامنه</value>
</data> </data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>فعال کردن عملکرد پیشرفته</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve"> <data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.Block Domain or IP</value> <value>3. مسدود کردن دامنه یا آیپی</value>
</data> </data>
<data name="TbRoutingTabDirect" xml:space="preserve"> <data name="TbRoutingTabDirect" xml:space="preserve">
<value>2.Direct Domain or IP</value> <value>2. دایرکت کردن دامنه یا IP</value>
</data> </data>
<data name="TbRoutingTabProxy" xml:space="preserve"> <data name="TbRoutingTabProxy" xml:space="preserve">
<value>1.Proxy Domain or IP</value> <value>1. پروکسی کردن دامنه یا IP</value>
</data> </data>
<data name="TbRoutingTabRuleList" xml:space="preserve"> <data name="TbRoutingTabRuleList" xml:space="preserve">
<value>لیست مجموعه قوانین از پیش تعریف شده</value> <value>لیست مجموعه قوانین از پیش تعریف شده</value>
</data> </data>
<data name="TbRoutingTips" xml:space="preserve"> <data name="TbRoutingTips" xml:space="preserve">
<value>*Set the rules, separated by commas (,); The comma in the regular is replaced by &lt;COMMA&gt;</value> <value>*قوانین را تنظیم کنید که با کاما از هم جدا شده اند (,); کاما در حالت عادی با &lt;COMMA&gt;</value>
</data> </data>
<data name="menuImportRulesFromClipboard" xml:space="preserve"> <data name="menuImportRulesFromClipboard" xml:space="preserve">
<value>وارد کردن قوانین از کلیپ بورد</value> <value>وارد کردن قوانین از کلیپ بورد</value>
@@ -878,7 +872,7 @@
<value>وارد کردن قوانین از فایل</value> <value>وارد کردن قوانین از فایل</value>
</data> </data>
<data name="menuImportRulesFromUrl" xml:space="preserve"> <data name="menuImportRulesFromUrl" xml:space="preserve">
<value>وارد کردن قوانین از Sub Url</value> <value>وارد کردن قوانین از آدرس اینترنتی Sub</value>
</data> </data>
<data name="menuRoutingRuleSetting" xml:space="preserve"> <data name="menuRoutingRuleSetting" xml:space="preserve">
<value>تنظیم قانون</value> <value>تنظیم قانون</value>
@@ -902,7 +896,7 @@
<value>دامنه و آی پی در هنگام ذخیره به طور خودکار مرتب می شوند</value> <value>دامنه و آی پی در هنگام ذخیره به طور خودکار مرتب می شوند</value>
</data> </data>
<data name="TbRuleobjectDoc" xml:space="preserve"> <data name="TbRuleobjectDoc" xml:space="preserve">
<value>Ruleobject Doc</value> <value>مستندات شی قانون</value>
</data> </data>
<data name="TbDnsObjectDoc" xml:space="preserve"> <data name="TbDnsObjectDoc" xml:space="preserve">
<value>پشتیبانی از DnsObject</value> <value>پشتیبانی از DnsObject</value>
@@ -920,16 +914,16 @@
<value>فقط مسیر</value> <value>فقط مسیر</value>
</data> </data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve"> <data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>يەرلىك (Intranet) ئادرېسلارغا ۋاكالەتچى مۇلازىمېتىر ئىشلەتمەڭ</value> <value>از سرورهای پروکسی برای آدرس های محلی (اینترانت) استفاده نکنید</value>
</data> </data>
<data name="menuMixedTestServer" xml:space="preserve"> <data name="menuMixedTestServer" xml:space="preserve">
<value>One-click test Latency and speed (Ctrl+E)</value> <value>تاخیر و سرعت تست با یک کلیک (Ctrl+E)</value>
</data> </data>
<data name="LvTestDelay" xml:space="preserve"> <data name="LvTestDelay" xml:space="preserve">
<value>تاخیر (میلی‌ثانیه)</value> <value>تاخیر (میلی‌ثانیه)</value>
</data> </data>
<data name="LvTestSpeed" xml:space="preserve"> <data name="LvTestSpeed" xml:space="preserve">
<value>Speed(M/s)</value> <value>سرعت (M/s)</value>
</data> </data>
<data name="FailedToRunCore" xml:space="preserve"> <data name="FailedToRunCore" xml:space="preserve">
<value>Core اجرا نشد، لطفاً گزارش را ببینید</value> <value>Core اجرا نشد، لطفاً گزارش را ببینید</value>
@@ -940,11 +934,8 @@
<data name="TbDisplayLog" xml:space="preserve"> <data name="TbDisplayLog" xml:space="preserve">
<value>نمایش گزارش</value> <value>نمایش گزارش</value>
</data> </data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>پیکربندی قدیمی guiNConfig را وارد شود</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve"> <data name="TbEnableTunAs" xml:space="preserve">
<value>Tun را فعال شود</value> <value>فعال سازی Tun</value>
</data> </data>
<data name="TbSettingsNewPort4LAN" xml:space="preserve"> <data name="TbSettingsNewPort4LAN" xml:space="preserve">
<value>پورت جدید برای LAN</value> <value>پورت جدید برای LAN</value>
@@ -956,10 +947,10 @@
<value>User-Agent</value> <value>User-Agent</value>
</data> </data>
<data name="TbSettingsDefUserAgentTips" xml:space="preserve"> <data name="TbSettingsDefUserAgentTips" xml:space="preserve">
<value>This parameter is valid only for tcp/http and ws</value> <value>این پارامتر فقط برای tcp/http و ws معتبر است</value>
</data> </data>
<data name="TbSettingsEnableHWA" xml:space="preserve"> <data name="TbSettingsEnableHWA" xml:space="preserve">
<value>فعال‌سازی شتاب‌دهنده سخت‌افزاری (نیاز به راه‌اندازی مجدد)</value> <value>فعال‌ سازی شتاب‌ دهنده سخت‌افزاری (نیاز به راه‌اندازی مجدد)</value>
</data> </data>
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve"> <data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
<value>فعال کردن کش فایل مجموعه قوانین برای sing-box</value> <value>فعال کردن کش فایل مجموعه قوانین برای sing-box</value>
@@ -968,7 +959,7 @@
<value>مرتب سازی</value> <value>مرتب سازی</value>
</data> </data>
<data name="TbSortingDefault" xml:space="preserve"> <data name="TbSortingDefault" xml:space="preserve">
<value>Default</value> <value>پیش فرض</value>
</data> </data>
<data name="TbSortingDelay" xml:space="preserve"> <data name="TbSortingDelay" xml:space="preserve">
<value>تاخیر</value> <value>تاخیر</value>
@@ -1007,10 +998,10 @@
<value>نوع قانون</value> <value>نوع قانون</value>
</data> </data>
<data name="menuModeDirect" xml:space="preserve"> <data name="menuModeDirect" xml:space="preserve">
<value>Direct</value> <value>مستقیم</value>
</data> </data>
<data name="menuModeGlobal" xml:space="preserve"> <data name="menuModeGlobal" xml:space="preserve">
<value>Global</value> <value>جهانی</value>
</data> </data>
<data name="menuModeNothing" xml:space="preserve"> <data name="menuModeNothing" xml:space="preserve">
<value>تغییر نده</value> <value>تغییر نده</value>
@@ -1019,193 +1010,193 @@
<value>قانون</value> <value>قانون</value>
</data> </data>
<data name="menuProxiesDelaytest" xml:space="preserve"> <data name="menuProxiesDelaytest" xml:space="preserve">
<value>Latency Test</value> <value>تست تأخیر</value>
</data> </data>
<data name="menuProxiesDelaytestPart" xml:space="preserve"> <data name="menuProxiesDelaytestPart" xml:space="preserve">
<value>Part Node Latency Test</value> <value>تست تاخیر قسمت گره (نقطه اتصال)</value>
</data> </data>
<data name="menuProxiesSelectActivity" xml:space="preserve"> <data name="menuProxiesSelectActivity" xml:space="preserve">
<value>Select active node (Enter)</value> <value>انتخاب گره فعال (Enter)</value>
</data> </data>
<data name="menuRemoteBackup" xml:space="preserve"> <data name="menuRemoteBackup" xml:space="preserve">
<value>Backup to remote (WebDAV)</value> <value>پشتیبان گیری از راه دور (WebDAV)</value>
</data> </data>
<data name="menuRemoteRestore" xml:space="preserve"> <data name="menuRemoteRestore" xml:space="preserve">
<value>Restore from remote (WebDAV)</value> <value>بازیابی از راه دور (WebDAV)</value>
</data> </data>
<data name="TbSettingsDomainStrategy4Out" xml:space="preserve"> <data name="TbSettingsDomainStrategy4Out" xml:space="preserve">
<value>Default domain strategy for outbound</value> <value>استراتژی دامنه پیش فرض برای خروجی</value>
</data> </data>
<data name="menuSetDefaultMultipleServer" xml:space="preserve"> <data name="menuSetDefaultMultipleServer" xml:space="preserve">
<value>Multi-Server lowest latency</value> <value>کمترین تأخیر چند سروره</value>
</data> </data>
<data name="TbSettingsMainGirdOrientation" xml:space="preserve"> <data name="TbSettingsMainGirdOrientation" xml:space="preserve">
<value>Main layout orientation(Require restart)</value> <value>جهت چیدمان اصلی (نیاز به راه اندازی مجدد)</value>
</data> </data>
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve"> <data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
<value>Multi-server load balancing</value> <value>تعادل بار چند سروره</value>
</data> </data>
<data name="TbSettingsDomainDNSAddress" xml:space="preserve"> <data name="TbSettingsDomainDNSAddress" xml:space="preserve">
<value>Outbound DNS address</value> <value>آدرس DNS خروجی</value>
</data> </data>
<data name="menuProfileAutofitColumnWidth" xml:space="preserve"> <data name="menuProfileAutofitColumnWidth" xml:space="preserve">
<value>Auto column width adjustment</value> <value>تنظیم خودکار عرض ستون</value>
</data> </data>
<data name="menuExport2ShareUrlBase64" xml:space="preserve"> <data name="menuExport2ShareUrlBase64" xml:space="preserve">
<value>Export Base64-encoded Share Links to Clipboard</value> <value>صادر کردن پیوندهای اشتراک گذاری کدگذاری شده با Base64 به کلیپ بورد</value>
</data> </data>
<data name="menuExport2ClientConfigClipboard" xml:space="preserve"> <data name="menuExport2ClientConfigClipboard" xml:space="preserve">
<value>Export selected server for complete configuration to clipboard</value> <value>صادر کردن سرور انتخاب شده برای پیکربندی کامل به کلیپ بورد</value>
</data> </data>
<data name="menuShowOrHideMainWindow" xml:space="preserve"> <data name="menuShowOrHideMainWindow" xml:space="preserve">
<value>Show or hide the main window</value> <value>نمایش یا پنهان کردن پنجره اصلی</value>
</data> </data>
<data name="UpdateStandalonePackageTip" xml:space="preserve"> <data name="UpdateStandalonePackageTip" xml:space="preserve">
<value>You are currently running a standalone package, please manually download the SelfContained.7z file to unzip and overwrite it!</value> <value>شما در حال حاضر در حال اجرای یک بسته مستقل هستید، لطفاً فایل SelfContained.7z را به صورت دستی دانلود کنید تا آن را از حالت فشرده خارج کرده و بازنویسی کنید!</value>
</data> </data>
<data name="TbPreSocksPort4Sub" xml:space="preserve"> <data name="TbPreSocksPort4Sub" xml:space="preserve">
<value>Custom config socks port</value> <value>پیکربندی سفارشی ساکس پورت</value>
</data> </data>
<data name="menuBackupAndRestore" xml:space="preserve"> <data name="menuBackupAndRestore" xml:space="preserve">
<value>Backup and Restore</value> <value>پشتیبان گیری و بازیابی</value>
</data> </data>
<data name="menuLocalBackup" xml:space="preserve"> <data name="menuLocalBackup" xml:space="preserve">
<value>Backup to local</value> <value>پشتیبان گیری به محلی</value>
</data> </data>
<data name="menuLocalRestore" xml:space="preserve"> <data name="menuLocalRestore" xml:space="preserve">
<value>Restore from local</value> <value>بازیابی از محلی</value>
</data> </data>
<data name="menuLocalBackupAndRestore" xml:space="preserve"> <data name="menuLocalBackupAndRestore" xml:space="preserve">
<value>Local</value> <value>محلی</value>
</data> </data>
<data name="menuRemoteBackupAndRestore" xml:space="preserve"> <data name="menuRemoteBackupAndRestore" xml:space="preserve">
<value>Remote (WebDAV)</value> <value>از راه دور (WebDAV)</value>
</data> </data>
<data name="LvWebDavUrl" xml:space="preserve"> <data name="LvWebDavUrl" xml:space="preserve">
<value>WebDav Url</value> <value>آدرس اینترنتی WebDav</value>
</data> </data>
<data name="LvWebDavUserName" xml:space="preserve"> <data name="LvWebDavUserName" xml:space="preserve">
<value>WebDav User Name</value> <value>نام کاربری WebDav</value>
</data> </data>
<data name="LvWebDavPassword" xml:space="preserve"> <data name="LvWebDavPassword" xml:space="preserve">
<value>WebDav Password</value> <value>پسورد WebDav</value>
</data> </data>
<data name="LvWebDavCheck" xml:space="preserve"> <data name="LvWebDavCheck" xml:space="preserve">
<value>WebDav Check</value> <value>چک کردن WebDav</value>
</data> </data>
<data name="LvWebDavDirName" xml:space="preserve"> <data name="LvWebDavDirName" xml:space="preserve">
<value>Remote folder name (optional)</value> <value>نام پوشه راه دور (اختیاری)</value>
</data> </data>
<data name="LocalRestoreInvalidZipTips" xml:space="preserve"> <data name="LocalRestoreInvalidZipTips" xml:space="preserve">
<value>Invalid backup file</value> <value>فایل پشتیبان نامعتبر است</value>
</data> </data>
<data name="ConnectionsHostFilterTitle" xml:space="preserve"> <data name="ConnectionsHostFilterTitle" xml:space="preserve">
<value>Host filter</value> <value>Host filter</value>
</data> </data>
<data name="TipActiveServer" xml:space="preserve"> <data name="TipActiveServer" xml:space="preserve">
<value>Active</value> <value>فعال سازی</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>Save Interface Layout</value>
</data> </data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve"> <data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo files source (optional)</value> <value>منبع فایل های جغرافیایی (اختیاری)</value>
</data> </data>
<data name="TbSettingsSrsFilesSource" xml:space="preserve"> <data name="TbSettingsSrsFilesSource" xml:space="preserve">
<value>sing-box ruleset files source (optional)</value> <value>منبع فایل های مجموعه قوانین sing-box (اختیاری)</value>
</data> </data>
<data name="UpgradeAppNotExistTip" xml:space="preserve"> <data name="UpgradeAppNotExistTip" xml:space="preserve">
<value>UpgradeApp does not exist</value> <value>برنامه ارتقا وجود ندارد</value>
</data> </data>
<data name="TbSettingsRoutingRulesSource" xml:space="preserve"> <data name="TbSettingsRoutingRulesSource" xml:space="preserve">
<value>Routing rules source (optional)</value> <value>منبع قوانین مسیریابی (اختیاری)</value>
</data> </data>
<data name="menuRegionalPresets" xml:space="preserve"> <data name="menuRegionalPresets" xml:space="preserve">
<value>Regional presets setting</value> <value>تنظیمات از پیش تعیین شده منطقه ای</value>
</data> </data>
<data name="menuRegionalPresetsDefault" xml:space="preserve"> <data name="menuRegionalPresetsDefault" xml:space="preserve">
<value>Default</value> <value>پیش فرض</value>
</data> </data>
<data name="menuRegionalPresetsRussia" xml:space="preserve"> <data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>Russia</value> <value>روسیه</value>
</data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>ایران</value>
</data> </data>
<data name="TbSettingsChinaUserTip" xml:space="preserve"> <data name="TbSettingsChinaUserTip" xml:space="preserve">
<value>Users in China region can ignore this item</value> <value>کاربران در منطقه چین می توانند این مورد را نادیده بگیرند</value>
</data> </data>
<data name="menuAddServerViaImage" xml:space="preserve"> <data name="menuAddServerViaImage" xml:space="preserve">
<value>Scan QR code in the image</value> <value>اسکن کردن QRcode موجود در تصویر</value>
</data> </data>
<data name="InvalidUrlTip" xml:space="preserve"> <data name="InvalidUrlTip" xml:space="preserve">
<value>Invalid address (Url)</value> <value>آدرس نامعتبر (آدرس اینترنتی)</value>
</data> </data>
<data name="InsecureUrlProtocol" xml:space="preserve"> <data name="InsecureUrlProtocol" xml:space="preserve">
<value>Please do not use the insecure HTTP protocol subscription address</value> <value>لطفاً از آدرس اشتراک پروتکل HTTP ناامن استفاده نکنید</value>
</data> </data>
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve"> <data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
<value>Install the font to the system and restart the settings</value> <value>فونت را روی سیستم نصب کنید و تنظیمات را مجددا راه اندازی کنید</value>
</data> </data>
<data name="menuExitTips" xml:space="preserve"> <data name="menuExitTips" xml:space="preserve">
<value>Are you sure to exit?</value> <value>آیا مطمئن هستید که خارج می شوید؟</value>
</data> </data>
<data name="LvMemo" xml:space="preserve"> <data name="LvMemo" xml:space="preserve">
<value>Remarks Memo</value> <value>یادداشت ملاحظات</value>
</data> </data>
<data name="TbSettingsLogEnabledToFile" xml:space="preserve"> <data name="TbSettingsLogEnabledToFile" xml:space="preserve">
<value>Enable logging to file</value> <value>فعال کردن ورود به فایل</value>
</data> </data>
<data name="MsgSkipSubscriptionUpdate" xml:space="preserve"> <data name="MsgSkipSubscriptionUpdate" xml:space="preserve">
<value>Updates are not enabled, skip this subscription</value> <value>به روز رسانی ها فعال نیستند، از این اشتراک رد شوید</value>
</data> </data>
<data name="menuRebootAsAdmin" xml:space="preserve"> <data name="menuRebootAsAdmin" xml:space="preserve">
<value>Restart as Administrator</value> <value>به عنوان مدیر راه اندازی مجدد</value>
</data> </data>
<data name="LvMoreUrl" xml:space="preserve"> <data name="LvMoreUrl" xml:space="preserve">
<value>More URLs, separated by commas; Subscription conversion will be invalid</value> <value>نشانی‌های وب بیشتر که با کاما از هم جدا شده‌اند. تبدیل اشتراک نامعتبر خواهد بود</value>
</data> </data>
<data name="SpeedDisplayText" xml:space="preserve"> <data name="SpeedDisplayText" xml:space="preserve">
<value>{0} : {1}/s↑ | {2}/s↓</value> <value>{0} : {1}/s↑ | {2}/s↓</value>
</data> </data>
<data name="LvAutoUpdateInterval" xml:space="preserve"> <data name="LvAutoUpdateInterval" xml:space="preserve">
<value>Automatic update interval (minutes)</value> <value>فاصله به روز رسانی خودکار (دقیقه)</value>
</data> </data>
<data name="LvConvertTarget" xml:space="preserve"> <data name="LvConvertTarget" xml:space="preserve">
<value>Convert target type</value> <value>تبدیل نوع هدف</value>
</data> </data>
<data name="LvConvertTargetTip" xml:space="preserve"> <data name="LvConvertTargetTip" xml:space="preserve">
<value>Please leave blank if no conversion is required</value> <value>اگر نیازی به تبدیل نیست، لطفاً خالی بگذارید</value>
</data> </data>
<data name="TipDisplayLog" xml:space="preserve"> <data name="TipDisplayLog" xml:space="preserve">
<value>Please turn off when there is an abnormal disconnection</value> <value>لطفاً در صورت قطع غیرعادی آن را خاموش کنید</value>
</data> </data>
<data name="menuDNSSetting" xml:space="preserve"> <data name="menuDNSSetting" xml:space="preserve">
<value>DNS Settings</value> <value>تنظیمات DNS</value>
</data> </data>
<data name="TbDnsSingboxObjectDoc" xml:space="preserve"> <data name="TbDnsSingboxObjectDoc" xml:space="preserve">
<value>Please fill in DNS Structure, Click to view the document</value> <value>لطفا ساختار DNS را پر کنید، برای مشاهده سند کلیک کنید</value>
</data> </data>
<data name="TbSettingDnsImportDefConfig" xml:space="preserve"> <data name="TbSettingDnsImportDefConfig" xml:space="preserve">
<value>Click to import default DNS config</value> <value>برای وارد کردن تنظیمات پیش‌فرض DNS کلیک کنید</value>
</data> </data>
<data name="TbdomainStrategy4Singbox" xml:space="preserve"> <data name="TbdomainStrategy4Singbox" xml:space="preserve">
<value>sing-box domain strategy</value> <value>استراتژی دامنه sing-box</value>
</data> </data>
<data name="TbSettingsMux4SboxProtocol" xml:space="preserve"> <data name="TbSettingsMux4SboxProtocol" xml:space="preserve">
<value>sing-box Mux Protocol</value> <value>پروتکل sing-box Mux</value>
</data> </data>
<data name="TbRoutingRuleProcess" xml:space="preserve"> <data name="TbRoutingRuleProcess" xml:space="preserve">
<value>Full process name (Tun mode)</value> <value>نام کامل فرانید (حالت Tun)</value>
</data> </data>
<data name="TbRoutingRuleIP" xml:space="preserve"> <data name="TbRoutingRuleIP" xml:space="preserve">
<value>IP or IP CIDR</value> <value>IP or IP CIDR</value>
</data> </data>
<data name="TbRoutingRuleDomain" xml:space="preserve"> <data name="TbRoutingRuleDomain" xml:space="preserve">
<value>Domain</value> <value>دامنه</value>
</data> </data>
<data name="TbSettingsCoreDnsSingbox" xml:space="preserve"> <data name="TbSettingsCoreDnsSingbox" xml:space="preserve">
<value>sing-box DNS settings</value> <value>تنظیمات DNS sing-box</value>
</data> </data>
<data name="SpeedtestingWait" xml:space="preserve"> <data name="SpeedtestingWait" xml:space="preserve">
<value>Waiting for testing (press ESC to terminate)...</value> <value>در انتظار آزمایش (برای پایان دادن به ESC فشار دهید)...</value>
</data> </data>
<data name="TbSpiderX" xml:space="preserve"> <data name="TbSpiderX" xml:space="preserve">
<value>SpiderX</value> <value>SpiderX</value>
@@ -1214,52 +1205,52 @@
<value>ShortId</value> <value>ShortId</value>
</data> </data>
<data name="menuMoveToGroup" xml:space="preserve"> <data name="menuMoveToGroup" xml:space="preserve">
<value>Move to group</value> <value>انتقال به گروه</value>
</data> </data>
<data name="TbSettingsEnableDragDropSort" xml:space="preserve"> <data name="TbSettingsEnableDragDropSort" xml:space="preserve">
<value>Enable Server Drag Drop Sort(Require restart)</value> <value>فعال کردن مرتب سازی با کشیدن سرور (نیاز به راه اندازی مجدد)</value>
</data> </data>
<data name="TbAutoRefresh" xml:space="preserve"> <data name="TbAutoRefresh" xml:space="preserve">
<value>AutoRefresh</value> <value>بازخوانی خودکار</value>
</data> </data>
<data name="SpeedtestingSkip" xml:space="preserve"> <data name="SpeedtestingSkip" xml:space="preserve">
<value>Skip test</value> <value>رد شدن از آزمون</value>
</data> </data>
<data name="menuEditServer" xml:space="preserve"> <data name="menuEditServer" xml:space="preserve">
<value>Edit Server (Ctrl+D)</value> <value>ویرایش سرور (Ctrl+D)</value>
</data> </data>
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve"> <data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
<value>Double-click server make active</value> <value>روی server make active دوبار کلیک کنید</value>
</data> </data>
<data name="SpeedtestingCompleted" xml:space="preserve"> <data name="SpeedtestingCompleted" xml:space="preserve">
<value>Test completed</value> <value>تست تکمیل شد</value>
</data> </data>
<data name="TbSettingsDefFingerprint" xml:space="preserve"> <data name="TbSettingsDefFingerprint" xml:space="preserve">
<value>Default TLS fingerprint</value> <value>اثر انگشت tls پیش فرض</value>
</data> </data>
<data name="TbSettingsCurrentFontFamily" xml:space="preserve"> <data name="TbSettingsCurrentFontFamily" xml:space="preserve">
<value>FontFamily(Require restart)</value> <value>FontFamily (نیاز به راه اندازی مجدد)</value>
</data> </data>
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve"> <data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
<value>Copy the font TTF/TTC file to the directory guiFonts, restart the settings</value> <value>فایل TTF/TTC فونت را در دایرکتوری guiFonts کپی کنید، تنظیمات را مجددا راه اندازی کنید</value>
</data> </data>
<data name="TbSettingsSocksPortTip" xml:space="preserve"> <data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>Pac port = +2; Xray API port = +3; mihomo API port = +4;</value> <value>پورت Pac = +3; پورت Xray API = +4; پورت mihomo API = +5;</value>
</data> </data>
<data name="TbSettingsStartBootTip" xml:space="preserve"> <data name="TbSettingsStartBootTip" xml:space="preserve">
<value>Set this with admin privileges, get admin privileges after startup</value> <value>این را با امتیازات ادمین تنظیم کنید، پس از راه اندازی، امتیازات مدیر را دریافت کنید</value>
</data> </data>
<data name="TbSettingsFontSize" xml:space="preserve"> <data name="TbSettingsFontSize" xml:space="preserve">
<value>Font Size</value> <value>اندازه فونت</value>
</data> </data>
<data name="TbSettingsSpeedTestTimeout" xml:space="preserve"> <data name="TbSettingsSpeedTestTimeout" xml:space="preserve">
<value>SpeedTest Single Timeout Value</value> <value>یمقدار تاخیر تست سرعت منفرد</value>
</data> </data>
<data name="TbSettingsSpeedTestUrl" xml:space="preserve"> <data name="TbSettingsSpeedTestUrl" xml:space="preserve">
<value>SpeedTest URL</value> <value>/آدرس اینترنتی SpeedTest</value>
</data> </data>
<data name="menuMoveTo" xml:space="preserve"> <data name="menuMoveTo" xml:space="preserve">
<value>Move up and down</value> <value>بالا و پایین حرکت کنید</value>
</data> </data>
<data name="TbPublicKey" xml:space="preserve"> <data name="TbPublicKey" xml:space="preserve">
<value>PublicKey</value> <value>PublicKey</value>
@@ -1268,46 +1259,43 @@
<value>Add [Hysteria2] server</value> <value>Add [Hysteria2] server</value>
</data> </data>
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve"> <data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
<value>Hysteria Max bandwidth (Up/Dw)</value> <value>حداکتر پهنای باند هیستریا (آپلود/دانلود)</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>Follow System Theme</value>
</data> </data>
<data name="menuAddTuicServer" xml:space="preserve"> <data name="menuAddTuicServer" xml:space="preserve">
<value>Add [TUIC] server</value> <value>افزودن سرور [TUIC]</value>
</data> </data>
<data name="TbSettingsEnableUpdateSubOnlyRemarksExist" xml:space="preserve"> <data name="TbSettingsEnableUpdateSubOnlyRemarksExist" xml:space="preserve">
<value>Updating subscription, only determine remarks exists</value> <value>اشتراک در حال به‌روزرسانی، فقط مشخص کنید که ملاحظاتی وجود دارد</value>
</data> </data>
<data name="menuProxiesReload" xml:space="preserve"> <data name="menuProxiesReload" xml:space="preserve">
<value>Refresh Proxies</value> <value>تازه سازی پروکسی ها</value>
</data> </data>
<data name="TbSortingNetwork" xml:space="preserve"> <data name="TbSortingNetwork" xml:space="preserve">
<value>Network</value> <value>شبکه</value>
</data> </data>
<data name="TbSortingType" xml:space="preserve"> <data name="TbSortingType" xml:space="preserve">
<value>Type</value> <value>نوع</value>
</data> </data>
<data name="TransportRequestHostTip5" xml:space="preserve"> <data name="TransportRequestHostTip5" xml:space="preserve">
<value>*grpc Authority</value> <value>*grpc Authority</value>
</data> </data>
<data name="menuAddHttpServer" xml:space="preserve"> <data name="menuAddHttpServer" xml:space="preserve">
<value>Add [HTTP] server</value> <value>افزودن سرور [HTTP]</value>
</data> </data>
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve"> <data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
<value>Speed Ping Test URL</value> <value>آدرس اینترنتی تست پینگ سرعت</value>
</data> </data>
<data name="TbSettingsEnableFragmentTips" xml:space="preserve"> <data name="TbSettingsEnableFragmentTips" xml:space="preserve">
<value>Use Xray and enable non-Tun mode, which conflicts with the group previous proxy</value> <value>از Xray استفاده کنید و حالت non-Tun را فعال کنید، که با پراکسی قبلی گروه در تضاد است</value>
</data> </data>
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve"> <data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
<value>Custom the rule-set of sing-box</value> <value>سفارش سازی مجموعه قوانین از sing box</value>
</data> </data>
<data name="NeedRebootTips" xml:space="preserve"> <data name="NeedRebootTips" xml:space="preserve">
<value>Successful operation. Click the settings menu to reboot the app.</value> <value>عملکرد موفقیت آمیز بود، روی منوی تنظیمات کلیک کنید تا برنامه راه اندازی مجدد شود.</value>
</data> </data>
<data name="menuOpenTheFileLocation" xml:space="preserve"> <data name="menuOpenTheFileLocation" xml:space="preserve">
<value>Open the storage location</value> <value>باز کردن محل ذخیره سازی</value>
</data> </data>
<data name="TbSortingChain" xml:space="preserve"> <data name="TbSortingChain" xml:space="preserve">
<value>Chain</value> <value>Chain</value>
@@ -1316,75 +1304,93 @@
<value>Host</value> <value>Host</value>
</data> </data>
<data name="TbSettingsUseSystemHosts" xml:space="preserve"> <data name="TbSettingsUseSystemHosts" xml:space="preserve">
<value>Use System Hosts</value> <value>استفاده کردن از System Hosts</value>
</data> </data>
<data name="TbSettingsEnableFragment" xml:space="preserve"> <data name="TbSettingsEnableFragment" xml:space="preserve">
<value>Enable fragment</value> <value>فعال کردن فرگمنت</value>
</data> </data>
<data name="TbAutoScrollToEnd" xml:space="preserve"> <data name="TbAutoScrollToEnd" xml:space="preserve">
<value>Auto ScrollToEnd</value> <value>خودکار ScrollToEnd</value>
</data> </data>
<data name="SpeedtestingStop" xml:space="preserve"> <data name="SpeedtestingStop" xml:space="preserve">
<value>Test terminating...</value> <value>پایان تست...</value>
</data> </data>
<data name="LvNextProfile" xml:space="preserve"> <data name="LvNextProfile" xml:space="preserve">
<value>Next proxy remarks</value> <value>Next proxy remarks</value>
</data> </data>
<data name="TbPath7" xml:space="preserve"> <data name="TbPath7" xml:space="preserve">
<value>obfs password</value> <value>پسورد obfs</value>
</data> </data>
<data name="TbHeaderType8" xml:space="preserve"> <data name="TbHeaderType8" xml:space="preserve">
<value>Congestion control</value> <value>کنترل تراکم</value>
</data> </data>
<data name="LvPrevProfile" xml:space="preserve"> <data name="LvPrevProfile" xml:space="preserve">
<value>Previous proxy remarks</value> <value>Previous proxy remarks</value>
</data> </data>
<data name="TbLocalAddress" xml:space="preserve"> <data name="TbLocalAddress" xml:space="preserve">
<value>Address(Ip,Ipv6)</value> <value>آدرس (IP, IPv6)</value>
</data> </data>
<data name="TbReserved" xml:space="preserve"> <data name="TbReserved" xml:space="preserve">
<value>Reserved(2,3,4)</value> <value>Reserved(2,3,4)</value>
</data> </data>
<data name="TbPrivateKey" xml:space="preserve"> <data name="TbPrivateKey" xml:space="preserve">
<value>PrivateKey</value> <value>کلید خصوصی</value>
</data> </data>
<data name="menuAddWireguardServer" xml:space="preserve"> <data name="menuAddWireguardServer" xml:space="preserve">
<value>Add [WireGuard] server</value> <value>افزودن سرور [WireGuard]</value>
</data> </data>
<data name="TbSettingsEnableIPv6Address" xml:space="preserve"> <data name="TbSettingsEnableIPv6Address" xml:space="preserve">
<value>Enable IPv6 Address</value> <value>فعال سازی آدرس IPv6</value>
</data> </data>
<data name="TbSettingsEnableExInbound" xml:space="preserve"> <data name="TbSettingsEnableExInbound" xml:space="preserve">
<value>Enable additional Inbound</value> <value>فعال سازی additional Inbound</value>
</data> </data>
<data name="LvPrevProfileTip" xml:space="preserve"> <data name="LvPrevProfileTip" xml:space="preserve">
<value>Please make sure the remarks exists and is unique</value> <value>لطفاً مطمئن شوید که ملاحظات وجود دارد و منحصر به فرد است</value>
</data> </data>
<data name="TbRuleMatchingTips" xml:space="preserve"> <data name="TbRuleMatchingTips" xml:space="preserve">
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag =&gt; OutboundTag</value> <value>(Domain or IP or ProcName) and Port and Protocol and InboundTag =&gt; OutboundTag</value>
</data> </data>
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve"> <data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
<value>System sudo password</value> <value>رمز عبور sudo سیستم</value>
</data> </data>
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve"> <data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
<value>The password is encrypted and stored only in local files.</value> <value>رمز عبور رمزگذاری شده و فقط در فایل های محلی ذخیره می شود.</value>
</data> </data>
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve"> <data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
<value>Please set the sudo password in Tun mode settings first</value> <value>لطفاً ابتدا رمز عبور sudo را در تنظیمات حالت Tun تنظیم کنید</value>
</data> </data>
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve"> <data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
<value>Please do not run this app with sudo</value> <value>لطفا این برنامه را با sudo اجرا نکنید</value>
</data> </data>
<data name="TransportHeaderTypeTip5" xml:space="preserve"> <data name="TransportHeaderTypeTip5" xml:space="preserve">
<value>*xhttp mode</value> <value>*حالت xhttp</value>
</data> </data>
<data name="TransportExtraTip" xml:space="preserve"> <data name="TransportExtraTip" xml:space="preserve">
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value> <value>جیسون خام XHTTP Extra, فرمت: { XHTTPObject }</value>
</data> </data>
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve"> <data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>Hide to tray when closing the window</value> <value>هنگام بستن پنجره در سینی پنهان شوید</value>
</data> </data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve"> <data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>Number per time for auto batch during speedtest(max 1000)</value> <value>تعداد در هر زمان برای دسته خودکار در طول تست سرعت (حداکثر 1000)</value>
</data> </data>
</root> <data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>استثنا:از سرور پروکسی برای آدرس ها، با کاما (،) استفاده نکنید</value>
</data>
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>نوع Sniffing</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>فعال کردن دومین پورت ترکیبی</value>
</data>
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks:پورت محلی، socks2: پورت دوم محلی، socks3: پورت LAN</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>تم</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>کپی کردن دستور پروکسی در کلیپ بورد</value>
</data>
</root>

File diff suppressed because it is too large Load Diff

View File

@@ -481,12 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve"> <data name="TbSettingsColor" xml:space="preserve">
<value>Color</value> <value>Color</value>
</data> </data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>Dark Mode</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>Follow System Theme</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve"> <data name="TbSettingsLanguage" xml:space="preserve">
<value>Language (Restart)</value> <value>Language (Restart)</value>
</data> </data>
@@ -842,7 +836,7 @@
<value>Add</value> <value>Add</value>
</data> </data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve"> <data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>Import Advanced Rules</value> <value>Import Rules</value>
</data> </data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve"> <data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>Remove selected (Delete)</value> <value>Remove selected (Delete)</value>
@@ -856,9 +850,6 @@
<data name="TbdomainStrategy" xml:space="preserve"> <data name="TbdomainStrategy" xml:space="preserve">
<value>Domain strategy</value> <value>Domain strategy</value>
</data> </data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>Enable advanced function</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve"> <data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.Block Domain or IP</value> <value>3.Block Domain or IP</value>
</data> </data>
@@ -943,9 +934,6 @@
<data name="TbDisplayLog" xml:space="preserve"> <data name="TbDisplayLog" xml:space="preserve">
<value>Display Log</value> <value>Display Log</value>
</data> </data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>Import old config (guiNConfig)</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve"> <data name="TbEnableTunAs" xml:space="preserve">
<value>Enable Tun</value> <value>Enable Tun</value>
</data> </data>
@@ -992,7 +980,7 @@
<value>Copy the font TTF/TTC file to the directory guiFonts, restart the settings</value> <value>Copy the font TTF/TTC file to the directory guiFonts, restart the settings</value>
</data> </data>
<data name="TbSettingsSocksPortTip" xml:space="preserve"> <data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>Pac port = +2; Xray API port = +3; mihomo API port = +4;</value> <value>Pac port = +3; Xray API port = +4; mihomo API port = +5;</value>
</data> </data>
<data name="TbSettingsStartBootTip" xml:space="preserve"> <data name="TbSettingsStartBootTip" xml:space="preserve">
<value>Set this with admin privileges, get admin privileges after startup</value> <value>Set this with admin privileges, get admin privileges after startup</value>
@@ -1318,9 +1306,6 @@
<data name="TipActiveServer" xml:space="preserve"> <data name="TipActiveServer" xml:space="preserve">
<value>Active</value> <value>Active</value>
</data> </data>
<data name="menuStorageUI" xml:space="preserve">
<value>Save Interface Layout</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve"> <data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo files source (optional)</value> <value>Geo files source (optional)</value>
</data> </data>
@@ -1342,6 +1327,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve"> <data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>Russia</value> <value>Russia</value>
</data> </data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>Iran</value>
</data>
<data name="TbSettingsChinaUserTip" xml:space="preserve"> <data name="TbSettingsChinaUserTip" xml:space="preserve">
<value>Users in China region can ignore this item</value> <value>Users in China region can ignore this item</value>
</data> </data>
@@ -1387,4 +1375,22 @@
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve"> <data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>Number per time for auto batch during speedtest(max 1000)</value> <value>Number per time for auto batch during speedtest(max 1000)</value>
</data> </data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
</data>
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>Sniffing type</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>Enable second mixed port</value>
</data>
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks: local port, socks2: second local port, socks3: LAN port</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>Theme</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value>
</data>
</root> </root>

View File

@@ -481,12 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve"> <data name="TbSettingsColor" xml:space="preserve">
<value>Цвет</value> <value>Цвет</value>
</data> </data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>Тёмный режим</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>Следить за системной темой</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve"> <data name="TbSettingsLanguage" xml:space="preserve">
<value>Язык (требуется перезапуск)</value> <value>Язык (требуется перезапуск)</value>
</data> </data>
@@ -862,9 +856,6 @@
<data name="TbdomainStrategy" xml:space="preserve"> <data name="TbdomainStrategy" xml:space="preserve">
<value>Доменная стратегия</value> <value>Доменная стратегия</value>
</data> </data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>Включить расширенные функции</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve"> <data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.Заблокировать домен или IP</value> <value>3.Заблокировать домен или IP</value>
</data> </data>
@@ -949,9 +940,6 @@
<data name="TbDisplayLog" xml:space="preserve"> <data name="TbDisplayLog" xml:space="preserve">
<value>Показать логи</value> <value>Показать логи</value>
</data> </data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>Импортировать старый конфиг guiNConfig</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve"> <data name="TbEnableTunAs" xml:space="preserve">
<value>Режим VPN</value> <value>Режим VPN</value>
</data> </data>
@@ -1039,6 +1027,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve"> <data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>Россия</value> <value>Россия</value>
</data> </data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>Иран</value>
</data>
<data name="TbSettingsChinaUserTip" xml:space="preserve"> <data name="TbSettingsChinaUserTip" xml:space="preserve">
<value>Используйте Настройки -&gt; Региональные пресеты вместо изменения этого поля</value> <value>Используйте Настройки -&gt; Региональные пресеты вместо изменения этого поля</value>
</data> </data>
@@ -1267,9 +1258,6 @@
<data name="LvConvertTarget" xml:space="preserve"> <data name="LvConvertTarget" xml:space="preserve">
<value>Convert target type</value> <value>Convert target type</value>
</data> </data>
<data name="menuStorageUI" xml:space="preserve">
<value>Save Interface Layout</value>
</data>
<data name="SpeedDisplayText" xml:space="preserve"> <data name="SpeedDisplayText" xml:space="preserve">
<value>{0} : {1}/s↑ | {2}/s↓</value> <value>{0} : {1}/s↑ | {2}/s↓</value>
</data> </data>
@@ -1310,7 +1298,7 @@
<value>Move up and down</value> <value>Move up and down</value>
</data> </data>
<data name="TbSettingsSocksPortTip" xml:space="preserve"> <data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>Pac port = +2; Xray API port = +3; mihomo API port = +4;</value> <value>Pac port = +3; Xray API port = +4; mihomo API port = +5;</value>
</data> </data>
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve"> <data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
<value>Install the font to the system and restart the settings</value> <value>Install the font to the system and restart the settings</value>
@@ -1387,4 +1375,22 @@
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve"> <data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>Number per time for auto batch during speedtest(max 1000)</value> <value>Number per time for auto batch during speedtest(max 1000)</value>
</data> </data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
</data>
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>Sniffing type</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>Enable second mixed port</value>
</data>
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks: local port, socks2: second local port, socks3: LAN port</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>Theme</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value>
</data>
</root> </root>

View File

@@ -127,7 +127,7 @@
<value>配置格式不正确</value> <value>配置格式不正确</value>
</data> </data>
<data name="CustomServerTips" xml:space="preserve"> <data name="CustomServerTips" xml:space="preserve">
<value>注意,自定义配置完全依赖您自己的配置,不能使用所有设置功能。如需使用系统代理请手动修改监听端口。</value> <value>注意自定义配置完全依赖您自己的配置,不能使用所有设置功能。如需使用系统代理请手动修改监听端口。</value>
</data> </data>
<data name="Downloading" xml:space="preserve"> <data name="Downloading" xml:space="preserve">
<value>下载开始...</value> <value>下载开始...</value>
@@ -136,7 +136,7 @@
<value>下载</value> <value>下载</value>
</data> </data>
<data name="DownloadYesNo" xml:space="preserve"> <data name="DownloadYesNo" xml:space="preserve">
<value>是否下载? {0}</value> <value>是否下载{0}</value>
</data> </data>
<data name="FailedConversionConfiguration" xml:space="preserve"> <data name="FailedConversionConfiguration" xml:space="preserve">
<value>转换配置文件失败</value> <value>转换配置文件失败</value>
@@ -154,7 +154,7 @@
<value>读取配置文件失败</value> <value>读取配置文件失败</value>
</data> </data>
<data name="FillCorrectServerPort" xml:space="preserve"> <data name="FillCorrectServerPort" xml:space="preserve">
<value>请填写正确格式服务器端口</value> <value>请填写正确格式服务器端口</value>
</data> </data>
<data name="FillLocalListeningPort" xml:space="preserve"> <data name="FillLocalListeningPort" xml:space="preserve">
<value>请填写本地监听端口</value> <value>请填写本地监听端口</value>
@@ -169,16 +169,16 @@
<value>请填写用户ID</value> <value>请填写用户ID</value>
</data> </data>
<data name="Incorrectconfiguration" xml:space="preserve"> <data name="Incorrectconfiguration" xml:space="preserve">
<value>不是正确的配置,请检查</value> <value>配置不正确,请检查</value>
</data> </data>
<data name="InitialConfiguration" xml:space="preserve"> <data name="InitialConfiguration" xml:space="preserve">
<value>初始化配置</value> <value>初始化配置</value>
</data> </data>
<data name="IsLatestCore" xml:space="preserve"> <data name="IsLatestCore" xml:space="preserve">
<value>{0} {1} 已是最新版本</value> <value>{0} {1} 已是最新版本</value>
</data> </data>
<data name="IsLatestN" xml:space="preserve"> <data name="IsLatestN" xml:space="preserve">
<value>{0} {1} 已是最新版本</value> <value>{0} {1} 已是最新版本</value>
</data> </data>
<data name="LvAddress" xml:space="preserve"> <data name="LvAddress" xml:space="preserve">
<value>地址</value> <value>地址</value>
@@ -226,7 +226,7 @@
<value>未设置有效的订阅</value> <value>未设置有效的订阅</value>
</data> </data>
<data name="MsgParsingSuccessfully" xml:space="preserve"> <data name="MsgParsingSuccessfully" xml:space="preserve">
<value>解析{0}成功</value> <value>解析 {0} 成功</value>
</data> </data>
<data name="MsgStartGettingSubscriptions" xml:space="preserve"> <data name="MsgStartGettingSubscriptions" xml:space="preserve">
<value>开始获取订阅内容</value> <value>开始获取订阅内容</value>
@@ -259,10 +259,10 @@
<value>在文件夹 ({0}) 下未找到Core文件 (文件名:{1}),请下载后放入文件夹,下载地址: {2}</value> <value>在文件夹 ({0}) 下未找到Core文件 (文件名:{1}),请下载后放入文件夹,下载地址: {2}</value>
</data> </data>
<data name="NoValidQRcodeFound" xml:space="preserve"> <data name="NoValidQRcodeFound" xml:space="preserve">
<value>扫描完成,未发现有效二维码</value> <value>扫描完成未发现有效二维码</value>
</data> </data>
<data name="OperationFailed" xml:space="preserve"> <data name="OperationFailed" xml:space="preserve">
<value>操作失败,请检查重试</value> <value>操作失败,请检查重试</value>
</data> </data>
<data name="PleaseFillRemarks" xml:space="preserve"> <data name="PleaseFillRemarks" xml:space="preserve">
<value>请填写别名</value> <value>请填写别名</value>
@@ -280,10 +280,10 @@
<value>服务器去重完成。原数量: {0},现数量: {1}</value> <value>服务器去重完成。原数量: {0},现数量: {1}</value>
</data> </data>
<data name="RemoveServer" xml:space="preserve"> <data name="RemoveServer" xml:space="preserve">
<value>是否确定移除服务器?</value> <value>是否确定移除服务器</value>
</data> </data>
<data name="SaveClientConfigurationIn" xml:space="preserve"> <data name="SaveClientConfigurationIn" xml:space="preserve">
<value>客户端配置文件保存在:{0}</value> <value>客户端配置文件保存在{0}</value>
</data> </data>
<data name="StartService" xml:space="preserve"> <data name="StartService" xml:space="preserve">
<value>启动服务({0})...</value> <value>启动服务({0})...</value>
@@ -311,10 +311,10 @@
<value>请先选择规则</value> <value>请先选择规则</value>
</data> </data>
<data name="RemoveRules" xml:space="preserve"> <data name="RemoveRules" xml:space="preserve">
<value>是否确定移除规则?</value> <value>是否确定移除规则</value>
</data> </data>
<data name="RoutingRuleDetailRequiredTips" xml:space="preserve"> <data name="RoutingRuleDetailRequiredTips" xml:space="preserve">
<value>{0},必填其中一项.</value> <value>{0}必填其中一项.</value>
</data> </data>
<data name="LvRemarks" xml:space="preserve"> <data name="LvRemarks" xml:space="preserve">
<value>别名</value> <value>别名</value>
@@ -329,10 +329,10 @@
<value>请填写Url</value> <value>请填写Url</value>
</data> </data>
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve"> <data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
<value>是否追加规则?选择则追加,选择否则替换</value> <value>是否追加规则选择“是”则追加选择“否”则全部替换</value>
</data> </data>
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve"> <data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
<value>下载 GeoFile: {0} 成功</value> <value>下载 GeoFile{0} 成功</value>
</data> </data>
<data name="MsgInformationTitle" xml:space="preserve"> <data name="MsgInformationTitle" xml:space="preserve">
<value>信息</value> <value>信息</value>
@@ -386,7 +386,7 @@
<value>*Kcp seed</value> <value>*Kcp seed</value>
</data> </data>
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve"> <data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
<value>注册全局热键 {0} 失败,原因 {1}</value> <value>注册全局热键 {0} 失败原因{1}</value>
</data> </data>
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve"> <data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
<value>注册全局热键 {0} 成功</value> <value>注册全局热键 {0} 成功</value>
@@ -481,14 +481,8 @@
<data name="TbSettingsColor" xml:space="preserve"> <data name="TbSettingsColor" xml:space="preserve">
<value>颜色</value> <value>颜色</value>
</data> </data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>暗黑模式</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>是否跟随系统主题</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve"> <data name="TbSettingsLanguage" xml:space="preserve">
<value>语言(重启)</value> <value>语言(重启)</value>
</data> </data>
<data name="menuAddServerViaClipboard" xml:space="preserve"> <data name="menuAddServerViaClipboard" xml:space="preserve">
<value>从剪贴板导入分享链接 (Ctrl+V)</value> <value>从剪贴板导入分享链接 (Ctrl+V)</value>
@@ -638,7 +632,7 @@
<value>传输层安全(TLS)</value> <value>传输层安全(TLS)</value>
</data> </data>
<data name="TipNetwork" xml:space="preserve"> <data name="TipNetwork" xml:space="preserve">
<value>*默认tcp,选错会无法连接</value> <value>*默认tcp选错会无法连接</value>
</data> </data>
<data name="TbCoreType" xml:space="preserve"> <data name="TbCoreType" xml:space="preserve">
<value>Core类型</value> <value>Core类型</value>
@@ -671,7 +665,7 @@
<value>Socks端口</value> <value>Socks端口</value>
</data> </data>
<data name="TipPreSocksPort" xml:space="preserve"> <data name="TipPreSocksPort" xml:space="preserve">
<value>* 自定义配置的Socks端口值可不设置当设置此值后将使用Xray/sing-box(Tun)额外启动一个前置Socks服务提供分流和速度显示等功能</value> <value>*自定义配置的Socks端口值可不设置当设置此值后将使用Xray/sing-box(Tun)额外启动一个前置Socks服务提供分流和速度显示等功能</value>
</data> </data>
<data name="TbBrowse" xml:space="preserve"> <data name="TbBrowse" xml:space="preserve">
<value>浏览</value> <value>浏览</value>
@@ -680,7 +674,7 @@
<value>编辑</value> <value>编辑</value>
</data> </data>
<data name="TbSettingsAdvancedProtocol" xml:space="preserve"> <data name="TbSettingsAdvancedProtocol" xml:space="preserve">
<value>高级代理设置, 协议选择(可选)</value> <value>高级代理设置协议选择(可选)</value>
</data> </data>
<data name="TbSettingsAllowLAN" xml:space="preserve"> <data name="TbSettingsAllowLAN" xml:space="preserve">
<value>允许来自局域网的连接</value> <value>允许来自局域网的连接</value>
@@ -689,19 +683,19 @@
<value>启动后隐藏窗口</value> <value>启动后隐藏窗口</value>
</data> </data>
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve"> <data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
<value>自动更新Geo文件的间隔(单位小时)</value> <value>自动更新Geo文件的间隔(小时)</value>
</data> </data>
<data name="TbSettingsCore" xml:space="preserve"> <data name="TbSettingsCore" xml:space="preserve">
<value>Core: 基础设置</value> <value>Core: 基础设置</value>
</data> </data>
<data name="TbSettingsCoreDns" xml:space="preserve"> <data name="TbSettingsCoreDns" xml:space="preserve">
<value>V2ray DNS设置</value> <value>v2ray DNS设置</value>
</data> </data>
<data name="TbSettingsCoreKcp" xml:space="preserve"> <data name="TbSettingsCoreKcp" xml:space="preserve">
<value>Core: KCP设置</value> <value>Core: KCP设置</value>
</data> </data>
<data name="TbSettingsCoreType" xml:space="preserve"> <data name="TbSettingsCoreType" xml:space="preserve">
<value>Core类型设置</value> <value>Core 类型设置</value>
</data> </data>
<data name="TbSettingsDefAllowInsecure" xml:space="preserve"> <data name="TbSettingsDefAllowInsecure" xml:space="preserve">
<value>默认跳过证书验证(allowInsecure)</value> <value>默认跳过证书验证(allowInsecure)</value>
@@ -719,7 +713,7 @@
<value>例外</value> <value>例外</value>
</data> </data>
<data name="TbSettingsExceptionTip" xml:space="preserve"> <data name="TbSettingsExceptionTip" xml:space="preserve">
<value>例外. 对于下列字符开头的地址不使用代理配置文件:使用分号(;)分隔</value> <value>例外对于下列字符开头的地址不使用代理配置文件使用分号(;)分隔</value>
</data> </data>
<data name="TbSettingsHttpPort" xml:space="preserve"> <data name="TbSettingsHttpPort" xml:space="preserve">
<value>本地http监听端口</value> <value>本地http监听端口</value>
@@ -746,7 +740,7 @@
<value>认证密码</value> <value>认证密码</value>
</data> </data>
<data name="TbSettingsRemoteDNS" xml:space="preserve"> <data name="TbSettingsRemoteDNS" xml:space="preserve">
<value>自定义DNS(可多个,用逗号(,)分隔)</value> <value>自定义DNS(可多个用逗号(,)分隔)</value>
</data> </data>
<data name="TbSettingsSetUWP" xml:space="preserve"> <data name="TbSettingsSetUWP" xml:space="preserve">
<value>解除Win10 UWP应用回环代理限制</value> <value>解除Win10 UWP应用回环代理限制</value>
@@ -791,7 +785,7 @@
<value>全局热键设置</value> <value>全局热键设置</value>
</data> </data>
<data name="TbGlobalHotkeySettingTip" xml:space="preserve"> <data name="TbGlobalHotkeySettingTip" xml:space="preserve">
<value>直接按键盘进行设置, 重启后生效</value> <value>直接按键盘进行设置重启后生效</value>
</data> </data>
<data name="TbNotChangeSystemProxy" xml:space="preserve"> <data name="TbNotChangeSystemProxy" xml:space="preserve">
<value>不改变系统代理</value> <value>不改变系统代理</value>
@@ -830,7 +824,7 @@
<value>上移 (U)</value> <value>上移 (U)</value>
</data> </data>
<data name="MsgFilterTitle" xml:space="preserve"> <data name="MsgFilterTitle" xml:space="preserve">
<value>过滤器, 支持正则</value> <value>过滤器(支持正则)</value>
</data> </data>
<data name="menuWebsiteItem" xml:space="preserve"> <data name="menuWebsiteItem" xml:space="preserve">
<value>{0} 官网</value> <value>{0} 官网</value>
@@ -842,7 +836,7 @@
<value>添加规则集</value> <value>添加规则集</value>
</data> </data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve"> <data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>一键导入高级规则</value> <value>一键导入规则</value>
</data> </data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve"> <data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>移除所选规则 (Delete)</value> <value>移除所选规则 (Delete)</value>
@@ -856,9 +850,6 @@
<data name="TbdomainStrategy" xml:space="preserve"> <data name="TbdomainStrategy" xml:space="preserve">
<value>域名解析策略</value> <value>域名解析策略</value>
</data> </data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>启用高级功能</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve"> <data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.阻止的Domain或IP</value> <value>3.阻止的Domain或IP</value>
</data> </data>
@@ -872,7 +863,7 @@
<value>预定义规则集列表</value> <value>预定义规则集列表</value>
</data> </data>
<data name="TbRoutingTips" xml:space="preserve"> <data name="TbRoutingTips" xml:space="preserve">
<value>*设置的路由规则,用逗号(,)分隔;正则中的逗号用&lt;COMMA&gt;替代</value> <value>*设置的路由规则用逗号(,)分隔正则中的逗号用&lt;COMMA&gt;替代</value>
</data> </data>
<data name="menuImportRulesFromClipboard" xml:space="preserve"> <data name="menuImportRulesFromClipboard" xml:space="preserve">
<value>从剪贴板中导入规则</value> <value>从剪贴板中导入规则</value>
@@ -902,13 +893,13 @@
<value>路由规则详情设置</value> <value>路由规则详情设置</value>
</data> </data>
<data name="TbAutoSort" xml:space="preserve"> <data name="TbAutoSort" xml:space="preserve">
<value>保存时Domain, IP, 进程名 自动排序</value> <value>保存时 Domain, IP, 进程名 自动排序</value>
</data> </data>
<data name="TbRuleobjectDoc" xml:space="preserve"> <data name="TbRuleobjectDoc" xml:space="preserve">
<value>规则详细说明文档</value> <value>规则详细说明文档</value>
</data> </data>
<data name="TbDnsObjectDoc" xml:space="preserve"> <data name="TbDnsObjectDoc" xml:space="preserve">
<value>支持填写DnsObject,JSON格式点击查看文档</value> <value>支持填写DnsObjectJSON格式点击查看文档</value>
</data> </data>
<data name="SubUrlTips" xml:space="preserve"> <data name="SubUrlTips" xml:space="preserve">
<value>普通分组此处请留空</value> <value>普通分组此处请留空</value>
@@ -920,7 +911,7 @@
<value>系统代理设置改变</value> <value>系统代理设置改变</value>
</data> </data>
<data name="TbSettingsRouteOnly" xml:space="preserve"> <data name="TbSettingsRouteOnly" xml:space="preserve">
<value>RouteOnly</value> <value>仅限路由(routeOnly)</value>
</data> </data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve"> <data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>请勿将代理服务器用于本地Intranet地址</value> <value>请勿将代理服务器用于本地Intranet地址</value>
@@ -935,7 +926,7 @@
<value>速度(M/s)</value> <value>速度(M/s)</value>
</data> </data>
<data name="FailedToRunCore" xml:space="preserve"> <data name="FailedToRunCore" xml:space="preserve">
<value>运行Core失败请看日志</value> <value>运行Core失败看日志</value>
</data> </data>
<data name="LvFilter" xml:space="preserve"> <data name="LvFilter" xml:space="preserve">
<value>别名正则过滤</value> <value>别名正则过滤</value>
@@ -943,9 +934,6 @@
<data name="TbDisplayLog" xml:space="preserve"> <data name="TbDisplayLog" xml:space="preserve">
<value>显示日志</value> <value>显示日志</value>
</data> </data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>导入旧的配置文件guiNConfig</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve"> <data name="TbEnableTunAs" xml:space="preserve">
<value>启用Tun</value> <value>启用Tun</value>
</data> </data>
@@ -953,7 +941,7 @@
<value>为局域网开启新的端口</value> <value>为局域网开启新的端口</value>
</data> </data>
<data name="TbSettingsTunMode" xml:space="preserve"> <data name="TbSettingsTunMode" xml:space="preserve">
<value>Tun模式设置</value> <value>Tun 模式设置</value>
</data> </data>
<data name="menuMoveToGroup" xml:space="preserve"> <data name="menuMoveToGroup" xml:space="preserve">
<value>移至订阅分组</value> <value>移至订阅分组</value>
@@ -992,7 +980,7 @@
<value>拷贝字体TTF/TTC文件到目录guiFonts重启设置</value> <value>拷贝字体TTF/TTC文件到目录guiFonts重启设置</value>
</data> </data>
<data name="TbSettingsSocksPortTip" xml:space="preserve"> <data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>Pac端口= +2Xray API端口= +3mihomo API端口= +4</value> <value>Pac端口= +3Xray API端口= +4mihomo API端口= +5</value>
</data> </data>
<data name="TbSettingsStartBootTip" xml:space="preserve"> <data name="TbSettingsStartBootTip" xml:space="preserve">
<value>以管理员权限设置此项,在启动后获得管理员权限</value> <value>以管理员权限设置此项,在启动后获得管理员权限</value>
@@ -1315,9 +1303,6 @@
<data name="TipActiveServer" xml:space="preserve"> <data name="TipActiveServer" xml:space="preserve">
<value>活动</value> <value>活动</value>
</data> </data>
<data name="menuStorageUI" xml:space="preserve">
<value>保存界面布局</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve"> <data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo文件来源(可选)</value> <value>Geo文件来源(可选)</value>
</data> </data>
@@ -1342,6 +1327,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve"> <data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>俄罗斯</value> <value>俄罗斯</value>
</data> </data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>伊朗</value>
</data>
<data name="menuAddServerViaImage" xml:space="preserve"> <data name="menuAddServerViaImage" xml:space="preserve">
<value>扫描图片中的二维码</value> <value>扫描图片中的二维码</value>
</data> </data>
@@ -1370,7 +1358,7 @@
<value>请先在Tun模式设置中设置sudo密码</value> <value>请先在Tun模式设置中设置sudo密码</value>
</data> </data>
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve"> <data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
<value>请不要用sudo运行本app</value> <value>请不要用sudo运行本程序</value>
</data> </data>
<data name="TransportHeaderTypeTip5" xml:space="preserve"> <data name="TransportHeaderTypeTip5" xml:space="preserve">
<value>*xhttp 模式</value> <value>*xhttp 模式</value>
@@ -1382,6 +1370,24 @@
<value>关闭窗口时隐藏至托盘</value> <value>关闭窗口时隐藏至托盘</value>
</data> </data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve"> <data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>测时自动分批的每批数量最大1000</value> <value>测时自动分批的每批数量最大1000</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>例外:对于下列地址不使用代理配置文件。使用逗号(,)分隔。</value>
</data>
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>流量探测类型</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>开启第二个本地监听端口</value>
</data>
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks本地端口socks2第二个本地端口socks3局域网端口</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>主题</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>复制终端代理命令至剪贴板</value>
</data> </data>
</root> </root>

View File

@@ -136,7 +136,7 @@
<value>下載</value> <value>下載</value>
</data> </data>
<data name="DownloadYesNo" xml:space="preserve"> <data name="DownloadYesNo" xml:space="preserve">
<value>是否下載? {0}</value> <value>是否下載{0}</value>
</data> </data>
<data name="FailedConversionConfiguration" xml:space="preserve"> <data name="FailedConversionConfiguration" xml:space="preserve">
<value>轉換設定檔失敗</value> <value>轉換設定檔失敗</value>
@@ -154,7 +154,7 @@
<value>讀取設定檔失敗</value> <value>讀取設定檔失敗</value>
</data> </data>
<data name="FillCorrectServerPort" xml:space="preserve"> <data name="FillCorrectServerPort" xml:space="preserve">
<value>請填寫正確格式伺服器埠</value> <value>請填寫正確格式伺服器埠</value>
</data> </data>
<data name="FillLocalListeningPort" xml:space="preserve"> <data name="FillLocalListeningPort" xml:space="preserve">
<value>請填寫本機偵聽埠</value> <value>請填寫本機偵聽埠</value>
@@ -169,16 +169,16 @@
<value>請填寫使用者ID</value> <value>請填寫使用者ID</value>
</data> </data>
<data name="Incorrectconfiguration" xml:space="preserve"> <data name="Incorrectconfiguration" xml:space="preserve">
<value>不是正確的設定,請檢查</value> <value>設定不正確,請檢查</value>
</data> </data>
<data name="InitialConfiguration" xml:space="preserve"> <data name="InitialConfiguration" xml:space="preserve">
<value>初始化設定</value> <value>初始化設定</value>
</data> </data>
<data name="IsLatestCore" xml:space="preserve"> <data name="IsLatestCore" xml:space="preserve">
<value>{0} {1} 已是最新版本</value> <value>{0} {1} 已是最新版本</value>
</data> </data>
<data name="IsLatestN" xml:space="preserve"> <data name="IsLatestN" xml:space="preserve">
<value>{0} {1} 已是最新版本</value> <value>{0} {1} 已是最新版本</value>
</data> </data>
<data name="LvAddress" xml:space="preserve"> <data name="LvAddress" xml:space="preserve">
<value>位址</value> <value>位址</value>
@@ -226,7 +226,7 @@
<value>未設定有效的訂閱</value> <value>未設定有效的訂閱</value>
</data> </data>
<data name="MsgParsingSuccessfully" xml:space="preserve"> <data name="MsgParsingSuccessfully" xml:space="preserve">
<value>解析{0}成功</value> <value>解析 {0} 成功</value>
</data> </data>
<data name="MsgStartGettingSubscriptions" xml:space="preserve"> <data name="MsgStartGettingSubscriptions" xml:space="preserve">
<value>開始獲取訂閱內容</value> <value>開始獲取訂閱內容</value>
@@ -259,10 +259,10 @@
<value>在資料夾 ({0}) 下未找到Core檔案 (檔案名:{1}),請下載後放入資料夾,下載網址: {2}</value> <value>在資料夾 ({0}) 下未找到Core檔案 (檔案名:{1}),請下載後放入資料夾,下載網址: {2}</value>
</data> </data>
<data name="NoValidQRcodeFound" xml:space="preserve"> <data name="NoValidQRcodeFound" xml:space="preserve">
<value>掃描完成,未發現有效二維碼</value> <value>掃描完成未發現有效二維碼</value>
</data> </data>
<data name="OperationFailed" xml:space="preserve"> <data name="OperationFailed" xml:space="preserve">
<value>操作失敗,請檢查重試</value> <value>操作失敗,請檢查重試</value>
</data> </data>
<data name="PleaseFillRemarks" xml:space="preserve"> <data name="PleaseFillRemarks" xml:space="preserve">
<value>請填寫別名</value> <value>請填寫別名</value>
@@ -280,16 +280,17 @@
<value>伺服器去重完成。原數量: {0},現數量: {1}</value> <value>伺服器去重完成。原數量: {0},現數量: {1}</value>
</data> </data>
<data name="RemoveServer" xml:space="preserve"> <data name="RemoveServer" xml:space="preserve">
<value>是否確定移除伺服器?</value> <value>是否確定移除伺服器</value>
</data> </data>
<data name="SaveClientConfigurationIn" xml:space="preserve"> <data name="SaveClientConfigurationIn" xml:space="preserve">
<value>用戶端設定檔儲存在:{0}</value> <value>用戶端設定檔儲存在{0}</value>
</data> </data>
<data name="StartService" xml:space="preserve"> <data name="StartService" xml:space="preserve">
<value>啟動服務({0})...</value> <value>啟動服務({0})...</value>
</data> </data>
<data name="SuccessfulConfiguration" xml:space="preserve"> <data name="SuccessfulConfiguration" xml:space="preserve">
<value>設定成功{0}</value> <value>設定成功
{0}</value>
</data> </data>
<data name="SuccessfullyImportedCustomServer" xml:space="preserve"> <data name="SuccessfullyImportedCustomServer" xml:space="preserve">
<value>成功匯入自訂設定伺服器</value> <value>成功匯入自訂設定伺服器</value>
@@ -310,10 +311,10 @@
<value>請先選擇規則</value> <value>請先選擇規則</value>
</data> </data>
<data name="RemoveRules" xml:space="preserve"> <data name="RemoveRules" xml:space="preserve">
<value>是否確定移除規則?</value> <value>是否確定移除規則</value>
</data> </data>
<data name="RoutingRuleDetailRequiredTips" xml:space="preserve"> <data name="RoutingRuleDetailRequiredTips" xml:space="preserve">
<value>{0},必填其中一項.</value> <value>{0}必填其中一項.</value>
</data> </data>
<data name="LvRemarks" xml:space="preserve"> <data name="LvRemarks" xml:space="preserve">
<value>別名</value> <value>別名</value>
@@ -328,10 +329,10 @@
<value>請填寫URL</value> <value>請填寫URL</value>
</data> </data>
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve"> <data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
<value>是否追加規則?選擇則追加,選擇否則取代</value> <value>是否追加規則選擇“是”則追加選擇“否”則完全取代</value>
</data> </data>
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve"> <data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
<value>下載 GeoFile: {0} 成功</value> <value>下載 GeoFile{0} 成功</value>
</data> </data>
<data name="MsgInformationTitle" xml:space="preserve"> <data name="MsgInformationTitle" xml:space="preserve">
<value>資訊</value> <value>資訊</value>
@@ -385,7 +386,7 @@
<value>*KCP seed</value> <value>*KCP seed</value>
</data> </data>
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve"> <data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
<value>註冊全域快速鍵 {0} 失敗,原因 {1}</value> <value>註冊全域快速鍵 {0} 失敗原因{1}</value>
</data> </data>
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve"> <data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
<value>註冊全域快速鍵 {0} 成功</value> <value>註冊全域快速鍵 {0} 成功</value>
@@ -480,14 +481,8 @@
<data name="TbSettingsColor" xml:space="preserve"> <data name="TbSettingsColor" xml:space="preserve">
<value>顏色</value> <value>顏色</value>
</data> </data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>暗黑模式</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>是否跟隨系統主題</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve"> <data name="TbSettingsLanguage" xml:space="preserve">
<value>語言(重啟)</value> <value>語言(重啟)</value>
</data> </data>
<data name="menuAddServerViaClipboard" xml:space="preserve"> <data name="menuAddServerViaClipboard" xml:space="preserve">
<value>從剪貼簿導入分享鏈接 (Ctrl+V)</value> <value>從剪貼簿導入分享鏈接 (Ctrl+V)</value>
@@ -637,7 +632,7 @@
<value>傳輸層安全(TLS)</value> <value>傳輸層安全(TLS)</value>
</data> </data>
<data name="TipNetwork" xml:space="preserve"> <data name="TipNetwork" xml:space="preserve">
<value>*預設TCP,選錯會無法連接</value> <value>*預設TCP選錯會無法連接</value>
</data> </data>
<data name="TbCoreType" xml:space="preserve"> <data name="TbCoreType" xml:space="preserve">
<value>Core類型</value> <value>Core類型</value>
@@ -670,7 +665,7 @@
<value>SOCKS埠</value> <value>SOCKS埠</value>
</data> </data>
<data name="TipPreSocksPort" xml:space="preserve"> <data name="TipPreSocksPort" xml:space="preserve">
<value>* 自訂設定的Socks埠值可不設定當設定此值後將使用Xray/sing-box(Tun)額外啟動一個前置Socks服務提供分流和速度顯示等功能</value> <value>*自訂設定的Socks埠值可不設定當設定此值後將使用Xray/sing-box(Tun)額外啟動一個前置Socks服務提供分流和速度顯示等功能</value>
</data> </data>
<!--********************************************--> <!--********************************************-->
<data name="TbBrowse" xml:space="preserve"> <data name="TbBrowse" xml:space="preserve">
@@ -680,7 +675,7 @@
<value>編輯</value> <value>編輯</value>
</data> </data>
<data name="TbSettingsAdvancedProtocol" xml:space="preserve"> <data name="TbSettingsAdvancedProtocol" xml:space="preserve">
<value>進階代理設定, 協定選擇(可選)</value> <value>進階代理設定協定選擇(可選)</value>
</data> </data>
<data name="TbSettingsAllowLAN" xml:space="preserve"> <data name="TbSettingsAllowLAN" xml:space="preserve">
<value>允許來自區域網路的連線</value> <value>允許來自區域網路的連線</value>
@@ -689,7 +684,7 @@
<value>啟動後隱藏視窗</value> <value>啟動後隱藏視窗</value>
</data> </data>
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve"> <data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
<value>自動更新Geo檔案的間隔(單位小時)</value> <value>自動更新Geo檔案的間隔(小時)</value>
</data> </data>
<data name="TbSettingsCore" xml:space="preserve"> <data name="TbSettingsCore" xml:space="preserve">
<value>Core: 基礎設定</value> <value>Core: 基礎設定</value>
@@ -701,7 +696,7 @@
<value>Core: KCP設定</value> <value>Core: KCP設定</value>
</data> </data>
<data name="TbSettingsCoreType" xml:space="preserve"> <data name="TbSettingsCoreType" xml:space="preserve">
<value>Core類型設定</value> <value>Core 類型設定</value>
</data> </data>
<data name="TbSettingsDefAllowInsecure" xml:space="preserve"> <data name="TbSettingsDefAllowInsecure" xml:space="preserve">
<value>預設跳過憑證驗證(allowinsecure)</value> <value>預設跳過憑證驗證(allowinsecure)</value>
@@ -719,7 +714,7 @@
<value>例外</value> <value>例外</value>
</data> </data>
<data name="TbSettingsExceptionTip" xml:space="preserve"> <data name="TbSettingsExceptionTip" xml:space="preserve">
<value>例外. 對於下列字元開頭的位址不使用代理設定檔:使用分號(;)分隔</value> <value>例外對於下列字元開頭的位址不使用代理設定檔使用分號(;)分隔</value>
</data> </data>
<data name="TbSettingsHttpPort" xml:space="preserve"> <data name="TbSettingsHttpPort" xml:space="preserve">
<value>本機HTTP偵聽埠</value> <value>本機HTTP偵聽埠</value>
@@ -746,7 +741,7 @@
<value>認證密碼</value> <value>認證密碼</value>
</data> </data>
<data name="TbSettingsRemoteDNS" xml:space="preserve"> <data name="TbSettingsRemoteDNS" xml:space="preserve">
<value>自訂DNS(可多個,用逗號(,)分隔)</value> <value>自訂DNS(可多個用逗號(,)分隔)</value>
</data> </data>
<data name="TbSettingsSetUWP" xml:space="preserve"> <data name="TbSettingsSetUWP" xml:space="preserve">
<value>解除Win10 UWP應用回環代理限制</value> <value>解除Win10 UWP應用回環代理限制</value>
@@ -791,7 +786,7 @@
<value>全域快速鍵設定</value> <value>全域快速鍵設定</value>
</data> </data>
<data name="TbGlobalHotkeySettingTip" xml:space="preserve"> <data name="TbGlobalHotkeySettingTip" xml:space="preserve">
<value>直接按鍵盤進行設定, 重啟後生效</value> <value>直接按鍵盤進行設定重啟後生效</value>
</data> </data>
<data name="TbNotChangeSystemProxy" xml:space="preserve"> <data name="TbNotChangeSystemProxy" xml:space="preserve">
<value>不改變系統代理</value> <value>不改變系統代理</value>
@@ -830,7 +825,7 @@
<value>上移 (U)</value> <value>上移 (U)</value>
</data> </data>
<data name="MsgFilterTitle" xml:space="preserve"> <data name="MsgFilterTitle" xml:space="preserve">
<value>過濾, 支援正則</value> <value>過濾(允許正則)</value>
</data> </data>
<data name="menuWebsiteItem" xml:space="preserve"> <data name="menuWebsiteItem" xml:space="preserve">
<value>{0} 官網</value> <value>{0} 官網</value>
@@ -842,7 +837,7 @@
<value>新增規則集</value> <value>新增規則集</value>
</data> </data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve"> <data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>一鍵匯入進階規則</value> <value>一鍵匯入規則</value>
</data> </data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve"> <data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>移除所選規則 (Delete)</value> <value>移除所選規則 (Delete)</value>
@@ -856,9 +851,6 @@
<data name="TbdomainStrategy" xml:space="preserve"> <data name="TbdomainStrategy" xml:space="preserve">
<value>域名解析策略</value> <value>域名解析策略</value>
</data> </data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>啟動進階功能</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve"> <data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.阻止的Domain或IP</value> <value>3.阻止的Domain或IP</value>
</data> </data>
@@ -872,7 +864,7 @@
<value>預定義規則集列表</value> <value>預定義規則集列表</value>
</data> </data>
<data name="TbRoutingTips" xml:space="preserve"> <data name="TbRoutingTips" xml:space="preserve">
<value>*設定的路由規則,用逗號(,)分隔;正則中的逗號用&lt;COMMA&gt;替代</value> <value>*設定的路由規則用逗號(,)分隔正則中的逗號用&lt;COMMA&gt;替代</value>
</data> </data>
<data name="menuImportRulesFromClipboard" xml:space="preserve"> <data name="menuImportRulesFromClipboard" xml:space="preserve">
<value>從剪貼簿中匯入規則</value> <value>從剪貼簿中匯入規則</value>
@@ -902,13 +894,13 @@
<value>路由規則詳情設定</value> <value>路由規則詳情設定</value>
</data> </data>
<data name="TbAutoSort" xml:space="preserve"> <data name="TbAutoSort" xml:space="preserve">
<value>儲存時Domain, IP, 行程名 自動排序</value> <value>儲存時 Domain, IP, 行程名 自動排序</value>
</data> </data>
<data name="TbRuleobjectDoc" xml:space="preserve"> <data name="TbRuleobjectDoc" xml:space="preserve">
<value>規則詳細說明檔案</value> <value>規則詳細說明檔案</value>
</data> </data>
<data name="TbDnsObjectDoc" xml:space="preserve"> <data name="TbDnsObjectDoc" xml:space="preserve">
<value>支援填寫DnsObject,JSON格式點擊查看檔案</value> <value>支援填寫DnsObjectJSON格式點擊查看説明</value>
</data> </data>
<data name="SubUrlTips" xml:space="preserve"> <data name="SubUrlTips" xml:space="preserve">
<value>普通分組此處請留空</value> <value>普通分組此處請留空</value>
@@ -920,7 +912,7 @@
<value>系統代理設定已改變</value> <value>系統代理設定已改變</value>
</data> </data>
<data name="TbSettingsRouteOnly" xml:space="preserve"> <data name="TbSettingsRouteOnly" xml:space="preserve">
<value>RouteOnly</value> <value>僅限路由(routeOnly)</value>
</data> </data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve"> <data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>請勿將代理伺服器用於本機Intranet位址</value> <value>請勿將代理伺服器用於本機Intranet位址</value>
@@ -935,7 +927,7 @@
<value>速度(M/s)</value> <value>速度(M/s)</value>
</data> </data>
<data name="FailedToRunCore" xml:space="preserve"> <data name="FailedToRunCore" xml:space="preserve">
<value>執行Core失敗日誌</value> <value>執行Core失敗查閲日誌</value>
</data> </data>
<data name="LvFilter" xml:space="preserve"> <data name="LvFilter" xml:space="preserve">
<value>別名正則過濾</value> <value>別名正則過濾</value>
@@ -943,17 +935,14 @@
<data name="TbDisplayLog" xml:space="preserve"> <data name="TbDisplayLog" xml:space="preserve">
<value>顯示日誌</value> <value>顯示日誌</value>
</data> </data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>匯入舊的設定檔guiNConfig</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve"> <data name="TbEnableTunAs" xml:space="preserve">
<value>啟用TUN</value> <value>啟用Tun</value>
</data> </data>
<data name="TbSettingsNewPort4LAN" xml:space="preserve"> <data name="TbSettingsNewPort4LAN" xml:space="preserve">
<value>為區域網路開啟新的埠</value> <value>為區域網路開啟新的埠</value>
</data> </data>
<data name="TbSettingsTunMode" xml:space="preserve"> <data name="TbSettingsTunMode" xml:space="preserve">
<value>TUN模式設定</value> <value>Tun 模式設定</value>
</data> </data>
<data name="menuMoveToGroup" xml:space="preserve"> <data name="menuMoveToGroup" xml:space="preserve">
<value>移至訂閱分組</value> <value>移至訂閱分組</value>
@@ -992,7 +981,7 @@
<value>複製字型TTF/TTC檔案到目錄guiFonts重啟設定</value> <value>複製字型TTF/TTC檔案到目錄guiFonts重啟設定</value>
</data> </data>
<data name="TbSettingsSocksPortTip" xml:space="preserve"> <data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>Pac連接埠= +2Xray API連接埠= +3mihomo API連接埠= +4</value> <value>Pac連接埠= +3Xray API連接埠= +4mihomo API連接埠= +5</value>
</data> </data>
<data name="TbSettingsStartBootTip" xml:space="preserve"> <data name="TbSettingsStartBootTip" xml:space="preserve">
<value>以管理員權限設定此項,在啟動後獲得管理員權限</value> <value>以管理員權限設定此項,在啟動後獲得管理員權限</value>
@@ -1067,7 +1056,7 @@
<value>sing-box Mux 多路復用協定</value> <value>sing-box Mux 多路復用協定</value>
</data> </data>
<data name="TbRoutingRuleProcess" xml:space="preserve"> <data name="TbRoutingRuleProcess" xml:space="preserve">
<value>行程名全稱 (TUN模式)</value> <value>行程名全稱 (Tun模式)</value>
</data> </data>
<data name="TbRoutingRuleDomain" xml:space="preserve"> <data name="TbRoutingRuleDomain" xml:space="preserve">
<value>Domain</value> <value>Domain</value>
@@ -1195,9 +1184,6 @@
<data name="TipActiveServer" xml:space="preserve"> <data name="TipActiveServer" xml:space="preserve">
<value>活動</value> <value>活動</value>
</data> </data>
<data name="menuStorageUI" xml:space="preserve">
<value>儲存介面佈局</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve"> <data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo檔案來源(可選)</value> <value>Geo檔案來源(可選)</value>
</data> </data>
@@ -1222,6 +1208,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve"> <data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>俄羅斯</value> <value>俄羅斯</value>
</data> </data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>伊朗</value>
</data>
<data name="menuAddServerViaImage" xml:space="preserve"> <data name="menuAddServerViaImage" xml:space="preserve">
<value>掃描圖片中的二維碼</value> <value>掃描圖片中的二維碼</value>
</data> </data>
@@ -1370,7 +1359,7 @@
<value>請先在Tun模式設定中設定sudo密碼</value> <value>請先在Tun模式設定中設定sudo密碼</value>
</data> </data>
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve"> <data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
<value>請不要用sudo來運行本app</value> <value>請不要用sudo來運行此App</value>
</data> </data>
<data name="TransportHeaderTypeTip5" xml:space="preserve"> <data name="TransportHeaderTypeTip5" xml:space="preserve">
<value>*xhttp 模式</value> <value>*xhttp 模式</value>
@@ -1382,6 +1371,24 @@
<value>關閉視窗時隱藏至托盤</value> <value>關閉視窗時隱藏至托盤</value>
</data> </data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve"> <data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>測時自動分批的每批數量最大1000</value> <value>測時自動分批的每批數量最大1000</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>例外:對於下列位址不使用代理設定檔,使用逗號(,)分隔。</value>
</data>
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>流量探測類型</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>開啟第二個本機監聽埠</value>
</data>
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks本地端口socks2第二個本地端口socks3區域網路端口</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>主題</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>複製終端代理指令至剪貼簿</value>
</data> </data>
</root> </root>

View File

@@ -5,24 +5,25 @@
"loglevel": "warning" "loglevel": "warning"
}, },
"inbounds": [], "inbounds": [],
"outbounds": [{ "outbounds": [
{
"tag": "proxy", "tag": "proxy",
"protocol": "vmess", "protocol": "vmess",
"settings": { "settings": {
"vnext": [{ "vnext": [{
"address": "v2ray.cool", "address": "",
"port": 10086, "port": 0,
"users": [{ "users": [{
"id": "a3482e88-686a-4a58-8126-99c9df64b7bf", "id": "",
"security": "auto" "security": "auto"
}] }]
}], }],
"servers": [{ "servers": [{
"address": "v2ray.cool", "address": "",
"method": "chacha20", "method": "",
"ota": false, "ota": false,
"password": "123456", "password": "",
"port": 10086, "port": 0,
"level": 1 "level": 1
}] }]
}, },
@@ -35,27 +36,23 @@
}, },
{ {
"protocol": "freedom", "protocol": "freedom",
"settings": {},
"tag": "direct" "tag": "direct"
}, },
{ {
"protocol": "blackhole", "protocol": "blackhole",
"tag": "block", "tag": "block"
"settings": {
"response": {
"type": "http"
}
}
} }
], ],
"routing": { "routing": {
"domainStrategy": "IPIfNonMatch", "domainStrategy": "IPIfNonMatch",
"rules": [ "rules": [
{ {
"inboundTag": ["api"], "inboundTag": [
"outboundTag": "api", "api"
"type": "field" ],
} "outboundTag": "api",
"type": "field"
}
] ]
} }
} }

View File

@@ -1,149 +1,156 @@
[ [
{ {
"remarks": "绕过bittorrent", "remarks": "绕过bittorrent",
"outboundTag": "direct", "outboundTag": "direct",
"protocol": [ "protocol": [
"bittorrent" "bittorrent"
] ]
}, },
{ {
"remarks": "Google cn", "remarks": "api.ip.sb",
"outboundTag": "proxy", "outboundTag": "proxy",
"domain": [ "domain": [
"domain:googleapis.cn", "api.ip.sb"
"domain:gstatic.com" ]
] },
}, {
{ "remarks": "Google cn",
"remarks": "阻断udp443", "outboundTag": "proxy",
"outboundTag": "block", "domain": [
"port": "443", "domain:googleapis.cn",
"network": "udp" "domain:gstatic.com"
}, ]
{ },
"remarks": "阻断广告", {
"outboundTag": "block", "remarks": "阻断udp443",
"domain": [ "outboundTag": "block",
"geosite:category-ads-all" "port": "443",
] "network": "udp"
}, },
{ {
"remarks": "绕过局域网IP", "remarks": "阻断广告",
"outboundTag": "direct", "outboundTag": "block",
"ip": [ "domain": [
"geoip:private" "geosite:category-ads-all"
] ]
}, },
{ {
"remarks": "绕过局域网域名", "remarks": "绕过局域网IP",
"outboundTag": "direct", "outboundTag": "direct",
"domain": [ "ip": [
"geosite:private" "geoip:private"
] ]
}, },
{ {
"remarks": "代理海外公共DNSIP", "remarks": "绕过局域网域名",
"outboundTag": "proxy", "outboundTag": "direct",
"ip": [ "domain": [
"1.1.1.1", "geosite:private"
"1.0.0.1", ]
"2606:4700:4700::1111", },
"2606:4700:4700::1001", {
"1.1.1.2", "remarks": "代理海外公共DNSIP",
"1.0.0.2", "outboundTag": "proxy",
"2606:4700:4700::1112", "ip": [
"2606:4700:4700::1002", "1.1.1.1",
"1.1.1.3", "1.0.0.1",
"1.0.0.3", "2606:4700:4700::1111",
"2606:4700:4700::1113", "2606:4700:4700::1001",
"2606:4700:4700::1003", "1.1.1.2",
"8.8.8.8", "1.0.0.2",
"8.8.4.4", "2606:4700:4700::1112",
"2001:4860:4860::8888", "2606:4700:4700::1002",
"2001:4860:4860::8844", "1.1.1.3",
"94.140.14.14", "1.0.0.3",
"94.140.15.15", "2606:4700:4700::1113",
"2a10:50c0::ad1:ff", "2606:4700:4700::1003",
"2a10:50c0::ad2:ff", "8.8.8.8",
"94.140.14.15", "8.8.4.4",
"94.140.15.16", "2001:4860:4860::8888",
"2a10:50c0::bad1:ff", "2001:4860:4860::8844",
"2a10:50c0::bad2:ff", "94.140.14.14",
"94.140.14.140", "94.140.15.15",
"94.140.14.141", "2a10:50c0::ad1:ff",
"2a10:50c0::1:ff", "2a10:50c0::ad2:ff",
"2a10:50c0::2:ff", "94.140.14.15",
"208.67.222.222", "94.140.15.16",
"208.67.220.220", "2a10:50c0::bad1:ff",
"2620:119:35::35", "2a10:50c0::bad2:ff",
"2620:119:53::53", "94.140.14.140",
"208.67.222.123", "94.140.14.141",
"208.67.220.123", "2a10:50c0::1:ff",
"2620:119:35::123", "2a10:50c0::2:ff",
"2620:119:53::123", "208.67.222.222",
"9.9.9.9", "208.67.220.220",
"149.112.112.112", "2620:119:35::35",
"2620:fe::9", "2620:119:53::53",
"2620:fe::fe", "208.67.222.123",
"9.9.9.11", "208.67.220.123",
"149.112.112.11", "2620:119:35::123",
"2620:fe::11", "2620:119:53::123",
"2620:fe::fe:11", "9.9.9.9",
"9.9.9.10", "149.112.112.112",
"149.112.112.10", "2620:fe::9",
"2620:fe::10", "2620:fe::fe",
"2620:fe::fe:10", "9.9.9.11",
"77.88.8.8", "149.112.112.11",
"77.88.8.1", "2620:fe::11",
"2a02:6b8::feed:0ff", "2620:fe::fe:11",
"2a02:6b8:0:1::feed:0ff", "9.9.9.10",
"77.88.8.88", "149.112.112.10",
"77.88.8.2", "2620:fe::10",
"2a02:6b8::feed:bad", "2620:fe::fe:10",
"2a02:6b8:0:1::feed:bad", "77.88.8.8",
"77.88.8.7", "77.88.8.1",
"77.88.8.3", "2a02:6b8::feed:0ff",
"2a02:6b8::feed:a11", "2a02:6b8:0:1::feed:0ff",
"2a02:6b8:0:1::feed:a11" "77.88.8.88",
] "77.88.8.2",
}, "2a02:6b8::feed:bad",
{ "2a02:6b8:0:1::feed:bad",
"remarks": "代理海外公共DNS域名", "77.88.8.7",
"outboundTag": "proxy", "77.88.8.3",
"domain": [ "2a02:6b8::feed:a11",
"domain:cloudflare-dns.com", "2a02:6b8:0:1::feed:a11"
"domain:one.one.one.one", ]
"domain:dns.google", },
"domain:adguard-dns.com", {
"domain:opendns.com", "remarks": "代理海外公共DNS域名",
"domain:umbrella.com", "outboundTag": "proxy",
"domain:quad9.net", "domain": [
"domain:yandex.net" "domain:cloudflare-dns.com",
] "domain:one.one.one.one",
}, "domain:dns.google",
{ "domain:adguard-dns.com",
"remarks": "代理IP", "domain:opendns.com",
"outboundTag": "proxy", "domain:umbrella.com",
"ip": [ "domain:quad9.net",
"geoip:facebook", "domain:yandex.net"
"geoip:fastly", ]
"geoip:google", },
"geoip:netflix", {
"geoip:telegram", "remarks": "代理IP",
"geoip:twitter" "outboundTag": "proxy",
] "ip": [
}, "geoip:facebook",
{ "geoip:fastly",
"remarks": "代理GFW", "geoip:google",
"outboundTag": "proxy", "geoip:netflix",
"domain": [ "geoip:telegram",
"geosite:gfw", "geoip:twitter"
"geosite:greatfire" ]
] },
}, {
{ "remarks": "代理GFW",
"remarks": "最终直连", "outboundTag": "proxy",
"port": "0-65535", "domain": [
"outboundTag": "direct" "geosite:gfw",
} "geosite:greatfire"
]
},
{
"remarks": "最终直连",
"port": "0-65535",
"outboundTag": "direct"
}
] ]

View File

@@ -1,21 +0,0 @@
[
{
"domain": [
"geosite:google"
],
"outboundTag": "proxy"
},
{
"outboundTag": "direct",
"domain": [
"domain:example-example.com",
"domain:example-example2.com"
]
},
{
"outboundTag": "block",
"domain": [
"geosite:category-ads-all"
]
}
]

View File

@@ -1,29 +0,0 @@
[
{
"remarks": "block",
"outboundTag": "block",
"domain": [
"geosite:category-ads-all"
]
},
{
"remarks": "direct",
"outboundTag": "direct",
"domain": [
"geosite:cn"
]
},
{
"remarks": "direct",
"outboundTag": "direct",
"ip": [
"geoip:private",
"geoip:cn"
]
},
{
"remarks": "proxy",
"port": "0-65535",
"outboundTag": "proxy"
}
]

View File

@@ -99,10 +99,5 @@
"domain": [ "domain": [
"geosite:cn" "geosite:cn"
] ]
},
{
"remarks": "最终代理",
"port": "0-65535",
"outboundTag": "proxy"
} }
] ]

View File

@@ -4,6 +4,15 @@
"proxy.example.com": "127.0.0.1" "proxy.example.com": "127.0.0.1"
}, },
"servers": [ "servers": [
{
"address": "1.1.1.1",
"domains": [
"geosite:geolocation-!cn"
],
"expectIPs": [
"geoip:!cn"
]
},
{ {
"address": "223.5.5.5", "address": "223.5.5.5",
"domains": [ "domains": [
@@ -13,7 +22,6 @@
"geoip:cn" "geoip:cn"
] ]
}, },
"1.1.1.1",
"8.8.8.8", "8.8.8.8",
"https://dns.google/dns-query" "https://dns.google/dns-query"
] ]

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Version>7.3.0</Version> <Version>7.6.1</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -14,9 +14,9 @@
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" /> <PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
<PackageReference Include="Splat.NLog" Version="15.2.22" /> <PackageReference Include="Splat.NLog" Version="15.2.22" />
<PackageReference Include="WebDav.Client" Version="2.8.0" /> <PackageReference Include="WebDav.Client" Version="2.8.0" />
<PackageReference Include="YamlDotNet" Version="16.2.1" /> <PackageReference Include="YamlDotNet" Version="16.3.0" />
<PackageReference Include="QRCoder" Version="1.6.0" /> <PackageReference Include="QRCoder" Version="1.6.0" />
<PackageReference Include="CliWrap" Version="3.6.7" /> <PackageReference Include="CliWrap" Version="3.7.0" />
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" /> <PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
<PackageReference Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" /> <PackageReference Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
<PackageReference Include="TaskScheduler" Version="2.11.0" /> <PackageReference Include="TaskScheduler" Version="2.11.0" />
@@ -28,8 +28,6 @@
<EmbeddedResource Include="Sample\clash_tun_yaml" /> <EmbeddedResource Include="Sample\clash_tun_yaml" />
<EmbeddedResource Include="Sample\custom_routing_black" /> <EmbeddedResource Include="Sample\custom_routing_black" />
<EmbeddedResource Include="Sample\custom_routing_global" /> <EmbeddedResource Include="Sample\custom_routing_global" />
<EmbeddedResource Include="Sample\custom_routing_locked" />
<EmbeddedResource Include="Sample\custom_routing_rules" />
<EmbeddedResource Include="Sample\custom_routing_white" /> <EmbeddedResource Include="Sample\custom_routing_white" />
<EmbeddedResource Include="Sample\dns_singbox_normal" /> <EmbeddedResource Include="Sample\dns_singbox_normal" />
<EmbeddedResource Include="Sample\dns_v2ray_normal" /> <EmbeddedResource Include="Sample\dns_v2ray_normal" />
@@ -60,6 +58,9 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>PublicResXFileCodeGenerator</Generator> <Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.hu.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.resx"> <EmbeddedResource Update="Resx\ResUI.resx">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<LastGenOutput>ResUI.Designer.cs</LastGenOutput> <LastGenOutput>ResUI.Designer.cs</LastGenOutput>

View File

@@ -6,6 +6,7 @@ namespace ServiceLib.Services.CoreConfig
public class CoreConfigClashService public class CoreConfigClashService
{ {
private Config _config; private Config _config;
private static readonly string _tag = "CoreConfigClashService";
public CoreConfigClashService(Config config) public CoreConfigClashService(Config config)
{ {
@@ -131,7 +132,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("GenerateClientConfigClash-Mixin", ex); Logging.SaveLog($"{_tag}-Mixin", ex);
} }
var txtFileNew = YamlUtils.ToYaml(fileContent).Replace(tagYamlStr2, tagYamlStr3); var txtFileNew = YamlUtils.ToYaml(fileContent).Replace(tagYamlStr2, tagYamlStr3);
@@ -151,7 +152,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("GenerateClientConfigClash", ex); Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }

View File

@@ -7,6 +7,7 @@ namespace ServiceLib.Services.CoreConfig
public class CoreConfigSingboxService public class CoreConfigSingboxService
{ {
private Config _config; private Config _config;
private static readonly string _tag = "CoreConfigSingboxService";
public CoreConfigSingboxService(Config config) public CoreConfigSingboxService(Config config)
{ {
@@ -71,7 +72,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("GenerateClientConfig4Singbox", ex); Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }
@@ -114,7 +115,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
await GenLog(singboxConfig); await GenLog(singboxConfig);
@@ -122,7 +123,7 @@ namespace ServiceLib.Services.CoreConfig
singboxConfig.inbounds.Clear(); singboxConfig.inbounds.Clear();
singboxConfig.outbounds.RemoveAt(0); singboxConfig.outbounds.RemoveAt(0);
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest); var initPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
foreach (var it in selecteds) foreach (var it in selecteds)
{ {
@@ -144,8 +145,8 @@ namespace ServiceLib.Services.CoreConfig
} }
//find unused port //find unused port
var port = httpPort; var port = initPort;
for (int k = httpPort; k < Global.MaxPort; k++) for (int k = initPort; k < Global.MaxPort; k++)
{ {
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0) if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
{ {
@@ -157,7 +158,7 @@ namespace ServiceLib.Services.CoreConfig
} }
//found //found
port = k; port = k;
httpPort = port + 1; initPort = port + 1;
break; break;
} }
@@ -235,7 +236,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }
@@ -312,7 +313,7 @@ namespace ServiceLib.Services.CoreConfig
var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound); var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
await GenOutbound(item, outbound); await GenOutbound(item, outbound);
outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}"; outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}";
singboxConfig.outbounds.Add(outbound); singboxConfig.outbounds.Insert(0, outbound);
tagProxy.Add(outbound.tag); tagProxy.Add(outbound.tag);
} }
if (tagProxy.Count <= 0) if (tagProxy.Count <= 0)
@@ -332,7 +333,7 @@ namespace ServiceLib.Services.CoreConfig
outbounds = tagProxy, outbounds = tagProxy,
interrupt_exist_connections = false, interrupt_exist_connections = false,
}; };
singboxConfig.outbounds.Add(outUrltest); singboxConfig.outbounds.Insert(0, outUrltest);
//add selector outbound //add selector outbound
var outSelector = new Outbound4Sbox var outSelector = new Outbound4Sbox
@@ -343,7 +344,7 @@ namespace ServiceLib.Services.CoreConfig
interrupt_exist_connections = false, interrupt_exist_connections = false,
}; };
outSelector.outbounds.Insert(0, outUrltest.tag); outSelector.outbounds.Insert(0, outUrltest.tag);
singboxConfig.outbounds.Add(outSelector); singboxConfig.outbounds.Insert(0, outSelector);
ret.Success = true; ret.Success = true;
ret.Data = JsonUtils.Serialize(singboxConfig); ret.Data = JsonUtils.Serialize(singboxConfig);
@@ -351,7 +352,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }
@@ -409,7 +410,9 @@ namespace ServiceLib.Services.CoreConfig
{ {
await GenInbounds(singboxConfig); await GenInbounds(singboxConfig);
await GenExperimental(singboxConfig); await GenExperimental(singboxConfig);
JsonUtils.ToFile(singboxConfig, fileName, false);
var content = JsonUtils.Serialize(singboxConfig, true);
await File.WriteAllTextAsync(fileName, content);
} }
} }
else else
@@ -430,7 +433,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }
@@ -440,7 +443,7 @@ namespace ServiceLib.Services.CoreConfig
#region private gen function #region private gen function
public async Task<int> GenLog(SingboxConfig singboxConfig) private async Task<int> GenLog(SingboxConfig singboxConfig)
{ {
try try
{ {
@@ -471,7 +474,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
@@ -505,11 +508,17 @@ namespace ServiceLib.Services.CoreConfig
inbound.domain_strategy = routing.DomainStrategy4Singbox; inbound.domain_strategy = routing.DomainStrategy4Singbox;
} }
if (_config.Inbound.First().SecondLocalPortEnabled)
{
var inbound2 = GetInbound(inbound, EInboundProtocol.socks2, true);
singboxConfig.inbounds.Add(inbound2);
}
if (_config.Inbound.First().AllowLANConn) if (_config.Inbound.First().AllowLANConn)
{ {
if (_config.Inbound.First().NewPort4LAN) if (_config.Inbound.First().NewPort4LAN)
{ {
var inbound3 = GetInbound(inbound, EInboundProtocol.socks2, true); var inbound3 = GetInbound(inbound, EInboundProtocol.socks3, true);
inbound3.listen = listen; inbound3.listen = listen;
singboxConfig.inbounds.Add(inbound3); singboxConfig.inbounds.Add(inbound3);
@@ -554,7 +563,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
@@ -568,7 +577,7 @@ namespace ServiceLib.Services.CoreConfig
return inbound; return inbound;
} }
public async Task<int> GenOutbound(ProfileItem node, Outbound4Sbox outbound) private async Task<int> GenOutbound(ProfileItem node, Outbound4Sbox outbound)
{ {
try try
{ {
@@ -687,12 +696,12 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
public async Task<int> GenOutboundMux(ProfileItem node, Outbound4Sbox outbound) private async Task<int> GenOutboundMux(ProfileItem node, Outbound4Sbox outbound)
{ {
try try
{ {
@@ -710,12 +719,12 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
public async Task<int> GenOutboundTls(ProfileItem node, Outbound4Sbox outbound) private async Task<int> GenOutboundTls(ProfileItem node, Outbound4Sbox outbound)
{ {
try try
{ {
@@ -760,12 +769,12 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
public async Task<int> GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound) private async Task<int> GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound)
{ {
try try
{ {
@@ -837,7 +846,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
@@ -889,7 +898,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
@@ -961,7 +970,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
@@ -992,7 +1001,7 @@ namespace ServiceLib.Services.CoreConfig
} }
} }
public async Task<int> GenRoutingUserRule(RulesItem item, List<Rule4Sbox> rules) private async Task<int> GenRoutingUserRule(RulesItem item, List<Rule4Sbox> rules)
{ {
try try
{ {
@@ -1077,7 +1086,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
@@ -1150,7 +1159,7 @@ namespace ServiceLib.Services.CoreConfig
return true; return true;
} }
public async Task<int> GenDns(ProfileItem? node, SingboxConfig singboxConfig) private async Task<int> GenDns(ProfileItem? node, SingboxConfig singboxConfig)
{ {
try try
{ {
@@ -1176,12 +1185,12 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
public async Task<int> GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem) private async Task<int> GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem)
{ {
var dns4Sbox = singboxConfig.dns ?? new(); var dns4Sbox = singboxConfig.dns ?? new();
dns4Sbox.servers ??= []; dns4Sbox.servers ??= [];
@@ -1234,7 +1243,7 @@ namespace ServiceLib.Services.CoreConfig
return 0; return 0;
} }
public async Task<int> GenExperimental(SingboxConfig singboxConfig) private async Task<int> GenExperimental(SingboxConfig singboxConfig)
{ {
//if (_config.guiItem.enableStatistics) //if (_config.guiItem.enableStatistics)
{ {
@@ -1250,7 +1259,8 @@ namespace ServiceLib.Services.CoreConfig
singboxConfig.experimental ??= new Experimental4Sbox(); singboxConfig.experimental ??= new Experimental4Sbox();
singboxConfig.experimental.cache_file = new CacheFile4Sbox() singboxConfig.experimental.cache_file = new CacheFile4Sbox()
{ {
enabled = true enabled = true,
path = Utils.GetConfigPath("cache.db")
}; };
} }

View File

@@ -7,6 +7,7 @@ namespace ServiceLib.Services.CoreConfig
public class CoreConfigV2rayService public class CoreConfigV2rayService
{ {
private Config _config; private Config _config;
private static readonly string _tag = "CoreConfigV2rayService";
public CoreConfigV2rayService(Config config) public CoreConfigV2rayService(Config config)
{ {
@@ -70,7 +71,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("GenerateClientConfig4V2ray", ex); Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }
@@ -153,7 +154,7 @@ namespace ServiceLib.Services.CoreConfig
var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound); var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
await GenOutbound(item, outbound); await GenOutbound(item, outbound);
outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}"; outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}";
v2rayConfig.outbounds.Add(outbound); v2rayConfig.outbounds.Insert(0, outbound);
tagProxy.Add(outbound.tag); tagProxy.Add(outbound.tag);
} }
if (tagProxy.Count <= 0) if (tagProxy.Count <= 0)
@@ -181,15 +182,12 @@ namespace ServiceLib.Services.CoreConfig
rule.balancerTag = balancer.tag; rule.balancerTag = balancer.tag;
} }
} }
else v2rayConfig.routing.rules.Add(new()
{ {
v2rayConfig.routing.rules.Add(new() network = "tcp,udp",
{ balancerTag = balancer.tag,
network = "tcp,udp", type = "field"
balancerTag = balancer.tag, });
type = "field"
});
}
ret.Success = true; ret.Success = true;
ret.Data = JsonUtils.Serialize(v2rayConfig); ret.Data = JsonUtils.Serialize(v2rayConfig);
@@ -197,7 +195,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }
@@ -240,7 +238,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
await GenLog(v2rayConfig); await GenLog(v2rayConfig);
@@ -248,7 +246,7 @@ namespace ServiceLib.Services.CoreConfig
v2rayConfig.outbounds.Clear(); v2rayConfig.outbounds.Clear();
v2rayConfig.routing.rules.Clear(); v2rayConfig.routing.rules.Clear();
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest); var initPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
foreach (var it in selecteds) foreach (var it in selecteds)
{ {
@@ -270,8 +268,8 @@ namespace ServiceLib.Services.CoreConfig
} }
//find unused port //find unused port
var port = httpPort; var port = initPort;
for (var k = httpPort; k < Global.MaxPort; k++) for (var k = initPort; k < Global.MaxPort; k++)
{ {
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0) if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
{ {
@@ -283,7 +281,7 @@ namespace ServiceLib.Services.CoreConfig
} }
//found //found
port = k; port = k;
httpPort = port + 1; initPort = port + 1;
break; break;
} }
@@ -349,7 +347,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }
@@ -359,7 +357,7 @@ namespace ServiceLib.Services.CoreConfig
#region private gen function #region private gen function
public async Task<int> GenLog(V2rayConfig v2rayConfig) private async Task<int> GenLog(V2rayConfig v2rayConfig)
{ {
try try
{ {
@@ -379,12 +377,12 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
public async Task<int> GenInbounds(V2rayConfig v2rayConfig) private async Task<int> GenInbounds(V2rayConfig v2rayConfig)
{ {
try try
{ {
@@ -394,11 +392,17 @@ namespace ServiceLib.Services.CoreConfig
var inbound = GetInbound(_config.Inbound.First(), EInboundProtocol.socks, true); var inbound = GetInbound(_config.Inbound.First(), EInboundProtocol.socks, true);
v2rayConfig.inbounds.Add(inbound); v2rayConfig.inbounds.Add(inbound);
if (_config.Inbound.First().SecondLocalPortEnabled)
{
var inbound2 = GetInbound(_config.Inbound.First(), EInboundProtocol.socks2, true);
v2rayConfig.inbounds.Add(inbound2);
}
if (_config.Inbound.First().AllowLANConn) if (_config.Inbound.First().AllowLANConn)
{ {
if (_config.Inbound.First().NewPort4LAN) if (_config.Inbound.First().NewPort4LAN)
{ {
var inbound3 = GetInbound(_config.Inbound.First(), EInboundProtocol.socks2, true); var inbound3 = GetInbound(_config.Inbound.First(), EInboundProtocol.socks3, true);
inbound3.listen = listen; inbound3.listen = listen;
v2rayConfig.inbounds.Add(inbound3); v2rayConfig.inbounds.Add(inbound3);
@@ -417,7 +421,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
@@ -476,12 +480,12 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
public async Task<int> GenRoutingUserRule(RulesItem4Ray? rule, V2rayConfig v2rayConfig) private async Task<int> GenRoutingUserRule(RulesItem4Ray? rule, V2rayConfig v2rayConfig)
{ {
try try
{ {
@@ -554,15 +558,16 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
public async Task<int> GenOutbound(ProfileItem node, Outbounds4Ray outbound) private async Task<int> GenOutbound(ProfileItem node, Outbounds4Ray outbound)
{ {
try try
{ {
var muxEnabled = _config.CoreBasicItem.MuxEnabled;
switch (node.ConfigType) switch (node.ConfigType)
{ {
case EConfigType.VMess: case EConfigType.VMess:
@@ -603,7 +608,7 @@ namespace ServiceLib.Services.CoreConfig
usersItem.security = Global.DefaultSecurity; usersItem.security = Global.DefaultSecurity;
} }
await GenOutboundMux(node, outbound, _config.CoreBasicItem.MuxEnabled); await GenOutboundMux(node, outbound, muxEnabled, muxEnabled);
outbound.settings.servers = null; outbound.settings.servers = null;
break; break;
@@ -628,7 +633,7 @@ namespace ServiceLib.Services.CoreConfig
serversItem.ota = false; serversItem.ota = false;
serversItem.level = 1; serversItem.level = 1;
await GenOutboundMux(node, outbound, false); await GenOutboundMux(node, outbound);
outbound.settings.vnext = null; outbound.settings.vnext = null;
break; break;
@@ -664,7 +669,7 @@ namespace ServiceLib.Services.CoreConfig
serversItem.users = new List<SocksUsersItem4Ray>() { socksUsersItem }; serversItem.users = new List<SocksUsersItem4Ray>() { socksUsersItem };
} }
await GenOutboundMux(node, outbound, false); await GenOutboundMux(node, outbound);
outbound.settings.vnext = null; outbound.settings.vnext = null;
break; break;
@@ -698,23 +703,15 @@ namespace ServiceLib.Services.CoreConfig
usersItem.email = Global.UserEMail; usersItem.email = Global.UserEMail;
usersItem.encryption = node.Security; usersItem.encryption = node.Security;
await GenOutboundMux(node, outbound, _config.CoreBasicItem.MuxEnabled); if (node.Flow.IsNullOrEmpty())
if (node.StreamSecurity == Global.StreamSecurityReality
|| node.StreamSecurity == Global.StreamSecurity)
{ {
if (Utils.IsNotEmpty(node.Flow)) await GenOutboundMux(node, outbound, muxEnabled, muxEnabled);
{
usersItem.flow = node.Flow;
await GenOutboundMux(node, outbound, false);
}
} }
if (node.StreamSecurity == Global.StreamSecurityReality && Utils.IsNullOrEmpty(node.Flow)) else
{ {
await GenOutboundMux(node, outbound, _config.CoreBasicItem.MuxEnabled); usersItem.flow = node.Flow;
await GenOutboundMux(node, outbound, false, muxEnabled);
} }
outbound.settings.servers = null; outbound.settings.servers = null;
break; break;
} }
@@ -737,7 +734,7 @@ namespace ServiceLib.Services.CoreConfig
serversItem.ota = false; serversItem.ota = false;
serversItem.level = 1; serversItem.level = 1;
await GenOutboundMux(node, outbound, false); await GenOutboundMux(node, outbound);
outbound.settings.vnext = null; outbound.settings.vnext = null;
break; break;
@@ -745,47 +742,51 @@ namespace ServiceLib.Services.CoreConfig
} }
outbound.protocol = Global.ProtocolTypes[node.ConfigType]; outbound.protocol = Global.ProtocolTypes[node.ConfigType];
await GenBoundStreamSettings(node, outbound.streamSettings); await GenBoundStreamSettings(node, outbound);
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
public async Task<int> GenOutboundMux(ProfileItem node, Outbounds4Ray outbound, bool enabled) private async Task<int> GenOutboundMux(ProfileItem node, Outbounds4Ray outbound, bool enabledTCP = false, bool enabledUDP = false)
{ {
try try
{ {
if (enabled) outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
if (enabledTCP)
{ {
outbound.mux.enabled = true; outbound.mux.enabled = true;
outbound.mux.concurrency = _config.Mux4RayItem.Concurrency; outbound.mux.concurrency = _config.Mux4RayItem.Concurrency;
}
else if (enabledUDP)
{
outbound.mux.enabled = true;
outbound.mux.xudpConcurrency = _config.Mux4RayItem.XudpConcurrency; outbound.mux.xudpConcurrency = _config.Mux4RayItem.XudpConcurrency;
outbound.mux.xudpProxyUDP443 = _config.Mux4RayItem.XudpProxyUDP443; outbound.mux.xudpProxyUDP443 = _config.Mux4RayItem.XudpProxyUDP443;
} }
else
{
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
}
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
public async Task<int> GenBoundStreamSettings(ProfileItem node, StreamSettings4Ray streamSettings) private async Task<int> GenBoundStreamSettings(ProfileItem node, Outbounds4Ray outbound)
{ {
try try
{ {
var streamSettings = outbound.streamSettings;
streamSettings.network = node.GetNetwork(); streamSettings.network = node.GetNetwork();
string host = node.RequestHost.TrimEx(); var host = node.RequestHost.TrimEx();
string sni = node.Sni; var path = node.Path.TrimEx();
string useragent = ""; var sni = node.Sni.TrimEx();
var useragent = "";
if (!_config.CoreBasicItem.DefUserAgent.IsNullOrEmpty()) if (!_config.CoreBasicItem.DefUserAgent.IsNullOrEmpty())
{ {
try try
@@ -858,9 +859,9 @@ namespace ServiceLib.Services.CoreConfig
{ {
type = node.HeaderType type = node.HeaderType
}; };
if (Utils.IsNotEmpty(node.Path)) if (Utils.IsNotEmpty(path))
{ {
kcpSettings.seed = node.Path; kcpSettings.seed = path;
} }
streamSettings.kcpSettings = kcpSettings; streamSettings.kcpSettings = kcpSettings;
break; break;
@@ -868,9 +869,10 @@ namespace ServiceLib.Services.CoreConfig
case nameof(ETransport.ws): case nameof(ETransport.ws):
WsSettings4Ray wsSettings = new(); WsSettings4Ray wsSettings = new();
wsSettings.headers = new Headers4Ray(); wsSettings.headers = new Headers4Ray();
string path = node.Path;
if (Utils.IsNotEmpty(host)) if (Utils.IsNotEmpty(host))
{ {
wsSettings.host = host;
wsSettings.headers.Host = host; wsSettings.headers.Host = host;
} }
if (Utils.IsNotEmpty(path)) if (Utils.IsNotEmpty(path))
@@ -888,9 +890,9 @@ namespace ServiceLib.Services.CoreConfig
case nameof(ETransport.httpupgrade): case nameof(ETransport.httpupgrade):
HttpupgradeSettings4Ray httpupgradeSettings = new(); HttpupgradeSettings4Ray httpupgradeSettings = new();
if (Utils.IsNotEmpty(node.Path)) if (Utils.IsNotEmpty(path))
{ {
httpupgradeSettings.path = node.Path; httpupgradeSettings.path = path;
} }
if (Utils.IsNotEmpty(host)) if (Utils.IsNotEmpty(host))
{ {
@@ -902,16 +904,11 @@ namespace ServiceLib.Services.CoreConfig
//xhttp //xhttp
case nameof(ETransport.xhttp): case nameof(ETransport.xhttp):
streamSettings.network = ETransport.xhttp.ToString(); streamSettings.network = ETransport.xhttp.ToString();
XhttpSettings4Ray xhttpSettings = new() XhttpSettings4Ray xhttpSettings = new();
{
scMaxEachPostBytes = "500000-1000000",
scMaxConcurrentPosts = "50-100",
scMinPostsIntervalMs = "30-50"
};
if (Utils.IsNotEmpty(node.Path)) if (Utils.IsNotEmpty(path))
{ {
xhttpSettings.path = node.Path; xhttpSettings.path = path;
} }
if (Utils.IsNotEmpty(host)) if (Utils.IsNotEmpty(host))
{ {
@@ -927,6 +924,7 @@ namespace ServiceLib.Services.CoreConfig
} }
streamSettings.xhttpSettings = xhttpSettings; streamSettings.xhttpSettings = xhttpSettings;
await GenOutboundMux(node, outbound);
break; break;
//h2 //h2
@@ -937,7 +935,7 @@ namespace ServiceLib.Services.CoreConfig
{ {
httpSettings.host = Utils.String2List(host); httpSettings.host = Utils.String2List(host);
} }
httpSettings.path = node.Path; httpSettings.path = path;
streamSettings.httpSettings = httpSettings; streamSettings.httpSettings = httpSettings;
@@ -947,7 +945,7 @@ namespace ServiceLib.Services.CoreConfig
QuicSettings4Ray quicsettings = new() QuicSettings4Ray quicsettings = new()
{ {
security = host, security = host,
key = node.Path, key = path,
header = new Header4Ray header = new Header4Ray
{ {
type = node.HeaderType type = node.HeaderType
@@ -971,7 +969,7 @@ namespace ServiceLib.Services.CoreConfig
GrpcSettings4Ray grpcSettings = new() GrpcSettings4Ray grpcSettings = new()
{ {
authority = Utils.IsNullOrEmpty(host) ? null : host, authority = Utils.IsNullOrEmpty(host) ? null : host,
serviceName = node.Path, serviceName = path,
multiMode = node.HeaderType == Global.GrpcMultiMode, multiMode = node.HeaderType == Global.GrpcMultiMode,
idle_timeout = _config.GrpcItem.IdleTimeout, idle_timeout = _config.GrpcItem.IdleTimeout,
health_check_timeout = _config.GrpcItem.HealthCheckTimeout, health_check_timeout = _config.GrpcItem.HealthCheckTimeout,
@@ -1001,9 +999,9 @@ namespace ServiceLib.Services.CoreConfig
request = request.Replace("$requestUserAgent$", $"{useragent.AppendQuotes()}"); request = request.Replace("$requestUserAgent$", $"{useragent.AppendQuotes()}");
//Path //Path
string pathHttp = @"/"; string pathHttp = @"/";
if (Utils.IsNotEmpty(node.Path)) if (Utils.IsNotEmpty(path))
{ {
string[] arrPath = node.Path.Split(','); string[] arrPath = path.Split(',');
pathHttp = string.Join(",".AppendQuotes(), arrPath); pathHttp = string.Join(",".AppendQuotes(), arrPath);
} }
request = request.Replace("$requestPath$", $"{pathHttp.AppendQuotes()}"); request = request.Replace("$requestPath$", $"{pathHttp.AppendQuotes()}");
@@ -1016,12 +1014,12 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
public async Task<int> GenDns(ProfileItem? node, V2rayConfig v2rayConfig) private async Task<int> GenDns(ProfileItem? node, V2rayConfig v2rayConfig)
{ {
try try
{ {
@@ -1036,9 +1034,13 @@ namespace ServiceLib.Services.CoreConfig
//Outbound Freedom domainStrategy //Outbound Freedom domainStrategy
if (Utils.IsNotEmpty(domainStrategy4Freedom)) if (Utils.IsNotEmpty(domainStrategy4Freedom))
{ {
var outbound = v2rayConfig.outbounds[1]; var outbound = v2rayConfig.outbounds.FirstOrDefault(t => t is { protocol: "freedom", tag: Global.DirectTag });
outbound.settings.domainStrategy = domainStrategy4Freedom; if (outbound != null)
outbound.settings.userLevel = 0; {
outbound.settings = new();
outbound.settings.domainStrategy = domainStrategy4Freedom;
outbound.settings.userLevel = 0;
}
} }
var obj = JsonUtils.ParseJson(normalDNS); var obj = JsonUtils.ParseJson(normalDNS);
@@ -1079,12 +1081,12 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;
} }
public async Task<int> GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem) private async Task<int> GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem)
{ {
if (node == null) if (node == null)
{ return 0; } { return 0; }
@@ -1104,7 +1106,7 @@ namespace ServiceLib.Services.CoreConfig
return 0; return 0;
} }
public async Task<int> GenStatistic(V2rayConfig v2rayConfig) private async Task<int> GenStatistic(V2rayConfig v2rayConfig)
{ {
if (_config.GuiItem.EnableStatistics) if (_config.GuiItem.EnableStatistics)
{ {
@@ -1165,9 +1167,9 @@ namespace ServiceLib.Services.CoreConfig
{ {
fragment = new() fragment = new()
{ {
packets = "tlshello", packets = _config.Fragment4RayItem?.Packets,
length = "100-200", length = _config.Fragment4RayItem?.Length,
interval = "10-20" interval = _config.Fragment4RayItem?.Interval
} }
} }
}; };
@@ -1237,7 +1239,7 @@ namespace ServiceLib.Services.CoreConfig
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return 0; return 0;

View File

@@ -14,6 +14,8 @@ namespace ServiceLib.Services
public event ErrorEventHandler? Error; public event ErrorEventHandler? Error;
private static readonly string _tag = "DownloadService";
public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action<bool, string> updateFunc) public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action<bool, string> updateFunc)
{ {
try try
@@ -68,7 +70,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex)); Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null) if (ex.InnerException != null)
@@ -113,7 +115,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex)); Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null) if (ex.InnerException != null)
{ {
@@ -131,7 +133,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex)); Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null) if (ex.InnerException != null)
{ {
@@ -177,7 +179,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex)); Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null) if (ex.InnerException != null)
{ {
@@ -208,7 +210,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex)); Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null) if (ex.InnerException != null)
{ {
@@ -232,13 +234,13 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
return -1; return -1;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
return -1; return -1;
} }
} }
@@ -280,13 +282,13 @@ namespace ServiceLib.Services
{ {
return null; return null;
} }
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks); var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
if (await SocketCheck(Global.Loopback, httpPort) == false) if (await SocketCheck(Global.Loopback, port) == false)
{ {
return null; return null;
} }
return new WebProxy(Global.Loopback, httpPort); return new WebProxy($"socks5://{Global.Loopback}:{port}");
} }
private async Task<bool> SocketCheck(string ip, int port) private async Task<bool> SocketCheck(string ip, int port)

View File

@@ -11,6 +11,7 @@ namespace ServiceLib.Services
private Action<SpeedTestResult>? _updateFunc; private Action<SpeedTestResult>? _updateFunc;
private bool _exitLoop = false; private bool _exitLoop = false;
private static readonly string _tag = "SpeedtestService";
public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc) public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc)
{ {
@@ -146,7 +147,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
})); }));
} }
@@ -154,7 +155,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
finally finally
{ {
@@ -191,7 +192,7 @@ namespace ServiceLib.Services
{ {
try try
{ {
WebProxy webProxy = new(Global.Loopback, it.Port); var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
var output = await GetRealPingTime(downloadHandle, webProxy); var output = await GetRealPingTime(downloadHandle, webProxy);
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output); ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
@@ -201,7 +202,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
})); }));
} }
@@ -209,13 +210,13 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
finally finally
{ {
if (pid > 0) if (pid > 0)
{ {
await CoreHandler.Instance.CoreStopPid(pid); await ProcUtils.ProcessKill(pid);
} }
await ProfileExHandler.Instance.SaveTo(); await ProfileExHandler.Instance.SaveTo();
} }
@@ -262,7 +263,7 @@ namespace ServiceLib.Services
var item = await AppHandler.Instance.GetProfileItem(it.IndexId); var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
if (item is null) continue; if (item is null) continue;
WebProxy webProxy = new(Global.Loopback, it.Port); var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) => await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
{ {
@@ -277,7 +278,7 @@ namespace ServiceLib.Services
if (pid > 0) if (pid > 0)
{ {
await CoreHandler.Instance.CoreStopPid(pid); await ProcUtils.ProcessKill(pid);
} }
await ProfileExHandler.Instance.SaveTo(); await ProfileExHandler.Instance.SaveTo();
} }
@@ -324,7 +325,7 @@ namespace ServiceLib.Services
var item = await AppHandler.Instance.GetProfileItem(it.IndexId); var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
if (item is null) continue; if (item is null) continue;
WebProxy webProxy = new(Global.Loopback, it.Port); var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) => _ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
{ {
decimal.TryParse(msg, out var dec); decimal.TryParse(msg, out var dec);
@@ -341,7 +342,7 @@ namespace ServiceLib.Services
if (pid > 0) if (pid > 0)
{ {
await CoreHandler.Instance.CoreStopPid(pid); await ProcUtils.ProcessKill(pid);
} }
await ProfileExHandler.Instance.SaveTo(); await ProfileExHandler.Instance.SaveTo();
} }
@@ -389,7 +390,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
return responseTime; return responseTime;
} }

View File

@@ -10,7 +10,8 @@ namespace ServiceLib.Services.Statistics
private ClientWebSocket? webSocket; private ClientWebSocket? webSocket;
private Action<ServerSpeedItem>? _updateFunc; private Action<ServerSpeedItem>? _updateFunc;
private string Url => $"ws://{Global.Loopback}:{AppHandler.Instance.StatePort2}/traffic"; private string Url => $"ws://{Global.Loopback}:{AppHandler.Instance.StatePort2}/traffic";
private static readonly string _tag = "StatisticsSingboxService";
public StatisticsSingboxService(Config config, Action<ServerSpeedItem> updateFunc) public StatisticsSingboxService(Config config, Action<ServerSpeedItem> updateFunc)
{ {
_config = config; _config = config;
@@ -48,7 +49,7 @@ namespace ServiceLib.Services.Statistics
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
} }
} }

View File

@@ -7,6 +7,7 @@ namespace ServiceLib.Services
{ {
private Action<bool, string>? _updateFunc; private Action<bool, string>? _updateFunc;
private int _timeout = 30; private int _timeout = 30;
private static readonly string _tag = "UpdateService";
public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease) public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease)
{ {
@@ -272,7 +273,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
_updateFunc?.Invoke(false, ex.Message); _updateFunc?.Invoke(false, ex.Message);
return new RetResult(false, ex.Message); return new RetResult(false, ex.Message);
} }
@@ -356,7 +357,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
_updateFunc?.Invoke(false, ex.Message); _updateFunc?.Invoke(false, ex.Message);
return new SemanticVersion(""); return new SemanticVersion("");
} }
@@ -415,7 +416,7 @@ namespace ServiceLib.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(ex.Message, ex); Logging.SaveLog(_tag, ex);
_updateFunc?.Invoke(false, ex.Message); _updateFunc?.Invoke(false, ex.Message);
return new RetResult(false, ex.Message); return new RetResult(false, ex.Message);
} }

View File

@@ -103,7 +103,7 @@ namespace ServiceLib.ViewModels
address = Utils.GetConfigPath(address); address = Utils.GetConfigPath(address);
if (File.Exists(address)) if (File.Exists(address))
{ {
Utils.ProcessStart(address); ProcUtils.ProcessStart(address);
} }
else else
{ {

View File

@@ -130,18 +130,31 @@ namespace ServiceLib.ViewModels
DisplayOperationMsg(ResUI.LocalRestoreInvalidZipTips); DisplayOperationMsg(ResUI.LocalRestoreInvalidZipTips);
return; return;
} }
if (!Utils.UpgradeAppExists(out _))
{
DisplayOperationMsg(ResUI.UpgradeAppNotExistTip);
return;
}
//backup first //backup first
var fileBackup = Utils.GetBackupPath(BackupFileName); var fileBackup = Utils.GetBackupPath(BackupFileName);
var result = await CreateZipFileFromDirectory(fileBackup); var result = await CreateZipFileFromDirectory(fileBackup);
if (result) if (result)
{ {
Locator.Current.GetService<MainWindowViewModel>()?.UpgradeApp(fileName); var service = Locator.Current.GetService<MainWindowViewModel>();
await service?.MyAppExitAsync(true);
await SQLiteHelper.Instance.DisposeDbConnectionAsync();
var toPath = Utils.GetConfigPath();
FileManager.ZipExtractToFile(fileName, toPath, "");
if (Utils.IsWindows())
{
ProcUtils.RebootAsAdmin(false);
}
else
{
if (Utils.UpgradeAppExists(out var upgradeFileName))
{
ProcUtils.ProcessStart(upgradeFileName, Global.RebootAs, Utils.StartupPath());
}
}
service?.Shutdown(true);
} }
else else
{ {
@@ -160,9 +173,9 @@ namespace ServiceLib.ViewModels
var configDirZipTemp = Utils.GetTempPath($"v2rayN_{DateTime.Now:yyyyMMddHHmmss}"); var configDirZipTemp = Utils.GetTempPath($"v2rayN_{DateTime.Now:yyyyMMddHHmmss}");
var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs); var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs);
await Task.Run(() => FileManager.CopyDirectory(configDir, configDirTemp, false, "cache.db")); FileManager.CopyDirectory(configDir, configDirTemp, false, "cache.db");
var ret = await Task.Run(() => FileManager.CreateFromDirectory(configDirZipTemp, fileName)); var ret = FileManager.CreateFromDirectory(configDirZipTemp, fileName);
await Task.Run(() => Directory.Delete(configDirZipTemp, true)); Directory.Delete(configDirZipTemp, true);
return ret; return ret;
} }
} }

View File

@@ -262,7 +262,7 @@ namespace ServiceLib.ViewModels
FileManager.ZipExtractToFile(fileName, toPath, _config.GuiItem.IgnoreGeoUpdateCore ? "geo" : ""); FileManager.ZipExtractToFile(fileName, toPath, _config.GuiItem.IgnoreGeoUpdateCore ? "geo" : "");
} }
if (Utils.IsLinux() || Utils.IsOSX()) if (Utils.IsNonWindows())
{ {
var filesList = (new DirectoryInfo(toPath)).GetFiles().Select(u => u.FullName).ToList(); var filesList = (new DirectoryInfo(toPath)).GetFiles().Select(u => u.FullName).ToList();
foreach (var file in filesList) foreach (var file in filesList)

View File

@@ -1,9 +1,7 @@
using ReactiveUI; using ReactiveUI;
using ReactiveUI.Fody.Helpers; using ReactiveUI.Fody.Helpers;
using Splat; using Splat;
using System.Diagnostics;
using System.Reactive; using System.Reactive;
using System.Reactive.Linq;
namespace ServiceLib.ViewModels namespace ServiceLib.ViewModels
{ {
@@ -50,6 +48,8 @@ namespace ServiceLib.ViewModels
public ReactiveCommand<Unit, Unit> RegionalPresetRussiaCmd { get; } public ReactiveCommand<Unit, Unit> RegionalPresetRussiaCmd { get; }
public ReactiveCommand<Unit, Unit> RegionalPresetIranCmd { get; }
public ReactiveCommand<Unit, Unit> ReloadCmd { get; } public ReactiveCommand<Unit, Unit> ReloadCmd { get; }
[Reactive] [Reactive]
@@ -197,6 +197,11 @@ namespace ServiceLib.ViewModels
await ApplyRegionalPreset(EPresetType.Russia); await ApplyRegionalPreset(EPresetType.Russia);
}); });
RegionalPresetIranCmd = ReactiveCommand.CreateFromTask(async () =>
{
await ApplyRegionalPreset(EPresetType.Iran);
});
#endregion WhenAnyValue && ReactiveCommand #endregion WhenAnyValue && ReactiveCommand
Init(); Init();
@@ -272,9 +277,8 @@ namespace ServiceLib.ViewModels
Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update); Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update);
} }
} }
catch (Exception ex) catch
{ {
Logging.SaveLog(ex.Message, ex);
} }
} }
@@ -282,50 +286,40 @@ namespace ServiceLib.ViewModels
{ {
try try
{ {
Logging.SaveLog("MyAppExit Begin"); Logging.SaveLog("MyAppExitAsync Begin");
await SysProxyHandler.UpdateSysProxy(_config, true); MessageBus.Current.SendMessage("", EMsgCommand.AppExit.ToString());
await ConfigHandler.SaveConfig(_config); await ConfigHandler.SaveConfig(_config);
await SysProxyHandler.UpdateSysProxy(_config, true);
await ProfileExHandler.Instance.SaveTo(); await ProfileExHandler.Instance.SaveTo();
await StatisticsHandler.Instance.SaveTo(); await StatisticsHandler.Instance.SaveTo();
StatisticsHandler.Instance.Close(); StatisticsHandler.Instance.Close();
await CoreHandler.Instance.CoreStop(); await CoreHandler.Instance.CoreStop();
Logging.SaveLog("MyAppExit End"); Logging.SaveLog("MyAppExitAsync End");
} }
catch { } catch { }
finally finally
{ {
if (!blWindowsShutDown) if (!blWindowsShutDown)
{ {
_updateView?.Invoke(EViewAction.Shutdown, null); _updateView?.Invoke(EViewAction.Shutdown, false);
} }
} }
} }
public async Task UpgradeApp(string arg) public async Task UpgradeApp(string arg)
{ {
if (!Utils.UpgradeAppExists(out var fileName)) if (!Utils.UpgradeAppExists(out var upgradeFileName))
{ {
NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.UpgradeAppNotExistTip); NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.UpgradeAppNotExistTip);
Logging.SaveLog("UpgradeApp does not exist"); Logging.SaveLog("UpgradeApp does not exist");
return; return;
} }
Process process = new() var id = ProcUtils.ProcessStart(upgradeFileName, arg, Utils.StartupPath());
if (id > 0)
{ {
StartInfo = new ProcessStartInfo
{
UseShellExecute = true,
FileName = fileName,
Arguments = arg.AppendQuotes(),
WorkingDirectory = Utils.StartupPath()
}
};
process.Start();
if (process.Id > 0)
{
await MyAppExitAsync(false);
await MyAppExitAsync(false); await MyAppExitAsync(false);
} }
} }
@@ -335,6 +329,11 @@ namespace ServiceLib.ViewModels
_updateView?.Invoke(EViewAction.ShowHideWindow, blShow); _updateView?.Invoke(EViewAction.ShowHideWindow, blShow);
} }
public void Shutdown(bool byUser)
{
_updateView?.Invoke(EViewAction.Shutdown, byUser);
}
#endregion Actions #endregion Actions
#region Servers && Groups #region Servers && Groups
@@ -503,20 +502,8 @@ namespace ServiceLib.ViewModels
public async Task RebootAsAdmin() public async Task RebootAsAdmin()
{ {
try ProcUtils.RebootAsAdmin();
{ await MyAppExitAsync(false);
ProcessStartInfo startInfo = new()
{
UseShellExecute = true,
Arguments = Global.RebootAs,
WorkingDirectory = Utils.StartupPath(),
FileName = Utils.GetExePath().AppendQuotes(),
Verb = "runas",
};
Process.Start(startInfo);
await MyAppExitAsync(false);
}
catch { }
} }
private async Task ClearServerStatistics() private async Task ClearServerStatistics()
@@ -527,17 +514,18 @@ namespace ServiceLib.ViewModels
private async Task OpenTheFileLocation() private async Task OpenTheFileLocation()
{ {
var path = Utils.StartupPath();
if (Utils.IsWindows()) if (Utils.IsWindows())
{ {
Utils.ProcessStart("Explorer", $"/select,{Utils.GetConfigPath()}"); ProcUtils.ProcessStart(path);
} }
else if (Utils.IsLinux()) else if (Utils.IsLinux())
{ {
Utils.ProcessStart("nautilus", Utils.GetConfigPath()); ProcUtils.ProcessStart("nautilus", path);
} }
else if (Utils.IsOSX()) else if (Utils.IsOSX())
{ {
Utils.ProcessStart("open", Utils.GetConfigPath()); ProcUtils.ProcessStart("open", path);
} }
} }

View File

@@ -9,7 +9,6 @@ namespace ServiceLib.ViewModels
{ {
private ConcurrentQueue<string> _queueMsg = new(); private ConcurrentQueue<string> _queueMsg = new();
private int _numMaxMsg = 500; private int _numMaxMsg = 500;
private string _lastMsgFilter = string.Empty;
private bool _lastMsgFilterNotAvailable; private bool _lastMsgFilterNotAvailable;
private bool _blLockShow = false; private bool _blLockShow = false;
@@ -28,7 +27,7 @@ namespace ServiceLib.ViewModels
this.WhenAnyValue( this.WhenAnyValue(
x => x.MsgFilter) x => x.MsgFilter)
.Subscribe(c => _config.MsgUIItem.MainMsgFilter = MsgFilter); .Subscribe(c => DoMsgFilter());
this.WhenAnyValue( this.WhenAnyValue(
x => x.AutoRefresh, x => x.AutoRefresh,
@@ -60,14 +59,14 @@ namespace ServiceLib.ViewModels
{ {
return; return;
} }
_blLockShow = true;
if (!_config.UiItem.ShowInTaskbar) if (!_config.UiItem.ShowInTaskbar)
{ {
await Task.Delay(1000); return;
} }
await Task.Delay(100); _blLockShow = true;
await Task.Delay(500);
var txt = string.Join("", _queueMsg.ToArray()); var txt = string.Join("", _queueMsg.ToArray());
await _updateView?.Invoke(EViewAction.DispatcherShowMsg, txt); await _updateView?.Invoke(EViewAction.DispatcherShowMsg, txt);
@@ -77,8 +76,7 @@ namespace ServiceLib.ViewModels
private async Task EnqueueQueueMsg(string msg) private async Task EnqueueQueueMsg(string msg)
{ {
//filter msg //filter msg
if (MsgFilter != _lastMsgFilter) _lastMsgFilterNotAvailable = false; if (MsgFilter.IsNotEmpty() && !_lastMsgFilterNotAvailable)
if (Utils.IsNotEmpty(MsgFilter) && !_lastMsgFilterNotAvailable)
{ {
try try
{ {
@@ -87,12 +85,12 @@ namespace ServiceLib.ViewModels
return; return;
} }
} }
catch (Exception) catch (Exception ex)
{ {
_queueMsg.Enqueue(ex.Message);
_lastMsgFilterNotAvailable = true; _lastMsgFilterNotAvailable = true;
} }
} }
_lastMsgFilter = MsgFilter;
//Enqueue //Enqueue
if (_queueMsg.Count > _numMaxMsg) if (_queueMsg.Count > _numMaxMsg)
@@ -113,5 +111,11 @@ namespace ServiceLib.ViewModels
{ {
_queueMsg.Clear(); _queueMsg.Clear();
} }
private void DoMsgFilter()
{
_config.MsgUIItem.MainMsgFilter = MsgFilter;
_lastMsgFilterNotAvailable = false;
}
} }
} }

View File

@@ -9,6 +9,7 @@ namespace ServiceLib.ViewModels
#region Core #region Core
[Reactive] public int localPort { get; set; } [Reactive] public int localPort { get; set; }
[Reactive] public bool SecondLocalPortEnabled { get; set; }
[Reactive] public bool udpEnabled { get; set; } [Reactive] public bool udpEnabled { get; set; }
[Reactive] public bool sniffingEnabled { get; set; } [Reactive] public bool sniffingEnabled { get; set; }
public IList<string> destOverride { get; set; } public IList<string> destOverride { get; set; }
@@ -125,6 +126,7 @@ namespace ServiceLib.ViewModels
var inbound = _config.Inbound.First(); var inbound = _config.Inbound.First();
localPort = inbound.LocalPort; localPort = inbound.LocalPort;
SecondLocalPortEnabled = inbound.SecondLocalPortEnabled;
udpEnabled = inbound.UdpEnabled; udpEnabled = inbound.UdpEnabled;
sniffingEnabled = inbound.SniffingEnabled; sniffingEnabled = inbound.SniffingEnabled;
routeOnly = inbound.RouteOnly; routeOnly = inbound.RouteOnly;
@@ -288,6 +290,7 @@ namespace ServiceLib.ViewModels
//Core //Core
_config.Inbound.First().LocalPort = localPort; _config.Inbound.First().LocalPort = localPort;
_config.Inbound.First().SecondLocalPortEnabled = SecondLocalPortEnabled;
_config.Inbound.First().UdpEnabled = udpEnabled; _config.Inbound.First().UdpEnabled = udpEnabled;
_config.Inbound.First().SniffingEnabled = sniffingEnabled; _config.Inbound.First().SniffingEnabled = sniffingEnabled;
_config.Inbound.First().DestOverride = destOverride?.ToList(); _config.Inbound.First().DestOverride = destOverride?.ToList();

View File

@@ -74,15 +74,16 @@ namespace ServiceLib.ViewModels
SelectedSource.Protocol = ProtocolItems?.ToList(); SelectedSource.Protocol = ProtocolItems?.ToList();
SelectedSource.InboundTag = InboundTagItems?.ToList(); SelectedSource.InboundTag = InboundTagItems?.ToList();
bool hasRule = SelectedSource.Domain?.Count > 0 var hasRule = SelectedSource.Domain?.Count > 0
|| SelectedSource.Ip?.Count > 0 || SelectedSource.Ip?.Count > 0
|| SelectedSource.Protocol?.Count > 0 || SelectedSource.Protocol?.Count > 0
|| SelectedSource.Process?.Count > 0 || SelectedSource.Process?.Count > 0
|| Utils.IsNotEmpty(SelectedSource.Port); || Utils.IsNotEmpty(SelectedSource.Port)
|| Utils.IsNotEmpty(SelectedSource.Network);
if (!hasRule) if (!hasRule)
{ {
NoticeHandler.Instance.Enqueue(string.Format(ResUI.RoutingRuleDetailRequiredTips, "Port/Protocol/Domain/IP/Process")); NoticeHandler.Instance.Enqueue(string.Format(ResUI.RoutingRuleDetailRequiredTips, "Network/Port/Protocol/Domain/IP/Process"));
return; return;
} }
//NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); //NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);

View File

@@ -2,6 +2,8 @@
using ReactiveUI; using ReactiveUI;
using ReactiveUI.Fody.Helpers; using ReactiveUI.Fody.Helpers;
using System.Reactive; using System.Reactive;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ServiceLib.ViewModels namespace ServiceLib.ViewModels
{ {
@@ -177,19 +179,25 @@ namespace ServiceLib.ViewModels
} }
var lst = new List<RulesItem>(); var lst = new List<RulesItem>();
foreach (var it in SelectedSources ?? [SelectedSource]) var sources = SelectedSources ?? [SelectedSource];
foreach (var it in _rules)
{ {
var item = _rules.FirstOrDefault(t => t.Id == it?.Id); if (sources.Any(t => t.Id == it?.Id))
if (item != null)
{ {
var item2 = JsonUtils.DeepCopy(item); //JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item)); var item2 = JsonUtils.DeepCopy(it);
item2.Id = null; item2.Id = null;
lst.Add(item2 ?? new()); lst.Add(item2 ?? new());
} }
} }
if (lst.Count > 0) if (lst.Count > 0)
{ {
await _updateView?.Invoke(EViewAction.SetClipboardData, JsonUtils.Serialize(lst)); var options = new JsonSerializerOptions
{
WriteIndented = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
await _updateView?.Invoke(EViewAction.SetClipboardData, JsonUtils.Serialize(lst, options));
} }
} }

View File

@@ -32,6 +32,7 @@ namespace ServiceLib.ViewModels
public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { get; } public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { get; }
public ReactiveCommand<Unit, Unit> SubUpdateCmd { get; } public ReactiveCommand<Unit, Unit> SubUpdateCmd { get; }
public ReactiveCommand<Unit, Unit> SubUpdateViaProxyCmd { get; } public ReactiveCommand<Unit, Unit> SubUpdateViaProxyCmd { get; }
public ReactiveCommand<Unit, Unit> CopyProxyCmdToClipboardCmd { get; }
public ReactiveCommand<Unit, Unit> NotifyLeftClickCmd { get; } public ReactiveCommand<Unit, Unit> NotifyLeftClickCmd { get; }
#region System Proxy #region System Proxy
@@ -48,18 +49,6 @@ namespace ServiceLib.ViewModels
[Reactive] [Reactive]
public bool BlSystemProxyPac { get; set; } public bool BlSystemProxyPac { get; set; }
[Reactive]
public bool BlNotSystemProxyClear { get; set; }
[Reactive]
public bool BlNotSystemProxySet { get; set; }
[Reactive]
public bool BlNotSystemProxyNothing { get; set; }
[Reactive]
public bool BlNotSystemProxyPac { get; set; }
public ReactiveCommand<Unit, Unit> SystemProxyClearCmd { get; } public ReactiveCommand<Unit, Unit> SystemProxyClearCmd { get; }
public ReactiveCommand<Unit, Unit> SystemProxySetCmd { get; } public ReactiveCommand<Unit, Unit> SystemProxySetCmd { get; }
public ReactiveCommand<Unit, Unit> SystemProxyNothingCmd { get; } public ReactiveCommand<Unit, Unit> SystemProxyNothingCmd { get; }
@@ -140,6 +129,11 @@ namespace ServiceLib.ViewModels
y => y == true) y => y == true)
.Subscribe(async c => await DoEnableTun(c)); .Subscribe(async c => await DoEnableTun(c));
CopyProxyCmdToClipboardCmd = ReactiveCommand.CreateFromTask(async () =>
{
await CopyProxyCmdToClipboard();
});
NotifyLeftClickCmd = ReactiveCommand.CreateFromTask(async () => NotifyLeftClickCmd = ReactiveCommand.CreateFromTask(async () =>
{ {
Locator.Current.GetService<MainWindowViewModel>()?.ShowHideWindow(null); Locator.Current.GetService<MainWindowViewModel>()?.ShowHideWindow(null);
@@ -210,6 +204,23 @@ namespace ServiceLib.ViewModels
await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null); await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null);
} }
private async Task CopyProxyCmdToClipboard()
{
var cmd = Utils.IsWindows() ? "set" : "export";
var address = $"{Global.Loopback}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)}";
var sb = new StringBuilder();
sb.AppendLine($"{cmd} http_proxy={Global.HttpProtocol}{address}");
sb.AppendLine($"{cmd} https_proxy={Global.HttpProtocol}{address}");
sb.AppendLine($"{cmd} all_proxy={Global.Socks5Protocol}{address}");
sb.AppendLine("");
sb.AppendLine($"{cmd} HTTP_PROXY={Global.HttpProtocol}{address}");
sb.AppendLine($"{cmd} HTTPS_PROXY={Global.HttpProtocol}{address}");
sb.AppendLine($"{cmd} ALL_PROXY={Global.Socks5Protocol}{address}");
await _updateView?.Invoke(EViewAction.SetClipboardData, sb.ToString());
}
private async Task AddServerViaClipboard() private async Task AddServerViaClipboard()
{ {
var service = Locator.Current.GetService<MainWindowViewModel>(); var service = Locator.Current.GetService<MainWindowViewModel>();
@@ -333,11 +344,6 @@ namespace ServiceLib.ViewModels
BlSystemProxyNothing = (type == ESysProxyType.Unchanged); BlSystemProxyNothing = (type == ESysProxyType.Unchanged);
BlSystemProxyPac = (type == ESysProxyType.Pac); BlSystemProxyPac = (type == ESysProxyType.Pac);
BlNotSystemProxyClear = !BlSystemProxyClear;
BlNotSystemProxySet = !BlSystemProxySet;
BlNotSystemProxyNothing = !BlSystemProxyNothing;
BlNotSystemProxyPac = !BlSystemProxyPac;
if (blChange) if (blChange)
{ {
_updateView?.Invoke(EViewAction.DispatcherRefreshIcon, null); _updateView?.Invoke(EViewAction.DispatcherRefreshIcon, null);
@@ -451,21 +457,20 @@ namespace ServiceLib.ViewModels
public async Task InboundDisplayStatus() public async Task InboundDisplayStatus()
{ {
StringBuilder sb = new(); StringBuilder sb = new();
sb.Append($"[{EInboundProtocol.mixed}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)}]"); sb.Append($"[{EInboundProtocol.mixed}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)}");
if (_config.Inbound.First().SecondLocalPortEnabled)
{
sb.Append($",{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks2)}");
}
sb.Append(']');
InboundDisplay = $"{ResUI.LabLocal}:{sb}"; InboundDisplay = $"{ResUI.LabLocal}:{sb}";
if (_config.Inbound.First().AllowLANConn) if (_config.Inbound.First().AllowLANConn)
{ {
if (_config.Inbound.First().NewPort4LAN) var lan = _config.Inbound.First().NewPort4LAN
{ ? $"[{EInboundProtocol.mixed}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks3)}]"
StringBuilder sb2 = new(); : $"[{EInboundProtocol.mixed}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)}]";
sb2.Append($"[{EInboundProtocol.mixed}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks2)}]"); InboundLanDisplay = $"{ResUI.LabLAN}:{lan}";
InboundLanDisplay = $"{ResUI.LabLAN}:{sb2}";
}
else
{
InboundLanDisplay = $"{ResUI.LabLAN}:{sb}";
}
} }
else else
{ {

View File

@@ -1,17 +0,0 @@
#!/bin/sh
echo 'Building'
OutputPath='./bin/v2rayN'
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-x64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o "${OutputPath}/osx-x64"
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-arm64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o "${OutputPath}/osx-arm64"
rm -rf "$OutputPath/osx-x64/*.pdb"
rm -rf "$OutputPath/osx-arm64/*.pdb"
echo 'Build done'
ls $OutputPath
7z a v2rayN-osx.zip $OutputPath
exit 0

View File

@@ -1,62 +0,0 @@
param (
[Parameter()]
[ValidateNotNullOrEmpty()]
[string]
$OutputPath = './bin/v2rayN'
)
Write-Host 'Building'
dotnet publish `
./v2rayN/v2rayN.csproj `
-c Release `
-r win-x64 `
--self-contained false `
-p:PublishReadyToRun=false `
-p:PublishSingleFile=true `
-o "$OutputPath/win-x64"
dotnet publish `
./v2rayN/v2rayN.csproj `
-c Release `
-r win-arm64 `
--self-contained false `
-p:PublishReadyToRun=false `
-p:PublishSingleFile=true `
-o "$OutputPath/win-arm64"
dotnet publish `
./v2rayN.Desktop/v2rayN.Desktop.csproj `
-c Release `
-r linux-x64 `
--self-contained true `
-p:PublishReadyToRun=false `
-p:PublishSingleFile=true `
-o "$OutputPath/linux-x64"
dotnet publish `
./v2rayN.Desktop/v2rayN.Desktop.csproj `
-c Release `
-r linux-arm64 `
--self-contained true `
-p:PublishReadyToRun=false `
-p:PublishSingleFile=true `
-o "$OutputPath/linux-arm64"
if ( -Not $? ) {
exit $lastExitCode
}
if ( Test-Path -Path ./bin/v2rayN ) {
rm -Force "$OutputPath/win-x64/*.pdb"
rm -Force "$OutputPath/win-arm64/*.pdb"
rm -Force "$OutputPath/linux-x64/*.pdb"
rm -Force "$OutputPath/linux-arm64/*.pdb"
}
Write-Host 'Build done'
ls $OutputPath
7z a v2rayN.zip $OutputPath
exit 0

View File

@@ -3,12 +3,13 @@
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib" xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:semi="https://irihi.tech/semi"
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib" xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
x:DataType="vms:StatusBarViewModel" x:DataType="vms:StatusBarViewModel"
RequestedThemeVariant="Default"> RequestedThemeVariant="Default">
<Application.Styles> <Application.Styles>
<semi:SemiTheme />
<StyleInclude Source="Assets/GlobalStyles.axaml" /> <StyleInclude Source="Assets/GlobalStyles.axaml" />
<StyleInclude Source="avares://Semi.Avalonia/Themes/Index.axaml" />
<StyleInclude Source="avares://Semi.Avalonia.DataGrid/Index.axaml" /> <StyleInclude Source="avares://Semi.Avalonia.DataGrid/Index.axaml" />
<StyleInclude Source="avares://DialogHost.Avalonia/Styles.xaml" /> <StyleInclude Source="avares://DialogHost.Avalonia/Styles.xaml" />
</Application.Styles> </Application.Styles>
@@ -31,38 +32,26 @@
<NativeMenuItem <NativeMenuItem
Command="{Binding SystemProxyClearCmd}" Command="{Binding SystemProxyClearCmd}"
Header="{x:Static resx:ResUI.menuSystemProxyClear}" Header="{x:Static resx:ResUI.menuSystemProxyClear}"
IsVisible="{Binding BlNotSystemProxyClear}" /> IsChecked="{Binding BlSystemProxyClear}"
<NativeMenuItem ToggleType="Radio" />
Command="{Binding SystemProxyClearCmd}"
Header="{x:Static resx:ResUI.menuSystemProxyClear}"
Icon="/Assets/NotifyIcon1.ico"
IsVisible="{Binding BlSystemProxyClear}" />
<NativeMenuItem <NativeMenuItem
Command="{Binding SystemProxySetCmd}" Command="{Binding SystemProxySetCmd}"
Header="{x:Static resx:ResUI.menuSystemProxySet}" Header="{x:Static resx:ResUI.menuSystemProxySet}"
IsVisible="{Binding BlNotSystemProxySet}" /> IsChecked="{Binding BlSystemProxySet}"
<NativeMenuItem ToggleType="Radio" />
Command="{Binding SystemProxySetCmd}"
Header="{x:Static resx:ResUI.menuSystemProxySet}"
Icon="/Assets/NotifyIcon2.ico"
IsVisible="{Binding BlSystemProxySet}" />
<NativeMenuItem <NativeMenuItem
Command="{Binding SystemProxyNothingCmd}" Command="{Binding SystemProxyNothingCmd}"
Header="{x:Static resx:ResUI.menuSystemProxyNothing}" Header="{x:Static resx:ResUI.menuSystemProxyNothing}"
IsVisible="{Binding BlNotSystemProxyNothing}" /> IsChecked="{Binding BlSystemProxyNothing}"
<NativeMenuItem ToggleType="Radio" />
Command="{Binding SystemProxyNothingCmd}"
Header="{x:Static resx:ResUI.menuSystemProxyNothing}"
Icon="/Assets/NotifyIcon3.ico"
IsVisible="{Binding BlSystemProxyNothing}" />
<NativeMenuItemSeparator /> <NativeMenuItemSeparator />
<NativeMenuItem Click="MenuAddServerViaClipboardClick" Header="{x:Static resx:ResUI.menuAddServerViaClipboard}" /> <NativeMenuItem Click="MenuAddServerViaClipboardClick" Header="{x:Static resx:ResUI.menuAddServerViaClipboard}" />
<NativeMenuItem Header="{x:Static resx:ResUI.menuAddServerViaScan}" IsVisible="False" /> <NativeMenuItem Header="{x:Static resx:ResUI.menuAddServerViaScan}" IsVisible="False" />
<NativeMenuItem Command="{Binding SubUpdateCmd}" Header="{x:Static resx:ResUI.menuSubUpdate}" /> <NativeMenuItem Command="{Binding SubUpdateCmd}" Header="{x:Static resx:ResUI.menuSubUpdate}" />
<NativeMenuItem Command="{Binding SubUpdateViaProxyCmd}" Header="{x:Static resx:ResUI.menuSubUpdateViaProxy}" /> <NativeMenuItem Command="{Binding SubUpdateViaProxyCmd}" Header="{x:Static resx:ResUI.menuSubUpdateViaProxy}" />
<NativeMenuItemSeparator /> <NativeMenuItemSeparator />
<NativeMenuItem Command="{Binding CopyProxyCmdToClipboardCmd}" Header="{x:Static resx:ResUI.menuCopyProxyCmdToClipboard}" />
<NativeMenuItemSeparator />
<NativeMenuItem Command="{Binding NotifyLeftClickCmd}" Header="{x:Static resx:ResUI.menuShowOrHideMainWindow}" /> <NativeMenuItem Command="{Binding NotifyLeftClickCmd}" Header="{x:Static resx:ResUI.menuShowOrHideMainWindow}" />
<NativeMenuItem Click="MenuExit_Click" Header="{x:Static resx:ResUI.menuExit}" /> <NativeMenuItem Click="MenuExit_Click" Header="{x:Static resx:ResUI.menuExit}" />
</NativeMenu> </NativeMenu>

View File

@@ -56,13 +56,13 @@ public partial class App : Application
{ {
} }
private void MenuAddServerViaClipboardClick(object? sender, EventArgs e) private async void MenuAddServerViaClipboardClick(object? sender, EventArgs e)
{ {
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
if (desktop.MainWindow != null) if (desktop.MainWindow != null)
{ {
var clipboardData = AvaUtils.GetClipboardData(desktop.MainWindow).Result; var clipboardData = await AvaUtils.GetClipboardData(desktop.MainWindow);
var service = Locator.Current.GetService<MainWindowViewModel>(); var service = Locator.Current.GetService<MainWindowViewModel>();
if (service != null) _ = service.AddServerViaClipboardAsync(clipboardData); if (service != null) _ = service.AddServerViaClipboardAsync(clipboardData);
} }
@@ -71,12 +71,8 @@ public partial class App : Application
private async void MenuExit_Click(object? sender, EventArgs e) private async void MenuExit_Click(object? sender, EventArgs e)
{ {
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) var service = Locator.Current.GetService<MainWindowViewModel>();
{ if (service != null) await service.MyAppExitAsync(true);
var service = Locator.Current.GetService<MainWindowViewModel>(); service?.Shutdown(true);
if (service != null) await service.MyAppExitAsync(false);
desktop.Shutdown();
}
} }
} }

View File

@@ -6,18 +6,18 @@
</Design.PreviewWith> </Design.PreviewWith>
<Style Selector="TextBlock.Margin8"> <Style Selector="TextBlock.Margin8">
<Setter Property="Margin" Value="10" /> <Setter Property="Margin" Value="8" />
</Style> </Style>
<Style Selector="StackPanel.Margin8"> <Style Selector="StackPanel.Margin8">
<Setter Property="Margin" Value="10" /> <Setter Property="Margin" Value="8" />
</Style> </Style>
<Style Selector="DockPanel.Margin8"> <Style Selector="DockPanel.Margin8">
<Setter Property="Margin" Value="10" /> <Setter Property="Margin" Value="8" />
</Style> </Style>
<Style Selector="WrapPanel.Margin8"> <Style Selector="WrapPanel.Margin8">
<Setter Property="Margin" Value="10" /> <Setter Property="Margin" Value="8" />
</Style> </Style>
<Style Selector="Grid.Margin8"> <Style Selector="Grid.Margin8">
<Setter Property="Margin" Value="10" /> <Setter Property="Margin" Value="8" />
</Style> </Style>
</Styles> </Styles>

View File

@@ -1,6 +1,5 @@
using Avalonia; using Avalonia;
using Avalonia.Media; using Avalonia.Media;
using System.Reflection;
namespace v2rayN.Desktop.Common namespace v2rayN.Desktop.Common
{ {
@@ -8,7 +7,7 @@ namespace v2rayN.Desktop.Common
{ {
public static AppBuilder WithFontByDefault(this AppBuilder appBuilder) public static AppBuilder WithFontByDefault(this AppBuilder appBuilder)
{ {
var uri = $"avares://{Assembly.GetExecutingAssembly().GetName().Name}/Assets/Fonts#Noto Sans SC"; var uri = Path.Combine(Global.AvaAssets, "Fonts#Noto Sans SC");
return appBuilder.With(new FontManagerOptions() return appBuilder.With(new FontManagerOptions()
{ {
DefaultFamilyName = uri, DefaultFamilyName = uri,

View File

@@ -3,7 +3,6 @@ using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Platform; using Avalonia.Platform;
using System.Reflection;
namespace v2rayN.Desktop.Common namespace v2rayN.Desktop.Common
{ {
@@ -41,7 +40,13 @@ namespace v2rayN.Desktop.Common
public static WindowIcon GetAppIcon(ESysProxyType sysProxyType) public static WindowIcon GetAppIcon(ESysProxyType sysProxyType)
{ {
var index = (int)sysProxyType + 1; var index = (int)sysProxyType + 1;
var uri = new Uri($"avares://{Assembly.GetExecutingAssembly().GetName().Name}/Assets/NotifyIcon{index}.ico"); var fileName = Utils.GetPath($"NotifyIcon{index}.ico");
if (File.Exists(fileName))
{
return new(fileName);
}
var uri = new Uri(Path.Combine(Global.AvaAssets, $"NotifyIcon{index}.ico"));
using var bitmap = new Bitmap(AssetLoader.Open(uri)); using var bitmap = new Bitmap(AssetLoader.Open(uri));
return new(bitmap); return new(bitmap);
} }

View File

@@ -17,13 +17,11 @@ namespace v2rayN.Desktop.Common
public static async Task<string?> OpenFileDialog(Window owner, FilePickerFileType? filter) public static async Task<string?> OpenFileDialog(Window owner, FilePickerFileType? filter)
{ {
var topLevel = TopLevel.GetTopLevel(owner); var sp = GetStorageProvider(owner);
if (topLevel == null) if (sp is null) return null;
{
return null;
}
// Start async operation to open the dialog. // Start async operation to open the dialog.
var files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions var files = await sp.OpenFilePickerAsync(new FilePickerOpenOptions
{ {
AllowMultiple = false, AllowMultiple = false,
FileTypeFilter = filter is null ? [FilePickerFileTypes.All, FilePickerFileTypes.ImagePng] : [filter] FileTypeFilter = filter is null ? [FilePickerFileTypes.All, FilePickerFileTypes.ImagePng] : [filter]
@@ -34,17 +32,21 @@ namespace v2rayN.Desktop.Common
public static async Task<string?> SaveFileDialog(Window owner, string filter) public static async Task<string?> SaveFileDialog(Window owner, string filter)
{ {
var topLevel = TopLevel.GetTopLevel(owner); var sp = GetStorageProvider(owner);
if (topLevel == null) if (sp is null) return null;
{
return null;
}
// Start async operation to open the dialog. // Start async operation to open the dialog.
var files = await topLevel.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions var files = await sp.SaveFilePickerAsync(new FilePickerSaveOptions
{ {
}); });
return files?.TryGetLocalPath(); return files?.TryGetLocalPath();
} }
private static IStorageProvider? GetStorageProvider(Window owner)
{
var topLevel = TopLevel.GetTopLevel(owner);
return topLevel?.StorageProvider;
}
} }
} }

View File

@@ -6,14 +6,14 @@ using Avalonia.Media;
using Avalonia.Styling; using Avalonia.Styling;
using ReactiveUI; using ReactiveUI;
using ReactiveUI.Fody.Helpers; using ReactiveUI.Fody.Helpers;
using Semi.Avalonia;
using System.Reactive.Linq; using System.Reactive.Linq;
namespace v2rayN.Desktop.ViewModels namespace v2rayN.Desktop.ViewModels
{ {
public class ThemeSettingViewModel : MyReactiveObject public class ThemeSettingViewModel : MyReactiveObject
{ {
[Reactive] public bool ColorModeDark { get; set; } [Reactive] public string CurrentTheme { get; set; }
[Reactive] public bool FollowSystemTheme { get; set; }
[Reactive] public int CurrentFontSize { get; set; } [Reactive] public int CurrentFontSize { get; set; }
@@ -31,32 +31,21 @@ namespace v2rayN.Desktop.ViewModels
{ {
ModifyTheme(); ModifyTheme();
ModifyFontFamily(); ModifyFontFamily();
ModifyFontSize();
} }
private void BindingUI() private void BindingUI()
{ {
ColorModeDark = _config.UiItem.ColorModeDark; CurrentTheme = _config.UiItem.CurrentTheme;
FollowSystemTheme = _config.UiItem.FollowSystemTheme;
CurrentFontSize = _config.UiItem.CurrentFontSize; CurrentFontSize = _config.UiItem.CurrentFontSize;
CurrentLanguage = _config.UiItem.CurrentLanguage; CurrentLanguage = _config.UiItem.CurrentLanguage;
this.WhenAnyValue(x => x.ColorModeDark) this.WhenAnyValue(x => x.CurrentTheme)
.Subscribe(c => .Subscribe(c =>
{ {
if (_config.UiItem.ColorModeDark != ColorModeDark) if (_config.UiItem.CurrentTheme != CurrentTheme)
{ {
_config.UiItem.ColorModeDark = ColorModeDark; _config.UiItem.CurrentTheme = CurrentTheme;
ModifyTheme();
ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(x => x.FollowSystemTheme,
y => y == true)
.Subscribe(c =>
{
if (_config.UiItem.FollowSystemTheme != FollowSystemTheme)
{
_config.UiItem.FollowSystemTheme = FollowSystemTheme;
ModifyTheme(); ModifyTheme();
ConfigHandler.SaveConfig(_config); ConfigHandler.SaveConfig(_config);
} }
@@ -67,11 +56,10 @@ namespace v2rayN.Desktop.ViewModels
y => y > 0) y => y > 0)
.Subscribe(c => .Subscribe(c =>
{ {
if (CurrentFontSize >= Global.MinFontSize) if (_config.UiItem.CurrentFontSize != CurrentFontSize && CurrentFontSize >= Global.MinFontSize)
{ {
_config.UiItem.CurrentFontSize = CurrentFontSize; _config.UiItem.CurrentFontSize = CurrentFontSize;
double size = CurrentFontSize; ModifyFontSize();
ModifyFontSize(size);
ConfigHandler.SaveConfig(_config); ConfigHandler.SaveConfig(_config);
} }
}); });
@@ -96,12 +84,24 @@ namespace v2rayN.Desktop.ViewModels
var app = Application.Current; var app = Application.Current;
if (app is not null) if (app is not null)
{ {
app.RequestedThemeVariant = FollowSystemTheme ? ThemeVariant.Default : (ColorModeDark ? ThemeVariant.Dark : ThemeVariant.Light); app.RequestedThemeVariant = CurrentTheme switch
{
nameof(ETheme.Dark) => ThemeVariant.Dark,
nameof(ETheme.Light) => ThemeVariant.Light,
nameof(ETheme.Aquatic) => SemiTheme.Aquatic,
nameof(ETheme.Desert) => SemiTheme.Desert,
nameof(ETheme.Dusk) => SemiTheme.Dusk,
nameof(ETheme.NightSky) => SemiTheme.NightSky,
_ => ThemeVariant.Default,
};
} }
} }
private void ModifyFontSize(double size) private void ModifyFontSize()
{ {
double size = CurrentFontSize;
if (size < Global.MinFontSize) return;
Style style = new(x => Selectors.Or( Style style = new(x => Selectors.Or(
x.OfType<Button>(), x.OfType<Button>(),
x.OfType<TextBox>(), x.OfType<TextBox>(),
@@ -109,7 +109,8 @@ namespace v2rayN.Desktop.ViewModels
x.OfType<Menu>(), x.OfType<Menu>(),
x.OfType<ContextMenu>(), x.OfType<ContextMenu>(),
x.OfType<DataGridRow>(), x.OfType<DataGridRow>(),
x.OfType<ListBoxItem>() x.OfType<ListBoxItem>(),
x.OfType<HeaderedContentControl>()
)); ));
style.Add(new Setter() style.Add(new Setter()
{ {
@@ -137,6 +138,7 @@ namespace v2rayN.Desktop.ViewModels
x.OfType<ContextMenu>(), x.OfType<ContextMenu>(),
x.OfType<DataGridRow>(), x.OfType<DataGridRow>(),
x.OfType<ListBoxItem>(), x.OfType<ListBoxItem>(),
x.OfType<HeaderedContentControl>(),
x.OfType<WindowNotificationManager>() x.OfType<WindowNotificationManager>()
)); ));
style.Add(new Setter() style.Add(new Setter()

View File

@@ -34,147 +34,126 @@
IsCancel="True" /> IsCancel="True" />
</StackPanel> </StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid> <Grid ColumnDefinitions="Auto,Auto,Auto" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"
Grid.Column="0" Grid.Column="0"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.menuServers}" /> Text="{x:Static resx:ResUI.menuServers}" />
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbRemarks}" /> Text="{x:Static resx:ResUI.TbRemarks}" />
<TextBox <TextBox
x:Name="txtRemarks" x:Name="txtRemarks"
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Width="400" Width="400"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="2"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbAddress}" /> Text="{x:Static resx:ResUI.TbAddress}" />
<TextBox <TextBox
x:Name="txtAddress" x:Name="txtAddress"
Grid.Row="2" Grid.Row="2"
Grid.Column="1" Grid.Column="1"
Width="400" Width="400"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
IsReadOnly="True" /> IsReadOnly="True" />
<StackPanel <StackPanel
Grid.Row="2" Grid.Row="2"
Grid.Column="2" Grid.Column="2"
VerticalAlignment="Center" VerticalAlignment="Center"
Orientation="Horizontal"> Orientation="Horizontal">
<Button <Button
x:Name="btnBrowse" x:Name="btnBrowse"
Margin="2,0" Margin="2,0"
Content="{x:Static resx:ResUI.TbBrowse}" /> Content="{x:Static resx:ResUI.TbBrowse}" />
<Button <Button
x:Name="btnEdit" x:Name="btnEdit"
Margin="2,0" Margin="2,0"
Content="{x:Static resx:ResUI.TbEdit}" /> Content="{x:Static resx:ResUI.TbEdit}" />
</StackPanel> </StackPanel>
<TextBlock <TextBlock
Grid.Row="3" Grid.Row="3"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbCoreType}" /> Text="{x:Static resx:ResUI.TbCoreType}" />
<ComboBox <ComboBox
x:Name="cmbCoreType" x:Name="cmbCoreType"
Grid.Row="3" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" Classes="Margin8"
MaxDropDownHeight="1000" /> MaxDropDownHeight="1000" />
<TextBlock <TextBlock
Grid.Row="4" Grid.Row="4"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbDisplayLog}" /> Text="{x:Static resx:ResUI.TbDisplayLog}" />
<StackPanel <StackPanel
Grid.Row="4" Grid.Row="4"
Grid.Column="1" Grid.Column="1"
Classes="Margin8" Classes="Margin8"
Orientation="Horizontal"> Orientation="Horizontal">
<ToggleSwitch <ToggleSwitch
x:Name="togDisplayLog" x:Name="togDisplayLog"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Margin="8,0"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TipDisplayLog}" />
</StackPanel>
<TextBlock
Grid.Row="5"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbPreSocksPort}" />
<TextBox
x:Name="txtPreSocksPort"
Grid.Row="5"
Grid.Column="1"
Width="200"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<StackPanel <TextBlock
Grid.Row="6" Margin="8,0"
Grid.Column="1" VerticalAlignment="Center"
Grid.ColumnSpan="2" Text="{x:Static resx:ResUI.TipDisplayLog}" />
Classes="Margin8"> </StackPanel>
<TextBlock
Width="500" <TextBlock
VerticalAlignment="Center" Grid.Row="5"
Text="{x:Static resx:ResUI.TipPreSocksPort}" Grid.Column="0"
TextWrapping="Wrap" /> VerticalAlignment="Center"
<TextBlock Classes="Margin8"
Width="500" Text="{x:Static resx:ResUI.TbPreSocksPort}" />
Margin="8,0" <TextBox
VerticalAlignment="Center" x:Name="txtPreSocksPort"
Text="{x:Static resx:ResUI.CustomServerTips}" Grid.Row="5"
TextWrapping="Wrap" /> Grid.Column="1"
</StackPanel> Width="200"
</Grid> HorizontalAlignment="Left"
Classes="Margin8" />
<StackPanel
Grid.Row="6"
Grid.Column="1"
Grid.ColumnSpan="2"
Classes="Margin8">
<TextBlock
Width="500"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TipPreSocksPort}"
TextWrapping="Wrap" />
<TextBlock
Width="500"
Margin="8,0"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.CustomServerTips}"
TextWrapping="Wrap" />
</StackPanel>
</Grid> </Grid>
</ScrollViewer> </ScrollViewer>
</DockPanel> </DockPanel>

View File

@@ -8,7 +8,7 @@
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib" xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
Title="{x:Static resx:ResUI.menuServers}" Title="{x:Static resx:ResUI.menuServers}"
Width="900" Width="900"
Height="700" Height="600"
x:DataType="vms:AddServerViewModel" x:DataType="vms:AddServerViewModel"
ShowInTaskbar="False" ShowInTaskbar="False"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
@@ -34,31 +34,12 @@
IsCancel="True" /> IsCancel="True" />
</StackPanel> </StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid> <Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0"> <Grid
<Grid.RowDefinitions> Grid.Row="0"
<RowDefinition Height="Auto" /> ColumnDefinitions="180,Auto,Auto"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"
@@ -122,18 +103,9 @@
<Grid <Grid
x:Name="gridVMess" x:Name="gridVMess"
Grid.Row="2" Grid.Row="2"
IsVisible="False"> ColumnDefinitions="180,Auto,Auto"
<Grid.RowDefinitions> IsVisible="False"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
@@ -184,17 +156,9 @@
<Grid <Grid
x:Name="gridSs" x:Name="gridSs"
Grid.Row="2" Grid.Row="2"
IsVisible="False"> ColumnDefinitions="180,Auto"
<Grid.RowDefinitions> IsVisible="False"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
@@ -225,17 +189,9 @@
<Grid <Grid
x:Name="gridSocks" x:Name="gridSocks"
Grid.Row="2" Grid.Row="2"
IsVisible="False"> ColumnDefinitions="180,Auto"
<Grid.RowDefinitions> IsVisible="False"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
@@ -266,18 +222,9 @@
<Grid <Grid
x:Name="gridVLESS" x:Name="gridVLESS"
Grid.Row="2" Grid.Row="2"
IsVisible="False"> ColumnDefinitions="180,Auto,Auto"
<Grid.RowDefinitions> IsVisible="False"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
@@ -328,17 +275,9 @@
<Grid <Grid
x:Name="gridTrojan" x:Name="gridTrojan"
Grid.Row="2" Grid.Row="2"
IsVisible="False"> ColumnDefinitions="180,Auto"
<Grid.RowDefinitions> IsVisible="False"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
@@ -369,17 +308,9 @@
<Grid <Grid
x:Name="gridHysteria2" x:Name="gridHysteria2"
Grid.Row="2" Grid.Row="2"
IsVisible="False"> ColumnDefinitions="180,Auto"
<Grid.RowDefinitions> IsVisible="False"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
@@ -410,17 +341,9 @@
<Grid <Grid
x:Name="gridTuic" x:Name="gridTuic"
Grid.Row="2" Grid.Row="2"
IsVisible="False"> ColumnDefinitions="180,Auto"
<Grid.RowDefinitions> IsVisible="False"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
@@ -464,19 +387,9 @@
<Grid <Grid
x:Name="gridWireguard" x:Name="gridWireguard"
Grid.Row="2" Grid.Row="2"
IsVisible="False"> ColumnDefinitions="180,Auto"
<Grid.RowDefinitions> IsVisible="False"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
@@ -551,22 +464,11 @@
Grid.Row="3" Grid.Row="3"
Margin="0,10" /> Margin="0,10" />
<Grid x:Name="gridTransport" Grid.Row="4"> <Grid
<Grid.RowDefinitions> x:Name="gridTransport"
<RowDefinition Height="Auto" /> Grid.Row="4"
<RowDefinition Height="Auto" /> ColumnDefinitions="180,Auto,Auto"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"
@@ -695,18 +597,11 @@
<Separator Grid.Row="5" Margin="0,10" /> <Separator Grid.Row="5" Margin="0,10" />
<Grid x:Name="gridTls" Grid.Row="6"> <Grid
<Grid.RowDefinitions> x:Name="gridTls"
<RowDefinition Height="Auto" /> Grid.Row="6"
<RowDefinition Height="Auto" /> ColumnDefinitions="180,Auto"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"
@@ -724,18 +619,9 @@
<Grid <Grid
x:Name="gridTlsMore" x:Name="gridTlsMore"
Grid.Row="7" Grid.Row="7"
IsVisible="False"> ColumnDefinitions="180,Auto"
<Grid.RowDefinitions> IsVisible="False"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
@@ -793,18 +679,9 @@
<Grid <Grid
x:Name="gridRealityMore" x:Name="gridRealityMore"
Grid.Row="7" Grid.Row="7"
IsVisible="False"> ColumnDefinitions="180,Auto"
<Grid.RowDefinitions> IsVisible="False"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"

View File

@@ -5,37 +5,33 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib" xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
d:DesignHeight="450" d:DesignHeight="450"
d:DesignWidth="800" d:DesignWidth="800"
x:DataType="vms:BackupAndRestoreViewModel"
mc:Ignorable="d"> mc:Ignorable="d">
<UserControl.Styles>
<Style Selector="Button">
<Setter Property="MinWidth" Value="180" />
</Style>
</UserControl.Styles>
<DockPanel Classes="Margin8"> <DockPanel Classes="Margin8">
<DockPanel Classes="Margin8" DockPanel.Dock="Bottom"> <StackPanel Classes="Margin8" DockPanel.Dock="Bottom">
<TextBlock <TextBlock
Name="txtMsg" Name="txtMsg"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
</DockPanel> </StackPanel>
<StackPanel> <StackPanel>
<Border <Border
Margin="4" Margin="4"
VerticalAlignment="Center" VerticalAlignment="Center"
Theme="{StaticResource CardBorder}"> Theme="{DynamicResource CardBorder}">
<Grid Classes="Margin8"> <Grid
<Grid.RowDefinitions> Classes="Margin8"
<RowDefinition Height="Auto" /> ColumnDefinitions="300,200"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"
Grid.Column="0" Grid.Column="0"
@@ -56,7 +52,10 @@
Classes="Margin8" Classes="Margin8"
Content="{x:Static resx:ResUI.menuLocalBackup}" /> Content="{x:Static resx:ResUI.menuLocalBackup}" />
<Separator Grid.Row="2" Grid.ColumnSpan="2" /> <Separator
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2" />
<TextBlock <TextBlock
Grid.Row="3" Grid.Row="3"
@@ -76,29 +75,21 @@
<Border <Border
Margin="4" Margin="4"
VerticalAlignment="Center" VerticalAlignment="Center"
Theme="{StaticResource CardBorder}"> Theme="{DynamicResource CardBorder}">
<Grid Classes="Margin8"> <Grid
<Grid.RowDefinitions> Classes="Margin8"
<RowDefinition Height="Auto" /> ColumnDefinitions="300,200"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" /> <StackPanel
<RowDefinition Height="Auto" /> Grid.Row="0"
<RowDefinition Height="Auto" /> Grid.Column="0"
</Grid.RowDefinitions> Orientation="Horizontal">
<Grid.ColumnDefinitions> <TextBlock Classes="Margin8" Text="{x:Static resx:ResUI.menuRemoteBackupAndRestore}" />
<ColumnDefinition Width="300" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<TextBlock
Grid.Row="0"
Grid.Column="0"
Classes="Margin8"
Text="{x:Static resx:ResUI.menuRemoteBackupAndRestore}" />
<Button <Button
Width="30" Width="30"
Height="30" Height="30"
MinWidth="30"
Margin="10,0" Margin="10,0"
Theme="{DynamicResource BorderlessButton}"> Theme="{DynamicResource BorderlessButton}">
<Button.Content> <Button.Content>
@@ -111,18 +102,7 @@
<Button.Flyout> <Button.Flyout>
<Flyout> <Flyout>
<StackPanel> <StackPanel>
<Grid> <Grid ColumnDefinitions="Auto,300" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="300" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"
Grid.Column="0" Grid.Column="0"
@@ -210,7 +190,10 @@
Classes="Margin8" Classes="Margin8"
Content="{x:Static resx:ResUI.menuRemoteBackup}" /> Content="{x:Static resx:ResUI.menuRemoteBackup}" />
<Separator Grid.Row="2" Grid.ColumnSpan="3" /> <Separator
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2" />
<TextBlock <TextBlock
Grid.Row="3" Grid.Row="3"
Grid.Column="0" Grid.Column="0"

View File

@@ -9,7 +9,12 @@ namespace v2rayN.Desktop.Views
{ {
public partial class BackupAndRestoreView : ReactiveUserControl<BackupAndRestoreViewModel> public partial class BackupAndRestoreView : ReactiveUserControl<BackupAndRestoreViewModel>
{ {
private Window _window; private Window? _window;
public BackupAndRestoreView()
{
InitializeComponent();
}
public BackupAndRestoreView(Window window) public BackupAndRestoreView(Window window)
{ {

View File

@@ -35,11 +35,16 @@
Content="{x:Static resx:ResUI.menuCheckUpdate}" /> Content="{x:Static resx:ResUI.menuCheckUpdate}" />
</StackPanel> </StackPanel>
<StackPanel> <Border
Margin="4"
VerticalAlignment="Center"
Theme="{DynamicResource CardBorder}">
<ListBox <ListBox
x:Name="lstCheckUpdates" x:Name="lstCheckUpdates"
BorderThickness="1" BorderThickness="1"
ItemsSource="{Binding CheckUpdateModels}"> ItemsSource="{Binding CheckUpdateModels}"
Theme="{StaticResource ButtonRadioGroupListBox}">
<ItemsControl.ItemsPanel> <ItemsControl.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<StackPanel Orientation="Vertical" /> <StackPanel Orientation="Vertical" />
@@ -47,27 +52,14 @@
</ItemsControl.ItemsPanel> </ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate> <DataTemplate>
<Border <Panel Width="500" VerticalAlignment="Center">
Width="500" <Grid ColumnDefinitions="1*,1*,3*" RowDefinitions="Auto">
Height="80"
Margin="-2"
VerticalAlignment="Center"
Theme="{StaticResource CardBorder}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<ToggleSwitch <ToggleSwitch
x:Name="togAutoRefresh" x:Name="togAutoRefresh"
Grid.Column="0" Grid.Column="0"
Margin="8" Margin="8"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Top" VerticalAlignment="Center"
IsChecked="{Binding IsSelected}" /> IsChecked="{Binding IsSelected}" />
<TextBlock <TextBlock
Grid.Column="1" Grid.Column="1"
@@ -81,11 +73,10 @@
Text="{Binding Remarks}" Text="{Binding Remarks}"
TextWrapping="WrapWithOverflow" /> TextWrapping="WrapWithOverflow" />
</Grid> </Grid>
</Border> </Panel>
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
</ListBox> </ListBox>
</StackPanel> </Border>
</DockPanel> </DockPanel>
</UserControl> </UserControl>

View File

@@ -28,7 +28,7 @@
Text="{x:Static resx:ResUI.menuRulemode}" /> Text="{x:Static resx:ResUI.menuRulemode}" />
<ComboBox <ComboBox
x:Name="cmbRulemode" x:Name="cmbRulemode"
Width="80" Width="100"
Margin="8,0"> Margin="8,0">
<ComboBoxItem Content="{x:Static resx:ResUI.menuModeRule}" /> <ComboBoxItem Content="{x:Static resx:ResUI.menuModeRule}" />
<ComboBoxItem Content="{x:Static resx:ResUI.menuModeGlobal}" /> <ComboBoxItem Content="{x:Static resx:ResUI.menuModeGlobal}" />
@@ -41,7 +41,7 @@
Text="{x:Static resx:ResUI.TbSorting}" /> Text="{x:Static resx:ResUI.TbSorting}" />
<ComboBox <ComboBox
x:Name="cmbSorting" x:Name="cmbSorting"
Width="60" Width="100"
Margin="8,0"> Margin="8,0">
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingDelay}" /> <ComboBoxItem Content="{x:Static resx:ResUI.TbSortingDelay}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingName}" /> <ComboBoxItem Content="{x:Static resx:ResUI.TbSortingName}" />
@@ -95,7 +95,8 @@
<ListBox <ListBox
x:Name="lstProxyGroups" x:Name="lstProxyGroups"
DockPanel.Dock="Left" DockPanel.Dock="Left"
ItemsSource="{Binding ProxyGroups}"> ItemsSource="{Binding ProxyGroups}"
Theme="{StaticResource ButtonRadioGroupListBox}">
<ItemsControl.ItemsPanel> <ItemsControl.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<StackPanel Orientation="Vertical" /> <StackPanel Orientation="Vertical" />
@@ -105,29 +106,25 @@
<DataTemplate> <DataTemplate>
<Border <Border
Width="160" Width="160"
Margin="0" Margin="-8,-4"
Padding="0" Padding="0"
Theme="{StaticResource CardBorder}"> Theme="{StaticResource CardBorder}">
<DockPanel> <Grid Classes="Margin8" RowDefinitions="1*,8,1*">
<Grid Grid.Column="0" Classes="Margin8"> <DockPanel Grid.Row="0">
<Grid.RowDefinitions> <TextBlock DockPanel.Dock="Right" Text="{Binding Type}" />
<RowDefinition Height="1*" /> <TextBlock Text="{Binding Name}" />
<RowDefinition Height="8" /> </DockPanel>
<RowDefinition Height="1*" /> <TextBlock Grid.Row="2" Text="{Binding Now}" />
</Grid.RowDefinitions> </Grid>
<DockPanel Grid.Row="0">
<TextBlock DockPanel.Dock="Right" Text="{Binding Type}" />
<TextBlock Text="{Binding Name}" />
</DockPanel>
<TextBlock Grid.Row="2" Text="{Binding Now}" />
</Grid>
</DockPanel>
</Border> </Border>
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
</ListBox> </ListBox>
<ListBox x:Name="lstProxyDetails" ItemsSource="{Binding ProxyDetails}"> <ListBox
x:Name="lstProxyDetails"
ItemsSource="{Binding ProxyDetails}"
Theme="{StaticResource ButtonRadioGroupListBox}">
<ItemsControl.ContextMenu> <ItemsControl.ContextMenu>
<ContextMenu> <ContextMenu>
<MenuItem x:Name="menuProxiesDelaytestPart" Header="{x:Static resx:ResUI.menuProxiesDelaytestPart}" /> <MenuItem x:Name="menuProxiesDelaytestPart" Header="{x:Static resx:ResUI.menuProxiesDelaytestPart}" />
@@ -143,24 +140,18 @@
<DataTemplate> <DataTemplate>
<Border <Border
Width="160" Width="160"
Margin="0" Margin="-12,-4"
Padding="0" Padding="0"
Theme="{StaticResource CardBorder}"> Theme="{StaticResource CardBorder}">
<DockPanel> <DockPanel>
<Border <Border
Width="5" Width="5"
Height="30"
Margin="0,1" Margin="0,1"
Background="YellowGreen" Background="YellowGreen"
CornerRadius="4" CornerRadius="4"
DockPanel.Dock="Left" DockPanel.Dock="Left"
IsVisible="{Binding IsActive}" /> IsVisible="{Binding IsActive}" />
<Grid Classes="Margin8"> <Grid Classes="Margin8" RowDefinitions="1*,8,1*">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="8" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Name}" /> <TextBlock Grid.Row="0" Text="{Binding Name}" />
<DockPanel Grid.Row="2"> <DockPanel Grid.Row="2">
<TextBlock <TextBlock

View File

@@ -7,8 +7,8 @@
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib" xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib" xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
Title="{x:Static resx:ResUI.menuDNSSetting}" Title="{x:Static resx:ResUI.menuDNSSetting}"
Width="1000" Width="900"
Height="700" Height="600"
x:DataType="vms:DNSSettingViewModel" x:DataType="vms:DNSSettingViewModel"
ShowInTaskbar="False" ShowInTaskbar="False"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
@@ -141,12 +141,7 @@
</StackPanel> </StackPanel>
</WrapPanel> </WrapPanel>
<Grid Classes="Margin8"> <Grid Classes="Margin8" ColumnDefinitions="*,10,*">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBox <TextBox
x:Name="txtnormalDNS2" x:Name="txtnormalDNS2"

View File

@@ -65,12 +65,12 @@ namespace v2rayN.Desktop.Views
private void linkDnsObjectDoc_Click(object? sender, RoutedEventArgs e) private void linkDnsObjectDoc_Click(object? sender, RoutedEventArgs e)
{ {
Utils.ProcessStart("https://xtls.github.io/config/dns.html#dnsobject"); ProcUtils.ProcessStart("https://xtls.github.io/config/dns.html#dnsobject");
} }
private void linkDnsSingboxObjectDoc_Click(object? sender, RoutedEventArgs e) private void linkDnsSingboxObjectDoc_Click(object? sender, RoutedEventArgs e)
{ {
Utils.ProcessStart("https://sing-box.sagernet.org/zh/configuration/dns/"); ProcUtils.ProcessStart("https://sing-box.sagernet.org/zh/configuration/dns/");
} }
} }
} }

View File

@@ -39,25 +39,12 @@
IsCancel="True" /> IsCancel="True" />
</StackPanel> </StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid> <Grid RowDefinitions="Auto,Auto,Auto">
<Grid.RowDefinitions> <Grid
<RowDefinition Height="Auto" /> x:Name="gridText"
<RowDefinition Height="Auto" /> Grid.Row="0"
<RowDefinition Height="Auto" /> ColumnDefinitions="Auto,400"
</Grid.RowDefinitions> RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto">
<Grid x:Name="gridText" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="400" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"

View File

@@ -10,7 +10,7 @@
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib" xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
Title="v2rayN" Title="v2rayN"
Width="900" Width="900"
Height="700" Height="600"
MinWidth="900" MinWidth="900"
x:DataType="vms:MainWindowViewModel" x:DataType="vms:MainWindowViewModel"
Icon="/Assets/NotifyIcon1.ico" Icon="/Assets/NotifyIcon1.ico"
@@ -80,6 +80,7 @@
<MenuItem Header="{x:Static resx:ResUI.menuRegionalPresets}"> <MenuItem Header="{x:Static resx:ResUI.menuRegionalPresets}">
<MenuItem x:Name="menuRegionalPresetsDefault" Header="{x:Static resx:ResUI.menuRegionalPresetsDefault}" /> <MenuItem x:Name="menuRegionalPresetsDefault" Header="{x:Static resx:ResUI.menuRegionalPresetsDefault}" />
<MenuItem x:Name="menuRegionalPresetsRussia" Header="{x:Static resx:ResUI.menuRegionalPresetsRussia}" /> <MenuItem x:Name="menuRegionalPresetsRussia" Header="{x:Static resx:ResUI.menuRegionalPresetsRussia}" />
<MenuItem x:Name="menuRegionalPresetsIran" Header="{x:Static resx:ResUI.menuRegionalPresetsIran}" />
</MenuItem> </MenuItem>
<MenuItem x:Name="menuBackupAndRestore" Header="{x:Static resx:ResUI.menuBackupAndRestore}" /> <MenuItem x:Name="menuBackupAndRestore" Header="{x:Static resx:ResUI.menuBackupAndRestore}" />
<MenuItem x:Name="menuOpenTheFileLocation" Header="{x:Static resx:ResUI.menuOpenTheFileLocation}" /> <MenuItem x:Name="menuOpenTheFileLocation" Header="{x:Static resx:ResUI.menuOpenTheFileLocation}" />
@@ -124,12 +125,10 @@
<view:StatusBarView DockPanel.Dock="Bottom" /> <view:StatusBarView DockPanel.Dock="Bottom" />
<Grid> <Grid>
<Grid x:Name="gridMain" IsVisible="False"> <Grid
<Grid.ColumnDefinitions> x:Name="gridMain"
<ColumnDefinition Width="1*" /> ColumnDefinitions="1*,10,1*"
<ColumnDefinition Width="10" /> IsVisible="False">
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<ContentControl x:Name="tabProfiles" Grid.Column="0" /> <ContentControl x:Name="tabProfiles" Grid.Column="0" />
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" /> <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
<TabControl <TabControl
@@ -141,83 +140,30 @@
<TabItem x:Name="tabClashConnections" Header="{x:Static resx:ResUI.TbConnections}" /> <TabItem x:Name="tabClashConnections" Header="{x:Static resx:ResUI.TbConnections}" />
</TabControl> </TabControl>
</Grid> </Grid>
<Grid x:Name="gridMain1" IsVisible="False"> <Grid
<Grid.RowDefinitions> x:Name="gridMain1"
<RowDefinition Height="1*" /> IsVisible="False"
<RowDefinition Height="10" /> RowDefinitions="1*,10,1*">
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<ContentControl x:Name="tabProfiles1" Grid.Row="0" /> <ContentControl x:Name="tabProfiles1" Grid.Row="0" />
<GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" /> <GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" />
<TabControl <TabControl
x:Name="tabMain1" x:Name="tabMain1"
Grid.Row="2" Grid.Row="2"
TabStripPlacement="Left"> TabStripPlacement="Left">
<TabItem x:Name="tabMsgView1"> <TabItem x:Name="tabMsgView1" Header="{x:Static resx:ResUI.MsgInformationTitle}" />
<TabItem.Header> <TabItem x:Name="tabClashProxies1" Header="{x:Static resx:ResUI.TbProxies}" />
<StackPanel> <TabItem x:Name="tabClashConnections1" Header="{x:Static resx:ResUI.TbConnections}" />
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.MsgInformationTitle}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashProxies1">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.TbProxies}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashConnections1">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.TbConnections}" />
</StackPanel>
</TabItem.Header>
</TabItem>
</TabControl> </TabControl>
</Grid> </Grid>
<Grid x:Name="gridMain2" IsVisible="False"> <Grid x:Name="gridMain2" IsVisible="False">
<TabControl x:Name="tabMain2" TabStripPlacement="Left"> <TabControl x:Name="tabMain2" TabStripPlacement="Left">
<TabItem x:Name="tabProfiles2"> <TabItem x:Name="tabProfiles2" Header="{x:Static resx:ResUI.menuServers}" />
<TabItem.Header> <TabItem x:Name="tabMsgView2" Header="{x:Static resx:ResUI.MsgInformationTitle}" />
<StackPanel> <TabItem x:Name="tabClashProxies2" Header="{x:Static resx:ResUI.TbProxies}" />
<TabItem x:Name="tabClashConnections2" Header="{x:Static resx:ResUI.TbConnections}" />
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.menuServers}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabMsgView2">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.MsgInformationTitle}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashProxies2">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.TbProxies}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashConnections2">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.TbConnections}" />
</StackPanel>
</TabItem.Header>
</TabItem>
</TabControl> </TabControl>
</Grid> </Grid>
</Grid> </Grid>
</DockPanel> </DockPanel>
</dialogHost:DialogHost> </dialogHost:DialogHost>
</Window> </Window>

View File

@@ -104,6 +104,7 @@ namespace v2rayN.Desktop.Views
this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RegionalPresetDefaultCmd, v => v.menuRegionalPresetsDefault).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.RegionalPresetDefaultCmd, v => v.menuRegionalPresetsDefault).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RegionalPresetRussiaCmd, v => v.menuRegionalPresetsRussia).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.RegionalPresetRussiaCmd, v => v.menuRegionalPresetsRussia).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RegionalPresetIranCmd, v => v.menuRegionalPresetsIran).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
@@ -133,7 +134,7 @@ namespace v2rayN.Desktop.Views
} }
}); });
this.Title = $"{Utils.GetVersion()} - {(AppHandler.Instance.IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}"; this.Title = $"{Utils.GetVersion()}";
if (Utils.IsWindows()) if (Utils.IsWindows())
{ {
ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false); ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);
@@ -152,10 +153,11 @@ namespace v2rayN.Desktop.Views
menuGlobalHotkeySetting.IsVisible = false; menuGlobalHotkeySetting.IsVisible = false;
} }
menuAddServerViaScan.IsVisible = false; menuAddServerViaScan.IsVisible = false;
RestoreUI(); RestoreUI();
AddHelpMenuItem(); AddHelpMenuItem();
//WindowsHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null); //WindowsHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null);
MessageBus.Current.Listen<string>(EMsgCommand.AppExit.ToString()).Subscribe(StorageUI);
} }
#region Event #region Event
@@ -221,6 +223,10 @@ namespace v2rayN.Desktop.Views
break; break;
case EViewAction.Shutdown: case EViewAction.Shutdown:
if (obj != null && _blCloseByUser == false)
{
_blCloseByUser = (bool)obj;
}
StorageUI(); StorageUI();
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
@@ -303,7 +309,7 @@ namespace v2rayN.Desktop.Views
private async void MainWindow_KeyDown(object? sender, KeyEventArgs e) private async void MainWindow_KeyDown(object? sender, KeyEventArgs e)
{ {
if (e.KeyModifiers == KeyModifiers.Control) if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)
{ {
switch (e.Key) switch (e.Key)
{ {
@@ -328,12 +334,12 @@ namespace v2rayN.Desktop.Views
private void menuPromotion_Click(object? sender, RoutedEventArgs e) private void menuPromotion_Click(object? sender, RoutedEventArgs e)
{ {
Utils.ProcessStart($"{Utils.Base64Decode(Global.PromotionUrl)}?t={DateTime.Now.Ticks}"); ProcUtils.ProcessStart($"{Utils.Base64Decode(Global.PromotionUrl)}?t={DateTime.Now.Ticks}");
} }
private void menuSettingsSetUWP_Click(object? sender, RoutedEventArgs e) private void menuSettingsSetUWP_Click(object? sender, RoutedEventArgs e)
{ {
Utils.ProcessStart(Utils.GetBinPath("EnableLoopback.exe")); ProcUtils.ProcessStart(Utils.GetBinPath("EnableLoopback.exe"));
} }
public async Task ScanScreenTaskAsync() public async Task ScanScreenTaskAsync()
@@ -441,7 +447,7 @@ namespace v2rayN.Desktop.Views
} }
} }
private void StorageUI() private void StorageUI(string? n = null)
{ {
_config.UiItem.MainWidth = Utils.ToInt(this.Width); _config.UiItem.MainWidth = Utils.ToInt(this.Width);
_config.UiItem.MainHeight = Utils.ToInt(this.Height); _config.UiItem.MainHeight = Utils.ToInt(this.Height);
@@ -456,7 +462,6 @@ namespace v2rayN.Desktop.Views
_config.UiItem.MainGirdHeight1 = Math.Ceiling(gridMain1.RowDefinitions[0].ActualHeight + 0.1); _config.UiItem.MainGirdHeight1 = Math.Ceiling(gridMain1.RowDefinitions[0].ActualHeight + 0.1);
_config.UiItem.MainGirdHeight2 = Math.Ceiling(gridMain1.RowDefinitions[2].ActualHeight + 0.1); _config.UiItem.MainGirdHeight2 = Math.Ceiling(gridMain1.RowDefinitions[2].ActualHeight + 0.1);
} }
ConfigHandler.SaveConfig(_config);
} }
private void AddHelpMenuItem() private void AddHelpMenuItem()
@@ -480,7 +485,7 @@ namespace v2rayN.Desktop.Views
{ {
if (sender is MenuItem item) if (sender is MenuItem item)
{ {
Utils.ProcessStart(item.Tag?.ToString()); ProcUtils.ProcessStart(item.Tag?.ToString());
} }
} }

View File

@@ -65,7 +65,7 @@
Margin="8,0" Margin="8,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
IsChecked="True" IsChecked="True"
Theme="{StaticResource SimpleToggleSwitch}" /> Theme="{DynamicResource SimpleToggleSwitch}" />
<TextBlock <TextBlock
Margin="8,0" Margin="8,0"
VerticalAlignment="Center" VerticalAlignment="Center"
@@ -75,7 +75,7 @@
Margin="8,0" Margin="8,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
IsChecked="True" IsChecked="True"
Theme="{StaticResource SimpleToggleSwitch}" /> Theme="{DynamicResource SimpleToggleSwitch}" />
</WrapPanel> </WrapPanel>
<TextBox <TextBox
Name="txtMsg" Name="txtMsg"

View File

@@ -8,7 +8,7 @@
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib" xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
Title="{x:Static resx:ResUI.menuSetting}" Title="{x:Static resx:ResUI.menuSetting}"
Width="1000" Width="1000"
Height="700" Height="600"
x:DataType="vms:OptionSettingViewModel" x:DataType="vms:OptionSettingViewModel"
ShowInTaskbar="False" ShowInTaskbar="False"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
@@ -37,33 +37,10 @@
<TabControl HorizontalContentAlignment="Stretch"> <TabControl HorizontalContentAlignment="Stretch">
<TabItem Header="{x:Static resx:ResUI.TbSettingsCore}"> <TabItem Header="{x:Static resx:ResUI.TbSettingsCore}">
<ScrollViewer VerticalScrollBarVisibility="Visible"> <ScrollViewer VerticalScrollBarVisibility="Visible">
<Grid Classes="Margin8"> <Grid
<Grid.RowDefinitions> Classes="Margin8"
<RowDefinition Height="Auto" /> ColumnDefinitions="Auto,Auto,Auto"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"
@@ -86,225 +63,244 @@
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsSecondLocalPortEnabled}" />
<ToggleSwitch
x:Name="togSecondLocalPortEnabled"
Grid.Row="2"
Grid.Column="1"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="3"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsUdpEnabled}" /> Text="{x:Static resx:ResUI.TbSettingsUdpEnabled}" />
<ToggleSwitch <ToggleSwitch
x:Name="togudpEnabled" x:Name="togudpEnabled"
Grid.Row="1" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="4"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsSniffingEnabled}" /> Text="{x:Static resx:ResUI.TbSettingsSniffingEnabled}" />
<StackPanel <ToggleSwitch
Grid.Row="2" x:Name="togsniffingEnabled"
Grid.Row="4"
Grid.Column="1" Grid.Column="1"
Grid.ColumnSpan="2" HorizontalAlignment="Left"
Orientation="Horizontal"> Classes="Margin8" />
<ToggleSwitch
x:Name="togsniffingEnabled"
HorizontalAlignment="Left"
Classes="Margin8" />
<ListBox
x:Name="clbdestOverride"
HorizontalAlignment="Left"
Classes="Margin8"
SelectionMode="Multiple"
Theme="{DynamicResource PureCardRadioGroupListBox}" />
</StackPanel>
<TextBlock <TextBlock
Grid.Row="3" Grid.Row="5"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsDestOverride}" />
<ListBox
x:Name="clbdestOverride"
Grid.Row="5"
Grid.Column="1"
Grid.ColumnSpan="2"
HorizontalAlignment="Left"
Classes="Margin8"
SelectionMode="Multiple,Toggle"
Theme="{DynamicResource CardCheckGroupListBox}" />
<TextBlock
Grid.Row="6"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsRouteOnly}" /> Text="{x:Static resx:ResUI.TbSettingsRouteOnly}" />
<ToggleSwitch <ToggleSwitch
x:Name="togrouteOnly" x:Name="togrouteOnly"
Grid.Row="3" Grid.Row="6"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="4" Grid.Row="7"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsAllowLAN}" /> Text="{x:Static resx:ResUI.TbSettingsAllowLAN}" />
<ToggleSwitch <ToggleSwitch
x:Name="togAllowLANConn" x:Name="togAllowLANConn"
Grid.Row="4" Grid.Row="7"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="5" Grid.Row="8"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsNewPort4LAN}" /> Text="{x:Static resx:ResUI.TbSettingsNewPort4LAN}" />
<ToggleSwitch <ToggleSwitch
x:Name="togNewPort4LAN" x:Name="togNewPort4LAN"
Grid.Row="5" Grid.Row="8"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="6" Grid.Row="9"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsUser}" /> Text="{x:Static resx:ResUI.TbSettingsUser}" />
<TextBox <TextBox
x:Name="txtuser" x:Name="txtuser"
Grid.Row="6" Grid.Row="9"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="7" Grid.Row="10"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsPass}" /> Text="{x:Static resx:ResUI.TbSettingsPass}" />
<TextBox <TextBox
x:Name="txtpass" x:Name="txtpass"
Grid.Row="7" Grid.Row="10"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="8" Grid.Row="11"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsMuxEnabled}" /> Text="{x:Static resx:ResUI.TbSettingsMuxEnabled}" />
<ToggleSwitch <ToggleSwitch
x:Name="togmuxEnabled" x:Name="togmuxEnabled"
Grid.Row="8" Grid.Row="11"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="9" Grid.Row="12"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsLogEnabledToFile}" /> Text="{x:Static resx:ResUI.TbSettingsLogEnabledToFile}" />
<ToggleSwitch <ToggleSwitch
x:Name="toglogEnabled" x:Name="toglogEnabled"
Grid.Row="9" Grid.Row="12"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="10" Grid.Row="13"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsLogLevel}" /> Text="{x:Static resx:ResUI.TbSettingsLogLevel}" />
<ComboBox <ComboBox
x:Name="cmbloglevel" x:Name="cmbloglevel"
Grid.Row="10" Grid.Row="13"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Classes="Margin8" Classes="Margin8"
ToolTip.Tip="Level" /> ToolTip.Tip="Level" />
<TextBlock <TextBlock
Grid.Row="11" Grid.Row="14"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsDefAllowInsecure}" /> Text="{x:Static resx:ResUI.TbSettingsDefAllowInsecure}" />
<ToggleSwitch <ToggleSwitch
x:Name="togdefAllowInsecure" x:Name="togdefAllowInsecure"
Grid.Row="11" Grid.Row="14"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="12" Grid.Row="15"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsDefFingerprint}" /> Text="{x:Static resx:ResUI.TbSettingsDefFingerprint}" />
<ComboBox <ComboBox
x:Name="cmbdefFingerprint" x:Name="cmbdefFingerprint"
Grid.Row="12" Grid.Row="15"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="13" Grid.Row="16"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsDefUserAgent}" /> Text="{x:Static resx:ResUI.TbSettingsDefUserAgent}" />
<ComboBox <ComboBox
x:Name="cmbdefUserAgent" x:Name="cmbdefUserAgent"
Grid.Row="13" Grid.Row="16"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="13" Grid.Row="16"
Grid.Column="3" Grid.Column="3"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsDefUserAgentTips}" /> Text="{x:Static resx:ResUI.TbSettingsDefUserAgentTips}" />
<TextBlock <TextBlock
Grid.Row="14" Grid.Row="17"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsMux4SboxProtocol}" /> Text="{x:Static resx:ResUI.TbSettingsMux4SboxProtocol}" />
<ComboBox <ComboBox
x:Name="cmbmux4SboxProtocol" x:Name="cmbmux4SboxProtocol"
Grid.Row="14" Grid.Row="17"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="15" Grid.Row="18"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsEnableCacheFile4Sbox}" /> Text="{x:Static resx:ResUI.TbSettingsEnableCacheFile4Sbox}" />
<ToggleSwitch <ToggleSwitch
x:Name="togenableCacheFile4Sbox" x:Name="togenableCacheFile4Sbox"
Grid.Row="15" Grid.Row="18"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="16" Grid.Row="19"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsHysteriaBandwidth}" /> Text="{x:Static resx:ResUI.TbSettingsHysteriaBandwidth}" />
<StackPanel <StackPanel
Grid.Row="16" Grid.Row="19"
Grid.Column="1" Grid.Column="1"
Orientation="Horizontal"> Orientation="Horizontal">
@@ -321,19 +317,19 @@
</StackPanel> </StackPanel>
<TextBlock <TextBlock
Grid.Row="17" Grid.Row="20"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsEnableFragment}" /> Text="{x:Static resx:ResUI.TbSettingsEnableFragment}" />
<ToggleSwitch <ToggleSwitch
x:Name="togenableFragment" x:Name="togenableFragment"
Grid.Row="17" Grid.Row="20"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="17" Grid.Row="20"
Grid.Column="2" Grid.Column="2"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsEnableFragmentTips}" Text="{x:Static resx:ResUI.TbSettingsEnableFragmentTips}"
@@ -344,39 +340,11 @@
<TabItem Header="{x:Static resx:ResUI.TbSettingsN}"> <TabItem Header="{x:Static resx:ResUI.TbSettingsN}">
<ScrollViewer VerticalScrollBarVisibility="Visible"> <ScrollViewer VerticalScrollBarVisibility="Visible">
<Grid Grid.Row="2" Classes="Margin8"> <Grid
<Grid.RowDefinitions> Grid.Row="2"
<RowDefinition Height="Auto" /> Classes="Margin8"
<RowDefinition Height="Auto" /> ColumnDefinitions="Auto,Auto,*"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
x:Name="tbAutoRun" x:Name="tbAutoRun"
@@ -503,7 +471,6 @@
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="11" Grid.Row="11"
Grid.Column="0" Grid.Column="0"
@@ -697,7 +664,10 @@
<TabItem Name="tabSystemproxy" Header="{x:Static resx:ResUI.TbSettingsSystemproxy}"> <TabItem Name="tabSystemproxy" Header="{x:Static resx:ResUI.TbSettingsSystemproxy}">
<DockPanel Classes="Margin8"> <DockPanel Classes="Margin8">
<StackPanel DockPanel.Dock="Bottom" Orientation="Vertical"> <StackPanel
Name="panSystemProxyAdvanced"
DockPanel.Dock="Bottom"
Orientation="Vertical">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock <TextBlock
VerticalAlignment="Center" VerticalAlignment="Center"
@@ -723,11 +693,17 @@
</StackPanel> </StackPanel>
<TextBlock <TextBlock
Grid.Row="1" Name="txbSettingsExceptionTip"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
DockPanel.Dock="Top" DockPanel.Dock="Top"
Text="{x:Static resx:ResUI.TbSettingsExceptionTip}" /> Text="{x:Static resx:ResUI.TbSettingsExceptionTip}" />
<TextBlock
Name="txbSettingsExceptionTip2"
VerticalAlignment="Center"
Classes="Margin8"
DockPanel.Dock="Top"
Text="{x:Static resx:ResUI.TbSettingsExceptionTip2}" />
<TextBox <TextBox
x:Name="txtsystemProxyExceptions" x:Name="txtsystemProxyExceptions"
VerticalAlignment="Stretch" VerticalAlignment="Stretch"
@@ -738,130 +714,107 @@
</TabItem> </TabItem>
<TabItem Header="{x:Static resx:ResUI.TbSettingsTunMode}"> <TabItem Header="{x:Static resx:ResUI.TbSettingsTunMode}">
<DockPanel Classes="Margin8"> <Grid
<Grid Classes="Margin8" DockPanel.Dock="Top"> Classes="Margin8"
<Grid.RowDefinitions> ColumnDefinitions="Auto,Auto,Auto"
<RowDefinition Height="Auto" /> DockPanel.Dock="Top"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="2" Grid.Row="2"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="Strict Route" /> Text="Strict Route" />
<ToggleSwitch <ToggleSwitch
x:Name="togStrictRoute" x:Name="togStrictRoute"
Grid.Row="2" Grid.Row="2"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="3" Grid.Row="3"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="Stack" /> Text="Stack" />
<ComboBox <ComboBox
x:Name="cmbStack" x:Name="cmbStack"
Grid.Row="3" Grid.Row="3"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="4" Grid.Row="4"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="Mtu" /> Text="Mtu" />
<ComboBox <ComboBox
x:Name="cmbMtu" x:Name="cmbMtu"
Grid.Row="4" Grid.Row="4"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="5" Grid.Row="5"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsEnableExInbound}" /> Text="{x:Static resx:ResUI.TbSettingsEnableExInbound}" />
<ToggleSwitch <ToggleSwitch
x:Name="togEnableExInbound" x:Name="togEnableExInbound"
Grid.Row="5" Grid.Row="5"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="6" Grid.Row="6"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsEnableIPv6Address}" /> Text="{x:Static resx:ResUI.TbSettingsEnableIPv6Address}" />
<ToggleSwitch <ToggleSwitch
x:Name="togEnableIPv6Address" x:Name="togEnableIPv6Address"
Grid.Row="6" Grid.Row="6"
Grid.Column="1" Grid.Column="1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="7" Grid.Row="7"
Grid.Column="0" Grid.Column="0"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPassword}" /> Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPassword}" />
<TextBox <TextBox
x:Name="txtLinuxSudoPassword" x:Name="txtLinuxSudoPassword"
Grid.Row="7" Grid.Row="7"
Grid.Column="1" Grid.Column="1"
Width="200" Width="200"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
<TextBlock <TextBlock
Grid.Row="7" Grid.Row="7"
Grid.Column="2" Grid.Column="2"
VerticalAlignment="Center" VerticalAlignment="Center"
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPasswordTip}" Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPasswordTip}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</Grid> </Grid>
</DockPanel>
</TabItem> </TabItem>
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreType}"> <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreType}">
<Grid Classes="Margin8"> <Grid
<Grid.RowDefinitions> Classes="Margin8"
<RowDefinition Height="Auto" /> ColumnDefinitions="Auto,Auto"
<RowDefinition Height="Auto" /> RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
Grid.Column="0" Grid.Column="0"

View File

@@ -102,6 +102,7 @@ namespace v2rayN.Desktop.Views
this.WhenActivated(disposables => this.WhenActivated(disposables =>
{ {
this.Bind(ViewModel, vm => vm.localPort, v => v.txtlocalPort.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.localPort, v => v.txtlocalPort.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SecondLocalPortEnabled, v => v.togSecondLocalPortEnabled.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.udpEnabled, v => v.togudpEnabled.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.udpEnabled, v => v.togudpEnabled.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.sniffingEnabled, v => v.togsniffingEnabled.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.sniffingEnabled, v => v.togsniffingEnabled.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.routeOnly, v => v.togrouteOnly.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.routeOnly, v => v.togrouteOnly.IsChecked).DisposeWith(disposables);
@@ -166,9 +167,14 @@ namespace v2rayN.Desktop.Views
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
}); });
if (!Utils.IsWindows()) if (Utils.IsWindows())
{ {
tabSystemproxy.IsVisible = false; txbSettingsExceptionTip2.IsVisible = false;
}
else
{
txbSettingsExceptionTip.IsVisible = false;
panSystemProxyAdvanced.IsVisible = false;
} }
if (Utils.IsOSX()) if (Utils.IsOSX())
@@ -210,7 +216,7 @@ namespace v2rayN.Desktop.Views
{ {
return lstFonts; return lstFonts;
} }
else if (Utils.IsLinux() || Utils.IsOSX()) else if (Utils.IsNonWindows())
{ {
var result = await Utils.GetLinuxFontFamily("zh"); var result = await Utils.GetLinuxFontFamily("zh");
if (result.IsNullOrEmpty()) if (result.IsNullOrEmpty())
@@ -229,7 +235,7 @@ namespace v2rayN.Desktop.Views
} }
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog("fill fonts error", ex); Logging.SaveLog("GetFonts", ex);
} }
return lstFonts; return lstFonts;
} }

View File

@@ -56,28 +56,23 @@
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" /> Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
</Button.Content> </Button.Content>
</Button> </Button>
<SplitButton
<Button
x:Name="btnAutofitColumnWidth" x:Name="btnAutofitColumnWidth"
Width="54" Width="30"
Height="30" Height="30"
Margin="20,0" Margin="4,0"
Padding="2" Classes="Success"
Classes="Tertiary" Theme="{DynamicResource BorderlessButton}"
Theme="{DynamicResource BorderlessSplitButton}"
ToolTip.Tip="{x:Static resx:ResUI.menuProfileAutofitColumnWidth}"> ToolTip.Tip="{x:Static resx:ResUI.menuProfileAutofitColumnWidth}">
<SplitButton.Content> <Button.Content>
<PathIcon <PathIcon
Width="24" Width="24"
Height="24" Height="24"
Data="{StaticResource building_fit}" Data="{StaticResource building_fit}"
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" /> Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
</SplitButton.Content> </Button.Content>
<SplitButton.Flyout> </Button>
<MenuFlyout>
<MenuItem Name="menuStorageUI" Header="{x:Static resx:ResUI.menuStorageUI}" />
</MenuFlyout>
</SplitButton.Flyout>
</SplitButton>
<TextBox <TextBox
x:Name="txtServerFilter" x:Name="txtServerFilter"
@@ -170,7 +165,7 @@
Classes="Solid Red" Classes="Solid Red"
Content="{x:Static resx:ResUI.TipActiveServer}" Content="{x:Static resx:ResUI.TipActiveServer}"
IsVisible="{Binding IsActive}" IsVisible="{Binding IsActive}"
Theme="{StaticResource TagLabel}" /> Theme="{DynamicResource TagLabel}" />
<TextBlock <TextBlock
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"

View File

@@ -15,7 +15,12 @@ namespace v2rayN.Desktop.Views
public partial class ProfilesView : ReactiveUserControl<ProfilesViewModel> public partial class ProfilesView : ReactiveUserControl<ProfilesViewModel>
{ {
private static Config _config; private static Config _config;
private Window _window; private Window? _window;
public ProfilesView()
{
InitializeComponent();
}
public ProfilesView(Window window) public ProfilesView(Window window)
{ {
@@ -27,7 +32,6 @@ namespace v2rayN.Desktop.Views
menuSelectAll.Click += menuSelectAll_Click; menuSelectAll.Click += menuSelectAll_Click;
btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click; btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click;
txtServerFilter.KeyDown += TxtServerFilter_KeyDown; txtServerFilter.KeyDown += TxtServerFilter_KeyDown;
menuStorageUI.Click += MenuStorageUI_Click;
lstProfiles.KeyDown += LstProfiles_KeyDown; lstProfiles.KeyDown += LstProfiles_KeyDown;
lstProfiles.SelectionChanged += lstProfiles_SelectionChanged; lstProfiles.SelectionChanged += lstProfiles_SelectionChanged;
lstProfiles.DoubleTapped += LstProfiles_DoubleTapped; lstProfiles.DoubleTapped += LstProfiles_DoubleTapped;
@@ -91,6 +95,7 @@ namespace v2rayN.Desktop.Views
RestoreUI(); RestoreUI();
ViewModel?.RefreshServers(); ViewModel?.RefreshServers();
MessageBus.Current.Listen<string>(EMsgCommand.AppExit.ToString()).Subscribe(StorageUI);
} }
private async void LstProfiles_Sorting(object? sender, DataGridColumnEventArgs e) private async void LstProfiles_Sorting(object? sender, DataGridColumnEventArgs e)
@@ -187,12 +192,7 @@ namespace v2rayN.Desktop.Views
private void lstProfiles_SelectionChanged(object? sender, SelectionChangedEventArgs e) private void lstProfiles_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{ {
List<ProfileItemModel> lst = []; ViewModel.SelectedProfiles = lstProfiles.SelectedItems.Cast<ProfileItemModel>().ToList();
foreach (var item in lstProfiles.SelectedItems)
{
lst.Add((ProfileItemModel)item);
}
ViewModel.SelectedProfiles = lst;
} }
private void LstProfiles_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e) private void LstProfiles_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)
@@ -233,7 +233,7 @@ namespace v2rayN.Desktop.Views
private void LstProfiles_KeyDown(object? sender, KeyEventArgs e) private void LstProfiles_KeyDown(object? sender, KeyEventArgs e)
{ {
if (e.KeyModifiers == KeyModifiers.Control) if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)
{ {
switch (e.Key) switch (e.Key)
{ {
@@ -324,11 +324,6 @@ namespace v2rayN.Desktop.Views
} }
} }
private void MenuStorageUI_Click(object? sender, RoutedEventArgs e)
{
StorageUI();
}
//#endregion Event //#endregion Event
//#region UI //#region UI
@@ -358,17 +353,14 @@ namespace v2rayN.Desktop.Views
} }
if (item.Name.ToLower().StartsWith("to")) if (item.Name.ToLower().StartsWith("to"))
{ {
if (!_config.GuiItem.EnableStatistics) item2.IsVisible = _config.GuiItem.EnableStatistics;
{
item2.IsVisible = false;
}
} }
} }
} }
} }
} }
private void StorageUI() private void StorageUI(string? n = null)
{ {
List<ColumnItem> lvColumnItem = new(); List<ColumnItem> lvColumnItem = new();
for (int k = 0; k < lstProfiles.Columns.Count; k++) for (int k = 0; k < lstProfiles.Columns.Count; k++)
@@ -386,7 +378,6 @@ namespace v2rayN.Desktop.Views
}); });
} }
_config.UiItem.MainColumnItem = lvColumnItem; _config.UiItem.MainColumnItem = lvColumnItem;
ConfigHandler.SaveConfig(_config);
} }
//#endregion UI //#endregion UI

Some files were not shown because too many files have changed in this diff Show More