Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05d446ed37 | ||
|
|
7a0b068642 | ||
|
|
c0ef8c09af | ||
|
|
a2db6dd468 | ||
|
|
471bc0f65d | ||
|
|
80f840a7c2 | ||
|
|
a2413fdf23 | ||
|
|
9cbe2b938c | ||
|
|
e915726c52 | ||
|
|
b11e68cfd8 | ||
|
|
bee66d06dd | ||
|
|
945a0add96 | ||
|
|
294cabcf05 | ||
|
|
22eb993ebf | ||
|
|
b5e1a297ae | ||
|
|
499a16feae | ||
|
|
1866a59d12 | ||
|
|
10513e0f3b | ||
|
|
2e32de2fbb | ||
|
|
30a838df77 | ||
|
|
7cf9b9f57e | ||
|
|
736d995d4c | ||
|
|
e335b2c0d6 | ||
|
|
96ae5517f6 | ||
|
|
fb4b8d923a | ||
|
|
2ade705e51 | ||
|
|
e0086b4b79 | ||
|
|
8f6d443104 |
18
README.md
18
README.md
@@ -1,5 +1,5 @@
|
|||||||
# v2rayN
|
# v2rayN
|
||||||
A GUI client for Windows and Linux, support [Xray core](https://github.com/XTLS/Xray-core) and [v2fly core](https://github.com/v2fly/v2ray-core) and [others](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
|
A GUI client for Windows and Linux, support [Xray core](https://github.com/XTLS/Xray-core) and [others](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
|
||||||
|
|
||||||
|
|
||||||
[](https://github.com/2dust/v2rayN/commits/master)
|
[](https://github.com/2dust/v2rayN/commits/master)
|
||||||
@@ -9,13 +9,19 @@ A GUI client for Windows and Linux, support [Xray core](https://github.com/XTLS/
|
|||||||
|
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
- If you are new to this, please download v2rayN-With-Core.zip from [releases](https://github.com/2dust/v2rayN/releases)
|
Check [Release files introduction](https://github.com/2dust/v2rayN/wiki/Release-files-introduction) and select the version you need to download
|
||||||
- Otherwise please download v2rayN.zip (you will also need to download cores in the bin directory)
|
### Windows
|
||||||
- Run v2rayN.exe
|
- Run `v2rayN.exe`
|
||||||
|
### Linux
|
||||||
|
- `chmod +x v2rayN` Run `./v2rayN`
|
||||||
|
```
|
||||||
|
Debian 9+
|
||||||
|
Ubuntu 16.04+
|
||||||
|
Fedora 30+
|
||||||
|
```
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
- (6.35 and above)[Microsoft .NET 8.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
|
- [Microsoft .NET 8.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
|
||||||
- (6.33 and below)[Microsoft .NET 6.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
|
|
||||||
- [Supported cores](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
|
- [Supported cores](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,5 +8,10 @@
|
|||||||
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
|
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
|
||||||
<FileVersion>1.3.0</FileVersion>
|
<FileVersion>1.3.0</FileVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Assets\en-US.json" />
|
||||||
|
<EmbeddedResource Include="Assets\zh-CN.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
14
v2rayN/AmazTool/Assets/en-US.json
Normal file
14
v2rayN/AmazTool/Assets/en-US.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"Restart_v2rayN": "Start v2rayN, please wait...",
|
||||||
|
"Guidelines": "Please run it from the main application.",
|
||||||
|
"Upgrade_File_Not_Found": "Upgrade failed, file not found.",
|
||||||
|
"In_Progress": "In progress, please wait...",
|
||||||
|
"Try_Terminate_Process": "Try to terminate the v2rayN process.",
|
||||||
|
"Failed_Terminate_Process": "Failed to terminate the v2rayN.Close it manually,or the upgrade may fail.",
|
||||||
|
"Start_Unzipping": "Start extracting the update package.",
|
||||||
|
"Success_Unzipping": "Successfully extracted the update package!",
|
||||||
|
"Failed_Unzipping": "Failed to extract the update package!",
|
||||||
|
"Failed_Upgrade": "Upgrade failed!",
|
||||||
|
"Success_Upgrade": "Upgrade success!",
|
||||||
|
"Information": "Information"
|
||||||
|
}
|
||||||
14
v2rayN/AmazTool/Assets/zh-CN.json
Normal file
14
v2rayN/AmazTool/Assets/zh-CN.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"Restart_v2rayN": "正在重启,请等待...",
|
||||||
|
"Guidelines": "请从主应用运行!",
|
||||||
|
"Upgrade_File_Not_Found": "升级失败,文件不存在!",
|
||||||
|
"In_Progress": "正在进行中,请等待...",
|
||||||
|
"Try_Terminate_Process": "尝试结束 v2rayN 进程...",
|
||||||
|
"Failed_Terminate_Process": "请手动关闭正在运行的v2rayN,否则可能升级失败。",
|
||||||
|
"Start_Unzipping": "开始解压缩更新包...",
|
||||||
|
"Success_Unzipping": "解压缩更新包成功!",
|
||||||
|
"Failed_Unzipping": "解压缩更新包失败!",
|
||||||
|
"Failed_Upgrade": "升级失败!",
|
||||||
|
"Success_Upgrade": "升级成功!",
|
||||||
|
"Information": "提示"
|
||||||
|
}
|
||||||
59
v2rayN/AmazTool/LocalizationHelper.cs
Normal file
59
v2rayN/AmazTool/LocalizationHelper.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace AmazTool
|
||||||
|
{
|
||||||
|
public class LocalizationHelper
|
||||||
|
{
|
||||||
|
private static Dictionary<string, string> _languageResources = [];
|
||||||
|
|
||||||
|
static LocalizationHelper()
|
||||||
|
{
|
||||||
|
// 加载语言资源
|
||||||
|
LoadLanguageResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void LoadLanguageResources()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var currentLanguage = CultureInfo.CurrentCulture.Name;
|
||||||
|
if (currentLanguage != "zh-CN" && currentLanguage != "en-US")
|
||||||
|
{
|
||||||
|
currentLanguage = "en-US";
|
||||||
|
}
|
||||||
|
|
||||||
|
var resourceName = $"AmazTool.Assets.{currentLanguage}.json";
|
||||||
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
|
|
||||||
|
using var stream = assembly.GetManifestResourceStream(resourceName);
|
||||||
|
if (stream == null) return;
|
||||||
|
|
||||||
|
using StreamReader reader = new(stream);
|
||||||
|
var json = reader.ReadToEnd();
|
||||||
|
if (!string.IsNullOrEmpty(json))
|
||||||
|
{
|
||||||
|
_languageResources = JsonSerializer.Deserialize<Dictionary<string, string>>(json) ?? new Dictionary<string, string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed to read language resource file: {ex.Message}");
|
||||||
|
}
|
||||||
|
catch (JsonException ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed to parse JSON data: {ex.Message}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Unexpected error occurred: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetLocalizedValue(string key)
|
||||||
|
{
|
||||||
|
return _languageResources.TryGetValue(key, out var translation) ? translation : key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
{
|
{
|
||||||
if (args.Length == 0)
|
if (args.Length == 0)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Please run it from the main application.(请从主应用运行)");
|
Console.WriteLine(LocalizationHelper.GetLocalizedValue("Guidelines"));
|
||||||
Thread.Sleep(5000);
|
Thread.Sleep(5000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,35 +8,37 @@ namespace AmazTool
|
|||||||
{
|
{
|
||||||
public static void Upgrade(string fileName)
|
public static void Upgrade(string fileName)
|
||||||
{
|
{
|
||||||
Console.WriteLine(fileName);
|
Console.WriteLine($"{LocalizationHelper.GetLocalizedValue("Start_Unzipping")}\n{fileName}");
|
||||||
Console.WriteLine("In progress, please wait...(正在进行中,请等待)");
|
|
||||||
|
|
||||||
Thread.Sleep(9000);
|
Waiting(9);
|
||||||
|
|
||||||
if (!File.Exists(fileName))
|
if (!File.Exists(fileName))
|
||||||
{
|
{
|
||||||
Console.WriteLine("Upgrade Failed, File Not Exist(升级失败,文件不存在).");
|
Console.WriteLine(LocalizationHelper.GetLocalizedValue("Upgrade_File_Not_Found"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Try to end the process(尝试结束进程).");
|
Console.WriteLine(LocalizationHelper.GetLocalizedValue("Try_Terminate_Process"));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var existing = Process.GetProcessesByName(V2rayN);
|
var existing = Process.GetProcessesByName(V2rayN);
|
||||||
foreach (var pp in existing)
|
foreach (var pp in existing)
|
||||||
{
|
{
|
||||||
pp?.Kill();
|
var path = pp.MainModule?.FileName ?? "";
|
||||||
pp?.WaitForExit(1000);
|
if (path.StartsWith(GetPath(V2rayN)))
|
||||||
|
{
|
||||||
|
pp?.Kill();
|
||||||
|
pp?.WaitForExit(1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Access may be denied without admin right. The user may not be an administrator.
|
// Access may be denied without admin right. The user may not be an administrator.
|
||||||
Console.WriteLine("Failed to close v2rayN(关闭v2rayN失败).\n" +
|
Console.WriteLine(LocalizationHelper.GetLocalizedValue("Failed_Terminate_Process") + ex.StackTrace);
|
||||||
"Close it manually, or the upgrade may fail.(请手动关闭正在运行的v2rayN,否则可能升级失败。\n\n" + ex.StackTrace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Start extracting files(开始解压文件).");
|
Console.WriteLine(LocalizationHelper.GetLocalizedValue("Start_Unzipping"));
|
||||||
StringBuilder sb = new();
|
StringBuilder sb = new();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -79,17 +81,17 @@ namespace AmazTool
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Upgrade Failed(升级失败)." + ex.StackTrace);
|
Console.WriteLine(LocalizationHelper.GetLocalizedValue("Failed_Upgrade") + ex.StackTrace);
|
||||||
//return;
|
//return;
|
||||||
}
|
}
|
||||||
if (sb.Length > 0)
|
if (sb.Length > 0)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Upgrade Failed(升级失败)." + sb.ToString());
|
Console.WriteLine(LocalizationHelper.GetLocalizedValue("Failed_Upgrade") + sb.ToString());
|
||||||
//return;
|
//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Start v2rayN, please wait...(正在重启,请等待)");
|
Console.WriteLine(LocalizationHelper.GetLocalizedValue("Restart_v2rayN"));
|
||||||
Thread.Sleep(9000);
|
Waiting(9);
|
||||||
Process process = new()
|
Process process = new()
|
||||||
{
|
{
|
||||||
StartInfo = new()
|
StartInfo = new()
|
||||||
@@ -122,6 +124,15 @@ namespace AmazTool
|
|||||||
return Path.Combine(startupPath, fileName);
|
return Path.Combine(startupPath, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void Waiting(int second)
|
||||||
|
{
|
||||||
|
for (var i = second; i > 0; i--)
|
||||||
|
{
|
||||||
|
Console.WriteLine(i);
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static string V2rayN => "v2rayN";
|
private static string V2rayN => "v2rayN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Protobuf Include="Statistics.proto" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.28.3" />
|
|
||||||
<PackageReference Include="Grpc.Net.Client" Version="2.66.0" />
|
|
||||||
<PackageReference Include="Grpc.Tools" Version="2.67.0">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package v2ray.core.app.stats.command;
|
|
||||||
option csharp_namespace = "ProtosLib.Statistics";
|
|
||||||
|
|
||||||
message GetStatsRequest {
|
|
||||||
// Name of the stat counter.
|
|
||||||
string name = 1;
|
|
||||||
// Whether or not to reset the counter to fetching its value.
|
|
||||||
bool reset = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Stat {
|
|
||||||
string name = 1;
|
|
||||||
int64 value = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GetStatsResponse {
|
|
||||||
Stat stat = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message QueryStatsRequest {
|
|
||||||
string pattern = 1;
|
|
||||||
bool reset = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message QueryStatsResponse {
|
|
||||||
repeated Stat stat = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SysStatsRequest {
|
|
||||||
}
|
|
||||||
|
|
||||||
message SysStatsResponse {
|
|
||||||
uint32 NumGoroutine = 1;
|
|
||||||
uint32 NumGC = 2;
|
|
||||||
uint64 Alloc = 3;
|
|
||||||
uint64 TotalAlloc = 4;
|
|
||||||
uint64 Sys = 5;
|
|
||||||
uint64 Mallocs = 6;
|
|
||||||
uint64 Frees = 7;
|
|
||||||
uint64 LiveObjects = 8;
|
|
||||||
uint64 PauseTotalNs = 9;
|
|
||||||
uint32 Uptime = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
service StatsService {
|
|
||||||
rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {}
|
|
||||||
rpc QueryStats(QueryStatsRequest) returns (QueryStatsResponse) {}
|
|
||||||
rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
message Config {}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using ProtosLib.Statistics;
|
|
||||||
|
|
||||||
namespace ProtosLib
|
|
||||||
{
|
|
||||||
public class Tests
|
|
||||||
{
|
|
||||||
private StatsService.StatsServiceClient client_;
|
|
||||||
|
|
||||||
public Tests()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases";
|
public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases";
|
||||||
public const string CustomRoutingListUrl = @"https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/";
|
public const string CustomRoutingListUrl = @"https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/";
|
||||||
public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs";
|
public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs";
|
||||||
|
public const string IPAPIUrl = "https://ipapi.co/json";
|
||||||
|
|
||||||
public const string PromotionUrl = @"aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw=";
|
public const string PromotionUrl = @"aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw=";
|
||||||
public const string ConfigFileName = "guiNConfig.json";
|
public const string ConfigFileName = "guiNConfig.json";
|
||||||
|
|||||||
@@ -211,12 +211,12 @@
|
|||||||
|
|
||||||
public async Task<List<RoutingItem>?> RoutingItems()
|
public async Task<List<RoutingItem>?> RoutingItems()
|
||||||
{
|
{
|
||||||
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().Where(it => it.Locked == false).OrderBy(t => t.Sort).ToListAsync();
|
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().OrderBy(t => t.Sort).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RoutingItem?> GetRoutingItem(string id)
|
public async Task<RoutingItem?> GetRoutingItem(string id)
|
||||||
{
|
{
|
||||||
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(it => it.Locked == false && it.Id == id);
|
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(it => it.Id == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<DNSItem>?> DNSItems()
|
public async Task<List<DNSItem>?> DNSItems()
|
||||||
|
|||||||
@@ -65,10 +65,8 @@ namespace ServiceLib.Handler
|
|||||||
config.Inbound[0].Protocol = EInboundProtocol.socks.ToString();
|
config.Inbound[0].Protocol = EInboundProtocol.socks.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
config.RoutingBasicItem ??= new()
|
|
||||||
{
|
config.RoutingBasicItem ??= new();
|
||||||
EnableRoutingAdvanced = true
|
|
||||||
};
|
|
||||||
|
|
||||||
if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy))
|
if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy))
|
||||||
{
|
{
|
||||||
@@ -959,7 +957,6 @@ namespace ServiceLib.Handler
|
|||||||
&& o.Address == n.Address
|
&& o.Address == n.Address
|
||||||
&& o.Port == n.Port
|
&& o.Port == n.Port
|
||||||
&& o.Id == n.Id
|
&& o.Id == n.Id
|
||||||
&& o.AlterId == n.AlterId
|
|
||||||
&& o.Security == n.Security
|
&& o.Security == n.Security
|
||||||
&& o.Network == n.Network
|
&& o.Network == n.Network
|
||||||
&& o.HeaderType == n.HeaderType
|
&& o.HeaderType == n.HeaderType
|
||||||
@@ -968,6 +965,10 @@ namespace ServiceLib.Handler
|
|||||||
&& (o.ConfigType == EConfigType.Trojan || o.StreamSecurity == n.StreamSecurity)
|
&& (o.ConfigType == EConfigType.Trojan || o.StreamSecurity == n.StreamSecurity)
|
||||||
&& o.Flow == n.Flow
|
&& o.Flow == n.Flow
|
||||||
&& o.Sni == n.Sni
|
&& o.Sni == n.Sni
|
||||||
|
&& o.Alpn == n.Alpn
|
||||||
|
&& o.Fingerprint == n.Fingerprint
|
||||||
|
&& o.PublicKey == n.PublicKey
|
||||||
|
&& o.ShortId == n.ShortId
|
||||||
&& (!remarks || o.Remarks == n.Remarks);
|
&& (!remarks || o.Remarks == n.Remarks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1295,6 +1296,20 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Keep the last traffic statistics
|
||||||
|
if (lstOriSub != null)
|
||||||
|
{
|
||||||
|
var lstSub = await AppHandler.Instance.ProfileItems(subid);
|
||||||
|
foreach (var item in lstSub)
|
||||||
|
{
|
||||||
|
var existItem = lstOriSub?.FirstOrDefault(t => config.UiItem.EnableUpdateSubOnlyRemarksExist ? t.Remarks == item.Remarks : CompareProfileItem(t, item, true));
|
||||||
|
if (existItem != null)
|
||||||
|
{
|
||||||
|
await StatisticsHandler.Instance.CloneServerStatItem(existItem.IndexId, item.IndexId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1597,7 +1612,7 @@ namespace ServiceLib.Handler
|
|||||||
var item = await AppHandler.Instance.GetRoutingItem(config.RoutingBasicItem.RoutingIndexId);
|
var item = await AppHandler.Instance.GetRoutingItem(config.RoutingBasicItem.RoutingIndexId);
|
||||||
if (item is null)
|
if (item is null)
|
||||||
{
|
{
|
||||||
var item2 = await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(t => t.Locked == false);
|
var item2 = await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync();
|
||||||
await SetDefaultRouting(config, item2);
|
await SetDefaultRouting(config, item2);
|
||||||
return item2;
|
return item2;
|
||||||
}
|
}
|
||||||
@@ -1671,6 +1686,15 @@ namespace ServiceLib.Handler
|
|||||||
{
|
{
|
||||||
var ver = "V3-";
|
var ver = "V3-";
|
||||||
var items = await AppHandler.Instance.RoutingItems();
|
var items = await AppHandler.Instance.RoutingItems();
|
||||||
|
|
||||||
|
//TODO Temporary code to be removed later
|
||||||
|
var lockItem = items?.FirstOrDefault(t => t.Locked == true);
|
||||||
|
if (lockItem != null)
|
||||||
|
{
|
||||||
|
await ConfigHandler.RemoveRoutingItem(lockItem);
|
||||||
|
items = await AppHandler.Instance.RoutingItems();
|
||||||
|
}
|
||||||
|
|
||||||
if (!blImportAdvancedRules && items.Where(t => t.Remarks.StartsWith(ver)).ToList().Count > 0)
|
if (!blImportAdvancedRules && items.Where(t => t.Remarks.StartsWith(ver)).ToList().Count > 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1711,11 +1735,6 @@ namespace ServiceLib.Handler
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<RoutingItem?> GetLockedRoutingItem(Config config)
|
|
||||||
{
|
|
||||||
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(it => it.Locked == true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task RemoveRoutingItem(RoutingItem routingItem)
|
public static async Task RemoveRoutingItem(RoutingItem routingItem)
|
||||||
{
|
{
|
||||||
await SQLiteHelper.Instance.DeleteAsync(routingItem);
|
await SQLiteHelper.Instance.DeleteAsync(routingItem);
|
||||||
|
|||||||
@@ -59,14 +59,16 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
var fileName = Utils.GetConfigPath(Global.CoreConfigFileName);
|
var fileName = Utils.GetConfigPath(Global.CoreConfigFileName);
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
|
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
|
||||||
ShowMsg(true, result.Msg);
|
|
||||||
if (result.Success != true)
|
if (result.Success != true)
|
||||||
{
|
{
|
||||||
|
ShowMsg(true, result.Msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ShowMsg(true, $"{node.GetSummary()}");
|
ShowMsg(true, $"{node.GetSummary()}");
|
||||||
|
ShowMsg(false, $"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
|
||||||
|
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
||||||
await CoreStop();
|
await CoreStop();
|
||||||
await Task.Delay(100);
|
await Task.Delay(100);
|
||||||
await CoreStart(node);
|
await CoreStart(node);
|
||||||
@@ -100,6 +102,8 @@ namespace ServiceLib.Handler
|
|||||||
ShowMsg(false, result.Msg);
|
ShowMsg(false, result.Msg);
|
||||||
if (result.Success)
|
if (result.Success)
|
||||||
{
|
{
|
||||||
|
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
||||||
|
ShowMsg(false, configPath);
|
||||||
pid = await CoreStartSpeedtest(configPath, coreType);
|
pid = await CoreStartSpeedtest(configPath, coreType);
|
||||||
}
|
}
|
||||||
return pid;
|
return pid;
|
||||||
@@ -167,9 +171,6 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
private async Task CoreStart(ProfileItem node)
|
private async Task CoreStart(ProfileItem node)
|
||||||
{
|
{
|
||||||
ShowMsg(false, $"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
|
|
||||||
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
|
||||||
|
|
||||||
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
|
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
|
||||||
_config.RunningCoreType = coreType;
|
_config.RunningCoreType = coreType;
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||||
@@ -229,9 +230,6 @@ namespace ServiceLib.Handler
|
|||||||
|
|
||||||
private async Task<int> CoreStartSpeedtest(string configPath, ECoreType coreType)
|
private async Task<int> CoreStartSpeedtest(string configPath, ECoreType coreType)
|
||||||
{
|
{
|
||||||
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
|
|
||||||
|
|
||||||
ShowMsg(false, configPath);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||||
@@ -261,7 +259,7 @@ namespace ServiceLib.Handler
|
|||||||
return _config.TunModeItem.EnableTun
|
return _config.TunModeItem.EnableTun
|
||||||
&& eCoreType == ECoreType.sing_box
|
&& eCoreType == ECoreType.sing_box
|
||||||
&& Utils.IsLinux()
|
&& Utils.IsLinux()
|
||||||
&& _config.TunModeItem.LinuxSudoPwd.IsNotEmpty()
|
//&& _config.TunModeItem.LinuxSudoPwd.IsNotEmpty()
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +275,6 @@ namespace ServiceLib.Handler
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var isNeedSudo = mayNeedSudo && IsNeedSudo(coreInfo.CoreType);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Process proc = new()
|
Process proc = new()
|
||||||
@@ -296,13 +293,10 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var isNeedSudo = mayNeedSudo && IsNeedSudo(coreInfo.CoreType);
|
||||||
if (isNeedSudo)
|
if (isNeedSudo)
|
||||||
{
|
{
|
||||||
proc.StartInfo.FileName = $"/bin/sudo";
|
await RunProcessAsLinuxRoot(proc, fileName, coreInfo, configPath);
|
||||||
proc.StartInfo.Arguments = $"-S {fileName} {string.Format(coreInfo.Arguments, Utils.GetConfigPath(configPath))}";
|
|
||||||
proc.StartInfo.WorkingDirectory = null;
|
|
||||||
proc.StartInfo.StandardInputEncoding = Encoding.UTF8;
|
|
||||||
proc.StartInfo.RedirectStandardInput = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var startUpErrorMessage = new StringBuilder();
|
var startUpErrorMessage = new StringBuilder();
|
||||||
@@ -327,7 +321,7 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
proc.Start();
|
proc.Start();
|
||||||
|
|
||||||
if (isNeedSudo)
|
if (isNeedSudo && _config.TunModeItem.LinuxSudoPwd.IsNotEmpty())
|
||||||
{
|
{
|
||||||
var pwd = DesUtils.Decrypt(_config.TunModeItem.LinuxSudoPwd);
|
var pwd = DesUtils.Decrypt(_config.TunModeItem.LinuxSudoPwd);
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
@@ -363,6 +357,37 @@ namespace ServiceLib.Handler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task RunProcessAsLinuxRoot(Process proc, string fileName, CoreInfo coreInfo, string configPath)
|
||||||
|
{
|
||||||
|
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetConfigPath(configPath).AppendQuotes())}";
|
||||||
|
|
||||||
|
//Prefer shell scripts
|
||||||
|
var shFilePath = Utils.GetBinPath("run_as_root.sh");
|
||||||
|
File.Delete(shFilePath);
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("#!/bin/sh");
|
||||||
|
sb.AppendLine(cmdLine);
|
||||||
|
await File.WriteAllTextAsync(shFilePath, sb.ToString());
|
||||||
|
await Utils.SetLinuxChmod(shFilePath);
|
||||||
|
|
||||||
|
//Replace command
|
||||||
|
var args = File.Exists(shFilePath) ? shFilePath : cmdLine;
|
||||||
|
if (_config.TunModeItem.LinuxSudoPwd.IsNotEmpty())
|
||||||
|
{
|
||||||
|
proc.StartInfo.FileName = $"/bin/sudo";
|
||||||
|
proc.StartInfo.Arguments = $"-S {args}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
proc.StartInfo.FileName = $"/bin/pkexec";
|
||||||
|
proc.StartInfo.Arguments = $"{args}";
|
||||||
|
}
|
||||||
|
proc.StartInfo.WorkingDirectory = null;
|
||||||
|
proc.StartInfo.StandardInputEncoding = Encoding.UTF8;
|
||||||
|
proc.StartInfo.RedirectStandardInput = true;
|
||||||
|
Logging.SaveLog(proc.StartInfo.Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task KillProcess(Process? proc)
|
private async Task KillProcess(Process? proc)
|
||||||
{
|
{
|
||||||
if (proc is null)
|
if (proc is null)
|
||||||
|
|||||||
@@ -165,7 +165,7 @@
|
|||||||
|
|
||||||
private string PortableMode()
|
private string PortableMode()
|
||||||
{
|
{
|
||||||
return $" -d \"{Utils.GetBinPath("")}\"";
|
return $" -d {Utils.GetBinPath("").AppendQuotes()}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
private ServerStatItem? _serverStatItem;
|
private ServerStatItem? _serverStatItem;
|
||||||
private List<ServerStatItem> _lstServerStat;
|
private List<ServerStatItem> _lstServerStat;
|
||||||
private Action<ServerSpeedItem>? _updateFunc;
|
private Action<ServerSpeedItem>? _updateFunc;
|
||||||
//private StatisticsV2rayService? _statisticsV2Ray;
|
|
||||||
private StatisticsXrayService? _statisticsXray;
|
private StatisticsXrayService? _statisticsXray;
|
||||||
private StatisticsSingboxService? _statisticsSingbox;
|
private StatisticsSingboxService? _statisticsSingbox;
|
||||||
|
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
await InitData();
|
await InitData();
|
||||||
|
|
||||||
//_statisticsV2Ray = new StatisticsV2rayService(config, UpdateServerStatHandler);
|
|
||||||
_statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler);
|
_statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler);
|
||||||
_statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler);
|
_statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler);
|
||||||
}
|
}
|
||||||
@@ -35,7 +34,6 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//_statisticsV2Ray?.Close();
|
|
||||||
_statisticsXray?.Close();
|
_statisticsXray?.Close();
|
||||||
_statisticsSingbox?.Close();
|
_statisticsSingbox?.Close();
|
||||||
}
|
}
|
||||||
@@ -67,6 +65,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task CloneServerStatItem(string indexId, string toIndexId)
|
||||||
|
{
|
||||||
|
if (_lstServerStat == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var stat = _lstServerStat.FirstOrDefault(t => t.IndexId == indexId);
|
||||||
|
if (stat == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var toStat = JsonUtils.DeepCopy(stat);
|
||||||
|
toStat.IndexId = toIndexId;
|
||||||
|
await SQLiteHelper.Instance.ReplaceAsync(toStat);
|
||||||
|
_lstServerStat.Add(toStat);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task InitData()
|
private async Task InitData()
|
||||||
{
|
{
|
||||||
await SQLiteHelper.Instance.ExecuteAsync($"delete from ServerStatItem where indexId not in ( select indexId from ProfileItem )");
|
await SQLiteHelper.Instance.ExecuteAsync($"delete from ServerStatItem where indexId not in ( select indexId from ProfileItem )");
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
/*
|
/*
|
||||||
* 仅测试了,MacOS 13.7.1 x86 版本,其他版本有待确认
|
* 仅测试了,MacOS 13.7.1 x86 版本,其他版本有待确认
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 应用接口类型
|
/// 应用接口类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -21,14 +22,12 @@
|
|||||||
await ExecCmd(lstCmd);
|
await ExecCmd(lstCmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static async Task UnsetProxy()
|
public static async Task UnsetProxy()
|
||||||
{
|
{
|
||||||
var lstCmd = GetUnsetCmds();
|
var lstCmd = GetUnsetCmds();
|
||||||
await ExecCmd(lstCmd);
|
await ExecCmd(lstCmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static async Task ExecCmd(List<CmdItem> lstCmd)
|
private static async Task ExecCmd(List<CmdItem> lstCmd)
|
||||||
{
|
{
|
||||||
foreach (var cmd in lstCmd)
|
foreach (var cmd in lstCmd)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
case ECoreType.Xray when RunningCoreType is ECoreType.Xray or ECoreType.v2fly or ECoreType.v2fly_v5:
|
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:
|
case ECoreType.sing_box when RunningCoreType is ECoreType.sing_box or ECoreType.mihomo:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
public bool IgnoreGeoUpdateCore { get; set; } = true;
|
public bool IgnoreGeoUpdateCore { get; set; } = true;
|
||||||
|
|
||||||
public int AutoUpdateInterval { get; set; }
|
public int AutoUpdateInterval { get; set; }
|
||||||
|
|
||||||
public bool EnableSecurityProtocolTls13 { get; set; }
|
public bool EnableSecurityProtocolTls13 { get; set; }
|
||||||
|
|
||||||
public int TrayMenuServersLimit { get; set; } = 20;
|
public int TrayMenuServersLimit { get; set; } = 20;
|
||||||
@@ -116,6 +116,7 @@
|
|||||||
public bool EnableDragDropSort { get; set; }
|
public bool EnableDragDropSort { get; set; }
|
||||||
public bool DoubleClick2Activate { get; set; }
|
public bool DoubleClick2Activate { get; set; }
|
||||||
public bool AutoHideStartup { get; set; }
|
public bool AutoHideStartup { get; set; }
|
||||||
|
public bool Hide2TrayWhenClose { get; set; }
|
||||||
public List<ColumnItem> MainColumnItem { get; set; }
|
public List<ColumnItem> MainColumnItem { get; set; }
|
||||||
public bool ShowInTaskbar { get; set; }
|
public bool ShowInTaskbar { get; set; }
|
||||||
}
|
}
|
||||||
@@ -179,7 +180,6 @@
|
|||||||
public string DomainStrategy4Singbox { get; set; }
|
public string DomainStrategy4Singbox { get; set; }
|
||||||
public string DomainMatcher { get; set; }
|
public string DomainMatcher { get; set; }
|
||||||
public string RoutingIndexId { get; set; }
|
public string RoutingIndexId { get; set; }
|
||||||
public bool EnableRoutingAdvanced { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|||||||
13
v2rayN/ServiceLib/Models/IPAPIInfo.cs
Normal file
13
v2rayN/ServiceLib/Models/IPAPIInfo.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace ServiceLib.Models
|
||||||
|
{
|
||||||
|
internal class IPAPIInfo
|
||||||
|
{
|
||||||
|
public string? ip { get; set; }
|
||||||
|
public string? city { get; set; }
|
||||||
|
public string? region { get; set; }
|
||||||
|
public string? region_code { get; set; }
|
||||||
|
public string? country { get; set; }
|
||||||
|
public string? country_name { get; set; }
|
||||||
|
public string? country_code { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
29
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
29
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
@@ -1365,24 +1365,6 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Basic Function 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string menuRoutingBasic {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("menuRoutingBasic", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Import Basic Rules 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string menuRoutingBasicImportRules {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("menuRoutingBasicImportRules", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 RoutingRuleDetailsSetting 的本地化字符串。
|
/// 查找类似 RoutingRuleDetailsSetting 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3103,6 +3085,15 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Hide to tray when closing the window 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsHide2TrayWhenClose {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsHide2TrayWhenClose", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 HTTP Port 的本地化字符串。
|
/// 查找类似 HTTP Port 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3635,7 +3626,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 The ping of current service: {0} ms 的本地化字符串。
|
/// 查找类似 The delay : {0} ms, {1} 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TestMeOutput {
|
public static string TestMeOutput {
|
||||||
get {
|
get {
|
||||||
|
|||||||
@@ -302,7 +302,7 @@
|
|||||||
<value>اسکن URL وارد کردن با موفقیت</value>
|
<value>اسکن URL وارد کردن با موفقیت</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestMeOutput" xml:space="preserve">
|
<data name="TestMeOutput" xml:space="preserve">
|
||||||
<value>پینگ سرویس فعلی: {0} ms</value>
|
<value>پینگ سرویس فعلی: {0} ms, {1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationSuccess" xml:space="preserve">
|
<data name="OperationSuccess" xml:space="preserve">
|
||||||
<value>موفقیت عملیات</value>
|
<value>موفقیت عملیات</value>
|
||||||
@@ -847,12 +847,6 @@
|
|||||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||||
<value>Set as active rule</value>
|
<value>Set as active rule</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingBasic" xml:space="preserve">
|
|
||||||
<value>عملکرد پایه</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingBasicImportRules" xml:space="preserve">
|
|
||||||
<value>واردات قوانین اساسی</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbdomainMatcher" xml:space="preserve">
|
<data name="TbdomainMatcher" xml:space="preserve">
|
||||||
<value>تطبیق دامنه</value>
|
<value>تطبیق دامنه</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1387,4 +1381,7 @@
|
|||||||
<data name="TransportExtraTip" xml:space="preserve">
|
<data name="TransportExtraTip" xml:space="preserve">
|
||||||
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
|
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
|
<value>Hide to tray when closing the window</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
<value>Scan import the shared link successfully</value>
|
<value>Scan import the shared link successfully</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestMeOutput" xml:space="preserve">
|
<data name="TestMeOutput" xml:space="preserve">
|
||||||
<value>The ping of current service: {0} ms</value>
|
<value>The delay : {0} ms, {1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationSuccess" xml:space="preserve">
|
<data name="OperationSuccess" xml:space="preserve">
|
||||||
<value>Operation success</value>
|
<value>Operation success</value>
|
||||||
@@ -850,12 +850,6 @@
|
|||||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||||
<value>Set as active rule(Enter)</value>
|
<value>Set as active rule(Enter)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingBasic" xml:space="preserve">
|
|
||||||
<value>Basic Function</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingBasicImportRules" xml:space="preserve">
|
|
||||||
<value>Import Basic Rules</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbdomainMatcher" xml:space="preserve">
|
<data name="TbdomainMatcher" xml:space="preserve">
|
||||||
<value>Domain Matcher</value>
|
<value>Domain Matcher</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1387,4 +1381,7 @@
|
|||||||
<data name="TransportExtraTip" xml:space="preserve">
|
<data name="TransportExtraTip" xml:space="preserve">
|
||||||
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
|
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
|
<value>Hide to tray when closing the window</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
<value>Сканирование URL-адреса импорта успешна.</value>
|
<value>Сканирование URL-адреса импорта успешна.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestMeOutput" xml:space="preserve">
|
<data name="TestMeOutput" xml:space="preserve">
|
||||||
<value>Задержка текущего сервера: {0} мс</value>
|
<value>Задержка текущего сервера: {0} мс, {1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationSuccess" xml:space="preserve">
|
<data name="OperationSuccess" xml:space="preserve">
|
||||||
<value>Операция успешна</value>
|
<value>Операция успешна</value>
|
||||||
@@ -856,12 +856,6 @@
|
|||||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||||
<value>Установить как активное правило</value>
|
<value>Установить как активное правило</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingBasic" xml:space="preserve">
|
|
||||||
<value>Основные функции</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingBasicImportRules" xml:space="preserve">
|
|
||||||
<value>Импорт основных правил</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbdomainMatcher" xml:space="preserve">
|
<data name="TbdomainMatcher" xml:space="preserve">
|
||||||
<value>Сопоставитель доменов</value>
|
<value>Сопоставитель доменов</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1387,4 +1381,7 @@
|
|||||||
<data name="TransportExtraTip" xml:space="preserve">
|
<data name="TransportExtraTip" xml:space="preserve">
|
||||||
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
|
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
|
<value>Hide to tray when closing the window</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
<value>扫描导入分享链接成功</value>
|
<value>扫描导入分享链接成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestMeOutput" xml:space="preserve">
|
<data name="TestMeOutput" xml:space="preserve">
|
||||||
<value>当前服务的真连接延迟: {0} ms</value>
|
<value>当前延迟: {0} ms,{1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationSuccess" xml:space="preserve">
|
<data name="OperationSuccess" xml:space="preserve">
|
||||||
<value>操作成功</value>
|
<value>操作成功</value>
|
||||||
@@ -850,12 +850,6 @@
|
|||||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||||
<value>设为活动规则 (Enter)</value>
|
<value>设为活动规则 (Enter)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingBasic" xml:space="preserve">
|
|
||||||
<value>基础功能</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingBasicImportRules" xml:space="preserve">
|
|
||||||
<value>一键导入基础规则</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbdomainMatcher" xml:space="preserve">
|
<data name="TbdomainMatcher" xml:space="preserve">
|
||||||
<value>域名匹配算法</value>
|
<value>域名匹配算法</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1370,7 +1364,7 @@
|
|||||||
<value>Linux系统的sudo密码</value>
|
<value>Linux系统的sudo密码</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
<value>密码已加密且只存储在本地文件中,无密码无法开启Tun</value>
|
<value>密码已加密且只存储在本地文件中,无密码则每次都要输入</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
<value>请先在Tun模式设置中设置sudo密码</value>
|
<value>请先在Tun模式设置中设置sudo密码</value>
|
||||||
@@ -1384,4 +1378,7 @@
|
|||||||
<data name="TransportExtraTip" xml:space="preserve">
|
<data name="TransportExtraTip" xml:space="preserve">
|
||||||
<value>XHTTP Extra 原始 JSON,格式: { XHTTPObject }</value>
|
<value>XHTTP Extra 原始 JSON,格式: { XHTTPObject }</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
|
<value>关闭窗口时隐藏至托盘</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
<value>設定格式不正確</value>
|
<value>設定格式不正確</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CustomServerTips" xml:space="preserve">
|
<data name="CustomServerTips" xml:space="preserve">
|
||||||
<value>注意,自訂設定完全依賴您自己的設定,不能使用所有設定功能。如需使用系統代理請手動修改監聽埠。</value>
|
<value>注意,自訂設定完全依賴您自己的設定,不能使用所有設定功能。如需使用系統代理請手動修改偵聽埠。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Downloading" xml:space="preserve">
|
<data name="Downloading" xml:space="preserve">
|
||||||
<value>下載開始...</value>
|
<value>下載開始...</value>
|
||||||
@@ -157,7 +157,7 @@
|
|||||||
<value>請填寫正確格式伺服器埠</value>
|
<value>請填寫正確格式伺服器埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FillLocalListeningPort" xml:space="preserve">
|
<data name="FillLocalListeningPort" xml:space="preserve">
|
||||||
<value>請填寫本機監聽埠</value>
|
<value>請填寫本機偵聽埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FillPassword" xml:space="preserve">
|
<data name="FillPassword" xml:space="preserve">
|
||||||
<value>請填寫密碼</value>
|
<value>請填寫密碼</value>
|
||||||
@@ -301,7 +301,7 @@
|
|||||||
<value>掃描匯入分享链接成功</value>
|
<value>掃描匯入分享链接成功</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TestMeOutput" xml:space="preserve">
|
<data name="TestMeOutput" xml:space="preserve">
|
||||||
<value>目前服務的真連線延遲: {0} ms</value>
|
<value>目前延遲: {0} ms,{1}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OperationSuccess" xml:space="preserve">
|
<data name="OperationSuccess" xml:space="preserve">
|
||||||
<value>操作成功</value>
|
<value>操作成功</value>
|
||||||
@@ -722,7 +722,7 @@
|
|||||||
<value>例外. 對於下列字元開頭的位址不使用代理設定檔:使用分號(;)分隔</value>
|
<value>例外. 對於下列字元開頭的位址不使用代理設定檔:使用分號(;)分隔</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsHttpPort" xml:space="preserve">
|
<data name="TbSettingsHttpPort" xml:space="preserve">
|
||||||
<value>本機HTTP監聽埠</value>
|
<value>本機HTTP偵聽埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
|
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
|
||||||
<value>更新Core時忽略Geo檔案</value>
|
<value>更新Core時忽略Geo檔案</value>
|
||||||
@@ -755,7 +755,7 @@
|
|||||||
<value>開啟流量探測</value>
|
<value>開啟流量探測</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSocksPort" xml:space="preserve">
|
<data name="TbSettingsSocksPort" xml:space="preserve">
|
||||||
<value>本機SOCKS監聽埠</value>
|
<value>本機SOCKS偵聽埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStartBoot" xml:space="preserve">
|
<data name="TbSettingsStartBoot" xml:space="preserve">
|
||||||
<value>開機啟動(可能會不成功)</value>
|
<value>開機啟動(可能會不成功)</value>
|
||||||
@@ -850,12 +850,6 @@
|
|||||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||||
<value>設為活動規則 (Enter)</value>
|
<value>設為活動規則 (Enter)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuRoutingBasic" xml:space="preserve">
|
|
||||||
<value>基礎功能</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuRoutingBasicImportRules" xml:space="preserve">
|
|
||||||
<value>一鍵匯入基礎規則</value>
|
|
||||||
</data>
|
|
||||||
<data name="TbdomainMatcher" xml:space="preserve">
|
<data name="TbdomainMatcher" xml:space="preserve">
|
||||||
<value>域名匹配演算法</value>
|
<value>域名匹配演算法</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -998,7 +992,7 @@
|
|||||||
<value>複製字型TTF/TTC檔案到目錄guiFonts,重啟設定</value>
|
<value>複製字型TTF/TTC檔案到目錄guiFonts,重啟設定</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||||
<value>http端口= +1;Pac端口= +4;*ray API端口= +5;mihomo API端口= +6;</value>
|
<value>http連接埠= +1;Pac連接埠= +4;*ray API連接埠= +5;mihomo API連接埠= +6;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsStartBootTip" xml:space="preserve">
|
<data name="TbSettingsStartBootTip" xml:space="preserve">
|
||||||
<value>以管理員權限設定此項,在啟動後獲得管理員權限</value>
|
<value>以管理員權限設定此項,在啟動後獲得管理員權限</value>
|
||||||
@@ -1094,7 +1088,7 @@
|
|||||||
<value>請確保別名存在並且唯一</value>
|
<value>請確保別名存在並且唯一</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
||||||
<value>啟用額外監聽端口</value>
|
<value>啟用額外偵聽連接埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||||
<value>啟用IPv6</value>
|
<value>啟用IPv6</value>
|
||||||
@@ -1154,7 +1148,7 @@
|
|||||||
<value>您目前運行的是獨立包,請手動下載 SelfContained.7z檔案解壓縮覆蓋!</value>
|
<value>您目前運行的是獨立包,請手動下載 SelfContained.7z檔案解壓縮覆蓋!</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||||
<value>自訂設定的Socks端口</value>
|
<value>自訂設定的Socks連接埠</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="menuBackupAndRestore" xml:space="preserve">
|
<data name="menuBackupAndRestore" xml:space="preserve">
|
||||||
<value>備份和還原</value>
|
<value>備份和還原</value>
|
||||||
@@ -1370,7 +1364,7 @@
|
|||||||
<value>Linux系統的sudo密碼</value>
|
<value>Linux系統的sudo密碼</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||||
<value>密碼已加密且只儲存在本機檔案中,無密碼無法開啟Tun</value>
|
<value>密碼已加密且只儲存在本機檔案中,無密碼則每次都要輸入</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||||
<value>請先在Tun模式設定中設定sudo密碼</value>
|
<value>請先在Tun模式設定中設定sudo密碼</value>
|
||||||
@@ -1384,4 +1378,7 @@
|
|||||||
<data name="TransportExtraTip" xml:space="preserve">
|
<data name="TransportExtraTip" xml:space="preserve">
|
||||||
<value>XHTTP Extra 原始 JSON,格式: { XHTTPObject }</value>
|
<value>XHTTP Extra 原始 JSON,格式: { XHTTPObject }</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||||
|
<value>關閉視窗時隱藏至托盤</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -4,11 +4,11 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Version>7.1.1</Version>
|
<Version>7.2.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Downloader" Version="3.2.1" />
|
<PackageReference Include="Downloader" Version="3.3.0" />
|
||||||
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
||||||
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||||
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
|
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
|
||||||
@@ -49,7 +49,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\PacLib\PacLib.csproj" />
|
<ProjectReference Include="..\PacLib\PacLib.csproj" />
|
||||||
<ProjectReference Include="..\ProtosLib\ProtosLib.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
string result = Utils.GetEmbedText(Global.SingboxSampleClient);
|
var result = Utils.GetEmbedText(Global.SingboxSampleClient);
|
||||||
string txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||||
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
@@ -119,10 +119,10 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
await GenLog(singboxConfig);
|
await GenLog(singboxConfig);
|
||||||
//GenDns(new(), singboxConfig);
|
//GenDns(new(), singboxConfig);
|
||||||
singboxConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts.
|
singboxConfig.inbounds.Clear();
|
||||||
singboxConfig.outbounds.RemoveAt(0);
|
singboxConfig.outbounds.RemoveAt(0);
|
||||||
|
|
||||||
int httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
||||||
|
|
||||||
foreach (var it in selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
@@ -499,13 +499,10 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
inbound.sniff_override_destination = _config.Inbound[0].RouteOnly ? false : _config.Inbound[0].SniffingEnabled;
|
inbound.sniff_override_destination = _config.Inbound[0].RouteOnly ? false : _config.Inbound[0].SniffingEnabled;
|
||||||
inbound.domain_strategy = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainStrategy4Singbox) ? null : _config.RoutingBasicItem.DomainStrategy4Singbox;
|
inbound.domain_strategy = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainStrategy4Singbox) ? null : _config.RoutingBasicItem.DomainStrategy4Singbox;
|
||||||
|
|
||||||
if (_config.RoutingBasicItem.EnableRoutingAdvanced)
|
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||||
|
if (Utils.IsNotEmpty(routing.DomainStrategy4Singbox))
|
||||||
{
|
{
|
||||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
inbound.domain_strategy = routing.DomainStrategy4Singbox;
|
||||||
if (Utils.IsNotEmpty(routing.DomainStrategy4Singbox))
|
|
||||||
{
|
|
||||||
inbound.domain_strategy = routing.DomainStrategy4Singbox;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//http
|
//http
|
||||||
@@ -958,28 +955,13 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_config.RoutingBasicItem.EnableRoutingAdvanced)
|
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||||
|
if (routing != null)
|
||||||
{
|
{
|
||||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
||||||
if (routing != null)
|
foreach (var item in rules ?? [])
|
||||||
{
|
{
|
||||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
if (item.Enabled)
|
||||||
foreach (var item in rules ?? [])
|
|
||||||
{
|
|
||||||
if (item.Enabled)
|
|
||||||
{
|
|
||||||
await GenRoutingUserRule(item, singboxConfig.route.rules);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var lockedItem = await ConfigHandler.GetLockedRoutingItem(_config);
|
|
||||||
if (lockedItem != null)
|
|
||||||
{
|
|
||||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(lockedItem.RuleSet);
|
|
||||||
foreach (var item in rules ?? [])
|
|
||||||
{
|
{
|
||||||
await GenRoutingUserRule(item, singboxConfig.route.rules);
|
await GenRoutingUserRule(item, singboxConfig.route.rules);
|
||||||
}
|
}
|
||||||
@@ -1334,20 +1316,18 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
//load custom ruleset file
|
//load custom ruleset file
|
||||||
List<Ruleset4Sbox> customRulesets = [];
|
List<Ruleset4Sbox> customRulesets = [];
|
||||||
if (_config.RoutingBasicItem.EnableRoutingAdvanced)
|
|
||||||
|
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||||
|
if (Utils.IsNotEmpty(routing.CustomRulesetPath4Singbox))
|
||||||
{
|
{
|
||||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
var result = Utils.LoadResource(routing.CustomRulesetPath4Singbox);
|
||||||
if (Utils.IsNotEmpty(routing.CustomRulesetPath4Singbox))
|
if (Utils.IsNotEmpty(result))
|
||||||
{
|
{
|
||||||
var result = Utils.LoadResource(routing.CustomRulesetPath4Singbox);
|
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
|
||||||
if (Utils.IsNotEmpty(result))
|
.Where(t => t.tag != null)
|
||||||
{
|
.Where(t => t.type != null)
|
||||||
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
|
.Where(t => t.format != null)
|
||||||
.Where(t => t.tag != null)
|
.ToList();
|
||||||
.Where(t => t.type != null)
|
|
||||||
.Where(t => t.format != null)
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -216,8 +216,8 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
ret.Msg = ResUI.InitialConfiguration;
|
ret.Msg = ResUI.InitialConfiguration;
|
||||||
|
|
||||||
string result = Utils.GetEmbedText(Global.V2raySampleClient);
|
var result = Utils.GetEmbedText(Global.V2raySampleClient);
|
||||||
string txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
||||||
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
@@ -244,10 +244,11 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
await GenLog(v2rayConfig);
|
await GenLog(v2rayConfig);
|
||||||
v2rayConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts.
|
v2rayConfig.inbounds.Clear();
|
||||||
v2rayConfig.outbounds.RemoveAt(0);
|
v2rayConfig.outbounds.Clear();
|
||||||
|
v2rayConfig.routing.rules.Clear();
|
||||||
|
|
||||||
int httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
||||||
|
|
||||||
foreach (var it in selecteds)
|
foreach (var it in selecteds)
|
||||||
{
|
{
|
||||||
@@ -270,7 +271,7 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
|
|
||||||
//find unused port
|
//find unused port
|
||||||
var port = httpPort;
|
var port = httpPort;
|
||||||
for (int k = httpPort; k < Global.MaxPort; k++)
|
for (var k = httpPort; k < Global.MaxPort; k++)
|
||||||
{
|
{
|
||||||
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
|
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
|
||||||
{
|
{
|
||||||
@@ -294,16 +295,6 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
it.Port = port;
|
it.Port = port;
|
||||||
it.AllowTest = true;
|
it.AllowTest = true;
|
||||||
|
|
||||||
//inbound
|
|
||||||
Inbounds4Ray inbound = new()
|
|
||||||
{
|
|
||||||
listen = Global.Loopback,
|
|
||||||
port = port,
|
|
||||||
protocol = EInboundProtocol.http.ToString(),
|
|
||||||
};
|
|
||||||
inbound.tag = inbound.protocol + inbound.port.ToString();
|
|
||||||
v2rayConfig.inbounds.Add(inbound);
|
|
||||||
|
|
||||||
//outbound
|
//outbound
|
||||||
if (item is null)
|
if (item is null)
|
||||||
{
|
{
|
||||||
@@ -326,6 +317,16 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//inbound
|
||||||
|
Inbounds4Ray inbound = new()
|
||||||
|
{
|
||||||
|
listen = Global.Loopback,
|
||||||
|
port = port,
|
||||||
|
protocol = EInboundProtocol.http.ToString(),
|
||||||
|
};
|
||||||
|
inbound.tag = inbound.protocol + inbound.port.ToString();
|
||||||
|
v2rayConfig.inbounds.Add(inbound);
|
||||||
|
|
||||||
var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
||||||
await GenOutbound(item, outbound);
|
await GenOutbound(item, outbound);
|
||||||
outbound.tag = Global.ProxyTag + inbound.port.ToString();
|
outbound.tag = Global.ProxyTag + inbound.port.ToString();
|
||||||
@@ -466,33 +467,17 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
v2rayConfig.routing.domainStrategy = _config.RoutingBasicItem.DomainStrategy;
|
v2rayConfig.routing.domainStrategy = _config.RoutingBasicItem.DomainStrategy;
|
||||||
v2rayConfig.routing.domainMatcher = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainMatcher) ? null : _config.RoutingBasicItem.DomainMatcher;
|
v2rayConfig.routing.domainMatcher = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainMatcher) ? null : _config.RoutingBasicItem.DomainMatcher;
|
||||||
|
|
||||||
if (_config.RoutingBasicItem.EnableRoutingAdvanced)
|
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||||
|
if (routing != null)
|
||||||
{
|
{
|
||||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
if (Utils.IsNotEmpty(routing.DomainStrategy))
|
||||||
if (routing != null)
|
|
||||||
{
|
{
|
||||||
if (Utils.IsNotEmpty(routing.DomainStrategy))
|
v2rayConfig.routing.domainStrategy = routing.DomainStrategy;
|
||||||
{
|
|
||||||
v2rayConfig.routing.domainStrategy = routing.DomainStrategy;
|
|
||||||
}
|
|
||||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
|
||||||
foreach (var item in rules)
|
|
||||||
{
|
|
||||||
if (item.Enabled)
|
|
||||||
{
|
|
||||||
var item2 = JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item));
|
|
||||||
await GenRoutingUserRule(item2, v2rayConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
||||||
else
|
foreach (var item in rules)
|
||||||
{
|
|
||||||
var lockedItem = await ConfigHandler.GetLockedRoutingItem(_config);
|
|
||||||
if (lockedItem != null)
|
|
||||||
{
|
{
|
||||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(lockedItem.RuleSet);
|
if (item.Enabled)
|
||||||
foreach (var item in rules)
|
|
||||||
{
|
{
|
||||||
var item2 = JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item));
|
var item2 = JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item));
|
||||||
await GenRoutingUserRule(item2, v2rayConfig);
|
await GenRoutingUserRule(item2, v2rayConfig);
|
||||||
@@ -1024,18 +1009,17 @@ namespace ServiceLib.Services.CoreConfig
|
|||||||
//request Host
|
//request Host
|
||||||
string request = Utils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
|
string request = Utils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
|
||||||
string[] arrHost = host.Split(',');
|
string[] arrHost = host.Split(',');
|
||||||
string host2 = string.Join("\",\"", arrHost);
|
string host2 = string.Join(",".AppendQuotes(), arrHost);
|
||||||
request = request.Replace("$requestHost$", $"\"{host2}\"");
|
request = request.Replace("$requestHost$", $"{host2.AppendQuotes()}");
|
||||||
//request = request.Replace("$requestHost$", string.Format("\"{0}\"", config.requestHost()));
|
request = request.Replace("$requestUserAgent$", $"{useragent.AppendQuotes()}");
|
||||||
request = request.Replace("$requestUserAgent$", $"\"{useragent}\"");
|
|
||||||
//Path
|
//Path
|
||||||
string pathHttp = @"/";
|
string pathHttp = @"/";
|
||||||
if (Utils.IsNotEmpty(node.Path))
|
if (Utils.IsNotEmpty(node.Path))
|
||||||
{
|
{
|
||||||
string[] arrPath = node.Path.Split(',');
|
string[] arrPath = node.Path.Split(',');
|
||||||
pathHttp = string.Join("\",\"", arrPath);
|
pathHttp = string.Join(",".AppendQuotes(), arrPath);
|
||||||
}
|
}
|
||||||
request = request.Replace("$requestPath$", $"\"{pathHttp}\"");
|
request = request.Replace("$requestPath$", $"{pathHttp.AppendQuotes()}");
|
||||||
tcpSettings.header.request = JsonUtils.Deserialize<object>(request);
|
tcpSettings.header.request = JsonUtils.Deserialize<object>(request);
|
||||||
|
|
||||||
streamSettings.tcpSettings = tcpSettings;
|
streamSettings.tcpSettings = tcpSettings;
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
using Grpc.Core;
|
|
||||||
using Grpc.Net.Client;
|
|
||||||
using ProtosLib.Statistics;
|
|
||||||
|
|
||||||
namespace ServiceLib.Services.Statistics
|
|
||||||
{
|
|
||||||
public class StatisticsV2rayService
|
|
||||||
{
|
|
||||||
private Models.Config _config;
|
|
||||||
private GrpcChannel? _channel;
|
|
||||||
private StatsService.StatsServiceClient? _client;
|
|
||||||
private bool _exitFlag;
|
|
||||||
private Action<ServerSpeedItem>? _updateFunc;
|
|
||||||
|
|
||||||
public StatisticsV2rayService(Models.Config config, Action<ServerSpeedItem> updateFunc)
|
|
||||||
{
|
|
||||||
_config = config;
|
|
||||||
_updateFunc = updateFunc;
|
|
||||||
_exitFlag = false;
|
|
||||||
|
|
||||||
GrpcInit();
|
|
||||||
|
|
||||||
Task.Run(Run);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GrpcInit()
|
|
||||||
{
|
|
||||||
if (_channel is null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_channel = GrpcChannel.ForAddress($"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort}");
|
|
||||||
_client = new StatsService.StatsServiceClient(_channel);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog(ex.Message, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Close()
|
|
||||||
{
|
|
||||||
_exitFlag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Run()
|
|
||||||
{
|
|
||||||
while (!_exitFlag)
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!_config.IsRunningCore(ECoreType.Xray))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_channel?.State == ConnectivityState.Ready)
|
|
||||||
{
|
|
||||||
QueryStatsResponse? res = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_client != null)
|
|
||||||
res = await _client.QueryStatsAsync(new QueryStatsRequest() { Pattern = "", Reset = true });
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res != null)
|
|
||||||
{
|
|
||||||
ParseOutput(res.Stat, out ServerSpeedItem server);
|
|
||||||
_updateFunc?.Invoke(server);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_channel != null)
|
|
||||||
await _channel.ConnectAsync();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ParseOutput(Google.Protobuf.Collections.RepeatedField<Stat> source, out ServerSpeedItem server)
|
|
||||||
{
|
|
||||||
server = new();
|
|
||||||
long aggregateProxyUp = 0;
|
|
||||||
long aggregateProxyDown = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (Stat stat in source)
|
|
||||||
{
|
|
||||||
string name = stat.Name;
|
|
||||||
long value = stat.Value / 1024; //KByte
|
|
||||||
string[] nStr = name.Split(">>>".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
string type = "";
|
|
||||||
|
|
||||||
name = name.Trim();
|
|
||||||
|
|
||||||
name = nStr[1];
|
|
||||||
type = nStr[3];
|
|
||||||
|
|
||||||
if (name.StartsWith(Global.ProxyTag))
|
|
||||||
{
|
|
||||||
if (type == "uplink")
|
|
||||||
{
|
|
||||||
aggregateProxyUp += value;
|
|
||||||
}
|
|
||||||
else if (type == "downlink")
|
|
||||||
{
|
|
||||||
aggregateProxyDown += value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (name == Global.DirectTag)
|
|
||||||
{
|
|
||||||
if (type == "uplink")
|
|
||||||
{
|
|
||||||
server.DirectUp = value;
|
|
||||||
}
|
|
||||||
else if (type == "downlink")
|
|
||||||
{
|
|
||||||
server.DirectDown = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
server.ProxyUp = aggregateProxyUp;
|
|
||||||
server.ProxyDown = aggregateProxyDown;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -244,8 +244,17 @@ namespace ServiceLib.Services
|
|||||||
|
|
||||||
public async Task RunAvailabilityCheck(Action<bool, string> updateFunc)
|
public async Task RunAvailabilityCheck(Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
var time = await new DownloadService().RunAvailabilityCheck(null);
|
var downloadHandle = new DownloadService();
|
||||||
updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time));
|
var time = await downloadHandle.RunAvailabilityCheck(null);
|
||||||
|
var ip = Global.None;
|
||||||
|
if (time > 0)
|
||||||
|
{
|
||||||
|
var result = await downloadHandle.TryDownloadString(Global.IPAPIUrl, true, "ipapi");
|
||||||
|
var ipInfo = JsonUtils.Deserialize<IPAPIInfo>(result);
|
||||||
|
ip = $"({ipInfo?.country}) {ipInfo?.ip}";
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time, ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
#region CheckUpdate private
|
#region CheckUpdate private
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ namespace ServiceLib.ViewModels
|
|||||||
var filesList = (new DirectoryInfo(toPath)).GetFiles().Select(u => u.FullName).ToList();
|
var filesList = (new DirectoryInfo(toPath)).GetFiles().Select(u => u.FullName).ToList();
|
||||||
foreach (var file in filesList)
|
foreach (var file in filesList)
|
||||||
{
|
{
|
||||||
await Utils.SetLinuxChmod(Path.Combine(toPath, item.CoreType));
|
await Utils.SetLinuxChmod(Path.Combine(toPath, item.CoreType.ToLower()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -324,6 +324,7 @@ namespace ServiceLib.ViewModels
|
|||||||
if (process.Id > 0)
|
if (process.Id > 0)
|
||||||
{
|
{
|
||||||
await MyAppExitAsync(false);
|
await MyAppExitAsync(false);
|
||||||
|
await MyAppExitAsync(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ namespace ServiceLib.ViewModels
|
|||||||
[Reactive] public bool EnableUpdateSubOnlyRemarksExist { get; set; }
|
[Reactive] public bool EnableUpdateSubOnlyRemarksExist { get; set; }
|
||||||
[Reactive] public bool EnableSecurityProtocolTls13 { get; set; }
|
[Reactive] public bool EnableSecurityProtocolTls13 { get; set; }
|
||||||
[Reactive] public bool AutoHideStartup { get; set; }
|
[Reactive] public bool AutoHideStartup { get; set; }
|
||||||
|
[Reactive] public bool Hide2TrayWhenClose { get; set; }
|
||||||
[Reactive] public bool EnableDragDropSort { get; set; }
|
[Reactive] public bool EnableDragDropSort { get; set; }
|
||||||
[Reactive] public bool DoubleClick2Activate { get; set; }
|
[Reactive] public bool DoubleClick2Activate { get; set; }
|
||||||
[Reactive] public int AutoUpdateInterval { get; set; }
|
[Reactive] public int AutoUpdateInterval { get; set; }
|
||||||
@@ -166,6 +167,7 @@ namespace ServiceLib.ViewModels
|
|||||||
EnableUpdateSubOnlyRemarksExist = _config.UiItem.EnableUpdateSubOnlyRemarksExist;
|
EnableUpdateSubOnlyRemarksExist = _config.UiItem.EnableUpdateSubOnlyRemarksExist;
|
||||||
EnableSecurityProtocolTls13 = _config.GuiItem.EnableSecurityProtocolTls13;
|
EnableSecurityProtocolTls13 = _config.GuiItem.EnableSecurityProtocolTls13;
|
||||||
AutoHideStartup = _config.UiItem.AutoHideStartup;
|
AutoHideStartup = _config.UiItem.AutoHideStartup;
|
||||||
|
Hide2TrayWhenClose = _config.UiItem.Hide2TrayWhenClose;
|
||||||
EnableDragDropSort = _config.UiItem.EnableDragDropSort;
|
EnableDragDropSort = _config.UiItem.EnableDragDropSort;
|
||||||
DoubleClick2Activate = _config.UiItem.DoubleClick2Activate;
|
DoubleClick2Activate = _config.UiItem.DoubleClick2Activate;
|
||||||
AutoUpdateInterval = _config.GuiItem.AutoUpdateInterval;
|
AutoUpdateInterval = _config.GuiItem.AutoUpdateInterval;
|
||||||
@@ -316,6 +318,7 @@ namespace ServiceLib.ViewModels
|
|||||||
_config.UiItem.EnableUpdateSubOnlyRemarksExist = EnableUpdateSubOnlyRemarksExist;
|
_config.UiItem.EnableUpdateSubOnlyRemarksExist = EnableUpdateSubOnlyRemarksExist;
|
||||||
_config.GuiItem.EnableSecurityProtocolTls13 = EnableSecurityProtocolTls13;
|
_config.GuiItem.EnableSecurityProtocolTls13 = EnableSecurityProtocolTls13;
|
||||||
_config.UiItem.AutoHideStartup = AutoHideStartup;
|
_config.UiItem.AutoHideStartup = AutoHideStartup;
|
||||||
|
_config.UiItem.Hide2TrayWhenClose = Hide2TrayWhenClose;
|
||||||
_config.GuiItem.AutoUpdateInterval = AutoUpdateInterval;
|
_config.GuiItem.AutoUpdateInterval = AutoUpdateInterval;
|
||||||
_config.UiItem.EnableDragDropSort = EnableDragDropSort;
|
_config.UiItem.EnableDragDropSort = EnableDragDropSort;
|
||||||
_config.UiItem.DoubleClick2Activate = DoubleClick2Activate;
|
_config.UiItem.DoubleClick2Activate = DoubleClick2Activate;
|
||||||
|
|||||||
@@ -729,7 +729,7 @@ namespace ServiceLib.ViewModels
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(item, null);
|
var result = await CoreConfigHandler.GenerateClientConfig(item, fileName);
|
||||||
if (result.Success != true)
|
if (result.Success != true)
|
||||||
{
|
{
|
||||||
NoticeHandler.Instance.Enqueue(result.Msg);
|
NoticeHandler.Instance.Enqueue(result.Msg);
|
||||||
|
|||||||
@@ -7,9 +7,6 @@ namespace ServiceLib.ViewModels
|
|||||||
{
|
{
|
||||||
public class RoutingSettingViewModel : MyReactiveObject
|
public class RoutingSettingViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
private RoutingItem _lockedItem;
|
|
||||||
private List<RulesItem> _lockedRules;
|
|
||||||
|
|
||||||
#region Reactive
|
#region Reactive
|
||||||
|
|
||||||
private IObservableCollection<RoutingItemModel> _routingItems = new ObservableCollectionExtended<RoutingItemModel>();
|
private IObservableCollection<RoutingItemModel> _routingItems = new ObservableCollectionExtended<RoutingItemModel>();
|
||||||
@@ -20,12 +17,6 @@ namespace ServiceLib.ViewModels
|
|||||||
|
|
||||||
public IList<RoutingItemModel> SelectedSources { get; set; }
|
public IList<RoutingItemModel> SelectedSources { get; set; }
|
||||||
|
|
||||||
[Reactive]
|
|
||||||
public bool enableRoutingAdvanced { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
|
||||||
public bool enableRoutingBasic { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
[Reactive]
|
||||||
public string domainStrategy { get; set; }
|
public string domainStrategy { get; set; }
|
||||||
|
|
||||||
@@ -35,25 +26,6 @@ namespace ServiceLib.ViewModels
|
|||||||
[Reactive]
|
[Reactive]
|
||||||
public string domainStrategy4Singbox { get; set; }
|
public string domainStrategy4Singbox { get; set; }
|
||||||
|
|
||||||
[Reactive]
|
|
||||||
public string ProxyDomain { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
|
||||||
public string ProxyIP { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
|
||||||
public string DirectDomain { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
|
||||||
public string DirectIP { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
|
||||||
public string BlockDomain { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
|
||||||
public string BlockIP { get; set; }
|
|
||||||
|
|
||||||
public ReactiveCommand<Unit, Unit> RoutingBasicImportRulesCmd { get; }
|
|
||||||
public ReactiveCommand<Unit, Unit> RoutingAdvancedAddCmd { get; }
|
public ReactiveCommand<Unit, Unit> RoutingAdvancedAddCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> RoutingAdvancedRemoveCmd { get; }
|
public ReactiveCommand<Unit, Unit> RoutingAdvancedRemoveCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> RoutingAdvancedSetDefaultCmd { get; }
|
public ReactiveCommand<Unit, Unit> RoutingAdvancedSetDefaultCmd { get; }
|
||||||
@@ -73,15 +45,6 @@ namespace ServiceLib.ViewModels
|
|||||||
x => x.SelectedSource,
|
x => x.SelectedSource,
|
||||||
selectedSource => selectedSource != null && !selectedSource.Remarks.IsNullOrEmpty());
|
selectedSource => selectedSource != null && !selectedSource.Remarks.IsNullOrEmpty());
|
||||||
|
|
||||||
this.WhenAnyValue(
|
|
||||||
x => x.enableRoutingAdvanced)
|
|
||||||
.Subscribe(c => enableRoutingBasic = !enableRoutingAdvanced);
|
|
||||||
|
|
||||||
RoutingBasicImportRulesCmd = ReactiveCommand.CreateFromTask(async () =>
|
|
||||||
{
|
|
||||||
await RoutingBasicImportRules();
|
|
||||||
});
|
|
||||||
|
|
||||||
RoutingAdvancedAddCmd = ReactiveCommand.CreateFromTask(async () =>
|
RoutingAdvancedAddCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||||
{
|
{
|
||||||
await RoutingAdvancedEditAsync(true);
|
await RoutingAdvancedEditAsync(true);
|
||||||
@@ -111,67 +74,14 @@ namespace ServiceLib.ViewModels
|
|||||||
{
|
{
|
||||||
SelectedSource = new();
|
SelectedSource = new();
|
||||||
|
|
||||||
enableRoutingAdvanced = true;//TODO _config.RoutingBasicItem.EnableRoutingAdvanced;
|
|
||||||
domainStrategy = _config.RoutingBasicItem.DomainStrategy;
|
domainStrategy = _config.RoutingBasicItem.DomainStrategy;
|
||||||
domainMatcher = _config.RoutingBasicItem.DomainMatcher;
|
domainMatcher = _config.RoutingBasicItem.DomainMatcher;
|
||||||
domainStrategy4Singbox = _config.RoutingBasicItem.DomainStrategy4Singbox;
|
domainStrategy4Singbox = _config.RoutingBasicItem.DomainStrategy4Singbox;
|
||||||
|
|
||||||
await ConfigHandler.InitBuiltinRouting(_config);
|
await ConfigHandler.InitBuiltinRouting(_config);
|
||||||
await RefreshRoutingItems();
|
await RefreshRoutingItems();
|
||||||
await BindingLockedData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region locked
|
|
||||||
|
|
||||||
private async Task BindingLockedData()
|
|
||||||
{
|
|
||||||
_lockedItem = await ConfigHandler.GetLockedRoutingItem(_config);
|
|
||||||
if (_lockedItem == null)
|
|
||||||
{
|
|
||||||
_lockedItem = new RoutingItem()
|
|
||||||
{
|
|
||||||
Remarks = "locked",
|
|
||||||
Url = string.Empty,
|
|
||||||
Locked = true,
|
|
||||||
};
|
|
||||||
await ConfigHandler.AddBatchRoutingRules(_lockedItem, Utils.GetEmbedText(Global.CustomRoutingFileName + "locked"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_lockedItem != null)
|
|
||||||
{
|
|
||||||
_lockedRules = JsonUtils.Deserialize<List<RulesItem>>(_lockedItem.RuleSet);
|
|
||||||
ProxyDomain = Utils.List2String(_lockedRules[0].Domain, true);
|
|
||||||
ProxyIP = Utils.List2String(_lockedRules[0].Ip, true);
|
|
||||||
|
|
||||||
DirectDomain = Utils.List2String(_lockedRules[1].Domain, true);
|
|
||||||
DirectIP = Utils.List2String(_lockedRules[1].Ip, true);
|
|
||||||
|
|
||||||
BlockDomain = Utils.List2String(_lockedRules[2].Domain, true);
|
|
||||||
BlockIP = Utils.List2String(_lockedRules[2].Ip, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task EndBindingLockedData()
|
|
||||||
{
|
|
||||||
if (_lockedItem != null)
|
|
||||||
{
|
|
||||||
_lockedRules[0].Domain = Utils.String2List(Utils.Convert2Comma(ProxyDomain.TrimEx()));
|
|
||||||
_lockedRules[0].Ip = Utils.String2List(Utils.Convert2Comma(ProxyIP.TrimEx()));
|
|
||||||
|
|
||||||
_lockedRules[1].Domain = Utils.String2List(Utils.Convert2Comma(DirectDomain.TrimEx()));
|
|
||||||
_lockedRules[1].Ip = Utils.String2List(Utils.Convert2Comma(DirectIP.TrimEx()));
|
|
||||||
|
|
||||||
_lockedRules[2].Domain = Utils.String2List(Utils.Convert2Comma(BlockDomain.TrimEx()));
|
|
||||||
_lockedRules[2].Ip = Utils.String2List(Utils.Convert2Comma(BlockIP.TrimEx()));
|
|
||||||
|
|
||||||
_lockedItem.RuleSet = JsonUtils.Serialize(_lockedRules, false);
|
|
||||||
|
|
||||||
await ConfigHandler.SaveRoutingItem(_config, _lockedItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion locked
|
|
||||||
|
|
||||||
#region Refresh Save
|
#region Refresh Save
|
||||||
|
|
||||||
public async Task RefreshRoutingItems()
|
public async Task RefreshRoutingItems()
|
||||||
@@ -205,12 +115,9 @@ namespace ServiceLib.ViewModels
|
|||||||
private async Task SaveRoutingAsync()
|
private async Task SaveRoutingAsync()
|
||||||
{
|
{
|
||||||
_config.RoutingBasicItem.DomainStrategy = domainStrategy;
|
_config.RoutingBasicItem.DomainStrategy = domainStrategy;
|
||||||
_config.RoutingBasicItem.EnableRoutingAdvanced = enableRoutingAdvanced;
|
|
||||||
_config.RoutingBasicItem.DomainMatcher = domainMatcher;
|
_config.RoutingBasicItem.DomainMatcher = domainMatcher;
|
||||||
_config.RoutingBasicItem.DomainStrategy4Singbox = domainStrategy4Singbox;
|
_config.RoutingBasicItem.DomainStrategy4Singbox = domainStrategy4Singbox;
|
||||||
|
|
||||||
await EndBindingLockedData();
|
|
||||||
|
|
||||||
if (await ConfigHandler.SaveConfig(_config) == 0)
|
if (await ConfigHandler.SaveConfig(_config) == 0)
|
||||||
{
|
{
|
||||||
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
||||||
@@ -224,18 +131,6 @@ namespace ServiceLib.ViewModels
|
|||||||
|
|
||||||
#endregion Refresh Save
|
#endregion Refresh Save
|
||||||
|
|
||||||
private async Task RoutingBasicImportRules()
|
|
||||||
{
|
|
||||||
//Extra to bypass the mainland
|
|
||||||
ProxyDomain = "geosite:google";
|
|
||||||
DirectDomain = "geosite:cn";
|
|
||||||
DirectIP = "geoip:private,geoip:cn";
|
|
||||||
BlockDomain = "geosite:category-ads-all";
|
|
||||||
|
|
||||||
//NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
|
||||||
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RoutingAdvancedEditAsync(bool blNew)
|
public async Task RoutingAdvancedEditAsync(bool blNew)
|
||||||
{
|
{
|
||||||
RoutingItem item;
|
RoutingItem item;
|
||||||
|
|||||||
@@ -347,11 +347,6 @@ namespace ServiceLib.ViewModels
|
|||||||
public async Task RefreshRoutingsMenu()
|
public async Task RefreshRoutingsMenu()
|
||||||
{
|
{
|
||||||
_routingItems.Clear();
|
_routingItems.Clear();
|
||||||
if (!_config.RoutingBasicItem.EnableRoutingAdvanced)
|
|
||||||
{
|
|
||||||
BlRouting = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlRouting = true;
|
BlRouting = true;
|
||||||
var routings = await AppHandler.Instance.RoutingItems();
|
var routings = await AppHandler.Instance.RoutingItems();
|
||||||
@@ -416,16 +411,16 @@ namespace ServiceLib.ViewModels
|
|||||||
// When running as a non-administrator, reboot to administrator mode
|
// When running as a non-administrator, reboot to administrator mode
|
||||||
if (EnableTun && AllowEnableTun() == false)
|
if (EnableTun && AllowEnableTun() == false)
|
||||||
{
|
{
|
||||||
_config.TunModeItem.EnableTun = false;
|
|
||||||
if (Utils.IsWindows())
|
if (Utils.IsWindows())
|
||||||
{
|
{
|
||||||
|
_config.TunModeItem.EnableTun = false;
|
||||||
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
|
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (Utils.IsLinux())
|
//else if (Utils.IsLinux())
|
||||||
{
|
//{
|
||||||
NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty);
|
// NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty);
|
||||||
}
|
//}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
await ConfigHandler.SaveConfig(_config);
|
await ConfigHandler.SaveConfig(_config);
|
||||||
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
|
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
|
||||||
@@ -474,7 +469,7 @@ namespace ServiceLib.ViewModels
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
InboundLanDisplay = $"{ResUI.LabLAN}:None";
|
InboundLanDisplay = $"{ResUI.LabLAN}:{Global.None}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace v2rayN.Desktop.ViewModels
|
|||||||
public class ThemeSettingViewModel : MyReactiveObject
|
public class ThemeSettingViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
[Reactive] public bool ColorModeDark { get; set; }
|
[Reactive] public bool ColorModeDark { get; set; }
|
||||||
|
[Reactive] public bool FollowSystemTheme { get; set; }
|
||||||
|
|
||||||
[Reactive] public int CurrentFontSize { get; set; }
|
[Reactive] public int CurrentFontSize { get; set; }
|
||||||
|
|
||||||
@@ -28,13 +29,14 @@ namespace v2rayN.Desktop.ViewModels
|
|||||||
|
|
||||||
private void RestoreUI()
|
private void RestoreUI()
|
||||||
{
|
{
|
||||||
ModifyTheme(_config.UiItem.ColorModeDark);
|
ModifyTheme();
|
||||||
ModifyFontFamily();
|
ModifyFontFamily();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BindingUI()
|
private void BindingUI()
|
||||||
{
|
{
|
||||||
ColorModeDark = _config.UiItem.ColorModeDark;
|
ColorModeDark = _config.UiItem.ColorModeDark;
|
||||||
|
FollowSystemTheme = _config.UiItem.FollowSystemTheme;
|
||||||
CurrentFontSize = _config.UiItem.CurrentFontSize;
|
CurrentFontSize = _config.UiItem.CurrentFontSize;
|
||||||
CurrentLanguage = _config.UiItem.CurrentLanguage;
|
CurrentLanguage = _config.UiItem.CurrentLanguage;
|
||||||
|
|
||||||
@@ -44,7 +46,18 @@ namespace v2rayN.Desktop.ViewModels
|
|||||||
if (_config.UiItem.ColorModeDark != ColorModeDark)
|
if (_config.UiItem.ColorModeDark != ColorModeDark)
|
||||||
{
|
{
|
||||||
_config.UiItem.ColorModeDark = ColorModeDark;
|
_config.UiItem.ColorModeDark = ColorModeDark;
|
||||||
ModifyTheme(ColorModeDark);
|
ModifyTheme();
|
||||||
|
ConfigHandler.SaveConfig(_config);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.WhenAnyValue(x => x.FollowSystemTheme,
|
||||||
|
y => y == true)
|
||||||
|
.Subscribe(c =>
|
||||||
|
{
|
||||||
|
if (_config.UiItem.FollowSystemTheme != FollowSystemTheme)
|
||||||
|
{
|
||||||
|
_config.UiItem.FollowSystemTheme = FollowSystemTheme;
|
||||||
|
ModifyTheme();
|
||||||
ConfigHandler.SaveConfig(_config);
|
ConfigHandler.SaveConfig(_config);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -59,7 +72,6 @@ namespace v2rayN.Desktop.ViewModels
|
|||||||
_config.UiItem.CurrentFontSize = CurrentFontSize;
|
_config.UiItem.CurrentFontSize = CurrentFontSize;
|
||||||
double size = CurrentFontSize;
|
double size = CurrentFontSize;
|
||||||
ModifyFontSize(size);
|
ModifyFontSize(size);
|
||||||
|
|
||||||
ConfigHandler.SaveConfig(_config);
|
ConfigHandler.SaveConfig(_config);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -79,12 +91,12 @@ namespace v2rayN.Desktop.ViewModels
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ModifyTheme(bool isDarkTheme)
|
private void ModifyTheme()
|
||||||
{
|
{
|
||||||
var app = Application.Current;
|
var app = Application.Current;
|
||||||
if (app is not null)
|
if (app is not null)
|
||||||
{
|
{
|
||||||
app.RequestedThemeVariant = isDarkTheme ? ThemeVariant.Dark : ThemeVariant.Light;
|
app.RequestedThemeVariant = FollowSystemTheme ? ThemeVariant.Default : (ColorModeDark ? ThemeVariant.Dark : ThemeVariant.Light);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Path, v => v.txtPath.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Path, v => v.txtPath.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Extra, v => v.txtExtra.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Extra, v => v.txtExtra.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.StreamSecurity, v => v.cmbStreamSecurity.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.StreamSecurity, v => v.cmbStreamSecurity.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.SelectedValue).DisposeWith(disposables);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
<Border
|
<Border
|
||||||
Width="500"
|
Width="500"
|
||||||
Height="80"
|
Height="80"
|
||||||
Margin="0"
|
Margin="-2"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Theme="{StaticResource CardBorder}">
|
Theme="{StaticResource CardBorder}">
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|||||||
@@ -398,7 +398,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Utils.IsWindows())
|
if (_config.UiItem.Hide2TrayWhenClose)
|
||||||
{
|
{
|
||||||
this.Hide();
|
this.Hide();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -489,6 +489,18 @@
|
|||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Classes="Margin8" />
|
Classes="Margin8" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="9"
|
||||||
|
Grid.Column="0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Classes="Margin8"
|
||||||
|
Text="{x:Static resx:ResUI.TbSettingsHide2TrayWhenClose}" />
|
||||||
|
<ToggleSwitch
|
||||||
|
x:Name="togHide2TrayWhenClose"
|
||||||
|
Grid.Row="9"
|
||||||
|
Grid.Column="1"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Classes="Margin8" />
|
||||||
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
this.Bind(ViewModel, vm => vm.EnableUpdateSubOnlyRemarksExist, v => v.togEnableUpdateSubOnlyRemarksExist.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.EnableUpdateSubOnlyRemarksExist, v => v.togEnableUpdateSubOnlyRemarksExist.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.EnableSecurityProtocolTls13, v => v.togEnableSecurityProtocolTls13.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.EnableSecurityProtocolTls13, v => v.togEnableSecurityProtocolTls13.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.AutoHideStartup, v => v.togAutoHideStartup.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.AutoHideStartup, v => v.togAutoHideStartup.IsChecked).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.Hide2TrayWhenClose, v => v.togHide2TrayWhenClose.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DoubleClick2Activate, v => v.togDoubleClick2Activate.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.DoubleClick2Activate, v => v.togDoubleClick2Activate.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CurrentFontFamily, v => v.cmbcurrentFontFamily.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CurrentFontFamily, v => v.cmbcurrentFontFamily.SelectedValue).DisposeWith(disposables);
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
Width="54"
|
Width="54"
|
||||||
Height="30"
|
Height="30"
|
||||||
Margin="20,0"
|
Margin="20,0"
|
||||||
|
Padding="2"
|
||||||
Classes="Tertiary"
|
Classes="Tertiary"
|
||||||
Theme="{DynamicResource BorderlessSplitButton}"
|
Theme="{DynamicResource BorderlessSplitButton}"
|
||||||
ToolTip.Tip="{x:Static resx:ResUI.menuProfileAutofitColumnWidth}">
|
ToolTip.Tip="{x:Static resx:ResUI.menuProfileAutofitColumnWidth}">
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel);
|
item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel);
|
||||||
item2.DisplayIndex = displayIndex++;
|
item2.DisplayIndex = displayIndex++;
|
||||||
}
|
}
|
||||||
if (item.Name.StartsWith("to"))
|
if (item.Name.ToLower().StartsWith("to"))
|
||||||
{
|
{
|
||||||
if (!_config.GuiItem.EnableStatistics)
|
if (!_config.GuiItem.EnableStatistics)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
|
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Classes="Margin8"
|
Classes="Margin8"
|
||||||
DockPanel.Dock="Top"
|
DockPanel.Dock="Top"
|
||||||
@@ -55,7 +54,6 @@
|
|||||||
Margin="8,0,0,0" />
|
Margin="8,0,0,0" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|
||||||
<StackPanel
|
<StackPanel
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Classes="Margin8"
|
Classes="Margin8"
|
||||||
@@ -134,9 +132,6 @@
|
|||||||
</DataGrid>
|
</DataGrid>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</TabControl>
|
</TabControl>
|
||||||
|
|
||||||
|
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</Window>
|
</Window>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
@@ -77,6 +78,9 @@ namespace v2rayN.Desktop.Views
|
|||||||
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
{
|
{
|
||||||
desktop.MainWindow.Icon = AvaUtils.GetAppIcon(_config.SystemProxyItem.SysProxyType);
|
desktop.MainWindow.Icon = AvaUtils.GetAppIcon(_config.SystemProxyItem.SysProxyType);
|
||||||
|
var iconslist = TrayIcon.GetIcons(Application.Current);
|
||||||
|
iconslist[0].Icon = desktop.MainWindow.Icon;
|
||||||
|
TrayIcon.SetIcons(Application.Current, iconslist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,14 @@
|
|||||||
Text="{x:Static resx:ResUI.TbSettingsColorMode}" />
|
Text="{x:Static resx:ResUI.TbSettingsColorMode}" />
|
||||||
<ToggleSwitch x:Name="togDarkMode" Classes="Margin8" />
|
<ToggleSwitch x:Name="togDarkMode" Classes="Margin8" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock
|
||||||
|
Width="100"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Classes="Margin8"
|
||||||
|
Text="{x:Static resx:ResUI.TbSettingsFollowSystemTheme}" />
|
||||||
|
<ToggleSwitch x:Name="togFollowSystemTheme" Classes="Margin8" />
|
||||||
|
</StackPanel>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Width="100"
|
Width="100"
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace v2rayN.Desktop.Views
|
|||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.togFollowSystemTheme.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.SelectedValue).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,16 +20,16 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.2.0" />
|
<PackageReference Include="Avalonia" Version="11.2.1" />
|
||||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.2.0" />
|
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.2.1" />
|
||||||
<PackageReference Include="Avalonia.Desktop" Version="11.2.0" />
|
<PackageReference Include="Avalonia.Desktop" Version="11.2.1" />
|
||||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.0" />
|
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.1" />
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.2.0" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.2.1" />
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.2.0" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="11.2.1" />
|
||||||
<PackageReference Include="DialogHost.Avalonia" Version="0.8.1" />
|
<PackageReference Include="DialogHost.Avalonia" Version="0.8.1" />
|
||||||
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0" />
|
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0" />
|
||||||
<PackageReference Include="Semi.Avalonia" Version="11.2.0" />
|
<PackageReference Include="Semi.Avalonia" Version="11.2.1" />
|
||||||
<PackageReference Include="Semi.Avalonia.DataGrid" Version="11.2.0" />
|
<PackageReference Include="Semi.Avalonia.DataGrid" Version="11.2.1" />
|
||||||
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
||||||
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ VisualStudioVersion = 17.3.32811.315
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "v2rayN", "v2rayN\v2rayN.csproj", "{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "v2rayN", "v2rayN\v2rayN.csproj", "{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProtosLib", "ProtosLib\ProtosLib.csproj", "{C5F24BB0-9CC1-44DD-82FF-D545F081819B}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PacLib", "PacLib\PacLib.csproj", "{EE4E6CD8-8353-446B-8F29-A841A02AE5EC}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PacLib", "PacLib\PacLib.csproj", "{EE4E6CD8-8353-446B-8F29-A841A02AE5EC}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceLib", "ServiceLib\ServiceLib.csproj", "{1B6456C4-FFAA-4298-80F6-7B689A6E9243}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceLib", "ServiceLib\ServiceLib.csproj", "{1B6456C4-FFAA-4298-80F6-7B689A6E9243}"
|
||||||
@@ -25,10 +23,6 @@ Global
|
|||||||
{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Release|Any CPU.Build.0 = Release|Any CPU
|
{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{C5F24BB0-9CC1-44DD-82FF-D545F081819B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{C5F24BB0-9CC1-44DD-82FF-D545F081819B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{C5F24BB0-9CC1-44DD-82FF-D545F081819B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{C5F24BB0-9CC1-44DD-82FF-D545F081819B}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{EE4E6CD8-8353-446B-8F29-A841A02AE5EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{EE4E6CD8-8353-446B-8F29-A841A02AE5EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{EE4E6CD8-8353-446B-8F29-A841A02AE5EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{EE4E6CD8-8353-446B-8F29-A841A02AE5EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{EE4E6CD8-8353-446B-8F29-A841A02AE5EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{EE4E6CD8-8353-446B-8F29-A841A02AE5EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<Application
|
<Application
|
||||||
x:Class="v2rayN.App"
|
x:Class="v2rayN.App"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:conv="clr-namespace:v2rayN.Converters"
|
xmlns:conv="clr-namespace:v2rayN.Converters"
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
|
||||||
ShutdownMode="OnExplicitShutdown"
|
ShutdownMode="OnExplicitShutdown"
|
||||||
StartupUri="Views/MainWindow.xaml">
|
StartupUri="Views/MainWindow.xaml">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
|
|||||||
@@ -62,11 +62,12 @@ namespace v2rayN
|
|||||||
BitmapSizeOptions.FromEmptyOptions());
|
BitmapSizeOptions.FromEmptyOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsLightTheme()
|
public static bool IsDarkTheme()
|
||||||
{
|
{
|
||||||
using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
|
using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
|
||||||
var value = key?.GetValue("AppsUseLightTheme");
|
var obj = key?.GetValue("AppsUseLightTheme");
|
||||||
return value is int i && i > 0;
|
int.TryParse(obj?.ToString(), out var value);
|
||||||
|
return value == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RemoveTunDevice()
|
public static void RemoveTunDevice()
|
||||||
|
|||||||
@@ -54,11 +54,6 @@ namespace v2rayN.Handler
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!config.RoutingBasicItem.EnableRoutingAdvanced)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var item = await ConfigHandler.GetDefaultRouting(config);
|
var item = await ConfigHandler.GetDefaultRouting(config);
|
||||||
if (item == null || Utils.IsNullOrEmpty(item.CustomIcon) || !File.Exists(item.CustomIcon))
|
if (item == null || Utils.IsNullOrEmpty(item.CustomIcon) || !File.Exists(item.CustomIcon))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace v2rayN.ViewModels
|
|||||||
{
|
{
|
||||||
_config = AppHandler.Instance.Config;
|
_config = AppHandler.Instance.Config;
|
||||||
|
|
||||||
RegisterSystemColorSet(_config, Application.Current.MainWindow, (bool bl) => { ModifyTheme(bl); });
|
RegisterSystemColorSet(_config, Application.Current.MainWindow, ModifyTheme);
|
||||||
|
|
||||||
BindingUI();
|
BindingUI();
|
||||||
RestoreUI();
|
RestoreUI();
|
||||||
@@ -46,15 +46,7 @@ namespace v2rayN.ViewModels
|
|||||||
|
|
||||||
private void RestoreUI()
|
private void RestoreUI()
|
||||||
{
|
{
|
||||||
if (FollowSystemTheme)
|
ModifyTheme();
|
||||||
{
|
|
||||||
ModifyTheme(!WindowsUtils.IsLightTheme());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ModifyTheme(_config.UiItem.ColorModeDark);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_config.UiItem.ColorPrimaryName.IsNullOrEmpty())
|
if (!_config.UiItem.ColorPrimaryName.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
var swatch = new SwatchesProvider().Swatches.FirstOrDefault(t => t.Name == _config.UiItem.ColorPrimaryName);
|
var swatch = new SwatchesProvider().Swatches.FirstOrDefault(t => t.Name == _config.UiItem.ColorPrimaryName);
|
||||||
@@ -87,7 +79,7 @@ namespace v2rayN.ViewModels
|
|||||||
if (_config.UiItem.ColorModeDark != ColorModeDark)
|
if (_config.UiItem.ColorModeDark != ColorModeDark)
|
||||||
{
|
{
|
||||||
_config.UiItem.ColorModeDark = ColorModeDark;
|
_config.UiItem.ColorModeDark = ColorModeDark;
|
||||||
ModifyTheme(ColorModeDark);
|
ModifyTheme();
|
||||||
ConfigHandler.SaveConfig(_config);
|
ConfigHandler.SaveConfig(_config);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -99,15 +91,8 @@ namespace v2rayN.ViewModels
|
|||||||
if (_config.UiItem.FollowSystemTheme != FollowSystemTheme)
|
if (_config.UiItem.FollowSystemTheme != FollowSystemTheme)
|
||||||
{
|
{
|
||||||
_config.UiItem.FollowSystemTheme = FollowSystemTheme;
|
_config.UiItem.FollowSystemTheme = FollowSystemTheme;
|
||||||
|
ModifyTheme();
|
||||||
ConfigHandler.SaveConfig(_config);
|
ConfigHandler.SaveConfig(_config);
|
||||||
if (FollowSystemTheme)
|
|
||||||
{
|
|
||||||
ModifyTheme(!WindowsUtils.IsLightTheme());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ModifyTheme(ColorModeDark);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -163,10 +148,11 @@ namespace v2rayN.ViewModels
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ModifyTheme(bool isDarkTheme)
|
public void ModifyTheme()
|
||||||
{
|
{
|
||||||
var theme = _paletteHelper.GetTheme();
|
var theme = _paletteHelper.GetTheme();
|
||||||
|
|
||||||
|
var isDarkTheme = FollowSystemTheme ? WindowsUtils.IsDarkTheme() : ColorModeDark;
|
||||||
theme.SetBaseTheme(isDarkTheme ? BaseTheme.Dark : BaseTheme.Light);
|
theme.SetBaseTheme(isDarkTheme ? BaseTheme.Dark : BaseTheme.Light);
|
||||||
_paletteHelper.SetTheme(theme);
|
_paletteHelper.SetTheme(theme);
|
||||||
WindowsUtils.SetDarkBorder(Application.Current.MainWindow, isDarkTheme);
|
WindowsUtils.SetDarkBorder(Application.Current.MainWindow, isDarkTheme);
|
||||||
@@ -183,7 +169,7 @@ namespace v2rayN.ViewModels
|
|||||||
_paletteHelper.SetTheme(theme);
|
_paletteHelper.SetTheme(theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterSystemColorSet(Config config, Window window, Action<bool> updateFunc)
|
public void RegisterSystemColorSet(Config config, Window window, Action updateFunc)
|
||||||
{
|
{
|
||||||
var helper = new WindowInteropHelper(window);
|
var helper = new WindowInteropHelper(window);
|
||||||
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
|
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
|
||||||
@@ -196,7 +182,7 @@ namespace v2rayN.ViewModels
|
|||||||
{
|
{
|
||||||
if (wParam == IntPtr.Zero && Marshal.PtrToStringUni(lParam) == "ImmersiveColorSet")
|
if (wParam == IntPtr.Zero && Marshal.PtrToStringUni(lParam) == "ImmersiveColorSet")
|
||||||
{
|
{
|
||||||
updateFunc?.Invoke(!WindowsUtils.IsLightTheme());
|
updateFunc?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace v2rayN.Views
|
|||||||
this.BindCommand(ViewModel, vm => vm.EditServerCmd, v => v.btnEdit).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.EditServerCmd, v => v.btnEdit).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.SaveServerCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveServerCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.IsLightTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ namespace v2rayN.Views
|
|||||||
this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Path, v => v.txtPath.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Path, v => v.txtPath.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Extra, v => v.txtExtra.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Extra, v => v.txtExtra.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.StreamSecurity, v => v.cmbStreamSecurity.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.StreamSecurity, v => v.cmbStreamSecurity.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.Text).DisposeWith(disposables);
|
||||||
@@ -220,7 +220,7 @@ namespace v2rayN.Views
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.Title = $"{profileItem.ConfigType}";
|
this.Title = $"{profileItem.ConfigType}";
|
||||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.IsLightTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<reactiveui:ReactiveUserControl
|
<reactiveui:ReactiveUserControl
|
||||||
x:Class="v2rayN.Views.ClashConnectionsView"
|
x:Class="v2rayN.Views.ClashConnectionsView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:reactiveui="http://reactiveui.net"
|
xmlns:reactiveui="http://reactiveui.net"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<reactiveui:ReactiveUserControl
|
<reactiveui:ReactiveUserControl
|
||||||
x:Class="v2rayN.Views.ClashProxiesView"
|
x:Class="v2rayN.Views.ClashProxiesView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:converters="clr-namespace:v2rayN.Converters"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:reactiveui="http://reactiveui.net"
|
xmlns:reactiveui="http://reactiveui.net"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||||
|
xmlns:converters="clr-namespace:v2rayN.Converters"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
x:TypeArguments="vms:ClashProxiesViewModel"
|
x:TypeArguments="vms:ClashProxiesViewModel"
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace v2rayN.Views
|
|||||||
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCmd, v => v.btnImportDefConfig4Singbox).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCmd, v => v.btnImportDefConfig4Singbox).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.IsLightTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
HotkeyHandler.Instance.IsPause = true;
|
HotkeyHandler.Instance.IsPause = true;
|
||||||
this.Closing += (s, e) => HotkeyHandler.Instance.IsPause = false;
|
this.Closing += (s, e) => HotkeyHandler.Instance.IsPause = false;
|
||||||
WindowsUtils.SetDarkBorder(this, _config.UiItem.FollowSystemTheme ? !WindowsUtils.IsLightTheme() : _config.UiItem.ColorModeDark);
|
WindowsUtils.SetDarkBorder(this, _config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : _config.UiItem.ColorModeDark);
|
||||||
InitData();
|
InitData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,8 +76,10 @@
|
|||||||
HorizontalScrollBarVisibility="Auto"
|
HorizontalScrollBarVisibility="Auto"
|
||||||
IsReadOnly="True"
|
IsReadOnly="True"
|
||||||
IsReadOnlyCaretVisible="True"
|
IsReadOnlyCaretVisible="True"
|
||||||
|
IsUndoEnabled="False"
|
||||||
TextAlignment="Left"
|
TextAlignment="Left"
|
||||||
TextWrapping="Wrap"
|
TextWrapping="Wrap"
|
||||||
|
UndoLimit="0"
|
||||||
VerticalScrollBarVisibility="Visible">
|
VerticalScrollBarVisibility="Visible">
|
||||||
<TextBox.ContextMenu>
|
<TextBox.ContextMenu>
|
||||||
<ContextMenu Style="{StaticResource DefContextMenu}">
|
<ContextMenu Style="{StaticResource DefContextMenu}">
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.IsLightTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ namespace v2rayN.Views
|
|||||||
item2.Width = item.Width;
|
item2.Width = item.Width;
|
||||||
item2.DisplayIndex = displayIndex++;
|
item2.DisplayIndex = displayIndex++;
|
||||||
}
|
}
|
||||||
if (item.Name.StartsWith("to"))
|
if (item.Name.ToLower().StartsWith("to"))
|
||||||
{
|
{
|
||||||
if (!_config.GuiItem.EnableStatistics)
|
if (!_config.GuiItem.EnableStatistics)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<reactiveui:ReactiveWindow
|
<reactiveui:ReactiveWindow
|
||||||
x:Class="v2rayN.Views.RoutingRuleDetailsWindow"
|
x:Class="v2rayN.Views.RoutingRuleDetailsWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:reactiveui="http://reactiveui.net"
|
xmlns:reactiveui="http://reactiveui.net"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||||
Title="{x:Static resx:ResUI.menuRoutingRuleDetailsSetting}"
|
Title="{x:Static resx:ResUI.menuRoutingRuleDetailsSetting}"
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.IsLightTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<reactiveui:ReactiveWindow
|
<reactiveui:ReactiveWindow
|
||||||
x:Class="v2rayN.Views.RoutingRuleSettingWindow"
|
x:Class="v2rayN.Views.RoutingRuleSettingWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:reactiveui="http://reactiveui.net"
|
xmlns:reactiveui="http://reactiveui.net"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||||
Title="{x:Static resx:ResUI.menuRoutingRuleSetting}"
|
Title="{x:Static resx:ResUI.menuRoutingRuleSetting}"
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.IsLightTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
|
|||||||
@@ -28,23 +28,6 @@
|
|||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
ClipToBounds="True"
|
ClipToBounds="True"
|
||||||
Style="{StaticResource MaterialDesignToolBar}">
|
Style="{StaticResource MaterialDesignToolBar}">
|
||||||
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
|
|
||||||
<MenuItem x:Name="menuRoutingBasic" Padding="8,0">
|
|
||||||
<MenuItem.Header>
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon
|
|
||||||
Margin="{StaticResource MarginRight8}"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Kind="Server" />
|
|
||||||
<TextBlock Text="{x:Static resx:ResUI.menuRoutingBasic}" />
|
|
||||||
</StackPanel>
|
|
||||||
</MenuItem.Header>
|
|
||||||
<MenuItem
|
|
||||||
x:Name="menuRoutingBasicImportRules"
|
|
||||||
Height="{StaticResource MenuItemHeight}"
|
|
||||||
Header="{x:Static resx:ResUI.menuRoutingBasicImportRules}" />
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
|
<Menu Margin="0,1" Style="{StaticResource ToolbarMenu}">
|
||||||
<MenuItem x:Name="menuRoutingAdvanced" Padding="8,0">
|
<MenuItem x:Name="menuRoutingAdvanced" Padding="8,0">
|
||||||
<MenuItem.Header>
|
<MenuItem.Header>
|
||||||
@@ -66,16 +49,6 @@
|
|||||||
Header="{x:Static resx:ResUI.menuRoutingAdvancedImportRules}" />
|
Header="{x:Static resx:ResUI.menuRoutingAdvancedImportRules}" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
<!--<Separator />
|
|
||||||
<TextBlock
|
|
||||||
Margin="{StaticResource MarginLeft8}"
|
|
||||||
VerticalAlignment="Center"
|
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
|
||||||
Text="{x:Static resx:ResUI.TbenableRoutingAdvanced}" />
|
|
||||||
<ToggleButton
|
|
||||||
x:Name="togenableRoutingAdvanced"
|
|
||||||
Margin="{StaticResource MarginLeft8}"
|
|
||||||
HorizontalAlignment="Left" />-->
|
|
||||||
<Separator />
|
<Separator />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="{StaticResource MarginLeft8}"
|
Margin="{StaticResource MarginLeft8}"
|
||||||
@@ -224,107 +197,6 @@
|
|||||||
</DataGrid>
|
</DataGrid>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</TabControl>
|
</TabControl>
|
||||||
|
|
||||||
<TabControl x:Name="tabBasic">
|
|
||||||
<TabItem Header="{x:Static resx:ResUI.TbRoutingTabProxy}">
|
|
||||||
<Grid Margin="{StaticResource Margin8}">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="1*" />
|
|
||||||
<ColumnDefinition Width="10" />
|
|
||||||
<ColumnDefinition Width="1*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<GroupBox
|
|
||||||
Grid.Column="0"
|
|
||||||
Header="Domain"
|
|
||||||
Style="{StaticResource MyGroupBox}">
|
|
||||||
<TextBox
|
|
||||||
Name="txtProxyDomain"
|
|
||||||
AcceptsReturn="True"
|
|
||||||
Style="{StaticResource DefTextBox}"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
VerticalScrollBarVisibility="Auto" />
|
|
||||||
</GroupBox>
|
|
||||||
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
|
|
||||||
<GroupBox
|
|
||||||
Grid.Column="2"
|
|
||||||
Header="IP"
|
|
||||||
Style="{StaticResource MyGroupBox}">
|
|
||||||
<TextBox
|
|
||||||
Name="txtProxyIP"
|
|
||||||
AcceptsReturn="True"
|
|
||||||
Style="{StaticResource DefTextBox}"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
VerticalScrollBarVisibility="Auto" />
|
|
||||||
</GroupBox>
|
|
||||||
</Grid>
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem Header="{x:Static resx:ResUI.TbRoutingTabDirect}">
|
|
||||||
<Grid Margin="{StaticResource Margin8}">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="1*" />
|
|
||||||
<ColumnDefinition Width="10" />
|
|
||||||
<ColumnDefinition Width="1*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<GroupBox
|
|
||||||
Grid.Column="0"
|
|
||||||
Header="Domain"
|
|
||||||
Style="{StaticResource MyGroupBox}">
|
|
||||||
<TextBox
|
|
||||||
Name="txtDirectDomain"
|
|
||||||
AcceptsReturn="True"
|
|
||||||
Style="{StaticResource DefTextBox}"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
VerticalScrollBarVisibility="Auto" />
|
|
||||||
</GroupBox>
|
|
||||||
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
|
|
||||||
<GroupBox
|
|
||||||
Grid.Column="2"
|
|
||||||
Header="IP"
|
|
||||||
Style="{StaticResource MyGroupBox}">
|
|
||||||
<TextBox
|
|
||||||
Name="txtDirectIP"
|
|
||||||
AcceptsReturn="True"
|
|
||||||
Style="{StaticResource DefTextBox}"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
VerticalScrollBarVisibility="Auto" />
|
|
||||||
</GroupBox>
|
|
||||||
</Grid>
|
|
||||||
</TabItem>
|
|
||||||
|
|
||||||
<TabItem Header="{x:Static resx:ResUI.TbRoutingTabBlock}">
|
|
||||||
<Grid Margin="{StaticResource Margin8}">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="1*" />
|
|
||||||
<ColumnDefinition Width="10" />
|
|
||||||
<ColumnDefinition Width="1*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<GroupBox
|
|
||||||
Grid.Column="0"
|
|
||||||
Header="Domain"
|
|
||||||
Style="{StaticResource MyGroupBox}">
|
|
||||||
<TextBox
|
|
||||||
Name="txtBlockDomain"
|
|
||||||
AcceptsReturn="True"
|
|
||||||
Style="{StaticResource DefTextBox}"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
VerticalScrollBarVisibility="Auto" />
|
|
||||||
</GroupBox>
|
|
||||||
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
|
|
||||||
<GroupBox
|
|
||||||
Grid.Column="2"
|
|
||||||
Header="IP"
|
|
||||||
Style="{StaticResource MyGroupBox}">
|
|
||||||
<TextBox
|
|
||||||
Name="txtBlockIP"
|
|
||||||
AcceptsReturn="True"
|
|
||||||
Style="{StaticResource DefTextBox}"
|
|
||||||
TextWrapping="Wrap"
|
|
||||||
VerticalScrollBarVisibility="Auto" />
|
|
||||||
</GroupBox>
|
|
||||||
</Grid>
|
|
||||||
</TabItem>
|
|
||||||
</TabControl>
|
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</reactiveui:ReactiveWindow>
|
</reactiveui:ReactiveWindow>
|
||||||
@@ -39,24 +39,10 @@ namespace v2rayN.Views
|
|||||||
this.OneWayBind(ViewModel, vm => vm.RoutingItems, v => v.lstRoutings.ItemsSource).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.RoutingItems, v => v.lstRoutings.ItemsSource).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstRoutings.SelectedItem).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstRoutings.SelectedItem).DisposeWith(disposables);
|
||||||
|
|
||||||
//this.Bind(ViewModel, vm => vm.enableRoutingAdvanced, v => v.togenableRoutingAdvanced.IsChecked).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.domainStrategy, v => v.cmbdomainStrategy.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.domainStrategy, v => v.cmbdomainStrategy.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.domainMatcher, v => v.cmbdomainMatcher.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.domainMatcher, v => v.cmbdomainMatcher.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.domainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.domainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.ProxyDomain, v => v.txtProxyDomain.Text).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.ProxyIP, v => v.txtProxyIP.Text).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.DirectDomain, v => v.txtDirectDomain.Text).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.DirectIP, v => v.txtDirectIP.Text).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.BlockDomain, v => v.txtBlockDomain.Text).DisposeWith(disposables);
|
|
||||||
this.Bind(ViewModel, vm => vm.BlockIP, v => v.txtBlockIP.Text).DisposeWith(disposables);
|
|
||||||
|
|
||||||
this.OneWayBind(ViewModel, vm => vm.enableRoutingBasic, v => v.menuRoutingBasic.Visibility).DisposeWith(disposables);
|
|
||||||
this.OneWayBind(ViewModel, vm => vm.enableRoutingAdvanced, v => v.menuRoutingAdvanced.Visibility).DisposeWith(disposables);
|
|
||||||
this.OneWayBind(ViewModel, vm => vm.enableRoutingBasic, v => v.tabBasic.Visibility).DisposeWith(disposables);
|
|
||||||
this.OneWayBind(ViewModel, vm => vm.enableRoutingAdvanced, v => v.tabAdvanced.Visibility).DisposeWith(disposables);
|
|
||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.RoutingBasicImportRulesCmd, v => v.menuRoutingBasicImportRules).DisposeWith(disposables);
|
|
||||||
this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd2).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd2).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.RoutingAdvancedRemoveCmd, v => v.menuRoutingAdvancedRemove).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.RoutingAdvancedRemoveCmd, v => v.menuRoutingAdvancedRemove).DisposeWith(disposables);
|
||||||
@@ -66,7 +52,7 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.IsLightTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
@@ -102,11 +88,6 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
private void RoutingSettingWindow_PreviewKeyDown(object sender, KeyEventArgs e)
|
private void RoutingSettingWindow_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (ViewModel?.enableRoutingBasic ?? false)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
||||||
{
|
{
|
||||||
if (e.Key == Key.A)
|
if (e.Key == Key.A)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<reactiveui:ReactiveWindow
|
<reactiveui:ReactiveWindow
|
||||||
x:Class="v2rayN.Views.SubEditWindow"
|
x:Class="v2rayN.Views.SubEditWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns: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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:reactiveui="http://reactiveui.net"
|
xmlns:reactiveui="http://reactiveui.net"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||||
Title="{x:Static resx:ResUI.menuSubSetting}"
|
Title="{x:Static resx:ResUI.menuSubSetting}"
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace v2rayN.Views
|
|||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.IsLightTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace v2rayN.Views
|
|||||||
this.BindCommand(ViewModel, vm => vm.SubEditCmd, v => v.menuSubEdit).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SubEditCmd, v => v.menuSubEdit).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.SubShareCmd, v => v.menuSubShare).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SubShareCmd, v => v.menuSubShare).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.IsLightTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : AppHandler.Instance.Config.UiItem.ColorModeDark);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<reactiveui:ReactiveUserControl
|
<reactiveui:ReactiveUserControl
|
||||||
x:Class="v2rayN.Views.ThemeSettingView"
|
x:Class="v2rayN.Views.ThemeSettingView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:reactiveui="http://reactiveui.net"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:reactiveui="http://reactiveui.net"
|
||||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||||
xmlns:vms="clr-namespace:v2rayN.ViewModels"
|
xmlns:vms="clr-namespace:v2rayN.ViewModels"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
Style="{StaticResource ToolbarTextBlock}"
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
Text="{x:Static resx:ResUI.TbSettingsFollowSystemTheme}" />
|
Text="{x:Static resx:ResUI.TbSettingsFollowSystemTheme}" />
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
x:Name="followSystemTheme"
|
x:Name="togFollowSystemTheme"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="{StaticResource Margin8}" />
|
Margin="{StaticResource Margin8}" />
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace v2rayN.Views
|
|||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.followSystemTheme.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.togFollowSystemTheme.IsChecked).DisposeWith(disposables);
|
||||||
this.OneWayBind(ViewModel, vm => vm.Swatches, v => v.cmbSwatches.ItemsSource).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.Swatches, v => v.cmbSwatches.ItemsSource).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);
|
||||||
|
|||||||
Reference in New Issue
Block a user