diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 2e331fea765..0df5228ba4a 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -62,6 +62,8 @@ TobiasSekan Img img resx +bak +tmp directx mvvm dlg @@ -85,4 +87,4 @@ searchplugin Noresult wpftk mkv -flac \ No newline at end of file +flac diff --git a/Flow.Launcher.Infrastructure/Helper.cs b/Flow.Launcher.Infrastructure/Helper.cs index faa4c93b513..db575de9004 100644 --- a/Flow.Launcher.Infrastructure/Helper.cs +++ b/Flow.Launcher.Infrastructure/Helper.cs @@ -1,4 +1,6 @@ -using System; +#nullable enable + +using System; using System.IO; using System.Runtime.CompilerServices; using System.Text.Json; @@ -16,7 +18,7 @@ static Helper() /// /// http://www.yinwang.org/blog-cn/2015/11/21/programming-philosophy /// - public static T NonNull(this T obj) + public static T NonNull(this T? obj) { if (obj == null) { diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs index 0083ccb87b0..500b0829ee2 100644 --- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using System.Globalization; using System.IO; using System.Text.Json; @@ -11,62 +12,73 @@ namespace Flow.Launcher.Infrastructure.Storage /// public class JsonStorage where T : new() { - protected T _data; + protected T? Data; // need a new directory name public const string DirectoryName = "Settings"; public const string FileSuffix = ".json"; - public string FilePath { get; set; } - public string DirectoryPath { get; set; } + protected string FilePath { get; init; } = null!; + private string TempFilePath => $"{FilePath}.tmp"; + private string BackupFilePath => $"{FilePath}.bak"; + protected string DirectoryPath { get; init; } = null!; public T Load() { + string? serialized = null; + if (File.Exists(FilePath)) { - var serialized = File.ReadAllText(FilePath); - if (!string.IsNullOrWhiteSpace(serialized)) + serialized = File.ReadAllText(FilePath); + } + + if (!string.IsNullOrEmpty(serialized)) + { + try { - Deserialize(serialized); + Data = JsonSerializer.Deserialize(serialized)?? TryLoadBackup() ?? LoadDefault(); } - else + catch (JsonException) { - LoadDefault(); + Data = TryLoadBackup() ?? LoadDefault(); } } else { - LoadDefault(); + Data = TryLoadBackup() ?? LoadDefault(); } - return _data.NonNull(); + return Data.NonNull(); } - private void Deserialize(string serialized) + private T LoadDefault() { - try - { - _data = JsonSerializer.Deserialize(serialized); - } - catch (JsonException e) + if (File.Exists(FilePath)) { - LoadDefault(); - Log.Exception($"|JsonStorage.Deserialize|Deserialize error for json <{FilePath}>", e); + BackupOriginFile(); } - if (_data == null) - { - LoadDefault(); - } + return new T(); } - private void LoadDefault() + private T? TryLoadBackup() { - if (File.Exists(FilePath)) + if (!File.Exists(BackupFilePath)) + return default; + + try { - BackupOriginFile(); + var data = JsonSerializer.Deserialize(File.ReadAllText(BackupFilePath)); + if (data != null) + { + Log.Info($"|JsonStorage.Load|Failed to load settings.json, {BackupFilePath} restored successfully"); + File.Replace(BackupFilePath, FilePath, null); + return data; + } + return default; + } + catch (JsonException) + { + return default; } - - _data = new T(); - Save(); } private void BackupOriginFile() @@ -82,13 +94,14 @@ private void BackupOriginFile() public void Save() { - string serialized = JsonSerializer.Serialize(_data, new JsonSerializerOptions() { WriteIndented = true }); + string serialized = JsonSerializer.Serialize(Data, new JsonSerializerOptions + { + WriteIndented = true + }); - File.WriteAllText(FilePath, serialized); + File.WriteAllText(TempFilePath, serialized); + File.Replace(TempFilePath, FilePath, BackupFilePath); + File.Delete(TempFilePath); } } - - [Obsolete("Deprecated as of Flow Launcher v1.8.0, on 2021.06.21. " + - "This is used only for Everything plugin v1.4.9 or below backwards compatibility")] - public class JsonStrorage : JsonStorage where T : new() { } } diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs index 923a1a6b56f..abe3f55b5ad 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs @@ -18,7 +18,7 @@ public PluginJsonStorage() public PluginJsonStorage(T data) : this() { - _data = data; + Data = data; } } }