Compare commits

..

10 Commits
7.5.0 ... 7.5.1

27 changed files with 119 additions and 66 deletions

View File

@@ -530,7 +530,7 @@ namespace ServiceLib.Common
try try
{ {
return blFull return blFull
? $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture} - {StartupPath()}" ? $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture}"
: $"{Global.AppName}/{GetVersionInfo()}"; : $"{Global.AppName}/{GetVersionInfo()}";
} }
catch (Exception ex) catch (Exception ex)
@@ -554,6 +554,11 @@ namespace ServiceLib.Common
} }
} }
public static string GetRuntimeInfo()
{
return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion} | {(Environment.Is64BitOperatingSystem ? 64 : 32)}";
}
/// <summary> /// <summary>
/// 取得GUID /// 取得GUID
/// </summary> /// </summary>
@@ -860,18 +865,19 @@ namespace ServiceLib.Common
{ {
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
} }
else
{
var id = GetLinuxUserId().Result ?? "1000";
if (int.TryParse(id, out var userId))
{
return userId == 0;
}
else
{
return false; return false;
} //else
} //{
// var id = GetLinuxUserId().Result ?? "1000";
// if (int.TryParse(id, out var userId))
// {
// return userId == 0;
// }
// else
// {
// return false;
// }
//}
} }
private static async Task<string?> GetLinuxUserId() private static async Task<string?> GetLinuxUserId()
@@ -883,6 +889,7 @@ namespace ServiceLib.Common
public static async Task<string?> SetLinuxChmod(string? fileName) public static async Task<string?> SetLinuxChmod(string? fileName)
{ {
if (fileName.IsNullOrEmpty()) return null; if (fileName.IsNullOrEmpty()) return null;
if (fileName.Contains(' ')) fileName = fileName.AppendQuotes();
//File.SetUnixFileMode(fileName, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute); //File.SetUnixFileMode(fileName, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
var arg = new List<string>() { "-c", $"chmod +x {fileName}" }; var arg = new List<string>() { "-c", $"chmod +x {fileName}" };
return await GetCliWrapOutput("/bin/bash", arg); return await GetCliWrapOutput("/bin/bash", arg);
@@ -902,6 +909,12 @@ namespace ServiceLib.Common
: Environment.GetEnvironmentVariable("HOME"); : Environment.GetEnvironmentVariable("HOME");
} }
public static async Task<string?> GetListNetworkServices()
{
var arg = new List<string>() { "-c", $"networksetup -listallnetworkservices" };
return await GetCliWrapOutput("/bin/bash", arg);
}
#endregion Platform #endregion Platform
} }
} }

View File

@@ -4,5 +4,6 @@
{ {
Default = 0, Default = 0,
Russia = 1, Russia = 1,
Iran = 2,
} }
} }

View File

@@ -124,21 +124,25 @@
public static readonly List<string> GeoFilesSources = new() { public static readonly List<string> GeoFilesSources = new() {
"", "",
@"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/{0}.dat", @"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/{0}.dat",
@"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-v2ray-rules@release/{0}.dat",
}; };
public static readonly List<string> SingboxRulesetSources = new() { public static readonly List<string> SingboxRulesetSources = new() {
"", "",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-rules-dat@release/sing-box/rule-set-{0}/{1}.srs", @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-rules-dat@release/sing-box/rule-set-{0}/{1}.srs",
@"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-sing-box-rules@rule-set/{1}.srs",
}; };
public static readonly List<string> RoutingRulesSources = new() { public static readonly List<string> RoutingRulesSources = new() {
"", "",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/template.json", @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/template.json",
@"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/template.json",
}; };
public static readonly List<string> DNSTemplateSources = new() { public static readonly List<string> DNSTemplateSources = new() {
"", "",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/", @"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/",
@"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/",
}; };
public static readonly Dictionary<string, string> UserAgentTexts = new() public static readonly Dictionary<string, string> UserAgentTexts = new()

View File

