mirror of https://github.com/2dust/v2rayN
Full Config Template (#7576)
* Feat. custom config * Fixes TypeInfoResolver Exception * Adjust UI * Fixes * Adjust Avalonia UI * Add Detour Feature * Avoids detour for private networks * Rename * Adds Documentspull/7733/head
parent
dffc6d9a9b
commit
b5e0a77401
|
@ -29,6 +29,7 @@ public enum EViewAction
|
|||
DNSSettingWindow,
|
||||
RoutingSettingWindow,
|
||||
OptionSettingWindow,
|
||||
FullConfigTemplateWindow,
|
||||
GlobalHotkeySettingWindow,
|
||||
SubSettingWindow,
|
||||
DispatcherSpeedTest,
|
||||
|
|
|
@ -64,6 +64,7 @@ public sealed class AppHandler
|
|||
SQLiteHelper.Instance.CreateTable<RoutingItem>();
|
||||
SQLiteHelper.Instance.CreateTable<ProfileExItem>();
|
||||
SQLiteHelper.Instance.CreateTable<DNSItem>();
|
||||
SQLiteHelper.Instance.CreateTable<FullConfigTemplateItem>();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -203,6 +204,16 @@ public sealed class AppHandler
|
|||
return await SQLiteHelper.Instance.TableAsync<DNSItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType);
|
||||
}
|
||||
|
||||
public async Task<List<FullConfigTemplateItem>?> FullConfigTemplateItem()
|
||||
{
|
||||
return await SQLiteHelper.Instance.TableAsync<FullConfigTemplateItem>().ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<FullConfigTemplateItem?> GetFullConfigTemplateItem(ECoreType eCoreType)
|
||||
{
|
||||
return await SQLiteHelper.Instance.TableAsync<FullConfigTemplateItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType);
|
||||
}
|
||||
|
||||
#endregion SqliteHelper
|
||||
|
||||
#region Core Type
|
||||
|
|
|
@ -2238,6 +2238,54 @@ public class ConfigHandler
|
|||
|
||||
#endregion Simple DNS
|
||||
|
||||
#region Custom Config
|
||||
|
||||
public static async Task<int> InitBuiltinFullConfigTemplate(Config config)
|
||||
{
|
||||
var items = await AppHandler.Instance.FullConfigTemplateItem();
|
||||
if (items.Count <= 0)
|
||||
{
|
||||
var item = new FullConfigTemplateItem()
|
||||
{
|
||||
Remarks = "V2ray",
|
||||
CoreType = ECoreType.Xray,
|
||||
};
|
||||
await SaveFullConfigTemplate(config, item);
|
||||
|
||||
var item2 = new FullConfigTemplateItem()
|
||||
{
|
||||
Remarks = "sing-box",
|
||||
CoreType = ECoreType.sing_box,
|
||||
};
|
||||
await SaveFullConfigTemplate(config, item2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
public static async Task<int> SaveFullConfigTemplate(Config config, FullConfigTemplateItem item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (item.Id.IsNullOrEmpty())
|
||||
{
|
||||
item.Id = Utils.GetGuid(false);
|
||||
}
|
||||
|
||||
if (await SQLiteHelper.Instance.ReplaceAsync(item) > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Custom Config
|
||||
|
||||
#region Regional Presets
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
using SQLite;
|
||||
|
||||
namespace ServiceLib.Models;
|
||||
|
||||
[Serializable]
|
||||
public class FullConfigTemplateItem
|
||||
{
|
||||
[PrimaryKey]
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Remarks { get; set; }
|
||||
public bool Enabled { get; set; } = false;
|
||||
public ECoreType CoreType { get; set; }
|
||||
public string? Config { get; set; }
|
||||
public string? TunConfig { get; set; }
|
||||
public bool? AddProxyOnly { get; set; } = false;
|
||||
public string? ProxyDetour { get; set; }
|
||||
}
|
|
@ -186,6 +186,15 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please fill in the correct config template 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string FillCorrectConfigTemplateText {
|
||||
get {
|
||||
return ResourceManager.GetString("FillCorrectConfigTemplateText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please fill in the correct custom DNS 的本地化字符串。
|
||||
/// </summary>
|
||||
|
@ -933,6 +942,15 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Full Config Template Setting 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuFullConfigTemplate {
|
||||
get {
|
||||
return ResourceManager.GetString("menuFullConfigTemplate", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Global Hotkey Setting 的本地化字符串。
|
||||
/// </summary>
|
||||
|
@ -2229,6 +2247,15 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Do Not Add Non-Proxy Protocol Outbound 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbAddProxyProtocolOutboundOnly {
|
||||
get {
|
||||
return ResourceManager.GetString("TbAddProxyProtocolOutboundOnly", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Address 的本地化字符串。
|
||||
/// </summary>
|
||||
|
@ -2508,6 +2535,24 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbFullConfigTemplateDesc {
|
||||
get {
|
||||
return ResourceManager.GetString("TbFullConfigTemplateDesc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Enable Full Config Template 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbFullConfigTemplateEnable {
|
||||
get {
|
||||
return ResourceManager.GetString("TbFullConfigTemplateEnable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Global Hotkey Settings 的本地化字符串。
|
||||
/// </summary>
|
||||
|
@ -2724,6 +2769,24 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 v2ray Full Config Template 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbRayFullConfigTemplate {
|
||||
get {
|
||||
return ResourceManager.GetString("TbRayFullConfigTemplate", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbRayFullConfigTemplateDesc {
|
||||
get {
|
||||
return ResourceManager.GetString("TbRayFullConfigTemplateDesc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Alias (remarks) 的本地化字符串。
|
||||
/// </summary>
|
||||
|
@ -2886,6 +2949,24 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 sing-box Full Config Template 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBFullConfigTemplate {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBFullConfigTemplate", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add Outbound and Endpoint Config Only, Click to view the document 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBFullConfigTemplateDesc {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBFullConfigTemplateDesc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Resolve Outbound Domains 的本地化字符串。
|
||||
/// </summary>
|
||||
|
@ -3696,6 +3777,15 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Set Upstream Proxy Tag 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSetUpstreamProxyDetour {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSetUpstreamProxyDetour", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Short Id 的本地化字符串。
|
||||
/// </summary>
|
||||
|
|
|
@ -1470,4 +1470,34 @@
|
|||
<data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve">
|
||||
<value>Custom DNS Enabled, This Page's Settings Invalid</value>
|
||||
</data>
|
||||
<data name="FillCorrectConfigTemplateText" xml:space="preserve">
|
||||
<value>Please fill in the correct config template</value>
|
||||
</data>
|
||||
<data name="menuFullConfigTemplate" xml:space="preserve">
|
||||
<value>Full Config Template Setting</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateEnable" xml:space="preserve">
|
||||
<value>Enable Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplate" xml:space="preserve">
|
||||
<value>v2ray Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve">
|
||||
<value>Do Not Add Non-Proxy Protocol Outbound</value>
|
||||
</data>
|
||||
<data name="TbSetUpstreamProxyDetour" xml:space="preserve">
|
||||
<value>Set Upstream Proxy Tag</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplate" xml:space="preserve">
|
||||
<value>sing-box Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound and Endpoint Config Only, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1470,4 +1470,34 @@
|
|||
<data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve">
|
||||
<value>Custom DNS Enabled, This Page's Settings Invalid</value>
|
||||
</data>
|
||||
<data name="FillCorrectConfigTemplateText" xml:space="preserve">
|
||||
<value>Please fill in the correct config template</value>
|
||||
</data>
|
||||
<data name="menuFullConfigTemplate" xml:space="preserve">
|
||||
<value>Full Config Template Setting</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateEnable" xml:space="preserve">
|
||||
<value>Enable Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplate" xml:space="preserve">
|
||||
<value>v2ray Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve">
|
||||
<value>Do Not Add Non-Proxy Protocol Outbound</value>
|
||||
</data>
|
||||
<data name="TbSetUpstreamProxyDetour" xml:space="preserve">
|
||||
<value>Set Upstream Proxy Tag</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplate" xml:space="preserve">
|
||||
<value>sing-box Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound and Endpoint Config Only, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1470,4 +1470,34 @@
|
|||
<data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve">
|
||||
<value>Custom DNS Enabled, This Page's Settings Invalid</value>
|
||||
</data>
|
||||
<data name="FillCorrectConfigTemplateText" xml:space="preserve">
|
||||
<value>Please fill in the correct config template</value>
|
||||
</data>
|
||||
<data name="menuFullConfigTemplate" xml:space="preserve">
|
||||
<value>Full Config Template Setting</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateEnable" xml:space="preserve">
|
||||
<value>Enable Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplate" xml:space="preserve">
|
||||
<value>v2ray Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve">
|
||||
<value>Do Not Add Non-Proxy Protocol Outbound</value>
|
||||
</data>
|
||||
<data name="TbSetUpstreamProxyDetour" xml:space="preserve">
|
||||
<value>Set Upstream Proxy Tag</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplate" xml:space="preserve">
|
||||
<value>sing-box Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound and Endpoint Config Only, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1470,4 +1470,34 @@
|
|||
<data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve">
|
||||
<value>Custom DNS Enabled, This Page's Settings Invalid</value>
|
||||
</data>
|
||||
<data name="FillCorrectConfigTemplateText" xml:space="preserve">
|
||||
<value>Please fill in the correct config template</value>
|
||||
</data>
|
||||
<data name="menuFullConfigTemplate" xml:space="preserve">
|
||||
<value>Full Config Template Setting</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateEnable" xml:space="preserve">
|
||||
<value>Enable Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplate" xml:space="preserve">
|
||||
<value>v2ray Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve">
|
||||
<value>Do Not Add Non-Proxy Protocol Outbound</value>
|
||||
</data>
|
||||
<data name="TbSetUpstreamProxyDetour" xml:space="preserve">
|
||||
<value>Set Upstream Proxy Tag</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplate" xml:space="preserve">
|
||||
<value>sing-box Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound and Endpoint Config Only, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1467,4 +1467,34 @@
|
|||
<data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve">
|
||||
<value>自定义 DNS 已启用,此页面配置将无效</value>
|
||||
</data>
|
||||
<data name="FillCorrectConfigTemplateText" xml:space="preserve">
|
||||
<value>请填写正确的配置模板</value>
|
||||
</data>
|
||||
<data name="menuFullConfigTemplate" xml:space="preserve">
|
||||
<value>完整配置模板设置</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateEnable" xml:space="preserve">
|
||||
<value>启用完整配置模板</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplate" xml:space="preserve">
|
||||
<value>v2ray 完整配置模板</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>仅添加出站配置,routing.balancers 和 routing.rules.outboundTag,点击查看文档</value>
|
||||
</data>
|
||||
<data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve">
|
||||
<value>不添加非代理协议出站</value>
|
||||
</data>
|
||||
<data name="TbSetUpstreamProxyDetour" xml:space="preserve">
|
||||
<value>设置上游代理 tag</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplate" xml:space="preserve">
|
||||
<value>sing-box 完整配置模板</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>仅添加出站和端点配置,点击查看文档</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>此功能供高级用户和有特殊需求的用户使用。 启用此功能后,将忽略 Core 的基础设置,DNS 设置 ,路由设置。你需要保证系统代理的端口和流量统计等功能的配置正确,一切都由你来设置。</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1467,4 +1467,34 @@
|
|||
<data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve">
|
||||
<value>Custom DNS Enabled, This Page's Settings Invalid</value>
|
||||
</data>
|
||||
<data name="FillCorrectConfigTemplateText" xml:space="preserve">
|
||||
<value>Please fill in the correct config template</value>
|
||||
</data>
|
||||
<data name="menuFullConfigTemplate" xml:space="preserve">
|
||||
<value>Full Config Template Setting</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateEnable" xml:space="preserve">
|
||||
<value>Enable Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplate" xml:space="preserve">
|
||||
<value>v2ray Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve">
|
||||
<value>Do Not Add Non-Proxy Protocol Outbound</value>
|
||||
</data>
|
||||
<data name="TbSetUpstreamProxyDetour" xml:space="preserve">
|
||||
<value>Set Upstream Proxy Tag</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplate" xml:space="preserve">
|
||||
<value>sing-box Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound and Endpoint Config Only, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1,6 +1,7 @@
|
|||
using System.Data;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace ServiceLib.Services.CoreConfig;
|
||||
|
||||
|
@ -78,7 +79,9 @@ public class CoreConfigSingboxService
|
|||
|
||||
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||
ret.Success = true;
|
||||
ret.Data = JsonUtils.Serialize(singboxConfig);
|
||||
|
||||
var fullConfigTemplate = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.sing_box);
|
||||
ret.Data = await ApplyFullConfigTemplate(fullConfigTemplate, singboxConfig);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -430,7 +433,9 @@ public class CoreConfigSingboxService
|
|||
await ConvertGeo2Ruleset(singboxConfig);
|
||||
|
||||
ret.Success = true;
|
||||
ret.Data = JsonUtils.Serialize(singboxConfig);
|
||||
|
||||
var fullConfigTemplate = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.sing_box);
|
||||
ret.Data = await ApplyFullConfigTemplate(fullConfigTemplate, singboxConfig);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -2197,5 +2202,61 @@ public class CoreConfigSingboxService
|
|||
return 0;
|
||||
}
|
||||
|
||||
private async Task<string> ApplyFullConfigTemplate(FullConfigTemplateItem fullConfigTemplate, SingboxConfig singboxConfig)
|
||||
{
|
||||
var fullConfigTemplateItem = fullConfigTemplate.Config;
|
||||
if (_config.TunModeItem.EnableTun)
|
||||
{
|
||||
fullConfigTemplateItem = fullConfigTemplate.TunConfig;
|
||||
}
|
||||
|
||||
if (!fullConfigTemplate.Enabled || fullConfigTemplateItem.IsNullOrEmpty())
|
||||
{
|
||||
return JsonUtils.Serialize(singboxConfig);
|
||||
}
|
||||
|
||||
var fullConfigTemplateNode = JsonNode.Parse(fullConfigTemplateItem);
|
||||
if (fullConfigTemplateNode == null)
|
||||
{
|
||||
return JsonUtils.Serialize(singboxConfig);
|
||||
}
|
||||
|
||||
// Process outbounds
|
||||
var customOutboundsNode = fullConfigTemplateNode["outbounds"] is JsonArray outbounds ? outbounds : new JsonArray();
|
||||
foreach (var outbound in singboxConfig.outbounds)
|
||||
{
|
||||
if (outbound.type.ToLower() is "direct" or "block")
|
||||
{
|
||||
if (fullConfigTemplate.AddProxyOnly == true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (outbound.detour.IsNullOrEmpty() && (!fullConfigTemplate.ProxyDetour.IsNullOrEmpty()) && !Utils.IsPrivateNetwork(outbound.server ?? string.Empty))
|
||||
{
|
||||
outbound.detour = fullConfigTemplate.ProxyDetour;
|
||||
}
|
||||
customOutboundsNode.Add(JsonUtils.DeepCopy(outbound));
|
||||
}
|
||||
fullConfigTemplateNode["outbounds"] = customOutboundsNode;
|
||||
|
||||
// Process endpoints
|
||||
if (singboxConfig.endpoints != null && singboxConfig.endpoints.Count > 0)
|
||||
{
|
||||
var customEndpointsNode = fullConfigTemplateNode["endpoints"] is JsonArray endpoints ? endpoints : new JsonArray();
|
||||
foreach (var endpoint in singboxConfig.endpoints)
|
||||
{
|
||||
if (endpoint.detour.IsNullOrEmpty() && (!fullConfigTemplate.ProxyDetour.IsNullOrEmpty()))
|
||||
{
|
||||
endpoint.detour = fullConfigTemplate.ProxyDetour;
|
||||
}
|
||||
customEndpointsNode.Add(JsonUtils.DeepCopy(endpoint));
|
||||
}
|
||||
fullConfigTemplateNode["endpoints"] = customEndpointsNode;
|
||||
}
|
||||
|
||||
return await Task.FromResult(JsonUtils.Serialize(fullConfigTemplateNode));
|
||||
}
|
||||
|
||||
#endregion private gen function
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Net.NetworkInformation;
|
|||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
using ServiceLib.Models;
|
||||
|
||||
namespace ServiceLib.Services.CoreConfig;
|
||||
|
||||
|
@ -68,7 +69,9 @@ public class CoreConfigV2rayService
|
|||
|
||||
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||
ret.Success = true;
|
||||
ret.Data = JsonUtils.Serialize(v2rayConfig);
|
||||
|
||||
var fullConfigTemplate = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.Xray);
|
||||
ret.Data = await ApplyFullConfigTemplate(fullConfigTemplate, v2rayConfig);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -197,7 +200,9 @@ public class CoreConfigV2rayService
|
|||
}
|
||||
|
||||
ret.Success = true;
|
||||
ret.Data = JsonUtils.Serialize(v2rayConfig);
|
||||
|
||||
var fullConfigTemplate = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.Xray);
|
||||
ret.Data = await ApplyFullConfigTemplate(fullConfigTemplate, v2rayConfig, true);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -1462,7 +1467,7 @@ public class CoreConfigV2rayService
|
|||
|
||||
await GenDnsDomainsCompatible(node, obj, item);
|
||||
|
||||
v2rayConfig.dns = JsonUtils.Deserialize<Dns4Ray>(obj.ToJsonString());
|
||||
v2rayConfig.dns = JsonUtils.Deserialize<Dns4Ray>(JsonUtils.Serialize(obj));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -1839,5 +1844,83 @@ public class CoreConfigV2rayService
|
|||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<string> ApplyFullConfigTemplate(FullConfigTemplateItem fullConfigTemplate, V2rayConfig v2rayConfig, bool handleBalancerAndRules = false)
|
||||
{
|
||||
if (!fullConfigTemplate.Enabled || fullConfigTemplate.Config.IsNullOrEmpty())
|
||||
{
|
||||
return JsonUtils.Serialize(v2rayConfig);
|
||||
}
|
||||
|
||||
var fullConfigTemplateNode = JsonNode.Parse(fullConfigTemplate.Config);
|
||||
if (fullConfigTemplateNode == null)
|
||||
{
|
||||
return JsonUtils.Serialize(v2rayConfig);
|
||||
}
|
||||
|
||||
// Handle balancer and rules modifications (for multiple load scenarios)
|
||||
if (handleBalancerAndRules && v2rayConfig.routing?.balancers?.Count > 0)
|
||||
{
|
||||
var balancer = v2rayConfig.routing.balancers.First();
|
||||
|
||||
// Modify existing rules in custom config
|
||||
var rulesNode = fullConfigTemplateNode["routing"]?["rules"];
|
||||
if (rulesNode != null)
|
||||
{
|
||||
foreach (var rule in rulesNode.AsArray())
|
||||
{
|
||||
if (rule["outboundTag"]?.GetValue<string>() == Global.ProxyTag)
|
||||
{
|
||||
rule.AsObject().Remove("outboundTag");
|
||||
rule["balancerTag"] = balancer.tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure routing node exists
|
||||
if (fullConfigTemplateNode["routing"] == null)
|
||||
{
|
||||
fullConfigTemplateNode["routing"] = new JsonObject();
|
||||
}
|
||||
|
||||
// Handle balancers - append instead of override
|
||||
if (fullConfigTemplateNode["routing"]["balancers"] is JsonArray customBalancersNode)
|
||||
{
|
||||
if (JsonNode.Parse(JsonUtils.Serialize(v2rayConfig.routing.balancers)) is JsonArray newBalancers)
|
||||
{
|
||||
foreach (var balancerNode in newBalancers)
|
||||
{
|
||||
customBalancersNode.Add(balancerNode?.DeepClone());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fullConfigTemplateNode["routing"]["balancers"] = JsonNode.Parse(JsonUtils.Serialize(v2rayConfig.routing.balancers));
|
||||
}
|
||||
}
|
||||
|
||||
// Handle outbounds - append instead of override
|
||||
var customOutboundsNode = fullConfigTemplateNode["outbounds"] is JsonArray outbounds ? outbounds : new JsonArray();
|
||||
foreach (var outbound in v2rayConfig.outbounds)
|
||||
{
|
||||
if (outbound.protocol.ToLower() is "blackhole" or "dns" or "freedom")
|
||||
{
|
||||
if (fullConfigTemplate.AddProxyOnly == true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ((outbound.streamSettings?.sockopt?.dialerProxy.IsNullOrEmpty() == true) && (!fullConfigTemplate.ProxyDetour.IsNullOrEmpty()) && !(Utils.IsPrivateNetwork(outbound.settings?.servers?.FirstOrDefault()?.address ?? string.Empty) || Utils.IsPrivateNetwork(outbound.settings?.vnext?.FirstOrDefault()?.address ?? string.Empty)))
|
||||
{
|
||||
outbound.streamSettings ??= new StreamSettings4Ray();
|
||||
outbound.streamSettings.sockopt ??= new Sockopt4Ray();
|
||||
outbound.streamSettings.sockopt.dialerProxy = fullConfigTemplate.ProxyDetour;
|
||||
}
|
||||
customOutboundsNode.Add(JsonUtils.DeepCopy(outbound));
|
||||
}
|
||||
|
||||
return await Task.FromResult(JsonUtils.Serialize(fullConfigTemplateNode));
|
||||
}
|
||||
|
||||
#endregion private gen function
|
||||
}
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
using System.Reactive;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
|
||||
namespace ServiceLib.ViewModels;
|
||||
public class FullConfigTemplateViewModel : MyReactiveObject
|
||||
{
|
||||
#region Reactive
|
||||
[Reactive]
|
||||
public bool EnableFullConfigTemplate4Ray { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool EnableFullConfigTemplate4Singbox { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string FullConfigTemplate4Ray { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string FullConfigTemplate4Singbox { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string FullTunConfigTemplate4Singbox { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool AddProxyOnly4Ray { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool AddProxyOnly4Singbox { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string ProxyDetour4Ray { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string ProxyDetour4Singbox { get; set; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SaveCmd { get; }
|
||||
#endregion Reactive
|
||||
|
||||
public FullConfigTemplateViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
|
||||
{
|
||||
_config = AppHandler.Instance.Config;
|
||||
_updateView = updateView;
|
||||
SaveCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await SaveSettingAsync();
|
||||
});
|
||||
|
||||
_ = Init();
|
||||
}
|
||||
private async Task Init()
|
||||
{
|
||||
var item = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.Xray);
|
||||
EnableFullConfigTemplate4Ray = item?.Enabled ?? false;
|
||||
FullConfigTemplate4Ray = item?.Config ?? string.Empty;
|
||||
AddProxyOnly4Ray = item?.AddProxyOnly ?? false;
|
||||
ProxyDetour4Ray = item?.ProxyDetour ?? string.Empty;
|
||||
|
||||
var item2 = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.sing_box);
|
||||
EnableFullConfigTemplate4Singbox = item2?.Enabled ?? false;
|
||||
FullConfigTemplate4Singbox = item2?.Config ?? string.Empty;
|
||||
FullTunConfigTemplate4Singbox = item2?.TunConfig ?? string.Empty;
|
||||
AddProxyOnly4Singbox = item2?.AddProxyOnly ?? false;
|
||||
ProxyDetour4Singbox = item2?.ProxyDetour ?? string.Empty;
|
||||
}
|
||||
|
||||
private async Task SaveSettingAsync()
|
||||
{
|
||||
if (!await SaveXrayConfigAsync())
|
||||
return;
|
||||
|
||||
if (!await SaveSingboxConfigAsync())
|
||||
return;
|
||||
|
||||
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
||||
_ = _updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||
}
|
||||
|
||||
private async Task<bool> SaveXrayConfigAsync()
|
||||
{
|
||||
var item = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.Xray);
|
||||
item.Enabled = EnableFullConfigTemplate4Ray;
|
||||
item.Config = null;
|
||||
|
||||
item.Config = FullConfigTemplate4Ray;
|
||||
|
||||
item.AddProxyOnly = AddProxyOnly4Ray;
|
||||
item.ProxyDetour = ProxyDetour4Ray;
|
||||
|
||||
await ConfigHandler.SaveFullConfigTemplate(_config, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> SaveSingboxConfigAsync()
|
||||
{
|
||||
var item = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.sing_box);
|
||||
item.Enabled = EnableFullConfigTemplate4Singbox;
|
||||
item.Config = null;
|
||||
item.TunConfig = null;
|
||||
|
||||
item.Config = FullConfigTemplate4Singbox;
|
||||
item.TunConfig = FullTunConfigTemplate4Singbox;
|
||||
|
||||
item.AddProxyOnly = AddProxyOnly4Singbox;
|
||||
item.ProxyDetour = ProxyDetour4Singbox;
|
||||
|
||||
await ConfigHandler.SaveFullConfigTemplate(_config, item);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -39,6 +39,7 @@ public class MainWindowViewModel : MyReactiveObject
|
|||
|
||||
public ReactiveCommand<Unit, Unit> RoutingSettingCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> DNSSettingCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> FullConfigTemplateCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> GlobalHotkeySettingCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> RebootAsAdminCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> ClearServerStatisticsCmd { get; }
|
||||
|
@ -169,6 +170,10 @@ public class MainWindowViewModel : MyReactiveObject
|
|||
{
|
||||
await DNSSettingAsync();
|
||||
});
|
||||
FullConfigTemplateCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await FullConfigTemplateAsync();
|
||||
});
|
||||
GlobalHotkeySettingCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
if (await _updateView?.Invoke(EViewAction.GlobalHotkeySettingWindow, null) == true)
|
||||
|
@ -220,6 +225,7 @@ public class MainWindowViewModel : MyReactiveObject
|
|||
|
||||
await ConfigHandler.InitBuiltinRouting(_config);
|
||||
await ConfigHandler.InitBuiltinDNS(_config);
|
||||
await ConfigHandler.InitBuiltinFullConfigTemplate(_config);
|
||||
await ProfileExHandler.Instance.Init();
|
||||
await CoreHandler.Instance.Init(_config, UpdateHandler);
|
||||
TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler);
|
||||
|
@ -508,6 +514,15 @@ public class MainWindowViewModel : MyReactiveObject
|
|||
}
|
||||
}
|
||||
|
||||
private async Task FullConfigTemplateAsync()
|
||||
{
|
||||
var ret = await _updateView?.Invoke(EViewAction.FullConfigTemplateWindow, null);
|
||||
if (ret == true)
|
||||
{
|
||||
await Reload();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RebootAsAdmin()
|
||||
{
|
||||
ProcUtils.RebootAsAdmin();
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
<Window
|
||||
x:Class="v2rayN.Desktop.Views.FullConfigTemplateWindow"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
Title="{x:Static resx:ResUI.menuFullConfigTemplate}"
|
||||
Width="900"
|
||||
Height="600"
|
||||
x:DataType="vms:FullConfigTemplateViewModel"
|
||||
ShowInTaskbar="False"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Center"
|
||||
DockPanel.Dock="Bottom"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
x:Name="btnSave"
|
||||
Width="100"
|
||||
Content="{x:Static resx:ResUI.TbConfirm}"
|
||||
Cursor="Hand"
|
||||
IsDefault="True" />
|
||||
<Button
|
||||
x:Name="btnCancel"
|
||||
Width="100"
|
||||
Margin="{StaticResource MarginLr8}"
|
||||
Content="{x:Static resx:ResUI.TbCancel}"
|
||||
Cursor="Hand"
|
||||
IsCancel="True" />
|
||||
</StackPanel>
|
||||
|
||||
<TabControl HorizontalContentAlignment="Stretch">
|
||||
<TabItem HorizontalAlignment="Left" Header="{x:Static resx:ResUI.TbRayFullConfigTemplate}">
|
||||
<DockPanel Margin="{StaticResource Margin4}">
|
||||
<Grid DockPanel.Dock="Top" RowDefinitions="Auto,Auto,Auto">
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateDesc}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center">
|
||||
<HyperlinkButton Classes="WithIcon" Click="linkFullConfigTemplateDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbRayFullConfigTemplateDesc}" />
|
||||
</HyperlinkButton>
|
||||
</TextBlock>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateEnable}" />
|
||||
<ToggleSwitch
|
||||
x:Name="rayFullConfigTemplateEnable"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togAddProxyProtocolOutboundOnly4Ray"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSetUpstreamProxyDetour}" />
|
||||
<TextBox
|
||||
x:Name="txtProxyDetour4Ray"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<HeaderedContentControl
|
||||
Margin="{StaticResource Margin4}"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
Header="xray config template json">
|
||||
<TextBox
|
||||
x:Name="rayFullConfigTemplate"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="TextArea"
|
||||
MinLines="10"
|
||||
TextWrapping="Wrap" />
|
||||
</HeaderedContentControl>
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
<TabItem HorizontalAlignment="Left" Header="{x:Static resx:ResUI.TbSBFullConfigTemplate}">
|
||||
<DockPanel Margin="{StaticResource Margin4}">
|
||||
<Grid DockPanel.Dock="Top" RowDefinitions="Auto,Auto,Auto">
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateDesc}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center">
|
||||
<HyperlinkButton Classes="WithIcon" Click="linkFullConfigTemplateDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbSBFullConfigTemplateDesc}" />
|
||||
</HyperlinkButton>
|
||||
</TextBlock>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateEnable}" />
|
||||
<ToggleSwitch
|
||||
x:Name="sbFullConfigTemplateEnable"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togAddProxyProtocolOutboundOnly4Singbox"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSetUpstreamProxyDetour}" />
|
||||
<TextBox
|
||||
x:Name="txtProxyDetour4Singbox"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<Grid Margin="{StaticResource Margin4}" ColumnDefinitions="*,10,*">
|
||||
|
||||
<HeaderedContentControl
|
||||
Grid.Column="0"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
Header="sing-box config template json">
|
||||
<TextBox
|
||||
x:Name="sbFullConfigTemplate"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="TextArea"
|
||||
MinLines="10"
|
||||
TextWrapping="Wrap" />
|
||||
</HeaderedContentControl>
|
||||
|
||||
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
|
||||
|
||||
<HeaderedContentControl
|
||||
Grid.Column="2"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
Header="sing-box tun config template json">
|
||||
<TextBox
|
||||
x:Name="sbFullTunConfigTemplate"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="TextArea"
|
||||
MinLines="10"
|
||||
TextWrapping="Wrap" />
|
||||
</HeaderedContentControl>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</DockPanel>
|
||||
</Window>
|
|
@ -0,0 +1,51 @@
|
|||
using System.Reactive.Disposables;
|
||||
using Avalonia.Interactivity;
|
||||
using ReactiveUI;
|
||||
using v2rayN.Desktop.Base;
|
||||
|
||||
namespace v2rayN.Desktop.Views;
|
||||
|
||||
public partial class FullConfigTemplateWindow : WindowBase<FullConfigTemplateViewModel>
|
||||
{
|
||||
private static Config _config;
|
||||
|
||||
public FullConfigTemplateWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_config = AppHandler.Instance.Config;
|
||||
btnCancel.Click += (s, e) => this.Close();
|
||||
ViewModel = new FullConfigTemplateViewModel(UpdateViewHandler);
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Ray, v => v.rayFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullConfigTemplate4Ray, v => v.rayFullConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.AddProxyOnly4Ray, v => v.togAddProxyProtocolOutboundOnly4Ray.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.ProxyDetour4Ray, v => v.txtProxyDetour4Ray.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Singbox, v => v.sbFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullConfigTemplate4Singbox, v => v.sbFullConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullTunConfigTemplate4Singbox, v => v.sbFullTunConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.AddProxyOnly4Singbox, v => v.togAddProxyProtocolOutboundOnly4Singbox.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.ProxyDetour4Singbox, v => v.txtProxyDetour4Singbox.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case EViewAction.CloseWindow:
|
||||
this.Close(true);
|
||||
break;
|
||||
}
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
private void linkFullConfigTemplateDoc_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ProcUtils.ProcessStart("https://github.com/2dust/v2rayN/wiki/Description-of-some-ui#%E5%AE%8C%E6%95%B4%E9%85%8D%E7%BD%AE%E6%A8%A1%E6%9D%BF%E8%AE%BE%E7%BD%AE");
|
||||
}
|
||||
}
|
|
@ -72,6 +72,7 @@
|
|||
<MenuItem x:Name="menuOptionSetting" Header="{x:Static resx:ResUI.menuOptionSetting}" />
|
||||
<MenuItem x:Name="menuRoutingSetting" Header="{x:Static resx:ResUI.menuRoutingSetting}" />
|
||||
<MenuItem x:Name="menuDNSSetting" Header="{x:Static resx:ResUI.menuDNSSetting}" />
|
||||
<MenuItem x:Name="menuFullConfigTemplate" Header="{x:Static resx:ResUI.menuFullConfigTemplate}" />
|
||||
<MenuItem x:Name="menuGlobalHotkeySetting" Header="{x:Static resx:ResUI.menuGlobalHotkeySetting}" />
|
||||
<Separator />
|
||||
<MenuItem x:Name="menuRebootAsAdmin" Header="{x:Static resx:ResUI.menuRebootAsAdmin}" />
|
||||
|
|
|
@ -100,6 +100,7 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
|||
this.BindCommand(ViewModel, vm => vm.OptionSettingCmd, v => v.menuOptionSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.RoutingSettingCmd, v => v.menuRoutingSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.DNSSettingCmd, v => v.menuDNSSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.FullConfigTemplateCmd, v => v.menuFullConfigTemplate).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.GlobalHotkeySettingCmd, v => v.menuGlobalHotkeySetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);
|
||||
|
@ -190,6 +191,9 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
|||
case EViewAction.DNSSettingWindow:
|
||||
return await new DNSSettingWindow().ShowDialog<bool>(this);
|
||||
|
||||
case EViewAction.FullConfigTemplateWindow:
|
||||
return await new FullConfigTemplateWindow().ShowDialog<bool>(this);
|
||||
|
||||
case EViewAction.RoutingSettingWindow:
|
||||
return await new RoutingSettingWindow().ShowDialog<bool>(this);
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@
|
|||
<EmbeddedResource Include="Assets\v2rayN.ico">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<Compile Update="Views\FullConfigTemplateWindow.axaml.cs">
|
||||
<DependentUpon>FullConfigTemplateWindow.axaml</DependentUpon>
|
||||
</Compile>
|
||||
<None Update="v2rayN.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
<base:WindowBase
|
||||
x:Class="v2rayN.Views.FullConfigTemplateWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:base="clr-namespace:v2rayN.Base"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:reactiveui="http://reactiveui.net"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
Title="{x:Static resx:ResUI.menuFullConfigTemplate}"
|
||||
Width="1000"
|
||||
Height="700"
|
||||
x:TypeArguments="vms:FullConfigTemplateViewModel"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Center"
|
||||
DockPanel.Dock="Bottom"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
x:Name="btnSave"
|
||||
Width="100"
|
||||
Content="{x:Static resx:ResUI.TbConfirm}"
|
||||
Cursor="Hand"
|
||||
IsDefault="True"
|
||||
Style="{StaticResource DefButton}" />
|
||||
<Button
|
||||
x:Name="btnCancel"
|
||||
Width="100"
|
||||
Margin="{StaticResource MarginLeftRight8}"
|
||||
Content="{x:Static resx:ResUI.TbCancel}"
|
||||
Cursor="Hand"
|
||||
IsCancel="true"
|
||||
Style="{StaticResource DefButton}" />
|
||||
</StackPanel>
|
||||
|
||||
<TabControl HorizontalContentAlignment="Left">
|
||||
<TabItem HorizontalAlignment="Left" Header="{x:Static resx:ResUI.TbRayFullConfigTemplate}">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateDesc}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}">
|
||||
<Hyperlink Click="linkFullConfigTemplateDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbRayFullConfigTemplateDesc}" />
|
||||
<materialDesign:PackIcon Kind="Link" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateEnable}" />
|
||||
<ToggleButton
|
||||
x:Name="rayFullConfigTemplateEnable"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}" />
|
||||
<ToggleButton
|
||||
x:Name="togAddProxyProtocolOutboundOnly4Ray"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSetUpstreamProxyDetour}" />
|
||||
<TextBox
|
||||
x:Name="txtProxyDetour4Ray"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<TextBox
|
||||
x:Name="rayFullConfigTemplate"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Stretch"
|
||||
materialDesign:HintAssist.Hint="xray config template json"
|
||||
AcceptsReturn="True"
|
||||
BorderThickness="1"
|
||||
Style="{StaticResource MaterialDesignOutlinedTextBox}"
|
||||
TextWrapping="Wrap"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
<TabItem HorizontalAlignment="Left" Header="{x:Static resx:ResUI.TbSBFullConfigTemplate}">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateDesc}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}">
|
||||
<Hyperlink Click="linkFullConfigTemplateDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbSBFullConfigTemplateDesc}" />
|
||||
<materialDesign:PackIcon Kind="Link" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateEnable}" />
|
||||
<ToggleButton
|
||||
x:Name="sbFullConfigTemplateEnable"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}" />
|
||||
<ToggleButton
|
||||
x:Name="togAddProxyProtocolOutboundOnly4Singbox"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSetUpstreamProxyDetour}" />
|
||||
<TextBox
|
||||
x:Name="txtProxyDetour4Singbox"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<Grid Margin="{StaticResource Margin8}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox
|
||||
x:Name="sbFullConfigTemplate"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Stretch"
|
||||
materialDesign:HintAssist.Hint="sing-box config template json"
|
||||
AcceptsReturn="True"
|
||||
BorderThickness="1"
|
||||
Style="{StaticResource MaterialDesignOutlinedTextBox}"
|
||||
TextWrapping="Wrap"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
|
||||
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
|
||||
|
||||
<TextBox
|
||||
x:Name="sbFullTunConfigTemplate"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Stretch"
|
||||
materialDesign:HintAssist.Hint="sing-box tun config template json"
|
||||
AcceptsReturn="True"
|
||||
BorderThickness="1"
|
||||
Style="{StaticResource MaterialDesignOutlinedTextBox}"
|
||||
TextWrapping="Wrap"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</DockPanel>
|
||||
</base:WindowBase>
|
|
@ -0,0 +1,52 @@
|
|||
using System.Reactive.Disposables;
|
||||
using System.Windows;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace v2rayN.Views;
|
||||
|
||||
public partial class FullConfigTemplateWindow
|
||||
{
|
||||
private static Config _config;
|
||||
|
||||
public FullConfigTemplateWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.Owner = Application.Current.MainWindow;
|
||||
_config = AppHandler.Instance.Config;
|
||||
|
||||
ViewModel = new FullConfigTemplateViewModel(UpdateViewHandler);
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Ray, v => v.rayFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullConfigTemplate4Ray, v => v.rayFullConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.AddProxyOnly4Ray, v => v.togAddProxyProtocolOutboundOnly4Ray.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.ProxyDetour4Ray, v => v.txtProxyDetour4Ray.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Singbox, v => v.sbFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullConfigTemplate4Singbox, v => v.sbFullConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullTunConfigTemplate4Singbox, v => v.sbFullTunConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.AddProxyOnly4Singbox, v => v.togAddProxyProtocolOutboundOnly4Singbox.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.ProxyDetour4Singbox, v => v.txtProxyDetour4Singbox.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case EViewAction.CloseWindow:
|
||||
this.DialogResult = true;
|
||||
break;
|
||||
}
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
private void linkFullConfigTemplateDoc_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ProcUtils.ProcessStart("https://github.com/2dust/v2rayN/wiki/Description-of-some-ui#%E5%AE%8C%E6%95%B4%E9%85%8D%E7%BD%AE%E6%A8%A1%E6%9D%BF%E8%AE%BE%E7%BD%AE");
|
||||
}
|
||||
}
|
|
@ -173,6 +173,10 @@
|
|||
x:Name="menuDNSSetting"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuDNSSetting}" />
|
||||
<MenuItem
|
||||
x:Name="menuFullConfigTemplate"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuFullConfigTemplate}" />
|
||||
<MenuItem
|
||||
x:Name="menuGlobalHotkeySetting"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
|
|
|
@ -97,6 +97,7 @@ public partial class MainWindow
|
|||
this.BindCommand(ViewModel, vm => vm.OptionSettingCmd, v => v.menuOptionSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.RoutingSettingCmd, v => v.menuRoutingSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.DNSSettingCmd, v => v.menuDNSSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.FullConfigTemplateCmd, v => v.menuFullConfigTemplate).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.GlobalHotkeySettingCmd, v => v.menuGlobalHotkeySetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);
|
||||
|
@ -186,6 +187,9 @@ public partial class MainWindow
|
|||
case EViewAction.OptionSettingWindow:
|
||||
return (new OptionSettingWindow().ShowDialog() ?? false);
|
||||
|
||||
case EViewAction.FullConfigTemplateWindow:
|
||||
return (new FullConfigTemplateWindow().ShowDialog() ?? false);
|
||||
|
||||
case EViewAction.GlobalHotkeySettingWindow:
|
||||
return (new GlobalHotkeySettingWindow().ShowDialog() ?? false);
|
||||
|
||||
|
|
Loading…
Reference in New Issue