Compare commits

...

27 Commits
7.7.1 ... 7.8.3

Author SHA1 Message Date
2dust
4104964e38 up 7.8.3 2025-02-12 20:04:29 +08:00
2dust
3bbd1edf06 Update V2rayConfig.cs 2025-02-12 19:18:59 +08:00
lyranico
41cc260b5c Fix Package AppImage script (#6681) 2025-02-12 14:33:02 +08:00
2dust
6cd5063c9b Fix call core file
https://github.com/2dust/v2rayN/issues/6680
2025-02-12 11:23:22 +08:00
2dust
e544df6d01 up 7.8.2 2025-02-11 16:30:16 +08:00
2dust
f952d2383c Remove IncludeNativeLibrariesForSelfExtract 2025-02-11 10:16:19 +08:00
2dust
8a29e147d3 Added Enable Mixin parameter 2025-02-10 20:04:47 +08:00
Alphax-Hue3682
8a19128e7f Update Persian translate (#6651)
* Update Persian translate

* Update ResUI.fa-Ir.resx
2025-02-10 17:40:21 +08:00
2dust
7dc9fbd8ff Improved and optimized speedtest 2025-02-10 10:08:03 +08:00
2dust
31a179e647 Code clean 2025-02-09 20:17:56 +08:00
2dust
c3fdfcc4bd up 7.8.1 2025-02-08 16:49:59 +08:00
2dust
7ea8fae2da Improve test logic
Retest the failed part of the test and call it recursively.
Remove the number of batches that are automatically divided when testing parameters.
2025-02-08 16:43:40 +08:00
2dust
67ffa810d3 Optimize code and remove Action 2025-02-06 15:28:51 +08:00
2dust
ba2a636dd2 Fixed the system language judgment during the first run
https://github.com/2dust/v2rayN/issues/6638
2025-02-06 14:36:38 +08:00
2dust
d471336994 Adjust App Exit function
https://github.com/2dust/v2rayN/issues/6634
2025-02-05 17:31:13 +08:00
2dust
7e6482fdff Adjust hysteria core run arguments
https://github.com/2dust/v2rayN/issues/6635
2025-02-05 17:14:56 +08:00
2dust
a8eba93ffd up 7.8.0 2025-02-04 14:30:42 +08:00
2dust
4ffe595db6 Code clean 2025-02-04 14:30:28 +08:00
2dust
885587e551 Update Directory.Packages.props 2025-02-04 14:19:56 +08:00
2dust
e986dc189e Fix ProcUtils NoAssociatedProcess issue 2025-02-04 10:30:33 +08:00
2dust
bccab41c8f Update Directory.Build.props 2025-02-04 10:28:49 +08:00
2dust
79a0538ca0 Improve core info 2025-02-03 20:19:20 +08:00
2dust
e6b27d17e4 Add support for overtls custom configuration
https://github.com/ShadowsocksR-Live/overtls
2025-02-03 15:43:26 +08:00
2dust
2a0012824a Add support for brook custom configuration
https://github.com/txthinking/brook
https://github.com/txthinking/brook/issues/1372
2025-02-03 15:06:21 +08:00
2dust
9d92be99ee Improve core running arguments 2025-02-03 14:48:53 +08:00
2dust
6914831d30 Code clean 2025-02-02 17:48:59 +08:00
2dust
19d83be6de Fix Package AppImage script 2025-02-01 19:10:54 +08:00
38 changed files with 478 additions and 364 deletions

View File

@@ -22,7 +22,7 @@ jobs:
matrix: matrix:
configuration: [Release] configuration: [Release]
runs-on: ubuntu-latest runs-on: ubuntu-22.04
steps: steps:
- name: Checkout - name: Checkout

View File

@@ -17,9 +17,11 @@ echo "When this file exists, app will not store configs under this folder" >"${P
if [ $Arch = "linux-64" ]; then if [ $Arch = "linux-64" ]; then
Arch2="x86_64" Arch2="x86_64"
Arch3="amd64" Arch3="amd64"
Interpreter="ld-linux-x86-64.so.2"
else else
Arch2="aarch64" Arch2="aarch64"
Arch3="arm64" Arch3="arm64"
Interpreter="ld-linux-aarch64.so.1"
fi fi
echo $Arch2 echo $Arch2
@@ -29,6 +31,7 @@ cat >"${PackagePath}/AppDir/AppRun" <<-EOF
HERE="\$(dirname "\$(readlink -f "\${0}")")" HERE="\$(dirname "\$(readlink -f "\${0}")")"
export PATH="\${HERE}"/opt/v2rayN/:"\${PATH}" export PATH="\${HERE}"/opt/v2rayN/:"\${PATH}"
export LD_LIBRARY_PATH="\${HERE}"/opt/v2rayN/:"\${LD_LIBRARY_PATH}" export LD_LIBRARY_PATH="\${HERE}"/opt/v2rayN/:"\${LD_LIBRARY_PATH}"
cd "\${HERE}/opt/v2rayN"
exec "\${HERE}/opt/v2rayN/v2rayN" \$@ exec "\${HERE}/opt/v2rayN/v2rayN" \$@
EOF EOF
@@ -45,9 +48,41 @@ EOF
sudo cp "${PackagePath}/AppDir/opt/v2rayN/v2rayN.png" "${PackagePath}/AppDir/v2rayN.png" sudo cp "${PackagePath}/AppDir/opt/v2rayN/v2rayN.png" "${PackagePath}/AppDir/v2rayN.png"
sudo dpkg --add-architecture ${Arch3} sudo dpkg --add-architecture ${Arch3}
sudo apt update
mkdir deb_folder mkdir deb_folder
cd deb_folder cd deb_folder
apt download libicu74:${Arch3} apt download libstdc++6:${Arch3}
apt download libc6:${Arch3}
apt download libcrypt1:${Arch3}
apt download libgcc-s1:${Arch3}
apt download libidn2-0:${Arch3}
apt download gcc-12-base:${Arch3}
apt download zlib1g:${Arch3}
apt download libfreetype6:${Arch3}
apt download libexpat1:${Arch3}
apt download libbrotli1:${Arch3}
apt download libx11-6:${Arch3}
apt download libx11-xcb1:${Arch3}
apt download libxcb1:${Arch3}
apt download libxau6:${Arch3}
apt download libxdmcp6:${Arch3}
apt download libbsd0:${Arch3}
apt download libmd0:${Arch3}
apt download libice6:${Arch3}
apt download libsm6:${Arch3}
apt download libuuid1:${Arch3}
apt download libxrandr2:${Arch3}
apt download libxext6:${Arch3}
apt download libxrender1:${Arch3}
apt download libxi6:${Arch3}
apt download libsm6:${Arch3}
apt download libxcursor1:${Arch3}
apt download libxfixes3:${Arch3}
apt download libpng16-16:${Arch3} || true
apt download libpng16-16t64:${Arch3} || true
apt download libicu66:${Arch3} || true
apt download libicu70:${Arch3} || true
apt download libicu74:${Arch3} || true
apt download libfontconfig1:${Arch3} || true apt download libfontconfig1:${Arch3} || true
apt download libfontconfig:${Arch3} || true apt download libfontconfig:${Arch3} || true
mkdir ../output_folder mkdir ../output_folder
@@ -62,9 +97,15 @@ rm -rf deb_folder output_folder
sudo chmod 0755 "${PackagePath}/AppDir/opt/v2rayN/v2rayN" sudo chmod 0755 "${PackagePath}/AppDir/opt/v2rayN/v2rayN"
sudo chmod 0755 "${PackagePath}/AppDir/AppRun" sudo chmod 0755 "${PackagePath}/AppDir/AppRun"
sudo apt install -y patchelf
pushd "${PackagePath}/AppDir/opt/v2rayN"
patchelf --set-interpreter ${Interpreter} v2rayN
popd
# desktop && PATH # desktop && PATH
wget "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" wget "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod a+x appimagetool-x86_64.AppImage chmod a+x appimagetool-x86_64.AppImage
sudo apt install -y libfuse2 sudo apt install -y libfuse2
sudo ./appimagetool-x86_64.AppImage "${PackagePath}/AppDir" sudo ./appimagetool-x86_64.AppImage "${PackagePath}/AppDir"

View File

@@ -1,33 +1,32 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>7.7.1</Version> <Version>7.8.3</Version>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow> <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<NoWarn>CA1031;CS1591;NU1507</NoWarn> <NoWarn>CA1031;CS1591;NU1507;CA1416</NoWarn>
<Nullable>annotations</Nullable> <Nullable>annotations</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Authors>2dust</Authors> <Authors>2dust</Authors>
<PackageLicenseExpression>GPL-3.0</PackageLicenseExpression> <PackageLicenseExpression>GPL-3.0</PackageLicenseExpression>
<Copyright>Copyright © 2017-$([System.DateTime]::UtcNow.Year) $(Authors)</Copyright> <Copyright>Copyright © 2017-$([System.DateTime]::UtcNow.Year) $(Authors)</Copyright>
<InvariantGlobalization>false</InvariantGlobalization> <InvariantGlobalization>false</InvariantGlobalization>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'"> <PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType>embedded</DebugType> <DebugType>embedded</DebugType>
<EventSourceSupport>false</EventSourceSupport> <EventSourceSupport>false</EventSourceSupport>
<StackTraceSupport>false</StackTraceSupport> <StackTraceSupport>false</StackTraceSupport>
<MetricsSupport>false</MetricsSupport> <MetricsSupport>false</MetricsSupport>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport> <MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization> <EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding> <EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
<UseSystemResourceKeys>true</UseSystemResourceKeys> <UseSystemResourceKeys>true</UseSystemResourceKeys>
<PublishSingleFile>true</PublishSingleFile> <PublishSingleFile>true</PublishSingleFile>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> </PropertyGroup>
</PropertyGroup>
</Project> </Project>

View File

@@ -1,33 +1,30 @@
<Project> <Project>
<PropertyGroup>
<PropertyGroup> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> <CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled> <CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled> </PropertyGroup>
</PropertyGroup> <ItemGroup>
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.2.3" />
<ItemGroup> <PackageVersion Include="Avalonia.Desktop" Version="11.2.3" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.2.3"/> <PackageVersion Include="Avalonia.Diagnostics" Version="11.2.3" />
<PackageVersion Include="Avalonia.Desktop" Version="11.2.3" /> <PackageVersion Include="Avalonia.ReactiveUI" Version="11.2.3" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.2.3" /> <PackageVersion Include="CliWrap" Version="3.7.1" />
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.2.3" /> <PackageVersion Include="Downloader" Version="3.3.3" />
<PackageVersion Include="CliWrap" Version="3.7.1" /> <PackageVersion Include="H.NotifyIcon.Wpf" Version="2.2.0" />
<PackageVersion Include="Downloader" Version="3.3.3" /> <PackageVersion Include="MaterialDesignThemes" Version="5.2.1" />
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.2.0" /> <PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" />
<PackageVersion Include="MaterialDesignThemes" Version="5.2.1" /> <PackageVersion Include="QRCoder" Version="1.6.0" />
<PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" /> <PackageVersion Include="ReactiveUI" Version="20.1.63" />
<PackageVersion Include="QRCoder" Version="1.6.0" /> <PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
<PackageVersion Include="ReactiveUI" Version="20.1.63" /> <PackageVersion Include="ReactiveUI.WPF" Version="20.1.63" />
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" /> <PackageVersion Include="Semi.Avalonia" Version="11.2.1.4" />
<PackageVersion Include="ReactiveUI.WPF" Version="20.1.63" /> <PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.2.1.4" />
<PackageVersion Include="Semi.Avalonia" Version="11.2.1.4" /> <PackageVersion Include="Splat.NLog" Version="15.3.1" />
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.2.1.4" /> <PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
<PackageVersion Include="Splat.NLog" Version="15.2.22" /> <PackageVersion Include="TaskScheduler" Version="2.11.0" />
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" /> <PackageVersion Include="WebDav.Client" Version="2.8.0" />
<PackageVersion Include="TaskScheduler" Version="2.11.0" /> <PackageVersion Include="YamlDotNet" Version="16.3.0" />
<PackageVersion Include="WebDav.Client" Version="2.8.0" /> <PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
<PackageVersion Include="YamlDotNet" Version="16.3.0" /> </ItemGroup>
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
</ItemGroup>
</Project> </Project>

View File

@@ -24,18 +24,18 @@ public static class ProcUtils
if (arguments.Contains(' ')) if (arguments.Contains(' '))
arguments = arguments.AppendQuotes(); arguments = arguments.AppendQuotes();
Process process = new() Process proc = new()
{ {
StartInfo = new ProcessStartInfo StartInfo = new ProcessStartInfo
{ {
UseShellExecute = true, UseShellExecute = true,
FileName = fileName, FileName = fileName,
Arguments = arguments, Arguments = arguments,
WorkingDirectory = dir WorkingDirectory = dir ?? string.Empty
} }
}; };
process.Start(); proc.Start();
return process.Id; return dir is null ? null : proc.Id;
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Enums namespace ServiceLib.Enums
{ {
public enum ECoreType public enum ECoreType
{ {
@@ -12,6 +12,8 @@
sing_box = 24, sing_box = 24,
juicity = 25, juicity = 25,
hysteria2 = 26, hysteria2 = 26,
brook = 27,
overtls = 28,
v2rayN = 99 v2rayN = 99
} }
} }

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Enums namespace ServiceLib.Enums
{ {
public enum EMsgCommand public enum EMsgCommand
{ {
@@ -6,7 +6,6 @@
SendMsgView, SendMsgView,
SendSnackMsg, SendSnackMsg,
RefreshProfiles, RefreshProfiles,
StopSpeedtest,
AppExit AppExit
} }
} }

View File

@@ -1,4 +1,4 @@
namespace ServiceLib namespace ServiceLib
{ {
public class Global public class Global
{ {
@@ -7,17 +7,8 @@
public const string AppName = "v2rayN"; public const string AppName = "v2rayN";
public const string GithubUrl = "https://github.com"; public const string GithubUrl = "https://github.com";
public const string GithubApiUrl = "https://api.github.com/repos"; public const string GithubApiUrl = "https://api.github.com/repos";
public const string V2flyCoreUrl = "https://github.com/v2fly/v2ray-core/releases";
public const string XrayCoreUrl = "https://github.com/XTLS/Xray-core/releases";
public const string NUrl = @"https://github.com/2dust/v2rayN/releases";
public const string MihomoCoreUrl = "https://github.com/MetaCubeX/mihomo/releases";
public const string HysteriaCoreUrl = "https://github.com/apernet/hysteria/releases";
public const string NaiveproxyCoreUrl = "https://github.com/klzgrad/naiveproxy/releases";
public const string TuicCoreUrl = "https://github.com/EAimTY/tuic/releases";
public const string SingboxCoreUrl = "https://github.com/SagerNet/sing-box/releases";
public const string GeoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/{0}.dat"; public const string GeoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/{0}.dat";
public const string SpeedPingTestUrl = @"https://www.google.com/generate_204"; public const string SpeedPingTestUrl = @"https://www.google.com/generate_204";
public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases";
public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs"; public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs";
public const string IPAPIUrl = "https://api.ip.sb/geoip"; public const string IPAPIUrl = "https://api.ip.sb/geoip";
@@ -81,6 +72,7 @@
public const string LocalAppData = "V2RAYN_LOCAL_APPLICATION_DATA"; public const string LocalAppData = "V2RAYN_LOCAL_APPLICATION_DATA";
public const string V2RayLocalAsset = "V2RAY_LOCATION_ASSET"; public const string V2RayLocalAsset = "V2RAY_LOCATION_ASSET";
public const string XrayLocalAsset = "XRAY_LOCATION_ASSET"; public const string XrayLocalAsset = "XRAY_LOCATION_ASSET";
public const int SpeedTestPageSize = 1000;
public static readonly List<string> IEProxyProtocols = public static readonly List<string> IEProxyProtocols =
[ [
@@ -168,27 +160,27 @@
public static readonly Dictionary<EConfigType, string> ProtocolShares = new() public static readonly Dictionary<EConfigType, string> ProtocolShares = new()
{ {
{EConfigType.VMess,"vmess://"}, { EConfigType.VMess, "vmess://" },
{EConfigType.Shadowsocks,"ss://"}, { EConfigType.Shadowsocks, "ss://" },
{EConfigType.SOCKS,"socks://"}, { EConfigType.SOCKS, "socks://" },
{EConfigType.VLESS,"vless://"}, { EConfigType.VLESS, "vless://" },
{EConfigType.Trojan,"trojan://"}, { EConfigType.Trojan, "trojan://" },
{EConfigType.Hysteria2,"hysteria2://"}, { EConfigType.Hysteria2, "hysteria2://" },
{EConfigType.TUIC,"tuic://"}, { EConfigType.TUIC, "tuic://" },
{EConfigType.WireGuard,"wireguard://"} { EConfigType.WireGuard, "wireguard://" }
}; };
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new() public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
{ {
{EConfigType.VMess,"vmess"}, { EConfigType.VMess, "vmess" },
{EConfigType.Shadowsocks,"shadowsocks"}, { EConfigType.Shadowsocks, "shadowsocks" },
{EConfigType.SOCKS,"socks"}, { EConfigType.SOCKS, "socks" },
{EConfigType.HTTP,"http"}, { EConfigType.HTTP, "http" },
{EConfigType.VLESS,"vless"}, { EConfigType.VLESS, "vless" },
{EConfigType.Trojan,"trojan"}, { EConfigType.Trojan, "trojan" },
{EConfigType.Hysteria2,"hysteria2"}, { EConfigType.Hysteria2, "hysteria2" },
{EConfigType.TUIC,"tuic"}, { EConfigType.TUIC, "tuic" },
{EConfigType.WireGuard,"wireguard"} { EConfigType.WireGuard, "wireguard" }
}; };
public static readonly List<string> VmessSecurities = public static readonly List<string> VmessSecurities =
@@ -500,6 +492,23 @@
"http" "http"
]; ];
public static readonly Dictionary<ECoreType, string> CoreUrls = new()
{
{ ECoreType.v2fly, "v2fly/v2ray-core" },
{ ECoreType.v2fly_v5, "v2fly/v2ray-core" },
{ ECoreType.Xray, "XTLS/Xray-core" },
{ ECoreType.sing_box, "SagerNet/sing-box" },
{ ECoreType.mihomo, "MetaCubeX/mihomo" },
{ ECoreType.hysteria, "apernet/hysteria" },
{ ECoreType.hysteria2, "apernet/hysteria" },
{ ECoreType.naiveproxy, "klzgrad/naiveproxy" },
{ ECoreType.tuic, "EAimTY/tuic" },
{ ECoreType.juicity, "juicity/juicity" },
{ ECoreType.brook, "txthinking/brook" },
{ ECoreType.overtls, "ShadowsocksR-Live/overtls" },
{ ECoreType.v2rayN, "2dust/v2rayN" },
};
#endregion const #endregion const
} }
} }

View File

@@ -1,4 +1,4 @@
using static ServiceLib.Models.ClashProxies; using static ServiceLib.Models.ClashProxies;
namespace ServiceLib.Handler namespace ServiceLib.Handler
{ {
@@ -38,63 +38,63 @@ namespace ServiceLib.Handler
public void ClashProxiesDelayTest(bool blAll, List<ClashProxyModel> lstProxy, Action<ClashProxyModel?, string> updateFunc) public void ClashProxiesDelayTest(bool blAll, List<ClashProxyModel> lstProxy, Action<ClashProxyModel?, string> updateFunc)
{ {
Task.Run(() => Task.Run(() =>
{
if (blAll)
{ {
for (int i = 0; i < 5; i++) if (blAll)
{ {
if (_proxies != null) for (var i = 0; i < 5; i++)
{ {
break; if (_proxies != null)
{
break;
}
Task.Delay(5000).Wait();
}
if (_proxies == null)
{
return;
}
lstProxy = new List<ClashProxyModel>();
foreach (KeyValuePair<string, ProxiesItem> kv in _proxies)
{
if (Global.notAllowTestType.Contains(kv.Value.type.ToLower()))
{
continue;
}
lstProxy.Add(new ClashProxyModel()
{
Name = kv.Value.name,
Type = kv.Value.type.ToLower(),
});
} }
Task.Delay(5000).Wait();
} }
if (_proxies == null)
if (lstProxy == null)
{ {
return; return;
} }
lstProxy = new List<ClashProxyModel>(); var urlBase = $"{GetApiUrl()}/proxies";
foreach (KeyValuePair<string, ProxiesItem> kv in _proxies) urlBase += @"/{0}/delay?timeout=10000&url=" + AppHandler.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
var tasks = new List<Task>();
foreach (var it in lstProxy)
{ {
if (Global.notAllowTestType.Contains(kv.Value.type.ToLower())) if (Global.notAllowTestType.Contains(it.Type.ToLower()))
{ {
continue; continue;
} }
lstProxy.Add(new ClashProxyModel() var name = it.Name;
var url = string.Format(urlBase, name);
tasks.Add(Task.Run(async () =>
{ {
Name = kv.Value.name, var result = await HttpClientHelper.Instance.TryGetAsync(url);
Type = kv.Value.type.ToLower(), updateFunc?.Invoke(it, result);
}); }));
} }
} Task.WaitAll(tasks.ToArray());
if (lstProxy == null) Task.Delay(1000).Wait();
{ updateFunc?.Invoke(null, "");
return; });
}
var urlBase = $"{GetApiUrl()}/proxies";
urlBase += @"/{0}/delay?timeout=10000&url=" + AppHandler.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
List<Task> tasks = new List<Task>();
foreach (var it in lstProxy)
{
if (Global.notAllowTestType.Contains(it.Type.ToLower()))
{
continue;
}
var name = it.Name;
var url = string.Format(urlBase, name);
tasks.Add(Task.Run(async () =>
{
var result = await HttpClientHelper.Instance.TryGetAsync(url);
updateFunc?.Invoke(it, result);
}));
}
Task.WaitAll(tasks.ToArray());
Task.Delay(1000).Wait();
updateFunc?.Invoke(null, "");
});
} }
public List<ProxiesItem>? GetClashProxyGroups() public List<ProxiesItem>? GetClashProxyGroups()
@@ -120,7 +120,7 @@ namespace ServiceLib.Handler
try try
{ {
var url = $"{GetApiUrl()}/proxies/{name}"; var url = $"{GetApiUrl()}/proxies/{name}";
Dictionary<string, string> headers = new Dictionary<string, string>(); var headers = new Dictionary<string, string>();
headers.Add("name", nameNode); headers.Add("name", nameNode);
await HttpClientHelper.Instance.PutAsync(url, headers); await HttpClientHelper.Instance.PutAsync(url, headers);
} }
@@ -148,7 +148,7 @@ namespace ServiceLib.Handler
try try
{ {
var url = $"{GetApiUrl()}/configs?force=true"; var url = $"{GetApiUrl()}/configs?force=true";
Dictionary<string, string> headers = new Dictionary<string, string>(); var headers = new Dictionary<string, string>();
headers.Add("path", filePath); headers.Add("path", filePath);
await HttpClientHelper.Instance.PutAsync(url, headers); await HttpClientHelper.Instance.PutAsync(url, headers);
} }

View File

@@ -105,14 +105,9 @@ namespace ServiceLib.Handler
if (Utils.IsNullOrEmpty(config.UiItem.CurrentLanguage)) if (Utils.IsNullOrEmpty(config.UiItem.CurrentLanguage))
{ {
if (Thread.CurrentThread.CurrentCulture.Name.Equals("zh-cn", StringComparison.CurrentCultureIgnoreCase)) config.UiItem.CurrentLanguage = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.Equals("zh", StringComparison.CurrentCultureIgnoreCase)
{ ? Global.Languages.First()
config.UiItem.CurrentLanguage = Global.Languages.First(); : Global.Languages[2];
}
else
{
config.UiItem.CurrentLanguage = Global.Languages[2];
}
} }
config.ConstItem ??= new ConstItem(); config.ConstItem ??= new ConstItem();

View File

@@ -225,7 +225,7 @@ namespace ServiceLib.Handler
StartInfo = new() StartInfo = new()
{ {
FileName = fileName, FileName = fileName,
Arguments = string.Format(coreInfo.Arguments, configPath), Arguments = string.Format(coreInfo.Arguments, coreInfo.AbsolutePath ? Utils.GetConfigPath(configPath) : configPath),
WorkingDirectory = Utils.GetConfigPath(), WorkingDirectory = Utils.GetConfigPath(),
UseShellExecute = false, UseShellExecute = false,
RedirectStandardOutput = displayLog, RedirectStandardOutput = displayLog,
@@ -287,7 +287,7 @@ namespace ServiceLib.Handler
catch (Exception ex) catch (Exception ex)
{ {
Logging.SaveLog(_tag, ex); Logging.SaveLog(_tag, ex);
UpdateFunc(true, ex.Message); UpdateFunc(mayNeedSudo, ex.Message);
return null; return null;
} }
} }

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Handler namespace ServiceLib.Handler
{ {
public sealed class CoreInfoHandler public sealed class CoreInfoHandler
{ {
@@ -44,7 +44,7 @@
} }
if (fileName.IsNullOrEmpty()) if (fileName.IsNullOrEmpty())
{ {
msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.CoreType.ToString()), string.Join(", ", coreInfo.CoreExes.ToArray()), coreInfo.Url); msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo?.CoreType.ToString()), coreInfo?.CoreExes?.LastOrDefault(), coreInfo?.Url);
Logging.SaveLog(msg); Logging.SaveLog(msg);
} }
return fileName; return fileName;
@@ -52,107 +52,102 @@
private void InitCoreInfo() private void InitCoreInfo()
{ {
var urlN = GetCoreUrl(ECoreType.v2rayN);
var urlXray = GetCoreUrl(ECoreType.Xray);
var urlMihomo = GetCoreUrl(ECoreType.mihomo);
var urlSingbox = GetCoreUrl(ECoreType.sing_box);
_coreInfo = _coreInfo =
[ [
new CoreInfo new CoreInfo
{ {
CoreType = ECoreType.v2rayN, CoreType = ECoreType.v2rayN,
Url = Global.NUrl, Url = GetCoreUrl(ECoreType.v2rayN),
ReleaseApiUrl = Global.NUrl.Replace(Global.GithubUrl, Global.GithubApiUrl), ReleaseApiUrl = urlN.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.NUrl + "/download/{0}/v2rayN-windows-64.zip", DownloadUrlWin64 = urlN + "/download/{0}/v2rayN-windows-64.zip",
DownloadUrlWinArm64 = Global.NUrl + "/download/{0}/v2rayN-windows-arm64.zip", DownloadUrlWinArm64 = urlN + "/download/{0}/v2rayN-windows-arm64.zip",
DownloadUrlLinux64 = Global.NUrl + "/download/{0}/v2rayN-linux-64.zip", DownloadUrlLinux64 = urlN + "/download/{0}/v2rayN-linux-64.zip",
DownloadUrlLinuxArm64 = Global.NUrl + "/download/{0}/v2rayN-linux-arm64.zip", DownloadUrlLinuxArm64 = urlN + "/download/{0}/v2rayN-linux-arm64.zip",
DownloadUrlOSX64 = Global.NUrl + "/download/{0}/v2rayN-macos-64.zip", DownloadUrlOSX64 = urlN + "/download/{0}/v2rayN-macos-64.zip",
DownloadUrlOSXArm64 = Global.NUrl + "/download/{0}/v2rayN-macos-arm64.zip", DownloadUrlOSXArm64 = urlN + "/download/{0}/v2rayN-macos-arm64.zip",
}, },
new CoreInfo new CoreInfo
{ {
CoreType = ECoreType.v2fly, CoreType = ECoreType.v2fly,
CoreExes = ["wv2ray", "v2ray"], CoreExes = ["v2ray"],
Arguments = "", Arguments = "{0}",
Url = Global.V2flyCoreUrl, Url = GetCoreUrl(ECoreType.v2fly),
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
Match = "V2Ray", Match = "V2Ray",
VersionArg = "-version", VersionArg = "-version",
RedirectInfo = true,
}, },
new CoreInfo new CoreInfo
{ {
CoreType = ECoreType.v2fly_v5, CoreType = ECoreType.v2fly_v5,
CoreExes = ["v2ray"], CoreExes = ["v2ray"],
Arguments = "run -c config.json -format jsonv5", Arguments = "run -c {0} -format jsonv5",
Url = Global.V2flyCoreUrl, Url = GetCoreUrl(ECoreType.v2fly_v5),
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
Match = "V2Ray", Match = "V2Ray",
VersionArg = "version", VersionArg = "version",
RedirectInfo = true,
}, },
new CoreInfo new CoreInfo
{ {
CoreType = ECoreType.Xray, CoreType = ECoreType.Xray,
CoreExes = ["xray", "wxray"], CoreExes = ["xray"],
Arguments = "run -c {0}", Arguments = "run -c {0}",
Url = Global.XrayCoreUrl, Url = GetCoreUrl(ECoreType.Xray),
ReleaseApiUrl = Global.XrayCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl), ReleaseApiUrl = urlXray.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-64.zip", DownloadUrlWin64 = urlXray + "/download/{0}/Xray-windows-64.zip",
DownloadUrlWinArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-arm64-v8a.zip", DownloadUrlWinArm64 = urlXray + "/download/{0}/Xray-windows-arm64-v8a.zip",
DownloadUrlLinux64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-64.zip", DownloadUrlLinux64 = urlXray + "/download/{0}/Xray-linux-64.zip",
DownloadUrlLinuxArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-arm64-v8a.zip", DownloadUrlLinuxArm64 = urlXray + "/download/{0}/Xray-linux-arm64-v8a.zip",
DownloadUrlOSX64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-64.zip", DownloadUrlOSX64 = urlXray + "/download/{0}/Xray-macos-64.zip",
DownloadUrlOSXArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-arm64-v8a.zip", DownloadUrlOSXArm64 = urlXray + "/download/{0}/Xray-macos-arm64-v8a.zip",
Match = "Xray", Match = "Xray",
VersionArg = "-version", VersionArg = "-version",
RedirectInfo = true,
}, },
new CoreInfo new CoreInfo
{ {
CoreType = ECoreType.mihomo, CoreType = ECoreType.mihomo,
CoreExes = ["mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-linux-amd64", "mihomo", "clash"], CoreExes = ["mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-linux-amd64", "clash", "mihomo"],
Arguments = "-f config.json" + PortableMode(), Arguments = "-f {0}" + PortableMode(),
Url = Global.MihomoCoreUrl, Url = GetCoreUrl(ECoreType.mihomo),
ReleaseApiUrl = Global.MihomoCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl), ReleaseApiUrl = urlMihomo.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-amd64-compatible-{0}.zip", DownloadUrlWin64 = urlMihomo + "/download/{0}/mihomo-windows-amd64-compatible-{0}.zip",
DownloadUrlWinArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-arm64-{0}.zip", DownloadUrlWinArm64 = urlMihomo + "/download/{0}/mihomo-windows-arm64-{0}.zip",
DownloadUrlLinux64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz", DownloadUrlLinux64 = urlMihomo + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
DownloadUrlLinuxArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-arm64-{0}.gz", DownloadUrlLinuxArm64 = urlMihomo + "/download/{0}/mihomo-linux-arm64-{0}.gz",
DownloadUrlOSX64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-amd64-compatible-{0}.gz", DownloadUrlOSX64 = urlMihomo + "/download/{0}/mihomo-darwin-amd64-compatible-{0}.gz",
DownloadUrlOSXArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-arm64-{0}.gz", DownloadUrlOSXArm64 = urlMihomo + "/download/{0}/mihomo-darwin-arm64-{0}.gz",
Match = "Mihomo", Match = "Mihomo",
VersionArg = "-v", VersionArg = "-v",
RedirectInfo = true,
}, },
new CoreInfo new CoreInfo
{ {
CoreType = ECoreType.hysteria, CoreType = ECoreType.hysteria,
CoreExes = ["hysteria-windows-amd64", "hysteria"], CoreExes = ["hysteria"],
Arguments = "", Arguments = "",
Url = Global.HysteriaCoreUrl, Url = GetCoreUrl(ECoreType.hysteria),
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
RedirectInfo = true,
}, },
new CoreInfo new CoreInfo
{ {
CoreType = ECoreType.naiveproxy, CoreType = ECoreType.naiveproxy,
CoreExes = ["naiveproxy", "naive"], CoreExes = [ "naive", "naiveproxy"],
Arguments = "config.json", Arguments = "{0}",
Url = Global.NaiveproxyCoreUrl, Url = GetCoreUrl(ECoreType.naiveproxy),
RedirectInfo = false,
}, },
new CoreInfo new CoreInfo
{ {
CoreType = ECoreType.tuic, CoreType = ECoreType.tuic,
CoreExes = ["tuic-client", "tuic"], CoreExes = ["tuic-client", "tuic"],
Arguments = "-c config.json", Arguments = "-c {0}",
Url = Global.TuicCoreUrl, Url = GetCoreUrl(ECoreType.tuic),
RedirectInfo = true,
}, },
new CoreInfo new CoreInfo
@@ -160,15 +155,15 @@
CoreType = ECoreType.sing_box, CoreType = ECoreType.sing_box,
CoreExes = ["sing-box-client", "sing-box"], CoreExes = ["sing-box-client", "sing-box"],
Arguments = "run -c {0} --disable-color", Arguments = "run -c {0} --disable-color",
Url = Global.SingboxCoreUrl, Url = GetCoreUrl(ECoreType.sing_box),
RedirectInfo = true,
ReleaseApiUrl = Global.SingboxCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl), ReleaseApiUrl = urlSingbox.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-amd64.zip", DownloadUrlWin64 = urlSingbox + "/download/{0}/sing-box-{1}-windows-amd64.zip",
DownloadUrlWinArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-arm64.zip", DownloadUrlWinArm64 = urlSingbox + "/download/{0}/sing-box-{1}-windows-arm64.zip",
DownloadUrlLinux64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz", DownloadUrlLinux64 = urlSingbox + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
DownloadUrlLinuxArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz", DownloadUrlLinuxArm64 = urlSingbox + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
DownloadUrlOSX64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz", DownloadUrlOSX64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz",
DownloadUrlOSXArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz", DownloadUrlOSXArm64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz",
Match = "sing-box", Match = "sing-box",
VersionArg = "version", VersionArg = "version",
}, },
@@ -177,8 +172,8 @@
{ {
CoreType = ECoreType.juicity, CoreType = ECoreType.juicity,
CoreExes = ["juicity-client", "juicity"], CoreExes = ["juicity-client", "juicity"],
Arguments = "run -c config.json", Arguments = "run -c {0}",
Url = Global.JuicityCoreUrl Url = GetCoreUrl(ECoreType.juicity)
}, },
new CoreInfo new CoreInfo
@@ -186,17 +181,38 @@
CoreType = ECoreType.hysteria2, CoreType = ECoreType.hysteria2,
CoreExes = ["hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria"], CoreExes = ["hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria"],
Arguments = "", Arguments = "",
Url = Global.HysteriaCoreUrl, Url = GetCoreUrl(ECoreType.hysteria2),
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl), },
RedirectInfo = true,
new CoreInfo
{
CoreType = ECoreType.brook,
CoreExes = ["brook_windows_amd64", "brook_linux_amd64", "brook"],
Arguments = " {0}",
Url = GetCoreUrl(ECoreType.brook),
AbsolutePath = true,
},
new CoreInfo
{
CoreType = ECoreType.overtls,
CoreExes = [ "overtls-bin", "overtls"],
Arguments = "-r client -c {0}",
Url = GetCoreUrl(ECoreType.overtls),
AbsolutePath = false,
} }
]; ];
} }
private string PortableMode() private static string PortableMode()
{ {
return $" -d {Utils.GetBinPath("").AppendQuotes()}"; return $" -d {Utils.GetBinPath("").AppendQuotes()}";
} }
private static string GetCoreUrl(ECoreType eCoreType)
{
return $"{Global.GithubUrl}/{Global.CoreUrls[eCoreType]}/releases";
}
} }
} }