@@ -77,8 +77,7 @@
public bool InitComponents() public bool InitComponents()
{ {
Logging.SaveLog($"v2rayN start up | {Utils.GetVersion()} | {Utils.GetExePath()}"); Logging.SaveLog($"v2rayN start up | {Utils.GetRuntimeInfo()}");
Logging.SaveLog($"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
Logging.LoggingEnabled(_config.GuiItem.EnableLog); Logging.LoggingEnabled(_config.GuiItem.EnableLog);
Logging.ClearLogs(); Logging.ClearLogs();

View File

@@ -68,7 +68,7 @@ namespace ServiceLib.Handler
config.RoutingBasicItem ??= new(); config.RoutingBasicItem ??= new();
if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy)) if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy))
{ {
config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies.First();//"IPIfNonMatch"; config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies.First();
} }
config.KcpItem ??= new KcpItem config.KcpItem ??= new KcpItem
@@ -1868,6 +1868,16 @@ namespace ServiceLib.Handler
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json")); await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json"));
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json")); await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json"));
return true;
case EPresetType.Iran:
config.ConstItem.GeoSourceUrl = Global.GeoFilesSources[2];
config.ConstItem.SrsSourceUrl = Global.SingboxRulesetSources[2];
config.ConstItem.RouteRulesTemplateSourceUrl = Global.RoutingRulesSources[2];
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[2] + "v2ray.json"));
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[2] + "sing_box.json"));
return true; return true;
} }

View File

@@ -67,7 +67,7 @@ namespace ServiceLib.Handler
} }
ShowMsg(true, $"{node.GetSummary()}"); ShowMsg(true, $"{node.GetSummary()}");
ShowMsg(false, $"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}"); ShowMsg(false, $"{Utils.GetRuntimeInfo()}");
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"))); ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
await CoreStop(); await CoreStop();
await Task.Delay(100); await Task.Delay(100);

View File

