Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49a3c84fc5 | ||
|
|
5e0c28438b | ||
|
|
a6dc801bc4 | ||
|
|
22009d1b71 | ||
|
|
50f39dc40e | ||
|
|
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 | ||
|
|
5dbce16895 | ||
|
|
1016dcb3d1 | ||
|
|
ba5ad12e13 | ||
|
|
57f9c8158e | ||
|
|
b8a0293b52 | ||
|
|
59b7daaef5 | ||
|
|
d781c768e9 | ||
|
|
04efed2079 | ||
|
|
2de9e14c7d | ||
|
|
a849dec6c2 | ||
|
|
28019dc511 | ||
|
|
9d638968a9 | ||
|
|
f921ff7d77 | ||
|
|
e3ea329795 | ||
|
|
87f1c129b6 | ||
|
|
a1c8bc0e61 | ||
|
|
61e9101851 | ||
|
|
a6289347cc | ||
|
|
9e84de8e76 | ||
|
|
d04cc53152 | ||
|
|
1ff3c5fc07 | ||
|
|
3db047a12f | ||
|
|
bf4615f2f2 | ||
|
|
798c7fad9a | ||
|
|
5797b37262 |
18
README.md
18
README.md
@@ -1,5 +1,5 @@
|
||||
# v2rayN
|
||||
A GUI client for Windows, 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)
|
||||
@@ -9,13 +9,19 @@ A GUI client for Windows, support [Xray core](https://github.com/XTLS/Xray-core)
|
||||
|
||||
|
||||
## How to use
|
||||
- If you are new to this, please download v2rayN-With-Core.zip from [releases](https://github.com/2dust/v2rayN/releases)
|
||||
- Otherwise please download v2rayN.zip (you will also need to download cores in the bin directory)
|
||||
- Run v2rayN.exe
|
||||
Check [Release files introduction](https://github.com/2dust/v2rayN/wiki/Release-files-introduction) and select the version you need to download
|
||||
### Windows
|
||||
- Run `v2rayN.exe`
|
||||
### Linux
|
||||
- `chmod +x v2rayN` Run `./v2rayN`
|
||||
```
|
||||
Debian 9+
|
||||
Ubuntu 16.04+
|
||||
Fedora 30+
|
||||
```
|
||||
|
||||
## Requirements
|
||||
- (6.35 and above)[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)
|
||||
- [Microsoft .NET 8.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
|
||||
- [Supported cores](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
|
||||
|
||||
|
||||
|
||||
@@ -8,5 +8,20 @@
|
||||
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
|
||||
<FileVersion>1.3.0</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Resx\Resource.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resource.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Resx\Resource.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -10,7 +10,7 @@
|
||||
{
|
||||
if (args.Length == 0)
|
||||
{
|
||||
Console.WriteLine("Please run it from the main application.(请从主应用运行)");
|
||||
Console.WriteLine(Resx.Resource.Guidelines);
|
||||
Thread.Sleep(5000);
|
||||
return;
|
||||
}
|
||||
|
||||
171
v2rayN/AmazTool/Resx/Resource.Designer.cs
generated
Normal file
171
v2rayN/AmazTool/Resx/Resource.Designer.cs
generated
Normal file
@@ -0,0 +1,171 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace AmazTool.Resx {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 一个强类型的资源类,用于查找本地化的字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resource {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resource() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AmazTool.Resx.Resource", typeof(Resource).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Failed to terminate the v2rayN.Close it manually,or the upgrade may fail. 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string FailedTerminateProcess {
|
||||
get {
|
||||
return ResourceManager.GetString("FailedTerminateProcess", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Failed to extract the update package. 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string FailedUnzipping {
|
||||
get {
|
||||
return ResourceManager.GetString("FailedUnzipping", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Upgrade failed. 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string FailedUpgrade {
|
||||
get {
|
||||
return ResourceManager.GetString("FailedUpgrade", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please run it from the main application. 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string Guidelines {
|
||||
get {
|
||||
return ResourceManager.GetString("Guidelines", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Information 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string Information {
|
||||
get {
|
||||
return ResourceManager.GetString("Information", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 In progress, please wait... 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string InProgress {
|
||||
get {
|
||||
return ResourceManager.GetString("InProgress", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Start v2rayN, please wait... 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string Restartv2rayN {
|
||||
get {
|
||||
return ResourceManager.GetString("Restartv2rayN", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Start extracting the update package... 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string StartUnzipping {
|
||||
get {
|
||||
return ResourceManager.GetString("StartUnzipping", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Successfully extracted the update package. 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string SuccessUnzipping {
|
||||
get {
|
||||
return ResourceManager.GetString("SuccessUnzipping", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Upgrade success. 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string SuccessUpgrade {
|
||||
get {
|
||||
return ResourceManager.GetString("SuccessUpgrade", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Try to terminate the v2rayN process... 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string TryTerminateProcess {
|
||||
get {
|
||||
return ResourceManager.GetString("TryTerminateProcess", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Upgrade failed, file not found. 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string UpgradeFileNotFound {
|
||||
get {
|
||||
return ResourceManager.GetString("UpgradeFileNotFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
156
v2rayN/AmazTool/Resx/Resource.resx
Normal file
156
v2rayN/AmazTool/Resx/Resource.resx
Normal file
@@ -0,0 +1,156 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Restartv2rayN" xml:space="preserve">
|
||||
<value>Start v2rayN, please wait...</value>
|
||||
</data>
|
||||
<data name="Guidelines" xml:space="preserve">
|
||||
<value>Please run it from the main application.</value>
|
||||
</data>
|
||||
<data name="UpgradeFileNotFound" xml:space="preserve">
|
||||
<value>Upgrade failed, file not found.</value>
|
||||
</data>
|
||||
<data name="InProgress" xml:space="preserve">
|
||||
<value>In progress, please wait...</value>
|
||||
</data>
|
||||
<data name="TryTerminateProcess" xml:space="preserve">
|
||||
<value>Try to terminate the v2rayN process...</value>
|
||||
</data>
|
||||
<data name="FailedTerminateProcess" xml:space="preserve">
|
||||
<value>Failed to terminate the v2rayN.Close it manually,or the upgrade may fail.</value>
|
||||
</data>
|
||||
<data name="StartUnzipping" xml:space="preserve">
|
||||
<value>Start extracting the update package...</value>
|
||||
</data>
|
||||
<data name="SuccessUnzipping" xml:space="preserve">
|
||||
<value>Successfully extracted the update package.</value>
|
||||
</data>
|
||||
<data name="FailedUnzipping" xml:space="preserve">
|
||||
<value>Failed to extract the update package.</value>
|
||||
</data>
|
||||
<data name="FailedUpgrade" xml:space="preserve">
|
||||
<value>Upgrade failed.</value>
|
||||
</data>
|
||||
<data name="SuccessUpgrade" xml:space="preserve">
|
||||
<value>Upgrade success.</value>
|
||||
</data>
|
||||
<data name="Information" xml:space="preserve">
|
||||
<value>Information</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
@@ -117,8 +117,40 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="pac" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Resources\pac.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;gb2312</value>
|
||||
<data name="Restartv2rayN" xml:space="preserve">
|
||||
<value>正在重启,请等待...</value>
|
||||
</data>
|
||||
<data name="Guidelines" xml:space="preserve">
|
||||
<value>请从主应用运行。</value>
|
||||
</data>
|
||||
<data name="UpgradeFileNotFound" xml:space="preserve">
|
||||
<value>升级失败,文件不存在。</value>
|
||||
</data>
|
||||
<data name="InProgress" xml:space="preserve">
|
||||
<value>正在进行中,请等待...</value>
|
||||
</data>
|
||||
<data name="TryTerminateProcess" xml:space="preserve">
|
||||
<value>尝试结束 v2rayN 进程...</value>
|
||||
</data>
|
||||
<data name="FailedTerminateProcess" xml:space="preserve">
|
||||
<value>请手动关闭正在运行的v2rayN,否则可能升级失败。</value>
|
||||
</data>
|
||||
<data name="StartUnzipping" xml:space="preserve">
|
||||
<value>开始解压缩更新包...</value>
|
||||
</data>
|
||||
<data name="SuccessUnzipping" xml:space="preserve">
|
||||
<value>解压缩更新包成功。</value>
|
||||
</data>
|
||||
<data name="FailedUnzipping" xml:space="preserve">
|
||||
<value>解压缩更新包失败。</value>
|
||||
</data>
|
||||
<data name="FailedUpgrade" xml:space="preserve">
|
||||
<value>升级失败。</value>
|
||||
</data>
|
||||
<data name="SuccessUpgrade" xml:space="preserve">
|
||||
<value>升级成功。</value>
|
||||
</data>
|
||||
<data name="Information" xml:space="preserve">
|
||||
<value>提示</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -8,35 +8,37 @@ namespace AmazTool
|
||||
{
|
||||
public static void Upgrade(string fileName)
|
||||
{
|
||||
Console.WriteLine(fileName);
|
||||
Console.WriteLine("In progress, please wait...(正在进行中,请等待)");
|
||||
Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
|
||||
|
||||
Thread.Sleep(9000);
|
||||
Waiting(9);
|
||||
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
Console.WriteLine("Upgrade Failed, File Not Exist(升级失败,文件不存在).");
|
||||
Console.WriteLine(Resx.Resource.UpgradeFileNotFound);
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Try to end the process(尝试结束进程).");
|
||||
Console.WriteLine(Resx.Resource.TryTerminateProcess);
|
||||
try
|
||||
{
|
||||
var existing = Process.GetProcessesByName(V2rayN);
|
||||
foreach (var pp in existing)
|
||||
{
|
||||
pp?.Kill();
|
||||
pp?.WaitForExit(1000);
|
||||
var path = pp.MainModule?.FileName ?? "";
|
||||
if (path.StartsWith(GetPath(V2rayN)))
|
||||
{
|
||||
pp?.Kill();
|
||||
pp?.WaitForExit(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Access may be denied without admin right. The user may not be an administrator.
|
||||
Console.WriteLine("Failed to close v2rayN(关闭v2rayN失败).\n" +
|
||||
"Close it manually, or the upgrade may fail.(请手动关闭正在运行的v2rayN,否则可能升级失败。\n\n" + ex.StackTrace);
|
||||
Console.WriteLine(Resx.Resource.FailedTerminateProcess + ex.StackTrace);
|
||||
}
|
||||
|
||||
Console.WriteLine("Start extracting files(开始解压文件).");
|
||||
Console.WriteLine(Resx.Resource.StartUnzipping);
|
||||
StringBuilder sb = new();
|
||||
try
|
||||
{
|
||||
@@ -79,17 +81,17 @@ namespace AmazTool
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Upgrade Failed(升级失败)." + ex.StackTrace);
|
||||
Console.WriteLine(Resx.Resource.FailedUpgrade + ex.StackTrace);
|
||||
//return;
|
||||
}
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
Console.WriteLine("Upgrade Failed(升级失败)." + sb.ToString());
|
||||
Console.WriteLine(Resx.Resource.FailedUpgrade + sb.ToString());
|
||||
//return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Start v2rayN, please wait...(正在重启,请等待)");
|
||||
Thread.Sleep(9000);
|
||||
Console.WriteLine(Resx.Resource.Restartv2rayN);
|
||||
Waiting(9);
|
||||
Process process = new()
|
||||
{
|
||||
StartInfo = new()
|
||||
@@ -122,6 +124,15 @@ namespace AmazTool
|
||||
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";
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PacLib;
|
||||
|
||||
public class PacHandler
|
||||
{
|
||||
private static string _configPath;
|
||||
private static int _httpPort;
|
||||
private static int _pacPort;
|
||||
private static TcpListener? _tcpListener;
|
||||
private static string _pacText;
|
||||
private static bool _isRunning;
|
||||
private static bool _needRestart = true;
|
||||
|
||||
public static void Start(string configPath, int httpPort, int pacPort)
|
||||
{
|
||||
_needRestart = (configPath != _configPath || httpPort != _httpPort || pacPort != _pacPort || !_isRunning);
|
||||
|
||||
_configPath = configPath;
|
||||
_httpPort = httpPort;
|
||||
_pacPort = pacPort;
|
||||
|
||||
InitText();
|
||||
|
||||
if (_needRestart)
|
||||
{
|
||||
Stop();
|
||||
RunListener();
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitText()
|
||||
{
|
||||
var path = Path.Combine(_configPath, "pac.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
File.AppendAllText(path, Resources.ResourceManager.GetString("pac"));
|
||||
}
|
||||
|
||||
_pacText = File.ReadAllText(path).Replace("__PROXY__", $"PROXY 127.0.0.1:{_httpPort};DIRECT;");
|
||||
}
|
||||
|
||||
private static void RunListener()
|
||||
{
|
||||
_tcpListener = TcpListener.Create(_pacPort);
|
||||
_isRunning = true;
|
||||
_tcpListener.Start();
|
||||
Task.Factory.StartNew(async () =>
|
||||
{
|
||||
while (_isRunning)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_tcpListener.Pending())
|
||||
{
|
||||
await Task.Delay(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
var client = _tcpListener.AcceptTcpClient();
|
||||
await Task.Run(() =>
|
||||
{
|
||||
var stream = client.GetStream();
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("HTTP/1.0 200 OK");
|
||||
sb.AppendLine("Content-type:application/x-ns-proxy-autoconfig");
|
||||
sb.AppendLine("Connection:close");
|
||||
sb.AppendLine("Content-Length:" + Encoding.UTF8.GetByteCount(_pacText));
|
||||
sb.AppendLine();
|
||||
sb.Append(_pacText);
|
||||
var content = Encoding.UTF8.GetBytes(sb.ToString());
|
||||
stream.Write(content, 0, content.Length);
|
||||
stream.Flush();
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}, TaskCreationOptions.LongRunning);
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
if (_tcpListener == null) return;
|
||||
try
|
||||
{
|
||||
_isRunning = false;
|
||||
_tcpListener.Stop();
|
||||
_tcpListener = null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<EmbeddedResource Update="Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
95
v2rayN/PacLib/Resources.Designer.cs
generated
95
v2rayN/PacLib/Resources.Designer.cs
generated
@@ -1,95 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace PacLib {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 一个强类型的资源类,用于查找本地化的字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PacLib.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 var proxy = '__PROXY__';
|
||||
///var rules = [
|
||||
/// [
|
||||
/// [],
|
||||
/// []
|
||||
/// ],
|
||||
/// [
|
||||
/// [
|
||||
/// "aftygh.gov.tw",
|
||||
/// "aide.gov.tw",
|
||||
/// "aliyun.com",
|
||||
/// "arte.gov.tw",
|
||||
/// "baidu.com",
|
||||
/// "chinaso.com",
|
||||
/// "chinaz.com",
|
||||
/// "chukuang.gov.tw",
|
||||
/// "cycab.gov.tw",
|
||||
/// "dbnsa.gov.tw",
|
||||
/// "df.gov.tw",
|
||||
/// "eastcoast-nsa.gov.tw",
|
||||
/// "erv-nsa.gov.tw",
|
||||
/// "grb.gov.tw",
|
||||
/// "haosou.com",
|
||||
/// [字符串的其余部分被截断]"; 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string pac {
|
||||
get {
|
||||
return ResourceManager.GetString("pac", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
75
v2rayN/ServiceLib/Common/DesUtils.cs
Normal file
75
v2rayN/ServiceLib/Common/DesUtils.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace ServiceLib.Common
|
||||
{
|
||||
public class DesUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Encrypt
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// /// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static string Encrypt(string? text, string? key = null)
|
||||
{
|
||||
if (text.IsNullOrEmpty())
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
GetKeyIv(key ?? GetDefaultKey(), out var rgbKey, out var rgbIv);
|
||||
var dsp = DES.Create();
|
||||
using var memStream = new MemoryStream();
|
||||
using var cryStream = new CryptoStream(memStream, dsp.CreateEncryptor(rgbKey, rgbIv), CryptoStreamMode.Write);
|
||||
using var sWriter = new StreamWriter(cryStream);
|
||||
sWriter.Write(text);
|
||||
sWriter.Flush();
|
||||
cryStream.FlushFinalBlock();
|
||||
memStream.Flush();
|
||||
return Convert.ToBase64String(memStream.GetBuffer(), 0, (int)memStream.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypt
|
||||
/// </summary>
|
||||
/// <param name="encryptText"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static string Decrypt(string? encryptText, string? key = null)
|
||||
{
|
||||
if (encryptText.IsNullOrEmpty())
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
GetKeyIv(key ?? GetDefaultKey(), out var rgbKey, out var rgbIv);
|
||||
var dsp = DES.Create();
|
||||
var buffer = Convert.FromBase64String(encryptText);
|
||||
|
||||
using var memStream = new MemoryStream();
|
||||
using var cryStream = new CryptoStream(memStream, dsp.CreateDecryptor(rgbKey, rgbIv), CryptoStreamMode.Write);
|
||||
cryStream.Write(buffer, 0, buffer.Length);
|
||||
cryStream.FlushFinalBlock();
|
||||
return Encoding.UTF8.GetString(memStream.ToArray());
|
||||
}
|
||||
|
||||
private static void GetKeyIv(string key, out byte[] rgbKey, out byte[] rgbIv)
|
||||
{
|
||||
if (key.IsNullOrEmpty())
|
||||
{
|
||||
throw new ArgumentNullException("The key cannot be null");
|
||||
}
|
||||
if (key.Length <= 8)
|
||||
{
|
||||
throw new ArgumentNullException("The key length cannot be less than 8 characters.");
|
||||
}
|
||||
|
||||
rgbKey = Encoding.ASCII.GetBytes(key.Substring(0, 8));
|
||||
rgbIv = Encoding.ASCII.GetBytes(key.Insert(0, "w").Substring(0, 8));
|
||||
}
|
||||
|
||||
private static string GetDefaultKey()
|
||||
{
|
||||
return Utils.GetMd5(Utils.GetHomePath() + "DesUtils");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,8 @@
|
||||
{
|
||||
v2fly = 1,
|
||||
Xray = 2,
|
||||
|
||||
//SagerNet = 3,
|
||||
v2fly_v5 = 4,
|
||||
|
||||
//clash = 11,
|
||||
//clash_meta = 12,
|
||||
mihomo = 13,
|
||||
|
||||
hysteria = 21,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
kcp,
|
||||
ws,
|
||||
httpupgrade,
|
||||
splithttp,
|
||||
xhttp,
|
||||
h2,
|
||||
http,
|
||||
quic,
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases";
|
||||
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 IPAPIUrl = "https://ipapi.co/json";
|
||||
|
||||
public const string PromotionUrl = @"aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw=";
|
||||
public const string ConfigFileName = "guiNConfig.json";
|
||||
@@ -46,6 +47,7 @@
|
||||
public const string ClashMixinYaml = NamespaceSample + "clash_mixin_yaml";
|
||||
public const string ClashTunYaml = NamespaceSample + "clash_tun_yaml";
|
||||
public const string LinuxAutostartConfig = NamespaceSample + "linux_autostart_config";
|
||||
public const string PacFileName = NamespaceSample + "pac";
|
||||
|
||||
public const string DefaultSecurity = "auto";
|
||||
public const string DefaultNetwork = "tcp";
|
||||
@@ -175,11 +177,10 @@
|
||||
|
||||
public static readonly List<string> VmessSecurities = new() { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" };
|
||||
public static readonly List<string> SsSecurities = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "none", "plain" };
|
||||
public static readonly List<string> SsSecuritiesInSagerNet = new() { "none", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "rc4", "rc4-md5", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-cfb8", "aes-192-cfb8", "aes-256-cfb8", "aes-128-ofb", "aes-192-ofb", "aes-256-ofb", "bf-cfb", "cast5-cfb", "des-cfb", "idea-cfb", "rc2-cfb", "seed-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", "camellia-128-cfb8", "camellia-192-cfb8", "camellia-256-cfb8", "salsa20", "chacha20", "chacha20-ietf", "xchacha20" };
|
||||
public static readonly List<string> SsSecuritiesInXray = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "xchacha20-poly1305", "xchacha20-ietf-poly1305", "none", "plain", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" };
|
||||
public static readonly List<string> SsSecuritiesInSingbox = new() { "aes-256-gcm", "aes-192-gcm", "aes-128-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "none", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "rc4-md5", "chacha20-ietf", "xchacha20" };
|
||||
public static readonly List<string> Flows = new() { "", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
|
||||
public static readonly List<string> Networks = new() { "tcp", "kcp", "ws", "httpupgrade", "splithttp", "h2", "quic", "grpc" };
|
||||
public static readonly List<string> Networks = new() { "tcp", "kcp", "ws", "httpupgrade", "xhttp", "h2", "quic", "grpc" };
|
||||
public static readonly List<string> KcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
|
||||
public static readonly List<string> CoreTypes = new() { "v2fly", "Xray", "sing_box" };
|
||||
public static readonly List<string> CoreTypes4VLESS = new() { "Xray", "sing_box" };
|
||||
@@ -188,6 +189,7 @@
|
||||
public static readonly List<string> DomainMatchers = new() { "linear", "mph", "" };
|
||||
public static readonly List<string> Fingerprints = new() { "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random", "randomized", "" };
|
||||
public static readonly List<string> UserAgent = new() { "chrome", "firefox", "safari", "edge", "none" };
|
||||
public static readonly List<string> XhttpMode = new() { "auto", "packet-up", "stream-up" };
|
||||
|
||||
public static readonly List<string> AllowInsecure = new() { "true", "false", "" };
|
||||
public static readonly List<string> DomainStrategy4Freedoms = new() { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" };
|
||||
@@ -207,9 +209,9 @@
|
||||
public static readonly List<string> SingboxMuxs = new() { "h2mux", "smux", "yamux", "" };
|
||||
public static readonly List<string> TuicCongestionControls = new() { "cubic", "new_reno", "bbr" };
|
||||
|
||||
public static readonly List<string> allowSelectType = new List<string> { "selector", "urltest", "loadbalance", "fallback" };
|
||||
public static readonly List<string> notAllowTestType = new List<string> { "selector", "urltest", "direct", "reject", "compatible", "pass", "loadbalance", "fallback" };
|
||||
public static readonly List<string> proxyVehicleType = new List<string> { "file", "http" };
|
||||
public static readonly List<string> allowSelectType = new() { "selector", "urltest", "loadbalance", "fallback" };
|
||||
public static readonly List<string> notAllowTestType = new() { "selector", "urltest", "direct", "reject", "compatible", "pass", "loadbalance", "fallback" };
|
||||
public static readonly List<string> proxyVehicleType = new() { "file", "http" };
|
||||
|
||||
#endregion const
|
||||
}
|
||||
|
||||
@@ -211,12 +211,12 @@
|
||||
|
||||
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)
|
||||
{
|
||||
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()
|
||||
@@ -247,7 +247,7 @@
|
||||
case ECoreType.sing_box:
|
||||
return Global.SsSecuritiesInSingbox;
|
||||
}
|
||||
return Global.SsSecuritiesInSagerNet;
|
||||
return Global.SsSecuritiesInSingbox;
|
||||
}
|
||||
|
||||
public ECoreType GetCoreType(ProfileItem profileItem, EConfigType eConfigType)
|
||||
|
||||
@@ -65,10 +65,8 @@ namespace ServiceLib.Handler
|
||||
config.Inbound[0].Protocol = EInboundProtocol.socks.ToString();
|
||||
}
|
||||
}
|
||||
config.RoutingBasicItem ??= new()
|
||||
{
|
||||
EnableRoutingAdvanced = true
|
||||
};
|
||||
|
||||
config.RoutingBasicItem ??= new();
|
||||
|
||||
if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy))
|
||||
{
|
||||
@@ -240,6 +238,7 @@ namespace ServiceLib.Handler
|
||||
item.PublicKey = profileItem.PublicKey;
|
||||
item.ShortId = profileItem.ShortId;
|
||||
item.SpiderX = profileItem.SpiderX;
|
||||
item.Extra = profileItem.Extra;
|
||||
}
|
||||
|
||||
var ret = item.ConfigType switch
|
||||
@@ -384,7 +383,7 @@ namespace ServiceLib.Handler
|
||||
}
|
||||
|
||||
var item = await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync(t => t.Port > 0);
|
||||
return await SetDefaultServerIndex(config, item.IndexId);
|
||||
return await SetDefaultServerIndex(config, item?.IndexId);
|
||||
}
|
||||
|
||||
public static async Task<ProfileItem?> GetDefaultServer(Config config)
|
||||
@@ -958,7 +957,6 @@ namespace ServiceLib.Handler
|
||||
&& o.Address == n.Address
|
||||
&& o.Port == n.Port
|
||||
&& o.Id == n.Id
|
||||
&& o.AlterId == n.AlterId
|
||||
&& o.Security == n.Security
|
||||
&& o.Network == n.Network
|
||||
&& o.HeaderType == n.HeaderType
|
||||
@@ -967,6 +965,10 @@ namespace ServiceLib.Handler
|
||||
&& (o.ConfigType == EConfigType.Trojan || o.StreamSecurity == n.StreamSecurity)
|
||||
&& o.Flow == n.Flow
|
||||
&& 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);
|
||||
}
|
||||
|
||||
@@ -1294,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;
|
||||
}
|
||||
|
||||
@@ -1596,7 +1612,7 @@ namespace ServiceLib.Handler
|
||||
var item = await AppHandler.Instance.GetRoutingItem(config.RoutingBasicItem.RoutingIndexId);
|
||||
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);
|
||||
return item2;
|
||||
}
|
||||
@@ -1670,6 +1686,15 @@ namespace ServiceLib.Handler
|
||||
{
|
||||
var ver = "V3-";
|
||||
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)
|
||||
{
|
||||
return 0;
|
||||
@@ -1710,11 +1735,6 @@ namespace ServiceLib.Handler
|
||||
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)
|
||||
{
|
||||
await SQLiteHelper.Instance.DeleteAsync(routingItem);
|
||||
|
||||
@@ -59,15 +59,18 @@ namespace ServiceLib.Handler
|
||||
|
||||
var fileName = Utils.GetConfigPath(Global.CoreConfigFileName);
|
||||
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
|
||||
ShowMsg(false, result.Msg);
|
||||
if (result.Success != true)
|
||||
{
|
||||
ShowMsg(true, result.Msg);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 Task.Delay(100);
|
||||
await CoreStart(node);
|
||||
|
||||
//In tun mode, do a delay check and restart the core
|
||||
@@ -99,6 +102,8 @@ namespace ServiceLib.Handler
|
||||
ShowMsg(false, result.Msg);
|
||||
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);
|
||||
}
|
||||
return pid;
|
||||
@@ -145,7 +150,7 @@ namespace ServiceLib.Handler
|
||||
|
||||
private string CoreFindExe(CoreInfo coreInfo)
|
||||
{
|
||||
string fileName = string.Empty;
|
||||
var fileName = string.Empty;
|
||||
foreach (var name in coreInfo.CoreExes)
|
||||
{
|
||||
var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());
|
||||
@@ -157,7 +162,7 @@ namespace ServiceLib.Handler
|
||||
}
|
||||
if (Utils.IsNullOrEmpty(fileName))
|
||||
{
|
||||
string msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.CoreType.ToString()), string.Join(", ", coreInfo.CoreExes.ToArray()), coreInfo.Url);
|
||||
var msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.CoreType.ToString()), string.Join(", ", coreInfo.CoreExes.ToArray()), coreInfo.Url);
|
||||
Logging.SaveLog(msg);
|
||||
ShowMsg(false, msg);
|
||||
}
|
||||
@@ -166,24 +171,12 @@ namespace ServiceLib.Handler
|
||||
|
||||
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")));
|
||||
|
||||
//ECoreType coreType;
|
||||
//if (node.configType != EConfigType.Custom && _config.tunModeItem.enableTun)
|
||||
//{
|
||||
// coreType = ECoreType.sing_box;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// coreType = LazyConfig.Instance.GetCoreType(node, node.configType);
|
||||
//}
|
||||
var coreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
|
||||
_config.RunningCoreType = coreType;
|
||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||
|
||||
var displayLog = node.ConfigType != EConfigType.Custom || node.DisplayLog;
|
||||
var proc = await RunProcess(node, coreInfo, "", displayLog);
|
||||
var proc = await RunProcess(coreInfo, Global.CoreConfigFileName, displayLog, true);
|
||||
if (proc is null)
|
||||
{
|
||||
return;
|
||||
@@ -220,12 +213,12 @@ namespace ServiceLib.Handler
|
||||
}
|
||||
if (itemSocks != null)
|
||||
{
|
||||
string fileName2 = Utils.GetConfigPath(Global.CorePreConfigFileName);
|
||||
var fileName2 = Utils.GetConfigPath(Global.CorePreConfigFileName);
|
||||
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName2);
|
||||
if (result.Success)
|
||||
{
|
||||
var coreInfo2 = CoreInfoHandler.Instance.GetCoreInfo(preCoreType);
|
||||
var proc2 = await RunProcess(node, coreInfo2, $" -c {Global.CorePreConfigFileName}", true);
|
||||
var proc2 = await RunProcess(coreInfo2, Global.CorePreConfigFileName, true, true);
|
||||
if (proc2 is not null)
|
||||
{
|
||||
_processPre = proc2;
|
||||
@@ -237,13 +230,10 @@ namespace ServiceLib.Handler
|
||||
|
||||
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
|
||||
{
|
||||
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
|
||||
var proc = await RunProcess(new(), coreInfo, $" -c {Global.CoreSpeedtestConfigFileName}", true);
|
||||
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true, false);
|
||||
if (proc is null)
|
||||
{
|
||||
return -1;
|
||||
@@ -254,8 +244,7 @@ namespace ServiceLib.Handler
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
string msg = ex.Message;
|
||||
ShowMsg(false, msg);
|
||||
ShowMsg(false, ex.Message);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -265,19 +254,29 @@ namespace ServiceLib.Handler
|
||||
_updateFunc?.Invoke(notify, msg);
|
||||
}
|
||||
|
||||
private bool IsNeedSudo(ECoreType eCoreType)
|
||||
{
|
||||
return _config.TunModeItem.EnableTun
|
||||
&& eCoreType == ECoreType.sing_box
|
||||
&& Utils.IsLinux()
|
||||
//&& _config.TunModeItem.LinuxSudoPwd.IsNotEmpty()
|
||||
;
|
||||
}
|
||||
|
||||
#endregion Private
|
||||
|
||||
#region Process
|
||||
|
||||
private async Task<Process?> RunProcess(ProfileItem node, CoreInfo coreInfo, string configPath, bool displayLog)
|
||||
private async Task<Process?> RunProcess(CoreInfo coreInfo, string configPath, bool displayLog, bool mayNeedSudo)
|
||||
{
|
||||
var fileName = CoreFindExe(coreInfo);
|
||||
if (Utils.IsNullOrEmpty(fileName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string fileName = CoreFindExe(coreInfo);
|
||||
if (Utils.IsNullOrEmpty(fileName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Process proc = new()
|
||||
{
|
||||
StartInfo = new()
|
||||
@@ -293,33 +292,44 @@ namespace ServiceLib.Handler
|
||||
StandardErrorEncoding = displayLog ? Encoding.UTF8 : null,
|
||||
}
|
||||
};
|
||||
|
||||
var isNeedSudo = mayNeedSudo && IsNeedSudo(coreInfo.CoreType);
|
||||
if (isNeedSudo)
|
||||
{
|
||||
await RunProcessAsLinuxRoot(proc, fileName, coreInfo, configPath);
|
||||
}
|
||||
|
||||
var startUpErrorMessage = new StringBuilder();
|
||||
var startUpSuccessful = false;
|
||||
if (displayLog)
|
||||
{
|
||||
proc.OutputDataReceived += (sender, e) =>
|
||||
{
|
||||
if (Utils.IsNotEmpty(e.Data))
|
||||
{
|
||||
string msg = e.Data + Environment.NewLine;
|
||||
ShowMsg(false, msg);
|
||||
}
|
||||
if (Utils.IsNullOrEmpty(e.Data)) return;
|
||||
ShowMsg(false, e.Data + Environment.NewLine);
|
||||
};
|
||||
proc.ErrorDataReceived += (sender, e) =>
|
||||
{
|
||||
if (Utils.IsNotEmpty(e.Data))
|
||||
{
|
||||
string msg = e.Data + Environment.NewLine;
|
||||
ShowMsg(false, msg);
|
||||
if (Utils.IsNullOrEmpty(e.Data)) return;
|
||||
ShowMsg(false, e.Data + Environment.NewLine);
|
||||
|
||||
if (!startUpSuccessful)
|
||||
{
|
||||
startUpErrorMessage.Append(msg);
|
||||
}
|
||||
if (!startUpSuccessful)
|
||||
{
|
||||
startUpErrorMessage.Append(e.Data + Environment.NewLine);
|
||||
}
|
||||
};
|
||||
}
|
||||
proc.Start();
|
||||
|
||||
if (isNeedSudo && _config.TunModeItem.LinuxSudoPwd.IsNotEmpty())
|
||||
{
|
||||
var pwd = DesUtils.Decrypt(_config.TunModeItem.LinuxSudoPwd);
|
||||
await Task.Delay(10);
|
||||
await proc.StandardInput.WriteLineAsync(pwd);
|
||||
await Task.Delay(10);
|
||||
await proc.StandardInput.WriteLineAsync(pwd);
|
||||
}
|
||||
|
||||
if (displayLog)
|
||||
{
|
||||
proc.BeginOutputReadLine();
|
||||
@@ -342,32 +352,68 @@ namespace ServiceLib.Handler
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
string msg = ex.Message;
|
||||
ShowMsg(true, msg);
|
||||
ShowMsg(true, ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (proc is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(1));
|
||||
try
|
||||
{
|
||||
await proc.WaitForExitAsync(timeout.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
proc.Kill();
|
||||
proc.WaitForExit(100);
|
||||
if (!proc.HasExited)
|
||||
}
|
||||
if (!proc.HasExited)
|
||||
{
|
||||
try
|
||||
{
|
||||
await proc.WaitForExitAsync(timeout.Token);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
proc.Kill();
|
||||
proc.WaitForExit(100);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Process
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
namespace ServiceLib.Handler
|
||||
namespace ServiceLib.Handler
|
||||
{
|
||||
public sealed class CoreInfoHandler
|
||||
{
|
||||
@@ -74,7 +72,7 @@ namespace ServiceLib.Handler
|
||||
{
|
||||
CoreType = ECoreType.Xray,
|
||||
CoreExes = new List<string> { "xray", "wxray" },
|
||||
Arguments = "run {0}",
|
||||
Arguments = "run -c {0}",
|
||||
Url = Global.XrayCoreUrl,
|
||||
ReleaseApiUrl = Global.XrayCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||
DownloadUrlWin64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-64.zip",
|
||||
@@ -89,7 +87,7 @@ namespace ServiceLib.Handler
|
||||
_coreInfo.Add(new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.mihomo,
|
||||
CoreExes = new List<string> { $"mihomo-windows-amd64{(Avx2.X64.IsSupported ? "" : "-compatible")}", "mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-windows-386", "mihomo", "clash" },
|
||||
CoreExes = new List<string> { "mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-linux-amd64", "mihomo", "clash" },
|
||||
Arguments = "-f config.json" + PortableMode(),
|
||||
Url = Global.MihomoCoreUrl,
|
||||
ReleaseApiUrl = Global.MihomoCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||
@@ -105,7 +103,7 @@ namespace ServiceLib.Handler
|
||||
_coreInfo.Add(new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.hysteria,
|
||||
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria-windows-386", "hysteria" },
|
||||
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria" },
|
||||
Arguments = "",
|
||||
Url = Global.HysteriaCoreUrl,
|
||||
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||
@@ -134,7 +132,7 @@ namespace ServiceLib.Handler
|
||||
{
|
||||
CoreType = ECoreType.sing_box,
|
||||
CoreExes = new List<string> { "sing-box-client", "sing-box" },
|
||||
Arguments = "run {0} --disable-color",
|
||||
Arguments = "run -c {0} --disable-color",
|
||||
Url = Global.SingboxCoreUrl,
|
||||
RedirectInfo = true,
|
||||
ReleaseApiUrl = Global.SingboxCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||
@@ -157,7 +155,7 @@ namespace ServiceLib.Handler
|
||||
_coreInfo.Add(new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.hysteria2,
|
||||
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria-windows-386", "hysteria" },
|
||||
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria" },
|
||||
Arguments = "",
|
||||
Url = Global.HysteriaCoreUrl,
|
||||
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
|
||||
@@ -167,7 +165,7 @@ namespace ServiceLib.Handler
|
||||
|
||||
private string PortableMode()
|
||||
{
|
||||
return $" -d \"{Utils.GetBinPath("")}\"";
|
||||
return $" -d {Utils.GetBinPath("").AppendQuotes()}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,7 +83,6 @@ namespace ServiceLib.Handler.Fmt
|
||||
|
||||
case nameof(ETransport.ws):
|
||||
case nameof(ETransport.httpupgrade):
|
||||
case nameof(ETransport.splithttp):
|
||||
if (Utils.IsNotEmpty(item.RequestHost))
|
||||
{
|
||||
dicQuery.Add("host", Utils.UrlEncode(item.RequestHost));
|
||||
@@ -94,6 +93,25 @@ namespace ServiceLib.Handler.Fmt
|
||||
}
|
||||
break;
|
||||
|
||||
case nameof(ETransport.xhttp):
|
||||
if (Utils.IsNotEmpty(item.RequestHost))
|
||||
{
|
||||
dicQuery.Add("host", Utils.UrlEncode(item.RequestHost));
|
||||
}
|
||||
if (Utils.IsNotEmpty(item.Path))
|
||||
{
|
||||
dicQuery.Add("path", Utils.UrlEncode(item.Path));
|
||||
}
|
||||
if (Utils.IsNotEmpty(item.HeaderType) && Global.XhttpMode.Contains(item.HeaderType))
|
||||
{
|
||||
dicQuery.Add("mode", Utils.UrlEncode(item.HeaderType));
|
||||
}
|
||||
if (Utils.IsNotEmpty(item.Extra))
|
||||
{
|
||||
dicQuery.Add("extra", Utils.UrlEncode(item.Extra));
|
||||
}
|
||||
break;
|
||||
|
||||
case nameof(ETransport.http):
|
||||
case nameof(ETransport.h2):
|
||||
dicQuery["type"] = nameof(ETransport.http);
|
||||
@@ -156,11 +174,17 @@ namespace ServiceLib.Handler.Fmt
|
||||
|
||||
case nameof(ETransport.ws):
|
||||
case nameof(ETransport.httpupgrade):
|
||||
case nameof(ETransport.splithttp):
|
||||
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
|
||||
item.Path = Utils.UrlDecode(query["path"] ?? "/");
|
||||
break;
|
||||
|
||||
case nameof(ETransport.xhttp):
|
||||
item.RequestHost = Utils.UrlDecode(query["host"] ?? "");
|
||||
item.Path = Utils.UrlDecode(query["path"] ?? "/");
|
||||
item.HeaderType = Utils.UrlDecode(query["mode"] ?? "");
|
||||
item.Extra = Utils.UrlDecode(query["extra"] ?? "");
|
||||
break;
|
||||
|
||||
case nameof(ETransport.http):
|
||||
case nameof(ETransport.h2):
|
||||
item.Network = nameof(ETransport.h2);
|
||||
|
||||
105
v2rayN/ServiceLib/Handler/PacHandler.cs
Normal file
105
v2rayN/ServiceLib/Handler/PacHandler.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace ServiceLib.Handler
|
||||
{
|
||||
public class PacHandler
|
||||
{
|
||||
private static string _configPath;
|
||||
private static int _httpPort;
|
||||
private static int _pacPort;
|
||||
private static TcpListener? _tcpListener;
|
||||
private static byte[] _writeContent;
|
||||
private static bool _isRunning;
|
||||
private static bool _needRestart = true;
|
||||
|
||||
public static async Task Start(string configPath, int httpPort, int pacPort)
|
||||
{
|
||||
_needRestart = (configPath != _configPath || httpPort != _httpPort || pacPort != _pacPort || !_isRunning);
|
||||
|
||||
_configPath = configPath;
|
||||
_httpPort = httpPort;
|
||||
_pacPort = pacPort;
|
||||
|
||||
await InitText();
|
||||
|
||||
if (_needRestart)
|
||||
{
|
||||
Stop();
|
||||
RunListener();
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task InitText()
|
||||
{
|
||||
var path = Path.Combine(_configPath, "pac.txt");
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
var pac = Utils.GetEmbedText(Global.PacFileName);
|
||||
await File.AppendAllTextAsync(path, pac);
|
||||
}
|
||||
|
||||
var pacText =
|
||||
(await File.ReadAllTextAsync(path)).Replace("__PROXY__", $"PROXY 127.0.0.1:{_httpPort};DIRECT;");
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("HTTP/1.0 200 OK");
|
||||
sb.AppendLine("Content-type:application/x-ns-proxy-autoconfig");
|
||||
sb.AppendLine("Connection:close");
|
||||
sb.AppendLine("Content-Length:" + Encoding.UTF8.GetByteCount(pacText));
|
||||
sb.AppendLine();
|
||||
sb.Append(pacText);
|
||||
_writeContent = Encoding.UTF8.GetBytes(sb.ToString());
|
||||
}
|
||||
|
||||
private static void RunListener()
|
||||
{
|
||||
_tcpListener = TcpListener.Create(_pacPort);
|
||||
_isRunning = true;
|
||||
_tcpListener.Start();
|
||||
Task.Factory.StartNew(async () =>
|
||||
{
|
||||
while (_isRunning)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_tcpListener.Pending())
|
||||
{
|
||||
await Task.Delay(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
var client = await _tcpListener.AcceptTcpClientAsync();
|
||||
await Task.Run(() => { WriteContent(client); });
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}, TaskCreationOptions.LongRunning);
|
||||
}
|
||||
|
||||
private static void WriteContent(TcpClient client)
|
||||
{
|
||||
var stream = client.GetStream();
|
||||
stream.Write(_writeContent, 0, _writeContent.Length);
|
||||
stream.Flush();
|
||||
}
|
||||
|
||||
public static void Stop()
|
||||
{
|
||||
if (_tcpListener == null) return;
|
||||
try
|
||||
{
|
||||
_isRunning = false;
|
||||
_tcpListener.Stop();
|
||||
_tcpListener = null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,8 @@
|
||||
private ServerStatItem? _serverStatItem;
|
||||
private List<ServerStatItem> _lstServerStat;
|
||||
private Action<ServerSpeedItem>? _updateFunc;
|
||||
private StatisticsV2rayService? _statisticsV2Ray;
|
||||
|
||||
private StatisticsXrayService? _statisticsXray;
|
||||
private StatisticsSingboxService? _statisticsSingbox;
|
||||
|
||||
public List<ServerStatItem> ServerStat => _lstServerStat;
|
||||
@@ -25,7 +26,7 @@
|
||||
|
||||
await InitData();
|
||||
|
||||
_statisticsV2Ray = new StatisticsV2rayService(config, UpdateServerStatHandler);
|
||||
_statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler);
|
||||
_statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler);
|
||||
}
|
||||
|
||||
@@ -33,7 +34,7 @@
|
||||
{
|
||||
try
|
||||
{
|
||||
_statisticsV2Ray?.Close();
|
||||
_statisticsXray?.Close();
|
||||
_statisticsSingbox?.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -64,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()
|
||||
{
|
||||
await SQLiteHelper.Instance.ExecuteAsync($"delete from ServerStatItem where indexId not in ( select indexId from ProfileItem )");
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
/*
|
||||
* 仅测试了,MacOS 13.7.1 x86 版本,其他版本有待确认
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// 应用接口类型
|
||||
/// </summary>
|
||||
@@ -21,14 +22,12 @@
|
||||
await ExecCmd(lstCmd);
|
||||
}
|
||||
|
||||
|
||||
public static async Task UnsetProxy()
|
||||
{
|
||||
var lstCmd = GetUnsetCmds();
|
||||
await ExecCmd(lstCmd);
|
||||
}
|
||||
|
||||
|
||||
private static async Task ExecCmd(List<CmdItem> lstCmd)
|
||||
{
|
||||
foreach (var cmd in lstCmd)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using PacLib;
|
||||
|
||||
namespace ServiceLib.Handler.SysProxy
|
||||
namespace ServiceLib.Handler.SysProxy
|
||||
{
|
||||
public static class SysProxyHandler
|
||||
{
|
||||
@@ -33,15 +31,10 @@ namespace ServiceLib.Handler.SysProxy
|
||||
await ProxySettingLinux.SetProxy(Global.Loopback, port);
|
||||
break;
|
||||
|
||||
case ESysProxyType.ForcedChange:
|
||||
{
|
||||
if (Utils.IsOSX())
|
||||
{
|
||||
await ProxySettingOSX.SetProxy(Global.Loopback, port);
|
||||
}
|
||||
case ESysProxyType.ForcedChange when Utils.IsOSX():
|
||||
await ProxySettingOSX.SetProxy(Global.Loopback, port);
|
||||
break;
|
||||
|
||||
break;
|
||||
}
|
||||
case ESysProxyType.ForcedClear when Utils.IsWindows():
|
||||
ProxySettingWindows.UnsetProxy();
|
||||
break;
|
||||
@@ -50,23 +43,13 @@ namespace ServiceLib.Handler.SysProxy
|
||||
await ProxySettingLinux.UnsetProxy();
|
||||
break;
|
||||
|
||||
case ESysProxyType.ForcedClear:
|
||||
{
|
||||
if (Utils.IsOSX())
|
||||
{
|
||||
await ProxySettingOSX.UnsetProxy();
|
||||
}
|
||||
case ESysProxyType.ForcedClear when Utils.IsOSX():
|
||||
await ProxySettingOSX.UnsetProxy();
|
||||
break;
|
||||
|
||||
break;
|
||||
}
|
||||
case ESysProxyType.Pac when Utils.IsWindows():
|
||||
{
|
||||
var portPac = AppHandler.Instance.GetLocalPort(EInboundProtocol.pac);
|
||||
PacHandler.Start(Utils.GetConfigPath(), port, portPac);
|
||||
var strProxy = $"{Global.HttpProtocol}{Global.Loopback}:{portPac}/pac?t={DateTime.Now.Ticks}";
|
||||
ProxySettingWindows.SetProxy(strProxy, "", 4);
|
||||
break;
|
||||
}
|
||||
await SetWindowsProxyPac(port);
|
||||
break;
|
||||
}
|
||||
|
||||
if (type != ESysProxyType.Pac && Utils.IsWindows())
|
||||
@@ -102,5 +85,13 @@ namespace ServiceLib.Handler.SysProxy
|
||||
.Replace("{socks_port}", portSocks.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task SetWindowsProxyPac(int port)
|
||||
{
|
||||
var portPac = AppHandler.Instance.GetLocalPort(EInboundProtocol.pac);
|
||||
await PacHandler.Start(Utils.GetConfigPath(), port, portPac);
|
||||
var strProxy = $"{Global.HttpProtocol}{Global.Loopback}:{portPac}/pac?t={DateTime.Now.Ticks}";
|
||||
ProxySettingWindows.SetProxy(strProxy, "", 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
case ECoreType.Xray when RunningCoreType is ECoreType.Xray or ECoreType.v2fly or ECoreType.v2fly_v5:
|
||||
case ECoreType.sing_box when RunningCoreType is ECoreType.sing_box or ECoreType.mihomo:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
public bool IgnoreGeoUpdateCore { get; set; } = true;
|
||||
|
||||
public int AutoUpdateInterval { get; set; }
|
||||
|
||||
|
||||
public bool EnableSecurityProtocolTls13 { get; set; }
|
||||
|
||||
public int TrayMenuServersLimit { get; set; } = 20;
|
||||
@@ -116,6 +116,7 @@
|
||||
public bool EnableDragDropSort { get; set; }
|
||||
public bool DoubleClick2Activate { get; set; }
|
||||
public bool AutoHideStartup { get; set; }
|
||||
public bool Hide2TrayWhenClose { get; set; }
|
||||
public List<ColumnItem> MainColumnItem { get; set; }
|
||||
public bool ShowInTaskbar { get; set; }
|
||||
}
|
||||
@@ -161,6 +162,7 @@
|
||||
public int Mtu { get; set; }
|
||||
public bool EnableExInbound { get; set; }
|
||||
public bool EnableIPv6Address { get; set; }
|
||||
public string? LinuxSudoPwd { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@@ -178,7 +180,6 @@
|
||||
public string DomainStrategy4Singbox { get; set; }
|
||||
public string DomainMatcher { get; set; }
|
||||
public string RoutingIndexId { get; set; }
|
||||
public bool EnableRoutingAdvanced { get; set; }
|
||||
}
|
||||
|
||||
[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; }
|
||||
}
|
||||
}
|
||||
@@ -30,44 +30,25 @@ namespace ServiceLib.Models
|
||||
|
||||
public string GetSummary()
|
||||
{
|
||||
string summary = string.Format("[{0}] ", (ConfigType).ToString());
|
||||
string[] arrAddr = Address.Split('.');
|
||||
string addr;
|
||||
if (arrAddr.Length > 2)
|
||||
var summary = $"[{(ConfigType).ToString()}] ";
|
||||
var arrAddr = Address.Split('.');
|
||||
var addr = arrAddr.Length switch
|
||||
{
|
||||
addr = $"{arrAddr.First()}***{arrAddr.Last()}";
|
||||
}
|
||||
else if (arrAddr.Length > 1)
|
||||
> 2 => $"{arrAddr.First()}***{arrAddr.Last()}",
|
||||
> 1 => $"***{arrAddr.Last()}",
|
||||
_ => Address
|
||||
};
|
||||
summary += ConfigType switch
|
||||
{
|
||||
addr = $"***{arrAddr.Last()}";
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = Address;
|
||||
}
|
||||
switch (ConfigType)
|
||||
{
|
||||
case EConfigType.Custom:
|
||||
summary += string.Format("[{1}]{0}", Remarks, CoreType.ToString());
|
||||
break;
|
||||
|
||||
default:
|
||||
summary += string.Format("{0}({1}:{2})", Remarks, addr, Port);
|
||||
break;
|
||||
}
|
||||
EConfigType.Custom => $"[{CoreType.ToString()}]{Remarks}",
|
||||
_ => $"{Remarks}({addr}:{Port})"
|
||||
};
|
||||
return summary;
|
||||
}
|
||||
|
||||
public List<string>? GetAlpn()
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(Alpn))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Utils.String2List(Alpn);
|
||||
}
|
||||
return Utils.IsNullOrEmpty(Alpn) ? null : Utils.String2List(Alpn);
|
||||
}
|
||||
|
||||
public string GetNetwork()
|
||||
@@ -110,5 +91,6 @@ namespace ServiceLib.Models
|
||||
public string PublicKey { get; set; }
|
||||
public string ShortId { get; set; }
|
||||
public string SpiderX { get; set; }
|
||||
public string Extra { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -78,8 +78,7 @@
|
||||
public int? listen_port { get; set; }
|
||||
public string? domain_strategy { get; set; }
|
||||
public string interface_name { get; set; }
|
||||
public string inet4_address { get; set; }
|
||||
public string? inet6_address { get; set; }
|
||||
public List<string>? address { get; set; }
|
||||
public int? mtu { get; set; }
|
||||
public bool? auto_route { get; set; }
|
||||
public bool? strict_route { get; set; }
|
||||
|
||||
@@ -2,60 +2,33 @@ using System.Text.Json.Serialization;
|
||||
|
||||
namespace ServiceLib.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// v2ray配置文件实体类 例子SampleConfig.txt
|
||||
/// </summary>
|
||||
public class V2rayConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Properties that do not belong to Ray
|
||||
/// </summary>
|
||||
public string? remarks { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 日志配置
|
||||
/// </summary>
|
||||
public Log4Ray log { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 传入连接配置
|
||||
/// </summary>
|
||||
public List<Inbounds4Ray> inbounds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 传出连接配置
|
||||
/// </summary>
|
||||
public List<Outbounds4Ray> outbounds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 统计需要, 空对象
|
||||
/// </summary>
|
||||
public Stats4Ray stats { get; set; }
|
||||
public Stats4Ray? stats { get; set; }
|
||||
|
||||
/// </summary>
|
||||
public API4Ray api { get; set; }
|
||||
public Metrics4Ray? metrics { get; set; }
|
||||
|
||||
/// </summary>
|
||||
public Policy4Ray policy { get; set; }
|
||||
public Policy4Ray? policy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// DNS 配置
|
||||
/// </summary>
|
||||
public object dns { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 路由配置
|
||||
/// </summary>
|
||||
public Routing4Ray routing { get; set; }
|
||||
}
|
||||
|
||||
public class Stats4Ray
|
||||
{ }
|
||||
|
||||
public class API4Ray
|
||||
public class Metrics4Ray
|
||||
{
|
||||
public string tag { get; set; }
|
||||
public List<string> services { get; set; }
|
||||
}
|
||||
|
||||
public class Policy4Ray
|
||||
@@ -71,124 +44,59 @@ namespace ServiceLib.Models
|
||||
|
||||
public class Log4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string access { get; set; }
|
||||
public string? access { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string error { get; set; }
|
||||
public string? error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string loglevel { get; set; }
|
||||
public string? loglevel { get; set; }
|
||||
}
|
||||
|
||||
public class Inbounds4Ray
|
||||
{
|
||||
public string tag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string listen { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string protocol { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Sniffing4Ray sniffing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Inboundsettings4Ray settings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public StreamSettings4Ray streamSettings { get; set; }
|
||||
}
|
||||
|
||||
public class Inboundsettings4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string auth { get; set; }
|
||||
public string? auth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool udp { get; set; }
|
||||
public bool? udp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string ip { get; set; }
|
||||
public string? ip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// api 使用
|
||||
/// </summary>
|
||||
public string address { get; set; }
|
||||
public string? address { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<UsersItem4Ray> clients { get; set; }
|
||||
public List<UsersItem4Ray>? clients { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// VLESS
|
||||
/// </summary>
|
||||
public string decryption { get; set; }
|
||||
public string? decryption { get; set; }
|
||||
|
||||
public bool allowTransparent { get; set; }
|
||||
public bool? allowTransparent { get; set; }
|
||||
|
||||
public List<AccountsItem4Ray> accounts { get; set; }
|
||||
public List<AccountsItem4Ray>? accounts { get; set; }
|
||||
}
|
||||
|
||||
public class UsersItem4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string id { get; set; }
|
||||
public string? id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int alterId { get; set; }
|
||||
public int? alterId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string email { get; set; }
|
||||
public string? email { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string security { get; set; }
|
||||
public string? security { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// VLESS
|
||||
/// </summary>
|
||||
public string encryption { get; set; }
|
||||
public string? encryption { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// VLESS
|
||||
/// </summary>
|
||||
public string? flow { get; set; }
|
||||
}
|
||||
|
||||
@@ -201,57 +109,27 @@ namespace ServiceLib.Models
|
||||
|
||||
public class Outbounds4Ray
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认值agentout
|
||||
/// </summary>
|
||||
public string tag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string protocol { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Outboundsettings4Ray settings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public StreamSettings4Ray streamSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Mux4Ray mux { get; set; }
|
||||
}
|
||||
|
||||
public class Outboundsettings4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<VnextItem4Ray>? vnext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<ServersItem4Ray> servers { get; set; }
|
||||
public List<ServersItem4Ray>? servers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Response4Ray response { get; set; }
|
||||
public Response4Ray? response { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string domainStrategy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int? userLevel { get; set; }
|
||||
|
||||
public FragmentItem4Ray? fragment { get; set; }
|
||||
@@ -259,85 +137,40 @@ namespace ServiceLib.Models
|
||||
|
||||
public class VnextItem4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string address { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<UsersItem4Ray> users { get; set; }
|
||||
}
|
||||
|
||||
public class ServersItem4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string email { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string address { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? method { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool? ota { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int? level { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// trojan
|
||||
/// </summary>
|
||||
public string flow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<SocksUsersItem4Ray> users { get; set; }
|
||||
}
|
||||
|
||||
public class SocksUsersItem4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string user { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string pass { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int? level { get; set; }
|
||||
}
|
||||
|
||||
@@ -351,17 +184,11 @@ namespace ServiceLib.Models
|
||||
|
||||
public class Response4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string type { get; set; }
|
||||
}
|
||||
|
||||
public class Dns4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<string> servers { get; set; }
|
||||
}
|
||||
|
||||
@@ -373,19 +200,10 @@ namespace ServiceLib.Models
|
||||
|
||||
public class Routing4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string domainStrategy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? domainMatcher { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<RulesItem4Ray> rules { get; set; }
|
||||
|
||||
public List<BalancersItem4Ray>? balancers { get; set; }
|
||||
@@ -426,87 +244,39 @@ namespace ServiceLib.Models
|
||||
|
||||
public class StreamSettings4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string network { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string security { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public TlsSettings4Ray? tlsSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tcp传输额外设置
|
||||
/// </summary>
|
||||
public TcpSettings4Ray? tcpSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Kcp传输额外设置
|
||||
/// </summary>
|
||||
public KcpSettings4Ray? kcpSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ws传输额外设置
|
||||
/// </summary>
|
||||
public WsSettings4Ray? wsSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public HttpupgradeSettings4Ray? httpupgradeSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public SplithttpSettings4Ray? splithttpSettings { get; set; }
|
||||
public XhttpSettings4Ray? xhttpSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// h2传输额外设置
|
||||
/// </summary>
|
||||
public HttpSettings4Ray? httpSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// QUIC
|
||||
/// </summary>
|
||||
public QuicSettings4Ray? quicSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// VLESS only
|
||||
/// </summary>
|
||||
public TlsSettings4Ray? realitySettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// grpc
|
||||
/// </summary>
|
||||
public GrpcSettings4Ray? grpcSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// sockopt
|
||||
/// </summary>
|
||||
public Sockopt4Ray? sockopt { get; set; }
|
||||
}
|
||||
|
||||
public class TlsSettings4Ray
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否允许不安全连接(用于客户端)
|
||||
/// </summary>
|
||||
public bool? allowInsecure { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? serverName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<string>? alpn { get; set; }
|
||||
|
||||
public string? fingerprint { get; set; }
|
||||
@@ -519,157 +289,94 @@ namespace ServiceLib.Models
|
||||
|
||||
public class TcpSettings4Ray
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据包头部伪装设置
|
||||
/// </summary>
|
||||
public Header4Ray header { get; set; }
|
||||
}
|
||||
|
||||
public class Header4Ray
|
||||
{
|
||||
/// <summary>
|
||||
/// 伪装
|
||||
/// </summary>
|
||||
public string type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结构复杂,直接存起来
|
||||
/// </summary>
|
||||
public object request { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 结构复杂,直接存起来
|
||||
/// </summary>
|
||||
public object response { get; set; }
|
||||
}
|
||||
|
||||
public class KcpSettings4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int mtu { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int tti { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int uplinkCapacity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int downlinkCapacity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool congestion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int readBufferSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int writeBufferSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Header4Ray header { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string seed { get; set; }
|
||||
}
|
||||
|
||||
public class WsSettings4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Headers4Ray headers { get; set; }
|
||||
}
|
||||
|
||||
public class Headers4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string Host { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户代理
|
||||
/// </summary>
|
||||
[JsonPropertyName("User-Agent")]
|
||||
public string UserAgent { get; set; }
|
||||
}
|
||||
|
||||
public class HttpupgradeSettings4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? host { get; set; }
|
||||
}
|
||||
|
||||
public class SplithttpSettings4Ray
|
||||
public class XhttpSettings4Ray
|
||||
{
|
||||
public string? path { get; set; }
|
||||
|
||||
public string? host { get; set; }
|
||||
public string? mode { get; set; }
|
||||
public string? scMaxEachPostBytes { get; set; }
|
||||
public string? scMaxConcurrentPosts { get; set; }
|
||||
public string? scMinPostsIntervalMs { get; set; }
|
||||
public Xmux4Ray? xmux { get; set; }
|
||||
public object? extra { get; set; }
|
||||
}
|
||||
|
||||
public int? maxUploadSize { get; set; }
|
||||
|
||||
public int? maxConcurrentUploads { get; set; }
|
||||
public class Xmux4Ray
|
||||
{
|
||||
public int? maxConcurrency { get; set; }
|
||||
public int? maxConnections { get; set; }
|
||||
public int? cMaxReuseTimes { get; set; }
|
||||
public int? cMaxLifetimeMs { get; set; }
|
||||
}
|
||||
|
||||
public class HttpSettings4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public List<string>? host { get; set; }
|
||||
}
|
||||
|
||||
public class QuicSettings4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string security { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string key { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Header4Ray header { get; set; }
|
||||
}
|
||||
|
||||
@@ -686,14 +393,8 @@ namespace ServiceLib.Models
|
||||
|
||||
public class AccountsItem4Ray
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string user { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string pass { get; set; }
|
||||
}
|
||||
|
||||
|
||||
20
v2rayN/ServiceLib/Models/V2rayMetricsVars.cs
Normal file
20
v2rayN/ServiceLib/Models/V2rayMetricsVars.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace ServiceLib.Models
|
||||
{
|
||||
internal class V2rayMetricsVars
|
||||
{
|
||||
public V2rayMetricsVarsStats? stats { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
public class V2rayMetricsVarsStats
|
||||
{
|
||||
public Hashtable? outbound { get; set; }
|
||||
}
|
||||
|
||||
public class V2rayMetricsVarsLink
|
||||
{
|
||||
public long downlink { get; set; }
|
||||
public long uplink { get; set; }
|
||||
}
|
||||
87
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
87
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>
|
||||
/// 查找类似 RoutingRuleDetailsSetting 的本地化字符串。
|
||||
/// </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>
|
||||
/// 查找类似 HTTP Port 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3148,6 +3139,42 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Linux system sudo password 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsLinuxSudoPassword {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsLinuxSudoPassword", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please set the sudo password in Tun mode settings first 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsLinuxSudoPasswordIsEmpty {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordIsEmpty", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please do not run this app with sudo 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsLinuxSudoPasswordNotSudoRunApp {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordNotSudoRunApp", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 The password is encrypted and stored only in local files. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsLinuxSudoPasswordTip {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsLinuxSudoPasswordTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Enable Log 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3599,7 +3626,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 The ping of current service: {0} ms 的本地化字符串。
|
||||
/// 查找类似 The delay : {0} ms, {1} 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TestMeOutput {
|
||||
get {
|
||||
@@ -3661,6 +3688,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 XHTTP Extra raw JSON, format: { XHTTPObject } 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TransportExtraTip {
|
||||
get {
|
||||
return ResourceManager.GetString("TransportExtraTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 *tcp camouflage type 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3698,7 +3734,16 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 *ws/httpupgrade/splithttp path 的本地化字符串。
|
||||
/// 查找类似 *xhttp mode 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TransportHeaderTypeTip5 {
|
||||
get {
|
||||
return ResourceManager.GetString("TransportHeaderTypeTip5", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 *ws/httpupgrade/xhttp path 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TransportPathTip1 {
|
||||
get {
|
||||
@@ -3752,7 +3797,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 *ws/httpupgrade/splithttp host 的本地化字符串。
|
||||
/// 查找类似 *ws/httpupgrade/xhttp host 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TransportRequestHostTip2 {
|
||||
get {
|
||||
|
||||
@@ -302,7 +302,7 @@
|
||||
<value>اسکن URL وارد کردن با موفقیت</value>
|
||||
</data>
|
||||
<data name="TestMeOutput" xml:space="preserve">
|
||||
<value>پینگ سرویس فعلی: {0} ms</value>
|
||||
<value>پینگ سرویس فعلی: {0} ms, {1}</value>
|
||||
</data>
|
||||
<data name="OperationSuccess" xml:space="preserve">
|
||||
<value>موفقیت عملیات</value>
|
||||
@@ -847,12 +847,6 @@
|
||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||
<value>Set as active rule</value>
|
||||
</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">
|
||||
<value>تطبیق دامنه</value>
|
||||
</data>
|
||||
@@ -1033,4 +1027,361 @@
|
||||
<data name="menuProxiesSelectActivity" xml:space="preserve">
|
||||
<value>Select active node (Enter)</value>
|
||||
</data>
|
||||
<data name="menuRemoteBackup" xml:space="preserve">
|
||||
<value>Backup to remote (WebDAV)</value>
|
||||
</data>
|
||||
<data name="menuRemoteRestore" xml:space="preserve">
|
||||
<value>Restore from remote (WebDAV)</value>
|
||||
</data>
|
||||
<data name="TbSettingsDomainStrategy4Out" xml:space="preserve">
|
||||
<value>Default domain strategy for outbound</value>
|
||||
</data>
|
||||
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
|
||||
<value>Multi-Server lowest latency</value>
|
||||
</data>
|
||||
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
|
||||
<value>Main layout orientation(Require restart)</value>
|
||||
</data>
|
||||
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
|
||||
<value>Multi-server load balancing</value>
|
||||
</data>
|
||||
<data name="TbSettingsDomainDNSAddress" xml:space="preserve">
|
||||
<value>Outbound DNS address</value>
|
||||
</data>
|
||||
<data name="menuProfileAutofitColumnWidth" xml:space="preserve">
|
||||
<value>Auto column width adjustment</value>
|
||||
</data>
|
||||
<data name="menuExport2ShareUrlBase64" xml:space="preserve">
|
||||
<value>Export Base64-encoded Share Links to Clipboard</value>
|
||||
</data>
|
||||
<data name="menuExport2ClientConfigClipboard" xml:space="preserve">
|
||||
<value>Export selected server for complete configuration to clipboard</value>
|
||||
</data>
|
||||
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
||||
<value>Show or hide the main window</value>
|
||||
</data>
|
||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
||||
<value>You are currently running a standalone package, please manually download the SelfContained.7z file to unzip and overwrite it!</value>
|
||||
</data>
|
||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||
<value>Custom config socks port</value>
|
||||
</data>
|
||||
<data name="menuBackupAndRestore" xml:space="preserve">
|
||||
<value>Backup and Restore</value>
|
||||
</data>
|
||||
<data name="menuLocalBackup" xml:space="preserve">
|
||||
<value>Backup to local</value>
|
||||
</data>
|
||||
<data name="menuLocalRestore" xml:space="preserve">
|
||||
<value>Restore from local</value>
|
||||
</data>
|
||||
<data name="menuLocalBackupAndRestore" xml:space="preserve">
|
||||
<value>Local</value>
|
||||
</data>
|
||||
<data name="menuRemoteBackupAndRestore" xml:space="preserve">
|
||||
<value>Remote (WebDAV)</value>
|
||||
</data>
|
||||
<data name="LvWebDavUrl" xml:space="preserve">
|
||||
<value>WebDav Url</value>
|
||||
</data>
|
||||
<data name="LvWebDavUserName" xml:space="preserve">
|
||||
<value>WebDav User Name</value>
|
||||
</data>
|
||||
<data name="LvWebDavPassword" xml:space="preserve">
|
||||
<value>WebDav Password</value>
|
||||
</data>
|
||||
<data name="LvWebDavCheck" xml:space="preserve">
|
||||
<value>WebDav Check</value>
|
||||
</data>
|
||||
<data name="LvWebDavDirName" xml:space="preserve">
|
||||
<value>Remote folder name (optional)</value>
|
||||
</data>
|
||||
<data name="LocalRestoreInvalidZipTips" xml:space="preserve">
|
||||
<value>Invalid backup file</value>
|
||||
</data>
|
||||
<data name="ConnectionsHostFilterTitle" xml:space="preserve">
|
||||
<value>Host filter</value>
|
||||
</data>
|
||||
<data name="TipActiveServer" xml:space="preserve">
|
||||
<value>Active</value>
|
||||
</data>
|
||||
<data name="menuStorageUI" xml:space="preserve">
|
||||
<value>Save Interface Layout</value>
|
||||
</data>
|
||||
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
|
||||
<value>Geo files source (optional)</value>
|
||||
</data>
|
||||
<data name="TbSettingsSrsFilesSource" xml:space="preserve">
|
||||
<value>sing-box ruleset files source (optional)</value>
|
||||
</data>
|
||||
<data name="UpgradeAppNotExistTip" xml:space="preserve">
|
||||
<value>UpgradeApp does not exist</value>
|
||||
</data>
|
||||
<data name="TbSettingsRoutingRulesSource" xml:space="preserve">
|
||||
<value>Routing rules source (optional)</value>
|
||||
</data>
|
||||
<data name="menuRegionalPresets" xml:space="preserve">
|
||||
<value>Regional presets setting</value>
|
||||
</data>
|
||||
<data name="menuRegionalPresetsDefault" xml:space="preserve">
|
||||
<value>Default</value>
|
||||
</data>
|
||||
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
||||
<value>Russia</value>
|
||||
</data>
|
||||
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
||||
<value>Users in China region can ignore this item</value>
|
||||
</data>
|
||||
<data name="menuAddServerViaImage" xml:space="preserve">
|
||||
<value>Scan QR code in the image</value>
|
||||
</data>
|
||||
<data name="InvalidUrlTip" xml:space="preserve">
|
||||
<value>Invalid address (Url)</value>
|
||||
</data>
|
||||
<data name="InsecureUrlProtocol" xml:space="preserve">
|
||||
<value>Please do not use the insecure HTTP protocol subscription address</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||
<value>Install the font to the system and restart the settings</value>
|
||||
</data>
|
||||
<data name="menuExitTips" xml:space="preserve">
|
||||
<value>Are you sure to exit?</value>
|
||||
</data>
|
||||
<data name="LvMemo" xml:space="preserve">
|
||||
<value>Remarks Memo</value>
|
||||
</data>
|
||||
<data name="TbSettingsLogEnabledToFile" xml:space="preserve">
|
||||
<value>Enable logging to file</value>
|
||||
</data>
|
||||
<data name="MsgSkipSubscriptionUpdate" xml:space="preserve">
|
||||
<value>Updates are not enabled, skip this subscription</value>
|
||||
</data>
|
||||
<data name="menuRebootAsAdmin" xml:space="preserve">
|
||||
<value>Restart as Administrator</value>
|
||||
</data>
|
||||
<data name="LvMoreUrl" xml:space="preserve">
|
||||
<value>More URLs, separated by commas; Subscription conversion will be invalid</value>
|
||||
</data>
|
||||
<data name="SpeedDisplayText" xml:space="preserve">
|
||||
<value>{0} : {1}/s↑ | {2}/s↓</value>
|
||||
</data>
|
||||
<data name="LvAutoUpdateInterval" xml:space="preserve">
|
||||
<value>Automatic update interval (minutes)</value>
|
||||
</data>
|
||||
<data name="LvConvertTarget" xml:space="preserve">
|
||||
<value>Convert target type</value>
|
||||
</data>
|
||||
<data name="LvConvertTargetTip" xml:space="preserve">
|
||||
<value>Please leave blank if no conversion is required</value>
|
||||
</data>
|
||||
<data name="TipDisplayLog" xml:space="preserve">
|
||||
<value>Please turn off when there is an abnormal disconnection</value>
|
||||
</data>
|
||||
<data name="menuDNSSetting" xml:space="preserve">
|
||||
<value>DNS Settings</value>
|
||||
</data>
|
||||
<data name="TbDnsSingboxObjectDoc" xml:space="preserve">
|
||||
<value>Please fill in DNS Structure, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbSettingDnsImportDefConfig" xml:space="preserve">
|
||||
<value>Click to import default DNS config</value>
|
||||
</data>
|
||||
<data name="TbdomainStrategy4Singbox" xml:space="preserve">
|
||||
<value>sing-box domain strategy</value>
|
||||
</data>
|
||||
<data name="TbSettingsMux4SboxProtocol" xml:space="preserve">
|
||||
<value>sing-box Mux Protocol</value>
|
||||
</data>
|
||||
<data name="TbRoutingRuleProcess" xml:space="preserve">
|
||||
<value>Full process name (Tun mode)</value>
|
||||
</data>
|
||||
<data name="TbRoutingRuleIP" xml:space="preserve">
|
||||
<value>IP or IP CIDR</value>
|
||||
</data>
|
||||
<data name="TbRoutingRuleDomain" xml:space="preserve">
|
||||
<value>Domain</value>
|
||||
</data>
|
||||
<data name="TbSettingsCoreDnsSingbox" xml:space="preserve">
|
||||
<value>sing-box DNS settings</value>
|
||||
</data>
|
||||
<data name="SpeedtestingWait" xml:space="preserve">
|
||||
<value>Waiting for testing (press ESC to terminate)...</value>
|
||||
</data>
|
||||
<data name="TbSpiderX" xml:space="preserve">
|
||||
<value>SpiderX</value>
|
||||
</data>
|
||||
<data name="TbShortId" xml:space="preserve">
|
||||
<value>ShortId</value>
|
||||
</data>
|
||||
<data name="menuMoveToGroup" xml:space="preserve">
|
||||
<value>Move to group</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
|
||||
<value>Enable Server Drag Drop Sort(Require restart)</value>
|
||||
</data>
|
||||
<data name="TbAutoRefresh" xml:space="preserve">
|
||||
<value>AutoRefresh</value>
|
||||
</data>
|
||||
<data name="SpeedtestingSkip" xml:space="preserve">
|
||||
<value>Skip test</value>
|
||||
</data>
|
||||
<data name="menuEditServer" xml:space="preserve">
|
||||
<value>Edit Server (Ctrl+D)</value>
|
||||
</data>
|
||||
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
|
||||
<value>Double-click server make active</value>
|
||||
</data>
|
||||
<data name="SpeedtestingCompleted" xml:space="preserve">
|
||||
<value>Test completed</value>
|
||||
</data>
|
||||
<data name="TbSettingsDefFingerprint" xml:space="preserve">
|
||||
<value>Default TLS fingerprint</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamily" xml:space="preserve">
|
||||
<value>FontFamily(Require restart)</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
|
||||
<value>Copy the font TTF/TTC file to the directory guiFonts, restart the settings</value>
|
||||
</data>
|
||||
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||
<value>http port = +1; Pac port = +4; *ray API port = +5; mihomo API port = +6;</value>
|
||||
</data>
|
||||
<data name="TbSettingsStartBootTip" xml:space="preserve">
|
||||
<value>Set this with admin privileges, get admin privileges after startup</value>
|
||||
</data>
|
||||
<data name="TbSettingsFontSize" xml:space="preserve">
|
||||
<value>Font Size</value>
|
||||
</data>
|
||||
<data name="TbSettingsSpeedTestTimeout" xml:space="preserve">
|
||||
<value>SpeedTest Single Timeout Value</value>
|
||||
</data>
|
||||
<data name="TbSettingsSpeedTestUrl" xml:space="preserve">
|
||||
<value>SpeedTest URL</value>
|
||||
</data>
|
||||
<data name="menuMoveTo" xml:space="preserve">
|
||||
<value>Move up and down</value>
|
||||
</data>
|
||||
<data name="TbPublicKey" xml:space="preserve">
|
||||
<value>PublicKey</value>
|
||||
</data>
|
||||
<data name="menuAddHysteria2Server" xml:space="preserve">
|
||||
<value>Add [Hysteria2] server</value>
|
||||
</data>
|
||||
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
|
||||
<value>Hysteria Max bandwidth (Up/Dw)</value>
|
||||
</data>
|
||||
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
|
||||
<value>Follow System Theme</value>
|
||||
</data>
|
||||
<data name="menuAddTuicServer" xml:space="preserve">
|
||||
<value>Add [TUIC] server</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableUpdateSubOnlyRemarksExist" xml:space="preserve">
|
||||
<value>Updating subscription, only determine remarks exists</value>
|
||||
</data>
|
||||
<data name="menuProxiesReload" xml:space="preserve">
|
||||
<value>Refresh Proxies</value>
|
||||
</data>
|
||||
<data name="TbSortingNetwork" xml:space="preserve">
|
||||
<value>Network</value>
|
||||
</data>
|
||||
<data name="TbSortingType" xml:space="preserve">
|
||||
<value>Type</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip5" xml:space="preserve">
|
||||
<value>*grpc Authority</value>
|
||||
</data>
|
||||
<data name="menuAddHttpServer" xml:space="preserve">
|
||||
<value>Add [HTTP] server</value>
|
||||
</data>
|
||||
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
|
||||
<value>Speed Ping Test URL</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
||||
<value>Use Xray and enable non-Tun mode, which conflicts with the group previous proxy</value>
|
||||
</data>
|
||||
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
|
||||
<value>Custom the rule-set of sing-box</value>
|
||||
</data>
|
||||
<data name="NeedRebootTips" xml:space="preserve">
|
||||
<value>Successful operation. Click the settings menu to reboot the app.</value>
|
||||
</data>
|
||||
<data name="menuOpenTheFileLocation" xml:space="preserve">
|
||||
<value>Open the storage location</value>
|
||||
</data>
|
||||
<data name="TbSortingChain" xml:space="preserve">
|
||||
<value>Chain</value>
|
||||
</data>
|
||||
<data name="TbSortingHost" xml:space="preserve">
|
||||
<value>Host</value>
|
||||
</data>
|
||||
<data name="TbSettingsUseSystemHosts" xml:space="preserve">
|
||||
<value>Use System Hosts</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||
<value>Enable fragment</value>
|
||||
</data>
|
||||
<data name="TbAutoScrollToEnd" xml:space="preserve">
|
||||
<value>Auto ScrollToEnd</value>
|
||||
</data>
|
||||
<data name="SpeedtestingStop" xml:space="preserve">
|
||||
<value>Test terminating...</value>
|
||||
</data>
|
||||
<data name="LvNextProfile" xml:space="preserve">
|
||||
<value>Next proxy remarks</value>
|
||||
</data>
|
||||
<data name="TbPath7" xml:space="preserve">
|
||||
<value>obfs password</value>
|
||||
</data>
|
||||
<data name="TbHeaderType8" xml:space="preserve">
|
||||
<value>Congestion control</value>
|
||||
</data>
|
||||
<data name="LvPrevProfile" xml:space="preserve">
|
||||
<value>Previous proxy remarks</value>
|
||||
</data>
|
||||
<data name="TbLocalAddress" xml:space="preserve">
|
||||
<value>Address(Ip,Ipv6)</value>
|
||||
</data>
|
||||
<data name="TbReserved" xml:space="preserve">
|
||||
<value>Reserved(2,3,4)</value>
|
||||
</data>
|
||||
<data name="TbPrivateKey" xml:space="preserve">
|
||||
<value>PrivateKey</value>
|
||||
</data>
|
||||
<data name="menuAddWireguardServer" xml:space="preserve">
|
||||
<value>Add [WireGuard] server</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||
<value>Enable IPv6 Address</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
||||
<value>Enable additional Inbound</value>
|
||||
</data>
|
||||
<data name="LvPrevProfileTip" xml:space="preserve">
|
||||
<value>Please make sure the remarks exists and is unique</value>
|
||||
</data>
|
||||
<data name="TbRuleMatchingTips" xml:space="preserve">
|
||||
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag => OutboundTag</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||
<value>Linux system sudo password</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>The password is encrypted and stored only in local files.</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||
<value>Please set the sudo password in Tun mode settings first</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||
<value>Please do not run this app with sudo</value>
|
||||
</data>
|
||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||
<value>*xhttp mode</value>
|
||||
</data>
|
||||
<data name="TransportExtraTip" xml:space="preserve">
|
||||
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
|
||||
</data>
|
||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||
<value>Hide to tray when closing the window</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -302,7 +302,7 @@
|
||||
<value>Scan import the shared link successfully</value>
|
||||
</data>
|
||||
<data name="TestMeOutput" xml:space="preserve">
|
||||
<value>The ping of current service: {0} ms</value>
|
||||
<value>The delay : {0} ms, {1}</value>
|
||||
</data>
|
||||
<data name="OperationSuccess" xml:space="preserve">
|
||||
<value>Operation success</value>
|
||||
@@ -344,7 +344,7 @@
|
||||
<value>Please fill in the correct custom DNS</value>
|
||||
</data>
|
||||
<data name="TransportPathTip1" xml:space="preserve">
|
||||
<value>*ws/httpupgrade/splithttp path</value>
|
||||
<value>*ws/httpupgrade/xhttp path</value>
|
||||
</data>
|
||||
<data name="TransportPathTip2" xml:space="preserve">
|
||||
<value>*h2 path</value>
|
||||
@@ -359,7 +359,7 @@
|
||||
<value>*http host Separated by commas (,)</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||
<value>*ws/httpupgrade/splithttp host</value>
|
||||
<value>*ws/httpupgrade/xhttp host</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||
<value>*h2 host Separated by commas (,)</value>
|
||||
@@ -850,12 +850,6 @@
|
||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||
<value>Set as active rule(Enter)</value>
|
||||
</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">
|
||||
<value>Domain Matcher</value>
|
||||
</data>
|
||||
@@ -1369,4 +1363,25 @@
|
||||
<data name="LvMemo" xml:space="preserve">
|
||||
<value>Remarks Memo</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||
<value>Linux system sudo password</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>The password is encrypted and stored only in local files.</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||
<value>Please set the sudo password in Tun mode settings first</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||
<value>Please do not run this app with sudo</value>
|
||||
</data>
|
||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||
<value>*xhttp mode</value>
|
||||
</data>
|
||||
<data name="TransportExtraTip" xml:space="preserve">
|
||||
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
|
||||
</data>
|
||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||
<value>Hide to tray when closing the window</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -302,7 +302,7 @@
|
||||
<value>Сканирование URL-адреса импорта успешна.</value>
|
||||
</data>
|
||||
<data name="TestMeOutput" xml:space="preserve">
|
||||
<value>Задержка текущего сервера: {0} мс</value>
|
||||
<value>Задержка текущего сервера: {0} мс, {1}</value>
|
||||
</data>
|
||||
<data name="OperationSuccess" xml:space="preserve">
|
||||
<value>Операция успешна</value>
|
||||
@@ -856,12 +856,6 @@
|
||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||
<value>Установить как активное правило</value>
|
||||
</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">
|
||||
<value>Сопоставитель доменов</value>
|
||||
</data>
|
||||
@@ -1046,6 +1040,348 @@
|
||||
<value>Россия</value>
|
||||
</data>
|
||||
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
||||
<value>Используйте Настройки -> Региональные пресеты вместо изменения этого поля</value>
|
||||
<value>Используйте Настройки -> Региональные пресеты вместо изменения этого поля</value>
|
||||
</data>
|
||||
<data name="LvMemo" xml:space="preserve">
|
||||
<value>Remarks Memo</value>
|
||||
</data>
|
||||
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
|
||||
<value>Speed Ping Test URL</value>
|
||||
</data>
|
||||
<data name="menuProxiesDelaytestPart" xml:space="preserve">
|
||||
<value>Part Node Latency Test</value>
|
||||
</data>
|
||||
<data name="menuProxiesReload" xml:space="preserve">
|
||||
<value>Refresh Proxies</value>
|
||||
</data>
|
||||
<data name="TbAutoScrollToEnd" xml:space="preserve">
|
||||
<value>Auto ScrollToEnd</value>
|
||||
</data>
|
||||
<data name="menuProxiesSelectActivity" xml:space="preserve">
|
||||
<value>Select active node (Enter)</value>
|
||||
</data>
|
||||
<data name="TbRuleMatchingTips" xml:space="preserve">
|
||||
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag => OutboundTag</value>
|
||||
</data>
|
||||
<data name="TbPath7" xml:space="preserve">
|
||||
<value>obfs password</value>
|
||||
</data>
|
||||
<data name="TbLocalAddress" xml:space="preserve">
|
||||
<value>Address(Ip,Ipv6)</value>
|
||||
</data>
|
||||
<data name="TbSettingsDomainStrategy4Out" xml:space="preserve">
|
||||
<value>Default domain strategy for outbound</value>
|
||||
</data>
|
||||
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
|
||||
<value>Multi-Server lowest latency</value>
|
||||
</data>
|
||||
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
|
||||
<value>Main layout orientation(Require restart)</value>
|
||||
</data>
|
||||
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
|
||||
<value>Multi-server load balancing</value>
|
||||
</data>
|
||||
<data name="menuProxiesDelaytest" xml:space="preserve">
|
||||
<value>Latency Test</value>
|
||||
</data>
|
||||
<data name="TbReserved" xml:space="preserve">
|
||||
<value>Reserved(2,3,4)</value>
|
||||
</data>
|
||||
<data name="TbPrivateKey" xml:space="preserve">
|
||||
<value>PrivateKey</value>
|
||||
</data>
|
||||
<data name="menuAddWireguardServer" xml:space="preserve">
|
||||
<value>Add [WireGuard] server</value>
|
||||
</data>
|
||||
<data name="menuProfileAutofitColumnWidth" xml:space="preserve">
|
||||
<value>Auto column width adjustment</value>
|
||||
</data>
|
||||
<data name="menuExport2ShareUrlBase64" xml:space="preserve">
|
||||
<value>Export Base64-encoded Share Links to Clipboard</value>
|
||||
</data>
|
||||
<data name="TbSortingDelay" xml:space="preserve">
|
||||
<value>Delay</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
||||
<value>Enable additional Inbound</value>
|
||||
</data>
|
||||
<data name="LvPrevProfileTip" xml:space="preserve">
|
||||
<value>Please make sure the remarks exists and is unique</value>
|
||||
</data>
|
||||
<data name="menuExport2ClientConfigClipboard" xml:space="preserve">
|
||||
<value>Export selected server for complete configuration to clipboard</value>
|
||||
</data>
|
||||
<data name="LvNextProfile" xml:space="preserve">
|
||||
<value>Next proxy remarks</value>
|
||||
</data>
|
||||
<data name="menuShowOrHideMainWindow" xml:space="preserve">
|
||||
<value>Show or hide the main window</value>
|
||||
</data>
|
||||
<data name="LvPrevProfile" xml:space="preserve">
|
||||
<value>Previous proxy remarks</value>
|
||||
</data>
|
||||
<data name="TbHeaderType8" xml:space="preserve">
|
||||
<value>Congestion control</value>
|
||||
</data>
|
||||
<data name="TbSettingsDomainDNSAddress" xml:space="preserve">
|
||||
<value>Outbound DNS address</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableUpdateSubOnlyRemarksExist" xml:space="preserve">
|
||||
<value>Updating subscription, only determine remarks exists</value>
|
||||
</data>
|
||||
<data name="SpeedtestingStop" xml:space="preserve">
|
||||
<value>Test terminating...</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip5" xml:space="preserve">
|
||||
<value>*grpc Authority</value>
|
||||
</data>
|
||||
<data name="TbSortingDefault" xml:space="preserve">
|
||||
<value>Default</value>
|
||||
</data>
|
||||
<data name="TbSortingChain" xml:space="preserve">
|
||||
<value>Chain</value>
|
||||
</data>
|
||||
<data name="TbSorting" xml:space="preserve">
|
||||
<value>Sorting</value>
|
||||
</data>
|
||||
<data name="menuOpenTheFileLocation" xml:space="preserve">
|
||||
<value>Open the storage location</value>
|
||||
</data>
|
||||
<data name="NeedRebootTips" xml:space="preserve">
|
||||
<value>Successful operation. Click the settings menu to reboot the app.</value>
|
||||
</data>
|
||||
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
|
||||
<value>Custom the rule-set of sing-box</value>
|
||||
</data>
|
||||
<data name="TbSortingDownTraffic" xml:space="preserve">
|
||||
<value>Download Traffic</value>
|
||||
</data>
|
||||
<data name="TbSortingHost" xml:space="preserve">
|
||||
<value>Host</value>
|
||||
</data>
|
||||
<data name="TbSortingName" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
</data>
|
||||
<data name="TbSortingNetwork" xml:space="preserve">
|
||||
<value>Network</value>
|
||||
</data>
|
||||
<data name="TbSortingTime" xml:space="preserve">
|
||||
<value>Time</value>
|
||||
</data>
|
||||
<data name="TbSortingType" xml:space="preserve">
|
||||
<value>Type</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
||||
<value>Enable cache file for sing-box (ruleset files)</value>
|
||||
</data>
|
||||
<data name="TbSortingUpSpeed" xml:space="preserve">
|
||||
<value>Upload Speed</value>
|
||||
</data>
|
||||
<data name="TbSortingUpTraffic" xml:space="preserve">
|
||||
<value>Upload Traffic</value>
|
||||
</data>
|
||||
<data name="TbConnections" xml:space="preserve">
|
||||
<value>Connections</value>
|
||||
</data>
|
||||
<data name="menuConnectionClose" xml:space="preserve">
|
||||
<value>Close Connection</value>
|
||||
</data>
|
||||
<data name="menuConnectionCloseAll" xml:space="preserve">
|
||||
<value>Close All Connection</value>
|
||||
</data>
|
||||
<data name="TbProxies" xml:space="preserve">
|
||||
<value>Proxies</value>
|
||||
</data>
|
||||
<data name="menuRulemode" xml:space="preserve">
|
||||
<value>Rule mode</value>
|
||||
</data>
|
||||
<data name="menuModeDirect" xml:space="preserve">
|
||||
<value>Direct</value>
|
||||
</data>
|
||||
<data name="menuModeGlobal" xml:space="preserve">
|
||||
<value>Global</value>
|
||||
</data>
|
||||
<data name="menuModeNothing" xml:space="preserve">
|
||||
<value>Do not change</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||
<value>Enable fragment</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
||||
<value>Use Xray and enable non-Tun mode, which conflicts with the group previous proxy</value>
|
||||
</data>
|
||||
<data name="menuModeRule" xml:space="preserve">
|
||||
<value>Rule</value>
|
||||
</data>
|
||||
<data name="menuAddHttpServer" xml:space="preserve">
|
||||
<value>Add [HTTP] server</value>
|
||||
</data>
|
||||
<data name="menuAddTuicServer" xml:space="preserve">
|
||||
<value>Add [TUIC] server</value>
|
||||
</data>
|
||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
||||
<value>You are currently running a standalone package, please manually download the SelfContained.7z file to unzip and overwrite it!</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||
<value>Enable IPv6 Address</value>
|
||||
</data>
|
||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||
<value>Custom config socks port</value>
|
||||
</data>
|
||||
<data name="LvWebDavCheck" xml:space="preserve">
|
||||
<value>WebDav Check</value>
|
||||
</data>
|
||||
<data name="TbRoutingRuleDomain" xml:space="preserve">
|
||||
<value>Domain</value>
|
||||
</data>
|
||||
<data name="TbRoutingRuleIP" xml:space="preserve">
|
||||
<value>IP or IP CIDR</value>
|
||||
</data>
|
||||
<data name="TbRoutingRuleProcess" xml:space="preserve">
|
||||
<value>Full process name (Tun mode)</value>
|
||||
</data>
|
||||
<data name="TbSettingsMux4SboxProtocol" xml:space="preserve">
|
||||
<value>sing-box Mux Protocol</value>
|
||||
</data>
|
||||
<data name="LocalRestoreInvalidZipTips" xml:space="preserve">
|
||||
<value>Invalid backup file</value>
|
||||
</data>
|
||||
<data name="TbdomainStrategy4Singbox" xml:space="preserve">
|
||||
<value>sing-box domain strategy</value>
|
||||
</data>
|
||||
<data name="ConnectionsHostFilterTitle" xml:space="preserve">
|
||||
<value>Host filter</value>
|
||||
</data>
|
||||
<data name="TbSettingDnsImportDefConfig" xml:space="preserve">
|
||||
<value>Click to import default DNS config</value>
|
||||
</data>
|
||||
<data name="TipActiveServer" xml:space="preserve">
|
||||
<value>Active</value>
|
||||
</data>
|
||||
<data name="TbDnsSingboxObjectDoc" xml:space="preserve">
|
||||
<value>Please fill in DNS Structure, Click to view the document</value>
|
||||
</data>
|
||||
<data name="LvConvertTargetTip" xml:space="preserve">
|
||||
<value>Please leave blank if no conversion is required</value>
|
||||
</data>
|
||||
<data name="LvConvertTarget" xml:space="preserve">
|
||||
<value>Convert target type</value>
|
||||
</data>
|
||||
<data name="menuStorageUI" xml:space="preserve">
|
||||
<value>Save Interface Layout</value>
|
||||
</data>
|
||||
<data name="SpeedDisplayText" xml:space="preserve">
|
||||
<value>{0} : {1}/s↑ | {2}/s↓</value>
|
||||
</data>
|
||||
<data name="LvMoreUrl" xml:space="preserve">
|
||||
<value>More URLs, separated by commas; Subscription conversion will be invalid</value>
|
||||
</data>
|
||||
<data name="MsgSkipSubscriptionUpdate" xml:space="preserve">
|
||||
<value>Updates are not enabled, skip this subscription</value>
|
||||
</data>
|
||||
<data name="UpgradeAppNotExistTip" xml:space="preserve">
|
||||
<value>UpgradeApp does not exist</value>
|
||||
</data>
|
||||
<data name="menuAddServerViaImage" xml:space="preserve">
|
||||
<value>Scan QR code in the image</value>
|
||||
</data>
|
||||
<data name="TipDisplayLog" xml:space="preserve">
|
||||
<value>Please turn off when there is an abnormal disconnection</value>
|
||||
</data>
|
||||
<data name="SpeedtestingWait" xml:space="preserve">
|
||||
<value>Waiting for testing (press ESC to terminate)...</value>
|
||||
</data>
|
||||
<data name="TbSpiderX" xml:space="preserve">
|
||||
<value>SpiderX</value>
|
||||
</data>
|
||||
<data name="TbShortId" xml:space="preserve">
|
||||
<value>ShortId</value>
|
||||
</data>
|
||||
<data name="InvalidUrlTip" xml:space="preserve">
|
||||
<value>Invalid address (Url)</value>
|
||||
</data>
|
||||
<data name="InsecureUrlProtocol" xml:space="preserve">
|
||||
<value>Please do not use the insecure HTTP protocol subscription address</value>
|
||||
</data>
|
||||
<data name="TbPublicKey" xml:space="preserve">
|
||||
<value>PublicKey</value>
|
||||
</data>
|
||||
<data name="menuMoveTo" xml:space="preserve">
|
||||
<value>Move up and down</value>
|
||||
</data>
|
||||
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||
<value>http port = +1; Pac port = +4; *ray API port = +5; mihomo API port = +6;</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||
<value>Install the font to the system and restart the settings</value>
|
||||
</data>
|
||||
<data name="menuAddHysteria2Server" xml:space="preserve">
|
||||
<value>Add [Hysteria2] server</value>
|
||||
</data>
|
||||
<data name="LvWebDavPassword" xml:space="preserve">
|
||||
<value>WebDav Password</value>
|
||||
</data>
|
||||
<data name="LvWebDavDirName" xml:space="preserve">
|
||||
<value>Remote folder name (optional)</value>
|
||||
</data>
|
||||
<data name="TbSortingDownSpeed" xml:space="preserve">
|
||||
<value>Download Speed</value>
|
||||
</data>
|
||||
<data name="menuRemoteRestore" xml:space="preserve">
|
||||
<value>Restore from remote (WebDAV)</value>
|
||||
</data>
|
||||
<data name="menuRemoteBackup" xml:space="preserve">
|
||||
<value>Backup to remote (WebDAV)</value>
|
||||
</data>
|
||||
<data name="LvWebDavUserName" xml:space="preserve">
|
||||
<value>WebDav User Name</value>
|
||||
</data>
|
||||
<data name="menuLocalRestore" xml:space="preserve">
|
||||
<value>Restore from local</value>
|
||||
</data>
|
||||
<data name="menuLocalBackup" xml:space="preserve">
|
||||
<value>Backup to local</value>
|
||||
</data>
|
||||
<data name="TbSettingsUseSystemHosts" xml:space="preserve">
|
||||
<value>Use System Hosts</value>
|
||||
</data>
|
||||
<data name="menuBackupAndRestore" xml:space="preserve">
|
||||
<value>Backup and Restore</value>
|
||||
</data>
|
||||
<data name="menuLocalBackupAndRestore" xml:space="preserve">
|
||||
<value>Local</value>
|
||||
</data>
|
||||
<data name="menuExitTips" xml:space="preserve">
|
||||
<value>Are you sure to exit?</value>
|
||||
</data>
|
||||
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
|
||||
<value>Hysteria Max bandwidth (Up/Dw)</value>
|
||||
</data>
|
||||
<data name="LvWebDavUrl" xml:space="preserve">
|
||||
<value>WebDav Url</value>
|
||||
</data>
|
||||
<data name="menuRemoteBackupAndRestore" xml:space="preserve">
|
||||
<value>Remote (WebDAV)</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||
<value>Linux system sudo password</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>The password is encrypted and stored only in local files.</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||
<value>Please set the sudo password in Tun mode settings first</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||
<value>Please do not run this app with sudo</value>
|
||||
</data>
|
||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||
<value>*xhttp mode</value>
|
||||
</data>
|
||||
<data name="TransportExtraTip" xml:space="preserve">
|
||||
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
|
||||
</data>
|
||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||
<value>Hide to tray when closing the window</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -302,7 +302,7 @@
|
||||
<value>扫描导入分享链接成功</value>
|
||||
</data>
|
||||
<data name="TestMeOutput" xml:space="preserve">
|
||||
<value>当前服务的真连接延迟: {0} ms</value>
|
||||
<value>当前延迟: {0} ms,{1}</value>
|
||||
</data>
|
||||
<data name="OperationSuccess" xml:space="preserve">
|
||||
<value>操作成功</value>
|
||||
@@ -344,7 +344,7 @@
|
||||
<value>请填写正确的自定义DNS</value>
|
||||
</data>
|
||||
<data name="TransportPathTip1" xml:space="preserve">
|
||||
<value>*ws/httpupgrade/splithttp path</value>
|
||||
<value>*ws/httpupgrade/xhttp path</value>
|
||||
</data>
|
||||
<data name="TransportPathTip2" xml:space="preserve">
|
||||
<value>*h2 path</value>
|
||||
@@ -359,7 +359,7 @@
|
||||
<value>*http host中间逗号(,)分隔</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||
<value>*ws/httpupgrade/splithttp host</value>
|
||||
<value>*ws/httpupgrade/xhttp host</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||
<value>*h2 host中间逗号(,)分隔</value>
|
||||
@@ -850,12 +850,6 @@
|
||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||
<value>设为活动规则 (Enter)</value>
|
||||
</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">
|
||||
<value>域名匹配算法</value>
|
||||
</data>
|
||||
@@ -1271,7 +1265,7 @@
|
||||
<value>显示或隐藏主界面</value>
|
||||
</data>
|
||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
||||
<value>您当前运行的是独立包,请手动下载 SelfContained.7z文件解压覆盖</value>
|
||||
<value>您当前运行的是独立包,请手动下载 SelfContained.7z文件解压覆盖!</value>
|
||||
</data>
|
||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||
<value>自定义配置的Socks端口</value>
|
||||
@@ -1366,4 +1360,25 @@
|
||||
<data name="LvMemo" xml:space="preserve">
|
||||
<value>备注备忘</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||
<value>Linux系统的sudo密码</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>密码已加密且只存储在本地文件中,无密码则每次都要输入</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||
<value>请先在Tun模式设置中设置sudo密码</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||
<value>请不要用sudo运行本app</value>
|
||||
</data>
|
||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||
<value>*xhttp 模式</value>
|
||||
</data>
|
||||
<data name="TransportExtraTip" xml:space="preserve">
|
||||
<value>XHTTP Extra 原始 JSON,格式: { XHTTPObject }</value>
|
||||
</data>
|
||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||
<value>关闭窗口时隐藏至托盘</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -127,7 +127,7 @@
|
||||
<value>設定格式不正確</value>
|
||||
</data>
|
||||
<data name="CustomServerTips" xml:space="preserve">
|
||||
<value>注意,自訂設定完全依賴您自己的設定,不能使用所有設定功能。如需使用系統代理請手動修改監聽埠。</value>
|
||||
<value>注意,自訂設定完全依賴您自己的設定,不能使用所有設定功能。如需使用系統代理請手動修改偵聽埠。</value>
|
||||
</data>
|
||||
<data name="Downloading" xml:space="preserve">
|
||||
<value>下載開始...</value>
|
||||
@@ -157,7 +157,7 @@
|
||||
<value>請填寫正確格式伺服器埠</value>
|
||||
</data>
|
||||
<data name="FillLocalListeningPort" xml:space="preserve">
|
||||
<value>請填寫本機監聽埠</value>
|
||||
<value>請填寫本機偵聽埠</value>
|
||||
</data>
|
||||
<data name="FillPassword" xml:space="preserve">
|
||||
<value>請填寫密碼</value>
|
||||
@@ -301,7 +301,7 @@
|
||||
<value>掃描匯入分享链接成功</value>
|
||||
</data>
|
||||
<data name="TestMeOutput" xml:space="preserve">
|
||||
<value>目前服務的真連接延遲: {0} ms</value>
|
||||
<value>目前延遲: {0} ms,{1}</value>
|
||||
</data>
|
||||
<data name="OperationSuccess" xml:space="preserve">
|
||||
<value>操作成功</value>
|
||||
@@ -343,7 +343,7 @@
|
||||
<value>請填寫正確的自訂DNS</value>
|
||||
</data>
|
||||
<data name="TransportPathTip1" xml:space="preserve">
|
||||
<value>*ws/httpupgrade/splithttp path</value>
|
||||
<value>*ws/httpupgrade/xhttp path</value>
|
||||
</data>
|
||||
<data name="TransportPathTip2" xml:space="preserve">
|
||||
<value>*h2 path</value>
|
||||
@@ -358,7 +358,7 @@
|
||||
<value>*http host中間逗號(,)分隔</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||
<value>*ws/httpupgrade/splithttp host</value>
|
||||
<value>*ws/httpupgrade/xhttp host</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||
<value>*h2 host中間逗號(,)分隔</value>
|
||||
@@ -511,7 +511,7 @@
|
||||
<value>清除所有服務統計資料</value>
|
||||
</data>
|
||||
<data name="menuRealPingServer" xml:space="preserve">
|
||||
<value>測試伺服器真連接延遲(多選) (Ctrl+R)</value>
|
||||
<value>測試伺服器真連線延遲(多選) (Ctrl+R)</value>
|
||||
</data>
|
||||
<data name="menuSortServerResult" xml:space="preserve">
|
||||
<value>按測試結果排序</value>
|
||||
@@ -683,7 +683,7 @@
|
||||
<value>進階代理設定, 協定選擇(可選)</value>
|
||||
</data>
|
||||
<data name="TbSettingsAllowLAN" xml:space="preserve">
|
||||
<value>允許來自區域網路的連接</value>
|
||||
<value>允許來自區域網路的連線</value>
|
||||
</data>
|
||||
<data name="TbSettingsAutoHideStartup" xml:space="preserve">
|
||||
<value>啟動後隱藏視窗</value>
|
||||
@@ -722,7 +722,7 @@
|
||||
<value>例外. 對於下列字元開頭的位址不使用代理設定檔:使用分號(;)分隔</value>
|
||||
</data>
|
||||
<data name="TbSettingsHttpPort" xml:space="preserve">
|
||||
<value>本機HTTP監聽埠</value>
|
||||
<value>本機HTTP偵聽埠</value>
|
||||
</data>
|
||||
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
|
||||
<value>更新Core時忽略Geo檔案</value>
|
||||
@@ -755,7 +755,7 @@
|
||||
<value>開啟流量探測</value>
|
||||
</data>
|
||||
<data name="TbSettingsSocksPort" xml:space="preserve">
|
||||
<value>本機SOCKS監聽埠</value>
|
||||
<value>本機SOCKS偵聽埠</value>
|
||||
</data>
|
||||
<data name="TbSettingsStartBoot" xml:space="preserve">
|
||||
<value>開機啟動(可能會不成功)</value>
|
||||
@@ -850,12 +850,6 @@
|
||||
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
|
||||
<value>設為活動規則 (Enter)</value>
|
||||
</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">
|
||||
<value>域名匹配演算法</value>
|
||||
</data>
|
||||
@@ -998,7 +992,7 @@
|
||||
<value>複製字型TTF/TTC檔案到目錄guiFonts,重啟設定</value>
|
||||
</data>
|
||||
<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 name="TbSettingsStartBootTip" xml:space="preserve">
|
||||
<value>以管理員權限設定此項,在啟動後獲得管理員權限</value>
|
||||
@@ -1094,7 +1088,7 @@
|
||||
<value>請確保別名存在並且唯一</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableExInbound" xml:space="preserve">
|
||||
<value>啟用額外監聽端口</value>
|
||||
<value>啟用額外偵聽連接埠</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
|
||||
<value>啟用IPv6</value>
|
||||
@@ -1106,7 +1100,7 @@
|
||||
<value>自动滚动到末尾</value>
|
||||
</data>
|
||||
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
|
||||
<value>真連接測試地址</value>
|
||||
<value>真連線測試位址</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableUpdateSubOnlyRemarksExist" xml:space="preserve">
|
||||
<value>更新訂閱時只判斷別名是否存在</value>
|
||||
@@ -1151,10 +1145,10 @@
|
||||
<value>顯示或隱藏主介面</value>
|
||||
</data>
|
||||
<data name="UpdateStandalonePackageTip" xml:space="preserve">
|
||||
<value>您目前運行的是獨立包,請手動下載 SelfContained.7z檔案解壓縮覆蓋</value>
|
||||
<value>您目前運行的是獨立包,請手動下載 SelfContained.7z檔案解壓縮覆蓋!</value>
|
||||
</data>
|
||||
<data name="TbPreSocksPort4Sub" xml:space="preserve">
|
||||
<value>自訂設定的Socks端口</value>
|
||||
<value>自訂設定的Socks連接埠</value>
|
||||
</data>
|
||||
<data name="menuBackupAndRestore" xml:space="preserve">
|
||||
<value>備份和還原</value>
|
||||
@@ -1187,7 +1181,7 @@
|
||||
<value>WebDav 密碼</value>
|
||||
</data>
|
||||
<data name="LvWebDavUrl" xml:space="preserve">
|
||||
<value>WebDav 伺服器地址</value>
|
||||
<value>WebDav 伺服器位址</value>
|
||||
</data>
|
||||
<data name="LvWebDavDirName" xml:space="preserve">
|
||||
<value>遠端資料夾名稱(可選)</value>
|
||||
@@ -1205,25 +1199,25 @@
|
||||
<value>儲存介面佈局</value>
|
||||
</data>
|
||||
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
|
||||
<value>Geo文件來源(可選)</value>
|
||||
<value>Geo檔案來源(可選)</value>
|
||||
</data>
|
||||
<data name="UpgradeAppNotExistTip" xml:space="preserve">
|
||||
<value>升级工具App不存在</value>
|
||||
<value>升級工具App不存在</value>
|
||||
</data>
|
||||
<data name="TbSettingsSrsFilesSource" xml:space="preserve">
|
||||
<value>sing-box ruleset文件來源(可選)</value>
|
||||
<value>sing-box ruleset檔案來源(可選)</value>
|
||||
</data>
|
||||
<data name="TbSettingsRoutingRulesSource" xml:space="preserve">
|
||||
<value>路由规则集来源(可选)</value>
|
||||
<value>路由規則集來源(可選)</value>
|
||||
</data>
|
||||
<data name="TbSettingsChinaUserTip" xml:space="preserve">
|
||||
<value>中国区域用户可忽略此项</value>
|
||||
<value>中國區域用戶可忽略此項</value>
|
||||
</data>
|
||||
<data name="menuRegionalPresets" xml:space="preserve">
|
||||
<value>区域预置设置</value>
|
||||
<value>區域預置設定</value>
|
||||
</data>
|
||||
<data name="menuRegionalPresetsDefault" xml:space="preserve">
|
||||
<value>默认区域</value>
|
||||
<value>預設區域</value>
|
||||
</data>
|
||||
<data name="menuRegionalPresetsRussia" xml:space="preserve">
|
||||
<value>俄羅斯</value>
|
||||
@@ -1232,13 +1226,13 @@
|
||||
<value>掃描圖片中的二維碼</value>
|
||||
</data>
|
||||
<data name="InvalidUrlTip" xml:space="preserve">
|
||||
<value>地址(Url)無效</value>
|
||||
<value>位址(Url)無效</value>
|
||||
</data>
|
||||
<data name="InsecureUrlProtocol" xml:space="preserve">
|
||||
<value>請不要使用不安全的HTTP協定訂閱位址</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||
<value>安裝字體到系統中,重新啟動設定</value>
|
||||
<value>安裝字型到系統中,重新啟動設定</value>
|
||||
</data>
|
||||
<data name="menuExitTips" xml:space="preserve">
|
||||
<value>是否確定退出?</value>
|
||||
@@ -1246,4 +1240,145 @@
|
||||
<data name="LvMemo" xml:space="preserve">
|
||||
<value>備註備忘</value>
|
||||
</data>
|
||||
<data name="TbHeaderType8" xml:space="preserve">
|
||||
<value>擁塞控制算法</value>
|
||||
</data>
|
||||
<data name="menuProxiesSelectActivity" xml:space="preserve">
|
||||
<value>設為活動節點 (Enter)</value>
|
||||
</data>
|
||||
<data name="menuProxiesReload" xml:space="preserve">
|
||||
<value>重新整理</value>
|
||||
</data>
|
||||
<data name="TbSorting" xml:space="preserve">
|
||||
<value>排序</value>
|
||||
</data>
|
||||
<data name="menuProxiesDelaytest" xml:space="preserve">
|
||||
<value>延遲測試</value>
|
||||
</data>
|
||||
<data name="menuModeRule" xml:space="preserve">
|
||||
<value>規則</value>
|
||||
</data>
|
||||
<data name="menuModeNothing" xml:space="preserve">
|
||||
<value>随原配置</value>
|
||||
</data>
|
||||
<data name="menuModeGlobal" xml:space="preserve">
|
||||
<value>全局</value>
|
||||
</data>
|
||||
<data name="menuModeDirect" xml:space="preserve">
|
||||
<value>直連</value>
|
||||
</data>
|
||||
<data name="menuRulemode" xml:space="preserve">
|
||||
<value>規則模式</value>
|
||||
</data>
|
||||
<data name="TbProxies" xml:space="preserve">
|
||||
<value>目前代理</value>
|
||||
</data>
|
||||
<data name="menuConnectionCloseAll" xml:space="preserve">
|
||||
<value>關閉所有連線</value>
|
||||
</data>
|
||||
<data name="TbSettingsDomainStrategy4Out" xml:space="preserve">
|
||||
<value>Outbound預設解析策略</value>
|
||||
</data>
|
||||
<data name="menuConnectionClose" xml:space="preserve">
|
||||
<value>關閉連線</value>
|
||||
</data>
|
||||
<data name="TbSortingUpTraffic" xml:space="preserve">
|
||||
<value>上傳流量</value>
|
||||
</data>
|
||||
<data name="TbSortingUpSpeed" xml:space="preserve">
|
||||
<value>上傳速度</value>
|
||||
</data>
|
||||
<data name="TbSortingType" xml:space="preserve">
|
||||
<value>類型</value>
|
||||
</data>
|
||||
<data name="TbSortingTime" xml:space="preserve">
|
||||
<value>時間</value>
|
||||
</data>
|
||||
<data name="TbSortingNetwork" xml:space="preserve">
|
||||
<value>網路</value>
|
||||
</data>
|
||||
<data name="TbSortingName" xml:space="preserve">
|
||||
<value>名稱</value>
|
||||
</data>
|
||||
<data name="TbSortingHost" xml:space="preserve">
|
||||
<value>主機</value>
|
||||
</data>
|
||||
<data name="TbSortingDownTraffic" xml:space="preserve">
|
||||
<value>下載流量</value>
|
||||
</data>
|
||||
<data name="TbSortingDownSpeed" xml:space="preserve">
|
||||
<value>下載速度</value>
|
||||
</data>
|
||||
<data name="TbSortingDelay" xml:space="preserve">
|
||||
<value>延遲</value>
|
||||
</data>
|
||||
<data name="TbSortingDefault" xml:space="preserve">
|
||||
<value>預設</value>
|
||||
</data>
|
||||
<data name="TbConnections" xml:space="preserve">
|
||||
<value>目前連線</value>
|
||||
</data>
|
||||
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
|
||||
<value>多伺服器最低延遲 (多選)</value>
|
||||
</data>
|
||||
<data name="menuProxiesDelaytestPart" xml:space="preserve">
|
||||
<value>目前部分節點延遲測試</value>
|
||||
</data>
|
||||
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
|
||||
<value>多伺服器負載平衡 (多選)</value>
|
||||
</data>
|
||||
<data name="menuAddHysteria2Server" xml:space="preserve">
|
||||
<value>添加[Hysteria2]伺服器</value>
|
||||
</data>
|
||||
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
|
||||
<value>Hysteria 最大頻寬(Up/Dw)</value>
|
||||
</data>
|
||||
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
|
||||
<value>主界面佈局方向(需重啟)</value>
|
||||
</data>
|
||||
<data name="menuAddWireguardServer" xml:space="preserve">
|
||||
<value>添加[WireGuard]伺服器</value>
|
||||
</data>
|
||||
<data name="TbPrivateKey" xml:space="preserve">
|
||||
<value>PrivateKey</value>
|
||||
</data>
|
||||
<data name="TbReserved" xml:space="preserve">
|
||||
<value>Reserved(2,3,4)</value>
|
||||
</data>
|
||||
<data name="TbLocalAddress" xml:space="preserve">
|
||||
<value>Address(Ip,Ipv6)</value>
|
||||
</data>
|
||||
<data name="TbSettingsUseSystemHosts" xml:space="preserve">
|
||||
<value>使用系統hosts</value>
|
||||
</data>
|
||||
<data name="TbSortingChain" xml:space="preserve">
|
||||
<value>路由鏈</value>
|
||||
</data>
|
||||
<data name="TbSettingsDomainDNSAddress" xml:space="preserve">
|
||||
<value>Outbound域名解析位址</value>
|
||||
</data>
|
||||
<data name="TbPath7" xml:space="preserve">
|
||||
<value>混淆密碼(obfs password)</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
|
||||
<value>Linux系統的sudo密碼</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>密碼已加密且只儲存在本機檔案中,無密碼則每次都要輸入</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
|
||||
<value>請先在Tun模式設定中設定sudo密碼</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
|
||||
<value>請不要用sudo來運行本app</value>
|
||||
</data>
|
||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||
<value>*xhttp 模式</value>
|
||||
</data>
|
||||
<data name="TransportExtraTip" xml:space="preserve">
|
||||
<value>XHTTP Extra 原始 JSON,格式: { XHTTPObject }</value>
|
||||
</data>
|
||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||
<value>關閉視窗時隱藏至托盤</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,73 +1,149 @@
|
||||
[
|
||||
{
|
||||
"remarks": "绕过bittorrent",
|
||||
"outboundTag": "direct",
|
||||
"protocol": [
|
||||
"bittorrent"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "Google cn",
|
||||
"outboundTag": "proxy",
|
||||
"domain": [
|
||||
"domain:googleapis.cn",
|
||||
"domain:gstatic.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "阻断udp443",
|
||||
"outboundTag": "block",
|
||||
"port": "443",
|
||||
"network": "udp"
|
||||
},
|
||||
{
|
||||
"remarks": "阻断广告",
|
||||
"outboundTag": "block",
|
||||
"domain": [
|
||||
"geosite:category-ads-all"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过局域网IP",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"geoip:private"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过局域网域名",
|
||||
"outboundTag": "direct",
|
||||
"domain": [
|
||||
"geosite:private"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理IP",
|
||||
"outboundTag": "proxy",
|
||||
"ip": [
|
||||
"1.0.0.1",
|
||||
"1.1.1.1",
|
||||
"8.8.8.8",
|
||||
"8.8.4.4",
|
||||
"geoip:facebook",
|
||||
"geoip:fastly",
|
||||
"geoip:google",
|
||||
"geoip:netflix",
|
||||
"geoip:telegram",
|
||||
"geoip:twitter"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理GFW",
|
||||
"outboundTag": "proxy",
|
||||
"domain": [
|
||||
"geosite:gfw",
|
||||
"geosite:greatfire"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "最终直连",
|
||||
"port": "0-65535",
|
||||
"outboundTag": "direct"
|
||||
}
|
||||
{
|
||||
"remarks": "绕过bittorrent",
|
||||
"outboundTag": "direct",
|
||||
"protocol": [
|
||||
"bittorrent"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "Google cn",
|
||||
"outboundTag": "proxy",
|
||||
"domain": [
|
||||
"domain:googleapis.cn",
|
||||
"domain:gstatic.com"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "阻断udp443",
|
||||
"outboundTag": "block",
|
||||
"port": "443",
|
||||
"network": "udp"
|
||||
},
|
||||
{
|
||||
"remarks": "阻断广告",
|
||||
"outboundTag": "block",
|
||||
"domain": [
|
||||
"geosite:category-ads-all"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过局域网IP",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"geoip:private"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过局域网域名",
|
||||
"outboundTag": "direct",
|
||||
"domain": [
|
||||
"geosite:private"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理海外公共DNSIP",
|
||||
"outboundTag": "proxy",
|
||||
"ip": [
|
||||
"1.1.1.1",
|
||||
"1.0.0.1",
|
||||
"2606:4700:4700::1111",
|
||||
"2606:4700:4700::1001",
|
||||
"1.1.1.2",
|
||||
"1.0.0.2",
|
||||
"2606:4700:4700::1112",
|
||||
"2606:4700:4700::1002",
|
||||
"1.1.1.3",
|
||||
"1.0.0.3",
|
||||
"2606:4700:4700::1113",
|
||||
"2606:4700:4700::1003",
|
||||
"8.8.8.8",
|
||||
"8.8.4.4",
|
||||
"2001:4860:4860::8888",
|
||||
"2001:4860:4860::8844",
|
||||
"94.140.14.14",
|
||||
"94.140.15.15",
|
||||
"2a10:50c0::ad1:ff",
|
||||
"2a10:50c0::ad2:ff",
|
||||
"94.140.14.15",
|
||||
"94.140.15.16",
|
||||
"2a10:50c0::bad1:ff",
|
||||
"2a10:50c0::bad2:ff",
|
||||
"94.140.14.140",
|
||||
"94.140.14.141",
|
||||
"2a10:50c0::1:ff",
|
||||
"2a10:50c0::2:ff",
|
||||
"208.67.222.222",
|
||||
"208.67.220.220",
|
||||
"2620:119:35::35",
|
||||
"2620:119:53::53",
|
||||
"208.67.222.123",
|
||||
"208.67.220.123",
|
||||
"2620:119:35::123",
|
||||
"2620:119:53::123",
|
||||
"9.9.9.9",
|
||||
"149.112.112.112",
|
||||
"2620:fe::9",
|
||||
"2620:fe::fe",
|
||||
"9.9.9.11",
|
||||
"149.112.112.11",
|
||||
"2620:fe::11",
|
||||
"2620:fe::fe:11",
|
||||
"9.9.9.10",
|
||||
"149.112.112.10",
|
||||
"2620:fe::10",
|
||||
"2620:fe::fe:10",
|
||||
"77.88.8.8",
|
||||
"77.88.8.1",
|
||||
"2a02:6b8::feed:0ff",
|
||||
"2a02:6b8:0:1::feed:0ff",
|
||||
"77.88.8.88",
|
||||
"77.88.8.2",
|
||||
"2a02:6b8::feed:bad",
|
||||
"2a02:6b8:0:1::feed:bad",
|
||||
"77.88.8.7",
|
||||
"77.88.8.3",
|
||||
"2a02:6b8::feed:a11",
|
||||
"2a02:6b8:0:1::feed:a11"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理海外公共DNS域名",
|
||||
"outboundTag": "proxy",
|
||||
"domain": [
|
||||
"domain:cloudflare-dns.com",
|
||||
"domain:one.one.one.one",
|
||||
"domain:dns.google",
|
||||
"domain:adguard-dns.com",
|
||||
"domain:opendns.com",
|
||||
"domain:umbrella.com",
|
||||
"domain:quad9.net",
|
||||
"domain:yandex.net"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理IP",
|
||||
"outboundTag": "proxy",
|
||||
"ip": [
|
||||
"geoip:facebook",
|
||||
"geoip:fastly",
|
||||
"geoip:google",
|
||||
"geoip:netflix",
|
||||
"geoip:telegram",
|
||||
"geoip:twitter"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理GFW",
|
||||
"outboundTag": "proxy",
|
||||
"domain": [
|
||||
"geosite:gfw",
|
||||
"geosite:greatfire"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "最终直连",
|
||||
"port": "0-65535",
|
||||
"outboundTag": "direct"
|
||||
}
|
||||
]
|
||||
@@ -1,4 +1,5 @@
|
||||
[{
|
||||
[
|
||||
{
|
||||
"remarks": "block",
|
||||
"outboundTag": "block",
|
||||
"domain": [
|
||||
@@ -12,14 +13,14 @@
|
||||
"geosite:cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "direct",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"geoip:private",
|
||||
"geoip:cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "direct",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"geoip:private",
|
||||
"geoip:cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "proxy",
|
||||
"port": "0-65535",
|
||||
|
||||
@@ -34,29 +34,62 @@
|
||||
"geosite:private"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国公共DNSIP",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"223.5.5.5",
|
||||
"223.6.6.6",
|
||||
"2400:3200::1",
|
||||
"2400:3200:baba::1",
|
||||
"119.29.29.29",
|
||||
"1.12.12.12",
|
||||
"120.53.53.53",
|
||||
"2402:4e00::",
|
||||
"2402:4e00:1::",
|
||||
"180.76.76.76",
|
||||
"2400:da00::6666",
|
||||
"114.114.114.114",
|
||||
"114.114.115.115",
|
||||
"114.114.114.119",
|
||||
"114.114.115.119",
|
||||
"114.114.114.110",
|
||||
"114.114.115.110",
|
||||
"180.184.1.1",
|
||||
"180.184.2.2",
|
||||
"101.226.4.6",
|
||||
"218.30.118.6",
|
||||
"123.125.81.6",
|
||||
"140.207.198.6",
|
||||
"1.2.4.8",
|
||||
"210.2.4.8",
|
||||
"52.80.66.66",
|
||||
"117.50.22.22",
|
||||
"2400:7fc0:849e:200::4",
|
||||
"2404:c2c0:85d8:901::4",
|
||||
"117.50.10.10",
|
||||
"52.80.52.52",
|
||||
"2400:7fc0:849e:200::8",
|
||||
"2404:c2c0:85d8:901::8",
|
||||
"117.50.60.30",
|
||||
"52.80.60.30"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国公共DNS域名",
|
||||
"outboundTag": "direct",
|
||||
"domain": [
|
||||
"domain:alidns.com",
|
||||
"domain:doh.pub",
|
||||
"domain:dot.pub",
|
||||
"domain:360.cn",
|
||||
"domain:onedns.net"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国IP",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"223.5.5.5/32",
|
||||
"223.6.6.6/32",
|
||||
"2400:3200::1/128",
|
||||
"2400:3200:baba::1/128",
|
||||
"119.29.29.29/32",
|
||||
"1.12.12.12/32",
|
||||
"120.53.53.53/32",
|
||||
"2402:4e00::/128",
|
||||
"2402:4e00:1::/128",
|
||||
"180.76.76.76/32",
|
||||
"2400:da00::6666/128",
|
||||
"114.114.114.114/32",
|
||||
"114.114.115.115/32",
|
||||
"180.184.1.1/32",
|
||||
"180.184.2.2/32",
|
||||
"101.226.4.6/32",
|
||||
"218.30.118.6/32",
|
||||
"123.125.81.6/32",
|
||||
"140.207.198.6/32",
|
||||
"geoip:cn"
|
||||
]
|
||||
},
|
||||
@@ -64,13 +97,7 @@
|
||||
"remarks": "绕过中国域名",
|
||||
"outboundTag": "direct",
|
||||
"domain": [
|
||||
"domain:dns.alidns.com",
|
||||
"domain:doh.pub",
|
||||
"domain:dot.pub",
|
||||
"domain:doh.360.cn",
|
||||
"domain:dot.360.cn",
|
||||
"geosite:cn",
|
||||
"geosite:geolocation-cn"
|
||||
"geosite:cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
"rules": [
|
||||
{
|
||||
"rule_set": [
|
||||
"geosite-cn",
|
||||
"geosite-geolocation-cn"
|
||||
"geosite-cn"
|
||||
],
|
||||
"server": "local"
|
||||
},
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
{
|
||||
"address": "223.5.5.5",
|
||||
"domains": [
|
||||
"geosite:cn",
|
||||
"geosite:geolocation-cn"
|
||||
"geosite:cn"
|
||||
],
|
||||
"expectIPs": [
|
||||
"geoip:cn"
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
"type": "tun",
|
||||
"tag": "tun-in",
|
||||
"interface_name": "singbox_tun",
|
||||
"inet4_address": "172.19.0.1/30",
|
||||
"inet6_address": "fdfe:dcba:9876::1/126",
|
||||
"address": [
|
||||
"172.18.0.1/30",
|
||||
"fdfe:dcba:9876::1/126"
|
||||
],
|
||||
"mtu": 9000,
|
||||
"auto_route": true,
|
||||
"strict_route": false,
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>7.0.8</Version>
|
||||
<Version>7.2.1</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<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.Fody" Version="19.5.41" />
|
||||
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
|
||||
<PackageReference Include="Splat.NLog" Version="15.2.22" />
|
||||
<PackageReference Include="WebDav.Client" Version="2.8.0" />
|
||||
<PackageReference Include="YamlDotNet" Version="16.1.3" />
|
||||
<PackageReference Include="YamlDotNet" Version="16.2.0" />
|
||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||
<PackageReference Include="CliWrap" Version="3.6.7" />
|
||||
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
|
||||
@@ -33,6 +33,7 @@
|
||||
<EmbeddedResource Include="Sample\custom_routing_white" />
|
||||
<EmbeddedResource Include="Sample\dns_singbox_normal" />
|
||||
<EmbeddedResource Include="Sample\dns_v2ray_normal" />
|
||||
<EmbeddedResource Include="Sample\pac" />
|
||||
<EmbeddedResource Include="Sample\SampleClientConfig" />
|
||||
<EmbeddedResource Include="Sample\SampleHttpRequest" />
|
||||
<EmbeddedResource Include="Sample\SampleHttpResponse" />
|
||||
@@ -46,12 +47,6 @@
|
||||
<EmbeddedResource Include="Sample\linux_autostart_config" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PacLib\PacLib.csproj" />
|
||||
<ProjectReference Include="..\ProtosLib\ProtosLib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Resx\ResUI.Designer.cs">
|
||||
<DependentUpon>ResUI.resx</DependentUpon>
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
ret.Msg = ResUI.CheckServerSettings;
|
||||
return ret;
|
||||
}
|
||||
if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.splithttp))
|
||||
if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))
|
||||
{
|
||||
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
|
||||
return ret;
|
||||
@@ -90,8 +90,8 @@ namespace ServiceLib.Services.CoreConfig
|
||||
|
||||
ret.Msg = ResUI.InitialConfiguration;
|
||||
|
||||
string result = Utils.GetEmbedText(Global.SingboxSampleClient);
|
||||
string txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||
var result = Utils.GetEmbedText(Global.SingboxSampleClient);
|
||||
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
||||
{
|
||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||
@@ -119,10 +119,10 @@ namespace ServiceLib.Services.CoreConfig
|
||||
|
||||
await GenLog(singboxConfig);
|
||||
//GenDns(new(), singboxConfig);
|
||||
singboxConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts.
|
||||
singboxConfig.inbounds.Clear();
|
||||
singboxConfig.outbounds.RemoveAt(0);
|
||||
|
||||
int httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
||||
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
|
||||
|
||||
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.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);
|
||||
if (Utils.IsNotEmpty(routing.DomainStrategy4Singbox))
|
||||
{
|
||||
inbound.domain_strategy = routing.DomainStrategy4Singbox;
|
||||
}
|
||||
inbound.domain_strategy = routing.DomainStrategy4Singbox;
|
||||
}
|
||||
|
||||
//http
|
||||
@@ -558,7 +555,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
//tunInbound.sniff_override_destination = _config.inbound[0].routeOnly ? false : _config.inbound[0].sniffingEnabled;
|
||||
if (_config.TunModeItem.EnableIPv6Address == false)
|
||||
{
|
||||
tunInbound.inet6_address = null;
|
||||
tunInbound.address = ["172.18.0.1/30"];
|
||||
}
|
||||
|
||||
singboxConfig.inbounds.Add(tunInbound);
|
||||
@@ -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);
|
||||
if (routing != null)
|
||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
||||
foreach (var item in rules ?? [])
|
||||
{
|
||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
||||
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 ?? [])
|
||||
if (item.Enabled)
|
||||
{
|
||||
await GenRoutingUserRule(item, singboxConfig.route.rules);
|
||||
}
|
||||
@@ -1334,20 +1316,18 @@ namespace ServiceLib.Services.CoreConfig
|
||||
|
||||
//load custom ruleset file
|
||||
List<Ruleset4Sbox> customRulesets = [];
|
||||
if (_config.RoutingBasicItem.EnableRoutingAdvanced)
|
||||
|
||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||
if (Utils.IsNotEmpty(routing.CustomRulesetPath4Singbox))
|
||||
{
|
||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||
if (Utils.IsNotEmpty(routing.CustomRulesetPath4Singbox))
|
||||
var result = Utils.LoadResource(routing.CustomRulesetPath4Singbox);
|
||||
if (Utils.IsNotEmpty(result))
|
||||
{
|
||||
var result = Utils.LoadResource(routing.CustomRulesetPath4Singbox);
|
||||
if (Utils.IsNotEmpty(result))
|
||||
{
|
||||
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
|
||||
.Where(t => t.tag != null)
|
||||
.Where(t => t.type != null)
|
||||
.Where(t => t.format != null)
|
||||
.ToList();
|
||||
}
|
||||
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
|
||||
.Where(t => t.tag != null)
|
||||
.Where(t => t.type != null)
|
||||
.Where(t => t.format != null)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,12 @@ namespace ServiceLib.Services.CoreConfig
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (node.GetNetwork() is nameof(ETransport.quic))
|
||||
{
|
||||
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.Msg = ResUI.InitialConfiguration;
|
||||
|
||||
var result = Utils.GetEmbedText(Global.V2raySampleClient);
|
||||
@@ -210,8 +216,8 @@ namespace ServiceLib.Services.CoreConfig
|
||||
|
||||
ret.Msg = ResUI.InitialConfiguration;
|
||||
|
||||
string result = Utils.GetEmbedText(Global.V2raySampleClient);
|
||||
string txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
||||
var result = Utils.GetEmbedText(Global.V2raySampleClient);
|
||||
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
||||
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
|
||||
{
|
||||
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||
@@ -238,10 +244,11 @@ namespace ServiceLib.Services.CoreConfig
|
||||
}
|
||||
|
||||
await GenLog(v2rayConfig);
|
||||
v2rayConfig.inbounds.Clear(); // Remove "proxy" service for speedtest, avoiding port conflicts.
|
||||
v2rayConfig.outbounds.RemoveAt(0);
|
||||
v2rayConfig.inbounds.Clear();
|
||||
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)
|
||||
{
|
||||
@@ -264,7 +271,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
|
||||
//find unused port
|
||||
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)
|
||||
{
|
||||
@@ -288,16 +295,6 @@ namespace ServiceLib.Services.CoreConfig
|
||||
it.Port = port;
|
||||
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
|
||||
if (item is null)
|
||||
{
|
||||
@@ -320,6 +317,16 @@ namespace ServiceLib.Services.CoreConfig
|
||||
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);
|
||||
await GenOutbound(item, outbound);
|
||||
outbound.tag = Global.ProxyTag + inbound.port.ToString();
|
||||
@@ -366,8 +373,8 @@ namespace ServiceLib.Services.CoreConfig
|
||||
else
|
||||
{
|
||||
v2rayConfig.log.loglevel = _config.CoreBasicItem.Loglevel;
|
||||
v2rayConfig.log.access = "";
|
||||
v2rayConfig.log.error = "";
|
||||
v2rayConfig.log.access = null;
|
||||
v2rayConfig.log.error = null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -460,33 +467,17 @@ namespace ServiceLib.Services.CoreConfig
|
||||
v2rayConfig.routing.domainStrategy = _config.RoutingBasicItem.DomainStrategy;
|
||||
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 (routing != null)
|
||||
if (Utils.IsNotEmpty(routing.DomainStrategy))
|
||||
{
|
||||
if (Utils.IsNotEmpty(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);
|
||||
}
|
||||
}
|
||||
v2rayConfig.routing.domainStrategy = routing.DomainStrategy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var lockedItem = await ConfigHandler.GetLockedRoutingItem(_config);
|
||||
if (lockedItem != null)
|
||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
|
||||
foreach (var item in rules)
|
||||
{
|
||||
var rules = JsonUtils.Deserialize<List<RulesItem>>(lockedItem.RuleSet);
|
||||
foreach (var item in rules)
|
||||
if (item.Enabled)
|
||||
{
|
||||
var item2 = JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item));
|
||||
await GenRoutingUserRule(item2, v2rayConfig);
|
||||
@@ -920,23 +911,34 @@ namespace ServiceLib.Services.CoreConfig
|
||||
streamSettings.httpupgradeSettings = httpupgradeSettings;
|
||||
|
||||
break;
|
||||
//splithttp
|
||||
case nameof(ETransport.splithttp):
|
||||
SplithttpSettings4Ray splithttpSettings = new()
|
||||
//xhttp
|
||||
case nameof(ETransport.xhttp):
|
||||
streamSettings.network = ETransport.xhttp.ToString();
|
||||
XhttpSettings4Ray xhttpSettings = new()
|
||||
{
|
||||
maxUploadSize = 1000000,
|
||||
maxConcurrentUploads = 10
|
||||
scMaxEachPostBytes = "500000-1000000",
|
||||
scMaxConcurrentPosts = "50-100",
|
||||
scMinPostsIntervalMs = "30-50"
|
||||
};
|
||||
|
||||
if (Utils.IsNotEmpty(node.Path))
|
||||
{
|
||||
splithttpSettings.path = node.Path;
|
||||
xhttpSettings.path = node.Path;
|
||||
}
|
||||
if (Utils.IsNotEmpty(host))
|
||||
{
|
||||
splithttpSettings.host = host;
|
||||
xhttpSettings.host = host;
|
||||
}
|
||||
streamSettings.splithttpSettings = splithttpSettings;
|
||||
if (Utils.IsNotEmpty(node.HeaderType) && Global.XhttpMode.Contains(node.HeaderType))
|
||||
{
|
||||
xhttpSettings.mode = node.HeaderType;
|
||||
}
|
||||
if (Utils.IsNotEmpty(node.Extra))
|
||||
{
|
||||
xhttpSettings.extra = JsonUtils.ParseJson(node.Extra);
|
||||
}
|
||||
|
||||
streamSettings.xhttpSettings = xhttpSettings;
|
||||
|
||||
break;
|
||||
//h2
|
||||
@@ -1006,18 +1008,17 @@ namespace ServiceLib.Services.CoreConfig
|
||||
//request Host
|
||||
string request = Utils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
|
||||
string[] arrHost = host.Split(',');
|
||||
string host2 = string.Join("\",\"", arrHost);
|
||||
request = request.Replace("$requestHost$", $"\"{host2}\"");
|
||||
//request = request.Replace("$requestHost$", string.Format("\"{0}\"", config.requestHost()));
|
||||
request = request.Replace("$requestUserAgent$", $"\"{useragent}\"");
|
||||
string host2 = string.Join(",".AppendQuotes(), arrHost);
|
||||
request = request.Replace("$requestHost$", $"{host2.AppendQuotes()}");
|
||||
request = request.Replace("$requestUserAgent$", $"{useragent.AppendQuotes()}");
|
||||
//Path
|
||||
string pathHttp = @"/";
|
||||
if (Utils.IsNotEmpty(node.Path))
|
||||
{
|
||||
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);
|
||||
|
||||
streamSettings.tcpSettings = tcpSettings;
|
||||
@@ -1120,17 +1121,14 @@ namespace ServiceLib.Services.CoreConfig
|
||||
if (_config.GuiItem.EnableStatistics)
|
||||
{
|
||||
string tag = EInboundProtocol.api.ToString();
|
||||
API4Ray apiObj = new();
|
||||
Metrics4Ray apiObj = new();
|
||||
Policy4Ray policyObj = new();
|
||||
SystemPolicy4Ray policySystemSetting = new();
|
||||
|
||||
string[] services = { "StatsService" };
|
||||
|
||||
v2rayConfig.stats = new Stats4Ray();
|
||||
|
||||
apiObj.tag = tag;
|
||||
apiObj.services = services.ToList();
|
||||
v2rayConfig.api = apiObj;
|
||||
v2rayConfig.metrics = apiObj;
|
||||
|
||||
policySystemSetting.statsOutboundDownlink = true;
|
||||
policySystemSetting.statsOutboundUplink = true;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
106
v2rayN/ServiceLib/Services/Statistics/StatisticsXrayService.cs
Normal file
106
v2rayN/ServiceLib/Services/Statistics/StatisticsXrayService.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
namespace ServiceLib.Services.Statistics
|
||||
{
|
||||
public class StatisticsXrayService
|
||||
{
|
||||
private const long linkBase = 1024;
|
||||
private string _url;
|
||||
private ServerSpeedItem _serverSpeedItem = new();
|
||||
private Config _config;
|
||||
private bool _exitFlag;
|
||||
private Action<ServerSpeedItem>? _updateFunc;
|
||||
|
||||
public StatisticsXrayService(Config config, Action<ServerSpeedItem> updateFunc)
|
||||
{
|
||||
_config = config;
|
||||
_updateFunc = updateFunc;
|
||||
_exitFlag = false;
|
||||
_url = $"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort}/debug/vars";
|
||||
|
||||
Task.Run(Run);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_exitFlag = true;
|
||||
}
|
||||
|
||||
private async void Run()
|
||||
{
|
||||
while (!_exitFlag)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
try
|
||||
{
|
||||
if (_config.RunningCoreType != ECoreType.Xray)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var result = await HttpClientHelper.Instance.TryGetAsync(_url);
|
||||
if (result != null)
|
||||
{
|
||||
var server = ParseOutput(result) ?? new ServerSpeedItem();
|
||||
_updateFunc?.Invoke(server);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ServerSpeedItem? ParseOutput(string result)
|
||||
{
|
||||
try
|
||||
{
|
||||
var source = JsonUtils.Deserialize<V2rayMetricsVars>(result);
|
||||
if (source?.stats?.outbound == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ServerSpeedItem server = new();
|
||||
foreach (string key in source.stats.outbound.Keys)
|
||||
{
|
||||
var value = source.stats.outbound[key];
|
||||
if (value == null) continue;
|
||||
var state = JsonUtils.Deserialize<V2rayMetricsVarsLink>(value.ToString());
|
||||
|
||||
if (key.StartsWith(Global.ProxyTag))
|
||||
{
|
||||
server.ProxyUp += state.uplink / linkBase;
|
||||
server.ProxyDown += state.downlink / linkBase;
|
||||
}
|
||||
else if (key == Global.DirectTag)
|
||||
{
|
||||
server.DirectUp = state.uplink / linkBase;
|
||||
server.DirectDown = state.downlink / linkBase;
|
||||
}
|
||||
}
|
||||
|
||||
if (server.DirectDown < _serverSpeedItem.DirectDown || server.ProxyDown < _serverSpeedItem.ProxyDown)
|
||||
{
|
||||
_serverSpeedItem = new();
|
||||
return null;
|
||||
}
|
||||
|
||||
ServerSpeedItem curItem = new()
|
||||
{
|
||||
ProxyUp = server.ProxyUp - _serverSpeedItem.ProxyUp,
|
||||
ProxyDown = server.ProxyDown - _serverSpeedItem.ProxyDown,
|
||||
DirectUp = server.DirectUp - _serverSpeedItem.DirectUp,
|
||||
DirectDown = server.DirectDown - _serverSpeedItem.DirectDown,
|
||||
};
|
||||
_serverSpeedItem = server;
|
||||
return curItem;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,8 +244,17 @@ namespace ServiceLib.Services
|
||||
|
||||
public async Task RunAvailabilityCheck(Action<bool, string> updateFunc)
|
||||
{
|
||||
var time = await new DownloadService().RunAvailabilityCheck(null);
|
||||
updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time));
|
||||
var downloadHandle = new DownloadService();
|
||||
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
|
||||
|
||||
@@ -267,7 +267,7 @@ namespace ServiceLib.ViewModels
|
||||
var filesList = (new DirectoryInfo(toPath)).GetFiles().Select(u => u.FullName).ToList();
|
||||
foreach (var file in filesList)
|
||||
{
|
||||
await Utils.SetLinuxChmod(Path.Combine(toPath, item.CoreType));
|
||||
await Utils.SetLinuxChmod(Path.Combine(toPath, item.CoreType.ToLower()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -219,6 +219,7 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
await Reload();
|
||||
await AutoHideStartup();
|
||||
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
|
||||
}
|
||||
|
||||
#endregion Init
|
||||
@@ -323,6 +324,7 @@ namespace ServiceLib.ViewModels
|
||||
if (process.Id > 0)
|
||||
{
|
||||
await MyAppExitAsync(false);
|
||||
await MyAppExitAsync(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,6 +533,10 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
Utils.ProcessStart("nautilus", Utils.GetConfigPath());
|
||||
}
|
||||
else if (Utils.IsOSX())
|
||||
{
|
||||
Utils.ProcessStart("open", Utils.GetConfigPath());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Setting
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace ServiceLib.ViewModels
|
||||
[Reactive] public bool EnableUpdateSubOnlyRemarksExist { get; set; }
|
||||
[Reactive] public bool EnableSecurityProtocolTls13 { get; set; }
|
||||
[Reactive] public bool AutoHideStartup { get; set; }
|
||||
[Reactive] public bool Hide2TrayWhenClose { get; set; }
|
||||
[Reactive] public bool EnableDragDropSort { get; set; }
|
||||
[Reactive] public bool DoubleClick2Activate { get; set; }
|
||||
[Reactive] public int AutoUpdateInterval { get; set; }
|
||||
@@ -85,6 +86,7 @@ namespace ServiceLib.ViewModels
|
||||
[Reactive] public int TunMtu { get; set; }
|
||||
[Reactive] public bool TunEnableExInbound { get; set; }
|
||||
[Reactive] public bool TunEnableIPv6Address { get; set; }
|
||||
[Reactive] public string TunLinuxSudoPassword { get; set; }
|
||||
|
||||
#endregion Tun mode
|
||||
|
||||
@@ -165,6 +167,7 @@ namespace ServiceLib.ViewModels
|
||||
EnableUpdateSubOnlyRemarksExist = _config.UiItem.EnableUpdateSubOnlyRemarksExist;
|
||||
EnableSecurityProtocolTls13 = _config.GuiItem.EnableSecurityProtocolTls13;
|
||||
AutoHideStartup = _config.UiItem.AutoHideStartup;
|
||||
Hide2TrayWhenClose = _config.UiItem.Hide2TrayWhenClose;
|
||||
EnableDragDropSort = _config.UiItem.EnableDragDropSort;
|
||||
DoubleClick2Activate = _config.UiItem.DoubleClick2Activate;
|
||||
AutoUpdateInterval = _config.GuiItem.AutoUpdateInterval;
|
||||
@@ -197,6 +200,7 @@ namespace ServiceLib.ViewModels
|
||||
TunMtu = _config.TunModeItem.Mtu;
|
||||
TunEnableExInbound = _config.TunModeItem.EnableExInbound;
|
||||
TunEnableIPv6Address = _config.TunModeItem.EnableIPv6Address;
|
||||
TunLinuxSudoPassword = _config.TunModeItem.LinuxSudoPwd;
|
||||
|
||||
#endregion Tun mode
|
||||
|
||||
@@ -314,6 +318,7 @@ namespace ServiceLib.ViewModels
|
||||
_config.UiItem.EnableUpdateSubOnlyRemarksExist = EnableUpdateSubOnlyRemarksExist;
|
||||
_config.GuiItem.EnableSecurityProtocolTls13 = EnableSecurityProtocolTls13;
|
||||
_config.UiItem.AutoHideStartup = AutoHideStartup;
|
||||
_config.UiItem.Hide2TrayWhenClose = Hide2TrayWhenClose;
|
||||
_config.GuiItem.AutoUpdateInterval = AutoUpdateInterval;
|
||||
_config.UiItem.EnableDragDropSort = EnableDragDropSort;
|
||||
_config.UiItem.DoubleClick2Activate = DoubleClick2Activate;
|
||||
@@ -340,6 +345,10 @@ namespace ServiceLib.ViewModels
|
||||
_config.TunModeItem.Mtu = TunMtu;
|
||||
_config.TunModeItem.EnableExInbound = TunEnableExInbound;
|
||||
_config.TunModeItem.EnableIPv6Address = TunEnableIPv6Address;
|
||||
if (TunLinuxSudoPassword != _config.TunModeItem.LinuxSudoPwd)
|
||||
{
|
||||
_config.TunModeItem.LinuxSudoPwd = DesUtils.Encrypt(TunLinuxSudoPassword);
|
||||
}
|
||||
|
||||
//coreType
|
||||
await SaveCoreType();
|
||||
|
||||
@@ -479,7 +479,10 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
await ConfigHandler.RemoveServer(_config, lstSelecteds);
|
||||
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
||||
|
||||
if (lstSelecteds.Count == _profileItems.Count)
|
||||
{
|
||||
_profileItems.Clear();
|
||||
}
|
||||
RefreshServers();
|
||||
if (exists)
|
||||
{
|
||||
@@ -726,7 +729,7 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
return;
|
||||
}
|
||||
var result = await CoreConfigHandler.GenerateClientConfig(item, null);
|
||||
var result = await CoreConfigHandler.GenerateClientConfig(item, fileName);
|
||||
if (result.Success != true)
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(result.Msg);
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace ServiceLib.ViewModels
|
||||
return;
|
||||
}
|
||||
//NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
||||
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||
await _updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,6 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
public class RoutingSettingViewModel : MyReactiveObject
|
||||
{
|
||||
private RoutingItem _lockedItem;
|
||||
private List<RulesItem> _lockedRules;
|
||||
|
||||
#region Reactive
|
||||
|
||||
private IObservableCollection<RoutingItemModel> _routingItems = new ObservableCollectionExtended<RoutingItemModel>();
|
||||
@@ -20,12 +17,6 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
public IList<RoutingItemModel> SelectedSources { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool enableRoutingAdvanced { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool enableRoutingBasic { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string domainStrategy { get; set; }
|
||||
|
||||
@@ -35,25 +26,6 @@ namespace ServiceLib.ViewModels
|
||||
[Reactive]
|
||||
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> RoutingAdvancedRemoveCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> RoutingAdvancedSetDefaultCmd { get; }
|
||||
@@ -73,15 +45,6 @@ namespace ServiceLib.ViewModels
|
||||
x => x.SelectedSource,
|
||||
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 () =>
|
||||
{
|
||||
await RoutingAdvancedEditAsync(true);
|
||||
@@ -111,67 +74,14 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
SelectedSource = new();
|
||||
|
||||
enableRoutingAdvanced = true;//TODO _config.RoutingBasicItem.EnableRoutingAdvanced;
|
||||
domainStrategy = _config.RoutingBasicItem.DomainStrategy;
|
||||
domainMatcher = _config.RoutingBasicItem.DomainMatcher;
|
||||
domainStrategy4Singbox = _config.RoutingBasicItem.DomainStrategy4Singbox;
|
||||
|
||||
await ConfigHandler.InitBuiltinRouting(_config);
|
||||
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
|
||||
|
||||
public async Task RefreshRoutingItems()
|
||||
@@ -205,12 +115,9 @@ namespace ServiceLib.ViewModels
|
||||
private async Task SaveRoutingAsync()
|
||||
{
|
||||
_config.RoutingBasicItem.DomainStrategy = domainStrategy;
|
||||
_config.RoutingBasicItem.EnableRoutingAdvanced = enableRoutingAdvanced;
|
||||
_config.RoutingBasicItem.DomainMatcher = domainMatcher;
|
||||
_config.RoutingBasicItem.DomainStrategy4Singbox = domainStrategy4Singbox;
|
||||
|
||||
await EndBindingLockedData();
|
||||
|
||||
if (await ConfigHandler.SaveConfig(_config) == 0)
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
||||
@@ -224,18 +131,6 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
#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)
|
||||
{
|
||||
RoutingItem item;
|
||||
|
||||
@@ -108,7 +108,7 @@ namespace ServiceLib.ViewModels
|
||||
SelectedServer = new();
|
||||
RunningServerToolTipText = "-";
|
||||
|
||||
if (_config.TunModeItem.EnableTun && AppHandler.Instance.IsAdministrator)
|
||||
if (_config.TunModeItem.EnableTun && AllowEnableTun())
|
||||
{
|
||||
EnableTun = true;
|
||||
}
|
||||
@@ -347,11 +347,6 @@ namespace ServiceLib.ViewModels
|
||||
public async Task RefreshRoutingsMenu()
|
||||
{
|
||||
_routingItems.Clear();
|
||||
if (!_config.RoutingBasicItem.EnableRoutingAdvanced)
|
||||
{
|
||||
BlRouting = false;
|
||||
return;
|
||||
}
|
||||
|
||||
BlRouting = true;
|
||||
var routings = await AppHandler.Instance.RoutingItems();
|
||||
@@ -414,17 +409,37 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
_config.TunModeItem.EnableTun = EnableTun;
|
||||
// When running as a non-administrator, reboot to administrator mode
|
||||
if (EnableTun && !AppHandler.Instance.IsAdministrator)
|
||||
if (EnableTun && AllowEnableTun() == false)
|
||||
{
|
||||
_config.TunModeItem.EnableTun = false;
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
|
||||
return;
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
_config.TunModeItem.EnableTun = false;
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
|
||||
return;
|
||||
}
|
||||
//else if (Utils.IsLinux())
|
||||
//{
|
||||
// NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty);
|
||||
//}
|
||||
}
|
||||
await ConfigHandler.SaveConfig(_config);
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
|
||||
}
|
||||
}
|
||||
|
||||
private bool AllowEnableTun()
|
||||
{
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
return AppHandler.Instance.IsAdministrator;
|
||||
}
|
||||
else if (Utils.IsLinux())
|
||||
{
|
||||
return _config.TunModeItem.LinuxSudoPwd.IsNotEmpty();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion System proxy and Routings
|
||||
|
||||
#region UI
|
||||
@@ -454,7 +469,7 @@ namespace ServiceLib.ViewModels
|
||||
}
|
||||
else
|
||||
{
|
||||
InboundLanDisplay = $"{ResUI.LabLAN}:None";
|
||||
InboundLanDisplay = $"{ResUI.LabLAN}:{Global.None}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace v2rayN.Desktop.ViewModels
|
||||
public class ThemeSettingViewModel : MyReactiveObject
|
||||
{
|
||||
[Reactive] public bool ColorModeDark { get; set; }
|
||||
[Reactive] public bool FollowSystemTheme { get; set; }
|
||||
|
||||
[Reactive] public int CurrentFontSize { get; set; }
|
||||
|
||||
@@ -28,13 +29,14 @@ namespace v2rayN.Desktop.ViewModels
|
||||
|
||||
private void RestoreUI()
|
||||
{
|
||||
ModifyTheme(_config.UiItem.ColorModeDark);
|
||||
ModifyTheme();
|
||||
ModifyFontFamily();
|
||||
}
|
||||
|
||||
private void BindingUI()
|
||||
{
|
||||
ColorModeDark = _config.UiItem.ColorModeDark;
|
||||
FollowSystemTheme = _config.UiItem.FollowSystemTheme;
|
||||
CurrentFontSize = _config.UiItem.CurrentFontSize;
|
||||
CurrentLanguage = _config.UiItem.CurrentLanguage;
|
||||
|
||||
@@ -44,7 +46,18 @@ namespace v2rayN.Desktop.ViewModels
|
||||
if (_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);
|
||||
}
|
||||
});
|
||||
@@ -59,7 +72,6 @@ namespace v2rayN.Desktop.ViewModels
|
||||
_config.UiItem.CurrentFontSize = CurrentFontSize;
|
||||
double size = CurrentFontSize;
|
||||
ModifyFontSize(size);
|
||||
|
||||
ConfigHandler.SaveConfig(_config);
|
||||
}
|
||||
});
|
||||
@@ -79,12 +91,12 @@ namespace v2rayN.Desktop.ViewModels
|
||||
});
|
||||
}
|
||||
|
||||
private void ModifyTheme(bool isDarkTheme)
|
||||
private void ModifyTheme()
|
||||
{
|
||||
var app = Application.Current;
|
||||
if (app is not null)
|
||||
{
|
||||
app.RequestedThemeVariant = isDarkTheme ? ThemeVariant.Dark : ThemeVariant.Light;
|
||||
app.RequestedThemeVariant = FollowSystemTheme ? ThemeVariant.Default : (ColorModeDark ? ThemeVariant.Dark : ThemeVariant.Light);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
x:Name="txtPort"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="Margin8" />
|
||||
</Grid>
|
||||
@@ -164,7 +164,7 @@
|
||||
x:Name="txtAlterId"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="Margin8" />
|
||||
|
||||
@@ -458,7 +458,7 @@
|
||||
x:Name="cmbHeaderType8"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
Classes="Margin8" />
|
||||
</Grid>
|
||||
<Grid
|
||||
@@ -541,7 +541,7 @@
|
||||
x:Name="txtShortId9"
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="Margin8" />
|
||||
</Grid>
|
||||
@@ -584,7 +584,7 @@
|
||||
x:Name="cmbNetwork"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
Classes="Margin8" />
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
@@ -600,12 +600,50 @@
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
Text="{x:Static resx:ResUI.TbHeaderType}" />
|
||||
<ComboBox
|
||||
x:Name="cmbHeaderType"
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Classes="Margin8" />
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<ComboBox
|
||||
x:Name="cmbHeaderType"
|
||||
Width="200"
|
||||
Classes="Margin8" />
|
||||
|
||||
<Button
|
||||
x:Name="btnExtra"
|
||||
Width="30"
|
||||
Height="30"
|
||||
Margin="10,0"
|
||||
Theme="{DynamicResource BorderlessButton}">
|
||||
<Button.Content>
|
||||
<PathIcon
|
||||
Width="20"
|
||||
Height="20"
|
||||
Data="{StaticResource building_more}"
|
||||
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
Text="{x:Static resx:ResUI.TransportExtraTip}" />
|
||||
<TextBox
|
||||
x:Name="txtExtra"
|
||||
Width="400"
|
||||
MinHeight="100"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Classes="TextArea Margin8"
|
||||
MinLines="6"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
x:Name="tipHeaderType"
|
||||
Grid.Row="2"
|
||||
@@ -680,7 +718,7 @@
|
||||
x:Name="cmbStreamSecurity"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
Classes="Margin8" />
|
||||
</Grid>
|
||||
<Grid
|
||||
@@ -749,7 +787,7 @@
|
||||
x:Name="cmbAllowInsecure"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
Classes="Margin8" />
|
||||
</Grid>
|
||||
<Grid
|
||||
|
||||
@@ -208,6 +208,7 @@ namespace v2rayN.Desktop.Views
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.SelectedValue).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.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.Sni, v => v.txtSNI.Text).DisposeWith(disposables);
|
||||
@@ -299,6 +300,13 @@ namespace v2rayN.Desktop.Views
|
||||
cmbHeaderType.Items.Add(it);
|
||||
});
|
||||
}
|
||||
else if (network is nameof(ETransport.xhttp))
|
||||
{
|
||||
Global.XhttpMode.ForEach(it =>
|
||||
{
|
||||
cmbHeaderType.Items.Add(it);
|
||||
});
|
||||
}
|
||||
else if (network == nameof(ETransport.grpc))
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.GrpcGunMode);
|
||||
@@ -319,6 +327,7 @@ namespace v2rayN.Desktop.Views
|
||||
network = Global.DefaultNetwork;
|
||||
}
|
||||
labHeaderType.IsVisible = true;
|
||||
btnExtra.IsVisible = false;
|
||||
tipRequestHost.Text =
|
||||
tipPath.Text =
|
||||
tipHeaderType.Text = string.Empty;
|
||||
@@ -337,11 +346,18 @@ namespace v2rayN.Desktop.Views
|
||||
|
||||
case nameof(ETransport.ws):
|
||||
case nameof(ETransport.httpupgrade):
|
||||
case nameof(ETransport.splithttp):
|
||||
tipRequestHost.Text = ResUI.TransportRequestHostTip2;
|
||||
tipPath.Text = ResUI.TransportPathTip1;
|
||||
break;
|
||||
|
||||
case nameof(ETransport.xhttp):
|
||||
tipRequestHost.Text = ResUI.TransportRequestHostTip2;
|
||||
tipPath.Text = ResUI.TransportPathTip1;
|
||||
tipHeaderType.Text = ResUI.TransportHeaderTypeTip5;
|
||||
labHeaderType.IsVisible = false;
|
||||
btnExtra.IsVisible = true;
|
||||
break;
|
||||
|
||||
case nameof(ETransport.h2):
|
||||
tipRequestHost.Text = ResUI.TransportRequestHostTip3;
|
||||
tipPath.Text = ResUI.TransportPathTip2;
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<Border
|
||||
Width="500"
|
||||
Height="80"
|
||||
Margin="0"
|
||||
Margin="-2"
|
||||
VerticalAlignment="Center"
|
||||
Theme="{StaticResource CardBorder}">
|
||||
<Grid>
|
||||
|
||||
@@ -117,6 +117,11 @@ namespace v2rayN.Desktop.Views
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AppHandler.Instance.IsAdministrator)
|
||||
{
|
||||
this.Title = $"{Utils.GetVersion()} - {ResUI.TbSettingsLinuxSudoPasswordNotSudoRunApp}";
|
||||
NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordNotSudoRunApp);
|
||||
}
|
||||
menuRebootAsAdmin.IsVisible = false;
|
||||
menuSettingsSetUWP.IsVisible = false;
|
||||
menuGlobalHotkeySetting.IsVisible = false;
|
||||
@@ -282,6 +287,7 @@ namespace v2rayN.Desktop.Views
|
||||
e.Cancel = true;
|
||||
ShowHideWindow(false);
|
||||
break;
|
||||
|
||||
case WindowCloseReason.ApplicationShutdown or WindowCloseReason.OSShutdown:
|
||||
await ViewModel?.MyAppExitAsync(true);
|
||||
break;
|
||||
@@ -392,7 +398,7 @@ namespace v2rayN.Desktop.Views
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Utils.IsWindows())
|
||||
if (_config.UiItem.Hide2TrayWhenClose)
|
||||
{
|
||||
this.Hide();
|
||||
}
|
||||
|
||||
@@ -489,7 +489,19 @@
|
||||
HorizontalAlignment="Left"
|
||||
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
|
||||
Grid.Row="11"
|
||||
@@ -721,6 +733,7 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@@ -794,6 +807,27 @@
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="Margin8" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="7"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPassword}" />
|
||||
<TextBox
|
||||
x:Name="txtLinuxSudoPassword"
|
||||
Grid.Row="7"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
HorizontalAlignment="Left"
|
||||
Classes="Margin8" />
|
||||
<TextBlock
|
||||
Grid.Row="7"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
Text="{x:Static resx:ResUI.TbSettingsLinuxSudoPasswordTip}"
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
|
||||
@@ -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.EnableSecurityProtocolTls13, v => v.togEnableSecurityProtocolTls13.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.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CurrentFontFamily, v => v.cmbcurrentFontFamily.SelectedValue).DisposeWith(disposables);
|
||||
@@ -152,6 +153,7 @@ namespace v2rayN.Desktop.Views
|
||||
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunEnableExInbound, v => v.togEnableExInbound.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunLinuxSudoPassword, v => v.txtLinuxSudoPassword.Text).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.SelectedValue).DisposeWith(disposables);
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
Width="54"
|
||||
Height="30"
|
||||
Margin="20,0"
|
||||
Padding="2"
|
||||
Classes="Tertiary"
|
||||
Theme="{DynamicResource BorderlessSplitButton}"
|
||||
ToolTip.Tip="{x:Static resx:ResUI.menuProfileAutofitColumnWidth}">
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace v2rayN.Desktop.Views
|
||||
private void LstProfiles_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)
|
||||
{
|
||||
var source = e.Source as Border;
|
||||
if (source == null || source.Name != "CellBorder") return;
|
||||
if (source?.Name == "HeaderBackground") return;
|
||||
if (_config.UiItem.DoubleClick2Activate)
|
||||
{
|
||||
ViewModel?.SetDefaultServer();
|
||||
@@ -356,7 +356,7 @@ namespace v2rayN.Desktop.Views
|
||||
item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel);
|
||||
item2.DisplayIndex = displayIndex++;
|
||||
}
|
||||
if (item.Name.StartsWith("to"))
|
||||
if (item.Name.ToLower().StartsWith("to"))
|
||||
{
|
||||
if (!_config.GuiItem.EnableStatistics)
|
||||
{
|
||||
|
||||
@@ -43,11 +43,11 @@ namespace v2rayN.Desktop.Views
|
||||
{
|
||||
rulesItem.Protocol?.ForEach(it =>
|
||||
{
|
||||
clbProtocol.SelectedItems.Add(it);
|
||||
clbProtocol?.SelectedItems?.Add(it);
|
||||
});
|
||||
rulesItem.InboundTag?.ForEach(it =>
|
||||
{
|
||||
clbInboundTag.SelectedItems.Add(it);
|
||||
clbInboundTag?.SelectedItems?.Add(it);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
mc:Ignorable="d">
|
||||
|
||||
<DockPanel>
|
||||
|
||||
<StackPanel
|
||||
Classes="Margin8"
|
||||
DockPanel.Dock="Top"
|
||||
@@ -55,7 +54,6 @@
|
||||
Margin="8,0,0,0" />
|
||||
</StackPanel>
|
||||
|
||||
|
||||
<StackPanel
|
||||
HorizontalAlignment="Right"
|
||||
Classes="Margin8"
|
||||
@@ -134,9 +132,6 @@
|
||||
</DataGrid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
|
||||
</DockPanel>
|
||||
|
||||
</DockPanel>
|
||||
</Window>
|
||||
@@ -1,4 +1,5 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Threading;
|
||||
@@ -41,7 +42,7 @@ namespace v2rayN.Desktop.Views
|
||||
this.Bind(ViewModel, vm => vm.SelectedRouting, v => v.cmbRoutings2.SelectedItem).DisposeWith(disposables);
|
||||
});
|
||||
|
||||
spEnableTun.IsVisible = (Utils.IsWindows() || AppHandler.Instance.IsAdministrator);
|
||||
//spEnableTun.IsVisible = (Utils.IsWindows() || AppHandler.Instance.IsAdministrator);
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
@@ -77,6 +78,9 @@ namespace v2rayN.Desktop.Views
|
||||
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,41 @@
|
||||
Classes="Margin8"
|
||||
TextWrapping="Wrap"
|
||||
Watermark="{x:Static resx:ResUI.SubUrlTips}" />
|
||||
<Button
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
Width="30"
|
||||
Height="30"
|
||||
Margin="10,0"
|
||||
Theme="{DynamicResource BorderlessButton}">
|
||||
<Button.Content>
|
||||
<PathIcon
|
||||
Width="20"
|
||||
Height="20"
|
||||
Data="{StaticResource building_more}"
|
||||
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
Text="{x:Static resx:ResUI.LvMoreUrl}" />
|
||||
<TextBox
|
||||
x:Name="txtMoreUrl"
|
||||
Width="400"
|
||||
MinHeight="100"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Classes="TextArea Margin8"
|
||||
MinLines="4"
|
||||
TextWrapping="Wrap"
|
||||
Watermark="{x:Static resx:ResUI.SubUrlTips}" />
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
@@ -245,24 +280,6 @@
|
||||
Classes="Margin8"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="13"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
Text="{x:Static resx:ResUI.LvMoreUrl}" />
|
||||
<TextBox
|
||||
x:Name="txtMoreUrl"
|
||||
Grid.Row="14"
|
||||
Grid.Column="1"
|
||||
MinHeight="100"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Classes="TextArea Margin8"
|
||||
MinLines="4"
|
||||
TextWrapping="Wrap"
|
||||
Watermark="{x:Static resx:ResUI.SubUrlTips}" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
Binding="{Binding Remarks}"
|
||||
Header="{x:Static resx:ResUI.LvRemarks}" />
|
||||
<DataGridTextColumn
|
||||
Width="150"
|
||||
Width="*"
|
||||
Binding="{Binding Url}"
|
||||
Header="{x:Static resx:ResUI.LvUrl}" />
|
||||
<DataGridCheckBoxColumn
|
||||
|
||||
@@ -33,7 +33,14 @@
|
||||
Text="{x:Static resx:ResUI.TbSettingsColorMode}" />
|
||||
<ToggleSwitch x:Name="togDarkMode" Classes="Margin8" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="100"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Margin8"
|
||||
Text="{x:Static resx:ResUI.TbSettingsFollowSystemTheme}" />
|
||||
<ToggleSwitch x:Name="togFollowSystemTheme" Classes="Margin8" />
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Width="100"
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace v2rayN.Desktop.Views
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.togFollowSystemTheme.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.SelectedValue).DisposeWith(disposables);
|
||||
});
|
||||
|
||||
@@ -20,16 +20,16 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.2.0" />
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.2.0" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.2.0" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.0" />
|
||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.2.0" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.2.0" />
|
||||
<PackageReference Include="Avalonia" Version="11.2.1" />
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.2.1" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.2.1" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.1" />
|
||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.2.1" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.2.1" />
|
||||
<PackageReference Include="DialogHost.Avalonia" Version="0.8.1" />
|
||||
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0" />
|
||||
<PackageReference Include="Semi.Avalonia" Version="11.2.0" />
|
||||
<PackageReference Include="Semi.Avalonia.DataGrid" Version="11.2.0" />
|
||||
<PackageReference Include="Semi.Avalonia" Version="11.2.1" />
|
||||
<PackageReference Include="Semi.Avalonia.DataGrid" Version="11.2.1" />
|
||||
<PackageReference Include="ReactiveUI" Version="20.1.63" />
|
||||
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -5,10 +5,6 @@ VisualStudioVersion = 17.3.32811.315
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "v2rayN", "v2rayN\v2rayN.csproj", "{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}"
|
||||
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}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceLib", "ServiceLib\ServiceLib.csproj", "{1B6456C4-FFAA-4298-80F6-7B689A6E9243}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "v2rayN.Desktop", "v2rayN.Desktop\v2rayN.Desktop.csproj", "{5D16541A-F971-4C17-9315-BB8955E3F984}"
|
||||
@@ -25,14 +21,6 @@ Global
|
||||
{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.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.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.Build.0 = Release|Any CPU
|
||||
{1B6456C4-FFAA-4298-80F6-7B689A6E9243}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1B6456C4-FFAA-4298-80F6-7B689A6E9243}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1B6456C4-FFAA-4298-80F6-7B689A6E9243}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
||||
@@ -62,11 +62,12 @@ namespace v2rayN
|
||||
BitmapSizeOptions.FromEmptyOptions());
|
||||
}
|
||||
|
||||
public static bool IsLightTheme()
|
||||
public static bool IsDarkTheme()
|
||||
{
|
||||
using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
|
||||
var value = key?.GetValue("AppsUseLightTheme");
|
||||
return value is int i && i > 0;
|
||||
var obj = key?.GetValue("AppsUseLightTheme");
|
||||
int.TryParse(obj?.ToString(), out var value);
|
||||
return value == 0;
|
||||
}
|
||||
|
||||
public static void RemoveTunDevice()
|
||||
|
||||
@@ -54,11 +54,6 @@ namespace v2rayN.Handler
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!config.RoutingBasicItem.EnableRoutingAdvanced)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var item = await ConfigHandler.GetDefaultRouting(config);
|
||||
if (item == null || Utils.IsNullOrEmpty(item.CustomIcon) || !File.Exists(item.CustomIcon))
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace v2rayN.ViewModels
|
||||
{
|
||||
_config = AppHandler.Instance.Config;
|
||||
|
||||
RegisterSystemColorSet(_config, Application.Current.MainWindow, (bool bl) => { ModifyTheme(bl); });
|
||||
RegisterSystemColorSet(_config, Application.Current.MainWindow, ModifyTheme);
|
||||
|
||||
BindingUI();
|
||||
RestoreUI();
|
||||
@@ -46,15 +46,7 @@ namespace v2rayN.ViewModels
|
||||
|
||||
private void RestoreUI()
|
||||
{
|
||||
if (FollowSystemTheme)
|
||||
{
|
||||
ModifyTheme(!WindowsUtils.IsLightTheme());
|
||||
}
|
||||
else
|
||||
{
|
||||
ModifyTheme(_config.UiItem.ColorModeDark);
|
||||
}
|
||||
|
||||
ModifyTheme();
|
||||
if (!_config.UiItem.ColorPrimaryName.IsNullOrEmpty())
|
||||
{
|
||||
var swatch = new SwatchesProvider().Swatches.FirstOrDefault(t => t.Name == _config.UiItem.ColorPrimaryName);
|
||||
@@ -87,7 +79,7 @@ namespace v2rayN.ViewModels
|
||||
if (_config.UiItem.ColorModeDark != ColorModeDark)
|
||||
{
|
||||
_config.UiItem.ColorModeDark = ColorModeDark;
|
||||
ModifyTheme(ColorModeDark);
|
||||
ModifyTheme();
|
||||
ConfigHandler.SaveConfig(_config);
|
||||
}
|
||||
});
|
||||
@@ -99,15 +91,8 @@ namespace v2rayN.ViewModels
|
||||
if (_config.UiItem.FollowSystemTheme != FollowSystemTheme)
|
||||
{
|
||||
_config.UiItem.FollowSystemTheme = FollowSystemTheme;
|
||||
ModifyTheme();
|
||||
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 isDarkTheme = FollowSystemTheme ? WindowsUtils.IsDarkTheme() : ColorModeDark;
|
||||
theme.SetBaseTheme(isDarkTheme ? BaseTheme.Dark : BaseTheme.Light);
|
||||
_paletteHelper.SetTheme(theme);
|
||||
WindowsUtils.SetDarkBorder(Application.Current.MainWindow, isDarkTheme);
|
||||
@@ -183,7 +169,7 @@ namespace v2rayN.ViewModels
|
||||
_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 hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
|
||||
@@ -196,7 +182,7 @@ namespace v2rayN.ViewModels
|
||||
{
|
||||
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.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)
|
||||
|
||||
@@ -17,6 +17,13 @@
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Popupbox.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin4}"
|
||||
@@ -128,7 +135,7 @@
|
||||
x:Name="txtPort"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
@@ -188,7 +195,7 @@
|
||||
x:Name="txtAlterId"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
@@ -513,7 +520,7 @@
|
||||
x:Name="cmbHeaderType8"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
</Grid>
|
||||
@@ -606,7 +613,7 @@
|
||||
x:Name="txtShortId9"
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
@@ -653,7 +660,7 @@
|
||||
x:Name="cmbNetwork"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
<TextBlock
|
||||
@@ -672,13 +679,40 @@
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbHeaderType}" />
|
||||
<ComboBox
|
||||
x:Name="cmbHeaderType"
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<ComboBox
|
||||
x:Name="cmbHeaderType"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<materialDesign:PopupBox
|
||||
x:Name="popExtra"
|
||||
HorizontalAlignment="Right"
|
||||
StaysOpen="True"
|
||||
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
|
||||
<StackPanel>
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TransportExtraTip}" />
|
||||
<TextBox
|
||||
x:Name="txtExtra"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Top"
|
||||
AcceptsReturn="True"
|
||||
MinLines="6"
|
||||
Style="{StaticResource MyOutlinedTextBox}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</materialDesign:PopupBox>
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
x:Name="tipHeaderType"
|
||||
Grid.Row="2"
|
||||
@@ -764,7 +798,7 @@
|
||||
x:Name="cmbStreamSecurity"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
</Grid>
|
||||
@@ -842,7 +876,7 @@
|
||||
x:Name="cmbAllowInsecure"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="100"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
</Grid>
|
||||
|
||||
@@ -202,6 +202,7 @@ namespace v2rayN.Views
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.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.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.Sni, v => v.txtSNI.Text).DisposeWith(disposables);
|
||||
@@ -219,7 +220,7 @@ namespace v2rayN.Views
|
||||
});
|
||||
|
||||
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)
|
||||
@@ -294,6 +295,13 @@ namespace v2rayN.Views
|
||||
cmbHeaderType.Items.Add(it);
|
||||
});
|
||||
}
|
||||
else if (network is nameof(ETransport.xhttp))
|
||||
{
|
||||
Global.XhttpMode.ForEach(it =>
|
||||
{
|
||||
cmbHeaderType.Items.Add(it);
|
||||
});
|
||||
}
|
||||
else if (network == nameof(ETransport.grpc))
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.GrpcGunMode);
|
||||
@@ -314,6 +322,7 @@ namespace v2rayN.Views
|
||||
network = Global.DefaultNetwork;
|
||||
}
|
||||
labHeaderType.Visibility = Visibility.Visible;
|
||||
popExtra.Visibility = Visibility.Hidden;
|
||||
tipRequestHost.Text =
|
||||
tipPath.Text =
|
||||
tipHeaderType.Text = string.Empty;
|
||||
@@ -332,11 +341,18 @@ namespace v2rayN.Views
|
||||
|
||||
case nameof(ETransport.ws):
|
||||
case nameof(ETransport.httpupgrade):
|
||||
case nameof(ETransport.splithttp):
|
||||
tipRequestHost.Text = ResUI.TransportRequestHostTip2;
|
||||
tipPath.Text = ResUI.TransportPathTip1;
|
||||
break;
|
||||
|
||||
case nameof(ETransport.xhttp):
|
||||
tipRequestHost.Text = ResUI.TransportRequestHostTip2;
|
||||
tipPath.Text = ResUI.TransportPathTip1;
|
||||
tipHeaderType.Text = ResUI.TransportHeaderTypeTip5;
|
||||
labHeaderType.Visibility = Visibility.Hidden;
|
||||
popExtra.Visibility = Visibility.Visible;
|
||||
break;
|
||||
|
||||
case nameof(ETransport.h2):
|
||||
tipRequestHost.Text = ResUI.TransportRequestHostTip3;
|
||||
tipPath.Text = ResUI.TransportPathTip2;
|
||||
|
||||
@@ -119,7 +119,6 @@
|
||||
Text="{x:Static resx:ResUI.menuRemoteBackupAndRestore}" />
|
||||
|
||||
<materialDesign:PopupBox
|
||||
Padding="8,0"
|
||||
HorizontalAlignment="Right"
|
||||
StaysOpen="True"
|
||||
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<reactiveui:ReactiveUserControl
|
||||
x:Class="v2rayN.Views.ClashConnectionsView"
|
||||
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
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:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
d:DesignHeight="450"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<reactiveui:ReactiveUserControl
|
||||
x:Class="v2rayN.Views.ClashProxiesView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:v2rayN.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:reactiveui="http://reactiveui.net"
|
||||
xmlns: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:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
xmlns:converters="clr-namespace:v2rayN.Converters"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
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.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)
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace v2rayN.Views
|
||||
|
||||
HotkeyHandler.Instance.IsPause = true;
|
||||
this.Closing += (s, e) => HotkeyHandler.Instance.IsPause = false;
|
||||
WindowsUtils.SetDarkBorder(this, _config.UiItem.FollowSystemTheme ? !WindowsUtils.IsLightTheme() : _config.UiItem.ColorModeDark);
|
||||
WindowsUtils.SetDarkBorder(this, _config.UiItem.FollowSystemTheme ? WindowsUtils.IsDarkTheme() : _config.UiItem.ColorModeDark);
|
||||
InitData();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
Height="700"
|
||||
MinWidth="900"
|
||||
x:TypeArguments="vms:MainWindowViewModel"
|
||||
ResizeMode="CanResizeWithGrip"
|
||||
ShowInTaskbar="True"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
@@ -276,7 +277,7 @@
|
||||
</Menu>
|
||||
|
||||
<materialDesign:PopupBox
|
||||
Padding="8,0"
|
||||
Padding="-2"
|
||||
HorizontalAlignment="Right"
|
||||
StaysOpen="True"
|
||||
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
|
||||
|
||||
@@ -76,8 +76,10 @@
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
IsReadOnly="True"
|
||||
IsReadOnlyCaretVisible="True"
|
||||
IsUndoEnabled="False"
|
||||
TextAlignment="Left"
|
||||
TextWrapping="Wrap"
|
||||
UndoLimit="0"
|
||||
VerticalScrollBarVisibility="Visible">
|
||||
<TextBox.ContextMenu>
|
||||
<ContextMenu Style="{StaticResource DefContextMenu}">
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace v2rayN.Views
|
||||
|
||||
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)
|
||||
|
||||
@@ -338,7 +338,7 @@ namespace v2rayN.Views
|
||||
item2.Width = item.Width;
|
||||
item2.DisplayIndex = displayIndex++;
|
||||
}
|
||||
if (item.Name.StartsWith("to"))
|
||||
if (item.Name.ToLower().StartsWith("to"))
|
||||
{
|
||||
if (!_config.GuiItem.EnableStatistics)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<reactiveui:ReactiveWindow
|
||||
x:Class="v2rayN.Views.RoutingRuleDetailsWindow"
|
||||
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
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:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
Title="{x:Static resx:ResUI.menuRoutingRuleDetailsSetting}"
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace v2rayN.Views
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.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)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<reactiveui:ReactiveWindow
|
||||
x:Class="v2rayN.Views.RoutingRuleSettingWindow"
|
||||
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
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:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
Title="{x:Static resx:ResUI.menuRoutingRuleSetting}"
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace v2rayN.Views
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.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)
|
||||
|
||||
@@ -28,23 +28,6 @@
|
||||
VerticalAlignment="Center"
|
||||
ClipToBounds="True"
|
||||
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}">
|
||||
<MenuItem x:Name="menuRoutingAdvanced" Padding="8,0">
|
||||
<MenuItem.Header>
|
||||
@@ -66,16 +49,6 @@
|
||||
Header="{x:Static resx:ResUI.menuRoutingAdvancedImportRules}" />
|
||||
</MenuItem>
|
||||
</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 />
|
||||
<TextBlock
|
||||
Margin="{StaticResource MarginLeft8}"
|
||||
@@ -224,107 +197,6 @@
|
||||
</DataGrid>
|
||||
</TabItem>
|
||||
</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>
|
||||
</reactiveui:ReactiveWindow>
|
||||
@@ -39,24 +39,10 @@ namespace v2rayN.Views
|
||||
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.enableRoutingAdvanced, v => v.togenableRoutingAdvanced.IsChecked).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.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.menuRoutingAdvancedAdd2).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);
|
||||
});
|
||||
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)
|
||||
@@ -102,11 +88,6 @@ namespace v2rayN.Views
|
||||
|
||||
private void RoutingSettingWindow_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (ViewModel?.enableRoutingBasic ?? false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
||||
{
|
||||
if (e.Key == Key.A)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<reactiveui:ReactiveWindow
|
||||
x:Class="v2rayN.Views.SubEditWindow"
|
||||
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
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:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
Title="{x:Static resx:ResUI.menuSubSetting}"
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace v2rayN.Views
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.FollowSystemTheme ? !WindowsUtils.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)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user