From 5d16216a5519a42c6f201219ddca60ef24289308 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 21:53:09 +0800 Subject: [PATCH 01/19] Fix environment exit --- Flow.Launcher.Core/Configuration/Portable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index 069154364ab..4f8287c16a4 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -169,7 +169,7 @@ public void PreStartCleanUpAfterPortabilityUpdate() { FilesFolders.OpenPath(Constant.RootDirectory, (s) => API.ShowMsgBox(s)); - Environment.Exit(0); + Application.Current.Shutdown(); } } // Otherwise, if the portable data folder is marked for deletion, From 96f10d27997f13e24866a415c346ba947e515f98 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 22:13:12 +0800 Subject: [PATCH 02/19] Code quality --- Flow.Launcher.Infrastructure/Win32Helper.cs | 11 +++++++++++ Flow.Launcher/Notification.cs | 5 ++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 7a3a0c36e26..42461dc180a 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -488,5 +488,16 @@ or PInvoke.LOCALE_TRANSIENT_KEYBOARD3 } #endregion + + #region Noticification + + public static bool IsNotificationSupport() + { + // Noticification only supported Windows 10 19041+ + return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && + Environment.OSVersion.Version.Build >= 19041; + } + + #endregion } } diff --git a/Flow.Launcher/Notification.cs b/Flow.Launcher/Notification.cs index cb1cbb729ec..23125de151e 100644 --- a/Flow.Launcher/Notification.cs +++ b/Flow.Launcher/Notification.cs @@ -9,8 +9,8 @@ namespace Flow.Launcher { internal static class Notification { - internal static bool legacy = Environment.OSVersion.Version.Build < 19041; - [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "")] + internal static bool legacy = !Win32Helper.IsNotificationSupport(); + internal static void Uninstall() { if (!legacy) @@ -25,7 +25,6 @@ public static void Show(string title, string subTitle, string iconPath = null) }); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "")] private static void ShowInternal(string title, string subTitle, string iconPath = null) { // Handle notification for win7/8/early win10 From b1721f15077c264a79df2642e12a5fd1c1b369fe Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 22:25:04 +0800 Subject: [PATCH 03/19] Code quality --- Flow.Launcher.Core/Updater.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 9a77ece3253..5b2144efe9f 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -4,10 +4,11 @@ using System.Net.Http; using System.Net.Sockets; using System.Linq; +using System.Text.Json.Serialization; +using System.Threading; using System.Threading.Tasks; using System.Windows; -using JetBrains.Annotations; -using Squirrel; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core.Resource; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Infrastructure; @@ -15,8 +16,8 @@ using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; -using System.Text.Json.Serialization; -using System.Threading; +using JetBrains.Annotations; +using Squirrel; namespace Flow.Launcher.Core { @@ -70,7 +71,7 @@ public async Task UpdateAppAsync(bool silentUpdate = true) if (DataLocation.PortableDataLocationInUse()) { - var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}"; + var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion}\\{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"), @@ -122,7 +123,7 @@ private class GithubRelease } // https://github.com/Squirrel/Squirrel.Windows/blob/master/src/Squirrel/UpdateManager.Factory.cs - private async Task GitHubUpdateManagerAsync(string repository) + private static async Task GitHubUpdateManagerAsync(string repository) { var uri = new Uri(repository); var api = $"https://api.github.com/repos{uri.AbsolutePath}/releases"; @@ -144,9 +145,9 @@ private async Task GitHubUpdateManagerAsync(string repository) return manager; } - public string NewVersionTips(string version) + private static string NewVersionTips(string version) { - var translator = InternationalizationManager.Instance; + var translator = Ioc.Default.GetRequiredService(); var tips = string.Format(translator.GetTranslation("newVersionTips"), version); return tips; From 0def881b9d74497974124c35327cfa10b6bc35fa Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 22:27:02 +0800 Subject: [PATCH 04/19] Code quality --- Flow.Launcher.Core/Configuration/Portable.cs | 40 ++++++++------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index 4f8287c16a4..8abdae8d856 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -22,7 +22,7 @@ public class Portable : IPortable /// As at Squirrel.Windows version 1.5.2, UpdateManager needs to be disposed after finish /// /// - private UpdateManager NewUpdateManager() + private static UpdateManager NewUpdateManager() { var applicationFolderName = Constant.ApplicationDirectory .Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None) @@ -81,20 +81,16 @@ public void EnablePortableMode() public void RemoveShortcuts() { - using (var portabilityUpdater = NewUpdateManager()) - { - portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu); - portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop); - portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup); - } + using var portabilityUpdater = NewUpdateManager(); + portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu); + portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop); + portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup); } public void RemoveUninstallerEntry() { - using (var portabilityUpdater = NewUpdateManager()) - { - portabilityUpdater.RemoveUninstallerRegistryEntry(); - } + using var portabilityUpdater = NewUpdateManager(); + portabilityUpdater.RemoveUninstallerRegistryEntry(); } public void MoveUserDataFolder(string fromLocation, string toLocation) @@ -110,12 +106,10 @@ public void VerifyUserDataAfterMove(string fromLocation, string toLocation) public void CreateShortcuts() { - using (var portabilityUpdater = NewUpdateManager()) - { - portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu, false); - portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop, false); - portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup, false); - } + using var portabilityUpdater = NewUpdateManager(); + portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu, false); + portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop, false); + portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup, false); } public void CreateUninstallerEntry() @@ -129,18 +123,14 @@ public void CreateUninstallerEntry() subKey2.SetValue("DisplayIcon", Path.Combine(Constant.ApplicationDirectory, "app.ico"), RegistryValueKind.String); } - using (var portabilityUpdater = NewUpdateManager()) - { - _ = portabilityUpdater.CreateUninstallerRegistryEntry(); - } + using var portabilityUpdater = NewUpdateManager(); + _ = portabilityUpdater.CreateUninstallerRegistryEntry(); } - internal void IndicateDeletion(string filePathTodelete) + private static void IndicateDeletion(string filePathTodelete) { var deleteFilePath = Path.Combine(filePathTodelete, DataLocation.DeletionIndicatorFile); - using (var _ = File.CreateText(deleteFilePath)) - { - } + using var _ = File.CreateText(deleteFilePath); } /// From 2f53a79a26fc84cb012d580a37c9c2bab7eb7965 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 22:56:31 +0800 Subject: [PATCH 05/19] Revert "Fix environment exit" This reverts commit 5d16216a5519a42c6f201219ddca60ef24289308. --- Flow.Launcher.Core/Configuration/Portable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index 8abdae8d856..2b570d2c088 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -159,7 +159,7 @@ public void PreStartCleanUpAfterPortabilityUpdate() { FilesFolders.OpenPath(Constant.RootDirectory, (s) => API.ShowMsgBox(s)); - Application.Current.Shutdown(); + Environment.Exit(0); } } // Otherwise, if the portable data folder is marked for deletion, From b725975b9898e249a7382171cf2edb07437871d0 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 23:01:16 +0800 Subject: [PATCH 06/19] Fix environment exit stuck issue --- Flow.Launcher/App.xaml.cs | 8 ++++++++ Flow.Launcher/MainWindow.xaml.cs | 13 +++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 9aee56bff81..f484d4dbadc 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -304,6 +304,14 @@ protected virtual void Dispose(bool disposing) return; } + // If we call Environment.Exit(0), the application dispose will be called before _mainWindow.Close() + // Accessing _mainWindow?.Dispatcher will cause the application stuck + // So here we need to check it and just return so that we will not acees _mainWindow?.Dispatcher + if (!_mainWindow.CanClose) + { + return; + } + _disposed = true; } diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 011d46d6b21..c62606743a6 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -32,6 +32,13 @@ namespace Flow.Launcher { public partial class MainWindow : IDisposable { + #region Public Property + + // Window Event: Close Event + public bool CanClose { get; set; } = false; + + #endregion + #region Private Fields // Dependency Injection @@ -45,8 +52,6 @@ public partial class MainWindow : IDisposable private readonly ContextMenu _contextMenu = new(); private readonly MainViewModel _viewModel; - // Window Event: Close Event - private bool _canClose = false; // Window Event: Key Event private bool _isArrowKeyPressed = false; @@ -279,7 +284,7 @@ private async void OnLoaded(object sender, RoutedEventArgs _) private async void OnClosing(object sender, CancelEventArgs e) { - if (!_canClose) + if (!CanClose) { _notifyIcon.Visible = false; App.API.SaveAppAllSettings(); @@ -287,7 +292,7 @@ private async void OnClosing(object sender, CancelEventArgs e) await PluginManager.DisposePluginsAsync(); Notification.Uninstall(); // After plugins are all disposed, we can close the main window - _canClose = true; + CanClose = true; // Use this instead of Close() to avoid InvalidOperationException when calling Close() in OnClosing event Application.Current.Shutdown(); } From 95b38d21af7b8790659d9eb49e2edbbba9a037b1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 09:57:03 +0800 Subject: [PATCH 07/19] Wait image cache saved before restarting --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 8 +++++++- Flow.Launcher/PublicAPIInstance.cs | 7 +++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 6f7b1cd908d..0ba059b7bd5 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -61,7 +61,7 @@ await Stopwatch.NormalAsync("|ImageLoader.Initialize|Preload images cost", async }); } - public static async Task Save() + public static async Task SaveAsync() { await storageLock.WaitAsync(); @@ -77,6 +77,12 @@ await _storage.SaveAsync(ImageCache.EnumerateEntries() } } + public static async Task WaitSaveAsync() + { + await storageLock.WaitAsync(); + storageLock.Release(); + } + private static async Task> LoadStorageToConcurrentDictionaryAsync() { await storageLock.WaitAsync(); diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index e19ad2fdcd4..b86e731b3b8 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -57,7 +57,7 @@ public void ChangeQuery(string query, bool requery = false) _mainVM.ChangeQueryText(query, requery); } - public void RestartApp() + public async void RestartApp() { _mainVM.Hide(); @@ -66,6 +66,9 @@ public void RestartApp() // which will cause ungraceful exit SaveAppAllSettings(); + // wait for all image caches to be saved + await ImageLoader.WaitSaveAsync(); + // Restart requires Squirrel's Update.exe to be present in the parent folder, // it is only published from the project's release pipeline. When debugging without it, // the project may not restart or just terminates. This is expected. @@ -88,7 +91,7 @@ public void SaveAppAllSettings() PluginManager.Save(); _mainVM.Save(); _settings.Save(); - _ = ImageLoader.Save(); + _ = ImageLoader.SaveAsync(); } public Task ReloadAllPluginData() => PluginManager.ReloadDataAsync(); From e4577eb23edbe6ce4e13154d2588d9e42e494764 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 10:02:47 +0800 Subject: [PATCH 08/19] Improve code comment --- Flow.Launcher/PublicAPIInstance.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index b86e731b3b8..a9862c74c8c 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -57,16 +57,18 @@ public void ChangeQuery(string query, bool requery = false) _mainVM.ChangeQueryText(query, requery); } +#pragma warning disable VSTHRD100 // Avoid async void methods + public async void RestartApp() { _mainVM.Hide(); - // we must manually save + // We must manually save // UpdateManager.RestartApp() will call Environment.Exit(0) // which will cause ungraceful exit SaveAppAllSettings(); - // wait for all image caches to be saved + // Wait for all image caches to be saved before restarting await ImageLoader.WaitSaveAsync(); // Restart requires Squirrel's Update.exe to be present in the parent folder, @@ -75,6 +77,8 @@ public async void RestartApp() UpdateManager.RestartApp(Constant.ApplicationFileName); } +#pragma warning restore VSTHRD100 // Avoid async void methods + public void ShowMainWindow() => _mainVM.Show(); public void HideMainWindow() => _mainVM.Hide(); From 043fe76a613a5768bcd0e983acb555c58a8d681f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 10:03:19 +0800 Subject: [PATCH 09/19] Add settings save lock --- Flow.Launcher/PublicAPIInstance.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index a9862c74c8c..d88eeb7c9e3 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -37,6 +37,8 @@ public class PublicAPIInstance : IPublicAPI private readonly Internationalization _translater; private readonly MainViewModel _mainVM; + private readonly object _saveSettingsLock = new(); + #region Constructor public PublicAPIInstance(Settings settings, Internationalization translater, MainViewModel mainVM) @@ -92,9 +94,12 @@ public async void RestartApp() public void SaveAppAllSettings() { - PluginManager.Save(); - _mainVM.Save(); - _settings.Save(); + lock (_saveSettingsLock) + { + _settings.Save(); + PluginManager.Save(); + _mainVM.Save(); + } _ = ImageLoader.SaveAsync(); } From 95a3fd36dea778911d0f4f8b9a434e4813096b6a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 10:34:59 +0800 Subject: [PATCH 10/19] Do not crash when caught exception on saving settings --- .../Plugin/JsonRPCPluginSettings.cs | 20 +++++++++-- .../Storage/FlowLauncherJsonStorage.cs | 35 ++++++++++++++++++- .../Storage/PluginJsonStorage.cs | 33 +++++++++++++++++ 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs index 944b2fd100d..e0a21725135 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs @@ -23,6 +23,8 @@ public class JsonRPCPluginSettings protected ConcurrentDictionary Settings { get; set; } = null!; public required IPublicAPI API { get; init; } + private static readonly string ClassName = nameof(JsonRPCPluginSettings); + private JsonStorage> _storage = null!; private static readonly Thickness SettingPanelMargin = (Thickness)Application.Current.FindResource("SettingPanelMargin"); @@ -122,12 +124,26 @@ public void UpdateSettings(IReadOnlyDictionary settings) public async Task SaveAsync() { - await _storage.SaveAsync(); + try + { + await _storage.SaveAsync(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin settings to path: {SettingPath}", e); + } } public void Save() { - _storage.Save(); + try + { + _storage.Save(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin settings to path: {SettingPath}", e); + } } public bool NeedCreateSettingPanel() diff --git a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs index 865041fb397..a3634a0e2e8 100644 --- a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs @@ -1,10 +1,19 @@ using System.IO; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Infrastructure.Storage { public class FlowLauncherJsonStorage : JsonStorage where T : new() { + private static readonly string ClassName = "FlowLauncherJsonStorage"; + + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + public FlowLauncherJsonStorage() { var directoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName); @@ -13,5 +22,29 @@ public FlowLauncherJsonStorage() var filename = typeof(T).Name; FilePath = Path.Combine(directoryPath, $"{filename}{FileSuffix}"); } + + public new void Save() + { + try + { + base.Save(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save FL settings to path: {FilePath}", e); + } + } + + public new async Task SaveAsync() + { + try + { + await base.SaveAsync(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save FL settings to path: {FilePath}", e); + } + } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs index b377c81aa14..e02d51bdbcf 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs @@ -1,5 +1,8 @@ using System.IO; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Infrastructure.Storage { @@ -8,6 +11,12 @@ namespace Flow.Launcher.Infrastructure.Storage // Use assembly name to check which plugin is using this storage public readonly string AssemblyName; + private static readonly string ClassName = "PluginJsonStorage"; + + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + public PluginJsonStorage() { // C# related, add python related below @@ -23,5 +32,29 @@ public PluginJsonStorage(T data) : this() { Data = data; } + + public new void Save() + { + try + { + base.Save(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin settings to path: {FilePath}", e); + } + } + + public new async Task SaveAsync() + { + try + { + await base.SaveAsync(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin settings to path: {FilePath}", e); + } + } } } From f6e3608f72ab28c48bf8563ea3bb58af7b9950bb Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 10:42:48 +0800 Subject: [PATCH 11/19] Do not crash when saving cache --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 0ba059b7bd5..1ee033821f0 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -71,6 +71,10 @@ await _storage.SaveAsync(ImageCache.EnumerateEntries() .Select(x => x.Key) .ToList()); } + catch (System.Exception e) + { + Log.Exception($"|ImageLoader.SaveAsync|Failed to save image cache to file", e); + } finally { storageLock.Release(); From 2d6667bb53549c5580004fe194b56b90d20cdcd7 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 10:42:55 +0800 Subject: [PATCH 12/19] Test save error --- Flow.Launcher.Infrastructure/Storage/JsonStorage.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs index 40106acd829..52bcdcfab8b 100644 --- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs @@ -180,20 +180,24 @@ private void BackupOriginFile() public void Save() { - string serialized = JsonSerializer.Serialize(Data, + throw new NotImplementedException("Save error"); + + /*string serialized = JsonSerializer.Serialize(Data, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(TempFilePath, serialized); - AtomicWriteSetting(); + AtomicWriteSetting();*/ } public async Task SaveAsync() { - await using var tempOutput = File.OpenWrite(TempFilePath); + throw new NotImplementedException("SaveAsync error"); + + /*await using var tempOutput = File.OpenWrite(TempFilePath); await JsonSerializer.SerializeAsync(tempOutput, Data, new JsonSerializerOptions { WriteIndented = true }); - AtomicWriteSetting(); + AtomicWriteSetting();*/ } private void AtomicWriteSetting() From c2f8480c049a4a818831c05558080907f2bac8d0 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:15:13 +0800 Subject: [PATCH 13/19] Revert "Test save error" This reverts commit 2d6667bb53549c5580004fe194b56b90d20cdcd7. --- Flow.Launcher.Infrastructure/Storage/JsonStorage.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs index 52bcdcfab8b..40106acd829 100644 --- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs @@ -180,24 +180,20 @@ private void BackupOriginFile() public void Save() { - throw new NotImplementedException("Save error"); - - /*string serialized = JsonSerializer.Serialize(Data, + string serialized = JsonSerializer.Serialize(Data, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(TempFilePath, serialized); - AtomicWriteSetting();*/ + AtomicWriteSetting(); } public async Task SaveAsync() { - throw new NotImplementedException("SaveAsync error"); - - /*await using var tempOutput = File.OpenWrite(TempFilePath); + await using var tempOutput = File.OpenWrite(TempFilePath); await JsonSerializer.SerializeAsync(tempOutput, Data, new JsonSerializerOptions { WriteIndented = true }); - AtomicWriteSetting();*/ + AtomicWriteSetting(); } private void AtomicWriteSetting() From 2a2ef234d952be3bc44507f95248b1622b92256d Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:17:30 +0800 Subject: [PATCH 14/19] Fix typos Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Infrastructure/Win32Helper.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 42461dc180a..f2b99588d66 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -489,8 +489,7 @@ or PInvoke.LOCALE_TRANSIENT_KEYBOARD3 #endregion - #region Noticification - + #region Notification public static bool IsNotificationSupport() { // Noticification only supported Windows 10 19041+ From 834780d6e7d57577a59f35c0ad5715f99e7b61cf Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:17:37 +0800 Subject: [PATCH 15/19] Fix typos Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Infrastructure/Win32Helper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index f2b99588d66..5bec3e5e79f 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -492,7 +492,7 @@ or PInvoke.LOCALE_TRANSIENT_KEYBOARD3 #region Notification public static bool IsNotificationSupport() { - // Noticification only supported Windows 10 19041+ + // Notification only supported Windows 10 19041+ return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version.Build >= 19041; } From 8df1e6a0ce9977346327c9e9249ef2359c3a9ad1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:18:57 +0800 Subject: [PATCH 16/19] Add blank line --- Flow.Launcher.Infrastructure/Win32Helper.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 5bec3e5e79f..d3023a3f05a 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -490,6 +490,7 @@ or PInvoke.LOCALE_TRANSIENT_KEYBOARD3 #endregion #region Notification + public static bool IsNotificationSupport() { // Notification only supported Windows 10 19041+ From 3283adce59384003887d5d91dfa767ca6822c92e Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:27:10 +0800 Subject: [PATCH 17/19] Fix typos Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Flow.Launcher.Infrastructure/Win32Helper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index d3023a3f05a..c21849403ca 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -491,9 +491,9 @@ or PInvoke.LOCALE_TRANSIENT_KEYBOARD3 #region Notification - public static bool IsNotificationSupport() + public static bool IsNotificationSupported() { - // Notification only supported Windows 10 19041+ + // Notifications only supported on Windows 10 19041+ return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version.Build >= 19041; } From ec7a4e8aaa1463524ae0cacebceb5ec7f89e94b8 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:27:50 +0800 Subject: [PATCH 18/19] Fix build issue --- Flow.Launcher/Notification.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Notification.cs b/Flow.Launcher/Notification.cs index 23125de151e..30b3a067334 100644 --- a/Flow.Launcher/Notification.cs +++ b/Flow.Launcher/Notification.cs @@ -9,7 +9,7 @@ namespace Flow.Launcher { internal static class Notification { - internal static bool legacy = !Win32Helper.IsNotificationSupport(); + internal static bool legacy = !Win32Helper.IsNotificationSupported(); internal static void Uninstall() { From 28ab71f11a60304db888c465e871c24be5b18ab5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:46:07 +0800 Subject: [PATCH 19/19] Fix build issue --- Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs | 1 + Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs index 0fbeed9f55f..8b4062b6b24 100644 --- a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs @@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage { diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs index 910672119c7..e8cbd70fb98 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs @@ -3,6 +3,7 @@ using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage {