Compare commits
18 Commits
7.15.6
...
d727ff40bb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d727ff40bb | ||
|
|
1b5069a933 | ||
|
|
18ea6fdc00 | ||
|
|
67494108ad | ||
|
|
38b2a7d2ca | ||
|
|
bf3703bca1 | ||
|
|
554632cc07 | ||
|
|
12fc3e9566 | ||
|
|
c2ef3a4a8c | ||
|
|
86eb8297dd | ||
|
|
c63d4e83f9 | ||
|
|
bf1fb0f92e | ||
|
|
3c4865982b | ||
|
|
22c233f0cd | ||
|
|
b2d6282755 | ||
|
|
c8d89e3dce | ||
|
|
d3b1810eab | ||
|
|
51409a3e28 |
108
.github/workflows/build-linux.yml
vendored
108
.github/workflows/build-linux.yml
vendored
@@ -9,6 +9,12 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
- 'V*'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
env:
|
env:
|
||||||
OutputArch: "linux-64"
|
OutputArch: "linux-64"
|
||||||
@@ -21,7 +27,6 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
configuration: [Release]
|
configuration: [Release]
|
||||||
|
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -31,21 +36,21 @@ jobs:
|
|||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
fetch-depth: '0'
|
fetch-depth: '0'
|
||||||
|
|
||||||
- name: Setup
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v5.0.0
|
uses: actions/setup-dotnet@v5.0.0
|
||||||
with:
|
with:
|
||||||
dotnet-version: '8.0.x'
|
dotnet-version: '8.0.x'
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cd v2rayN
|
cd v2rayN
|
||||||
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-x64 --self-contained=true -o $OutputPath64
|
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-x64 --self-contained=true -o "$OutputPath64"
|
||||||
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-arm64 --self-contained=true -o $OutputPathArm64
|
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-arm64 --self-contained=true -o "$OutputPathArm64"
|
||||||
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-x64 --self-contained=true -p:PublishTrimmed=true -o $OutputPath64
|
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-x64 --self-contained=true -p:PublishTrimmed=true -o "$OutputPath64"
|
||||||
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-arm64 --self-contained=true -p:PublishTrimmed=true -o $OutputPathArm64
|
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-arm64 --self-contained=true -p:PublishTrimmed=true -o "$OutputPathArm64"
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v4.6.2
|
uses: actions/upload-artifact@v5.0.0
|
||||||
with:
|
with:
|
||||||
name: v2rayN-linux
|
name: v2rayN-linux
|
||||||
path: |
|
path: |
|
||||||
@@ -56,8 +61,8 @@ jobs:
|
|||||||
if: github.event.inputs.release_tag != ''
|
if: github.event.inputs.release_tag != ''
|
||||||
run: |
|
run: |
|
||||||
chmod 755 package-debian.sh
|
chmod 755 package-debian.sh
|
||||||
./package-debian.sh $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }}
|
./package-debian.sh "$OutputArch" "$OutputPath64" "${{ github.event.inputs.release_tag }}"
|
||||||
./package-debian.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}
|
./package-debian.sh "$OutputArchArm" "$OutputPathArm64" "${{ github.event.inputs.release_tag }}"
|
||||||
|
|
||||||
- name: Upload deb to release
|
- name: Upload deb to release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
@@ -68,28 +73,13 @@ jobs:
|
|||||||
file_glob: true
|
file_glob: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
|
|
||||||
- name: Package AppImage
|
|
||||||
if: github.event.inputs.release_tag != ''
|
|
||||||
run: |
|
|
||||||
chmod a+x package-appimage.sh
|
|
||||||
./package-appimage.sh
|
|
||||||
|
|
||||||
- name: Upload AppImage to release
|
|
||||||
uses: svenstaro/upload-release-action@v2
|
|
||||||
if: github.event.inputs.release_tag != ''
|
|
||||||
with:
|
|
||||||
file: ${{ github.workspace }}/v2rayN*.AppImage
|
|
||||||
tag: ${{ github.event.inputs.release_tag }}
|
|
||||||
file_glob: true
|
|
||||||
prerelease: true
|
|
||||||
|
|
||||||
# release zip archive
|
# release zip archive
|
||||||
- name: Package release zip archive
|
- name: Package release zip archive
|
||||||
if: github.event.inputs.release_tag != ''
|
if: github.event.inputs.release_tag != ''
|
||||||
run: |
|
run: |
|
||||||
chmod 755 package-release-zip.sh
|
chmod 755 package-release-zip.sh
|
||||||
./package-release-zip.sh $OutputArch $OutputPath64
|
./package-release-zip.sh "$OutputArch" "$OutputPath64"
|
||||||
./package-release-zip.sh $OutputArchArm $OutputPathArm64
|
./package-release-zip.sh "$OutputArchArm" "$OutputPathArm64"
|
||||||
|
|
||||||
- name: Upload zip archive to release
|
- name: Upload zip archive to release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
@@ -100,36 +90,62 @@ jobs:
|
|||||||
file_glob: true
|
file_glob: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
|
|
||||||
# release RHEL package
|
rpm:
|
||||||
- name: Package RPM (RHEL-family)
|
needs: build
|
||||||
if: github.event.inputs.release_tag != ''
|
if: |
|
||||||
|
(github.event_name == 'workflow_dispatch' && github.event.inputs.release_tag != '') ||
|
||||||
|
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
container:
|
||||||
|
image: quay.io/almalinuxorg/10-base:latest
|
||||||
|
options: --platform=linux/amd64/v2
|
||||||
|
env:
|
||||||
|
RELEASE_TAG: ${{ github.event.inputs.release_tag != '' && github.event.inputs.release_tag || github.ref_name }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Prepare tools (Red Hat)
|
||||||
run: |
|
run: |
|
||||||
chmod 755 package-rhel.sh
|
dnf -y makecache
|
||||||
# Build for both x86_64 and aarch64 in one go (explicit version passed; no --buildfrom)
|
dnf -y install epel-release
|
||||||
./package-rhel.sh "${{ github.event.inputs.release_tag }}" --arch all
|
dnf -y install sudo git rpm-build rpmdevtools dnf-plugins-core rsync findutils tar gzip unzip which
|
||||||
|
|
||||||
|
- name: Checkout repo (for scripts)
|
||||||
|
uses: actions/checkout@v5.0.0
|
||||||
|
with:
|
||||||
|
submodules: 'recursive'
|
||||||
|
fetch-depth: '0'
|
||||||
|
|
||||||
|
- name: Restore build artifacts
|
||||||
|
uses: actions/download-artifact@v6
|
||||||
|
with:
|
||||||
|
name: v2rayN-linux
|
||||||
|
path: ${{ github.workspace }}/v2rayN/Release
|
||||||
|
|
||||||
|
- name: Ensure script permissions
|
||||||
|
run: chmod 755 package-rhel.sh
|
||||||
|
|
||||||
|
- name: Package RPM (RHEL-family)
|
||||||
|
run: ./package-rhel.sh "${RELEASE_TAG}" --arch all
|
||||||
|
|
||||||
- name: Collect RPMs into workspace
|
- name: Collect RPMs into workspace
|
||||||
if: github.event.inputs.release_tag != ''
|
|
||||||
run: |
|
run: |
|
||||||
mkdir -p "${{ github.workspace }}/dist/rpm"
|
mkdir -p "$GITHUB_WORKSPACE/dist/rpm"
|
||||||
rsync -av "$HOME/rpmbuild/RPMS/" "${{ github.workspace }}/dist/rpm/"
|
rsync -av "$HOME/rpmbuild/RPMS/" "$GITHUB_WORKSPACE/dist/rpm/" || true
|
||||||
# Rename to requested filenames
|
find "$GITHUB_WORKSPACE/dist/rpm" -name "v2rayN-*-1*.x86_64.rpm" -exec mv {} "$GITHUB_WORKSPACE/dist/rpm/v2rayN-linux-rhel-64.rpm" \; || true
|
||||||
find "${{ github.workspace }}/dist/rpm" -name "v2rayN-*-1.x86_64.rpm" -exec mv {} "${{ github.workspace }}/dist/rpm/v2rayN-linux-rhel-x64.rpm" \; || true
|
find "$GITHUB_WORKSPACE/dist/rpm" -name "v2rayN-*-1*.aarch64.rpm" -exec mv {} "$GITHUB_WORKSPACE/dist/rpm/v2rayN-linux-rhel-arm64.rpm" \; || true
|
||||||
find "${{ github.workspace }}/dist/rpm" -name "v2rayN-*-1.aarch64.rpm" -exec mv {} "${{ github.workspace }}/dist/rpm/v2rayN-linux-rhel-arm64.rpm" \; || true
|
echo "==== Dist tree ===="
|
||||||
|
ls -R "$GITHUB_WORKSPACE/dist/rpm" || true
|
||||||
|
|
||||||
- name: Upload RPM artifacts
|
- name: Upload RPM artifacts
|
||||||
if: github.event.inputs.release_tag != ''
|
uses: actions/upload-artifact@v5.0.0
|
||||||
uses: actions/upload-artifact@v4.6.2
|
|
||||||
with:
|
with:
|
||||||
name: v2rayN-rpm
|
name: v2rayN-rpm
|
||||||
path: |
|
path: dist/rpm/**/*.rpm
|
||||||
${{ github.workspace }}/dist/rpm/**/*.rpm
|
|
||||||
|
|
||||||
- name: Upload RPMs to release
|
- name: Upload RPMs to release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
if: github.event.inputs.release_tag != ''
|
|
||||||
with:
|
with:
|
||||||
file: ${{ github.workspace }}/dist/rpm/**/*.rpm
|
file: dist/rpm/**/*.rpm
|
||||||
tag: ${{ github.event.inputs.release_tag }}
|
tag: ${{ env.RELEASE_TAG }}
|
||||||
file_glob: true
|
file_glob: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
|
|||||||
2
.github/workflows/build-osx.yml
vendored
2
.github/workflows/build-osx.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
|||||||
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-arm64 --self-contained=true -p:PublishTrimmed=true -o $OutputPathArm64
|
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-arm64 --self-contained=true -p:PublishTrimmed=true -o $OutputPathArm64
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v4.6.2
|
uses: actions/upload-artifact@v5.0.0
|
||||||
with:
|
with:
|
||||||
name: v2rayN-macos
|
name: v2rayN-macos
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
2
.github/workflows/build-windows-desktop.yml
vendored
2
.github/workflows/build-windows-desktop.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
|||||||
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPathArm64
|
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPathArm64
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v4.6.2
|
uses: actions/upload-artifact@v5.0.0
|
||||||
with:
|
with:
|
||||||
name: v2rayN-windows-desktop
|
name: v2rayN-windows-desktop
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
2
.github/workflows/build-windows.yml
vendored
2
.github/workflows/build-windows.yml
vendored
@@ -46,7 +46,7 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v4.6.2
|
uses: actions/upload-artifact@v5.0.0
|
||||||
with:
|
with:
|
||||||
name: v2rayN-windows
|
name: v2rayN-windows
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Install deps
|
|
||||||
sudo apt update -y
|
|
||||||
sudo apt install -y libfuse2 wget file
|
|
||||||
|
|
||||||
# Get tools
|
|
||||||
wget -qO appimagetool https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
|
||||||
chmod +x appimagetool
|
|
||||||
|
|
||||||
# x86_64 AppDir
|
|
||||||
APPDIR_X64="AppDir-x86_64"
|
|
||||||
rm -rf "$APPDIR_X64"
|
|
||||||
mkdir -p "$APPDIR_X64/usr/lib/v2rayN" "$APPDIR_X64/usr/bin" "$APPDIR_X64/usr/share/applications" "$APPDIR_X64/usr/share/pixmaps"
|
|
||||||
cp -rf "$OutputPath64"/* "$APPDIR_X64/usr/lib/v2rayN" || true
|
|
||||||
[ -f "$APPDIR_X64/usr/lib/v2rayN/v2rayN.png" ] && cp "$APPDIR_X64/usr/lib/v2rayN/v2rayN.png" "$APPDIR_X64/usr/share/pixmaps/v2rayN.png" || true
|
|
||||||
[ -f "$APPDIR_X64/usr/lib/v2rayN/v2rayN.png" ] && cp "$APPDIR_X64/usr/lib/v2rayN/v2rayN.png" "$APPDIR_X64/v2rayN.png" || true
|
|
||||||
|
|
||||||
printf '%s\n' '#!/bin/sh' 'HERE="$(dirname "$(readlink -f "$0")")"' 'cd "$HERE/usr/lib/v2rayN"' 'exec "$HERE/usr/lib/v2rayN/v2rayN" "$@"' > "$APPDIR_X64/AppRun"
|
|
||||||
chmod +x "$APPDIR_X64/AppRun"
|
|
||||||
ln -sf usr/lib/v2rayN/v2rayN "$APPDIR_X64/usr/bin/v2rayN"
|
|
||||||
cat > "$APPDIR_X64/v2rayN.desktop" <<EOF
|
|
||||||
[Desktop Entry]
|
|
||||||
Name=v2rayN
|
|
||||||
Comment=A GUI client for Windows and Linux, support Xray core and sing-box-core and others
|
|
||||||
Exec=v2rayN
|
|
||||||
Icon=v2rayN
|
|
||||||
Terminal=false
|
|
||||||
Type=Application
|
|
||||||
Categories=Network;
|
|
||||||
EOF
|
|
||||||
install -Dm644 "$APPDIR_X64/v2rayN.desktop" "$APPDIR_X64/usr/share/applications/v2rayN.desktop"
|
|
||||||
|
|
||||||
ARCH=x86_64 ./appimagetool "$APPDIR_X64" "v2rayN-${OutputArch}.AppImage"
|
|
||||||
file "v2rayN-${OutputArch}.AppImage" | grep -q 'x86-64'
|
|
||||||
|
|
||||||
# aarch64 AppDir
|
|
||||||
APPDIR_ARM64="AppDir-aarch64"
|
|
||||||
rm -rf "$APPDIR_ARM64"
|
|
||||||
mkdir -p "$APPDIR_ARM64/usr/lib/v2rayN" "$APPDIR_ARM64/usr/bin" "$APPDIR_ARM64/usr/share/applications" "$APPDIR_ARM64/usr/share/pixmaps"
|
|
||||||
cp -rf "$OutputPathArm64"/* "$APPDIR_ARM64/usr/lib/v2rayN" || true
|
|
||||||
[ -f "$APPDIR_ARM64/usr/lib/v2rayN/v2rayN.png" ] && cp "$APPDIR_ARM64/usr/lib/v2rayN/v2rayN.png" "$APPDIR_ARM64/usr/share/pixmaps/v2rayN.png" || true
|
|
||||||
[ -f "$APPDIR_ARM64/usr/lib/v2rayN/v2rayN.png" ] && cp "$APPDIR_ARM64/usr/lib/v2rayN/v2rayN.png" "$APPDIR_ARM64/v2rayN.png" || true
|
|
||||||
|
|
||||||
printf '%s\n' '#!/bin/sh' 'HERE="$(dirname "$(readlink -f "$0")")"' 'cd "$HERE/usr/lib/v2rayN"' 'exec "$HERE/usr/lib/v2rayN/v2rayN" "$@"' > "$APPDIR_ARM64/AppRun"
|
|
||||||
chmod +x "$APPDIR_ARM64/AppRun"
|
|
||||||
ln -sf usr/lib/v2rayN/v2rayN "$APPDIR_ARM64/usr/bin/v2rayN"
|
|
||||||
cat > "$APPDIR_ARM64/v2rayN.desktop" <<EOF
|
|
||||||
[Desktop Entry]
|
|
||||||
Name=v2rayN
|
|
||||||
Comment=A GUI client for Windows and Linux, support Xray core and sing-box-core and others
|
|
||||||
Exec=v2rayN
|
|
||||||
Icon=v2rayN
|
|
||||||
Terminal=false
|
|
||||||
Type=Application
|
|
||||||
Categories=Network;
|
|
||||||
EOF
|
|
||||||
install -Dm644 "$APPDIR_ARM64/v2rayN.desktop" "$APPDIR_ARM64/usr/share/applications/v2rayN.desktop"
|
|
||||||
|
|
||||||
# aarch64 runtime
|
|
||||||
wget -qO runtime-aarch64 https://github.com/AppImage/AppImageKit/releases/download/continuous/runtime-aarch64
|
|
||||||
chmod +x runtime-aarch64
|
|
||||||
|
|
||||||
# build aarch64 AppImage
|
|
||||||
ARCH=aarch64 ./appimagetool --runtime-file ./runtime-aarch64 "$APPDIR_ARM64" "v2rayN-${OutputArchArm}.AppImage"
|
|
||||||
file "v2rayN-${OutputArchArm}.AppImage" | grep -q 'ARM aarch64'
|
|
||||||
@@ -28,7 +28,7 @@ Package: v2rayN
|
|||||||
Version: $Version
|
Version: $Version
|
||||||
Architecture: $Arch2
|
Architecture: $Arch2
|
||||||
Maintainer: https://github.com/2dust/v2rayN
|
Maintainer: https://github.com/2dust/v2rayN
|
||||||
Depends: desktop-file-utils, xdg-utils
|
Depends: libc6 (>= 2.34), fontconfig (>= 2.13.1), desktop-file-utils (>= 0.26), xdg-utils (>= 1.1.3), coreutils (>= 8.32), bash (>= 5.1)
|
||||||
Description: A GUI client for Windows and Linux, support Xray core and sing-box-core and others
|
Description: A GUI client for Windows and Linux, support Xray core and sing-box-core and others
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,23 @@ else
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ======================== Kernel version check (require >= 6.11) =======================
|
||||||
|
MIN_KERNEL_MAJOR=6
|
||||||
|
MIN_KERNEL_MINOR=11
|
||||||
|
KERNEL_FULL=$(uname -r)
|
||||||
|
KERNEL_MAJOR=$(echo "$KERNEL_FULL" | cut -d. -f1)
|
||||||
|
KERNEL_MINOR=$(echo "$KERNEL_FULL" | cut -d. -f2)
|
||||||
|
|
||||||
|
echo "[INFO] Detected kernel version: $KERNEL_FULL"
|
||||||
|
|
||||||
|
if (( KERNEL_MAJOR < MIN_KERNEL_MAJOR )) || { (( KERNEL_MAJOR == MIN_KERNEL_MAJOR )) && (( KERNEL_MINOR < MIN_KERNEL_MINOR )); }; then
|
||||||
|
echo "[ERROR] Kernel $KERNEL_FULL is too old. Requires Linux >= ${MIN_KERNEL_MAJOR}.${MIN_KERNEL_MINOR}."
|
||||||
|
echo "Please upgrade your system or use a newer container (e.g. Fedora 42+, RHEL 10+, Debian 13+)."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[OK] Kernel version >= ${MIN_KERNEL_MAJOR}.${MIN_KERNEL_MINOR}."
|
||||||
|
|
||||||
# ===== Config & Parse arguments =========================================================
|
# ===== Config & Parse arguments =========================================================
|
||||||
VERSION_ARG="${1:-}" # Pass version number like 7.13.8, or leave empty
|
VERSION_ARG="${1:-}" # Pass version number like 7.13.8, or leave empty
|
||||||
WITH_CORE="both" # Default: bundle both xray+sing-box
|
WITH_CORE="both" # Default: bundle both xray+sing-box
|
||||||
@@ -614,8 +631,13 @@ ExclusiveArch: aarch64 x86_64
|
|||||||
Source0: __PKGROOT__.tar.gz
|
Source0: __PKGROOT__.tar.gz
|
||||||
|
|
||||||
# Runtime dependencies (Avalonia / X11 / Fonts / GL)
|
# Runtime dependencies (Avalonia / X11 / Fonts / GL)
|
||||||
Requires: libX11, libXrandr, libXcursor, libXi, libXext, libxcb, libXrender, libXfixes, libXinerama, libxkbcommon
|
Requires: freetype, cairo, pango, openssl, mesa-libEGL, mesa-libGL
|
||||||
Requires: fontconfig, freetype, cairo, pango, mesa-libEGL, mesa-libGL, xdg-utils
|
Requires: glibc >= 2.34
|
||||||
|
Requires: fontconfig >= 2.13.1
|
||||||
|
Requires: desktop-file-utils >= 0.26
|
||||||
|
Requires: xdg-utils >= 1.1.3
|
||||||
|
Requires: coreutils >= 8.32
|
||||||
|
Requires: bash >= 5.1
|
||||||
|
|
||||||
%description
|
%description
|
||||||
v2rayN Linux for Red Hat Enterprise Linux
|
v2rayN Linux for Red Hat Enterprise Linux
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project>
|
<Project>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>7.15.6</Version>
|
<Version>7.15.7</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@@ -9,16 +9,16 @@
|
|||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.8" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.8" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.8" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.3.8" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.8" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.8" />
|
||||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.3.8" />
|
<PackageVersion Include="ReactiveUI.Avalonia" Version="11.3.8" />
|
||||||
<PackageVersion Include="CliWrap" Version="3.9.0" />
|
<PackageVersion Include="CliWrap" Version="3.9.0" />
|
||||||
<PackageVersion Include="Downloader" Version="4.0.3" />
|
<PackageVersion Include="Downloader" Version="4.0.3" />
|
||||||
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.3.2" />
|
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.3.2" />
|
||||||
<PackageVersion Include="MaterialDesignThemes" Version="5.3.0" />
|
<PackageVersion Include="MaterialDesignThemes" Version="5.3.0" />
|
||||||
<PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" />
|
<PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" />
|
||||||
<PackageVersion Include="QRCoder" Version="1.7.0" />
|
<PackageVersion Include="QRCoder" Version="1.7.0" />
|
||||||
<PackageVersion Include="ReactiveUI" Version="20.4.1" />
|
<PackageVersion Include="ReactiveUI" Version="22.2.1" />
|
||||||
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
|
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||||
<PackageVersion Include="ReactiveUI.WPF" Version="20.4.1" />
|
<PackageVersion Include="ReactiveUI.WPF" Version="22.2.1" />
|
||||||
<PackageVersion Include="Semi.Avalonia" Version="11.3.7" />
|
<PackageVersion Include="Semi.Avalonia" Version="11.3.7" />
|
||||||
<PackageVersion Include="Semi.Avalonia.AvaloniaEdit" Version="11.2.0.1" />
|
<PackageVersion Include="Semi.Avalonia.AvaloniaEdit" Version="11.2.0.1" />
|
||||||
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.3.7" />
|
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.3.7" />
|
||||||
|
|||||||
@@ -35,9 +35,13 @@ public class JsonUtils
|
|||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="obj"></param>
|
/// <param name="obj"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static T DeepCopy<T>(T obj)
|
public static T? DeepCopy<T>(T? obj)
|
||||||
{
|
{
|
||||||
return Deserialize<T>(Serialize(obj, false))!;
|
if (obj is null)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
return Deserialize<T>(Serialize(obj, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -67,7 +71,7 @@ public class JsonUtils
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="strJson"></param>
|
/// <param name="strJson"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static JsonNode? ParseJson(string strJson)
|
public static JsonNode? ParseJson(string? strJson)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -116,7 +120,7 @@ public class JsonUtils
|
|||||||
/// <param name="obj"></param>
|
/// <param name="obj"></param>
|
||||||
/// <param name="options"></param>
|
/// <param name="options"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string Serialize(object? obj, JsonSerializerOptions options)
|
public static string Serialize(object? obj, JsonSerializerOptions? options)
|
||||||
{
|
{
|
||||||
var result = string.Empty;
|
var result = string.Empty;
|
||||||
try
|
try
|
||||||
@@ -125,7 +129,7 @@ public class JsonUtils
|
|||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = JsonSerializer.Serialize(obj, options);
|
result = JsonSerializer.Serialize(obj, options ?? _defaultSerializeOptions);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -424,7 +424,7 @@ public class Utils
|
|||||||
// Handle IPv6 addresses, e.g., "[2001:db8::1]:443"
|
// Handle IPv6 addresses, e.g., "[2001:db8::1]:443"
|
||||||
if (authority.StartsWith("[") && authority.Contains("]"))
|
if (authority.StartsWith("[") && authority.Contains("]"))
|
||||||
{
|
{
|
||||||
int closingBracketIndex = authority.LastIndexOf(']');
|
var closingBracketIndex = authority.LastIndexOf(']');
|
||||||
if (closingBracketIndex < authority.Length - 1 && authority[closingBracketIndex + 1] == ':')
|
if (closingBracketIndex < authority.Length - 1 && authority[closingBracketIndex + 1] == ':')
|
||||||
{
|
{
|
||||||
// Port exists
|
// Port exists
|
||||||
@@ -963,13 +963,13 @@ public class Utils
|
|||||||
|
|
||||||
#region Platform
|
#region Platform
|
||||||
|
|
||||||
public static bool IsWindows() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
public static bool IsWindows() => OperatingSystem.IsWindows();
|
||||||
|
|
||||||
public static bool IsLinux() => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
|
public static bool IsLinux() => OperatingSystem.IsLinux();
|
||||||
|
|
||||||
public static bool IsOSX() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
|
public static bool IsOSX() => OperatingSystem.IsMacOS();
|
||||||
|
|
||||||
public static bool IsNonWindows() => !RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
public static bool IsNonWindows() => !OperatingSystem.IsWindows();
|
||||||
|
|
||||||
public static string GetExeName(string name)
|
public static string GetExeName(string name)
|
||||||
{
|
{
|
||||||
@@ -994,11 +994,6 @@ public class Utils
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("APPIMAGE")))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var exePath = GetExePath();
|
var exePath = GetExePath();
|
||||||
var baseDir = string.IsNullOrEmpty(exePath) ? StartupPath() : Path.GetDirectoryName(exePath) ?? "";
|
var baseDir = string.IsNullOrEmpty(exePath) ? StartupPath() : Path.GetDirectoryName(exePath) ?? "";
|
||||||
var p = baseDir.Replace('\\', '/');
|
var p = baseDir.Replace('\\', '/');
|
||||||
@@ -1008,11 +1003,6 @@ public class Utils
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.Contains("/.mount_", StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p.StartsWith("/opt/v2rayN", StringComparison.OrdinalIgnoreCase))
|
if (p.StartsWith("/opt/v2rayN", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace ServiceLib.Common;
|
namespace ServiceLib.Common;
|
||||||
/*
|
/*
|
||||||
* See:
|
* See:
|
||||||
|
|||||||
@@ -427,6 +427,7 @@ public class Global
|
|||||||
"zh-Hant",
|
"zh-Hant",
|
||||||
"en",
|
"en",
|
||||||
"fa-Ir",
|
"fa-Ir",
|
||||||
|
"fr",
|
||||||
"ru",
|
"ru",
|
||||||
"hu"
|
"hu"
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -447,13 +447,13 @@ public static class ConfigHandler
|
|||||||
/// <returns>0 if successful, -1 if failed</returns>
|
/// <returns>0 if successful, -1 if failed</returns>
|
||||||
public static async Task<int> MoveServer(Config config, List<ProfileItem> lstProfile, int index, EMove eMove, int pos = -1)
|
public static async Task<int> MoveServer(Config config, List<ProfileItem> lstProfile, int index, EMove eMove, int pos = -1)
|
||||||
{
|
{
|
||||||
int count = lstProfile.Count;
|
var count = lstProfile.Count;
|
||||||
if (index < 0 || index > lstProfile.Count - 1)
|
if (index < 0 || index > lstProfile.Count - 1)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < lstProfile.Count; i++)
|
for (var i = 0; i < lstProfile.Count; i++)
|
||||||
{
|
{
|
||||||
ProfileExManager.Instance.SetSort(lstProfile[i].IndexId, (i + 1) * 10);
|
ProfileExManager.Instance.SetSort(lstProfile[i].IndexId, (i + 1) * 10);
|
||||||
}
|
}
|
||||||
@@ -527,7 +527,7 @@ public static class ConfigHandler
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
var ext = Path.GetExtension(fileName);
|
var ext = Path.GetExtension(fileName);
|
||||||
string newFileName = $"{Utils.GetGuid()}{ext}";
|
var newFileName = $"{Utils.GetGuid()}{ext}";
|
||||||
//newFileName = Path.Combine(Utile.GetTempPath(), newFileName);
|
//newFileName = Path.Combine(Utile.GetTempPath(), newFileName);
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -1356,7 +1356,7 @@ public static class ConfigHandler
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var profileItem = FmtHandler.ResolveConfig(str, out string msg);
|
var profileItem = FmtHandler.ResolveConfig(str, out var msg);
|
||||||
if (profileItem is null)
|
if (profileItem is null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -1440,7 +1440,7 @@ public static class ConfigHandler
|
|||||||
{
|
{
|
||||||
await RemoveServersViaSubid(config, subid, isSub);
|
await RemoveServersViaSubid(config, subid, isSub);
|
||||||
}
|
}
|
||||||
int count = 0;
|
var count = 0;
|
||||||
foreach (var it in lstProfiles)
|
foreach (var it in lstProfiles)
|
||||||
{
|
{
|
||||||
it.Subid = subid;
|
it.Subid = subid;
|
||||||
@@ -1530,7 +1530,7 @@ public static class ConfigHandler
|
|||||||
var lstSsServer = ShadowsocksFmt.ResolveSip008(strData);
|
var lstSsServer = ShadowsocksFmt.ResolveSip008(strData);
|
||||||
if (lstSsServer?.Count > 0)
|
if (lstSsServer?.Count > 0)
|
||||||
{
|
{
|
||||||
int counter = 0;
|
var counter = 0;
|
||||||
foreach (var ssItem in lstSsServer)
|
foreach (var ssItem in lstSsServer)
|
||||||
{
|
{
|
||||||
ssItem.Subid = subid;
|
ssItem.Subid = subid;
|
||||||
@@ -1705,7 +1705,7 @@ public static class ConfigHandler
|
|||||||
var maxSort = 0;
|
var maxSort = 0;
|
||||||
if (await SQLiteHelper.Instance.TableAsync<SubItem>().CountAsync() > 0)
|
if (await SQLiteHelper.Instance.TableAsync<SubItem>().CountAsync() > 0)
|
||||||
{
|
{
|
||||||
var lstSubs = (await AppManager.Instance.SubItems());
|
var lstSubs = await AppManager.Instance.SubItems();
|
||||||
maxSort = lstSubs.LastOrDefault()?.Sort ?? 0;
|
maxSort = lstSubs.LastOrDefault()?.Sort ?? 0;
|
||||||
}
|
}
|
||||||
item.Sort = maxSort + 1;
|
item.Sort = maxSort + 1;
|
||||||
@@ -1867,7 +1867,7 @@ public static class ConfigHandler
|
|||||||
/// <returns>0 if successful, -1 if failed</returns>
|
/// <returns>0 if successful, -1 if failed</returns>
|
||||||
public static async Task<int> MoveRoutingRule(List<RulesItem> rules, int index, EMove eMove, int pos = -1)
|
public static async Task<int> MoveRoutingRule(List<RulesItem> rules, int index, EMove eMove, int pos = -1)
|
||||||
{
|
{
|
||||||
int count = rules.Count;
|
var count = rules.Count;
|
||||||
if (index < 0 || index > rules.Count - 1)
|
if (index < 0 || index > rules.Count - 1)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public static class CoreConfigHandler
|
|||||||
File.Delete(fileName);
|
File.Delete(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
string addressFileName = node.Address;
|
var addressFileName = node.Address;
|
||||||
if (!File.Exists(addressFileName))
|
if (!File.Exists(addressFileName))
|
||||||
{
|
{
|
||||||
addressFileName = Utils.GetConfigPath(addressFileName);
|
addressFileName = Utils.GetConfigPath(addressFileName);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class FmtHandler
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string str = config.TrimEx();
|
var str = config.TrimEx();
|
||||||
if (str.IsNullOrEmpty())
|
if (str.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
msg = ResUI.FailedReadConfiguration;
|
msg = ResUI.FailedReadConfiguration;
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ public class Hysteria2Fmt : BaseFmt
|
|||||||
{
|
{
|
||||||
if (item == null)
|
if (item == null)
|
||||||
return null;
|
return null;
|
||||||
string url = string.Empty;
|
var url = string.Empty;
|
||||||
|
|
||||||
string remark = string.Empty;
|
var remark = string.Empty;
|
||||||
if (item.Remarks.IsNotEmpty())
|
if (item.Remarks.IsNotEmpty())
|
||||||
{
|
{
|
||||||
remark = "#" + Utils.UrlEncode(item.Remarks);
|
remark = "#" + Utils.UrlEncode(item.Remarks);
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class ActionPrecheckManager(Config config)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EConfigType.VLESS:
|
case EConfigType.VLESS:
|
||||||
if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id) && item.Id.Length > 30)
|
if (item.Id.IsNullOrEmpty() || (!Utils.IsGuidByParse(item.Id) && item.Id.Length > 30))
|
||||||
errors.Add(string.Format(ResUI.InvalidProperty, "Id"));
|
errors.Add(string.Format(ResUI.InvalidProperty, "Id"));
|
||||||
if (!Global.Flows.Contains(item.Flow))
|
if (!Global.Flows.Contains(item.Flow))
|
||||||
errors.Add(string.Format(ResUI.InvalidProperty, "Flow"));
|
errors.Add(string.Format(ResUI.InvalidProperty, "Flow"));
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class CoreAdminManager
|
|||||||
StringBuilder sb = new();
|
StringBuilder sb = new();
|
||||||
sb.AppendLine("#!/bin/bash");
|
sb.AppendLine("#!/bin/bash");
|
||||||
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
|
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
|
||||||
sb.AppendLine($"sudo -S {cmdLine}");
|
sb.AppendLine($"exec sudo -S -- {cmdLine}");
|
||||||
var shFilePath = await FileManager.CreateLinuxShellFile("run_as_sudo.sh", sb.ToString(), true);
|
var shFilePath = await FileManager.CreateLinuxShellFile("run_as_sudo.sh", sb.ToString(), true);
|
||||||
|
|
||||||
var procService = new ProcessService(
|
var procService = new ProcessService(
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class ProfileItem : ReactiveObject
|
|||||||
|
|
||||||
public string GetSummary()
|
public string GetSummary()
|
||||||
{
|
{
|
||||||
var summary = $"[{(ConfigType).ToString()}] ";
|
var summary = $"[{ConfigType.ToString()}] ";
|
||||||
if (IsComplex())
|
if (IsComplex())
|
||||||
{
|
{
|
||||||
summary += $"[{CoreType.ToString()}]{Remarks}";
|
summary += $"[{CoreType.ToString()}]{Remarks}";
|
||||||
|
|||||||
1599
v2rayN/ServiceLib/Resx/ResUI.fr.resx
Normal file
1599
v2rayN/ServiceLib/Resx/ResUI.fr.resx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -427,7 +427,7 @@
|
|||||||
<value>路由设置</value>
|
<value>路由设置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuServers" xml:space="preserve">
|
<data name="menuServers" xml:space="preserve">
|
||||||
<value>配置文件</value>
|
<value>配置项</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuSetting" xml:space="preserve">
|
<data name="menuSetting" xml:space="preserve">
|
||||||
<value>设置</value>
|
<value>设置</value>
|
||||||
|
|||||||
@@ -28,15 +28,15 @@ fi
|
|||||||
kill_children() {
|
kill_children() {
|
||||||
local parent=$1
|
local parent=$1
|
||||||
local children=$(ps -o pid --no-headers --ppid "$parent")
|
local children=$(ps -o pid --no-headers --ppid "$parent")
|
||||||
|
|
||||||
# Output information about processes being terminated
|
# Output information about processes being terminated
|
||||||
echo "Processing children of PID: $parent..."
|
echo "Processing children of PID: $parent..."
|
||||||
|
|
||||||
# Process each child
|
# Process each child
|
||||||
for child in $children; do
|
for child in $children; do
|
||||||
# Recursively find and kill child's children first
|
# Recursively find and kill child's children first
|
||||||
kill_children "$child"
|
kill_children "$child"
|
||||||
|
|
||||||
# Force kill the child process
|
# Force kill the child process
|
||||||
echo "Terminating child process: $child"
|
echo "Terminating child process: $child"
|
||||||
kill -9 "$child" 2>/dev/null || true
|
kill -9 "$child" 2>/dev/null || true
|
||||||
@@ -47,6 +47,18 @@ echo "============================================"
|
|||||||
echo "Starting termination of process $PID and all its children"
|
echo "Starting termination of process $PID and all its children"
|
||||||
echo "============================================"
|
echo "============================================"
|
||||||
|
|
||||||
|
# Try graceful termination first
|
||||||
|
echo "Attempting graceful termination (SIGTERM) of PID: $PID"
|
||||||
|
kill -15 "$PID" 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
# If still running, fall back to kill_children
|
||||||
|
if ps -p $PID > /dev/null; then
|
||||||
|
echo "Process $PID did not exit after SIGTERM; proceeding with forced termination of its children and itself"
|
||||||
|
else
|
||||||
|
echo "Process $PID exited cleanly after SIGTERM"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
# Find and kill all child processes
|
# Find and kill all child processes
|
||||||
kill_children "$PID"
|
kill_children "$PID"
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,20 @@ echo "============================================"
|
|||||||
echo "Starting termination of process $PID and all its descendants"
|
echo "Starting termination of process $PID and all its descendants"
|
||||||
echo "============================================"
|
echo "============================================"
|
||||||
|
|
||||||
|
# Try graceful termination first
|
||||||
|
echo "Attempting graceful termination (SIGTERM) of PID: $PID"
|
||||||
|
kill -15 "$PID" 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# If still running, fall back to kill_descendants
|
||||||
|
# Use the macOS-native 'kill -0' check
|
||||||
|
if kill -0 $PID 2>/dev/null; then
|
||||||
|
echo "Process $PID did not exit after SIGTERM; proceeding with forced termination of its descendants and itself"
|
||||||
|
else
|
||||||
|
echo "Process $PID exited cleanly after SIGTERM"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
# Find and kill all descendant processes
|
# Find and kill all descendant processes
|
||||||
kill_descendants "$PID"
|
kill_descendants "$PID"
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,9 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Update="Resx\ResUI.fr.resx">
|
||||||
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Update="Resx\ResUI.hu.resx">
|
<EmbeddedResource Update="Resx\ResUI.hu.resx">
|
||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
@@ -79,4 +82,4 @@
|
|||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -94,8 +94,8 @@ public partial class CoreConfigV2rayService(Config config)
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
string result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
||||||
string txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);
|
var txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);
|
||||||
if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty())
|
if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
@@ -200,8 +200,8 @@ public partial class CoreConfigV2rayService(Config config)
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
string result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
||||||
string txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);
|
var txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);
|
||||||
if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty())
|
if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public partial class CoreConfigV2rayService
|
|||||||
}
|
}
|
||||||
|
|
||||||
var customOutboundsNode = new JsonArray();
|
var customOutboundsNode = new JsonArray();
|
||||||
|
|
||||||
foreach (var outbound in v2rayConfig.outbounds)
|
foreach (var outbound in v2rayConfig.outbounds)
|
||||||
{
|
{
|
||||||
if (outbound.protocol.ToLower() is "blackhole" or "dns" or "freedom")
|
if (outbound.protocol.ToLower() is "blackhole" or "dns" or "freedom")
|
||||||
@@ -112,7 +112,7 @@ public partial class CoreConfigV2rayService
|
|||||||
}
|
}
|
||||||
customOutboundsNode.Add(JsonUtils.DeepCopy(outbound));
|
customOutboundsNode.Add(JsonUtils.DeepCopy(outbound));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fullConfigTemplateNode["outbounds"] is JsonArray templateOutbounds)
|
if (fullConfigTemplateNode["outbounds"] is JsonArray templateOutbounds)
|
||||||
{
|
{
|
||||||
foreach (var outbound in templateOutbounds)
|
foreach (var outbound in templateOutbounds)
|
||||||
@@ -120,7 +120,7 @@ public partial class CoreConfigV2rayService
|
|||||||
customOutboundsNode.Add(outbound?.DeepClone());
|
customOutboundsNode.Add(outbound?.DeepClone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fullConfigTemplateNode["outbounds"] = customOutboundsNode;
|
fullConfigTemplateNode["outbounds"] = customOutboundsNode;
|
||||||
|
|
||||||
return await Task.FromResult(JsonUtils.Serialize(fullConfigTemplateNode));
|
return await Task.FromResult(JsonUtils.Serialize(fullConfigTemplateNode));
|
||||||
|
|||||||
@@ -347,8 +347,8 @@ public partial class CoreConfigV2rayService
|
|||||||
if (obj is null)
|
if (obj is null)
|
||||||
{
|
{
|
||||||
List<string> servers = [];
|
List<string> servers = [];
|
||||||
string[] arrDNS = normalDNS.Split(',');
|
var arrDNS = normalDNS.Split(',');
|
||||||
foreach (string str in arrDNS)
|
foreach (var str in arrDNS)
|
||||||
{
|
{
|
||||||
servers.Add(str);
|
servers.Add(str);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public partial class CoreConfigV2rayService
|
|||||||
|
|
||||||
private Inbounds4Ray GetInbound(InItem inItem, EInboundProtocol protocol, bool bSocks)
|
private Inbounds4Ray GetInbound(InItem inItem, EInboundProtocol protocol, bool bSocks)
|
||||||
{
|
{
|
||||||
string result = EmbedUtils.GetEmbedText(Global.V2raySampleInbound);
|
var result = EmbedUtils.GetEmbedText(Global.V2raySampleInbound);
|
||||||
if (result.IsNullOrEmpty())
|
if (result.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
return new();
|
return new();
|
||||||
|
|||||||
@@ -453,16 +453,16 @@ public partial class CoreConfigV2rayService
|
|||||||
};
|
};
|
||||||
|
|
||||||
//request Host
|
//request Host
|
||||||
string request = EmbedUtils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
|
var request = EmbedUtils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
|
||||||
string[] arrHost = host.Split(',');
|
var arrHost = host.Split(',');
|
||||||
string host2 = string.Join(",".AppendQuotes(), arrHost);
|
var host2 = string.Join(",".AppendQuotes(), arrHost);
|
||||||
request = request.Replace("$requestHost$", $"{host2.AppendQuotes()}");
|
request = request.Replace("$requestHost$", $"{host2.AppendQuotes()}");
|
||||||
request = request.Replace("$requestUserAgent$", $"{useragent.AppendQuotes()}");
|
request = request.Replace("$requestUserAgent$", $"{useragent.AppendQuotes()}");
|
||||||
//Path
|
//Path
|
||||||
string pathHttp = @"/";
|
var pathHttp = @"/";
|
||||||
if (path.IsNotEmpty())
|
if (path.IsNotEmpty())
|
||||||
{
|
{
|
||||||
string[] arrPath = path.Split(',');
|
var 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()}");
|
||||||
@@ -623,10 +623,10 @@ public partial class CoreConfigV2rayService
|
|||||||
// Cache for chain proxies to avoid duplicate generation
|
// Cache for chain proxies to avoid duplicate generation
|
||||||
var nextProxyCache = new Dictionary<string, Outbounds4Ray?>();
|
var nextProxyCache = new Dictionary<string, Outbounds4Ray?>();
|
||||||
var prevProxyTags = new Dictionary<string, string?>(); // Map from profile name to tag
|
var prevProxyTags = new Dictionary<string, string?>(); // Map from profile name to tag
|
||||||
int prevIndex = 0; // Index for prev outbounds
|
var prevIndex = 0; // Index for prev outbounds
|
||||||
|
|
||||||
// Process nodes
|
// Process nodes
|
||||||
int index = 0;
|
var index = 0;
|
||||||
foreach (var node in nodes)
|
foreach (var node in nodes)
|
||||||
{
|
{
|
||||||
index++;
|
index++;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ public partial class CoreConfigV2rayService
|
|||||||
{
|
{
|
||||||
if (_config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)
|
if (_config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)
|
||||||
{
|
{
|
||||||
string tag = EInboundProtocol.api.ToString();
|
var tag = EInboundProtocol.api.ToString();
|
||||||
Metrics4Ray apiObj = new();
|
Metrics4Ray apiObj = new();
|
||||||
Policy4Ray policyObj = new();
|
Policy4Ray policyObj = new();
|
||||||
SystemPolicy4Ray policySystemSetting = new();
|
SystemPolicy4Ray policySystemSetting = new();
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ public class UpdateService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(type);
|
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(type);
|
||||||
string filePath = string.Empty;
|
var filePath = string.Empty;
|
||||||
foreach (var name in coreInfo.CoreExes)
|
foreach (var name in coreInfo.CoreExes)
|
||||||
{
|
{
|
||||||
var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());
|
var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());
|
||||||
@@ -180,14 +180,14 @@ public class UpdateService
|
|||||||
|
|
||||||
if (!File.Exists(filePath))
|
if (!File.Exists(filePath))
|
||||||
{
|
{
|
||||||
string msg = string.Format(ResUI.NotFoundCore, @"", "", "");
|
var msg = string.Format(ResUI.NotFoundCore, @"", "", "");
|
||||||
//ShowMsg(true, msg);
|
//ShowMsg(true, msg);
|
||||||
return new SemanticVersion("");
|
return new SemanticVersion("");
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await Utils.GetCliWrapOutput(filePath, coreInfo.VersionArg);
|
var result = await Utils.GetCliWrapOutput(filePath, coreInfo.VersionArg);
|
||||||
var echo = result ?? "";
|
var echo = result ?? "";
|
||||||
string version = string.Empty;
|
var version = string.Empty;
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ECoreType.v2fly:
|
case ECoreType.v2fly:
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ public class ClashProxiesViewModel : MyReactiveObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
//from api
|
//from api
|
||||||
foreach (KeyValuePair<string, ProxiesItem> kv in _proxies)
|
foreach (var kv in _proxies)
|
||||||
{
|
{
|
||||||
if (!Global.allowSelectType.Contains(kv.Value.type.ToLower()))
|
if (!Global.allowSelectType.Contains(kv.Value.type.ToLower()))
|
||||||
{
|
{
|
||||||
@@ -319,7 +319,7 @@ public class ClashProxiesViewModel : MyReactiveObject
|
|||||||
//from providers
|
//from providers
|
||||||
if (_providers != null)
|
if (_providers != null)
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<string, ProvidersItem> kv in _providers)
|
foreach (var kv in _providers)
|
||||||
{
|
{
|
||||||
if (Global.proxyVehicleType.Contains(kv.Value.vehicleType.ToLower()))
|
if (Global.proxyVehicleType.Contains(kv.Value.vehicleType.ToLower()))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -273,12 +273,12 @@ public class OptionSettingViewModel : MyReactiveObject
|
|||||||
NoticeManager.Instance.Enqueue(ResUI.FillLocalListeningPort);
|
NoticeManager.Instance.Enqueue(ResUI.FillLocalListeningPort);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var needReboot = (EnableStatistics != _config.GuiItem.EnableStatistics
|
var needReboot = EnableStatistics != _config.GuiItem.EnableStatistics
|
||||||
|| DisplayRealTimeSpeed != _config.GuiItem.DisplayRealTimeSpeed
|
|| DisplayRealTimeSpeed != _config.GuiItem.DisplayRealTimeSpeed
|
||||||
|| EnableDragDropSort != _config.UiItem.EnableDragDropSort
|
|| EnableDragDropSort != _config.UiItem.EnableDragDropSort
|
||||||
|| EnableHWA != _config.GuiItem.EnableHWA
|
|| EnableHWA != _config.GuiItem.EnableHWA
|
||||||
|| CurrentFontFamily != _config.UiItem.CurrentFontFamily
|
|| CurrentFontFamily != _config.UiItem.CurrentFontFamily
|
||||||
|| MainGirdOrientation != (int)_config.UiItem.MainGirdOrientation);
|
|| MainGirdOrientation != (int)_config.UiItem.MainGirdOrientation;
|
||||||
|
|
||||||
//if (Utile.IsNullOrEmpty(Kcpmtu.ToString()) || !Utile.IsNumeric(Kcpmtu.ToString())
|
//if (Utile.IsNullOrEmpty(Kcpmtu.ToString()) || !Utile.IsNumeric(Kcpmtu.ToString())
|
||||||
// || Utile.IsNullOrEmpty(Kcptti.ToString()) || !Utile.IsNumeric(Kcptti.ToString())
|
// || Utile.IsNullOrEmpty(Kcptti.ToString()) || !Utile.IsNumeric(Kcptti.ToString())
|
||||||
@@ -375,7 +375,7 @@ public class OptionSettingViewModel : MyReactiveObject
|
|||||||
|
|
||||||
private async Task SaveCoreType()
|
private async Task SaveCoreType()
|
||||||
{
|
{
|
||||||
for (int k = 1; k <= _config.CoreTypeItem.Count; k++)
|
for (var k = 1; k <= _config.CoreTypeItem.Count; k++)
|
||||||
{
|
{
|
||||||
var item = _config.CoreTypeItem[k - 1];
|
var item = _config.CoreTypeItem[k - 1];
|
||||||
var type = string.Empty;
|
var type = string.Empty;
|
||||||
|
|||||||
@@ -658,7 +658,7 @@ public class ProfilesViewModel : MyReactiveObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
_dicHeaderSort.TryAdd(colName, true);
|
_dicHeaderSort.TryAdd(colName, true);
|
||||||
_dicHeaderSort.TryGetValue(colName, out bool asc);
|
_dicHeaderSort.TryGetValue(colName, out var asc);
|
||||||
if (await ConfigHandler.SortServers(_config, _config.SubIndexId, colName, asc) != 0)
|
if (await ConfigHandler.SortServers(_config, _config.SubIndexId, colName, asc) != 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ public class RoutingRuleSettingViewModel : MyReactiveObject
|
|||||||
|
|
||||||
private async Task SaveRoutingAsync()
|
private async Task SaveRoutingAsync()
|
||||||
{
|
{
|
||||||
string remarks = SelectedRouting.Remarks;
|
var remarks = SelectedRouting.Remarks;
|
||||||
if (remarks.IsNullOrEmpty())
|
if (remarks.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
NoticeManager.Instance.Enqueue(ResUI.PleaseFillRemarks);
|
NoticeManager.Instance.Enqueue(ResUI.PleaseFillRemarks);
|
||||||
@@ -286,7 +286,7 @@ public class RoutingRuleSettingViewModel : MyReactiveObject
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadService downloadHandle = new DownloadService();
|
var downloadHandle = new DownloadService();
|
||||||
var result = await downloadHandle.TryDownloadString(url, true, "");
|
var result = await downloadHandle.TryDownloadString(url, true, "");
|
||||||
var ret = await AddBatchRoutingRulesAsync(SelectedRouting, result);
|
var ret = await AddBatchRoutingRulesAsync(SelectedRouting, result);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
@@ -298,7 +298,7 @@ public class RoutingRuleSettingViewModel : MyReactiveObject
|
|||||||
|
|
||||||
private async Task<int> AddBatchRoutingRulesAsync(RoutingItem routingItem, string? clipboardData)
|
private async Task<int> AddBatchRoutingRulesAsync(RoutingItem routingItem, string? clipboardData)
|
||||||
{
|
{
|
||||||
bool blReplace = false;
|
var blReplace = false;
|
||||||
if (await _updateView?.Invoke(EViewAction.AddBatchRoutingRulesYesNo, null) == false)
|
if (await _updateView?.Invoke(EViewAction.AddBatchRoutingRulesYesNo, null) == false)
|
||||||
{
|
{
|
||||||
blReplace = true;
|
blReplace = true;
|
||||||
|
|||||||
@@ -313,10 +313,10 @@ public class StatusBarViewModel : MyReactiveObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
BlServers = true;
|
BlServers = true;
|
||||||
for (int k = 0; k < lstModel.Count; k++)
|
for (var k = 0; k < lstModel.Count; k++)
|
||||||
{
|
{
|
||||||
ProfileItem it = lstModel[k];
|
ProfileItem it = lstModel[k];
|
||||||
string name = it.GetSummary();
|
var name = it.GetSummary();
|
||||||
|
|
||||||
var item = new ComboItem() { ID = it.IndexId, Text = name };
|
var item = new ComboItem() { ID = it.IndexId, Text = name };
|
||||||
Servers.Add(item);
|
Servers.Add(item);
|
||||||
@@ -394,10 +394,10 @@ public class StatusBarViewModel : MyReactiveObject
|
|||||||
{
|
{
|
||||||
await SysProxyHandler.UpdateSysProxy(_config, false);
|
await SysProxyHandler.UpdateSysProxy(_config, false);
|
||||||
|
|
||||||
BlSystemProxyClear = (type == ESysProxyType.ForcedClear);
|
BlSystemProxyClear = type == ESysProxyType.ForcedClear;
|
||||||
BlSystemProxySet = (type == ESysProxyType.ForcedChange);
|
BlSystemProxySet = type == ESysProxyType.ForcedChange;
|
||||||
BlSystemProxyNothing = (type == ESysProxyType.Unchanged);
|
BlSystemProxyNothing = type == ESysProxyType.Unchanged;
|
||||||
BlSystemProxyPac = (type == ESysProxyType.Pac);
|
BlSystemProxyPac = type == ESysProxyType.Pac;
|
||||||
|
|
||||||
if (blChange)
|
if (blChange)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,15 +10,17 @@ public partial class App : Application
|
|||||||
|
|
||||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||||
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
|
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
|
||||||
|
|
||||||
DataContext = StatusBarViewModel.Instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnFrameworkInitializationCompleted()
|
public override void OnFrameworkInitializationCompleted()
|
||||||
{
|
{
|
||||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
{
|
{
|
||||||
AppManager.Instance.InitComponents();
|
if (!Design.IsDesignMode)
|
||||||
|
{
|
||||||
|
AppManager.Instance.InitComponents();
|
||||||
|
DataContext = StatusBarViewModel.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
desktop.Exit += OnExit;
|
desktop.Exit += OnExit;
|
||||||
desktop.MainWindow = new MainWindow();
|
desktop.MainWindow = new MainWindow();
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ global using System.Collections.Generic;
|
|||||||
global using System.Globalization;
|
global using System.Globalization;
|
||||||
global using System.IO;
|
global using System.IO;
|
||||||
global using System.Linq;
|
global using System.Linq;
|
||||||
global using System.Reactive.Disposables;
|
global using System.Reactive.Disposables.Fluent;
|
||||||
global using System.Reactive.Linq;
|
global using System.Reactive.Linq;
|
||||||
global using System.Text;
|
global using System.Text;
|
||||||
global using System.Threading;
|
global using System.Threading;
|
||||||
@@ -17,13 +17,13 @@ global using Avalonia.Markup.Xaml;
|
|||||||
global using Avalonia.Media;
|
global using Avalonia.Media;
|
||||||
global using Avalonia.Media.Imaging;
|
global using Avalonia.Media.Imaging;
|
||||||
global using Avalonia.Platform;
|
global using Avalonia.Platform;
|
||||||
global using Avalonia.ReactiveUI;
|
|
||||||
global using Avalonia.Styling;
|
global using Avalonia.Styling;
|
||||||
global using Avalonia.Threading;
|
global using Avalonia.Threading;
|
||||||
global using ReactiveUI;
|
|
||||||
global using ReactiveUI.Fody.Helpers;
|
|
||||||
global using DynamicData;
|
global using DynamicData;
|
||||||
global using MsBox.Avalonia.Enums;
|
global using MsBox.Avalonia.Enums;
|
||||||
|
global using ReactiveUI;
|
||||||
|
global using ReactiveUI.Avalonia;
|
||||||
|
global using ReactiveUI.Fody.Helpers;
|
||||||
global using ServiceLib;
|
global using ServiceLib;
|
||||||
global using ServiceLib.Base;
|
global using ServiceLib.Base;
|
||||||
global using ServiceLib.Common;
|
global using ServiceLib.Common;
|
||||||
|
|||||||
@@ -54,12 +54,19 @@ internal class Program
|
|||||||
// Avalonia configuration, don't remove; also used by visual designer.
|
// Avalonia configuration, don't remove; also used by visual designer.
|
||||||
public static AppBuilder BuildAvaloniaApp()
|
public static AppBuilder BuildAvaloniaApp()
|
||||||
{
|
{
|
||||||
return AppBuilder.Configure<App>()
|
var builder = AppBuilder.Configure<App>()
|
||||||
.UsePlatformDetect()
|
.UsePlatformDetect()
|
||||||
//.WithInterFont()
|
//.WithInterFont()
|
||||||
.WithFontByDefault()
|
.WithFontByDefault()
|
||||||
.LogToTrace()
|
.LogToTrace()
|
||||||
.UseReactiveUI()
|
.UseReactiveUI();
|
||||||
.With(new MacOSPlatformOptions { ShowInDock = AppManager.Instance.Config.UiItem.MacOSShowInDock });
|
|
||||||
|
if (OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
var showInDock = Design.IsDesignMode || AppManager.Instance.Config.UiItem.MacOSShowInDock;
|
||||||
|
builder = builder.With(new MacOSPlatformOptions { ShowInDock = showInDock });
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
btnCancel.Click += (s, e) => this.Close();
|
btnCancel.Click += (s, e) => Close();
|
||||||
lstChild.SelectionChanged += LstChild_SelectionChanged;
|
lstChild.SelectionChanged += LstChild_SelectionChanged;
|
||||||
|
|
||||||
ViewModel = new AddGroupServerViewModel(profileItem, UpdateViewHandler);
|
ViewModel = new AddGroupServerViewModel(profileItem, UpdateViewHandler);
|
||||||
@@ -32,11 +32,11 @@ public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
|
|||||||
switch (profileItem.ConfigType)
|
switch (profileItem.ConfigType)
|
||||||
{
|
{
|
||||||
case EConfigType.PolicyGroup:
|
case EConfigType.PolicyGroup:
|
||||||
this.Title = ResUI.TbConfigTypePolicyGroup;
|
Title = ResUI.TbConfigTypePolicyGroup;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EConfigType.ProxyChain:
|
case EConfigType.ProxyChain:
|
||||||
this.Title = ResUI.TbConfigTypeProxyChain;
|
Title = ResUI.TbConfigTypeProxyChain;
|
||||||
gridPolicyGroup.IsVisible = false;
|
gridPolicyGroup.IsVisible = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
|
|||||||
menuSelectAllChild.Click += (s, e) => lstChild.SelectAll();
|
menuSelectAllChild.Click += (s, e) => lstChild.SelectAll();
|
||||||
|
|
||||||
// Keyboard shortcuts when focus is within grid
|
// Keyboard shortcuts when focus is within grid
|
||||||
this.AddHandler(KeyDownEvent, AddGroupServerWindow_KeyDown, RoutingStrategies.Tunnel);
|
AddHandler(KeyDownEvent, AddGroupServerWindow_KeyDown, RoutingStrategies.Tunnel);
|
||||||
lstChild.LoadingRow += LstChild_LoadingRow;
|
lstChild.LoadingRow += LstChild_LoadingRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
Close(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ public partial class AddServer2Window : WindowBase<AddServer2ViewModel>
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
btnCancel.Click += (s, e) => this.Close();
|
btnCancel.Click += (s, e) => Close();
|
||||||
ViewModel = new AddServer2ViewModel(profileItem, UpdateViewHandler);
|
ViewModel = new AddServer2ViewModel(profileItem, UpdateViewHandler);
|
||||||
|
|
||||||
cmbCoreType.ItemsSource = Utils.GetEnumNames<ECoreType>().Where(t => t != ECoreType.v2rayN.ToString()).ToList().AppendEmpty();
|
cmbCoreType.ItemsSource = Utils.GetEnumNames<ECoreType>().Where(t => t != ECoreType.v2rayN.ToString()).ToList().AppendEmpty();
|
||||||
@@ -39,7 +39,7 @@ public partial class AddServer2Window : WindowBase<AddServer2ViewModel>
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
Close(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.BrowseServer:
|
case EViewAction.BrowseServer:
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
btnCancel.Click += (s, e) => this.Close();
|
btnCancel.Click += (s, e) => Close();
|
||||||
cmbNetwork.SelectionChanged += CmbNetwork_SelectionChanged;
|
cmbNetwork.SelectionChanged += CmbNetwork_SelectionChanged;
|
||||||
cmbStreamSecurity.SelectionChanged += CmbStreamSecurity_SelectionChanged;
|
cmbStreamSecurity.SelectionChanged += CmbStreamSecurity_SelectionChanged;
|
||||||
btnGUID.Click += btnGUID_Click;
|
btnGUID.Click += btnGUID_Click;
|
||||||
@@ -196,7 +196,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
|||||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Title = $"{profileItem.ConfigType}";
|
Title = $"{profileItem.ConfigType}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
@@ -204,7 +204,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
Close(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ public partial class ClashProxiesView : ReactiveUserControl<ClashProxiesViewMode
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
ViewModel = new ClashProxiesViewModel(UpdateViewHandler);
|
ViewModel = new ClashProxiesViewModel(UpdateViewHandler);
|
||||||
lstProxyDetails.DoubleTapped += LstProxyDetails_DoubleTapped;
|
lstProxyDetails.DoubleTapped += LstProxyDetails_DoubleTapped;
|
||||||
this.KeyDown += ClashProxiesView_KeyDown;
|
KeyDown += ClashProxiesView_KeyDown;
|
||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public partial class DNSSettingWindow : WindowBase<DNSSettingViewModel>
|
|||||||
|
|
||||||
_config = AppManager.Instance.Config;
|
_config = AppManager.Instance.Config;
|
||||||
Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
btnCancel.Click += (s, e) => this.Close();
|
btnCancel.Click += (s, e) => Close();
|
||||||
ViewModel = new DNSSettingViewModel(UpdateViewHandler);
|
ViewModel = new DNSSettingViewModel(UpdateViewHandler);
|
||||||
|
|
||||||
cmbRayFreedomDNSStrategy.ItemsSource = Global.DomainStrategy4Freedoms;
|
cmbRayFreedomDNSStrategy.ItemsSource = Global.DomainStrategy4Freedoms;
|
||||||
@@ -77,7 +77,7 @@ public partial class DNSSettingWindow : WindowBase<DNSSettingViewModel>
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
Close(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public partial class FullConfigTemplateWindow : WindowBase<FullConfigTemplateVie
|
|||||||
|
|
||||||
_config = AppManager.Instance.Config;
|
_config = AppManager.Instance.Config;
|
||||||
Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
btnCancel.Click += (s, e) => this.Close();
|
btnCancel.Click += (s, e) => Close();
|
||||||
ViewModel = new FullConfigTemplateViewModel(UpdateViewHandler);
|
ViewModel = new FullConfigTemplateViewModel(UpdateViewHandler);
|
||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
@@ -36,7 +36,7 @@ public partial class FullConfigTemplateWindow : WindowBase<FullConfigTemplateVie
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
Close(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ public partial class GlobalHotkeySettingWindow : WindowBase<GlobalHotkeySettingV
|
|||||||
|
|
||||||
HotkeyManager.Instance.IsPause = true;
|
HotkeyManager.Instance.IsPause = true;
|
||||||
Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
this.Closing += (s, e) => HotkeyManager.Instance.IsPause = false;
|
Closing += (s, e) => HotkeyManager.Instance.IsPause = false;
|
||||||
btnCancel.Click += (s, e) => this.Close();
|
btnCancel.Click += (s, e) => Close();
|
||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
@@ -34,7 +34,7 @@ public partial class GlobalHotkeySettingWindow : WindowBase<GlobalHotkeySettingV
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
Close(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
|||||||
_config = AppManager.Instance.Config;
|
_config = AppManager.Instance.Config;
|
||||||
_manager = new WindowNotificationManager(TopLevel.GetTopLevel(this)) { MaxItems = 3, Position = NotificationPosition.TopRight };
|
_manager = new WindowNotificationManager(TopLevel.GetTopLevel(this)) { MaxItems = 3, Position = NotificationPosition.TopRight };
|
||||||
|
|
||||||
this.KeyDown += MainWindow_KeyDown;
|
KeyDown += MainWindow_KeyDown;
|
||||||
menuSettingsSetUWP.Click += menuSettingsSetUWP_Click;
|
menuSettingsSetUWP.Click += menuSettingsSetUWP_Click;
|
||||||
menuPromotion.Click += menuPromotion_Click;
|
menuPromotion.Click += menuPromotion_Click;
|
||||||
menuCheckUpdate.Click += MenuCheckUpdate_Click;
|
menuCheckUpdate.Click += MenuCheckUpdate_Click;
|
||||||
@@ -153,14 +153,14 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
|||||||
|
|
||||||
if (Utils.IsWindows())
|
if (Utils.IsWindows())
|
||||||
{
|
{
|
||||||
this.Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
|
Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
|
||||||
|
|
||||||
ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);
|
ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);
|
||||||
HotkeyManager.Instance.Init(_config, OnHotkeyHandler);
|
HotkeyManager.Instance.Init(_config, OnHotkeyHandler);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.Title = $"{Utils.GetVersion()}";
|
Title = $"{Utils.GetVersion()}";
|
||||||
|
|
||||||
menuRebootAsAdmin.IsVisible = false;
|
menuRebootAsAdmin.IsVisible = false;
|
||||||
menuSettingsSetUWP.IsVisible = false;
|
menuSettingsSetUWP.IsVisible = false;
|
||||||
@@ -168,9 +168,9 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
|||||||
}
|
}
|
||||||
menuAddServerViaScan.IsVisible = false;
|
menuAddServerViaScan.IsVisible = false;
|
||||||
|
|
||||||
if (_config.UiItem.AutoHideStartup)
|
if (_config.UiItem.AutoHideStartup && Utils.IsWindows())
|
||||||
{
|
{
|
||||||
this.WindowState = WindowState.Minimized;
|
WindowState = WindowState.Minimized;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddHelpMenuItem();
|
AddHelpMenuItem();
|
||||||
@@ -402,32 +402,32 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
|||||||
public void ShowHideWindow(bool? blShow)
|
public void ShowHideWindow(bool? blShow)
|
||||||
{
|
{
|
||||||
var bl = blShow ??
|
var bl = blShow ??
|
||||||
Utils.IsLinux()
|
(Utils.IsLinux()
|
||||||
? (!_config.UiItem.ShowInTaskbar ^ (WindowState == WindowState.Minimized))
|
? (!_config.UiItem.ShowInTaskbar ^ (WindowState == WindowState.Minimized))
|
||||||
: !_config.UiItem.ShowInTaskbar;
|
: !_config.UiItem.ShowInTaskbar);
|
||||||
if (bl)
|
if (bl)
|
||||||
{
|
{
|
||||||
this.Show();
|
Show();
|
||||||
if (this.WindowState == WindowState.Minimized)
|
if (WindowState == WindowState.Minimized)
|
||||||
{
|
{
|
||||||
this.WindowState = WindowState.Normal;
|
WindowState = WindowState.Normal;
|
||||||
}
|
}
|
||||||
this.Activate();
|
Activate();
|
||||||
this.Focus();
|
Focus();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Utils.IsLinux() && _config.UiItem.Hide2TrayWhenClose == false)
|
if (Utils.IsLinux() && _config.UiItem.Hide2TrayWhenClose == false)
|
||||||
{
|
{
|
||||||
this.WindowState = WindowState.Minimized;
|
WindowState = WindowState.Minimized;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var ownedWindow in this.OwnedWindows)
|
foreach (var ownedWindow in OwnedWindows)
|
||||||
{
|
{
|
||||||
ownedWindow.Close();
|
ownedWindow.Close();
|
||||||
}
|
}
|
||||||
this.Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
_config.UiItem.ShowInTaskbar = bl;
|
_config.UiItem.ShowInTaskbar = bl;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
btnCancel.Click += (s, e) => this.Close();
|
btnCancel.Click += (s, e) => Close();
|
||||||
_config = AppManager.Instance.Config;
|
_config = AppManager.Instance.Config;
|
||||||
|
|
||||||
ViewModel = new OptionSettingViewModel(UpdateViewHandler);
|
ViewModel = new OptionSettingViewModel(UpdateViewHandler);
|
||||||
@@ -153,7 +153,7 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
Close(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.InitSettingFont:
|
case EViewAction.InitSettingFont:
|
||||||
|
|||||||
@@ -75,6 +75,15 @@
|
|||||||
<PathIcon Data="{StaticResource SemiIconBolt}" />
|
<PathIcon Data="{StaticResource SemiIconBolt}" />
|
||||||
</Button.Content>
|
</Button.Content>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
x:Name="menuMixedTestServer"
|
||||||
|
Margin="{StaticResource MarginLr4}"
|
||||||
|
Classes="IconButton Success"
|
||||||
|
ToolTip.Tip="{x:Static resx:ResUI.menuMixedTestServer}">
|
||||||
|
<Button.Content>
|
||||||
|
<PathIcon Data="{StaticResource building_ping}" />
|
||||||
|
</Button.Content>
|
||||||
|
</Button>
|
||||||
|
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
<DataGrid
|
<DataGrid
|
||||||
@@ -99,15 +108,12 @@
|
|||||||
<MenuItem x:Name="menuCopyServer" Header="{x:Static resx:ResUI.menuCopyServer}" />
|
<MenuItem x:Name="menuCopyServer" Header="{x:Static resx:ResUI.menuCopyServer}" />
|
||||||
<MenuItem x:Name="menuRemoveServer" Header="{x:Static resx:ResUI.menuRemoveServer}" />
|
<MenuItem x:Name="menuRemoveServer" Header="{x:Static resx:ResUI.menuRemoveServer}" />
|
||||||
<MenuItem x:Name="menuRemoveDuplicateServer" Header="{x:Static resx:ResUI.menuRemoveDuplicateServer}" />
|
<MenuItem x:Name="menuRemoveDuplicateServer" Header="{x:Static resx:ResUI.menuRemoveDuplicateServer}" />
|
||||||
|
<MenuItem x:Name="menuRemoveInvalidServerResult" Header="{x:Static resx:ResUI.menuRemoveInvalidServerResult}" />
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem x:Name="menuMixedTestServer" Header="{x:Static resx:ResUI.menuMixedTestServer}" />
|
|
||||||
<MenuItem x:Name="menuTcpingServer" Header="{x:Static resx:ResUI.menuTcpingServer}" />
|
<MenuItem x:Name="menuTcpingServer" Header="{x:Static resx:ResUI.menuTcpingServer}" />
|
||||||
<MenuItem x:Name="menuRealPingServer" Header="{x:Static resx:ResUI.menuRealPingServer}" />
|
<MenuItem x:Name="menuRealPingServer" Header="{x:Static resx:ResUI.menuRealPingServer}" />
|
||||||
<MenuItem x:Name="menuSpeedServer" Header="{x:Static resx:ResUI.menuSpeedServer}" />
|
<MenuItem x:Name="menuSpeedServer" Header="{x:Static resx:ResUI.menuSpeedServer}" />
|
||||||
<MenuItem Header="{x:Static resx:ResUI.menuTestServerResult}">
|
<MenuItem x:Name="menuSortServerResult" Header="{x:Static resx:ResUI.menuSortServerResult}" />
|
||||||
<MenuItem x:Name="menuSortServerResult" Header="{x:Static resx:ResUI.menuSortServerResult}" />
|
|
||||||
<MenuItem x:Name="menuRemoveInvalidServerResult" Header="{x:Static resx:ResUI.menuRemoveInvalidServerResult}" />
|
|
||||||
</MenuItem>
|
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem x:Name="menuMoveToGroup" Header="{x:Static resx:ResUI.menuMoveToGroup}">
|
<MenuItem x:Name="menuMoveToGroup" Header="{x:Static resx:ResUI.menuMoveToGroup}">
|
||||||
<MenuItem>
|
<MenuItem>
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ public partial class RoutingRuleDetailsWindow : WindowBase<RoutingRuleDetailsVie
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
btnCancel.Click += (s, e) => this.Close();
|
btnCancel.Click += (s, e) => Close();
|
||||||
clbProtocol.SelectionChanged += ClbProtocol_SelectionChanged;
|
clbProtocol.SelectionChanged += ClbProtocol_SelectionChanged;
|
||||||
clbInboundTag.SelectionChanged += ClbInboundTag_SelectionChanged;
|
clbInboundTag.SelectionChanged += ClbInboundTag_SelectionChanged;
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ public partial class RoutingRuleDetailsWindow : WindowBase<RoutingRuleDetailsVie
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
Close(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ public partial class RoutingRuleSettingWindow : WindowBase<RoutingRuleSettingVie
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
btnCancel.Click += (s, e) => this.Close();
|
btnCancel.Click += (s, e) => Close();
|
||||||
this.KeyDown += RoutingRuleSettingWindow_KeyDown;
|
KeyDown += RoutingRuleSettingWindow_KeyDown;
|
||||||
lstRules.SelectionChanged += lstRules_SelectionChanged;
|
lstRules.SelectionChanged += lstRules_SelectionChanged;
|
||||||
lstRules.DoubleTapped += LstRules_DoubleTapped;
|
lstRules.DoubleTapped += LstRules_DoubleTapped;
|
||||||
menuRuleSelectAll.Click += menuRuleSelectAll_Click;
|
menuRuleSelectAll.Click += menuRuleSelectAll_Click;
|
||||||
@@ -64,7 +64,7 @@ public partial class RoutingRuleSettingWindow : WindowBase<RoutingRuleSettingVie
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
Close(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.ShowYesNo:
|
case EViewAction.ShowYesNo:
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ public partial class RoutingSettingWindow : WindowBase<RoutingSettingViewModel>
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
this.Closing += RoutingSettingWindow_Closing;
|
Closing += RoutingSettingWindow_Closing;
|
||||||
btnCancel.Click += (s, e) => this.Close();
|
btnCancel.Click += (s, e) => Close();
|
||||||
this.KeyDown += RoutingSettingWindow_KeyDown;
|
KeyDown += RoutingSettingWindow_KeyDown;
|
||||||
lstRoutings.SelectionChanged += lstRoutings_SelectionChanged;
|
lstRoutings.SelectionChanged += lstRoutings_SelectionChanged;
|
||||||
lstRoutings.DoubleTapped += LstRoutings_DoubleTapped;
|
lstRoutings.DoubleTapped += LstRoutings_DoubleTapped;
|
||||||
menuRoutingAdvancedSelectAll.Click += menuRoutingAdvancedSelectAll_Click;
|
menuRoutingAdvancedSelectAll.Click += menuRoutingAdvancedSelectAll_Click;
|
||||||
@@ -48,7 +48,7 @@ public partial class RoutingSettingWindow : WindowBase<RoutingSettingViewModel>
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
Close(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.ShowYesNo:
|
case EViewAction.ShowYesNo:
|
||||||
@@ -116,7 +116,7 @@ public partial class RoutingSettingWindow : WindowBase<RoutingSettingViewModel>
|
|||||||
private void btnCancel_Click(object? sender, RoutedEventArgs e)
|
private void btnCancel_Click(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
_manualClose = true;
|
_manualClose = true;
|
||||||
this.Close(ViewModel?.IsModified);
|
Close(ViewModel?.IsModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RoutingSettingWindow_Closing(object? sender, WindowClosingEventArgs e)
|
private void RoutingSettingWindow_Closing(object? sender, WindowClosingEventArgs e)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public partial class SubEditWindow : WindowBase<SubEditViewModel>
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
btnCancel.Click += (s, e) => this.Close();
|
btnCancel.Click += (s, e) => Close();
|
||||||
|
|
||||||
ViewModel = new SubEditViewModel(subItem, UpdateViewHandler);
|
ViewModel = new SubEditViewModel(subItem, UpdateViewHandler);
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ public partial class SubEditWindow : WindowBase<SubEditViewModel>
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
Close(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ public partial class SubSettingWindow : WindowBase<SubSettingViewModel>
|
|||||||
|
|
||||||
menuClose.Click += menuClose_Click;
|
menuClose.Click += menuClose_Click;
|
||||||
Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
this.Closing += SubSettingWindow_Closing;
|
Closing += SubSettingWindow_Closing;
|
||||||
this.KeyDown += SubSettingWindow_KeyDown;
|
KeyDown += SubSettingWindow_KeyDown;
|
||||||
ViewModel = new SubSettingViewModel(UpdateViewHandler);
|
ViewModel = new SubSettingViewModel(UpdateViewHandler);
|
||||||
lstSubscription.DoubleTapped += LstSubscription_DoubleTapped;
|
lstSubscription.DoubleTapped += LstSubscription_DoubleTapped;
|
||||||
lstSubscription.SelectionChanged += LstSubscription_SelectionChanged;
|
lstSubscription.SelectionChanged += LstSubscription_SelectionChanged;
|
||||||
@@ -37,7 +37,7 @@ public partial class SubSettingWindow : WindowBase<SubSettingViewModel>
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close();
|
Close();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.ShowYesNo:
|
case EViewAction.ShowYesNo:
|
||||||
@@ -89,7 +89,7 @@ public partial class SubSettingWindow : WindowBase<SubSettingViewModel>
|
|||||||
private void menuClose_Click(object? sender, RoutedEventArgs e)
|
private void menuClose_Click(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
_manualClose = true;
|
_manualClose = true;
|
||||||
this.Close(ViewModel?.IsModified);
|
Close(ViewModel?.IsModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SubSettingWindow_Closing(object? sender, WindowClosingEventArgs e)
|
private void SubSettingWindow_Closing(object? sender, WindowClosingEventArgs e)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public partial class SudoPasswordInputView : UserControl
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Loaded += (s, e) => txtPassword.Focus();
|
Loaded += (s, e) => txtPassword.Focus();
|
||||||
|
|
||||||
btnSave.Click += async (_, _) => await SavePasswordAsync();
|
btnSave.Click += async (_, _) => await SavePasswordAsync();
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Avalonia.Desktop" />
|
<PackageReference Include="Avalonia.Desktop" />
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" />
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" />
|
<PackageReference Include="ReactiveUI.Avalonia" />
|
||||||
<PackageReference Include="MessageBox.Avalonia" />
|
<PackageReference Include="MessageBox.Avalonia" />
|
||||||
<PackageReference Include="Semi.Avalonia" />
|
<PackageReference Include="Semi.Avalonia" />
|
||||||
<PackageReference Include="Semi.Avalonia.AvaloniaEdit" />
|
<PackageReference Include="Semi.Avalonia.AvaloniaEdit" />
|
||||||
|
|||||||
@@ -26,11 +26,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHub Action", "GitHub Act
|
|||||||
..\.github\workflows\build-osx.yml = ..\.github\workflows\build-osx.yml
|
..\.github\workflows\build-osx.yml = ..\.github\workflows\build-osx.yml
|
||||||
..\.github\workflows\build-windows-desktop.yml = ..\.github\workflows\build-windows-desktop.yml
|
..\.github\workflows\build-windows-desktop.yml = ..\.github\workflows\build-windows-desktop.yml
|
||||||
..\.github\workflows\build-windows.yml = ..\.github\workflows\build-windows.yml
|
..\.github\workflows\build-windows.yml = ..\.github\workflows\build-windows.yml
|
||||||
..\package-appimage.sh = ..\package-appimage.sh
|
|
||||||
..\package-debian.sh = ..\package-debian.sh
|
..\package-debian.sh = ..\package-debian.sh
|
||||||
..\package-osx.sh = ..\package-osx.sh
|
..\package-osx.sh = ..\package-osx.sh
|
||||||
..\package-release-zip.sh = ..\package-release-zip.sh
|
..\package-release-zip.sh = ..\package-release-zip.sh
|
||||||
..\pkg2appimage.yml = ..\pkg2appimage.yml
|
|
||||||
..\.github\workflows\winget-publish.yml = ..\.github\workflows\winget-publish.yml
|
..\.github\workflows\winget-publish.yml = ..\.github\workflows\winget-publish.yml
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
@@ -6,11 +6,9 @@
|
|||||||
<File Path="../.github/workflows/build-windows-desktop.yml" />
|
<File Path="../.github/workflows/build-windows-desktop.yml" />
|
||||||
<File Path="../.github/workflows/build-windows.yml" />
|
<File Path="../.github/workflows/build-windows.yml" />
|
||||||
<File Path="../.github/workflows/winget-publish.yml" />
|
<File Path="../.github/workflows/winget-publish.yml" />
|
||||||
<File Path="../package-appimage.sh" />
|
|
||||||
<File Path="../package-debian.sh" />
|
<File Path="../package-debian.sh" />
|
||||||
<File Path="../package-osx.sh" />
|
<File Path="../package-osx.sh" />
|
||||||
<File Path="../package-release-zip.sh" />
|
<File Path="../package-release-zip.sh" />
|
||||||
<File Path="../pkg2appimage.yml" />
|
|
||||||
</Folder>
|
</Folder>
|
||||||
<Folder Name="/Solution Files/">
|
<Folder Name="/Solution Files/">
|
||||||
<File Path="Directory.Build.props" />
|
<File Path="Directory.Build.props" />
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public partial class App : Application
|
|||||||
|
|
||||||
public App()
|
public App()
|
||||||
{
|
{
|
||||||
this.DispatcherUnhandledException += App_DispatcherUnhandledException;
|
DispatcherUnhandledException += App_DispatcherUnhandledException;
|
||||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||||
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
|
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ public partial class App : Application
|
|||||||
var exePathKey = Utils.GetMd5(Utils.GetExePath());
|
var exePathKey = Utils.GetMd5(Utils.GetExePath());
|
||||||
|
|
||||||
var rebootas = (e.Args ?? Array.Empty<string>()).Any(t => t == Global.RebootAs);
|
var rebootas = (e.Args ?? Array.Empty<string>()).Any(t => t == Global.RebootAs);
|
||||||
ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew);
|
ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out var bCreatedNew);
|
||||||
if (!rebootas && !bCreatedNew)
|
if (!rebootas && !bCreatedNew)
|
||||||
{
|
{
|
||||||
ProgramStarted.Set();
|
ProgramStarted.Set();
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ using System.Drawing;
|
|||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
namespace v2rayN;
|
namespace v2rayN.Common;
|
||||||
|
|
||||||
public class QRCodeUtils
|
public class QRCodeWindowsUtils
|
||||||
{
|
{
|
||||||
public static ImageSource? GetQRCode(string? strContent)
|
public static ImageSource? GetQRCode(string? strContent)
|
||||||
{
|
{
|
||||||
@@ -14,7 +14,7 @@ public class QRCodeUtils
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var qrCodeImage = ServiceLib.Common.QRCodeUtils.GenQRCode(strContent);
|
var qrCodeImage = QRCodeUtils.GenQRCode(strContent);
|
||||||
return qrCodeImage is null ? null : ByteToImage(qrCodeImage);
|
return qrCodeImage is null ? null : ByteToImage(qrCodeImage);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
|
||||||
namespace v2rayN;
|
namespace v2rayN.Common;
|
||||||
|
|
||||||
internal class UI
|
internal class UI
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.Windows.Media;
|
|||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
|
||||||
namespace v2rayN;
|
namespace v2rayN.Common;
|
||||||
|
|
||||||
internal static class WindowsUtils
|
internal static class WindowsUtils
|
||||||
{
|
{
|
||||||
@@ -40,13 +40,13 @@ internal static class WindowsUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("dwmapi.dll")]
|
[DllImport("dwmapi.dll")]
|
||||||
public static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attribute, ref int attributeValue, uint attributeSize);
|
public static extern int DwmSetWindowAttribute(nint hwnd, DWMWINDOWATTRIBUTE attribute, ref int attributeValue, uint attributeSize);
|
||||||
|
|
||||||
public static ImageSource IconToImageSource(Icon icon)
|
public static ImageSource IconToImageSource(Icon icon)
|
||||||
{
|
{
|
||||||
return Imaging.CreateBitmapSourceFromHIcon(
|
return Imaging.CreateBitmapSourceFromHIcon(
|
||||||
icon.Handle,
|
icon.Handle,
|
||||||
new System.Windows.Int32Rect(0, 0, icon.Width, icon.Height),
|
new Int32Rect(0, 0, icon.Width, icon.Height),
|
||||||
BitmapSizeOptions.FromEmptyOptions());
|
BitmapSizeOptions.FromEmptyOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,9 +65,9 @@ internal static class WindowsUtils
|
|||||||
private static void SetDarkBorder(Window window, bool dark)
|
private static void SetDarkBorder(Window window, bool dark)
|
||||||
{
|
{
|
||||||
// Make sure the handle is created before the window is shown
|
// Make sure the handle is created before the window is shown
|
||||||
IntPtr hWnd = new WindowInteropHelper(window).EnsureHandle();
|
var hWnd = new WindowInteropHelper(window).EnsureHandle();
|
||||||
int attribute = dark ? 1 : 0;
|
var attribute = dark ? 1 : 0;
|
||||||
uint attributeSize = (uint)Marshal.SizeOf(attribute);
|
var attributeSize = (uint)Marshal.SizeOf(attribute);
|
||||||
DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, ref attribute, attributeSize);
|
DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, ref attribute, attributeSize);
|
||||||
DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize);
|
DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ global using System.Diagnostics;
|
|||||||
global using System.Globalization;
|
global using System.Globalization;
|
||||||
global using System.IO;
|
global using System.IO;
|
||||||
global using System.Linq;
|
global using System.Linq;
|
||||||
global using System.Reactive.Disposables;
|
global using System.Reactive.Disposables.Fluent;
|
||||||
global using System.Reactive.Linq;
|
global using System.Reactive.Linq;
|
||||||
global using System.Runtime.InteropServices;
|
global using System.Runtime.InteropServices;
|
||||||
global using System.Text;
|
global using System.Text;
|
||||||
@@ -31,3 +31,4 @@ global using ServiceLib.Manager;
|
|||||||
global using ServiceLib.Models;
|
global using ServiceLib.Models;
|
||||||
global using ServiceLib.Resx;
|
global using ServiceLib.Resx;
|
||||||
global using ServiceLib.ViewModels;
|
global using ServiceLib.ViewModels;
|
||||||
|
global using v2rayN.Common;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public sealed class HotkeyManager
|
|||||||
modifiers |= KeyModifiers.Alt;
|
modifiers |= KeyModifiers.Alt;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = key << 16 | (int)modifiers;
|
key = (key << 16) | (int)modifiers;
|
||||||
if (!_hotkeyTriggerDic.ContainsKey(key))
|
if (!_hotkeyTriggerDic.ContainsKey(key))
|
||||||
{
|
{
|
||||||
_hotkeyTriggerDic.Add(key, new() { item.EGlobalHotkey });
|
_hotkeyTriggerDic.Add(key, new() { item.EGlobalHotkey });
|
||||||
@@ -103,7 +103,7 @@ public sealed class HotkeyManager
|
|||||||
private (int fsModifiers, int vKey, string hotkeyStr, List<string> Names) GetHotkeyInfo(int hotkeyCode)
|
private (int fsModifiers, int vKey, string hotkeyStr, List<string> Names) GetHotkeyInfo(int hotkeyCode)
|
||||||
{
|
{
|
||||||
var fsModifiers = hotkeyCode & 0xffff;
|
var fsModifiers = hotkeyCode & 0xffff;
|
||||||
var vKey = hotkeyCode >> 16 & 0xffff;
|
var vKey = (hotkeyCode >> 16) & 0xffff;
|
||||||
var hotkeyStr = new StringBuilder();
|
var hotkeyStr = new StringBuilder();
|
||||||
var names = new List<string>();
|
var names = new List<string>();
|
||||||
|
|
||||||
|
|||||||
@@ -60,18 +60,18 @@ public sealed class WindowsManager
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color color = ColorTranslator.FromHtml("#3399CC");
|
var color = ColorTranslator.FromHtml("#3399CC");
|
||||||
int index = (int)config.SystemProxyItem.SysProxyType;
|
var index = (int)config.SystemProxyItem.SysProxyType;
|
||||||
if (index > 0)
|
if (index > 0)
|
||||||
{
|
{
|
||||||
color = (new[] { Color.Red, Color.Purple, Color.DarkGreen, Color.Orange, Color.DarkSlateBlue, Color.RoyalBlue })[index - 1];
|
color = (new[] { Color.Red, Color.Purple, Color.DarkGreen, Color.Orange, Color.DarkSlateBlue, Color.RoyalBlue })[index - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int width = 128;
|
var width = 128;
|
||||||
int height = 128;
|
var height = 128;
|
||||||
|
|
||||||
Bitmap bitmap = new(width, height);
|
Bitmap bitmap = new(width, height);
|
||||||
Graphics graphics = Graphics.FromImage(bitmap);
|
var graphics = Graphics.FromImage(bitmap);
|
||||||
SolidBrush drawBrush = new(color);
|
SolidBrush drawBrush = new(color);
|
||||||
|
|
||||||
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
||||||
@@ -79,7 +79,7 @@ public sealed class WindowsManager
|
|||||||
graphics.DrawImage(new Bitmap(item.CustomIcon), 0, 0, width, height);
|
graphics.DrawImage(new Bitmap(item.CustomIcon), 0, 0, width, height);
|
||||||
graphics.FillEllipse(drawBrush, width / 2, width / 2, width / 2, width / 2);
|
graphics.FillEllipse(drawBrush, width / 2, width / 2, width / 2, width / 2);
|
||||||
|
|
||||||
Icon createdIcon = Icon.FromHandle(bitmap.GetHicon());
|
var createdIcon = Icon.FromHandle(bitmap.GetHicon());
|
||||||
|
|
||||||
drawBrush.Dispose();
|
drawBrush.Dispose();
|
||||||
graphics.Dispose();
|
graphics.Dispose();
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ public partial class AddGroupServerWindow
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
this.Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
this.PreviewKeyDown += AddGroupServerWindow_PreviewKeyDown;
|
PreviewKeyDown += AddGroupServerWindow_PreviewKeyDown;
|
||||||
lstChild.SelectionChanged += LstChild_SelectionChanged;
|
lstChild.SelectionChanged += LstChild_SelectionChanged;
|
||||||
menuSelectAllChild.Click += MenuSelectAllChild_Click;
|
menuSelectAllChild.Click += MenuSelectAllChild_Click;
|
||||||
|
|
||||||
@@ -27,11 +27,11 @@ public partial class AddGroupServerWindow
|
|||||||
switch (profileItem.ConfigType)
|
switch (profileItem.ConfigType)
|
||||||
{
|
{
|
||||||
case EConfigType.PolicyGroup:
|
case EConfigType.PolicyGroup:
|
||||||
this.Title = ResUI.TbConfigTypePolicyGroup;
|
Title = ResUI.TbConfigTypePolicyGroup;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EConfigType.ProxyChain:
|
case EConfigType.ProxyChain:
|
||||||
this.Title = ResUI.TbConfigTypeProxyChain;
|
Title = ResUI.TbConfigTypeProxyChain;
|
||||||
gridPolicyGroup.Visibility = Visibility.Collapsed;
|
gridPolicyGroup.Visibility = Visibility.Collapsed;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ public partial class AddGroupServerWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ public partial class AddServer2Window
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
this.Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
ViewModel = new AddServer2ViewModel(profileItem, UpdateViewHandler);
|
ViewModel = new AddServer2ViewModel(profileItem, UpdateViewHandler);
|
||||||
|
|
||||||
cmbCoreType.ItemsSource = Utils.GetEnumNames<ECoreType>().Where(t => t != ECoreType.v2rayN.ToString()).ToList().AppendEmpty();
|
cmbCoreType.ItemsSource = Utils.GetEnumNames<ECoreType>().Where(t => t != ECoreType.v2rayN.ToString()).ToList().AppendEmpty();
|
||||||
@@ -32,11 +32,11 @@ public partial class AddServer2Window
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.BrowseServer:
|
case EViewAction.BrowseServer:
|
||||||
if (UI.OpenFileDialog(out string fileName, "Config|*.json|YAML|*.yaml;*.yml|All|*.*") != true)
|
if (UI.OpenFileDialog(out var fileName, "Config|*.json|YAML|*.yaml;*.yml|All|*.*") != true)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ public partial class AddServerWindow
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
this.Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
cmbNetwork.SelectionChanged += CmbNetwork_SelectionChanged;
|
cmbNetwork.SelectionChanged += CmbNetwork_SelectionChanged;
|
||||||
cmbStreamSecurity.SelectionChanged += CmbStreamSecurity_SelectionChanged;
|
cmbStreamSecurity.SelectionChanged += CmbStreamSecurity_SelectionChanged;
|
||||||
btnGUID.Click += btnGUID_Click;
|
btnGUID.Click += btnGUID_Click;
|
||||||
@@ -191,7 +191,7 @@ public partial class AddServerWindow
|
|||||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Title = $"{profileItem.ConfigType}";
|
Title = $"{profileItem.ConfigType}";
|
||||||
WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);
|
WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ public partial class AddServerWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public partial class BackupAndRestoreView
|
|||||||
|
|
||||||
private void MenuLocalBackup_Click(object sender, RoutedEventArgs e)
|
private void MenuLocalBackup_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (UI.SaveFileDialog(out string fileName, "Zip|*.zip") != true)
|
if (UI.SaveFileDialog(out var fileName, "Zip|*.zip") != true)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ public partial class BackupAndRestoreView
|
|||||||
|
|
||||||
private void MenuLocalRestore_Click(object sender, RoutedEventArgs e)
|
private void MenuLocalRestore_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (UI.OpenFileDialog(out string fileName, "Zip|*.zip|All|*.*") != true)
|
if (UI.OpenFileDialog(out var fileName, "Zip|*.zip|All|*.*") != true)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ public partial class DNSSettingWindow
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
_config = AppManager.Instance.Config;
|
_config = AppManager.Instance.Config;
|
||||||
|
|
||||||
ViewModel = new DNSSettingViewModel(UpdateViewHandler);
|
ViewModel = new DNSSettingViewModel(UpdateViewHandler);
|
||||||
@@ -78,7 +78,7 @@ public partial class DNSSettingWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ public partial class FullConfigTemplateWindow
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
_config = AppManager.Instance.Config;
|
_config = AppManager.Instance.Config;
|
||||||
|
|
||||||
ViewModel = new FullConfigTemplateViewModel(UpdateViewHandler);
|
ViewModel = new FullConfigTemplateViewModel(UpdateViewHandler);
|
||||||
@@ -35,7 +35,7 @@ public partial class FullConfigTemplateWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ public partial class GlobalHotkeySettingWindow
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
|
|
||||||
ViewModel = new GlobalHotkeySettingViewModel(UpdateViewHandler);
|
ViewModel = new GlobalHotkeySettingViewModel(UpdateViewHandler);
|
||||||
|
|
||||||
btnReset.Click += btnReset_Click;
|
btnReset.Click += btnReset_Click;
|
||||||
|
|
||||||
HotkeyManager.Instance.IsPause = true;
|
HotkeyManager.Instance.IsPause = true;
|
||||||
this.Closing += (s, e) => HotkeyManager.Instance.IsPause = false;
|
Closing += (s, e) => HotkeyManager.Instance.IsPause = false;
|
||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
@@ -35,7 +35,7 @@ public partial class GlobalHotkeySettingWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ public partial class MainWindow
|
|||||||
ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);
|
ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);
|
||||||
|
|
||||||
App.Current.SessionEnding += Current_SessionEnding;
|
App.Current.SessionEnding += Current_SessionEnding;
|
||||||
this.Closing += MainWindow_Closing;
|
Closing += MainWindow_Closing;
|
||||||
this.PreviewKeyDown += MainWindow_PreviewKeyDown;
|
PreviewKeyDown += MainWindow_PreviewKeyDown;
|
||||||
menuSettingsSetUWP.Click += menuSettingsSetUWP_Click;
|
menuSettingsSetUWP.Click += menuSettingsSetUWP_Click;
|
||||||
menuPromotion.Click += menuPromotion_Click;
|
menuPromotion.Click += menuPromotion_Click;
|
||||||
menuClose.Click += menuClose_Click;
|
menuClose.Click += menuClose_Click;
|
||||||
@@ -150,10 +150,10 @@ public partial class MainWindow
|
|||||||
.DisposeWith(disposables);
|
.DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
|
Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
|
||||||
if (_config.UiItem.AutoHideStartup)
|
if (_config.UiItem.AutoHideStartup)
|
||||||
{
|
{
|
||||||
this.WindowState = WindowState.Minimized;
|
WindowState = WindowState.Minimized;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_config.GuiItem.EnableHWA)
|
if (!_config.GuiItem.EnableHWA)
|
||||||
@@ -187,35 +187,35 @@ public partial class MainWindow
|
|||||||
case EViewAction.AddServerWindow:
|
case EViewAction.AddServerWindow:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
return (new AddServerWindow((ProfileItem)obj)).ShowDialog() ?? false;
|
return new AddServerWindow((ProfileItem)obj).ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.AddServer2Window:
|
case EViewAction.AddServer2Window:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
return (new AddServer2Window((ProfileItem)obj)).ShowDialog() ?? false;
|
return new AddServer2Window((ProfileItem)obj).ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.AddGroupServerWindow:
|
case EViewAction.AddGroupServerWindow:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
return (new AddGroupServerWindow((ProfileItem)obj)).ShowDialog() ?? false;
|
return new AddGroupServerWindow((ProfileItem)obj).ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.DNSSettingWindow:
|
case EViewAction.DNSSettingWindow:
|
||||||
return (new DNSSettingWindow().ShowDialog() ?? false);
|
return new DNSSettingWindow().ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.RoutingSettingWindow:
|
case EViewAction.RoutingSettingWindow:
|
||||||
return (new RoutingSettingWindow().ShowDialog() ?? false);
|
return new RoutingSettingWindow().ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.OptionSettingWindow:
|
case EViewAction.OptionSettingWindow:
|
||||||
return (new OptionSettingWindow().ShowDialog() ?? false);
|
return new OptionSettingWindow().ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.FullConfigTemplateWindow:
|
case EViewAction.FullConfigTemplateWindow:
|
||||||
return (new FullConfigTemplateWindow().ShowDialog() ?? false);
|
return new FullConfigTemplateWindow().ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.GlobalHotkeySettingWindow:
|
case EViewAction.GlobalHotkeySettingWindow:
|
||||||
return (new GlobalHotkeySettingWindow().ShowDialog() ?? false);
|
return new GlobalHotkeySettingWindow().ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.SubSettingWindow:
|
case EViewAction.SubSettingWindow:
|
||||||
return (new SubSettingWindow().ShowDialog() ?? false);
|
return new SubSettingWindow().ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.ScanScreenTask:
|
case EViewAction.ScanScreenTask:
|
||||||
await ScanScreenTaskAsync();
|
await ScanScreenTaskAsync();
|
||||||
@@ -328,7 +328,7 @@ public partial class MainWindow
|
|||||||
|
|
||||||
if (Application.Current?.MainWindow is Window window)
|
if (Application.Current?.MainWindow is Window window)
|
||||||
{
|
{
|
||||||
var bytes = QRCodeUtils.CaptureScreen(window);
|
var bytes = QRCodeWindowsUtils.CaptureScreen(window);
|
||||||
await ViewModel?.ScanScreenResult(bytes);
|
await ViewModel?.ScanScreenResult(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ public partial class MainWindow
|
|||||||
this?.Show();
|
this?.Show();
|
||||||
if (this?.WindowState == WindowState.Minimized)
|
if (this?.WindowState == WindowState.Minimized)
|
||||||
{
|
{
|
||||||
this.WindowState = WindowState.Normal;
|
WindowState = WindowState.Normal;
|
||||||
}
|
}
|
||||||
this?.Activate();
|
this?.Activate();
|
||||||
this?.Focus();
|
this?.Focus();
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ public partial class MsgView
|
|||||||
case EViewAction.DispatcherShowMsg:
|
case EViewAction.DispatcherShowMsg:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
Application.Current?.Dispatcher.Invoke((() =>
|
Application.Current?.Dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
ShowMsg(obj);
|
ShowMsg(obj);
|
||||||
}), DispatcherPriority.ApplicationIdle);
|
}, DispatcherPriority.ApplicationIdle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public partial class OptionSettingWindow
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
_config = AppManager.Instance.Config;
|
_config = AppManager.Instance.Config;
|
||||||
|
|
||||||
ViewModel = new OptionSettingViewModel(UpdateViewHandler);
|
ViewModel = new OptionSettingViewModel(UpdateViewHandler);
|
||||||
@@ -136,7 +136,7 @@ public partial class OptionSettingWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.InitSettingFont:
|
case EViewAction.InitSettingFont:
|
||||||
@@ -168,12 +168,12 @@ public partial class OptionSettingWindow
|
|||||||
foreach (var ttf in files)
|
foreach (var ttf in files)
|
||||||
{
|
{
|
||||||
var families = Fonts.GetFontFamilies(Utils.GetFontsPath(ttf));
|
var families = Fonts.GetFontFamilies(Utils.GetFontsPath(ttf));
|
||||||
foreach (FontFamily family in families)
|
foreach (var family in families)
|
||||||
{
|
{
|
||||||
var typefaces = family.GetTypefaces();
|
var typefaces = family.GetTypefaces();
|
||||||
foreach (Typeface typeface in typefaces)
|
foreach (var typeface in typefaces)
|
||||||
{
|
{
|
||||||
typeface.TryGetGlyphTypeface(out GlyphTypeface glyph);
|
typeface.TryGetGlyphTypeface(out var glyph);
|
||||||
//var fontFace = glyph.Win32FaceNames[new CultureInfo("en-us")];
|
//var fontFace = glyph.Win32FaceNames[new CultureInfo("en-us")];
|
||||||
//if (!fontFace.Equals("Regular") && !fontFace.Equals("Normal"))
|
//if (!fontFace.Equals("Regular") && !fontFace.Equals("Normal"))
|
||||||
//{
|
//{
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public partial class ProfilesSelectWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -87,6 +87,15 @@
|
|||||||
ToolTip="{x:Static resx:ResUI.menuFastRealPing}">
|
ToolTip="{x:Static resx:ResUI.menuFastRealPing}">
|
||||||
<materialDesign:PackIcon VerticalAlignment="Center" Kind="LightningBolt" />
|
<materialDesign:PackIcon VerticalAlignment="Center" Kind="LightningBolt" />
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
x:Name="menuMixedTestServer"
|
||||||
|
Width="30"
|
||||||
|
Height="30"
|
||||||
|
Margin="{StaticResource MarginLeftRight4}"
|
||||||
|
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
|
||||||
|
ToolTip="{x:Static resx:ResUI.menuMixedTestServer}">
|
||||||
|
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Speedometer" />
|
||||||
|
</Button>
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
<DataGrid
|
<DataGrid
|
||||||
x:Name="lstProfiles"
|
x:Name="lstProfiles"
|
||||||
@@ -131,11 +140,11 @@
|
|||||||
x:Name="menuRemoveDuplicateServer"
|
x:Name="menuRemoveDuplicateServer"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
Header="{x:Static resx:ResUI.menuRemoveDuplicateServer}" />
|
Header="{x:Static resx:ResUI.menuRemoveDuplicateServer}" />
|
||||||
<Separator />
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuMixedTestServer"
|
x:Name="menuRemoveInvalidServerResult"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
Header="{x:Static resx:ResUI.menuMixedTestServer}" />
|
Header="{x:Static resx:ResUI.menuRemoveInvalidServerResult}" />
|
||||||
|
<Separator />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuTcpingServer"
|
x:Name="menuTcpingServer"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
@@ -148,16 +157,10 @@
|
|||||||
x:Name="menuSpeedServer"
|
x:Name="menuSpeedServer"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
Header="{x:Static resx:ResUI.menuSpeedServer}" />
|
Header="{x:Static resx:ResUI.menuSpeedServer}" />
|
||||||
<MenuItem Header="{x:Static resx:ResUI.menuTestServerResult}">
|
<MenuItem
|
||||||
<MenuItem
|
x:Name="menuSortServerResult"
|
||||||
x:Name="menuSortServerResult"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Header="{x:Static resx:ResUI.menuSortServerResult}" />
|
||||||
Header="{x:Static resx:ResUI.menuSortServerResult}" />
|
|
||||||
<MenuItem
|
|
||||||
x:Name="menuRemoveInvalidServerResult"
|
|
||||||
Height="{StaticResource MenuItemHeight}"
|
|
||||||
Header="{x:Static resx:ResUI.menuRemoveInvalidServerResult}" />
|
|
||||||
</MenuItem>
|
|
||||||
<Separator />
|
<Separator />
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuMoveToGroup"
|
x:Name="menuMoveToGroup"
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ public partial class ProfilesView
|
|||||||
case EViewAction.SaveFileDialog:
|
case EViewAction.SaveFileDialog:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
if (UI.SaveFileDialog(out string fileName, "Config|*.json") != true)
|
if (UI.SaveFileDialog(out var fileName, "Config|*.json") != true)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -137,17 +137,17 @@ public partial class ProfilesView
|
|||||||
case EViewAction.AddServerWindow:
|
case EViewAction.AddServerWindow:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
return (new AddServerWindow((ProfileItem)obj)).ShowDialog() ?? false;
|
return new AddServerWindow((ProfileItem)obj).ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.AddServer2Window:
|
case EViewAction.AddServer2Window:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
return (new AddServer2Window((ProfileItem)obj)).ShowDialog() ?? false;
|
return new AddServer2Window((ProfileItem)obj).ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.AddGroupServerWindow:
|
case EViewAction.AddGroupServerWindow:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
return (new AddGroupServerWindow((ProfileItem)obj)).ShowDialog() ?? false;
|
return new AddGroupServerWindow((ProfileItem)obj).ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.ShareServer:
|
case EViewAction.ShareServer:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
@@ -158,7 +158,7 @@ public partial class ProfilesView
|
|||||||
case EViewAction.SubEditWindow:
|
case EViewAction.SubEditWindow:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
return (new SubEditWindow((SubItem)obj)).ShowDialog() ?? false;
|
return new SubEditWindow((SubItem)obj).ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.DispatcherRefreshServersBiz:
|
case EViewAction.DispatcherRefreshServersBiz:
|
||||||
Application.Current?.Dispatcher.Invoke(RefreshServersBiz, DispatcherPriority.Normal);
|
Application.Current?.Dispatcher.Invoke(RefreshServersBiz, DispatcherPriority.Normal);
|
||||||
@@ -170,7 +170,7 @@ public partial class ProfilesView
|
|||||||
|
|
||||||
public async void ShareServer(string url)
|
public async void ShareServer(string url)
|
||||||
{
|
{
|
||||||
var img = QRCodeUtils.GetQRCode(url);
|
var img = QRCodeWindowsUtils.GetQRCode(url);
|
||||||
var dialog = new QrcodeView()
|
var dialog = new QrcodeView()
|
||||||
{
|
{
|
||||||
imgQrcode = { Source = img },
|
imgQrcode = { Source = img },
|
||||||
@@ -415,8 +415,8 @@ public partial class ProfilesView
|
|||||||
private void LstProfiles_MouseMove(object sender, MouseEventArgs e)
|
private void LstProfiles_MouseMove(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
// Get the current mouse position
|
// Get the current mouse position
|
||||||
Point mousePos = e.GetPosition(null);
|
var mousePos = e.GetPosition(null);
|
||||||
Vector diff = startPoint - mousePos;
|
var diff = startPoint - mousePos;
|
||||||
|
|
||||||
if (e.LeftButton == MouseButtonState.Pressed &&
|
if (e.LeftButton == MouseButtonState.Pressed &&
|
||||||
(Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
|
(Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
|
||||||
@@ -429,7 +429,7 @@ public partial class ProfilesView
|
|||||||
if (listViewItem == null)
|
if (listViewItem == null)
|
||||||
return; // Abort
|
return; // Abort
|
||||||
// Find the data behind the ListViewItem
|
// Find the data behind the ListViewItem
|
||||||
ProfileItemModel item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
|
var item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
|
||||||
if (item == null)
|
if (item == null)
|
||||||
return; // Abort
|
return; // Abort
|
||||||
// Initialize the drag & drop operation
|
// Initialize the drag & drop operation
|
||||||
@@ -462,7 +462,7 @@ public partial class ProfilesView
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Find the data behind the Item
|
// Find the data behind the Item
|
||||||
ProfileItemModel item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
|
var item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);
|
||||||
if (item == null)
|
if (item == null)
|
||||||
return;
|
return;
|
||||||
// Move item into observable collection
|
// Move item into observable collection
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ public partial class RoutingRuleDetailsWindow
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
this.Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
clbProtocol.SelectionChanged += ClbProtocol_SelectionChanged;
|
clbProtocol.SelectionChanged += ClbProtocol_SelectionChanged;
|
||||||
clbInboundTag.SelectionChanged += ClbInboundTag_SelectionChanged;
|
clbInboundTag.SelectionChanged += ClbInboundTag_SelectionChanged;
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ public partial class RoutingRuleDetailsWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ public partial class RoutingRuleSettingWindow
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
this.Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
this.PreviewKeyDown += RoutingRuleSettingWindow_PreviewKeyDown;
|
PreviewKeyDown += RoutingRuleSettingWindow_PreviewKeyDown;
|
||||||
lstRules.SelectionChanged += lstRules_SelectionChanged;
|
lstRules.SelectionChanged += lstRules_SelectionChanged;
|
||||||
lstRules.MouseDoubleClick += LstRules_MouseDoubleClick;
|
lstRules.MouseDoubleClick += LstRules_MouseDoubleClick;
|
||||||
menuRuleSelectAll.Click += menuRuleSelectAll_Click;
|
menuRuleSelectAll.Click += menuRuleSelectAll_Click;
|
||||||
@@ -57,7 +57,7 @@ public partial class RoutingRuleSettingWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.ShowYesNo:
|
case EViewAction.ShowYesNo:
|
||||||
@@ -80,11 +80,11 @@ public partial class RoutingRuleSettingWindow
|
|||||||
|
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
return (new RoutingRuleDetailsWindow((RulesItem)obj)).ShowDialog() ?? false;
|
return new RoutingRuleDetailsWindow((RulesItem)obj).ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.ImportRulesFromFile:
|
case EViewAction.ImportRulesFromFile:
|
||||||
|
|
||||||
if (UI.OpenFileDialog(out string fileName, "Rules|*.json|All|*.*") != true)
|
if (UI.OpenFileDialog(out var fileName, "Rules|*.json|All|*.*") != true)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,7 @@ public partial class RoutingRuleSettingWindow
|
|||||||
|
|
||||||
private void btnBrowseCustomIcon_Click(object sender, System.Windows.RoutedEventArgs e)
|
private void btnBrowseCustomIcon_Click(object sender, System.Windows.RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (UI.OpenFileDialog(out string fileName,
|
if (UI.OpenFileDialog(out var fileName,
|
||||||
"PNG,ICO|*.png;*.ico") != true)
|
"PNG,ICO|*.png;*.ico") != true)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -185,7 +185,7 @@ public partial class RoutingRuleSettingWindow
|
|||||||
|
|
||||||
private void btnBrowseCustomRulesetPath4Singbox_Click(object sender, RoutedEventArgs e)
|
private void btnBrowseCustomRulesetPath4Singbox_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (UI.OpenFileDialog(out string fileName,
|
if (UI.OpenFileDialog(out var fileName,
|
||||||
"Config|*.json|All|*.*") != true)
|
"Config|*.json|All|*.*") != true)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ public partial class RoutingSettingWindow
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
this.Closing += RoutingSettingWindow_Closing;
|
Closing += RoutingSettingWindow_Closing;
|
||||||
this.PreviewKeyDown += RoutingSettingWindow_PreviewKeyDown;
|
PreviewKeyDown += RoutingSettingWindow_PreviewKeyDown;
|
||||||
lstRoutings.SelectionChanged += lstRoutings_SelectionChanged;
|
lstRoutings.SelectionChanged += lstRoutings_SelectionChanged;
|
||||||
lstRoutings.MouseDoubleClick += LstRoutings_MouseDoubleClick;
|
lstRoutings.MouseDoubleClick += LstRoutings_MouseDoubleClick;
|
||||||
menuRoutingAdvancedSelectAll.Click += menuRoutingAdvancedSelectAll_Click;
|
menuRoutingAdvancedSelectAll.Click += menuRoutingAdvancedSelectAll_Click;
|
||||||
@@ -44,7 +44,7 @@ public partial class RoutingSettingWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.ShowYesNo:
|
case EViewAction.ShowYesNo:
|
||||||
@@ -58,7 +58,7 @@ public partial class RoutingSettingWindow
|
|||||||
|
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
return (new RoutingRuleSettingWindow((RoutingItem)obj)).ShowDialog() ?? false;
|
return new RoutingRuleSettingWindow((RoutingItem)obj).ShowDialog() ?? false;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ public partial class RoutingSettingWindow
|
|||||||
{
|
{
|
||||||
if (ViewModel?.IsModified == true)
|
if (ViewModel?.IsModified == true)
|
||||||
{
|
{
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,11 +122,11 @@ public partial class RoutingSettingWindow
|
|||||||
{
|
{
|
||||||
if (ViewModel?.IsModified == true)
|
if (ViewModel?.IsModified == true)
|
||||||
{
|
{
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,11 +71,11 @@ public partial class StatusBarView
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.DispatcherRefreshIcon:
|
case EViewAction.DispatcherRefreshIcon:
|
||||||
Application.Current?.Dispatcher.Invoke((async () =>
|
Application.Current?.Dispatcher.Invoke(async () =>
|
||||||
{
|
{
|
||||||
tbNotify.Icon = await WindowsManager.Instance.GetNotifyIcon(_config);
|
tbNotify.Icon = await WindowsManager.Instance.GetNotifyIcon(_config);
|
||||||
Application.Current.MainWindow.Icon = WindowsManager.Instance.GetAppIcon(_config);
|
Application.Current.MainWindow.Icon = WindowsManager.Instance.GetAppIcon(_config);
|
||||||
}), DispatcherPriority.Normal);
|
}, DispatcherPriority.Normal);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.SetClipboardData:
|
case EViewAction.SetClipboardData:
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ public partial class SubEditWindow
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
this.Loaded += Window_Loaded;
|
Loaded += Window_Loaded;
|
||||||
|
|
||||||
ViewModel = new SubEditViewModel(subItem, UpdateViewHandler);
|
ViewModel = new SubEditViewModel(subItem, UpdateViewHandler);
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ public partial class SubEditWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ public partial class SubSettingWindow
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
this.Owner = Application.Current.MainWindow;
|
Owner = Application.Current.MainWindow;
|
||||||
|
|
||||||
ViewModel = new SubSettingViewModel(UpdateViewHandler);
|
ViewModel = new SubSettingViewModel(UpdateViewHandler);
|
||||||
this.Closing += SubSettingWindow_Closing;
|
Closing += SubSettingWindow_Closing;
|
||||||
lstSubscription.MouseDoubleClick += LstSubscription_MouseDoubleClick;
|
lstSubscription.MouseDoubleClick += LstSubscription_MouseDoubleClick;
|
||||||
lstSubscription.SelectionChanged += LstSubscription_SelectionChanged;
|
lstSubscription.SelectionChanged += LstSubscription_SelectionChanged;
|
||||||
menuClose.Click += menuClose_Click;
|
menuClose.Click += menuClose_Click;
|
||||||
@@ -34,7 +34,7 @@ public partial class SubSettingWindow
|
|||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EViewAction.ShowYesNo:
|
case EViewAction.ShowYesNo:
|
||||||
@@ -47,7 +47,7 @@ public partial class SubSettingWindow
|
|||||||
case EViewAction.SubEditWindow:
|
case EViewAction.SubEditWindow:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
return false;
|
return false;
|
||||||
return (new SubEditWindow((SubItem)obj)).ShowDialog() ?? false;
|
return new SubEditWindow((SubItem)obj).ShowDialog() ?? false;
|
||||||
|
|
||||||
case EViewAction.ShareSub:
|
case EViewAction.ShareSub:
|
||||||
if (obj is null)
|
if (obj is null)
|
||||||
@@ -64,7 +64,7 @@ public partial class SubSettingWindow
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var img = QRCodeUtils.GetQRCode(url);
|
var img = QRCodeWindowsUtils.GetQRCode(url);
|
||||||
var dialog = new QrcodeView()
|
var dialog = new QrcodeView()
|
||||||
{
|
{
|
||||||
imgQrcode = { Source = img },
|
imgQrcode = { Source = img },
|
||||||
@@ -78,7 +78,7 @@ public partial class SubSettingWindow
|
|||||||
{
|
{
|
||||||
if (ViewModel?.IsModified == true)
|
if (ViewModel?.IsModified == true)
|
||||||
{
|
{
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,11 +99,11 @@ public partial class SubSettingWindow
|
|||||||
{
|
{
|
||||||
if (ViewModel?.IsModified == true)
|
if (ViewModel?.IsModified == true)
|
||||||
{
|
{
|
||||||
this.DialogResult = true;
|
DialogResult = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user