Compare commits

..

35 Commits
7.5.6 ... 7.6.2

Author SHA1 Message Date
2dust
43c95422b7 up 7.6.2 2025-01-15 19:49:14 +08:00
esmaiel777
2662243641 Update dns_singbox_normal (#6511) 2025-01-15 19:47:45 +08:00
esmaiel777
060a35e091 Update tun_singbox_dns (#6510) 2025-01-15 19:47:34 +08:00
2dust
de1132c2df Added option to display real-time speed 2025-01-15 19:45:53 +08:00
2dust
f19edc9370 Improvements and Adjustments
InitCoreInfo()
2025-01-15 17:31:13 +08:00
2dust
f1601c463b Improvements and Adjustments
await Task.CompletedTask;
return await Task.FromResult(0);
2025-01-15 17:26:15 +08:00
2dust
77b15cd530 Add a prompt for not setting a password when open Tun on macos 2025-01-15 11:02:49 +08:00
2dust
a6479fe0d0 Update build-windows.yml 2025-01-14 18:15:45 +08:00
2dust
4ad4e27dc1 Improve reload function 2025-01-14 17:05:13 +08:00
2dust
7370684985 Improve delete expired files 2025-01-14 17:04:43 +08:00
2dust
5ae58e6a98 Improve reload function 2025-01-14 14:49:17 +08:00
2dust
780ccb1932 Improved ProfileItemsEx 2025-01-14 11:48:02 +08:00
2dust
6b4076be10 up 7.6.1 2025-01-12 19:36:19 +08:00
alphax-hue3682
d7a04a15ae Update Persian translate (#6487) 2025-01-12 19:33:57 +08:00
2dust
2ae43f8bdb Revert "Remove rules custom Icon"
This reverts commit d3ebc17a10.
2025-01-12 19:33:23 +08:00
2dust
d3ebc17a10 Remove rules custom Icon 2025-01-12 14:35:59 +08:00
2dust
7a8680711e Improvements and Adjustments 2025-01-12 14:30:49 +08:00
2dust
649e89e7af Added Copy Terminal proxy command to clipboard in tray menu
https://github.com/2dust/v2rayN/issues/6482
2025-01-12 11:07:34 +08:00
2dust
cb94d64395 Bug fix 2025-01-11 19:35:32 +08:00
2dust
2440dc2440 Remove deprecated DefIEProxyExceptions 2025-01-11 19:34:04 +08:00
Little丶Dreams
364a24c580 CloneServerStatItem 时检查indexId和toIndexId是否相同 (#6478) 2025-01-11 14:44:09 +08:00
2dust
8f3e0dbd82 up 7.6.0 2025-01-11 11:48:57 +08:00
alphax-hue3682
596234df26 Update Persian translate (#6465)
* Update ResUI.fa-Ir.resx

e0ae101ff4

* Update ResUI.fa-Ir.resx
2025-01-11 11:30:06 +08:00
2dust
c38aec50dc Delete unused resources 2025-01-11 11:28:35 +08:00
2dust
40915b5f98 Adjust theme options for windows 2025-01-11 11:23:40 +08:00
2dust
a176613119 Bug fix for ProcUtils 2025-01-11 10:44:34 +08:00
2dust
6c6de1ae7f Improvements and Adjustments 2025-01-10 20:12:42 +08:00
2dust
edbd168dcf Add theme options for desktop 2025-01-10 15:53:06 +08:00
2dust
127858d582 Adjust UI for desktop 2025-01-10 14:23:03 +08:00
2dust
baf90cfbdd Sing-box cache file specified path
https://github.com/2dust/v2rayN/issues/6460
2025-01-10 10:00:00 +08:00
2dust
1a5eeb9401 Adjust UI for desktop 2025-01-09 21:03:17 +08:00
2dust
e0ae101ff4 Adjust UI for desktop 2025-01-09 15:14:03 +08:00
Long Yixing
8b4a07dfe8 Modify the macos build script (#6461)
No longer generate AppIcon.icns
2025-01-09 10:21:07 +08:00
2dust
db934e70cb The icon of the system proxy can be customized
https://github.com/2dust/v2rayN/issues/6459
2025-01-08 20:35:33 +08:00
2dust
b770048f05 The exported routing rules are compatible with the import function of v2rayNG 2025-01-08 17:57:23 +08:00
95 changed files with 1066 additions and 1085 deletions

View File

@@ -29,6 +29,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Setup
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Build
run: |
cd v2rayN

View File

@@ -7,22 +7,10 @@ Version="$3"
PackagePath="v2rayN-Package-${Arch}"
mkdir -p "$PackagePath/v2rayN.app/Contents/Resources"
cp -rf "$OutputPath" "$PackagePath/v2rayN.app/Contents/MacOS"
cp -f "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.icns" "$PackagePath/v2rayN.app/Contents/Resources/AppIcon.icns"
echo "When this file exists, app will not store configs under this folder" > "$PackagePath/v2rayN.app/Contents/MacOS/NotStoreConfigHere.txt"
chmod +x "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN"
mkdir -p "$PackagePath/icons.iconset"
sips -z 16 16 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_16x16.png"
sips -z 32 32 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_16x16@2x.png"
sips -z 32 32 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_32x32.png"
sips -z 64 64 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_32x32@2x.png"
sips -z 128 128 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_128x128.png"
sips -z 256 256 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_128x128@2x.png"
sips -z 256 256 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_256x256.png"
sips -z 512 512 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_256x256@2x.png"
sips -z 512 512 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_512x512.png"
sips -z 1024 1024 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_512x512@2x.png"
iconutil -c icns "$PackagePath/icons.iconset" -o "$PackagePath/v2rayN.app/Contents/Resources/AppIcon.icns"
cat >"$PackagePath/v2rayN.app/Contents/Info.plist" <<-EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

View File

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

View File

@@ -10,7 +10,7 @@ namespace AmazTool
{
Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
Waiting(3);
Waiting(5);
if (!File.Exists(fileName))
{

View File

@@ -196,5 +196,26 @@ namespace ServiceLib.Common
}
}
}
public static void DeleteExpiredFiles(string sourceDir, DateTime dtLine)
{
try
{
var files = Directory.GetFiles(sourceDir, "*.*");
foreach (var filePath in files)
{
var file = new FileInfo(filePath);
if (file.CreationTime >= dtLine)
{
continue;
}
file.Delete();
}
}
catch
{
// ignored
}
}
}
}

View File

@@ -97,6 +97,30 @@ namespace ServiceLib.Common
return result;
}
/// <summary>
/// Serialize Object to Json string
/// </summary>
/// <param name="obj"></param>
/// <param name="options"></param>
/// <returns></returns>
public static string Serialize(object? obj, JsonSerializerOptions options)
{
var result = string.Empty;
try
{
if (obj == null)
{
return result;
}
result = JsonSerializer.Serialize(obj, options);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return result;
}
/// <summary>
/// SerializeToNode
/// </summary>

View File

@@ -25,36 +25,6 @@ namespace ServiceLib.Common
}
}
public static void ClearLogs()
{
Task.Run(() =>
{
try
{
var now = DateTime.Now.AddMonths(-1);
var dir = Utils.GetLogPath();
var files = Directory.GetFiles(dir, "*.txt");
foreach (var filePath in files)
{
var file = new FileInfo(filePath);
if (file.CreationTime >= now) continue;
try
{
file.Delete();
}
catch
{
// ignored
}
}
}
catch
{
// ignored
}
});
}
public static void SaveLog(string strContent)
{
if (!LogManager.IsLoggingEnabled()) return;

View File

@@ -81,9 +81,7 @@ public static class ProcUtils
return;
}
var procId = review ? proc?.Id : null;
var fileName = review ? proc?.MainModule?.FileName : null;
var processName = review ? proc?.ProcessName : null;
GetProcessKeyInfo(proc, review, out var procId, out var fileName, out var processName);
try { proc?.Kill(true); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
try { proc?.Kill(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
@@ -91,6 +89,29 @@ public static class ProcUtils
try { proc?.Dispose(); } catch (Exception ex) { Logging.SaveLog(_tag, ex); }
await Task.Delay(300);
await ProcessKillByKeyInfo(review, procId, fileName, processName);
}
private static void GetProcessKeyInfo(Process? proc, bool review, out int? procId, out string? fileName, out string? processName)
{
procId = null;
fileName = null;
processName = null;
if (!review) return;
try
{
procId = proc?.Id;
fileName = proc?.MainModule?.FileName;
processName = proc?.ProcessName;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
private static async Task ProcessKillByKeyInfo(bool review, int? procId, string? fileName, string? processName)
{
if (review && procId != null && fileName != null)
{
try

View File

@@ -558,7 +558,7 @@ namespace ServiceLib.Common
public static string GetRuntimeInfo()
{
return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion} | {(Environment.Is64BitOperatingSystem ? 64 : 32)}";
return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion}";
}
/// <summary>

View File

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

View File

@@ -63,13 +63,14 @@
public const string HttpProtocol = "http://";
public const string HttpsProtocol = "https://";
public const string SocksProtocol = "socks://";
public const string Socks5Protocol = "socks5://";
public const string UserEMail = "t@t.tt";
public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
public const string AutoRunName = "v2rayNAutoRun";
public const string CustomIconName = "v2rayN.ico";
public const string SystemProxyExceptionsWindows = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
public const string SystemProxyExceptionsLinux = "localhost, 127.0.0.0/8, ::1";
public const string SystemProxyExceptionsLinux = "localhost,127.0.0.0/8,::1";
public const string RoutingRuleComma = "<COMMA>";
public const string GrpcGunMode = "gun";
public const string GrpcMultiMode = "multi";

View File

@@ -79,7 +79,8 @@
{
Logging.SaveLog($"v2rayN start up | {Utils.GetRuntimeInfo()}");
Logging.LoggingEnabled(_config.GuiItem.EnableLog);
Logging.ClearLogs();
ClearExpiredFiles();
return true;
}
@@ -91,6 +92,15 @@
return true;
}
private void ClearExpiredFiles()
{
Task.Run(() =>
{
FileManager.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1));
FileManager.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1));
});
}
#endregion Init
#region Config
@@ -106,7 +116,13 @@
if (Utils.IsWindows())
{
_processJob ??= new();
_processJob?.AddProcess(processHandle);
try
{
_processJob?.AddProcess(processHandle);
}
catch
{
}
}
}
@@ -119,7 +135,7 @@
return await SQLiteHelper.Instance.TableAsync<SubItem>().OrderBy(t => t.Sort).ToListAsync();
}
public async Task<SubItem?> GetSubItem(string subid)
public async Task<SubItem?> GetSubItem(string? subid)
{
return await SQLiteHelper.Instance.TableAsync<SubItem>().FirstOrDefaultAsync(t => t.Id == subid);
}
@@ -164,45 +180,6 @@
return await SQLiteHelper.Instance.QueryAsync<ProfileItemModel>(sql);
}
public async Task<List<ProfileItemModel>?> ProfileItemsEx(string subid, string filter)
{
var lstModel = await ProfileItems(_config.SubIndexId, filter);
await ConfigHandler.SetDefaultServer(_config, lstModel);
var lstServerStat = (_config.GuiItem.EnableStatistics ? StatisticsHandler.Instance.ServerStat : null) ?? [];
var lstProfileExs = await ProfileExHandler.Instance.GetProfileExs();
lstModel = (from t in lstModel
join t2 in lstServerStat on t.IndexId equals t2.IndexId into t2b
from t22 in t2b.DefaultIfEmpty()
join t3 in lstProfileExs on t.IndexId equals t3.IndexId into t3b
from t33 in t3b.DefaultIfEmpty()
select new ProfileItemModel
{
IndexId = t.IndexId,
ConfigType = t.ConfigType,
Remarks = t.Remarks,
Address = t.Address,
Port = t.Port,
Security = t.Security,
Network = t.Network,
StreamSecurity = t.StreamSecurity,
Subid = t.Subid,
SubRemarks = t.SubRemarks,
IsActive = t.IndexId == _config.IndexId,
Sort = t33 == null ? 0 : t33.Sort,
Delay = t33 == null ? 0 : t33.Delay,
DelayVal = t33?.Delay != 0 ? $"{t33?.Delay} {Global.DelayUnit}" : string.Empty,
SpeedVal = t33?.Speed != 0 ? $"{t33?.Speed} {Global.SpeedUnit}" : string.Empty,
TodayDown = t22 == null ? "" : Utils.HumanFy(t22.TodayDown),
TodayUp = t22 == null ? "" : Utils.HumanFy(t22.TodayUp),
TotalDown = t22 == null ? "" : Utils.HumanFy(t22.TotalDown),
TotalUp = t22 == null ? "" : Utils.HumanFy(t22.TotalUp)
}).OrderBy(t => t.Sort).ToList();
return lstModel;
}
public async Task<ProfileItem?> GetProfileItem(string indexId)
{
if (Utils.IsNullOrEmpty(indexId))

View File

@@ -45,6 +45,8 @@ namespace ServiceLib.Handler
{
AutoStartTaskService(autoRunName, "", "");
}
await Task.CompletedTask;
}
private static async Task SetTaskWindows()
@@ -66,6 +68,7 @@ namespace ServiceLib.Handler
{
Logging.SaveLog(_tag, ex);
}
await Task.CompletedTask;
}
/// <summary>
@@ -127,6 +130,7 @@ namespace ServiceLib.Handler
{
Logging.SaveLog(_tag, ex);
}
await Task.CompletedTask;
}
private static async Task SetTaskLinux()

View File