View File

@@ -69,7 +69,7 @@ namespace ServiceLib.Handler.SysProxy
} }
return result; return result;
} }
catch (Exception ex) catch
{ {
SetProxyFallback(strProxy, exceptions, type); SetProxyFallback(strProxy, exceptions, type);
return false; return false;

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Models namespace ServiceLib.Models
{ {
[Serializable] [Serializable]
public class CoreInfo public class CoreInfo
@@ -16,6 +16,6 @@
public string? DownloadUrlOSXArm64 { get; set; } public string? DownloadUrlOSXArm64 { get; set; }
public string? Match { get; set; } public string? Match { get; set; }
public string? VersionArg { get; set; } public string? VersionArg { get; set; }
public bool RedirectInfo { get; set; } public bool AbsolutePath { get; set; }
} }
} }

View File

@@ -4,23 +4,15 @@ namespace ServiceLib.Models
{ {
public class V2rayConfig public class V2rayConfig
{ {
public string? remarks { get; set; }
public Log4Ray log { get; set; } public Log4Ray log { get; set; }
public List<Inbounds4Ray> inbounds { get; set; }
public List<Outbounds4Ray> outbounds { get; set; }
public Stats4Ray? stats { get; set; }
public Metrics4Ray? metrics { get; set; }
public Policy4Ray? policy { get; set; }
public object dns { get; set; } public object dns { get; set; }
public List<Inbounds4Ray> inbounds { get; set; }
public List<Outbounds4Ray> outbounds { get; set; }
public Routing4Ray routing { get; set; } public Routing4Ray routing { get; set; }
public Metrics4Ray? metrics { get; set; }
public Policy4Ray? policy { get; set; }
public Stats4Ray? stats { get; set; }
public string? remarks { get; set; }
} }
public class Stats4Ray public class Stats4Ray

View File

@@ -2094,6 +2094,15 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Starting retesting failed parts, {0} remaining. Press ESC to terminate... 的本地化字符串。
/// </summary>
public static string SpeedtestingTestFailedPart {
get {
return ResourceManager.GetString("SpeedtestingTestFailedPart", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Waiting for testing (press ESC to terminate)... 的本地化字符串。 /// 查找类似 Waiting for testing (press ESC to terminate)... 的本地化字符串。
/// </summary> /// </summary>

View File

@@ -344,10 +344,10 @@
<value>لطفاً DNS سفارشی صحیح را پر کنید</value> <value>لطفاً DNS سفارشی صحیح را پر کنید</value>
</data> </data>
<data name="TransportPathTip1" xml:space="preserve"> <data name="TransportPathTip1" xml:space="preserve">
<value>*ws path</value> <value>* مسیر ws</value>
</data> </data>
<data name="TransportPathTip2" xml:space="preserve"> <data name="TransportPathTip2" xml:space="preserve">
<value>*h2 path</value> <value>* مسیر h2</value>
</data> </data>
<data name="TransportPathTip3" xml:space="preserve"> <data name="TransportPathTip3" xml:space="preserve">
<value>*QUIC key/Kcp seed</value> <value>*QUIC key/Kcp seed</value>
@@ -356,13 +356,13 @@
<value>*grpc serviceName</value> <value>*grpc serviceName</value>
</data> </data>
<data name="TransportRequestHostTip1" xml:space="preserve"> <data name="TransportRequestHostTip1" xml:space="preserve">
<value>*http host Separated by commas (,)</value> <value>*هاست http جدا شده با کاما (،)</value>
</data> </data>
<data name="TransportRequestHostTip2" xml:space="preserve"> <data name="TransportRequestHostTip2" xml:space="preserve">
<value>*ws host</value> <value>*هاست ws</value>
</data> </data>
<data name="TransportRequestHostTip3" xml:space="preserve"> <data name="TransportRequestHostTip3" xml:space="preserve">
<value>*h2 host Separated by commas (,)</value> <value>*هاست h2 با کاما (،) جدا شده است</value>
</data> </data>
<data name="TransportRequestHostTip4" xml:space="preserve"> <data name="TransportRequestHostTip4" xml:space="preserve">
<value>*QUIC securty</value> <value>*QUIC securty</value>
@@ -377,7 +377,7 @@
<value>*QUIC camouflage type</value> <value>*QUIC camouflage type</value>
</data> </data>
<data name="TransportHeaderTypeTip4" xml:space="preserve"> <data name="TransportHeaderTypeTip4" xml:space="preserve">
<value>*grpc mode</value> <value>*حالت grpc</value>
</data> </data>
<data name="LvTLS" xml:space="preserve"> <data name="LvTLS" xml:space="preserve">
<value>TLS</value> <value>TLS</value>
@@ -404,7 +404,7 @@
<value>درحال تست کردن...</value> <value>درحال تست کردن...</value>
</data> </data>
<data name="LabLAN" xml:space="preserve"> <data name="LabLAN" xml:space="preserve">
<value>LAN</value> <value>شبکه محلی</value>
</data> </data>
<data name="LabLocal" xml:space="preserve"> <data name="LabLocal" xml:space="preserve">
<value>محلی</value> <value>محلی</value>
@@ -1393,4 +1393,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve"> <data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>کپی کردن دستور پروکسی در کلیپ بورد</value> <value>کپی کردن دستور پروکسی در کلیپ بورد</value>
</data> </data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>شروع آزمایش مجدد قطعات ناموفق، {0} باقی مانده است. برای خاتمه ESC را فشار دهید...</value>
</data>
</root> </root>

View File

@@ -1393,4 +1393,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve"> <data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value> <value>Copy proxy command to clipboard</value>
</data> </data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
</data>
</root> </root>

View File

@@ -1393,4 +1393,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve"> <data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value> <value>Copy proxy command to clipboard</value>
</data> </data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
</data>
</root> </root>

View File

@@ -1393,4 +1393,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve"> <data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value> <value>Copy proxy command to clipboard</value>
</data> </data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
</data>
</root> </root>

View File

@@ -1390,4 +1390,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve"> <data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>复制终端代理命令至剪贴板</value> <value>复制终端代理命令至剪贴板</value>
</data> </data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>开始对失败部分进行重新测试,剩余 {0} 个。可按 ESC 终止...</value>
</data>
</root> </root>

View File

@@ -1391,4 +1391,7 @@
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve"> <data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>複製終端代理指令至剪貼簿</value> <value>複製終端代理指令至剪貼簿</value>
</data> </data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>開始對失敗部分進行重新測試,剩餘 {0} 個。可按 ESC 終止...</value>
</data>
</root> </root>

View File

@@ -128,7 +128,7 @@ namespace ServiceLib.Services.CoreConfig
//Mixin //Mixin
try try
{ {
MixinContent(fileContent, node); await MixinContent(fileContent, node);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -158,20 +158,21 @@ namespace ServiceLib.Services.CoreConfig
} }
} }
private void MixinContent(Dictionary<string, object> fileContent, ProfileItem node) private async Task MixinContent(Dictionary<string, object> fileContent, ProfileItem node)
{ {
//if (!_config.clashUIItem.enableMixinContent) if (!_config.ClashUIItem.EnableMixinContent)
//{
// return;
//}
var path = Utils.GetConfigPath(Global.ClashMixinConfigFileName);
if (!File.Exists(path))
{ {
return; return;
} }
var txtFile = File.ReadAllText(Utils.GetConfigPath(Global.ClashMixinConfigFileName)); var path = Utils.GetConfigPath(Global.ClashMixinConfigFileName);
if (!File.Exists(path))
{
var mixin = EmbedUtils.GetEmbedText(Global.ClashMixinYaml);
await File.AppendAllTextAsync(path, mixin);
}
var txtFile = await File.ReadAllTextAsync(Utils.GetConfigPath(Global.ClashMixinConfigFileName));
var mixinContent = YamlUtils.FromYaml<Dictionary<string, object>>(txtFile); var mixinContent = YamlUtils.FromYaml<Dictionary<string, object>>(txtFile);
if (mixinContent == null) if (mixinContent == null)

View File

@@ -1,23 +1,94 @@
using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using ReactiveUI;
namespace ServiceLib.Services namespace ServiceLib.Services
{ {
public class SpeedtestService public class SpeedtestService
{ {
private static readonly string _tag = "SpeedtestService";
private Config? _config; private Config? _config;
private Action<SpeedTestResult>? _updateFunc; private Action<SpeedTestResult>? _updateFunc;
private static readonly ConcurrentBag<string> _lstExitLoop = new();
private bool _exitLoop = false; public SpeedtestService(Config config, Action<SpeedTestResult> updateFunc)
private static readonly string _tag = "SpeedtestService";
public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc)
{ {
_config = config; _config = config;
_updateFunc = updateFunc; _updateFunc = updateFunc;
}
public void RunLoop(ESpeedActionType actionType, List<ProfileItem> selecteds)
{
Task.Run(async () =>
{
var exitLoopKey = Utils.GetGuid(false);
_lstExitLoop.Add(exitLoopKey);
var lstSelected = GetClearItem(actionType, selecteds);
await RunAsync(actionType, lstSelected, exitLoopKey);
UpdateFunc("", ResUI.SpeedtestingCompleted);
});
}
public void ExitLoop()
{
if (_lstExitLoop.Count > 0)
{
UpdateFunc("", ResUI.SpeedtestingStop);
_lstExitLoop.Clear();
}
}
private async Task RunAsync(ESpeedActionType actionType, List<ServerTestItem> lstSelected, string exitLoopKey, int pageSize = 0)
{
if (actionType == ESpeedActionType.Tcping)
{
await RunTcpingAsync(lstSelected);
return;
}
if (pageSize <= 0)
{
pageSize = lstSelected.Count < Global.SpeedTestPageSize ? lstSelected.Count : Global.SpeedTestPageSize;
}
var lstTest = GetTestBatchItem(lstSelected, pageSize);
List<ServerTestItem> lstFailed = new();
foreach (var lst in lstTest)
{
var ret = actionType switch
{
ESpeedActionType.Realping => await RunRealPingAsync(lst, exitLoopKey),
ESpeedActionType.Speedtest => await RunSpeedTestAsync(lst, exitLoopKey),
ESpeedActionType.Mixedtest => await RunMixedTestAsync(lst, exitLoopKey),
_ => true
};
if (ret == false)
{
lstFailed.AddRange(lst);
}
await Task.Delay(100);
}
//Retest the failed part
var pageSizeNext = pageSize / 2;
if (lstFailed.Count > 0 && pageSizeNext > 0)
{
if (_lstExitLoop.Any(p => p == exitLoopKey) == false)
{
UpdateFunc("", ResUI.SpeedtestingSkip);
return;
}
UpdateFunc("", string.Format(ResUI.SpeedtestingTestFailedPart, lstFailed.Count));
await RunAsync(actionType, lstFailed, exitLoopKey, pageSizeNext);
}
}
private List<ServerTestItem> GetClearItem(ESpeedActionType actionType, List<ProfileItem> selecteds)
{
var lstSelected = new List<ServerTestItem>(); var lstSelected = new List<ServerTestItem>();
foreach (var it in selecteds) foreach (var it in selecteds)
{ {
@@ -25,10 +96,12 @@ namespace ServiceLib.Services
{ {
continue; continue;
} }
if (it.Port <= 0) if (it.Port <= 0)
{ {
continue; continue;
} }
lstSelected.Add(new ServerTestItem() lstSelected.Add(new ServerTestItem()
{ {
IndexId = it.IndexId, IndexId = it.IndexId,
@@ -62,25 +135,11 @@ namespace ServiceLib.Services
} }
} }
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop); return lstSelected;
Task.Run(async () => { await RunAsync(actionType, lstSelected); });
} }
private async Task RunAsync(ESpeedActionType actionType, List<ServerTestItem> lstSelected) private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)
{ {
if (actionType == ESpeedActionType.Tcping)
{
await RunTcpingAsync(lstSelected);
return;
}
var pageSize = _config.SpeedTestItem.SpeedTestPageSize;
if (pageSize is <= 0 or > 1000)
{
pageSize = 1000;
}
List<List<ServerTestItem>> lstTest = new(); List<List<ServerTestItem>> lstTest = new();
var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard)).ToList(); var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard)).ToList();
var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard).ToList(); var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard).ToList();
@@ -94,35 +153,7 @@ namespace ServiceLib.Services
lstTest.Add(lst2.Skip(num * pageSize).Take(pageSize).ToList()); lstTest.Add(lst2.Skip(num * pageSize).Take(pageSize).ToList());
} }
foreach (var lst in lstTest) return lstTest;
{
switch (actionType)
{
case ESpeedActionType.Realping:
await RunRealPingAsync(lst);
break;
case ESpeedActionType.Speedtest:
await RunSpeedTestAsync(lst);
break;
case ESpeedActionType.Mixedtest:
await RunMixedTestAsync(lst);
break;
}
await Task.Delay(100);
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
}
private void ExitLoop(string x)
{
if (_exitLoop)
return;
_exitLoop = true;
UpdateFunc("", ResUI.SpeedtestingStop);
} }
private async Task RunTcpingAsync(List<ServerTestItem> selecteds) private async Task RunTcpingAsync(List<ServerTestItem> selecteds)
@@ -164,7 +195,7 @@ namespace ServiceLib.Services
} }
} }
private async Task RunRealPingAsync(List<ServerTestItem> selecteds) private async Task<bool> RunRealPingAsync(List<ServerTestItem> selecteds, string exitLoopKey)
{ {
var pid = -1; var pid = -1;
try try
@@ -172,8 +203,7 @@ namespace ServiceLib.Services
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds); pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
if (pid < 0) if (pid < 0)
{ {
UpdateFunc("", ResUI.FailedToRunCore); return false;
return;
} }
var downloadHandle = new DownloadService(); var downloadHandle = new DownloadService();
@@ -221,16 +251,16 @@ namespace ServiceLib.Services
} }
await ProfileExHandler.Instance.SaveTo(); await ProfileExHandler.Instance.SaveTo();
} }
return true;
} }
private async Task RunSpeedTestAsync(List<ServerTestItem> selecteds) private async Task<bool> RunSpeedTestAsync(List<ServerTestItem> selecteds, string exitLoopKey)
{ {
var pid = -1; var pid = -1;
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds); pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
if (pid < 0) if (pid < 0)
{ {
UpdateFunc("", ResUI.FailedToRunCore); return false;
return;
} }
var url = _config.SpeedTestItem.SpeedTestUrl; var url = _config.SpeedTestItem.SpeedTestUrl;
@@ -240,11 +270,12 @@ namespace ServiceLib.Services
foreach (var it in selecteds) foreach (var it in selecteds)
{ {
if (_exitLoop) if (_lstExitLoop.Any(p => p == exitLoopKey) == false)
{ {
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip); UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
continue; continue;
} }
if (!it.AllowTest) if (!it.AllowTest)
{ {
continue; continue;
@@ -283,16 +314,16 @@ namespace ServiceLib.Services
await ProcUtils.ProcessKill(pid); await ProcUtils.ProcessKill(pid);
} }
await ProfileExHandler.Instance.SaveTo(); await ProfileExHandler.Instance.SaveTo();
return true;
} }
private async Task RunSpeedTestMulti(List<ServerTestItem> selecteds) private async Task<bool> RunSpeedTestMultiAsync(List<ServerTestItem> selecteds, string exitLoopKey)
{ {
var pid = -1; var pid = -1;
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds); pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
if (pid < 0) if (pid < 0)
{ {
UpdateFunc("", ResUI.FailedToRunCore); return false;
return;
} }
var url = _config.SpeedTestItem.SpeedTestUrl; var url = _config.SpeedTestItem.SpeedTestUrl;
@@ -302,7 +333,7 @@ namespace ServiceLib.Services
foreach (var it in selecteds) foreach (var it in selecteds)
{ {
if (_exitLoop) if (_lstExitLoop.Any(p => p == exitLoopKey) == false)
{ {
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip); UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
continue; continue;
@@ -348,21 +379,30 @@ namespace ServiceLib.Services
await ProcUtils.ProcessKill(pid); await ProcUtils.ProcessKill(pid);
} }
await ProfileExHandler.Instance.SaveTo(); await ProfileExHandler.Instance.SaveTo();
return true;
} }
private async Task RunMixedTestAsync(List<ServerTestItem> selecteds) private async Task<bool> RunMixedTestAsync(List<ServerTestItem> selecteds, string exitLoopKey)
{ {
await RunRealPingAsync(selecteds); var ret = await RunRealPingAsync(selecteds, exitLoopKey);
if (ret == false)
{
return false;
}
await Task.Delay(1000); await Task.Delay(1000);
await RunSpeedTestMulti(selecteds); var ret2 = await RunSpeedTestMultiAsync(selecteds, exitLoopKey);
if (ret2 == false)
{
return false;
}
return true;
} }
private async Task<string> GetRealPingTime(DownloadService downloadHandle, IWebProxy webProxy) private async Task<string> GetRealPingTime(DownloadService downloadHandle, IWebProxy webProxy)
{ {
var responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10); var responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
//string output = Utile.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status;
return FormatOut(responseTime, Global.DelayUnit); return FormatOut(responseTime, Global.DelayUnit);
} }

