diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
index c7eba05fd5c..37fc57cb060 100644
--- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
+++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Globalization;
using System.IO;
using System.Text.Json;
@@ -37,6 +37,11 @@ protected JsonStorage()
{
}
+ ///
+ /// Initializes a new instance of the JsonStorage<T> class for the specified file path.
+ ///
+ /// The full path to the JSON file used for storage.
+ /// Thrown if the provided file path does not contain a valid directory.
public JsonStorage(string filePath)
{
FilePath = filePath;
@@ -45,11 +50,18 @@ public JsonStorage(string filePath)
FilesFolders.ValidateDirectory(DirectoryPath);
}
+ ///
+ /// Determines whether the main JSON storage file exists on disk.
+ ///
+ /// True if the storage file exists; otherwise, false.
public bool Exists()
{
return File.Exists(FilePath);
}
+ ///
+ /// Deletes the main JSON storage file, its backup, and temporary file if they exist.
+ ///
public void Delete()
{
foreach (var path in new[] { FilePath, BackupFilePath, TempFilePath })
@@ -61,6 +73,10 @@ public void Delete()
}
}
+ ///
+ /// Asynchronously loads and deserializes the JSON file into Data, falling back to a backup or a default instance if necessary.
+ ///
+ /// The loaded or newly created instance of .
public async Task LoadAsync()
{
if (Data != null)
diff --git a/Flow.Launcher/Storage/TopMostRecord.cs b/Flow.Launcher/Storage/TopMostRecord.cs
index 7c45bcf66f3..c3cf146e865 100644
--- a/Flow.Launcher/Storage/TopMostRecord.cs
+++ b/Flow.Launcher/Storage/TopMostRecord.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
@@ -14,6 +14,12 @@ public class FlowLauncherJsonStorageTopMostRecord
private readonly FlowLauncherJsonStorage _topMostRecordStorage;
private readonly MultipleTopMostRecord _topMostRecord;
+ ///
+ /// Initializes the top most records storage, handling migration from the old single-record-per-query format to the new multiple-records-per-query format if necessary.
+ ///
+ ///
+ /// If new-format data exists, it loads it and deletes any old-format data. If only old-format data exists, it migrates the data to the new format, deletes the old data, and saves the new structure. If neither exists, it initializes an empty new-format storage.
+ ///
public FlowLauncherJsonStorageTopMostRecord()
{
// Get old data & new data
@@ -63,21 +69,35 @@ public FlowLauncherJsonStorageTopMostRecord()
}
}
+ ///
+ /// Persists the current top most records to storage.
+ ///
public void Save()
{
_topMostRecordStorage.Save();
}
+ ///
+ /// Determines whether the specified result is marked as top most in the current records.
+ ///
+ /// The result to check.
+ /// True if the result is marked as top most; otherwise, false.
public bool IsTopMost(Result result)
{
return _topMostRecord.IsTopMost(result);
}
+ ///
+ /// Removes the specified result from the top most records if it exists.
+ ///
public void Remove(Result result)
{
_topMostRecord.Remove(result);
}
+ ///
+ /// Adds a result to the top most records or updates it if it already exists.
+ ///
public void AddOrUpdate(Result result)
{
_topMostRecord.AddOrUpdate(result);
@@ -92,6 +112,11 @@ internal class TopMostRecord
[JsonInclude]
public ConcurrentDictionary records { get; private set; } = new();
+ ///
+ /// Determines whether the specified result is the top most record for its originating query.
+ ///
+ /// The result to check.
+ /// True if the result matches the stored top most record for its query; otherwise, false.
internal bool IsTopMost(Result result)
{
// origin query is null when user select the context menu item directly of one item from query list
@@ -118,6 +143,10 @@ internal void Remove(Result result)
records.Remove(result.OriginQuery.RawQuery, out _);
}
+ ///
+ /// Adds or updates the top most record for the specified result's query, replacing any existing record for that query.
+ ///
+ /// The result whose information is to be stored as the top most record for its originating query. If OriginQuery is null, no action is taken.
internal void AddOrUpdate(Result result)
{
// origin query is null when user select the context menu item directly of one item from query list
@@ -147,6 +176,10 @@ internal class MultipleTopMostRecord
[JsonConverter(typeof(ConcurrentDictionaryConcurrentBagConverter))]
public ConcurrentDictionary> records { get; private set; } = new();
+ ///
+ /// Migrates all records from an existing into this multiple-records-per-query structure.
+ ///
+ /// The old single-record-per-query data structure to migrate from.
internal void Add(TopMostRecord topMostRecord)
{
if (topMostRecord == null || topMostRecord.records.IsEmpty)
@@ -164,6 +197,11 @@ internal void Add(TopMostRecord topMostRecord)
}
}
+ ///
+ /// Determines whether the specified result is marked as top most for its originating query.
+ ///
+ /// The result to check.
+ /// True if the result is a top most record for its query; otherwise, false.
internal bool IsTopMost(Result result)
{
// origin query is null when user select the context menu item directly of one item from query list
@@ -178,6 +216,10 @@ internal bool IsTopMost(Result result)
return value.Any(record => record.Equals(result));
}
+ ///
+ /// Removes a matching record for the given result from the collection of top most records for its query.
+ ///
+ /// The result whose corresponding record should be removed.
internal void Remove(Result result)
{
// origin query is null when user select the context menu item directly of one item from query list
@@ -202,6 +244,10 @@ internal void Remove(Result result)
}
}
+ ///
+ /// Adds a result as a top most record for its originating query, or updates the existing record if it already exists.
+ ///
+ /// The result to add or update as top most for its query. Ignored if the result's OriginQuery is null.
internal void AddOrUpdate(Result result)
{
// origin query is null when user select the context menu item directly of one item from query list
@@ -254,6 +300,13 @@ internal void AddOrUpdate(Result result)
///
internal class ConcurrentDictionaryConcurrentBagConverter : JsonConverter>>
{
+ ///
+ /// Deserializes JSON into a mapping strings to of .
+ ///
+ /// The JSON reader positioned at the start of the object.
+ /// The type to convert (ignored).
+ /// Serialization options to use during deserialization.
+ /// A concurrent dictionary where each key maps to a concurrent bag of records.
public override ConcurrentDictionary> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var dictionary = JsonSerializer.Deserialize>>(ref reader, options);
@@ -265,6 +318,12 @@ public override ConcurrentDictionary> Read(ref Utf
return concurrentDictionary;
}
+ ///
+ /// Serializes a of records to JSON by converting each bag to a list.
+ ///
+ /// The JSON writer to which the data will be serialized.
+ /// The concurrent dictionary containing bags of records to serialize.
+ /// Serialization options to use.
public override void Write(Utf8JsonWriter writer, ConcurrentDictionary> value, JsonSerializerOptions options)
{
var dict = new Dictionary>();
@@ -283,6 +342,11 @@ internal class Record
public string PluginID { get; init; }
public string RecordKey { get; init; }
+ ///
+ /// Determines whether the current record is equal to the specified result based on key or identifying properties.
+ ///
+ /// The result to compare with this record.
+ /// True if the records are considered equal; otherwise, false.
public bool Equals(Result r)
{
if (string.IsNullOrEmpty(RecordKey) || string.IsNullOrEmpty(r.RecordKey))
diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs
index 54ad6c288cd..028742fff4c 100644
--- a/Flow.Launcher/ViewModel/MainViewModel.cs
+++ b/Flow.Launcher/ViewModel/MainViewModel.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
@@ -54,6 +54,9 @@ public partial class MainViewModel : BaseModel, ISavable, IDisposable
#region Constructor
+ ///
+ /// Initializes a new instance of the MainViewModel class, setting up application state, loading persistent data, configuring results view models, and registering property change handlers and background update tasks.
+ ///
public MainViewModel()
{
_queryTextBeforeLeaveResults = "";
@@ -1605,6 +1608,8 @@ public async void Hide()
///
/// Save history, user selected records and top most records
+ ///
+ /// Persists the current history, user-selected records, and top-most records to storage.
///
public void Save()
{