@@ -94,10 +94,7 @@ namespace ServiceLib.Handler
EnableTun = false,
Mtu = 9000,
};
config.GuiItem ??= new()
{
EnableStatistics = false,
};
config.GuiItem ??= new();
config.MsgUIItem ??= new();
config.UiItem ??= new UIItem()
@@ -163,11 +160,6 @@ namespace ServiceLib.Handler
Interval = "10-20"
};
if (Utils.IsNotEmpty(config.ConstItem.DefIEProxyExceptions))
{
config.SystemProxyItem.SystemProxyExceptions = $"{config.ConstItem.DefIEProxyExceptions};{config.SystemProxyItem.SystemProxyExceptions}";
config.ConstItem.DefIEProxyExceptions = string.Empty;
}
if (config.SystemProxyItem.SystemProxyExceptions.IsNullOrEmpty())
{
config.SystemProxyItem.SystemProxyExceptions = Utils.IsWindows() ? Global.SystemProxyExceptionsWindows : Global.SystemProxyExceptionsLinux;
@@ -477,7 +469,7 @@ namespace ServiceLib.Handler
}
ProfileExHandler.Instance.SetSort(lstProfile[index].IndexId, sort);
return 0;
return await Task.FromResult(0);
}
/// <summary>
@@ -1055,7 +1047,7 @@ namespace ServiceLib.Handler
Port = node.PreSocksPort.Value,
};
}
await Task.CompletedTask;
return itemSocks;
}
@@ -1625,7 +1617,7 @@ namespace ServiceLib.Handler
break;
}
}
return 0;
return await Task.FromResult(0);
}
public static async Task<int> SetDefaultRouting(Config config, RoutingItem routingItem)

View File

@@ -80,7 +80,7 @@
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
ret.Success = true;
return ret;
return await Task.FromResult(ret);
}
catch (Exception ex)
{

View File

@@ -67,13 +67,17 @@ namespace ServiceLib.Handler
return;
}
UpdateFunc(true, $"{node.GetSummary()}");
UpdateFunc(false, $"{node.GetSummary()}");
UpdateFunc(false, $"{Utils.GetRuntimeInfo()}");
UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
await CoreStop();
await Task.Delay(100);
await CoreStart(node);
await CoreStartPreService(node);
if (_process != null)
{
UpdateFunc(true, $"{node.GetSummary()}");
}
}
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
@@ -220,8 +224,6 @@ namespace ServiceLib.Handler
await RunProcessAsLinuxSudo(proc, fileName, coreInfo, configPath);
}
var startUpErrorMessage = new StringBuilder();
var startUpSuccessful = false;
if (displayLog)
{
proc.OutputDataReceived += (sender, e) =>
@@ -233,11 +235,6 @@ namespace ServiceLib.Handler
{
if (Utils.IsNullOrEmpty(e.Data)) return;
UpdateFunc(false, e.Data + Environment.NewLine);
if (!startUpSuccessful)
{
startUpErrorMessage.Append(e.Data + Environment.NewLine);
}
};
}
proc.Start();
@@ -258,17 +255,12 @@ namespace ServiceLib.Handler
proc.BeginErrorReadLine();
}
if (proc.WaitForExit(1000))
{
proc.CancelErrorRead();
throw new Exception(displayLog ? startUpErrorMessage.ToString() : "启动进程失败并退出 (Failed to start the process and exited)");
}
else
{
startUpSuccessful = true;
}
await Task.Delay(500);
AppHandler.Instance.AddProcess(proc.Handle);
if (proc is null or { HasExited: true })
{
throw new Exception(ResUI.FailedToRunCore);
}
return proc;
}
catch (Exception ex)

View File

@@ -52,144 +52,146 @@
private void InitCoreInfo()
{
_coreInfo = [];
_coreInfo =
[
new CoreInfo
{
CoreType = ECoreType.v2rayN,
Url = Global.NUrl,
ReleaseApiUrl = Global.NUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.NUrl + "/download/{0}/v2rayN-windows-64.zip",
DownloadUrlWinArm64 = Global.NUrl + "/download/{0}/v2rayN-windows-arm64.zip",
DownloadUrlLinux64 = Global.NUrl + "/download/{0}/v2rayN-linux-64.zip",
DownloadUrlLinuxArm64 = Global.NUrl + "/download/{0}/v2rayN-linux-arm64.zip",
DownloadUrlOSX64 = Global.NUrl + "/download/{0}/v2rayN-macos-64.zip",
DownloadUrlOSXArm64 = Global.NUrl + "/download/{0}/v2rayN-macos-arm64.zip",
},
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.v2rayN,
Url = Global.NUrl,
ReleaseApiUrl = Global.NUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.NUrl + "/download/{0}/v2rayN-windows-64.zip",
DownloadUrlWinArm64 = Global.NUrl + "/download/{0}/v2rayN-windows-arm64.zip",
DownloadUrlLinux64 = Global.NUrl + "/download/{0}/v2rayN-linux-64.zip",
DownloadUrlLinuxArm64 = Global.NUrl + "/download/{0}/v2rayN-linux-arm64.zip",
DownloadUrlOSX64 = Global.NUrl + "/download/{0}/v2rayN-macos-64.zip",
DownloadUrlOSXArm64 = Global.NUrl + "/download/{0}/v2rayN-macos-arm64.zip",
});
new CoreInfo
{
CoreType = ECoreType.v2fly,
CoreExes = ["wv2ray", "v2ray"],
Arguments = "",
Url = Global.V2flyCoreUrl,
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
Match = "V2Ray",
VersionArg = "-version",
RedirectInfo = true,
},
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.v2fly,
CoreExes = new List<string> { "wv2ray", "v2ray" },
Arguments = "",
Url = Global.V2flyCoreUrl,
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
Match = "V2Ray",
VersionArg = "-version",
RedirectInfo = true,
});
new CoreInfo
{
CoreType = ECoreType.v2fly_v5,
CoreExes = ["v2ray"],
Arguments = "run -c config.json -format jsonv5",
Url = Global.V2flyCoreUrl,
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
Match = "V2Ray",
VersionArg = "version",
RedirectInfo = true,
},
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.v2fly_v5,
CoreExes = new List<string> { "v2ray" },
Arguments = "run -c config.json -format jsonv5",
Url = Global.V2flyCoreUrl,
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
Match = "V2Ray",
VersionArg = "version",
RedirectInfo = true,
});
new CoreInfo
{
CoreType = ECoreType.Xray,
CoreExes = ["xray", "wxray"],
Arguments = "run -c {0}",
Url = Global.XrayCoreUrl,
ReleaseApiUrl = Global.XrayCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-64.zip",
DownloadUrlWinArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-arm64-v8a.zip",
DownloadUrlLinux64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-64.zip",
DownloadUrlLinuxArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-arm64-v8a.zip",
DownloadUrlOSX64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-64.zip",
DownloadUrlOSXArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-arm64-v8a.zip",
Match = "Xray",
VersionArg = "-version",
RedirectInfo = true,
},
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.Xray,
CoreExes = new List<string> { "xray", "wxray" },
Arguments = "run -c {0}",
Url = Global.XrayCoreUrl,
ReleaseApiUrl = Global.XrayCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-64.zip",
DownloadUrlWinArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-arm64-v8a.zip",
DownloadUrlLinux64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-64.zip",
DownloadUrlLinuxArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-arm64-v8a.zip",
DownloadUrlOSX64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-64.zip",
DownloadUrlOSXArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-arm64-v8a.zip",
Match = "Xray",
VersionArg = "-version",
RedirectInfo = true,
});
new CoreInfo
{
CoreType = ECoreType.mihomo,
CoreExes = ["mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-linux-amd64", "mihomo", "clash"],
Arguments = "-f config.json" + PortableMode(),
Url = Global.MihomoCoreUrl,
ReleaseApiUrl = Global.MihomoCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-amd64-compatible-{0}.zip",
DownloadUrlWinArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-arm64-{0}.zip",
DownloadUrlLinux64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
DownloadUrlLinuxArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-arm64-{0}.gz",
DownloadUrlOSX64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-amd64-compatible-{0}.gz",
DownloadUrlOSXArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-arm64-{0}.gz",
Match = "Mihomo",
VersionArg = "-v",
RedirectInfo = true,
},
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.mihomo,
CoreExes = new List<string> { "mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-linux-amd64", "mihomo", "clash" },
Arguments = "-f config.json" + PortableMode(),
Url = Global.MihomoCoreUrl,
ReleaseApiUrl = Global.MihomoCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-amd64-compatible-{0}.zip",
DownloadUrlWinArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-arm64-{0}.zip",
DownloadUrlLinux64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
DownloadUrlLinuxArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-arm64-{0}.gz",
DownloadUrlOSX64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-amd64-compatible-{0}.gz",
DownloadUrlOSXArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-arm64-{0}.gz",
Match = "Mihomo",
VersionArg = "-v",
RedirectInfo = true,
});
new CoreInfo
{
CoreType = ECoreType.hysteria,
CoreExes = ["hysteria-windows-amd64", "hysteria"],
Arguments = "",
Url = Global.HysteriaCoreUrl,
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
RedirectInfo = true,
},
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.hysteria,
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria" },
Arguments = "",
Url = Global.HysteriaCoreUrl,
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
RedirectInfo = true,
});
new CoreInfo
{
CoreType = ECoreType.naiveproxy,
CoreExes = ["naiveproxy", "naive"],
Arguments = "config.json",
Url = Global.NaiveproxyCoreUrl,
RedirectInfo = false,
},
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.naiveproxy,
CoreExes = new List<string> { "naiveproxy", "naive" },
Arguments = "config.json",
Url = Global.NaiveproxyCoreUrl,
RedirectInfo = false,
});
new CoreInfo
{
CoreType = ECoreType.tuic,
CoreExes = ["tuic-client", "tuic"],
Arguments = "-c config.json",
Url = Global.TuicCoreUrl,
RedirectInfo = true,
},
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.tuic,
CoreExes = new List<string> { "tuic-client", "tuic" },
Arguments = "-c config.json",
Url = Global.TuicCoreUrl,
RedirectInfo = true,
});
new CoreInfo
{
CoreType = ECoreType.sing_box,
CoreExes = ["sing-box-client", "sing-box"],
Arguments = "run -c {0} --disable-color",
Url = Global.SingboxCoreUrl,
RedirectInfo = true,
ReleaseApiUrl = Global.SingboxCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-amd64.zip",
DownloadUrlWinArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-arm64.zip",
DownloadUrlLinux64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
DownloadUrlLinuxArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
DownloadUrlOSX64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz",
DownloadUrlOSXArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz",
Match = "sing-box",
VersionArg = "version",
},
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.sing_box,
CoreExes = new List<string> { "sing-box-client", "sing-box" },
Arguments = "run -c {0} --disable-color",
Url = Global.SingboxCoreUrl,
RedirectInfo = true,
ReleaseApiUrl = Global.SingboxCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-amd64.zip",
DownloadUrlWinArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-arm64.zip",
DownloadUrlLinux64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
DownloadUrlLinuxArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
DownloadUrlOSX64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz",
DownloadUrlOSXArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz",
Match = "sing-box",
VersionArg = "version",
});
new CoreInfo
{
CoreType = ECoreType.juicity,
CoreExes = ["juicity-client", "juicity"],
Arguments = "run -c config.json",
Url = Global.JuicityCoreUrl
},
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.juicity,
CoreExes = new List<string> { "juicity-client", "juicity" },
Arguments = "run -c config.json",
Url = Global.JuicityCoreUrl
});
new CoreInfo
{
CoreType = ECoreType.hysteria2,
CoreExes = ["hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria"],
Arguments = "",
Url = Global.HysteriaCoreUrl,
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
RedirectInfo = true,
}
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.hysteria2,
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria" },
Arguments = "",
Url = Global.HysteriaCoreUrl,
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
RedirectInfo = true,
});
];
}
private string PortableMode()

View File

