diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs index 20aacb344..db9ccc28a 100644 --- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs @@ -50,6 +50,22 @@ namespace Flow.Launcher.Infrastructure.Storage return File.Exists(FilePath); } + public void Delete() + { + if (File.Exists(FilePath)) + { + File.Delete(FilePath); + } + if (File.Exists(BackupFilePath)) + { + File.Delete(BackupFilePath); + } + if (File.Exists(TempFilePath)) + { + File.Delete(TempFilePath); + } + } + public async Task LoadAsync() { if (Data != null) diff --git a/Flow.Launcher/Storage/TopMostRecord.cs b/Flow.Launcher/Storage/TopMostRecord.cs index 25774a2c0..f7459dc40 100644 --- a/Flow.Launcher/Storage/TopMostRecord.cs +++ b/Flow.Launcher/Storage/TopMostRecord.cs @@ -1,35 +1,64 @@ -using System.Collections.Concurrent; +using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Text.Json.Serialization; using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Plugin; namespace Flow.Launcher.Storage { - public class FlowLauncherJsonStorageTopMostRecord : ISavable + public class FlowLauncherJsonStorageTopMostRecord { private readonly FlowLauncherJsonStorage _topMostRecordStorage; private readonly MultipleTopMostRecord _topMostRecord; public FlowLauncherJsonStorageTopMostRecord() { + // Get old data & new data var topMostRecordStorage = new FlowLauncherJsonStorage(); - var exist = topMostRecordStorage.Exists(); - if (exist) - { - // Get old data - var topMostRecord = topMostRecordStorage.Load(); + _topMostRecordStorage = new FlowLauncherJsonStorage(); - // Convert to new data - _topMostRecordStorage = new FlowLauncherJsonStorage(); + // Check if data exist + var oldDataExist = topMostRecordStorage.Exists(); + var newDataExist = _topMostRecordStorage.Exists(); + + // If new data exist, it means we have already migrated the old data + // So we can safely delete the old data and load the new data + if (newDataExist) + { + try + { + topMostRecordStorage.Delete(); + } + catch + { + // Ignored + } _topMostRecord = _topMostRecordStorage.Load(); - _topMostRecord.Add(topMostRecord); } + // If new data does not exist and old data exist, we need to migrate the old data to the new data + else if (oldDataExist) + { + // Migrate old data to new data + _topMostRecord = _topMostRecordStorage.Load(); + _topMostRecord.Add(topMostRecordStorage.Load()); + + // Delete old data and save the new data + try + { + topMostRecordStorage.Delete(); + } + catch + { + // Ignored + } + Save(); + } + // If both data do not exist, we just need to create a new data else { - // Get new data - _topMostRecordStorage = new FlowLauncherJsonStorage(); _topMostRecord = _topMostRecordStorage.Load(); } } @@ -109,6 +138,7 @@ namespace Flow.Launcher.Storage public class MultipleTopMostRecord { [JsonInclude] + [JsonConverter(typeof(ConcurrentDictionaryConcurrentBagConverter))] public ConcurrentDictionary> records { get; private set; } = new(); internal void Add(TopMostRecord topMostRecord) @@ -207,6 +237,30 @@ namespace Flow.Launcher.Storage } } + public class ConcurrentDictionaryConcurrentBagConverter : JsonConverter>> + { + public override ConcurrentDictionary> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var dictionary = JsonSerializer.Deserialize>>(ref reader, options); + var concurrentDictionary = new ConcurrentDictionary>(); + foreach (var kvp in dictionary) + { + concurrentDictionary.TryAdd(kvp.Key, new ConcurrentBag(kvp.Value)); + } + return concurrentDictionary; + } + + public override void Write(Utf8JsonWriter writer, ConcurrentDictionary> value, JsonSerializerOptions options) + { + var dict = new Dictionary>(); + foreach (var kvp in value) + { + dict.Add(kvp.Key, kvp.Value.ToList()); + } + JsonSerializer.Serialize(writer, dict, options); + } + } + public class Record { public string Title { get; init; }