@@ -2,14 +2,10 @@
{ {
public class ProxySettingOSX public class ProxySettingOSX
{ {
/*
* 仅测试了MacOS 13.7.1 x86 版本,其他版本有待确认
*/
/// <summary> /// <summary>
/// 应用接口类型 /// 应用接口类型
/// </summary> /// </summary>
private static readonly List<string> LstInterface = ["Ethernet", "Wi-Fi", "Thunderbolt Bridge"]; private static readonly List<string> LstInterface = ["Ethernet", "Wi-Fi", "Thunderbolt Bridge", "USB 10/100/1000 LAN"];
/// <summary> /// <summary>
/// 代理类型,对应 http,https,socks /// 代理类型,对应 http,https,socks
@@ -18,13 +14,15 @@
public static async Task SetProxy(string host, int port, string exceptions) public static async Task SetProxy(string host, int port, string exceptions)
{ {
var lstCmd = GetSetCmds(host, port, exceptions); var lstInterface = await GetListNetworkServices();
var lstCmd = GetSetCmds(lstInterface, host, port, exceptions);
await ExecCmd(lstCmd); await ExecCmd(lstCmd);
} }
public static async Task UnsetProxy() public static async Task UnsetProxy()
{ {
var lstCmd = GetUnsetCmds(); var lstInterface = await GetListNetworkServices();
var lstCmd = GetUnsetCmds(lstInterface);
await ExecCmd(lstCmd); await ExecCmd(lstCmd);
} }
@@ -42,10 +40,10 @@
} }
} }
private static List<CmdItem> GetSetCmds(string host, int port, string exceptions) private static List<CmdItem> GetSetCmds(List<string> lstInterface, string host, int port, string exceptions)
{ {
List<CmdItem> lstCmd = []; List<CmdItem> lstCmd = [];
foreach (var interf in LstInterface) foreach (var interf in lstInterface)
{ {
foreach (var type in LstTypes) foreach (var type in LstTypes)
{ {
@@ -70,10 +68,10 @@
return lstCmd; return lstCmd;
} }
private static List<CmdItem> GetUnsetCmds() private static List<CmdItem> GetUnsetCmds(List<string> lstInterface)
{ {
List<CmdItem> lstCmd = []; List<CmdItem> lstCmd = [];
foreach (var interf in LstInterface) foreach (var interf in lstInterface)
{ {
foreach (var type in LstTypes) foreach (var type in LstTypes)
{ {
@@ -87,5 +85,16 @@
return lstCmd; return lstCmd;
} }
public static async Task<List<string>> GetListNetworkServices()
{
var services = await Utils.GetListNetworkServices();
if (services.IsNullOrEmpty())
{
return LstInterface;
}
var lst = services.Split(Environment.NewLine);
return lst.Length > 0 ? LstInterface.Intersect(lst).ToList() : LstInterface;
}
} }
} }

View File

@@ -1248,6 +1248,15 @@ namespace ServiceLib.Resx {
} }
} }
/// <summary>
/// 查找类似 Iran 的本地化字符串。
/// </summary>
public static string menuRegionalPresetsIran {
get {
return ResourceManager.GetString("menuRegionalPresetsIran", resourceCulture);
}
}
/// <summary> /// <summary>
/// 查找类似 Russia 的本地化字符串。 /// 查找类似 Russia 的本地化字符串。
/// </summary> /// </summary>

View File

@@ -1129,6 +1129,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve"> <data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>روسیه</value> <value>روسیه</value>
</data> </data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>ایران</value>
</data>
<data name="TbSettingsChinaUserTip" xml:space="preserve"> <data name="TbSettingsChinaUserTip" xml:space="preserve">
<value>کاربران در منطقه چین می توانند این مورد را نادیده بگیرند</value> <value>کاربران در منطقه چین می توانند این مورد را نادیده بگیرند</value>
</data> </data>

View File

@@ -1342,6 +1342,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve"> <data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>Oroszország</value> <value>Oroszország</value>
</data> </data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>Irán</value>
</data>
<data name="TbSettingsChinaUserTip" xml:space="preserve"> <data name="TbSettingsChinaUserTip" xml:space="preserve">
<value>A Kínában élő felhasználók figyelmen kívül hagyhatják ezt a tételt</value> <value>A Kínában élő felhasználók figyelmen kívül hagyhatják ezt a tételt</value>
</data> </data>

View File

@@ -1342,6 +1342,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve"> <data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>Russia</value> <value>Russia</value>
</data> </data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>Iran</value>
</data>
<data name="TbSettingsChinaUserTip" xml:space="preserve"> <data name="TbSettingsChinaUserTip" xml:space="preserve">
<value>Users in China region can ignore this item</value> <value>Users in China region can ignore this item</value>
</data> </data>

View File

@@ -1039,6 +1039,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve"> <data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>Россия</value> <value>Россия</value>
</data> </data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>Иран</value>
</data>
<data name="TbSettingsChinaUserTip" xml:space="preserve"> <data name="TbSettingsChinaUserTip" xml:space="preserve">
<value>Используйте Настройки -&gt; Региональные пресеты вместо изменения этого поля</value> <value>Используйте Настройки -&gt; Региональные пресеты вместо изменения этого поля</value>
</data> </data>

View File

@@ -1342,6 +1342,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve"> <data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>俄罗斯</value> <value>俄罗斯</value>
</data> </data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>伊朗</value>
</data>
<data name="menuAddServerViaImage" xml:space="preserve"> <data name="menuAddServerViaImage" xml:space="preserve">
<value>扫描图片中的二维码</value> <value>扫描图片中的二维码</value>
</data> </data>

View File

@@ -1222,6 +1222,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve"> <data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>俄羅斯</value> <value>俄羅斯</value>
</data> </data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>伊朗</value>
</data>
<data name="menuAddServerViaImage" xml:space="preserve"> <data name="menuAddServerViaImage" xml:space="preserve">
<value>掃描圖片中的二維碼</value> <value>掃描圖片中的二維碼</value>
</data> </data>

View File

@@ -99,10 +99,5 @@
"domain": [ "domain": [
"geosite:cn" "geosite:cn"
] ]
},
{
"remarks": "最终代理",
"port": "0-65535",
"outboundTag": "proxy"
} }
] ]

View File

@@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Version>7.5.0</Version> <Version>7.5.1</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -50,6 +50,8 @@ namespace ServiceLib.ViewModels
public ReactiveCommand<Unit, Unit> RegionalPresetRussiaCmd { get; } public ReactiveCommand<Unit, Unit> RegionalPresetRussiaCmd { get; }
public ReactiveCommand<Unit, Unit> RegionalPresetIranCmd { get; }
public ReactiveCommand<Unit, Unit> ReloadCmd { get; } public ReactiveCommand<Unit, Unit> ReloadCmd { get; }
[Reactive] [Reactive]
@@ -197,6 +199,11 @@ namespace ServiceLib.ViewModels
await ApplyRegionalPreset(EPresetType.Russia); await ApplyRegionalPreset(EPresetType.Russia);
}); });
RegionalPresetIranCmd = ReactiveCommand.CreateFromTask(async () =>
{
await ApplyRegionalPreset(EPresetType.Iran);
});
#endregion WhenAnyValue && ReactiveCommand #endregion WhenAnyValue && ReactiveCommand
Init(); Init();