@@ -20,7 +20,7 @@ namespace ServiceLib.Handler
public async Task Init()
{
await InitData();
Task.Run(async () =>
_ = Task.Run(async () =>
{
while (true)
{
@@ -32,7 +32,7 @@ namespace ServiceLib.Handler
public async Task<ConcurrentBag<ProfileExItem>> GetProfileExs()
{
return _lstProfileEx;
return await Task.FromResult(_lstProfileEx);
}
private async Task InitData()

View File

@@ -19,15 +19,13 @@
{
_config = config;
_updateFunc = updateFunc;
if (!config.GuiItem.EnableStatistics)
if (config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)
{
return;
await InitData();
_statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler);
_statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler);
}
await InitData();
_statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler);
_statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler);
}
public void Close()
@@ -72,6 +70,11 @@
return;
}
if (indexId == toIndexId)
{
return;
}
var stat = _lstServerStat.FirstOrDefault(t => t.IndexId == indexId);
if (stat == null)
{
@@ -96,7 +99,7 @@
private void UpdateServerStatHandler(ServerSpeedItem server)
{
UpdateServerStat(server);
_ = UpdateServerStat(server);
}
private async Task UpdateServerStat(ServerSpeedItem server)

View File

@@ -16,7 +16,7 @@
try
{
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
var exceptions = config.SystemProxyItem.SystemProxyExceptions;
var exceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
if (port <= 0)
{
return false;
@@ -68,7 +68,7 @@
private static void GetWindowsProxyString(Config config, int port, out string strProxy, out string strExceptions)
{
strExceptions = config.SystemProxyItem.SystemProxyExceptions;
strExceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
if (config.SystemProxyItem.NotProxyLocalAddress)
{
strExceptions = $"<local>;{strExceptions}";

View File

@@ -29,7 +29,7 @@
public string? destinationPort { get; set; }
public string? host { get; set; }
public string? nsMode { get; set; }
public object uid { get; set; }
public object? uid { get; set; }
public string? process { get; set; }
public string? processPath { get; set; }
public string? remoteDestination { get; set; }

View File

@@ -67,21 +67,13 @@
public class GUIItem
{
public bool AutoRun { get; set; }
public bool EnableStatistics { get; set; }
public bool DisplayRealTimeSpeed { get; set; }
public bool KeepOlderDedupl { get; set; }
public bool IgnoreGeoUpdateCore { get; set; } = true;
public int AutoUpdateInterval { get; set; }
public bool EnableSecurityProtocolTls13 { get; set; }
public int TrayMenuServersLimit { get; set; } = 20;
public bool EnableHWA { get; set; } = false;
public bool EnableLog { get; set; } = true;
}
@@ -102,9 +94,8 @@
public double MainGirdHeight1 { get; set; }
public double MainGirdHeight2 { get; set; }
public EGirdOrientation MainGirdOrientation { get; set; } = EGirdOrientation.Vertical;
public bool ColorModeDark { get; set; }
public bool FollowSystemTheme { get; set; }
public string? ColorPrimaryName { get; set; }
public string? CurrentTheme { get; set; }
public string CurrentLanguage { get; set; }
public string CurrentFontFamily { get; set; }
public int CurrentFontSize { get; set; }
@@ -119,8 +110,7 @@
[Serializable]
public class ConstItem
{
public string DefIEProxyExceptions { get; set; }
public string SubConvertUrl { get; set; } = string.Empty;
public string? SubConvertUrl { get; set; }
public string? GeoSourceUrl { get; set; }
public string? SrsSourceUrl { get; set; }
public string? RouteRulesTemplateSourceUrl { get; set; }

View File

@@ -843,6 +843,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Copy proxy command to clipboard 的本地化字符串。
/// </summary>
public static string menuCopyProxyCmdToClipboard {
get {
return ResourceManager.GetString("menuCopyProxyCmdToClipboard", resourceCulture);
}
}
/// <summary>
/// 查找类似 Clone selected server 的本地化字符串。
/// </summary>
@@ -942,15 +951,6 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Import old config (guiNConfig) 的本地化字符串。
/// </summary>
public static string menuImportOldGuiConfig {
get {
return ResourceManager.GetString("menuImportOldGuiConfig", resourceCulture);
}
}
/// <summary>
/// 查找类似 Import Rules From Clipboard 的本地化字符串。
/// </summary>
@@ -1348,7 +1348,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Import Advanced Rules 的本地化字符串。
/// 查找类似 Import Rules 的本地化字符串。
/// </summary>
public static string menuRoutingAdvancedImportRules {
get {
@@ -1536,15 +1536,6 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Save Interface Layout 的本地化字符串。
/// </summary>
public static string menuStorageUI {
get {
return ResourceManager.GetString("menuStorageUI", resourceCulture);
}
}
/// <summary>
/// 查找类似 Add 的本地化字符串。
/// </summary>
@@ -2356,15 +2347,6 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Enable advanced function 的本地化字符串。
/// </summary>
public static string TbenableRoutingAdvanced {
get {
return ResourceManager.GetString("TbenableRoutingAdvanced", resourceCulture);
}
}
/// <summary>
/// 查找类似 Enable Tun 的本地化字符串。
/// </summary>
@@ -2815,15 +2797,6 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Dark Mode 的本地化字符串。
/// </summary>
public static string TbSettingsColorMode {
get {
return ResourceManager.GetString("TbSettingsColorMode", resourceCulture);
}
}
/// <summary>
/// 查找类似 Core: basic settings 的本地化字符串。
/// </summary>
@@ -2941,6 +2914,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Display real-time speed 的本地化字符串。
/// </summary>
public static string TbSettingsDisplayRealTimeSpeed {
get {
return ResourceManager.GetString("TbSettingsDisplayRealTimeSpeed", resourceCulture);
}
}
/// <summary>
/// 查找类似 Outbound DNS address 的本地化字符串。
/// </summary>
@@ -3094,15 +3076,6 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Follow System Theme 的本地化字符串。
/// </summary>
public static string TbSettingsFollowSystemTheme {
get {
return ResourceManager.GetString("TbSettingsFollowSystemTheme", resourceCulture);
}
}
/// <summary>
/// 查找类似 Font Size 的本地化字符串。
/// </summary>
@@ -3148,15 +3121,6 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Ignore Geo files when updating core 的本地化字符串。
/// </summary>
public static string TbSettingsIgnoreGeoUpdateCore {
get {
return ResourceManager.GetString("TbSettingsIgnoreGeoUpdateCore", resourceCulture);
}
}
/// <summary>
/// 查找类似 Keep older when deduplication 的本地化字符串。
/// </summary>
@@ -3437,7 +3401,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Enable Statistics (Require restart) 的本地化字符串。
/// 查找类似 Enable traffic statistics (Require restart) 的本地化字符串。
/// </summary>
public static string TbSettingsStatistics {
get {
@@ -3463,6 +3427,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Theme 的本地化字符串。
/// </summary>
public static string TbSettingsTheme {
get {
return ResourceManager.GetString("TbSettingsTheme", resourceCulture);
}
}
/// <summary>
/// 查找类似 Enable Security Protocol TLS v1.3 (subscription/update) 的本地化字符串。
/// </summary>

View File

@@ -481,9 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve">
<value>رنگ</value>
</data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>حالت تاریک</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>زبان</value>
</data>
@@ -721,8 +718,8 @@
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>پورت Http</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>هنگام به‌روزرسانی هسته، فایل‌های Geo را نادیده بگیرید</value>
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
<value>Display real-time speed</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>هنگام کپی برداری، نگه داری قدیمی تر ها</value>
@@ -839,7 +836,7 @@
<value>اضافه کردن</value>
</data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>وارد کردن قوانین پیشرفته</value>
<value>وارد کردن مجموعه قوانین</value>
</data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>حذف انتخاب شده</value>
@@ -853,9 +850,6 @@
<data name="TbdomainStrategy" xml:space="preserve">
<value>استراتژی دامنه</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>فعال کردن عملکرد پیشرفته</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3. مسدود کردن دامنه یا آیپی</value>
</data>
@@ -940,9 +934,6 @@
<data name="TbDisplayLog" xml:space="preserve">
<value>نمایش گزارش</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>پیکربندی قدیمی guiNConfig را وارد شود</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>فعال سازی Tun</value>
</data>
@@ -1105,9 +1096,6 @@
<data name="TipActiveServer" xml:space="preserve">
<value>فعال سازی</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>ذخیره طرح رابط</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>منبع فایل های جغرافیایی (اختیاری)</value>
</data>
@@ -1273,9 +1261,6 @@
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
<value>حداکتر پهنای باند هیستریا (آپلود/دانلود)</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>دنبال کردن تم سیستم</value>
</data>
<data name="menuAddTuicServer" xml:space="preserve">
<value>افزودن سرور [TUIC]</value>
</data>
@@ -1402,4 +1387,10 @@
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks:پورت محلی، socks2: پورت دوم محلی، socks3: پورت LAN</value>
</data>
</root>
<data name="TbSettingsTheme" xml:space="preserve">
<value>تم</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>کپی کردن دستور پروکسی در کلیپ بورد</value>
</data>
</root>

View File

@@ -481,12 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve">
<value>Szín</value>
</data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>Sötét mód</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>Kövesse a rendszer témáját</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>Nyelv (Újraindítás)</value>
</data>
@@ -724,8 +718,8 @@
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>HTTP Port</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>Geo fájlok figyelmen kívül hagyása a yalap frissítésekor</value>
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
<value>Display real-time speed</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>Régi megőrzése a deduplikáció során</value>
@@ -856,9 +850,6 @@
<data name="TbdomainStrategy" xml:space="preserve">
<value>Domain stratégia</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>Fejlett funkció engedélyezése</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3. Domain vagy IP blokkolása</value>
</data>
@@ -943,9 +934,6 @@
<data name="TbDisplayLog" xml:space="preserve">
<value>Napló megjelenítése</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>Régi konfiguráció importálása (guiNConfig)</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>Tun engedélyezése</value>
</data>
@@ -1318,9 +1306,6 @@
<data name="TipActiveServer" xml:space="preserve">
<value>Aktív</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>Szoftverfelület elmentése</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo fájlok forrása (opcionális)</value>
</data>
@@ -1402,4 +1387,10 @@
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks: local port, socks2: second local port, socks3: LAN port</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>Theme</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value>
</data>
</root>

View File

@@ -481,12 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve">
<value>Color</value>
</data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>Dark Mode</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>Follow System Theme</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>Language (Restart)</value>
</data>
@@ -724,8 +718,8 @@
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>HTTP Port</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>Ignore Geo files when updating core</value>
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
<value>Display real-time speed (Require restart)</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>Keep older when deduplication</value>
@@ -761,7 +755,7 @@
<value>Start on boot</value>
</data>
<data name="TbSettingsStatistics" xml:space="preserve">
<value>Enable Statistics (Require restart)</value>
<value>Enable traffic statistics (Require restart)</value>
</data>
<data name="TbSettingsSubConvert" xml:space="preserve">
<value>Subscription conversion URL</value>
@@ -842,7 +836,7 @@
<value>Add</value>
</data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>Import Advanced Rules</value>
<value>Import Rules</value>
</data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>Remove selected (Delete)</value>
@@ -856,9 +850,6 @@
<data name="TbdomainStrategy" xml:space="preserve">
<value>Domain strategy</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>Enable advanced function</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.Block Domain or IP</value>
</data>
@@ -943,9 +934,6 @@
<data name="TbDisplayLog" xml:space="preserve">
<value>Display Log</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>Import old config (guiNConfig)</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>Enable Tun</value>
</data>
@@ -1318,9 +1306,6 @@
<data name="TipActiveServer" xml:space="preserve">
<value>Active</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>Save Interface Layout</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo files source (optional)</value>
</data>
@@ -1402,4 +1387,10 @@
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks: local port, socks2: second local port, socks3: LAN port</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>Theme</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value>
</data>
</root>

View File

@@ -481,12 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve">
<value>Цвет</value>
</data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>Тёмный режим</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>Следить за системной темой</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>Язык (требуется перезапуск)</value>
</data>
@@ -730,8 +724,8 @@
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>HTTP порт</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>Игнорировать файлы Geo при обновлении ядра</value>
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
<value>Display real-time speed</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>Сохранить старые при удалении дублей</value>
@@ -862,9 +856,6 @@
<data name="TbdomainStrategy" xml:space="preserve">
<value>Доменная стратегия</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>Включить расширенные функции</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.Заблокировать домен или IP</value>
</data>
@@ -949,9 +940,6 @@
<data name="TbDisplayLog" xml:space="preserve">
<value>Показать логи</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>Импортировать старый конфиг guiNConfig</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>Режим VPN</value>
</data>
@@ -1270,9 +1258,6 @@
<data name="LvConvertTarget" xml:space="preserve">
<value>Convert target type</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>Save Interface Layout</value>
</data>
<data name="SpeedDisplayText" xml:space="preserve">
<value>{0} : {1}/s↑ | {2}/s↓</value>
</data>
@@ -1402,4 +1387,10 @@
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks: local port, socks2: second local port, socks3: LAN port</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>Theme</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value>
</data>
</root>

View File

@@ -481,12 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve">
<value>颜色</value>
</data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>暗黑模式</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>跟随系统主题</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>语言(需重启)</value>
</data>
@@ -724,8 +718,8 @@
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>本地http监听端口</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>更新Core时忽略Geo文件</value>
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
<value>显示实时速度(需重启)</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>去重时保留序号较小的项</value>
@@ -761,7 +755,7 @@
<value>开机启动(可能会不成功)</value>
</data>
<data name="TbSettingsStatistics" xml:space="preserve">
<value>启用统计(实时网速显示,需重启)</value>
<value>启用流量统计(需重启</value>
</data>
<data name="TbSettingsSubConvert" xml:space="preserve">
<value>订阅转换网址(可选)</value>
@@ -842,7 +836,7 @@
<value>添加规则集</value>
</data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>一键导入高级规则</value>
<value>一键导入规则</value>
</data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>移除所选规则 (Delete)</value>
@@ -856,9 +850,6 @@
<data name="TbdomainStrategy" xml:space="preserve">
<value>域名解析策略</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>启用高级功能</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.阻止的Domain或IP</value>
</data>
@@ -943,9 +934,6 @@
<data name="TbDisplayLog" xml:space="preserve">
<value>显示日志</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>导入旧的配置文件guiNConfig</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>启用Tun</value>
</data>
@@ -1315,9 +1303,6 @@
<data name="TipActiveServer" xml:space="preserve">
<value>活动</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>保存界面布局</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo文件来源(可选)</value>
</data>
@@ -1399,4 +1384,10 @@
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks本地端口socks2第二个本地端口socks3局域网端口</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>主题</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>复制终端代理命令至剪贴板</value>
</data>
</root>

View File

@@ -481,12 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve">
<value>顏色</value>
</data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>暗黑模式</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>跟隨系統主題</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>語言(需重啟)</value>
</data>
@@ -725,8 +719,8 @@
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>本機HTTP偵聽埠</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>更新Core時忽略Geo檔案</value>
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
<value>顯示即時速度(需重啟)</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>去重時保留序號較小的項</value>
@@ -762,7 +756,7 @@
<value>開機啟動(可能會不成功)</value>
</data>
<data name="TbSettingsStatistics" xml:space="preserve">
<value>啟用統計(即時網速顯示,需重啟)</value>
<value>啟用流量統計(需重啟</value>
</data>
<data name="TbSettingsSubConvert" xml:space="preserve">
<value>訂閱轉換網址(可選)</value>
@@ -843,7 +837,7 @@
<value>新增規則集</value>
</data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>一鍵匯入進階規則</value>
<value>一鍵匯入規則</value>
</data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>移除所選規則 (Delete)</value>
@@ -857,9 +851,6 @@
<data name="TbdomainStrategy" xml:space="preserve">
<value>域名解析策略</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>啟動進階功能</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.阻止的Domain或IP</value>
</data>
@@ -944,9 +935,6 @@
<data name="TbDisplayLog" xml:space="preserve">
<value>顯示日誌</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>匯入舊的設定檔guiNConfig</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>啟用Tun</value>
</data>
@@ -1196,9 +1184,6 @@
<data name="TipActiveServer" xml:space="preserve">
<value>活動</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>儲存介面佈局</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo檔案來源(可選)</value>
</data>
@@ -1400,4 +1385,10 @@
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks本地端口socks2第二個本地端口socks3區域網路端口</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>主題</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>複製終端代理指令至剪貼簿</value>
</data>
</root>

View File

@@ -2,7 +2,7 @@
"servers": [
{
"tag": "remote",
"address": "8.8.8.8",
"address": "tcp://8.8.8.8",
"strategy": "prefer_ipv4",
"detour": "proxy"
},
@@ -32,4 +32,4 @@
}
],
"final": "remote"
}
}

View File

@@ -2,7 +2,7 @@
"servers": [
{
"tag": "remote",
"address": "8.8.8.8",
"address": "tcp://8.8.8.8",
"strategy": "prefer_ipv4",
"detour": "proxy"
},
@@ -33,4 +33,4 @@
}
],
"final": "remote"
}
}

View File

@@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>7.5.6</Version>
<Version>7.6.2</Version>
</PropertyGroup>
<ItemGroup>

View File

@@ -476,7 +476,7 @@ namespace ServiceLib.Services.CoreConfig
{
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenInbounds(SingboxConfig singboxConfig)
@@ -721,7 +721,7 @@ namespace ServiceLib.Services.CoreConfig
{
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenOutboundTls(ProfileItem node, Outbound4Sbox outbound)
@@ -771,7 +771,7 @@ namespace ServiceLib.Services.CoreConfig
{
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound)
@@ -848,7 +848,7 @@ namespace ServiceLib.Services.CoreConfig
{
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenMoreOutbounds(ProfileItem node, SingboxConfig singboxConfig)
@@ -1088,7 +1088,7 @@ namespace ServiceLib.Services.CoreConfig
{
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private bool ParseV2Domain(string domain, Rule4Sbox rule)
@@ -1240,7 +1240,7 @@ namespace ServiceLib.Services.CoreConfig
}
singboxConfig.dns = dns4Sbox;
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenExperimental(SingboxConfig singboxConfig)
@@ -1259,11 +1259,12 @@ namespace ServiceLib.Services.CoreConfig
singboxConfig.experimental ??= new Experimental4Sbox();
singboxConfig.experimental.cache_file = new CacheFile4Sbox()
{
enabled = true
enabled = true,
path = Utils.GetConfigPath("cache.db")
};
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> ConvertGeo2Ruleset(SingboxConfig singboxConfig)

View File

@@ -379,7 +379,7 @@ namespace ServiceLib.Services.CoreConfig
{
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenInbounds(V2rayConfig v2rayConfig)
@@ -423,7 +423,7 @@ namespace ServiceLib.Services.CoreConfig
{
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private Inbounds4Ray GetInbound(InItem inItem, EInboundProtocol protocol, bool bSocks)
@@ -560,7 +560,7 @@ namespace ServiceLib.Services.CoreConfig
{
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenOutbound(ProfileItem node, Outbounds4Ray outbound)
@@ -774,7 +774,7 @@ namespace ServiceLib.Services.CoreConfig
{
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenBoundStreamSettings(ProfileItem node, Outbounds4Ray outbound)
@@ -1103,12 +1103,12 @@ namespace ServiceLib.Services.CoreConfig
servers.AsArray().Add(JsonUtils.SerializeToNode(dnsServer));
}
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenStatistic(V2rayConfig v2rayConfig)
{
if (_config.GuiItem.EnableStatistics)
if (_config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)
{
string tag = EInboundProtocol.api.ToString();
Metrics4Ray apiObj = new();
@@ -1150,7 +1150,7 @@ namespace ServiceLib.Services.CoreConfig
v2rayConfig.routing.rules.Add(apiRoutingRule);
}
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenMoreOutbounds(ProfileItem node, V2rayConfig v2rayConfig)

View File

@@ -25,6 +25,7 @@ namespace ServiceLib.ViewModels
BrowseServerCmd = ReactiveCommand.CreateFromTask(async () =>
{
_updateView?.Invoke(EViewAction.BrowseServer, null);
await Task.CompletedTask;
});
EditServerCmd = ReactiveCommand.CreateFromTask(async () =>
{
@@ -109,6 +110,7 @@ namespace ServiceLib.ViewModels
{
NoticeHandler.Instance.Enqueue(ResUI.FailedReadConfiguration);
}
await Task.CompletedTask;
}
}
}

View File

@@ -176,7 +176,7 @@ namespace ServiceLib.ViewModels
FileManager.CopyDirectory(configDir, configDirTemp, false, "cache.db");
var ret = FileManager.CreateFromDirectory(configDirZipTemp, fileName);
Directory.Delete(configDirZipTemp, true);
return ret;
return await Task.FromResult(ret);
}
}
}

View File

@@ -259,7 +259,7 @@ namespace ServiceLib.ViewModels
}
else
{
FileManager.ZipExtractToFile(fileName, toPath, _config.GuiItem.IgnoreGeoUpdateCore ? "geo" : "");
FileManager.ZipExtractToFile(fileName, toPath, "geo");
}
if (Utils.IsNonWindows())

View File

@@ -48,7 +48,7 @@ namespace ServiceLib.ViewModels
await ClashConnectionClose(true);
});
Init();
_ = Init();
}
private async Task Init()
@@ -73,6 +73,7 @@ namespace ServiceLib.ViewModels
Task.Delay(1000).Wait();
}
});
await Task.CompletedTask;
}
private async Task GetClashConnections()

View File

@@ -90,13 +90,13 @@ namespace ServiceLib.ViewModels
y => y == true)
.Subscribe(c => { _config.ClashUIItem.ProxiesAutoRefresh = AutoRefresh; });
Init();
_ = Init();
}
private async Task Init()
{
await ProxiesReload();
DelayTestTask();
_ = DelayTestTask();
}
private async Task DoRulemodeSelected(bool c)
@@ -265,7 +265,7 @@ namespace ServiceLib.ViewModels
return;
}
_proxies.TryGetValue(name, out ProxiesItem proxy);
_proxies.TryGetValue(name, out var proxy);
if (proxy == null || proxy.all == null)
{
return;
@@ -316,7 +316,7 @@ namespace ServiceLib.ViewModels
{
if (_proxies is null)
return null;
_proxies.TryGetValue(name, out ProxiesItem proxy2);
_proxies.TryGetValue(name, out var proxy2);
if (proxy2 != null)
{
return proxy2;
@@ -399,6 +399,7 @@ namespace ServiceLib.ViewModels
_updateView?.Invoke(EViewAction.DispatcherProxiesDelayTest, new SpeedTestResult() { IndexId = item.Name, Delay = result });
});
await Task.CompletedTask;
}
public void ProxiesDelayTestResult(SpeedTestResult result)
@@ -434,7 +435,7 @@ namespace ServiceLib.ViewModels
public async Task DelayTestTask()
{
var lastTime = DateTime.Now;
Task.Run(async () =>
_ = Task.Run(async () =>
{
while (true)
{
@@ -457,6 +458,7 @@ namespace ServiceLib.ViewModels
lastTime = dtNow;
}
});
await Task.CompletedTask;
}
#endregion task

View File

@@ -32,15 +32,17 @@ namespace ServiceLib.ViewModels
ImportDefConfig4V2rayCmd = ReactiveCommand.CreateFromTask(async () =>
{
normalDNS = Utils.GetEmbedText(Global.DNSV2rayNormalFileName);
await Task.CompletedTask;
});
ImportDefConfig4SingboxCmd = ReactiveCommand.CreateFromTask(async () =>
{
normalDNS2 = Utils.GetEmbedText(Global.DNSSingboxNormalFileName);
tunDNS2 = Utils.GetEmbedText(Global.TunSingboxDNSFileName);
await Task.CompletedTask;
});
Init();
_ = Init();
}
private async Task Init()

