Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45febe3fff | ||
|
|
689a81a985 | ||
|
|
28620b385a | ||
|
|
be13446e69 | ||
|
|
ee57d5b8e6 | ||
|
|
4eda3dd8fa | ||
|
|
911dc7f90e | ||
|
|
18005b96e8 | ||
|
|
a3e45d206e | ||
|
|
0accf262dc | ||
|
|
e0eb73bb0a | ||
|
|
258e822c13 | ||
|
|
4f05b93d63 | ||
|
|
bb661d4f50 | ||
|
|
201cfaa922 | ||
|
|
c339aa349c | ||
|
|
046421f345 | ||
|
|
3a2c9e7aaa |
@@ -22,12 +22,12 @@ namespace AmazTool
|
|||||||
Console.WriteLine("Try to end the process(尝试结束进程).");
|
Console.WriteLine("Try to end the process(尝试结束进程).");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var path = GetPath(V2rayN);
|
|
||||||
Console.WriteLine(path);
|
|
||||||
var existing = Process.GetProcessesByName(V2rayN);
|
var existing = Process.GetProcessesByName(V2rayN);
|
||||||
var pp = existing.FirstOrDefault(p => p.MainModule?.FileName != null && p.MainModule?.FileName.Contains(path) == true);
|
foreach (var pp in existing)
|
||||||
pp?.Kill();
|
{
|
||||||
pp?.WaitForExit(1000);
|
pp?.Kill();
|
||||||
|
pp?.WaitForExit(1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
ClearMsg,
|
ClearMsg,
|
||||||
SendMsgView,
|
SendMsgView,
|
||||||
SendSnackMsg,
|
SendSnackMsg,
|
||||||
RefreshProfiles
|
RefreshProfiles,
|
||||||
|
StopSpeedtest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
public const string ClashMixinYaml = NamespaceSample + "clash_mixin_yaml";
|
public const string ClashMixinYaml = NamespaceSample + "clash_mixin_yaml";
|
||||||
public const string ClashTunYaml = NamespaceSample + "clash_tun_yaml";
|
public const string ClashTunYaml = NamespaceSample + "clash_tun_yaml";
|
||||||
public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
|
public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
|
||||||
|
|
||||||
public const string DefaultSecurity = "auto";
|
public const string DefaultSecurity = "auto";
|
||||||
public const string DefaultNetwork = "tcp";
|
public const string DefaultNetwork = "tcp";
|
||||||
public const string TcpHeaderHttp = "http";
|
public const string TcpHeaderHttp = "http";
|
||||||
@@ -105,9 +105,9 @@
|
|||||||
|
|
||||||
public static readonly List<string> SpeedTestUrls = new() {
|
public static readonly List<string> SpeedTestUrls = new() {
|
||||||
@"https://speed.cloudflare.com/__down?bytes=100000000",
|
@"https://speed.cloudflare.com/__down?bytes=100000000",
|
||||||
|
@"https://speed.cloudflare.com/__down?bytes=50000000",
|
||||||
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
||||||
@"http://cachefly.cachefly.net/50mb.test",
|
@"https://cachefly.cachefly.net/50mb.test",
|
||||||
@"http://cachefly.cachefly.net/10mb.test"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly List<string> SpeedPingTestUrls = new() {
|
public static readonly List<string> SpeedPingTestUrls = new() {
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var logonUser = WindowsIdentity.GetCurrent().Name;
|
var logonUser = WindowsIdentity.GetCurrent().Name;
|
||||||
using var taskService = new Microsoft.Win32.TaskScheduler.TaskService();
|
using var taskService = new Microsoft.Win32.TaskScheduler.TaskService();
|
||||||
var tasks = taskService.RootFolder.GetTasks(new Regex(taskName));
|
var tasks = taskService.RootFolder.GetTasks(new Regex(taskName));
|
||||||
@@ -113,7 +113,14 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
private static async Task ClearTaskLinux()
|
private static async Task ClearTaskLinux()
|
||||||
{
|
{
|
||||||
File.Delete(GetHomePathLinux());
|
try
|
||||||
|
{
|
||||||
|
File.Delete(GetHomePathLinux());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(ex.Message, ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task SetTaskLinux()
|
private static async Task SetTaskLinux()
|
||||||
@@ -127,8 +134,6 @@ namespace ServiceLib.Handler
|
|||||||
Logging.SaveLog(linuxConfig);
|
Logging.SaveLog(linuxConfig);
|
||||||
|
|
||||||
var homePath = GetHomePathLinux();
|
var homePath = GetHomePathLinux();
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(homePath));
|
|
||||||
|
|
||||||
await File.WriteAllTextAsync(homePath, linuxConfig);
|
await File.WriteAllTextAsync(homePath, linuxConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,7 +145,9 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
private static string GetHomePathLinux()
|
private static string GetHomePathLinux()
|
||||||
{
|
{
|
||||||
return Path.Combine(Utils.GetHomePath(), ".config", "autostart", $"{Global.AppName}.desktop");
|
var homePath = Path.Combine(Utils.GetHomePath(), ".config", "autostart", $"{Global.AppName}.desktop");
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(homePath));
|
||||||
|
return homePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Linux
|
#endregion Linux
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ namespace ServiceLib.Handler
|
|||||||
config.ClashUIItem ??= new();
|
config.ClashUIItem ??= new();
|
||||||
config.SystemProxyItem ??= new();
|
config.SystemProxyItem ??= new();
|
||||||
config.WebDavItem ??= new();
|
config.WebDavItem ??= new();
|
||||||
|
config.CheckUpdateItem ??= new();
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@@ -1197,7 +1198,7 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
await RemoveServerViaSubid(config, subid, isSub);
|
await RemoveServerViaSubid(config, subid, isSub);
|
||||||
}
|
}
|
||||||
|
|
||||||
profileItem.Subid = subid;
|
profileItem.Subid = subid;
|
||||||
profileItem.IsSub = isSub;
|
profileItem.IsSub = isSub;
|
||||||
profileItem.PreSocksPort = preSocksPort;
|
profileItem.PreSocksPort = preSocksPort;
|
||||||
@@ -1358,6 +1359,7 @@ namespace ServiceLib.Handler
|
|||||||
item.PrevProfile = subItem.PrevProfile;
|
item.PrevProfile = subItem.PrevProfile;
|
||||||
item.NextProfile = subItem.NextProfile;
|
item.NextProfile = subItem.NextProfile;
|
||||||
item.PreSocksPort = subItem.PreSocksPort;
|
item.PreSocksPort = subItem.PreSocksPort;
|
||||||
|
item.Memo = subItem.Memo;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Utils.IsNullOrEmpty(item.Id))
|
if (Utils.IsNullOrEmpty(item.Id))
|
||||||
|
|||||||
@@ -108,13 +108,11 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool hasProc = false;
|
|
||||||
if (_process != null)
|
if (_process != null)
|
||||||
{
|
{
|
||||||
await KillProcess(_process);
|
await KillProcess(_process);
|
||||||
_process.Dispose();
|
_process.Dispose();
|
||||||
_process = null;
|
_process = null;
|
||||||
hasProc = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_processPre != null)
|
if (_processPre != null)
|
||||||
@@ -122,26 +120,6 @@ namespace ServiceLib.Handler
|
|||||||
await KillProcess(_processPre);
|
await KillProcess(_processPre);
|
||||||
_processPre.Dispose();
|
_processPre.Dispose();
|
||||||
_processPre = null;
|
_processPre = null;
|
||||||
hasProc = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasProc)
|
|
||||||
{
|
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
|
|
||||||
foreach (var it in coreInfo)
|
|
||||||
{
|
|
||||||
if (it.CoreType == ECoreType.v2rayN)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
foreach (var name in it.CoreExes)
|
|
||||||
{
|
|
||||||
var path = Utils.GetBinPath(Utils.GetExeName(name), it.CoreType.ToString());
|
|
||||||
var existing = Process.GetProcessesByName(name);
|
|
||||||
var pp = existing.FirstOrDefault(p => p.MainModule?.FileName != null && p.MainModule?.FileName.Contains(path) == true);
|
|
||||||
await KillProcess(pp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace ServiceLib.Models
|
namespace ServiceLib.Models
|
||||||
{
|
{
|
||||||
public class CheckUpdateItem
|
public class CheckUpdateModel
|
||||||
{
|
{
|
||||||
public bool? IsSelected { get; set; }
|
public bool? IsSelected { get; set; }
|
||||||
public string? CoreType { get; set; }
|
public string? CoreType { get; set; }
|
||||||
@@ -15,15 +15,14 @@
|
|||||||
|
|
||||||
public bool IsRunningCore(ECoreType type)
|
public bool IsRunningCore(ECoreType type)
|
||||||
{
|
{
|
||||||
if (type == ECoreType.Xray && RunningCoreType is ECoreType.Xray or ECoreType.v2fly or ECoreType.v2fly_v5)
|
switch (type)
|
||||||
{
|
{
|
||||||
return true;
|
case ECoreType.Xray when RunningCoreType is ECoreType.Xray or ECoreType.v2fly or ECoreType.v2fly_v5:
|
||||||
|
case ECoreType.sing_box when RunningCoreType is ECoreType.sing_box or ECoreType.mihomo:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (type == ECoreType.sing_box && RunningCoreType is ECoreType.sing_box or ECoreType.mihomo)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion property
|
#endregion property
|
||||||
@@ -46,6 +45,7 @@
|
|||||||
public ClashUIItem ClashUIItem { get; set; }
|
public ClashUIItem ClashUIItem { get; set; }
|
||||||
public SystemProxyItem SystemProxyItem { get; set; }
|
public SystemProxyItem SystemProxyItem { get; set; }
|
||||||
public WebDavItem WebDavItem { get; set; }
|
public WebDavItem WebDavItem { get; set; }
|
||||||
|
public CheckUpdateItem CheckUpdateItem { get; set; }
|
||||||
public List<InItem> Inbound { get; set; }
|
public List<InItem> Inbound { get; set; }
|
||||||
public List<KeyEventItem> GlobalHotkeys { get; set; }
|
public List<KeyEventItem> GlobalHotkeys { get; set; }
|
||||||
public List<CoreTypeItem> CoreTypeItem { get; set; }
|
public List<CoreTypeItem> CoreTypeItem { get; set; }
|
||||||
|
|||||||
@@ -80,9 +80,7 @@
|
|||||||
public bool IgnoreGeoUpdateCore { get; set; } = true;
|
public bool IgnoreGeoUpdateCore { get; set; } = true;
|
||||||
|
|
||||||
public int AutoUpdateInterval { get; set; }
|
public int AutoUpdateInterval { get; set; }
|
||||||
|
|
||||||
public bool CheckPreReleaseUpdate { get; set; } = false;
|
|
||||||
|
|
||||||
public bool EnableSecurityProtocolTls13 { get; set; }
|
public bool EnableSecurityProtocolTls13 { get; set; }
|
||||||
|
|
||||||
public int TrayMenuServersLimit { get; set; } = 20;
|
public int TrayMenuServersLimit { get; set; } = 20;
|
||||||
@@ -245,4 +243,11 @@
|
|||||||
public string? Password { get; set; }
|
public string? Password { get; set; }
|
||||||
public string? DirName { get; set; }
|
public string? DirName { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class CheckUpdateItem
|
||||||
|
{
|
||||||
|
public bool CheckPreReleaseUpdate { get; set; }
|
||||||
|
public List<string>? SelectedCoreTypes { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -33,5 +33,7 @@ namespace ServiceLib.Models
|
|||||||
public string? NextProfile { get; set; }
|
public string? NextProfile { get; set; }
|
||||||
|
|
||||||
public int? PreSocksPort { get; set; }
|
public int? PreSocksPort { get; set; }
|
||||||
|
|
||||||
|
public string? Memo { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
18
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
18
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
@@ -447,6 +447,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Remarks Memo 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string LvMemo {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LvMemo", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 More URLs, separated by commas; Subscription conversion will be invalid 的本地化字符串。
|
/// 查找类似 More URLs, separated by commas; Subscription conversion will be invalid 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -870,6 +879,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Are you sure to exit? 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string menuExitTips {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("menuExitTips", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Export selected server for complete configuration 的本地化字符串。
|
/// 查找类似 Export selected server for complete configuration 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1363,4 +1363,10 @@
|
|||||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||||
<value>Install the font to the system and restart the settings</value>
|
<value>Install the font to the system and restart the settings</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuExitTips" xml:space="preserve">
|
||||||
|
<value>Are you sure to exit?</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvMemo" xml:space="preserve">
|
||||||
|
<value>Remarks Memo</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -1360,4 +1360,10 @@
|
|||||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||||
<value>安装字体到系统中,重启设置</value>
|
<value>安装字体到系统中,重启设置</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuExitTips" xml:space="preserve">
|
||||||
|
<value>是否确定退出?</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvMemo" xml:space="preserve">
|
||||||
|
<value>备注备忘</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -1240,4 +1240,10 @@
|
|||||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||||
<value>安裝字體到系統中,重新啟動設定</value>
|
<value>安裝字體到系統中,重新啟動設定</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="menuExitTips" xml:space="preserve">
|
||||||
|
<value>是否確定退出?</value>
|
||||||
|
</data>
|
||||||
|
<data name="LvMemo" xml:space="preserve">
|
||||||
|
<value>備註備忘</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Version>7.0.5</Version>
|
<Version>7.0.7</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using ReactiveUI;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
||||||
@@ -80,10 +81,12 @@ namespace ServiceLib.Services
|
|||||||
Task.Run(RunMixedtestAsync);
|
Task.Run(RunMixedtestAsync);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExitLoop()
|
private void ExitLoop(string x)
|
||||||
{
|
{
|
||||||
|
if (_exitLoop) return;
|
||||||
_exitLoop = true;
|
_exitLoop = true;
|
||||||
UpdateFunc("", ResUI.SpeedtestingStop);
|
UpdateFunc("", ResUI.SpeedtestingStop);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,10 @@ namespace ServiceLib.Services
|
|||||||
public class UpdateService
|
public class UpdateService
|
||||||
{
|
{
|
||||||
private Action<bool, string>? _updateFunc;
|
private Action<bool, string>? _updateFunc;
|
||||||
private Config _config;
|
|
||||||
private int _timeout = 30;
|
private int _timeout = 30;
|
||||||
|
|
||||||
public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease)
|
public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease)
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
var url = string.Empty;
|
var url = string.Empty;
|
||||||
var fileName = string.Empty;
|
var fileName = string.Empty;
|
||||||
@@ -53,7 +51,6 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
public async Task CheckUpdateCore(ECoreType type, Config config, Action<bool, string> updateFunc, bool preRelease)
|
public async Task CheckUpdateCore(ECoreType type, Config config, Action<bool, string> updateFunc, bool preRelease)
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
var url = string.Empty;
|
var url = string.Empty;
|
||||||
var fileName = string.Empty;
|
var fileName = string.Empty;
|
||||||
@@ -108,7 +105,6 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
public async Task UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> updateFunc)
|
public async Task UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
|
|
||||||
_updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart);
|
_updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart);
|
||||||
@@ -232,7 +228,7 @@ namespace ServiceLib.Services
|
|||||||
}
|
}
|
||||||
_updateFunc?.Invoke(false, "-------------------------------------------------------");
|
_updateFunc?.Invoke(false, "-------------------------------------------------------");
|
||||||
|
|
||||||
await ConfigHandler.DedupServerList(config, id);
|
//await ConfigHandler.DedupServerList(config, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateFunc?.Invoke(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
|
_updateFunc?.Invoke(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
|
||||||
@@ -454,7 +450,6 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
private async Task UpdateGeoFile(string geoName, Config config, Action<bool, string> updateFunc)
|
private async Task UpdateGeoFile(string geoName, Config config, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
|
|
||||||
var geoUrl = string.IsNullOrEmpty(config?.ConstItem.GeoSourceUrl)
|
var geoUrl = string.IsNullOrEmpty(config?.ConstItem.GeoSourceUrl)
|
||||||
@@ -470,7 +465,6 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
private async Task UpdateSrsFileAll(Config config, Action<bool, string> updateFunc)
|
private async Task UpdateSrsFileAll(Config config, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
_updateFunc = updateFunc;
|
||||||
|
|
||||||
var geoipFiles = new List<string>();
|
var geoipFiles = new List<string>();
|
||||||
@@ -521,9 +515,9 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
private async Task UpdateSrsFile(string type, string srsName, Config config, Action<bool, string> updateFunc)
|
private async Task UpdateSrsFile(string type, string srsName, Config config, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
var srsUrl = string.IsNullOrEmpty(_config.ConstItem.SrsSourceUrl)
|
var srsUrl = string.IsNullOrEmpty(config.ConstItem.SrsSourceUrl)
|
||||||
? Global.SingboxRulesetUrl
|
? Global.SingboxRulesetUrl
|
||||||
: _config.ConstItem.SrsSourceUrl;
|
: config.ConstItem.SrsSourceUrl;
|
||||||
|
|
||||||
var fileName = $"{type}-{srsName}.srs";
|
var fileName = $"{type}-{srsName}.srs";
|
||||||
var targetPath = Path.Combine(Utils.GetBinPath("srss"), fileName);
|
var targetPath = Path.Combine(Utils.GetBinPath("srss"), fileName);
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ namespace ServiceLib.ViewModels
|
|||||||
{
|
{
|
||||||
private const string _geo = "GeoFiles";
|
private const string _geo = "GeoFiles";
|
||||||
private string _v2rayN = ECoreType.v2rayN.ToString();
|
private string _v2rayN = ECoreType.v2rayN.ToString();
|
||||||
private List<CheckUpdateItem> _lstUpdated = [];
|
private List<CheckUpdateModel> _lstUpdated = [];
|
||||||
|
|
||||||
private IObservableCollection<CheckUpdateItem> _checkUpdateItem = new ObservableCollectionExtended<CheckUpdateItem>();
|
private IObservableCollection<CheckUpdateModel> _checkUpdateModel = new ObservableCollectionExtended<CheckUpdateModel>();
|
||||||
public IObservableCollection<CheckUpdateItem> CheckUpdateItems => _checkUpdateItem;
|
public IObservableCollection<CheckUpdateModel> CheckUpdateModels => _checkUpdateModel;
|
||||||
public ReactiveCommand<Unit, Unit> CheckUpdateCmd { get; }
|
public ReactiveCommand<Unit, Unit> CheckUpdateCmd { get; }
|
||||||
[Reactive] public bool EnableCheckPreReleaseUpdate { get; set; }
|
[Reactive] public bool EnableCheckPreReleaseUpdate { get; set; }
|
||||||
|
|
||||||
@@ -29,65 +29,56 @@ namespace ServiceLib.ViewModels
|
|||||||
await CheckUpdate();
|
await CheckUpdate();
|
||||||
});
|
});
|
||||||
|
|
||||||
EnableCheckPreReleaseUpdate = _config.GuiItem.CheckPreReleaseUpdate;
|
EnableCheckPreReleaseUpdate = _config.CheckUpdateItem.CheckPreReleaseUpdate;
|
||||||
|
|
||||||
this.WhenAnyValue(
|
this.WhenAnyValue(
|
||||||
x => x.EnableCheckPreReleaseUpdate,
|
x => x.EnableCheckPreReleaseUpdate,
|
||||||
y => y == true)
|
y => y == true)
|
||||||
.Subscribe(c => { _config.GuiItem.CheckPreReleaseUpdate = EnableCheckPreReleaseUpdate; });
|
.Subscribe(c => { _config.CheckUpdateItem.CheckPreReleaseUpdate = EnableCheckPreReleaseUpdate; });
|
||||||
|
|
||||||
RefreshSubItems();
|
RefreshCheckUpdateItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshSubItems()
|
private void RefreshCheckUpdateItems()
|
||||||
{
|
{
|
||||||
_checkUpdateItem.Clear();
|
_checkUpdateModel.Clear();
|
||||||
|
|
||||||
if (RuntimeInformation.ProcessArchitecture != Architecture.X86)
|
if (RuntimeInformation.ProcessArchitecture != Architecture.X86)
|
||||||
{
|
{
|
||||||
_checkUpdateItem.Add(new CheckUpdateItem()
|
_checkUpdateModel.Add(GetCheckUpdateModel(_v2rayN));
|
||||||
{
|
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.Xray.ToString()));
|
||||||
IsSelected = false,
|
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.mihomo.ToString()));
|
||||||
CoreType = _v2rayN,
|
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.sing_box.ToString()));
|
||||||
Remarks = ResUI.menuCheckUpdate,
|
|
||||||
});
|
|
||||||
_checkUpdateItem.Add(new CheckUpdateItem()
|
|
||||||
{
|
|
||||||
IsSelected = true,
|
|
||||||
CoreType = ECoreType.Xray.ToString(),
|
|
||||||
Remarks = ResUI.menuCheckUpdate,
|
|
||||||
});
|
|
||||||
_checkUpdateItem.Add(new CheckUpdateItem()
|
|
||||||
{
|
|
||||||
IsSelected = true,
|
|
||||||
CoreType = ECoreType.mihomo.ToString(),
|
|
||||||
Remarks = ResUI.menuCheckUpdate,
|
|
||||||
});
|
|
||||||
_checkUpdateItem.Add(new CheckUpdateItem()
|
|
||||||
{
|
|
||||||
IsSelected = true,
|
|
||||||
CoreType = ECoreType.sing_box.ToString(),
|
|
||||||
Remarks = ResUI.menuCheckUpdate,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
_checkUpdateModel.Add(GetCheckUpdateModel(_geo));
|
||||||
|
}
|
||||||
|
|
||||||
_checkUpdateItem.Add(new CheckUpdateItem()
|
private CheckUpdateModel GetCheckUpdateModel(string coreType)
|
||||||
|
{
|
||||||
|
return new()
|
||||||
{
|
{
|
||||||
IsSelected = true,
|
IsSelected = _config.CheckUpdateItem.SelectedCoreTypes?.Contains(coreType) ?? true,
|
||||||
CoreType = _geo,
|
CoreType = coreType,
|
||||||
Remarks = ResUI.menuCheckUpdate,
|
Remarks = ResUI.menuCheckUpdate,
|
||||||
});
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveSelectedCoreTypes()
|
||||||
|
{
|
||||||
|
_config.CheckUpdateItem.SelectedCoreTypes = _checkUpdateModel.Where(t => t.IsSelected == true).Select(t => t.CoreType ?? "").ToList();
|
||||||
|
await ConfigHandler.SaveConfig(_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CheckUpdate()
|
private async Task CheckUpdate()
|
||||||
{
|
{
|
||||||
_lstUpdated.Clear();
|
_lstUpdated.Clear();
|
||||||
_lstUpdated = _checkUpdateItem.Where(x => x.IsSelected == true)
|
_lstUpdated = _checkUpdateModel.Where(x => x.IsSelected == true)
|
||||||
.Select(x => new CheckUpdateItem() { CoreType = x.CoreType }).ToList();
|
.Select(x => new CheckUpdateModel() { CoreType = x.CoreType }).ToList();
|
||||||
|
await SaveSelectedCoreTypes();
|
||||||
|
|
||||||
for (var k = _checkUpdateItem.Count - 1; k >= 0; k--)
|
for (var k = _checkUpdateModel.Count - 1; k >= 0; k--)
|
||||||
{
|
{
|
||||||
var item = _checkUpdateItem[k];
|
var item = _checkUpdateModel[k];
|
||||||
if (item.IsSelected != true) continue;
|
if (item.IsSelected != true) continue;
|
||||||
|
|
||||||
UpdateView(item.CoreType, "...");
|
UpdateView(item.CoreType, "...");
|
||||||
@@ -161,23 +152,23 @@ namespace ServiceLib.ViewModels
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CheckUpdateCore(CheckUpdateItem item, bool preRelease)
|
private async Task CheckUpdateCore(CheckUpdateModel model, bool preRelease)
|
||||||
{
|
{
|
||||||
void _updateUI(bool success, string msg)
|
void _updateUI(bool success, string msg)
|
||||||
{
|
{
|
||||||
UpdateView(item.CoreType, msg);
|
UpdateView(model.CoreType, msg);
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
UpdateView(item.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfullyMore);
|
UpdateView(model.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfullyMore);
|
||||||
|
|
||||||
UpdatedPlusPlus(item.CoreType, msg);
|
UpdatedPlusPlus(model.CoreType, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var type = (ECoreType)Enum.Parse(typeof(ECoreType), item.CoreType);
|
var type = (ECoreType)Enum.Parse(typeof(ECoreType), model.CoreType);
|
||||||
await (new UpdateService()).CheckUpdateCore(type, _config, _updateUI, preRelease)
|
await (new UpdateService()).CheckUpdateCore(type, _config, _updateUI, preRelease)
|
||||||
.ContinueWith(t =>
|
.ContinueWith(t =>
|
||||||
{
|
{
|
||||||
UpdatedPlusPlus(item.CoreType, "");
|
UpdatedPlusPlus(model.CoreType, "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,7 +282,7 @@ namespace ServiceLib.ViewModels
|
|||||||
|
|
||||||
private void UpdateView(string coreType, string msg)
|
private void UpdateView(string coreType, string msg)
|
||||||
{
|
{
|
||||||
var item = new CheckUpdateItem()
|
var item = new CheckUpdateModel()
|
||||||
{
|
{
|
||||||
CoreType = coreType,
|
CoreType = coreType,
|
||||||
Remarks = msg,
|
Remarks = msg,
|
||||||
@@ -299,13 +290,13 @@ namespace ServiceLib.ViewModels
|
|||||||
_updateView?.Invoke(EViewAction.DispatcherCheckUpdate, item);
|
_updateView?.Invoke(EViewAction.DispatcherCheckUpdate, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateViewResult(CheckUpdateItem item)
|
public void UpdateViewResult(CheckUpdateModel model)
|
||||||
{
|
{
|
||||||
var found = _checkUpdateItem.FirstOrDefault(t => t.CoreType == item.CoreType);
|
var found = _checkUpdateModel.FirstOrDefault(t => t.CoreType == model.CoreType);
|
||||||
if (found == null) return;
|
if (found == null) return;
|
||||||
var itemCopy = JsonUtils.DeepCopy(found);
|
var itemCopy = JsonUtils.DeepCopy(found);
|
||||||
itemCopy.Remarks = item.Remarks;
|
itemCopy.Remarks = model.Remarks;
|
||||||
_checkUpdateItem.Replace(found, itemCopy);
|
_checkUpdateModel.Replace(found, itemCopy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,6 +52,8 @@ namespace ServiceLib.ViewModels
|
|||||||
|
|
||||||
public ReactiveCommand<Unit, Unit> ReloadCmd { get; }
|
public ReactiveCommand<Unit, Unit> ReloadCmd { get; }
|
||||||
|
|
||||||
|
public ReactiveCommand<Unit, Unit> ExitCmd { get; }
|
||||||
|
|
||||||
[Reactive]
|
[Reactive]
|
||||||
public bool BlReloadEnabled { get; set; }
|
public bool BlReloadEnabled { get; set; }
|
||||||
|
|
||||||
@@ -187,6 +189,11 @@ namespace ServiceLib.ViewModels
|
|||||||
await Reload();
|
await Reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ExitCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
|
{
|
||||||
|
await Exit();
|
||||||
|
});
|
||||||
|
|
||||||
RegionalPresetDefaultCmd = ReactiveCommand.CreateFromTask(async () =>
|
RegionalPresetDefaultCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
{
|
{
|
||||||
await ApplyRegionalPreset(EPresetType.Default);
|
await ApplyRegionalPreset(EPresetType.Default);
|
||||||
@@ -266,7 +273,7 @@ namespace ServiceLib.ViewModels
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Locator.Current.GetService<StatusBarViewModel>()?.UpdateStatistics(update);
|
Locator.Current.GetService<StatusBarViewModel>()?.UpdateStatistics(update);
|
||||||
if ((update.ProxyUp + update.ProxyDown) > 0 && DateTime.Now.Second % 3 == 0)
|
if ((update.ProxyUp + update.ProxyDown) > 0 && DateTime.Now.Second % 9 == 0)
|
||||||
{
|
{
|
||||||
Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update);
|
Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update);
|
||||||
}
|
}
|
||||||
@@ -289,7 +296,7 @@ namespace ServiceLib.ViewModels
|
|||||||
await ProfileExHandler.Instance.SaveTo();
|
await ProfileExHandler.Instance.SaveTo();
|
||||||
await StatisticsHandler.Instance.SaveTo();
|
await StatisticsHandler.Instance.SaveTo();
|
||||||
StatisticsHandler.Instance.Close();
|
StatisticsHandler.Instance.Close();
|
||||||
CoreHandler.Instance.CoreStop();
|
await CoreHandler.Instance.CoreStop();
|
||||||
|
|
||||||
Logging.SaveLog("MyAppExit End");
|
Logging.SaveLog("MyAppExit End");
|
||||||
}
|
}
|
||||||
@@ -588,6 +595,16 @@ namespace ServiceLib.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task Exit()
|
||||||
|
{
|
||||||
|
if (await _updateView?.Invoke(EViewAction.ShowYesNo, null) == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await MyAppExitAsync(false);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion core job
|
#endregion core job
|
||||||
|
|
||||||
#region Presets
|
#region Presets
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ namespace ServiceLib.ViewModels
|
|||||||
[Reactive] public bool EnableUpdateSubOnlyRemarksExist { get; set; }
|
[Reactive] public bool EnableUpdateSubOnlyRemarksExist { get; set; }
|
||||||
[Reactive] public bool EnableSecurityProtocolTls13 { get; set; }
|
[Reactive] public bool EnableSecurityProtocolTls13 { get; set; }
|
||||||
[Reactive] public bool AutoHideStartup { get; set; }
|
[Reactive] public bool AutoHideStartup { get; set; }
|
||||||
[Reactive] public bool EnableCheckPreReleaseUpdate { get; set; }
|
|
||||||
[Reactive] public bool EnableDragDropSort { get; set; }
|
[Reactive] public bool EnableDragDropSort { get; set; }
|
||||||
[Reactive] public bool DoubleClick2Activate { get; set; }
|
[Reactive] public bool DoubleClick2Activate { get; set; }
|
||||||
[Reactive] public int AutoUpdateInterval { get; set; }
|
[Reactive] public int AutoUpdateInterval { get; set; }
|
||||||
@@ -166,7 +165,6 @@ namespace ServiceLib.ViewModels
|
|||||||
EnableUpdateSubOnlyRemarksExist = _config.UiItem.EnableUpdateSubOnlyRemarksExist;
|
EnableUpdateSubOnlyRemarksExist = _config.UiItem.EnableUpdateSubOnlyRemarksExist;
|
||||||
EnableSecurityProtocolTls13 = _config.GuiItem.EnableSecurityProtocolTls13;
|
EnableSecurityProtocolTls13 = _config.GuiItem.EnableSecurityProtocolTls13;
|
||||||
AutoHideStartup = _config.UiItem.AutoHideStartup;
|
AutoHideStartup = _config.UiItem.AutoHideStartup;
|
||||||
EnableCheckPreReleaseUpdate = _config.GuiItem.CheckPreReleaseUpdate;
|
|
||||||
EnableDragDropSort = _config.UiItem.EnableDragDropSort;
|
EnableDragDropSort = _config.UiItem.EnableDragDropSort;
|
||||||
DoubleClick2Activate = _config.UiItem.DoubleClick2Activate;
|
DoubleClick2Activate = _config.UiItem.DoubleClick2Activate;
|
||||||
AutoUpdateInterval = _config.GuiItem.AutoUpdateInterval;
|
AutoUpdateInterval = _config.GuiItem.AutoUpdateInterval;
|
||||||
@@ -317,7 +315,6 @@ namespace ServiceLib.ViewModels
|
|||||||
_config.GuiItem.EnableSecurityProtocolTls13 = EnableSecurityProtocolTls13;
|
_config.GuiItem.EnableSecurityProtocolTls13 = EnableSecurityProtocolTls13;
|
||||||
_config.UiItem.AutoHideStartup = AutoHideStartup;
|
_config.UiItem.AutoHideStartup = AutoHideStartup;
|
||||||
_config.GuiItem.AutoUpdateInterval = AutoUpdateInterval;
|
_config.GuiItem.AutoUpdateInterval = AutoUpdateInterval;
|
||||||
_config.GuiItem.CheckPreReleaseUpdate = EnableCheckPreReleaseUpdate;
|
|
||||||
_config.UiItem.EnableDragDropSort = EnableDragDropSort;
|
_config.UiItem.EnableDragDropSort = EnableDragDropSort;
|
||||||
_config.UiItem.DoubleClick2Activate = DoubleClick2Activate;
|
_config.UiItem.DoubleClick2Activate = DoubleClick2Activate;
|
||||||
_config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;
|
_config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ namespace ServiceLib.ViewModels
|
|||||||
private List<ProfileItem> _lstProfile;
|
private List<ProfileItem> _lstProfile;
|
||||||
private string _serverFilter = string.Empty;
|
private string _serverFilter = string.Empty;
|
||||||
private Dictionary<string, bool> _dicHeaderSort = new();
|
private Dictionary<string, bool> _dicHeaderSort = new();
|
||||||
private SpeedtestService? _speedtestHandler;
|
|
||||||
|
|
||||||
#endregion private prop
|
#endregion private prop
|
||||||
|
|
||||||
@@ -686,12 +685,12 @@ namespace ServiceLib.ViewModels
|
|||||||
}
|
}
|
||||||
//ClearTestResult();
|
//ClearTestResult();
|
||||||
|
|
||||||
_speedtestHandler = new SpeedtestService(_config, lstSelecteds, actionType, UpdateSpeedtestHandler);
|
_ = new SpeedtestService(_config, lstSelecteds, actionType, UpdateSpeedtestHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ServerSpeedtestStop()
|
public void ServerSpeedtestStop()
|
||||||
{
|
{
|
||||||
_speedtestHandler?.ExitLoop();
|
MessageBus.Current.SendMessage("", EMsgCommand.StopSpeedtest.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Export2ClientConfigAsync(bool blClipboard)
|
private async Task Export2ClientConfigAsync(bool blClipboard)
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ namespace v2rayN.Desktop;
|
|||||||
|
|
||||||
public partial class App : Application
|
public partial class App : Application
|
||||||
{
|
{
|
||||||
//public static EventWaitHandle ProgramStarted;
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
if (!AppHandler.Instance.InitApp())
|
if (!AppHandler.Instance.InitApp())
|
||||||
@@ -32,7 +30,7 @@ public partial class App : Application
|
|||||||
{
|
{
|
||||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
{
|
{
|
||||||
OnStartup(desktop.Args);
|
AppHandler.Instance.InitComponents();
|
||||||
|
|
||||||
desktop.Exit += OnExit;
|
desktop.Exit += OnExit;
|
||||||
desktop.MainWindow = new MainWindow();
|
desktop.MainWindow = new MainWindow();
|
||||||
@@ -41,22 +39,6 @@ public partial class App : Application
|
|||||||
base.OnFrameworkInitializationCompleted();
|
base.OnFrameworkInitializationCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStartup(string[]? Args)
|
|
||||||
{
|
|
||||||
var exePathKey = Utils.GetMd5(Utils.GetExePath());
|
|
||||||
|
|
||||||
var rebootas = (Args ?? new string[] { }).Any(t => t == Global.RebootAs);
|
|
||||||
//ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew);
|
|
||||||
//if (!rebootas && !bCreatedNew)
|
|
||||||
//{
|
|
||||||
// ProgramStarted.Set();
|
|
||||||
// Environment.Exit(0);
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
AppHandler.Instance.InitComponents();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.ExceptionObject != null)
|
if (e.ExceptionObject != null)
|
||||||
|
|||||||
BIN
v2rayN/v2rayN.Desktop/Assets/Fonts/NotoSansSC-Regular.ttf
Normal file
BIN
v2rayN/v2rayN.Desktop/Assets/Fonts/NotoSansSC-Regular.ttf
Normal file
Binary file not shown.
19
v2rayN/v2rayN.Desktop/Common/AppBuilderExtension.cs
Normal file
19
v2rayN/v2rayN.Desktop/Common/AppBuilderExtension.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Media;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace v2rayN.Desktop.Common
|
||||||
|
{
|
||||||
|
public static class AppBuilderExtension
|
||||||
|
{
|
||||||
|
public static AppBuilder WithFontByDefault(this AppBuilder appBuilder)
|
||||||
|
{
|
||||||
|
var uri = $"avares://{Assembly.GetExecutingAssembly().GetName().Name}/Assets/Fonts#Noto Sans SC";
|
||||||
|
return appBuilder.With(new FontManagerOptions()
|
||||||
|
{
|
||||||
|
DefaultFamilyName = uri,
|
||||||
|
FontFallbacks = new[] { new FontFallback { FontFamily = new FontFamily(uri) } }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +1,56 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
using v2rayN.Desktop.Common;
|
||||||
|
|
||||||
namespace v2rayN.Desktop;
|
namespace v2rayN.Desktop;
|
||||||
|
|
||||||
internal class Program
|
internal class Program
|
||||||
{
|
{
|
||||||
|
public static EventWaitHandle ProgramStarted;
|
||||||
|
|
||||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||||
// yet and stuff might break.
|
// yet and stuff might break.
|
||||||
[STAThread]
|
[STAThread]
|
||||||
public static void Main(string[] args) => BuildAvaloniaApp()
|
public static void Main(string[] args)
|
||||||
.StartWithClassicDesktopLifetime(args);
|
{
|
||||||
|
OnStartup(args);
|
||||||
|
|
||||||
|
BuildAvaloniaApp()
|
||||||
|
.StartWithClassicDesktopLifetime(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnStartup(string[]? Args)
|
||||||
|
{
|
||||||
|
if (Utils.IsWindows())
|
||||||
|
{
|
||||||
|
var exePathKey = Utils.GetMd5(Utils.GetExePath());
|
||||||
|
var rebootas = (Args ?? new string[] { }).Any(t => t == Global.RebootAs);
|
||||||
|
ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew);
|
||||||
|
if (!rebootas && !bCreatedNew)
|
||||||
|
{
|
||||||
|
ProgramStarted.Set();
|
||||||
|
Environment.Exit(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ = new Mutex(true, "v2rayN", out var bOnlyOneInstance);
|
||||||
|
if (!bOnlyOneInstance)
|
||||||
|
{
|
||||||
|
Environment.Exit(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Avalonia configuration, don't remove; also used by visual designer.
|
// Avalonia configuration, don't remove; also used by visual designer.
|
||||||
public static AppBuilder BuildAvaloniaApp()
|
public static AppBuilder BuildAvaloniaApp()
|
||||||
=> AppBuilder.Configure<App>()
|
=> AppBuilder.Configure<App>()
|
||||||
.UsePlatformDetect()
|
.UsePlatformDetect()
|
||||||
.WithInterFont()
|
//.WithInterFont()
|
||||||
|
.WithFontByDefault()
|
||||||
.LogToTrace()
|
.LogToTrace()
|
||||||
.UseReactiveUI();
|
.UseReactiveUI();
|
||||||
}
|
}
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
<ListBox
|
<ListBox
|
||||||
x:Name="lstCheckUpdates"
|
x:Name="lstCheckUpdates"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
ItemsSource="{Binding CheckUpdateItems}">
|
ItemsSource="{Binding CheckUpdateModels}">
|
||||||
<ItemsControl.ItemsPanel>
|
<ItemsControl.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
<StackPanel Orientation="Vertical" />
|
<StackPanel Orientation="Vertical" />
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
this.OneWayBind(ViewModel, vm => vm.CheckUpdateItems, v => v.lstCheckUpdates.ItemsSource).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.CheckUpdateModels, v => v.lstCheckUpdates.ItemsSource).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);
|
||||||
@@ -29,7 +29,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
case EViewAction.DispatcherCheckUpdate:
|
case EViewAction.DispatcherCheckUpdate:
|
||||||
if (obj is null) return false;
|
if (obj is null) return false;
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
ViewModel?.UpdateViewResult((CheckUpdateItem)obj),
|
ViewModel?.UpdateViewResult((CheckUpdateModel)obj),
|
||||||
DispatcherPriority.Default);
|
DispatcherPriority.Default);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@
|
|||||||
<MenuItem x:Name="menuClose" Padding="8,0">
|
<MenuItem x:Name="menuClose" Padding="8,0">
|
||||||
<MenuItem.Header>
|
<MenuItem.Header>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock Text="{x:Static resx:ResUI.menuClose}" />
|
<TextBlock Text="{x:Static resx:ResUI.menuExit}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</MenuItem.Header>
|
</MenuItem.Header>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Avalonia.Interactivity;
|
|||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using DialogHostAvalonia;
|
using DialogHostAvalonia;
|
||||||
|
using MsBox.Avalonia.Enums;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using Splat;
|
using Splat;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
@@ -29,13 +30,10 @@ namespace v2rayN.Desktop.Views
|
|||||||
_config = AppHandler.Instance.Config;
|
_config = AppHandler.Instance.Config;
|
||||||
_manager = new WindowNotificationManager(TopLevel.GetTopLevel(this)) { MaxItems = 3, Position = NotificationPosition.BottomRight };
|
_manager = new WindowNotificationManager(TopLevel.GetTopLevel(this)) { MaxItems = 3, Position = NotificationPosition.BottomRight };
|
||||||
|
|
||||||
//ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);
|
|
||||||
|
|
||||||
this.Closing += MainWindow_Closing;
|
this.Closing += MainWindow_Closing;
|
||||||
this.KeyDown += MainWindow_KeyDown;
|
this.KeyDown += MainWindow_KeyDown;
|
||||||
menuSettingsSetUWP.Click += menuSettingsSetUWP_Click;
|
menuSettingsSetUWP.Click += menuSettingsSetUWP_Click;
|
||||||
menuPromotion.Click += menuPromotion_Click;
|
menuPromotion.Click += menuPromotion_Click;
|
||||||
menuClose.Click += menuClose_Click;
|
|
||||||
menuCheckUpdate.Click += MenuCheckUpdate_Click;
|
menuCheckUpdate.Click += MenuCheckUpdate_Click;
|
||||||
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
|
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
|
||||||
|
|
||||||
@@ -82,6 +80,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
||||||
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
||||||
|
this.BindCommand(ViewModel, vm => vm.ExitCmd, v => v.menuClose).DisposeWith(disposables);
|
||||||
|
|
||||||
switch (_config.UiItem.MainGirdOrientation)
|
switch (_config.UiItem.MainGirdOrientation)
|
||||||
{
|
{
|
||||||
@@ -114,6 +113,8 @@ namespace v2rayN.Desktop.Views
|
|||||||
this.Title = $"{Utils.GetVersion()} - {(AppHandler.Instance.IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
|
this.Title = $"{Utils.GetVersion()} - {(AppHandler.Instance.IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
|
||||||
if (Utils.IsWindows())
|
if (Utils.IsWindows())
|
||||||
{
|
{
|
||||||
|
ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);
|
||||||
|
|
||||||
menuGlobalHotkeySetting.IsVisible = false;
|
menuGlobalHotkeySetting.IsVisible = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -158,7 +159,9 @@ namespace v2rayN.Desktop.Views
|
|||||||
|
|
||||||
private void OnProgramStarted(object state, bool timeout)
|
private void OnProgramStarted(object state, bool timeout)
|
||||||
{
|
{
|
||||||
ShowHideWindow(true);
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
ShowHideWindow(true),
|
||||||
|
DispatcherPriority.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DelegateSnackMsg(string content)
|
private void DelegateSnackMsg(string content)
|
||||||
@@ -240,6 +243,14 @@ namespace v2rayN.Desktop.Views
|
|||||||
Locator.Current.GetService<ProfilesViewModel>()?.AutofitColumnWidthAsync(),
|
Locator.Current.GetService<ProfilesViewModel>()?.AutofitColumnWidthAsync(),
|
||||||
DispatcherPriority.Default);
|
DispatcherPriority.Default);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EViewAction.ShowYesNo:
|
||||||
|
if (await UI.ShowYesNo(this, ResUI.menuExitTips) == ButtonResult.No)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
StorageUI();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await Task.FromResult(true);
|
return await Task.FromResult(true);
|
||||||
@@ -302,12 +313,6 @@ namespace v2rayN.Desktop.Views
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void menuClose_Click(object? sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
StorageUI();
|
|
||||||
ShowHideWindow(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void menuPromotion_Click(object? sender, RoutedEventArgs e)
|
private void menuPromotion_Click(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Utils.ProcessStart($"{Utils.Base64Decode(Global.PromotionUrl)}?t={DateTime.Now.Ticks}");
|
Utils.ProcessStart($"{Utils.Base64Decode(Global.PromotionUrl)}?t={DateTime.Now.Ticks}");
|
||||||
@@ -374,8 +379,16 @@ namespace v2rayN.Desktop.Views
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.Hide();
|
if (Utils.IsWindows())
|
||||||
|
{
|
||||||
|
this.Hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.WindowState = WindowState.Minimized;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_config.UiItem.ShowInTaskbar = bl;
|
_config.UiItem.ShowInTaskbar = bl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@
|
|||||||
Classes="TextArea"
|
Classes="TextArea"
|
||||||
IsReadOnly="True"
|
IsReadOnly="True"
|
||||||
TextAlignment="Left"
|
TextAlignment="Left"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
TextWrapping="Wrap">
|
TextWrapping="Wrap">
|
||||||
<TextBox.ContextMenu>
|
<TextBox.ContextMenu>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
|
|||||||
@@ -489,18 +489,7 @@
|
|||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Classes="Margin8" />
|
Classes="Margin8" />
|
||||||
|
|
||||||
<TextBlock
|
|
||||||
Grid.Row="9"
|
|
||||||
Grid.Column="0"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Classes="Margin8"
|
|
||||||
Text="{x:Static resx:ResUI.TbSettingsEnableCheckPreReleaseUpdate}" />
|
|
||||||
<ToggleSwitch
|
|
||||||
x:Name="togEnableCheckPreReleaseUpdate"
|
|
||||||
Grid.Row="9"
|
|
||||||
Grid.Column="1"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Classes="Margin8" />
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="11"
|
Grid.Row="11"
|
||||||
|
|||||||
@@ -131,7 +131,6 @@ namespace v2rayN.Desktop.Views
|
|||||||
this.Bind(ViewModel, vm => vm.EnableUpdateSubOnlyRemarksExist, v => v.togEnableUpdateSubOnlyRemarksExist.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);
|
this.Bind(ViewModel, vm => vm.EnableSecurityProtocolTls13, v => v.togEnableSecurityProtocolTls13.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.AutoHideStartup, v => v.togAutoHideStartup.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.AutoHideStartup, v => v.togAutoHideStartup.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.DoubleClick2Activate, v => v.togDoubleClick2Activate.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.DoubleClick2Activate, v => v.togDoubleClick2Activate.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CurrentFontFamily, v => v.cmbcurrentFontFamily.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CurrentFontFamily, v => v.cmbcurrentFontFamily.SelectedValue).DisposeWith(disposables);
|
||||||
@@ -174,7 +173,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
{
|
{
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case EViewAction.CloseWindow:
|
case EViewAction.CloseWindow:
|
||||||
this.Close(true);
|
this.Close(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -189,6 +189,8 @@ namespace v2rayN.Desktop.Views
|
|||||||
|
|
||||||
private void LstProfiles_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)
|
private void LstProfiles_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)
|
||||||
{
|
{
|
||||||
|
var source = e.Source as Border;
|
||||||
|
if (source == null || source.Name != "CellBorder") return;
|
||||||
if (_config.UiItem.DoubleClick2Activate)
|
if (_config.UiItem.DoubleClick2Activate)
|
||||||
{
|
{
|
||||||
ViewModel?.SetDefaultServer();
|
ViewModel?.SetDefaultServer();
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
@@ -114,7 +115,7 @@
|
|||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
x:Name="txtAutoUpdateInterval"
|
x:Name="txtAutoUpdateInterval"
|
||||||
Width="200"
|
Width="100"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Classes="Margin8"
|
Classes="Margin8"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
@@ -233,13 +234,27 @@
|
|||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="12"
|
Grid.Row="12"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Classes="Margin8"
|
||||||
|
Text="{x:Static resx:ResUI.LvMemo}" />
|
||||||
|
<TextBox
|
||||||
|
x:Name="txtMemo"
|
||||||
|
Grid.Row="12"
|
||||||
|
Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Classes="Margin8"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="13"
|
||||||
|
Grid.Column="0"
|
||||||
Grid.ColumnSpan="2"
|
Grid.ColumnSpan="2"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Classes="Margin8"
|
Classes="Margin8"
|
||||||
Text="{x:Static resx:ResUI.LvMoreUrl}" />
|
Text="{x:Static resx:ResUI.LvMoreUrl}" />
|
||||||
<TextBox
|
<TextBox
|
||||||
x:Name="txtMoreUrl"
|
x:Name="txtMoreUrl"
|
||||||
Grid.Row="13"
|
Grid.Row="14"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
MinHeight="100"
|
MinHeight="100"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
this.Bind(ViewModel, vm => vm.SelectedSource.PrevProfile, v => v.txtPrevProfile.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.PrevProfile, v => v.txtPrevProfile.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.NextProfile, v => v.txtNextProfile.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.NextProfile, v => v.txtNextProfile.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.PreSocksPort, v => v.txtPreSocksPort.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.PreSocksPort, v => v.txtPreSocksPort.Text).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.SelectedSource.Memo, v => v.txtMemo.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,16 +20,16 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.1.4" />
|
<PackageReference Include="Avalonia" Version="11.2.0" />
|
||||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.1.4" />
|
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.2.0" />
|
||||||
<PackageReference Include="Avalonia.Desktop" Version="11.1.4" />
|
<PackageReference Include="Avalonia.Desktop" Version="11.2.0" />
|
||||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.1.4" />
|
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.0" />
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.1.4" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.2.0" />
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.1.4" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="11.2.0" />
|
||||||
<PackageReference Include="DialogHost.Avalonia" Version="0.8.1" />
|
<PackageReference Include="DialogHost.Avalonia" Version="0.8.1" />
|
||||||
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0" />
|
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0" />
|
||||||
<PackageReference Include="Semi.Avalonia" Version="11.1.0.4" />
|
<PackageReference Include="Semi.Avalonia" Version="11.2.0" />
|
||||||
<PackageReference Include="Semi.Avalonia.DataGrid" Version="11.1.0.4" />
|
<PackageReference Include="Semi.Avalonia.DataGrid" Version="11.2.0" />
|
||||||
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
||||||
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
this.OneWayBind(ViewModel, vm => vm.CheckUpdateItems, v => v.lstCheckUpdates.ItemsSource).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.CheckUpdateModels, v => v.lstCheckUpdates.ItemsSource).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);
|
||||||
@@ -30,7 +30,7 @@ namespace v2rayN.Views
|
|||||||
if (obj is null) return false;
|
if (obj is null) return false;
|
||||||
Application.Current?.Dispatcher.Invoke((() =>
|
Application.Current?.Dispatcher.Invoke((() =>
|
||||||
{
|
{
|
||||||
ViewModel?.UpdateViewResult((CheckUpdateItem)obj);
|
ViewModel?.UpdateViewResult((CheckUpdateModel)obj);
|
||||||
}), DispatcherPriority.Normal);
|
}), DispatcherPriority.Normal);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -367,17 +367,17 @@ namespace v2rayN.Views
|
|||||||
var bl = blShow ?? !_config.UiItem.ShowInTaskbar;
|
var bl = blShow ?? !_config.UiItem.ShowInTaskbar;
|
||||||
if (bl)
|
if (bl)
|
||||||
{
|
{
|
||||||
Application.Current.MainWindow.Show();
|
this?.Show();
|
||||||
if (Application.Current.MainWindow.WindowState == WindowState.Minimized)
|
if (this?.WindowState == WindowState.Minimized)
|
||||||
{
|
{
|
||||||
Application.Current.MainWindow.WindowState = WindowState.Normal;
|
this.WindowState = WindowState.Normal;
|
||||||
}
|
}
|
||||||
Application.Current.MainWindow.Activate();
|
this?.Activate();
|
||||||
Application.Current.MainWindow.Focus();
|
this?.Focus();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Application.Current.MainWindow.Hide();
|
this?.Hide();
|
||||||
}
|
}
|
||||||
_config.UiItem.ShowInTaskbar = bl;
|
_config.UiItem.ShowInTaskbar = bl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,8 @@
|
|||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
<TextBox
|
<TextBox
|
||||||
Name="txtMsg"
|
Name="txtMsg"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
AcceptsReturn="True"
|
||||||
BorderThickness="0"
|
BorderThickness="0"
|
||||||
FontSize="{DynamicResource StdFontSize-1}"
|
FontSize="{DynamicResource StdFontSize-1}"
|
||||||
HorizontalScrollBarVisibility="Auto"
|
HorizontalScrollBarVisibility="Auto"
|
||||||
|
|||||||
@@ -661,20 +661,6 @@
|
|||||||
Margin="{StaticResource Margin8}"
|
Margin="{StaticResource Margin8}"
|
||||||
HorizontalAlignment="Left" />
|
HorizontalAlignment="Left" />
|
||||||
|
|
||||||
<TextBlock
|
|
||||||
Grid.Row="9"
|
|
||||||
Grid.Column="0"
|
|
||||||
Margin="{StaticResource Margin8}"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
|
||||||
Text="{x:Static resx:ResUI.TbSettingsEnableCheckPreReleaseUpdate}" />
|
|
||||||
<ToggleButton
|
|
||||||
x:Name="togEnableCheckPreReleaseUpdate"
|
|
||||||
Grid.Row="9"
|
|
||||||
Grid.Column="1"
|
|
||||||
Margin="{StaticResource Margin8}"
|
|
||||||
HorizontalAlignment="Left" />
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="10"
|
Grid.Row="10"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
|
|||||||
@@ -141,7 +141,6 @@ namespace v2rayN.Views
|
|||||||
this.Bind(ViewModel, vm => vm.EnableUpdateSubOnlyRemarksExist, v => v.togEnableUpdateSubOnlyRemarksExist.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);
|
this.Bind(ViewModel, vm => vm.EnableSecurityProtocolTls13, v => v.togEnableSecurityProtocolTls13.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.AutoHideStartup, v => v.togAutoHideStartup.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.AutoHideStartup, v => v.togAutoHideStartup.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.EnableDragDropSort, v => v.togEnableDragDropSort.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.EnableDragDropSort, v => v.togEnableDragDropSort.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DoubleClick2Activate, v => v.togDoubleClick2Activate.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.DoubleClick2Activate, v => v.togDoubleClick2Activate.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<reactiveui:ReactiveWindow
|
<reactiveui:ReactiveWindow
|
||||||
x:Class="v2rayN.Views.SubEditWindow"
|
x:Class="v2rayN.Views.SubEditWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
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:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:conv="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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:reactiveui="http://reactiveui.net"
|
||||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||||
xmlns:conv="clr-namespace:v2rayN.Converters"
|
|
||||||
Title="{x:Static resx:ResUI.menuSubSetting}"
|
Title="{x:Static resx:ResUI.menuSubSetting}"
|
||||||
Width="700"
|
Width="700"
|
||||||
Height="600"
|
Height="600"
|
||||||
@@ -70,6 +70,7 @@
|
|||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
@@ -165,7 +166,7 @@
|
|||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
x:Name="txtAutoUpdateInterval"
|
x:Name="txtAutoUpdateInterval"
|
||||||
Width="200"
|
Width="100"
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.SubUrlTips}"
|
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.SubUrlTips}"
|
||||||
@@ -300,6 +301,24 @@
|
|||||||
AcceptsReturn="True"
|
AcceptsReturn="True"
|
||||||
Style="{StaticResource MyOutlinedTextBox}"
|
Style="{StaticResource MyOutlinedTextBox}"
|
||||||
ToolTip="{x:Static resx:ResUI.TipPreSocksPort}" />
|
ToolTip="{x:Static resx:ResUI.TipPreSocksPort}" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="12"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="{StaticResource Margin4}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
|
Text="{x:Static resx:ResUI.LvMemo}" />
|
||||||
|
<TextBox
|
||||||
|
x:Name="txtMemo"
|
||||||
|
Grid.Row="12"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="{StaticResource Margin4}"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
AcceptsReturn="True"
|
||||||
|
Style="{StaticResource MyOutlinedTextBox}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ namespace v2rayN.Views
|
|||||||
this.Bind(ViewModel, vm => vm.SelectedSource.PrevProfile, v => v.txtPrevProfile.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.PrevProfile, v => v.txtPrevProfile.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.NextProfile, v => v.txtNextProfile.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.NextProfile, v => v.txtNextProfile.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.PreSocksPort, v => v.txtPreSocksPort.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.PreSocksPort, v => v.txtPreSocksPort.Text).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.SelectedSource.Memo, v => v.txtMemo.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user