Improve dependency injection in updater & settings view model & settings page

This commit is contained in:
Jack251970 2025-01-13 12:00:45 +08:00
parent 3bebb69093
commit 8d8384965e
9 changed files with 46 additions and 56 deletions

View file

@ -34,14 +34,14 @@ namespace Flow.Launcher.Core
private SemaphoreSlim UpdateLock { get; } = new SemaphoreSlim(1);
public async Task UpdateAppAsync(IPublicAPI api, bool silentUpdate = true)
public async Task UpdateAppAsync(bool silentUpdate = true)
{
await UpdateLock.WaitAsync().ConfigureAwait(false);
try
{
if (!silentUpdate)
api.ShowMsg(api.GetTranslation("pleaseWait"),
api.GetTranslation("update_flowlauncher_update_check"));
API.ShowMsg(API.GetTranslation("pleaseWait"),
API.GetTranslation("update_flowlauncher_update_check"));
using var updateManager = await GitHubUpdateManagerAsync(GitHubRepository).ConfigureAwait(false);
@ -56,13 +56,13 @@ namespace Flow.Launcher.Core
if (newReleaseVersion <= currentVersion)
{
if (!silentUpdate)
API.ShowMsgBox(api.GetTranslation("update_flowlauncher_already_on_latest"));
API.ShowMsgBox(API.GetTranslation("update_flowlauncher_already_on_latest"));
return;
}
if (!silentUpdate)
api.ShowMsg(api.GetTranslation("update_flowlauncher_update_found"),
api.GetTranslation("update_flowlauncher_updating"));
API.ShowMsg(API.GetTranslation("update_flowlauncher_update_found"),
API.GetTranslation("update_flowlauncher_updating"));
await updateManager.DownloadReleases(newUpdateInfo.ReleasesToApply).ConfigureAwait(false);
@ -73,7 +73,7 @@ namespace Flow.Launcher.Core
var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}";
FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination, (s) => API.ShowMsgBox(s));
if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination, (s) => API.ShowMsgBox(s)))
API.ShowMsgBox(string.Format(api.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"),
API.ShowMsgBox(string.Format(API.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"),
DataLocation.PortableDataPath,
targetDestination));
}
@ -86,7 +86,7 @@ namespace Flow.Launcher.Core
Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}");
if (API.ShowMsgBox(newVersionTips, api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes)
if (API.ShowMsgBox(newVersionTips, API.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
UpdateManager.RestartApp(Constant.ApplicationFileName);
}
@ -99,8 +99,8 @@ namespace Flow.Launcher.Core
Log.Exception($"|Updater.UpdateApp|Error Occurred", e);
if (!silentUpdate)
api.ShowMsg(api.GetTranslation("update_flowlauncher_fail"),
api.GetTranslation("update_flowlauncher_check_connection"));
API.ShowMsg(API.GetTranslation("update_flowlauncher_fail"),
API.GetTranslation("update_flowlauncher_check_connection"));
}
finally
{

View file

@ -74,8 +74,6 @@ namespace Flow.Launcher
Ioc.Default.GetRequiredService<Portable>().PreStartCleanUpAfterPortabilityUpdate();
Ioc.Default.GetRequiredService<SettingWindowViewModel>().Initialize();
Log.Info("|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------");
Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}");
@ -96,6 +94,7 @@ namespace Flow.Launcher
PluginManager.LoadPlugins(_settings.PluginSettings);
API = Ioc.Default.GetRequiredService<IPublicAPI>();
((PublicAPIInstance)API).Initialize();
Http.API = API;
Http.Proxy = _settings.Proxy;
@ -160,11 +159,11 @@ namespace Flow.Launcher
{
// check update every 5 hours
var timer = new PeriodicTimer(TimeSpan.FromHours(5));
await Ioc.Default.GetRequiredService<Updater>().UpdateAppAsync(API);
await Ioc.Default.GetRequiredService<Updater>().UpdateAppAsync();
while (await timer.WaitForNextTickAsync())
// check updates on startup
await Ioc.Default.GetRequiredService<Updater>().UpdateAppAsync(API);
await Ioc.Default.GetRequiredService<Updater>().UpdateAppAsync();
}
});
}

View file