View File

@@ -63,6 +63,8 @@ namespace ServiceLib.ViewModels
#endregion Menu
private bool _hasNextReloadJob = false;
#region Init
public MainWindowViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
@@ -204,7 +206,7 @@ namespace ServiceLib.ViewModels
#endregion WhenAnyValue && ReactiveCommand
Init();
_ = Init();
}
private async Task Init()
@@ -217,11 +219,12 @@ namespace ServiceLib.ViewModels
await CoreHandler.Instance.Init(_config, UpdateHandler);
TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler);
if (_config.GuiItem.EnableStatistics)
if (_config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)
{
await StatisticsHandler.Instance.Init(_config, UpdateStatisticsHandler);
}
BlReloadEnabled = true;
await Reload();
await AutoHideStartup();
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
@@ -249,7 +252,7 @@ namespace ServiceLib.ViewModels
RefreshServers();
if (indexIdOld != _config.IndexId)
{
Reload();
_ = Reload();
}
if (_config.UiItem.EnableAutoAdjustMainLvColWidth)
{
@@ -269,16 +272,13 @@ namespace ServiceLib.ViewModels
public void SetStatisticsResult(ServerSpeedItem update)
{
try
if (_config.GuiItem.DisplayRealTimeSpeed)
{
Locator.Current.GetService<StatusBarViewModel>()?.UpdateStatistics(update);
if ((update.ProxyUp + update.ProxyDown) > 0 && DateTime.Now.Second % 9 == 0)
{
Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update);
}
}
catch
if (_config.GuiItem.EnableStatistics && (update.ProxyUp + update.ProxyDown) > 0 && DateTime.Now.Second % 9 == 0)
{
Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update);
}
}
@@ -403,6 +403,7 @@ namespace ServiceLib.ViewModels
public async Task AddServerViaScanAsync()
{
_updateView?.Invoke(EViewAction.ScanScreenTask, null);
await Task.CompletedTask;
}
public async Task ScanScreenResult(byte[]? bytes)
@@ -414,6 +415,7 @@ namespace ServiceLib.ViewModels
public async Task AddServerViaImageAsync()
{
_updateView?.Invoke(EViewAction.ScanImageTask, null);
await Task.CompletedTask;
}
public async Task ScanImageResult(string fileName)
@@ -527,6 +529,7 @@ namespace ServiceLib.ViewModels
{
ProcUtils.ProcessStart("open", path);
}
await Task.CompletedTask;
}
#endregion Setting
@@ -535,19 +538,33 @@ namespace ServiceLib.ViewModels
public async Task Reload()
{
//If there are unfinished reload job, marked with next job.
if (!BlReloadEnabled)
{
_hasNextReloadJob = true;
return;
}
BlReloadEnabled = false;
await LoadCore();
Locator.Current.GetService<StatusBarViewModel>()?.TestServerAvailability();
await SysProxyHandler.UpdateSysProxy(_config, false);
Locator.Current.GetService<StatusBarViewModel>()?.TestServerAvailability();
_updateView?.Invoke(EViewAction.DispatcherReload, null);
BlReloadEnabled = true;
if (_hasNextReloadJob)
{
_hasNextReloadJob = false;
await Reload();
}
}
public void ReloadResult()
{
// BlReloadEnabled = true;
//Locator.Current.GetService<StatusBarViewModel>()?.ChangeSystemProxyAsync(_config.systemProxyItem.sysProxyType, false);
BlReloadEnabled = true;
ShowClashUI = _config.IsRunningCore(ECoreType.sing_box);
if (ShowClashUI)
{
@@ -558,16 +575,8 @@ namespace ServiceLib.ViewModels
private async Task LoadCore()
{
//if (_config.tunModeItem.enableTun)
//{
// Task.Delay(1000).Wait();
// WindowsUtils.RemoveTunDevice();
//}
await Task.Run(async () =>
{
var node = await ConfigHandler.GetDefaultServer(_config);
await CoreHandler.Instance.LoadCore(node);
});
var node = await ConfigHandler.GetDefaultServer(_config);
await CoreHandler.Instance.LoadCore(node);
}
public async Task CloseCore()
@@ -582,6 +591,7 @@ namespace ServiceLib.ViewModels
{
ShowHideWindow(false);
}
await Task.CompletedTask;
}
#endregion core job

View File

@@ -59,14 +59,14 @@ namespace ServiceLib.ViewModels
{
return;
}
_blLockShow = true;
if (!_config.UiItem.ShowInTaskbar)
{
await Task.Delay(1000);
return;
}
await Task.Delay(100);
_blLockShow = true;
await Task.Delay(500);
var txt = string.Join("", _queueMsg.ToArray());
await _updateView?.Invoke(EViewAction.DispatcherShowMsg, txt);
@@ -105,6 +105,7 @@ namespace ServiceLib.ViewModels
{
_queueMsg.Enqueue(Environment.NewLine);
}
await Task.CompletedTask;
}
public void ClearMsg()

View File