View File

@@ -21,7 +21,7 @@ namespace ServiceLib.Services.Statistics
Task.Run(Run); Task.Run(Run);
} }
private async void Init() private async Task Init()
{ {
await Task.Delay(5000); await Task.Delay(5000);
@@ -53,9 +53,9 @@ namespace ServiceLib.Services.Statistics
} }
} }
private async void Run() private async Task Run()
{ {
Init(); await Init();
while (!_exitFlag) while (!_exitFlag)
{ {
@@ -73,7 +73,7 @@ namespace ServiceLib.Services.Statistics
{ {
webSocket.Abort(); webSocket.Abort();
webSocket = null; webSocket = null;
Init(); await Init();
continue; continue;
} }

View File

@@ -23,7 +23,7 @@ namespace ServiceLib.Services.Statistics
_exitFlag = true; _exitFlag = true;
} }
private async void Run() private async Task Run()
{ {
while (!_exitFlag) while (!_exitFlag)
{ {

View File

@@ -243,7 +243,7 @@ namespace ServiceLib.Services
_updateFunc?.Invoke(true, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, "geo")); _updateFunc?.Invoke(true, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, "geo"));
} }
public async Task RunAvailabilityCheck(Action<bool, string> updateFunc) public async Task<string> RunAvailabilityCheck()
{ {
var downloadHandle = new DownloadService(); var downloadHandle = new DownloadService();
var time = await downloadHandle.RunAvailabilityCheck(null); var time = await downloadHandle.RunAvailabilityCheck(null);
@@ -255,7 +255,7 @@ namespace ServiceLib.Services
ip = $"({ipInfo?.country_code}) {ipInfo?.ip}"; ip = $"({ipInfo?.country_code}) {ipInfo?.ip}";
} }
updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time, ip)); return string.Format(ResUI.TestMeOutput, time, ip);
} }
#region CheckUpdate private #region CheckUpdate private

