Add binary storage api functions

This commit is contained in:
Jack251970 2025-04-01 14:19:59 +08:00
parent 24327533c6
commit ca221d7100
5 changed files with 91 additions and 12 deletions

View file

@ -185,5 +185,10 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models
{
_api.StopLoadingBar();
}
public void SavePluginCaches()
{
_api.SavePluginCaches();
}
}
}

View file

@ -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

View file

@ -344,5 +344,38 @@ namespace Flow.Launcher.Plugin
/// Stop the loading bar in main window
/// </summary>
public void StopLoadingBar();
/// <summary>
/// Save all Flow's plugins caches
/// </summary>
void SavePluginCaches();
/// <summary>
/// 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.
/// </summary>
/// <typeparam name="T">Type for deserialization</typeparam>
/// <param name="cacheName">Cache file name</param>
/// <param name="cacheDirectory">Cache directory from plugin metadata</param>
/// <param name="defaultData">Default data to return</param>
/// <returns></returns>
/// <remarks>
/// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable <see href="https://github.com/Cysharp/MemoryPack"/>
/// </remarks>
Task<T> LoadCacheBinaryStorageAsync<T>(string cacheName, string cacheDirectory, T defaultData) where T : new();
/// <summary>
/// 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.
/// </summary>
/// <typeparam name="T">Type for Serialization</typeparam>
/// <param name="cacheName">Cache file name</param>
/// <param name="cacheDirectory">Cache directory from plugin metadata</param>
/// <returns></returns>
/// <remarks>
/// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable <see href="https://github.com/Cysharp/MemoryPack"/>
/// </remarks>
Task SaveCacheBinaryStorageAsync<T>(string cacheName, string cacheDirectory) where T : new();
}
}

View file

@ -1,11 +1,12 @@
namespace Flow.Launcher.Plugin
namespace Flow.Launcher.Plugin
{
/// <summary>
/// Inherit this interface if additional data e.g. cache needs to be saved.
/// </summary>
/// <remarks>
/// For storing plugin settings, prefer <see cref="IPublicAPI.LoadSettingJsonStorage{T}"/>
/// or <see cref="IPublicAPI.SaveSettingJsonStorage{T}"/>.
/// or <see cref="IPublicAPI.SaveSettingJsonStorage{T}"/>.
/// or <see cref="IPublicAPI.SaveCacheBinaryStorageAsync{T}(string, string)"/>.
/// Once called, your settings will be automatically saved by Flow.
/// </remarks>
public interface ISavable : IFeatures
@ -15,4 +16,4 @@ namespace Flow.Launcher.Plugin
/// </summary>
void Save();
}
}
}

View file

@ -236,14 +236,6 @@ namespace Flow.Launcher
((PluginJsonStorage<T>)_pluginJsonStorages[type]).Save();
}
public void SaveJsonStorage<T>(T settings) where T : new()
{
var type = typeof(T);
_pluginJsonStorages[type] = new PluginJsonStorage<T>(settings);
((PluginJsonStorage<T>)_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<Action<double>, 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 _);
}
}
}
/// <summary>
/// Save plugin caches.
/// </summary>
public void SavePluginCaches()
{
foreach (var value in _pluginBinaryStorages.Values)
{
var method = value.GetType().GetMethod("Save");
method?.Invoke(value, null);
}
}
public async Task<T> LoadCacheBinaryStorageAsync<T>(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<T>(cacheName, cacheDirectory);
return await ((PluginBinaryStorage<T>)_pluginBinaryStorages[(cacheName, cacheDirectory, type)]).TryLoadAsync(defaultData);
}
public async Task SaveCacheBinaryStorageAsync<T>(string cacheName, string cacheDirectory) where T : new()
{
var type = typeof(T);
if (!_pluginBinaryStorages.ContainsKey((cacheName, cacheDirectory, type)))
_pluginBinaryStorages[(cacheName, cacheDirectory, type)] = new PluginBinaryStorage<T>(cacheName, cacheDirectory);
await ((PluginBinaryStorage<T>)_pluginBinaryStorages[(cacheName, cacheDirectory, type)]).SaveAsync();
}
#endregion
#region Private Methods