@@ -49,7 +49,7 @@ namespace ServiceLib.ViewModels
[Reactive] public bool AutoRun { get; set; }
[Reactive] public bool EnableStatistics { get; set; }
[Reactive] public bool KeepOlderDedupl { get; set; }
[Reactive] public bool IgnoreGeoUpdateCore { get; set; }
[Reactive] public bool DisplayRealTimeSpeed { get; set; }
[Reactive] public bool EnableAutoAdjustMainLvColWidth { get; set; }
[Reactive] public bool EnableUpdateSubOnlyRemarksExist { get; set; }
[Reactive] public bool EnableSecurityProtocolTls13 { get; set; }
@@ -115,7 +115,7 @@ namespace ServiceLib.ViewModels
await SaveSettingAsync();
});
Init();
_ = Init();
}
private async Task Init()
@@ -164,8 +164,8 @@ namespace ServiceLib.ViewModels
AutoRun = _config.GuiItem.AutoRun;
EnableStatistics = _config.GuiItem.EnableStatistics;
DisplayRealTimeSpeed = _config.GuiItem.DisplayRealTimeSpeed;
KeepOlderDedupl = _config.GuiItem.KeepOlderDedupl;
IgnoreGeoUpdateCore = _config.GuiItem.IgnoreGeoUpdateCore;
EnableAutoAdjustMainLvColWidth = _config.UiItem.EnableAutoAdjustMainLvColWidth;
EnableUpdateSubOnlyRemarksExist = _config.UiItem.EnableUpdateSubOnlyRemarksExist;
EnableSecurityProtocolTls13 = _config.GuiItem.EnableSecurityProtocolTls13;
@@ -261,6 +261,7 @@ namespace ServiceLib.ViewModels
break;
}
});
await Task.CompletedTask;
}
private async Task SaveSettingAsync()
@@ -272,6 +273,7 @@ namespace ServiceLib.ViewModels
return;
}
var needReboot = (EnableStatistics != _config.GuiItem.EnableStatistics
|| DisplayRealTimeSpeed != _config.GuiItem.DisplayRealTimeSpeed
|| EnableDragDropSort != _config.UiItem.EnableDragDropSort
|| EnableHWA != _config.GuiItem.EnableHWA
|| CurrentFontFamily != _config.UiItem.CurrentFontFamily
@@ -317,8 +319,8 @@ namespace ServiceLib.ViewModels
_config.GuiItem.AutoRun = AutoRun;
_config.GuiItem.EnableStatistics = EnableStatistics;
_config.GuiItem.DisplayRealTimeSpeed = DisplayRealTimeSpeed;
_config.GuiItem.KeepOlderDedupl = KeepOlderDedupl;
_config.GuiItem.IgnoreGeoUpdateCore = IgnoreGeoUpdateCore;
_config.UiItem.EnableAutoAdjustMainLvColWidth = EnableAutoAdjustMainLvColWidth;
_config.UiItem.EnableUpdateSubOnlyRemarksExist = EnableUpdateSubOnlyRemarksExist;
_config.GuiItem.EnableSecurityProtocolTls13 = EnableSecurityProtocolTls13;
@@ -410,6 +412,7 @@ namespace ServiceLib.ViewModels
}
item.CoreType = (ECoreType)Enum.Parse(typeof(ECoreType), type);
}
await Task.CompletedTask;
}
}
}

View File

@@ -231,7 +231,7 @@ namespace ServiceLib.ViewModels
MessageBus.Current.Listen<string>(EMsgCommand.RefreshProfiles.ToString()).Subscribe(OnNext);
}
Init();
_ = Init();
}
private async Task Init()
@@ -360,7 +360,7 @@ namespace ServiceLib.ViewModels
public async Task RefreshServersBiz()
{
var lstModel = await AppHandler.Instance.ProfileItemsEx(_config.SubIndexId, _serverFilter);
var lstModel = await GetProfileItemsEx(_config.SubIndexId, _serverFilter);
_lstProfile = JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(lstModel)) ?? [];
_profileItems.Clear();
@@ -399,6 +399,45 @@ namespace ServiceLib.ViewModels
}
}
private async Task<List<ProfileItemModel>?> GetProfileItemsEx(string subid, string filter)
{
var lstModel = await AppHandler.Instance.ProfileItems(_config.SubIndexId, filter);
await ConfigHandler.SetDefaultServer(_config, lstModel);
var lstServerStat = (_config.GuiItem.EnableStatistics ? StatisticsHandler.Instance.ServerStat : null) ?? [];
var lstProfileExs = await ProfileExHandler.Instance.GetProfileExs();
lstModel = (from t in lstModel
join t2 in lstServerStat on t.IndexId equals t2.IndexId into t2b
from t22 in t2b.DefaultIfEmpty()
join t3 in lstProfileExs on t.IndexId equals t3.IndexId into t3b
from t33 in t3b.DefaultIfEmpty()
select new ProfileItemModel
{
IndexId = t.IndexId,
ConfigType = t.ConfigType,
Remarks = t.Remarks,
Address = t.Address,
Port = t.Port,
Security = t.Security,
Network = t.Network,
StreamSecurity = t.StreamSecurity,
Subid = t.Subid,
SubRemarks = t.SubRemarks,
IsActive = t.IndexId == _config.IndexId,
Sort = t33 == null ? 0 : t33.Sort,
Delay = t33 == null ? 0 : t33.Delay,
DelayVal = t33?.Delay != 0 ? $"{t33?.Delay} {Global.DelayUnit}" : string.Empty,
SpeedVal = t33?.Speed != 0 ? $"{t33?.Speed} {Global.SpeedUnit}" : string.Empty,
TodayDown = t22 == null ? "" : Utils.HumanFy(t22.TodayDown),
TodayUp = t22 == null ? "" : Utils.HumanFy(t22.TodayUp),
TotalDown = t22 == null ? "" : Utils.HumanFy(t22.TotalDown),
TotalUp = t22 == null ? "" : Utils.HumanFy(t22.TotalUp)
}).OrderBy(t => t.Sort).ToList();
return lstModel;
}
#endregion Servers && Groups
#region Add Servers

View File

@@ -2,6 +2,8 @@
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System.Reactive;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ServiceLib.ViewModels
{
@@ -189,7 +191,13 @@ namespace ServiceLib.ViewModels
}
if (lst.Count > 0)
{
await _updateView?.Invoke(EViewAction.SetClipboardData, JsonUtils.Serialize(lst));
var options = new JsonSerializerOptions
{
WriteIndented = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
await _updateView?.Invoke(EViewAction.SetClipboardData, JsonUtils.Serialize(lst, options));
}
}
@@ -249,7 +257,7 @@ namespace ServiceLib.ViewModels
return;
}
string result = Utils.LoadResource(fileName);
var result = Utils.LoadResource(fileName);
if (Utils.IsNullOrEmpty(result))
{
return;

View File

@@ -67,7 +67,7 @@ namespace ServiceLib.ViewModels
await SaveRoutingAsync();
});
Init();
_ = Init();
}
private async Task Init()

View File

@@ -32,6 +32,7 @@ namespace ServiceLib.ViewModels
public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { get; }
public ReactiveCommand<Unit, Unit> SubUpdateCmd { get; }
public ReactiveCommand<Unit, Unit> SubUpdateViaProxyCmd { get; }
public ReactiveCommand<Unit, Unit> CopyProxyCmdToClipboardCmd { get; }
public ReactiveCommand<Unit, Unit> NotifyLeftClickCmd { get; }
#region System Proxy
@@ -48,18 +49,6 @@ namespace ServiceLib.ViewModels
[Reactive]
public bool BlSystemProxyPac { get; set; }
[Reactive]
public bool BlNotSystemProxyClear { get; set; }
[Reactive]
public bool BlNotSystemProxySet { get; set; }
[Reactive]
public bool BlNotSystemProxyNothing { get; set; }
[Reactive]
public bool BlNotSystemProxyPac { get; set; }
public ReactiveCommand<Unit, Unit> SystemProxyClearCmd { get; }
public ReactiveCommand<Unit, Unit> SystemProxySetCmd { get; }
public ReactiveCommand<Unit, Unit> SystemProxyNothingCmd { get; }
@@ -140,9 +129,15 @@ namespace ServiceLib.ViewModels
y => y == true)
.Subscribe(async c => await DoEnableTun(c));
CopyProxyCmdToClipboardCmd = ReactiveCommand.CreateFromTask(async () =>
{
await CopyProxyCmdToClipboard();
});
NotifyLeftClickCmd = ReactiveCommand.CreateFromTask(async () =>
{
Locator.Current.GetService<MainWindowViewModel>()?.ShowHideWindow(null);
await Task.CompletedTask;
});
AddServerViaClipboardCmd = ReactiveCommand.CreateFromTask(async () =>
@@ -186,7 +181,7 @@ namespace ServiceLib.ViewModels
{
InitUpdateView(updateView);
}
Init();
_ = Init();
}
private async Task Init()
@@ -210,6 +205,23 @@ namespace ServiceLib.ViewModels
await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null);
}
private async Task CopyProxyCmdToClipboard()
{
var cmd = Utils.IsWindows() ? "set" : "export";
var address = $"{Global.Loopback}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)}";
var sb = new StringBuilder();
sb.AppendLine($"{cmd} http_proxy={Global.HttpProtocol}{address}");
sb.AppendLine($"{cmd} https_proxy={Global.HttpProtocol}{address}");
sb.AppendLine($"{cmd} all_proxy={Global.Socks5Protocol}{address}");
sb.AppendLine("");
sb.AppendLine($"{cmd} HTTP_PROXY={Global.HttpProtocol}{address}");
sb.AppendLine($"{cmd} HTTPS_PROXY={Global.HttpProtocol}{address}");
sb.AppendLine($"{cmd} ALL_PROXY={Global.Socks5Protocol}{address}");
await _updateView?.Invoke(EViewAction.SetClipboardData, sb.ToString());
}
private async Task AddServerViaClipboard()
{
var service = Locator.Current.GetService<MainWindowViewModel>();
@@ -333,11 +345,6 @@ namespace ServiceLib.ViewModels
BlSystemProxyNothing = (type == ESysProxyType.Unchanged);
BlSystemProxyPac = (type == ESysProxyType.Pac);
BlNotSystemProxyClear = !BlSystemProxyClear;
BlNotSystemProxySet = !BlSystemProxySet;
BlNotSystemProxyNothing = !BlSystemProxyNothing;
BlNotSystemProxyPac = !BlSystemProxyPac;
if (blChange)
{
_updateView?.Invoke(EViewAction.DispatcherRefreshIcon, null);
@@ -417,10 +424,12 @@ namespace ServiceLib.ViewModels
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
return;
}
//else if (Utils.IsLinux())
//{
// NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty);
//}
else if (Utils.IsOSX())
{
_config.TunModeItem.EnableTun = false;
NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty);
return;
}
}
await ConfigHandler.SaveConfig(_config);
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
@@ -470,12 +479,19 @@ namespace ServiceLib.ViewModels
{
InboundLanDisplay = $"{ResUI.LabLAN}:{Global.None}";
}
await Task.CompletedTask;
}
public void UpdateStatistics(ServerSpeedItem update)
{
SpeedProxyDisplay = string.Format(ResUI.SpeedDisplayText, Global.ProxyTag, Utils.HumanFy(update.ProxyUp), Utils.HumanFy(update.ProxyDown));
SpeedDirectDisplay = string.Format(ResUI.SpeedDisplayText, Global.DirectTag, Utils.HumanFy(update.DirectUp), Utils.HumanFy(update.DirectDown));
try
{
SpeedProxyDisplay = string.Format(ResUI.SpeedDisplayText, Global.ProxyTag, Utils.HumanFy(update.ProxyUp), Utils.HumanFy(update.ProxyDown));
SpeedDirectDisplay = string.Format(ResUI.SpeedDisplayText, Global.DirectTag, Utils.HumanFy(update.DirectUp), Utils.HumanFy(update.DirectDown));
}
catch
{
}
}
#endregion UI

View File

@@ -48,7 +48,7 @@ namespace ServiceLib.ViewModels
await _updateView?.Invoke(EViewAction.ShareSub, SelectedSource?.Url);
}, canEditRemove);
Init();
_ = Init();
}
private async Task Init()

View File

@@ -32,38 +32,26 @@
<NativeMenuItem
Command="{Binding SystemProxyClearCmd}"
Header="{x:Static resx:ResUI.menuSystemProxyClear}"
IsVisible="{Binding BlNotSystemProxyClear}" />
<NativeMenuItem
Command="{Binding SystemProxyClearCmd}"
Header="{x:Static resx:ResUI.menuSystemProxyClear}"
Icon="/Assets/NotifyIcon1.ico"
IsVisible="{Binding BlSystemProxyClear}" />
IsChecked="{Binding BlSystemProxyClear}"
ToggleType="Radio" />
<NativeMenuItem
Command="{Binding SystemProxySetCmd}"
Header="{x:Static resx:ResUI.menuSystemProxySet}"
IsVisible="{Binding BlNotSystemProxySet}" />
<NativeMenuItem
Command="{Binding SystemProxySetCmd}"
Header="{x:Static resx:ResUI.menuSystemProxySet}"
Icon="/Assets/NotifyIcon2.ico"
IsVisible="{Binding BlSystemProxySet}" />
IsChecked="{Binding BlSystemProxySet}"
ToggleType="Radio" />
<NativeMenuItem
Command="{Binding SystemProxyNothingCmd}"
Header="{x:Static resx:ResUI.menuSystemProxyNothing}"
IsVisible="{Binding BlNotSystemProxyNothing}" />
<NativeMenuItem
Command="{Binding SystemProxyNothingCmd}"
Header="{x:Static resx:ResUI.menuSystemProxyNothing}"
Icon="/Assets/NotifyIcon3.ico"
IsVisible="{Binding BlSystemProxyNothing}" />
IsChecked="{Binding BlSystemProxyNothing}"
ToggleType="Radio" />
<NativeMenuItemSeparator />
<NativeMenuItem Click="MenuAddServerViaClipboardClick" Header="{x:Static resx:ResUI.menuAddServerViaClipboard}" />
<NativeMenuItem Header="{x:Static resx:ResUI.menuAddServerViaScan}" IsVisible="False" />
<NativeMenuItem Command="{Binding SubUpdateCmd}" Header="{x:Static resx:ResUI.menuSubUpdate}" />
<NativeMenuItem Command="{Binding SubUpdateViaProxyCmd}" Header="{x:Static resx:ResUI.menuSubUpdateViaProxy}" />
<NativeMenuItemSeparator />
<NativeMenuItem Command="{Binding CopyProxyCmdToClipboardCmd}" Header="{x:Static resx:ResUI.menuCopyProxyCmdToClipboard}" />
<NativeMenuItemSeparator />
<NativeMenuItem Command="{Binding NotifyLeftClickCmd}" Header="{x:Static resx:ResUI.menuShowOrHideMainWindow}" />
<NativeMenuItem Click="MenuExit_Click" Header="{x:Static resx:ResUI.menuExit}" />
</NativeMenu>

