From a6af95e083262509c48deca95ddc83ee5ff66334 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Sat, 8 Nov 2025 20:10:20 +0800 Subject: [PATCH 1/7] Bug fix https://github.com/2dust/v2rayN/issues/8276 --- v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs index ad91fa02..74271149 100644 --- a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs @@ -268,7 +268,7 @@ public class MainWindowViewModel : MyReactiveObject } await RefreshServers(); - SetReloadEnabled(true); + BlReloadEnabled = true; await Reload(); } From e20c11c1a7a0759771df87bfec1fe0d9c6a3ae93 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Sat, 8 Nov 2025 20:48:55 +0800 Subject: [PATCH 2/7] Refactor reload logic with semaphore for concurrency --- .../ViewModels/MainWindowViewModel.cs | 75 ++++++++++--------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs index 74271149..ce68d96b 100644 --- a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs @@ -64,8 +64,6 @@ public class MainWindowViewModel : MyReactiveObject #endregion Menu - private bool _hasNextReloadJob = false; - #region Init public MainWindowViewModel(Func>? updateView) @@ -268,7 +266,6 @@ public class MainWindowViewModel : MyReactiveObject } await RefreshServers(); - BlReloadEnabled = true; await Reload(); } @@ -525,49 +522,59 @@ public class MainWindowViewModel : MyReactiveObject #region core job + private bool _hasNextReloadJob = false; + private readonly SemaphoreSlim _reloadSemaphore = new(1, 1); + public async Task Reload() { //If there are unfinished reload job, marked with next job. - if (!BlReloadEnabled) + if (!await _reloadSemaphore.WaitAsync(0)) { _hasNextReloadJob = true; return; } - SetReloadEnabled(false); - - var msgs = await ActionPrecheckManager.Instance.Check(_config.IndexId); - if (msgs.Count > 0) + try { - foreach (var msg in msgs) + SetReloadEnabled(false); + + var msgs = await ActionPrecheckManager.Instance.Check(_config.IndexId); + if (msgs.Count > 0) { - NoticeManager.Instance.SendMessage(msg); + foreach (var msg in msgs) + { + NoticeManager.Instance.SendMessage(msg); + } + NoticeManager.Instance.Enqueue(Utils.List2String(msgs.Take(10).ToList(), true)); + return; } - NoticeManager.Instance.Enqueue(Utils.List2String(msgs.Take(10).ToList(), true)); + + await Task.Run(async () => + { + await LoadCore(); + await SysProxyHandler.UpdateSysProxy(_config, false); + await Task.Delay(1000); + }); + AppEvents.TestServerRequested.Publish(); + + var showClashUI = _config.IsRunningCore(ECoreType.sing_box); + if (showClashUI) + { + AppEvents.ProxiesReloadRequested.Publish(); + } + + ReloadResult(showClashUI); + } + finally + { SetReloadEnabled(true); - return; - } - - await Task.Run(async () => - { - await LoadCore(); - await SysProxyHandler.UpdateSysProxy(_config, false); - await Task.Delay(1000); - }); - AppEvents.TestServerRequested.Publish(); - - var showClashUI = _config.IsRunningCore(ECoreType.sing_box); - if (showClashUI) - { - AppEvents.ProxiesReloadRequested.Publish(); - } - - ReloadResult(showClashUI); - SetReloadEnabled(true); - if (_hasNextReloadJob) - { - _hasNextReloadJob = false; - await Reload(); + _reloadSemaphore.Release(); + //If there is a next reload job, execute it. + if (_hasNextReloadJob) + { + _hasNextReloadJob = false; + await Reload(); + } } } From 4da59cd767858adab6ceee83907c75dd0ba4ec28 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Sun, 9 Nov 2025 10:52:46 +0800 Subject: [PATCH 3/7] Rename IsOSX to IsMacOS in Utils and usages --- v2rayN/ServiceLib/Common/Utils.cs | 4 ++-- v2rayN/ServiceLib/Handler/AutoStartupHandler.cs | 2 +- v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs | 4 ++-- v2rayN/ServiceLib/Manager/CoreAdminManager.cs | 2 +- .../Services/CoreConfig/Singbox/SingboxInboundService.cs | 2 +- v2rayN/ServiceLib/Services/UpdateService.cs | 2 +- v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs | 2 +- v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs | 2 +- v2rayN/v2rayN.Desktop/Base/WindowBase.cs | 2 +- v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/v2rayN/ServiceLib/Common/Utils.cs b/v2rayN/ServiceLib/Common/Utils.cs index 5fb14023..1712b40c 100644 --- a/v2rayN/ServiceLib/Common/Utils.cs +++ b/v2rayN/ServiceLib/Common/Utils.cs @@ -998,7 +998,7 @@ public class Utils public static bool IsLinux() => OperatingSystem.IsLinux(); - public static bool IsOSX() => OperatingSystem.IsMacOS(); + public static bool IsMacOS() => OperatingSystem.IsMacOS(); public static bool IsNonWindows() => !OperatingSystem.IsWindows(); @@ -1020,7 +1020,7 @@ public class Utils { try { - if (IsWindows() || IsOSX()) + if (IsWindows() || IsMacOS()) { return false; } diff --git a/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs b/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs index 82e94517..bc86cd7f 100644 --- a/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs +++ b/v2rayN/ServiceLib/Handler/AutoStartupHandler.cs @@ -26,7 +26,7 @@ public static class AutoStartupHandler await SetTaskLinux(); } } - else if (Utils.IsOSX()) + else if (Utils.IsMacOS()) { await ClearTaskOSX(); diff --git a/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs b/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs index 426945e0..21453591 100644 --- a/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs +++ b/v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs @@ -33,7 +33,7 @@ public static class SysProxyHandler await ProxySettingLinux.SetProxy(Global.Loopback, port, exceptions); break; - case ESysProxyType.ForcedChange when Utils.IsOSX(): + case ESysProxyType.ForcedChange when Utils.IsMacOS(): await ProxySettingOSX.SetProxy(Global.Loopback, port, exceptions); break; @@ -45,7 +45,7 @@ public static class SysProxyHandler await ProxySettingLinux.UnsetProxy(); break; - case ESysProxyType.ForcedClear when Utils.IsOSX(): + case ESysProxyType.ForcedClear when Utils.IsMacOS(): await ProxySettingOSX.UnsetProxy(); break; diff --git a/v2rayN/ServiceLib/Manager/CoreAdminManager.cs b/v2rayN/ServiceLib/Manager/CoreAdminManager.cs index 6c54e1e1..254688e4 100644 --- a/v2rayN/ServiceLib/Manager/CoreAdminManager.cs +++ b/v2rayN/ServiceLib/Manager/CoreAdminManager.cs @@ -67,7 +67,7 @@ public class CoreAdminManager try { - var shellFileName = Utils.IsOSX() ? Global.KillAsSudoOSXShellFileName : Global.KillAsSudoLinuxShellFileName; + var shellFileName = Utils.IsMacOS() ? Global.KillAsSudoOSXShellFileName : Global.KillAsSudoLinuxShellFileName; var shFilePath = await FileUtils.CreateLinuxShellFile("kill_as_sudo.sh", EmbedUtils.GetEmbedText(shellFileName), true); if (shFilePath.Contains(' ')) { diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxInboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxInboundService.cs index 91f76ad9..76e90110 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxInboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxInboundService.cs @@ -61,7 +61,7 @@ public partial class CoreConfigSingboxService } var tunInbound = JsonUtils.Deserialize(EmbedUtils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { }; - tunInbound.interface_name = Utils.IsOSX() ? $"utun{new Random().Next(99)}" : "singbox_tun"; + tunInbound.interface_name = Utils.IsMacOS() ? $"utun{new Random().Next(99)}" : "singbox_tun"; tunInbound.mtu = _config.TunModeItem.Mtu; tunInbound.auto_route = _config.TunModeItem.AutoRoute; tunInbound.strict_route = _config.TunModeItem.StrictRoute; diff --git a/v2rayN/ServiceLib/Services/UpdateService.cs b/v2rayN/ServiceLib/Services/UpdateService.cs index b5129fc7..fc636c60 100644 --- a/v2rayN/ServiceLib/Services/UpdateService.cs +++ b/v2rayN/ServiceLib/Services/UpdateService.cs @@ -313,7 +313,7 @@ public class UpdateService(Config config, Func updateFunc) _ => null, }; } - else if (Utils.IsOSX()) + else if (Utils.IsMacOS()) { return RuntimeInformation.ProcessArchitecture switch { diff --git a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs index ce68d96b..48792a0c 100644 --- a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs @@ -511,7 +511,7 @@ public class MainWindowViewModel : MyReactiveObject { ProcUtils.ProcessStart("xdg-open", path); } - else if (Utils.IsOSX()) + else if (Utils.IsMacOS()) { ProcUtils.ProcessStart("open", path); } diff --git a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs index b7c2a1e7..7617ac6f 100644 --- a/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs @@ -504,7 +504,7 @@ public class StatusBarViewModel : MyReactiveObject { return AppManager.Instance.LinuxSudoPwd.IsNotEmpty(); } - else if (Utils.IsOSX()) + else if (Utils.IsMacOS()) { return AppManager.Instance.LinuxSudoPwd.IsNotEmpty(); } diff --git a/v2rayN/v2rayN.Desktop/Base/WindowBase.cs b/v2rayN/v2rayN.Desktop/Base/WindowBase.cs index 63b00036..d1419b30 100644 --- a/v2rayN/v2rayN.Desktop/Base/WindowBase.cs +++ b/v2rayN/v2rayN.Desktop/Base/WindowBase.cs @@ -26,7 +26,7 @@ public class WindowBase : ReactiveWindow where TViewMode Height = sizeItem.Height; var workingArea = (Screens.ScreenFromWindow(this) ?? Screens.Primary).WorkingArea; - var scaling = (Utils.IsOSX() ? null : VisualRoot?.RenderScaling) ?? 1.0; + var scaling = (Utils.IsMacOS() ? null : VisualRoot?.RenderScaling) ?? 1.0; var x = workingArea.X + ((workingArea.Width - (Width * scaling)) / 2); var y = workingArea.Y + ((workingArea.Height - (Height * scaling)) / 2); diff --git a/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs index 7bef84be..4d545bf5 100644 --- a/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs @@ -142,7 +142,7 @@ public partial class OptionSettingWindow : WindowBase tbAutoRunTip.IsVisible = false; } - else if (Utils.IsOSX()) + else if (Utils.IsMacOS()) { txbSettingsExceptionTip.IsVisible = false; panSystemProxyAdvanced.IsVisible = false; From e6cb146671ab409beea2f768b0f13e537f4e0928 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Sun, 9 Nov 2025 11:11:23 +0800 Subject: [PATCH 4/7] Refactor UI platform visibility to use ViewModel properties --- .../ViewModels/MainWindowViewModel.cs | 3 ++ .../ViewModels/OptionSettingViewModel.cs | 13 +++++++++ v2rayN/v2rayN.Desktop/Views/MainWindow.axaml | 6 ++-- .../v2rayN.Desktop/Views/MainWindow.axaml.cs | 4 --- .../Views/OptionSettingWindow.axaml | 21 +++++++------- .../Views/OptionSettingWindow.axaml.cs | 28 ------------------- 6 files changed, 30 insertions(+), 45 deletions(-) diff --git a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs index 48792a0c..c3bb0fe3 100644 --- a/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs @@ -62,6 +62,8 @@ public class MainWindowViewModel : MyReactiveObject [Reactive] public int TabMainSelectedIndex { get; set; } + [Reactive] public bool BlIsWindows { get; set; } + #endregion Menu #region Init @@ -70,6 +72,7 @@ public class MainWindowViewModel : MyReactiveObject { _config = AppManager.Instance.Config; _updateView = updateView; + BlIsWindows = Utils.IsWindows(); #region WhenAnyValue && ReactiveCommand diff --git a/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs b/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs index 81f63d00..4012e663 100644 --- a/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs @@ -69,6 +69,15 @@ public class OptionSettingViewModel : MyReactiveObject #endregion UI + #region UI visibility + + [Reactive] public bool BlIsWindows { get; set; } + [Reactive] public bool BlIsLinux { get; set; } + [Reactive] public bool BlIsIsMacOS { get; set; } + [Reactive] public bool BlIsNonWindows { get; set; } + + #endregion UI visibility + #region System proxy [Reactive] public bool notProxyLocalAddress { get; set; } @@ -108,6 +117,10 @@ public class OptionSettingViewModel : MyReactiveObject { _config = AppManager.Instance.Config; _updateView = updateView; + BlIsWindows = Utils.IsWindows(); + BlIsLinux = Utils.IsLinux(); + BlIsIsMacOS = Utils.IsMacOS(); + BlIsNonWindows = Utils.IsNonWindows(); SaveCmd = ReactiveCommand.CreateFromTask(async () => { diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml index e02d0ba5..5a391134 100644 --- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml @@ -75,10 +75,10 @@ - + - - + + diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs index 64063de8..08f66dcd 100644 --- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs @@ -161,10 +161,6 @@ public partial class MainWindow : WindowBase else { Title = $"{Utils.GetVersion()}"; - - menuRebootAsAdmin.IsVisible = false; - menuSettingsSetUWP.IsVisible = false; - menuGlobalHotkeySetting.IsVisible = false; } menuAddServerViaScan.IsVisible = false; diff --git a/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml b/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml index 321dba74..36a57637 100644 --- a/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml @@ -356,11 +356,11 @@ Margin="{StaticResource Margin4}" HorizontalAlignment="Left" /> @@ -443,24 +443,25 @@ HorizontalAlignment="Left" /> + HorizontalAlignment="Left" + IsVisible="{Binding BlIsLinux}" /> + Watermark="proxy_set.sh" />