From 1c7c100a42c2885ba8ef49c530c4440180896fec Mon Sep 17 00:00:00 2001 From: gokcekantarci <115616017+gokcekantarci@users.noreply.github.com> Date: Tue, 6 Feb 2024 18:33:19 +0300 Subject: [PATCH] [PTRun]Don't clear config data on upgrade (#30187) * [PTRun] Implemented a new JSON storage method for PTRun settings files. * [PTRun] Removed uncessary parts. * [PTRun] Spell checks. * [PTRun] New JsonSerializerOptions added for information files. * [PTRun] Unnecessary null check is removed. * [PT Run] - ExtractFields function removed. - Creating instance is used instead of deserializing. * [PTRun] Build fix * [PTRun] Removed unncessary parts * [PTRun] CheckWithInformationFileToClear reversed. * [PTRun] Build fix. * [PTRun] Deserialization is used instead of key by key comparison. * [PTRun] Removed unncessary parts. * [PTRun] Removed unncessary parts. * [PTRun] Remove entry if query is null or empty. --- .../PowerLauncher/Storage/QueryHistory.cs | 18 ++++ .../PowerLauncher/ViewModel/MainViewModel.cs | 18 ++++ .../ViewModel/SettingWindowViewModel.cs | 18 ++++ .../launcher/Wox.Infrastructure/Alphabet.cs | 12 +-- .../Storage/JsonStorage`1.cs | 82 ++++++++++++++----- .../Storage/PluginJsonStorage`1.cs | 25 ++++++ .../launcher/Wox.Plugin/UserSelectedRecord.cs | 29 +++++++ 7 files changed, 174 insertions(+), 28 deletions(-) diff --git a/src/modules/launcher/PowerLauncher/Storage/QueryHistory.cs b/src/modules/launcher/PowerLauncher/Storage/QueryHistory.cs index 79621dde24..61cf6c40f4 100644 --- a/src/modules/launcher/PowerLauncher/Storage/QueryHistory.cs +++ b/src/modules/launcher/PowerLauncher/Storage/QueryHistory.cs @@ -41,5 +41,23 @@ namespace PowerLauncher.Storage }); } } + + public void Update() + { + for (int i = Items.Count - 1; i >= 0; i--) + { + if (string.IsNullOrEmpty(Items[i].Query)) + { + Items.RemoveAt(i); + } + else + { + if (Items[i].ExecutedDateTime == DateTime.MinValue) + { + Items[i].ExecutedDateTime = DateTime.Now; + } + } + } + } } } diff --git a/src/modules/launcher/PowerLauncher/ViewModel/MainViewModel.cs b/src/modules/launcher/PowerLauncher/ViewModel/MainViewModel.cs index 7f7098acd8..0e81bcaa75 100644 --- a/src/modules/launcher/PowerLauncher/ViewModel/MainViewModel.cs +++ b/src/modules/launcher/PowerLauncher/ViewModel/MainViewModel.cs @@ -9,6 +9,7 @@ using System.Globalization; using System.Linq; using System.Reflection; using System.Text; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -1033,7 +1034,24 @@ namespace PowerLauncher.ViewModel { if (!_saved) { + if (_historyItemsStorage.CheckVersionMismatch()) + { + if (!_historyItemsStorage.TryLoadData()) + { + _history.Update(); + } + } + _historyItemsStorage.Save(); + + if (_userSelectedRecordStorage.CheckVersionMismatch()) + { + if (!_userSelectedRecordStorage.TryLoadData()) + { + _userSelectedRecord.Update(); + } + } + _userSelectedRecordStorage.Save(); _saved = true; diff --git a/src/modules/launcher/PowerLauncher/ViewModel/SettingWindowViewModel.cs b/src/modules/launcher/PowerLauncher/ViewModel/SettingWindowViewModel.cs index a86be57be6..97773f6b24 100644 --- a/src/modules/launcher/PowerLauncher/ViewModel/SettingWindowViewModel.cs +++ b/src/modules/launcher/PowerLauncher/ViewModel/SettingWindowViewModel.cs @@ -2,9 +2,11 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Text.Json; using Wox.Infrastructure.Storage; using Wox.Infrastructure.UserSettings; using Wox.Plugin; +using Wox.Plugin.Logger; namespace PowerLauncher.ViewModel { @@ -16,6 +18,22 @@ namespace PowerLauncher.ViewModel { _storage = new WoxJsonStorage(); Settings = _storage.Load(); + + // Check information file for version mismatch + try + { + if (_storage.CheckVersionMismatch()) + { + if (!_storage.TryLoadData()) + { + _storage.Clear(); + } + } + } + catch (JsonException e) + { + Log.Exception($"Error in Load of PowerToysRunSettings: {e.Message}", e, GetType()); + } } public PowerToysRunSettings Settings { get; } diff --git a/src/modules/launcher/Wox.Infrastructure/Alphabet.cs b/src/modules/launcher/Wox.Infrastructure/Alphabet.cs index fb81591047..7e630cdc34 100644 --- a/src/modules/launcher/Wox.Infrastructure/Alphabet.cs +++ b/src/modules/launcher/Wox.Infrastructure/Alphabet.cs @@ -24,9 +24,8 @@ public class Alphabet : IAlphabet PinyinFormat.WITHOUT_TONE; private ConcurrentDictionary _pinyinCache; - private WoxJsonStorage> _pinyinStorage; + private WoxJsonStorage> _pinyinStorage; private PowerToysRunSettings _settings; - private Dictionary __cache; public void Initialize(PowerToysRunSettings settings) { @@ -38,8 +37,8 @@ public class Alphabet : IAlphabet { Stopwatch.Normal("|Wox.Infrastructure.Alphabet.Initialize|Preload pinyin cache", () => { - _pinyinStorage = new WoxJsonStorage>("Pinyin"); - SetPinyinCacheAsDictionary(__cache = _pinyinStorage.Load()); + _pinyinStorage = new WoxJsonStorage>("Pinyin"); + _pinyinCache = _pinyinStorage.Load(); // force pinyin library static constructor initialize Pinyin4Net.GetPinyin('δΈ€', _pinyinFormat); @@ -204,9 +203,4 @@ public class Alphabet : IAlphabet { return new Dictionary(_pinyinCache); } - - private void SetPinyinCacheAsDictionary(Dictionary usage) - { - _pinyinCache = new ConcurrentDictionary(usage); - } } diff --git a/src/modules/launcher/Wox.Infrastructure/Storage/JsonStorage`1.cs b/src/modules/launcher/Wox.Infrastructure/Storage/JsonStorage`1.cs index 9181364855..b51d9a0df8 100644 --- a/src/modules/launcher/Wox.Infrastructure/Storage/JsonStorage`1.cs +++ b/src/modules/launcher/Wox.Infrastructure/Storage/JsonStorage`1.cs @@ -3,9 +3,11 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.IO.Abstractions; +using System.Linq; using System.Text.Json; using Wox.Plugin.Logger; @@ -20,6 +22,8 @@ namespace Wox.Infrastructure.Storage private static readonly IPath Path = FileSystem.Path; private static readonly IFile File = FileSystem.File; + private readonly object _saveLock = new object(); + // use property initialization instead of DefaultValueAttribute // easier and flexible for default value of object private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions @@ -28,6 +32,15 @@ namespace Wox.Infrastructure.Storage IncludeFields = true, PropertyNameCaseInsensitive = true, WriteIndented = true, + UnmappedMemberHandling = System.Text.Json.Serialization.JsonUnmappedMemberHandling.Disallow, + }; + + private static readonly JsonSerializerOptions _deserializerOptions = new JsonSerializerOptions + { + DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.Never, + IncludeFields = true, + PropertyNameCaseInsensitive = true, + WriteIndented = true, }; private T _data; @@ -44,20 +57,10 @@ namespace Wox.Infrastructure.Storage private const int _jsonStorage = 1; private StoragePowerToysVersionInfo _storageHelper; - public T Load() + public virtual T Load() { _storageHelper = new StoragePowerToysVersionInfo(FilePath, _jsonStorage); - // Depending on the version number of the previously installed PT Run, delete the cache if it is found to be incompatible - if (_storageHelper.ClearCache) - { - if (File.Exists(FilePath)) - { - File.Delete(FilePath); - Log.Info($"Deleting cached data at <{FilePath}>", GetType()); - } - } - if (File.Exists(FilePath)) { var serialized = File.ReadAllText(FilePath); @@ -82,7 +85,7 @@ namespace Wox.Infrastructure.Storage { try { - _data = JsonSerializer.Deserialize(serialized, _serializerOptions); + _data = JsonSerializer.Deserialize(serialized, _deserializerOptions); } catch (JsonException e) { @@ -121,18 +124,59 @@ namespace Wox.Infrastructure.Storage } public void Save() + { + lock (_saveLock) + { + try + { + string serialized = JsonSerializer.Serialize(_data, _serializerOptions); + File.WriteAllText(FilePath, serialized); + _storageHelper.Close(); + + Log.Info($"Saving cached data at <{FilePath}>", GetType()); + } + catch (IOException e) + { + Log.Exception($"Error in saving data at <{FilePath}>", e, GetType()); + } + } + } + + public void Clear() + { + if (File.Exists(FilePath)) + { + File.Delete(FilePath); + LoadDefault(); + Log.Info($"Deleting cached data at <{FilePath}>", GetType()); + } + } + + public bool CheckVersionMismatch() + { + // Skip the fields check if the version hasn't changed. + // This optimization prevents unnecessary fields processing when the cache + // is already up to date, enhancing performance and reducing IO operations + if (!_storageHelper.ClearCache) + { + return false; + } + + _storageHelper.ClearCache = false; + return true; + } + + public bool TryLoadData() { try { - string serialized = JsonSerializer.Serialize(_data, _serializerOptions); - File.WriteAllText(FilePath, serialized); - _storageHelper.Close(); - - Log.Info($"Saving cached data at <{FilePath}>", GetType()); + JsonSerializer.Deserialize(File.ReadAllText(FilePath), _serializerOptions); + return true; } - catch (IOException e) + catch (JsonException e) { - Log.Exception($"Error in saving data at <{FilePath}>", e, GetType()); + Log.Exception($"Error in TryLoadData at <{FilePath}>", e, GetType()); + return false; } } } diff --git a/src/modules/launcher/Wox.Infrastructure/Storage/PluginJsonStorage`1.cs b/src/modules/launcher/Wox.Infrastructure/Storage/PluginJsonStorage`1.cs index d372615408..a6cdc5bda3 100644 --- a/src/modules/launcher/Wox.Infrastructure/Storage/PluginJsonStorage`1.cs +++ b/src/modules/launcher/Wox.Infrastructure/Storage/PluginJsonStorage`1.cs @@ -3,7 +3,9 @@ // See the LICENSE file in the project root for more information. using System.IO.Abstractions; +using System.Text.Json; using Wox.Plugin; +using Wox.Plugin.Logger; namespace Wox.Infrastructure.Storage { @@ -23,5 +25,28 @@ namespace Wox.Infrastructure.Storage FilePath = Path.Combine(DirectoryPath, $"{dataType.Name}{FileSuffix}"); } + + public override T Load() + { + var data = base.Load(); + + // Check information file for version mismatch + try + { + if (CheckVersionMismatch()) + { + if (!TryLoadData()) + { + Clear(); + } + } + } + catch (JsonException e) + { + Log.Exception($"Error in Load of PluginJsonStorage: {e.Message}", e, GetType()); + } + + return data.NonNull(); + } } } diff --git a/src/modules/launcher/Wox.Plugin/UserSelectedRecord.cs b/src/modules/launcher/Wox.Plugin/UserSelectedRecord.cs index f821e8477a..4989c7a51a 100644 --- a/src/modules/launcher/Wox.Plugin/UserSelectedRecord.cs +++ b/src/modules/launcher/Wox.Plugin/UserSelectedRecord.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text.Json.Serialization; namespace Wox.Plugin @@ -73,6 +74,34 @@ namespace Wox.Plugin } } + public void Update() + { + foreach (var key in Records.Keys.ToList()) + { + // Check if any of the specified fields are empty + if (string.IsNullOrEmpty(Records[key].IconPath) || + string.IsNullOrEmpty(Records[key].Title) || + string.IsNullOrEmpty(Records[key].SubTitle) || + string.IsNullOrEmpty(Records[key].Search) || + string.IsNullOrEmpty(Records[key].PluginID)) + { + Records.Remove(key); + } + else + { + if (Records[key].SelectedCount == 0) + { + Records[key].SelectedCount = 1; + } + + if (Records[key].LastSelected == DateTime.MinValue) + { + Records[key].LastSelected = DateTime.UtcNow; + } + } + } + } + public UserSelectedRecordItem GetSelectedData(Result result) { ArgumentNullException.ThrowIfNull(result);