View File

@@ -40,6 +40,12 @@ namespace v2rayN.Desktop.Common
public static WindowIcon GetAppIcon(ESysProxyType sysProxyType)
{
var index = (int)sysProxyType + 1;
var fileName = Utils.GetPath($"NotifyIcon{index}.ico");
if (File.Exists(fileName))
{
return new(fileName);
}
var uri = new Uri(Path.Combine(Global.AvaAssets, $"NotifyIcon{index}.ico"));
using var bitmap = new Bitmap(AssetLoader.Open(uri));
return new(bitmap);

View File

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

View File

@@ -6,14 +6,14 @@ using Avalonia.Media;
using Avalonia.Styling;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Semi.Avalonia;
using System.Reactive.Linq;
namespace v2rayN.Desktop.ViewModels
{
public class ThemeSettingViewModel : MyReactiveObject
{
[Reactive] public bool ColorModeDark { get; set; }
[Reactive] public bool FollowSystemTheme { get; set; }
[Reactive] public string CurrentTheme { get; set; }
[Reactive] public int CurrentFontSize { get; set; }
@@ -36,28 +36,16 @@ namespace v2rayN.Desktop.ViewModels
private void BindingUI()
{
ColorModeDark = _config.UiItem.ColorModeDark;
FollowSystemTheme = _config.UiItem.FollowSystemTheme;
CurrentTheme = _config.UiItem.CurrentTheme;
CurrentFontSize = _config.UiItem.CurrentFontSize;
CurrentLanguage = _config.UiItem.CurrentLanguage;
this.WhenAnyValue(x => x.ColorModeDark)
this.WhenAnyValue(x => x.CurrentTheme)
.Subscribe(c =>
{
if (_config.UiItem.ColorModeDark != ColorModeDark)
if (_config.UiItem.CurrentTheme != CurrentTheme)
{
_config.UiItem.ColorModeDark = ColorModeDark;
ModifyTheme();
ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(x => x.FollowSystemTheme,
y => y == true)
.Subscribe(c =>
{
if (_config.UiItem.FollowSystemTheme != FollowSystemTheme)
{
_config.UiItem.FollowSystemTheme = FollowSystemTheme;
_config.UiItem.CurrentTheme = CurrentTheme;
ModifyTheme();
ConfigHandler.SaveConfig(_config);
}
@@ -96,7 +84,16 @@ namespace v2rayN.Desktop.ViewModels
var app = Application.Current;
if (app is not null)
{
app.RequestedThemeVariant = FollowSystemTheme ? ThemeVariant.Default : (ColorModeDark ? ThemeVariant.Dark : ThemeVariant.Light);
app.RequestedThemeVariant = CurrentTheme switch
{
nameof(ETheme.Dark) => ThemeVariant.Dark,
nameof(ETheme.Light) => ThemeVariant.Light,
nameof(ETheme.Aquatic) => SemiTheme.Aquatic,
nameof(ETheme.Desert) => SemiTheme.Desert,
nameof(ETheme.Dusk) => SemiTheme.Dusk,
nameof(ETheme.NightSky) => SemiTheme.NightSky,
_ => ThemeVariant.Default,
};
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -150,71 +150,20 @@
x:Name="tabMain1"
Grid.Row="2"
TabStripPlacement="Left">
<TabItem x:Name="tabMsgView1">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.MsgInformationTitle}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashProxies1">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.TbProxies}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashConnections1">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.TbConnections}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabMsgView1" Header="{x:Static resx:ResUI.MsgInformationTitle}" />
<TabItem x:Name="tabClashProxies1" Header="{x:Static resx:ResUI.TbProxies}" />
<TabItem x:Name="tabClashConnections1" Header="{x:Static resx:ResUI.TbConnections}" />
</TabControl>
</Grid>
<Grid x:Name="gridMain2" IsVisible="False">
<TabControl x:Name="tabMain2" TabStripPlacement="Left">
<TabItem x:Name="tabProfiles2">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.menuServers}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabMsgView2">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.MsgInformationTitle}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashProxies2">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.TbProxies}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabClashConnections2">
<TabItem.Header>
<StackPanel>
<TextBlock HorizontalAlignment="Center" Text="{x:Static resx:ResUI.TbConnections}" />
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem x:Name="tabProfiles2" Header="{x:Static resx:ResUI.menuServers}" />
<TabItem x:Name="tabMsgView2" Header="{x:Static resx:ResUI.MsgInformationTitle}" />
<TabItem x:Name="tabClashProxies2" Header="{x:Static resx:ResUI.TbProxies}" />
<TabItem x:Name="tabClashConnections2" Header="{x:Static resx:ResUI.TbConnections}" />
</TabControl>
</Grid>
</Grid>
</DockPanel>
</dialogHost:DialogHost>
</Window>

View File

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

View File

@@ -114,8 +114,8 @@
Grid.ColumnSpan="2"
HorizontalAlignment="Left"
Classes="Margin8"
SelectionMode="Multiple"
Theme="{DynamicResource PureCardRadioGroupListBox}" />
SelectionMode="Multiple,Toggle"
Theme="{DynamicResource CardCheckGroupListBox}" />
<TextBlock
Grid.Row="6"
@@ -385,9 +385,9 @@
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsKeepOlderDedupl}" />
Text="{x:Static resx:ResUI.TbSettingsDisplayRealTimeSpeed}" />
<ToggleSwitch
x:Name="togKeepOlderDedupl"
x:Name="togDisplayRealTimeSpeed"
Grid.Row="3"
Grid.Column="1"
HorizontalAlignment="Left"
@@ -398,9 +398,9 @@
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsIgnoreGeoUpdateCore}" />
Text="{x:Static resx:ResUI.TbSettingsKeepOlderDedupl}" />
<ToggleSwitch
x:Name="togIgnoreGeoUpdateCore"
x:Name="togKeepOlderDedupl"
Grid.Row="4"
Grid.Column="1"
HorizontalAlignment="Left"
@@ -714,102 +714,100 @@
</TabItem>
<TabItem Header="{x:Static resx:ResUI.TbSettingsTunMode}">
<DockPanel Classes="Margin8">
<Grid
<Grid
Classes="Margin8"
ColumnDefinitions="Auto,Auto,Auto"
DockPanel.Dock="Top"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<TextBlock
Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
ColumnDefinitions="Auto,Auto,Auto"
DockPanel.Dock="Top"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
Text="Strict Route" />
<ToggleSwitch
x:Name="togStrictRoute"
Grid.Row="2"
Grid.Column="1"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="Strict Route" />
<ToggleSwitch
x:Name="togStrictRoute"
Grid.Row="2"
Grid.Column="1"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="Stack" />
<ComboBox
x:Name="cmbStack"
Grid.Row="3"
Grid.Column="1"
Width="200"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="Stack" />
<ComboBox
x:Name="cmbStack"
Grid.Row="3"
Grid.Column="1"
Width="200"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="Mtu" />
<ComboBox
x:Name="cmbMtu"
Grid.Row="4"
Grid.Column="1"
Width="200"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="Mtu" />
<ComboBox
x:Name="cmbMtu"
Grid.Row="4"
Grid.Column="1"
Width="200"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsEnableExInbound}" />
<ToggleSwitch
x:Name="togEnableExInbound"
Grid.Row="5"
Grid.Column="1"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsEnableExInbound}" />
<ToggleSwitch
x:Name="togEnableExInbound"
Grid.Row="5"
Grid.Column="1"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="6"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsEnableIPv6Address}" />
<ToggleSwitch
x:Name="togEnableIPv6Address"
Grid.Row="6"
Grid.Column="1"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="6"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsEnableIPv6Address}" />
<ToggleSwitch
x:Name="togEnableIPv6Address"
Grid.Row="6"
Grid.Column="1"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="7"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPassword}" />
<TextBox
x:Name="txtLinuxSudoPassword"
Grid.Row="7"
Grid.Column="1"
Width="200"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="7"
Grid.Column="2"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPasswordTip}"
TextWrapping="Wrap" />
</Grid>
</DockPanel>
<TextBlock
Grid.Row="7"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPassword}" />
<TextBox
x:Name="txtLinuxSudoPassword"
Grid.Row="7"
Grid.Column="1"
Width="200"
HorizontalAlignment="Left"
Classes="Margin8" />
<TextBlock
Grid.Row="7"
Grid.Column="2"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPasswordTip}"
TextWrapping="Wrap" />
</Grid>
</TabItem>
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreType}">

View File

@@ -126,8 +126,8 @@ namespace v2rayN.Desktop.Views
this.Bind(ViewModel, vm => vm.AutoRun, v => v.togAutoRun.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableStatistics, v => v.togEnableStatistics.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DisplayRealTimeSpeed, v => v.togDisplayRealTimeSpeed.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.KeepOlderDedupl, v => v.togKeepOlderDedupl.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.IgnoreGeoUpdateCore, v => v.togIgnoreGeoUpdateCore.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableAutoAdjustMainLvColWidth, v => v.togEnableAutoAdjustMainLvColWidth.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableUpdateSubOnlyRemarksExist, v => v.togEnableUpdateSubOnlyRemarksExist.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableSecurityProtocolTls13, v => v.togEnableSecurityProtocolTls13.IsChecked).DisposeWith(disposables);

View File

@@ -165,7 +165,7 @@
Classes="Solid Red"
Content="{x:Static resx:ResUI.TipActiveServer}"
IsVisible="{Binding IsActive}"
Theme="{StaticResource TagLabel}" />
Theme="{DynamicResource TagLabel}" />
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"

View File