@ -6,20 +6,17 @@ using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using Flow.Launcher.Core;
namespace Flow.Launcher
{
public partial class CustomQueryHotkeySetting : Window
{
private SettingWindow _settingWidow;
private bool update;
private CustomPluginHotkey updateCustomHotkey;
public Settings Settings { get; }
public CustomQueryHotkeySetting(SettingWindow settingWidow, Settings settings)
public CustomQueryHotkeySetting(Settings settings)
{
_settingWidow = settingWidow;
Settings = settings;
InitializeComponent();
}

View file

@ -26,6 +26,7 @@ using System.Collections.Concurrent;
using System.Diagnostics;
using System.Collections.Specialized;
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Core;
namespace Flow.Launcher
{
@ -33,19 +34,26 @@ namespace Flow.Launcher
{
private readonly SettingWindowViewModel _settingsVM;
private readonly MainViewModel _mainVM;
private readonly IAlphabet _alphabet;
#region Constructor
private Updater _updater;
#region Constructor & Initialization
public PublicAPIInstance()
{
_settingsVM = Ioc.Default.GetRequiredService<SettingWindowViewModel>();
_mainVM = Ioc.Default.GetRequiredService<MainViewModel>();
_alphabet = Ioc.Default.GetRequiredService<IAlphabet>();
GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback;
WebRequest.RegisterPrefix("data", new DataWebRequestFactory());
}
public void Initialize()
{
// We need to initialize Updater not in the constructor because we want to avoid
// recrusive dependency injection
_updater = Ioc.Default.GetRequiredService<Updater>();
}
#endregion
#region Public API
@ -78,14 +86,14 @@ namespace Flow.Launcher
public event VisibilityChangedEventHandler VisibilityChanged { add => _mainVM.VisibilityChanged += value; remove => _mainVM.VisibilityChanged -= value; }
public void CheckForNewUpdate() => _settingsVM.UpdateApp();
public void CheckForNewUpdate() => _ = _updater.UpdateAppAsync(false);
public void SaveAppAllSettings()
{
PluginManager.Save();
_mainVM.Save();
_settingsVM.Save();
ImageLoader.Save();
_ = ImageLoader.Save();
}
public Task ReloadAllPluginData() => PluginManager.ReloadDataAsync();
@ -105,7 +113,7 @@ namespace Flow.Launcher
{
Application.Current.Dispatcher.Invoke(() =>
{
SettingWindow sw = SingletonWindowOpener.Open<SettingWindow>(this, _settingsVM);
SettingWindow sw = SingletonWindowOpener.Open<SettingWindow>();
});
}

View file

@ -96,7 +96,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel
}
[RelayCommand]
private Task UpdateApp() => _updater.UpdateAppAsync(App.API, false);
private Task UpdateApp() => _updater.UpdateAppAsync(false);
private void ClearLogFolder()
{

View file

@ -160,7 +160,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
private void UpdateApp()
{
_ = _updater.UpdateAppAsync(App.API, false);
_ = _updater.UpdateAppAsync(false);
}
public bool AutoUpdates

View file

@ -7,7 +7,6 @@ using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Hotkey;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Core;
namespace Flow.Launcher.SettingPages.ViewModels;
@ -71,7 +70,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel
return;
}
var window = new CustomQueryHotkeySetting(null, Settings);
var window = new CustomQueryHotkeySetting(Settings);
window.UpdateItem(item);
window.ShowDialog();
}
@ -79,7 +78,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel
[RelayCommand]
private void CustomHotkeyAdd()
{
new CustomQueryHotkeySetting(null, Settings).ShowDialog();
new CustomQueryHotkeySetting(Settings).ShowDialog();
}
[RelayCommand]

View file

@ -3,6 +3,7 @@ using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Core;
using Flow.Launcher.Core.Configuration;
using Flow.Launcher.Helper;
@ -17,16 +18,21 @@ namespace Flow.Launcher;
public partial class SettingWindow
{
private readonly Updater _updater;
private readonly IPortable _portable;
private readonly IPublicAPI _api;
private readonly Settings _settings;
private readonly SettingWindowViewModel _viewModel;
public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel)
public SettingWindow()
{
var viewModel = Ioc.Default.GetRequiredService<SettingWindowViewModel>();
_settings = viewModel.Settings;
DataContext = viewModel;
_viewModel = viewModel;
_api = api;
_updater = Ioc.Default.GetRequiredService<Updater>();
_portable = Ioc.Default.GetRequiredService<Portable>();
_api = Ioc.Default.GetRequiredService<IPublicAPI>();
InitializePosition();
InitializeComponent();
}
@ -125,7 +131,7 @@ public partial class SettingWindow
WindowState = _settings.SettingWindowState;
}
private bool IsPositionValid(double top, double left)
private static bool IsPositionValid(double top, double left)
{
foreach (var screen in Screen.AllScreens)
{
@ -145,7 +151,7 @@ public partial class SettingWindow
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0);
var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0);
var left = (dip2.X - this.ActualWidth) / 2 + dip1.X;
var left = (dip2.X - ActualWidth) / 2 + dip1.X;
return left;
}
@ -154,13 +160,13 @@ public partial class SettingWindow
var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position);
var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y);
var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height);
var top = (dip2.Y - this.ActualHeight) / 2 + dip1.Y - 20;
var top = (dip2.Y - ActualHeight) / 2 + dip1.Y - 20;
return top;
}
private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
{
var paneData = new PaneData(_settings, _viewModel.Updater, _viewModel.Portable);
var paneData = new PaneData(_settings, _updater, _portable);
if (args.IsSettingsSelected)
{
ContentFrame.Navigate(typeof(SettingsPaneGeneral), paneData);

View file

@ -1,37 +1,18 @@
using CommunityToolkit.Mvvm.DependencyInjection;
using Flow.Launcher.Core;
using Flow.Launcher.Core.Configuration;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
namespace Flow.Launcher.ViewModel;
public class SettingWindowViewModel : BaseModel
public partial class SettingWindowViewModel : BaseModel
{
public Updater Updater { get; private set; }
public IPortable Portable { get; private set; }
public Settings Settings { get; }
public Settings Settings { get; init; }
public SettingWindowViewModel()
{
Settings = Ioc.Default.GetRequiredService<Settings>();
}
public void Initialize()
{
// We don not initialize Updater and Portable in the constructor because we want to avoid
// recrusive dependency injection
Updater = Ioc.Default.GetRequiredService<Updater>();
Portable = Ioc.Default.GetRequiredService<Portable>();
}
public async void UpdateApp()
{
await Updater.UpdateAppAsync(App.API, false);
}
/// <summary>
/// Save Flow settings. Plugins settings are not included.
/// </summary>