View File

@@ -287,14 +287,15 @@ namespace ServiceLib.ViewModels
try try
{ {
Logging.SaveLog("MyAppExitAsync Begin"); Logging.SaveLog("MyAppExitAsync Begin");
await SysProxyHandler.UpdateSysProxy(_config, true);
MessageBus.Current.SendMessage("", EMsgCommand.AppExit.ToString()); MessageBus.Current.SendMessage("", EMsgCommand.AppExit.ToString());
await ConfigHandler.SaveConfig(_config); await ConfigHandler.SaveConfig(_config);
await SysProxyHandler.UpdateSysProxy(_config, true);
await ProfileExHandler.Instance.SaveTo(); await ProfileExHandler.Instance.SaveTo();
await StatisticsHandler.Instance.SaveTo(); await StatisticsHandler.Instance.SaveTo();
StatisticsHandler.Instance.Close();
await CoreHandler.Instance.CoreStop(); await CoreHandler.Instance.CoreStop();
StatisticsHandler.Instance.Close();
Logging.SaveLog("MyAppExitAsync End"); Logging.SaveLog("MyAppExitAsync End");
} }

View File

@@ -63,7 +63,7 @@ namespace ServiceLib.ViewModels
[Reactive] public int SpeedTestTimeout { get; set; } [Reactive] public int SpeedTestTimeout { get; set; }
[Reactive] public string SpeedTestUrl { get; set; } [Reactive] public string SpeedTestUrl { get; set; }
[Reactive] public string SpeedPingTestUrl { get; set; } [Reactive] public string SpeedPingTestUrl { get; set; }
[Reactive] public int SpeedTestPageSize { get; set; } //[Reactive] public int SpeedTestPageSize { get; set; }
[Reactive] public bool EnableHWA { get; set; } [Reactive] public bool EnableHWA { get; set; }
[Reactive] public string SubConvertUrl { get; set; } [Reactive] public string SubConvertUrl { get; set; }
[Reactive] public int MainGirdOrientation { get; set; } [Reactive] public int MainGirdOrientation { get; set; }
@@ -178,7 +178,7 @@ namespace ServiceLib.ViewModels
CurrentFontFamily = _config.UiItem.CurrentFontFamily; CurrentFontFamily = _config.UiItem.CurrentFontFamily;
SpeedTestTimeout = _config.SpeedTestItem.SpeedTestTimeout; SpeedTestTimeout = _config.SpeedTestItem.SpeedTestTimeout;
SpeedTestUrl = _config.SpeedTestItem.SpeedTestUrl; SpeedTestUrl = _config.SpeedTestItem.SpeedTestUrl;
SpeedTestPageSize = _config.SpeedTestItem.SpeedTestPageSize; //SpeedTestPageSize = _config.SpeedTestItem.SpeedTestPageSize;
SpeedPingTestUrl = _config.SpeedTestItem.SpeedPingTestUrl; SpeedPingTestUrl = _config.SpeedTestItem.SpeedPingTestUrl;
EnableHWA = _config.GuiItem.EnableHWA; EnableHWA = _config.GuiItem.EnableHWA;
SubConvertUrl = _config.ConstItem.SubConvertUrl; SubConvertUrl = _config.ConstItem.SubConvertUrl;
@@ -332,7 +332,7 @@ namespace ServiceLib.ViewModels
_config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit; _config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;
_config.UiItem.CurrentFontFamily = CurrentFontFamily; _config.UiItem.CurrentFontFamily = CurrentFontFamily;
_config.SpeedTestItem.SpeedTestTimeout = SpeedTestTimeout; _config.SpeedTestItem.SpeedTestTimeout = SpeedTestTimeout;
_config.SpeedTestItem.SpeedTestPageSize = SpeedTestPageSize; //_config.SpeedTestItem.SpeedTestPageSize = SpeedTestPageSize;
_config.SpeedTestItem.SpeedTestUrl = SpeedTestUrl; _config.SpeedTestItem.SpeedTestUrl = SpeedTestUrl;
_config.SpeedTestItem.SpeedPingTestUrl = SpeedPingTestUrl; _config.SpeedTestItem.SpeedPingTestUrl = SpeedPingTestUrl;
_config.GuiItem.EnableHWA = EnableHWA; _config.GuiItem.EnableHWA = EnableHWA;