View File

@@ -74,15 +74,16 @@ namespace ServiceLib.ViewModels
SelectedSource.Protocol = ProtocolItems?.ToList(); SelectedSource.Protocol = ProtocolItems?.ToList();
SelectedSource.InboundTag = InboundTagItems?.ToList(); SelectedSource.InboundTag = InboundTagItems?.ToList();
bool hasRule = SelectedSource.Domain?.Count > 0 var hasRule = SelectedSource.Domain?.Count > 0
|| SelectedSource.Ip?.Count > 0 || SelectedSource.Ip?.Count > 0
|| SelectedSource.Protocol?.Count > 0 || SelectedSource.Protocol?.Count > 0
|| SelectedSource.Process?.Count > 0 || SelectedSource.Process?.Count > 0
|| Utils.IsNotEmpty(SelectedSource.Port); || Utils.IsNotEmpty(SelectedSource.Port)
|| Utils.IsNotEmpty(SelectedSource.Network);
if (!hasRule) if (!hasRule)
{ {
NoticeHandler.Instance.Enqueue(string.Format(ResUI.RoutingRuleDetailRequiredTips, "Port/Protocol/Domain/IP/Process")); NoticeHandler.Instance.Enqueue(string.Format(ResUI.RoutingRuleDetailRequiredTips, "Network/Port/Protocol/Domain/IP/Process"));
return; return;
} }
//NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); //NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);

View File

@@ -177,12 +177,12 @@ namespace ServiceLib.ViewModels
} }
var lst = new List<RulesItem>(); var lst = new List<RulesItem>();
foreach (var it in SelectedSources ?? [SelectedSource]) var sources = SelectedSources ?? [SelectedSource];
foreach (var it in _rules)
{ {
var item = _rules.FirstOrDefault(t => t.Id == it?.Id); if (sources.Any(t => t.Id == it?.Id))
if (item != null)
{ {
var item2 = JsonUtils.DeepCopy(item); //JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item)); var item2 = JsonUtils.DeepCopy(it);
item2.Id = null; item2.Id = null;
lst.Add(item2 ?? new()); lst.Add(item2 ?? new());
} }

View File

@@ -80,6 +80,7 @@
<MenuItem Header="{x:Static resx:ResUI.menuRegionalPresets}"> <MenuItem Header="{x:Static resx:ResUI.menuRegionalPresets}">
<MenuItem x:Name="menuRegionalPresetsDefault" Header="{x:Static resx:ResUI.menuRegionalPresetsDefault}" /> <MenuItem x:Name="menuRegionalPresetsDefault" Header="{x:Static resx:ResUI.menuRegionalPresetsDefault}" />
<MenuItem x:Name="menuRegionalPresetsRussia" Header="{x:Static resx:ResUI.menuRegionalPresetsRussia}" /> <MenuItem x:Name="menuRegionalPresetsRussia" Header="{x:Static resx:ResUI.menuRegionalPresetsRussia}" />
<MenuItem x:Name="menuRegionalPresetsIran" Header="{x:Static resx:ResUI.menuRegionalPresetsIran}" />
</MenuItem> </MenuItem>
<MenuItem x:Name="menuBackupAndRestore" Header="{x:Static resx:ResUI.menuBackupAndRestore}" /> <MenuItem x:Name="menuBackupAndRestore" Header="{x:Static resx:ResUI.menuBackupAndRestore}" />
<MenuItem x:Name="menuOpenTheFileLocation" Header="{x:Static resx:ResUI.menuOpenTheFileLocation}" /> <MenuItem x:Name="menuOpenTheFileLocation" Header="{x:Static resx:ResUI.menuOpenTheFileLocation}" />

View File

@@ -104,6 +104,7 @@ namespace v2rayN.Desktop.Views
this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RegionalPresetDefaultCmd, v => v.menuRegionalPresetsDefault).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.RegionalPresetDefaultCmd, v => v.menuRegionalPresetsDefault).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RegionalPresetRussiaCmd, v => v.menuRegionalPresetsRussia).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.RegionalPresetRussiaCmd, v => v.menuRegionalPresetsRussia).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RegionalPresetIranCmd, v => v.menuRegionalPresetsIran).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
@@ -133,7 +134,7 @@ namespace v2rayN.Desktop.Views
} }
}); });
this.Title = $"{Utils.GetVersion()} - {(AppHandler.Instance.IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}"; this.Title = $"{Utils.GetVersion()}";
if (Utils.IsWindows()) if (Utils.IsWindows())
{ {
ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false); ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);

