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