Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
798c7fad9a | ||
|
|
5797b37262 | ||
|
|
ce22f34cd6 | ||
|
|
4c49e52e26 | ||
|
|
47318b5d70 | ||
|
|
d12297909c | ||
|
|
5fb4edae2d | ||
|
|
c4b490e46d | ||
|
|
45febe3fff | ||
|
|
689a81a985 | ||
|
|
28620b385a | ||
|
|
be13446e69 | ||
|
|
ee57d5b8e6 | ||
|
|
4eda3dd8fa | ||
|
|
911dc7f90e | ||
|
|
18005b96e8 | ||
|
|
a3e45d206e | ||
|
|
0accf262dc | ||
|
|
e0eb73bb0a | ||
|
|
258e822c13 | ||
|
|
4f05b93d63 | ||
|
|
bb661d4f50 | ||
|
|
201cfaa922 | ||
|
|
c339aa349c | ||
|
|
046421f345 | ||
|
|
3a2c9e7aaa | ||
|
|
0bb6e6bd86 | ||
|
|
693e8ab157 | ||
|
|
033c16c992 | ||
|
|
6ec61433fb | ||
|
|
072f773245 | ||
|
|
0086f65a96 | ||
|
|
281f14f47e | ||
|
|
9fd20ff001 | ||
|
|
7df90a6034 | ||
|
|
019869ec28 | ||
|
|
b7f4fd7469 | ||
|
|
1273d2aee1 | ||
|
|
88990b4828 | ||
|
|
2f02c2970c | ||
|
|
ade789c6d4 | ||
|
|
9738f90970 | ||
|
|
6ed0741339 | ||
|
|
e6b1e22245 | ||
|
|
6b922be0c6 | ||
|
|
6e35a260e8 | ||
|
|
1106fd8cf1 | ||
|
|
fb92b90d5c | ||
|
|
5effbee50b | ||
|
|
9bc50a9f34 | ||
|
|
2a5a339c27 | ||
|
|
78d182fff3 | ||
|
|
0efb0b5e3e | ||
|
|
a2e8755730 | ||
|
|
06ddedbc4c | ||
|
|
fa148cdf42 |
@@ -1,6 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace AmazTool
|
||||
@@ -12,7 +11,7 @@ namespace AmazTool
|
||||
Console.WriteLine(fileName);
|
||||
Console.WriteLine("In progress, please wait...(正在进行中,请等待)");
|
||||
|
||||
Thread.Sleep(5000);
|
||||
Thread.Sleep(9000);
|
||||
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
@@ -20,17 +19,14 @@ namespace AmazTool
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Try to end the process(尝试结束进程).");
|
||||
try
|
||||
{
|
||||
Process[] existing = Process.GetProcessesByName(V2rayN());
|
||||
foreach (Process p in existing)
|
||||
var existing = Process.GetProcessesByName(V2rayN);
|
||||
foreach (var pp in existing)
|
||||
{
|
||||
var path = p.MainModule?.FileName ?? "";
|
||||
if (path.StartsWith(GetPath(V2rayN())))
|
||||
{
|
||||
p.Kill();
|
||||
p.WaitForExit(100);
|
||||
}
|
||||
pp?.Kill();
|
||||
pp?.WaitForExit(1000);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -40,6 +36,7 @@ namespace AmazTool
|
||||
"Close it manually, or the upgrade may fail.(请手动关闭正在运行的v2rayN,否则可能升级失败。\n\n" + ex.StackTrace);
|
||||
}
|
||||
|
||||
Console.WriteLine("Start extracting files(开始解压文件).");
|
||||
StringBuilder sb = new();
|
||||
try
|
||||
{
|
||||
@@ -57,6 +54,8 @@ namespace AmazTool
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine(entry.FullName);
|
||||
|
||||
var lst = entry.FullName.Split(splitKey);
|
||||
if (lst.Length == 1) continue;
|
||||
string fullName = string.Join(splitKey, lst[1..lst.Length]);
|
||||
@@ -81,22 +80,22 @@ namespace AmazTool
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Upgrade Failed(升级失败)." + ex.StackTrace);
|
||||
return;
|
||||
//return;
|
||||
}
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
Console.WriteLine("Upgrade Failed.\n" +
|
||||
"(升级失败)." + sb.ToString());
|
||||
return;
|
||||
Console.WriteLine("Upgrade Failed(升级失败)." + sb.ToString());
|
||||
//return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Start v2rayN, please wait...(正在重启,请等待)");
|
||||
Thread.Sleep(3000);
|
||||
Thread.Sleep(9000);
|
||||
Process process = new()
|
||||
{
|
||||
StartInfo = new()
|
||||
{
|
||||
FileName = V2rayN(),
|
||||
UseShellExecute = true,
|
||||
FileName = V2rayN,
|
||||
WorkingDirectory = StartupPath()
|
||||
}
|
||||
};
|
||||
@@ -123,19 +122,6 @@ namespace AmazTool
|
||||
return Path.Combine(startupPath, fileName);
|
||||
}
|
||||
|
||||
private static string V2rayN()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
if (File.Exists(GetPath("v2rayN.exe")))
|
||||
return "v2rayN";
|
||||
else
|
||||
return "v2rayN.Desktop";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "v2rayN.Desktop";
|
||||
}
|
||||
}
|
||||
private static string V2rayN => "v2rayN";
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Mime;
|
||||
using System.Text;
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace ServiceLib.Common
|
||||
totalRead += read;
|
||||
|
||||
if (read == 0) break;
|
||||
await file.WriteAsync(buffer, 0, read, token);
|
||||
await file.WriteAsync(buffer.AsMemory(0, read), token);
|
||||
|
||||
if (canReportProgress)
|
||||
{
|
||||
|
||||
@@ -37,40 +37,41 @@ namespace ServiceLib.Common
|
||||
foreach (var filePath in files)
|
||||
{
|
||||
var file = new FileInfo(filePath);
|
||||
if (file.CreationTime < now)
|
||||
if (file.CreationTime >= now) continue;
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
file.Delete();
|
||||
}
|
||||
catch { }
|
||||
file.Delete();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void SaveLog(string strContent)
|
||||
{
|
||||
if (LogManager.IsLoggingEnabled())
|
||||
{
|
||||
var logger = LogManager.GetLogger("Log1");
|
||||
logger.Info(strContent);
|
||||
}
|
||||
if (!LogManager.IsLoggingEnabled()) return;
|
||||
|
||||
LogManager.GetLogger("Log1").Info(strContent);
|
||||
}
|
||||
|
||||
public static void SaveLog(string strTitle, Exception ex)
|
||||
{
|
||||
if (LogManager.IsLoggingEnabled())
|
||||
if (!LogManager.IsLoggingEnabled()) return;
|
||||
|
||||
var logger = LogManager.GetLogger("Log2");
|
||||
logger.Debug($"{strTitle},{ex.Message}");
|
||||
logger.Debug(ex.StackTrace);
|
||||
if (ex?.InnerException != null)
|
||||
{
|
||||
var logger = LogManager.GetLogger("Log2");
|
||||
logger.Debug($"{strTitle},{ex.Message}");
|
||||
logger.Debug(ex.StackTrace);
|
||||
if (ex?.InnerException != null)
|
||||
{
|
||||
logger.Error(ex.InnerException);
|
||||
}
|
||||
logger.Error(ex.InnerException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using CliWrap;
|
||||
using CliWrap;
|
||||
using CliWrap.Buffered;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
@@ -38,6 +38,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -58,6 +59,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -92,6 +94,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
@@ -116,6 +119,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -137,6 +141,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -156,6 +161,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Logging.SaveLog("Base64Encode", ex);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
@@ -170,16 +176,16 @@ namespace ServiceLib.Common
|
||||
{
|
||||
if (plainText.IsNullOrEmpty()) return "";
|
||||
plainText = plainText.Trim()
|
||||
.Replace(Environment.NewLine, "")
|
||||
.Replace("\n", "")
|
||||
.Replace("\r", "")
|
||||
.Replace('_', '/')
|
||||
.Replace('-', '+')
|
||||
.Replace(" ", "");
|
||||
.Replace(Environment.NewLine, "")
|
||||
.Replace("\n", "")
|
||||
.Replace("\r", "")
|
||||
.Replace('_', '/')
|
||||
.Replace('-', '+')
|
||||
.Replace(" ", "");
|
||||
|
||||
if (plainText.Length % 4 > 0)
|
||||
{
|
||||
plainText = plainText.PadRight(plainText.Length + 4 - plainText.Length % 4, '=');
|
||||
plainText = plainText.PadRight(plainText.Length + 4 - (plainText.Length % 4), '=');
|
||||
}
|
||||
|
||||
var data = Convert.FromBase64String(plainText);
|
||||
@@ -189,6 +195,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Logging.SaveLog("Base64Decode", ex);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
@@ -251,14 +258,17 @@ namespace ServiceLib.Common
|
||||
unit = "TB";
|
||||
return;
|
||||
}
|
||||
|
||||
result = GBs + ((MBs % factor) / (factor + 0.0));
|
||||
unit = "GB";
|
||||
return;
|
||||
}
|
||||
|
||||
result = MBs + ((KBs % factor) / (factor + 0.0));
|
||||
unit = "MB";
|
||||
return;
|
||||
}
|
||||
|
||||
result = KBs + ((amount % factor) / (factor + 0.0));
|
||||
unit = "KB";
|
||||
return;
|
||||
@@ -302,6 +312,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var key = Uri.UnescapeDataString(keyValue[0]);
|
||||
var val = Uri.UnescapeDataString(keyValue[1]);
|
||||
|
||||
@@ -323,6 +334,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
sb.Append(b.ToString("x2"));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -337,6 +349,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
return url;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Uri uri = new(url);
|
||||
@@ -368,6 +381,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
return text.Replace(",", ",").Replace(Environment.NewLine, ",");
|
||||
}
|
||||
|
||||
@@ -391,6 +405,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return text == "null";
|
||||
}
|
||||
|
||||
@@ -424,6 +439,7 @@ namespace ServiceLib.Common
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -448,6 +464,7 @@ namespace ServiceLib.Common
|
||||
if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) return true;
|
||||
if (ipBytes[0] == 192 && ipBytes[1] == 168) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -468,6 +485,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -489,6 +507,7 @@ namespace ServiceLib.Common
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
return 59090;
|
||||
}
|
||||
|
||||
@@ -512,7 +531,8 @@ namespace ServiceLib.Common
|
||||
{
|
||||
if (blFull)
|
||||
{
|
||||
return $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture} - {File.GetLastWriteTime(GetExePath()):yyyy/MM/dd}";
|
||||
return
|
||||
$"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture} - {File.GetLastWriteTime(GetExePath()):yyyy/MM/dd}";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -523,6 +543,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
|
||||
return Global.AppName;
|
||||
}
|
||||
|
||||
@@ -560,6 +581,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
@@ -572,7 +594,11 @@ namespace ServiceLib.Common
|
||||
{
|
||||
try
|
||||
{
|
||||
if (fileName.IsNullOrEmpty()) { return; }
|
||||
if (fileName.IsNullOrEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Process.Start(new ProcessStartInfo(fileName, arguments) { UseShellExecute = true });
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -605,6 +631,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
|
||||
return systemHosts;
|
||||
}
|
||||
|
||||
@@ -629,17 +656,20 @@ namespace ServiceLib.Common
|
||||
cmd = cmd.WithArguments(args);
|
||||
}
|
||||
}
|
||||
|
||||
var result = await cmd.ExecuteBufferedAsync();
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
return result.StandardOutput.ToString();
|
||||
}
|
||||
|
||||
Logging.SaveLog(result.ToString() ?? "");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog("GetCliWrapOutput", ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -654,6 +684,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
return startupPath;
|
||||
}
|
||||
|
||||
return Path.Combine(startupPath, fileName);
|
||||
}
|
||||
|
||||
@@ -674,6 +705,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Directory.CreateDirectory(tempPath);
|
||||
}
|
||||
|
||||
if (IsNullOrEmpty(filename))
|
||||
{
|
||||
return tempPath;
|
||||
@@ -691,6 +723,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Directory.CreateDirectory(tempPath);
|
||||
}
|
||||
|
||||
return Path.Combine(tempPath, filename);
|
||||
}
|
||||
|
||||
@@ -701,6 +734,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Directory.CreateDirectory(tempPath);
|
||||
}
|
||||
|
||||
if (Utils.IsNullOrEmpty(filename))
|
||||
{
|
||||
return tempPath;
|
||||
@@ -718,14 +752,16 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Directory.CreateDirectory(tempPath);
|
||||
}
|
||||
|
||||
if (coreType != null)
|
||||
{
|
||||
tempPath = Path.Combine(tempPath, coreType.ToString());
|
||||
tempPath = Path.Combine(tempPath, coreType.ToLower().ToString());
|
||||
if (!Directory.Exists(tempPath))
|
||||
{
|
||||
Directory.CreateDirectory(tempPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsNullOrEmpty(filename))
|
||||
{
|
||||
return tempPath;
|
||||
@@ -743,6 +779,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Directory.CreateDirectory(tempPath);
|
||||
}
|
||||
|
||||
if (Utils.IsNullOrEmpty(filename))
|
||||
{
|
||||
return tempPath;
|
||||
@@ -760,6 +797,7 @@ namespace ServiceLib.Common
|
||||
{
|
||||
Directory.CreateDirectory(tempPath);
|
||||
}
|
||||
|
||||
if (Utils.IsNullOrEmpty(filename))
|
||||
{
|
||||
return tempPath;
|
||||
@@ -818,6 +856,20 @@ namespace ServiceLib.Common
|
||||
return await GetCliWrapOutput("/bin/bash", arg);
|
||||
}
|
||||
|
||||
public static async Task<string?> GetLinuxFontFamily(string lang)
|
||||
{
|
||||
// var arg = new List<string>() { "-c", $"fc-list :lang={lang} family" };
|
||||
var arg = new List<string>() { "-c", $"fc-list : family" };
|
||||
return await GetCliWrapOutput("/bin/bash", arg);
|
||||
}
|
||||
|
||||
public static string? GetHomePath()
|
||||
{
|
||||
return IsWindows()
|
||||
? Environment.ExpandEnvironmentVariables("%HOMEDRIVE%%HOMEPATH%")
|
||||
: Environment.GetEnvironmentVariable("HOME");
|
||||
}
|
||||
|
||||
#endregion Platform
|
||||
}
|
||||
}
|
||||
52
v2rayN/ServiceLib/Common/WindowsUtils.cs
Normal file
52
v2rayN/ServiceLib/Common/WindowsUtils.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace ServiceLib.Common
|
||||
{
|
||||
internal static class WindowsUtils
|
||||
{
|
||||
public static string? RegReadValue(string path, string name, string def)
|
||||
{
|
||||
RegistryKey? regKey = null;
|
||||
try
|
||||
{
|
||||
regKey = Registry.CurrentUser.OpenSubKey(path, false);
|
||||
var value = regKey?.GetValue(name) as string;
|
||||
return Utils.IsNullOrEmpty(value) ? def : value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
regKey?.Close();
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static void RegWriteValue(string path, string name, object value)
|
||||
{
|
||||
RegistryKey? regKey = null;
|
||||
try
|
||||
{
|
||||
regKey = Registry.CurrentUser.CreateSubKey(path);
|
||||
if (Utils.IsNullOrEmpty(value.ToString()))
|
||||
{
|
||||
regKey?.DeleteValue(name, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
regKey?.SetValue(name, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
regKey?.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
ClearMsg,
|
||||
SendMsgView,
|
||||
SendSnackMsg,
|
||||
RefreshProfiles
|
||||
RefreshProfiles,
|
||||
StopSpeedtest
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
Shutdown,
|
||||
BrowseServer,
|
||||
ImportRulesFromFile,
|
||||
InitSettingFont,
|
||||
SubEditWindow,
|
||||
RoutingRuleSettingWindow,
|
||||
RoutingRuleDetailsWindow,
|
||||
|
||||
@@ -28,21 +28,24 @@
|
||||
public const string CoreSpeedtestConfigFileName = "configSpeedtest.json";
|
||||
public const string CoreMultipleLoadConfigFileName = "configMultipleLoad.json";
|
||||
public const string ClashMixinConfigFileName = "Mixin.yaml";
|
||||
public const string V2raySampleClient = "ServiceLib.Sample.SampleClientConfig";
|
||||
public const string SingboxSampleClient = "ServiceLib.Sample.SingboxSampleClientConfig";
|
||||
public const string V2raySampleHttpRequestFileName = "ServiceLib.Sample.SampleHttpRequest";
|
||||
public const string V2raySampleHttpResponseFileName = "ServiceLib.Sample.SampleHttpResponse";
|
||||
public const string V2raySampleInbound = "ServiceLib.Sample.SampleInbound";
|
||||
public const string V2raySampleOutbound = "ServiceLib.Sample.SampleOutbound";
|
||||
public const string SingboxSampleOutbound = "ServiceLib.Sample.SingboxSampleOutbound";
|
||||
public const string CustomRoutingFileName = "ServiceLib.Sample.custom_routing_";
|
||||
public const string TunSingboxDNSFileName = "ServiceLib.Sample.tun_singbox_dns";
|
||||
public const string TunSingboxInboundFileName = "ServiceLib.Sample.tun_singbox_inbound";
|
||||
public const string TunSingboxRulesFileName = "ServiceLib.Sample.tun_singbox_rules";
|
||||
public const string DNSV2rayNormalFileName = "ServiceLib.Sample.dns_v2ray_normal";
|
||||
public const string DNSSingboxNormalFileName = "ServiceLib.Sample.dns_singbox_normal";
|
||||
public const string ClashMixinYaml = "ServiceLib.Sample.clash_mixin_yaml";
|
||||
public const string ClashTunYaml = "ServiceLib.Sample.clash_tun_yaml";
|
||||
|
||||
public const string NamespaceSample = "ServiceLib.Sample.";
|
||||
public const string V2raySampleClient = NamespaceSample + "SampleClientConfig";
|
||||
public const string SingboxSampleClient = NamespaceSample + "SingboxSampleClientConfig";
|
||||
public const string V2raySampleHttpRequestFileName = NamespaceSample + "SampleHttpRequest";
|
||||
public const string V2raySampleHttpResponseFileName = NamespaceSample + "SampleHttpResponse";
|
||||
public const string V2raySampleInbound = NamespaceSample + "SampleInbound";
|
||||
public const string V2raySampleOutbound = NamespaceSample + "SampleOutbound";
|
||||
public const string SingboxSampleOutbound = NamespaceSample + "SingboxSampleOutbound";
|
||||
public const string CustomRoutingFileName = NamespaceSample + "custom_routing_";
|
||||
public const string TunSingboxDNSFileName = NamespaceSample + "tun_singbox_dns";
|
||||
public const string TunSingboxInboundFileName = NamespaceSample + "tun_singbox_inbound";
|
||||
public const string TunSingboxRulesFileName = NamespaceSample + "tun_singbox_rules";
|
||||
public const string DNSV2rayNormalFileName = NamespaceSample + "dns_v2ray_normal";
|
||||
public const string DNSSingboxNormalFileName = NamespaceSample + "dns_singbox_normal";
|
||||
public const string ClashMixinYaml = NamespaceSample + "clash_mixin_yaml";
|
||||
public const string ClashTunYaml = NamespaceSample + "clash_tun_yaml";
|
||||
public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
|
||||
|
||||
public const string DefaultSecurity = "auto";
|
||||
public const string DefaultNetwork = "tcp";
|
||||
@@ -102,9 +105,9 @@
|
||||
|
||||
public static readonly List<string> SpeedTestUrls = new() {
|
||||
@"https://speed.cloudflare.com/__down?bytes=100000000",
|
||||
@"https://speed.cloudflare.com/__down?bytes=50000000",
|
||||
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
||||
@"http://cachefly.cachefly.net/50mb.test",
|
||||
@"http://cachefly.cachefly.net/10mb.test"
|
||||
@"https://cachefly.cachefly.net/50mb.test",
|
||||
};
|
||||
|
||||
public static readonly List<string> SpeedPingTestUrls = new() {
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
public bool InitComponents()
|
||||
{
|
||||
Logging.Setup();
|
||||
Logging.LoggingEnabled(true);
|
||||
Logging.LoggingEnabled(_config.GuiItem.EnableLog);
|
||||
Logging.SaveLog($"v2rayN start up | {Utils.GetVersion()} | {Utils.GetExePath()}");
|
||||
Logging.SaveLog($"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
|
||||
Logging.ClearLogs();
|
||||
@@ -159,7 +159,7 @@
|
||||
await ConfigHandler.SetDefaultServer(_config, lstModel);
|
||||
|
||||
var lstServerStat = (_config.GuiItem.EnableStatistics ? StatisticsHandler.Instance.ServerStat : null) ?? [];
|
||||
var lstProfileExs = ProfileExHandler.Instance.ProfileExs;
|
||||
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()
|
||||
|
||||
155
v2rayN/ServiceLib/Handler/AutoStartupHandler.cs
Normal file
155
v2rayN/ServiceLib/Handler/AutoStartupHandler.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using System.Security.Principal;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ServiceLib.Handler
|
||||
{
|
||||
public static class AutoStartupHandler
|
||||
{
|
||||
public static async Task<bool> UpdateTask(Config config)
|
||||
{
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
await ClearTaskWindows();
|
||||
|
||||
if (config.GuiItem.AutoRun)
|
||||
{
|
||||
await SetTaskWindows();
|
||||
}
|
||||
}
|
||||
else if (Utils.IsLinux())
|
||||
{
|
||||
await ClearTaskLinux();
|
||||
|
||||
if (config.GuiItem.AutoRun)
|
||||
{
|
||||
await SetTaskLinux();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region Windows
|
||||
|
||||
private static async Task ClearTaskWindows()
|
||||
{
|
||||
var autoRunName = GetAutoRunNameWindows();
|
||||
WindowsUtils.RegWriteValue(Global.AutoRunRegPath, autoRunName, "");
|
||||
if (Utils.IsAdministrator())
|
||||
{
|
||||
AutoStartTaskService(autoRunName, "", "");
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task SetTaskWindows()
|
||||
{
|
||||
try
|
||||
{
|
||||
var autoRunName = GetAutoRunNameWindows();
|
||||
var exePath = Utils.GetExePath();
|
||||
if (Utils.IsAdministrator())
|
||||
{
|
||||
AutoStartTaskService(autoRunName, exePath, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowsUtils.RegWriteValue(Global.AutoRunRegPath, autoRunName, exePath.AppendQuotes());
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Auto Start via TaskService
|
||||
/// </summary>
|
||||
/// <param name="taskName"></param>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="description"></param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static void AutoStartTaskService(string taskName, string fileName, string description)
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(taskName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var logonUser = WindowsIdentity.GetCurrent().Name;
|
||||
using var taskService = new Microsoft.Win32.TaskScheduler.TaskService();
|
||||
var tasks = taskService.RootFolder.GetTasks(new Regex(taskName));
|
||||
if (Utils.IsNullOrEmpty(fileName))
|
||||
{
|
||||
foreach (var t in tasks)
|
||||
{
|
||||
taskService.RootFolder.DeleteTask(t.Name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var task = taskService.NewTask();
|
||||
task.RegistrationInfo.Description = description;
|
||||
task.Settings.DisallowStartIfOnBatteries = false;
|
||||
task.Settings.StopIfGoingOnBatteries = false;
|
||||
task.Settings.RunOnlyIfIdle = false;
|
||||
task.Settings.IdleSettings.StopOnIdleEnd = false;
|
||||
task.Settings.ExecutionTimeLimit = TimeSpan.Zero;
|
||||
task.Triggers.Add(new Microsoft.Win32.TaskScheduler.LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(10) });
|
||||
task.Principal.RunLevel = Microsoft.Win32.TaskScheduler.TaskRunLevel.Highest;
|
||||
task.Actions.Add(new Microsoft.Win32.TaskScheduler.ExecAction(fileName.AppendQuotes(), null, Path.GetDirectoryName(fileName)));
|
||||
|
||||
taskService.RootFolder.RegisterTaskDefinition(taskName, task);
|
||||
}
|
||||
|
||||
private static string GetAutoRunNameWindows()
|
||||
{
|
||||
return $"{Global.AutoRunName}_{Utils.GetMd5(Utils.StartupPath())}";
|
||||
}
|
||||
|
||||
#endregion Windows
|
||||
|
||||
#region Linux
|
||||
|
||||
private static async Task ClearTaskLinux()
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(GetHomePathLinux());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task SetTaskLinux()
|
||||
{
|
||||
try
|
||||
{
|
||||
var linuxConfig = Utils.GetEmbedText(Global.LinuxAutostartConfig);
|
||||
if (linuxConfig.IsNotEmpty())
|
||||
{
|
||||
linuxConfig = linuxConfig.Replace("$ExecPath$", Utils.GetExePath());
|
||||
Logging.SaveLog(linuxConfig);
|
||||
|
||||
var homePath = GetHomePathLinux();
|
||||
await File.WriteAllTextAsync(homePath, linuxConfig);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetHomePathLinux()
|
||||
{
|
||||
var homePath = Path.Combine(Utils.GetHomePath(), ".config", "autostart", $"{Global.AppName}.desktop");
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(homePath));
|
||||
return homePath;
|
||||
}
|
||||
|
||||
#endregion Linux
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ namespace ServiceLib.Handler
|
||||
return new Tuple<ClashProxies, ClashProviders>(clashProxies, clashProviders);
|
||||
}
|
||||
|
||||
await Task.Delay(5000);
|
||||
await Task.Delay(2000);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Data;
|
||||
using System.Data;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ServiceLib.Handler
|
||||
@@ -162,6 +162,7 @@ namespace ServiceLib.Handler
|
||||
config.ClashUIItem ??= new();
|
||||
config.SystemProxyItem ??= new();
|
||||
config.WebDavItem ??= new();
|
||||
config.CheckUpdateItem ??= new();
|
||||
|
||||
return config;
|
||||
}
|
||||
@@ -465,7 +466,7 @@ namespace ServiceLib.Handler
|
||||
break;
|
||||
}
|
||||
case EMove.Position:
|
||||
sort = pos * 10 + 1;
|
||||
sort = (pos * 10) + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -746,7 +747,7 @@ namespace ServiceLib.Handler
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
var lstProfileExs = ProfileExHandler.Instance.ProfileExs;
|
||||
var lstProfileExs = await ProfileExHandler.Instance.GetProfileExs();
|
||||
var lstProfile = (from t in lstModel
|
||||
join t3 in lstProfileExs on t.IndexId equals t3.IndexId into t3b
|
||||
from t33 in t3b.DefaultIfEmpty()
|
||||
@@ -1034,14 +1035,14 @@ namespace ServiceLib.Handler
|
||||
/// <param name="strData"></param>
|
||||
/// <param name="subid"></param>
|
||||
/// <returns>成功导入的数量</returns>
|
||||
private static async Task<int> AddBatchServers(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
||||
private static async Task<int> AddBatchServersCommon(Config config, string strData, string subid, bool isSub)
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(strData))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
string subFilter = string.Empty;
|
||||
var subFilter = string.Empty;
|
||||
//remove sub items
|
||||
if (isSub && Utils.IsNotEmpty(subid))
|
||||
{
|
||||
@@ -1049,16 +1050,14 @@ namespace ServiceLib.Handler
|
||||
subFilter = (await AppHandler.Instance.GetSubItem(subid))?.Filter ?? "";
|
||||
}
|
||||
|
||||
int countServers = 0;
|
||||
//Check for duplicate indexId
|
||||
List<string>? lstDbIndexId = null;
|
||||
var countServers = 0;
|
||||
List<ProfileItem> lstAdd = new();
|
||||
var arrData = strData.Split(Environment.NewLine.ToCharArray()).Where(t => !t.IsNullOrEmpty());
|
||||
if (isSub)
|
||||
{
|
||||
arrData = arrData.Distinct();
|
||||
}
|
||||
foreach (string str in arrData)
|
||||
foreach (var str in arrData)
|
||||
{
|
||||
//maybe sub
|
||||
if (!isSub && (str.StartsWith(Global.HttpsProtocol) || str.StartsWith(Global.HttpProtocol)))
|
||||
@@ -1075,35 +1074,12 @@ namespace ServiceLib.Handler
|
||||
continue;
|
||||
}
|
||||
|
||||
//exist sub items
|
||||
if (isSub && Utils.IsNotEmpty(subid))
|
||||
//exist sub items //filter
|
||||
if (isSub && Utils.IsNotEmpty(subid) && Utils.IsNotEmpty(subFilter))
|
||||
{
|
||||
var existItem = lstOriSub?.FirstOrDefault(t => t.IsSub == isSub
|
||||
&& config.UiItem.EnableUpdateSubOnlyRemarksExist ? t.Remarks == profileItem.Remarks : CompareProfileItem(t, profileItem, true));
|
||||
if (existItem != null)
|
||||
if (!Regex.IsMatch(profileItem.Remarks, subFilter))
|
||||
{
|
||||
//Check for duplicate indexId
|
||||
if (lstDbIndexId is null)
|
||||
{
|
||||
lstDbIndexId = await AppHandler.Instance.ProfileItemIndexes("");
|
||||
}
|
||||
if (lstAdd.Any(t => t.IndexId == existItem.IndexId)
|
||||
|| lstDbIndexId.Any(t => t == existItem.IndexId))
|
||||
{
|
||||
profileItem.IndexId = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
profileItem.IndexId = existItem.IndexId;
|
||||
}
|
||||
}
|
||||
//filter
|
||||
if (Utils.IsNotEmpty(subFilter))
|
||||
{
|
||||
if (!Regex.IsMatch(profileItem.Remarks, subFilter))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
profileItem.Subid = subid;
|
||||
@@ -1138,7 +1114,7 @@ namespace ServiceLib.Handler
|
||||
return countServers;
|
||||
}
|
||||
|
||||
private static async Task<int> AddBatchServers4Custom(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
||||
private static async Task<int> AddBatchServers4Custom(Config config, string strData, string subid, bool isSub)
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(strData))
|
||||
{
|
||||
@@ -1222,10 +1198,7 @@ namespace ServiceLib.Handler
|
||||
{
|
||||
await RemoveServerViaSubid(config, subid, isSub);
|
||||
}
|
||||
if (isSub && lstOriSub?.Count == 1)
|
||||
{
|
||||
profileItem.IndexId = lstOriSub[0].IndexId;
|
||||
}
|
||||
|
||||
profileItem.Subid = subid;
|
||||
profileItem.IsSub = isSub;
|
||||
profileItem.PreSocksPort = preSocksPort;
|
||||
@@ -1239,7 +1212,7 @@ namespace ServiceLib.Handler
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<int> AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub, List<ProfileItem> lstOriSub)
|
||||
private static async Task<int> AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub)
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(strData))
|
||||
{
|
||||
@@ -1278,34 +1251,47 @@ namespace ServiceLib.Handler
|
||||
return -1;
|
||||
}
|
||||
List<ProfileItem>? lstOriSub = null;
|
||||
ProfileItem? activeProfile = null;
|
||||
if (isSub && Utils.IsNotEmpty(subid))
|
||||
{
|
||||
lstOriSub = await AppHandler.Instance.ProfileItems(subid);
|
||||
activeProfile = lstOriSub?.FirstOrDefault(t => t.IndexId == config.IndexId);
|
||||
}
|
||||
|
||||
var counter = 0;
|
||||
if (Utils.IsBase64String(strData))
|
||||
{
|
||||
counter = await AddBatchServers(config, Utils.Base64Decode(strData), subid, isSub, lstOriSub);
|
||||
counter = await AddBatchServersCommon(config, Utils.Base64Decode(strData), subid, isSub);
|
||||
}
|
||||
if (counter < 1)
|
||||
{
|
||||
counter = await AddBatchServers(config, strData, subid, isSub, lstOriSub);
|
||||
counter = await AddBatchServersCommon(config, strData, subid, isSub);
|
||||
}
|
||||
if (counter < 1)
|
||||
{
|
||||
counter = await AddBatchServers(config, Utils.Base64Decode(strData), subid, isSub, lstOriSub);
|
||||
counter = await AddBatchServersCommon(config, Utils.Base64Decode(strData), subid, isSub);
|
||||
}
|
||||
|
||||
if (counter < 1)
|
||||
{
|
||||
counter = await AddBatchServers4SsSIP008(config, strData, subid, isSub, lstOriSub);
|
||||
counter = await AddBatchServers4SsSIP008(config, strData, subid, isSub);
|
||||
}
|
||||
|
||||
//maybe other sub
|
||||
if (counter < 1)
|
||||
{
|
||||
counter = await AddBatchServers4Custom(config, strData, subid, isSub, lstOriSub);
|
||||
counter = await AddBatchServers4Custom(config, strData, subid, isSub);
|
||||
}
|
||||
|
||||
//Select active node
|
||||
if (activeProfile != null)
|
||||
{
|
||||
var lstSub = await AppHandler.Instance.ProfileItems(subid);
|
||||
var existItem = lstSub?.FirstOrDefault(t => config.UiItem.EnableUpdateSubOnlyRemarksExist ? t.Remarks == activeProfile.Remarks : CompareProfileItem(t, activeProfile, true));
|
||||
if (existItem != null)
|
||||
{
|
||||
await ConfigHandler.SetDefaultServerIndex(config, existItem.IndexId);
|
||||
}
|
||||
}
|
||||
|
||||
return counter;
|
||||
@@ -1340,7 +1326,9 @@ namespace ServiceLib.Handler
|
||||
//Do not allow http protocol
|
||||
if (url.StartsWith(Global.HttpProtocol) && !Utils.IsPrivateNetwork(uri.IdnHost))
|
||||
{
|
||||
return -1;
|
||||
//TODO Temporary reminder to be removed later
|
||||
NoticeHandler.Instance.Enqueue(ResUI.InsecureUrlProtocol);
|
||||
//return -1;
|
||||
}
|
||||
|
||||
var queryVars = Utils.ParseQueryString(uri.Query);
|
||||
@@ -1371,6 +1359,7 @@ namespace ServiceLib.Handler
|
||||
item.PrevProfile = subItem.PrevProfile;
|
||||
item.NextProfile = subItem.NextProfile;
|
||||
item.PreSocksPort = subItem.PreSocksPort;
|
||||
item.Memo = subItem.Memo;
|
||||
}
|
||||
|
||||
if (Utils.IsNullOrEmpty(item.Id))
|
||||
|
||||
@@ -12,18 +12,12 @@
|
||||
|
||||
if (node.ConfigType == EConfigType.Custom)
|
||||
{
|
||||
if (node.CoreType is ECoreType.mihomo)
|
||||
result = node.CoreType switch
|
||||
{
|
||||
result = await new CoreConfigClashService(config).GenerateClientCustomConfig(node, fileName);
|
||||
}
|
||||
if (node.CoreType is ECoreType.sing_box)
|
||||
{
|
||||
result = await new CoreConfigSingboxService(config).GenerateClientCustomConfig(node, fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await GenerateClientCustomConfig(node, fileName);
|
||||
}
|
||||
ECoreType.mihomo => await new CoreConfigClashService(config).GenerateClientCustomConfig(node, fileName),
|
||||
ECoreType.sing_box => await new CoreConfigSingboxService(config).GenerateClientCustomConfig(node, fileName),
|
||||
_ => await GenerateClientCustomConfig(node, fileName)
|
||||
};
|
||||
}
|
||||
else if (AppHandler.Instance.GetCoreType(node, node.ConfigType) == ECoreType.sing_box)
|
||||
{
|
||||
|
||||
@@ -15,13 +15,38 @@ namespace ServiceLib.Handler
|
||||
private Process? _processPre;
|
||||
private Action<bool, string>? _updateFunc;
|
||||
|
||||
public void Init(Config config, Action<bool, string> updateFunc)
|
||||
public async Task Init(Config config, Action<bool, string> updateFunc)
|
||||
{
|
||||
_config = config;
|
||||
_updateFunc = updateFunc;
|
||||
|
||||
Environment.SetEnvironmentVariable("v2ray.location.asset", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
|
||||
Environment.SetEnvironmentVariable("xray.location.asset", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
|
||||
Environment.SetEnvironmentVariable("V2RAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
|
||||
Environment.SetEnvironmentVariable("XRAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
|
||||
|
||||
if (Utils.IsLinux())
|
||||
{
|
||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
|
||||
foreach (var it in coreInfo)
|
||||
{
|
||||
if (it.CoreType == ECoreType.v2rayN)
|
||||
{
|
||||
if (Utils.UpgradeAppExists(out var fileName))
|
||||
{
|
||||
await Utils.SetLinuxChmod(fileName);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var name in it.CoreExes)
|
||||
{
|
||||
var exe = Utils.GetBinPath(Utils.GetExeName(name), it.CoreType.ToString());
|
||||
if (File.Exists(exe))
|
||||
{
|
||||
await Utils.SetLinuxChmod(exe);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task LoadCore(ProfileItem? node)
|
||||
@@ -83,13 +108,11 @@ namespace ServiceLib.Handler
|
||||
{
|
||||
try
|
||||
{
|
||||
bool hasProc = false;
|
||||
if (_process != null)
|
||||
{
|
||||
await KillProcess(_process);
|
||||
_process.Dispose();
|
||||
_process = null;
|
||||
hasProc = true;
|
||||
}
|
||||
|
||||
if (_processPre != null)
|
||||
@@ -97,31 +120,6 @@ namespace ServiceLib.Handler
|
||||
await KillProcess(_processPre);
|
||||
_processPre.Dispose();
|
||||
_processPre = null;
|
||||
hasProc = true;
|
||||
}
|
||||
|
||||
if (!hasProc)
|
||||
{
|
||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
|
||||
foreach (var it in coreInfo)
|
||||
{
|
||||
if (it.CoreType == ECoreType.v2rayN)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (string vName in it.CoreExes)
|
||||
{
|
||||
var existing = Process.GetProcessesByName(vName);
|
||||
foreach (Process p in existing)
|
||||
{
|
||||
string? path = p.MainModule?.FileName;
|
||||
if (path == Utils.GetExeName(Utils.GetBinPath(vName, it.CoreType.ToString())))
|
||||
{
|
||||
await KillProcess(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -148,10 +146,9 @@ namespace ServiceLib.Handler
|
||||
private string CoreFindExe(CoreInfo coreInfo)
|
||||
{
|
||||
string fileName = string.Empty;
|
||||
foreach (string name in coreInfo.CoreExes)
|
||||
foreach (var name in coreInfo.CoreExes)
|
||||
{
|
||||
string vName = Utils.GetExeName(name);
|
||||
vName = Utils.GetBinPath(vName, coreInfo.CoreType.ToString());
|
||||
var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());
|
||||
if (File.Exists(vName))
|
||||
{
|
||||
fileName = vName;
|
||||
|
||||
@@ -9,27 +9,31 @@ namespace ServiceLib.Handler
|
||||
private static readonly Lazy<ProfileExHandler> _instance = new(() => new());
|
||||
private ConcurrentBag<ProfileExItem> _lstProfileEx = [];
|
||||
private Queue<string> _queIndexIds = new();
|
||||
public ConcurrentBag<ProfileExItem> ProfileExs => _lstProfileEx;
|
||||
public static ProfileExHandler Instance => _instance.Value;
|
||||
|
||||
public ProfileExHandler()
|
||||
{
|
||||
Init();
|
||||
//Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
public async Task Init()
|
||||
{
|
||||
await InitData();
|
||||
await Task.Run(async () =>
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
await SaveQueueIndexIds();
|
||||
await Task.Delay(1000 * 600);
|
||||
await SaveQueueIndexIds();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<ConcurrentBag<ProfileExItem>> GetProfileExs()
|
||||
{
|
||||
return _lstProfileEx;
|
||||
}
|
||||
|
||||
private async Task InitData()
|
||||
{
|
||||
await SQLiteHelper.Instance.ExecuteAsync($"delete from ProfileExItem where indexId not in ( select indexId from ProfileItem )");
|
||||
|
||||
@@ -2,12 +2,81 @@
|
||||
{
|
||||
public class ProxySettingOSX
|
||||
{
|
||||
/*
|
||||
* 仅测试了,MacOS 13.7.1 x86 版本,其他版本有待确认
|
||||
*/
|
||||
/// <summary>
|
||||
/// 应用接口类型
|
||||
/// </summary>
|
||||
private static readonly List<string> LstInterface = ["Ethernet", "Wi-Fi", "Thunderbolt Bridge"];
|
||||
|
||||
/// <summary>
|
||||
/// 代理类型,对应 http,https,socks
|
||||
/// </summary>
|
||||
private static readonly List<string> LstTypes = ["setwebproxy", "setsecurewebproxy", "setsocksfirewallproxy"];
|
||||
|
||||
public static async Task SetProxy(string host, int port)
|
||||
{
|
||||
var lstCmd = GetSetCmds(host, port);
|
||||
await ExecCmd(lstCmd);
|
||||
}
|
||||
|
||||
|
||||
public static async Task UnsetProxy()
|
||||
{
|
||||
var lstCmd = GetUnsetCmds();
|
||||
await ExecCmd(lstCmd);
|
||||
}
|
||||
|
||||
|
||||
private static async Task ExecCmd(List<CmdItem> lstCmd)
|
||||
{
|
||||
foreach (var cmd in lstCmd)
|
||||
{
|
||||
if (cmd is null || cmd.Cmd.IsNullOrEmpty() || cmd.Arguments is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
await Task.Delay(10);
|
||||
await Utils.GetCliWrapOutput(cmd.Cmd, cmd.Arguments);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<CmdItem> GetSetCmds(string host, int port)
|
||||
{
|
||||
List<CmdItem> lstCmd = [];
|
||||
foreach (var interf in LstInterface)
|
||||
{
|
||||
foreach (var type in LstTypes)
|
||||
{
|
||||
lstCmd.Add(new CmdItem()
|
||||
{
|
||||
Cmd = "networksetup",
|
||||
Arguments = [$"-{type}", interf, host, (type.Contains("socks") ? (port - 1) : port).ToString()]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return lstCmd;
|
||||
}
|
||||
|
||||
private static List<CmdItem> GetUnsetCmds()
|
||||
{
|
||||
List<CmdItem> lstCmd = [];
|
||||
foreach (var interf in LstInterface)
|
||||
{
|
||||
foreach (var type in LstTypes)
|
||||
{
|
||||
lstCmd.Add(new CmdItem()
|
||||
{
|
||||
Cmd = "networksetup",
|
||||
Arguments = [$"-{type}state", interf, "off"]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return lstCmd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using static ServiceLib.Handler.SysProxy.ProxySettingWindows.InternetConnectionOption;
|
||||
|
||||
namespace ServiceLib.Handler.SysProxy
|
||||
@@ -11,24 +11,24 @@ namespace ServiceLib.Handler.SysProxy
|
||||
{
|
||||
if (type == 1)
|
||||
{
|
||||
RegWriteValue(_regPath, "ProxyEnable", 0);
|
||||
RegWriteValue(_regPath, "ProxyServer", string.Empty);
|
||||
RegWriteValue(_regPath, "ProxyOverride", string.Empty);
|
||||
RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
|
||||
WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 0);
|
||||
WindowsUtils.RegWriteValue(_regPath, "ProxyServer", string.Empty);
|
||||
WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", string.Empty);
|
||||
WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
|
||||
}
|
||||
if (type == 2)
|
||||
{
|
||||
RegWriteValue(_regPath, "ProxyEnable", 1);
|
||||
RegWriteValue(_regPath, "ProxyServer", strProxy ?? string.Empty);
|
||||
RegWriteValue(_regPath, "ProxyOverride", exceptions ?? string.Empty);
|
||||
RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
|
||||
WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 1);
|
||||
WindowsUtils.RegWriteValue(_regPath, "ProxyServer", strProxy ?? string.Empty);
|
||||
WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", exceptions ?? string.Empty);
|
||||
WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", string.Empty);
|
||||
}
|
||||
else if (type == 4)
|
||||
{
|
||||
RegWriteValue(_regPath, "ProxyEnable", 0);
|
||||
RegWriteValue(_regPath, "ProxyServer", string.Empty);
|
||||
RegWriteValue(_regPath, "ProxyOverride", string.Empty);
|
||||
RegWriteValue(_regPath, "AutoConfigURL", strProxy ?? string.Empty);
|
||||
WindowsUtils.RegWriteValue(_regPath, "ProxyEnable", 0);
|
||||
WindowsUtils.RegWriteValue(_regPath, "ProxyServer", string.Empty);
|
||||
WindowsUtils.RegWriteValue(_regPath, "ProxyOverride", string.Empty);
|
||||
WindowsUtils.RegWriteValue(_regPath, "AutoConfigURL", strProxy ?? string.Empty);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -144,12 +144,12 @@ namespace ServiceLib.Handler.SysProxy
|
||||
{
|
||||
if (Environment.Is64BitOperatingSystem)
|
||||
{
|
||||
nint opt = new(optionsPtr.ToInt64() + i * optSize);
|
||||
nint opt = new(optionsPtr.ToInt64() + (i * optSize));
|
||||
Marshal.StructureToPtr(options[i], opt, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
nint opt = new(optionsPtr.ToInt32() + i * optSize);
|
||||
nint opt = new(optionsPtr.ToInt32() + (i * optSize));
|
||||
Marshal.StructureToPtr(options[i], opt, false);
|
||||
}
|
||||
}
|
||||
@@ -247,7 +247,7 @@ namespace ServiceLib.Handler.SysProxy
|
||||
|
||||
//[MarshalAs(UnmanagedType.)]
|
||||
public nint options;
|
||||
};
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public struct InternetConnectionOption
|
||||
@@ -356,30 +356,5 @@ namespace ServiceLib.Handler.SysProxy
|
||||
ref int lpcEntries // Number of entries written to the buffer
|
||||
);
|
||||
}
|
||||
|
||||
private static void RegWriteValue(string path, string name, object value)
|
||||
{
|
||||
Microsoft.Win32.RegistryKey? regKey = null;
|
||||
try
|
||||
{
|
||||
regKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(path);
|
||||
if (string.IsNullOrEmpty(value.ToString()))
|
||||
{
|
||||
regKey?.DeleteValue(name, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
regKey?.SetValue(name, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
regKey?.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace ServiceLib.Models
|
||||
{
|
||||
public class CheckUpdateItem
|
||||
public class CheckUpdateModel
|
||||
{
|
||||
public bool? IsSelected { get; set; }
|
||||
public string? CoreType { get; set; }
|
||||
@@ -15,15 +15,14 @@
|
||||
|
||||
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
|
||||
@@ -46,6 +45,7 @@
|
||||
public ClashUIItem ClashUIItem { get; set; }
|
||||
public SystemProxyItem SystemProxyItem { get; set; }
|
||||
public WebDavItem WebDavItem { get; set; }
|
||||
public CheckUpdateItem CheckUpdateItem { get; set; }
|
||||
public List<InItem> Inbound { get; set; }
|
||||
public List<KeyEventItem> GlobalHotkeys { get; set; }
|
||||
public List<CoreTypeItem> CoreTypeItem { get; set; }
|
||||
|
||||
@@ -80,14 +80,14 @@
|
||||
public bool IgnoreGeoUpdateCore { get; set; } = true;
|
||||
|
||||
public int AutoUpdateInterval { get; set; }
|
||||
|
||||
public bool CheckPreReleaseUpdate { get; set; } = false;
|
||||
|
||||
|
||||
public bool EnableSecurityProtocolTls13 { get; set; }
|
||||
|
||||
public int TrayMenuServersLimit { get; set; } = 20;
|
||||
|
||||
public bool EnableHWA { get; set; } = false;
|
||||
|
||||
public bool EnableLog { get; set; } = true;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@@ -243,4 +243,11 @@
|
||||
public string? Password { 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 int? PreSocksPort { get; set; }
|
||||
|
||||
public string? Memo { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ServiceLib.Models
|
||||
{
|
||||
@@ -50,7 +50,7 @@ namespace ServiceLib.Models
|
||||
}
|
||||
|
||||
public class Stats4Ray
|
||||
{ };
|
||||
{ }
|
||||
|
||||
public class API4Ray
|
||||
{
|
||||
|
||||
45
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
45
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
@@ -294,6 +294,24 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please do not use the insecure HTTP protocol subscription address 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string InsecureUrlProtocol {
|
||||
get {
|
||||
return ResourceManager.GetString("InsecureUrlProtocol", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Invalid address (Url) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string InvalidUrlTip {
|
||||
get {
|
||||
return ResourceManager.GetString("InvalidUrlTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 {0} {1} already up to date. 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -429,6 +447,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Remarks Memo 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string LvMemo {
|
||||
get {
|
||||
return ResourceManager.GetString("LvMemo", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 More URLs, separated by commas; Subscription conversion will be invalid 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -852,6 +879,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Are you sure to exit? 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuExitTips {
|
||||
get {
|
||||
return ResourceManager.GetString("menuExitTips", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Export selected server for complete configuration 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2842,6 +2878,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Install the font to the system and restart the settings 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsCurrentFontFamilyLinuxTip {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsCurrentFontFamilyLinuxTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Copy the font TTF/TTC file to the directory guiFonts, restart the settings 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -1354,4 +1354,19 @@
|
||||
<data name="menuAddServerViaImage" xml:space="preserve">
|
||||
<value>Scan QR code in the image</value>
|
||||
</data>
|
||||
<data name="InvalidUrlTip" xml:space="preserve">
|
||||
<value>Invalid address (Url)</value>
|
||||
</data>
|
||||
<data name="InsecureUrlProtocol" xml:space="preserve">
|
||||
<value>Please do not use the insecure HTTP protocol subscription address</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||
<value>Install the font to the system and restart the settings</value>
|
||||
</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>
|
||||
@@ -1351,4 +1351,19 @@
|
||||
<data name="menuAddServerViaImage" xml:space="preserve">
|
||||
<value>扫描图片中的二维码</value>
|
||||
</data>
|
||||
<data name="InvalidUrlTip" xml:space="preserve">
|
||||
<value>地址(Url)无效</value>
|
||||
</data>
|
||||
<data name="InsecureUrlProtocol" xml:space="preserve">
|
||||
<value>请不要使用不安全的HTTP协议订阅地址</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||
<value>安装字体到系统中,重启设置</value>
|
||||
</data>
|
||||
<data name="menuExitTips" xml:space="preserve">
|
||||
<value>是否确定退出?</value>
|
||||
</data>
|
||||
<data name="LvMemo" xml:space="preserve">
|
||||
<value>备注备忘</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1231,4 +1231,19 @@
|
||||
<data name="menuAddServerViaImage" xml:space="preserve">
|
||||
<value>掃描圖片中的二維碼</value>
|
||||
</data>
|
||||
<data name="InvalidUrlTip" xml:space="preserve">
|
||||
<value>地址(Url)無效</value>
|
||||
</data>
|
||||
<data name="InsecureUrlProtocol" xml:space="preserve">
|
||||
<value>請不要使用不安全的HTTP協定訂閱位址</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||
<value>安裝字體到系統中,重新啟動設定</value>
|
||||
</data>
|
||||
<data name="menuExitTips" xml:space="preserve">
|
||||
<value>是否確定退出?</value>
|
||||
</data>
|
||||
<data name="LvMemo" xml:space="preserve">
|
||||
<value>備註備忘</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -42,15 +42,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理GFW",
|
||||
"outboundTag": "proxy",
|
||||
"domain": [
|
||||
"geosite:gfw",
|
||||
"geosite:greatfire"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理Google等",
|
||||
"remarks": "代理IP",
|
||||
"outboundTag": "proxy",
|
||||
"ip": [
|
||||
"1.0.0.1",
|
||||
@@ -65,6 +57,14 @@
|
||||
"geoip:twitter"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理GFW",
|
||||
"outboundTag": "proxy",
|
||||
"domain": [
|
||||
"geosite:gfw",
|
||||
"geosite:greatfire"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "最终直连",
|
||||
"port": "0-65535",
|
||||
|
||||
@@ -34,19 +34,6 @@
|
||||
"geosite:private"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国域名",
|
||||
"outboundTag": "direct",
|
||||
"domain": [
|
||||
"domain:dns.alidns.com",
|
||||
"domain:doh.pub",
|
||||
"domain:dot.pub",
|
||||
"domain:doh.360.cn",
|
||||
"domain:dot.360.cn",
|
||||
"geosite:cn",
|
||||
"geosite:geolocation-cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国IP",
|
||||
"outboundTag": "direct",
|
||||
@@ -73,6 +60,19 @@
|
||||
"geoip:cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国域名",
|
||||
"outboundTag": "direct",
|
||||
"domain": [
|
||||
"domain:dns.alidns.com",
|
||||
"domain:doh.pub",
|
||||
"domain:dot.pub",
|
||||
"domain:doh.360.cn",
|
||||
"domain:dot.360.cn",
|
||||
"geosite:cn",
|
||||
"geosite:geolocation-cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "最终代理",
|
||||
"port": "0-65535",
|
||||
|
||||
10
v2rayN/ServiceLib/Sample/linux_autostart_config
Normal file
10
v2rayN/ServiceLib/Sample/linux_autostart_config
Normal file
@@ -0,0 +1,10 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Exec=$ExecPath$
|
||||
Hidden=false
|
||||
NoDisplay=false
|
||||
X-GNOME-Autostart-enabled=true
|
||||
Name[en_US]=v2rayN
|
||||
Name=v2rayN
|
||||
Comment[en_US]=v2rayN
|
||||
Comment=v2rayN
|
||||
@@ -4,9 +4,9 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>7.0.0</Version>
|
||||
<Version>7.0.9</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Downloader" Version="3.2.1" />
|
||||
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
||||
@@ -16,9 +16,11 @@
|
||||
<PackageReference Include="WebDav.Client" Version="2.8.0" />
|
||||
<PackageReference Include="YamlDotNet" Version="16.1.3" />
|
||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||
<PackageReference Include="CliWrap" Version="3.6.6" />
|
||||
<PackageReference Include="CliWrap" Version="3.6.7" />
|
||||
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
|
||||
<PackageReference Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.11.0" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -41,6 +43,7 @@
|
||||
<EmbeddedResource Include="Sample\tun_singbox_dns" />
|
||||
<EmbeddedResource Include="Sample\tun_singbox_inbound" />
|
||||
<EmbeddedResource Include="Sample\tun_singbox_rules" />
|
||||
<EmbeddedResource Include="Sample\linux_autostart_config" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ServiceLib.Services.CoreConfig
|
||||
namespace ServiceLib.Services.CoreConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Core configuration file processing class
|
||||
@@ -66,7 +66,7 @@
|
||||
txtFile = txtFile.Replace(tagYamlStr1, tagYamlStr2);
|
||||
|
||||
//YAML anchors
|
||||
if (txtFile.Contains("<<:") && txtFile.Contains("*") && txtFile.Contains("&"))
|
||||
if (txtFile.Contains("<<:") && txtFile.Contains('*') && txtFile.Contains('&'))
|
||||
{
|
||||
txtFile = YamlUtils.PreprocessYaml(txtFile);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Data;
|
||||
using System.Data;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
|
||||
@@ -484,7 +484,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
singboxConfig.inbounds = [];
|
||||
|
||||
if (!_config.TunModeItem.EnableTun
|
||||
|| _config.TunModeItem.EnableTun && _config.TunModeItem.EnableExInbound && _config.RunningCoreType == ECoreType.sing_box)
|
||||
|| (_config.TunModeItem.EnableTun && _config.TunModeItem.EnableExInbound && _config.RunningCoreType == ECoreType.sing_box))
|
||||
{
|
||||
var inbound = new Inbound4Sbox()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using ReactiveUI;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
@@ -80,10 +81,12 @@ namespace ServiceLib.Services
|
||||
Task.Run(RunMixedtestAsync);
|
||||
break;
|
||||
}
|
||||
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
|
||||
}
|
||||
|
||||
public void ExitLoop()
|
||||
private void ExitLoop(string x)
|
||||
{
|
||||
if (_exitLoop) return;
|
||||
_exitLoop = true;
|
||||
UpdateFunc("", ResUI.SpeedtestingStop);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ServiceLib.Services
|
||||
@@ -6,12 +6,10 @@ namespace ServiceLib.Services
|
||||
public class UpdateService
|
||||
{
|
||||
private Action<bool, string>? _updateFunc;
|
||||
private Config _config;
|
||||
private int _timeout = 30;
|
||||
|
||||
public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease)
|
||||
{
|
||||
_config = config;
|
||||
_updateFunc = updateFunc;
|
||||
var url = 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)
|
||||
{
|
||||
_config = config;
|
||||
_updateFunc = updateFunc;
|
||||
var url = string.Empty;
|
||||
var fileName = string.Empty;
|
||||
@@ -108,13 +105,12 @@ namespace ServiceLib.Services
|
||||
|
||||
public async Task UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> updateFunc)
|
||||
{
|
||||
_config = config;
|
||||
_updateFunc = updateFunc;
|
||||
|
||||
_updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart);
|
||||
var subItem = await AppHandler.Instance.SubItems();
|
||||
|
||||
if (subItem == null || subItem.Count <= 0)
|
||||
if (subItem is not { Count: > 0 })
|
||||
{
|
||||
_updateFunc?.Invoke(false, ResUI.MsgNoValidSubscription);
|
||||
return;
|
||||
@@ -122,11 +118,11 @@ namespace ServiceLib.Services
|
||||
|
||||
foreach (var item in subItem)
|
||||
{
|
||||
string id = item.Id.TrimEx();
|
||||
string url = item.Url.TrimEx();
|
||||
string userAgent = item.UserAgent.TrimEx();
|
||||
string hashCode = $"{item.Remarks}->";
|
||||
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || Utils.IsNotEmpty(subId) && item.Id != subId)
|
||||
var id = item.Id.TrimEx();
|
||||
var url = item.Url.TrimEx();
|
||||
var userAgent = item.UserAgent.TrimEx();
|
||||
var hashCode = $"{item.Remarks}->";
|
||||
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url) || (Utils.IsNotEmpty(subId) && item.Id != subId))
|
||||
{
|
||||
//_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
|
||||
continue;
|
||||
@@ -219,7 +215,7 @@ namespace ServiceLib.Services
|
||||
_updateFunc?.Invoke(false, $"{hashCode}{result}");
|
||||
}
|
||||
|
||||
int ret = await ConfigHandler.AddBatchServers(config, result, id, true);
|
||||
var ret = await ConfigHandler.AddBatchServers(config, result, id, true);
|
||||
if (ret <= 0)
|
||||
{
|
||||
Logging.SaveLog("FailedImportSubscription");
|
||||
@@ -231,6 +227,8 @@ namespace ServiceLib.Services
|
||||
: $"{hashCode}{ResUI.MsgFailedImportSubscription}");
|
||||
}
|
||||
_updateFunc?.Invoke(false, "-------------------------------------------------------");
|
||||
|
||||
//await ConfigHandler.DedupServerList(config, id);
|
||||
}
|
||||
|
||||
_updateFunc?.Invoke(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
|
||||
@@ -309,10 +307,9 @@ namespace ServiceLib.Services
|
||||
{
|
||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);
|
||||
string filePath = string.Empty;
|
||||
foreach (string name in coreInfo.CoreExes)
|
||||
foreach (var name in coreInfo.CoreExes)
|
||||
{
|
||||
string vName = Utils.GetExeName(name);
|
||||
vName = Utils.GetBinPath(vName, coreInfo.CoreType.ToString());
|
||||
var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());
|
||||
if (File.Exists(vName))
|
||||
{
|
||||
filePath = vName;
|
||||
@@ -453,7 +450,6 @@ namespace ServiceLib.Services
|
||||
|
||||
private async Task UpdateGeoFile(string geoName, Config config, Action<bool, string> updateFunc)
|
||||
{
|
||||
_config = config;
|
||||
_updateFunc = updateFunc;
|
||||
|
||||
var geoUrl = string.IsNullOrEmpty(config?.ConstItem.GeoSourceUrl)
|
||||
@@ -469,7 +465,6 @@ namespace ServiceLib.Services
|
||||
|
||||
private async Task UpdateSrsFileAll(Config config, Action<bool, string> updateFunc)
|
||||
{
|
||||
_config = config;
|
||||
_updateFunc = updateFunc;
|
||||
|
||||
var geoipFiles = new List<string>();
|
||||
@@ -520,9 +515,9 @@ namespace ServiceLib.Services
|
||||
|
||||
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
|
||||
: _config.ConstItem.SrsSourceUrl;
|
||||
: config.ConstItem.SrsSourceUrl;
|
||||
|
||||
var fileName = $"{type}-{srsName}.srs";
|
||||
var targetPath = Path.Combine(Utils.GetBinPath("srss"), fileName);
|
||||
|
||||
@@ -12,10 +12,10 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
private const string _geo = "GeoFiles";
|
||||
private string _v2rayN = ECoreType.v2rayN.ToString();
|
||||
private List<CheckUpdateItem> _lstUpdated = [];
|
||||
private List<CheckUpdateModel> _lstUpdated = [];
|
||||
|
||||
private IObservableCollection<CheckUpdateItem> _checkUpdateItem = new ObservableCollectionExtended<CheckUpdateItem>();
|
||||
public IObservableCollection<CheckUpdateItem> CheckUpdateItems => _checkUpdateItem;
|
||||
private IObservableCollection<CheckUpdateModel> _checkUpdateModel = new ObservableCollectionExtended<CheckUpdateModel>();
|
||||
public IObservableCollection<CheckUpdateModel> CheckUpdateModels => _checkUpdateModel;
|
||||
public ReactiveCommand<Unit, Unit> CheckUpdateCmd { get; }
|
||||
[Reactive] public bool EnableCheckPreReleaseUpdate { get; set; }
|
||||
|
||||
@@ -29,65 +29,56 @@ namespace ServiceLib.ViewModels
|
||||
await CheckUpdate();
|
||||
});
|
||||
|
||||
EnableCheckPreReleaseUpdate = _config.GuiItem.CheckPreReleaseUpdate;
|
||||
EnableCheckPreReleaseUpdate = _config.CheckUpdateItem.CheckPreReleaseUpdate;
|
||||
|
||||
this.WhenAnyValue(
|
||||
x => x.EnableCheckPreReleaseUpdate,
|
||||
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)
|
||||
{
|
||||
_checkUpdateItem.Add(new CheckUpdateItem()
|
||||
{
|
||||
IsSelected = false,
|
||||
CoreType = _v2rayN,
|
||||
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(_v2rayN));
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.Xray.ToString()));
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.mihomo.ToString()));
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.sing_box.ToString()));
|
||||
}
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(_geo));
|
||||
}
|
||||
|
||||
_checkUpdateItem.Add(new CheckUpdateItem()
|
||||
private CheckUpdateModel GetCheckUpdateModel(string coreType)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
IsSelected = true,
|
||||
CoreType = _geo,
|
||||
IsSelected = _config.CheckUpdateItem.SelectedCoreTypes?.Contains(coreType) ?? true,
|
||||
CoreType = coreType,
|
||||
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()
|
||||
{
|
||||
_lstUpdated.Clear();
|
||||
_lstUpdated = _checkUpdateItem.Where(x => x.IsSelected == true)
|
||||
.Select(x => new CheckUpdateItem() { CoreType = x.CoreType }).ToList();
|
||||
_lstUpdated = _checkUpdateModel.Where(x => x.IsSelected == true)
|
||||
.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;
|
||||
|
||||
UpdateView(item.CoreType, "...");
|
||||
@@ -99,13 +90,13 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
await CheckUpdateN(EnableCheckPreReleaseUpdate);
|
||||
}
|
||||
else if (item.CoreType == ECoreType.mihomo.ToString())
|
||||
else if (item.CoreType == ECoreType.Xray.ToString())
|
||||
{
|
||||
await CheckUpdateCore(item, false);
|
||||
await CheckUpdateCore(item, EnableCheckPreReleaseUpdate);
|
||||
}
|
||||
else
|
||||
{
|
||||
await CheckUpdateCore(item, EnableCheckPreReleaseUpdate);
|
||||
await CheckUpdateCore(item, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
UpdateView(item.CoreType, msg);
|
||||
UpdateView(model.CoreType, msg);
|
||||
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)
|
||||
.ContinueWith(t =>
|
||||
{
|
||||
UpdatedPlusPlus(item.CoreType, "");
|
||||
UpdatedPlusPlus(model.CoreType, "");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -291,7 +282,7 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
private void UpdateView(string coreType, string msg)
|
||||
{
|
||||
var item = new CheckUpdateItem()
|
||||
var item = new CheckUpdateModel()
|
||||
{
|
||||
CoreType = coreType,
|
||||
Remarks = msg,
|
||||
@@ -299,13 +290,13 @@ namespace ServiceLib.ViewModels
|
||||
_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;
|
||||
var itemCopy = JsonUtils.DeepCopy(found);
|
||||
itemCopy.Remarks = item.Remarks;
|
||||
_checkUpdateItem.Replace(found, itemCopy);
|
||||
itemCopy.Remarks = model.Remarks;
|
||||
_checkUpdateModel.Replace(found, itemCopy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ namespace ServiceLib.ViewModels
|
||||
private async Task Init()
|
||||
{
|
||||
await ProxiesReload();
|
||||
await DelayTestTask();
|
||||
DelayTestTask();
|
||||
}
|
||||
|
||||
private async Task DoRulemodeSelected(bool c)
|
||||
@@ -434,25 +434,29 @@ namespace ServiceLib.ViewModels
|
||||
public async Task DelayTestTask()
|
||||
{
|
||||
var lastTime = DateTime.Now;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
await Task.Delay(1000 * 60);
|
||||
|
||||
Observable.Interval(TimeSpan.FromSeconds(60))
|
||||
.Subscribe(async x =>
|
||||
{
|
||||
if (!(AutoRefresh && _config.UiItem.ShowInTaskbar && _config.IsRunningCore(ECoreType.sing_box)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var dtNow = DateTime.Now;
|
||||
if (_config.ClashUIItem.ProxiesAutoDelayTestInterval > 0)
|
||||
{
|
||||
if ((dtNow - lastTime).Minutes % _config.ClashUIItem.ProxiesAutoDelayTestInterval == 0)
|
||||
{
|
||||
await ProxiesDelayTest();
|
||||
lastTime = dtNow;
|
||||
}
|
||||
Task.Delay(1000).Wait();
|
||||
}
|
||||
});
|
||||
if (!(AutoRefresh && _config.UiItem.ShowInTaskbar && _config.IsRunningCore(ECoreType.sing_box)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (_config.ClashUIItem.ProxiesAutoDelayTestInterval <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var dtNow = DateTime.Now;
|
||||
if ((dtNow - lastTime).Minutes % _config.ClashUIItem.ProxiesAutoDelayTestInterval != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
await ProxiesDelayTest();
|
||||
lastTime = dtNow;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#endregion task
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using ReactiveUI;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Reactive;
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace ServiceLib.ViewModels
|
||||
item2.DomainStrategy4Freedom = domainStrategy4Freedom2;
|
||||
item2.DomainDNSAddress = domainDNSAddress2;
|
||||
item2.NormalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(normalDNS2));
|
||||
item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(tunDNS2)); ;
|
||||
item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(tunDNS2));
|
||||
await ConfigHandler.SaveDNSItems(_config, item2);
|
||||
|
||||
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
||||
|
||||
@@ -208,7 +208,8 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
await ConfigHandler.InitBuiltinRouting(_config);
|
||||
await ConfigHandler.InitBuiltinDNS(_config);
|
||||
CoreHandler.Instance.Init(_config, UpdateHandler);
|
||||
await ProfileExHandler.Instance.Init();
|
||||
await CoreHandler.Instance.Init(_config, UpdateHandler);
|
||||
TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler);
|
||||
|
||||
if (_config.GuiItem.EnableStatistics)
|
||||
@@ -265,7 +266,7 @@ namespace ServiceLib.ViewModels
|
||||
try
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -288,7 +289,7 @@ namespace ServiceLib.ViewModels
|
||||
await ProfileExHandler.Instance.SaveTo();
|
||||
await StatisticsHandler.Instance.SaveTo();
|
||||
StatisticsHandler.Instance.Close();
|
||||
CoreHandler.Instance.CoreStop();
|
||||
await CoreHandler.Instance.CoreStop();
|
||||
|
||||
Logging.SaveLog("MyAppExit End");
|
||||
}
|
||||
@@ -312,6 +313,7 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
UseShellExecute = true,
|
||||
FileName = fileName,
|
||||
Arguments = arg.AppendQuotes(),
|
||||
WorkingDirectory = Utils.StartupPath()
|
||||
@@ -389,6 +391,10 @@ namespace ServiceLib.ViewModels
|
||||
RefreshServers();
|
||||
NoticeHandler.Instance.Enqueue(string.Format(ResUI.SuccessfullyImportedServerViaClipboard, ret));
|
||||
}
|
||||
else
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(ResUI.OperationFailed);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task AddServerViaScanAsync()
|
||||
@@ -433,6 +439,10 @@ namespace ServiceLib.ViewModels
|
||||
RefreshServers();
|
||||
NoticeHandler.Instance.Enqueue(ResUI.SuccessfullyImportedServerViaScan);
|
||||
}
|
||||
else
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(ResUI.OperationFailed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ namespace ServiceLib.ViewModels
|
||||
[Reactive] public bool EnableUpdateSubOnlyRemarksExist { get; set; }
|
||||
[Reactive] public bool EnableSecurityProtocolTls13 { get; set; }
|
||||
[Reactive] public bool AutoHideStartup { get; set; }
|
||||
[Reactive] public bool EnableCheckPreReleaseUpdate { get; set; }
|
||||
[Reactive] public bool EnableDragDropSort { get; set; }
|
||||
[Reactive] public bool DoubleClick2Activate { get; set; }
|
||||
[Reactive] public int AutoUpdateInterval { get; set; }
|
||||
@@ -117,6 +116,8 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
private async Task Init()
|
||||
{
|
||||
await _updateView?.Invoke(EViewAction.InitSettingFont, null);
|
||||
|
||||
#region Core
|
||||
|
||||
var inbound = _config.Inbound[0];
|
||||
@@ -164,7 +165,6 @@ namespace ServiceLib.ViewModels
|
||||
EnableUpdateSubOnlyRemarksExist = _config.UiItem.EnableUpdateSubOnlyRemarksExist;
|
||||
EnableSecurityProtocolTls13 = _config.GuiItem.EnableSecurityProtocolTls13;
|
||||
AutoHideStartup = _config.UiItem.AutoHideStartup;
|
||||
EnableCheckPreReleaseUpdate = _config.GuiItem.CheckPreReleaseUpdate;
|
||||
EnableDragDropSort = _config.UiItem.EnableDragDropSort;
|
||||
DoubleClick2Activate = _config.UiItem.DoubleClick2Activate;
|
||||
AutoUpdateInterval = _config.GuiItem.AutoUpdateInterval;
|
||||
@@ -315,7 +315,6 @@ namespace ServiceLib.ViewModels
|
||||
_config.GuiItem.EnableSecurityProtocolTls13 = EnableSecurityProtocolTls13;
|
||||
_config.UiItem.AutoHideStartup = AutoHideStartup;
|
||||
_config.GuiItem.AutoUpdateInterval = AutoUpdateInterval;
|
||||
_config.GuiItem.CheckPreReleaseUpdate = EnableCheckPreReleaseUpdate;
|
||||
_config.UiItem.EnableDragDropSort = EnableDragDropSort;
|
||||
_config.UiItem.DoubleClick2Activate = DoubleClick2Activate;
|
||||
_config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;
|
||||
@@ -347,14 +346,9 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
if (await ConfigHandler.SaveConfig(_config) == 0)
|
||||
{
|
||||
if (needReboot)
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(ResUI.NeedRebootTips);
|
||||
}
|
||||
else
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
||||
}
|
||||
await AutoStartupHandler.UpdateTask(_config);
|
||||
|
||||
NoticeHandler.Instance.Enqueue(needReboot ? ResUI.NeedRebootTips : ResUI.OperationSuccess);
|
||||
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -16,7 +16,6 @@ namespace ServiceLib.ViewModels
|
||||
private List<ProfileItem> _lstProfile;
|
||||
private string _serverFilter = string.Empty;
|
||||
private Dictionary<string, bool> _dicHeaderSort = new();
|
||||
private SpeedtestService? _speedtestHandler;
|
||||
|
||||
#endregion private prop
|
||||
|
||||
@@ -686,12 +685,12 @@ namespace ServiceLib.ViewModels
|
||||
}
|
||||
//ClearTestResult();
|
||||
|
||||
_speedtestHandler = new SpeedtestService(_config, lstSelecteds, actionType, UpdateSpeedtestHandler);
|
||||
_ = new SpeedtestService(_config, lstSelecteds, actionType, UpdateSpeedtestHandler);
|
||||
}
|
||||
|
||||
public void ServerSpeedtestStop()
|
||||
{
|
||||
_speedtestHandler?.ExitLoop();
|
||||
MessageBus.Current.SendMessage("", EMsgCommand.StopSpeedtest.ToString());
|
||||
}
|
||||
|
||||
private async Task Export2ClientConfigAsync(bool blClipboard)
|
||||
|
||||
@@ -176,13 +176,14 @@ namespace ServiceLib.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
var lst = new List<RulesItem4Ray>();
|
||||
var lst = new List<RulesItem>();
|
||||
foreach (var it in SelectedSources ?? [SelectedSource])
|
||||
{
|
||||
var item = _rules.FirstOrDefault(t => t.Id == it?.Id);
|
||||
if (item != null)
|
||||
{
|
||||
var item2 = JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item));
|
||||
var item2 = JsonUtils.DeepCopy(item); //JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item));
|
||||
item2.Id = null;
|
||||
lst.Add(item2 ?? new());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +104,18 @@ namespace ServiceLib.ViewModels
|
||||
public StatusBarViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
|
||||
{
|
||||
_config = AppHandler.Instance.Config;
|
||||
SelectedRouting = new();
|
||||
SelectedServer = new();
|
||||
RunningServerToolTipText = "-";
|
||||
|
||||
if (_config.TunModeItem.EnableTun && AppHandler.Instance.IsAdministrator)
|
||||
{
|
||||
EnableTun = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_config.TunModeItem.EnableTun = EnableTun = false;
|
||||
}
|
||||
|
||||
#region WhenAnyValue && ReactiveCommand
|
||||
|
||||
@@ -179,19 +191,6 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
private async Task Init()
|
||||
{
|
||||
SelectedRouting = new();
|
||||
SelectedServer = new();
|
||||
RunningServerToolTipText = "-";
|
||||
|
||||
if (_config.TunModeItem.EnableTun && AppHandler.Instance.IsAdministrator)
|
||||
{
|
||||
EnableTun = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_config.TunModeItem.EnableTun = EnableTun = false;
|
||||
}
|
||||
|
||||
await RefreshRoutingsMenu();
|
||||
await InboundDisplayStatus();
|
||||
await ChangeSystemProxyAsync(_config.SystemProxyItem.SysProxyType, true);
|
||||
|
||||
@@ -39,14 +39,14 @@ namespace ServiceLib.ViewModels
|
||||
var uri = Utils.TryUri(url);
|
||||
if (uri == null)
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(ResUI.LvUrl);
|
||||
NoticeHandler.Instance.Enqueue(ResUI.InvalidUrlTip);
|
||||
return;
|
||||
}
|
||||
//Do not allow http protocol
|
||||
if (url.StartsWith(Global.HttpProtocol) && !Utils.IsPrivateNetwork(uri.IdnHost))
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(ResUI.LvUrl);
|
||||
return;
|
||||
NoticeHandler.Instance.Enqueue(ResUI.InsecureUrlProtocol);
|
||||
//return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@ namespace v2rayN.Desktop;
|
||||
|
||||
public partial class App : Application
|
||||
{
|
||||
//public static EventWaitHandle ProgramStarted;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
if (!AppHandler.Instance.InitApp())
|
||||
@@ -32,7 +30,7 @@ public partial class App : Application
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
OnStartup(desktop.Args);
|
||||
AppHandler.Instance.InitComponents();
|
||||
|
||||
desktop.Exit += OnExit;
|
||||
desktop.MainWindow = new MainWindow();
|
||||
@@ -41,22 +39,6 @@ public partial class App : Application
|
||||
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)
|
||||
{
|
||||
if (e.ExceptionObject != null)
|
||||
@@ -87,11 +69,12 @@ public partial class App : Application
|
||||
}
|
||||
}
|
||||
|
||||
private void MenuExit_Click(object? sender, EventArgs e)
|
||||
private async void MenuExit_Click(object? sender, EventArgs e)
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.MyAppExitAsync(false);
|
||||
var service = Locator.Current.GetService<MainWindowViewModel>();
|
||||
if (service != null) await service.MyAppExitAsync(false);
|
||||
|
||||
desktop.Shutdown();
|
||||
}
|
||||
|
||||
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 v2rayN.Desktop.Common;
|
||||
|
||||
namespace v2rayN.Desktop;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
public static EventWaitHandle ProgramStarted;
|
||||
|
||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||
// yet and stuff might break.
|
||||
[STAThread]
|
||||
public static void Main(string[] args) => BuildAvaloniaApp()
|
||||
.StartWithClassicDesktopLifetime(args);
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
OnStartup(args);
|
||||
|
||||
BuildAvaloniaApp()
|
||||
.StartWithClassicDesktopLifetime(args);
|
||||
}
|
||||
|
||||
private static void OnStartup(string[]? Args)
|
||||
{
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
var exePathKey = Utils.GetMd5(Utils.GetExePath());
|
||||
var rebootas = (Args ?? Array.Empty<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.
|
||||
public static AppBuilder BuildAvaloniaApp()
|
||||
=> AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
.WithInterFont()
|
||||
//.WithInterFont()
|
||||
.WithFontByDefault()
|
||||
.LogToTrace()
|
||||
.UseReactiveUI();
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Notifications;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
@@ -9,14 +12,11 @@ namespace v2rayN.Desktop.ViewModels
|
||||
{
|
||||
public class ThemeSettingViewModel : MyReactiveObject
|
||||
{
|
||||
[Reactive]
|
||||
public bool ColorModeDark { get; set; }
|
||||
[Reactive] public bool ColorModeDark { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public int CurrentFontSize { get; set; }
|
||||
[Reactive] public int CurrentFontSize { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string CurrentLanguage { get; set; }
|
||||
[Reactive] public string CurrentLanguage { get; set; }
|
||||
|
||||
public ThemeSettingViewModel()
|
||||
{
|
||||
@@ -29,6 +29,7 @@ namespace v2rayN.Desktop.ViewModels
|
||||
private void RestoreUI()
|
||||
{
|
||||
ModifyTheme(_config.UiItem.ColorModeDark);
|
||||
ModifyFontFamily();
|
||||
}
|
||||
|
||||
private void BindingUI()
|
||||
@@ -38,34 +39,34 @@ namespace v2rayN.Desktop.ViewModels
|
||||
CurrentLanguage = _config.UiItem.CurrentLanguage;
|
||||
|
||||
this.WhenAnyValue(x => x.ColorModeDark)
|
||||
.Subscribe(c =>
|
||||
{
|
||||
if (_config.UiItem.ColorModeDark != ColorModeDark)
|
||||
{
|
||||
_config.UiItem.ColorModeDark = ColorModeDark;
|
||||
ModifyTheme(ColorModeDark);
|
||||
ConfigHandler.SaveConfig(_config);
|
||||
}
|
||||
});
|
||||
.Subscribe(c =>
|
||||
{
|
||||
if (_config.UiItem.ColorModeDark != ColorModeDark)
|
||||
{
|
||||
_config.UiItem.ColorModeDark = ColorModeDark;
|
||||
ModifyTheme(ColorModeDark);
|
||||
ConfigHandler.SaveConfig(_config);
|
||||
}
|
||||
});
|
||||
|
||||
this.WhenAnyValue(
|
||||
x => x.CurrentFontSize,
|
||||
y => y > 0)
|
||||
.Subscribe(c =>
|
||||
{
|
||||
if (CurrentFontSize >= Global.MinFontSize)
|
||||
{
|
||||
_config.UiItem.CurrentFontSize = CurrentFontSize;
|
||||
double size = CurrentFontSize;
|
||||
ModifyFontSize(size);
|
||||
x => x.CurrentFontSize,
|
||||
y => y > 0)
|
||||
.Subscribe(c =>
|
||||
{
|
||||
if (CurrentFontSize >= Global.MinFontSize)
|
||||
{
|
||||
_config.UiItem.CurrentFontSize = CurrentFontSize;
|
||||
double size = CurrentFontSize;
|
||||
ModifyFontSize(size);
|
||||
|
||||
ConfigHandler.SaveConfig(_config);
|
||||
}
|
||||
});
|
||||
ConfigHandler.SaveConfig(_config);
|
||||
}
|
||||
});
|
||||
|
||||
this.WhenAnyValue(
|
||||
x => x.CurrentLanguage,
|
||||
y => y != null && !y.IsNullOrEmpty())
|
||||
x => x.CurrentLanguage,
|
||||
y => y != null && !y.IsNullOrEmpty())
|
||||
.Subscribe(c =>
|
||||
{
|
||||
if (Utils.IsNotEmpty(CurrentLanguage) && _config.UiItem.CurrentLanguage != CurrentLanguage)
|
||||
@@ -89,53 +90,54 @@ namespace v2rayN.Desktop.ViewModels
|
||||
|
||||
private void ModifyFontSize(double size)
|
||||
{
|
||||
Style buttonStyle = new(x => x.OfType<Button>());
|
||||
buttonStyle.Add(new Setter()
|
||||
Style style = new(x => Selectors.Or(
|
||||
x.OfType<Button>(),
|
||||
x.OfType<TextBox>(),
|
||||
x.OfType<TextBlock>(),
|
||||
x.OfType<Menu>(),
|
||||
x.OfType<ContextMenu>(),
|
||||
x.OfType<DataGridRow>(),
|
||||
x.OfType<ListBoxItem>()
|
||||
));
|
||||
style.Add(new Setter()
|
||||
{
|
||||
Property = Button.FontSizeProperty,
|
||||
Property = TemplatedControl.FontSizeProperty,
|
||||
Value = size,
|
||||
});
|
||||
Application.Current?.Styles.Add(buttonStyle);
|
||||
Application.Current?.Styles.Add(style);
|
||||
}
|
||||
|
||||
Style textStyle = new(x => x.OfType<TextBox>());
|
||||
textStyle.Add(new Setter()
|
||||
private void ModifyFontFamily()
|
||||
{
|
||||
var currentFontFamily = _config.UiItem.CurrentFontFamily;
|
||||
if (currentFontFamily.IsNullOrEmpty())
|
||||
{
|
||||
Property = TextBox.FontSizeProperty,
|
||||
Value = size,
|
||||
});
|
||||
Application.Current?.Styles.Add(textStyle);
|
||||
return;
|
||||
}
|
||||
|
||||
Style textBlockStyle = new(x => x.OfType<TextBlock>());
|
||||
textBlockStyle.Add(new Setter()
|
||||
try
|
||||
{
|
||||
Property = TextBlock.FontSizeProperty,
|
||||
Value = size,
|
||||
});
|
||||
Application.Current?.Styles.Add(textBlockStyle);
|
||||
|
||||
Style menuStyle = new(x => x.OfType<Menu>());
|
||||
menuStyle.Add(new Setter()
|
||||
Style style = new(x => Selectors.Or(
|
||||
x.OfType<Button>(),
|
||||
x.OfType<TextBox>(),
|
||||
x.OfType<TextBlock>(),
|
||||
x.OfType<Menu>(),
|
||||
x.OfType<ContextMenu>(),
|
||||
x.OfType<DataGridRow>(),
|
||||
x.OfType<ListBoxItem>(),
|
||||
x.OfType<WindowNotificationManager>()
|
||||
));
|
||||
style.Add(new Setter()
|
||||
{
|
||||
Property = TemplatedControl.FontFamilyProperty,
|
||||
Value = new FontFamily(currentFontFamily),
|
||||
});
|
||||
Application.Current?.Styles.Add(style);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Property = Menu.FontSizeProperty,
|
||||
Value = size,
|
||||
});
|
||||
Application.Current?.Styles.Add(menuStyle);
|
||||
|
||||
Style dataStyle = new(x => x.OfType<DataGridRow>());
|
||||
dataStyle.Add(new Setter()
|
||||
{
|
||||
Property = DataGridRow.FontSizeProperty,
|
||||
Value = size,
|
||||
});
|
||||
Application.Current?.Styles.Add(dataStyle);
|
||||
|
||||
Style listStyle = new(x => x.OfType<ListBoxItem>());
|
||||
listStyle.Add(new Setter()
|
||||
{
|
||||
Property = ListBoxItem.FontSizeProperty,
|
||||
Value = size,
|
||||
});
|
||||
Application.Current?.Styles.Add(listStyle);
|
||||
Logging.SaveLog("ModifyFontFamily", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@
|
||||
<ListBox
|
||||
x:Name="lstCheckUpdates"
|
||||
BorderThickness="1"
|
||||
ItemsSource="{Binding CheckUpdateItems}">
|
||||
ItemsSource="{Binding CheckUpdateModels}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical" />
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace v2rayN.Desktop.Views
|
||||
|
||||
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.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);
|
||||
@@ -29,7 +29,7 @@ namespace v2rayN.Desktop.Views
|
||||
case EViewAction.DispatcherCheckUpdate:
|
||||
if (obj is null) return false;
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
ViewModel?.UpdateViewResult((CheckUpdateItem)obj),
|
||||
ViewModel?.UpdateViewResult((CheckUpdateModel)obj),
|
||||
DispatcherPriority.Default);
|
||||
break;
|
||||
|
||||
|
||||
@@ -161,10 +161,7 @@
|
||||
<RowDefinition Height="8" />
|
||||
<RowDefinition Height="1*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Text="{Binding Name}"
|
||||
TextWrapping="WrapWithOverflow" />
|
||||
<TextBlock Grid.Row="0" Text="{Binding Name}" />
|
||||
<DockPanel Grid.Row="2">
|
||||
<TextBlock
|
||||
DockPanel.Dock="Right"
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
<MenuItem x:Name="menuClose" Padding="8,0">
|
||||
<MenuItem.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuClose}" />
|
||||
<TextBlock Text="{x:Static resx:ResUI.menuExit}" />
|
||||
</StackPanel>
|
||||
</MenuItem.Header>
|
||||
</MenuItem>
|
||||
|
||||
@@ -7,9 +7,9 @@ using Avalonia.Interactivity;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Threading;
|
||||
using DialogHostAvalonia;
|
||||
using MsBox.Avalonia.Enums;
|
||||
using ReactiveUI;
|
||||
using Splat;
|
||||
using System.ComponentModel;
|
||||
using System.Reactive.Disposables;
|
||||
using v2rayN.Desktop.Common;
|
||||
|
||||
@@ -29,15 +29,12 @@ namespace v2rayN.Desktop.Views
|
||||
_config = AppHandler.Instance.Config;
|
||||
_manager = new WindowNotificationManager(TopLevel.GetTopLevel(this)) { MaxItems = 3, Position = NotificationPosition.BottomRight };
|
||||
|
||||
//ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);
|
||||
|
||||
this.Closing += MainWindow_Closing;
|
||||
this.KeyDown += MainWindow_KeyDown;
|
||||
menuSettingsSetUWP.Click += menuSettingsSetUWP_Click;
|
||||
menuPromotion.Click += menuPromotion_Click;
|
||||
menuClose.Click += menuClose_Click;
|
||||
menuCheckUpdate.Click += MenuCheckUpdate_Click;
|
||||
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
|
||||
menuClose.Click += MenuClose_Click;
|
||||
|
||||
MessageBus.Current.Listen<string>(EMsgCommand.SendSnackMsg.ToString()).Subscribe(DelegateSnackMsg);
|
||||
ViewModel = new MainWindowViewModel(UpdateViewHandler);
|
||||
@@ -114,6 +111,8 @@ namespace v2rayN.Desktop.Views
|
||||
this.Title = $"{Utils.GetVersion()} - {(AppHandler.Instance.IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);
|
||||
|
||||
menuGlobalHotkeySetting.IsVisible = false;
|
||||
}
|
||||
else
|
||||
@@ -158,7 +157,9 @@ namespace v2rayN.Desktop.Views
|
||||
|
||||
private void OnProgramStarted(object state, bool timeout)
|
||||
{
|
||||
ShowHideWindow(true);
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
ShowHideWindow(true),
|
||||
DispatcherPriority.Default);
|
||||
}
|
||||
|
||||
private void DelegateSnackMsg(string content)
|
||||
@@ -271,10 +272,22 @@ namespace v2rayN.Desktop.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void MainWindow_Closing(object? sender, CancelEventArgs e)
|
||||
protected override async void OnClosing(WindowClosingEventArgs e)
|
||||
{
|
||||
e.Cancel = true;
|
||||
ShowHideWindow(false);
|
||||
Logging.SaveLog("OnClosing -> " + e.CloseReason.ToString());
|
||||
|
||||
switch (e.CloseReason)
|
||||
{
|
||||
case WindowCloseReason.OwnerWindowClosing or WindowCloseReason.WindowClosing:
|
||||
e.Cancel = true;
|
||||
ShowHideWindow(false);
|
||||
break;
|
||||
case WindowCloseReason.ApplicationShutdown or WindowCloseReason.OSShutdown:
|
||||
await ViewModel?.MyAppExitAsync(true);
|
||||
break;
|
||||
}
|
||||
|
||||
base.OnClosing(e);
|
||||
}
|
||||
|
||||
private async void MainWindow_KeyDown(object? sender, KeyEventArgs e)
|
||||
@@ -302,12 +315,6 @@ namespace v2rayN.Desktop.Views
|
||||
}
|
||||
}
|
||||
|
||||
private void menuClose_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
StorageUI();
|
||||
ShowHideWindow(false);
|
||||
}
|
||||
|
||||
private void menuPromotion_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
Utils.ProcessStart($"{Utils.Base64Decode(Global.PromotionUrl)}?t={DateTime.Now.Ticks}");
|
||||
@@ -355,6 +362,17 @@ namespace v2rayN.Desktop.Views
|
||||
DialogHost.Show(_backupAndRestoreView);
|
||||
}
|
||||
|
||||
private async void MenuClose_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (await UI.ShowYesNo(this, ResUI.menuExitTips) == ButtonResult.No)
|
||||
{
|
||||
return;
|
||||
}
|
||||
StorageUI();
|
||||
|
||||
await ViewModel?.MyAppExitAsync(false);
|
||||
}
|
||||
|
||||
#endregion Event
|
||||
|
||||
#region UI
|
||||
@@ -374,8 +392,16 @@ namespace v2rayN.Desktop.Views
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Hide();
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
this.Hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.WindowState = WindowState.Minimized;
|
||||
}
|
||||
}
|
||||
|
||||
_config.UiItem.ShowInTaskbar = bl;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
Classes="TextArea"
|
||||
IsReadOnly="True"
|
||||
TextAlignment="Left"
|
||||
VerticalAlignment="Stretch"
|
||||
TextWrapping="Wrap">
|
||||
<TextBox.ContextMenu>
|
||||
<ContextMenu>
|
||||
|
||||
@@ -377,7 +377,7 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<!--
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
@@ -390,7 +390,8 @@
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="Margin8" />
|
||||
<TextBlock
|
||||
<!--
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
@@ -488,18 +489,7 @@
|
||||
HorizontalAlignment="Left"
|
||||
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
|
||||
Grid.Row="11"
|
||||
@@ -533,7 +523,6 @@
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
IsVisible="False"
|
||||
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamily}" />
|
||||
<ComboBox
|
||||
x:Name="cmbcurrentFontFamily"
|
||||
@@ -541,15 +530,13 @@
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Classes="Margin8"
|
||||
IsVisible="False"
|
||||
MaxDropDownHeight="1000" />
|
||||
<TextBlock
|
||||
Grid.Row="16"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
IsVisible="False"
|
||||
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsCurrentFontFamilyLinuxTip}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
@@ -677,7 +664,6 @@
|
||||
Classes="Margin8"
|
||||
Text="{x:Static resx:ResUI.TbSettingsChinaUserTip}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
@@ -15,7 +15,6 @@ namespace v2rayN.Desktop.Views
|
||||
|
||||
btnCancel.Click += (s, e) => this.Close();
|
||||
_config = AppHandler.Instance.Config;
|
||||
// var lstFonts = GetFonts(Utils.GetFontsPath());
|
||||
|
||||
ViewModel = new OptionSettingViewModel(UpdateViewHandler);
|
||||
|
||||
@@ -100,9 +99,6 @@ namespace v2rayN.Desktop.Views
|
||||
cmbMainGirdOrientation.Items.Add(it.ToString());
|
||||
}
|
||||
|
||||
//lstFonts.ForEach(it => { cmbcurrentFontFamily.Items.Add(it); });
|
||||
//cmbcurrentFontFamily.Items.Add(string.Empty);
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.localPort, v => v.txtlocalPort.Text).DisposeWith(disposables);
|
||||
@@ -127,7 +123,7 @@ namespace v2rayN.Desktop.Views
|
||||
this.Bind(ViewModel, vm => vm.hyDownMbps, v => v.txtDownMbps.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.enableFragment, v => v.togenableFragment.IsChecked).DisposeWith(disposables);
|
||||
|
||||
//this.Bind(ViewModel, vm => vm.AutoRun, v => v.togAutoRun.IsChecked).DisposeWith(disposables);
|
||||
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.KeepOlderDedupl, v => v.togKeepOlderDedupl.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.IgnoreGeoUpdateCore, v => v.togIgnoreGeoUpdateCore.IsChecked).DisposeWith(disposables);
|
||||
@@ -135,7 +131,6 @@ namespace v2rayN.Desktop.Views
|
||||
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.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.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CurrentFontFamily, v => v.cmbcurrentFontFamily.SelectedValue).DisposeWith(disposables);
|
||||
@@ -179,61 +174,55 @@ namespace v2rayN.Desktop.Views
|
||||
switch (action)
|
||||
{
|
||||
case EViewAction.CloseWindow:
|
||||
// WindowsUtils.SetAutoRun(Global.AutoRunRegPath, Global.AutoRunName, togAutoRun.IsChecked ?? false);
|
||||
this.Close(true);
|
||||
break;
|
||||
|
||||
case EViewAction.InitSettingFont:
|
||||
await InitSettingFont();
|
||||
break;
|
||||
}
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
//private List<string> GetFonts(string path)
|
||||
//{
|
||||
// var lstFonts = new List<string>();
|
||||
// try
|
||||
// {
|
||||
// string[] searchPatterns = { "*.ttf", "*.ttc" };
|
||||
// var files = new List<string>();
|
||||
// foreach (var pattern in searchPatterns)
|
||||
// {
|
||||
// files.AddRange(Directory.GetFiles(path, pattern));
|
||||
// }
|
||||
// var culture = _config.uiItem.currentLanguage == Global.Languages[0] ? "zh-cn" : "en-us";
|
||||
// var culture2 = "en-us";
|
||||
// foreach (var ttf in files)
|
||||
// {
|
||||
// var families = Fonts.GetFontFamilies(Utils.GetFontsPath(ttf));
|
||||
// foreach (FontFamily family in families)
|
||||
// {
|
||||
// var typefaces = family.GetTypefaces();
|
||||
// foreach (Typeface typeface in typefaces)
|
||||
// {
|
||||
// typeface.TryGetGlyphTypeface(out GlyphTypeface glyph);
|
||||
// //var fontFace = glyph.Win32FaceNames[new CultureInfo("en-us")];
|
||||
// //if (!fontFace.Equals("Regular") && !fontFace.Equals("Normal"))
|
||||
// //{
|
||||
// // continue;
|
||||
// //}
|
||||
// var fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture)];
|
||||
// if (Utils.IsNullOrEmpty(fontFamily))
|
||||
// {
|
||||
// fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture2)];
|
||||
// if (Utils.IsNullOrEmpty(fontFamily))
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// lstFonts.Add(fontFamily);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Logging.SaveLog("fill fonts error", ex);
|
||||
// }
|
||||
// return lstFonts;
|
||||
//}
|
||||
private async Task InitSettingFont()
|
||||
{
|
||||
var lstFonts = await GetFonts();
|
||||
lstFonts.ForEach(it => { cmbcurrentFontFamily.Items.Add(it); });
|
||||
cmbcurrentFontFamily.Items.Add(string.Empty);
|
||||
}
|
||||
|
||||
private async Task<List<string>> GetFonts()
|
||||
{
|
||||
var lstFonts = new List<string>();
|
||||
try
|
||||
{
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
return lstFonts;
|
||||
}
|
||||
else if (Utils.IsLinux())
|
||||
{
|
||||
var result = await Utils.GetLinuxFontFamily("zh");
|
||||
if (result.IsNullOrEmpty())
|
||||
{
|
||||
return lstFonts;
|
||||
}
|
||||
|
||||
var lst = result.Split(Environment.NewLine)
|
||||
.Where(t => t.IsNotEmpty())
|
||||
.ToList()
|
||||
.Select(t => t.Split(",").FirstOrDefault() ?? "")
|
||||
.OrderBy(t => t)
|
||||
.ToList();
|
||||
return lst;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog("fill fonts error", ex);
|
||||
}
|
||||
return lstFonts;
|
||||
}
|
||||
|
||||
private void ClbdestOverride_SelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
|
||||
@@ -204,7 +204,7 @@
|
||||
Binding="{Binding SubRemarks}"
|
||||
Header="{x:Static resx:ResUI.LvSubscription}"
|
||||
Tag="SubRemarks" />
|
||||
<DataGridTemplateColumn SortMemberPath="Delay" Tag="Delay">
|
||||
<DataGridTemplateColumn SortMemberPath="Delay" Tag="DelayVal">
|
||||
<DataGridTemplateColumn.Header>
|
||||
<TextBlock Text="{x:Static resx:ResUI.LvTestDelay}" />
|
||||
</DataGridTemplateColumn.Header>
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace v2rayN.Desktop.Views
|
||||
lstProfiles.SelectionChanged += lstProfiles_SelectionChanged;
|
||||
lstProfiles.DoubleTapped += LstProfiles_DoubleTapped;
|
||||
lstProfiles.LoadingRow += LstProfiles_LoadingRow;
|
||||
lstProfiles.Sorting += LstProfiles_Sorting;
|
||||
//if (_config.uiItem.enableDragDropSort)
|
||||
//{
|
||||
// lstProfiles.AllowDrop = true;
|
||||
@@ -92,6 +93,13 @@ namespace v2rayN.Desktop.Views
|
||||
ViewModel?.RefreshServers();
|
||||
}
|
||||
|
||||
private async void LstProfiles_Sorting(object? sender, DataGridColumnEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
await ViewModel?.SortServer(e.Column.Tag.ToString());
|
||||
e.Handled = false;
|
||||
}
|
||||
|
||||
//#region Event
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
@@ -189,6 +197,8 @@ namespace v2rayN.Desktop.Views
|
||||
|
||||
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)
|
||||
{
|
||||
ViewModel?.SetDefaultServer();
|
||||
@@ -343,7 +353,7 @@ namespace v2rayN.Desktop.Views
|
||||
}
|
||||
else
|
||||
{
|
||||
item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel); ;
|
||||
item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel);
|
||||
item2.DisplayIndex = displayIndex++;
|
||||
}
|
||||
if (item.Name.StartsWith("to"))
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@@ -114,7 +115,7 @@
|
||||
|
||||
<TextBox
|
||||
x:Name="txtAutoUpdateInterval"
|
||||
Width="200"
|
||||
Width="100"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
DockPanel.Dock="Right"
|
||||
@@ -233,13 +234,27 @@
|
||||
<TextBlock
|
||||
Grid.Row="12"
|
||||
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"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
Text="{x:Static resx:ResUI.LvMoreUrl}" />
|
||||
<TextBox
|
||||
x:Name="txtMoreUrl"
|
||||
Grid.Row="13"
|
||||
Grid.Row="14"
|
||||
Grid.Column="1"
|
||||
MinHeight="100"
|
||||
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.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.Memo, v => v.txtMemo.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
<AssemblyName>v2rayN</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -19,16 +20,16 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.1.4" />
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.1.4" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.1.4" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.1.4" />
|
||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.1.4" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.1.4" />
|
||||
<PackageReference Include="Avalonia" Version="11.2.0" />
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.2.0" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.2.0" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.0" />
|
||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.2.0" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.2.0" />
|
||||
<PackageReference Include="DialogHost.Avalonia" Version="0.8.1" />
|
||||
<PackageReference Include="MessageBox.Avalonia" Version="3.1.6.13" />
|
||||
<PackageReference Include="Semi.Avalonia" Version="11.1.0.4" />
|
||||
<PackageReference Include="Semi.Avalonia.DataGrid" Version="11.1.0.4" />
|
||||
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0" />
|
||||
<PackageReference Include="Semi.Avalonia" Version="11.2.0" />
|
||||
<PackageReference Include="Semi.Avalonia.DataGrid" Version="11.2.0" />
|
||||
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
||||
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<Application
|
||||
x:Class="v2rayN.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:conv="clr-namespace:v2rayN.Converters"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
ShutdownMode="OnExplicitShutdown"
|
||||
StartupUri="Views/MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
@@ -211,6 +211,11 @@
|
||||
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
|
||||
<Setter Property="TextOptions.TextRenderingMode" Value="ClearType" />
|
||||
<Setter Property="TextOptions.TextHintingMode" Value="Fixed" />
|
||||
<Setter Property="TextElement.Foreground" Value="{DynamicResource MaterialDesignBody}" />
|
||||
<Setter Property="Background" Value="{DynamicResource MaterialDesignPaper}" />
|
||||
<Setter Property="TextElement.FontFamily" Value="{x:Static conv:MaterialDesignFonts.MyFont}" />
|
||||
<Setter Property="FontFamily" Value="{x:Static conv:MaterialDesignFonts.MyFont}" />
|
||||
<Setter Property="ResizeMode" Value="NoResize" />
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="ViewGlobal"
|
||||
@@ -219,6 +224,10 @@
|
||||
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
|
||||
<Setter Property="TextOptions.TextRenderingMode" Value="ClearType" />
|
||||
<Setter Property="TextOptions.TextHintingMode" Value="Fixed" />
|
||||
<Setter Property="TextElement.Foreground" Value="{DynamicResource MaterialDesignBody}" />
|
||||
<Setter Property="Background" Value="{DynamicResource MaterialDesignPaper}" />
|
||||
<Setter Property="TextElement.FontFamily" Value="{x:Static conv:MaterialDesignFonts.MyFont}" />
|
||||
<Setter Property="FontFamily" Value="{x:Static conv:MaterialDesignFonts.MyFont}" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace v2rayN
|
||||
{
|
||||
var exePathKey = Utils.GetMd5(Utils.GetExePath());
|
||||
|
||||
var rebootas = (e.Args ?? new string[] { }).Any(t => t == Global.RebootAs);
|
||||
var rebootas = (e.Args ?? Array.Empty<string>()).Any(t => t == Global.RebootAs);
|
||||
ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew);
|
||||
if (!rebootas && !bCreatedNew)
|
||||
{
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
using Microsoft.Win32;
|
||||
using Microsoft.Win32.TaskScheduler;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
@@ -55,49 +51,6 @@ namespace v2rayN
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Auto Start via TaskService
|
||||
/// </summary>
|
||||
/// <param name="taskName"></param>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="description"></param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public static void AutoStart(string taskName, string fileName, string description)
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(taskName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
string TaskName = taskName;
|
||||
var logonUser = WindowsIdentity.GetCurrent().Name;
|
||||
string taskDescription = description;
|
||||
string deamonFileName = fileName;
|
||||
|
||||
using var taskService = new TaskService();
|
||||
var tasks = taskService.RootFolder.GetTasks(new Regex(TaskName));
|
||||
foreach (var t in tasks)
|
||||
{
|
||||
taskService.RootFolder.DeleteTask(t.Name);
|
||||
}
|
||||
if (Utils.IsNullOrEmpty(fileName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var task = taskService.NewTask();
|
||||
task.RegistrationInfo.Description = taskDescription;
|
||||
task.Settings.DisallowStartIfOnBatteries = false;
|
||||
task.Settings.StopIfGoingOnBatteries = false;
|
||||
task.Settings.RunOnlyIfIdle = false;
|
||||
task.Settings.IdleSettings.StopOnIdleEnd = false;
|
||||
task.Settings.ExecutionTimeLimit = TimeSpan.Zero;
|
||||
task.Triggers.Add(new LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(10) });
|
||||
task.Principal.RunLevel = TaskRunLevel.Highest;
|
||||
task.Actions.Add(new ExecAction(deamonFileName.AppendQuotes(), null, Path.GetDirectoryName(deamonFileName)));
|
||||
|
||||
taskService.RootFolder.RegisterTaskDefinition(TaskName, task);
|
||||
}
|
||||
|
||||
[DllImport("dwmapi.dll")]
|
||||
public static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attribute, ref int attributeValue, uint attributeSize);
|
||||
|
||||
@@ -116,58 +69,6 @@ namespace v2rayN
|
||||
return value is int i && i > 0;
|
||||
}
|
||||
|
||||
public static string? RegReadValue(string path, string name, string def)
|
||||
{
|
||||
RegistryKey? regKey = null;
|
||||
try
|
||||
{
|
||||
regKey = Registry.CurrentUser.OpenSubKey(path, false);
|
||||
string? value = regKey?.GetValue(name) as string;
|
||||
if (Utils.IsNullOrEmpty(value))
|
||||
{
|
||||
return def;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
regKey?.Close();
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public static void RegWriteValue(string path, string name, object value)
|
||||
{
|
||||
RegistryKey? regKey = null;
|
||||
try
|
||||
{
|
||||
regKey = Registry.CurrentUser.CreateSubKey(path);
|
||||
if (Utils.IsNullOrEmpty(value.ToString()))
|
||||
{
|
||||
regKey?.DeleteValue(name, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
regKey?.SetValue(name, value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
regKey?.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveTunDevice()
|
||||
{
|
||||
try
|
||||
@@ -209,42 +110,6 @@ namespace v2rayN
|
||||
DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开机自动启动
|
||||
/// </summary>
|
||||
/// <param name="run"></param>
|
||||
/// <returns></returns>
|
||||
public static void SetAutoRun(string AutoRunRegPath, string AutoRunName, bool run)
|
||||
{
|
||||
try
|
||||
{
|
||||
var autoRunName = $"{AutoRunName}_{Utils.GetMd5(Utils.StartupPath())}";
|
||||
//delete first
|
||||
RegWriteValue(AutoRunRegPath, autoRunName, "");
|
||||
if (Utils.IsAdministrator())
|
||||
{
|
||||
AutoStart(autoRunName, "", "");
|
||||
}
|
||||
|
||||
if (run)
|
||||
{
|
||||
string exePath = Utils.GetExePath();
|
||||
if (Utils.IsAdministrator())
|
||||
{
|
||||
AutoStart(autoRunName, exePath, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
RegWriteValue(AutoRunRegPath, autoRunName, exePath.AppendQuotes());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
#region Windows API
|
||||
|
||||
[Flags]
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
x:Class="v2rayN.Views.AddServer2Window"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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"
|
||||
@@ -13,13 +12,8 @@
|
||||
Width="700"
|
||||
Height="500"
|
||||
x:TypeArguments="vms:AddServer2ViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
x:Class="v2rayN.Views.AddServerWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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"
|
||||
@@ -13,13 +12,9 @@
|
||||
Width="900"
|
||||
Height="700"
|
||||
x:TypeArguments="vms:AddServerViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
ResizeMode="CanResize"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace v2rayN.Views
|
||||
|
||||
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.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);
|
||||
@@ -30,7 +30,7 @@ namespace v2rayN.Views
|
||||
if (obj is null) return false;
|
||||
Application.Current?.Dispatcher.Invoke((() =>
|
||||
{
|
||||
ViewModel?.UpdateViewResult((CheckUpdateItem)obj);
|
||||
ViewModel?.UpdateViewResult((CheckUpdateModel)obj);
|
||||
}), DispatcherPriority.Normal);
|
||||
break;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<reactiveui:ReactiveUserControl
|
||||
x:Class="v2rayN.Views.ClashConnectionsView"
|
||||
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: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"
|
||||
d:DesignHeight="450"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
x:Class="v2rayN.Views.DNSSettingWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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"
|
||||
@@ -13,13 +12,8 @@
|
||||
Width="1000"
|
||||
Height="700"
|
||||
x:TypeArguments="vms:DNSSettingViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
x:Class="v2rayN.Views.GlobalHotkeySettingWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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"
|
||||
@@ -13,14 +12,9 @@
|
||||
Width="700"
|
||||
Height="500"
|
||||
x:TypeArguments="vms:SubEditViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
KeyDown="GlobalHotkeySettingWindow_KeyDown"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
x:Class="v2rayN.Views.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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"
|
||||
@@ -15,12 +14,9 @@
|
||||
Height="700"
|
||||
MinWidth="900"
|
||||
x:TypeArguments="vms:MainWindowViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
ResizeMode="CanResizeWithGrip"
|
||||
ShowInTaskbar="True"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
|
||||
@@ -270,11 +270,11 @@ namespace v2rayN.Views
|
||||
StorageUI();
|
||||
}
|
||||
|
||||
private void Current_SessionEnding(object sender, SessionEndingCancelEventArgs e)
|
||||
private async void Current_SessionEnding(object sender, SessionEndingCancelEventArgs e)
|
||||
{
|
||||
Logging.SaveLog("Current_SessionEnding");
|
||||
StorageUI();
|
||||
ViewModel?.MyAppExitAsync(true);
|
||||
await ViewModel?.MyAppExitAsync(true);
|
||||
}
|
||||
|
||||
private void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||
@@ -284,6 +284,8 @@ namespace v2rayN.Views
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.V:
|
||||
if (_backupAndRestoreView?.IsVisible == true) return;
|
||||
|
||||
var clipboardData = WindowsUtils.GetClipboardData();
|
||||
ViewModel?.AddServerViaClipboardAsync(clipboardData);
|
||||
break;
|
||||
@@ -365,17 +367,17 @@ namespace v2rayN.Views
|
||||
var bl = blShow ?? !_config.UiItem.ShowInTaskbar;
|
||||
if (bl)
|
||||
{
|
||||
Application.Current.MainWindow.Show();
|
||||
if (Application.Current.MainWindow.WindowState == WindowState.Minimized)
|
||||
this?.Show();
|
||||
if (this?.WindowState == WindowState.Minimized)
|
||||
{
|
||||
Application.Current.MainWindow.WindowState = WindowState.Normal;
|
||||
this.WindowState = WindowState.Normal;
|
||||
}
|
||||
Application.Current.MainWindow.Activate();
|
||||
Application.Current.MainWindow.Focus();
|
||||
this?.Activate();
|
||||
this?.Focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
Application.Current.MainWindow.Hide();
|
||||
this?.Hide();
|
||||
}
|
||||
_config.UiItem.ShowInTaskbar = bl;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,8 @@
|
||||
</WrapPanel>
|
||||
<TextBox
|
||||
Name="txtMsg"
|
||||
VerticalAlignment="Stretch"
|
||||
AcceptsReturn="True"
|
||||
BorderThickness="0"
|
||||
FontSize="{DynamicResource StdFontSize-1}"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
x:Class="v2rayN.Views.OptionSettingWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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"
|
||||
@@ -13,13 +12,8 @@
|
||||
Width="1000"
|
||||
Height="700"
|
||||
x:TypeArguments="vms:OptionSettingViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
@@ -661,20 +655,6 @@
|
||||
Margin="{StaticResource Margin8}"
|
||||
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
|
||||
Grid.Row="10"
|
||||
Grid.Column="0"
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace v2rayN.Views
|
||||
|
||||
this.Owner = Application.Current.MainWindow;
|
||||
_config = AppHandler.Instance.Config;
|
||||
var lstFonts = GetFonts(Utils.GetFontsPath());
|
||||
|
||||
ViewModel = new OptionSettingViewModel(UpdateViewHandler);
|
||||
|
||||
@@ -102,9 +101,6 @@ namespace v2rayN.Views
|
||||
cmbMainGirdOrientation.Items.Add(it.ToString());
|
||||
}
|
||||
|
||||
lstFonts.ForEach(it => { cmbcurrentFontFamily.Items.Add(it); });
|
||||
cmbcurrentFontFamily.Items.Add(string.Empty);
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.localPort, v => v.txtlocalPort.Text).DisposeWith(disposables);
|
||||
@@ -145,7 +141,6 @@ namespace v2rayN.Views
|
||||
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.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.DoubleClick2Activate, v => v.togDoubleClick2Activate.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);
|
||||
@@ -188,14 +183,24 @@ namespace v2rayN.Views
|
||||
switch (action)
|
||||
{
|
||||
case EViewAction.CloseWindow:
|
||||
WindowsUtils.SetAutoRun(Global.AutoRunRegPath, Global.AutoRunName, togAutoRun.IsChecked ?? false);
|
||||
this.DialogResult = true;
|
||||
break;
|
||||
|
||||
case EViewAction.InitSettingFont:
|
||||
await InitSettingFont();
|
||||
break;
|
||||
}
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
private List<string> GetFonts(string path)
|
||||
private async Task InitSettingFont()
|
||||
{
|
||||
var lstFonts = await GetFonts(Utils.GetFontsPath());
|
||||
lstFonts.ForEach(it => { cmbcurrentFontFamily.Items.Add(it); });
|
||||
cmbcurrentFontFamily.Items.Add(string.Empty);
|
||||
}
|
||||
|
||||
private async Task<List<string>> GetFonts(string path)
|
||||
{
|
||||
var lstFonts = new List<string>();
|
||||
try
|
||||
@@ -241,7 +246,7 @@ namespace v2rayN.Views
|
||||
{
|
||||
Logging.SaveLog("fill fonts error", ex);
|
||||
}
|
||||
return lstFonts;
|
||||
return lstFonts.OrderBy(t => t).ToList();
|
||||
}
|
||||
|
||||
private void ClbdestOverride_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
<reactiveui:ReactiveWindow
|
||||
x:Class="v2rayN.Views.RoutingRuleDetailsWindow"
|
||||
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: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:conv="clr-namespace:v2rayN.Converters"
|
||||
Title="{x:Static resx:ResUI.menuRoutingRuleDetailsSetting}"
|
||||
Width="900"
|
||||
Height="700"
|
||||
x:TypeArguments="vms:RoutingRuleDetailsViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel>
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
<reactiveui:ReactiveWindow
|
||||
x:Class="v2rayN.Views.RoutingRuleSettingWindow"
|
||||
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: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:conv="clr-namespace:v2rayN.Converters"
|
||||
Title="{x:Static resx:ResUI.menuRoutingRuleSetting}"
|
||||
Width="960"
|
||||
Height="700"
|
||||
x:TypeArguments="vms:RoutingRuleSettingViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
x:Class="v2rayN.Views.RoutingSettingWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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"
|
||||
@@ -13,13 +12,8 @@
|
||||
Width="990"
|
||||
Height="700"
|
||||
x:TypeArguments="vms:RoutingSettingViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
|
||||
@@ -100,11 +100,11 @@ namespace v2rayN.Views
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
private void menuExit_Click(object sender, RoutedEventArgs e)
|
||||
private async void menuExit_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
tbNotify.Dispose();
|
||||
var service = Locator.Current.GetService<MainWindowViewModel>();
|
||||
if (service != null) service.MyAppExitAsync(false);
|
||||
if (service != null) await service.MyAppExitAsync(false);
|
||||
}
|
||||
|
||||
private void txtRunningInfoDisplay_MouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
<reactiveui:ReactiveWindow
|
||||
x:Class="v2rayN.Views.SubEditWindow"
|
||||
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: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:conv="clr-namespace:v2rayN.Converters"
|
||||
Title="{x:Static resx:ResUI.menuSubSetting}"
|
||||
Width="700"
|
||||
Height="600"
|
||||
x:TypeArguments="vms:SubEditViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
@@ -70,6 +64,7 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@@ -165,7 +160,7 @@
|
||||
|
||||
<TextBox
|
||||
x:Name="txtAutoUpdateInterval"
|
||||
Width="200"
|
||||
Width="100"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Top"
|
||||
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.SubUrlTips}"
|
||||
@@ -300,6 +295,23 @@
|
||||
AcceptsReturn="True"
|
||||
Style="{StaticResource MyOutlinedTextBox}"
|
||||
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>
|
||||
</ScrollViewer>
|
||||
</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.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.Memo, v => v.txtMemo.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
x:Class="v2rayN.Views.SubSettingWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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"
|
||||
@@ -13,13 +12,8 @@
|
||||
Width="800"
|
||||
Height="600"
|
||||
x:TypeArguments="vms:SubSettingViewModel"
|
||||
Background="{DynamicResource MaterialDesignPaper}"
|
||||
FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}"
|
||||
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<materialDesign:DialogHost
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MaterialDesignThemes" Version="5.1.0" />
|
||||
<PackageReference Include="H.NotifyIcon.Wpf" Version="2.1.4" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.11.0" />
|
||||
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||
<PackageReference Include="ReactiveUI.WPF" Version="20.1.63" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user