Support multiple topmost records

This commit is contained in:
Jack251970 2025-05-01 11:41:53 +08:00
parent 980b792cb3
commit 0d61908575
2 changed files with 132 additions and 10 deletions

View file

@ -45,6 +45,11 @@ namespace Flow.Launcher.Infrastructure.Storage
FilesFolders.ValidateDirectory(DirectoryPath);
}
public bool Exists()
{
return File.Exists(FilePath);
}
public async Task<T> LoadAsync()
{
if (Data != null)

View file

@ -1,5 +1,6 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using Flow.Launcher.Infrastructure.Storage;
using Flow.Launcher.Plugin;
@ -8,14 +9,29 @@ namespace Flow.Launcher.Storage
{
public class FlowLauncherJsonStorageTopMostRecord : ISavable
{
private readonly FlowLauncherJsonStorage<TopMostRecord> _topMostRecordStorage;
private readonly TopMostRecord _topMostRecord;
private readonly FlowLauncherJsonStorage<MultipleTopMostRecord> _topMostRecordStorage;
private readonly MultipleTopMostRecord _topMostRecord;
public FlowLauncherJsonStorageTopMostRecord()
{
_topMostRecordStorage = new FlowLauncherJsonStorage<TopMostRecord>();
_topMostRecord = _topMostRecordStorage.Load();
var topMostRecordStorage = new FlowLauncherJsonStorage<TopMostRecord>();
var exist = topMostRecordStorage.Exists();
if (exist)
{
// Get old data
var topMostRecord = topMostRecordStorage.Load();
// Convert to new data
_topMostRecordStorage = new FlowLauncherJsonStorage<MultipleTopMostRecord>();
_topMostRecord = _topMostRecordStorage.Load();
_topMostRecord.Add(topMostRecord);
}
else
{
// Get new data
_topMostRecordStorage = new FlowLauncherJsonStorage<MultipleTopMostRecord>();
_topMostRecord = _topMostRecordStorage.Load();
}
}
public void Save()
@ -42,7 +58,7 @@ namespace Flow.Launcher.Storage
public class TopMostRecord
{
[JsonInclude]
public ConcurrentDictionary<string, Record> records { get; private set; } = new ConcurrentDictionary<string, Record>();
public ConcurrentDictionary<string, Record> records { get; private set; } = new();
internal bool IsTopMost(Result result)
{
@ -90,12 +106,113 @@ namespace Flow.Launcher.Storage
}
}
public class MultipleTopMostRecord
{
[JsonInclude]
public ConcurrentDictionary<string, ConcurrentBag<Record>> records { get; private set; } = new();
internal void Add(TopMostRecord topMostRecord)
{
if (topMostRecord == null || topMostRecord.records.IsEmpty)
{
return;
}
foreach (var record in topMostRecord.records)
{
records.AddOrUpdate(record.Key, new ConcurrentBag<Record> { record.Value }, (key, oldValue) =>
{
oldValue.Add(record.Value);
return oldValue;
});
}
}
internal bool IsTopMost(Result result)
{
// origin query is null when user select the context menu item directly of one item from query list
// in this case, we do not need to check if the result is top most
if (records.IsEmpty || result.OriginQuery == null ||
!records.TryGetValue(result.OriginQuery.RawQuery, out var value))
{
return false;
}
// since this dictionary should be very small (or empty) going over it should be pretty fast.
return value.Any(record => record.Equals(result));
}
internal void Remove(Result result)
{
// origin query is null when user select the context menu item directly of one item from query list
// in this case, we do not need to remove the record
if (result.OriginQuery == null ||
!records.TryGetValue(result.OriginQuery.RawQuery, out var value))
{
return;
}
// remove the record from the bag
var recordToRemove = value.FirstOrDefault(r => r.Equals(result));
if (recordToRemove != null)
{
value.TryTake(out recordToRemove);
}
}
internal void AddOrUpdate(Result result)
{
// origin query is null when user select the context menu item directly of one item from query list
// in this case, we do not need to add or update the record
if (result.OriginQuery == null)
{
return;
}
var record = new Record
{
PluginID = result.PluginID,
Title = result.Title,
SubTitle = result.SubTitle,
RecordKey = result.RecordKey
};
if (!records.TryGetValue(result.OriginQuery.RawQuery, out var value))
{
// create a new bag if it does not exist
value = new ConcurrentBag<Record>()
{
record
};
records.TryAdd(result.OriginQuery.RawQuery, value);
}
else
{
// add or update the record in the bag
if (value.Any(r => r.Equals(result)))
{
// update the record
var recordToUpdate = value.FirstOrDefault(r => r.Equals(result));
if (recordToUpdate != null)
{
value.TryTake(out recordToUpdate);
value.Add(record);
}
}
else
{
// add the record
value.Add(record);
}
}
}
}
public class Record
{
public string Title { get; set; }
public string SubTitle { get; set; }
public string PluginID { get; set; }
public string RecordKey { get; set; }
public string Title { get; init; }
public string SubTitle { get; init; }
public string PluginID { get; init; }
public string RecordKey { get; init; }
public bool Equals(Result r)
{