View File

@@ -16,6 +16,7 @@ namespace ServiceLib.ViewModels
private List<ProfileItem> _lstProfile; private List<ProfileItem> _lstProfile;
private string _serverFilter = string.Empty; private string _serverFilter = string.Empty;
private Dictionary<string, bool> _dicHeaderSort = new(); private Dictionary<string, bool> _dicHeaderSort = new();
private SpeedtestService? _speedtestService;
#endregion private prop #endregion private prop
@@ -259,11 +260,6 @@ namespace ServiceLib.ViewModels
Locator.Current.GetService<MainWindowViewModel>()?.Reload(); Locator.Current.GetService<MainWindowViewModel>()?.Reload();
} }
private void UpdateSpeedtestHandler(SpeedTestResult result)
{
_updateView?.Invoke(EViewAction.DispatcherSpeedTest, result);
}
public void SetSpeedTestResult(SpeedTestResult result) public void SetSpeedTestResult(SpeedTestResult result)
{ {
if (Utils.IsNullOrEmpty(result.IndexId)) if (Utils.IsNullOrEmpty(result.IndexId))
@@ -272,7 +268,7 @@ namespace ServiceLib.ViewModels
NoticeHandler.Instance.Enqueue(result.Delay); NoticeHandler.Instance.Enqueue(result.Delay);
return; return;
} }
var item = _profileItems.Where(it => it.IndexId == result.IndexId).FirstOrDefault(); var item = _profileItems.FirstOrDefault(it => it.IndexId == result.IndexId);
if (item != null) if (item != null)
{ {
if (Utils.IsNotEmpty(result.Delay)) if (Utils.IsNotEmpty(result.Delay))
@@ -293,7 +289,7 @@ namespace ServiceLib.ViewModels
{ {
try try
{ {
var item = _profileItems.Where(it => it.IndexId == update.IndexId).FirstOrDefault(); var item = _profileItems.FirstOrDefault(it => it.IndexId == update.IndexId);
if (item != null) if (item != null)
{ {
item.TodayDown = Utils.HumanFy(update.TodayDown); item.TodayDown = Utils.HumanFy(update.TodayDown);
@@ -726,14 +722,14 @@ namespace ServiceLib.ViewModels
{ {
return; return;
} }
//ClearTestResult();
_ = new SpeedtestService(_config, lstSelecteds, actionType, UpdateSpeedtestHandler); _speedtestService ??= new SpeedtestService(_config, (SpeedTestResult result) => _updateView?.Invoke(EViewAction.DispatcherSpeedTest, result));
_speedtestService?.RunLoop(actionType, lstSelecteds);
} }
public void ServerSpeedtestStop() public void ServerSpeedtestStop()
{ {
MessageBus.Current.SendMessage("", EMsgCommand.StopSpeedtest.ToString()); _speedtestService?.ExitLoop();
} }
private async Task Export2ClientConfigAsync(bool blClipboard) private async Task Export2ClientConfigAsync(bool blClipboard)

View File

@@ -311,11 +311,11 @@ namespace ServiceLib.ViewModels
{ {
return; return;
} }
await (new UpdateService()).RunAvailabilityCheck(async (bool success, string msg) =>
{ var msg = await (new UpdateService()).RunAvailabilityCheck();
NoticeHandler.Instance.SendMessageEx(msg);
_updateView?.Invoke(EViewAction.DispatcherServerAvailability, msg); NoticeHandler.Instance.SendMessageEx(msg);
}); _updateView?.Invoke(EViewAction.DispatcherServerAvailability, msg);
} }
public void TestServerAvailabilityResult(string msg) public void TestServerAvailabilityResult(string msg)

View File

@@ -350,7 +350,7 @@ namespace v2rayN.Desktop.Views
//ShowHideWindow(false); //ShowHideWindow(false);
NoticeHandler.Instance.SendMessageAndEnqueue("Not yet implemented.(还未实现)"); NoticeHandler.Instance.SendMessageAndEnqueue("Not yet implemented.(还未实现)");
return; await Task.CompletedTask;
//if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) //if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
//{ //{
// //var bytes = QRCodeHelper.CaptureScreen(desktop); // //var bytes = QRCodeHelper.CaptureScreen(desktop);

View File

@@ -1,4 +1,4 @@
<Window <Window
x:Class="v2rayN.Desktop.Views.OptionSettingWindow" x:Class="v2rayN.Desktop.Views.OptionSettingWindow"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -518,7 +518,7 @@
Classes="Margin8" Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyLinuxTip}" Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyLinuxTip}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<!--
<TextBlock <TextBlock
Grid.Row="16" Grid.Row="16"
Grid.Column="0" Grid.Column="0"
@@ -532,7 +532,7 @@
Width="200" Width="200"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Classes="Margin8" /> Classes="Margin8" />
-->
<TextBlock <TextBlock
Grid.Row="17" Grid.Row="17"
Grid.Column="0" Grid.Column="0"

View File

@@ -139,7 +139,7 @@ namespace v2rayN.Desktop.Views
this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestPageSize, v => v.txtSpeedTestPageSize.Text).DisposeWith(disposables); //this.Bind(ViewModel, vm => vm.SpeedTestPageSize, v => v.txtSpeedTestPageSize.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables);

View File

@@ -219,7 +219,7 @@ namespace v2rayN.Desktop.Views
private void LstProfiles_LoadingRow(object? sender, DataGridRowEventArgs e) private void LstProfiles_LoadingRow(object? sender, DataGridRowEventArgs e)
{ {
e.Row.Header = $" {e.Row.GetIndex() + 1}"; e.Row.Header = $" {e.Row.Index + 1}";
} }
//private void LstProfiles_ColumnHeader_Click(object? sender, RoutedEventArgs e) //private void LstProfiles_ColumnHeader_Click(object? sender, RoutedEventArgs e)

View File

@@ -10,7 +10,6 @@ namespace v2rayN
public partial class App : Application public partial class App : Application
{ {
public static EventWaitHandle ProgramStarted; public static EventWaitHandle ProgramStarted;
private static Config _config;
public App() public App()
{ {

View File

@@ -1,4 +1,4 @@
<reactiveui:ReactiveWindow <reactiveui:ReactiveWindow
x:Class="v2rayN.Views.OptionSettingWindow" x:Class="v2rayN.Views.OptionSettingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -776,7 +776,7 @@
Style="{StaticResource ToolbarTextBlock}" Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}" Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<!--
<TextBlock <TextBlock
Grid.Row="16" Grid.Row="16"
Grid.Column="0" Grid.Column="0"
@@ -792,7 +792,7 @@
Margin="{StaticResource Margin8}" Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" /> Style="{StaticResource DefTextBox}" />
-->
<TextBlock <TextBlock
Grid.Row="17" Grid.Row="17"
Grid.Column="0" Grid.Column="0"

View File

@@ -150,7 +150,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SpeedTestPageSize, v => v.txtSpeedTestPageSize.Text).DisposeWith(disposables); //this.Bind(ViewModel, vm => vm.SpeedTestPageSize, v => v.txtSpeedTestPageSize.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableHWA, v => v.togEnableHWA.IsChecked).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.EnableHWA, v => v.togEnableHWA.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);