From 6b6a9a9935aee30ad7c2d34b8dde0ed11903bf09 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 1 Jan 2026 14:30:28 +1100 Subject: [PATCH] simplify GetHistoryItems --- Flow.Launcher.Plugin/Result.cs | 27 +--- .../Storage/LastOpenedHistoryResult.cs | 86 +++++-------- Flow.Launcher/Storage/QueryHistory.cs | 9 +- Flow.Launcher/ViewModel/MainViewModel.cs | 116 +++--------------- 4 files changed, 57 insertions(+), 181 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 2ad19effe..f1dd53b22 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Security.Policy; using System.Threading.Tasks; using System.Windows.Controls; using System.Windows.Media; @@ -10,7 +9,8 @@ using System.Text.Json.Serialization; namespace Flow.Launcher.Plugin { /// - /// Describes a result of a executed by a plugin + /// Describes a result of a executed by a plugin. + /// This or its child classses is serializable. /// public class Result { @@ -104,29 +104,6 @@ namespace Flow.Launcher.Plugin /// public string IcoAbsoluteFullPath => _icoAbsoluteFullPath; - /// - /// Returns IcoPath's relative path based on the plugin directory or original value if not file path. - /// This property is useful for storage where it needs to be resistant to changes in plugin location from update - /// or portable mode change. - /// - public string IcoPathRelative - { - get - { - if (string.IsNullOrEmpty(IcoAbsoluteFullPath) - || string.IsNullOrEmpty(PluginDirectory) - || !Path.IsPathRooted(IcoAbsoluteFullPath) - || IcoAbsoluteFullPath.StartsWith("http://", StringComparison.OrdinalIgnoreCase) - || IcoAbsoluteFullPath.StartsWith("https://", StringComparison.OrdinalIgnoreCase) - || IcoAbsoluteFullPath.StartsWith("data:image", StringComparison.OrdinalIgnoreCase)) - { - return IcoAbsoluteFullPath; - } - - return Path.GetRelativePath(PluginDirectory, IcoAbsoluteFullPath); - } - } - /// /// The image to be displayed for the badge of the result. /// diff --git a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs index 98fdc1a74..4eb76da1c 100644 --- a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs +++ b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs @@ -13,6 +13,7 @@ public class LastOpenedHistoryResult : Result public LastOpenedHistoryResult() { + this.OriginQuery = new Query { RawQuery = Query }; } public LastOpenedHistoryResult(Result result) @@ -21,71 +22,42 @@ public class LastOpenedHistoryResult : Result SubTitle = result.SubTitle; PluginID = result.PluginID; Query = result.OriginQuery.RawQuery; + OriginQuery = result.OriginQuery; RecordKey = result.RecordKey; IcoPath = result.IcoPath; PluginDirectory = result.PluginDirectory; Glyph = result.Glyph; ExecutedDateTime = DateTime.Now; + // Used for Query History style reopening + Action = _ => + { + App.API.BackToQueryResults(); + App.API.ChangeQuery(result.OriginQuery.RawQuery); + return false; + }; + //Used for last history style reopening, currently need to be assigned at MainViewModel.cs + AsyncAction = null; } - //public Result ToResult(bool isQueryHistoryStyle) - //{ - // Result result = null; + public LastOpenedHistoryResult Copy() + { - // if (isQueryHistoryStyle) - // { - // result = new Result - // { - // Action = _ => - // { - // App.API.BackToQueryResults(); - // App.API.ChangeQuery(Query); - // return false; - // }, - // Glyph = Glyph, - // }; - // } - // else - // { - // result = new Result - // { - // AsyncAction = async c => - // { - // var reflectResult = await ResultHelper.PopulateResultsAsync(item); - // if (reflectResult != null) - // { - // // Record the user selected record for result ranking - // _userSelectedRecord.Add(reflectResult); - - // // Since some actions may need to hide the Flow window to execute - // // So let us populate the results of them - // return await reflectResult.ExecuteAsync(c); - // } - - // // If we cannot get the result, fallback to re-query - // App.API.BackToQueryResults(); - // App.API.ChangeQuery(item.Query); - // return false; - // }, - // Glyph = Glyph, - // }; - // } - - // var result = new Result - // { - // Title = Title, - // SubTitle = Localize.lastExecuteTime(ExecutedDateTime), - // IcoPath = IcoPath, - // OriginQuery = new Query { RawQuery = Query }, - // Action = _ => - // { - // App.API.BackToQueryResults(); - // App.API.ChangeQuery(Query); - // return false; - // }, - // Glyph = Glyph, - // }; - //} + return new LastOpenedHistoryResult + { + Title = this.Title, + SubTitle = this.SubTitle, + PluginID = this.PluginID, + Query = this.Query, + OriginQuery = this.OriginQuery, + RecordKey = this.RecordKey, + IcoPath = this.IcoPath, + PluginDirectory = this.PluginDirectory, + Action = this.Action, + AsyncAction = this.AsyncAction, + Glyph = this.Glyph, + ExecutedDateTime = this.ExecutedDateTime + }; + } public bool Equals(Result r) { diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index c95a9308b..cbde3e9aa 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -1,13 +1,10 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Text.Json.Serialization; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin; -using Windows.Devices.Geolocation; -using YamlDotNet.Core.Tokens; namespace Flow.Launcher.Storage { @@ -36,6 +33,12 @@ namespace Flow.Launcher.Storage OriginQuery = new Query { RawQuery = item.Query }, Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C"), Query = item.Query, + Action = _ => + { + App.API.BackToQueryResults(); + App.API.ChangeQuery(item.Query); + return false; + }, ExecutedDateTime = item.ExecutedDateTime }); } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 2ff571f19..9a32b0d03 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1349,107 +1349,31 @@ namespace Flow.Launcher.ViewModel foreach (var item in historyItems) { - Result result = null; - //var glyph = item.Glyph is null && !string.IsNullOrEmpty(item.IcoPath) // Some plugins won't have Glyph, then prefer IcoPath - // ? null - // : item.Glyph is not null - // ? item.Glyph - // : new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C"); // Default fallback - - //var icoPath = !string.IsNullOrEmpty(item.IcoPath) ? item.IcoPath : Constant.HistoryIcon; - - - - - - - result = new Result + var copiedItem = item.Copy(); + // Subtitle has datetime which can cause duplicates when saving. + copiedItem.SubTitle = Localize.lastExecuteTime(item.ExecutedDateTime); + // Empty PluginID so the source of last opened history results won't be updated, these results are meant to be temporary copy. + copiedItem.PluginID = string.Empty; + copiedItem.AsyncAction = async c => { - Title = Settings.HistoryStyle == HistoryStyle.Query - ? Localize.executeQuery(item.Query) - : item.Title, - SubTitle = Localize.lastExecuteTime(item.ExecutedDateTime), - IcoPath = item.IcoAbsoluteFullPath, - OriginQuery = new Query { RawQuery = item.Query }, - Action = _ => + var reflectResult = await ResultHelper.PopulateResultsAsync(item); + if (reflectResult != null) { - App.API.BackToQueryResults(); - App.API.ChangeQuery(item.Query); - return false; - }, - AsyncAction = async c => - { - var reflectResult = await ResultHelper.PopulateResultsAsync(item); - if (reflectResult != null) - { - // Record the user selected record for result ranking - _userSelectedRecord.Add(reflectResult); + // Record the user selected record for result ranking + _userSelectedRecord.Add(reflectResult); - // Since some actions may need to hide the Flow window to execute - // So let us populate the results of them - return await reflectResult.ExecuteAsync(c); - } + // Since some actions may need to hide the Flow window to execute + // So let us populate the results of them + return await reflectResult.ExecuteAsync(c); + } - // If we cannot get the result, fallback to re-query - App.API.BackToQueryResults(); - App.API.ChangeQuery(item.Query); - return false; - }, - Glyph = item.Glyph - }; + // If we cannot get the result, fallback to re-query + App.API.BackToQueryResults(); + App.API.ChangeQuery(item.Query); + return false; + }; - - - //if (Settings.HistoryStyle == HistoryStyle.Query) - //{ - // result = new Result - // { - // Title = Localize.executeQuery(item.Query), - // SubTitle = Localize.lastExecuteTime(item.ExecutedDateTime), - // IcoPath = icoPath, - // OriginQuery = new Query { RawQuery = item.Query }, - // Action = _ => - // { - // App.API.BackToQueryResults(); - // App.API.ChangeQuery(item.Query); - // return false; - // }, - // Glyph = glyph - // }; - //} - //else - //{ - // result = new Result - // { - // Title = string.IsNullOrEmpty(item.Title) ? // Old migrated history items have no title - // Localize.executeQuery(item.Query) : - // item.Title, - // SubTitle = Localize.lastExecuteTime(item.ExecutedDateTime), - // IcoPath = icoPath, - // OriginQuery = new Query { RawQuery = item.Query }, - // AsyncAction = async c => - // { - // var reflectResult = await ResultHelper.PopulateResultsAsync(item); - // if (reflectResult != null) - // { - // // Record the user selected record for result ranking - // _userSelectedRecord.Add(reflectResult); - - // // Since some actions may need to hide the Flow window to execute - // // So let us populate the results of them - // return await reflectResult.ExecuteAsync(c); - // } - - // // If we cannot get the result, fallback to re-query - // App.API.BackToQueryResults(); - // App.API.ChangeQuery(item.Query); - // return false; - // }, - // Glyph = glyph - // }; - //} - - results.Add(result); + results.Add(copiedItem); } return results;