@@ -15,7 +15,12 @@ namespace v2rayN.Desktop.Views
public partial class ProfilesView : ReactiveUserControl<ProfilesViewModel>
{
private static Config _config;
private Window _window;
private Window? _window;
public ProfilesView()
{
InitializeComponent();
}
public ProfilesView(Window window)
{

View File

@@ -4,12 +4,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
d:DesignHeight="480"
d:DesignWidth="400"
mc:Ignorable="d">
<Grid Margin="30" RowDefinitions="Auto,Auto">
<Image
Name="imgQrcode"
Width="300"
@@ -24,6 +22,5 @@
IsReadOnly="True"
MaxLines="1" />
</Grid>
</UserControl>

View File

@@ -5,6 +5,11 @@ namespace v2rayN.Desktop.Views
{
public partial class QrcodeView : UserControl
{
public QrcodeView()
{
InitializeComponent();
}
public QrcodeView(string? url)
{
InitializeComponent();

View File

@@ -94,8 +94,8 @@
Grid.Column="1"
HorizontalAlignment="Left"
Classes="Margin8"
SelectionMode="Multiple"
Theme="{DynamicResource PureCardRadioGroupListBox}" />
SelectionMode="Multiple,Toggle"
Theme="{DynamicResource CardCheckGroupListBox}" />
<TextBlock
Grid.Row="4"
@@ -108,8 +108,8 @@
Grid.Row="4"
Grid.Column="1"
Classes="Margin8"
SelectionMode="Multiple"
Theme="{DynamicResource PureCardRadioGroupListBox}" />
SelectionMode="Multiple,Toggle"
Theme="{DynamicResource CardCheckGroupListBox}" />
<TextBlock
Grid.Row="4"
Grid.Column="2"

View File

@@ -123,6 +123,7 @@
Classes="Margin8"
TextWrapping="Wrap" />
<!--
<TextBlock
Grid.Row="3"
Grid.Column="0"
@@ -144,6 +145,7 @@
Grid.Column="2"
Classes="Margin8"
Content="{x:Static resx:ResUI.TbBrowse}" />
-->
<TextBlock
Grid.Row="4"

View File

@@ -27,7 +27,7 @@ namespace v2rayN.Desktop.Views
lstRules.SelectionChanged += lstRules_SelectionChanged;
lstRules.DoubleTapped += LstRules_DoubleTapped;
menuRuleSelectAll.Click += menuRuleSelectAll_Click;
btnBrowseCustomIcon.Click += btnBrowseCustomIcon_Click;
//btnBrowseCustomIcon.Click += btnBrowseCustomIcon_Click;
btnBrowseCustomRulesetPath4Singbox.Click += btnBrowseCustomRulesetPath4Singbox_ClickAsync;
ViewModel = new RoutingRuleSettingViewModel(routingItem, UpdateViewHandler);
@@ -51,7 +51,7 @@ namespace v2rayN.Desktop.Views
this.Bind(ViewModel, vm => vm.SelectedRouting.DomainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.Url, v => v.txtUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.CustomIcon, v => v.txtCustomIcon.Text).DisposeWith(disposables);
//this.Bind(ViewModel, vm => vm.SelectedRouting.CustomIcon, v => v.txtCustomIcon.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.CustomRulesetPath4Singbox, v => v.txtCustomRulesetPath4Singbox.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.Sort, v => v.txtSort.Text).DisposeWith(disposables);
@@ -179,16 +179,16 @@ namespace v2rayN.Desktop.Views
lstRules.SelectAll();
}
private async void btnBrowseCustomIcon_Click(object? sender, RoutedEventArgs e)
{
var fileName = await UI.OpenFileDialog(this, FilePickerFileTypes.ImagePng);
if (fileName.IsNullOrEmpty())
{
return;
}
//private async void btnBrowseCustomIcon_Click(object? sender, RoutedEventArgs e)
//{
// var fileName = await UI.OpenFileDialog(this, FilePickerFileTypes.ImagePng);
// if (fileName.IsNullOrEmpty())
// {
// return;
// }
txtCustomIcon.Text = fileName;
}
// txtCustomIcon.Text = fileName;
//}
private async void btnBrowseCustomRulesetPath4Singbox_ClickAsync(object? sender, RoutedEventArgs e)
{

View File

@@ -18,40 +18,29 @@
<StackPanel
Classes="Margin8"
DockPanel.Dock="Top"
Orientation="Horizontal">
Orientation="Horizontal"
Spacing="4">
<Menu>
<MenuItem x:Name="menuRoutingAdvancedAdd2" Header="{x:Static resx:ResUI.menuRoutingAdvancedAdd}" />
<MenuItem x:Name="menuRoutingAdvancedImportRules2" Header="{x:Static resx:ResUI.menuRoutingAdvancedImportRules}" />
</Menu>
<TextBlock Margin="8,0,0,0" VerticalAlignment="Center">
<TextBlock VerticalAlignment="Center">
<HyperlinkButton Classes="WithIcon" Click="linkdomainStrategy_Click">
<TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy}" />
</HyperlinkButton>
</TextBlock>
<ComboBox
x:Name="cmbdomainStrategy"
Width="110"
Margin="8,0,0,0" />
<ComboBox x:Name="cmbdomainStrategy" Width="110" />
<Separator />
<TextBlock
Margin="8,0,0,0"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbdomainMatcher}" />
<ComboBox
x:Name="cmbdomainMatcher"
Width="60"
Margin="8,0,0,0" />
<TextBlock VerticalAlignment="Center" Text="{x:Static resx:ResUI.TbdomainMatcher}" />
<ComboBox x:Name="cmbdomainMatcher" Width="60" />
<Separator />
<TextBlock Margin="8,0,0,0" VerticalAlignment="Center">
<TextBlock VerticalAlignment="Center">
<HyperlinkButton Classes="WithIcon" Click="linkdomainStrategy4Singbox_Click">
<TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy4Singbox}" />
</HyperlinkButton>
</TextBlock>
<ComboBox
x:Name="cmbdomainStrategy4Singbox"
Width="100"
Margin="8,0,0,0" />
<ComboBox x:Name="cmbdomainStrategy4Singbox" Width="100" />
</StackPanel>
<StackPanel

View File

@@ -11,73 +11,71 @@
x:DataType="vms:StatusBarViewModel"
mc:Ignorable="d">
<Grid>
<StackPanel Height="50">
<DockPanel>
<StackPanel
<DockPanel Margin="4">
<StackPanel
Margin="8,0"
VerticalAlignment="Center"
DockPanel.Dock="Right">
<TextBlock x:Name="txtSpeedProxyDisplay" HorizontalAlignment="Right" />
<Border Margin="1" />
<TextBlock x:Name="txtSpeedDirectDisplay" HorizontalAlignment="Right" />
</StackPanel>
<StackPanel
Margin="8,0"
VerticalAlignment="Center"
DockPanel.Dock="Left">
<TextBlock x:Name="txtInboundDisplay" />
<Border Margin="1" />
<TextBlock x:Name="txtInboundLanDisplay" />
</StackPanel>
<StackPanel
x:Name="spEnableTun"
Margin="8,0"
VerticalAlignment="Center"
DockPanel.Dock="Left"
Orientation="Horizontal">
<TextBlock
Margin="8,0"
VerticalAlignment="Center"
DockPanel.Dock="Right">
<TextBlock x:Name="txtSpeedProxyDisplay" />
<Border Margin="2" />
<TextBlock x:Name="txtSpeedDirectDisplay" />
</StackPanel>
Text="{x:Static resx:ResUI.TbEnableTunAs}" />
<ToggleSwitch
x:Name="togEnableTun"
HorizontalAlignment="Center"
Classes="Margin8"
Theme="{DynamicResource SimpleToggleSwitch}" />
</StackPanel>
<StackPanel
<StackPanel
Margin="8,0"
VerticalAlignment="Center"
DockPanel.Dock="Left"
Orientation="Horizontal">
<ComboBox
x:Name="cmbSystemProxy"
Width="160"
Margin="8,0"
VerticalAlignment="Center"
DockPanel.Dock="Left">
<TextBlock x:Name="txtInboundDisplay" />
<Border Margin="2" />
<TextBlock x:Name="txtInboundLanDisplay" />
</StackPanel>
ToolTip.Tip="{x:Static resx:ResUI.menuSystemproxy}">
<ComboBoxItem Content="{x:Static resx:ResUI.menuSystemProxyClear}" />
<ComboBoxItem Content="{x:Static resx:ResUI.menuSystemProxySet}" />
<ComboBoxItem Content="{x:Static resx:ResUI.menuSystemProxyNothing}" />
</ComboBox>
<StackPanel
x:Name="spEnableTun"
<ComboBox
x:Name="cmbRoutings2"
Width="160"
Margin="8,0"
VerticalAlignment="Center"
DockPanel.Dock="Left"
Orientation="Horizontal">
<TextBlock
Margin="8,0"
VerticalAlignment="Center"
Text="{x:Static resx:ResUI.TbEnableTunAs}" />
<ToggleSwitch
x:Name="togEnableTun"
HorizontalAlignment="Center"
Classes="Margin8"
Theme="{StaticResource SimpleToggleSwitch}" />
</StackPanel>
DisplayMemberBinding="{Binding Remarks}"
ItemsSource="{Binding RoutingItems}"
ToolTip.Tip="{x:Static resx:ResUI.menuRouting}" />
</StackPanel>
<StackPanel
Margin="8,0"
VerticalAlignment="Center"
DockPanel.Dock="Left"
Orientation="Horizontal">
<ComboBox
x:Name="cmbSystemProxy"
Width="160"
Margin="8,0"
ToolTip.Tip="{x:Static resx:ResUI.menuSystemproxy}">
<ComboBoxItem Content="{x:Static resx:ResUI.menuSystemProxyClear}" />
<ComboBoxItem Content="{x:Static resx:ResUI.menuSystemProxySet}" />
<ComboBoxItem Content="{x:Static resx:ResUI.menuSystemProxyNothing}" />
</ComboBox>
<ComboBox
x:Name="cmbRoutings2"
Width="160"
Margin="8,0"
DisplayMemberBinding="{Binding Remarks}"
ItemsSource="{Binding RoutingItems}"
ToolTip.Tip="{x:Static resx:ResUI.menuRouting}" />
</StackPanel>
<StackPanel Margin="8,0" VerticalAlignment="Center">
<TextBlock x:Name="txtRunningServerDisplay" />
<Border Margin="2" />
<TextBlock x:Name="txtRunningInfoDisplay" />
</StackPanel>
</DockPanel>
</StackPanel>
<StackPanel Margin="8,0" VerticalAlignment="Center">
<TextBlock x:Name="txtRunningServerDisplay" />
<Border Margin="1" />
<TextBlock x:Name="txtRunningInfoDisplay" />
</StackPanel>
</DockPanel>
</Grid>
</UserControl>

View File

@@ -69,6 +69,11 @@ namespace v2rayN.Desktop.Views
},
DispatcherPriority.Default);
break;
case EViewAction.SetClipboardData:
if (obj is null) return false;
await AvaUtils.SetClipboardData(this, (string)obj);
break;
}
return await Task.FromResult(true);
}

View File

@@ -10,6 +10,15 @@
d:DesignWidth="800"
x:DataType="vms:ThemeSettingViewModel"
mc:Ignorable="d">
<UserControl.Styles>
<Style Selector="TextBlock">
<Setter Property="Width" Value="100" />
</Style>
<Style Selector="ComboBox">
<Setter Property="Width" Value="130" />
</Style>
</UserControl.Styles>
<Button
Width="30"
Height="30"
@@ -24,43 +33,35 @@
</Button.Content>
<Button.Flyout>
<Flyout>
<StackPanel>
<StackPanel Margin="0,12">
<StackPanel Orientation="Horizontal">
<TextBlock
Width="100"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsColorMode}" />
<ToggleSwitch x:Name="togDarkMode" Classes="Margin8" />
Text="{x:Static resx:ResUI.TbSettingsTheme}" />
<ComboBox
x:Name="cmbCurrentTheme"
HorizontalAlignment="Center"
Classes="Margin8" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Width="100"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsFollowSystemTheme}" />
<ToggleSwitch x:Name="togFollowSystemTheme" Classes="Margin8" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Width="100"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsFontSize}" />
<ComboBox
x:Name="cmbCurrentFontSize"
Width="100"
HorizontalAlignment="Center"
Classes="Margin8" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Width="100"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsLanguage}" />
<ComboBox
x:Name="cmbCurrentLanguage"
Width="100"
HorizontalAlignment="Center"
Classes="Margin8" />
</StackPanel>
</StackPanel>

View File

@@ -16,6 +16,11 @@ namespace v2rayN.Desktop.Views
InitializeComponent();
ViewModel = new ThemeSettingViewModel();
foreach (ETheme it in Enum.GetValues(typeof(ETheme)))
{
cmbCurrentTheme.Items.Add(it.ToString());
}
for (int i = Global.MinFontSize; i <= Global.MinFontSize + 10; i++)
{
cmbCurrentFontSize.Items.Add(i);
@@ -28,8 +33,7 @@ namespace v2rayN.Desktop.Views
this.WhenActivated(disposables =>
{
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.togFollowSystemTheme.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentTheme, v => v.cmbCurrentTheme.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.SelectedValue).DisposeWith(disposables);
});

View File

@@ -6,7 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<ApplicationIcon>Assets\v2rayN.ico</ApplicationIcon>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
<Copyright>Copyright © 2017-2025 (GPLv3)</Copyright>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<AssemblyName>v2rayN</AssemblyName>
</PropertyGroup>
@@ -48,7 +48,7 @@
<None Update="v2rayN.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="v2rayN2.png">
<None Update="v2rayN.icns">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -64,14 +64,6 @@ namespace v2rayN
BitmapSizeOptions.FromEmptyOptions());
}
public static bool IsDarkTheme()
{
using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
var obj = key?.GetValue("AppsUseLightTheme");
int.TryParse(obj?.ToString(), out var value);
return value == 0;
}
public static void RemoveTunDevice()
{
try
@@ -103,7 +95,19 @@ namespace v2rayN
}
}
public static void SetDarkBorder(Window window, bool dark)
public static void SetDarkBorder(Window window, string? theme)
{
var isDark = theme switch
{
nameof(ETheme.Dark) => true,
nameof(ETheme.Light) => false,
_ => IsDarkTheme(),
};
SetDarkBorder(window, isDark);
}
private static void SetDarkBorder(Window window, bool dark)
{
// Make sure the handle is created before the window is shown
IntPtr hWnd = new WindowInteropHelper(window).EnsureHandle();
@@ -113,6 +117,14 @@ namespace v2rayN
DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize);
}
private static bool IsDarkTheme()
{
using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
var obj = key?.GetValue("AppsUseLightTheme");
int.TryParse(obj?.ToString(), out var value);
return value == 0;
}
#region Windows API
[Flags]

View File

