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; - } } }