From 6f0126d3ba3f4ab8c6928141287391602d77cf1f Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 1 Apr 2025 11:47:18 +0800
Subject: [PATCH 01/46] Add log error api function for csharp and jsonrpc
---
.../Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs | 8 ++++++--
Flow.Launcher.Infrastructure/Logger/Log.cs | 11 ++---------
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 5 +++++
Flow.Launcher/PublicAPIInstance.cs | 3 +++
4 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs
index 8df2ce9ed..102d0089f 100644
--- a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs
+++ b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs
@@ -12,7 +12,7 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models
{
public class JsonRPCPublicAPI
{
- private IPublicAPI _api;
+ private readonly IPublicAPI _api;
public JsonRPCPublicAPI(IPublicAPI api)
{
@@ -104,7 +104,6 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models
return _api.GetAllPlugins();
}
-
public MatchResult FuzzySearch(string query, string stringToCompare)
{
return _api.FuzzySearch(query, stringToCompare);
@@ -156,6 +155,11 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models
_api.LogWarn(className, message, methodName);
}
+ public void LogError(string className, string message, [CallerMemberName] string methodName = "")
+ {
+ _api.LogError(className, message, methodName);
+ }
+
public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null)
{
_api.OpenDirectory(DirectoryPath, FileNameOrFilePath);
diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs
index 9f5d6725e..9e1173f34 100644
--- a/Flow.Launcher.Infrastructure/Logger/Log.cs
+++ b/Flow.Launcher.Infrastructure/Logger/Log.cs
@@ -1,12 +1,12 @@
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
+using System.Runtime.ExceptionServices;
+using Flow.Launcher.Infrastructure.UserSettings;
using NLog;
using NLog.Config;
using NLog.Targets;
-using Flow.Launcher.Infrastructure.UserSettings;
using NLog.Targets.Wrappers;
-using System.Runtime.ExceptionServices;
namespace Flow.Launcher.Infrastructure.Logger
{
@@ -135,13 +135,6 @@ namespace Flow.Launcher.Infrastructure.Logger
return className;
}
- private static void ExceptionInternal(string classAndMethod, string message, System.Exception e)
- {
- var logger = LogManager.GetLogger(classAndMethod);
-
- logger.Error(e, message);
- }
-
private static void LogInternal(string message, LogLevel level)
{
if (FormatValid(message))
diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
index f178ebb90..9258e5147 100644
--- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
@@ -227,6 +227,11 @@ namespace Flow.Launcher.Plugin
///
void LogWarn(string className, string message, [CallerMemberName] string methodName = "");
+ ///
+ /// Log error message
+ ///
+ void LogError(string className, string message, [CallerMemberName] string methodName = "");
+
///
/// Log an Exception. Will throw if in debug mode so developer will be aware,
/// otherwise logs the eror message. This is the primary logging method used for Flow
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index e19ad2fdc..31307b668 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -187,6 +187,9 @@ namespace Flow.Launcher
public void LogWarn(string className, string message, [CallerMemberName] string methodName = "") =>
Log.Warn(className, message, methodName);
+ public void LogError(string className, string message, [CallerMemberName] string methodName = "") =>
+ Log.Error(className, message, methodName);
+
public void LogException(string className, string message, Exception e,
[CallerMemberName] string methodName = "") => Log.Exception(className, message, e, methodName);
From 1381248e9e71444b56704548167830010f97ac68 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 1 Apr 2025 11:54:18 +0800
Subject: [PATCH 02/46] Adjust code formats
---
Flow.Launcher/PublicAPIInstance.cs | 35 ++++++++++++++++++++----------
1 file changed, 23 insertions(+), 12 deletions(-)
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 31307b668..2d2713e79 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -11,9 +11,9 @@ using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using CommunityToolkit.Mvvm.DependencyInjection;
-using Squirrel;
using Flow.Launcher.Core;
using Flow.Launcher.Core.Plugin;
+using Flow.Launcher.Core.Resource;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Http;
@@ -27,7 +27,7 @@ using Flow.Launcher.Plugin.SharedModels;
using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.ViewModel;
using JetBrains.Annotations;
-using Flow.Launcher.Core.Resource;
+using Squirrel;
namespace Flow.Launcher
{
@@ -78,7 +78,11 @@ namespace Flow.Launcher
public bool IsMainWindowVisible() => _mainVM.MainWindowVisibilityStatus;
- public event VisibilityChangedEventHandler VisibilityChanged { add => _mainVM.VisibilityChanged += value; remove => _mainVM.VisibilityChanged -= value; }
+ public event VisibilityChangedEventHandler VisibilityChanged
+ {
+ add => _mainVM.VisibilityChanged += value;
+ remove => _mainVM.VisibilityChanged -= value;
+ }
// Must use Ioc.Default.GetRequiredService() to avoid circular dependency
public void CheckForNewUpdate() => _ = Ioc.Default.GetRequiredService().UpdateAppAsync(false);
@@ -162,13 +166,14 @@ namespace Flow.Launcher
public MatchResult FuzzySearch(string query, string stringToCompare) =>
StringMatcher.FuzzySearch(query, stringToCompare);
- public Task HttpGetStringAsync(string url, CancellationToken token = default) => Http.GetAsync(url, token);
+ public Task HttpGetStringAsync(string url, CancellationToken token = default) =>
+ Http.GetAsync(url, token);
public Task HttpGetStreamAsync(string url, CancellationToken token = default) =>
Http.GetStreamAsync(url, token);
public Task HttpDownloadAsync([NotNull] string url, [NotNull] string filePath, Action reportProgress = null,
- CancellationToken token = default) => Http.DownloadAsync(url, filePath, reportProgress, token);
+ CancellationToken token = default) =>Http.DownloadAsync(url, filePath, reportProgress, token);
public void AddActionKeyword(string pluginId, string newActionKeyword) =>
PluginManager.AddActionKeyword(pluginId, newActionKeyword);
@@ -190,8 +195,8 @@ namespace Flow.Launcher
public void LogError(string className, string message, [CallerMemberName] string methodName = "") =>
Log.Error(className, message, methodName);
- public void LogException(string className, string message, Exception e,
- [CallerMemberName] string methodName = "") => Log.Exception(className, message, e, methodName);
+ public void LogException(string className, string message, Exception e, [CallerMemberName] string methodName = "") =>
+ Log.Exception(className, message, e, methodName);
private readonly ConcurrentDictionary _pluginJsonStorages = new();
@@ -204,7 +209,7 @@ namespace Flow.Launcher
var name = value.GetType().GetField("AssemblyName")?.GetValue(value)?.ToString();
if (name == assemblyName)
{
- _pluginJsonStorages.Remove(key, out var pluginJsonStorage);
+ _pluginJsonStorages.Remove(key, out var _);
}
}
}
@@ -333,17 +338,23 @@ namespace Flow.Launcher
private readonly List> _globalKeyboardHandlers = new();
- public void RegisterGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Add(callback);
- public void RemoveGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Remove(callback);
+ public void RegisterGlobalKeyboardCallback(Func callback) =>
+ _globalKeyboardHandlers.Add(callback);
+
+ public void RemoveGlobalKeyboardCallback(Func callback) =>
+ _globalKeyboardHandlers.Remove(callback);
public void ReQuery(bool reselect = true) => _mainVM.ReQuery(reselect);
public void BackToQueryResults() => _mainVM.BackToQueryResults();
- public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.OK) =>
+ public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "",
+ MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None,
+ MessageBoxResult defaultResult = MessageBoxResult.OK) =>
MessageBoxEx.Show(messageBoxText, caption, button, icon, defaultResult);
- public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress);
+ public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync,
+ Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress);
#endregion
From 835e4096c8ec781e6bd319946853060f9de2b493 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 1 Apr 2025 11:56:51 +0800
Subject: [PATCH 03/46] Fix build issue
---
Flow.Launcher.Infrastructure/Logger/Log.cs | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs
index 9e1173f34..84331ef70 100644
--- a/Flow.Launcher.Infrastructure/Logger/Log.cs
+++ b/Flow.Launcher.Infrastructure/Logger/Log.cs
@@ -135,6 +135,15 @@ namespace Flow.Launcher.Infrastructure.Logger
return className;
}
+#if !DEBUG
+ private static void ExceptionInternal(string classAndMethod, string message, System.Exception e)
+ {
+ var logger = LogManager.GetLogger(classAndMethod);
+
+ logger.Error(e, message);
+ }
+#endif
+
private static void LogInternal(string message, LogLevel level)
{
if (FormatValid(message))
From 24327533c6e165f0cfa02e9a822fcf973c1880df Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 1 Apr 2025 14:16:32 +0800
Subject: [PATCH 04/46] Add plugin json storage
---
.../Image/ImageLoader.cs | 1 +
.../Storage/BinaryStorage.cs | 62 +++++++++++++++----
.../Storage/PluginBinaryStorage.cs | 15 +++++
.../Storage/PluginJsonStorage.cs | 6 --
4 files changed, 65 insertions(+), 19 deletions(-)
create mode 100644 Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs
diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
index 6f7b1cd90..cca4bd2a4 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
@@ -37,6 +37,7 @@ namespace Flow.Launcher.Infrastructure.Image
_hashGenerator = new ImageHashGenerator();
var usage = await LoadStorageToConcurrentDictionaryAsync();
+ _storage.ClearData();
ImageCache.Initialize(usage);
diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
index 5b73faae6..69ac6000b 100644
--- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
@@ -4,6 +4,8 @@ using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using MemoryPack;
+#nullable enable
+
namespace Flow.Launcher.Infrastructure.Storage
{
///
@@ -15,40 +17,53 @@ namespace Flow.Launcher.Infrastructure.Storage
///
public class BinaryStorage
{
+ protected T? Data;
+
public const string FileSuffix = ".cache";
- // Let the derived class to set the file path
- public BinaryStorage(string filename, string directoryPath = null)
- {
- directoryPath ??= DataLocation.CacheDirectory;
- Helper.ValidateDirectory(directoryPath);
+ protected string FilePath { get; init; } = null!;
- FilePath = Path.Combine(directoryPath, $"{filename}{FileSuffix}");
+ protected string DirectoryPath { get; init; } = null!;
+
+ // Let the derived class to set the file path
+ protected BinaryStorage()
+ {
}
- public string FilePath { get; }
+ public BinaryStorage(string filename)
+ {
+ DirectoryPath = DataLocation.CacheDirectory;
+ Helper.ValidateDirectory(DirectoryPath);
+
+ FilePath = Path.Combine(DirectoryPath, $"{filename}{FileSuffix}");
+ }
public async ValueTask TryLoadAsync(T defaultData)
{
+ if (Data != null)
+ return Data;
+
if (File.Exists(FilePath))
{
if (new FileInfo(FilePath).Length == 0)
{
Log.Error($"|BinaryStorage.TryLoad|Zero length cache file <{FilePath}>");
- await SaveAsync(defaultData);
- return defaultData;
+ Data = defaultData;
+ await SaveAsync();
}
await using var stream = new FileStream(FilePath, FileMode.Open);
var d = await DeserializeAsync(stream, defaultData);
- return d;
+ Data = d;
}
else
{
Log.Info("|BinaryStorage.TryLoad|Cache file not exist, load default data");
- await SaveAsync(defaultData);
- return defaultData;
+ Data = defaultData;
+ await SaveAsync();
}
+
+ return Data;
}
private static async ValueTask DeserializeAsync(Stream stream, T defaultData)
@@ -56,7 +71,7 @@ namespace Flow.Launcher.Infrastructure.Storage
try
{
var t = await MemoryPackSerializer.DeserializeAsync(stream);
- return t;
+ return t ?? defaultData;
}
catch (System.Exception)
{
@@ -65,6 +80,27 @@ namespace Flow.Launcher.Infrastructure.Storage
}
}
+ public async ValueTask SaveAsync()
+ {
+ await using var stream = new FileStream(FilePath, FileMode.Create);
+ await MemoryPackSerializer.SerializeAsync(stream, Data);
+ }
+
+ // For SavePluginSettings function
+ public void Save()
+ {
+ var serialized = MemoryPackSerializer.Serialize(Data);
+
+ File.WriteAllBytes(FilePath, serialized);
+ }
+
+ // ImageCache need to be converted into concurrent dictionary, so it does not need to cache loading results into Data
+ public void ClearData()
+ {
+ Data = default;
+ }
+
+ // ImageCache storages data in its class, so it needs to pass it to SaveAsync
public async ValueTask SaveAsync(T data)
{
await using var stream = new FileStream(FilePath, FileMode.Create);
diff --git a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs
new file mode 100644
index 000000000..87f51d5d7
--- /dev/null
+++ b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs
@@ -0,0 +1,15 @@
+using System.IO;
+
+namespace Flow.Launcher.Infrastructure.Storage
+{
+ public class PluginBinaryStorage : BinaryStorage where T : new()
+ {
+ public PluginBinaryStorage(string cacheName, string cacheDirectory)
+ {
+ DirectoryPath = cacheDirectory;
+ Helper.ValidateDirectory(DirectoryPath);
+
+ FilePath = Path.Combine(DirectoryPath, $"{cacheName}{FileSuffix}");
+ }
+ }
+}
diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs
index b377c81aa..9c6547c66 100644
--- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs
@@ -10,7 +10,6 @@ namespace Flow.Launcher.Infrastructure.Storage
public PluginJsonStorage()
{
- // C# related, add python related below
var dataType = typeof(T);
AssemblyName = dataType.Assembly.GetName().Name;
DirectoryPath = Path.Combine(DataLocation.PluginSettingsDirectory, AssemblyName);
@@ -18,10 +17,5 @@ namespace Flow.Launcher.Infrastructure.Storage
FilePath = Path.Combine(DirectoryPath, $"{dataType.Name}{FileSuffix}");
}
-
- public PluginJsonStorage(T data) : this()
- {
- Data = data;
- }
}
}
From ca221d710026b3e402873a174696a48e28e5d958 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 1 Apr 2025 14:19:59 +0800
Subject: [PATCH 05/46] Add binary storage api functions
---
.../JsonRPCV2Models/JsonRPCPublicAPI.cs | 5 ++
Flow.Launcher.Core/Plugin/PluginManager.cs | 5 +-
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 33 ++++++++++++
Flow.Launcher.Plugin/Interfaces/ISavable.cs | 7 +--
Flow.Launcher/PublicAPIInstance.cs | 53 ++++++++++++++++---
5 files changed, 91 insertions(+), 12 deletions(-)
diff --git a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs
index 8df2ce9ed..cf1c57f3e 100644
--- a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs
+++ b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs
@@ -185,5 +185,10 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models
{
_api.StopLoadingBar();
}
+
+ public void SavePluginCaches()
+ {
+ _api.SavePluginCaches();
+ }
}
}
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index 4f869901c..fa4e43e07 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -66,6 +66,7 @@ namespace Flow.Launcher.Core.Plugin
}
API.SavePluginSettings();
+ API.SavePluginCaches();
}
public static async ValueTask DisposePluginsAsync()
@@ -587,11 +588,13 @@ namespace Flow.Launcher.Core.Plugin
if (removePluginSettings)
{
- // For dotnet plugins, we need to remove their PluginJsonStorage instance
+ // For dotnet plugins, we need to remove their PluginJsonStorage and PluginBinaryStorage instances
if (AllowedLanguage.IsDotNet(plugin.Language))
{
var method = API.GetType().GetMethod("RemovePluginSettings");
method?.Invoke(API, new object[] { plugin.AssemblyName });
+ var method1 = API.GetType().GetMethod("RemovePluginCache");
+ method1?.Invoke(API, new object[] { plugin.PluginCacheDirectoryPath });
}
try
diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
index f178ebb90..be776b068 100644
--- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
@@ -344,5 +344,38 @@ namespace Flow.Launcher.Plugin
/// Stop the loading bar in main window
///
public void StopLoadingBar();
+
+ ///
+ /// Save all Flow's plugins caches
+ ///
+ void SavePluginCaches();
+
+ ///
+ /// Load BinaryStorage for current plugin's cache. This is the method used to load cache from binary in Flow.
+ /// When the file is not exist, it will create a new instance for the specific type.
+ ///
+ /// Type for deserialization
+ /// Cache file name
+ /// Cache directory from plugin metadata
+ /// Default data to return
+ ///
+ ///
+ /// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable
+ ///
+ Task LoadCacheBinaryStorageAsync(string cacheName, string cacheDirectory, T defaultData) where T : new();
+
+ ///
+ /// Save BinaryStorage for current plugin's cache. This is the method used to save cache to binary in Flow.Launcher
+ /// This method will save the original instance loaded with LoadCacheBinaryStorageAsync.
+ /// This API call is for manually Save. Flow will automatically save all cache type that has called LoadCacheBinaryStorageAsync or SaveCacheBinaryStorageAsync previously.
+ ///
+ /// Type for Serialization
+ /// Cache file name
+ /// Cache directory from plugin metadata
+ ///
+ ///
+ /// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable
+ ///
+ Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new();
}
}
diff --git a/Flow.Launcher.Plugin/Interfaces/ISavable.cs b/Flow.Launcher.Plugin/Interfaces/ISavable.cs
index 77bd304e4..cabd26962 100644
--- a/Flow.Launcher.Plugin/Interfaces/ISavable.cs
+++ b/Flow.Launcher.Plugin/Interfaces/ISavable.cs
@@ -1,11 +1,12 @@
-namespace Flow.Launcher.Plugin
+namespace Flow.Launcher.Plugin
{
///
/// Inherit this interface if additional data e.g. cache needs to be saved.
///
///
/// For storing plugin settings, prefer
- /// or .
+ /// or .
+ /// or .
/// Once called, your settings will be automatically saved by Flow.
///
public interface ISavable : IFeatures
@@ -15,4 +16,4 @@ namespace Flow.Launcher.Plugin
///
void Save();
}
-}
\ No newline at end of file
+}
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index e19ad2fdc..17d7e103e 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -236,14 +236,6 @@ namespace Flow.Launcher
((PluginJsonStorage)_pluginJsonStorages[type]).Save();
}
- public void SaveJsonStorage(T settings) where T : new()
- {
- var type = typeof(T);
- _pluginJsonStorages[type] = new PluginJsonStorage(settings);
-
- ((PluginJsonStorage)_pluginJsonStorages[type]).Save();
- }
-
public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null)
{
using var explorer = new Process();
@@ -342,6 +334,51 @@ namespace Flow.Launcher
public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress);
+ private readonly ConcurrentDictionary<(string, string, Type), object> _pluginBinaryStorages = new();
+
+ public void RemovePluginCache(string cacheDirectory)
+ {
+ foreach (var keyValuePair in _pluginBinaryStorages)
+ {
+ var key = keyValuePair.Key;
+ var currentCacheDirectory = key.Item2;
+ if (cacheDirectory == currentCacheDirectory)
+ {
+ _pluginBinaryStorages.Remove(key, out var _);
+ }
+ }
+ }
+
+ ///
+ /// Save plugin caches.
+ ///
+ public void SavePluginCaches()
+ {
+ foreach (var value in _pluginBinaryStorages.Values)
+ {
+ var method = value.GetType().GetMethod("Save");
+ method?.Invoke(value, null);
+ }
+ }
+
+ public async Task LoadCacheBinaryStorageAsync(string cacheName, string cacheDirectory, T defaultData) where T : new()
+ {
+ var type = typeof(T);
+ if (!_pluginBinaryStorages.ContainsKey((cacheName, cacheDirectory, type)))
+ _pluginBinaryStorages[(cacheName, cacheDirectory, type)] = new PluginBinaryStorage(cacheName, cacheDirectory);
+
+ return await ((PluginBinaryStorage)_pluginBinaryStorages[(cacheName, cacheDirectory, type)]).TryLoadAsync(defaultData);
+ }
+
+ public async Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new()
+ {
+ var type = typeof(T);
+ if (!_pluginBinaryStorages.ContainsKey((cacheName, cacheDirectory, type)))
+ _pluginBinaryStorages[(cacheName, cacheDirectory, type)] = new PluginBinaryStorage(cacheName, cacheDirectory);
+
+ await ((PluginBinaryStorage)_pluginBinaryStorages[(cacheName, cacheDirectory, type)]).SaveAsync();
+ }
+
#endregion
#region Private Methods
From 0496d6c04ac2bed323060f41519c41fe1358dc73 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 1 Apr 2025 14:21:29 +0800
Subject: [PATCH 06/46] Use api functions for Program plugin
---
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 82 +++++++++----------
.../Programs/UWPPackage.cs | 2 +-
.../Programs/Win32.cs | 2 +-
.../Views/ProgramSetting.xaml.cs | 6 +-
4 files changed, 46 insertions(+), 46 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index 3be23214c..5bc518105 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -8,7 +8,6 @@ using System.Threading.Tasks;
using System.Windows.Controls;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Logger;
-using Flow.Launcher.Infrastructure.Storage;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin.Program.Programs;
using Flow.Launcher.Plugin.Program.Views;
@@ -19,19 +18,17 @@ using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
namespace Flow.Launcher.Plugin.Program
{
- public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, ISavable, IAsyncReloadable,
- IDisposable
+ public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, IAsyncReloadable, IDisposable
{
- internal static Win32[] _win32s { get; set; }
- internal static UWPApp[] _uwps { get; set; }
- internal static Settings _settings { get; set; }
+ private const string Win32CacheName = "Win32";
+ private const string UwpCacheName = "UWP";
+ internal static List _win32s { get; private set; }
+ internal static List _uwps { get; private set; }
+ internal static Settings _settings { get; private set; }
internal static PluginInitContext Context { get; private set; }
- private static BinaryStorage _win32Storage;
- private static BinaryStorage _uwpStorage;
-
private static readonly List emptyResults = new();
private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 };
@@ -81,12 +78,6 @@ namespace Flow.Launcher.Plugin.Program
{
}
- public void Save()
- {
- _win32Storage.SaveAsync(_win32s);
- _uwpStorage.SaveAsync(_uwps);
- }
-
public async Task> QueryAsync(Query query, CancellationToken token)
{
var result = await cache.GetOrCreateAsync(query.Search, async entry =>
@@ -191,7 +182,9 @@ namespace Flow.Launcher.Plugin.Program
await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () =>
{
- Helper.ValidateDirectory(Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
+ var pluginCachePath = Context.CurrentPluginMetadata.PluginCacheDirectoryPath;
+
+ Helper.ValidateDirectory(pluginCachePath);
static void MoveFile(string sourcePath, string destinationPath)
{
@@ -236,20 +229,18 @@ namespace Flow.Launcher.Plugin.Program
}
// Move old cache files to the new cache directory
- var oldWin32CacheFile = Path.Combine(DataLocation.CacheDirectory, $"Win32.cache");
- var newWin32CacheFile = Path.Combine(Context.CurrentPluginMetadata.PluginCacheDirectoryPath, $"Win32.cache");
+ var oldWin32CacheFile = Path.Combine(DataLocation.CacheDirectory, $"{Win32CacheName}.cache");
+ var newWin32CacheFile = Path.Combine(pluginCachePath, $"{Win32CacheName}.cache");
MoveFile(oldWin32CacheFile, newWin32CacheFile);
- var oldUWPCacheFile = Path.Combine(DataLocation.CacheDirectory, $"UWP.cache");
- var newUWPCacheFile = Path.Combine(Context.CurrentPluginMetadata.PluginCacheDirectoryPath, $"UWP.cache");
+ var oldUWPCacheFile = Path.Combine(DataLocation.CacheDirectory, $"{UwpCacheName}.cache");
+ var newUWPCacheFile = Path.Combine(pluginCachePath, $"{UwpCacheName}.cache");
MoveFile(oldUWPCacheFile, newUWPCacheFile);
- _win32Storage = new BinaryStorage("Win32", Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
- _win32s = await _win32Storage.TryLoadAsync(Array.Empty());
- _uwpStorage = new BinaryStorage("UWP", Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
- _uwps = await _uwpStorage.TryLoadAsync(Array.Empty());
+ _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List());
+ _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List());
});
- Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Length}>");
- Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Length}>");
+ Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Count}>");
+ Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Count}>");
bool cacheEmpty = !_win32s.Any() || !_uwps.Any();
@@ -273,36 +264,45 @@ namespace Flow.Launcher.Plugin.Program
}
}
- public static void IndexWin32Programs()
+ public static async Task IndexWin32ProgramsAsync()
{
var win32S = Win32.All(_settings);
- _win32s = win32S;
+ _win32s.Clear();
+ foreach (var win32 in win32S)
+ {
+ _win32s.Add(win32);
+ }
ResetCache();
- _win32Storage.SaveAsync(_win32s);
+ await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
_settings.LastIndexTime = DateTime.Now;
}
- public static void IndexUwpPrograms()
+ public static async Task IndexUwpProgramsAsync()
{
- var applications = UWPPackage.All(_settings);
- _uwps = applications;
+ var uwps = UWPPackage.All(_settings);
+ _uwps.Clear();
+ foreach (var uwp in uwps)
+ {
+ _uwps.Add(uwp);
+ }
ResetCache();
- _uwpStorage.SaveAsync(_uwps);
+ await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
_settings.LastIndexTime = DateTime.Now;
}
public static async Task IndexProgramsAsync()
{
- var a = Task.Run(() =>
+ var win32Task = Task.Run(async () =>
{
- Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexWin32Programs);
+ await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexWin32ProgramsAsync);
});
- var b = Task.Run(() =>
+ var uwpTask = Task.Run(async () =>
{
- Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|UWPProgram index cost", IndexUwpPrograms);
+ await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|UWPProgram index cost", IndexUwpProgramsAsync);
});
- await Task.WhenAll(a, b).ConfigureAwait(false);
+
+ await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false);
}
internal static void ResetCache()
@@ -314,7 +314,7 @@ namespace Flow.Launcher.Plugin.Program
public Control CreateSettingPanel()
{
- return new ProgramSetting(Context, _settings, _win32s, _uwps);
+ return new ProgramSetting(Context, _settings);
}
public string GetTranslatedPluginTitle()
@@ -370,7 +370,7 @@ namespace Flow.Launcher.Plugin.Program
_settings.DisabledProgramSources.Add(new ProgramSource(program));
_ = Task.Run(() =>
{
- IndexUwpPrograms();
+ _ = IndexUwpProgramsAsync();
});
}
else if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
@@ -380,7 +380,7 @@ namespace Flow.Launcher.Plugin.Program
_settings.DisabledProgramSources.Add(new ProgramSource(program));
_ = Task.Run(() =>
{
- IndexWin32Programs();
+ _ = IndexWin32ProgramsAsync();
});
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs
index 654897cc5..bf100ed7e 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs
@@ -317,7 +317,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
{
await Task.Delay(3000).ConfigureAwait(false);
PackageChangeChannel.Reader.TryRead(out _);
- await Task.Run(Main.IndexUwpPrograms);
+ await Task.Run(Main.IndexUwpProgramsAsync);
}
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
index a64a708ef..06be2a628 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs
@@ -797,7 +797,7 @@ namespace Flow.Launcher.Plugin.Program.Programs
{
}
- await Task.Run(Main.IndexWin32Programs);
+ await Task.Run(Main.IndexWin32ProgramsAsync);
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
index 91864cb68..5ad7fcea3 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
@@ -18,8 +18,8 @@ namespace Flow.Launcher.Plugin.Program.Views
///
public partial class ProgramSetting : UserControl
{
- private PluginInitContext context;
- private Settings _settings;
+ private readonly PluginInitContext context;
+ private readonly Settings _settings;
private GridViewColumnHeader _lastHeaderClicked;
private ListSortDirection _lastDirection;
@@ -109,7 +109,7 @@ namespace Flow.Launcher.Plugin.Program.Views
public bool ShowUWPCheckbox => UWPPackage.SupportUWP();
- public ProgramSetting(PluginInitContext context, Settings settings, Win32[] win32s, UWPApp[] uwps)
+ public ProgramSetting(PluginInitContext context, Settings settings)
{
this.context = context;
_settings = settings;
From 68e1fc28efcc31362193aab4e73aa7459bf1b1af Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 1 Apr 2025 14:35:43 +0800
Subject: [PATCH 07/46] Use try remove for safety
---
Flow.Launcher/PublicAPIInstance.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 17d7e103e..770195550 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -201,7 +201,7 @@ namespace Flow.Launcher
var name = value.GetType().GetField("AssemblyName")?.GetValue(value)?.ToString();
if (name == assemblyName)
{
- _pluginJsonStorages.Remove(key, out var pluginJsonStorage);
+ _pluginJsonStorages.TryRemove(key, out var pluginJsonStorage);
}
}
}
@@ -344,7 +344,7 @@ namespace Flow.Launcher
var currentCacheDirectory = key.Item2;
if (cacheDirectory == currentCacheDirectory)
{
- _pluginBinaryStorages.Remove(key, out var _);
+ _pluginBinaryStorages.TryRemove(key, out var _);
}
}
}
From 53c12327c0bcce76b770273c6a95f2c15ed0d27b Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Wed, 2 Apr 2025 11:51:34 +0800
Subject: [PATCH 08/46] Revert changes
---
Flow.Launcher.Infrastructure/Logger/Log.cs | 2 --
1 file changed, 2 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs
index 84331ef70..807d631c7 100644
--- a/Flow.Launcher.Infrastructure/Logger/Log.cs
+++ b/Flow.Launcher.Infrastructure/Logger/Log.cs
@@ -135,14 +135,12 @@ namespace Flow.Launcher.Infrastructure.Logger
return className;
}
-#if !DEBUG
private static void ExceptionInternal(string classAndMethod, string message, System.Exception e)
{
var logger = LogManager.GetLogger(classAndMethod);
logger.Error(e, message);
}
-#endif
private static void LogInternal(string message, LogLevel level)
{
From 5165ce8f2a5d11f3b81f3feb37887e03f4c6677f Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Wed, 2 Apr 2025 18:22:36 +0800
Subject: [PATCH 09/46] Add LoadImageAsync api function
---
.../Image/ImageLoader.cs | 14 ++++++++------
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 16 ++++++++++++++++
Flow.Launcher/PublicAPIInstance.cs | 4 ++++
3 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
index 6f7b1cd90..4bd4c29c8 100644
--- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
+++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs
@@ -277,7 +277,7 @@ namespace Flow.Launcher.Infrastructure.Image
return ImageCache.TryGetValue(path, loadFullImage, out image);
}
- public static async ValueTask LoadAsync(string path, bool loadFullImage = false)
+ public static async ValueTask LoadAsync(string path, bool loadFullImage = false, bool cacheImage = true)
{
var imageResult = await LoadInternalAsync(path, loadFullImage);
@@ -293,16 +293,18 @@ namespace Flow.Launcher.Infrastructure.Image
// image already exists
img = ImageCache[key, loadFullImage] ?? img;
}
- else
+ else if (cacheImage)
{
- // new guid
-
+ // save guid key
GuidToKey[hash] = path;
}
}
- // update cache
- ImageCache[path, loadFullImage] = img;
+ if (cacheImage)
+ {
+ // update cache
+ ImageCache[path, loadFullImage] = img;
+ }
}
return img;
diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
index f178ebb90..fb80ede83 100644
--- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
@@ -8,6 +8,7 @@ using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
+using System.Windows.Media;
namespace Flow.Launcher.Plugin
{
@@ -344,5 +345,20 @@ namespace Flow.Launcher.Plugin
/// Stop the loading bar in main window
///
public void StopLoadingBar();
+
+ ///
+ /// Load image from path. Support local, remote and data:image url.
+ /// If image path is missing, it will retun a missing icon.
+ ///
+ /// The path of the image.
+ ///
+ /// Load full image or not.
+ ///
+ ///
+ /// Cache the image or not. Cached image will be stored in FL cache.
+ /// If the image is just used one time, it's better to set this to false.
+ ///
+ ///
+ ValueTask LoadImageAsync(string path, bool loadFullImage = false, bool cacheImage = true);
}
}
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index e19ad2fdc..d12c6ac3e 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -10,6 +10,7 @@ using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
+using System.Windows.Media;
using CommunityToolkit.Mvvm.DependencyInjection;
using Squirrel;
using Flow.Launcher.Core;
@@ -342,6 +343,9 @@ namespace Flow.Launcher
public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress);
+ public ValueTask LoadImageAsync(string path, bool loadFullImage = false, bool cacheImage = true) =>
+ ImageLoader.LoadAsync(path, loadFullImage, cacheImage);
+
#endregion
#region Private Methods
From f76110856fdc1c104d3dc1c5a888073b1ac3f413 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Wed, 2 Apr 2025 18:25:06 +0800
Subject: [PATCH 10/46] Use api function in main project
---
Flow.Launcher/MessageBoxEx.xaml.cs | 2 +-
Flow.Launcher/Msg.xaml.cs | 6 +++---
Flow.Launcher/ViewModel/MainViewModel.cs | 2 +-
Flow.Launcher/ViewModel/PluginViewModel.cs | 2 +-
Flow.Launcher/ViewModel/ResultViewModel.cs | 2 +-
5 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/Flow.Launcher/MessageBoxEx.xaml.cs b/Flow.Launcher/MessageBoxEx.xaml.cs
index e9b434fd9..3d94769d0 100644
--- a/Flow.Launcher/MessageBoxEx.xaml.cs
+++ b/Flow.Launcher/MessageBoxEx.xaml.cs
@@ -156,7 +156,7 @@ namespace Flow.Launcher
private async Task SetImageAsync(string imageName)
{
var imagePath = Path.Combine(Constant.ProgramDirectory, "Images", imageName);
- var imageSource = await ImageLoader.LoadAsync(imagePath);
+ var imageSource = await App.API.LoadImageAsync(imagePath);
Img.Source = imageSource;
}
diff --git a/Flow.Launcher/Msg.xaml.cs b/Flow.Launcher/Msg.xaml.cs
index 94184ff63..ff9accd62 100644
--- a/Flow.Launcher/Msg.xaml.cs
+++ b/Flow.Launcher/Msg.xaml.cs
@@ -43,7 +43,7 @@ namespace Flow.Launcher
private async System.Threading.Tasks.Task LoadImageAsync()
{
- imgClose.Source = await ImageLoader.LoadAsync(Path.Combine(Infrastructure.Constant.ProgramDirectory, "Images\\close.png"));
+ imgClose.Source = await App.API.LoadImageAsync(Path.Combine(Constant.ProgramDirectory, "Images\\close.png"));
}
void imgClose_MouseUp(object sender, MouseButtonEventArgs e)
@@ -71,11 +71,11 @@ namespace Flow.Launcher
if (!File.Exists(iconPath))
{
- imgIco.Source = await ImageLoader.LoadAsync(Path.Combine(Constant.ProgramDirectory, "Images\\app.png"));
+ imgIco.Source = await App.API.LoadImageAsync(Path.Combine(Constant.ProgramDirectory, "Images\\app.png"));
}
else
{
- imgIco.Source = await ImageLoader.LoadAsync(iconPath);
+ imgIco.Source = await App.API.LoadImageAsync(iconPath);
}
Show();
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 17e4b55b7..bfa5bd504 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -1168,7 +1168,7 @@ namespace Flow.Launcher.ViewModel
else if (plugins.Count == 1)
{
PluginIconPath = plugins.Single().Metadata.IcoPath;
- PluginIconSource = await ImageLoader.LoadAsync(PluginIconPath);
+ PluginIconSource = await App.API.LoadImageAsync(PluginIconPath);
SearchIconVisibility = Visibility.Hidden;
}
else
diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs
index e91badb38..93a595de4 100644
--- a/Flow.Launcher/ViewModel/PluginViewModel.cs
+++ b/Flow.Launcher/ViewModel/PluginViewModel.cs
@@ -45,7 +45,7 @@ namespace Flow.Launcher.ViewModel
private async Task LoadIconAsync()
{
- Image = await ImageLoader.LoadAsync(PluginPair.Metadata.IcoPath);
+ Image = await App.API.LoadImageAsync(PluginPair.Metadata.IcoPath);
OnPropertyChanged(nameof(Image));
}
diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs
index db124e078..9aab71a32 100644
--- a/Flow.Launcher/ViewModel/ResultViewModel.cs
+++ b/Flow.Launcher/ViewModel/ResultViewModel.cs
@@ -199,7 +199,7 @@ namespace Flow.Launcher.ViewModel
}
}
- return await ImageLoader.LoadAsync(imagePath, loadFullImage).ConfigureAwait(false);
+ return await App.API.LoadImageAsync(imagePath, loadFullImage).ConfigureAwait(false);
}
private async Task LoadImageAsync()
From 4572068e768921e0834c53f6f4192c71ae762c04 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Wed, 2 Apr 2025 18:25:28 +0800
Subject: [PATCH 11/46] Use api functions in plugin projects
---
.../Views/PreviewPanel.xaml.cs | 3 +--
.../SearchSourceViewModel.cs | 9 ++++-----
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs
index 878832e4f..aaf1efdc1 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs
@@ -7,7 +7,6 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
-using Flow.Launcher.Infrastructure.Image;
using Flow.Launcher.Plugin.Explorer.Search;
namespace Flow.Launcher.Plugin.Explorer.Views;
@@ -89,7 +88,7 @@ public partial class PreviewPanel : UserControl, INotifyPropertyChanged
private async Task LoadImageAsync()
{
- PreviewImage = await ImageLoader.LoadAsync(FilePath, true).ConfigureAwait(false);
+ PreviewImage = await Main.Context.API.LoadImageAsync(FilePath, true).ConfigureAwait(false);
}
public event PropertyChangedEventHandler? PropertyChanged;
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs
index 9c5e81cb5..6554edd83 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs
@@ -1,5 +1,4 @@
-using Flow.Launcher.Infrastructure.Image;
-using System;
+using System;
using System.IO;
using System.Threading.Tasks;
#pragma warning disable IDE0005
@@ -41,8 +40,8 @@ namespace Flow.Launcher.Plugin.WebSearch
#if DEBUG
throw;
#else
- Main._context.API.ShowMsgBox(string.Format("Copying the selected image file to {0} has failed, changes will now be reverted", destinationFileNameFullPath));
- UpdateIconAttributes(selectedSearchSource, fullPathToOriginalImage);
+ Main._context.API.ShowMsgBox(string.Format("Copying the selected image file to {0} has failed, changes will now be reverted", destinationFileNameFullPath));
+ UpdateIconAttributes(selectedSearchSource, fullPathToOriginalImage);
#endif
}
}
@@ -61,7 +60,7 @@ namespace Flow.Launcher.Plugin.WebSearch
internal async ValueTask LoadPreviewIconAsync(string pathToPreviewIconImage)
{
- return await ImageLoader.LoadAsync(pathToPreviewIconImage);
+ return await Main._context.API.LoadImageAsync(pathToPreviewIconImage);
}
}
}
From 3de8005297fcba6e517ea674e3b2dc1129aea8e8 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Wed, 2 Apr 2025 18:26:22 +0800
Subject: [PATCH 12/46] Improve WebSearch project code quality
---
.../SuggestionSources/Baidu.cs | 8 +++-----
.../SuggestionSources/Bing.cs | 16 +++++-----------
.../SuggestionSources/DuckDuckGo.cs | 8 +++-----
.../SuggestionSources/Google.cs | 8 +++-----
4 files changed, 14 insertions(+), 26 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
index 51f81b718..590666af7 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
@@ -4,8 +4,6 @@ using System.Linq;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
-using Flow.Launcher.Infrastructure.Http;
-using Flow.Launcher.Infrastructure.Logger;
using System.Net.Http;
using System.Threading;
@@ -22,11 +20,11 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
try
{
const string api = "http://suggestion.baidu.com/su?json=1&wd=";
- result = await Http.GetAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false);
+ result = await Main._context.API.HttpGetStringAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false);
}
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
{
- Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e);
+ Main._context.API.LogException(nameof(Baidu), "Can't get suggestion from baidu", e);
return null;
}
@@ -41,7 +39,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
}
catch (JsonException e)
{
- Log.Exception("|Baidu.Suggestions|can't parse suggestions", e);
+ Main._context.API.LogException(nameof(Baidu), "Can't parse suggestions", e);
return new List();
}
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs
index 640674243..938f7d387 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs
@@ -1,6 +1,4 @@
-using Flow.Launcher.Infrastructure.Http;
-using Flow.Launcher.Infrastructure.Logger;
-using System;
+using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
@@ -10,16 +8,15 @@ using System.Threading;
namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
{
- class Bing : SuggestionSource
+ public class Bing : SuggestionSource
{
public override async Task> SuggestionsAsync(string query, CancellationToken token)
{
-
try
{
const string api = "https://api.bing.com/qsonhs.aspx?q=";
- await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false);
+ await using var resultStream = await Main._context.API.HttpGetStreamAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false);
using var json = (await JsonDocument.ParseAsync(resultStream, cancellationToken: token));
var root = json.RootElement.GetProperty("AS");
@@ -33,18 +30,15 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
.EnumerateArray()
.Select(s => s.GetProperty("Txt").GetString()))
.ToList();
-
-
-
}
catch (Exception e) when (e is HttpRequestException or { InnerException: TimeoutException })
{
- Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e);
+ Main._context.API.LogException(nameof(Bing), "Can't get suggestion from baidu", e);
return null;
}
catch (JsonException e)
{
- Log.Exception("|Bing.Suggestions|can't parse suggestions", e);
+ Main._context.API.LogException(nameof(Bing), "Can't parse suggestions", e);
return new List();
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs
index 8fafb44cc..1d248caf3 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs
@@ -2,8 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using Flow.Launcher.Infrastructure.Http;
-using Flow.Launcher.Infrastructure.Logger;
using System.Net.Http;
using System.Threading;
using System.Text.Json;
@@ -25,7 +23,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
{
const string api = "https://duckduckgo.com/ac/?type=list&q=";
- await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), token: token).ConfigureAwait(false);
+ await using var resultStream = await Main._context.API.HttpGetStreamAsync(api + Uri.EscapeDataString(query), token: token).ConfigureAwait(false);
using var json = await JsonDocument.ParseAsync(resultStream, cancellationToken: token);
@@ -36,12 +34,12 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
}
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
{
- Log.Exception("|DuckDuckGo.Suggestions|Can't get suggestion from DuckDuckGo", e);
+ Main._context.API.LogException(nameof(DuckDuckGo), "Can't get suggestion from DuckDuckGo", e);
return null;
}
catch (JsonException e)
{
- Log.Exception("|DuckDuckGo.Suggestions|can't parse suggestions", e);
+ Main._context.API.LogException(nameof(DuckDuckGo), "Can't parse suggestions", e);
return new List();
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
index 265de4a98..5f2504009 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
@@ -2,8 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using Flow.Launcher.Infrastructure.Http;
-using Flow.Launcher.Infrastructure.Logger;
using System.Net.Http;
using System.Threading;
using System.Text.Json;
@@ -18,7 +16,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
{
const string api = "https://www.google.com/complete/search?output=chrome&q=";
- await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), token: token).ConfigureAwait(false);
+ await using var resultStream = await Main._context.API.HttpGetStreamAsync(api + Uri.EscapeDataString(query), token: token).ConfigureAwait(false);
using var json = await JsonDocument.ParseAsync(resultStream, cancellationToken: token);
@@ -29,12 +27,12 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
}
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
{
- Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e);
+ Main._context.API.LogException(nameof(Google), "Can't get suggestion from baidu", e);
return null;
}
catch (JsonException e)
{
- Log.Exception("|Google.Suggestions|can't parse suggestions", e);
+ Main._context.API.LogException(nameof(Google), "Can't parse suggestions", e);
return new List();
}
}
From f9a01e10025563e069c3caafce85b80e89d60d2f Mon Sep 17 00:00:00 2001
From: Jack Ye <1160210343@qq.com>
Date: Wed, 2 Apr 2025 18:34:04 +0800
Subject: [PATCH 13/46] Fix typos
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
index fb80ede83..0ee576b2e 100644
--- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
@@ -348,7 +348,7 @@ namespace Flow.Launcher.Plugin
///
/// Load image from path. Support local, remote and data:image url.
- /// If image path is missing, it will retun a missing icon.
+ /// If image path is missing, it will return a missing icon.
///
/// The path of the image.
///
From 15a7e3a5afd8af4a9139935fd376d963963fb66b Mon Sep 17 00:00:00 2001
From: Jack Ye <1160210343@qq.com>
Date: Wed, 2 Apr 2025 18:35:03 +0800
Subject: [PATCH 14/46] Fix log typos
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
.../Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs
index 938f7d387..9efc36263 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs
@@ -33,7 +33,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
}
catch (Exception e) when (e is HttpRequestException or { InnerException: TimeoutException })
{
- Main._context.API.LogException(nameof(Bing), "Can't get suggestion from baidu", e);
+ Main._context.API.LogException(nameof(Bing), "Can't get suggestion from Bing", e);
return null;
}
catch (JsonException e)
From a33ecdbb971869605c4e8c03b5a0a00465040bd4 Mon Sep 17 00:00:00 2001
From: Jack Ye <1160210343@qq.com>
Date: Wed, 2 Apr 2025 18:35:27 +0800
Subject: [PATCH 15/46] Fix log typos
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---
.../Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
index 5f2504009..ad8fb508f 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs
@@ -27,7 +27,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
}
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
{
- Main._context.API.LogException(nameof(Google), "Can't get suggestion from baidu", e);
+ Main._context.API.LogException(nameof(Google), "Can't get suggestion from Google", e);
return null;
}
catch (JsonException e)
From e6a8fe3523b7c810faebf2b2235e1322884c0696 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Wed, 2 Apr 2025 18:36:25 +0800
Subject: [PATCH 16/46] Use caption letter
---
.../Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
index 590666af7..65be06b53 100644
--- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
+++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs
@@ -24,7 +24,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
}
catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException})
{
- Main._context.API.LogException(nameof(Baidu), "Can't get suggestion from baidu", e);
+ Main._context.API.LogException(nameof(Baidu), "Can't get suggestion from Baidu", e);
return null;
}
From 56536d018891a7a28e1c5916a1426045b3682360 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 4 Apr 2025 16:45:58 +0800
Subject: [PATCH 17/46] Add log for plugin binary storage
---
.../Storage/PluginBinaryStorage.cs | 36 ++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs
index 87f51d5d7..d18060e3d 100644
--- a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs
@@ -1,15 +1,49 @@
using System.IO;
+using System.Threading.Tasks;
+using CommunityToolkit.Mvvm.DependencyInjection;
+using Flow.Launcher.Plugin;
+using Flow.Launcher.Plugin.SharedCommands;
namespace Flow.Launcher.Infrastructure.Storage
{
public class PluginBinaryStorage : BinaryStorage where T : new()
{
+ private static readonly string ClassName = "PluginBinaryStorage";
+
+ // 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 PluginBinaryStorage(string cacheName, string cacheDirectory)
{
DirectoryPath = cacheDirectory;
- Helper.ValidateDirectory(DirectoryPath);
+ FilesFolders.ValidateDirectory(DirectoryPath);
FilePath = Path.Combine(DirectoryPath, $"{cacheName}{FileSuffix}");
}
+
+ public new void Save()
+ {
+ try
+ {
+ base.Save();
+ }
+ catch (System.Exception e)
+ {
+ API.LogException(ClassName, $"Failed to save plugin caches to path: {FilePath}", e);
+ }
+ }
+
+ public new async Task SaveAsync()
+ {
+ try
+ {
+ await base.SaveAsync();
+ }
+ catch (System.Exception e)
+ {
+ API.LogException(ClassName, $"Failed to save plugin caches to path: {FilePath}", e);
+ }
+ }
}
}
From 358b1fd7c875e4e4863227d53ee977872a9bd703 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 4 Apr 2025 20:10:39 +0800
Subject: [PATCH 18/46] Move theme data and functions into api
---
Flow.Launcher.Core/Resource/Theme.cs | 31 ++++----
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 19 +++++
Flow.Launcher.Plugin/ThemeData.cs | 71 +++++++++++++++++++
Flow.Launcher/PublicAPIInstance.cs | 13 ++++
4 files changed, 116 insertions(+), 18 deletions(-)
create mode 100644 Flow.Launcher.Plugin/ThemeData.cs
diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs
index e5980b62f..4cf9ce7a7 100644
--- a/Flow.Launcher.Core/Resource/Theme.cs
+++ b/Flow.Launcher.Core/Resource/Theme.cs
@@ -81,11 +81,6 @@ namespace Flow.Launcher.Core.Resource
#region Theme Resources
- public string GetCurrentTheme()
- {
- return _settings.Theme;
- }
-
private void MakeSureThemeDirectoriesExist()
{
foreach (var dir in _themeDirectories.Where(dir => !Directory.Exists(dir)))
@@ -127,7 +122,7 @@ namespace Flow.Launcher.Core.Resource
try
{
// Load a ResourceDictionary for the specified theme.
- var themeName = GetCurrentTheme();
+ var themeName = _settings.Theme;
var dict = GetThemeResourceDictionary(themeName);
// Apply font settings to the theme resource.
@@ -330,7 +325,7 @@ namespace Flow.Launcher.Core.Resource
private ResourceDictionary GetCurrentResourceDictionary()
{
- return GetResourceDictionary(GetCurrentTheme());
+ return GetResourceDictionary(_settings.Theme);
}
private ThemeData GetThemeDataFromPath(string path)
@@ -383,9 +378,15 @@ namespace Flow.Launcher.Core.Resource
#endregion
- #region Load & Change
+ #region Get & Change Theme
- public List LoadAvailableThemes()
+ public ThemeData GetCurrentTheme()
+ {
+ var themes = GetAvailableThemes();
+ return themes.FirstOrDefault(t => t.FileNameWithoutExtension == _settings.Theme) ?? themes.FirstOrDefault();
+ }
+
+ public List GetAvailableThemes()
{
List themes = new List();
foreach (var themeDirectory in _themeDirectories)
@@ -403,7 +404,7 @@ namespace Flow.Launcher.Core.Resource
public bool ChangeTheme(string theme = null)
{
if (string.IsNullOrEmpty(theme))
- theme = GetCurrentTheme();
+ theme = _settings.Theme;
string path = GetThemePath(theme);
try
@@ -591,7 +592,7 @@ namespace Flow.Launcher.Core.Resource
{
AutoDropShadow(useDropShadowEffect);
}
- SetBlurForWindow(GetCurrentTheme(), backdropType);
+ SetBlurForWindow(_settings.Theme, backdropType);
if (!BlurEnabled)
{
@@ -610,7 +611,7 @@ namespace Flow.Launcher.Core.Resource
// Get the actual backdrop type and drop shadow effect settings
var (backdropType, _) = GetActualValue();
- SetBlurForWindow(GetCurrentTheme(), backdropType);
+ SetBlurForWindow(_settings.Theme, backdropType);
}, DispatcherPriority.Render);
}
@@ -898,11 +899,5 @@ namespace Flow.Launcher.Core.Resource
}
#endregion
-
- #region Classes
-
- public record ThemeData(string FileNameWithoutExtension, string Name, bool? IsDark = null, bool? HasBlur = null);
-
- #endregion
}
}
diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
index f178ebb90..bfcc2f9e0 100644
--- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
@@ -344,5 +344,24 @@ namespace Flow.Launcher.Plugin
/// Stop the loading bar in main window
///
public void StopLoadingBar();
+
+ ///
+ /// Get all available themes
+ ///
+ ///
+ public List GetAvailableThemes();
+
+ ///
+ /// Get the current theme
+ ///
+ ///
+ public ThemeData GetCurrentTheme();
+
+ ///
+ /// Set the current theme
+ ///
+ ///
+ ///
+ public void SetCurrentTheme(ThemeData theme);
}
}
diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs
new file mode 100644
index 000000000..d4a69ef09
--- /dev/null
+++ b/Flow.Launcher.Plugin/ThemeData.cs
@@ -0,0 +1,71 @@
+namespace Flow.Launcher.Plugin;
+
+///
+/// Theme data model
+///
+public class ThemeData
+{
+ ///
+ /// Theme file name without extension
+ ///
+ public string FileNameWithoutExtension { get; private init; }
+
+ ///
+ /// Theme name
+ ///
+ public string Name { get; private init; }
+
+ ///
+ /// Theme file path
+ ///
+ public bool? IsDark { get; private init; }
+
+ ///
+ /// Theme file path
+ ///
+ public bool? HasBlur { get; private init; }
+
+ ///
+ /// Theme data constructor
+ ///
+ public ThemeData(string fileNameWithoutExtension, string name, bool? isDark = null, bool? hasBlur = null)
+ {
+ FileNameWithoutExtension = fileNameWithoutExtension;
+ Name = name;
+ IsDark = isDark;
+ HasBlur = hasBlur;
+ }
+
+ ///
+ public static bool operator ==(ThemeData left, ThemeData right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ public static bool operator !=(ThemeData left, ThemeData right)
+ {
+ return !(left == right);
+ }
+
+ ///
+ public override bool Equals(object obj)
+ {
+ if (obj is not ThemeData other)
+ return false;
+ return FileNameWithoutExtension == other.FileNameWithoutExtension &&
+ Name == other.Name;
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return Name?.GetHashCode() ?? 0;
+ }
+
+ ///
+ public override string ToString()
+ {
+ return Name;
+ }
+}
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index d88eeb7c9..96ccb55c4 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -37,6 +37,9 @@ namespace Flow.Launcher
private readonly Internationalization _translater;
private readonly MainViewModel _mainVM;
+ private Theme _theme;
+ private Theme Theme => _theme ??= Ioc.Default.GetRequiredService();
+
private readonly object _saveSettingsLock = new();
#region Constructor
@@ -354,6 +357,16 @@ namespace Flow.Launcher
public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress);
+ public List GetAvailableThemes() => Theme.GetAvailableThemes();
+
+ public ThemeData GetCurrentTheme() => Theme.GetCurrentTheme();
+
+ public void SetCurrentTheme(ThemeData theme)
+ {
+ Theme.ChangeTheme(theme.FileNameWithoutExtension);
+ _ = _theme.RefreshFrameAsync();
+ }
+
#endregion
#region Private Methods
From 9b9704e938f1e74584c8bc7688bc333387700c6b Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 4 Apr 2025 20:11:01 +0800
Subject: [PATCH 19/46] Improve settings panel theme page & theme selector
---
.../ViewModels/SettingsPaneThemeViewModel.cs | 14 +++---
.../Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 47 +++++--------------
2 files changed, 17 insertions(+), 44 deletions(-)
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs
index 6e2488fe1..58cf3a314 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs
@@ -28,25 +28,23 @@ public partial class SettingsPaneThemeViewModel : BaseModel
public static string LinkHowToCreateTheme => @"https://www.flowlauncher.com/theme-builder/";
public static string LinkThemeGallery => "https://github.com/Flow-Launcher/Flow.Launcher/discussions/1438";
- private List _themes;
- public List Themes => _themes ??= _theme.LoadAvailableThemes();
+ private List _themes;
+ public List Themes => _themes ??= App.API.GetAvailableThemes();
- private Theme.ThemeData _selectedTheme;
- public Theme.ThemeData SelectedTheme
+ private ThemeData _selectedTheme;
+ public ThemeData SelectedTheme
{
- get => _selectedTheme ??= Themes.Find(v => v.FileNameWithoutExtension == _theme.GetCurrentTheme());
+ get => _selectedTheme ??= Themes.Find(v => v == App.API.GetCurrentTheme());
set
{
_selectedTheme = value;
- _theme.ChangeTheme(value.FileNameWithoutExtension);
+ App.API.SetCurrentTheme(value);
// Update UI state
OnPropertyChanged(nameof(BackdropType));
OnPropertyChanged(nameof(IsBackdropEnabled));
OnPropertyChanged(nameof(IsDropShadowEnabled));
OnPropertyChanged(nameof(DropShadowEffect));
-
- _ = _theme.RefreshFrameAsync();
}
}
diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
index 31faeba52..84bfa218e 100644
--- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
+++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
@@ -1,7 +1,5 @@
using System.Collections.Generic;
using System.Linq;
-using CommunityToolkit.Mvvm.DependencyInjection;
-using Flow.Launcher.Core.Resource;
namespace Flow.Launcher.Plugin.Sys
{
@@ -11,32 +9,6 @@ namespace Flow.Launcher.Plugin.Sys
private readonly PluginInitContext _context;
- // Do not initialize it in the constructor, because it will cause null reference in
- // var dicts = Application.Current.Resources.MergedDictionaries; line of Theme
- private Theme theme = null;
- private Theme Theme => theme ??= Ioc.Default.GetRequiredService();
-
- #region Theme Selection
-
- // Theme select codes simplified from SettingsPaneThemeViewModel.cs
-
- private Theme.ThemeData _selectedTheme;
- public Theme.ThemeData SelectedTheme
- {
- get => _selectedTheme ??= Themes.Find(v => v.FileNameWithoutExtension == Theme.GetCurrentTheme());
- set
- {
- _selectedTheme = value;
- Theme.ChangeTheme(value.FileNameWithoutExtension);
-
- _ = Theme.RefreshFrameAsync();
- }
- }
-
- private List Themes => Theme.LoadAvailableThemes();
-
- #endregion
-
public ThemeSelector(PluginInitContext context)
{
_context = context;
@@ -44,28 +16,31 @@ namespace Flow.Launcher.Plugin.Sys
public List Query(Query query)
{
+ var themes = _context.API.GetAvailableThemes();
+ var selectedTheme = _context.API.GetCurrentTheme();
+
var search = query.SecondToEndSearch;
if (string.IsNullOrWhiteSpace(search))
{
- return Themes.Select(CreateThemeResult)
+ return themes.Select(x => CreateThemeResult(x, selectedTheme))
.OrderBy(x => x.Title)
.ToList();
}
- return Themes.Select(theme => (theme, matchResult: _context.API.FuzzySearch(search, theme.Name)))
+ return themes.Select(theme => (theme, matchResult: _context.API.FuzzySearch(search, theme.Name)))
.Where(x => x.matchResult.IsSearchPrecisionScoreMet())
- .Select(x => CreateThemeResult(x.theme, x.matchResult.Score, x.matchResult.MatchData))
+ .Select(x => CreateThemeResult(x.theme, selectedTheme, x.matchResult.Score, x.matchResult.MatchData))
.OrderBy(x => x.Title)
.ToList();
}
- private Result CreateThemeResult(Theme.ThemeData theme) => CreateThemeResult(theme, 0, null);
+ private Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme) => CreateThemeResult(theme, selectedTheme, 0, null);
- private Result CreateThemeResult(Theme.ThemeData theme, int score, IList highlightData)
+ private Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme, int score, IList highlightData)
{
- string themeName = theme.Name;
+ var themeName = theme.FileNameWithoutExtension;
string title;
- if (theme == SelectedTheme)
+ if (theme == selectedTheme)
{
title = $"{theme.Name} ★";
// Set current theme to the top
@@ -101,7 +76,7 @@ namespace Flow.Launcher.Plugin.Sys
Score = score,
Action = c =>
{
- SelectedTheme = theme;
+ _context.API.SetCurrentTheme(theme);
_context.API.ReQuery();
return false;
}
From 1611ad37f37fde5ac054529cfa3a136e28fa3168 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 4 Apr 2025 20:15:47 +0800
Subject: [PATCH 20/46] Fix ThemeData hashcode issue
---
Flow.Launcher.Plugin/ThemeData.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs
index d4a69ef09..6cbd0fe74 100644
--- a/Flow.Launcher.Plugin/ThemeData.cs
+++ b/Flow.Launcher.Plugin/ThemeData.cs
@@ -1,4 +1,6 @@
-namespace Flow.Launcher.Plugin;
+using System;
+
+namespace Flow.Launcher.Plugin;
///
/// Theme data model
@@ -60,7 +62,7 @@ public class ThemeData
///
public override int GetHashCode()
{
- return Name?.GetHashCode() ?? 0;
+ return HashCode.Combine(FileNameWithoutExtension, Name);
}
///
From 514fa0037a0f0ad6b78ad6ae17d943764cf696c7 Mon Sep 17 00:00:00 2001
From: Jack Ye <1160210343@qq.com>
Date: Fri, 4 Apr 2025 20:23:07 +0800
Subject: [PATCH 21/46] Improve documents
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
Flow.Launcher.Plugin/ThemeData.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs
index 6cbd0fe74..90a45182c 100644
--- a/Flow.Launcher.Plugin/ThemeData.cs
+++ b/Flow.Launcher.Plugin/ThemeData.cs
@@ -23,7 +23,7 @@ public class ThemeData
public bool? IsDark { get; private init; }
///
- /// Theme file path
+ /// Indicates whether the theme supports blur effects
///
public bool? HasBlur { get; private init; }
From 28d92c789f181acb2060f7ff0b1c9f226bdb4905 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 4 Apr 2025 20:23:36 +0800
Subject: [PATCH 22/46] Improve documents
---
Flow.Launcher.Plugin/ThemeData.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs
index 90a45182c..1888be65e 100644
--- a/Flow.Launcher.Plugin/ThemeData.cs
+++ b/Flow.Launcher.Plugin/ThemeData.cs
@@ -18,7 +18,7 @@ public class ThemeData
public string Name { get; private init; }
///
- /// Theme file path
+ /// Indicates whether the theme supports dark mode
///
public bool? IsDark { get; private init; }
From 2e885ea5ccec4a42de61e1d1fe6ced1e319656ce Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Fri, 4 Apr 2025 20:45:24 +0800
Subject: [PATCH 23/46] Remove useless variable
---
Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
index 84bfa218e..4b99efe3b 100644
--- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
+++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
@@ -38,7 +38,6 @@ namespace Flow.Launcher.Plugin.Sys
private Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme, int score, IList highlightData)
{
- var themeName = theme.FileNameWithoutExtension;
string title;
if (theme == selectedTheme)
{
From e6d3d0fa9efba36feec5dbeb68e5e41e3af47039 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 5 Apr 2025 11:11:14 +0800
Subject: [PATCH 24/46] Improve code quality
---
.../Storage/BinaryStorage.cs | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
index 81e2503ad..208e4bf11 100644
--- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
@@ -81,13 +81,6 @@ namespace Flow.Launcher.Infrastructure.Storage
}
}
- public async ValueTask SaveAsync()
- {
- await using var stream = new FileStream(FilePath, FileMode.Create);
- await MemoryPackSerializer.SerializeAsync(stream, Data);
- }
-
- // For SavePluginSettings function
public void Save()
{
var serialized = MemoryPackSerializer.Serialize(Data);
@@ -95,13 +88,20 @@ namespace Flow.Launcher.Infrastructure.Storage
File.WriteAllBytes(FilePath, serialized);
}
- // ImageCache need to be converted into concurrent dictionary, so it does not need to cache loading results into Data
+ public async ValueTask SaveAsync()
+ {
+ await SaveAsync(Data.NonNull());
+ }
+
+ // ImageCache need to convert data into concurrent dictionary for usage,
+ // so we would better to clear the data
public void ClearData()
{
Data = default;
}
- // ImageCache storages data in its class, so it needs to pass it to SaveAsync
+ // ImageCache storages data in its class,
+ // so we need to pass it to SaveAsync
public async ValueTask SaveAsync(T data)
{
await using var stream = new FileStream(FilePath, FileMode.Create);
From 6e5c7ad190a539903f068995bac117b15ca45cc3 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 5 Apr 2025 11:19:01 +0800
Subject: [PATCH 25/46] Use ISavable interface instead of reflection
---
Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs | 3 ++-
Flow.Launcher.Infrastructure/Storage/JsonStorage.cs | 8 +++++---
Flow.Launcher/PublicAPIInstance.cs | 8 ++++----
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
index 208e4bf11..f218c5d8d 100644
--- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
@@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
+using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
using MemoryPack;
@@ -16,7 +17,7 @@ namespace Flow.Launcher.Infrastructure.Storage
///
/// It utilize MemoryPack, which means the object must be MemoryPackSerializable
///
- public class BinaryStorage
+ public class BinaryStorage : ISavable
{
protected T? Data;
diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
index a3488124b..cdf3ae909 100644
--- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
@@ -1,18 +1,20 @@
-#nullable enable
-using System;
+using System;
using System.Globalization;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using Flow.Launcher.Infrastructure.Logger;
+using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
+#nullable enable
+
namespace Flow.Launcher.Infrastructure.Storage
{
///
/// Serialize object using json format.
///
- public class JsonStorage where T : new()
+ public class JsonStorage : ISavable where T : new()
{
protected T? Data;
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 99d4cf233..50052f1c9 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -225,8 +225,8 @@ namespace Flow.Launcher
{
foreach (var value in _pluginJsonStorages.Values)
{
- var method = value.GetType().GetMethod("Save");
- method?.Invoke(value, null);
+ var savable = value as ISavable;
+ savable?.Save();
}
}
@@ -368,8 +368,8 @@ namespace Flow.Launcher
{
foreach (var value in _pluginBinaryStorages.Values)
{
- var method = value.GetType().GetMethod("Save");
- method?.Invoke(value, null);
+ var savable = value as ISavable;
+ savable?.Save();
}
}
From 3185bda824ab19a132703d77dbf7c6844dd0a2a8 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Sat, 5 Apr 2025 11:31:24 +0800
Subject: [PATCH 26/46] Use IRemovable interface instead of reflection
---
Flow.Launcher.Core/Plugin/PluginManager.cs | 9 ++++-----
Flow.Launcher.Core/Storage/IRemovable.cs | 19 +++++++++++++++++++
Flow.Launcher/PublicAPIInstance.cs | 7 ++++---
3 files changed, 27 insertions(+), 8 deletions(-)
create mode 100644 Flow.Launcher.Core/Storage/IRemovable.cs
diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs
index c167a5b21..03ddcb13d 100644
--- a/Flow.Launcher.Core/Plugin/PluginManager.cs
+++ b/Flow.Launcher.Core/Plugin/PluginManager.cs
@@ -13,6 +13,7 @@ using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.SharedCommands;
+using IRemovable = Flow.Launcher.Core.Storage.IRemovable;
using ISavable = Flow.Launcher.Plugin.ISavable;
namespace Flow.Launcher.Core.Plugin
@@ -588,12 +589,10 @@ namespace Flow.Launcher.Core.Plugin
if (removePluginSettings)
{
// For dotnet plugins, we need to remove their PluginJsonStorage and PluginBinaryStorage instances
- if (AllowedLanguage.IsDotNet(plugin.Language))
+ if (AllowedLanguage.IsDotNet(plugin.Language) && API is IRemovable removable)
{
- var method = API.GetType().GetMethod("RemovePluginSettings");
- method?.Invoke(API, new object[] { plugin.AssemblyName });
- var method1 = API.GetType().GetMethod("RemovePluginCache");
- method1?.Invoke(API, new object[] { plugin.PluginCacheDirectoryPath });
+ removable.RemovePluginSettings(plugin.AssemblyName);
+ removable.RemovePluginCaches(plugin.PluginCacheDirectoryPath);
}
try
diff --git a/Flow.Launcher.Core/Storage/IRemovable.cs b/Flow.Launcher.Core/Storage/IRemovable.cs
new file mode 100644
index 000000000..fc34395e0
--- /dev/null
+++ b/Flow.Launcher.Core/Storage/IRemovable.cs
@@ -0,0 +1,19 @@
+namespace Flow.Launcher.Core.Storage;
+
+///
+/// Remove storage instances from instance
+///
+public interface IRemovable
+{
+ ///
+ /// Remove all instances of one plugin
+ ///
+ ///
+ public void RemovePluginSettings(string assemblyName);
+
+ ///
+ /// Remove all instances of one plugin
+ ///
+ ///
+ public void RemovePluginCaches(string cacheDirectory);
+}
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 50052f1c9..b34006272 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -14,6 +14,8 @@ using CommunityToolkit.Mvvm.DependencyInjection;
using Squirrel;
using Flow.Launcher.Core;
using Flow.Launcher.Core.Plugin;
+using Flow.Launcher.Core.Resource;
+using Flow.Launcher.Core.Storage;
using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Http;
@@ -27,11 +29,10 @@ using Flow.Launcher.Plugin.SharedModels;
using Flow.Launcher.Plugin.SharedCommands;
using Flow.Launcher.ViewModel;
using JetBrains.Annotations;
-using Flow.Launcher.Core.Resource;
namespace Flow.Launcher
{
- public class PublicAPIInstance : IPublicAPI
+ public class PublicAPIInstance : IPublicAPI, IRemovable
{
private readonly Settings _settings;
private readonly Internationalization _translater;
@@ -348,7 +349,7 @@ namespace Flow.Launcher
private readonly ConcurrentDictionary<(string, string, Type), object> _pluginBinaryStorages = new();
- public void RemovePluginCache(string cacheDirectory)
+ public void RemovePluginCaches(string cacheDirectory)
{
foreach (var keyValuePair in _pluginBinaryStorages)
{
From ecd019dd6b0c286a6cf223cf598bc1fc57dd4279 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 15:56:54 +0800
Subject: [PATCH 27/46] Move ThemeData class to SharedModels
---
Flow.Launcher.Core/Resource/Theme.cs | 1 +
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 6 +++---
Flow.Launcher.Plugin/{ => SharedModels}/ThemeData.cs | 2 +-
.../SettingPages/ViewModels/SettingsPaneThemeViewModel.cs | 1 +
Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 1 +
5 files changed, 7 insertions(+), 4 deletions(-)
rename Flow.Launcher.Plugin/{ => SharedModels}/ThemeData.cs (97%)
diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs
index 4cf9ce7a7..f3eba7ba7 100644
--- a/Flow.Launcher.Core/Resource/Theme.cs
+++ b/Flow.Launcher.Core/Resource/Theme.cs
@@ -16,6 +16,7 @@ using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
+using Flow.Launcher.Plugin.SharedModels;
using Microsoft.Win32;
namespace Flow.Launcher.Core.Resource
diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
index 64bdcec34..1090a3a1e 100644
--- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
@@ -1,6 +1,4 @@
-using Flow.Launcher.Plugin.SharedModels;
-using JetBrains.Annotations;
-using System;
+using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
@@ -8,6 +6,8 @@ using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
+using Flow.Launcher.Plugin.SharedModels;
+using JetBrains.Annotations;
namespace Flow.Launcher.Plugin
{
diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs
similarity index 97%
rename from Flow.Launcher.Plugin/ThemeData.cs
rename to Flow.Launcher.Plugin/SharedModels/ThemeData.cs
index 1888be65e..6a5e54f55 100644
--- a/Flow.Launcher.Plugin/ThemeData.cs
+++ b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs
@@ -1,6 +1,6 @@
using System;
-namespace Flow.Launcher.Plugin;
+namespace Flow.Launcher.Plugin.SharedModels;
///
/// Theme data model
diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs
index 58cf3a314..f78704ef2 100644
--- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs
+++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs
@@ -12,6 +12,7 @@ using Flow.Launcher.Helper;
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
+using Flow.Launcher.Plugin.SharedModels;
using Flow.Launcher.ViewModel;
using ModernWpf;
using ThemeManagerForColorSchemeSwitch = ModernWpf.ThemeManager;
diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
index 4b99efe3b..feacc3f99 100644
--- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
+++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
+using Flow.Launcher.Plugin.SharedModels;
namespace Flow.Launcher.Plugin.Sys
{
From 6c458828bc9d24a58de29240f1417c253c64a7d6 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 16:01:46 +0800
Subject: [PATCH 28/46] Fix possible NullReferenceException
---
Flow.Launcher.Plugin/SharedModels/ThemeData.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs
index 6a5e54f55..322985f3a 100644
--- a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs
+++ b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs
@@ -41,12 +41,16 @@ public class ThemeData
///
public static bool operator ==(ThemeData left, ThemeData right)
{
+ if (left is null && right is null)
+ return true;
return left.Equals(right);
}
///
public static bool operator !=(ThemeData left, ThemeData right)
{
+ if (left is null && right is null)
+ return false;
return !(left == right);
}
From 6c5bb7d184d1f5a1284f94647e6f34ce1f0b2b84 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 8 Apr 2025 18:12:10 +1000
Subject: [PATCH 29/46] update summary
---
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
index 30004952e..111bc716c 100644
--- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
@@ -228,7 +228,7 @@ namespace Flow.Launcher.Plugin
void LogWarn(string className, string message, [CallerMemberName] string methodName = "");
///
- /// Log error message
+ /// Log error message. Preferred error logging method for plugins.
///
void LogError(string className, string message, [CallerMemberName] string methodName = "");
From 537c03f2d751345176bbeacf1d58a657da3aef31 Mon Sep 17 00:00:00 2001
From: Jack Ye <1160210343@qq.com>
Date: Tue, 8 Apr 2025 16:13:58 +0800
Subject: [PATCH 30/46] Fix null check issue
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---
Flow.Launcher.Plugin/SharedModels/ThemeData.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs
index 322985f3a..093e1ee8e 100644
--- a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs
+++ b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs
@@ -43,6 +43,8 @@ public class ThemeData
{
if (left is null && right is null)
return true;
+ if (left is null || right is null)
+ return false;
return left.Equals(right);
}
From b3aa89773ce1fdfadc9dfd06b13acc596d504265 Mon Sep 17 00:00:00 2001
From: Jack Ye <1160210343@qq.com>
Date: Tue, 8 Apr 2025 16:14:17 +0800
Subject: [PATCH 31/46] Use == for != operator
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
---
Flow.Launcher.Plugin/SharedModels/ThemeData.cs | 2 --
1 file changed, 2 deletions(-)
diff --git a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs
index 093e1ee8e..cb389c21f 100644
--- a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs
+++ b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs
@@ -51,8 +51,6 @@ public class ThemeData
///
public static bool operator !=(ThemeData left, ThemeData right)
{
- if (left is null && right is null)
- return false;
return !(left == right);
}
From a2d99573855b145a4ac68f270494c05f07ea06a6 Mon Sep 17 00:00:00 2001
From: Jack Ye <1160210343@qq.com>
Date: Tue, 8 Apr 2025 16:20:11 +0800
Subject: [PATCH 32/46] Log warning if cannot find matched theme
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
Flow.Launcher.Core/Resource/Theme.cs | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs
index f3eba7ba7..d7c619330 100644
--- a/Flow.Launcher.Core/Resource/Theme.cs
+++ b/Flow.Launcher.Core/Resource/Theme.cs
@@ -384,7 +384,12 @@ namespace Flow.Launcher.Core.Resource
public ThemeData GetCurrentTheme()
{
var themes = GetAvailableThemes();
- return themes.FirstOrDefault(t => t.FileNameWithoutExtension == _settings.Theme) ?? themes.FirstOrDefault();
+ var matchingTheme = themes.FirstOrDefault(t => t.FileNameWithoutExtension == _settings.Theme);
+ if (matchingTheme == null)
+ {
+ Log.Warn($"No matching theme found for '{_settings.Theme}'. Falling back to the first available theme.");
+ }
+ return matchingTheme ?? themes.FirstOrDefault();
}
public List GetAvailableThemes()
From 7da2884e84ebd45dc70c16cd3dde6f6ef1e2b4af Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 16:29:03 +0800
Subject: [PATCH 33/46] Add locks for win32s & uwps
---
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 61 +++++++++++++++----
.../Views/Commands/ProgramSettingDisplay.cs | 34 ++++++++---
.../Views/ProgramSetting.xaml.cs | 18 +++---
3 files changed, 83 insertions(+), 30 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index d3c50b406..6d2ae70fc 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -27,6 +27,9 @@ namespace Flow.Launcher.Plugin.Program
internal static List _uwps { get; private set; }
internal static Settings _settings { get; private set; }
+ internal static SemaphoreSlim _win32sLock = new(1, 1);
+ internal static SemaphoreSlim _uwpsLock = new(1, 1);
+
internal static PluginInitContext Context { get; private set; }
private static readonly List emptyResults = new();
@@ -82,8 +85,11 @@ namespace Flow.Launcher.Plugin.Program
{
var result = await cache.GetOrCreateAsync(query.Search, async entry =>
{
- var resultList = await Task.Run(() =>
+ var resultList = await Task.Run(async () =>
{
+ await _win32sLock.WaitAsync(token);
+ await _uwpsLock.WaitAsync(token);
+
try
{
// Collect all UWP Windows app directories
@@ -95,22 +101,26 @@ namespace Flow.Launcher.Plugin.Program
.ToArray() : null;
return _win32s.Cast()
- .Concat(_uwps)
- .AsParallel()
- .WithCancellation(token)
- .Where(HideUninstallersFilter)
- .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories))
- .Where(p => p.Enabled)
- .Select(p => p.Result(query.Search, Context.API))
- .Where(r => r?.Score > 0)
- .ToList();
+ .Concat(_uwps)
+ .AsParallel()
+ .WithCancellation(token)
+ .Where(HideUninstallersFilter)
+ .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories))
+ .Where(p => p.Enabled)
+ .Select(p => p.Result(query.Search, Context.API))
+ .Where(r => r?.Score > 0)
+ .ToList();
}
catch (OperationCanceledException)
{
Log.Debug("|Flow.Launcher.Plugin.Program.Main|Query operation cancelled");
return emptyResults;
}
-
+ finally
+ {
+ _uwpsLock.Release();
+ _win32sLock.Release();
+ }
}, token);
resultList = resultList.Any() ? resultList : emptyResults;
@@ -236,14 +246,25 @@ namespace Flow.Launcher.Plugin.Program
var newUWPCacheFile = Path.Combine(pluginCachePath, $"{UwpCacheName}.cache");
MoveFile(oldUWPCacheFile, newUWPCacheFile);
+ await _win32sLock.WaitAsync();
_win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List());
+ _win32sLock.Release();
+
+ await _uwpsLock.WaitAsync();
_uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List());
+ _uwpsLock.Release();
});
+ await _win32sLock.WaitAsync();
+ await _uwpsLock.WaitAsync();
+
Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Count}>");
Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Count}>");
bool cacheEmpty = !_win32s.Any() || !_uwps.Any();
+ _win32sLock.Release();
+ _uwpsLock.Release();
+
if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now)
{
_ = Task.Run(async () =>
@@ -267,11 +288,13 @@ namespace Flow.Launcher.Plugin.Program
public static async Task IndexWin32ProgramsAsync()
{
var win32S = Win32.All(_settings);
+ await _win32sLock.WaitAsync();
_win32s.Clear();
foreach (var win32 in win32S)
{
_win32s.Add(win32);
}
+ _win32sLock.Release();
ResetCache();
await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
_settings.LastIndexTime = DateTime.Now;
@@ -280,11 +303,13 @@ namespace Flow.Launcher.Plugin.Program
public static async Task IndexUwpProgramsAsync()
{
var uwps = UWPPackage.All(_settings);
+ await _uwpsLock.WaitAsync();
_uwps.Clear();
foreach (var uwp in uwps)
{
_uwps.Add(uwp);
}
+ _uwpsLock.Release();
ResetCache();
await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
_settings.LastIndexTime = DateTime.Now;
@@ -358,26 +383,36 @@ namespace Flow.Launcher.Plugin.Program
return menuOptions;
}
- private static void DisableProgram(IProgram programToDelete)
+ private static async Task DisableProgram(IProgram programToDelete)
{
if (_settings.DisabledProgramSources.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
return;
+ await _uwpsLock.WaitAsync();
if (_uwps.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
{
var program = _uwps.First(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier);
program.Enabled = false;
_settings.DisabledProgramSources.Add(new ProgramSource(program));
+ _uwpsLock.Release();
+
+ // Reindex UWP programs
_ = Task.Run(() =>
{
_ = IndexUwpProgramsAsync();
});
+ return;
}
- else if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
+
+ await _win32sLock.WaitAsync();
+ if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
{
var program = _win32s.First(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier);
program.Enabled = false;
_settings.DisabledProgramSources.Add(new ProgramSource(program));
+ _win32sLock.Release();
+
+ // Reindex Win32 programs
_ = Task.Run(() =>
{
_ = IndexWin32ProgramsAsync();
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs
index e4d7c323a..b89a2a6ba 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
using Flow.Launcher.Plugin.Program.Views.Models;
namespace Flow.Launcher.Plugin.Program.Views.Commands
@@ -15,21 +16,24 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands
.ToList();
}
- internal static void DisplayAllPrograms()
+ internal static async Task DisplayAllProgramsAsync()
{
+ await Main._win32sLock.WaitAsync();
var win32 = Main._win32s
.Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
.Select(x => new ProgramSource(x));
+ ProgramSetting.ProgramSettingDisplayList.AddRange(win32);
+ Main._win32sLock.Release();
+ await Main._uwpsLock.WaitAsync();
var uwp = Main._uwps
.Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
.Select(x => new ProgramSource(x));
-
- ProgramSetting.ProgramSettingDisplayList.AddRange(win32);
ProgramSetting.ProgramSettingDisplayList.AddRange(uwp);
+ Main._uwpsLock.Release();
}
- internal static void SetProgramSourcesStatus(List selectedProgramSourcesToDisable, bool status)
+ internal static async Task SetProgramSourcesStatusAsync(List selectedProgramSourcesToDisable, bool status)
{
foreach(var program in ProgramSetting.ProgramSettingDisplayList)
{
@@ -39,14 +43,17 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands
}
}
- foreach(var program in Main._win32s)
+ await Main._win32sLock.WaitAsync();
+ foreach (var program in Main._win32s)
{
if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status))
{
program.Enabled = status;
}
}
+ Main._win32sLock.Release();
+ await Main._uwpsLock.WaitAsync();
foreach (var program in Main._uwps)
{
if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status))
@@ -54,6 +61,7 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands
program.Enabled = status;
}
}
+ Main._uwpsLock.Release();
}
internal static void StoreDisabledInSettings()
@@ -72,12 +80,22 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands
Main._settings.DisabledProgramSources.RemoveAll(t1 => t1.Enabled);
}
- internal static bool IsReindexRequired(this List selectedItems)
+ internal static async Task IsReindexRequiredAsync(this List selectedItems)
{
// Not in cache
- if (selectedItems.Any(t1 => t1.Enabled && !Main._uwps.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier))
+ await Main._win32sLock.WaitAsync();
+ await Main._uwpsLock.WaitAsync();
+ try
+ {
+ if (selectedItems.Any(t1 => t1.Enabled && !Main._uwps.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier))
&& selectedItems.Any(t1 => t1.Enabled && !Main._win32s.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier)))
- return true;
+ return true;
+ }
+ finally
+ {
+ Main._win32sLock.Release();
+ Main._uwpsLock.Release();
+ }
// ProgramSources holds list of user added directories,
// so when we enable/disable we need to reindex to show/not show the programs
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
index 5ad7fcea3..c42bd4f30 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs
@@ -183,7 +183,7 @@ namespace Flow.Launcher.Plugin.Program.Views
EditProgramSource(selectedProgramSource);
}
- private void EditProgramSource(ProgramSource selectedProgramSource)
+ private async void EditProgramSource(ProgramSource selectedProgramSource)
{
if (selectedProgramSource == null)
{
@@ -202,13 +202,13 @@ namespace Flow.Launcher.Plugin.Program.Views
{
if (selectedProgramSource.Enabled)
{
- ProgramSettingDisplay.SetProgramSourcesStatus(new List { selectedProgramSource },
+ await ProgramSettingDisplay.SetProgramSourcesStatusAsync(new List { selectedProgramSource },
true); // sync status in win32, uwp and disabled
ProgramSettingDisplay.RemoveDisabledFromSettings();
}
else
{
- ProgramSettingDisplay.SetProgramSourcesStatus(new List { selectedProgramSource },
+ await ProgramSettingDisplay.SetProgramSourcesStatusAsync(new List { selectedProgramSource },
false);
ProgramSettingDisplay.StoreDisabledInSettings();
}
@@ -277,14 +277,14 @@ namespace Flow.Launcher.Plugin.Program.Views
}
}
- private void btnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e)
+ private async void btnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e)
{
- ProgramSettingDisplay.DisplayAllPrograms();
+ await ProgramSettingDisplay.DisplayAllProgramsAsync();
ViewRefresh();
}
- private void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e)
+ private async void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e)
{
var selectedItems = programSourceView
.SelectedItems.Cast()
@@ -311,18 +311,18 @@ namespace Flow.Launcher.Plugin.Program.Views
}
else if (HasMoreOrEqualEnabledItems(selectedItems))
{
- ProgramSettingDisplay.SetProgramSourcesStatus(selectedItems, false);
+ await ProgramSettingDisplay.SetProgramSourcesStatusAsync(selectedItems, false);
ProgramSettingDisplay.StoreDisabledInSettings();
}
else
{
- ProgramSettingDisplay.SetProgramSourcesStatus(selectedItems, true);
+ await ProgramSettingDisplay.SetProgramSourcesStatusAsync(selectedItems, true);
ProgramSettingDisplay.RemoveDisabledFromSettings();
}
- if (selectedItems.IsReindexRequired())
+ if (await selectedItems.IsReindexRequiredAsync())
ReIndexing();
programSourceView.SelectedItems.Clear();
From dd210ad41968a1e9112fb6b364a08093534ae136 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 16:41:06 +0800
Subject: [PATCH 34/46] Remove RefreshFrameAsync since ChangeTheme calls this
function
---
Flow.Launcher.Core/Resource/Theme.cs | 2 +-
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 6 ++++--
Flow.Launcher/PublicAPIInstance.cs | 5 +----
3 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs
index d7c619330..59e76e2d2 100644
--- a/Flow.Launcher.Core/Resource/Theme.cs
+++ b/Flow.Launcher.Core/Resource/Theme.cs
@@ -433,7 +433,7 @@ namespace Flow.Launcher.Core.Resource
BlurEnabled = IsBlurTheme();
- // Can only apply blur but here also apply drop shadow effect to avoid possible drop shadow effect issues
+ // Apply blur and drop shadow effect so that we do not need to call it again
_ = RefreshFrameAsync();
return true;
diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
index 056c4a437..7701fcdd0 100644
--- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
@@ -367,8 +367,10 @@ namespace Flow.Launcher.Plugin
/// Set the current theme
///
///
- ///
- public void SetCurrentTheme(ThemeData theme);
+ ///
+ /// True if the theme is set successfully, false otherwise.
+ ///
+ public bool SetCurrentTheme(ThemeData theme);
/// Load image from path. Support local, remote and data:image url.
/// If image path is missing, it will return a missing icon.
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index b19b21db1..8cce460d7 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -377,11 +377,8 @@ namespace Flow.Launcher
public ThemeData GetCurrentTheme() => Theme.GetCurrentTheme();
- public void SetCurrentTheme(ThemeData theme)
- {
+ public bool SetCurrentTheme(ThemeData theme) =>
Theme.ChangeTheme(theme.FileNameWithoutExtension);
- _ = _theme.RefreshFrameAsync();
- }
public ValueTask LoadImageAsync(string path, bool loadFullImage = false, bool cacheImage = true) =>
ImageLoader.LoadAsync(path, loadFullImage, cacheImage);
From a3c7be95597f8c0765f0e62749b7f263749e78cd Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 16:49:29 +0800
Subject: [PATCH 35/46] Handle results from SetCurrentTheme
---
Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
index feacc3f99..f8aeaeafd 100644
--- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
+++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs
@@ -76,8 +76,10 @@ namespace Flow.Launcher.Plugin.Sys
Score = score,
Action = c =>
{
- _context.API.SetCurrentTheme(theme);
- _context.API.ReQuery();
+ if (_context.API.SetCurrentTheme(theme))
+ {
+ _context.API.ReQuery();
+ }
return false;
}
};
From 734c5bb67deb769190fa46572083e64ffcef8cf8 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 16:59:27 +0800
Subject: [PATCH 36/46] Fix lock release issue
---
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index 6d2ae70fc..a5fbc6c70 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -367,7 +367,7 @@ namespace Flow.Launcher.Plugin.Program
Title = Context.API.GetTranslation("flowlauncher_plugin_program_disable_program"),
Action = c =>
{
- DisableProgram(program);
+ _ = DisableProgramAsync(program);
Context.API.ShowMsg(
Context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_success"),
Context.API.GetTranslation(
@@ -383,7 +383,7 @@ namespace Flow.Launcher.Plugin.Program
return menuOptions;
}
- private static async Task DisableProgram(IProgram programToDelete)
+ private static async Task DisableProgramAsync(IProgram programToDelete)
{
if (_settings.DisabledProgramSources.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
return;
@@ -403,7 +403,12 @@ namespace Flow.Launcher.Plugin.Program
});
return;
}
-
+ else
+ {
+ // Release the lock if we cannot find the program
+ _uwpsLock.Release();
+ }
+
await _win32sLock.WaitAsync();
if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
{
@@ -418,6 +423,11 @@ namespace Flow.Launcher.Plugin.Program
_ = IndexWin32ProgramsAsync();
});
}
+ else
+ {
+ // Release the lock if we cannot find the program
+ _win32sLock.Release();
+ }
}
public static void StartProcess(Func runProcess, ProcessStartInfo info)
From c11ee2f9e78fa626bd7801fed293d990fdfaf682 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 17:20:57 +0800
Subject: [PATCH 37/46] Improve code quality & comments & Fix lock issue
---
.../Storage/BinaryStorage.cs | 6 ++--
.../Storage/PluginJsonStorage.cs | 1 +
Flow.Launcher.Plugin/Interfaces/ISavable.cs | 9 ++++--
Flow.Launcher/PublicAPIInstance.cs | 6 ----
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 29 +++++++------------
5 files changed, 20 insertions(+), 31 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
index f218c5d8d..b5de3b50f 100644
--- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
@@ -42,8 +42,7 @@ namespace Flow.Launcher.Infrastructure.Storage
public async ValueTask TryLoadAsync(T defaultData)
{
- if (Data != null)
- return Data;
+ if (Data != null) return Data;
if (File.Exists(FilePath))
{
@@ -55,8 +54,7 @@ namespace Flow.Launcher.Infrastructure.Storage
}
await using var stream = new FileStream(FilePath, FileMode.Open);
- var d = await DeserializeAsync(stream, defaultData);
- Data = d;
+ Data = await DeserializeAsync(stream, defaultData);
}
else
{
diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs
index b63e8c1ef..e8cbd70fb 100644
--- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs
@@ -20,6 +20,7 @@ namespace Flow.Launcher.Infrastructure.Storage
public PluginJsonStorage()
{
+ // C# related, add python related below
var dataType = typeof(T);
AssemblyName = dataType.Assembly.GetName().Name;
DirectoryPath = Path.Combine(DataLocation.PluginSettingsDirectory, AssemblyName);
diff --git a/Flow.Launcher.Plugin/Interfaces/ISavable.cs b/Flow.Launcher.Plugin/Interfaces/ISavable.cs
index cabd26962..0d23c0fc8 100644
--- a/Flow.Launcher.Plugin/Interfaces/ISavable.cs
+++ b/Flow.Launcher.Plugin/Interfaces/ISavable.cs
@@ -1,18 +1,21 @@
namespace Flow.Launcher.Plugin
{
///
- /// Inherit this interface if additional data e.g. cache needs to be saved.
+ /// Inherit this interface if additional data.
+ /// If you need to save data which is not a setting or cache,
+ /// please implement this interface.
///
///
/// For storing plugin settings, prefer
/// or .
+ /// For storing plugin caches, prefer
/// or .
- /// Once called, your settings will be automatically saved by Flow.
+ /// Once called, those settings and caches will be automatically saved by Flow.
///
public interface ISavable : IFeatures
{
///
- /// Save additional plugin data, such as cache.
+ /// Save additional plugin data.
///
void Save();
}
diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs
index 4dd0268d2..a523f90bb 100644
--- a/Flow.Launcher/PublicAPIInstance.cs
+++ b/Flow.Launcher/PublicAPIInstance.cs
@@ -229,9 +229,6 @@ namespace Flow.Launcher
}
}
- ///
- /// Save plugin settings.
- ///
public void SavePluginSettings()
{
foreach (var value in _pluginJsonStorages.Values)
@@ -378,9 +375,6 @@ namespace Flow.Launcher
}
}
- ///
- /// Save plugin caches.
- ///
public void SavePluginCaches()
{
foreach (var value in _pluginBinaryStorages.Values)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index a5fbc6c70..561044981 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -77,10 +77,6 @@ namespace Flow.Launcher.Plugin.Program
private static readonly string WindowsAppPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WindowsApps");
- static Main()
- {
- }
-
public async Task> QueryAsync(Query query, CancellationToken token)
{
var result = await cache.GetOrCreateAsync(query.Search, async entry =>
@@ -101,15 +97,15 @@ namespace Flow.Launcher.Plugin.Program
.ToArray() : null;
return _win32s.Cast()
- .Concat(_uwps)
- .AsParallel()
- .WithCancellation(token)
- .Where(HideUninstallersFilter)
- .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories))
- .Where(p => p.Enabled)
- .Select(p => p.Result(query.Search, Context.API))
- .Where(r => r?.Score > 0)
- .ToList();
+ .Concat(_uwps)
+ .AsParallel()
+ .WithCancellation(token)
+ .Where(HideUninstallersFilter)
+ .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories))
+ .Where(p => p.Enabled)
+ .Select(p => p.Result(query.Search, Context.API))
+ .Where(r => r?.Score > 0)
+ .ToList();
}
catch (OperationCanceledException)
{
@@ -193,7 +189,6 @@ namespace Flow.Launcher.Plugin.Program
await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () =>
{
var pluginCachePath = Context.CurrentPluginMetadata.PluginCacheDirectoryPath;
-
FilesFolders.ValidateDirectory(pluginCachePath);
static void MoveFile(string sourcePath, string destinationPath)
@@ -294,10 +289,10 @@ namespace Flow.Launcher.Plugin.Program
{
_win32s.Add(win32);
}
- _win32sLock.Release();
ResetCache();
await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
_settings.LastIndexTime = DateTime.Now;
+ _win32sLock.Release();
}
public static async Task IndexUwpProgramsAsync()
@@ -309,10 +304,10 @@ namespace Flow.Launcher.Plugin.Program
{
_uwps.Add(uwp);
}
- _uwpsLock.Release();
ResetCache();
await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
_settings.LastIndexTime = DateTime.Now;
+ _uwpsLock.Release();
}
public static async Task IndexProgramsAsync()
@@ -405,7 +400,6 @@ namespace Flow.Launcher.Plugin.Program
}
else
{
- // Release the lock if we cannot find the program
_uwpsLock.Release();
}
@@ -425,7 +419,6 @@ namespace Flow.Launcher.Plugin.Program
}
else
{
- // Release the lock if we cannot find the program
_win32sLock.Release();
}
}
From 54e7652084245900e06c4513a1c6926ae13cf3b3 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 17:22:32 +0800
Subject: [PATCH 38/46] Fix see cref issue
---
Flow.Launcher.Core/Storage/IRemovable.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Flow.Launcher.Core/Storage/IRemovable.cs b/Flow.Launcher.Core/Storage/IRemovable.cs
index fc34395e0..bcf1cdd5e 100644
--- a/Flow.Launcher.Core/Storage/IRemovable.cs
+++ b/Flow.Launcher.Core/Storage/IRemovable.cs
@@ -1,18 +1,18 @@
namespace Flow.Launcher.Core.Storage;
///
-/// Remove storage instances from instance
+/// Remove storage instances from instance
///
public interface IRemovable
{
///
- /// Remove all instances of one plugin
+ /// Remove all instances of one plugin
///
///
public void RemovePluginSettings(string assemblyName);
///
- /// Remove all instances of one plugin
+ /// Remove all instances of one plugin
///
///
public void RemovePluginCaches(string cacheDirectory);
From 68268026de3261ea5eb7a28ff09f943adc816d0c Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 19:21:03 +0800
Subject: [PATCH 39/46] Improve performance
---
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index 561044981..c235fb587 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -186,6 +186,8 @@ namespace Flow.Launcher.Plugin.Program
_settings = context.API.LoadSettingJsonStorage();
+ var _win32sCount = 0;
+ var _uwpsCount = 0;
await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () =>
{
var pluginCachePath = Context.CurrentPluginMetadata.PluginCacheDirectoryPath;
@@ -243,19 +245,18 @@ namespace Flow.Launcher.Plugin.Program
await _win32sLock.WaitAsync();
_win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List());
+ _win32sCount = _win32s.Count;
_win32sLock.Release();
await _uwpsLock.WaitAsync();
_uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List());
+ _uwpsCount = _uwps.Count;
_uwpsLock.Release();
});
- await _win32sLock.WaitAsync();
- await _uwpsLock.WaitAsync();
+ Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32sCount}>");
+ Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwpsCount}>");
- Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Count}>");
- Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Count}>");
-
- bool cacheEmpty = !_win32s.Any() || !_uwps.Any();
+ var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0;
_win32sLock.Release();
_uwpsLock.Release();
From 4c4a6c0e22f65a7c1fd0865c70ad69b86e8a0aea Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 19:27:53 +0800
Subject: [PATCH 40/46] Add log handler for indexing
---
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 52 ++++++++++++++------
1 file changed, 36 insertions(+), 16 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index c235fb587..11deb710d 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -283,32 +283,52 @@ namespace Flow.Launcher.Plugin.Program
public static async Task IndexWin32ProgramsAsync()
{
- var win32S = Win32.All(_settings);
await _win32sLock.WaitAsync();
- _win32s.Clear();
- foreach (var win32 in win32S)
+ try
{
- _win32s.Add(win32);
+ var win32S = Win32.All(_settings);
+ _win32s.Clear();
+ foreach (var win32 in win32S)
+ {
+ _win32s.Add(win32);
+ }
+ ResetCache();
+ await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
+ _settings.LastIndexTime = DateTime.Now;
+ }
+ catch (Exception e)
+ {
+ Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Win32 programs", e);
+ }
+ finally
+ {
+ _win32sLock.Release();
}
- ResetCache();
- await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
- _settings.LastIndexTime = DateTime.Now;
- _win32sLock.Release();
}
public static async Task IndexUwpProgramsAsync()
{
- var uwps = UWPPackage.All(_settings);
await _uwpsLock.WaitAsync();
- _uwps.Clear();
- foreach (var uwp in uwps)
+ try
{
- _uwps.Add(uwp);
+ var uwps = UWPPackage.All(_settings);
+ _uwps.Clear();
+ foreach (var uwp in uwps)
+ {
+ _uwps.Add(uwp);
+ }
+ ResetCache();
+ await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
+ _settings.LastIndexTime = DateTime.Now;
+ }
+ catch (Exception e)
+ {
+ Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Uwp programs", e);
+ }
+ finally
+ {
+ _uwpsLock.Release();
}
- ResetCache();
- await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
- _settings.LastIndexTime = DateTime.Now;
- _uwpsLock.Release();
}
public static async Task IndexProgramsAsync()
From aaadf167777a9374f07a523a11b3c102c403ee5b Mon Sep 17 00:00:00 2001
From: Jack Ye <1160210343@qq.com>
Date: Tue, 8 Apr 2025 19:28:29 +0800
Subject: [PATCH 41/46] Fix typos
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
index 2f8672e13..85c48f8a4 100644
--- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
@@ -366,7 +366,7 @@ namespace Flow.Launcher.Plugin
/// Default data to return
///
///
- /// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable
+ /// BinaryStorage utilizes MemoryPack, which means the object must be MemoryPackSerializable
///
Task LoadCacheBinaryStorageAsync(string cacheName, string cacheDirectory, T defaultData) where T : new();
From 4749ca208abe9dbcfeb4f80470e2e6e489300e12 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 19:33:48 +0800
Subject: [PATCH 42/46] Improve code comments
---
Flow.Launcher.Plugin/Interfaces/ISavable.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/Flow.Launcher.Plugin/Interfaces/ISavable.cs b/Flow.Launcher.Plugin/Interfaces/ISavable.cs
index 0d23c0fc8..38cbf8e08 100644
--- a/Flow.Launcher.Plugin/Interfaces/ISavable.cs
+++ b/Flow.Launcher.Plugin/Interfaces/ISavable.cs
@@ -1,8 +1,7 @@
namespace Flow.Launcher.Plugin
{
///
- /// Inherit this interface if additional data.
- /// If you need to save data which is not a setting or cache,
+ /// Inherit this interface if you need to save additional data which is not a setting or cache,
/// please implement this interface.
///
///
From 2ff09cf9b0acb61e3323c80481e6eac5e2873891 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 19:41:02 +0800
Subject: [PATCH 43/46] Improve code quality
---
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index 11deb710d..107673f89 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -413,10 +413,7 @@ namespace Flow.Launcher.Plugin.Program
_uwpsLock.Release();
// Reindex UWP programs
- _ = Task.Run(() =>
- {
- _ = IndexUwpProgramsAsync();
- });
+ _ = Task.Run(IndexUwpProgramsAsync);
return;
}
else
@@ -433,10 +430,8 @@ namespace Flow.Launcher.Plugin.Program
_win32sLock.Release();
// Reindex Win32 programs
- _ = Task.Run(() =>
- {
- _ = IndexWin32ProgramsAsync();
- });
+ _ = Task.Run(IndexWin32ProgramsAsync);
+ return;
}
else
{
From 653b8335700290f175b7f9bce369a849d0d48f81 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 19:42:59 +0800
Subject: [PATCH 44/46] Fix typos
---
Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs | 2 +-
Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
index b5de3b50f..43bb8dade 100644
--- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs
@@ -15,7 +15,7 @@ namespace Flow.Launcher.Infrastructure.Storage
/// Normally, it has better performance, but not readable
///
///
- /// It utilize MemoryPack, which means the object must be MemoryPackSerializable
+ /// It utilizes MemoryPack, which means the object must be MemoryPackSerializable
///
public class BinaryStorage : ISavable
{
diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
index 85c48f8a4..a3020b607 100644
--- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
+++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs
@@ -380,7 +380,7 @@ namespace Flow.Launcher.Plugin
/// Cache directory from plugin metadata
///
///
- /// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable
+ /// BinaryStorage utilizes MemoryPack, which means the object must be MemoryPackSerializable
///
Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new();
From d7ca36e60a39892295fe2c42c9e2f81e56b59a66 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 19:44:30 +0800
Subject: [PATCH 45/46] Change variable name
---
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index 107673f89..745b042e6 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -190,8 +190,8 @@ namespace Flow.Launcher.Plugin.Program
var _uwpsCount = 0;
await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () =>
{
- var pluginCachePath = Context.CurrentPluginMetadata.PluginCacheDirectoryPath;
- FilesFolders.ValidateDirectory(pluginCachePath);
+ var pluginCacheDirectory = Context.CurrentPluginMetadata.PluginCacheDirectoryPath;
+ FilesFolders.ValidateDirectory(pluginCacheDirectory);
static void MoveFile(string sourcePath, string destinationPath)
{
@@ -237,19 +237,19 @@ namespace Flow.Launcher.Plugin.Program
// Move old cache files to the new cache directory
var oldWin32CacheFile = Path.Combine(DataLocation.CacheDirectory, $"{Win32CacheName}.cache");
- var newWin32CacheFile = Path.Combine(pluginCachePath, $"{Win32CacheName}.cache");
+ var newWin32CacheFile = Path.Combine(pluginCacheDirectory, $"{Win32CacheName}.cache");
MoveFile(oldWin32CacheFile, newWin32CacheFile);
var oldUWPCacheFile = Path.Combine(DataLocation.CacheDirectory, $"{UwpCacheName}.cache");
- var newUWPCacheFile = Path.Combine(pluginCachePath, $"{UwpCacheName}.cache");
+ var newUWPCacheFile = Path.Combine(pluginCacheDirectory, $"{UwpCacheName}.cache");
MoveFile(oldUWPCacheFile, newUWPCacheFile);
await _win32sLock.WaitAsync();
- _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List());
+ _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCacheDirectory, new List());
_win32sCount = _win32s.Count;
_win32sLock.Release();
await _uwpsLock.WaitAsync();
- _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List());
+ _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCacheDirectory, new List());
_uwpsCount = _uwps.Count;
_uwpsLock.Release();
});
From 482e37316a1fee76b924e3b151a4507a42ad2cb7 Mon Sep 17 00:00:00 2001
From: Jack251970 <1160210343@qq.com>
Date: Tue, 8 Apr 2025 19:46:40 +0800
Subject: [PATCH 46/46] Remove useless releases
---
Plugins/Flow.Launcher.Plugin.Program/Main.cs | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
index 745b042e6..a50868b69 100644
--- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs
+++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs
@@ -258,9 +258,6 @@ namespace Flow.Launcher.Plugin.Program
var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0;
- _win32sLock.Release();
- _uwpsLock.Release();
-
if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now)
{
_ = Task.Run(async () =>