View File

@@ -187,12 +187,7 @@ namespace v2rayN.Desktop.Views
private void lstProfiles_SelectionChanged(object? sender, SelectionChangedEventArgs e) private void lstProfiles_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{ {
List<ProfileItemModel> lst = []; ViewModel.SelectedProfiles = lstProfiles.SelectedItems.Cast<ProfileItemModel>().ToList();
foreach (var item in lstProfiles.SelectedItems)
{
lst.Add((ProfileItemModel)item);
}
ViewModel.SelectedProfiles = lst;
} }
private void LstProfiles_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e) private void LstProfiles_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)

View File

@@ -166,12 +166,7 @@ namespace v2rayN.Desktop.Views
private void lstRules_SelectionChanged(object? sender, SelectionChangedEventArgs e) private void lstRules_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{ {
List<RulesItemModel> lst = []; ViewModel.SelectedSources = lstRules.SelectedItems.Cast<RulesItemModel>().ToList();
foreach (var item in lstRules.SelectedItems)
{
lst.Add((RulesItemModel)item);
}
ViewModel.SelectedSources = lst;
} }
private void LstRules_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e) private void LstRules_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)

View File

@@ -107,12 +107,7 @@ namespace v2rayN.Desktop.Views
private void lstRoutings_SelectionChanged(object? sender, SelectionChangedEventArgs e) private void lstRoutings_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{ {
List<RoutingItemModel> lst = []; ViewModel.SelectedSources = lstRoutings.SelectedItems.Cast<RoutingItemModel>().ToList();
foreach (var item in lstRoutings.SelectedItems)
{
lst.Add((RoutingItemModel)item);
}
ViewModel.SelectedSources = lst;
} }
private void LstRoutings_DoubleTapped(object? sender, TappedEventArgs e) private void LstRoutings_DoubleTapped(object? sender, TappedEventArgs e)

View File

@@ -82,12 +82,7 @@ namespace v2rayN.Desktop.Views
private void LstSubscription_SelectionChanged(object? sender, SelectionChangedEventArgs e) private void LstSubscription_SelectionChanged(object? sender, SelectionChangedEventArgs e)
{ {
List<SubItem> lst = []; ViewModel.SelectedSources = lstSubscription.SelectedItems.Cast<SubItem>().ToList();
foreach (var item in lstSubscription.SelectedItems)
{
lst.Add((SubItem)item);
}
ViewModel.SelectedSources = lst;
} }
private void menuClose_Click(object? sender, RoutedEventArgs e) private void menuClose_Click(object? sender, RoutedEventArgs e)

View File

@@ -194,6 +194,10 @@
x:Name="menuRegionalPresetsRussia" x:Name="menuRegionalPresetsRussia"
Height="{StaticResource MenuItemHeight}" Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuRegionalPresetsRussia}" /> Header="{x:Static resx:ResUI.menuRegionalPresetsRussia}" />
<MenuItem
x:Name="menuRegionalPresetsIran"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuRegionalPresetsIran}" />
</MenuItem> </MenuItem>
<MenuItem <MenuItem
x:Name="menuBackupAndRestore" x:Name="menuBackupAndRestore"

View File

@@ -102,6 +102,7 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RegionalPresetDefaultCmd, v => v.menuRegionalPresetsDefault).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.RegionalPresetDefaultCmd, v => v.menuRegionalPresetsDefault).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RegionalPresetRussiaCmd, v => v.menuRegionalPresetsRussia).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.RegionalPresetRussiaCmd, v => v.menuRegionalPresetsRussia).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.RegionalPresetIranCmd, v => v.menuRegionalPresetsIran).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);