mirror of
https://github.com/2dust/v2rayN.git
synced 2026-05-19 08:04:40 +03:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f500d2b9f4 | |||
| 79e53bf1f5 | |||
| 31de7ec094 | |||
| 2e4501187c | |||
| 4430c9bd74 | |||
| cf8be85ff7 | |||
| 0759be1223 | |||
| 21f8ddcf9f | |||
| 37cba5ee34 | |||
| ff642fd1ac | |||
| 647f1d9c8b | |||
| d886195ee3 | |||
| e2b8f4f89a | |||
| 1dcfe661e9 | |||
| d6dd110781 | |||
| a0f956c885 | |||
| 88bcafed97 | |||
| 6e4f15ab52 | |||
| 20cae1ff4d | |||
| dcf621b822 | |||
| eafa20032b | |||
| 7375e1a490 | |||
| 199d87ba84 | |||
| b43975ebfc |
@@ -1,10 +1,20 @@
|
|||||||
name: release Linux
|
name: release Linux
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
release_tag:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
push:
|
push:
|
||||||
branches: [ "master" ]
|
branches:
|
||||||
pull_request:
|
- master
|
||||||
branches: [ "master" ]
|
|
||||||
|
env:
|
||||||
|
OutputArch: "linux-64"
|
||||||
|
OutputArchArm: "linux-arm64"
|
||||||
|
OutputPath64: "${{ github.workspace }}/v2rayN/Release/linux-64"
|
||||||
|
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/linux-arm64"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -21,14 +31,46 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cd v2rayN
|
cd v2rayN
|
||||||
chmod 755 build-linux.sh
|
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-x64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPath64
|
||||||
./build-linux.sh
|
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
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: v2rayN-linux
|
name: v2rayN-linux
|
||||||
path: |
|
path: |
|
||||||
./v2rayN/v2rayN-linux.zip
|
${{ 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
|
||||||
@@ -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:
|
||||||
@@ -21,14 +31,47 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cd v2rayN
|
cd v2rayN
|
||||||
chmod 755 build-osx.sh
|
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-x64 --self-contained true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPath64
|
||||||
./build-osx.sh
|
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
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
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
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
name: release Windows
|
|
||||||
|
|
||||||
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: Build
|
|
||||||
run: cd v2rayN &&
|
|
||||||
./build.ps1
|
|
||||||
|
|
||||||
- name: Upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: v2rayN-windows-64
|
|
||||||
path: |
|
|
||||||
./v2rayN/v2rayN-windows-64.zip
|
|
||||||
|
|
||||||
- name: Upload build artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: v2rayN-windows-arm64
|
|
||||||
path: |
|
|
||||||
./v2rayN/v2rayN-windows-arm64.zip
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
[](https://github.com/2dust/v2rayN/commits/master)
|
[](https://github.com/2dust/v2rayN/commits/master)
|
||||||
@@ -19,6 +19,11 @@ Debian 9+
|
|||||||
Ubuntu 16.04+
|
Ubuntu 16.04+
|
||||||
Fedora 30+
|
Fedora 30+
|
||||||
```
|
```
|
||||||
|
### macOS
|
||||||
|
- `chmod +x v2rayN` Run `./v2rayN` under user permissions
|
||||||
|
```
|
||||||
|
macOS 10.14+
|
||||||
|
```
|
||||||
|
|
||||||
## 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)
|
||||||
|
|||||||
@@ -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"
|
||||||
Executable
+65
@@ -0,0 +1,65 @@
|
|||||||
|
#!/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"
|
||||||
|
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"
|
||||||
|
|
||||||
|
mkdir -p "$PackagePath/icons.iconset"
|
||||||
|
sips -z 16 16 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.png" --out "$PackagePath/icons.iconset/icon_16x16.png"
|
||||||
|
sips -z 32 32 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.png" --out "$PackagePath/icons.iconset/icon_16x16@2x.png"
|
||||||
|
sips -z 32 32 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.png" --out "$PackagePath/icons.iconset/icon_32x32.png"
|
||||||
|
sips -z 64 64 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.png" --out "$PackagePath/icons.iconset/icon_32x32@2x.png"
|
||||||
|
sips -z 128 128 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.png" --out "$PackagePath/icons.iconset/icon_128x128.png"
|
||||||
|
sips -z 256 256 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.png" --out "$PackagePath/icons.iconset/icon_128x128@2x.png"
|
||||||
|
sips -z 256 256 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.png" --out "$PackagePath/icons.iconset/icon_256x256.png"
|
||||||
|
sips -z 512 512 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.png" --out "$PackagePath/icons.iconset/icon_256x256@2x.png"
|
||||||
|
sips -z 512 512 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.png" --out "$PackagePath/icons.iconset/icon_512x512.png"
|
||||||
|
sips -z 1024 1024 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.png" --out "$PackagePath/icons.iconset/icon_512x512@2x.png"
|
||||||
|
iconutil -c icns "$PackagePath/icons.iconset" -o "$PackagePath/v2rayN.app/Contents/Resources/AppIcon.icns"
|
||||||
|
|
||||||
|
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"
|
||||||
@@ -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
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
|
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
|
||||||
<FileVersion>1.3.0</FileVersion>
|
<FileVersion>1.3.1</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace AmazTool
|
|||||||
{
|
{
|
||||||
Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
|
Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
|
||||||
|
|
||||||
Waiting(9);
|
Waiting(8);
|
||||||
|
|
||||||
if (!File.Exists(fileName))
|
if (!File.Exists(fileName))
|
||||||
{
|
{
|
||||||
@@ -91,7 +91,7 @@ namespace AmazTool
|
|||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine(Resx.Resource.Restartv2rayN);
|
Console.WriteLine(Resx.Resource.Restartv2rayN);
|
||||||
Waiting(9);
|
Waiting(3);
|
||||||
Process process = new()
|
Process process = new()
|
||||||
{
|
{
|
||||||
StartInfo = new()
|
StartInfo = new()
|
||||||
|
|||||||
@@ -517,7 +517,7 @@ namespace ServiceLib.Common
|
|||||||
|
|
||||||
public static bool UpgradeAppExists(out string fileName)
|
public static bool UpgradeAppExists(out string fileName)
|
||||||
{
|
{
|
||||||
fileName = Path.Combine(Utils.StartupPath(), GetExeName("AmazTool"));
|
fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, GetExeName("AmazTool"));
|
||||||
return File.Exists(fileName);
|
return File.Exists(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,7 +530,7 @@ namespace ServiceLib.Common
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
return blFull
|
return blFull
|
||||||
? $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture} - {StartupPath()}"
|
? $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture}"
|
||||||
: $"{Global.AppName}/{GetVersionInfo()}";
|
: $"{Global.AppName}/{GetVersionInfo()}";
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -554,6 +554,11 @@ namespace ServiceLib.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string GetRuntimeInfo()
|
||||||
|
{
|
||||||
|
return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion} | {(Environment.Is64BitOperatingSystem ? 64 : 32)}";
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 取得GUID
|
/// 取得GUID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -593,6 +598,9 @@ namespace ServiceLib.Common
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fileName.Contains(' ')) fileName = fileName.AppendQuotes();
|
||||||
|
if (arguments.Contains(' ')) arguments = arguments.AppendQuotes();
|
||||||
|
|
||||||
Process.Start(new ProcessStartInfo(fileName, arguments) { UseShellExecute = true });
|
Process.Start(new ProcessStartInfo(fileName, arguments) { UseShellExecute = true });
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -675,6 +683,12 @@ namespace ServiceLib.Common
|
|||||||
{
|
{
|
||||||
try
|
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");
|
var tempPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "guiTemps");
|
||||||
if (!Directory.Exists(tempPath))
|
if (!Directory.Exists(tempPath))
|
||||||
{
|
{
|
||||||
@@ -851,18 +865,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()
|
||||||
@@ -874,6 +889,7 @@ 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);
|
//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);
|
||||||
@@ -893,6 +909,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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,5 +4,6 @@
|
|||||||
{
|
{
|
||||||
Default = 0,
|
Default = 0,
|
||||||
Russia = 1,
|
Russia = 1,
|
||||||
|
Iran = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,21 +124,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()
|
||||||
|
|||||||
@@ -77,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();
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ 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
|
||||||
@@ -1868,6 +1868,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
ShowMsg(true, $"{node.GetSummary()}");
|
ShowMsg(true, $"{node.GetSummary()}");
|
||||||
ShowMsg(false, $"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
|
ShowMsg(false, $"{Utils.GetRuntimeInfo()}");
|
||||||
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
ShowMsg(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);
|
||||||
|
|||||||
@@ -2,14 +2,10 @@
|
|||||||
{
|
{
|
||||||
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
|
||||||
@@ -18,13 +14,15 @@
|
|||||||
|
|
||||||
public static async Task SetProxy(string host, int port, string exceptions)
|
public static async Task SetProxy(string host, int port, string exceptions)
|
||||||
{
|
{
|
||||||
var lstCmd = GetSetCmds(host, port, exceptions);
|
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,10 +40,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<CmdItem> GetSetCmds(string host, int port, string exceptions)
|
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)
|
||||||
{
|
{
|
||||||
@@ -70,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)
|
||||||
{
|
{
|
||||||
@@ -87,5 +85,16 @@
|
|||||||
|
|
||||||
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);
|
||||||
|
return lst.Length > 0 ? LstInterface.Intersect(lst).ToList() : LstInterface;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Generated
+9
@@ -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>
|
||||||
|
|||||||
@@ -1129,6 +1129,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>کاربران در منطقه چین می توانند این مورد را نادیده بگیرند</value>
|
<value>کاربران در منطقه چین می توانند این مورد را نادیده بگیرند</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -1342,6 +1342,9 @@
|
|||||||
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
||||||
<value>Oroszország</value>
|
<value>Oroszország</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuRegionalPresetsIran" xml:space="preserve">
|
||||||
|
<value>Irán</value>
|
||||||
|
</data>
|
||||||
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
||||||
<value>A Kínában élő felhasználók figyelmen kívül hagyhatják ezt a tételt</value>
|
<value>A Kínában élő felhasználók figyelmen kívül hagyhatják ezt a tételt</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -1342,6 +1342,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>
|
||||||
|
|||||||
@@ -1039,6 +1039,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>Используйте Настройки -> Региональные пресеты вместо изменения этого поля</value>
|
<value>Используйте Настройки -> Региональные пресеты вместо изменения этого поля</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -1342,6 +1342,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>
|
||||||
|
|||||||
@@ -1222,6 +1222,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>
|
||||||
|
|||||||
@@ -99,10 +99,5 @@
|
|||||||
"domain": [
|
"domain": [
|
||||||
"geosite:cn"
|
"geosite:cn"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"remarks": "最终代理",
|
|
||||||
"port": "0-65535",
|
|
||||||
"outboundTag": "proxy"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
+5826
-1
File diff suppressed because it is too large
Load Diff
@@ -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.4.2</Version>
|
<Version>7.5.1</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
<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.7.0" />
|
<PackageReference Include="CliWrap" Version="3.7.0" />
|
||||||
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
|
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
|
||||||
|
|||||||
@@ -50,6 +50,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 +199,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();
|
||||||
@@ -528,17 +535,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()}");
|
Utils.ProcessStart(path);
|
||||||
}
|
}
|
||||||
else if (Utils.IsLinux())
|
else if (Utils.IsLinux())
|
||||||
{
|
{
|
||||||
Utils.ProcessStart("nautilus", Utils.GetConfigPath());
|
Utils.ProcessStart("nautilus", path);
|
||||||
}
|
}
|
||||||
else if (Utils.IsOSX())
|
else if (Utils.IsOSX())
|
||||||
{
|
{
|
||||||
Utils.ProcessStart("open", Utils.GetConfigPath());
|
Utils.ProcessStart("open", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -177,12 +177,12 @@ 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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
echo 'Building Linux'
|
|
||||||
|
|
||||||
OutputPath='./bin/v2rayN'
|
|
||||||
OutputPath64="${OutputPath}/linux-x64"
|
|
||||||
OutputPathArm64="${OutputPath}/linux-arm64"
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
rm -rf "$OutputPath64/*.pdb"
|
|
||||||
rm -rf "$OutputPathArm64/*.pdb"
|
|
||||||
|
|
||||||
echo 'Build done'
|
|
||||||
|
|
||||||
7z a v2rayN-linux.zip $OutputPath
|
|
||||||
exit 0
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
echo 'Building macOS'
|
|
||||||
|
|
||||||
OutputPath='./bin/v2rayN'
|
|
||||||
OutputPath64="${OutputPath}/osx-x64"
|
|
||||||
OutputPathArm64="${OutputPath}/osx-arm64"
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
rm -rf "$OutputPath64/*.pdb"
|
|
||||||
rm -rf "$OutputPathArm64/*.pdb"
|
|
||||||
|
|
||||||
echo 'Build done'
|
|
||||||
|
|
||||||
7z a v2rayN-osx.zip $OutputPath
|
|
||||||
exit 0
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
param (
|
|
||||||
[Parameter()]
|
|
||||||
[ValidateNotNullOrEmpty()]
|
|
||||||
[string]
|
|
||||||
$OutputPathWin64 = './bin/v2rayN/win-x64',
|
|
||||||
$OutputPathWinArm64 = './bin/v2rayN/win-arm64'
|
|
||||||
)
|
|
||||||
|
|
||||||
Write-Host 'Building Windows'
|
|
||||||
|
|
||||||
dotnet publish `
|
|
||||||
./v2rayN/v2rayN.csproj `
|
|
||||||
-c Release `
|
|
||||||
-r win-x64 `
|
|
||||||
--self-contained false `
|
|
||||||
-p:PublishReadyToRun=false `
|
|
||||||
-p:PublishSingleFile=true `
|
|
||||||
-o $OutputPathWin64
|
|
||||||
|
|
||||||
dotnet publish `
|
|
||||||
./v2rayN/v2rayN.csproj `
|
|
||||||
-c Release `
|
|
||||||
-r win-arm64 `
|
|
||||||
--self-contained false `
|
|
||||||
-p:PublishReadyToRun=false `
|
|
||||||
-p:PublishSingleFile=true `
|
|
||||||
-o $OutputPathWinArm64
|
|
||||||
|
|
||||||
if ( -Not $? ) {
|
|
||||||
exit $lastExitCode
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( Test-Path -Path ./bin/v2rayN ) {
|
|
||||||
rm -Force "$OutputPathWin64/*.pdb"
|
|
||||||
rm -Force "$OutputPathWinArm64/*.pdb"
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host 'Build done'
|
|
||||||
|
|
||||||
7z a v2rayN-windows-64.zip $OutputPathWin64
|
|
||||||
7z a v2rayN-windows-arm64.zip $OutputPathWinArm64
|
|
||||||
exit 0
|
|
||||||
@@ -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}" />
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -304,7 +305,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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -187,12 +187,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 +228,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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
|
|
||||||
private void RoutingRuleSettingWindow_KeyDown(object? sender, KeyEventArgs e)
|
private void RoutingRuleSettingWindow_KeyDown(object? sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.KeyModifiers == KeyModifiers.Control)
|
if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)
|
||||||
{
|
{
|
||||||
if (e.Key == Key.A)
|
if (e.Key == Key.A)
|
||||||
{
|
{
|
||||||
@@ -166,12 +166,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
|
|
||||||
private void lstRules_SelectionChanged(object? sender, SelectionChangedEventArgs e)
|
private void lstRules_SelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
List<RulesItemModel> lst = [];
|
ViewModel.SelectedSources = lstRules.SelectedItems.Cast<RulesItemModel>().ToList();
|
||||||
foreach (var item in lstRules.SelectedItems)
|
|
||||||
{
|
|
||||||
lst.Add((RulesItemModel)item);
|
|
||||||
}
|
|
||||||
ViewModel.SelectedSources = lst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LstRules_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)
|
private void LstRules_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
|
|
||||||
private void RoutingSettingWindow_KeyDown(object? sender, KeyEventArgs e)
|
private void RoutingSettingWindow_KeyDown(object? sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.KeyModifiers == KeyModifiers.Control)
|
if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)
|
||||||
{
|
{
|
||||||
if (e.Key == Key.A)
|
if (e.Key == Key.A)
|
||||||
{
|
{
|
||||||
@@ -107,12 +107,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
|
|
||||||
private void lstRoutings_SelectionChanged(object? sender, SelectionChangedEventArgs e)
|
private void lstRoutings_SelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
List<RoutingItemModel> lst = [];
|
ViewModel.SelectedSources = lstRoutings.SelectedItems.Cast<RoutingItemModel>().ToList();
|
||||||
foreach (var item in lstRoutings.SelectedItems)
|
|
||||||
{
|
|
||||||
lst.Add((RoutingItemModel)item);
|
|
||||||
}
|
|
||||||
ViewModel.SelectedSources = lst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LstRoutings_DoubleTapped(object? sender, TappedEventArgs e)
|
private void LstRoutings_DoubleTapped(object? sender, TappedEventArgs e)
|
||||||
|
|||||||
@@ -82,12 +82,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
|
|
||||||
private void LstSubscription_SelectionChanged(object? sender, SelectionChangedEventArgs e)
|
private void LstSubscription_SelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
List<SubItem> lst = [];
|
ViewModel.SelectedSources = lstSubscription.SelectedItems.Cast<SubItem>().ToList();
|
||||||
foreach (var item in lstSubscription.SelectedItems)
|
|
||||||
{
|
|
||||||
lst.Add((SubItem)item);
|
|
||||||
}
|
|
||||||
ViewModel.SelectedSources = lst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void menuClose_Click(object? sender, RoutedEventArgs e)
|
private void menuClose_Click(object? sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -42,6 +42,12 @@
|
|||||||
<EmbeddedResource Include="Assets\v2rayN.ico">
|
<EmbeddedResource Include="Assets\v2rayN.ico">
|
||||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="v2rayN.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
@@ -194,6 +194,10 @@
|
|||||||
x:Name="menuRegionalPresetsRussia"
|
x:Name="menuRegionalPresetsRussia"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
Header="{x:Static resx:ResUI.menuRegionalPresetsRussia}" />
|
Header="{x:Static resx:ResUI.menuRegionalPresetsRussia}" />
|
||||||
|
<MenuItem
|
||||||
|
x:Name="menuRegionalPresetsIran"
|
||||||
|
Height="{StaticResource MenuItemHeight}"
|
||||||
|
Header="{x:Static resx:ResUI.menuRegionalPresetsIran}" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuBackupAndRestore"
|
x:Name="menuBackupAndRestore"
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ namespace v2rayN.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);
|
||||||
|
|||||||
Reference in New Issue
Block a user