Using RxApp replace ViewAction
Some checks are pending
release Linux / build (Release) (push) Waiting to run
release macOS / build (Release) (push) Waiting to run
release Windows desktop (Avalonia UI) / build (Release) (push) Waiting to run
release Windows / build (Release) (push) Waiting to run

This commit is contained in:
2dust 2025-09-02 17:12:38 +08:00
parent 3f67a23f8b
commit 1a6fbf782d
10 changed files with 87 additions and 93 deletions

View file

@ -15,7 +15,6 @@ public enum EViewAction
ShowHideWindow, ShowHideWindow,
ScanScreenTask, ScanScreenTask,
ScanImageTask, ScanImageTask,
Shutdown,
BrowseServer, BrowseServer,
ImportRulesFromFile, ImportRulesFromFile,
InitSettingFont, InitSettingFont,

View file

@ -13,6 +13,8 @@ public static class AppEvents
public static readonly Subject<Unit> AppExitRequested = new(); public static readonly Subject<Unit> AppExitRequested = new();
public static readonly Subject<bool> ShutdownRequested = new();
public static readonly Subject<Unit> AdjustMainLvColWidthRequested = new(); public static readonly Subject<Unit> AdjustMainLvColWidthRequested = new();
public static readonly Subject<ServerSpeedItem> DispatcherStatisticsRequested = new(); public static readonly Subject<ServerSpeedItem> DispatcherStatisticsRequested = new();

View file

@ -1,3 +1,5 @@
using System.Reactive;
namespace ServiceLib.Manager; namespace ServiceLib.Manager;
public sealed class AppManager public sealed class AppManager
@ -34,7 +36,7 @@ public sealed class AppManager
#endregion Property #endregion Property
#region Init #region App
public bool InitApp() public bool InitApp()
{ {
@ -87,7 +89,40 @@ public sealed class AppManager
return true; return true;
} }
#endregion Init public async Task AppExitAsync(bool needShutdown)
{
try
{
Logging.SaveLog("AppExitAsync Begin");
await SysProxyHandler.UpdateSysProxy(_config, true);
AppEvents.AppExitRequested.OnNext(Unit.Default);
await Task.Delay(50); //Wait for AppExitRequested to be processed
await ConfigHandler.SaveConfig(_config);
await ProfileExManager.Instance.SaveTo();
await StatisticsManager.Instance.SaveTo();
await CoreManager.Instance.CoreStop();
StatisticsManager.Instance.Close();
Logging.SaveLog("AppExitAsync End");
}
catch { }
finally
{
if (needShutdown)
{
Shutdown(false);
}
}
}
public void Shutdown(bool byUser)
{
AppEvents.ShutdownRequested.OnNext(byUser);
}
#endregion App
#region Config #region Config

View file

@ -136,8 +136,7 @@ public class BackupAndRestoreViewModel : MyReactiveObject
var result = await CreateZipFileFromDirectory(fileBackup); var result = await CreateZipFileFromDirectory(fileBackup);
if (result) if (result)
{ {
var service = Locator.Current.GetService<MainWindowViewModel>(); await AppManager.Instance.AppExitAsync(false);
await service?.MyAppExitAsync(true);
await SQLiteHelper.Instance.DisposeDbConnectionAsync(); await SQLiteHelper.Instance.DisposeDbConnectionAsync();
var toPath = Utils.GetConfigPath(); var toPath = Utils.GetConfigPath();
@ -154,7 +153,7 @@ public class BackupAndRestoreViewModel : MyReactiveObject
_ = ProcUtils.ProcessStart(upgradeFileName, Global.RebootAs, Utils.StartupPath()); _ = ProcUtils.ProcessStart(upgradeFileName, Global.RebootAs, Utils.StartupPath());
} }
} }
service?.Shutdown(true); AppManager.Instance.Shutdown(true);
} }
else else
{ {

View file

@ -236,12 +236,19 @@ public class CheckUpdateViewModel : MyReactiveObject
{ {
return; return;
} }
if (!Utils.UpgradeAppExists(out _)) if (!Utils.UpgradeAppExists(out var upgradeFileName))
{ {
await UpdateView(_v2rayN, ResUI.UpgradeAppNotExistTip); await UpdateView(_v2rayN, ResUI.UpgradeAppNotExistTip);
NoticeManager.Instance.SendMessageAndEnqueue(ResUI.UpgradeAppNotExistTip);
Logging.SaveLog("UpgradeApp does not exist");
return; return;
} }
Locator.Current.GetService<MainWindowViewModel>()?.UpgradeApp(fileName);
var id = ProcUtils.ProcessStart(upgradeFileName, fileName, Utils.StartupPath());
if (id > 0)
{
await AppManager.Instance.AppExitAsync(true);
}
} }
catch (Exception ex) catch (Exception ex)
{ {

View file

@ -282,59 +282,11 @@ public class MainWindowViewModel : MyReactiveObject
AppEvents.DispatcherStatisticsRequested.OnNext(update); AppEvents.DispatcherStatisticsRequested.OnNext(update);
} }
public async Task MyAppExitAsync(bool blWindowsShutDown)
{
try
{
Logging.SaveLog("MyAppExitAsync Begin");
await SysProxyHandler.UpdateSysProxy(_config, true);
AppEvents.AppExitRequested.OnNext(Unit.Default);
await ConfigHandler.SaveConfig(_config);
await ProfileExManager.Instance.SaveTo();
await StatisticsManager.Instance.SaveTo();
await CoreManager.Instance.CoreStop();
StatisticsManager.Instance.Close();
Logging.SaveLog("MyAppExitAsync End");
}
catch { }
finally
{
if (!blWindowsShutDown)
{
_updateView?.Invoke(EViewAction.Shutdown, false);
}
}
}
public async Task UpgradeApp(string arg)
{
if (!Utils.UpgradeAppExists(out var upgradeFileName))
{
NoticeManager.Instance.SendMessageAndEnqueue(ResUI.UpgradeAppNotExistTip);
Logging.SaveLog("UpgradeApp does not exist");
return;
}
var id = ProcUtils.ProcessStart(upgradeFileName, arg, Utils.StartupPath());
if (id > 0)
{
await MyAppExitAsync(false);
}
}
public void ShowHideWindow(bool? blShow) public void ShowHideWindow(bool? blShow)
{ {
_updateView?.Invoke(EViewAction.ShowHideWindow, blShow); _updateView?.Invoke(EViewAction.ShowHideWindow, blShow);
} }
public void Shutdown(bool byUser)
{
_updateView?.Invoke(EViewAction.Shutdown, byUser);
}
#endregion Actions #endregion Actions
#region Servers && Groups #region Servers && Groups
@ -517,7 +469,7 @@ public class MainWindowViewModel : MyReactiveObject
public async Task RebootAsAdmin() public async Task RebootAsAdmin()
{ {
ProcUtils.RebootAsAdmin(); ProcUtils.RebootAsAdmin();
await MyAppExitAsync(false); await AppManager.Instance.AppExitAsync(true);
} }
private async Task ClearServerStatistics() private async Task ClearServerStatistics()