@@ -16,23 +16,17 @@ namespace v2rayN.ViewModels
{
private readonly PaletteHelper _paletteHelper = new();
[Reactive]
public bool ColorModeDark { get; set; }
private IObservableCollection<Swatch> _swatches = new ObservableCollectionExtended<Swatch>();
public IObservableCollection<Swatch> Swatches => _swatches;
[Reactive]
public Swatch SelectedSwatch { get; set; }
[Reactive]
public int CurrentFontSize { get; set; }
[Reactive] public string CurrentTheme { get; set; }
[Reactive]
public bool FollowSystemTheme { get; set; }
[Reactive] public int CurrentFontSize { get; set; }
[Reactive]
public string CurrentLanguage { get; set; }
[Reactive] public string CurrentLanguage { get; set; }
public ThemeSettingViewModel()
{
@@ -62,40 +56,27 @@ namespace v2rayN.ViewModels
private void BindingUI()
{
ColorModeDark = _config.UiItem.ColorModeDark;
FollowSystemTheme = _config.UiItem.FollowSystemTheme;
_swatches.AddRange(new SwatchesProvider().Swatches);
if (!_config.UiItem.ColorPrimaryName.IsNullOrEmpty())
{
SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.UiItem.ColorPrimaryName);
}
CurrentTheme = _config.UiItem.CurrentTheme;
CurrentFontSize = _config.UiItem.CurrentFontSize;
CurrentLanguage = _config.UiItem.CurrentLanguage;
this.WhenAnyValue(
x => x.ColorModeDark,
y => y == true)
.Subscribe(c =>
{
if (_config.UiItem.ColorModeDark != ColorModeDark)
{
_config.UiItem.ColorModeDark = ColorModeDark;
ModifyTheme();
ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(x => x.FollowSystemTheme,
y => y == true)
.Subscribe(c =>
{
if (_config.UiItem.FollowSystemTheme != FollowSystemTheme)
{
_config.UiItem.FollowSystemTheme = FollowSystemTheme;
ModifyTheme();
ConfigHandler.SaveConfig(_config);
}
});
x => x.CurrentTheme,
y => y != null && !y.IsNullOrEmpty())
.Subscribe(c =>
{
if (_config.UiItem.CurrentTheme != CurrentTheme)
{
_config.UiItem.CurrentTheme = CurrentTheme;
ModifyTheme();
ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(
x => x.SelectedSwatch,
@@ -147,12 +128,18 @@ namespace v2rayN.ViewModels
public void ModifyTheme()
{
var theme = _paletteHelper.GetTheme();
var baseTheme = CurrentTheme switch
{
nameof(ETheme.Dark) => BaseTheme.Dark,
nameof(ETheme.Light) => BaseTheme.Light,
_ => BaseTheme.Inherit,
};
var isDarkTheme = FollowSystemTheme ? WindowsUtils.IsDarkTheme() : ColorModeDark;
theme.SetBaseTheme(isDarkTheme ? BaseTheme.Dark : BaseTheme.Light);
var theme = _paletteHelper.GetTheme();
theme.SetBaseTheme(baseTheme);
_paletteHelper.SetTheme(theme);
WindowsUtils.SetDarkBorder(Application.Current.MainWindow, isDarkTheme);
WindowsUtils.SetDarkBorder(Application.Current.MainWindow, CurrentTheme);
}
private void ModifyFontSize()
@@ -182,7 +169,7 @@ namespace v2rayN.ViewModels
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
hwndSource.AddHook((IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) =>
{
if (config.UiItem.FollowSystemTheme)
if (config.UiItem.CurrentTheme == nameof(ETheme.FollowSystem))
{
const int WM_SETTINGCHANGE = 0x001A;
if (msg == WM_SETTINGCHANGE)

View File

@@ -34,7 +34,7 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.EditServerCmd, v => v.btnEdit).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveServerCmd, v => v.btnSave).DisposeWith(disposables);
});
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
}
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)

View File

@@ -210,7 +210,7 @@ namespace v2rayN.Views
});
this.Title = $"{profileItem.ConfigType}";
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
}
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)

View File

@@ -64,7 +64,6 @@
<DataTemplate>
<Border
Width="500"
Height="50"
Margin="{StaticResource Margin8}"
Padding="0"
VerticalAlignment="Center">

View File

@@ -1,14 +1,14 @@
<reactiveui:ReactiveUserControl
x:Class="v2rayN.Views.ClashProxiesView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:reactiveui="http://reactiveui.net"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:reactiveui="http://reactiveui.net"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
xmlns:converters="clr-namespace:v2rayN.Converters"
d:DesignHeight="450"
d:DesignWidth="800"
x:TypeArguments="vms:ClashProxiesViewModel"
@@ -34,7 +34,7 @@
Text="{x:Static resx:ResUI.menuRulemode}" />
<ComboBox
x:Name="cmbRulemode"
Width="80"
Width="100"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource DefComboBox}">
<ComboBoxItem Content="{x:Static resx:ResUI.menuModeRule}" />
@@ -49,7 +49,7 @@
Text="{x:Static resx:ResUI.TbSorting}" />
<ComboBox
x:Name="cmbSorting"
Width="60"
Width="100"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource DefComboBox}">
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingDelay}" />

View File

@@ -50,7 +50,7 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCmd, v => v.btnImportDefConfig4Singbox).DisposeWith(disposables);
});
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
}
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)

View File

@@ -30,7 +30,7 @@ namespace v2rayN.Views
HotkeyHandler.Instance.IsPause = true;
this.Closing += (s, e) => HotkeyHandler.Instance.IsPause = false;
WindowsUtils.SetDarkBorder(this, _config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : _config.UiItem.ColorModeDark);
WindowsUtils.SetDarkBorder(this, _config.UiItem.CurrentTheme);
InitData();
}

View File

@@ -601,9 +601,9 @@
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsKeepOlderDedupl}" />
Text="{x:Static resx:ResUI.TbSettingsDisplayRealTimeSpeed}" />
<ToggleButton
x:Name="togKeepOlderDedupl"
x:Name="togDisplayRealTimeSpeed"
Grid.Row="3"
Grid.Column="1"
Margin="{StaticResource Margin8}"
@@ -615,9 +615,9 @@
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsIgnoreGeoUpdateCore}" />
Text="{x:Static resx:ResUI.TbSettingsKeepOlderDedupl}" />
<ToggleButton
x:Name="togIgnoreGeoUpdateCore"
x:Name="togKeepOlderDedupl"
Grid.Row="4"
Grid.Column="1"
Margin="{StaticResource Margin8}"
@@ -997,98 +997,96 @@
</TabItem>
<TabItem Header="{x:Static resx:ResUI.TbSettingsTunMode}">
<DockPanel Margin="{StaticResource Margin8}">
<Grid Margin="{StaticResource Margin8}" DockPanel.Dock="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid Margin="{StaticResource Margin8}" DockPanel.Dock="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="Strict Route" />
<ToggleButton
x:Name="togStrictRoute"
Grid.Row="2"
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="Strict Route" />
<ToggleButton
x:Name="togStrictRoute"
Grid.Row="2"
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="Stack" />
<ComboBox
x:Name="cmbStack"
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="Stack" />
<ComboBox
x:Name="cmbStack"
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="Mtu" />
<ComboBox
x:Name="cmbMtu"
Grid.Row="4"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="Mtu" />
<ComboBox
x:Name="cmbMtu"
Grid.Row="4"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsEnableExInbound}" />
<ToggleButton
x:Name="togEnableExInbound"
Grid.Row="5"
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsEnableExInbound}" />
<ToggleButton
x:Name="togEnableExInbound"
Grid.Row="5"
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="6"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsEnableIPv6Address}" />
<ToggleButton
x:Name="togEnableIPv6Address"
Grid.Row="6"
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
</Grid>
</DockPanel>
<TextBlock
Grid.Row="6"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsEnableIPv6Address}" />
<ToggleButton
x:Name="togEnableIPv6Address"
Grid.Row="6"
Grid.Column="1"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
</Grid>
</TabItem>
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreType}">

View File

@@ -136,8 +136,8 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.AutoRun, v => v.togAutoRun.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableStatistics, v => v.togEnableStatistics.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.DisplayRealTimeSpeed, v => v.togDisplayRealTimeSpeed.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.KeepOlderDedupl, v => v.togKeepOlderDedupl.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.IgnoreGeoUpdateCore, v => v.togIgnoreGeoUpdateCore.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableAutoAdjustMainLvColWidth, v => v.togEnableAutoAdjustMainLvColWidth.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableUpdateSubOnlyRemarksExist, v => v.togEnableUpdateSubOnlyRemarksExist.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.EnableSecurityProtocolTls13, v => v.togEnableSecurityProtocolTls13.IsChecked).DisposeWith(disposables);
@@ -177,7 +177,7 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
});
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
}
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
@@ -248,7 +248,9 @@ namespace v2rayN.Views
{
Logging.SaveLog("GetFonts", ex);
}
return lstFonts.OrderBy(t => t).ToList();
var lst = lstFonts.OrderBy(t => t).ToList();
return await Task.FromResult(lst);
}
private void ClbdestOverride_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)

View File

@@ -58,7 +58,7 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
});
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
}
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)

View File

@@ -60,7 +60,7 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
});
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
}
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)

View File

@@ -52,7 +52,7 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
});
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
}
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)

View File

@@ -15,15 +15,24 @@
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<Grid>
<materialDesign:ColorZone Height="50" Mode="Standard">
<materialDesign:ColorZone
Height="auto"
Margin="{StaticResource Margin4}"
Mode="Standard">
<DockPanel>
<StackPanel
Margin="{StaticResource MarginLeftRight8}"
VerticalAlignment="Center"
DockPanel.Dock="Right">
<TextBlock x:Name="txtSpeedProxyDisplay" Style="{StaticResource StatusbarItem}" />
<Border Margin="{StaticResource Margin4}" />
<TextBlock x:Name="txtSpeedDirectDisplay" Style="{StaticResource StatusbarItem}" />
<TextBlock
x:Name="txtSpeedProxyDisplay"
HorizontalAlignment="Right"
Style="{StaticResource StatusbarItem}" />
<Border Margin="1" />
<TextBlock
x:Name="txtSpeedDirectDisplay"
HorizontalAlignment="Right"
Style="{StaticResource StatusbarItem}" />
</StackPanel>
<StackPanel
@@ -32,7 +41,7 @@
VerticalAlignment="Center"
DockPanel.Dock="Left">
<TextBlock x:Name="txtInboundDisplay" Style="{StaticResource StatusbarItem}" />
<Border Margin="{StaticResource Margin4}" />
<Border Margin="1" />
<TextBlock x:Name="txtInboundLanDisplay" Style="{StaticResource StatusbarItem}" />
</StackPanel>
@@ -85,7 +94,7 @@
<StackPanel Margin="{StaticResource MarginLeftRight8}" VerticalAlignment="Center">
<TextBlock x:Name="txtRunningServerDisplay" Style="{StaticResource StatusbarItem}" />
<Border Margin="{StaticResource Margin4}" />
<Border Margin="1" />
<TextBlock x:Name="txtRunningInfoDisplay" Style="{StaticResource StatusbarItem}" />
</StackPanel>
</DockPanel>
@@ -193,6 +202,11 @@
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuSubUpdateViaProxy}" />
<Separator />
<MenuItem
x:Name="menuCopyProxyCmdToClipboard"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuCopyProxyCmdToClipboard}" />
<Separator />
<MenuItem
x:Name="menuExit"
Height="{StaticResource MenuItemHeight}"

View File

@@ -51,6 +51,8 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.SubUpdateCmd, v => v.menuSubUpdate2).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SubUpdateViaProxyCmd, v => v.menuSubUpdateViaProxy2).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.CopyProxyCmdToClipboardCmd, v => v.menuCopyProxyCmdToClipboard).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.RunningServerToolTipText, v => v.tbNotify.ToolTipText).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.NotifyLeftClickCmd, v => v.tbNotify.LeftClickCommand).DisposeWith(disposables);
@@ -96,6 +98,10 @@ namespace v2rayN.Views
Application.Current.MainWindow.Icon = WindowsHandler.Instance.GetAppIcon(_config);
}), DispatcherPriority.Normal);
break;
case EViewAction.SetClipboardData:
if (obj is null) return false;
WindowsUtils.SetClipboardData((string)obj);
break;
}
return await Task.FromResult(true);
}

View File

@@ -38,7 +38,7 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
});
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
}
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)

View File

@@ -31,7 +31,7 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.SubEditCmd, v => v.menuSubEdit).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SubShareCmd, v => v.menuSubShare).DisposeWith(disposables);
});
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
}
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)

View File

@@ -25,29 +25,20 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsColorMode}" />
<ToggleButton
x:Name="togDarkMode"
Grid.Row="0"
Grid.Column="1"
Margin="{StaticResource Margin8}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsFollowSystemTheme}" />
<ToggleButton
x:Name="togFollowSystemTheme"
Text="{x:Static resx:ResUI.TbSettingsTheme}" />
<ComboBox
x:Name="cmbCurrentTheme"
Grid.Row="1"
Grid.Column="1"
Margin="{StaticResource Margin8}" />
Width="120"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="2"
@@ -59,7 +50,7 @@
x:Name="cmbSwatches"
Grid.Row="2"
Grid.Column="1"
Width="100"
Width="120"
Margin="{StaticResource Margin8}"
DisplayMemberPath="Name"
Style="{StaticResource DefComboBox}" />
@@ -74,7 +65,7 @@
x:Name="cmbCurrentFontSize"
Grid.Row="3"
Grid.Column="1"
Width="100"
Width="120"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
@@ -88,7 +79,7 @@
x:Name="cmbCurrentLanguage"
Grid.Row="4"
Grid.Column="1"
Width="100"
Width="120"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
</Grid>

View File

@@ -13,6 +13,11 @@ namespace v2rayN.Views
{
InitializeComponent();
ViewModel = new ThemeSettingViewModel();
foreach (ETheme it in Enum.GetValues(typeof(ETheme)))
{
if ((int)it > 2) continue;
cmbCurrentTheme.Items.Add(it.ToString());
}
for (int i = Global.MinFontSize; i <= Global.MinFontSize + 10; i++)
{
@@ -26,8 +31,7 @@ namespace v2rayN.Views
this.WhenActivated(disposables =>
{
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.togFollowSystemTheme.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentTheme, v => v.cmbCurrentTheme.SelectedValue).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.Swatches, v => v.cmbSwatches.ItemsSource).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);

View File

@@ -9,12 +9,12 @@
<ApplicationManifest>app.manifest</ApplicationManifest>
<ImplicitUsings>enable</ImplicitUsings>
<ApplicationIcon>Resources\v2rayN.ico</ApplicationIcon>
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
<Copyright>Copyright © 2017-2025 (GPLv3)</Copyright>
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MaterialDesignThemes" Version="5.2.0" />
<PackageReference Include="MaterialDesignThemes" Version="5.2.1" />
<PackageReference Include="H.NotifyIcon.Wpf" Version="2.2.0" />
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
<PackageReference Include="ReactiveUI.WPF" Version="20.1.63" />