View file

@ -74,11 +74,7 @@ public partial class App : Application
private async void MenuExit_Click(object? sender, EventArgs e) private async void MenuExit_Click(object? sender, EventArgs e)
{ {
var service = Locator.Current.GetService<MainWindowViewModel>(); await AppManager.Instance.AppExitAsync(false);
if (service != null) AppManager.Instance.Shutdown(true);
{
await service.MyAppExitAsync(true);
}
service?.Shutdown(true);
} }
} }

View file

@ -148,6 +148,12 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
.ObserveOn(RxApp.MainThreadScheduler) .ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ => StorageUI()) .Subscribe(_ => StorageUI())
.DisposeWith(disposables); .DisposeWith(disposables);
AppEvents.ShutdownRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(content => Shutdown(content))
.DisposeWith(disposables);
}); });
if (Utils.IsWindows()) if (Utils.IsWindows())
@ -222,19 +228,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
DispatcherPriority.Default); DispatcherPriority.Default);
break; break;
case EViewAction.Shutdown:
if (obj != null && _blCloseByUser == false)
{
_blCloseByUser = (bool)obj;
}
StorageUI();
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
HotkeyManager.Instance.Dispose();
desktop.Shutdown();
}
break;
case EViewAction.ScanScreenTask: case EViewAction.ScanScreenTask:
await ScanScreenTaskAsync(); await ScanScreenTaskAsync();
break; break;
@ -289,10 +282,7 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
break; break;
case WindowCloseReason.ApplicationShutdown or WindowCloseReason.OSShutdown: case WindowCloseReason.ApplicationShutdown or WindowCloseReason.OSShutdown:
if (ViewModel != null) await AppManager.Instance.AppExitAsync(false);
{
await ViewModel.MyAppExitAsync(true);
}
break; break;
} }
@ -387,9 +377,21 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
_blCloseByUser = true; _blCloseByUser = true;
StorageUI(); StorageUI();
if (ViewModel != null)
await AppManager.Instance.AppExitAsync(true);
}
private void Shutdown(bool obj)
{
if (obj is bool b && _blCloseByUser == false)
{ {
await ViewModel.MyAppExitAsync(false); _blCloseByUser = b;
}
StorageUI();
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
HotkeyManager.Instance.Dispose();
desktop.Shutdown();
} }
} }

View file

@ -145,6 +145,12 @@ public partial class MainWindow
.ObserveOn(RxApp.MainThreadScheduler) .ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ => StorageUI()) .Subscribe(_ => StorageUI())
.DisposeWith(disposables); .DisposeWith(disposables);
AppEvents.ShutdownRequested
.AsObservable()
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(content => Shutdown(content))
.DisposeWith(disposables);
}); });
this.Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}"; this.Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
@ -212,13 +218,6 @@ public partial class MainWindow
}), DispatcherPriority.Normal); }), DispatcherPriority.Normal);
break; break;
case EViewAction.Shutdown:
Application.Current?.Dispatcher.Invoke((() =>
{
Application.Current.Shutdown();
}), DispatcherPriority.Normal);
break;
case EViewAction.ScanScreenTask: case EViewAction.ScanScreenTask:
await ScanScreenTaskAsync(); await ScanScreenTaskAsync();
break; break;
@ -266,7 +265,12 @@ public partial class MainWindow
{ {
Logging.SaveLog("Current_SessionEnding"); Logging.SaveLog("Current_SessionEnding");
StorageUI(); StorageUI();
await ViewModel?.MyAppExitAsync(true); await AppManager.Instance.AppExitAsync(false);
}
private void Shutdown(bool obj)
{
Application.Current.Shutdown();
} }
private void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e) private void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)

View file

@ -97,9 +97,7 @@ public partial class StatusBarView
private async void menuExit_Click(object sender, RoutedEventArgs e) private async void menuExit_Click(object sender, RoutedEventArgs e)
{ {
tbNotify.Dispose(); tbNotify.Dispose();
var service = Locator.Current.GetService<MainWindowViewModel>(); await AppManager.Instance.AppExitAsync(true);
if (service != null)
await service.MyAppExitAsync(false);
} }
private void txtRunningInfoDisplay_MouseDoubleClick(object sender, MouseButtonEventArgs e) private void txtRunningInfoDisplay_MouseDoubleClick(object sender, MouseButtonEventArgs e)