From 7883e7a0a95c6609c5cf5622dfc7d4ac810c18fc Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sat, 18 Oct 2025 10:35:23 +1100 Subject: [PATCH 001/124] add result IcoPath & Glyph + handling show badge switching --- Flow.Launcher/Storage/LastOpenedHistoryItem.cs | 2 ++ Flow.Launcher/Storage/QueryHistory.cs | 4 +++- Flow.Launcher/ViewModel/MainViewModel.cs | 10 +++++++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/Storage/LastOpenedHistoryItem.cs b/Flow.Launcher/Storage/LastOpenedHistoryItem.cs index 47647066c..c7f9144a7 100644 --- a/Flow.Launcher/Storage/LastOpenedHistoryItem.cs +++ b/Flow.Launcher/Storage/LastOpenedHistoryItem.cs @@ -10,6 +10,8 @@ public class LastOpenedHistoryItem public string PluginID { get; set; } = string.Empty; public string Query { get; set; } = string.Empty; public string RecordKey { get; set; } = string.Empty; + public string IcoPath { get; set; } = string.Empty; + public GlyphInfo Glyph { get; init; } = null; public DateTime ExecutedDateTime { get; set; } public bool Equals(Result r) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 8284f7eea..bcf080669 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; @@ -59,6 +59,8 @@ namespace Flow.Launcher.Storage PluginID = result.PluginID, Query = result.OriginQuery.RawQuery, RecordKey = result.RecordKey, + IcoPath = result.IcoPath, + Glyph = result.Glyph, ExecutedDateTime = DateTime.Now }); } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index f0f4b257a..f26e0f60f 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; @@ -1349,7 +1349,9 @@ namespace Flow.Launcher.ViewModel Localize.executeQuery(h.Query) : h.Title, SubTitle = Localize.lastExecuteTime(h.ExecutedDateTime), - IcoPath = Constant.HistoryIcon, + IcoPath = Settings.ShowBadges ? h.IcoPath : Constant.HistoryIcon, + BadgeIcoPath = Settings.ShowBadges ? Constant.HistoryIcon : h.IcoPath, + ShowBadge = Settings.ShowBadges, OriginQuery = new Query { RawQuery = h.Query }, AsyncAction = async c => { @@ -1369,7 +1371,9 @@ namespace Flow.Launcher.ViewModel App.API.ChangeQuery(h.Query); return false; }, - Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C") + Glyph = Settings.ShowBadges ? + h.Glyph is not null ? h.Glyph : null + : new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C") }; results.Add(result); } From 10d3ba268dd216b41113c762604668b3dd276bcc Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 19 Oct 2025 20:22:03 +1100 Subject: [PATCH 002/124] update history result icon display logic & remove badge icon logic --- Flow.Launcher/ViewModel/MainViewModel.cs | 46 +++++++++++++----------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index f26e0f60f..b8d56a652 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; @@ -1318,15 +1318,24 @@ namespace Flow.Launcher.ViewModel private List GetHistoryItems(IEnumerable historyItems) { var results = new List(); - if (Settings.HistoryStyle == HistoryStyle.Query) + foreach (var h in historyItems) { - foreach (var h in historyItems) + Result result = null; + var glyph = h.Glyph is null && !string.IsNullOrEmpty(h.IcoPath) // Some plugins won't have Glyph, then prefer IcoPath + ? null + : h.Glyph is not null + ? h.Glyph + : new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C"); // Default fallback + + var icoPath = !string.IsNullOrEmpty(h.IcoPath) ? h.IcoPath : Constant.HistoryIcon; + + if (Settings.HistoryStyle == HistoryStyle.Query) { - var result = new Result + result = new Result { Title = Localize.executeQuery(h.Query), SubTitle = Localize.lastExecuteTime(h.ExecutedDateTime), - IcoPath = Constant.HistoryIcon, + IcoPath = icoPath, OriginQuery = new Query { RawQuery = h.Query }, Action = _ => { @@ -1334,24 +1343,19 @@ namespace Flow.Launcher.ViewModel App.API.ChangeQuery(h.Query); return false; }, - Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C") + Glyph = glyph }; - results.Add(result); } - } - else - { - foreach (var h in historyItems) + else { - var result = new Result + + result = new Result { Title = string.IsNullOrEmpty(h.Title) ? // Old migrated history items have no title - Localize.executeQuery(h.Query) : - h.Title, + Localize.executeQuery(h.Query) : + h.Title, SubTitle = Localize.lastExecuteTime(h.ExecutedDateTime), - IcoPath = Settings.ShowBadges ? h.IcoPath : Constant.HistoryIcon, - BadgeIcoPath = Settings.ShowBadges ? Constant.HistoryIcon : h.IcoPath, - ShowBadge = Settings.ShowBadges, + IcoPath = icoPath, OriginQuery = new Query { RawQuery = h.Query }, AsyncAction = async c => { @@ -1371,13 +1375,13 @@ namespace Flow.Launcher.ViewModel App.API.ChangeQuery(h.Query); return false; }, - Glyph = Settings.ShowBadges ? - h.Glyph is not null ? h.Glyph : null - : new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C") + Glyph = glyph }; - results.Add(result); } + + results.Add(result); } + return results; } From 26ad47359203c120829af9c5816d9cddee67ea95 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 19 Oct 2025 21:46:02 +1100 Subject: [PATCH 003/124] change getting last history item to get the same result if exists --- Flow.Launcher/Storage/QueryHistory.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index bcf080669..fde74bf17 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; @@ -44,11 +44,11 @@ namespace Flow.Launcher.Storage LastOpenedHistoryItems.RemoveAt(0); } - // If the last item is the same as the current result, just update the timestamp - if (LastOpenedHistoryItems.Count > 0 && - LastOpenedHistoryItems.Last().Equals(result)) + if (LastOpenedHistoryItems.Count > 0 && + TryGetLastOpenedHistoryResult(result, out var existingHistoryItem)) { - LastOpenedHistoryItems.Last().ExecutedDateTime = DateTime.Now; + existingHistoryItem.IcoPath = result.IcoPath; + existingHistoryItem.ExecutedDateTime = DateTime.Now; } else { @@ -65,5 +65,11 @@ namespace Flow.Launcher.Storage }); } } + + private bool TryGetLastOpenedHistoryResult(Result result, out LastOpenedHistoryItem historyItem) + { + historyItem = LastOpenedHistoryItems.FirstOrDefault(x => x.Equals(result)); + return historyItem is not null; + } } } From 92551c58a5d65b2d7ff6563ee9fdf75a22959043 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 21 Oct 2025 21:53:32 +1100 Subject: [PATCH 004/124] show distinct records when history style is last opened --- Flow.Launcher/ViewModel/MainViewModel.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index b8d56a652..b70d6e5e2 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; @@ -1319,6 +1319,13 @@ namespace Flow.Launcher.ViewModel { var results = new List(); foreach (var h in historyItems) + if (Settings.HistoryStyle == HistoryStyle.LastOpened) + { + historyItems = historyItems + .GroupBy(r => new { r.Title, r.SubTitle, r.PluginID, r.RecordKey }) + .Select(g => g.First()); + } + { Result result = null; var glyph = h.Glyph is null && !string.IsNullOrEmpty(h.IcoPath) // Some plugins won't have Glyph, then prefer IcoPath From 25aa5bf2af1cd683211b9ea1829c1d80aa98a141 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 21 Oct 2025 21:54:38 +1100 Subject: [PATCH 005/124] show history result sorted descending by execution time --- Flow.Launcher/ViewModel/MainViewModel.cs | 37 ++++++++++++------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index b70d6e5e2..eeb15d74e 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; @@ -1318,7 +1318,7 @@ namespace Flow.Launcher.ViewModel private List GetHistoryItems(IEnumerable historyItems) { var results = new List(); - foreach (var h in historyItems) + if (Settings.HistoryStyle == HistoryStyle.LastOpened) { historyItems = historyItems @@ -1326,28 +1326,29 @@ namespace Flow.Launcher.ViewModel .Select(g => g.First()); } + foreach (var item in historyItems.OrderByDescending(h => h.ExecutedDateTime)) { Result result = null; - var glyph = h.Glyph is null && !string.IsNullOrEmpty(h.IcoPath) // Some plugins won't have Glyph, then prefer IcoPath + var glyph = item.Glyph is null && !string.IsNullOrEmpty(item.IcoPath) // Some plugins won't have Glyph, then prefer IcoPath ? null - : h.Glyph is not null - ? h.Glyph + : item.Glyph is not null + ? item.Glyph : new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C"); // Default fallback - var icoPath = !string.IsNullOrEmpty(h.IcoPath) ? h.IcoPath : Constant.HistoryIcon; + var icoPath = !string.IsNullOrEmpty(item.IcoPath) ? item.IcoPath : Constant.HistoryIcon; if (Settings.HistoryStyle == HistoryStyle.Query) { result = new Result { - Title = Localize.executeQuery(h.Query), - SubTitle = Localize.lastExecuteTime(h.ExecutedDateTime), + Title = Localize.executeQuery(item.Query), + SubTitle = Localize.lastExecuteTime(item.ExecutedDateTime), IcoPath = icoPath, - OriginQuery = new Query { RawQuery = h.Query }, + OriginQuery = new Query { RawQuery = item.Query }, Action = _ => { App.API.BackToQueryResults(); - App.API.ChangeQuery(h.Query); + App.API.ChangeQuery(item.Query); return false; }, Glyph = glyph @@ -1358,15 +1359,15 @@ namespace Flow.Launcher.ViewModel result = new Result { - Title = string.IsNullOrEmpty(h.Title) ? // Old migrated history items have no title - Localize.executeQuery(h.Query) : - h.Title, - SubTitle = Localize.lastExecuteTime(h.ExecutedDateTime), + 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 = h.Query }, + OriginQuery = new Query { RawQuery = item.Query }, AsyncAction = async c => { - var reflectResult = await ResultHelper.PopulateResultsAsync(h); + var reflectResult = await ResultHelper.PopulateResultsAsync(item); if (reflectResult != null) { // Record the user selected record for result ranking @@ -1379,7 +1380,7 @@ namespace Flow.Launcher.ViewModel // If we cannot get the result, fallback to re-query App.API.BackToQueryResults(); - App.API.ChangeQuery(h.Query); + App.API.ChangeQuery(item.Query); return false; }, Glyph = glyph @@ -1388,7 +1389,7 @@ namespace Flow.Launcher.ViewModel results.Add(result); } - + return results; } From 0f269455b1c9fac303d11bed238bd1ec14e92d44 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 21 Oct 2025 22:18:29 +1100 Subject: [PATCH 006/124] remove duplicate history item sort call --- Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index eeb15d74e..08d4e0d03 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1326,7 +1326,7 @@ namespace Flow.Launcher.ViewModel .Select(g => g.First()); } - foreach (var item in historyItems.OrderByDescending(h => h.ExecutedDateTime)) + 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 From 7f5efc5ca11bd54126d52817c02040a49eeae082 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 26 Oct 2025 20:40:37 +0800 Subject: [PATCH 007/124] Refactor caching and improve QueryAsync method Removed the `ResetCache` method and its associated calls to streamline caching management and improve performance. Refactored the `QueryAsync` method for better thread safety, synchronization, and exception handling. Simplified UWP and Win32 program filtering logic and removed redundant code. Eliminated manual cache disposal and reset logic, favoring a more efficient and automated caching mechanism. These changes enhance maintainability, responsiveness, and overall plugin performance. --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 85 ++++++++----------- .../Views/ProgramSetting.xaml.cs | 4 - 2 files changed, 34 insertions(+), 55 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 0258a10d2..627bf533d 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -78,53 +78,45 @@ namespace Flow.Launcher.Plugin.Program public async Task> QueryAsync(Query query, CancellationToken token) { - var result = await cache.GetOrCreateAsync(query.Search, async entry => + var resultList = await Task.Run(async () => { - var resultList = await Task.Run(async () => + await _win32sLock.WaitAsync(token); + await _uwpsLock.WaitAsync(token); + try { - await _win32sLock.WaitAsync(token); - await _uwpsLock.WaitAsync(token); - try - { - // Collect all UWP Windows app directories - var uwpsDirectories = _settings.HideDuplicatedWindowsApp ? _uwps - .Where(uwp => !string.IsNullOrEmpty(uwp.Location)) // Exclude invalid paths - .Where(uwp => uwp.Location.StartsWith(WindowsAppPath, StringComparison.OrdinalIgnoreCase)) // Keep system apps - .Select(uwp => uwp.Location.TrimEnd('\\')) // Remove trailing slash - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray() : null; + // Collect all UWP Windows app directories + var uwpsDirectories = _settings.HideDuplicatedWindowsApp ? _uwps + .Where(uwp => !string.IsNullOrEmpty(uwp.Location)) // Exclude invalid paths + .Where(uwp => uwp.Location.StartsWith(WindowsAppPath, StringComparison.OrdinalIgnoreCase)) // Keep system apps + .Select(uwp => uwp.Location.TrimEnd('\\')) // Remove trailing slash + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToArray() : null; - return _win32s.Cast() - .Concat(_uwps) - .AsParallel() - .WithCancellation(token) - .Where(HideUninstallersFilter) - .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories)) - .Where(p => p.Enabled) - .Select(p => p.Result(query.Search, Context.API)) - .Where(r => string.IsNullOrEmpty(query.Search) || r?.Score > 0) - .ToList(); - } - catch (OperationCanceledException) - { - return emptyResults; - } - finally - { - _uwpsLock.Release(); - _win32sLock.Release(); - } - }, token); + return _win32s.Cast() + .Concat(_uwps) + .AsParallel() + .WithCancellation(token) + .Where(HideUninstallersFilter) + .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories)) + .Where(p => p.Enabled) + .Select(p => p.Result(query.Search, Context.API)) + .Where(r => string.IsNullOrEmpty(query.Search) || r?.Score > 0) + .ToList(); + } + catch (OperationCanceledException) + { + return emptyResults; + } + finally + { + _uwpsLock.Release(); + _win32sLock.Release(); + } + }, token); - resultList = resultList.Count != 0 ? resultList : emptyResults; + resultList = resultList.Count != 0 ? resultList : emptyResults; - entry.SetSize(resultList.Count); - entry.SetSlidingExpiration(TimeSpan.FromHours(8)); - - return resultList; - }); - - return result; + return resultList; } private bool HideUninstallersFilter(IProgram program) @@ -306,7 +298,6 @@ namespace Flow.Launcher.Plugin.Program { _win32s.Add(win32); } - ResetCache(); await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); _settings.LastIndexTime = DateTime.Now; } @@ -331,7 +322,6 @@ namespace Flow.Launcher.Plugin.Program { _uwps.Add(uwp); } - ResetCache(); await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); _settings.LastIndexTime = DateTime.Now; } @@ -360,13 +350,6 @@ namespace Flow.Launcher.Plugin.Program await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false); } - internal static void ResetCache() - { - var oldCache = cache; - cache = new MemoryCache(cacheOptions); - oldCache.Dispose(); - } - public Control CreateSettingPanel() { return new ProgramSetting(Context, _settings); diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs index 860f20954..8770dd651 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs @@ -32,7 +32,6 @@ namespace Flow.Launcher.Plugin.Program.Views get => _settings.EnableDescription; set { - Main.ResetCache(); _settings.EnableDescription = value; } } @@ -42,7 +41,6 @@ namespace Flow.Launcher.Plugin.Program.Views get => _settings.HideAppsPath; set { - Main.ResetCache(); _settings.HideAppsPath = value; } } @@ -52,7 +50,6 @@ namespace Flow.Launcher.Plugin.Program.Views get => _settings.HideUninstallers; set { - Main.ResetCache(); _settings.HideUninstallers = value; } } @@ -62,7 +59,6 @@ namespace Flow.Launcher.Plugin.Program.Views get => _settings.HideDuplicatedWindowsApp; set { - Main.ResetCache(); _settings.HideDuplicatedWindowsApp = value; } } From 637d926f7ada1690857e1f5cbb05797e704bea1a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 26 Oct 2025 20:41:06 +0800 Subject: [PATCH 008/124] Remove caching logic and initialize emptyResults list The caching-related code, including `cacheOptions` and `cache`, has been removed from `Main.cs`, indicating that the caching mechanism is no longer in use or has been refactored elsewhere. Additionally, the `emptyResults` list is now explicitly initialized as an empty list (`[]`). No changes were made to the `Context` property or the `commonUninstallerNames` array. --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 627bf533d..1a72ea975 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -33,9 +33,6 @@ namespace Flow.Launcher.Plugin.Program private static readonly List emptyResults = []; - private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; - private static MemoryCache cache = new(cacheOptions); - private static readonly string[] commonUninstallerNames = { "uninst.exe", From 6a65f8090f108c565ef6d4151591f8723ab82d1b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 26 Oct 2025 20:51:08 +0800 Subject: [PATCH 009/124] Enhance thread safety and refactor reindexing logic Introduced `_lastIndexTimeLock` to ensure thread-safe access and updates to `_settings.LastIndexTime`, preventing race conditions. Refactored reindexing logic to use a `lock` block for evaluating and updating the reindexing condition. Added `emptyResults` as a static readonly placeholder list. Improved code clarity and maintainability without altering existing functionality. --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 1a72ea975..f321e4626 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -31,6 +31,8 @@ namespace Flow.Launcher.Plugin.Program internal static PluginInitContext Context { get; private set; } + private static readonly Lock _lastIndexTimeLock = new(); + private static readonly List emptyResults = []; private static readonly string[] commonUninstallerNames = @@ -264,7 +266,12 @@ namespace Flow.Launcher.Plugin.Program var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0; - if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now) + bool needReindex; + lock (_lastIndexTimeLock) + { + needReindex = _settings.LastIndexTime.AddHours(30) < DateTime.Now; + } + if (cacheEmpty || needReindex) { _ = Task.Run(async () => { @@ -296,8 +303,11 @@ namespace Flow.Launcher.Plugin.Program _win32s.Add(win32); } await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); + lock (_lastIndexTimeLock) + { _settings.LastIndexTime = DateTime.Now; } + } catch (Exception e) { Context.API.LogException(ClassName, "Failed to index Win32 programs", e); @@ -320,8 +330,11 @@ namespace Flow.Launcher.Plugin.Program _uwps.Add(uwp); } await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); + lock (_lastIndexTimeLock) + { _settings.LastIndexTime = DateTime.Now; } + } catch (Exception e) { Context.API.LogException(ClassName, "Failed to index Uwp programs", e); From e2fa122362b319548f09bf289c0de1a843af9d6a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 26 Oct 2025 20:56:08 +0800 Subject: [PATCH 010/124] Improve program indexing with logging and thread safety Added detailed debug logging to `IndexWin32ProgramsAsync` and `IndexUwpProgramsAsync` to track the indexing process, including preparation, start, retrieval, caching, and completion. Replaced direct updates to `_settings.LastIndexTime` with a thread-safe lock to prevent race conditions. Enhanced `IndexProgramsAsync` with a debug log to indicate the start of indexing for better traceability. Updated program retrieval logic to process Win32 and UWP programs in parallel with cancellation support and applied the `HideUninstallersFilter` for cleaner results. --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 22 +++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index f321e4626..e8554198e 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -90,7 +90,7 @@ namespace Flow.Launcher.Plugin.Program .Select(uwp => uwp.Location.TrimEnd('\\')) // Remove trailing slash .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray() : null; - + return _win32s.Cast() .Concat(_uwps) .AsParallel() @@ -293,20 +293,24 @@ namespace Flow.Launcher.Plugin.Program public static async Task IndexWin32ProgramsAsync() { + Context.API.LogDebug(ClassName, "Prepare indexing Win32 programs"); await _win32sLock.WaitAsync(); + Context.API.LogDebug(ClassName, "Start indexing Win32 programs"); try { var win32S = Win32.All(_settings); + Context.API.LogDebug(ClassName, "Get all Win32 programs"); _win32s.Clear(); foreach (var win32 in win32S) { _win32s.Add(win32); } + Context.API.LogDebug(ClassName, "Cache all Win32 programs"); await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); lock (_lastIndexTimeLock) { - _settings.LastIndexTime = DateTime.Now; - } + _settings.LastIndexTime = DateTime.Now; + } } catch (Exception e) { @@ -316,24 +320,29 @@ namespace Flow.Launcher.Plugin.Program { _win32sLock.Release(); } + Context.API.LogDebug(ClassName, "End indexing Win32 programs"); } public static async Task IndexUwpProgramsAsync() { + Context.API.LogDebug(ClassName, "Prepare indexing Uwp programs"); await _uwpsLock.WaitAsync(); + Context.API.LogDebug(ClassName, "Start indexing Uwp programs"); try { var uwps = UWPPackage.All(_settings); + Context.API.LogDebug(ClassName, "Get all Uwp programs"); _uwps.Clear(); foreach (var uwp in uwps) { _uwps.Add(uwp); } + Context.API.LogDebug(ClassName, "Cache all Uwp programs"); await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); lock (_lastIndexTimeLock) { - _settings.LastIndexTime = DateTime.Now; - } + _settings.LastIndexTime = DateTime.Now; + } } catch (Exception e) { @@ -343,6 +352,7 @@ namespace Flow.Launcher.Plugin.Program { _uwpsLock.Release(); } + Context.API.LogDebug(ClassName, "End indexing Uwp programs"); } public static async Task IndexProgramsAsync() @@ -357,6 +367,8 @@ namespace Flow.Launcher.Plugin.Program await Context.API.StopwatchLogInfoAsync(ClassName, "UWPProgram index cost", IndexUwpProgramsAsync); }); + Context.API.LogDebug(ClassName, "Start indexing"); + await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false); } From f632a4b773a2a5f4b229685e6139f7ac843bf08c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 26 Oct 2025 20:59:29 +0800 Subject: [PATCH 011/124] Add caching to QueryAsync and integrate cache reset logic Introduced a MemoryCache to improve QueryAsync performance by caching query results, reducing redundant computations. Added a ResetCache method to reinitialize the cache when settings are updated. Integrated cache reset calls into settings property setters to ensure consistency. Refactored query logic to leverage MemoryCache.GetOrCreateAsync for streamlined caching. Removed redundant code and debug logging for improved readability and maintainability. Ensured thread safety with proper locking mechanisms. Simplified and consolidated caching logic for better maintainability. --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 90 +++++++++++-------- .../Views/ProgramSetting.xaml.cs | 4 + 2 files changed, 57 insertions(+), 37 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index e8554198e..bb850b4de 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -35,6 +35,9 @@ namespace Flow.Launcher.Plugin.Program private static readonly List emptyResults = []; + private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; + private static MemoryCache cache = new(cacheOptions); + private static readonly string[] commonUninstallerNames = { "uninst.exe", @@ -77,45 +80,53 @@ namespace Flow.Launcher.Plugin.Program public async Task> QueryAsync(Query query, CancellationToken token) { - var resultList = await Task.Run(async () => + var result = await cache.GetOrCreateAsync(query.Search, async entry => { - await _win32sLock.WaitAsync(token); - await _uwpsLock.WaitAsync(token); - try + var resultList = await Task.Run(async () => { - // Collect all UWP Windows app directories - var uwpsDirectories = _settings.HideDuplicatedWindowsApp ? _uwps - .Where(uwp => !string.IsNullOrEmpty(uwp.Location)) // Exclude invalid paths - .Where(uwp => uwp.Location.StartsWith(WindowsAppPath, StringComparison.OrdinalIgnoreCase)) // Keep system apps - .Select(uwp => uwp.Location.TrimEnd('\\')) // Remove trailing slash - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray() : null; - - return _win32s.Cast() - .Concat(_uwps) - .AsParallel() - .WithCancellation(token) - .Where(HideUninstallersFilter) - .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories)) - .Where(p => p.Enabled) - .Select(p => p.Result(query.Search, Context.API)) - .Where(r => string.IsNullOrEmpty(query.Search) || r?.Score > 0) - .ToList(); - } - catch (OperationCanceledException) - { - return emptyResults; - } - finally - { - _uwpsLock.Release(); - _win32sLock.Release(); - } - }, token); + await _win32sLock.WaitAsync(token); + await _uwpsLock.WaitAsync(token); + try + { + // Collect all UWP Windows app directories + var uwpsDirectories = _settings.HideDuplicatedWindowsApp ? _uwps + .Where(uwp => !string.IsNullOrEmpty(uwp.Location)) // Exclude invalid paths + .Where(uwp => uwp.Location.StartsWith(WindowsAppPath, StringComparison.OrdinalIgnoreCase)) // Keep system apps + .Select(uwp => uwp.Location.TrimEnd('\\')) // Remove trailing slash + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToArray() : null; - resultList = resultList.Count != 0 ? resultList : emptyResults; + return _win32s.Cast() + .Concat(_uwps) + .AsParallel() + .WithCancellation(token) + .Where(HideUninstallersFilter) + .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories)) + .Where(p => p.Enabled) + .Select(p => p.Result(query.Search, Context.API)) + .Where(r => string.IsNullOrEmpty(query.Search) || r?.Score > 0) + .ToList(); + } + catch (OperationCanceledException) + { + return emptyResults; + } + finally + { + _uwpsLock.Release(); + _win32sLock.Release(); + } + }, token); - return resultList; + resultList = resultList.Count != 0 ? resultList : emptyResults; + + entry.SetSize(resultList.Count); + entry.SetSlidingExpiration(TimeSpan.FromHours(8)); + + return resultList; + }); + + return result; } private bool HideUninstallersFilter(IProgram program) @@ -305,7 +316,6 @@ namespace Flow.Launcher.Plugin.Program { _win32s.Add(win32); } - Context.API.LogDebug(ClassName, "Cache all Win32 programs"); await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); lock (_lastIndexTimeLock) { @@ -337,7 +347,6 @@ namespace Flow.Launcher.Plugin.Program { _uwps.Add(uwp); } - Context.API.LogDebug(ClassName, "Cache all Uwp programs"); await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); lock (_lastIndexTimeLock) { @@ -372,6 +381,13 @@ namespace Flow.Launcher.Plugin.Program await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false); } + internal static void ResetCache() + { + var oldCache = cache; + cache = new MemoryCache(cacheOptions); + oldCache.Dispose(); + } + public Control CreateSettingPanel() { return new ProgramSetting(Context, _settings); diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs index 8770dd651..860f20954 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs @@ -32,6 +32,7 @@ namespace Flow.Launcher.Plugin.Program.Views get => _settings.EnableDescription; set { + Main.ResetCache(); _settings.EnableDescription = value; } } @@ -41,6 +42,7 @@ namespace Flow.Launcher.Plugin.Program.Views get => _settings.HideAppsPath; set { + Main.ResetCache(); _settings.HideAppsPath = value; } } @@ -50,6 +52,7 @@ namespace Flow.Launcher.Plugin.Program.Views get => _settings.HideUninstallers; set { + Main.ResetCache(); _settings.HideUninstallers = value; } } @@ -59,6 +62,7 @@ namespace Flow.Launcher.Plugin.Program.Views get => _settings.HideDuplicatedWindowsApp; set { + Main.ResetCache(); _settings.HideDuplicatedWindowsApp = value; } } From 4cf942ac3aaeffa3bdd0035f689b0311ac9767ba Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 26 Oct 2025 21:01:07 +0800 Subject: [PATCH 012/124] Add detailed debug logging for query execution process Enhanced logging to provide better traceability and insights: - Added debug logs for query reception, cache misses, and lock acquisition. - Logged query cancellation and completion with result counts. - Added logs for caching results, including item counts and query details. - Improved logging for filtering and program selection processes. - Ensured no functional changes to existing query and filtering logic. --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index bb850b4de..088f42817 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -80,12 +80,16 @@ namespace Flow.Launcher.Plugin.Program public async Task> QueryAsync(Query query, CancellationToken token) { + Context.API.LogDebug(ClassName, $"Query received: {query.Search}"); var result = await cache.GetOrCreateAsync(query.Search, async entry => { + Context.API.LogDebug(ClassName, $"Cache miss for query: {query.Search}"); var resultList = await Task.Run(async () => { + Context.API.LogDebug(ClassName, "Acquiring locks for querying programs"); await _win32sLock.WaitAsync(token); await _uwpsLock.WaitAsync(token); + Context.API.LogDebug(ClassName, "Locks acquired for querying programs"); try { // Collect all UWP Windows app directories @@ -95,6 +99,7 @@ namespace Flow.Launcher.Plugin.Program .Select(uwp => uwp.Location.TrimEnd('\\')) // Remove trailing slash .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray() : null; + Context.API.LogDebug(ClassName, "Start filtering and selecting programs"); return _win32s.Cast() .Concat(_uwps) @@ -109,6 +114,7 @@ namespace Flow.Launcher.Plugin.Program } catch (OperationCanceledException) { + Context.API.LogDebug(ClassName, "Query operation was canceled"); return emptyResults; } finally @@ -120,9 +126,11 @@ namespace Flow.Launcher.Plugin.Program resultList = resultList.Count != 0 ? resultList : emptyResults; + Context.API.LogDebug(ClassName, $"Query completed with {resultList.Count} results"); entry.SetSize(resultList.Count); entry.SetSlidingExpiration(TimeSpan.FromHours(8)); - + Context.API.LogDebug(ClassName, $"Caching results for query: {query.Search} with {resultList.Count} items"); + return resultList; }); From 6e17d5d7565e0146d01811ab8b96d0a74816aaa9 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 4 Nov 2025 12:27:59 +0800 Subject: [PATCH 013/124] Improve logging for Win32 program lock acquisition Added a debug log statement to indicate when the lock for querying Win32 programs is being acquired. This enhances granularity in logging, making it easier to distinguish between the acquisition of locks for Win32 and UWP programs. Improves traceability and debugging of the program's execution flow. --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 088f42817..79f169642 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -88,6 +88,7 @@ namespace Flow.Launcher.Plugin.Program { Context.API.LogDebug(ClassName, "Acquiring locks for querying programs"); await _win32sLock.WaitAsync(token); + Context.API.LogDebug(ClassName, "Acquiring locks for querying win32 programs"); await _uwpsLock.WaitAsync(token); Context.API.LogDebug(ClassName, "Locks acquired for querying programs"); try From db0c86d50ceeaee66c415d88922ac4c0f6a843c9 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 4 Nov 2025 14:25:55 +0800 Subject: [PATCH 014/124] Remove CancellationToken from semaphore WaitAsync calls Removed the `CancellationToken` parameter from `WaitAsync` calls on semaphores in `EverythingAPI.cs` and `Main.cs`. This change eliminates cancellation support for semaphore waits, likely due to a design decision prioritizing simplicity or avoiding issues with cancellation handling. In `EverythingAPI.cs`, `WaitAsync(token)` was replaced with `WaitAsync()` in two methods. Similarly, in `Main.cs`, the `WaitAsync` calls for `_win32sLock` and `_uwpsLock` were updated to remove the `token` parameter. Note: This change may impact the ability to gracefully handle cancellation during semaphore waits. --- .../Search/Everything/EverythingAPI.cs | 5 ++--- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index fd62566d5..8e295b960 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -48,7 +48,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public static async ValueTask IsEverythingRunningAsync(CancellationToken token = default) { - await _semaphore.WaitAsync(token); + await _semaphore.WaitAsync(); try { @@ -77,8 +77,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything if (option.MaxCount < 0) throw new ArgumentOutOfRangeException(nameof(option.MaxCount), option.MaxCount, "MaxCount must be greater than or equal to 0"); - await _semaphore.WaitAsync(token); - + await _semaphore.WaitAsync(); try { diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 79f169642..201062aa6 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -86,10 +86,10 @@ namespace Flow.Launcher.Plugin.Program Context.API.LogDebug(ClassName, $"Cache miss for query: {query.Search}"); var resultList = await Task.Run(async () => { - Context.API.LogDebug(ClassName, "Acquiring locks for querying programs"); - await _win32sLock.WaitAsync(token); Context.API.LogDebug(ClassName, "Acquiring locks for querying win32 programs"); - await _uwpsLock.WaitAsync(token); + await _win32sLock.WaitAsync(); + Context.API.LogDebug(ClassName, "Acquiring locks for querying uwp programs"); + await _uwpsLock.WaitAsync(); Context.API.LogDebug(ClassName, "Locks acquired for querying programs"); try { From 3d8fd1d35295dc54c8264b1ebb262ffe8eda0bb8 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Nov 2025 15:28:13 +0800 Subject: [PATCH 015/124] Improve cancellation, locking, and logging mechanisms Enhanced cancellation handling by adding `token.IsCancellationRequested` checks to improve responsiveness. Refactored locking mechanisms for `_win32sLock` and `_uwpsLock` using `try-finally` blocks to ensure proper acquisition and release, improving thread safety and preventing deadlocks. Reorganized Win32 and UWP program querying logic for better modularity and readability. Replaced shared collection access with local variables to improve clarity and maintain thread safety. Simplified empty result handling by directly returning `emptyResults` when canceled. Removed redundant debug log statements to reduce verbosity and updated remaining logs for clarity. Suppressed unused result warnings by replacing direct calls to `EverythingApiDllImport.Everything_GetMajorVersion()` with null-coalescing assignments. --- .../Search/Everything/EverythingAPI.cs | 5 +- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 47 +++++++++++-------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 8e295b960..35f4c10c6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -52,7 +52,10 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything try { - EverythingApiDllImport.Everything_GetMajorVersion(); + if (token.IsCancellationRequested) + return false; + + _ = EverythingApiDllImport.Everything_GetMajorVersion(); var result = EverythingApiDllImport.Everything_GetLastError() != StateCode.IPCError; return result; } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 201062aa6..f6d48a531 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -80,17 +80,37 @@ namespace Flow.Launcher.Plugin.Program public async Task> QueryAsync(Query query, CancellationToken token) { - Context.API.LogDebug(ClassName, $"Query received: {query.Search}"); var result = await cache.GetOrCreateAsync(query.Search, async entry => { - Context.API.LogDebug(ClassName, $"Cache miss for query: {query.Search}"); var resultList = await Task.Run(async () => { - Context.API.LogDebug(ClassName, "Acquiring locks for querying win32 programs"); + Context.API.LogDebug(ClassName, "Preparing win32 programs"); + List win32s; await _win32sLock.WaitAsync(); - Context.API.LogDebug(ClassName, "Acquiring locks for querying uwp programs"); + try + { + win32s = [.. _win32s]; + if (token.IsCancellationRequested) return emptyResults; + } + finally + { + _win32sLock.Release(); + } + + Context.API.LogDebug(ClassName, "Preparing UWP programs"); + List uwps; await _uwpsLock.WaitAsync(); - Context.API.LogDebug(ClassName, "Locks acquired for querying programs"); + try + { + uwps = [.. _uwps]; + if (token.IsCancellationRequested) return emptyResults; + } + finally + { + _uwpsLock.Release(); + } + + Context.API.LogDebug(ClassName, "Start hanlding programs"); try { // Collect all UWP Windows app directories @@ -100,10 +120,9 @@ namespace Flow.Launcher.Plugin.Program .Select(uwp => uwp.Location.TrimEnd('\\')) // Remove trailing slash .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray() : null; - Context.API.LogDebug(ClassName, "Start filtering and selecting programs"); - return _win32s.Cast() - .Concat(_uwps) + return win32s.Cast() + .Concat(uwps) .AsParallel() .WithCancellation(token) .Where(HideUninstallersFilter) @@ -115,22 +134,14 @@ namespace Flow.Launcher.Plugin.Program } catch (OperationCanceledException) { - Context.API.LogDebug(ClassName, "Query operation was canceled"); return emptyResults; } - finally - { - _uwpsLock.Release(); - _win32sLock.Release(); - } }, token); resultList = resultList.Count != 0 ? resultList : emptyResults; - Context.API.LogDebug(ClassName, $"Query completed with {resultList.Count} results"); entry.SetSize(resultList.Count); entry.SetSlidingExpiration(TimeSpan.FromHours(8)); - Context.API.LogDebug(ClassName, $"Caching results for query: {query.Search} with {resultList.Count} items"); return resultList; }); @@ -319,7 +330,6 @@ namespace Flow.Launcher.Plugin.Program try { var win32S = Win32.All(_settings); - Context.API.LogDebug(ClassName, "Get all Win32 programs"); _win32s.Clear(); foreach (var win32 in win32S) { @@ -339,7 +349,6 @@ namespace Flow.Launcher.Plugin.Program { _win32sLock.Release(); } - Context.API.LogDebug(ClassName, "End indexing Win32 programs"); } public static async Task IndexUwpProgramsAsync() @@ -350,7 +359,6 @@ namespace Flow.Launcher.Plugin.Program try { var uwps = UWPPackage.All(_settings); - Context.API.LogDebug(ClassName, "Get all Uwp programs"); _uwps.Clear(); foreach (var uwp in uwps) { @@ -370,7 +378,6 @@ namespace Flow.Launcher.Plugin.Program { _uwpsLock.Release(); } - Context.API.LogDebug(ClassName, "End indexing Uwp programs"); } public static async Task IndexProgramsAsync() From 7e332fa615a790f5d45abd5f6edfb2ea92e501fa Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Nov 2025 15:29:38 +0800 Subject: [PATCH 016/124] Refactor caching and indexing logic Added `ResetCache` calls after clearing `_win32s` and `_uwps` lists to ensure proper cache reset during indexing. Updated logic to return `resultList` after setting cache size and expiration for improved clarity. Removed `await Task.WhenAll` to adjust asynchronous flow in the indexing process. --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index f6d48a531..a2dfecff4 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -142,7 +142,7 @@ namespace Flow.Launcher.Plugin.Program entry.SetSize(resultList.Count); entry.SetSlidingExpiration(TimeSpan.FromHours(8)); - + return resultList; }); @@ -335,6 +335,7 @@ namespace Flow.Launcher.Plugin.Program { _win32s.Add(win32); } + ResetCache(); await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); lock (_lastIndexTimeLock) { @@ -364,6 +365,7 @@ namespace Flow.Launcher.Plugin.Program { _uwps.Add(uwp); } + ResetCache(); await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); lock (_lastIndexTimeLock) { @@ -393,7 +395,6 @@ namespace Flow.Launcher.Plugin.Program }); Context.API.LogDebug(ClassName, "Start indexing"); - await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false); } From 30d7f67d426e4d5248034efad5b568f7e4d7a804 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Nov 2025 15:30:32 +0800 Subject: [PATCH 017/124] Refactor token cancellation check for readability Simplified the `if` statement that checks for token cancellation by condensing it into a single line. This improves code readability and eliminates unnecessary line breaks. --- .../Search/Everything/EverythingAPI.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 35f4c10c6..28c9b49fc 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -52,9 +52,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything try { - if (token.IsCancellationRequested) - return false; - + if (token.IsCancellationRequested) return false; _ = EverythingApiDllImport.Everything_GetMajorVersion(); var result = EverythingApiDllImport.Everything_GetLastError() != StateCode.IPCError; return result; From bfaff5cca5eeb71254ca51b463a1cd0b876e788c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Nov 2025 15:32:08 +0800 Subject: [PATCH 018/124] Improve semaphore usage and logging clarity Added comments in `EverythingAPI.cs` and `Main.cs` to explain why `CancellationToken` is not directly passed to semaphore locks, preventing unexpected `OperationCanceledException`. Updated debug log messages in `Main.cs` for better clarity, including changing "Start handling programs" to "Start querying programs". Removed redundant log messages to improve logging consistency. --- .../Search/Everything/EverythingAPI.cs | 2 ++ Plugins/Flow.Launcher.Plugin.Program/Main.cs | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 28c9b49fc..c8f8de77f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -48,6 +48,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public static async ValueTask IsEverythingRunningAsync(CancellationToken token = default) { + // We do not directly pass token here, but we check IsCancellationRequested inside the lock + // So that it will not raise OperationCanceledException, which is not expected by the caller.` await _semaphore.WaitAsync(); try diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index a2dfecff4..6a8b404b5 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -84,6 +84,8 @@ namespace Flow.Launcher.Plugin.Program { var resultList = await Task.Run(async () => { + // We do not directly pass token here, but we check IsCancellationRequested inside the lock + // So that it will not raise OperationCanceledException, which is not expected by the caller.` Context.API.LogDebug(ClassName, "Preparing win32 programs"); List win32s; await _win32sLock.WaitAsync(); @@ -97,6 +99,8 @@ namespace Flow.Launcher.Plugin.Program _win32sLock.Release(); } + // We do not directly pass token here, but we check IsCancellationRequested inside the lock + // So that it will not raise OperationCanceledException, which is not expected by the caller.` Context.API.LogDebug(ClassName, "Preparing UWP programs"); List uwps; await _uwpsLock.WaitAsync(); @@ -110,7 +114,7 @@ namespace Flow.Launcher.Plugin.Program _uwpsLock.Release(); } - Context.API.LogDebug(ClassName, "Start hanlding programs"); + Context.API.LogDebug(ClassName, "Start querying programs"); try { // Collect all UWP Windows app directories @@ -324,7 +328,6 @@ namespace Flow.Launcher.Plugin.Program public static async Task IndexWin32ProgramsAsync() { - Context.API.LogDebug(ClassName, "Prepare indexing Win32 programs"); await _win32sLock.WaitAsync(); Context.API.LogDebug(ClassName, "Start indexing Win32 programs"); try @@ -354,7 +357,6 @@ namespace Flow.Launcher.Plugin.Program public static async Task IndexUwpProgramsAsync() { - Context.API.LogDebug(ClassName, "Prepare indexing Uwp programs"); await _uwpsLock.WaitAsync(); Context.API.LogDebug(ClassName, "Start indexing Uwp programs"); try From d0a47c84b9b5641330af13808cac387bfa458b2e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Nov 2025 15:39:19 +0800 Subject: [PATCH 019/124] Clarify CancellationToken handling in comments Updated comments to explain the rationale for not directly passing CancellationToken to methods and instead checking IsCancellationRequested within locks. This prevents unexpected OperationCanceledException. Changes made in EverythingAPI.cs (IsEverythingRunningAsync) and Main.cs (Win32 and UWP program preparation). No functional changes to the code. --- .../Search/Everything/EverythingAPI.cs | 2 +- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index c8f8de77f..d06fdfa98 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -49,7 +49,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public static async ValueTask IsEverythingRunningAsync(CancellationToken token = default) { // We do not directly pass token here, but we check IsCancellationRequested inside the lock - // So that it will not raise OperationCanceledException, which is not expected by the caller.` + // So that it will not raise OperationCanceledException, which is not expected by the caller. await _semaphore.WaitAsync(); try diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 6a8b404b5..aac5de2c2 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -85,7 +85,7 @@ namespace Flow.Launcher.Plugin.Program var resultList = await Task.Run(async () => { // We do not directly pass token here, but we check IsCancellationRequested inside the lock - // So that it will not raise OperationCanceledException, which is not expected by the caller.` + // So that it will not raise OperationCanceledException, which is not expected by the caller. Context.API.LogDebug(ClassName, "Preparing win32 programs"); List win32s; await _win32sLock.WaitAsync(); @@ -100,7 +100,7 @@ namespace Flow.Launcher.Plugin.Program } // We do not directly pass token here, but we check IsCancellationRequested inside the lock - // So that it will not raise OperationCanceledException, which is not expected by the caller.` + // So that it will not raise OperationCanceledException, which is not expected by the caller. Context.API.LogDebug(ClassName, "Preparing UWP programs"); List uwps; await _uwpsLock.WaitAsync(); From 49f89e33b5127a434bd903265cf7cc977624d8ae Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Nov 2025 20:46:29 +0800 Subject: [PATCH 020/124] Make locking operations cancelable with tokens Updated `_semaphore.WaitAsync` in `EverythingAPI.cs` to accept a `CancellationToken` and handle `OperationCanceledException` gracefully, returning `false` instead of propagating the exception. Refactored locking mechanisms in `Main.cs` to use `CancellationToken` for `_win32sLock` and `_uwpsLock`. Added `try-catch` blocks to handle `OperationCanceledException` and ensure proper lock release. Methods now return `emptyResults` when operations are canceled. --- .../Search/Everything/EverythingAPI.cs | 12 +++++++---- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 20 ++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index d06fdfa98..eccbb2bf9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -48,13 +48,17 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public static async ValueTask IsEverythingRunningAsync(CancellationToken token = default) { - // We do not directly pass token here, but we check IsCancellationRequested inside the lock - // So that it will not raise OperationCanceledException, which is not expected by the caller. - await _semaphore.WaitAsync(); + try + { + await _semaphore.WaitAsync(token); + } + catch (OperationCanceledException) + { + return false; + } try { - if (token.IsCancellationRequested) return false; _ = EverythingApiDllImport.Everything_GetMajorVersion(); var result = EverythingApiDllImport.Everything_GetLastError() != StateCode.IPCError; return result; diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index aac5de2c2..a0f418fe0 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -84,35 +84,31 @@ namespace Flow.Launcher.Plugin.Program { var resultList = await Task.Run(async () => { - // We do not directly pass token here, but we check IsCancellationRequested inside the lock - // So that it will not raise OperationCanceledException, which is not expected by the caller. Context.API.LogDebug(ClassName, "Preparing win32 programs"); List win32s; - await _win32sLock.WaitAsync(); try { + await _win32sLock.WaitAsync(token); win32s = [.. _win32s]; - if (token.IsCancellationRequested) return emptyResults; } - finally + catch (OperationCanceledException) { - _win32sLock.Release(); + return emptyResults; } + _win32sLock.Release(); - // We do not directly pass token here, but we check IsCancellationRequested inside the lock - // So that it will not raise OperationCanceledException, which is not expected by the caller. Context.API.LogDebug(ClassName, "Preparing UWP programs"); List uwps; - await _uwpsLock.WaitAsync(); try { + await _uwpsLock.WaitAsync(token); uwps = [.. _uwps]; - if (token.IsCancellationRequested) return emptyResults; } - finally + catch (OperationCanceledException) { - _uwpsLock.Release(); + return emptyResults; } + _uwpsLock.Release(); Context.API.LogDebug(ClassName, "Start querying programs"); try From 88fd1e56d030a3de62eac30be9f805db4885c660 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Nov 2025 20:47:54 +0800 Subject: [PATCH 021/124] Handle OperationCanceledException gracefully Added a `catch` block for `OperationCanceledException` in `PluginsManifest.cs` to ignore canceled operations. Updated `EverythingAPI.cs` to use cancellation tokens with `_semaphore.WaitAsync` and handle cancellations by exiting the method cleanly with `yield break`. --- Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs | 4 ++++ .../Search/Everything/EverythingAPI.cs | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index eab9a8c43..568dbb4bd 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -54,6 +54,10 @@ namespace Flow.Launcher.Core.ExternalPlugins return true; } } + catch (OperationCanceledException) + { + // Ignored + } catch (Exception e) { PublicApi.Instance.LogException(ClassName, "Http request failed", e); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index eccbb2bf9..d49080280 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -84,7 +84,14 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything if (option.MaxCount < 0) throw new ArgumentOutOfRangeException(nameof(option.MaxCount), option.MaxCount, "MaxCount must be greater than or equal to 0"); - await _semaphore.WaitAsync(); + try + { + await _semaphore.WaitAsync(token); + } + catch (OperationCanceledException) + { + yield break; + } try { From 05c8dd2fe11755b9982ad5305824aa710ad9e441 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Nov 2025 20:48:41 +0800 Subject: [PATCH 022/124] Remove unnecessary debug information --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index a0f418fe0..6b532d901 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -84,7 +84,7 @@ namespace Flow.Launcher.Plugin.Program { var resultList = await Task.Run(async () => { - Context.API.LogDebug(ClassName, "Preparing win32 programs"); + // Preparing win32 programs List win32s; try { @@ -97,7 +97,7 @@ namespace Flow.Launcher.Plugin.Program } _win32sLock.Release(); - Context.API.LogDebug(ClassName, "Preparing UWP programs"); + // Preparing UWP programs List uwps; try { @@ -110,7 +110,7 @@ namespace Flow.Launcher.Plugin.Program } _uwpsLock.Release(); - Context.API.LogDebug(ClassName, "Start querying programs"); + // Start querying programs try { // Collect all UWP Windows app directories @@ -325,7 +325,6 @@ namespace Flow.Launcher.Plugin.Program public static async Task IndexWin32ProgramsAsync() { await _win32sLock.WaitAsync(); - Context.API.LogDebug(ClassName, "Start indexing Win32 programs"); try { var win32S = Win32.All(_settings); @@ -354,7 +353,6 @@ namespace Flow.Launcher.Plugin.Program public static async Task IndexUwpProgramsAsync() { await _uwpsLock.WaitAsync(); - Context.API.LogDebug(ClassName, "Start indexing Uwp programs"); try { var uwps = UWPPackage.All(_settings); @@ -392,7 +390,6 @@ namespace Flow.Launcher.Plugin.Program await Context.API.StopwatchLogInfoAsync(ClassName, "UWPProgram index cost", IndexUwpProgramsAsync); }); - Context.API.LogDebug(ClassName, "Start indexing"); await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false); } From 2adbc334a2d20ff5f68808484725a02a6c2662f6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 7 Nov 2025 15:30:07 +0800 Subject: [PATCH 023/124] Improve semaphore lock handling and code robustness Added `lockAcquired` flags in `PluginsManifest.cs` and `Main.cs` to ensure semaphore locks are only released if successfully acquired, preventing potential runtime errors. Updated `finally` blocks to conditionally release locks based on these flags. Removed redundant cancellation check in `EverythingAPI.cs` to simplify code, assuming cancellation is handled elsewhere. These changes enhance reliability and maintainability of the codebase. --- .../ExternalPlugins/PluginsManifest.cs | 5 ++++- .../Search/Everything/EverythingAPI.cs | 2 -- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 16 ++++++++++++++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index 568dbb4bd..4fed10d25 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -26,9 +26,11 @@ namespace Flow.Launcher.Core.ExternalPlugins public static async Task UpdateManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default) { + bool lockAcquired = false; try { await manifestUpdateLock.WaitAsync(token).ConfigureAwait(false); + lockAcquired = true; if (UserPlugins == null || usePrimaryUrlOnly || DateTime.Now.Subtract(lastFetchedAt) >= fetchTimeout) { @@ -64,7 +66,8 @@ namespace Flow.Launcher.Core.ExternalPlugins } finally { - manifestUpdateLock.Release(); + // Only release the lock if it was acquired + if (lockAcquired) manifestUpdateLock.Release(); } return false; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index d49080280..a4e959dd9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -133,8 +133,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything EverythingApiDllImport.Everything_SetRequestFlags(EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME); } - - if (token.IsCancellationRequested) yield break; if (!EverythingApiDllImport.Everything_QueryW(true)) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 6b532d901..456085fca 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -86,29 +86,41 @@ namespace Flow.Launcher.Plugin.Program { // Preparing win32 programs List win32s; + bool win32LockAcquired = false; try { await _win32sLock.WaitAsync(token); + win32LockAcquired = true; win32s = [.. _win32s]; } catch (OperationCanceledException) { return emptyResults; } - _win32sLock.Release(); + finally + { + // Only release the lock if it was acquired + if (win32LockAcquired) _win32sLock.Release(); + } // Preparing UWP programs List uwps; + bool uwpsLockAcquired = false; try { await _uwpsLock.WaitAsync(token); + uwpsLockAcquired = true; uwps = [.. _uwps]; } catch (OperationCanceledException) { return emptyResults; } - _uwpsLock.Release(); + finally + { + // Only release the lock if it was acquired + if (uwpsLockAcquired) _uwpsLock.Release(); + } // Start querying programs try From 3492aac2c0e6a8d51df2bde23bfc732555e4d4b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 22:07:56 +0000 Subject: [PATCH 024/124] Bump Microsoft.Data.Sqlite from 9.0.10 to 10.0.0 --- updated-dependencies: - dependency-name: Microsoft.Data.Sqlite dependency-version: 10.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .../Flow.Launcher.Plugin.BrowserBookmark.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 8f0dfb4f5..ba547c86a 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -105,7 +105,7 @@ - + From f1b80ab90f6da2cc7c8a9256ade99d3e2f7c38c3 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Fri, 14 Nov 2025 17:54:45 +0900 Subject: [PATCH 025/124] Add new sponsor to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 49331decf..f2f7a495d 100644 --- a/README.md +++ b/README.md @@ -362,6 +362,7 @@ Or download the [early access version](https://github.com/Flow-Launcher/Prerelea + From 05f15d983196f666e165666cf608235f25d4947f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 18 Nov 2025 22:19:02 +0800 Subject: [PATCH 026/124] Upgrade iNKORE.UI.WPF.Modern and refactor scroll logic Upgraded `iNKORE.UI.WPF.Modern` to version `0.10.2.1` and replaced the custom `CustomScrollViewerEx` implementation with the built-in `ScrollViewerEx` for simplified scrolling behavior. Updated `Flow.Launcher.Plugin` to version `5.1.0` for compatibility. Removed unused namespaces and adjusted styles in `Base.xaml` to align with the new `ScrollViewerEx` usage. --- Flow.Launcher/Flow.Launcher.csproj | 2 +- .../Controls/CustomScrollViewerEx.cs | 253 ------------------ Flow.Launcher/Themes/Base.xaml | 12 +- Flow.Launcher/packages.lock.json | 10 +- 4 files changed, 13 insertions(+), 264 deletions(-) delete mode 100644 Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 576bf6f2f..f3c614702 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -138,7 +138,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs b/Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs deleted file mode 100644 index 78985108c..000000000 --- a/Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs +++ /dev/null @@ -1,253 +0,0 @@ -using iNKORE.UI.WPF.Modern.Controls; -using iNKORE.UI.WPF.Modern.Controls.Helpers; -using iNKORE.UI.WPF.Modern.Controls.Primitives; -using System; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; - -namespace Flow.Launcher.Resources.Controls -{ - // TODO: Use IsScrollAnimationEnabled property in future: https://github.com/iNKORE-NET/UI.WPF.Modern/pull/347 - public class CustomScrollViewerEx : ScrollViewer - { - private double LastVerticalLocation = 0; - private double LastHorizontalLocation = 0; - - public CustomScrollViewerEx() - { - Loaded += OnLoaded; - var valueSource = DependencyPropertyHelper.GetValueSource(this, AutoPanningMode.IsEnabledProperty).BaseValueSource; - if (valueSource == BaseValueSource.Default) - { - AutoPanningMode.SetIsEnabled(this, true); - } - } - - #region Orientation - - public static readonly DependencyProperty OrientationProperty = - DependencyProperty.Register( - nameof(Orientation), - typeof(Orientation), - typeof(CustomScrollViewerEx), - new PropertyMetadata(Orientation.Vertical)); - - public Orientation Orientation - { - get => (Orientation)GetValue(OrientationProperty); - set => SetValue(OrientationProperty, value); - } - - #endregion - - #region AutoHideScrollBars - - public static readonly DependencyProperty AutoHideScrollBarsProperty = - ScrollViewerHelper.AutoHideScrollBarsProperty - .AddOwner( - typeof(CustomScrollViewerEx), - new PropertyMetadata(true, OnAutoHideScrollBarsChanged)); - - public bool AutoHideScrollBars - { - get => (bool)GetValue(AutoHideScrollBarsProperty); - set => SetValue(AutoHideScrollBarsProperty, value); - } - - private static void OnAutoHideScrollBarsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is CustomScrollViewerEx sv) - { - sv.UpdateVisualState(); - } - } - - #endregion - - private void OnLoaded(object sender, RoutedEventArgs e) - { - LastVerticalLocation = VerticalOffset; - LastHorizontalLocation = HorizontalOffset; - UpdateVisualState(false); - } - - /// - protected override void OnInitialized(EventArgs e) - { - base.OnInitialized(e); - - if (Style == null && ReadLocalValue(StyleProperty) == DependencyProperty.UnsetValue) - { - SetResourceReference(StyleProperty, typeof(ScrollViewer)); - } - } - - /// - protected override void OnMouseWheel(MouseWheelEventArgs e) - { - var Direction = GetDirection(); - ScrollViewerBehavior.SetIsAnimating(this, true); - - if (Direction == Orientation.Vertical) - { - if (ScrollableHeight > 0) - { - e.Handled = true; - } - - var WheelChange = e.Delta * (ViewportHeight / 1.5) / ActualHeight; - var newOffset = LastVerticalLocation - WheelChange; - - if (newOffset < 0) - { - newOffset = 0; - } - - if (newOffset > ScrollableHeight) - { - newOffset = ScrollableHeight; - } - - if (newOffset == LastVerticalLocation) - { - return; - } - - ScrollToVerticalOffset(LastVerticalLocation); - - ScrollToValue(newOffset, Direction); - LastVerticalLocation = newOffset; - } - else - { - if (ScrollableWidth > 0) - { - e.Handled = true; - } - - var WheelChange = e.Delta * (ViewportWidth / 1.5) / ActualWidth; - var newOffset = LastHorizontalLocation - WheelChange; - - if (newOffset < 0) - { - newOffset = 0; - } - - if (newOffset > ScrollableWidth) - { - newOffset = ScrollableWidth; - } - - if (newOffset == LastHorizontalLocation) - { - return; - } - - ScrollToHorizontalOffset(LastHorizontalLocation); - - ScrollToValue(newOffset, Direction); - LastHorizontalLocation = newOffset; - } - } - - /// - protected override void OnScrollChanged(ScrollChangedEventArgs e) - { - base.OnScrollChanged(e); - if (!ScrollViewerBehavior.GetIsAnimating(this)) - { - LastVerticalLocation = VerticalOffset; - LastHorizontalLocation = HorizontalOffset; - } - } - - private Orientation GetDirection() - { - var isShiftDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift); - - if (Orientation == Orientation.Horizontal) - { - return isShiftDown ? Orientation.Vertical : Orientation.Horizontal; - } - else - { - return isShiftDown ? Orientation.Horizontal : Orientation.Vertical; - } - } - - /// - /// Causes the to load a new view into the viewport using the specified offsets and zoom factor. - /// - /// A value between 0 and that specifies the distance the content should be scrolled horizontally. - /// A value between 0 and that specifies the distance the content should be scrolled vertically. - /// A value between MinZoomFactor and MaxZoomFactor that specifies the required target ZoomFactor. - /// if the view is changed; otherwise, . - public bool ChangeView(double? horizontalOffset, double? verticalOffset, float? zoomFactor) - { - return ChangeView(horizontalOffset, verticalOffset, zoomFactor, false); - } - - /// - /// Causes the to load a new view into the viewport using the specified offsets and zoom factor, and optionally disables scrolling animation. - /// - /// A value between 0 and that specifies the distance the content should be scrolled horizontally. - /// A value between 0 and that specifies the distance the content should be scrolled vertically. - /// A value between MinZoomFactor and MaxZoomFactor that specifies the required target ZoomFactor. - /// to disable zoom/pan animations while changing the view; otherwise, . The default is false. - /// if the view is changed; otherwise, . - public bool ChangeView(double? horizontalOffset, double? verticalOffset, float? zoomFactor, bool disableAnimation) - { - if (disableAnimation) - { - if (horizontalOffset.HasValue) - { - ScrollToHorizontalOffset(horizontalOffset.Value); - } - - if (verticalOffset.HasValue) - { - ScrollToVerticalOffset(verticalOffset.Value); - } - } - else - { - if (horizontalOffset.HasValue) - { - ScrollToHorizontalOffset(LastHorizontalLocation); - ScrollToValue(Math.Min(ScrollableWidth, horizontalOffset.Value), Orientation.Horizontal); - LastHorizontalLocation = horizontalOffset.Value; - } - - if (verticalOffset.HasValue) - { - ScrollToVerticalOffset(LastVerticalLocation); - ScrollToValue(Math.Min(ScrollableHeight, verticalOffset.Value), Orientation.Vertical); - LastVerticalLocation = verticalOffset.Value; - } - } - - return true; - } - - private void ScrollToValue(double value, Orientation Direction) - { - if (Direction == Orientation.Vertical) - { - ScrollToVerticalOffset(value); - } - else - { - ScrollToHorizontalOffset(value); - } - - ScrollViewerBehavior.SetIsAnimating(this, false); - } - - private void UpdateVisualState(bool useTransitions = true) - { - var stateName = AutoHideScrollBars ? "NoIndicator" : "MouseIndicator"; - VisualStateManager.GoToState(this, stateName, useTransitions); - } - } -} diff --git a/Flow.Launcher/Themes/Base.xaml b/Flow.Launcher/Themes/Base.xaml index c5b45890b..c3831e68f 100644 --- a/Flow.Launcher/Themes/Base.xaml +++ b/Flow.Launcher/Themes/Base.xaml @@ -252,12 +252,14 @@ - - - - + - + diff --git a/Flow.Launcher/packages.lock.json b/Flow.Launcher/packages.lock.json index b4b929d19..8c3a16e5e 100644 --- a/Flow.Launcher/packages.lock.json +++ b/Flow.Launcher/packages.lock.json @@ -28,9 +28,9 @@ }, "iNKORE.UI.WPF.Modern": { "type": "Direct", - "requested": "[0.10.1, )", - "resolved": "0.10.1", - "contentHash": "nRYmBosiL+42eUpLbHeqP7qJqtp5EpzuIMZTpvq4mFV33VB/JjkFg1y82gk50pjkXlAQWDvRyrfSAmPR5AM+3g==", + "requested": "[0.10.2.1, )", + "resolved": "0.10.2.1", + "contentHash": "nGwuuVul+TcLCTgPmaAZCc0fYFqUpCNZ8PiulVT3gZnsWt/AvxMZ0DSPpuyI/iRPc/NhFIg9lSIR7uaHWV0I/Q==", "dependencies": { "iNKORE.UI.WPF": "1.2.8" } @@ -1619,7 +1619,7 @@ "FSharp.Core": "[9.0.303, )", "Flow.Launcher.Infrastructure": "[1.0.0, )", "Flow.Launcher.Localization": "[0.0.6, )", - "Flow.Launcher.Plugin": "[5.0.0, )", + "Flow.Launcher.Plugin": "[5.1.0, )", "Meziantou.Framework.Win32.Jobs": "[3.4.5, )", "Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )", "SemanticVersioning": "[3.0.0, )", @@ -1634,7 +1634,7 @@ "BitFaster.Caching": "[2.5.4, )", "CommunityToolkit.Mvvm": "[8.4.0, )", "Flow.Launcher.Localization": "[0.0.6, )", - "Flow.Launcher.Plugin": "[5.0.0, )", + "Flow.Launcher.Plugin": "[5.1.0, )", "InputSimulator": "[1.0.4, )", "MemoryPack": "[1.21.4, )", "Microsoft.VisualStudio.Threading": "[17.14.15, )", From a773b51adafa2f31712388ce5c9af28a196ec529 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Thu, 20 Nov 2025 04:16:09 +0800 Subject: [PATCH 027/124] Handle recoverable DWM composition exceptions gracefully (#4113) --- Flow.Launcher/Helper/ErrorReporting.cs | 9 ++++++ Flow.Launcher/Helper/ExceptionHelper.cs | 42 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 Flow.Launcher/Helper/ExceptionHelper.cs diff --git a/Flow.Launcher/Helper/ErrorReporting.cs b/Flow.Launcher/Helper/ErrorReporting.cs index e201284cb..797f31482 100644 --- a/Flow.Launcher/Helper/ErrorReporting.cs +++ b/Flow.Launcher/Helper/ErrorReporting.cs @@ -16,6 +16,15 @@ public static class ErrorReporting var logger = LogManager.GetLogger(methodName); logger.Fatal(ExceptionFormatter.FormatExcpetion(e)); if (silent) return; + + // Workaround for issue https://github.com/Flow-Launcher/Flow.Launcher/issues/4016 + // The crash occurs in PresentationFramework.dll, not necessarily when the Runner UI is visible, originating from this line: + // https://github.com/dotnet/wpf/blob/3439f20fb8c685af6d9247e8fd2978cac42e74ac/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Shell/WindowChromeWorker.cs#L1005 + // Many bug reports because users see the "Error report UI" after the crash with System.Runtime.InteropServices.COMException 0xD0000701 or 0x80263001. + // However, displaying this "Error report UI" during WPF crashes, especially when DWM composition is changing, is not ideal; some users reported it hangs for up to a minute before the it appears. + // This change modifies the behavior to log the exception instead of showing the "Error report UI". + if (ExceptionHelper.IsRecoverableDwmCompositionException(e)) return; + var reportWindow = new ReportWindow(e); reportWindow.Show(); } diff --git a/Flow.Launcher/Helper/ExceptionHelper.cs b/Flow.Launcher/Helper/ExceptionHelper.cs new file mode 100644 index 000000000..5dd57f9bb --- /dev/null +++ b/Flow.Launcher/Helper/ExceptionHelper.cs @@ -0,0 +1,42 @@ +// This is a direct copy of the file at https://github.com/microsoft/PowerToys/blob/main/src/modules/launcher/PowerLauncher/Helper/ExceptionHelper.cs and adapted for flow. + +using System; +using System.Runtime.InteropServices; + +namespace Flow.Launcher.Helper; + +internal static class ExceptionHelper +{ + private const string PresentationFrameworkExceptionSource = "PresentationFramework"; + + private const int DWM_E_COMPOSITIONDISABLED = unchecked((int)0x80263001); + + // HRESULT for NT STATUS STATUS_MESSAGE_LOST (0xC0000701 | 0x10000000 == 0xD0000701) + private const int STATUS_MESSAGE_LOST_HR = unchecked((int)0xD0000701); + + /// + /// Returns true if the exception is a recoverable DWM composition exception. + /// + internal static bool IsRecoverableDwmCompositionException(Exception exception) + { + if (exception is not COMException comException) + { + return false; + } + + if (comException.HResult is DWM_E_COMPOSITIONDISABLED) + { + return true; + } + + if (comException.HResult is STATUS_MESSAGE_LOST_HR && comException.Source == PresentationFrameworkExceptionSource) + { + return true; + } + + // Check for common DWM composition changed patterns in the stack trace + var stackTrace = comException.StackTrace; + return !string.IsNullOrEmpty(stackTrace) && + stackTrace.Contains("DwmCompositionChanged", StringComparison.OrdinalIgnoreCase); + } +} From 7958b17968ac1936ea171037e96c446efd058c93 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 20 Nov 2025 21:02:19 +1100 Subject: [PATCH 028/124] wip show result icon --- Flow.Launcher.Plugin/Result.cs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 2c9b8d4fd..0f118e36d 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -90,6 +90,34 @@ namespace Flow.Launcher.Plugin } } + /// + /// Returns the plugin directory relative IcoPath or URL. This path is useful for storage where the it needs + /// to be resistant to changes in plugin location from update or portable mode change. + /// + /// Must be a local file path. + /// This will be empty string if IcoPath is a URL, so must check for empty string during usage + public string IcoPathRelative + { + get => _icoPath; + set + { + // As a standard this property will handle prepping and converting to absolute local path for icon image processing + if (!string.IsNullOrEmpty(value) + && !string.IsNullOrEmpty(PluginDirectory) + && !Path.IsPathRooted(value) + && !value.StartsWith("http://", StringComparison.OrdinalIgnoreCase) + && !value.StartsWith("https://", StringComparison.OrdinalIgnoreCase) + && !value.StartsWith("data:image", StringComparison.OrdinalIgnoreCase)) + { + _icoPath = Path.Combine(PluginDirectory, value); + } + else + { + _icoPath = value; + } + } + } + /// /// The image to be displayed for the badge of the result. /// From 533a58d08383ca0bd85494a19b0c36108dcf749e Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 20 Nov 2025 21:26:31 +1100 Subject: [PATCH 029/124] New Crowdin updates (#4051) --- Flow.Launcher/Languages/ar.xaml | 10 +- Flow.Launcher/Languages/cs.xaml | 10 +- Flow.Launcher/Languages/da.xaml | 10 +- Flow.Launcher/Languages/de.xaml | 10 +- Flow.Launcher/Languages/es-419.xaml | 10 +- Flow.Launcher/Languages/es.xaml | 10 +- Flow.Launcher/Languages/fr.xaml | 38 +++++--- Flow.Launcher/Languages/he.xaml | 10 +- Flow.Launcher/Languages/it.xaml | 10 +- Flow.Launcher/Languages/ja.xaml | 10 +- Flow.Launcher/Languages/ko.xaml | 10 +- Flow.Launcher/Languages/nb.xaml | 10 +- Flow.Launcher/Languages/nl.xaml | 10 +- Flow.Launcher/Languages/pl.xaml | 10 +- Flow.Launcher/Languages/pt-br.xaml | 14 ++- Flow.Launcher/Languages/pt-pt.xaml | 10 +- Flow.Launcher/Languages/ru.xaml | 10 +- Flow.Launcher/Languages/sk.xaml | 18 +++- Flow.Launcher/Languages/sr-Cyrl-RS.xaml | 10 +- Flow.Launcher/Languages/sr.xaml | 10 +- Flow.Launcher/Languages/tr.xaml | 10 +- Flow.Launcher/Languages/uk-UA.xaml | 16 +++- Flow.Launcher/Languages/vi.xaml | 10 +- Flow.Launcher/Languages/zh-cn.xaml | 16 +++- Flow.Launcher/Languages/zh-tw.xaml | 14 ++- .../Languages/zh-cn.xaml | 2 +- .../Languages/zh-tw.xaml | 10 +- .../Languages/ja.xaml | 10 +- .../Languages/uk-UA.xaml | 2 +- .../Languages/zh-tw.xaml | 4 +- .../Languages/zh-tw.xaml | 2 +- .../Languages/zh-tw.xaml | 2 +- .../Languages/uk-UA.xaml | 6 +- .../Languages/zh-tw.xaml | 2 +- .../Languages/es.xaml | 8 +- .../Languages/ja.xaml | 12 +-- .../Languages/tr.xaml | 8 +- .../Languages/uk-UA.xaml | 8 +- .../Languages/es.xaml | 2 +- .../Languages/ja.xaml | 2 +- .../Languages/tr.xaml | 2 +- .../Languages/uk-UA.xaml | 2 +- .../Properties/Resources.ja-JP.resx | 96 +++++++++---------- .../Properties/Resources.sk-SK.resx | 2 +- 44 files changed, 344 insertions(+), 144 deletions(-) diff --git a/Flow.Launcher/Languages/ar.xaml b/Flow.Launcher/Languages/ar.xaml index 7dcfcdb09..67f1f766e 100644 --- a/Flow.Launcher/Languages/ar.xaml +++ b/Flow.Launcher/Languages/ar.xaml @@ -64,6 +64,10 @@ إعادة تعيين الموقع Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info الإعدادات @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ الأيقونات لقد قمت بتفعيل Flow Launcher {0} مرات التحقق من التحديثات - كن راعيا + Become a Sponsor الإصدار الجديد {0} متاح، هل ترغب في إعادة تشغيل Flow Launcher لاستخدام التحديث فشل التحقق من التحديثات، يرجى التحقق من الاتصال وإعدادات البروكسي لـ api.github.com. diff --git a/Flow.Launcher/Languages/cs.xaml b/Flow.Launcher/Languages/cs.xaml index d08653a04..96cbe95e7 100644 --- a/Flow.Launcher/Languages/cs.xaml +++ b/Flow.Launcher/Languages/cs.xaml @@ -64,6 +64,10 @@ Obnovit pozici Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Nastavení @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Ikony Flow Launcher byl aktivován {0} krát Zkontrolovat Aktualizace - Staňte se sponzorem + Become a Sponsor Je k dispozici nová verze {0}, chcete Flow Launcher restartovat, aby se mohl aktualizovat? Hledání aktualizací se nezdařilo, zkontrolujte prosím své internetové připojení a nastavení proxy serveru k api.github.com. diff --git a/Flow.Launcher/Languages/da.xaml b/Flow.Launcher/Languages/da.xaml index 7ad686fe8..a1fc771d2 100644 --- a/Flow.Launcher/Languages/da.xaml +++ b/Flow.Launcher/Languages/da.xaml @@ -64,6 +64,10 @@ Position Reset Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Indstillinger @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Icons Du har aktiveret Flow Launcher {0} gange Tjek for opdateringer - Become A Sponsor + Become a Sponsor Ny version {0} er tilgængelig, genstart venligst Flow Launcher Check updates failed, please check your connection and proxy settings to api.github.com. diff --git a/Flow.Launcher/Languages/de.xaml b/Flow.Launcher/Languages/de.xaml index 064ac4038..2c083646f 100644 --- a/Flow.Launcher/Languages/de.xaml +++ b/Flow.Launcher/Languages/de.xaml @@ -64,6 +64,10 @@ Zurücksetzen der Position Position des Suchfensters zurücksetzen Zum Suchen hier tippen + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Einstellungen @@ -171,6 +175,10 @@ Ergebnisse der Homepage zeigen, wenn Abfragetext leer ist. Historie-Ergebnisse auf Homepage zeigen Maximal gezeigte Historie-Ergebnisse auf Homepage + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history Dies kann nur bearbeitet werden, wenn das Plug-in das Home-Feature unterstützt und die Homepage aktiviert ist. Suchfenster an vorderster zeigen Setzt die Einstellung 'Immer im Vordergrund' anderer Programme außer Kraft und zeigt Flow in der vordersten Position an. @@ -446,7 +454,7 @@ Icons Sie haben Flow Launcher {0} mal aktiviert Nach Updates suchen - Ein Sponsor werden + Become a Sponsor Neue Version {0} ist verfügbar. Möchten Sie Flow Launcher neu starten, um das Update zu verwenden? Überprüfung der Updates fehlgeschlagen. Bitte überprüfen Sie Ihre Verbindungs- und Proxy-Einstellungen zu api.github.com. diff --git a/Flow.Launcher/Languages/es-419.xaml b/Flow.Launcher/Languages/es-419.xaml index 8554f3847..9f06c4436 100644 --- a/Flow.Launcher/Languages/es-419.xaml +++ b/Flow.Launcher/Languages/es-419.xaml @@ -64,6 +64,10 @@ Position Reset Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Ajustes @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Icons Has activado Flow Launcher {0} veces Buscar actualizaciones - Become A Sponsor + Become a Sponsor La nueva versión {0} está disponible, ¿desea reiniciar Flow Launcher para usar la actualización? Falló la comprobación de actualizaciones, compruebe su conexión y configuración de proxy a api.github.com. diff --git a/Flow.Launcher/Languages/es.xaml b/Flow.Launcher/Languages/es.xaml index be00fac94..f7a3fbb22 100644 --- a/Flow.Launcher/Languages/es.xaml +++ b/Flow.Launcher/Languages/es.xaml @@ -64,6 +64,10 @@ Restablecer posición Restablece la posición de la ventana de búsqueda Escribir aquí para buscar + {0}: Este complemento aún se está inicializando... + Seleccione este resultado para volver a realizar la consulta + {0}: ¡No se ha recibido respuesta! + Seleccione este resultado para más información Configuración @@ -171,6 +175,10 @@ Muestra los resultados de la página de inicio cuando el texto de la consulta está vacío. Mostrar historial de resultados en la página de inicio Número máximo de resultados del historial en la página de inicio + Estilo del historial + Elija el tipo de historial que desea mostrar en el historial y la página de inicio + Historial de consultas + Historial de últimas aperturas Esto solo se puede editar si el complemento soporta la función de Inicio y la Página de Inicio está activada. Mostrar ventana de búsqueda en primer plano Anula el ajuste «Siempre arriba» de otros programas y muestra Flow en primer plano. @@ -446,7 +454,7 @@ Iconos Ha activado Flow Launcher {0} veces Buscar actualizaciones - Hágase Patrocinador + Conviértase en Patrocinador La nueva versión {0} está disponible, ¿desea reiniciar Flow Launcher para actualizar? Ha fallado la comprobación de las actualizaciones, por favor, compruebe la configuración de su proxy y conexión a api.github.com. diff --git a/Flow.Launcher/Languages/fr.xaml b/Flow.Launcher/Languages/fr.xaml index b9ac0de4b..bdce6ddb9 100644 --- a/Flow.Launcher/Languages/fr.xaml +++ b/Flow.Launcher/Languages/fr.xaml @@ -64,6 +64,10 @@ Réinitialiser la position Réinitialiser la position de la fenêtre de recherche Tapez ici pour rechercher + {0}: Ce plugin est toujours en cours d'initialisation... + Sélectionner ce résultat pour la requête + {0}: Ne répond pas ! + Sélectionnez ce résultat pour plus d'informations Paramètres @@ -171,6 +175,10 @@ Afficher les résultats de la page d'accueil lorsque le texte de la requête est vide. Afficher les résultats de l'historique sur la page d'accueil Maximum de résultats de l'historique affichés sur la page d'accueil + Style d'historique + Choisissez le type d'historique à afficher dans l'historique et la page d'accueil + Historique des requêtes + Historique des dernières ouvertures Ceci ne peut être édité que si le plugin prend en charge la fonction Accueil et que la page d'accueil est activée. Afficher la fenêtre de recherche en premier plan Outrepasse le paramètre 'toujours en premier plan' des autres programmes et affiche Flow Launcher en première position. @@ -399,24 +407,24 @@ Pour les plugins pris en charge, des badges sont affichés afin de les distinguer plus facilement. Afficher les badges de résultats pour la requête globale uniquement Afficher les badges pour les résultats des requêtes globales uniquement - Dialog Jump + Saut de dialogue Entrez le raccourci pour naviguer rapidement dans la fenêtre de dialogue Ouvrir/Enregistrer sous, vers le chemin du gestionnaire de fichiers actuel. - Dialog Jump + Saut de dialogue Lorsque la fenêtre de dialogue Ouvrir/Enregistrer sous s'ouvre, accédez rapidement au chemin d'accès actuel du gestionnaire de fichiers. - Dialog Jump Automatically + Saut de dialogue automatique Lorsque la fenêtre de dialogue Ouvrir/Enregistrer sous est affichée, naviguez automatiquement vers le chemin du gestionnaire de fichiers actuel. (Expérimental) - Show Dialog Jump Window - Display Dialog Jump search window when the open/save dialog window is shown to quickly navigate to file/folder locations. - Dialog Jump Window Position - Select position for the Dialog Jump search window - Fixed under the Open/Save As dialog window. Displayed on open and stays until the window is closed - Default search window position. Displayed when triggered by search window hotkey - Dialog Jump Result Navigation Behaviour - Behaviour to navigate Open/Save As dialog window to the selected result path - Left click or Enter key + Afficher la fenêtre de saut de dialogue + Afficher la fenêtre de recherche de saut de dialogue lorsque la fenêtre de dialogue Ouvrir/Enregistrer sous est affichée pour naviguer rapidement vers les emplacements de fichier/dossier. + Position de la fenêtre de saut de dialogue + Sélectionnez la position pour la fenêtre de recherche de saut de dialogue + Fixé sous la fenêtre de dialogue Ouvrir/Enregistrer sous. Affiché à l'ouverture et reste jusqu'à ce que la fenêtre soit fermée. + Position de la fenêtre de recherche par défaut. Affiché lorsqu'il est déclenché par le raccourci clavier de la fenêtre de recherche + Comportement de navigation des résultats du saut de dialogue + Comportement pour naviguer dans la fenêtre de dialogue Ouvrir/Enregistrer sous vers le chemin de résultat sélectionné + Clic gauche ou touche Entrée Clique droit - Dialog Jump File Navigation Behaviour - Behaviour to navigate Open/Save As dialog window when the result is a file path + Comportement de navigation des résultats du saut de dialogue + Comportement pour naviguer dans la fenêtre de dialogue Ouvrir/Enregistrer sous lorsque le résultat est un chemin de fichier Remplir le chemin complet dans la zone de nom de fichier Remplir le chemin complet dans la zone de nom de fichier et ouvrir Remplir le répertoire dans la zone de chemin @@ -446,7 +454,7 @@ Icônes Vous avez utilisé Flow Launcher {0} fois Vérifier les mises à jour - Devenir un Sponsor + Devenez un sponsor Nouvelle version {0} disponible, souhaitez-vous redémarrer Flow Launcher pour l'installer ? Échec de la vérification de la mise à jour, vérifiez votre connexion et vos paramètres de configuration proxy pour pouvoir acceder à api.github.com. diff --git a/Flow.Launcher/Languages/he.xaml b/Flow.Launcher/Languages/he.xaml index ca69ddb50..39f02c702 100644 --- a/Flow.Launcher/Languages/he.xaml +++ b/Flow.Launcher/Languages/he.xaml @@ -64,6 +64,10 @@ איפוס מיקום אפס את מיקום חלון החיפוש הקלד כאן כדי לחפש + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info הגדרות @@ -170,6 +174,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history ניתן לערוך זאת רק אם התוסף תומך בתכונת הבית ודף הבית מופעל. Show Search Window at Foremost עוקף את הגדרת תמיד עליון של תוכנות אחרות, ומציג את Flow במיקום הגבוה ביותר. @@ -445,7 +453,7 @@ סמלים הפעלת את Flow Launcher {0} פעמים בדוק עדכונים - תן חסות + Become a Sponsor גרסה חדשה {0} זמינה, האם ברצונך להפעיל מחדש את Flow Launcher כדי להשתמש בעדכון? בדיקת העדכונים נכשלה, אנא בדוק את הגדרות החיבור ואת הגדרות ה-Proxy שלך לכתובת api.github.com. diff --git a/Flow.Launcher/Languages/it.xaml b/Flow.Launcher/Languages/it.xaml index 01062bed0..ffb716658 100644 --- a/Flow.Launcher/Languages/it.xaml +++ b/Flow.Launcher/Languages/it.xaml @@ -64,6 +64,10 @@ Ripristina Posizione Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Impostazioni @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Icone Hai usato Flow Launcher {0} volte Cerca aggiornamenti - Diventa un sostenitore + Become a Sponsor Una nuova versione {0} è disponibile, riavvia Flow Launcher per favore. Ricerca aggiornamenti fallita, per favore controlla la tua connessione e le eventuali impostazioni proxy per api.github.com. diff --git a/Flow.Launcher/Languages/ja.xaml b/Flow.Launcher/Languages/ja.xaml index 206791821..51ec99ddd 100644 --- a/Flow.Launcher/Languages/ja.xaml +++ b/Flow.Launcher/Languages/ja.xaml @@ -64,6 +64,10 @@ 位置のリセット 検索ウィンドウの位置をリセット ここに入力して検索 + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info 設定 @@ -171,6 +175,10 @@ 検索文字列が空の場合、ホームページの結果を表示します。 クエリの履歴をホームページに表示 ホームページに表示される最大の履歴の数 + 履歴のスタイル + 履歴とホームページに表示する履歴の種類を選択します + クエリの履歴 + Last opened history これは、プラグインがホーム機能をサポートし、ホームページが有効な場合にのみ編集することができます。 検索ウィンドウを最前面に表示 他のプログラムの 'Always on Top' (最前面に表示)設定を上書きし、常に最前面のウィンドウで Flow を表示します。 @@ -446,7 +454,7 @@ アイコン あなたはFlow Launcherを {0} 回利用しました アップデートを確認する - スポンサーになる + Become a Sponsor 新しいバージョン {0} が利用可能です。Flow Launcherを再起動してください。 アップデートの確認に失敗しました、api.github.com への接続とプロキシ設定を確認してください。 diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml index 674cca7a7..503ff2f11 100644 --- a/Flow.Launcher/Languages/ko.xaml +++ b/Flow.Launcher/Languages/ko.xaml @@ -64,6 +64,10 @@ 창 위치 초기화 검색창 위치 초기화 검색어 입력 + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info 설정 @@ -162,6 +166,10 @@ 쿼리 입력창이 비어있을때, 홈페이지의 결과를 표시합니다. 히스토리를 홈페이지에 표시 홈페이지에 표시할 최대 히스토리 수 + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -437,7 +445,7 @@ 아이콘 Flow Launcher를 {0}번 실행했습니다. 업데이트 확인 - 후원하기 + Become a Sponsor 새 버전({0})이 있습니다. Flow Launcher를 재시작하세요. 업데이트 확인을 실패했습니다. api.github.com로의 연결 또는 프록시 설정을 확인해주세요. diff --git a/Flow.Launcher/Languages/nb.xaml b/Flow.Launcher/Languages/nb.xaml index 68e63e37e..8bd7f94a4 100644 --- a/Flow.Launcher/Languages/nb.xaml +++ b/Flow.Launcher/Languages/nb.xaml @@ -64,6 +64,10 @@ Tilbakestilling av posisjon Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Innstillinger @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Ikoner Du har aktivert Flow Launcher {0} ganger Se etter oppdateringer - Bli en sponsor + Become a Sponsor Ny versjon {0} er tilgjengelig, vil du starte Flow Launcher på nytt for å bruke oppdateringen? Sjekk oppdateringer mislyktes, vennligst sjekk tilkoblingen og proxy-innstillingene til api.github.com. diff --git a/Flow.Launcher/Languages/nl.xaml b/Flow.Launcher/Languages/nl.xaml index 69e2107bf..8b7b86329 100644 --- a/Flow.Launcher/Languages/nl.xaml +++ b/Flow.Launcher/Languages/nl.xaml @@ -64,6 +64,10 @@ Positie resetten Reset search window position Type om te zoeken + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Instellingen @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Pictogrammen U heeft Flow Launcher {0} keer opgestart Zoek naar Updates - Sponsor worden + Become a Sponsor Nieuwe versie {0} beschikbaar, start Flow Launcher opnieuw op Controleren op updates mislukt, controleer uw verbinding en proxy-instellingen voor api.github.com. diff --git a/Flow.Launcher/Languages/pl.xaml b/Flow.Launcher/Languages/pl.xaml index 5786f98ab..382626eb7 100644 --- a/Flow.Launcher/Languages/pl.xaml +++ b/Flow.Launcher/Languages/pl.xaml @@ -64,6 +64,10 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Resetowanie pozycji Zresetuj pozycję okna wyszukiwania Wpisz tutaj, aby wyszukać + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Ustawienia @@ -170,6 +174,10 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Wyświetl wyniki strony głównej, gdy pole wyszukiwania jest puste. Pokaż wyniki historii na stronie głównej Maksymalna liczba wyników historii wyświetlanych na stronie głównej + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history Można edytować tylko wtedy, gdy wtyczka obsługuje funkcję Strona główna i jest ona włączona. Wyświetl okno wyszukiwania na wierzchu Wyświetl okno wyszukiwania ponad innymi oknami @@ -445,7 +453,7 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Ikony Uaktywniłeś Flow Launcher {0} razy Szukaj aktualizacji - Zostań sponsorem + Become a Sponsor Nowa wersja {0} jest dostępna, uruchom ponownie Flow Launcher Sprawdzenie aktualizacji nie powiodło się. Sprawdź swoje połączenie i ustawienia proxy dla api.github.com. diff --git a/Flow.Launcher/Languages/pt-br.xaml b/Flow.Launcher/Languages/pt-br.xaml index 6127e839b..15dcae2f4 100644 --- a/Flow.Launcher/Languages/pt-br.xaml +++ b/Flow.Launcher/Languages/pt-br.xaml @@ -64,6 +64,10 @@ Redefinição de Posição Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Configurações @@ -90,7 +94,7 @@ Posição Personalizada Idioma Estilo da Última Consulta - Mostrar/ocultar resultados anteriores quando o Lançador de Fluxos é reativado. + Mostrar/ocultar resultados anteriores quando o Flow Launcher for reativado. Preservar Última Consulta Selecionar última consulta Limpar última consulta @@ -138,7 +142,7 @@ Xiao Lang Sempre Pré-visualizar - Sempre abrir o painel de pré-visualização quando o Flow é ativado. Pressione {0} para ativar ou desativar a pré-visualização. + Sempre abrir o painel de pré-visualização quando o Flow for ativado. Pressione {0} para alternar a pré-visualização. O efeito de sombra não é permitido enquanto o tema atual tem o efeito de desfoque ativado Search Delay Adds a short delay while typing to reduce UI flicker and result load. Recommended if your typing speed is average. @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Ícones Você ativou o Flow Launcher {0} vezes Procurar atualizações - Torne-se um Sponsor + Become a Sponsor A nova versão {0} está disponível, por favor reinicie o Flow Launcher. Falha ao procurar atualizações, confira sua conexão e configuração de proxy para api.github.com. diff --git a/Flow.Launcher/Languages/pt-pt.xaml b/Flow.Launcher/Languages/pt-pt.xaml index 2be609c99..3746ada13 100644 --- a/Flow.Launcher/Languages/pt-pt.xaml +++ b/Flow.Launcher/Languages/pt-pt.xaml @@ -64,6 +64,10 @@ Repor posição Repor posição da janela de pesquisa Escreva aqui para pesquisar + {0}: Este plugin está a ser iniciado... + Selecione este resultado para pesquisar novamente + {0}: Falha na resposta! + Selecione este resultado para mais informação Definições @@ -170,6 +174,10 @@ Mostrar resultados da página inicial se o termo de pesquisa estiver vazio. Mostrar histórico na página inicial Máximo de resultados a mostrar na Página inicial + Estilo do histórico + Escolha o tipo de histórico a ser mostrado no Histórico e na Página inicial + Histórico de pesquisas + Último histórico aberto Esta opção apenas pode ser editada se o plugin tiver suporte a Página inicial e se estiver ativo. Janela de pesquisa à frente Sobrepõe a definição 'Sempre na frente' das outras aplicações e mostra Flow Launcher à frente de qualquer janela. @@ -445,7 +453,7 @@ Ícones Ativou o Flow Launcher {0} vezes Procurar atualizações - Tornar-se patrocinador + Torne-se um Patrocinador Está disponível a versão {0}. Gostaria de reiniciar Flow Launcher para atualizar a sua versão? Erro ao procurar atualizações. Verifique a sua ligação e as definições do proxy estabelecidas para api.github.com diff --git a/Flow.Launcher/Languages/ru.xaml b/Flow.Launcher/Languages/ru.xaml index df7c9d994..7bb5a8ff1 100644 --- a/Flow.Launcher/Languages/ru.xaml +++ b/Flow.Launcher/Languages/ru.xaml @@ -64,6 +64,10 @@ Сброс положения Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Настройки @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Значки Вы воспользовались Flow Launcher уже {0} раз Проверить наличие обновлений - Стать спонсором + Become a Sponsor Доступна новая версия {0}. Вы хотите перезапустить Flow Launcher, чтобы использовать обновление? Проверка обновлений не удалась, пожалуйста, проверьте настройки подключения и прокси-сервера к api.github.com. diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml index a07613b13..e76061a3b 100644 --- a/Flow.Launcher/Languages/sk.xaml +++ b/Flow.Launcher/Languages/sk.xaml @@ -65,6 +65,10 @@ Nevykonali sa žiadne zmeny. Resetovať pozíciu Resetovať pozíciu vyhľadávacieho okna Zadajte text na vyhľadávanie + {0}: Tento plugin sa stále inicializuje… + Vyberte tento výsledok na opätovné vyhľadávanie + {0}: Nepodarilo sa odpovedať! + Vyberte tento výsledok pre viac informácií Nastavenia @@ -169,10 +173,14 @@ Nevykonali sa žiadne zmeny. Nepodarilo sa zmeniť nastavenie kórejského IME Skontrolujte prístup do systémového registra alebo kontaktujte podporu. Domovská stránka - Zobraziť výsledky Domovskej stránky, keď je text dopytu prázdny. - Zobraziť výsledky histórie na Domovskej stránke - Maximálny počet zobrazených výsledkov histórie na Domovskej stránke - Úprava je možná len vtedy, ak plugin podporuje funkciu Domovská stránka a Domovská stránka je povolená. + Zobraziť výsledky domovskej stránky, keď je text dopytu prázdny. + Zobraziť výsledky histórie na domovskej stránke + Maximálny počet histórie výsledkov zobrazenej na domovskej stránke + Štýl histórie + Vyberte, ktorý typ histórie sa má zobraziť v histórii a na domovskej stránke + História dopytov + História naposledy otvorených + Úprava je možná len vtedy, ak plugin podporuje funkciu domovská stránka a zároveň je povolená. Zobraziť vyhľadávacie okno v popredí Prepíše nastavenie "Vždy na vrchu" ostatných programov a zobrazí navrchu Flow. Reštartovať po úprave pluginu cez Repozitár pluginov @@ -535,7 +543,7 @@ Nevykonali sa žiadne zmeny. Domovská stránka - Ak chcete zobrazovať výsledky pluginu, keď je dopyt prázdny, povoľte funkciu Domovská stránka. + Ak chcete zobrazovať výsledky pluginu, keď je dopyt prázdny, povoľte funkciu domovská stránka. Klávesová skratka vlastného vyhľadávania diff --git a/Flow.Launcher/Languages/sr-Cyrl-RS.xaml b/Flow.Launcher/Languages/sr-Cyrl-RS.xaml index c9cd61886..d7d60e6a0 100644 --- a/Flow.Launcher/Languages/sr-Cyrl-RS.xaml +++ b/Flow.Launcher/Languages/sr-Cyrl-RS.xaml @@ -64,6 +64,10 @@ Position Reset Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Settings @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Icons You have activated Flow Launcher {0} times Check for Updates - Become A Sponsor + Become a Sponsor New version {0} is available, would you like to restart Flow Launcher to use the update? Check updates failed, please check your connection and proxy settings to api.github.com. diff --git a/Flow.Launcher/Languages/sr.xaml b/Flow.Launcher/Languages/sr.xaml index bfc41e5b8..7d1bcb9f3 100644 --- a/Flow.Launcher/Languages/sr.xaml +++ b/Flow.Launcher/Languages/sr.xaml @@ -64,6 +64,10 @@ Position Reset Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Podešavanja @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Icons Aktivirali ste Flow Launcher {0} puta Proveri ažuriranja - Become A Sponsor + Become a Sponsor Nove verzija {0} je dostupna, molim Vas ponovo pokrenite Flow Launcher. Neuspešna provera ažuriranja, molim Vas proverite vašu vezu i podešavanja za proksi prema api.github.com. diff --git a/Flow.Launcher/Languages/tr.xaml b/Flow.Launcher/Languages/tr.xaml index 2133bbb5a..67cdf9da4 100644 --- a/Flow.Launcher/Languages/tr.xaml +++ b/Flow.Launcher/Languages/tr.xaml @@ -64,6 +64,10 @@ Pencere Konumunu Sıfırla Arama penceresinin konumunu sıfırla Aramak için buraya yazın + {0}: Bu eklenti hala başlatılıyor... + Yeniden sorgulamak için bu sonucu seçin + {0}: Yanıt veremedi! + Daha fazla bilgi için bu sonucu seçin Ayarlar @@ -171,6 +175,10 @@ Sorgu metni boş olduğunda ana sayfa sonuçlarını gösterin. Geçmiş Sonuçlarını Ana Sayfada Göster Ana Sayfada Gösterilen Maksimum Geçmiş Sonuçları + Geçmiş Stili + Geçmiş ve Ana Sayfada gösterilecek geçmiş türünü seçin + Sorgu geçmişi + Son açılan geçmiş Bu sadece eklenti Ana Sayfa özelliğini destekliyorsa ve Ana Sayfa etkinleştirilmiş ise düzenlenebilir. Arama Penceresini En Üstte Göster Diğer programların 'Her Zaman Üstte' ayarını geçersiz kılar ve Flow’u en önde gösterir. @@ -446,7 +454,7 @@ Kullanılan Simgeler Şu ana kadar Flow Launcher'ı {0} kez aktifleştirdiniz. Güncellemeleri Kontrol Et - Sponsor Olun + Become a Sponsor Uygulamanın yeni sürümü ({0}) mevcut, Lütfen Flow Launcher'ı yeniden başlatın. Güncelleme kontrolü başarısız oldu. Lütfen bağlantınız ve vekil sunucu ayarlarınızın api.github.com adresine ulaşabilir olduğunu kontrol edin. diff --git a/Flow.Launcher/Languages/uk-UA.xaml b/Flow.Launcher/Languages/uk-UA.xaml index 53dcb8933..bec1f85e3 100644 --- a/Flow.Launcher/Languages/uk-UA.xaml +++ b/Flow.Launcher/Languages/uk-UA.xaml @@ -64,6 +64,10 @@ Скидання позиції Скинути положення вікна пошуку Напишіть тут, аби знайти + {0}: Цей плагін все ще ініціалізується... + Виберіть цей результат, щоб повторити запит + {0}: Не вдалося відповісти! + Виберіть цей результат, щоб отримати додаткову інформацію Налаштування @@ -171,6 +175,10 @@ Показувати результати на головній сторінці, коли текст запиту порожній. Показати результати історії на головній Максимальна кількість результатів історії, що показуються на головній + Стиль історії + Виберіть тип історії, який буде показуватися на сторінці «Історія» та «Головна». + Історія запитів + Остання відкрита історія Це можна редагувати тільки в тому випадку, якщо плагін підтримує функцію «Головна сторінка» і вона ввімкнена. Показувати вікно пошуку на передньому плані Перекриває налаштування «Завжди зверху» інших програм і виводить Flow на передній план. @@ -214,8 +222,8 @@ Версія Сайт Видалити - Search delay time: default - Search delay time: {0}ms + Час затримки пошуку: типово + Час затримки пошуку: {0} мс Не вдалося видалити налаштування плагіну Плагіни: {0} — Не вдалося видалити файли налаштувань плагінів, видаліть їх вручну. Не вдалося видалити кеш плагіну @@ -597,9 +605,9 @@ Вказаний файловий менеджер не знайдено. Перевірте налаштування вашого файлового менеджера в розділі Налаштування > Загальні. Помилка - An error occurred while opening the folder. + Під час відкриття теки сталася помилка. Під час відкриття URL-адреси в браузері сталася помилка. Перевірте налаштування типового веббраузера у розділі «Загальні» вікна налаштувань. - File or directory not found: {0} + Файл або каталог не знайдено: {0} Будь ласка, зачекайте... diff --git a/Flow.Launcher/Languages/vi.xaml b/Flow.Launcher/Languages/vi.xaml index 0618dc9a5..5809c7837 100644 --- a/Flow.Launcher/Languages/vi.xaml +++ b/Flow.Launcher/Languages/vi.xaml @@ -64,6 +64,10 @@ Đặt lại vị trí Cài lại vị trí cửa sổ tìm kiếm Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Cài đặt @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Biểu tượng Bạn đã kích hoạt Flow Launcher {0} lần Kiểm tra các bản cập nhật - Trở thành nhà tài trợ + Become a Sponsor Đã có phiên bản mới {0}, bạn có muốn khởi động lại Flow Launcher để sử dụng bản cập nhật không? Kiểm tra cập nhật không thành công. Vui lòng kiểm tra kết nối và cài đặt proxy của bạn tới api.github.com. diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index a5a412439..7af54dc54 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -64,6 +64,10 @@ 重置位置 重置搜索窗口位置 在此处输入以搜索 + {0}:此插件仍在初始化... + 选择此结果以重试 + {0}:响应失败! + 选择此结果以获取更多信息 设置 @@ -123,7 +127,7 @@ 常规 使用拼音搜索 - 拼音是翻译中文的罗马化拼写的标准系统。请注意,启用此功能可以大大增加搜索时的内存使用量。 + 拼音是翻译中文的罗马化拼写的标准系统。请注意,启用此功能会大幅增加搜索时的内存使用量。 使用双拼 使用双拼而不是全拼进行搜索。 双拼方案 @@ -141,7 +145,7 @@ Flow 启动时总是打开预览面板。按 {0} 以切换预览。 当前主题已启用模糊效果,不允许启用阴影效果 延迟搜索 - 在输入时添加一个短时间延迟以减少UI闪烁和加载结果的负载。建议您的输入速度是平均的。 + 在输入时添加一个短时间延迟以减少UI闪烁和加载结果的负载。如果您的打字速度处于中等水平,建议启用此功能。 输入等待时间(毫秒),直到输入被认为完成。这只能在启用搜索延迟时进行编辑。 默认搜索延迟时间 在输入停止后显示结果之前等待时间。更高的数值等待更长时间(毫秒) @@ -171,6 +175,10 @@ 当查询文本为空时显示主页结果。 在主页中显示历史记录 在主页显示的最大历史结果数 + 历史样式 + 选择要在历史和主页中显示的历史类型 + 查询历史 + 最近打开历史 这只能在插件支持主页功能和主页启用时进行编辑。 将搜索窗口置于顶层 覆盖其他“总是在顶部”的程序窗口并在最顶层的位置显示 Flow Launcher 搜索窗口。 @@ -289,7 +297,7 @@ 项目高度 查询框字体 结果标题字体 - 结果字幕字体 + 结果副标题字体 重置 重置为推荐字体和大小设置。 导入主题尺寸 @@ -606,7 +614,7 @@ 检查新的更新 - 您已经拥有最新的 Flow Launcher 版本 + 您当前使用的 Flow Launcher 已是最新版本 检查到更新 更新中... diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index 7c0fef077..ca7da7624 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -64,6 +64,10 @@ 重設位置 Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info 設定 @@ -171,11 +175,15 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. - Restart after modifying plugin via Plugin Store - Restart Flow Launcher automatically after installing/uninstalling/updating plugin via Plugin Store + 在插件商店改動插件後重新啟動 + 在插件商店安裝/移除/更新插件後自動重新啟動Flow Launcher Show unknown source warning Show warning when installing plugins from unknown sources Auto update plugins @@ -446,7 +454,7 @@ 圖示 您已經啟動了 Flow Launcher {0} 次 檢查更新 - 成為贊助者 + Become a Sponsor 發現有新版本 {0}, 請重新啟動 Flow Launcher。 檢查更新失敗,請檢查你對 api.github.com 的連線和代理設定。 diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml index 234c613c6..44a126e61 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml @@ -2,7 +2,7 @@ 计算器 - 进行数学计算,包括十六进制值和高级函数,如“最小(1,2,3)”、“sqrt(123)”和“cos123”等。 + 进行数学计算,包括十六进制值和高级函数,如“min(1,2,3)”、“sqrt(123)”和“cos(123)”等。 请输入数字 表达错误或不完整(您是否忘记了一些括号?) 将结果复制到剪贴板 diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml index b56e4660f..0cf66c1cb 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml @@ -2,16 +2,16 @@ 計算機 - Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. + 執行數學計算,包括十六進位數值以及進階函數,例如 'min(1,2,3)'、'sqrt(123)' 和 'cos(123)'。 不是一個數 (NaN) - Expression wrong or incomplete (Did you forget some parentheses?) + 表示式錯誤或不完整(你是否忘記了某些括號?) 複製此數至剪貼簿 小數點分隔符號 - The decimal separator to be used in the output. + 用於輸出的小數點分隔符。 使用系統區域設定 逗號 (,) 點 (.) 小數點後最大位數 - Copy failed, please try later - Show error message when calculation fails + 複製失敗,請稍後再試 + 計算失敗時顯示錯誤訊息 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml index 8a701ebc6..b9a825bf2 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml @@ -70,9 +70,9 @@ Content Search Engine Directory Recursive Search Engine - Index Search Engine + インデックス検索エンジン Windowsのインデックスオプションを開く - Excluded File Types (comma seperated) + 除外されたファイルタイプ(カンマ区切りで入力) 例: exe,jpg,png 結果の最大表示件数 The maximum number of results requested from active search engine @@ -163,8 +163,8 @@ 作成日時 ↓ 更新日時 ↑ 更新日時 ↓ - Attributes ↑ - Attributes ↓ + 属性 ↑ + 属性 ↓ File List FileName ↑ File List FileName ↓ 実行回数 ↑ @@ -187,7 +187,7 @@ Everything サービスをインストールしています。お待ちください… Everything サービスを正常にインストールしました Everything サービスを自動的にインストールできませんでした。https://www.voidtools.com から手動でインストールしてください - Click here to start it + ここをクリックして開始 Everythingのインストールが見つかりませんでした。手動で場所を指定しますか?{0}{0}「いいえ」をクリックすると、Everythingが自動的にインストールされます。 Everything でのコンテンツ検索を有効にしますか? インデックスなしでは非常に遅くなることがあります(Everything v1.5以降でのみサポートされています) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml index 60a08a82f..7600757a2 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml @@ -22,7 +22,7 @@ Виникла помилка під час пошуку: {0} Не вдалося відкрити папку Не вдалося відкрити файл - This new action keyword is already assigned to another plugin, please choose a different one + Нова команда активації вже призначена іншому плагіну, виберіть іншу Видалити diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml index ddd24d0ed..c13048133 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml @@ -31,7 +31,7 @@ Please check if you can connect to github.com. This error means you may not be able to install or update plugins. Update all plugins Would you like to update all plugins? - Would you like to update {0} plugins?{1}Flow Launcher will restart after updating all plugins. + 你要更新{0}個插件?{1}Flow Launcher會在更新所有插件後重新啟動。 Would you like to update {0} plugins? {0} plugins successfully updated. Restarting Flow, please wait... Plugin {0} successfully updated. Restarting Flow, please wait... @@ -66,5 +66,5 @@ Install from unknown source warning - Restart Flow Launcher automatically after installing/uninstalling/updating plugin via Plugins Manager + 以插件管理員安裝/移除/更新插件後自動重新啟動Flow Launcher diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/zh-tw.xaml index a8ff4ecbc..2653b69da 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/zh-tw.xaml @@ -82,7 +82,7 @@ 程式 在 Flow Launcher 中搜尋程式 - Invalid Path + 無效的路徑 Customized Explorer Args diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Shell/Languages/zh-tw.xaml index 02eb35336..3fa06dabc 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Shell/Languages/zh-tw.xaml @@ -13,7 +13,7 @@ 此指令已執行了 {0} 次 執行指令 以系統管理員身分執行 - Copy the command + 複製命令 Only show number of most used commands: Command not found: {0} Error running the command: {0} diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml index 8b5f3c94b..8f19cdcb3 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml @@ -77,8 +77,8 @@ Надає команди, пов'язані з системою, наприклад, вимкнення, блокування, налаштування тощо. - This theme supports two (light/dark) modes and Blur Transparent Background - This theme supports two (light/dark) modes - This theme supports Blur Transparent Background + Ця тема підтримує два режими (світлий / темний) та розмитий прозорий фон + Ця тема підтримує два (світлий / темний) режими + Ця тема підтримує розмитий прозорий фон diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml index 18ac48fd0..bd705490c 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml @@ -44,7 +44,7 @@ Open recycle bin 索引選項 Hibernate computer - Save all Flow Launcher settings + 儲存所有Flow Lanuncher設定 Refreshes plugin data with new content Open Flow Launcher's log location Check for new Flow Launcher update diff --git a/Plugins/Flow.Launcher.Plugin.Url/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/es.xaml index 5d402f293..e84a02a30 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/es.xaml @@ -10,13 +10,13 @@ Elegir Aplicación(*.exe)|*.exe|Todos los archivos|*.* - Use custom instead of Flow's default web browser - Browser path + Utilizar un navegador web personalizado en lugar del predeterminado de Flow + Ruta del navegador Nueva pestaña Nueva ventana - Private mode + Modo privado - Prefer https over http + Priorizar https frente a http diff --git a/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml index f643a1081..b51c79899 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml @@ -10,13 +10,13 @@ 選択 Application(*.exe)|*.exe|All files|*.* - Use custom instead of Flow's default web browser - Browser path + FlowのデフォルトのWebブラウザの代わりにカスタムを使用する + ブラウザーのパス - New tab - New window + 新しいタブ + 新しいウインドウ - Private mode + プライベートモード - Prefer https over http + httpよりもhttpsを優先 diff --git a/Plugins/Flow.Launcher.Plugin.Url/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/tr.xaml index 2ce323d08..0318b4301 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/tr.xaml @@ -10,13 +10,13 @@ Seç Programlar (*.exe)|*.exe|Tüm Dosyalar|*.* - Use custom instead of Flow's default web browser - Browser path + Flow'un varsayılan web tarayıcısı yerine özel tarayıcıyı kullanın + Tarayıcı yolu Yeni sekme Yeni pencere - Private mode + Gizli mod - Prefer https over http + http yerine https'yi tercih et diff --git a/Plugins/Flow.Launcher.Plugin.Url/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/uk-UA.xaml index f7ccd7cc1..a3cf6e02d 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/uk-UA.xaml @@ -10,13 +10,13 @@ Обрати Application(*.exe)|*.exe|Усі файли|*.* - Use custom instead of Flow's default web browser - Browser path + Використовувати власний веббраузер замість стандартного браузера Flow + Шлях до браузера Нова вкладка Нове вікно - Private mode + Приватний режим - Prefer https over http + Віддавати перевагу HTTPS над HTTP diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml index 7daee625b..41a6325b3 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml @@ -45,7 +45,7 @@ Por favor, introduzca una URL La palabra clave de acción ya está en uso, por favor, introduzca una diferente Correcto - Failed to update search source. The item may have been removed. + No se ha podido actualizar la fuente de búsqueda. Es posible que el elemento haya sido eliminado. Sugerencia: No es necesario colocar imágenes personalizadas en esta carpeta, al actualizar Flow se perderán. Flow copiará automáticamente cualquier imagen externa a esta carpeta en la ubicación de imágenes personalizada de WebSearch. Búsquedas Web diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml index 3ad1461e6..51aa07bab 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml @@ -46,7 +46,7 @@ https://www.netflix.com/search?q={q} URLを入力してください キーワードはすでに存在します。違うキーワードを入力してください 成功しました - Failed to update search source. The item may have been removed. + 検索ソースの更新に失敗しました。項目が削除されている可能性があります。 Hint: You do not need to place custom images in this directory, if Flow's version is updated they will be lost. Flow will automatically copy any images outside of this directory across to WebSearch's custom image location. Web検索 diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml index 8c2dd2104..e706b7bf7 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml @@ -45,7 +45,7 @@ Lütfen bir URL giriniz Anahtar kelime zaten mevcut. Lütfen yeni bir tane seçiniz. Başarılı - Failed to update search source. The item may have been removed. + Arama kaynağı güncellenemedi. Öge kaldırılmış olabilir. İpucu: Bu dizine özel resimler yerleştirmenize gerek yoktur, Flow'un sürümü güncellenirse bunlar kaybolacaktır. Flow, bu dizinin dışındaki tüm görüntüleri otomatik olarak WebSearch'ün özel görüntü konumuna kopyalayacaktır. Web Araması diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml index 3fe7068d1..2163c29be 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml @@ -45,7 +45,7 @@ Будь ласка, введіть URL-адресу Ключове слово дії вже існує, будь ласка, введіть інше Успішно - Failed to update search source. The item may have been removed. + Не вдалося оновити джерело пошуку. Елемент, можливо, було видалено. Підказка: Вам не потрібно розміщувати власні зображення в цьому каталозі, якщо версія Flow оновиться, вони будуть втрачені. Flow автоматично копіює всі зображення з цього каталогу до спеціального каталогу WebSearch. Вебпошук diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx index 3a2f991a1..ec98231ae 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx @@ -150,7 +150,7 @@ Area Control Panel (legacy settings) - アクティブ化 + アクティベーション Area UpdateAndSecurity @@ -1206,7 +1206,7 @@ Windows の設定を検索するためのプラグイン - Windows Settings + Windows の設定 電源とスリープ @@ -1836,19 +1836,19 @@ Check firewall status - Send or receive a file + ファイルを送受信する - Add or remove user accounts + ユーザーアカウントの追加または削除 Edit the system environment variables - Manage BitLocker + BitLocker の管理 - Auto-hide the taskbar + タスクバーを自動的に隠す Change sound card settings @@ -1947,10 +1947,10 @@ View recommended actions to keep Windows running smoothly - Change cursor blink rate + カーソルの点滅速度を変更する - Add or remove programs + プログラムの追加と削除 Create a password reset disk @@ -2070,7 +2070,7 @@ Change temporary Internet file settings - Connect to the Internet + インターネットに接続 Find and fix audio playback problems @@ -2079,7 +2079,7 @@ Change the mouse pointer display or speed - Back up your recovery key + リカバリーキーのバックアップ Save backup copies of your files with File History @@ -2094,31 +2094,31 @@ Change how your mouse works - Show how much RAM is on this computer + このコンピュータにあるRAMの量を表示する - Edit power plan + 電源プランを編集 - Adjust system volume + システム音量の調整 - Defragment and optimise your drives + ドライブのデフラグと最適化 Set up ODBC data sources (32-bit) - Change Font Settings + フォント設定を変更 - Magnify portions of the screen using Magnifier + 拡大鏡を使って画面の一部を拡大する Change the file type associated with a file extension - View event logs + イベントログを表示 Manage Windows Credentials @@ -2127,7 +2127,7 @@ Set up a microphone - Change how the mouse pointer looks + マウスポインタの見た目を変更する Change power-saving settings @@ -2152,7 +2152,7 @@ Manage Work Folders - Encrypt your offline files + オフラインファイルを暗号化 Train the computer to recognise your voice @@ -2161,7 +2161,7 @@ Advanced printer setup - Change default printer + 既定のプリンタを変更する Edit environment variables for your account @@ -2188,19 +2188,19 @@ Private Character Editor - Record steps to reproduce a problem + 問題を再現するためのステップを記録 - Adjust the appearance and performance of Windows + Windowsの外観とパフォーマンスを調整する - Settings for Microsoft IME (Japanese) + 日本語用 Microsoft IME の設定 Invite someone to connect to your PC and help you, or offer to help someone else - Run programs made for previous versions of Windows + 以前のバージョンの Windows 用に作られたプログラムを実行 Choose the order of how your screen rotates @@ -2212,10 +2212,10 @@ Set flicks to perform certain tasks - Change account type + アカウントタイプの変更 - Change screen saver + スクリーンセーバーを変更 Change User Account Control settings @@ -2224,37 +2224,37 @@ Turn on easy access keys - Identify and repair network problems + ネットワークの問題を特定して修復する Find and fix networking and connection problems - Play CDs or other media automatically + CD やその他のメディアを自動的に再生 View basic information about your computer - Choose how you open links + リンクを開く方法の選択 Allow Remote Assistance invitations to be sent from this computer - Task Manager + タスクマネージャー Turn flicks on or off - Add a language + 言語を追加 View network status and tasks - Turn Magnifier on or off + 拡大鏡のオン/オフ See the name of this computer @@ -2269,10 +2269,10 @@ Manage disk space used by your offline files - Turn High Contrast on or off + ハイコントラストのオン/オフ - Change the way time is displayed + 時間の表示方法を変更する Change how web pages are displayed in tabs @@ -2284,22 +2284,22 @@ Manage audio devices - Change security settings + セキュリティ設定を変更 Check security status - Delete cookies or temporary files + Cookie や一時ファイルを削除 - Specify which hand you write with + どの手で書くかを指定する Change touch input settings - How to change the size of virtual memory + 仮想メモリのサイズを変更する方法 Hear text read aloud with Narrator @@ -2353,13 +2353,13 @@ Manage Storage Spaces - Show or hide file extensions + 拡張子の表示/非表示 - Allow an app through Windows Firewall + Windowsファイアウォールでアプリを許可する - Change system sounds + システムのサウンドを変更 ClearTypeテキストを調整 @@ -2380,7 +2380,7 @@ Internet Explorer の検索プロバイダを変更する - Join a domain + ドメインに参加 端末を追加 @@ -2398,7 +2398,7 @@ プログラムのアンインストール - Create and format hard disk partitions + ハードディスクのパーティション作成とフォーマット 日付、時刻、数の書式を変更 @@ -2410,7 +2410,7 @@ Manage network passwords - Change input methods + 入力方法を変更 Manage advanced sharing settings @@ -2428,13 +2428,13 @@ Manage Web Credentials - Change the time zone + タイムゾーンの変更 音声認識を開始 - View installed updates + インストール済みのアップデートを表示 What's happened to the Quick Launch toolbar? @@ -2452,7 +2452,7 @@ Change the way measurements are displayed - Press key combinations one at a time + キーの組み合わせを同時に押してください Restore data, files or computer from backup (Windows 7) @@ -2467,7 +2467,7 @@ ペンまたはタッチ入力の画面をキャリブレーション - Manage user certificates + ユーザー証明書の管理 タスクのスケジュール diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx index 5b4dea6a9..2d242d5b1 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx @@ -1377,7 +1377,7 @@ Area SurfaceHub - Domov + Nastavenia dovmoskej stránky Area Home, Overview-page for all areas of settings From 229987ee90ee3a483e1e37c1a9b412e7a8ae0421 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 20 Nov 2025 22:01:51 +1100 Subject: [PATCH 030/124] Release 2.0.3 (#4121) --- .github/workflows/dotnet.yml | 10 +- Flow.Launcher.Core/Configuration/Portable.cs | 4 +- .../ExternalPlugins/PluginsManifest.cs | 9 +- Flow.Launcher.Core/Flow.Launcher.Core.csproj | 5 +- Flow.Launcher.Core/Plugin/PluginConfig.cs | 5 +- Flow.Launcher.Core/Plugin/PluginManager.cs | 2 +- Flow.Launcher.Core/packages.lock.json | 925 +++++++++++++++++- .../DialogJump/DialogJump.cs | 22 +- .../UserSettings/DataLocation.cs | 1 + Flow.Launcher/Helper/ErrorReporting.cs | 9 + Flow.Launcher/Helper/ExceptionHelper.cs | 42 + Flow.Launcher/Languages/ar.xaml | 10 +- Flow.Launcher/Languages/cs.xaml | 10 +- Flow.Launcher/Languages/da.xaml | 10 +- Flow.Launcher/Languages/de.xaml | 10 +- Flow.Launcher/Languages/en.xaml | 2 +- Flow.Launcher/Languages/es-419.xaml | 10 +- Flow.Launcher/Languages/es.xaml | 10 +- Flow.Launcher/Languages/fr.xaml | 38 +- Flow.Launcher/Languages/he.xaml | 10 +- Flow.Launcher/Languages/it.xaml | 10 +- Flow.Launcher/Languages/ja.xaml | 10 +- Flow.Launcher/Languages/ko.xaml | 10 +- Flow.Launcher/Languages/nb.xaml | 10 +- Flow.Launcher/Languages/nl.xaml | 10 +- Flow.Launcher/Languages/pl.xaml | 10 +- Flow.Launcher/Languages/pt-br.xaml | 14 +- Flow.Launcher/Languages/pt-pt.xaml | 10 +- Flow.Launcher/Languages/ru.xaml | 10 +- Flow.Launcher/Languages/sk.xaml | 18 +- Flow.Launcher/Languages/sr-Cyrl-RS.xaml | 10 +- Flow.Launcher/Languages/sr.xaml | 10 +- Flow.Launcher/Languages/tr.xaml | 10 +- Flow.Launcher/Languages/uk-UA.xaml | 16 +- Flow.Launcher/Languages/vi.xaml | 10 +- Flow.Launcher/Languages/zh-cn.xaml | 16 +- Flow.Launcher/Languages/zh-tw.xaml | 14 +- Flow.Launcher/packages.lock.json | 777 ++++++++++++++- ...low.Launcher.Plugin.BrowserBookmark.csproj | 2 +- .../Languages/zh-cn.xaml | 2 +- .../Languages/zh-tw.xaml | 10 +- .../Languages/ja.xaml | 10 +- .../Languages/uk-UA.xaml | 2 +- .../Search/Everything/EverythingAPI.cs | 23 +- .../Search/SearchManager.cs | 15 +- .../Languages/zh-tw.xaml | 4 +- .../Languages/zh-tw.xaml | 2 +- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 69 +- .../Languages/zh-tw.xaml | 2 +- .../Languages/uk-UA.xaml | 6 +- .../Languages/zh-tw.xaml | 2 +- .../Languages/es.xaml | 8 +- .../Languages/ja.xaml | 12 +- .../Languages/tr.xaml | 8 +- .../Languages/uk-UA.xaml | 8 +- .../Languages/es.xaml | 2 +- .../Languages/ja.xaml | 2 +- .../Languages/tr.xaml | 2 +- .../Languages/uk-UA.xaml | 2 +- .../Properties/Resources.ja-JP.resx | 96 +- .../Properties/Resources.sk-SK.resx | 2 +- Scripts/post_build.ps1 | 4 +- appveyor.yml | 2 +- 63 files changed, 2210 insertions(+), 206 deletions(-) create mode 100644 Flow.Launcher/Helper/ExceptionHelper.cs diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 957f836bb..416c75a9d 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -54,28 +54,28 @@ jobs: shell: powershell run: .\Scripts\post_build.ps1 - name: Upload Plugin Nupkg - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: Plugin nupkg path: | Output\Release\Flow.Launcher.Plugin.*.nupkg compression-level: 0 - name: Upload Setup - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: Flow Installer path: | Output\Packages\Flow-Launcher-*.exe compression-level: 0 - name: Upload Portable Version - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: Portable Version path: | Output\Packages\Flow-Launcher-Portable.zip compression-level: 0 - name: Upload Full Nupkg - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: Full nupkg path: | @@ -83,7 +83,7 @@ jobs: compression-level: 0 - name: Upload Release Information - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: RELEASES path: | diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index 721e14dca..bc6f073c3 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -139,8 +139,8 @@ namespace Flow.Launcher.Core.Configuration public void PreStartCleanUpAfterPortabilityUpdate() { // Specify here so this method does not rely on other environment variables to initialise - var portableDataDir = Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location.NonNull()).ToString(), "UserData"); - var roamingDataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FlowLauncher"); + var portableDataDir = DataLocation.PortableDataPath; + var roamingDataDir = DataLocation.RoamingDataPath; // Get full path to the .dead files for each case var portableDataDeleteFilePath = Path.Combine(portableDataDir, DataLocation.DeletionIndicatorFile); diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index 1e845498c..7d3d78ef0 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -31,9 +31,11 @@ namespace Flow.Launcher.Core.ExternalPlugins public static async Task UpdateManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default) { + bool lockAcquired = false; try { await manifestUpdateLock.WaitAsync(token).ConfigureAwait(false); + lockAcquired = true; if (UserPlugins == null || usePrimaryUrlOnly || DateTime.Now.Subtract(lastFetchedAt) >= fetchTimeout) { @@ -59,13 +61,18 @@ namespace Flow.Launcher.Core.ExternalPlugins return true; } } + catch (OperationCanceledException) + { + // Ignored + } catch (Exception e) { API.LogException(ClassName, "Http request failed", e); } finally { - manifestUpdateLock.Release(); + // Only release the lock if it was acquired + if (lockAcquired) manifestUpdateLock.Release(); } return false; diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj index 1369d7e5d..540eabbf0 100644 --- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj +++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj @@ -56,10 +56,11 @@ - + - + + diff --git a/Flow.Launcher.Core/Plugin/PluginConfig.cs b/Flow.Launcher.Core/Plugin/PluginConfig.cs index f7457b4e1..4313a51af 100644 --- a/Flow.Launcher.Core/Plugin/PluginConfig.cs +++ b/Flow.Launcher.Core/Plugin/PluginConfig.cs @@ -1,10 +1,11 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.IO; using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin; using System.Text.Json; +using Flow.Launcher.Infrastructure.UserSettings; using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Core.Plugin @@ -30,7 +31,7 @@ namespace Flow.Launcher.Core.Plugin // todo use linq when diable plugin is implmented since parallel.foreach + list is not thread saft foreach (var directory in directories) { - if (File.Exists(Path.Combine(directory, "NeedDelete.txt"))) + if (File.Exists(Path.Combine(directory, DataLocation.PluginDeleteFile))) { try { diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index a4ab8de08..7bdfc8009 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -815,7 +815,7 @@ namespace Flow.Launcher.Core.Plugin } // Marked for deletion. Will be deleted on next start up - using var _ = File.CreateText(Path.Combine(plugin.PluginDirectory, "NeedDelete.txt")); + using var _ = File.CreateText(Path.Combine(plugin.PluginDirectory, DataLocation.PluginDeleteFile)); if (checkModified) { diff --git a/Flow.Launcher.Core/packages.lock.json b/Flow.Launcher.Core/packages.lock.json index b7a00d94d..b499a5860 100644 --- a/Flow.Launcher.Core/packages.lock.json +++ b/Flow.Launcher.Core/packages.lock.json @@ -19,9 +19,9 @@ }, "Meziantou.Framework.Win32.Jobs": { "type": "Direct", - "requested": "[3.4.4, )", - "resolved": "3.4.4", - "contentHash": "AivBzH5wM1NHBLehclim+o37SmireP7JxCRUoTilsc/h7LH9+YCPjb6Ig6y0khnQhFcO1P8RHYw4oiR15TGHUg==" + "requested": "[3.4.5, )", + "resolved": "3.4.5", + "contentHash": "R/d2VSdbRQHDWfPf5sjvMOWrWvxh/CswdMDKODppHTjsDLIkLQbQrnjmtAaVqu0qgUf8KFlVzEfxy3GIVoCK9g==" }, "Microsoft.IO.RecyclableMemoryStream": { "type": "Direct", @@ -37,12 +37,13 @@ }, "squirrel.windows": { "type": "Direct", - "requested": "[1.5.2, )", - "resolved": "1.5.2", - "contentHash": "89Y/CFxWm7SEOjvuV2stVa8p+SNM9GOLk4tUNm2nUF792nfkimAgwRA/umVsdyd/OXBH8byXSh4V1qck88ZAyQ==", + "requested": "[1.9.0, )", + "resolved": "1.9.0", + "contentHash": "1xOe9lgQX7u+AV19n7vTjRXn45fZ6rQ5pMSe6q54Nfe9sWHUikMz5d3Mc15T0Gw/9hVausR8BLIMVsp170DH/Q==", "dependencies": { - "DeltaCompressionDotNet": "[1.0.0, 2.0.0)", + "DeltaCompressionDotNet": "[1.1.0, 2.0.0)", "Mono.Cecil": "0.9.6.1", + "SharpCompress": "0.17.1", "Splat": "1.6.2" } }, @@ -80,8 +81,8 @@ }, "DeltaCompressionDotNet": { "type": "Transitive", - "resolved": "1.0.0", - "contentHash": "nwbZAYd+DblXAIzlnwDSnl0CiCm8jWLfHSYnoN4wYhtIav6AegB3+T/vKzLbU2IZlPB8Bvl8U3NXpx3eaz+N5w==" + "resolved": "1.1.0", + "contentHash": "j/zGAQ9hLbl7JDpeO40DaXvyyNxwQNDwnJEN7eCexn5F9Kid+VKya/Er0rfIv5Zod/32XarkqFP/V6WFHS/UpQ==" }, "InputSimulator": { "type": "Transitive", @@ -131,6 +132,16 @@ "resolved": "17.6.3", "contentHash": "N0ZIanl1QCgvUumEL1laasU0a7sOE5ZwLZVTn0pAePnfhq8P7SvTjF8Axq+CnavuQkmdQpGNXQ1efZtu5kDFbA==" }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, "Microsoft.VisualStudio.Threading": { "type": "Transitive", "resolved": "17.14.15", @@ -159,6 +170,16 @@ "resolved": "17.8.8", "contentHash": "rWXThIpyQd4YIXghNkiv2+VLvzS+MCMKVRDR0GAMlflsdo+YcAN2g2r5U1Ah98OFjQMRexTFtXQQ2LkajxZi3g==" }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, "Microsoft.Win32.SystemEvents": { "type": "Transitive", "resolved": "7.0.0", @@ -179,6 +200,57 @@ "System.IO.Pipelines": "8.0.0" } }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, "Newtonsoft.Json": { "type": "Transitive", "resolved": "13.0.3", @@ -210,6 +282,121 @@ "NLog": "6.0.4" } }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" + }, + "SharpCompress": { + "type": "Transitive", + "resolved": "0.17.1", + "contentHash": "NSofrWwVr0z0ZNRCoV6XFjdopMbOSY6QVRLBfLXUDcjMLNKKhDV6zibiFEVa9eVaz24deslc8kqdVYurKJq/aA==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, "SharpVectors.Wpf": { "type": "Transitive", "resolved": "1.8.5", @@ -220,6 +407,107 @@ "resolved": "1.6.2", "contentHash": "DeH0MxPU+D4JchkIDPYG4vUT+hsWs9S41cFle0/4K5EJMXWurx5DzAkj2366DfK14/XKNhsu6tCl4dZXJ3CD4w==" }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, "System.Drawing.Common": { "type": "Transitive", "resolved": "7.0.0", @@ -228,16 +516,635 @@ "Microsoft.Win32.SystemEvents": "7.0.0" } }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, "System.IO.Pipelines": { "type": "Transitive", "resolved": "8.0.0", "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, "System.Reflection.Metadata": { "type": "Transitive", "resolved": "5.0.0", "contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ==" }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, "ToolGood.Words.Pinyin": { "type": "Transitive", "resolved": "3.1.0.3", diff --git a/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs b/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs index 65652878f..aa2c641ca 100644 --- a/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs +++ b/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs @@ -832,9 +832,25 @@ namespace Flow.Launcher.Infrastructure.DialogJump return true; } // file: URI paths - var localPath = path.StartsWith("file:", StringComparison.OrdinalIgnoreCase) - ? new Uri(path).LocalPath - : path; + string localPath; + if (path.StartsWith("file:", StringComparison.OrdinalIgnoreCase)) + { + // Try to create a URI from the path + if (Uri.TryCreate(path, UriKind.Absolute, out var uri)) + { + localPath = uri.LocalPath; + } + else + { + // If URI creation fails, treat it as a regular path + // by removing the "file:" prefix + localPath = path.Substring(5); + } + } + else + { + localPath = path; + } // Is folder? var isFolder = Directory.Exists(localPath); // Is file? diff --git a/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs b/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs index de9cb841e..82f83b11a 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs @@ -40,6 +40,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings public const string PythonEnvironmentName = "Python"; public const string NodeEnvironmentName = "Node.js"; public const string PluginEnvironments = "Environments"; + public const string PluginDeleteFile = "NeedDelete.txt"; public static readonly string PluginEnvironmentsPath = Path.Combine(DataDirectory(), PluginEnvironments); } } diff --git a/Flow.Launcher/Helper/ErrorReporting.cs b/Flow.Launcher/Helper/ErrorReporting.cs index e201284cb..797f31482 100644 --- a/Flow.Launcher/Helper/ErrorReporting.cs +++ b/Flow.Launcher/Helper/ErrorReporting.cs @@ -16,6 +16,15 @@ public static class ErrorReporting var logger = LogManager.GetLogger(methodName); logger.Fatal(ExceptionFormatter.FormatExcpetion(e)); if (silent) return; + + // Workaround for issue https://github.com/Flow-Launcher/Flow.Launcher/issues/4016 + // The crash occurs in PresentationFramework.dll, not necessarily when the Runner UI is visible, originating from this line: + // https://github.com/dotnet/wpf/blob/3439f20fb8c685af6d9247e8fd2978cac42e74ac/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Shell/WindowChromeWorker.cs#L1005 + // Many bug reports because users see the "Error report UI" after the crash with System.Runtime.InteropServices.COMException 0xD0000701 or 0x80263001. + // However, displaying this "Error report UI" during WPF crashes, especially when DWM composition is changing, is not ideal; some users reported it hangs for up to a minute before the it appears. + // This change modifies the behavior to log the exception instead of showing the "Error report UI". + if (ExceptionHelper.IsRecoverableDwmCompositionException(e)) return; + var reportWindow = new ReportWindow(e); reportWindow.Show(); } diff --git a/Flow.Launcher/Helper/ExceptionHelper.cs b/Flow.Launcher/Helper/ExceptionHelper.cs new file mode 100644 index 000000000..5dd57f9bb --- /dev/null +++ b/Flow.Launcher/Helper/ExceptionHelper.cs @@ -0,0 +1,42 @@ +// This is a direct copy of the file at https://github.com/microsoft/PowerToys/blob/main/src/modules/launcher/PowerLauncher/Helper/ExceptionHelper.cs and adapted for flow. + +using System; +using System.Runtime.InteropServices; + +namespace Flow.Launcher.Helper; + +internal static class ExceptionHelper +{ + private const string PresentationFrameworkExceptionSource = "PresentationFramework"; + + private const int DWM_E_COMPOSITIONDISABLED = unchecked((int)0x80263001); + + // HRESULT for NT STATUS STATUS_MESSAGE_LOST (0xC0000701 | 0x10000000 == 0xD0000701) + private const int STATUS_MESSAGE_LOST_HR = unchecked((int)0xD0000701); + + /// + /// Returns true if the exception is a recoverable DWM composition exception. + /// + internal static bool IsRecoverableDwmCompositionException(Exception exception) + { + if (exception is not COMException comException) + { + return false; + } + + if (comException.HResult is DWM_E_COMPOSITIONDISABLED) + { + return true; + } + + if (comException.HResult is STATUS_MESSAGE_LOST_HR && comException.Source == PresentationFrameworkExceptionSource) + { + return true; + } + + // Check for common DWM composition changed patterns in the stack trace + var stackTrace = comException.StackTrace; + return !string.IsNullOrEmpty(stackTrace) && + stackTrace.Contains("DwmCompositionChanged", StringComparison.OrdinalIgnoreCase); + } +} diff --git a/Flow.Launcher/Languages/ar.xaml b/Flow.Launcher/Languages/ar.xaml index 7dcfcdb09..67f1f766e 100644 --- a/Flow.Launcher/Languages/ar.xaml +++ b/Flow.Launcher/Languages/ar.xaml @@ -64,6 +64,10 @@ إعادة تعيين الموقع Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info الإعدادات @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ الأيقونات لقد قمت بتفعيل Flow Launcher {0} مرات التحقق من التحديثات - كن راعيا + Become a Sponsor الإصدار الجديد {0} متاح، هل ترغب في إعادة تشغيل Flow Launcher لاستخدام التحديث فشل التحقق من التحديثات، يرجى التحقق من الاتصال وإعدادات البروكسي لـ api.github.com. diff --git a/Flow.Launcher/Languages/cs.xaml b/Flow.Launcher/Languages/cs.xaml index d08653a04..96cbe95e7 100644 --- a/Flow.Launcher/Languages/cs.xaml +++ b/Flow.Launcher/Languages/cs.xaml @@ -64,6 +64,10 @@ Obnovit pozici Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Nastavení @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Ikony Flow Launcher byl aktivován {0} krát Zkontrolovat Aktualizace - Staňte se sponzorem + Become a Sponsor Je k dispozici nová verze {0}, chcete Flow Launcher restartovat, aby se mohl aktualizovat? Hledání aktualizací se nezdařilo, zkontrolujte prosím své internetové připojení a nastavení proxy serveru k api.github.com. diff --git a/Flow.Launcher/Languages/da.xaml b/Flow.Launcher/Languages/da.xaml index 7ad686fe8..a1fc771d2 100644 --- a/Flow.Launcher/Languages/da.xaml +++ b/Flow.Launcher/Languages/da.xaml @@ -64,6 +64,10 @@ Position Reset Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Indstillinger @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Icons Du har aktiveret Flow Launcher {0} gange Tjek for opdateringer - Become A Sponsor + Become a Sponsor Ny version {0} er tilgængelig, genstart venligst Flow Launcher Check updates failed, please check your connection and proxy settings to api.github.com. diff --git a/Flow.Launcher/Languages/de.xaml b/Flow.Launcher/Languages/de.xaml index 064ac4038..2c083646f 100644 --- a/Flow.Launcher/Languages/de.xaml +++ b/Flow.Launcher/Languages/de.xaml @@ -64,6 +64,10 @@ Zurücksetzen der Position Position des Suchfensters zurücksetzen Zum Suchen hier tippen + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Einstellungen @@ -171,6 +175,10 @@ Ergebnisse der Homepage zeigen, wenn Abfragetext leer ist. Historie-Ergebnisse auf Homepage zeigen Maximal gezeigte Historie-Ergebnisse auf Homepage + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history Dies kann nur bearbeitet werden, wenn das Plug-in das Home-Feature unterstützt und die Homepage aktiviert ist. Suchfenster an vorderster zeigen Setzt die Einstellung 'Immer im Vordergrund' anderer Programme außer Kraft und zeigt Flow in der vordersten Position an. @@ -446,7 +454,7 @@ Icons Sie haben Flow Launcher {0} mal aktiviert Nach Updates suchen - Ein Sponsor werden + Become a Sponsor Neue Version {0} ist verfügbar. Möchten Sie Flow Launcher neu starten, um das Update zu verwenden? Überprüfung der Updates fehlgeschlagen. Bitte überprüfen Sie Ihre Verbindungs- und Proxy-Einstellungen zu api.github.com. diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 4f60b3750..22d93f1bd 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -438,7 +438,7 @@ Icons You have activated Flow Launcher {0} times Check for Updates - Become A Sponsor + Become a Sponsor New version {0} is available, would you like to restart Flow Launcher to use the update? Check updates failed, please check your connection and proxy settings to api.github.com. diff --git a/Flow.Launcher/Languages/es-419.xaml b/Flow.Launcher/Languages/es-419.xaml index 8554f3847..9f06c4436 100644 --- a/Flow.Launcher/Languages/es-419.xaml +++ b/Flow.Launcher/Languages/es-419.xaml @@ -64,6 +64,10 @@ Position Reset Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Ajustes @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Icons Has activado Flow Launcher {0} veces Buscar actualizaciones - Become A Sponsor + Become a Sponsor La nueva versión {0} está disponible, ¿desea reiniciar Flow Launcher para usar la actualización? Falló la comprobación de actualizaciones, compruebe su conexión y configuración de proxy a api.github.com. diff --git a/Flow.Launcher/Languages/es.xaml b/Flow.Launcher/Languages/es.xaml index be00fac94..f7a3fbb22 100644 --- a/Flow.Launcher/Languages/es.xaml +++ b/Flow.Launcher/Languages/es.xaml @@ -64,6 +64,10 @@ Restablecer posición Restablece la posición de la ventana de búsqueda Escribir aquí para buscar + {0}: Este complemento aún se está inicializando... + Seleccione este resultado para volver a realizar la consulta + {0}: ¡No se ha recibido respuesta! + Seleccione este resultado para más información Configuración @@ -171,6 +175,10 @@ Muestra los resultados de la página de inicio cuando el texto de la consulta está vacío. Mostrar historial de resultados en la página de inicio Número máximo de resultados del historial en la página de inicio + Estilo del historial + Elija el tipo de historial que desea mostrar en el historial y la página de inicio + Historial de consultas + Historial de últimas aperturas Esto solo se puede editar si el complemento soporta la función de Inicio y la Página de Inicio está activada. Mostrar ventana de búsqueda en primer plano Anula el ajuste «Siempre arriba» de otros programas y muestra Flow en primer plano. @@ -446,7 +454,7 @@ Iconos Ha activado Flow Launcher {0} veces Buscar actualizaciones - Hágase Patrocinador + Conviértase en Patrocinador La nueva versión {0} está disponible, ¿desea reiniciar Flow Launcher para actualizar? Ha fallado la comprobación de las actualizaciones, por favor, compruebe la configuración de su proxy y conexión a api.github.com. diff --git a/Flow.Launcher/Languages/fr.xaml b/Flow.Launcher/Languages/fr.xaml index b9ac0de4b..bdce6ddb9 100644 --- a/Flow.Launcher/Languages/fr.xaml +++ b/Flow.Launcher/Languages/fr.xaml @@ -64,6 +64,10 @@ Réinitialiser la position Réinitialiser la position de la fenêtre de recherche Tapez ici pour rechercher + {0}: Ce plugin est toujours en cours d'initialisation... + Sélectionner ce résultat pour la requête + {0}: Ne répond pas ! + Sélectionnez ce résultat pour plus d'informations Paramètres @@ -171,6 +175,10 @@ Afficher les résultats de la page d'accueil lorsque le texte de la requête est vide. Afficher les résultats de l'historique sur la page d'accueil Maximum de résultats de l'historique affichés sur la page d'accueil + Style d'historique + Choisissez le type d'historique à afficher dans l'historique et la page d'accueil + Historique des requêtes + Historique des dernières ouvertures Ceci ne peut être édité que si le plugin prend en charge la fonction Accueil et que la page d'accueil est activée. Afficher la fenêtre de recherche en premier plan Outrepasse le paramètre 'toujours en premier plan' des autres programmes et affiche Flow Launcher en première position. @@ -399,24 +407,24 @@ Pour les plugins pris en charge, des badges sont affichés afin de les distinguer plus facilement. Afficher les badges de résultats pour la requête globale uniquement Afficher les badges pour les résultats des requêtes globales uniquement - Dialog Jump + Saut de dialogue Entrez le raccourci pour naviguer rapidement dans la fenêtre de dialogue Ouvrir/Enregistrer sous, vers le chemin du gestionnaire de fichiers actuel. - Dialog Jump + Saut de dialogue Lorsque la fenêtre de dialogue Ouvrir/Enregistrer sous s'ouvre, accédez rapidement au chemin d'accès actuel du gestionnaire de fichiers. - Dialog Jump Automatically + Saut de dialogue automatique Lorsque la fenêtre de dialogue Ouvrir/Enregistrer sous est affichée, naviguez automatiquement vers le chemin du gestionnaire de fichiers actuel. (Expérimental) - Show Dialog Jump Window - Display Dialog Jump search window when the open/save dialog window is shown to quickly navigate to file/folder locations. - Dialog Jump Window Position - Select position for the Dialog Jump search window - Fixed under the Open/Save As dialog window. Displayed on open and stays until the window is closed - Default search window position. Displayed when triggered by search window hotkey - Dialog Jump Result Navigation Behaviour - Behaviour to navigate Open/Save As dialog window to the selected result path - Left click or Enter key + Afficher la fenêtre de saut de dialogue + Afficher la fenêtre de recherche de saut de dialogue lorsque la fenêtre de dialogue Ouvrir/Enregistrer sous est affichée pour naviguer rapidement vers les emplacements de fichier/dossier. + Position de la fenêtre de saut de dialogue + Sélectionnez la position pour la fenêtre de recherche de saut de dialogue + Fixé sous la fenêtre de dialogue Ouvrir/Enregistrer sous. Affiché à l'ouverture et reste jusqu'à ce que la fenêtre soit fermée. + Position de la fenêtre de recherche par défaut. Affiché lorsqu'il est déclenché par le raccourci clavier de la fenêtre de recherche + Comportement de navigation des résultats du saut de dialogue + Comportement pour naviguer dans la fenêtre de dialogue Ouvrir/Enregistrer sous vers le chemin de résultat sélectionné + Clic gauche ou touche Entrée Clique droit - Dialog Jump File Navigation Behaviour - Behaviour to navigate Open/Save As dialog window when the result is a file path + Comportement de navigation des résultats du saut de dialogue + Comportement pour naviguer dans la fenêtre de dialogue Ouvrir/Enregistrer sous lorsque le résultat est un chemin de fichier Remplir le chemin complet dans la zone de nom de fichier Remplir le chemin complet dans la zone de nom de fichier et ouvrir Remplir le répertoire dans la zone de chemin @@ -446,7 +454,7 @@ Icônes Vous avez utilisé Flow Launcher {0} fois Vérifier les mises à jour - Devenir un Sponsor + Devenez un sponsor Nouvelle version {0} disponible, souhaitez-vous redémarrer Flow Launcher pour l'installer ? Échec de la vérification de la mise à jour, vérifiez votre connexion et vos paramètres de configuration proxy pour pouvoir acceder à api.github.com. diff --git a/Flow.Launcher/Languages/he.xaml b/Flow.Launcher/Languages/he.xaml index ca69ddb50..39f02c702 100644 --- a/Flow.Launcher/Languages/he.xaml +++ b/Flow.Launcher/Languages/he.xaml @@ -64,6 +64,10 @@ איפוס מיקום אפס את מיקום חלון החיפוש הקלד כאן כדי לחפש + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info הגדרות @@ -170,6 +174,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history ניתן לערוך זאת רק אם התוסף תומך בתכונת הבית ודף הבית מופעל. Show Search Window at Foremost עוקף את הגדרת תמיד עליון של תוכנות אחרות, ומציג את Flow במיקום הגבוה ביותר. @@ -445,7 +453,7 @@ סמלים הפעלת את Flow Launcher {0} פעמים בדוק עדכונים - תן חסות + Become a Sponsor גרסה חדשה {0} זמינה, האם ברצונך להפעיל מחדש את Flow Launcher כדי להשתמש בעדכון? בדיקת העדכונים נכשלה, אנא בדוק את הגדרות החיבור ואת הגדרות ה-Proxy שלך לכתובת api.github.com. diff --git a/Flow.Launcher/Languages/it.xaml b/Flow.Launcher/Languages/it.xaml index 01062bed0..ffb716658 100644 --- a/Flow.Launcher/Languages/it.xaml +++ b/Flow.Launcher/Languages/it.xaml @@ -64,6 +64,10 @@ Ripristina Posizione Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Impostazioni @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Icone Hai usato Flow Launcher {0} volte Cerca aggiornamenti - Diventa un sostenitore + Become a Sponsor Una nuova versione {0} è disponibile, riavvia Flow Launcher per favore. Ricerca aggiornamenti fallita, per favore controlla la tua connessione e le eventuali impostazioni proxy per api.github.com. diff --git a/Flow.Launcher/Languages/ja.xaml b/Flow.Launcher/Languages/ja.xaml index 206791821..51ec99ddd 100644 --- a/Flow.Launcher/Languages/ja.xaml +++ b/Flow.Launcher/Languages/ja.xaml @@ -64,6 +64,10 @@ 位置のリセット 検索ウィンドウの位置をリセット ここに入力して検索 + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info 設定 @@ -171,6 +175,10 @@ 検索文字列が空の場合、ホームページの結果を表示します。 クエリの履歴をホームページに表示 ホームページに表示される最大の履歴の数 + 履歴のスタイル + 履歴とホームページに表示する履歴の種類を選択します + クエリの履歴 + Last opened history これは、プラグインがホーム機能をサポートし、ホームページが有効な場合にのみ編集することができます。 検索ウィンドウを最前面に表示 他のプログラムの 'Always on Top' (最前面に表示)設定を上書きし、常に最前面のウィンドウで Flow を表示します。 @@ -446,7 +454,7 @@ アイコン あなたはFlow Launcherを {0} 回利用しました アップデートを確認する - スポンサーになる + Become a Sponsor 新しいバージョン {0} が利用可能です。Flow Launcherを再起動してください。 アップデートの確認に失敗しました、api.github.com への接続とプロキシ設定を確認してください。 diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml index 674cca7a7..503ff2f11 100644 --- a/Flow.Launcher/Languages/ko.xaml +++ b/Flow.Launcher/Languages/ko.xaml @@ -64,6 +64,10 @@ 창 위치 초기화 검색창 위치 초기화 검색어 입력 + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info 설정 @@ -162,6 +166,10 @@ 쿼리 입력창이 비어있을때, 홈페이지의 결과를 표시합니다. 히스토리를 홈페이지에 표시 홈페이지에 표시할 최대 히스토리 수 + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -437,7 +445,7 @@ 아이콘 Flow Launcher를 {0}번 실행했습니다. 업데이트 확인 - 후원하기 + Become a Sponsor 새 버전({0})이 있습니다. Flow Launcher를 재시작하세요. 업데이트 확인을 실패했습니다. api.github.com로의 연결 또는 프록시 설정을 확인해주세요. diff --git a/Flow.Launcher/Languages/nb.xaml b/Flow.Launcher/Languages/nb.xaml index 68e63e37e..8bd7f94a4 100644 --- a/Flow.Launcher/Languages/nb.xaml +++ b/Flow.Launcher/Languages/nb.xaml @@ -64,6 +64,10 @@ Tilbakestilling av posisjon Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Innstillinger @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Ikoner Du har aktivert Flow Launcher {0} ganger Se etter oppdateringer - Bli en sponsor + Become a Sponsor Ny versjon {0} er tilgjengelig, vil du starte Flow Launcher på nytt for å bruke oppdateringen? Sjekk oppdateringer mislyktes, vennligst sjekk tilkoblingen og proxy-innstillingene til api.github.com. diff --git a/Flow.Launcher/Languages/nl.xaml b/Flow.Launcher/Languages/nl.xaml index 69e2107bf..8b7b86329 100644 --- a/Flow.Launcher/Languages/nl.xaml +++ b/Flow.Launcher/Languages/nl.xaml @@ -64,6 +64,10 @@ Positie resetten Reset search window position Type om te zoeken + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Instellingen @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Pictogrammen U heeft Flow Launcher {0} keer opgestart Zoek naar Updates - Sponsor worden + Become a Sponsor Nieuwe versie {0} beschikbaar, start Flow Launcher opnieuw op Controleren op updates mislukt, controleer uw verbinding en proxy-instellingen voor api.github.com. diff --git a/Flow.Launcher/Languages/pl.xaml b/Flow.Launcher/Languages/pl.xaml index 5786f98ab..382626eb7 100644 --- a/Flow.Launcher/Languages/pl.xaml +++ b/Flow.Launcher/Languages/pl.xaml @@ -64,6 +64,10 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Resetowanie pozycji Zresetuj pozycję okna wyszukiwania Wpisz tutaj, aby wyszukać + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Ustawienia @@ -170,6 +174,10 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Wyświetl wyniki strony głównej, gdy pole wyszukiwania jest puste. Pokaż wyniki historii na stronie głównej Maksymalna liczba wyników historii wyświetlanych na stronie głównej + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history Można edytować tylko wtedy, gdy wtyczka obsługuje funkcję Strona główna i jest ona włączona. Wyświetl okno wyszukiwania na wierzchu Wyświetl okno wyszukiwania ponad innymi oknami @@ -445,7 +453,7 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Ikony Uaktywniłeś Flow Launcher {0} razy Szukaj aktualizacji - Zostań sponsorem + Become a Sponsor Nowa wersja {0} jest dostępna, uruchom ponownie Flow Launcher Sprawdzenie aktualizacji nie powiodło się. Sprawdź swoje połączenie i ustawienia proxy dla api.github.com. diff --git a/Flow.Launcher/Languages/pt-br.xaml b/Flow.Launcher/Languages/pt-br.xaml index 6127e839b..15dcae2f4 100644 --- a/Flow.Launcher/Languages/pt-br.xaml +++ b/Flow.Launcher/Languages/pt-br.xaml @@ -64,6 +64,10 @@ Redefinição de Posição Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Configurações @@ -90,7 +94,7 @@ Posição Personalizada Idioma Estilo da Última Consulta - Mostrar/ocultar resultados anteriores quando o Lançador de Fluxos é reativado. + Mostrar/ocultar resultados anteriores quando o Flow Launcher for reativado. Preservar Última Consulta Selecionar última consulta Limpar última consulta @@ -138,7 +142,7 @@ Xiao Lang Sempre Pré-visualizar - Sempre abrir o painel de pré-visualização quando o Flow é ativado. Pressione {0} para ativar ou desativar a pré-visualização. + Sempre abrir o painel de pré-visualização quando o Flow for ativado. Pressione {0} para alternar a pré-visualização. O efeito de sombra não é permitido enquanto o tema atual tem o efeito de desfoque ativado Search Delay Adds a short delay while typing to reduce UI flicker and result load. Recommended if your typing speed is average. @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Ícones Você ativou o Flow Launcher {0} vezes Procurar atualizações - Torne-se um Sponsor + Become a Sponsor A nova versão {0} está disponível, por favor reinicie o Flow Launcher. Falha ao procurar atualizações, confira sua conexão e configuração de proxy para api.github.com. diff --git a/Flow.Launcher/Languages/pt-pt.xaml b/Flow.Launcher/Languages/pt-pt.xaml index 2be609c99..3746ada13 100644 --- a/Flow.Launcher/Languages/pt-pt.xaml +++ b/Flow.Launcher/Languages/pt-pt.xaml @@ -64,6 +64,10 @@ Repor posição Repor posição da janela de pesquisa Escreva aqui para pesquisar + {0}: Este plugin está a ser iniciado... + Selecione este resultado para pesquisar novamente + {0}: Falha na resposta! + Selecione este resultado para mais informação Definições @@ -170,6 +174,10 @@ Mostrar resultados da página inicial se o termo de pesquisa estiver vazio. Mostrar histórico na página inicial Máximo de resultados a mostrar na Página inicial + Estilo do histórico + Escolha o tipo de histórico a ser mostrado no Histórico e na Página inicial + Histórico de pesquisas + Último histórico aberto Esta opção apenas pode ser editada se o plugin tiver suporte a Página inicial e se estiver ativo. Janela de pesquisa à frente Sobrepõe a definição 'Sempre na frente' das outras aplicações e mostra Flow Launcher à frente de qualquer janela. @@ -445,7 +453,7 @@ Ícones Ativou o Flow Launcher {0} vezes Procurar atualizações - Tornar-se patrocinador + Torne-se um Patrocinador Está disponível a versão {0}. Gostaria de reiniciar Flow Launcher para atualizar a sua versão? Erro ao procurar atualizações. Verifique a sua ligação e as definições do proxy estabelecidas para api.github.com diff --git a/Flow.Launcher/Languages/ru.xaml b/Flow.Launcher/Languages/ru.xaml index df7c9d994..7bb5a8ff1 100644 --- a/Flow.Launcher/Languages/ru.xaml +++ b/Flow.Launcher/Languages/ru.xaml @@ -64,6 +64,10 @@ Сброс положения Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Настройки @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Значки Вы воспользовались Flow Launcher уже {0} раз Проверить наличие обновлений - Стать спонсором + Become a Sponsor Доступна новая версия {0}. Вы хотите перезапустить Flow Launcher, чтобы использовать обновление? Проверка обновлений не удалась, пожалуйста, проверьте настройки подключения и прокси-сервера к api.github.com. diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml index a07613b13..e76061a3b 100644 --- a/Flow.Launcher/Languages/sk.xaml +++ b/Flow.Launcher/Languages/sk.xaml @@ -65,6 +65,10 @@ Nevykonali sa žiadne zmeny. Resetovať pozíciu Resetovať pozíciu vyhľadávacieho okna Zadajte text na vyhľadávanie + {0}: Tento plugin sa stále inicializuje… + Vyberte tento výsledok na opätovné vyhľadávanie + {0}: Nepodarilo sa odpovedať! + Vyberte tento výsledok pre viac informácií Nastavenia @@ -169,10 +173,14 @@ Nevykonali sa žiadne zmeny. Nepodarilo sa zmeniť nastavenie kórejského IME Skontrolujte prístup do systémového registra alebo kontaktujte podporu. Domovská stránka - Zobraziť výsledky Domovskej stránky, keď je text dopytu prázdny. - Zobraziť výsledky histórie na Domovskej stránke - Maximálny počet zobrazených výsledkov histórie na Domovskej stránke - Úprava je možná len vtedy, ak plugin podporuje funkciu Domovská stránka a Domovská stránka je povolená. + Zobraziť výsledky domovskej stránky, keď je text dopytu prázdny. + Zobraziť výsledky histórie na domovskej stránke + Maximálny počet histórie výsledkov zobrazenej na domovskej stránke + Štýl histórie + Vyberte, ktorý typ histórie sa má zobraziť v histórii a na domovskej stránke + História dopytov + História naposledy otvorených + Úprava je možná len vtedy, ak plugin podporuje funkciu domovská stránka a zároveň je povolená. Zobraziť vyhľadávacie okno v popredí Prepíše nastavenie "Vždy na vrchu" ostatných programov a zobrazí navrchu Flow. Reštartovať po úprave pluginu cez Repozitár pluginov @@ -535,7 +543,7 @@ Nevykonali sa žiadne zmeny. Domovská stránka - Ak chcete zobrazovať výsledky pluginu, keď je dopyt prázdny, povoľte funkciu Domovská stránka. + Ak chcete zobrazovať výsledky pluginu, keď je dopyt prázdny, povoľte funkciu domovská stránka. Klávesová skratka vlastného vyhľadávania diff --git a/Flow.Launcher/Languages/sr-Cyrl-RS.xaml b/Flow.Launcher/Languages/sr-Cyrl-RS.xaml index c9cd61886..d7d60e6a0 100644 --- a/Flow.Launcher/Languages/sr-Cyrl-RS.xaml +++ b/Flow.Launcher/Languages/sr-Cyrl-RS.xaml @@ -64,6 +64,10 @@ Position Reset Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Settings @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Icons You have activated Flow Launcher {0} times Check for Updates - Become A Sponsor + Become a Sponsor New version {0} is available, would you like to restart Flow Launcher to use the update? Check updates failed, please check your connection and proxy settings to api.github.com. diff --git a/Flow.Launcher/Languages/sr.xaml b/Flow.Launcher/Languages/sr.xaml index bfc41e5b8..7d1bcb9f3 100644 --- a/Flow.Launcher/Languages/sr.xaml +++ b/Flow.Launcher/Languages/sr.xaml @@ -64,6 +64,10 @@ Position Reset Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Podešavanja @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Icons Aktivirali ste Flow Launcher {0} puta Proveri ažuriranja - Become A Sponsor + Become a Sponsor Nove verzija {0} je dostupna, molim Vas ponovo pokrenite Flow Launcher. Neuspešna provera ažuriranja, molim Vas proverite vašu vezu i podešavanja za proksi prema api.github.com. diff --git a/Flow.Launcher/Languages/tr.xaml b/Flow.Launcher/Languages/tr.xaml index 2133bbb5a..67cdf9da4 100644 --- a/Flow.Launcher/Languages/tr.xaml +++ b/Flow.Launcher/Languages/tr.xaml @@ -64,6 +64,10 @@ Pencere Konumunu Sıfırla Arama penceresinin konumunu sıfırla Aramak için buraya yazın + {0}: Bu eklenti hala başlatılıyor... + Yeniden sorgulamak için bu sonucu seçin + {0}: Yanıt veremedi! + Daha fazla bilgi için bu sonucu seçin Ayarlar @@ -171,6 +175,10 @@ Sorgu metni boş olduğunda ana sayfa sonuçlarını gösterin. Geçmiş Sonuçlarını Ana Sayfada Göster Ana Sayfada Gösterilen Maksimum Geçmiş Sonuçları + Geçmiş Stili + Geçmiş ve Ana Sayfada gösterilecek geçmiş türünü seçin + Sorgu geçmişi + Son açılan geçmiş Bu sadece eklenti Ana Sayfa özelliğini destekliyorsa ve Ana Sayfa etkinleştirilmiş ise düzenlenebilir. Arama Penceresini En Üstte Göster Diğer programların 'Her Zaman Üstte' ayarını geçersiz kılar ve Flow’u en önde gösterir. @@ -446,7 +454,7 @@ Kullanılan Simgeler Şu ana kadar Flow Launcher'ı {0} kez aktifleştirdiniz. Güncellemeleri Kontrol Et - Sponsor Olun + Become a Sponsor Uygulamanın yeni sürümü ({0}) mevcut, Lütfen Flow Launcher'ı yeniden başlatın. Güncelleme kontrolü başarısız oldu. Lütfen bağlantınız ve vekil sunucu ayarlarınızın api.github.com adresine ulaşabilir olduğunu kontrol edin. diff --git a/Flow.Launcher/Languages/uk-UA.xaml b/Flow.Launcher/Languages/uk-UA.xaml index 53dcb8933..bec1f85e3 100644 --- a/Flow.Launcher/Languages/uk-UA.xaml +++ b/Flow.Launcher/Languages/uk-UA.xaml @@ -64,6 +64,10 @@ Скидання позиції Скинути положення вікна пошуку Напишіть тут, аби знайти + {0}: Цей плагін все ще ініціалізується... + Виберіть цей результат, щоб повторити запит + {0}: Не вдалося відповісти! + Виберіть цей результат, щоб отримати додаткову інформацію Налаштування @@ -171,6 +175,10 @@ Показувати результати на головній сторінці, коли текст запиту порожній. Показати результати історії на головній Максимальна кількість результатів історії, що показуються на головній + Стиль історії + Виберіть тип історії, який буде показуватися на сторінці «Історія» та «Головна». + Історія запитів + Остання відкрита історія Це можна редагувати тільки в тому випадку, якщо плагін підтримує функцію «Головна сторінка» і вона ввімкнена. Показувати вікно пошуку на передньому плані Перекриває налаштування «Завжди зверху» інших програм і виводить Flow на передній план. @@ -214,8 +222,8 @@ Версія Сайт Видалити - Search delay time: default - Search delay time: {0}ms + Час затримки пошуку: типово + Час затримки пошуку: {0} мс Не вдалося видалити налаштування плагіну Плагіни: {0} — Не вдалося видалити файли налаштувань плагінів, видаліть їх вручну. Не вдалося видалити кеш плагіну @@ -597,9 +605,9 @@ Вказаний файловий менеджер не знайдено. Перевірте налаштування вашого файлового менеджера в розділі Налаштування > Загальні. Помилка - An error occurred while opening the folder. + Під час відкриття теки сталася помилка. Під час відкриття URL-адреси в браузері сталася помилка. Перевірте налаштування типового веббраузера у розділі «Загальні» вікна налаштувань. - File or directory not found: {0} + Файл або каталог не знайдено: {0} Будь ласка, зачекайте... diff --git a/Flow.Launcher/Languages/vi.xaml b/Flow.Launcher/Languages/vi.xaml index 0618dc9a5..5809c7837 100644 --- a/Flow.Launcher/Languages/vi.xaml +++ b/Flow.Launcher/Languages/vi.xaml @@ -64,6 +64,10 @@ Đặt lại vị trí Cài lại vị trí cửa sổ tìm kiếm Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info Cài đặt @@ -171,6 +175,10 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. @@ -446,7 +454,7 @@ Biểu tượng Bạn đã kích hoạt Flow Launcher {0} lần Kiểm tra các bản cập nhật - Trở thành nhà tài trợ + Become a Sponsor Đã có phiên bản mới {0}, bạn có muốn khởi động lại Flow Launcher để sử dụng bản cập nhật không? Kiểm tra cập nhật không thành công. Vui lòng kiểm tra kết nối và cài đặt proxy của bạn tới api.github.com. diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index a5a412439..7af54dc54 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -64,6 +64,10 @@ 重置位置 重置搜索窗口位置 在此处输入以搜索 + {0}:此插件仍在初始化... + 选择此结果以重试 + {0}:响应失败! + 选择此结果以获取更多信息 设置 @@ -123,7 +127,7 @@ 常规 使用拼音搜索 - 拼音是翻译中文的罗马化拼写的标准系统。请注意,启用此功能可以大大增加搜索时的内存使用量。 + 拼音是翻译中文的罗马化拼写的标准系统。请注意,启用此功能会大幅增加搜索时的内存使用量。 使用双拼 使用双拼而不是全拼进行搜索。 双拼方案 @@ -141,7 +145,7 @@ Flow 启动时总是打开预览面板。按 {0} 以切换预览。 当前主题已启用模糊效果,不允许启用阴影效果 延迟搜索 - 在输入时添加一个短时间延迟以减少UI闪烁和加载结果的负载。建议您的输入速度是平均的。 + 在输入时添加一个短时间延迟以减少UI闪烁和加载结果的负载。如果您的打字速度处于中等水平,建议启用此功能。 输入等待时间(毫秒),直到输入被认为完成。这只能在启用搜索延迟时进行编辑。 默认搜索延迟时间 在输入停止后显示结果之前等待时间。更高的数值等待更长时间(毫秒) @@ -171,6 +175,10 @@ 当查询文本为空时显示主页结果。 在主页中显示历史记录 在主页显示的最大历史结果数 + 历史样式 + 选择要在历史和主页中显示的历史类型 + 查询历史 + 最近打开历史 这只能在插件支持主页功能和主页启用时进行编辑。 将搜索窗口置于顶层 覆盖其他“总是在顶部”的程序窗口并在最顶层的位置显示 Flow Launcher 搜索窗口。 @@ -289,7 +297,7 @@ 项目高度 查询框字体 结果标题字体 - 结果字幕字体 + 结果副标题字体 重置 重置为推荐字体和大小设置。 导入主题尺寸 @@ -606,7 +614,7 @@ 检查新的更新 - 您已经拥有最新的 Flow Launcher 版本 + 您当前使用的 Flow Launcher 已是最新版本 检查到更新 更新中... diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index 7c0fef077..ca7da7624 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -64,6 +64,10 @@ 重設位置 Reset search window position Type here to search + {0}: This plugin is still initializing... + Select this result to requery + {0}: Failed to respond! + Select this result for more info 設定 @@ -171,11 +175,15 @@ Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page + History Style + Choose the type of history to show in the History and Home Page + Query history + Last opened history This can only be edited if plugin supports Home feature and Home Page is enabled. Show Search Window at Foremost Overrides other programs' 'Always on Top' setting and displays Flow in the foremost position. - Restart after modifying plugin via Plugin Store - Restart Flow Launcher automatically after installing/uninstalling/updating plugin via Plugin Store + 在插件商店改動插件後重新啟動 + 在插件商店安裝/移除/更新插件後自動重新啟動Flow Launcher Show unknown source warning Show warning when installing plugins from unknown sources Auto update plugins @@ -446,7 +454,7 @@ 圖示 您已經啟動了 Flow Launcher {0} 次 檢查更新 - 成為贊助者 + Become a Sponsor 發現有新版本 {0}, 請重新啟動 Flow Launcher。 檢查更新失敗,請檢查你對 api.github.com 的連線和代理設定。 diff --git a/Flow.Launcher/packages.lock.json b/Flow.Launcher/packages.lock.json index c90db6b0c..2c685ea09 100644 --- a/Flow.Launcher/packages.lock.json +++ b/Flow.Launcher/packages.lock.json @@ -178,8 +178,8 @@ }, "DeltaCompressionDotNet": { "type": "Transitive", - "resolved": "1.0.0", - "contentHash": "nwbZAYd+DblXAIzlnwDSnl0CiCm8jWLfHSYnoN4wYhtIav6AegB3+T/vKzLbU2IZlPB8Bvl8U3NXpx3eaz+N5w==" + "resolved": "1.1.0", + "contentHash": "j/zGAQ9hLbl7JDpeO40DaXvyyNxwQNDwnJEN7eCexn5F9Kid+VKya/Er0rfIv5Zod/32XarkqFP/V6WFHS/UpQ==" }, "Droplex": { "type": "Transitive", @@ -249,8 +249,8 @@ }, "Meziantou.Framework.Win32.Jobs": { "type": "Transitive", - "resolved": "3.4.4", - "contentHash": "AivBzH5wM1NHBLehclim+o37SmireP7JxCRUoTilsc/h7LH9+YCPjb6Ig6y0khnQhFcO1P8RHYw4oiR15TGHUg==" + "resolved": "3.4.5", + "contentHash": "R/d2VSdbRQHDWfPf5sjvMOWrWvxh/CswdMDKODppHTjsDLIkLQbQrnjmtAaVqu0qgUf8KFlVzEfxy3GIVoCK9g==" }, "Microsoft.Extensions.Configuration": { "type": "Transitive", @@ -541,6 +541,16 @@ "resolved": "17.8.8", "contentHash": "rWXThIpyQd4YIXghNkiv2+VLvzS+MCMKVRDR0GAMlflsdo+YcAN2g2r5U1Ah98OFjQMRexTFtXQQ2LkajxZi3g==" }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, "Microsoft.Win32.Registry": { "type": "Transitive", "resolved": "5.0.0", @@ -570,6 +580,57 @@ "System.IO.Pipelines": "8.0.0" } }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, "Newtonsoft.Json": { "type": "Transitive", "resolved": "13.0.3", @@ -601,11 +662,126 @@ "NLog": "6.0.4" } }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" + }, "runtime.osx.10.10-x64.CoreCompat.System.Drawing": { "type": "Transitive", "resolved": "5.8.64", "contentHash": "Ey7xQgWwixxdrmhzEUvaR4kxZDSQMWQScp8ViLvmL5xCBKG6U3TaMv/jzHilpfQXpHmJ4IylKGzzMvnYX2FwHQ==" }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" + }, + "SharpCompress": { + "type": "Transitive", + "resolved": "0.17.1", + "contentHash": "NSofrWwVr0z0ZNRCoV6XFjdopMbOSY6QVRLBfLXUDcjMLNKKhDV6zibiFEVa9eVaz24deslc8kqdVYurKJq/aA==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, "SharpVectors.Wpf": { "type": "Transitive", "resolved": "1.8.5", @@ -618,11 +794,12 @@ }, "squirrel.windows": { "type": "Transitive", - "resolved": "1.5.2", - "contentHash": "89Y/CFxWm7SEOjvuV2stVa8p+SNM9GOLk4tUNm2nUF792nfkimAgwRA/umVsdyd/OXBH8byXSh4V1qck88ZAyQ==", + "resolved": "1.9.0", + "contentHash": "1xOe9lgQX7u+AV19n7vTjRXn45fZ6rQ5pMSe6q54Nfe9sWHUikMz5d3Mc15T0Gw/9hVausR8BLIMVsp170DH/Q==", "dependencies": { - "DeltaCompressionDotNet": "[1.0.0, 2.0.0)", + "DeltaCompressionDotNet": "[1.1.0, 2.0.0)", "Mono.Cecil": "0.9.6.1", + "SharpCompress": "0.17.1", "Splat": "1.6.2" } }, @@ -650,6 +827,26 @@ "runtime.osx.10.10-x64.CoreCompat.System.Drawing": "5.8.64" } }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, "System.Collections": { "type": "Transitive", "resolved": "4.3.0", @@ -660,6 +857,35 @@ "System.Runtime": "4.3.0" } }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, "System.Diagnostics.Debug": { "type": "Transitive", "resolved": "4.3.0", @@ -670,11 +896,43 @@ "System.Runtime": "4.3.0" } }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, "System.Diagnostics.EventLog": { "type": "Transitive", "resolved": "9.0.9", "contentHash": "wpsUfnyv8E5K4WQaok6weewvAbQhcLwXFcHBm5U0gdEaBs85N//ssuYvRPFWwz2rO/9/DFP3A1sGMzUFBj8y3w==" }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, "System.Drawing.Common": { "type": "Transitive", "resolved": "7.0.0", @@ -693,6 +951,30 @@ "System.Runtime": "4.3.0" } }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, "System.IO": { "type": "Transitive", "resolved": "4.3.0", @@ -705,11 +987,165 @@ "System.Threading.Tasks": "4.3.0" } }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, "System.IO.Pipelines": { "type": "Transitive", "resolved": "8.0.0", "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA==" }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, "System.ObjectModel": { "type": "Transitive", "resolved": "4.3.0", @@ -739,6 +1175,38 @@ "resolved": "4.7.0", "contentHash": "VR4kk8XLKebQ4MZuKuIni/7oh+QGFmZW3qORd1GvBq/8026OpW501SzT/oypwiQl4TvT8ErnReh/NzY9u+C6wQ==" }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, "System.Reflection.Metadata": { "type": "Transitive", "resolved": "5.0.0", @@ -754,6 +1222,15 @@ "System.Runtime": "4.3.0" } }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, "System.Resources.ResourceManager": { "type": "Transitive", "resolved": "4.3.0", @@ -775,11 +1252,213 @@ "Microsoft.NETCore.Targets": "1.1.0" } }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, "System.Security.AccessControl": { "type": "Transitive", "resolved": "6.0.1", "contentHash": "IQ4NXP/B3Ayzvw0rDQzVTYsCKyy0Jp9KI6aYcK7UnGVlR9+Awz++TIPCQtPYfLJfOpm8ajowMR09V7quD3sEHw==" }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, "System.Security.Principal.Windows": { "type": "Transitive", "resolved": "5.0.0", @@ -795,6 +1474,25 @@ "System.Runtime": "4.3.0" } }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, "System.Threading": { "type": "Transitive", "resolved": "4.3.0", @@ -814,11 +1512,72 @@ "System.Runtime": "4.3.0" } }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, "System.ValueTuple": { "type": "Transitive", "resolved": "4.5.0", "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, "ToolGood.Words.Pinyin": { "type": "Transitive", "resolved": "3.1.0.3", @@ -841,11 +1600,11 @@ "FSharp.Core": "[9.0.303, )", "Flow.Launcher.Infrastructure": "[1.0.0, )", "Flow.Launcher.Plugin": "[5.0.0, )", - "Meziantou.Framework.Win32.Jobs": "[3.4.4, )", + "Meziantou.Framework.Win32.Jobs": "[3.4.5, )", "Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )", "SemanticVersioning": "[3.0.0, )", "StreamJsonRpc": "[2.22.11, )", - "squirrel.windows": "[1.5.2, )" + "squirrel.windows": "[1.9.0, )" } }, "flow.launcher.infrastructure": { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 875ffd7cf..8249b354a 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -105,7 +105,7 @@ - + diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml index 234c613c6..44a126e61 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml @@ -2,7 +2,7 @@ 计算器 - 进行数学计算,包括十六进制值和高级函数,如“最小(1,2,3)”、“sqrt(123)”和“cos123”等。 + 进行数学计算,包括十六进制值和高级函数,如“min(1,2,3)”、“sqrt(123)”和“cos(123)”等。 请输入数字 表达错误或不完整(您是否忘记了一些括号?) 将结果复制到剪贴板 diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml index b56e4660f..0cf66c1cb 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml @@ -2,16 +2,16 @@ 計算機 - Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. + 執行數學計算,包括十六進位數值以及進階函數,例如 'min(1,2,3)'、'sqrt(123)' 和 'cos(123)'。 不是一個數 (NaN) - Expression wrong or incomplete (Did you forget some parentheses?) + 表示式錯誤或不完整(你是否忘記了某些括號?) 複製此數至剪貼簿 小數點分隔符號 - The decimal separator to be used in the output. + 用於輸出的小數點分隔符。 使用系統區域設定 逗號 (,) 點 (.) 小數點後最大位數 - Copy failed, please try later - Show error message when calculation fails + 複製失敗,請稍後再試 + 計算失敗時顯示錯誤訊息 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml index 8a701ebc6..b9a825bf2 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml @@ -70,9 +70,9 @@ Content Search Engine Directory Recursive Search Engine - Index Search Engine + インデックス検索エンジン Windowsのインデックスオプションを開く - Excluded File Types (comma seperated) + 除外されたファイルタイプ(カンマ区切りで入力) 例: exe,jpg,png 結果の最大表示件数 The maximum number of results requested from active search engine @@ -163,8 +163,8 @@ 作成日時 ↓ 更新日時 ↑ 更新日時 ↓ - Attributes ↑ - Attributes ↓ + 属性 ↑ + 属性 ↓ File List FileName ↑ File List FileName ↓ 実行回数 ↑ @@ -187,7 +187,7 @@ Everything サービスをインストールしています。お待ちください… Everything サービスを正常にインストールしました Everything サービスを自動的にインストールできませんでした。https://www.voidtools.com から手動でインストールしてください - Click here to start it + ここをクリックして開始 Everythingのインストールが見つかりませんでした。手動で場所を指定しますか?{0}{0}「いいえ」をクリックすると、Everythingが自動的にインストールされます。 Everything でのコンテンツ検索を有効にしますか? インデックスなしでは非常に遅くなることがあります(Everything v1.5以降でのみサポートされています) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml index 60a08a82f..7600757a2 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml @@ -22,7 +22,7 @@ Виникла помилка під час пошуку: {0} Не вдалося відкрити папку Не вдалося відкрити файл - This new action keyword is already assigned to another plugin, please choose a different one + Нова команда активації вже призначена іншому плагіну, виберіть іншу Видалити diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index fd62566d5..a4e959dd9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -48,11 +48,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything public static async ValueTask IsEverythingRunningAsync(CancellationToken token = default) { - await _semaphore.WaitAsync(token); + try + { + await _semaphore.WaitAsync(token); + } + catch (OperationCanceledException) + { + return false; + } try { - EverythingApiDllImport.Everything_GetMajorVersion(); + _ = EverythingApiDllImport.Everything_GetMajorVersion(); var result = EverythingApiDllImport.Everything_GetLastError() != StateCode.IPCError; return result; } @@ -77,8 +84,14 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything if (option.MaxCount < 0) throw new ArgumentOutOfRangeException(nameof(option.MaxCount), option.MaxCount, "MaxCount must be greater than or equal to 0"); - await _semaphore.WaitAsync(token); - + try + { + await _semaphore.WaitAsync(token); + } + catch (OperationCanceledException) + { + yield break; + } try { @@ -120,8 +133,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything EverythingApiDllImport.Everything_SetRequestFlags(EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME); } - - if (token.IsCancellationRequested) yield break; if (!EverythingApiDllImport.Everything_QueryW(true)) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index f9d8963e6..d7b069082 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -57,19 +57,16 @@ namespace Flow.Launcher.Plugin.Explorer.Search { if (string.IsNullOrEmpty(query.Search) && ActionKeywordMatch(query, Settings.ActionKeyword.QuickAccessActionKeyword)) return QuickAccess.AccessLinkListAll(query, Settings.QuickAccessLinks); - - var quickAccessLinks = QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); - - results.UnionWith(quickAccessLinks); } else { + // No action keyword matched- plugin should not handle this query, return empty results. return new List(); } IAsyncEnumerable searchResults; - bool isPathSearch = query.Search.IsLocationPathString() + bool isPathSearch = query.Search.IsLocationPathString() || EnvironmentVariables.IsEnvironmentVariableSearch(query.Search) || EnvironmentVariables.HasEnvironmentVar(query.Search); @@ -103,10 +100,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search searchResults = Settings.IndexProvider.SearchAsync(query.Search, token); engineName = Enum.GetName(Settings.IndexSearchEngine); break; + + case true or false + when ActionKeywordMatch(query, Settings.ActionKeyword.QuickAccessActionKeyword): + return QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); + default: return results.ToList(); } + // Merge Quick Access Link results for non-path searches. + results.UnionWith(QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks)); + try { await foreach (var search in searchResults.WithCancellation(token).ConfigureAwait(false)) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml index ddd24d0ed..c13048133 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml @@ -31,7 +31,7 @@ Please check if you can connect to github.com. This error means you may not be able to install or update plugins. Update all plugins Would you like to update all plugins? - Would you like to update {0} plugins?{1}Flow Launcher will restart after updating all plugins. + 你要更新{0}個插件?{1}Flow Launcher會在更新所有插件後重新啟動。 Would you like to update {0} plugins? {0} plugins successfully updated. Restarting Flow, please wait... Plugin {0} successfully updated. Restarting Flow, please wait... @@ -66,5 +66,5 @@ Install from unknown source warning - Restart Flow Launcher automatically after installing/uninstalling/updating plugin via Plugins Manager + 以插件管理員安裝/移除/更新插件後自動重新啟動Flow Launcher diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/zh-tw.xaml index a8ff4ecbc..2653b69da 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/zh-tw.xaml @@ -82,7 +82,7 @@ 程式 在 Flow Launcher 中搜尋程式 - Invalid Path + 無效的路徑 Customized Explorer Args diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 0258a10d2..456085fca 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -31,6 +31,8 @@ namespace Flow.Launcher.Plugin.Program internal static PluginInitContext Context { get; private set; } + private static readonly Lock _lastIndexTimeLock = new(); + private static readonly List emptyResults = []; private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; @@ -82,8 +84,45 @@ namespace Flow.Launcher.Plugin.Program { var resultList = await Task.Run(async () => { - await _win32sLock.WaitAsync(token); - await _uwpsLock.WaitAsync(token); + // Preparing win32 programs + List win32s; + bool win32LockAcquired = false; + try + { + await _win32sLock.WaitAsync(token); + win32LockAcquired = true; + win32s = [.. _win32s]; + } + catch (OperationCanceledException) + { + return emptyResults; + } + finally + { + // Only release the lock if it was acquired + if (win32LockAcquired) _win32sLock.Release(); + } + + // Preparing UWP programs + List uwps; + bool uwpsLockAcquired = false; + try + { + await _uwpsLock.WaitAsync(token); + uwpsLockAcquired = true; + uwps = [.. _uwps]; + } + catch (OperationCanceledException) + { + return emptyResults; + } + finally + { + // Only release the lock if it was acquired + if (uwpsLockAcquired) _uwpsLock.Release(); + } + + // Start querying programs try { // Collect all UWP Windows app directories @@ -94,8 +133,8 @@ namespace Flow.Launcher.Plugin.Program .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray() : null; - return _win32s.Cast() - .Concat(_uwps) + return win32s.Cast() + .Concat(uwps) .AsParallel() .WithCancellation(token) .Where(HideUninstallersFilter) @@ -109,11 +148,6 @@ namespace Flow.Launcher.Plugin.Program { return emptyResults; } - finally - { - _uwpsLock.Release(); - _win32sLock.Release(); - } }, token); resultList = resultList.Count != 0 ? resultList : emptyResults; @@ -275,7 +309,12 @@ namespace Flow.Launcher.Plugin.Program var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0; - if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now) + bool needReindex; + lock (_lastIndexTimeLock) + { + needReindex = _settings.LastIndexTime.AddHours(30) < DateTime.Now; + } + if (cacheEmpty || needReindex) { _ = Task.Run(async () => { @@ -308,7 +347,10 @@ namespace Flow.Launcher.Plugin.Program } ResetCache(); await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); - _settings.LastIndexTime = DateTime.Now; + lock (_lastIndexTimeLock) + { + _settings.LastIndexTime = DateTime.Now; + } } catch (Exception e) { @@ -333,7 +375,10 @@ namespace Flow.Launcher.Plugin.Program } ResetCache(); await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); - _settings.LastIndexTime = DateTime.Now; + lock (_lastIndexTimeLock) + { + _settings.LastIndexTime = DateTime.Now; + } } catch (Exception e) { diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Shell/Languages/zh-tw.xaml index 02eb35336..3fa06dabc 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Shell/Languages/zh-tw.xaml @@ -13,7 +13,7 @@ 此指令已執行了 {0} 次 執行指令 以系統管理員身分執行 - Copy the command + 複製命令 Only show number of most used commands: Command not found: {0} Error running the command: {0} diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml index 8b5f3c94b..8f19cdcb3 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml @@ -77,8 +77,8 @@ Надає команди, пов'язані з системою, наприклад, вимкнення, блокування, налаштування тощо. - This theme supports two (light/dark) modes and Blur Transparent Background - This theme supports two (light/dark) modes - This theme supports Blur Transparent Background + Ця тема підтримує два режими (світлий / темний) та розмитий прозорий фон + Ця тема підтримує два (світлий / темний) режими + Ця тема підтримує розмитий прозорий фон diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml index 18ac48fd0..bd705490c 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml @@ -44,7 +44,7 @@ Open recycle bin 索引選項 Hibernate computer - Save all Flow Launcher settings + 儲存所有Flow Lanuncher設定 Refreshes plugin data with new content Open Flow Launcher's log location Check for new Flow Launcher update diff --git a/Plugins/Flow.Launcher.Plugin.Url/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/es.xaml index 5d402f293..e84a02a30 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/es.xaml @@ -10,13 +10,13 @@ Elegir Aplicación(*.exe)|*.exe|Todos los archivos|*.* - Use custom instead of Flow's default web browser - Browser path + Utilizar un navegador web personalizado en lugar del predeterminado de Flow + Ruta del navegador Nueva pestaña Nueva ventana - Private mode + Modo privado - Prefer https over http + Priorizar https frente a http diff --git a/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml index f643a1081..b51c79899 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml @@ -10,13 +10,13 @@ 選択 Application(*.exe)|*.exe|All files|*.* - Use custom instead of Flow's default web browser - Browser path + FlowのデフォルトのWebブラウザの代わりにカスタムを使用する + ブラウザーのパス - New tab - New window + 新しいタブ + 新しいウインドウ - Private mode + プライベートモード - Prefer https over http + httpよりもhttpsを優先 diff --git a/Plugins/Flow.Launcher.Plugin.Url/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/tr.xaml index 2ce323d08..0318b4301 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/tr.xaml @@ -10,13 +10,13 @@ Seç Programlar (*.exe)|*.exe|Tüm Dosyalar|*.* - Use custom instead of Flow's default web browser - Browser path + Flow'un varsayılan web tarayıcısı yerine özel tarayıcıyı kullanın + Tarayıcı yolu Yeni sekme Yeni pencere - Private mode + Gizli mod - Prefer https over http + http yerine https'yi tercih et diff --git a/Plugins/Flow.Launcher.Plugin.Url/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/uk-UA.xaml index f7ccd7cc1..a3cf6e02d 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/uk-UA.xaml @@ -10,13 +10,13 @@ Обрати Application(*.exe)|*.exe|Усі файли|*.* - Use custom instead of Flow's default web browser - Browser path + Використовувати власний веббраузер замість стандартного браузера Flow + Шлях до браузера Нова вкладка Нове вікно - Private mode + Приватний режим - Prefer https over http + Віддавати перевагу HTTPS над HTTP diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml index 7daee625b..41a6325b3 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml @@ -45,7 +45,7 @@ Por favor, introduzca una URL La palabra clave de acción ya está en uso, por favor, introduzca una diferente Correcto - Failed to update search source. The item may have been removed. + No se ha podido actualizar la fuente de búsqueda. Es posible que el elemento haya sido eliminado. Sugerencia: No es necesario colocar imágenes personalizadas en esta carpeta, al actualizar Flow se perderán. Flow copiará automáticamente cualquier imagen externa a esta carpeta en la ubicación de imágenes personalizada de WebSearch. Búsquedas Web diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml index 3ad1461e6..51aa07bab 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml @@ -46,7 +46,7 @@ https://www.netflix.com/search?q={q} URLを入力してください キーワードはすでに存在します。違うキーワードを入力してください 成功しました - Failed to update search source. The item may have been removed. + 検索ソースの更新に失敗しました。項目が削除されている可能性があります。 Hint: You do not need to place custom images in this directory, if Flow's version is updated they will be lost. Flow will automatically copy any images outside of this directory across to WebSearch's custom image location. Web検索 diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml index 8c2dd2104..e706b7bf7 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml @@ -45,7 +45,7 @@ Lütfen bir URL giriniz Anahtar kelime zaten mevcut. Lütfen yeni bir tane seçiniz. Başarılı - Failed to update search source. The item may have been removed. + Arama kaynağı güncellenemedi. Öge kaldırılmış olabilir. İpucu: Bu dizine özel resimler yerleştirmenize gerek yoktur, Flow'un sürümü güncellenirse bunlar kaybolacaktır. Flow, bu dizinin dışındaki tüm görüntüleri otomatik olarak WebSearch'ün özel görüntü konumuna kopyalayacaktır. Web Araması diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml index 3fe7068d1..2163c29be 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml @@ -45,7 +45,7 @@ Будь ласка, введіть URL-адресу Ключове слово дії вже існує, будь ласка, введіть інше Успішно - Failed to update search source. The item may have been removed. + Не вдалося оновити джерело пошуку. Елемент, можливо, було видалено. Підказка: Вам не потрібно розміщувати власні зображення в цьому каталозі, якщо версія Flow оновиться, вони будуть втрачені. Flow автоматично копіює всі зображення з цього каталогу до спеціального каталогу WebSearch. Вебпошук diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx index 3a2f991a1..ec98231ae 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx @@ -150,7 +150,7 @@ Area Control Panel (legacy settings) - アクティブ化 + アクティベーション Area UpdateAndSecurity @@ -1206,7 +1206,7 @@ Windows の設定を検索するためのプラグイン - Windows Settings + Windows の設定 電源とスリープ @@ -1836,19 +1836,19 @@ Check firewall status - Send or receive a file + ファイルを送受信する - Add or remove user accounts + ユーザーアカウントの追加または削除 Edit the system environment variables - Manage BitLocker + BitLocker の管理 - Auto-hide the taskbar + タスクバーを自動的に隠す Change sound card settings @@ -1947,10 +1947,10 @@ View recommended actions to keep Windows running smoothly - Change cursor blink rate + カーソルの点滅速度を変更する - Add or remove programs + プログラムの追加と削除 Create a password reset disk @@ -2070,7 +2070,7 @@ Change temporary Internet file settings - Connect to the Internet + インターネットに接続 Find and fix audio playback problems @@ -2079,7 +2079,7 @@ Change the mouse pointer display or speed - Back up your recovery key + リカバリーキーのバックアップ Save backup copies of your files with File History @@ -2094,31 +2094,31 @@ Change how your mouse works - Show how much RAM is on this computer + このコンピュータにあるRAMの量を表示する - Edit power plan + 電源プランを編集 - Adjust system volume + システム音量の調整 - Defragment and optimise your drives + ドライブのデフラグと最適化 Set up ODBC data sources (32-bit) - Change Font Settings + フォント設定を変更 - Magnify portions of the screen using Magnifier + 拡大鏡を使って画面の一部を拡大する Change the file type associated with a file extension - View event logs + イベントログを表示 Manage Windows Credentials @@ -2127,7 +2127,7 @@ Set up a microphone - Change how the mouse pointer looks + マウスポインタの見た目を変更する Change power-saving settings @@ -2152,7 +2152,7 @@ Manage Work Folders - Encrypt your offline files + オフラインファイルを暗号化 Train the computer to recognise your voice @@ -2161,7 +2161,7 @@ Advanced printer setup - Change default printer + 既定のプリンタを変更する Edit environment variables for your account @@ -2188,19 +2188,19 @@ Private Character Editor - Record steps to reproduce a problem + 問題を再現するためのステップを記録 - Adjust the appearance and performance of Windows + Windowsの外観とパフォーマンスを調整する - Settings for Microsoft IME (Japanese) + 日本語用 Microsoft IME の設定 Invite someone to connect to your PC and help you, or offer to help someone else - Run programs made for previous versions of Windows + 以前のバージョンの Windows 用に作られたプログラムを実行 Choose the order of how your screen rotates @@ -2212,10 +2212,10 @@ Set flicks to perform certain tasks - Change account type + アカウントタイプの変更 - Change screen saver + スクリーンセーバーを変更 Change User Account Control settings @@ -2224,37 +2224,37 @@ Turn on easy access keys - Identify and repair network problems + ネットワークの問題を特定して修復する Find and fix networking and connection problems - Play CDs or other media automatically + CD やその他のメディアを自動的に再生 View basic information about your computer - Choose how you open links + リンクを開く方法の選択 Allow Remote Assistance invitations to be sent from this computer - Task Manager + タスクマネージャー Turn flicks on or off - Add a language + 言語を追加 View network status and tasks - Turn Magnifier on or off + 拡大鏡のオン/オフ See the name of this computer @@ -2269,10 +2269,10 @@ Manage disk space used by your offline files - Turn High Contrast on or off + ハイコントラストのオン/オフ - Change the way time is displayed + 時間の表示方法を変更する Change how web pages are displayed in tabs @@ -2284,22 +2284,22 @@ Manage audio devices - Change security settings + セキュリティ設定を変更 Check security status - Delete cookies or temporary files + Cookie や一時ファイルを削除 - Specify which hand you write with + どの手で書くかを指定する Change touch input settings - How to change the size of virtual memory + 仮想メモリのサイズを変更する方法 Hear text read aloud with Narrator @@ -2353,13 +2353,13 @@ Manage Storage Spaces - Show or hide file extensions + 拡張子の表示/非表示 - Allow an app through Windows Firewall + Windowsファイアウォールでアプリを許可する - Change system sounds + システムのサウンドを変更 ClearTypeテキストを調整 @@ -2380,7 +2380,7 @@ Internet Explorer の検索プロバイダを変更する - Join a domain + ドメインに参加 端末を追加 @@ -2398,7 +2398,7 @@ プログラムのアンインストール - Create and format hard disk partitions + ハードディスクのパーティション作成とフォーマット 日付、時刻、数の書式を変更 @@ -2410,7 +2410,7 @@ Manage network passwords - Change input methods + 入力方法を変更 Manage advanced sharing settings @@ -2428,13 +2428,13 @@ Manage Web Credentials - Change the time zone + タイムゾーンの変更 音声認識を開始 - View installed updates + インストール済みのアップデートを表示 What's happened to the Quick Launch toolbar? @@ -2452,7 +2452,7 @@ Change the way measurements are displayed - Press key combinations one at a time + キーの組み合わせを同時に押してください Restore data, files or computer from backup (Windows 7) @@ -2467,7 +2467,7 @@ ペンまたはタッチ入力の画面をキャリブレーション - Manage user certificates + ユーザー証明書の管理 タスクのスケジュール diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx index 5b4dea6a9..2d242d5b1 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx @@ -1377,7 +1377,7 @@ Area SurfaceHub - Domov + Nastavenia dovmoskej stránky Area Home, Overview-page for all areas of settings diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1 index 8d2d14a80..dc7c39407 100644 --- a/Scripts/post_build.ps1 +++ b/Scripts/post_build.ps1 @@ -33,7 +33,7 @@ function Build-Path { function Copy-Resources ($path) { # making version static as multiple versions can exist in the nuget folder and in the case a breaking change is introduced. - Copy-Item -Force $env:USERPROFILE\.nuget\packages\squirrel.windows\1.5.2\tools\Squirrel.exe $path\Output\Update.exe + Copy-Item -Force $env:USERPROFILE\.nuget\packages\squirrel.windows\1.9.0\tools\Squirrel.exe $path\Output\Update.exe } function Delete-Unused ($path, $config) { @@ -79,7 +79,7 @@ function Pack-Squirrel-Installer ($path, $version, $output) { $icon = "$path\Flow.Launcher\Resources\app.ico" Write-Host "icon: $icon" # Squirrel.com: https://github.com/Squirrel/Squirrel.Windows/issues/369 - New-Alias Squirrel $env:USERPROFILE\.nuget\packages\squirrel.windows\1.5.2\tools\Squirrel.exe -Force + New-Alias Squirrel $env:USERPROFILE\.nuget\packages\squirrel.windows\1.9.0\tools\Squirrel.exe -Force # why we need Write-Output: https://github.com/Squirrel/Squirrel.Windows/issues/489#issuecomment-156039327 # directory of releaseDir in squirrel can't be same as directory ($nupkg) in releasify $temp = "$output\Temp" diff --git a/appveyor.yml b/appveyor.yml index b015c19ab..03542e8d2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: '2.0.2.{build}' +version: '2.0.3.{build}' # Do not build on tags because we create a release on merge to master. Otherwise will upload artifacts twice changing the hash, as well as triggering duplicate GitHub release action & NuGet deployments. skip_tags: true From 28065f72314824cc50435c2c12a56294f3fb4771 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Nov 2025 22:05:52 +0000 Subject: [PATCH 031/124] Bump actions/checkout from 5 to 6 Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/default_plugins.yml | 2 +- .github/workflows/dotnet.yml | 2 +- .github/workflows/release_pr.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/default_plugins.yml b/.github/workflows/default_plugins.yml index 83e830d75..381044c51 100644 --- a/.github/workflows/default_plugins.yml +++ b/.github/workflows/default_plugins.yml @@ -10,7 +10,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Setup .NET uses: actions/setup-dotnet@v5 with: diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 416c75a9d..f3c76027a 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -20,7 +20,7 @@ jobs: NUGET_CERT_REVOCATION_MODE: offline BUILD_NUMBER: ${{ github.run_number }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Set Flow.Launcher.csproj version id: update uses: vers-one/dotnet-project-version-updater@v1.7 diff --git a/.github/workflows/release_pr.yml b/.github/workflows/release_pr.yml index 58a877ba3..c7e9a90a6 100644 --- a/.github/workflows/release_pr.yml +++ b/.github/workflows/release_pr.yml @@ -11,7 +11,7 @@ jobs: update-pr: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: From 5623bf253bcc4b57af8525d586f02aac10645088 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 23 Nov 2025 18:05:12 +0800 Subject: [PATCH 032/124] Add null checks and improve dialog window handling Added early null checks for `hwnd` to prevent invalid processing. Enhanced thread safety by locking `_dialogWindow` updates. Documented dialog window state handling with comments for clarity. Handled scenarios for dialog window movement, resizing, hiding, destruction, and termination. Improved robustness and maintainability. --- .../DialogJump/DialogJump.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs b/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs index 4a3e6474e..53df05bf2 100644 --- a/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs +++ b/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs @@ -496,6 +496,8 @@ namespace Flow.Launcher.Infrastructure.DialogJump uint dwmsEventTime ) { + if (hwnd.IsNull) return; + await _foregroundChangeLock.WaitAsync(); try { @@ -647,6 +649,8 @@ namespace Flow.Launcher.Infrastructure.DialogJump uint dwmsEventTime ) { + if (hwnd.IsNull) return; + // If the dialog window is moved, update the Dialog Jump window position var dialogWindowExist = false; lock (_dialogWindowLock) @@ -672,6 +676,8 @@ namespace Flow.Launcher.Infrastructure.DialogJump uint dwmsEventTime ) { + if (hwnd.IsNull) return; + // If the dialog window is moved or resized, update the Dialog Jump window position if (_dragMoveTimer != null) { @@ -697,6 +703,8 @@ namespace Flow.Launcher.Infrastructure.DialogJump uint dwmsEventTime ) { + if (hwnd.IsNull) return; + // If the dialog window is destroyed, set _dialogWindowHandle to null var dialogWindowExist = false; lock (_dialogWindowLock) @@ -728,6 +736,8 @@ namespace Flow.Launcher.Infrastructure.DialogJump uint dwmsEventTime ) { + if (hwnd.IsNull) return; + // If the dialog window is hidden, set _dialogWindowHandle to null var dialogWindowExist = false; lock (_dialogWindowLock) @@ -759,6 +769,8 @@ namespace Flow.Launcher.Infrastructure.DialogJump uint dwmsEventTime ) { + if (hwnd.IsNull) return; + // If the dialog window is ended, set _dialogWindowHandle to null var dialogWindowExist = false; lock (_dialogWindowLock) From ce4a37b2924efa70e6bdde98b97f6aee66695346 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 22:35:13 +0000 Subject: [PATCH 033/124] Bump Mages from 3.0.0 to 3.0.1 --- updated-dependencies: - dependency-name: Mages dependency-version: 3.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../Flow.Launcher.Plugin.Calculator.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj index d3ce290ab..f30b24e4f 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj @@ -64,7 +64,7 @@ - + \ No newline at end of file From 48f67b188613cf519ab863d0f8dbfcd5aa9a16ce Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Wed, 26 Nov 2025 18:15:12 +0800 Subject: [PATCH 034/124] Improve and fix query result update logic issue & provide access to exact query typed by user (#3502) --- Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs | 4 +- Flow.Launcher.Core/Plugin/PluginManager.cs | 6 +- Flow.Launcher.Core/Plugin/QueryBuilder.cs | 17 +- Flow.Launcher.Plugin/Query.cs | 33 ++- Flow.Launcher.Test/QueryBuilderTest.cs | 10 +- Flow.Launcher/Helper/ResultHelper.cs | 4 +- Flow.Launcher/MainWindow.xaml.cs | 2 +- Flow.Launcher/ResultListBox.xaml.cs | 47 ++-- .../Storage/LastOpenedHistoryItem.cs | 4 +- Flow.Launcher/Storage/QueryHistory.cs | 4 +- Flow.Launcher/Storage/TopMostRecord.cs | 22 +- Flow.Launcher/ViewModel/MainViewModel.cs | 212 +++++++++--------- .../Search/SearchManager.cs | 2 +- 13 files changed, 201 insertions(+), 166 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs index 148fd969e..470019143 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs @@ -100,11 +100,11 @@ namespace Flow.Launcher.Core.Plugin RPC = new JsonRpc(handler, new JsonRPCPublicAPI(Context.API)); - RPC.AddLocalRpcMethod("UpdateResults", new Action((rawQuery, response) => + RPC.AddLocalRpcMethod("UpdateResults", new Action((trimmedQuery, response) => { var results = ParseResults(response); ResultsUpdated?.Invoke(this, - new ResultUpdatedEventArgs { Query = new Query() { RawQuery = rawQuery }, Results = results }); + new ResultUpdatedEventArgs { Query = new Query() { TrimmedQuery = trimmedQuery }, Results = results }); })); RPC.SynchronizationContext = null; RPC.StartListening(); diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index d3a8003c1..54712942c 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -401,7 +401,7 @@ namespace Flow.Launcher.Core.Plugin { Title = Localize.pluginStillInitializing(metadata.Name), SubTitle = Localize.pluginStillInitializingSubtitle(), - AutoCompleteText = query.RawQuery, + AutoCompleteText = query.TrimmedQuery, IcoPath = metadata.IcoPath, PluginDirectory = metadata.PluginDirectory, ActionKeywordAssigned = query.ActionKeyword, @@ -443,7 +443,7 @@ namespace Flow.Launcher.Core.Plugin { Title = Localize.pluginFailedToRespond(metadata.Name), SubTitle = Localize.pluginFailedToRespondSubtitle(), - AutoCompleteText = query.RawQuery, + AutoCompleteText = query.TrimmedQuery, IcoPath = Constant.ErrorIcon, PluginDirectory = metadata.PluginDirectory, ActionKeywordAssigned = query.ActionKeyword, @@ -467,7 +467,7 @@ namespace Flow.Launcher.Core.Plugin { Title = Localize.pluginStillInitializing(metadata.Name), SubTitle = Localize.pluginStillInitializingSubtitle(), - AutoCompleteText = query.RawQuery, + AutoCompleteText = query.TrimmedQuery, IcoPath = metadata.IcoPath, PluginDirectory = metadata.PluginDirectory, ActionKeywordAssigned = query.ActionKeyword, diff --git a/Flow.Launcher.Core/Plugin/QueryBuilder.cs b/Flow.Launcher.Core/Plugin/QueryBuilder.cs index 25a32a728..aac620cce 100644 --- a/Flow.Launcher.Core/Plugin/QueryBuilder.cs +++ b/Flow.Launcher.Core/Plugin/QueryBuilder.cs @@ -6,15 +6,16 @@ namespace Flow.Launcher.Core.Plugin { public static class QueryBuilder { - public static Query Build(string text, Dictionary nonGlobalPlugins) + public static Query Build(string originalQuery, string trimmedQuery, Dictionary nonGlobalPlugins) { // home query - if (string.IsNullOrEmpty(text)) + if (string.IsNullOrEmpty(trimmedQuery)) { return new Query() { Search = string.Empty, - RawQuery = string.Empty, + OriginalQuery = string.Empty, + TrimmedQuery = string.Empty, SearchTerms = Array.Empty(), ActionKeyword = string.Empty, IsHomeQuery = true @@ -22,14 +23,13 @@ namespace Flow.Launcher.Core.Plugin } // replace multiple white spaces with one white space - var terms = text.Split(Query.TermSeparator, StringSplitOptions.RemoveEmptyEntries); + var terms = trimmedQuery.Split(Query.TermSeparator, StringSplitOptions.RemoveEmptyEntries); if (terms.Length == 0) { // nothing was typed return null; } - var rawQuery = text; string actionKeyword, search; string possibleActionKeyword = terms[0]; string[] searchTerms; @@ -38,21 +38,22 @@ namespace Flow.Launcher.Core.Plugin { // use non global plugin for query actionKeyword = possibleActionKeyword; - search = terms.Length > 1 ? rawQuery[(actionKeyword.Length + 1)..].TrimStart() : string.Empty; + search = terms.Length > 1 ? trimmedQuery[(actionKeyword.Length + 1)..].TrimStart() : string.Empty; searchTerms = terms[1..]; } else { // non action keyword actionKeyword = string.Empty; - search = rawQuery.TrimStart(); + search = trimmedQuery.TrimStart(); searchTerms = terms; } return new Query() { Search = search, - RawQuery = rawQuery, + OriginalQuery = originalQuery, + TrimmedQuery = trimmedQuery, SearchTerms = searchTerms, ActionKeyword = actionKeyword, IsHomeQuery = false diff --git a/Flow.Launcher.Plugin/Query.cs b/Flow.Launcher.Plugin/Query.cs index f50614699..79e6f7d62 100644 --- a/Flow.Launcher.Plugin/Query.cs +++ b/Flow.Launcher.Plugin/Query.cs @@ -1,4 +1,5 @@ -using System.Text.Json.Serialization; +using System; +using System.Text.Json.Serialization; namespace Flow.Launcher.Plugin { @@ -8,11 +9,29 @@ namespace Flow.Launcher.Plugin public class Query { /// - /// Raw query, this includes action keyword if it has. - /// It has handled buildin custom query shortkeys and build-in shortcuts, and it trims the whitespace. - /// We didn't recommend use this property directly. You should always use Search property. + /// Original query, exactly how the user has typed into the search box. + /// We don't recommend using this property directly. You should always use Search property. /// - public string RawQuery { get; internal init; } + public string OriginalQuery { get; internal init; } + + /// + /// Raw query, this includes action keyword if it has. + /// It has handled built-in custom query hotkeys and built-in shortcuts, and it trims the whitespace. + /// We don't recommend using this property directly. You should always use Search property. + /// + [Obsolete("RawQuery is renamed to TrimmedQuery. This property will be removed. Update the code to use TrimmedQuery instead.")] + public string RawQuery { + get => TrimmedQuery; + internal init { TrimmedQuery = value; } + } + + /// + /// Original query but with trimmed whitespace. Includes action keyword. + /// It has handled built-in custom query hotkeys and build-in shortcuts. + /// If you need the exact original query from the search box, use OriginalQuery property instead. + /// We don't recommend using this property directly. You should always use Search property. + /// + public string TrimmedQuery { get; internal init; } /// /// Determines whether the query was forced to execute again. @@ -28,7 +47,7 @@ namespace Flow.Launcher.Plugin /// /// Search part of a query. - /// This will not include action keyword if exclusive plugin gets it, otherwise it should be same as RawQuery. + /// This will not include action keyword if exclusive plugin gets it, otherwise it should be same as TrimmedQuery. /// Since we allow user to switch a exclusive plugin to generic plugin, /// so this property will always give you the "real" query part of the query /// @@ -103,6 +122,6 @@ namespace Flow.Launcher.Plugin } /// - public override string ToString() => RawQuery; + public override string ToString() => TrimmedQuery; } } diff --git a/Flow.Launcher.Test/QueryBuilderTest.cs b/Flow.Launcher.Test/QueryBuilderTest.cs index c8ac17748..0ede781f8 100644 --- a/Flow.Launcher.Test/QueryBuilderTest.cs +++ b/Flow.Launcher.Test/QueryBuilderTest.cs @@ -16,9 +16,9 @@ namespace Flow.Launcher.Test {">", new PluginPair {Metadata = new PluginMetadata {ActionKeywords = new List {">"}}}} }; - Query q = QueryBuilder.Build("> ping google.com -n 20 -6", nonGlobalPlugins); + Query q = QueryBuilder.Build("> ping google.com -n 20 -6", "> ping google.com -n 20 -6", nonGlobalPlugins); - ClassicAssert.AreEqual("> ping google.com -n 20 -6", q.RawQuery); + ClassicAssert.AreEqual("> ping google.com -n 20 -6", q.TrimmedQuery); ClassicAssert.AreEqual("ping google.com -n 20 -6", q.Search, "Search should not start with the ActionKeyword."); ClassicAssert.AreEqual(">", q.ActionKeyword); @@ -39,10 +39,10 @@ namespace Flow.Launcher.Test {">", new PluginPair {Metadata = new PluginMetadata {ActionKeywords = new List {">"}, Disabled = true}}} }; - Query q = QueryBuilder.Build("> ping google.com -n 20 -6", nonGlobalPlugins); + Query q = QueryBuilder.Build("> ping google.com -n 20 -6", "> ping google.com -n 20 -6", nonGlobalPlugins); ClassicAssert.AreEqual("> ping google.com -n 20 -6", q.Search); - ClassicAssert.AreEqual(q.Search, q.RawQuery, "RawQuery should be equal to Search."); + ClassicAssert.AreEqual(q.Search, q.TrimmedQuery, "TrimmedQuery should be equal to Search."); ClassicAssert.AreEqual(6, q.SearchTerms.Length, "The length of SearchTerms should match."); ClassicAssert.AreNotEqual(">", q.ActionKeyword, "ActionKeyword should not match that of a disabled plugin."); ClassicAssert.AreEqual("ping google.com -n 20 -6", q.SecondToEndSearch, "SecondToEndSearch should be trimmed of multiple whitespace characters"); @@ -51,7 +51,7 @@ namespace Flow.Launcher.Test [Test] public void GenericPluginQueryTest() { - Query q = QueryBuilder.Build("file.txt file2 file3", new Dictionary()); + Query q = QueryBuilder.Build("file.txt file2 file3", "file.txt file2 file3", new Dictionary()); ClassicAssert.AreEqual("file.txt file2 file3", q.Search); ClassicAssert.AreEqual("", q.ActionKeyword); diff --git a/Flow.Launcher/Helper/ResultHelper.cs b/Flow.Launcher/Helper/ResultHelper.cs index 5f9a69f28..b8b7ff98e 100644 --- a/Flow.Launcher/Helper/ResultHelper.cs +++ b/Flow.Launcher/Helper/ResultHelper.cs @@ -16,11 +16,11 @@ public static class ResultHelper return await PopulateResultsAsync(item.PluginID, item.Query, item.Title, item.SubTitle, item.RecordKey); } - public static async Task PopulateResultsAsync(string pluginId, string rawQuery, string title, string subTitle, string recordKey) + public static async Task PopulateResultsAsync(string pluginId, string trimmedQuery, string title, string subTitle, string recordKey) { var plugin = PluginManager.GetPluginForId(pluginId); if (plugin == null) return null; - var query = QueryBuilder.Build(rawQuery, PluginManager.GetNonGlobalPlugins()); + var query = QueryBuilder.Build(trimmedQuery, trimmedQuery, PluginManager.GetNonGlobalPlugins()); if (query == null) return null; try { diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 2b65737da..06b2dda9e 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -477,7 +477,7 @@ namespace Flow.Launcher && QueryTextBox.CaretIndex == QueryTextBox.Text.Length) { var queryWithoutActionKeyword = - QueryBuilder.Build(QueryTextBox.Text.Trim(), PluginManager.GetNonGlobalPlugins())?.Search; + QueryBuilder.Build(QueryTextBox.Text, QueryTextBox.Text.Trim(), PluginManager.GetNonGlobalPlugins())?.Search; if (FilesFolders.IsLocationPathString(queryWithoutActionKeyword)) { diff --git a/Flow.Launcher/ResultListBox.xaml.cs b/Flow.Launcher/ResultListBox.xaml.cs index ac51b195c..fcc73e9ce 100644 --- a/Flow.Launcher/ResultListBox.xaml.cs +++ b/Flow.Launcher/ResultListBox.xaml.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Input; @@ -9,7 +10,7 @@ namespace Flow.Launcher { public partial class ResultListBox { - protected object _lock = new object(); + protected Lock _lock = new(); private Point _lastpos; private ListBoxItem curItem = null; public ResultListBox() @@ -88,12 +89,11 @@ namespace Flow.Launcher } } - - private Point start; - private string path; - private string query; + private Point _start; + private string _path; + private string _trimmedQuery; // this method is called by the UI thread, which is single threaded, so we can be sloppy with locking - private bool isDragging; + private bool _isDragging; private void ResultList_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { @@ -104,53 +104,55 @@ namespace Flow.Launcher Result: { CopyText: { } copyText, - OriginQuery.RawQuery: { } rawQuery + OriginQuery.TrimmedQuery: { } trimmedQuery } } }) return; - path = copyText; - query = rawQuery; - start = e.GetPosition(null); - isDragging = true; + _path = copyText; + _trimmedQuery = trimmedQuery; + _start = e.GetPosition(null); + _isDragging = true; } + private void ResultList_MouseMove(object sender, MouseEventArgs e) { - if (e.LeftButton != MouseButtonState.Pressed || !isDragging) + if (e.LeftButton != MouseButtonState.Pressed || !_isDragging) { - start = default; - path = string.Empty; - query = string.Empty; - isDragging = false; + _start = default; + _path = string.Empty; + _trimmedQuery = string.Empty; + _isDragging = false; return; } - if (!File.Exists(path) && !Directory.Exists(path)) + if (!File.Exists(_path) && !Directory.Exists(_path)) return; Point mousePosition = e.GetPosition(null); - Vector diff = this.start - mousePosition; + Vector diff = _start - mousePosition; if (Math.Abs(diff.X) < SystemParameters.MinimumHorizontalDragDistance || Math.Abs(diff.Y) < SystemParameters.MinimumVerticalDragDistance) return; - isDragging = false; + _isDragging = false; App.API.HideMainWindow(); var data = new DataObject(DataFormats.FileDrop, new[] { - path + _path }); // Reassigning query to a new variable because for some reason // after DragDrop.DoDragDrop call, 'query' loses its content, i.e. becomes empty string - var rawQuery = query; + var trimmedQuery = _trimmedQuery; var effect = DragDrop.DoDragDrop((DependencyObject)sender, data, DragDropEffects.Move | DragDropEffects.Copy); if (effect == DragDropEffects.Move) - App.API.ChangeQuery(rawQuery, true); + App.API.ChangeQuery(trimmedQuery, true); } + private void ResultListBox_OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) { if (Mouse.DirectlyOver is not FrameworkElement { DataContext: ResultViewModel result }) @@ -158,6 +160,7 @@ namespace Flow.Launcher RightClickResultCommand?.Execute(result.Result); } + private void ResultListBox_OnPreviewMouseUp(object sender, MouseButtonEventArgs e) { if (Mouse.DirectlyOver is not FrameworkElement { DataContext: ResultViewModel result }) diff --git a/Flow.Launcher/Storage/LastOpenedHistoryItem.cs b/Flow.Launcher/Storage/LastOpenedHistoryItem.cs index 47647066c..7f375e34d 100644 --- a/Flow.Launcher/Storage/LastOpenedHistoryItem.cs +++ b/Flow.Launcher/Storage/LastOpenedHistoryItem.cs @@ -19,13 +19,13 @@ public class LastOpenedHistoryItem return Title == r.Title && SubTitle == r.SubTitle && PluginID == r.PluginID - && Query == r.OriginQuery.RawQuery; + && Query == r.OriginQuery.TrimmedQuery; } else { return RecordKey == r.RecordKey && PluginID == r.PluginID - && Query == r.OriginQuery.RawQuery; + && Query == r.OriginQuery.TrimmedQuery; } } } diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 8284f7eea..6998a4ae3 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -35,7 +35,7 @@ namespace Flow.Launcher.Storage public void Add(Result result) { - if (string.IsNullOrEmpty(result.OriginQuery.RawQuery)) return; + if (string.IsNullOrEmpty(result.OriginQuery.TrimmedQuery)) return; if (string.IsNullOrEmpty(result.PluginID)) return; // Maintain the max history limit @@ -57,7 +57,7 @@ namespace Flow.Launcher.Storage Title = result.Title, SubTitle = result.SubTitle, PluginID = result.PluginID, - Query = result.OriginQuery.RawQuery, + Query = result.OriginQuery.TrimmedQuery, RecordKey = result.RecordKey, ExecutedDateTime = DateTime.Now }); diff --git a/Flow.Launcher/Storage/TopMostRecord.cs b/Flow.Launcher/Storage/TopMostRecord.cs index 7fc9dcaaa..9708eab97 100644 --- a/Flow.Launcher/Storage/TopMostRecord.cs +++ b/Flow.Launcher/Storage/TopMostRecord.cs @@ -113,7 +113,7 @@ namespace Flow.Launcher.Storage internal bool IsTopMost(Result result) { - if (records.IsEmpty || !records.TryGetValue(result.OriginQuery.RawQuery, out var value)) + if (records.IsEmpty || !records.TryGetValue(result.OriginQuery.TrimmedQuery, out var value)) { return false; } @@ -124,7 +124,7 @@ namespace Flow.Launcher.Storage internal void Remove(Result result) { - records.Remove(result.OriginQuery.RawQuery, out _); + records.Remove(result.OriginQuery.TrimmedQuery, out _); } internal void AddOrUpdate(Result result) @@ -136,7 +136,7 @@ namespace Flow.Launcher.Storage SubTitle = result.SubTitle, RecordKey = result.RecordKey }; - records.AddOrUpdate(result.OriginQuery.RawQuery, record, (key, oldValue) => record); + records.AddOrUpdate(result.OriginQuery.TrimmedQuery, record, (key, oldValue) => record); } } @@ -154,7 +154,7 @@ namespace Flow.Launcher.Storage // 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)) + !records.TryGetValue(result.OriginQuery.TrimmedQuery, out var value)) { return false; } @@ -168,7 +168,7 @@ namespace Flow.Launcher.Storage // 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)) + !records.TryGetValue(result.OriginQuery.TrimmedQuery, out var value)) { return -1; } @@ -194,7 +194,7 @@ namespace Flow.Launcher.Storage // 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)) + !records.TryGetValue(result.OriginQuery.TrimmedQuery, out var value)) { return; } @@ -204,12 +204,12 @@ namespace Flow.Launcher.Storage if (queue.IsEmpty) { // if the queue is empty, remove the queue from the dictionary - records.TryRemove(result.OriginQuery.RawQuery, out _); + records.TryRemove(result.OriginQuery.TrimmedQuery, out _); } else { // change the queue in the dictionary - records[result.OriginQuery.RawQuery] = queue; + records[result.OriginQuery.TrimmedQuery] = queue; } } @@ -229,19 +229,19 @@ namespace Flow.Launcher.Storage SubTitle = result.SubTitle, RecordKey = result.RecordKey }; - if (!records.TryGetValue(result.OriginQuery.RawQuery, out var value)) + if (!records.TryGetValue(result.OriginQuery.TrimmedQuery, out var value)) { // create a new queue if it does not exist value = new ConcurrentQueue(); value.Enqueue(record); - records.TryAdd(result.OriginQuery.RawQuery, value); + records.TryAdd(result.OriginQuery.TrimmedQuery, value); } else { // add or update the record in the queue var queue = new ConcurrentQueue(value.Where(r => !r.Equals(result))); // make sure we don't have duplicates queue.Enqueue(record); - records[result.OriginQuery.RawQuery] = queue; + records[result.OriginQuery.TrimmedQuery] = queue; } } } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index f0f4b257a..c35f96e62 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -35,9 +35,10 @@ namespace Flow.Launcher.ViewModel private static readonly string ClassName = nameof(MainViewModel); - private bool _isQueryRunning; private Query _lastQuery; private bool _previousIsHomeQuery; + private Query _progressQuery; // Used for QueryResultAsync + private Query _updateQuery; // Used for ResultsUpdated private string _queryTextBeforeLeaveResults; private string _ignoredQueryText; // Used to ignore query text change when switching between context menu and query results @@ -283,7 +284,7 @@ namespace Flow.Launcher.ViewModel plugin.ResultsUpdated += (s, e) => { - if (e.Query.RawQuery != QueryText || e.Token.IsCancellationRequested) + if (_updateQuery == null || e.Query.OriginalQuery != _updateQuery.OriginalQuery || e.Token.IsCancellationRequested) { return; } @@ -442,7 +443,7 @@ namespace Flow.Launcher.ViewModel [RelayCommand] private void Backspace(object index) { - var query = QueryBuilder.Build(QueryText.Trim(), PluginManager.GetNonGlobalPlugins()); + var query = QueryBuilder.Build(QueryText, QueryText.Trim(), PluginManager.GetNonGlobalPlugins()); // GetPreviousExistingDirectory does not require trailing '\', otherwise will return empty string var path = FilesFolders.GetPreviousExistingDirectory((_) => true, query.Search.TrimEnd('\\')); @@ -1327,7 +1328,7 @@ namespace Flow.Launcher.ViewModel Title = Localize.executeQuery(h.Query), SubTitle = Localize.lastExecuteTime(h.ExecutedDateTime), IcoPath = Constant.HistoryIcon, - OriginQuery = new Query { RawQuery = h.Query }, + OriginQuery = new Query { TrimmedQuery = h.Query }, Action = _ => { App.API.BackToQueryResults(); @@ -1350,7 +1351,7 @@ namespace Flow.Launcher.ViewModel h.Title, SubTitle = Localize.lastExecuteTime(h.ExecutedDateTime), IcoPath = Constant.HistoryIcon, - OriginQuery = new Query { RawQuery = h.Query }, + OriginQuery = new Query { TrimmedQuery = h.Query }, AsyncAction = async c => { var reflectResult = await ResultHelper.PopulateResultsAsync(h); @@ -1391,7 +1392,7 @@ namespace Flow.Launcher.ViewModel return; } - App.API.LogDebug(ClassName, $"Start query with ActionKeyword <{query.ActionKeyword}> and RawQuery <{query.RawQuery}>"); + App.API.LogDebug(ClassName, $"Start query with ActionKeyword <{query.ActionKeyword}> and TrimmedQuery <{query.TrimmedQuery}>"); var currentIsHomeQuery = query.IsHomeQuery; var currentIsDialogJump = _isDialogJump; @@ -1403,69 +1404,73 @@ namespace Flow.Launcher.ViewModel return; } - _updateSource?.Dispose(); - - var currentUpdateSource = new CancellationTokenSource(); - _updateSource = currentUpdateSource; - var currentCancellationToken = _updateSource.Token; - _updateToken = currentCancellationToken; - - ProgressBarVisibility = Visibility.Hidden; - _isQueryRunning = true; - - // Switch to ThreadPool thread - await TaskScheduler.Default; - - if (currentCancellationToken.IsCancellationRequested) return; - - // Update the query's IsReQuery property to true if this is a re-query - query.IsReQuery = isReQuery; - - ICollection plugins = Array.Empty(); - if (currentIsHomeQuery) + try { - if (Settings.ShowHomePage) - { - plugins = PluginManager.ValidPluginsForHomeQuery(); - } + _updateSource?.Dispose(); - PluginIconPath = null; - PluginIconSource = null; - SearchIconVisibility = Visibility.Visible; - } - else - { - plugins = PluginManager.ValidPluginsForQuery(query, currentIsDialogJump); + var currentUpdateSource = new CancellationTokenSource(); + _updateSource = currentUpdateSource; + var currentCancellationToken = _updateSource.Token; + _updateToken = currentCancellationToken; - if (plugins.Count == 1) - { - PluginIconPath = plugins.Single().Metadata.IcoPath; - PluginIconSource = await App.API.LoadImageAsync(PluginIconPath); - SearchIconVisibility = Visibility.Hidden; - } - else + ProgressBarVisibility = Visibility.Hidden; + + _progressQuery = query; + _updateQuery = query; + + // Switch to ThreadPool thread + await TaskScheduler.Default; + + if (currentCancellationToken.IsCancellationRequested) return; + + // Update the query's IsReQuery property to true if this is a re-query + query.IsReQuery = isReQuery; + + ICollection plugins = Array.Empty(); + if (currentIsHomeQuery) { + if (Settings.ShowHomePage) + { + plugins = PluginManager.ValidPluginsForHomeQuery(); + } + PluginIconPath = null; PluginIconSource = null; SearchIconVisibility = Visibility.Visible; } - } + else + { + plugins = PluginManager.ValidPluginsForQuery(query, currentIsDialogJump); - App.API.LogDebug(ClassName, $"Valid <{plugins.Count}> plugins: {string.Join(" ", plugins.Select(x => $"<{x.Metadata.Name}>"))}"); + if (plugins.Count == 1) + { + PluginIconPath = plugins.Single().Metadata.IcoPath; + PluginIconSource = await App.API.LoadImageAsync(PluginIconPath); + SearchIconVisibility = Visibility.Hidden; + } + else + { + PluginIconPath = null; + PluginIconSource = null; + SearchIconVisibility = Visibility.Visible; + } + } - // Do not wait for performance improvement - /*if (string.IsNullOrEmpty(query.ActionKeyword)) - { - // Wait 15 millisecond for query change in global query - // if query changes, return so that it won't be calculated - await Task.Delay(15, currentCancellationToken); - if (currentCancellationToken.IsCancellationRequested) return; - }*/ + App.API.LogDebug(ClassName, $"Valid <{plugins.Count}> plugins: {string.Join(" ", plugins.Select(x => $"<{x.Metadata.Name}>"))}"); - _ = Task.Delay(200, currentCancellationToken).ContinueWith(_ => + // Do not wait for performance improvement + /*if (string.IsNullOrEmpty(query.ActionKeyword)) + { + // Wait 15 millisecond for query change in global query + // if query changes, return so that it won't be calculated + await Task.Delay(15, currentCancellationToken); + if (currentCancellationToken.IsCancellationRequested) return; + }*/ + + _ = Task.Delay(200, currentCancellationToken).ContinueWith(_ => { // start the progress bar if query takes more than 200 ms and this is the current running query and it didn't finish yet - if (_isQueryRunning) + if (_progressQuery != null && _progressQuery.OriginalQuery == query.OriginalQuery) { ProgressBarVisibility = Visibility.Visible; } @@ -1474,58 +1479,65 @@ namespace Flow.Launcher.ViewModel TaskContinuationOptions.NotOnCanceled, TaskScheduler.Default); - // plugins are ICollection, meaning LINQ will get the Count and preallocate Array + // plugins are ICollection, meaning LINQ will get the Count and preallocate Array - Task[] tasks; - if (currentIsHomeQuery) - { - if (ShouldClearExistingResultsForNonQuery(plugins)) + Task[] tasks; + if (currentIsHomeQuery) { - Results.Clear(); - App.API.LogDebug(ClassName, $"Existing results are cleared for non-query"); + if (ShouldClearExistingResultsForNonQuery(plugins)) + { + // there are no update tasks and so we can directly return + ClearResults(); + return; + } + + tasks = plugins.Select(plugin => plugin.Metadata.HomeDisabled switch + { + false => QueryTaskAsync(plugin, currentCancellationToken), + true => Task.CompletedTask + }).ToArray(); + + // Query history results for home page firstly so it will be put on top of the results + if (Settings.ShowHistoryResultsForHomePage) + { + QueryHistoryTask(currentCancellationToken); + } + } + else + { + tasks = plugins.Select(plugin => plugin.Metadata.Disabled switch + { + false => QueryTaskAsync(plugin, currentCancellationToken), + true => Task.CompletedTask + }).ToArray(); } - tasks = plugins.Select(plugin => plugin.Metadata.HomeDisabled switch + try { - false => QueryTaskAsync(plugin, currentCancellationToken), - true => Task.CompletedTask - }).ToArray(); + // Check the code, WhenAll will translate all type of IEnumerable or Collection to Array, so make an array at first + await Task.WhenAll(tasks); + } + catch (OperationCanceledException) + { + // nothing to do here + } - // Query history results for home page firstly so it will be put on top of the results - if (Settings.ShowHistoryResultsForHomePage) + if (currentCancellationToken.IsCancellationRequested) return; + + // this should happen once after all queries are done so progress bar should continue + // until the end of all querying + _progressQuery = null; + + if (!currentCancellationToken.IsCancellationRequested) { - QueryHistoryTask(currentCancellationToken); + // update to hidden if this is still the current query + ProgressBarVisibility = Visibility.Hidden; } } - else + finally { - tasks = plugins.Select(plugin => plugin.Metadata.Disabled switch - { - false => QueryTaskAsync(plugin, currentCancellationToken), - true => Task.CompletedTask - }).ToArray(); - } - - try - { - // Check the code, WhenAll will translate all type of IEnumerable or Collection to Array, so make an array at first - await Task.WhenAll(tasks); - } - catch (OperationCanceledException) - { - // nothing to do here - } - - if (currentCancellationToken.IsCancellationRequested) return; - - // this should happen once after all queries are done so progress bar should continue - // until the end of all querying - _isQueryRunning = false; - - if (!currentCancellationToken.IsCancellationRequested) - { - // update to hidden if this is still the current query - ProgressBarVisibility = Visibility.Hidden; + // this make sures progress query is null when this query is canceled + _progressQuery = null; } // Local function @@ -1625,7 +1637,7 @@ namespace Flow.Launcher.ViewModel { if (string.IsNullOrWhiteSpace(queryText)) { - return QueryBuilder.Build(string.Empty, PluginManager.GetNonGlobalPlugins()); + return QueryBuilder.Build(string.Empty, string.Empty, PluginManager.GetNonGlobalPlugins()); } var queryBuilder = new StringBuilder(queryText); @@ -1645,7 +1657,7 @@ namespace Flow.Launcher.ViewModel // Applying builtin shortcuts await BuildQueryAsync(builtInShortcuts, queryBuilder, queryBuilderTmp); - return QueryBuilder.Build(queryBuilder.ToString().Trim(), PluginManager.GetNonGlobalPlugins()); + return QueryBuilder.Build(queryText, queryBuilder.ToString().Trim(), PluginManager.GetNonGlobalPlugins()); } private async Task BuildQueryAsync(IEnumerable builtInShortcuts, diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index d7b069082..21a6945a8 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -172,7 +172,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search Action = c => { Settings.EnableEverythingContentSearch = true; - Context.API.ChangeQuery(query.RawQuery, true); + Context.API.ChangeQuery(query.TrimmedQuery, true); return false; } } From 7d9de4b0d2b5fbaecc5f21004e989c6c53035a89 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 7 Dec 2025 18:16:09 +0800 Subject: [PATCH 035/124] Fix index lookup for boundary --- Flow.Launcher.Infrastructure/TranslationMapping.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/TranslationMapping.cs b/Flow.Launcher.Infrastructure/TranslationMapping.cs index b4c6764df..e70443077 100644 --- a/Flow.Launcher.Infrastructure/TranslationMapping.cs +++ b/Flow.Launcher.Infrastructure/TranslationMapping.cs @@ -21,7 +21,7 @@ namespace Flow.Launcher.Infrastructure public int MapToOriginalIndex(int translatedIndex) { var searchResult = _originalToTranslated.BinarySearch(translatedIndex); - return searchResult >= 0 ? searchResult : ~searchResult; + return searchResult >= 0 ? searchResult + 1 : ~searchResult; } public void EndConstruct() From b869eb8d1d2a6e0c342379fae579aa1747754cc4 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 7 Dec 2025 18:50:54 +0800 Subject: [PATCH 036/124] Avoid adding unnecessary space and improve unit test --- .../PinyinAlphabet.cs | 27 ++++++++------- Flow.Launcher.Test/TranslationMappingTest.cs | 33 +++++++++++++------ 2 files changed, 38 insertions(+), 22 deletions(-) diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index 1c0cc6872..7f55d8909 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -27,7 +27,7 @@ namespace Flow.Launcher.Infrastructure { switch (e.PropertyName) { - case nameof (Settings.ShouldUsePinyin): + case nameof(Settings.ShouldUsePinyin): if (_settings.ShouldUsePinyin) { Reload(); @@ -52,7 +52,7 @@ namespace Flow.Launcher.Infrastructure private void CreateDoublePinyinTableFromStream(Stream jsonStream) { - var table = JsonSerializer.Deserialize>>(jsonStream) ?? + var table = JsonSerializer.Deserialize>>(jsonStream) ?? throw new InvalidOperationException("Failed to deserialize double pinyin table: result is null"); var schemaKey = _settings.DoublePinyinSchema.ToString(); @@ -128,12 +128,12 @@ namespace Flow.Launcher.Infrastructure if (IsChineseCharacter(content[i])) { var translated = _settings.UseDoublePinyin ? ToDoublePinyin(resultList[i]) : resultList[i]; - - if (i > 0) + + if (i > 0 && content[i - 1] != ' ') { resultBuilder.Append(' '); } - + map.AddNewIndex(resultBuilder.Length, translated.Length); resultBuilder.Append(translated); previousIsChinese = true; @@ -144,11 +144,14 @@ namespace Flow.Launcher.Infrastructure if (previousIsChinese) { previousIsChinese = false; - resultBuilder.Append(' '); + if (content[i] != ' ') + { + resultBuilder.Append(' '); + } } - - map.AddNewIndex(resultBuilder.Length, resultList[i].Length); - resultBuilder.Append(resultList[i]); + + map.AddNewIndex(resultBuilder.Length, 1); + resultBuilder.Append(content[i]); } } @@ -156,7 +159,7 @@ namespace Flow.Launcher.Infrastructure var translation = resultBuilder.ToString(); var result = (translation, map); - + return _pinyinCache[content] = result; } @@ -185,8 +188,8 @@ namespace Flow.Launcher.Infrastructure private string ToDoublePinyin(string fullPinyin) { - return currentDoublePinyinTable.TryGetValue(fullPinyin, out var doublePinyinValue) - ? doublePinyinValue + return currentDoublePinyinTable.TryGetValue(fullPinyin, out var doublePinyinValue) + ? doublePinyinValue : fullPinyin; } } diff --git a/Flow.Launcher.Test/TranslationMappingTest.cs b/Flow.Launcher.Test/TranslationMappingTest.cs index bd3636f0a..ab02b23b2 100644 --- a/Flow.Launcher.Test/TranslationMappingTest.cs +++ b/Flow.Launcher.Test/TranslationMappingTest.cs @@ -22,19 +22,32 @@ namespace Flow.Launcher.Test ClassicAssert.AreEqual(10, GetOriginalToTranslatedAt(mapping, 1)); } - [TestCase(0, 0)] - [TestCase(2, 1)] - [TestCase(3, 1)] - [TestCase(5, 2)] - [TestCase(6, 2)] + + [TestCase(0, 0)] // "F" -> "F" + [TestCase(1, 1)] // "l" -> "l" + [TestCase(2, 2)] // "o" -> "o" + [TestCase(3, 3)] // "w" -> "w" + [TestCase(4, 4)] // " " -> " " + [TestCase(5, 5)] // "Y" (translated from "用") -> original index 5 + [TestCase(6, 5)] // "o" (translated from "用") -> original index 5 + [TestCase(7, 5)] // "n" (translated from "用") -> original index 5 + [TestCase(8, 5)] // "g" (translated from "用") -> original index 5 + [TestCase(10, 6)] // "H" (translated from "户") -> original index 6 public void MapToOriginalIndex_ShouldReturnExpectedIndex(int translatedIndex, int expectedOriginalIndex) { var mapping = new TranslationMapping(); - // a测试 - // a Ce Shi - mapping.AddNewIndex(0, 1); - mapping.AddNewIndex(2, 2); - mapping.AddNewIndex(5, 3); + // Test case : + // 0123456 + // Flow 用户 + // 0123456789012 + // Flow Yong Hu" + mapping.AddNewIndex(0, 1); // F + mapping.AddNewIndex(1, 1); // l + mapping.AddNewIndex(2, 1); // o + mapping.AddNewIndex(3, 1); // w + mapping.AddNewIndex(4, 1); // ' ' + mapping.AddNewIndex(5, 4); // 用 -> Yong + mapping.AddNewIndex(11, 2); // 户 -> Hu var result = mapping.MapToOriginalIndex(translatedIndex); ClassicAssert.AreEqual(expectedOriginalIndex, result); From a7c67bbb35b2ab49778b534867c196d46661fe09 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 7 Dec 2025 19:18:49 +0800 Subject: [PATCH 037/124] Fix incorrect index marker Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Test/TranslationMappingTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Test/TranslationMappingTest.cs b/Flow.Launcher.Test/TranslationMappingTest.cs index ab02b23b2..be208d599 100644 --- a/Flow.Launcher.Test/TranslationMappingTest.cs +++ b/Flow.Launcher.Test/TranslationMappingTest.cs @@ -39,8 +39,8 @@ namespace Flow.Launcher.Test // Test case : // 0123456 // Flow 用户 - // 0123456789012 - // Flow Yong Hu" + // 012345678901 + // Flow Yong Hu mapping.AddNewIndex(0, 1); // F mapping.AddNewIndex(1, 1); // l mapping.AddNewIndex(2, 1); // o From 769179d04b48f06c3998942c83020a56fd5be6aa Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 7 Dec 2025 19:28:17 +0800 Subject: [PATCH 038/124] Fix test case Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Test/TranslationMappingTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Test/TranslationMappingTest.cs b/Flow.Launcher.Test/TranslationMappingTest.cs index be208d599..bcbbf8bf8 100644 --- a/Flow.Launcher.Test/TranslationMappingTest.cs +++ b/Flow.Launcher.Test/TranslationMappingTest.cs @@ -47,7 +47,7 @@ namespace Flow.Launcher.Test mapping.AddNewIndex(3, 1); // w mapping.AddNewIndex(4, 1); // ' ' mapping.AddNewIndex(5, 4); // 用 -> Yong - mapping.AddNewIndex(11, 2); // 户 -> Hu + mapping.AddNewIndex(10, 2); // 户 -> Hu var result = mapping.MapToOriginalIndex(translatedIndex); ClassicAssert.AreEqual(expectedOriginalIndex, result); From 42e04d459b19d61f37d52831d0b7e9ead9b70289 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Mon, 8 Dec 2025 00:41:08 +0800 Subject: [PATCH 039/124] Cover all positions in unit test Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Flow.Launcher.Test/TranslationMappingTest.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Flow.Launcher.Test/TranslationMappingTest.cs b/Flow.Launcher.Test/TranslationMappingTest.cs index bcbbf8bf8..53a394405 100644 --- a/Flow.Launcher.Test/TranslationMappingTest.cs +++ b/Flow.Launcher.Test/TranslationMappingTest.cs @@ -32,7 +32,10 @@ namespace Flow.Launcher.Test [TestCase(6, 5)] // "o" (translated from "用") -> original index 5 [TestCase(7, 5)] // "n" (translated from "用") -> original index 5 [TestCase(8, 5)] // "g" (translated from "用") -> original index 5 + [TestCase(9, 6)] // " " (space between "Yong" and "Hu") -> original index 6 [TestCase(10, 6)] // "H" (translated from "户") -> original index 6 + [TestCase(11, 6)] // "u" (translated from "户") -> original index 6 + public void MapToOriginalIndex_ShouldReturnExpectedIndex(int translatedIndex, int expectedOriginalIndex) public void MapToOriginalIndex_ShouldReturnExpectedIndex(int translatedIndex, int expectedOriginalIndex) { var mapping = new TranslationMapping(); From b6339d38fa48955984b6ba6884fabb6a1fd88657 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Mon, 8 Dec 2025 13:06:14 +0800 Subject: [PATCH 040/124] Fix compile error introduced by coderabbit --- Flow.Launcher.Test/TranslationMappingTest.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Flow.Launcher.Test/TranslationMappingTest.cs b/Flow.Launcher.Test/TranslationMappingTest.cs index 53a394405..a3c0026c0 100644 --- a/Flow.Launcher.Test/TranslationMappingTest.cs +++ b/Flow.Launcher.Test/TranslationMappingTest.cs @@ -32,11 +32,9 @@ namespace Flow.Launcher.Test [TestCase(6, 5)] // "o" (translated from "用") -> original index 5 [TestCase(7, 5)] // "n" (translated from "用") -> original index 5 [TestCase(8, 5)] // "g" (translated from "用") -> original index 5 - [TestCase(9, 6)] // " " (space between "Yong" and "Hu") -> original index 6 [TestCase(10, 6)] // "H" (translated from "户") -> original index 6 [TestCase(11, 6)] // "u" (translated from "户") -> original index 6 public void MapToOriginalIndex_ShouldReturnExpectedIndex(int translatedIndex, int expectedOriginalIndex) - public void MapToOriginalIndex_ShouldReturnExpectedIndex(int translatedIndex, int expectedOriginalIndex) { var mapping = new TranslationMapping(); // Test case : From 4c44877af454836a119d756e8b3cf634e793ffbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 22:04:55 +0000 Subject: [PATCH 041/124] Bump actions/upload-artifact from 5 to 6 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dotnet.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index f3c76027a..0659ae645 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -54,28 +54,28 @@ jobs: shell: powershell run: .\Scripts\post_build.ps1 - name: Upload Plugin Nupkg - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: Plugin nupkg path: | Output\Release\Flow.Launcher.Plugin.*.nupkg compression-level: 0 - name: Upload Setup - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: Flow Installer path: | Output\Packages\Flow-Launcher-*.exe compression-level: 0 - name: Upload Portable Version - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: Portable Version path: | Output\Packages\Flow-Launcher-Portable.zip compression-level: 0 - name: Upload Full Nupkg - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: Full nupkg path: | @@ -83,7 +83,7 @@ jobs: compression-level: 0 - name: Upload Release Information - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: RELEASES path: | From 90669137106d5cad25341bca1d3fad566f8b1ac3 Mon Sep 17 00:00:00 2001 From: Diego Henrique <124473653+01Dri@users.noreply.github.com> Date: Sun, 14 Dec 2025 07:18:21 -0300 Subject: [PATCH 042/124] [FEATURE] Folder and File Action Keywords (#4093) --- .../Languages/en.xaml | 2 + .../Search/SearchManager.cs | 219 ++++++++++++------ .../Flow.Launcher.Plugin.Explorer/Settings.cs | 50 +++- .../ViewModels/SettingsViewModel.cs | 6 +- 4 files changed, 197 insertions(+), 80 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index c40040df5..45c0d72ac 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -58,6 +58,8 @@ File Content Search: Index Search: Quick Access: + Folder Search: + File Search: Current Action Keyword Done Enabled diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 21a6945a8..9420e3d3a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -1,13 +1,14 @@ -using Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo; -using Flow.Launcher.Plugin.Explorer.Search.Everything; -using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; -using Flow.Launcher.Plugin.SharedCommands; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Flow.Launcher.Plugin.Explorer.Exceptions; +using Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo; +using Flow.Launcher.Plugin.Explorer.Search.Everything; +using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; +using Flow.Launcher.Plugin.SharedCommands; +using static Flow.Launcher.Plugin.Explorer.Settings; using Path = System.IO.Path; namespace Flow.Launcher.Plugin.Explorer.Search @@ -18,6 +19,14 @@ namespace Flow.Launcher.Plugin.Explorer.Search internal Settings Settings; + private readonly Dictionary _allowedTypesByActionKeyword = new() + { + { ActionKeyword.FileSearchActionKeyword, [ResultType.File] }, + { ActionKeyword.FolderSearchActionKeyword, [ResultType.Folder, ResultType.Volume] }, + { ActionKeyword.SearchActionKeyword, [ResultType.File, ResultType.Folder, ResultType.Volume] }, + }; + + public SearchManager(Settings settings, PluginInitContext context) { Context = context; @@ -44,48 +53,71 @@ namespace Flow.Launcher.Plugin.Explorer.Search } } + /// + /// Results for the different types of searches as follows: + /// 1. Search, only include results from: + /// - Files + /// - Folders + /// - Quick Access Links + /// - Path navigation + /// 2. File Content Search, only include results from: + /// - File contents from index search engines i.e. Windows Index, Everything (may not be available due its beta version) + /// 3. Path Search, only include results from: + /// - Path navigation + /// 4. Quick Access Links, only include results from: + /// - Full list of Quick Access Links if query is empty + /// - Matched Quick Access Links if query is not empty + /// - Quick Access Links that are matched on path, e.g. query "window" for results that contain 'window' in the path (even if not in the title), + /// i.e. result with path c:\windows\system32 + /// 5. Folder Search, only include results from: + /// - Folders + /// - Quick Access Links + /// 6. File Search, only include results from: + /// - Files + /// - Quick Access Links + /// internal async Task> SearchAsync(Query query, CancellationToken token) { var results = new HashSet(PathEqualityComparator.Instance); - // This allows the user to type the below action keywords and see/search the list of quick folder links - if (ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.QuickAccessActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.PathSearchActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.IndexSearchActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.FileContentSearchActionKeyword)) + var keyword = query.ActionKeyword.Length == 0 ? Query.GlobalPluginWildcardSign : query.ActionKeyword; + + // No action keyword matched - plugin should not handle this query, return empty results. + var activeActionKeywords = Settings.GetActiveActionKeywords(keyword); + if (activeActionKeywords.Count == 0) { - if (string.IsNullOrEmpty(query.Search) && ActionKeywordMatch(query, Settings.ActionKeyword.QuickAccessActionKeyword)) - return QuickAccess.AccessLinkListAll(query, Settings.QuickAccessLinks); - } - else - { - // No action keyword matched- plugin should not handle this query, return empty results. - return new List(); + return [.. results]; } - IAsyncEnumerable searchResults; + var queryIsEmpty = string.IsNullOrEmpty(query.Search); + if (queryIsEmpty && activeActionKeywords.ContainsKey(ActionKeyword.QuickAccessActionKeyword)) + { + return QuickAccess.AccessLinkListAll(query, Settings.QuickAccessLinks); + } - bool isPathSearch = query.Search.IsLocationPathString() + if (queryIsEmpty) + { + return [.. results]; + } + + var isPathSearch = query.Search.IsLocationPathString() || EnvironmentVariables.IsEnvironmentVariableSearch(query.Search) || EnvironmentVariables.HasEnvironmentVar(query.Search); + IAsyncEnumerable searchResults; + string engineName; switch (isPathSearch) { case true - when ActionKeywordMatch(query, Settings.ActionKeyword.PathSearchActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword): - + when CanUsePathSearchByActionKeywords(activeActionKeywords): results.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false)); - - return results.ToList(); + return [.. results]; case false - when ActionKeywordMatch(query, Settings.ActionKeyword.FileContentSearchActionKeyword): - // Intentionally require enabling of Everything's content search due to its slowness + when activeActionKeywords.ContainsKey(ActionKeyword.FileContentSearchActionKeyword): if (Settings.ContentIndexProvider is EverythingSearchManager && !Settings.EnableEverythingContentSearch) return EverythingContentSearchResult(query); @@ -93,37 +125,41 @@ namespace Flow.Launcher.Plugin.Explorer.Search engineName = Enum.GetName(Settings.ContentSearchEngine); break; - case false - when ActionKeywordMatch(query, Settings.ActionKeyword.IndexSearchActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword): + case true or false + when activeActionKeywords.ContainsKey(ActionKeyword.QuickAccessActionKeyword): + return QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); + + case false + when CanUseIndexSearchByActionKeywords(activeActionKeywords): searchResults = Settings.IndexProvider.SearchAsync(query.Search, token); engineName = Enum.GetName(Settings.IndexSearchEngine); break; - - case true or false - when ActionKeywordMatch(query, Settings.ActionKeyword.QuickAccessActionKeyword): - return QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); - default: - return results.ToList(); + return [.. results]; + } - // Merge Quick Access Link results for non-path searches. - results.UnionWith(QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks)); + var actions = activeActionKeywords.Keys.ToList(); + //Merge Quick Access Link results for non-path searches. + results.UnionWith(GetQuickAccessResultsFilteredByActionKeyword(query, actions)); try { await foreach (var search in searchResults.WithCancellation(token).ConfigureAwait(false)) - if (search.Type == ResultType.File && IsExcludedFile(search)) { + { + if (search.Type == ResultType.File && IsExcludedFile(search)) continue; - } else { - results.Add(ResultManager.CreateResult(query, search)); - } + + if (IsResultTypeFilteredByActionKeyword(search.Type, actions)) + continue; + + results.Add(ResultManager.CreateResult(query, search)); + } } catch (OperationCanceledException) { - return new List(); + return [.. results]; } catch (EngineNotAvailableException) { @@ -137,33 +173,13 @@ namespace Flow.Launcher.Plugin.Explorer.Search results.RemoveWhere(r => Settings.IndexSearchExcludedSubdirectoryPaths.Any( excludedPath => FilesFolders.PathContains(excludedPath.Path, r.SubTitle, allowEqual: true))); - return results.ToList(); - } - - private bool ActionKeywordMatch(Query query, Settings.ActionKeyword allowedActionKeyword) - { - var keyword = query.ActionKeyword.Length == 0 ? Query.GlobalPluginWildcardSign : query.ActionKeyword; - - return allowedActionKeyword switch - { - Settings.ActionKeyword.SearchActionKeyword => Settings.SearchActionKeywordEnabled && - keyword == Settings.SearchActionKeyword, - Settings.ActionKeyword.PathSearchActionKeyword => Settings.PathSearchKeywordEnabled && - keyword == Settings.PathSearchActionKeyword, - Settings.ActionKeyword.FileContentSearchActionKeyword => Settings.FileContentSearchKeywordEnabled && - keyword == Settings.FileContentSearchActionKeyword, - Settings.ActionKeyword.IndexSearchActionKeyword => Settings.IndexSearchKeywordEnabled && - keyword == Settings.IndexSearchActionKeyword, - Settings.ActionKeyword.QuickAccessActionKeyword => Settings.QuickAccessKeywordEnabled && - keyword == Settings.QuickAccessActionKeyword, - _ => throw new ArgumentOutOfRangeException(nameof(allowedActionKeyword), allowedActionKeyword, "actionKeyword out of range") - }; + return [.. results]; } private List EverythingContentSearchResult(Query query) { - return new List() - { + return + [ new() { Title = Localize.flowlauncher_plugin_everything_enable_content_search(), @@ -176,7 +192,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search return false; } } - }; + ]; } private async Task> PathSearchAsync(Query query, CancellationToken token = default) @@ -197,7 +213,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search // Check that actual location exists, otherwise directory search will throw directory not found exception if (!FilesFolders.ReturnPreviousDirectoryIfIncompleteString(path).LocationExists()) - return results.ToList(); + return [.. results]; var useIndexSearch = Settings.IndexSearchEngine is Settings.IndexSearchEngineOption.WindowsIndex && UseWindowsIndexForDirectorySearch(path); @@ -209,7 +225,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search : ResultManager.CreateOpenCurrentFolderResult(retrievedDirectoryPath, query.ActionKeyword, useIndexSearch)); if (token.IsCancellationRequested) - return new List(); + return [.. results]; IAsyncEnumerable directoryResult; @@ -231,7 +247,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search } if (token.IsCancellationRequested) - return new List(); + return [.. results]; try { @@ -246,14 +262,14 @@ namespace Flow.Launcher.Plugin.Explorer.Search } - return results.ToList(); + return [.. results]; } public bool IsFileContentSearch(string actionKeyword) => actionKeyword == Settings.FileContentSearchActionKeyword; public static bool UseIndexSearch(string path) { - if (Main.Settings.IndexSearchEngine is not Settings.IndexSearchEngineOption.WindowsIndex) + if (Main.Settings.IndexSearchEngine is not IndexSearchEngineOption.WindowsIndex) return false; // Check if the path is using windows index search @@ -275,10 +291,67 @@ namespace Flow.Launcher.Plugin.Explorer.Search private bool IsExcludedFile(SearchResult result) { - string[] excludedFileTypes = Settings.ExcludedFileTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + string[] excludedFileTypes = Settings.ExcludedFileTypes.Split([','], StringSplitOptions.RemoveEmptyEntries); string fileExtension = Path.GetExtension(result.FullPath).TrimStart('.'); return excludedFileTypes.Contains(fileExtension, StringComparer.OrdinalIgnoreCase); } + + private List GetQuickAccessResultsFilteredByActionKeyword(Query query, List actions) + { + if (!Settings.QuickAccessKeywordEnabled) + return []; + + var results = QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); + if (results.Count == 0) + return []; + + return results + .Where(r => r.ContextData is SearchResult result + && !IsResultTypeFilteredByActionKeyword(result.Type, actions)) + .ToList(); + } + private bool IsResultTypeFilteredByActionKeyword(ResultType type, List actions) + { + var actionsWithWhitelist = actions.Intersect(_allowedTypesByActionKeyword.Keys).ToList(); + if (actionsWithWhitelist.Count == 0) return false; + + // Check if ANY active keyword allows this type (union behavior) + foreach (var action in actionsWithWhitelist) + { + if (_allowedTypesByActionKeyword.TryGetValue(action, out var allowedTypes)) + { + if (allowedTypes.Contains(type)) + return false; + } + } + + return true; + } + + private bool CanUseIndexSearchByActionKeywords(Dictionary actions) + { + var keysToUseIndexSearch = new[] + { + ActionKeyword.FileSearchActionKeyword, ActionKeyword.FolderSearchActionKeyword, + ActionKeyword.IndexSearchActionKeyword, ActionKeyword.SearchActionKeyword + }; + + return keysToUseIndexSearch.Any(actions.ContainsKey); + } + + // Action keywords that supports patch search in results. + private bool CanUsePathSearchByActionKeywords(Dictionary actions) + { + var keysThatSupportPathSearch = new[] + { + ActionKeyword.PathSearchActionKeyword, + ActionKeyword.SearchActionKeyword, + }; + + return keysThatSupportPathSearch.Any(actions.ContainsKey); + + } + } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 8d62531cd..e65c03e9b 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -1,12 +1,13 @@ -using Flow.Launcher.Plugin.Explorer.Search; -using Flow.Launcher.Plugin.Explorer.Search.Everything; -using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; -using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex; -using System; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Text.Json.Serialization; +using Flow.Launcher.Plugin.Explorer.Search; +using Flow.Launcher.Plugin.Explorer.Search.Everything; using Flow.Launcher.Plugin.Explorer.Search.IProvider; +using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; +using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex; namespace Flow.Launcher.Plugin.Explorer { @@ -58,6 +59,15 @@ namespace Flow.Launcher.Plugin.Explorer public bool QuickAccessKeywordEnabled { get; set; } + + public string FolderSearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign; + + public bool FolderSearchKeywordEnabled { get; set; } + + public string FileSearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign; + + public bool FileSearchKeywordEnabled { get; set; } + public bool WarnWindowsSearchServiceOff { get; set; } = true; public bool ShowFileSizeInPreviewPanel { get; set; } = true; @@ -160,7 +170,9 @@ namespace Flow.Launcher.Plugin.Explorer PathSearchActionKeyword, FileContentSearchActionKeyword, IndexSearchActionKeyword, - QuickAccessActionKeyword + QuickAccessActionKeyword, + FolderSearchActionKeyword, + FileSearchActionKeyword, } internal string GetActionKeyword(ActionKeyword actionKeyword) => actionKeyword switch @@ -170,6 +182,8 @@ namespace Flow.Launcher.Plugin.Explorer ActionKeyword.FileContentSearchActionKeyword => FileContentSearchActionKeyword, ActionKeyword.IndexSearchActionKeyword => IndexSearchActionKeyword, ActionKeyword.QuickAccessActionKeyword => QuickAccessActionKeyword, + ActionKeyword.FolderSearchActionKeyword => FolderSearchActionKeyword, + ActionKeyword.FileSearchActionKeyword => FileSearchActionKeyword, _ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyWord property not found") }; @@ -180,6 +194,8 @@ namespace Flow.Launcher.Plugin.Explorer ActionKeyword.FileContentSearchActionKeyword => FileContentSearchActionKeyword = keyword, ActionKeyword.IndexSearchActionKeyword => IndexSearchActionKeyword = keyword, ActionKeyword.QuickAccessActionKeyword => QuickAccessActionKeyword = keyword, + ActionKeyword.FolderSearchActionKeyword => FolderSearchActionKeyword = keyword, + ActionKeyword.FileSearchActionKeyword => FileSearchActionKeyword = keyword, _ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyWord property not found") }; @@ -190,6 +206,8 @@ namespace Flow.Launcher.Plugin.Explorer ActionKeyword.IndexSearchActionKeyword => IndexSearchKeywordEnabled, ActionKeyword.FileContentSearchActionKeyword => FileContentSearchKeywordEnabled, ActionKeyword.QuickAccessActionKeyword => QuickAccessKeywordEnabled, + ActionKeyword.FolderSearchActionKeyword => FolderSearchKeywordEnabled, + ActionKeyword.FileSearchActionKeyword => FileSearchKeywordEnabled, _ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyword enabled status not defined") }; @@ -200,7 +218,27 @@ namespace Flow.Launcher.Plugin.Explorer ActionKeyword.IndexSearchActionKeyword => IndexSearchKeywordEnabled = enable, ActionKeyword.FileContentSearchActionKeyword => FileContentSearchKeywordEnabled = enable, ActionKeyword.QuickAccessActionKeyword => QuickAccessKeywordEnabled = enable, + ActionKeyword.FolderSearchActionKeyword => FolderSearchKeywordEnabled = enable, + ActionKeyword.FileSearchActionKeyword => FileSearchKeywordEnabled = enable, _ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyword enabled status not defined") }; + + // Returns a dictionary because some ActionKeywords may use wildcards (*), + // which means multiple ActionKeywords can be considered active at the same time. + // Using a dictionary ensures O(1) lookup time when checking which actions + // are enabled. + internal Dictionary GetActiveActionKeywords(string actionKeywordStr) + { + var result = new Dictionary(); + if (string.IsNullOrEmpty(actionKeywordStr)) return null; + foreach (var action in Enum.GetValues()) + { + var keywordStr = GetActionKeyword(action); + if (string.IsNullOrEmpty(keywordStr)) continue; + var isEnabled = GetActionKeywordEnabled(action); + if (keywordStr == actionKeywordStr && isEnabled) result.Add(action, keywordStr); + } + return result; + } } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 2d46c6307..956c84db2 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -279,7 +279,11 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels new(Settings.ActionKeyword.IndexSearchActionKeyword, "plugin_explorer_actionkeywordview_indexsearch"), new(Settings.ActionKeyword.QuickAccessActionKeyword, - "plugin_explorer_actionkeywordview_quickaccess") + "plugin_explorer_actionkeywordview_quickaccess"), + new(Settings.ActionKeyword.FolderSearchActionKeyword, + "plugin_explorer_actionkeywordview_foldersearch"), + new(Settings.ActionKeyword.FileSearchActionKeyword, + "plugin_explorer_actionkeywordview_filesearch") }; } From 666d525243a017f5e1ffcb74dadd1a8a336796b7 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Mon, 15 Dec 2025 20:59:18 +1100 Subject: [PATCH 043/124] Add sponsor to README Added sponsor to the README. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index f2f7a495d..9bd99d7ad 100644 --- a/README.md +++ b/README.md @@ -351,6 +351,9 @@ Or download the [early access version](https://github.com/Flow-Launcher/Prerelea + + +

From 31f569843794081b2111a98f4c1256fbe3edd462 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Mon, 15 Dec 2025 21:20:35 +1100 Subject: [PATCH 044/124] update readme --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 9bd99d7ad..bd07a9a53 100644 --- a/README.md +++ b/README.md @@ -348,9 +348,6 @@ Or download the [early access version](https://github.com/Flow-Launcher/Prerelea - - - From 437b7da0f779505508bfc0da7628a3464351b485 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Mon, 15 Dec 2025 21:24:14 +1100 Subject: [PATCH 045/124] formatting --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bd07a9a53..d36a752fc 100644 --- a/README.md +++ b/README.md @@ -350,7 +350,7 @@ Or download the [early access version](https://github.com/Flow-Launcher/Prerelea - +

From bb3c8fbe0cce42061f216284577a8fedeb3825b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 22:04:28 +0000 Subject: [PATCH 046/124] Bump toshimaru/auto-author-assign from 2.1.1 to 2.1.2 Bumps [toshimaru/auto-author-assign](https://github.com/toshimaru/auto-author-assign) from 2.1.1 to 2.1.2. - [Release notes](https://github.com/toshimaru/auto-author-assign/releases) - [Changelog](https://github.com/toshimaru/auto-author-assign/blob/main/CHANGELOG.md) - [Commits](https://github.com/toshimaru/auto-author-assign/compare/v2.1.1...v2.1.2) --- updated-dependencies: - dependency-name: toshimaru/auto-author-assign dependency-version: 2.1.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/pr_assignee.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_assignee.yml b/.github/workflows/pr_assignee.yml index 5be603df6..76a0cd407 100644 --- a/.github/workflows/pr_assignee.yml +++ b/.github/workflows/pr_assignee.yml @@ -14,4 +14,4 @@ jobs: runs-on: ubuntu-latest steps: - name: Assign PR to creator - uses: toshimaru/auto-author-assign@v2.1.1 + uses: toshimaru/auto-author-assign@v2.1.2 From b4ec4804054a9928e47f2a564b4f1f160812661e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Dec 2025 22:07:00 +0000 Subject: [PATCH 047/124] Bump Microsoft.Data.Sqlite from 10.0.0 to 10.0.1 --- updated-dependencies: - dependency-name: Microsoft.Data.Sqlite dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../Flow.Launcher.Plugin.BrowserBookmark.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index ba547c86a..ed121375b 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -105,7 +105,7 @@ - + From e01869afda569281c58e6d365ded5f4ba2e0465a Mon Sep 17 00:00:00 2001 From: Heck-R Date: Wed, 17 Dec 2025 23:37:43 +0100 Subject: [PATCH 048/124] Fix: Result.Preview.Description is not ignored anymore --- Flow.Launcher/MainWindow.xaml | 2 +- Flow.Launcher/ViewModel/ResultViewModel.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index dd47f9d4e..c758f35b5 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -526,7 +526,7 @@ + Text="{Binding DefaultPreviewCustomDescription}" /> diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index d4382fb7f..768968b84 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -288,6 +288,8 @@ namespace Flow.Launcher.ViewModel } } + public string DefaultPreviewCustomDescription => Result.Preview?.Description ?? Result.SubTitle; + public Result Result { get; } public int ResultProgress { From a07af87cb1abd07cf197d5d8b206eca129f5f775 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 19 Dec 2025 15:56:58 +0800 Subject: [PATCH 049/124] Update name --- Flow.Launcher/MainWindow.xaml | 2 +- Flow.Launcher/ViewModel/ResultViewModel.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index c758f35b5..747975b2a 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -526,7 +526,7 @@ + Text="{Binding PreviewDescription}" /> diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index 768968b84..f2f49f8f1 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -288,7 +288,7 @@ namespace Flow.Launcher.ViewModel } } - public string DefaultPreviewCustomDescription => Result.Preview?.Description ?? Result.SubTitle; + public string PreviewDescription => Result.Preview?.Description ?? Result.SubTitle; public Result Result { get; } public int ResultProgress From d1518a490fadab6f9ad34516b5b9f095836d15b5 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Mon, 22 Dec 2025 00:02:47 +0800 Subject: [PATCH 050/124] Replace old clipboard plugin with a new one in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d36a752fc..e7595fff5 100644 --- a/README.md +++ b/README.md @@ -246,9 +246,9 @@ Or download the [early access version](https://github.com/Flow-Launcher/Prerelea -### [Clipboard History](https://github.com/liberize/Flow.Launcher.Plugin.ClipboardHistory) +### [Clipboard+](https://github.com/Jack251970/Flow.Launcher.Plugin.ClipboardPlus) - + ### [Home Assistant Commander](https://github.com/Garulf/HA-Commander) From 0d4775bb7d707284b8bf9961b0a3afd1b23a5739 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 22:04:55 +0000 Subject: [PATCH 051/124] Bump toshimaru/auto-author-assign from 2.1.2 to 3.0.0 Bumps [toshimaru/auto-author-assign](https://github.com/toshimaru/auto-author-assign) from 2.1.2 to 3.0.0. - [Release notes](https://github.com/toshimaru/auto-author-assign/releases) - [Changelog](https://github.com/toshimaru/auto-author-assign/blob/main/CHANGELOG.md) - [Commits](https://github.com/toshimaru/auto-author-assign/compare/v2.1.2...v3.0.0) --- updated-dependencies: - dependency-name: toshimaru/auto-author-assign dependency-version: 3.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/pr_assignee.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_assignee.yml b/.github/workflows/pr_assignee.yml index 76a0cd407..bbd06a425 100644 --- a/.github/workflows/pr_assignee.yml +++ b/.github/workflows/pr_assignee.yml @@ -14,4 +14,4 @@ jobs: runs-on: ubuntu-latest steps: - name: Assign PR to creator - uses: toshimaru/auto-author-assign@v2.1.2 + uses: toshimaru/auto-author-assign@v3.0.0 From bb1dfcde9b9072169bd34a04187987ab4ab21018 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Thu, 25 Dec 2025 13:01:47 +0800 Subject: [PATCH 052/124] Fix hide item option not working in Program plugin (#4141) --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 110 +++++++++++------- .../Programs/UWPPackage.cs | 4 +- .../Programs/Win32.cs | 2 +- 3 files changed, 73 insertions(+), 43 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 456085fca..9c84747d2 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -334,7 +334,7 @@ namespace Flow.Launcher.Plugin.Program } } - public static async Task IndexWin32ProgramsAsync() + public static async Task IndexWin32ProgramsAsync(bool resetCache) { await _win32sLock.WaitAsync(); try @@ -345,7 +345,10 @@ namespace Flow.Launcher.Plugin.Program { _win32s.Add(win32); } - ResetCache(); + if (resetCache) + { + ResetCache(); + } await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); lock (_lastIndexTimeLock) { @@ -362,7 +365,7 @@ namespace Flow.Launcher.Plugin.Program } } - public static async Task IndexUwpProgramsAsync() + public static async Task IndexUwpProgramsAsync(bool resetCache) { await _uwpsLock.WaitAsync(); try @@ -373,7 +376,10 @@ namespace Flow.Launcher.Plugin.Program { _uwps.Add(uwp); } - ResetCache(); + if (resetCache) + { + ResetCache(); + } await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); lock (_lastIndexTimeLock) { @@ -394,12 +400,12 @@ namespace Flow.Launcher.Plugin.Program { var win32Task = Task.Run(async () => { - await Context.API.StopwatchLogInfoAsync(ClassName, "Win32Program index cost", IndexWin32ProgramsAsync); + await Context.API.StopwatchLogInfoAsync(ClassName, "Win32Program index cost", () => IndexWin32ProgramsAsync(resetCache: true)); }); var uwpTask = Task.Run(async () => { - await Context.API.StopwatchLogInfoAsync(ClassName, "UWPProgram index cost", IndexUwpProgramsAsync); + await Context.API.StopwatchLogInfoAsync(ClassName, "UWPProgram index cost", () => IndexUwpProgramsAsync(resetCache: true)); }); await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false); @@ -407,9 +413,21 @@ namespace Flow.Launcher.Plugin.Program internal static void ResetCache() { - var oldCache = cache; - cache = new MemoryCache(cacheOptions); - oldCache.Dispose(); + var newCache = new MemoryCache(cacheOptions); + + // Atomically swap and get the previous cache instance, avoids double-dispose/lost-assignment race + // where each caller receives a distinct prior instance to dispose. + var oldCache = Interlocked.Exchange(ref cache, newCache); + + // Dispose the previous instance (if any)- each caller gets a unique prior instance from above + try + { + oldCache?.Dispose(); + } + catch (Exception e) + { + Context.API.LogException(ClassName, "Failed to dispose old program cache", e); + } } public Control CreateSettingPanel() @@ -442,12 +460,26 @@ namespace Flow.Launcher.Plugin.Program Title = Context.API.GetTranslation("flowlauncher_plugin_program_disable_program"), Action = c => { - _ = DisableProgramAsync(program); - Context.API.ShowMsg( - Context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_success"), - Context.API.GetTranslation( - "flowlauncher_plugin_program_disable_dlgtitle_success_message")); - Context.API.ReQuery(); + _ = Task.Run(async () => + { + try + { + var disabled = await DisableProgramAsync(program); + if (disabled) + { + ResetCache(); + Context.API.ShowMsg( + Context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_success"), + Context.API.GetTranslation( + "flowlauncher_plugin_program_disable_dlgtitle_success_message")); + } + Context.API.ReQuery(); + } + catch (Exception e) + { + Context.API.LogException(ClassName, "Failed to disable program", e); + } + }); return false; }, IcoPath = "Images/disable.png", @@ -458,52 +490,50 @@ namespace Flow.Launcher.Plugin.Program return menuOptions; } - private static async Task DisableProgramAsync(IProgram programToDelete) + private static async Task DisableProgramAsync(IProgram programToDelete) { if (_settings.DisabledProgramSources.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) - return; + { + return false; + } await _uwpsLock.WaitAsync(); - var reindexUwps = true; try { - reindexUwps = _uwps.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier); - var program = _uwps.First(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier); - program.Enabled = false; - _settings.DisabledProgramSources.Add(new ProgramSource(program)); + var program = _uwps.FirstOrDefault(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier); + if (program != null) + { + program.Enabled = false; + _settings.DisabledProgramSources.Add(new ProgramSource(program)); + // Reindex UWP programs + _ = Task.Run(() => IndexUwpProgramsAsync(resetCache: false)); + return true; + } } finally { _uwpsLock.Release(); } - // Reindex UWP programs - if (reindexUwps) - { - _ = Task.Run(IndexUwpProgramsAsync); - return; - } - await _win32sLock.WaitAsync(); - var reindexWin32s = true; try { - reindexWin32s = _win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier); - var program = _win32s.First(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier); - program.Enabled = false; - _settings.DisabledProgramSources.Add(new ProgramSource(program)); + var program = _win32s.FirstOrDefault(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier); + if (program != null) + { + program.Enabled = false; + _settings.DisabledProgramSources.Add(new ProgramSource(program)); + // Reindex Win32 programs + _ = Task.Run(() => IndexWin32ProgramsAsync(resetCache: false)); + return true; + } } finally { _win32sLock.Release(); } - // Reindex Win32 programs - if (reindexWin32s) - { - _ = Task.Run(IndexWin32ProgramsAsync); - return; - } + return false; } public static void StartProcess(Func runProcess, ProcessStartInfo info) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs index 9a8326e9a..8e3362285 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs @@ -290,7 +290,7 @@ namespace Flow.Launcher.Plugin.Program.Programs } private static readonly Channel PackageChangeChannel = Channel.CreateBounded(1); - private static PackageCatalog? catalog; + private static PackageCatalog catalog; public static async Task WatchPackageChangeAsync() { @@ -317,7 +317,7 @@ namespace Flow.Launcher.Plugin.Program.Programs { await Task.Delay(3000).ConfigureAwait(false); PackageChangeChannel.Reader.TryRead(out _); - await Task.Run(Main.IndexUwpProgramsAsync); + await Main.IndexUwpProgramsAsync(resetCache: true).ConfigureAwait(false); } } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 7aca8f3b6..6c7ff1dc1 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -796,7 +796,7 @@ namespace Flow.Launcher.Plugin.Program.Programs { } - await Task.Run(Main.IndexWin32ProgramsAsync); + await Main.IndexWin32ProgramsAsync(resetCache: true).ConfigureAwait(false); } } From ffb37d3e12cadfe520351b136414ea9bcdbaeea0 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 25 Dec 2025 20:06:56 +1100 Subject: [PATCH 053/124] New Crowdin updates (#4127) --- Flow.Launcher/Languages/ja.xaml | 10 +++++----- Flow.Launcher/Languages/pt-pt.xaml | 10 +++++----- Flow.Launcher/Languages/sk.xaml | 2 +- .../Flow.Launcher.Plugin.Explorer/Languages/ar.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/cs.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/da.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/de.xaml | 2 ++ .../Languages/es-419.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/es.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/fr.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/he.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/it.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/ja.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/ko.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/nb.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/nl.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/pl.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/ru.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/sk.xaml | 2 ++ .../Languages/sr-Cyrl-RS.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/sr.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/tr.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/vi.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml | 2 ++ .../Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml | 2 ++ 28 files changed, 61 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher/Languages/ja.xaml b/Flow.Launcher/Languages/ja.xaml index 51ec99ddd..6ebe5271e 100644 --- a/Flow.Launcher/Languages/ja.xaml +++ b/Flow.Launcher/Languages/ja.xaml @@ -64,10 +64,10 @@ 位置のリセット 検索ウィンドウの位置をリセット ここに入力して検索 - {0}: This plugin is still initializing... - Select this result to requery - {0}: Failed to respond! - Select this result for more info + {0}: このプラグインはまだ初期化中です… + この結果を選択して再検索する + {0}: 応答に失敗しました! + 詳細については、この結果を選択してください 設定 @@ -454,7 +454,7 @@ アイコン あなたはFlow Launcherを {0} 回利用しました アップデートを確認する - Become a Sponsor + スポンサーになる 新しいバージョン {0} が利用可能です。Flow Launcherを再起動してください。 アップデートの確認に失敗しました、api.github.com への接続とプロキシ設定を確認してください。 diff --git a/Flow.Launcher/Languages/pt-pt.xaml b/Flow.Launcher/Languages/pt-pt.xaml index 3746ada13..b9bafc3a4 100644 --- a/Flow.Launcher/Languages/pt-pt.xaml +++ b/Flow.Launcher/Languages/pt-pt.xaml @@ -420,13 +420,13 @@ Default search window position. Displayed when triggered by search window hotkey Dialog Jump Result Navigation Behaviour Behaviour to navigate Open/Save As dialog window to the selected result path - Left click or Enter key - Right click + Clique esquerdo ou tecla Enter + Clique direito Dialog Jump File Navigation Behaviour Behaviour to navigate Open/Save As dialog window when the result is a file path - Fill full path in file name box - Fill full path in file name box and open - Fill directory in path box + Preencher caminho total na caixa Nome do ficheiro + Preencher caminho total na caixa Nome do ficheiro e abrir + Preencher diretório na caixa Caminho Proxy HTTP diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml index e76061a3b..881ccf340 100644 --- a/Flow.Launcher/Languages/sk.xaml +++ b/Flow.Launcher/Languages/sk.xaml @@ -636,7 +636,7 @@ Ak pri zadávaní skratky pred ňu pridáte "@", bude sa zhodovať s Po aktualizácii pluginov reštartovať Flow Launcher - {0}: Aktualizované z v{1} na v{2} + {0}: Aktualizácia z v{1} na v{2} Nie je vybraný žiaden plugin diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml index 608fe88a1..1edc1f2aa 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml @@ -56,6 +56,8 @@ بحث في محتوى الملفات: بحث مفهرس: وصول سريع: + Folder Search: + File Search: الكلمة المفتاحية الحالية للإجراء تم مفعّل diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml index 2381d501b..3fd1b721a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml @@ -56,6 +56,8 @@ Vyhledávání obsahu souborů: Vyhledávání v indexu: Rychlý přístup: + Folder Search: + File Search: Aktuální aktivační příkaz Hotovo Povoleno diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml index f5f13e5a3..59b1216e7 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml @@ -56,6 +56,8 @@ File Content Search: Index Search: Quick Access: + Folder Search: + File Search: Current Action Keyword Færdig Enabled diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml index 8e352e614..3292568a6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml @@ -56,6 +56,8 @@ Suche nach Dateiinhalten: Index-Suche: Schnellzugriff: + Folder Search: + File Search: Aktuelles Aktions-Schlüsselwort Fertig Aktiviert diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml index 7379571a7..dc8860bd7 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml @@ -56,6 +56,8 @@ File Content Search: Index Search: Quick Access: + Folder Search: + File Search: Current Action Keyword Hecho Enabled diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml index b59ada7ea..860d64572 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml @@ -56,6 +56,8 @@ Búsqueda de contenido de archivo: Buscar índice: Acceso rápido: + Folder Search: + File Search: Palabra clave de acción actual Aceptar Activado diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml index b0b714154..5a91d3648 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml @@ -56,6 +56,8 @@ Recherche de contenu de fichier : Recherche dans l'index : Accès rapide : + Recherche de dossier : + Recherche de fichier : Mot-clé de l'action en cours Terminer Activé diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml index a84d7707d..a5d4c3829 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml @@ -56,6 +56,8 @@ חיפוש תוכן קובץ: חיפוש אינדקס: גישה מהירה: + Folder Search: + File Search: מילת פעולה נוכחית בוצע מופעל diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml index a88ad2da1..ca774ce80 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml @@ -56,6 +56,8 @@ Ricerca Contenuto File: Ricerca in Indice: Accesso Rapido: + Folder Search: + File Search: Parola Chiave Corrente Conferma Abilitato diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml index b9a825bf2..34b9095cd 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml @@ -56,6 +56,8 @@ File Content Search: Index Search: Quick Access: + Folder Search: + File Search: Current Action Keyword 完了 Enabled diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml index e437926c8..0cbf40621 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml @@ -56,6 +56,8 @@ 파일 내용 검색: 색인 검색: 빠른 접근: + Folder Search: + File Search: 현재 액션 키워드 완료 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml index b0672d3ad..9e96011b3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml @@ -56,6 +56,8 @@ Søk etter filinnhold: Indekssøk: Hurtigtilgang: + Folder Search: + File Search: Nåværende nøkkelord for handling Utført Aktivert diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml index 3de4ce5e5..796bd0a97 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml @@ -56,6 +56,8 @@ File Content Search: Index Search: Quick Access: + Folder Search: + File Search: Current Action Keyword Klaar Enabled diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml index 1a01e8b90..11c3b83b6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml @@ -56,6 +56,8 @@ Przeszukiwanie zawartości plików: Wyszukiwanie indeksowe: Szybki dostęp: + Folder Search: + File Search: Bieżące słowo kluczowe akcji Zapisz Aktywny diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml index 9a3a4ffeb..360342aed 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml @@ -56,6 +56,8 @@ File Content Search: Index Search: Quick Access: + Folder Search: + File Search: Current Action Keyword Finalizado Enabled diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml index 2d33768f9..82990de3c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml @@ -56,6 +56,8 @@ Pesquisa no conteúdo dos ficheiros: Pesquisa no índice: Acesso rápido: + Pesquisar pasta: + Pesquisar ficheiro: Palavra-chave atual OK Ativo diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml index cb28fcfd5..08d28d76f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml @@ -56,6 +56,8 @@ File Content Search: Index Search: Quick Access: + Folder Search: + File Search: Current Action Keyword Подтвердить Включено diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml index 1350969b6..1fc487585 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml @@ -56,6 +56,8 @@ Vyhľadávanie obsahu súborov: Vyhľadávanie v indexe: Rýchly prístup: + Vyhľadávanie priečinkov: + Vyhľadávanie súborov: Aktuálny aktivačný príkaz Hotovo Povolené diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml index e7979f6dd..e9c2f6f84 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml @@ -56,6 +56,8 @@ File Content Search: Index Search: Quick Access: + Folder Search: + File Search: Current Action Keyword Done Enabled diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml index ef7e6a5c3..00bf880a6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml @@ -56,6 +56,8 @@ File Content Search: Index Search: Quick Access: + Folder Search: + File Search: Current Action Keyword Gotovo Enabled diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml index 92461291b..38104d366 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml @@ -56,6 +56,8 @@ Dosya İçeriğini Ara: Dizin Araması: Hızlı Erişim: + Folder Search: + File Search: Geçerli Anahtar Kelime Tamam Etkin diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml index 7600757a2..a6536afb4 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml @@ -56,6 +56,8 @@ Пошук вмісту файлу: Індексний пошук: Швидкий доступ: + Пошук теки: + Пошук файлу: Поточне ключове слово дії Готово Увімкнено diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml index 6416fc447..3b960522d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml @@ -56,6 +56,8 @@ Tìm kiếm nội dung tệp: Tìm kiếm chỉ mục: Truy cập nhanh + Folder Search: + File Search: Từ hành động hiện tại Xong Đã bật diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml index bcef2b668..9758062b3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml @@ -56,6 +56,8 @@ 文件内容搜索: 索引搜索: 快速访问: + 目录搜索: + 文件搜索: 当前触发关键字 确认 已启用 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml index d64cd7698..43e428093 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml @@ -56,6 +56,8 @@ File Content Search: Index Search: 快速存取: + Folder Search: + File Search: Current Action Keyword 已啟用 From 285680337153720119b15045004177c322b65d0b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 25 Dec 2025 21:14:11 +0800 Subject: [PATCH 054/124] Ensure hotkey actions return to query results page first Added a call to App.API.BackToQueryResults() after showing the main window when a hotkey is triggered. This prevents issues that can occur if the current page is a context menu before changing the query. --- Flow.Launcher/Helper/HotKeyMapper.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index bb1cddc6c..0a2826484 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -143,6 +143,8 @@ internal static class HotKeyMapper return; App.API.ShowMainWindow(); + // Make sure to go back to the query results page first since it can cause issues if current page is context menu + App.API.BackToQueryResults(); App.API.ChangeQuery(hotkey.ActionKeyword, true); }); } From 23caeb477c09c964a97157ac04d0be729e4569c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Dec 2025 22:03:58 +0000 Subject: [PATCH 055/124] Bump toshimaru/auto-author-assign from 3.0.0 to 3.0.1 Bumps [toshimaru/auto-author-assign](https://github.com/toshimaru/auto-author-assign) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/toshimaru/auto-author-assign/releases) - [Changelog](https://github.com/toshimaru/auto-author-assign/blob/main/CHANGELOG.md) - [Commits](https://github.com/toshimaru/auto-author-assign/compare/v3.0.0...v3.0.1) --- updated-dependencies: - dependency-name: toshimaru/auto-author-assign dependency-version: 3.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/pr_assignee.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_assignee.yml b/.github/workflows/pr_assignee.yml index bbd06a425..33098672b 100644 --- a/.github/workflows/pr_assignee.yml +++ b/.github/workflows/pr_assignee.yml @@ -14,4 +14,4 @@ jobs: runs-on: ubuntu-latest steps: - name: Assign PR to creator - uses: toshimaru/auto-author-assign@v3.0.0 + uses: toshimaru/auto-author-assign@v3.0.1 From d78d313372dd07aa2df5bd8fc3c27228fa2220a6 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 26 Dec 2025 21:37:30 +1100 Subject: [PATCH 056/124] update to use IcoAbsoluteLocalPath --- Flow.Launcher.Plugin/Result.cs | 50 +++++++++++-------- .../Views/SettingsPanePluginStore.xaml | 2 +- Flow.Launcher/ViewModel/ResultViewModel.cs | 6 +-- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 0f118e36d..e5b3155b6 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -1,6 +1,7 @@ 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; @@ -21,6 +22,8 @@ namespace Flow.Launcher.Plugin private string _icoPath; + private string _icoAbsoluteFullPath; + private string _copyText = string.Empty; private string _badgeIcoPath; @@ -67,12 +70,17 @@ namespace Flow.Launcher.Plugin /// The image to be displayed for the result. ///

/// Can be a local file path or a URL. - /// GlyphInfo is prioritized if not null + /// + /// GlyphInfo is prioritized if not null. + /// Use IcoPathRelative for storage where it needs to be resistant to plugin location change. + /// public string IcoPath { get => _icoPath; set { + _icoPath = value; + // As a standard this property will handle prepping and converting to absolute local path for icon image processing if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(PluginDirectory) @@ -81,40 +89,40 @@ namespace Flow.Launcher.Plugin && !value.StartsWith("https://", StringComparison.OrdinalIgnoreCase) && !value.StartsWith("data:image", StringComparison.OrdinalIgnoreCase)) { - _icoPath = Path.Combine(PluginDirectory, value); + _icoAbsoluteFullPath = Path.Combine(PluginDirectory, value); } else { - _icoPath = value; + _icoAbsoluteFullPath = value; } } } /// - /// Returns the plugin directory relative IcoPath or URL. This path is useful for storage where the it needs - /// to be resistant to changes in plugin location from update or portable mode change. + /// TODO COMMENT + /// + 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. /// - /// Must be a local file path. - /// This will be empty string if IcoPath is a URL, so must check for empty string during usage public string IcoPathRelative { - get => _icoPath; - set + get { - // As a standard this property will handle prepping and converting to absolute local path for icon image processing - if (!string.IsNullOrEmpty(value) - && !string.IsNullOrEmpty(PluginDirectory) - && !Path.IsPathRooted(value) - && !value.StartsWith("http://", StringComparison.OrdinalIgnoreCase) - && !value.StartsWith("https://", StringComparison.OrdinalIgnoreCase) - && !value.StartsWith("data:image", StringComparison.OrdinalIgnoreCase)) + 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)) { - _icoPath = Path.Combine(PluginDirectory, value); - } - else - { - _icoPath = value; + return IcoAbsoluteFullPath; } + + return Path.GetRelativePath(PluginDirectory, IcoAbsoluteFullPath); } } diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml index aa027e19e..5d8837891 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml @@ -333,7 +333,7 @@ Margin="18 24 0 0" HorizontalAlignment="Left" RenderOptions.BitmapScalingMode="Fant" - Source="{Binding IcoPath, IsAsync=True}" /> + Source="{Binding IcoAbsoluteFullPath, IsAsync=True}" /> Glyph is not null; - private bool ImgIconAvailable => !string.IsNullOrEmpty(Result.IcoPath) || Result.Icon is not null; + private bool ImgIconAvailable => !string.IsNullOrEmpty(Result.IcoAbsoluteFullPath) || Result.Icon is not null; private bool BadgeIconAvailable => !string.IsNullOrEmpty(Result.BadgeIcoPath) || Result.BadgeIcon is not null; @@ -236,7 +236,7 @@ namespace Flow.Launcher.ViewModel private async Task LoadImageAsync() { - var imagePath = Result.IcoPath; + var imagePath = Result.IcoAbsoluteFullPath; var iconDelegate = Result.Icon; if (ImageLoader.TryGetValue(imagePath, false, out var img)) { @@ -266,7 +266,7 @@ namespace Flow.Launcher.ViewModel private async Task LoadPreviewImageAsync() { - var imagePath = Result.Preview.PreviewImagePath ?? Result.IcoPath; + var imagePath = Result.Preview.PreviewImagePath ?? Result.IcoAbsoluteFullPath; var iconDelegate = Result.Preview.PreviewDelegate ?? Result.Icon; if (ImageLoader.TryGetValue(imagePath, true, out var img)) { From de0d022268dd0e8ee682042444e357a5e83e2547 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Wed, 31 Dec 2025 12:14:07 +1100 Subject: [PATCH 057/124] rename last opened class; use inheritance; initialise at startup --- Flow.Launcher.Plugin/Result.cs | 8 + Flow.Launcher/App.xaml.cs | 2 + Flow.Launcher/Helper/ResultHelper.cs | 2 +- .../Storage/LastOpenedHistoryItem.cs | 33 --- .../Storage/LastOpenedHistoryResult.cs | 106 +++++++++ Flow.Launcher/Storage/QueryHistory.cs | 52 +++-- Flow.Launcher/ViewModel/MainViewModel.cs | 201 ++++++++++++------ 7 files changed, 293 insertions(+), 111 deletions(-) delete mode 100644 Flow.Launcher/Storage/LastOpenedHistoryItem.cs create mode 100644 Flow.Launcher/Storage/LastOpenedHistoryResult.cs diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index e5b3155b6..2ad19effe 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -5,6 +5,7 @@ using System.Security.Policy; using System.Threading.Tasks; using System.Windows.Controls; using System.Windows.Media; +using System.Text.Json.Serialization; namespace Flow.Launcher.Plugin { @@ -167,11 +168,13 @@ namespace Flow.Launcher.Plugin /// /// Delegate to load an icon for this result. /// + [JsonIgnore] public IconDelegate Icon = null; /// /// Delegate to load an icon for the badge of this result. /// + [JsonIgnore] public IconDelegate BadgeIcon = null; /// @@ -187,6 +190,7 @@ namespace Flow.Launcher.Plugin /// Its result determines what happens to Flow Launcher's query form: /// when true, the form will be hidden; when false, it will stay in focus. /// + [JsonIgnore] public Func Action { get; set; } /// @@ -197,6 +201,7 @@ namespace Flow.Launcher.Plugin /// Its result determines what happens to Flow Launcher's query form: /// when true, the form will be hidden; when false, it will stay in focus. /// + [JsonIgnore] public Func> AsyncAction { get; set; } /// @@ -239,6 +244,7 @@ namespace Flow.Launcher.Plugin /// /// As external information for ContextMenu /// + [JsonIgnore] public object ContextData { get; set; } /// @@ -259,6 +265,7 @@ namespace Flow.Launcher.Plugin /// /// Customized Preview Panel /// + [JsonIgnore] public Lazy PreviewPanel { get; set; } /// @@ -388,6 +395,7 @@ namespace Flow.Launcher.Plugin /// /// Delegate to get the preview panel's image /// + [JsonIgnore] public IconDelegate PreviewDelegate { get; set; } = null; /// diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index b45bbc549..1f1b3c546 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -259,6 +259,8 @@ namespace Flow.Launcher await PluginManager.InitializePluginsAsync(_mainVM); + _mainVM.InitializeQueryHistoryItems(); + // Refresh home page after plugins are initialized because users may open main window during plugin initialization // And home page is created without full plugin list if (_settings.ShowHomePage && _mainVM.QueryResultsSelected() && string.IsNullOrEmpty(_mainVM.QueryText)) diff --git a/Flow.Launcher/Helper/ResultHelper.cs b/Flow.Launcher/Helper/ResultHelper.cs index 5f9a69f28..d0cf2dddc 100644 --- a/Flow.Launcher/Helper/ResultHelper.cs +++ b/Flow.Launcher/Helper/ResultHelper.cs @@ -11,7 +11,7 @@ namespace Flow.Launcher.Helper; public static class ResultHelper { - public static async Task PopulateResultsAsync(LastOpenedHistoryItem item) + public static async Task PopulateResultsAsync(LastOpenedHistoryResult item) { return await PopulateResultsAsync(item.PluginID, item.Query, item.Title, item.SubTitle, item.RecordKey); } diff --git a/Flow.Launcher/Storage/LastOpenedHistoryItem.cs b/Flow.Launcher/Storage/LastOpenedHistoryItem.cs deleted file mode 100644 index c7f9144a7..000000000 --- a/Flow.Launcher/Storage/LastOpenedHistoryItem.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using Flow.Launcher.Plugin; - -namespace Flow.Launcher.Storage; - -public class LastOpenedHistoryItem -{ - public string Title { get; set; } = string.Empty; - public string SubTitle { get; set; } = string.Empty; - public string PluginID { get; set; } = string.Empty; - public string Query { get; set; } = string.Empty; - public string RecordKey { get; set; } = string.Empty; - public string IcoPath { get; set; } = string.Empty; - public GlyphInfo Glyph { get; init; } = null; - public DateTime ExecutedDateTime { get; set; } - - public bool Equals(Result r) - { - if (string.IsNullOrEmpty(RecordKey) || string.IsNullOrEmpty(r.RecordKey)) - { - return Title == r.Title - && SubTitle == r.SubTitle - && PluginID == r.PluginID - && Query == r.OriginQuery.RawQuery; - } - else - { - return RecordKey == r.RecordKey - && PluginID == r.PluginID - && Query == r.OriginQuery.RawQuery; - } - } -} diff --git a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs new file mode 100644 index 000000000..98fdc1a74 --- /dev/null +++ b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs @@ -0,0 +1,106 @@ +using System; +using System.DirectoryServices.ActiveDirectory; +using Flow.Launcher.Helper; +using Flow.Launcher.Plugin; + +namespace Flow.Launcher.Storage; + +public class LastOpenedHistoryResult : Result +{ + public string Query { get; set; } = string.Empty; + + public DateTime ExecutedDateTime { get; set; } + + public LastOpenedHistoryResult() + { + } + + public LastOpenedHistoryResult(Result result) + { + Title = result.Title; + SubTitle = result.SubTitle; + PluginID = result.PluginID; + Query = result.OriginQuery.RawQuery; + RecordKey = result.RecordKey; + IcoPath = result.IcoPath; + PluginDirectory = result.PluginDirectory; + Glyph = result.Glyph; + ExecutedDateTime = DateTime.Now; + } + + //public Result ToResult(bool isQueryHistoryStyle) + //{ + // Result result = null; + + // 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, + // }; + //} + + public bool Equals(Result r) + { + if (string.IsNullOrEmpty(RecordKey) || string.IsNullOrEmpty(r.RecordKey)) + { + return Title == r.Title + && SubTitle == r.SubTitle + && PluginID == r.PluginID + && Query == r.OriginQuery.RawQuery; + } + else + { + return RecordKey == r.RecordKey + && PluginID == r.PluginID + && Query == r.OriginQuery.RawQuery; + } + } +} diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index fde74bf17..c95a9308b 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -1,8 +1,13 @@ 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 { @@ -14,7 +19,7 @@ namespace Flow.Launcher.Storage #pragma warning restore CS0618 // Type or member is obsolete [JsonInclude] - public List LastOpenedHistoryItems { get; private set; } = []; + public List LastOpenedHistoryItems { get; private set; } = []; private readonly int _maxHistory = 300; @@ -24,8 +29,12 @@ namespace Flow.Launcher.Storage // Migrate old history items to new LastOpenedHistoryItems foreach (var item in Items) { - LastOpenedHistoryItems.Add(new LastOpenedHistoryItem + LastOpenedHistoryItems.Add(new LastOpenedHistoryResult { + Title = Localize.executeQuery(item.Query), + IcoPath = Constant.HistoryIcon, + OriginQuery = new Query { RawQuery = item.Query }, + Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C"), Query = item.Query, ExecutedDateTime = item.ExecutedDateTime }); @@ -47,29 +56,42 @@ namespace Flow.Launcher.Storage if (LastOpenedHistoryItems.Count > 0 && TryGetLastOpenedHistoryResult(result, out var existingHistoryItem)) { - existingHistoryItem.IcoPath = result.IcoPath; + //existingHistoryItem.IcoPath = result.IcoPath; existingHistoryItem.ExecutedDateTime = DateTime.Now; } else { - LastOpenedHistoryItems.Add(new LastOpenedHistoryItem - { - Title = result.Title, - SubTitle = result.SubTitle, - PluginID = result.PluginID, - Query = result.OriginQuery.RawQuery, - RecordKey = result.RecordKey, - IcoPath = result.IcoPath, - Glyph = result.Glyph, - ExecutedDateTime = DateTime.Now - }); + LastOpenedHistoryItems.Add(new LastOpenedHistoryResult(result)); } } - private bool TryGetLastOpenedHistoryResult(Result result, out LastOpenedHistoryItem historyItem) + private bool TryGetLastOpenedHistoryResult(Result result, out LastOpenedHistoryResult historyItem) { historyItem = LastOpenedHistoryItems.FirstOrDefault(x => x.Equals(result)); return historyItem is not null; } + + /// + /// Refresh stored PluginDirectory (and optionally normalize relative ico paths) + /// using current plugin metadata. Call this after plugins are loaded/initialized. + /// + public void UpdateIcoAbsoluteFullPath() + { + if (LastOpenedHistoryItems.Count == 0) return; + + foreach (var item in LastOpenedHistoryItems) + { + if (string.IsNullOrEmpty(item.PluginID)) + continue; + + var pluginPair = PluginManager.GetPluginForId(item.PluginID); + if (pluginPair == null) + continue; + + //item.IcoPath = Path.Combine(pluginPair.Metadata.PluginDirectory, item.IcoPath); + + item.PluginDirectory = pluginPair.Metadata.PluginDirectory; + } + } } } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 08d4e0d03..2ff571f19 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; @@ -41,10 +42,32 @@ namespace Flow.Launcher.ViewModel private string _queryTextBeforeLeaveResults; private string _ignoredQueryText; // Used to ignore query text change when switching between context menu and query results - private readonly FlowLauncherJsonStorage _historyItemsStorage; + private int QueryHistoryItemsInitialized = 0; + private FlowLauncherJsonStorage _historyItemsStorage; + private History _queryHistoryItems; + private History QueryHistoryItems + { + get + { + if (QueryHistoryItemsInitialized == 0) + { + App.API.LogException(ClassName, + "QueryHistoryItems is not initialized. Call InitializeQueryHistoryItems() before accessing QueryHistoryItems.", + new InvalidOperationException(), + "QueryHistoryItems"); + throw new InvalidOperationException("QueryHistoryItems is not initialized. Call InitializeQueryHistoryItems() before accessing QueryHistoryItems."); + } + + return _queryHistoryItems; + } + set + { + _queryHistoryItems = value; + } + } + private readonly FlowLauncherJsonStorage _userSelectedRecordStorage; private readonly FlowLauncherJsonStorageTopMostRecord _topMostRecord; - private readonly History _history; private int lastHistoryIndex = 1; private readonly UserSelectedRecord _userSelectedRecord; @@ -151,8 +174,6 @@ namespace Flow.Launcher.ViewModel _historyItemsStorage = new FlowLauncherJsonStorage(); _userSelectedRecordStorage = new FlowLauncherJsonStorage(); _topMostRecord = new FlowLauncherJsonStorageTopMostRecord(); - _history = _historyItemsStorage.Load(); - _history.PopulateHistoryFromLegacyHistory(); _userSelectedRecord = _userSelectedRecordStorage.Load(); ContextMenu = new ResultsViewModel(Settings, this) @@ -352,7 +373,7 @@ namespace Flow.Launcher.ViewModel if (QueryResultsSelected()) { SelectedResults = History; - History.SelectedIndex = _history.LastOpenedHistoryItems.Count - 1; + History.SelectedIndex = QueryHistoryItems.LastOpenedHistoryItems.Count - 1; } else { @@ -380,7 +401,7 @@ namespace Flow.Launcher.ViewModel [RelayCommand] public void ReverseHistory() { - var historyItems = _history.LastOpenedHistoryItems; + var historyItems = QueryHistoryItems.LastOpenedHistoryItems; if (historyItems.Count > 0) { ChangeQueryText(historyItems[^lastHistoryIndex].Query); @@ -394,7 +415,7 @@ namespace Flow.Launcher.ViewModel [RelayCommand] public void ForwardHistory() { - var historyItems = _history.LastOpenedHistoryItems; + var historyItems = QueryHistoryItems.LastOpenedHistoryItems; if (historyItems.Count > 0) { ChangeQueryText(historyItems[^lastHistoryIndex].Query); @@ -536,7 +557,7 @@ namespace Flow.Launcher.ViewModel // Add item to history only if it is from results but not context menu or history if (queryResultsSelected) { - _history.Add(result); + QueryHistoryItems.Add(result); lastHistoryIndex = 1; } } @@ -612,7 +633,7 @@ namespace Flow.Launcher.ViewModel [RelayCommand] private void SelectPrevItem() { - var historyItems = _history.LastOpenedHistoryItems; + var historyItems = QueryHistoryItems.LastOpenedHistoryItems; if (QueryResultsSelected() // Results selected && string.IsNullOrEmpty(QueryText) // No input && Results.Visibility != Visibility.Visible // No items in result list, e.g. when home page is off and no query text is entered, therefore the view is collapsed. @@ -1298,7 +1319,7 @@ namespace Flow.Launcher.ViewModel var query = QueryText.ToLower().Trim(); History.Clear(); - var results = GetHistoryItems(_history.LastOpenedHistoryItems); + var results = GetHistoryItems(QueryHistoryItems.LastOpenedHistoryItems); if (!string.IsNullOrEmpty(query)) { @@ -1315,7 +1336,7 @@ namespace Flow.Launcher.ViewModel } } - private List GetHistoryItems(IEnumerable historyItems) + private List GetHistoryItems(IEnumerable historyItems) { var results = new List(); @@ -1329,70 +1350,126 @@ 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 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; + //var icoPath = !string.IsNullOrEmpty(item.IcoPath) ? item.IcoPath : Constant.HistoryIcon; - if (Settings.HistoryStyle == HistoryStyle.Query) + + + + + + result = new Result { - result = new Result + 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 = _ => { - 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 + App.API.BackToQueryResults(); + App.API.ChangeQuery(item.Query); + return false; + }, + AsyncAction = async c => { - 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) { - 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 = glyph - }; - } + // If we cannot get the result, fallback to re-query + App.API.BackToQueryResults(); + App.API.ChangeQuery(item.Query); + return false; + }, + Glyph = item.Glyph + }; + + + + //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); } - + return results; } + /// + /// TODO COMMENT- Requires the plugins to have initialized first because + /// it needs the plugin directory paths for initialization + /// + public void InitializeQueryHistoryItems() + { + // ensure single-run even if called from multiple threads + if (Interlocked.Exchange(ref QueryHistoryItemsInitialized, 1) == 1) + return; + + QueryHistoryItems = _historyItemsStorage.Load(); + QueryHistoryItems.PopulateHistoryFromLegacyHistory(); + QueryHistoryItems.UpdateIcoAbsoluteFullPath(); + } + private async Task QueryResultsAsync(bool searchDelay, bool isReQuery = false, bool reSelect = true) { _updateSource?.Cancel(); @@ -1620,7 +1697,7 @@ namespace Flow.Launcher.ViewModel void QueryHistoryTask(CancellationToken token) { // Select last history results and revert its order to make sure last history results are on top - var historyItems = _history.LastOpenedHistoryItems.TakeLast(Settings.MaxHistoryResultsToShowForHomePage).Reverse(); + var historyItems = QueryHistoryItems.LastOpenedHistoryItems.TakeLast(Settings.MaxHistoryResultsToShowForHomePage).Reverse(); var results = GetHistoryItems(historyItems); From 8e80c3bde60a903a05ec970a3147680ccac79af6 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Wed, 31 Dec 2025 18:05:53 +0800 Subject: [PATCH 058/124] Add option to show taskbar when Flow Launcher is opend (#4177) * Add option to show taskbar when Flow Launcher is invoked Co-authored-by: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> * Fix: Use ABM_ACTIVATE instead of ABM_SETSTATE for temporary taskbar showing Co-authored-by: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> * Remove unnecessary unsafe keyword from ShowTaskbar method Co-authored-by: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> * Fix missing closing braces in Win32Helper.cs Co-authored-by: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> * Change wording from 'invoked' to 'opened' in localization strings Co-authored-by: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> * Show/hide tasking when showing/hiding Flow * Remove unused APPBARDATA * Guard HideTaskbar() with state so show/hide stay balanced * Improve taskbar visibility management in MainViewModel Moved taskbar show logic to after keyboard layout switch in Show().Ensures consistent taskbar state when invoking or hiding the app. * Clean code * Clean code * Remove blank line --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Jack Ye Co-authored-by: Jack251970 <1160210343@qq.com> --- .../NativeMethods.txt | 4 ++- .../UserSettings/Settings.cs | 1 + Flow.Launcher.Infrastructure/Win32Helper.cs | 27 +++++++++++++++++++ Flow.Launcher/Languages/en.xaml | 2 ++ .../Views/SettingsPaneGeneral.xaml | 10 +++++++ Flow.Launcher/ViewModel/MainViewModel.cs | 16 +++++++++++ 6 files changed, 59 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/NativeMethods.txt b/Flow.Launcher.Infrastructure/NativeMethods.txt index cd072f635..8c5633cfe 100644 --- a/Flow.Launcher.Infrastructure/NativeMethods.txt +++ b/Flow.Launcher.Infrastructure/NativeMethods.txt @@ -91,4 +91,6 @@ PBT_APMRESUMEAUTOMATIC PBT_APMRESUMESUSPEND PowerRegisterSuspendResumeNotification PowerUnregisterSuspendResumeNotification -DeviceNotifyCallbackRoutine \ No newline at end of file +DeviceNotifyCallbackRoutine + +MonitorFromWindow \ No newline at end of file diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 6adefdb6a..7524d6c1a 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -481,6 +481,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings } public bool LeaveCmdOpen { get; set; } public bool HideWhenDeactivated { get; set; } = true; + public bool ShowTaskbarWhenInvoked { get; set; } = false; private bool _showAtTopmost = false; public bool ShowAtTopmost diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 8a41e12b4..635a43354 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -1016,5 +1016,32 @@ namespace Flow.Launcher.Infrastructure } #endregion + + #region Taskbar + + public static unsafe void ShowTaskbar() + { + // Find the taskbar window + var taskbarHwnd = PInvoke.FindWindowEx(HWND.Null, HWND.Null, "Shell_TrayWnd", null); + if (taskbarHwnd == HWND.Null) return; + + // Magic from https://github.com/Oliviaophia/SmartTaskbar + const uint TrayBarFlag = 0x05D1; + var mon = PInvoke.MonitorFromWindow(taskbarHwnd, Windows.Win32.Graphics.Gdi.MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST); + PInvoke.PostMessage(taskbarHwnd, TrayBarFlag, new WPARAM(1), new LPARAM((nint)mon.Value)); + } + + public static void HideTaskbar() + { + // Find the taskbar window + var taskbarHwnd = PInvoke.FindWindowEx(HWND.Null, HWND.Null, "Shell_TrayWnd", null); + if (taskbarHwnd == HWND.Null) return; + + // Magic from https://github.com/Oliviaophia/SmartTaskbar + const uint TrayBarFlag = 0x05D1; + PInvoke.PostMessage(taskbarHwnd, TrayBarFlag, new WPARAM(0), IntPtr.Zero); + } + + #endregion } } diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 2a21840f7..145e1883d 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -81,6 +81,8 @@ After uninstallation, you need to manually remove this task (Flow.Launcher Startup) via Task Scheduler Error setting launch on startup Hide Flow Launcher when focus is lost + Show taskbar when Flow Launcher is opened + Temporarily show the taskbar when Flow Launcher is opened, useful for auto-hidden taskbars. Do not show new version notifications Search Window Location Remember Last Position diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 720cb440b..b4c94cb35 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -72,6 +72,16 @@ OnContent="{DynamicResource enable}" /> + + + + Date: Thu, 1 Jan 2026 14:30:28 +1100 Subject: [PATCH 059/124] 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; From 8d7fa1d397f2e3f590c294bef345bf99290b2435 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 1 Jan 2026 15:14:05 +1100 Subject: [PATCH 060/124] revert QueryHistoryItems property --- Flow.Launcher/App.xaml.cs | 2 +- Flow.Launcher/ViewModel/MainViewModel.cs | 56 +++++++----------------- 2 files changed, 16 insertions(+), 42 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 1f1b3c546..30036cb10 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -259,7 +259,7 @@ namespace Flow.Launcher await PluginManager.InitializePluginsAsync(_mainVM); - _mainVM.InitializeQueryHistoryItems(); + _mainVM.RefreshLastOpenedHistoryResult(); // Refresh home page after plugins are initialized because users may open main window during plugin initialization // And home page is created without full plugin list diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 9a32b0d03..47183489f 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -42,33 +42,11 @@ namespace Flow.Launcher.ViewModel private string _queryTextBeforeLeaveResults; private string _ignoredQueryText; // Used to ignore query text change when switching between context menu and query results - private int QueryHistoryItemsInitialized = 0; - private FlowLauncherJsonStorage _historyItemsStorage; - private History _queryHistoryItems; - private History QueryHistoryItems - { - get - { - if (QueryHistoryItemsInitialized == 0) - { - App.API.LogException(ClassName, - "QueryHistoryItems is not initialized. Call InitializeQueryHistoryItems() before accessing QueryHistoryItems.", - new InvalidOperationException(), - "QueryHistoryItems"); - throw new InvalidOperationException("QueryHistoryItems is not initialized. Call InitializeQueryHistoryItems() before accessing QueryHistoryItems."); - } - - return _queryHistoryItems; - } - set - { - _queryHistoryItems = value; - } - } - + private readonly FlowLauncherJsonStorage _historyItemsStorage; + private readonly History _history; + private int lastHistoryIndex = 1; private readonly FlowLauncherJsonStorage _userSelectedRecordStorage; private readonly FlowLauncherJsonStorageTopMostRecord _topMostRecord; - private int lastHistoryIndex = 1; private readonly UserSelectedRecord _userSelectedRecord; private CancellationTokenSource _updateSource; // Used to cancel old query flows @@ -172,9 +150,10 @@ namespace Flow.Launcher.ViewModel }; _historyItemsStorage = new FlowLauncherJsonStorage(); + _history = _historyItemsStorage.Load(); _userSelectedRecordStorage = new FlowLauncherJsonStorage(); - _topMostRecord = new FlowLauncherJsonStorageTopMostRecord(); _userSelectedRecord = _userSelectedRecordStorage.Load(); + _topMostRecord = new FlowLauncherJsonStorageTopMostRecord(); ContextMenu = new ResultsViewModel(Settings, this) { @@ -373,7 +352,7 @@ namespace Flow.Launcher.ViewModel if (QueryResultsSelected()) { SelectedResults = History; - History.SelectedIndex = QueryHistoryItems.LastOpenedHistoryItems.Count - 1; + History.SelectedIndex = _history.LastOpenedHistoryItems.Count - 1; } else { @@ -401,7 +380,7 @@ namespace Flow.Launcher.ViewModel [RelayCommand] public void ReverseHistory() { - var historyItems = QueryHistoryItems.LastOpenedHistoryItems; + var historyItems = _history.LastOpenedHistoryItems; if (historyItems.Count > 0) { ChangeQueryText(historyItems[^lastHistoryIndex].Query); @@ -415,7 +394,7 @@ namespace Flow.Launcher.ViewModel [RelayCommand] public void ForwardHistory() { - var historyItems = QueryHistoryItems.LastOpenedHistoryItems; + var historyItems = _history.LastOpenedHistoryItems; if (historyItems.Count > 0) { ChangeQueryText(historyItems[^lastHistoryIndex].Query); @@ -557,7 +536,7 @@ namespace Flow.Launcher.ViewModel // Add item to history only if it is from results but not context menu or history if (queryResultsSelected) { - QueryHistoryItems.Add(result); + _history.Add(result); lastHistoryIndex = 1; } } @@ -633,7 +612,7 @@ namespace Flow.Launcher.ViewModel [RelayCommand] private void SelectPrevItem() { - var historyItems = QueryHistoryItems.LastOpenedHistoryItems; + var historyItems = _history.LastOpenedHistoryItems; if (QueryResultsSelected() // Results selected && string.IsNullOrEmpty(QueryText) // No input && Results.Visibility != Visibility.Visible // No items in result list, e.g. when home page is off and no query text is entered, therefore the view is collapsed. @@ -1319,7 +1298,7 @@ namespace Flow.Launcher.ViewModel var query = QueryText.ToLower().Trim(); History.Clear(); - var results = GetHistoryItems(QueryHistoryItems.LastOpenedHistoryItems); + var results = GetHistoryItems(_history.LastOpenedHistoryItems); if (!string.IsNullOrEmpty(query)) { @@ -1383,15 +1362,10 @@ namespace Flow.Launcher.ViewModel /// TODO COMMENT- Requires the plugins to have initialized first because /// it needs the plugin directory paths for initialization /// - public void InitializeQueryHistoryItems() + internal void RefreshLastOpenedHistoryResult() { - // ensure single-run even if called from multiple threads - if (Interlocked.Exchange(ref QueryHistoryItemsInitialized, 1) == 1) - return; - - QueryHistoryItems = _historyItemsStorage.Load(); - QueryHistoryItems.PopulateHistoryFromLegacyHistory(); - QueryHistoryItems.UpdateIcoAbsoluteFullPath(); + _history.PopulateHistoryFromLegacyHistory(); + _history.UpdateIcoAbsoluteFullPath(); } private async Task QueryResultsAsync(bool searchDelay, bool isReQuery = false, bool reSelect = true) @@ -1621,7 +1595,7 @@ namespace Flow.Launcher.ViewModel void QueryHistoryTask(CancellationToken token) { // Select last history results and revert its order to make sure last history results are on top - var historyItems = QueryHistoryItems.LastOpenedHistoryItems.TakeLast(Settings.MaxHistoryResultsToShowForHomePage).Reverse(); + var historyItems = _history.LastOpenedHistoryItems.TakeLast(Settings.MaxHistoryResultsToShowForHomePage).Reverse(); var results = GetHistoryItems(historyItems); From 810725cc6b8930ffd284e6d5a6074fa98fe02a1a Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 1 Jan 2026 15:43:23 +1100 Subject: [PATCH 061/124] add explicit JsonInclude for PluginID internal set --- Flow.Launcher.Plugin/Result.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index f1dd53b22..edfa5bb99 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -227,6 +227,7 @@ namespace Flow.Launcher.Plugin /// /// Plugin ID that generated this result /// + [JsonInclude] public string PluginID { get; internal set; } /// From 20854ba5d72d62db13a6b980c1963f7efb595290 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 1 Jan 2026 18:20:29 +1100 Subject: [PATCH 062/124] formatting --- Flow.Launcher/Storage/QueryHistory.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index c1ea4b520..25ab521b6 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; @@ -48,6 +48,9 @@ namespace Flow.Launcher.Storage public void Add(Result result) { if (string.IsNullOrEmpty(result.OriginQuery.TrimmedQuery)) return; + // History results triggered from homepage do not contain PluginID, + // these are intentionally not saved otherwise cause duplicates due to subtitle + // containing datetime string. if (string.IsNullOrEmpty(result.PluginID)) return; // Maintain the max history limit @@ -59,7 +62,6 @@ namespace Flow.Launcher.Storage if (LastOpenedHistoryItems.Count > 0 && TryGetLastOpenedHistoryResult(result, out var existingHistoryItem)) { - //existingHistoryItem.IcoPath = result.IcoPath; existingHistoryItem.ExecutedDateTime = DateTime.Now; } else @@ -91,8 +93,6 @@ namespace Flow.Launcher.Storage if (pluginPair == null) continue; - //item.IcoPath = Path.Combine(pluginPair.Metadata.PluginDirectory, item.IcoPath); - item.PluginDirectory = pluginPair.Metadata.PluginDirectory; } } From 7c670de7c2d548ed60675399b07056f9e04fe4d4 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 1 Jan 2026 18:23:12 +1100 Subject: [PATCH 063/124] fix history result highlight and scroll when history mode activated --- Flow.Launcher/ViewModel/MainViewModel.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index e7b4023c2..c3c9d8fc8 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; @@ -355,7 +355,9 @@ namespace Flow.Launcher.ViewModel if (QueryResultsSelected()) { SelectedResults = History; - History.SelectedIndex = _history.LastOpenedHistoryItems.Count - 1; + + SelectedResults.SelectedIndex = 0; + SelectedResults.SelectedItem = SelectedResults.Results[0]; } else { From f9df44a2cdca26ea92a83ea3e08f65075fbead67 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 1 Jan 2026 22:32:39 +1100 Subject: [PATCH 064/124] rename to IcoPathAbsolute --- Flow.Launcher.Plugin/Result.cs | 12 +++++------- .../SettingPages/Views/SettingsPanePluginStore.xaml | 2 +- Flow.Launcher/Storage/QueryHistory.cs | 2 +- Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- Flow.Launcher/ViewModel/ResultViewModel.cs | 6 +++--- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index edfa5bb99..a34608454 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -23,7 +23,7 @@ namespace Flow.Launcher.Plugin private string _icoPath; - private string _icoAbsoluteFullPath; + private string _icoPathAbsolute; private string _copyText = string.Empty; @@ -72,9 +72,7 @@ namespace Flow.Launcher.Plugin /// /// Can be a local file path or a URL. /// - /// GlyphInfo is prioritized if not null. - /// Use IcoPathRelative for storage where it needs to be resistant to plugin location change. - /// + /// GlyphInfo is prioritized if not null public string IcoPath { get => _icoPath; @@ -90,11 +88,11 @@ namespace Flow.Launcher.Plugin && !value.StartsWith("https://", StringComparison.OrdinalIgnoreCase) && !value.StartsWith("data:image", StringComparison.OrdinalIgnoreCase)) { - _icoAbsoluteFullPath = Path.Combine(PluginDirectory, value); + _icoPathAbsolute = Path.Combine(PluginDirectory, value); } else { - _icoAbsoluteFullPath = value; + _icoPathAbsolute = value; } } } @@ -102,7 +100,7 @@ namespace Flow.Launcher.Plugin /// /// TODO COMMENT /// - public string IcoAbsoluteFullPath => _icoAbsoluteFullPath; + public string IcoPathAbsolute => _icoPathAbsolute; /// /// The image to be displayed for the badge of the result. diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml index 5d8837891..4d37dc93a 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml @@ -333,7 +333,7 @@ Margin="18 24 0 0" HorizontalAlignment="Left" RenderOptions.BitmapScalingMode="Fant" - Source="{Binding IcoAbsoluteFullPath, IsAsync=True}" /> + Source="{Binding IcoPathAbsolute, IsAsync=True}" /> - public void UpdateIcoAbsoluteFullPath() + public void UpdateIcoPathAbsolute() { if (LastOpenedHistoryItems.Count == 0) return; diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index c3c9d8fc8..650c0a34c 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1370,7 +1370,7 @@ namespace Flow.Launcher.ViewModel internal void RefreshLastOpenedHistoryResult() { _history.PopulateHistoryFromLegacyHistory(); - _history.UpdateIcoAbsoluteFullPath(); + _history.UpdateIcoPathAbsolute(); } private async Task QueryResultsAsync(bool searchDelay, bool isReQuery = false, bool reSelect = true) diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index 974b2e83b..077acfce7 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -141,7 +141,7 @@ namespace Flow.Launcher.ViewModel private bool GlyphAvailable => Glyph is not null; - private bool ImgIconAvailable => !string.IsNullOrEmpty(Result.IcoAbsoluteFullPath) || Result.Icon is not null; + private bool ImgIconAvailable => !string.IsNullOrEmpty(Result.IcoPathAbsolute) || Result.Icon is not null; private bool BadgeIconAvailable => !string.IsNullOrEmpty(Result.BadgeIcoPath) || Result.BadgeIcon is not null; @@ -236,7 +236,7 @@ namespace Flow.Launcher.ViewModel private async Task LoadImageAsync() { - var imagePath = Result.IcoAbsoluteFullPath; + var imagePath = Result.IcoPathAbsolute; var iconDelegate = Result.Icon; if (ImageLoader.TryGetValue(imagePath, false, out var img)) { @@ -266,7 +266,7 @@ namespace Flow.Launcher.ViewModel private async Task LoadPreviewImageAsync() { - var imagePath = Result.Preview.PreviewImagePath ?? Result.IcoAbsoluteFullPath; + var imagePath = Result.Preview.PreviewImagePath ?? Result.IcoPathAbsolute; var iconDelegate = Result.Preview.PreviewDelegate ?? Result.Icon; if (ImageLoader.TryGetValue(imagePath, true, out var img)) { From 6d6003fd8051efb19df7e740a35e9e020739bce2 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 1 Jan 2026 22:45:52 +1100 Subject: [PATCH 065/124] switch to using TrimmedQuery --- Flow.Launcher/App.xaml.cs | 2 +- Flow.Launcher/Storage/LastOpenedHistoryResult.cs | 12 ++++++------ Flow.Launcher/Storage/QueryHistory.cs | 2 +- Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 30036cb10..1d6130c48 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -259,7 +259,7 @@ namespace Flow.Launcher await PluginManager.InitializePluginsAsync(_mainVM); - _mainVM.RefreshLastOpenedHistoryResult(); + _mainVM.RefreshLastOpenedHistoryResults(); // Refresh home page after plugins are initialized because users may open main window during plugin initialization // And home page is created without full plugin list diff --git a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs index 4eb76da1c..7d49df44b 100644 --- a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs +++ b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs @@ -13,7 +13,7 @@ public class LastOpenedHistoryResult : Result public LastOpenedHistoryResult() { - this.OriginQuery = new Query { RawQuery = Query }; + this.OriginQuery = new Query { TrimmedQuery = Query }; } public LastOpenedHistoryResult(Result result) @@ -21,7 +21,7 @@ public class LastOpenedHistoryResult : Result Title = result.Title; SubTitle = result.SubTitle; PluginID = result.PluginID; - Query = result.OriginQuery.RawQuery; + Query = result.OriginQuery.TrimmedQuery; OriginQuery = result.OriginQuery; RecordKey = result.RecordKey; IcoPath = result.IcoPath; @@ -32,10 +32,10 @@ public class LastOpenedHistoryResult : Result Action = _ => { App.API.BackToQueryResults(); - App.API.ChangeQuery(result.OriginQuery.RawQuery); + App.API.ChangeQuery(result.OriginQuery.TrimmedQuery); return false; }; - //Used for last history style reopening, currently need to be assigned at MainViewModel.cs + //Used for Last Opened History style reopening, currently need to be assigned at MainViewModel.cs AsyncAction = null; } @@ -66,13 +66,13 @@ public class LastOpenedHistoryResult : Result return Title == r.Title && SubTitle == r.SubTitle && PluginID == r.PluginID - && Query == r.OriginQuery.RawQuery; + && Query == r.OriginQuery.TrimmedQuery; } else { return RecordKey == r.RecordKey && PluginID == r.PluginID - && Query == r.OriginQuery.RawQuery; + && Query == r.OriginQuery.TrimmedQuery; } } } diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 8b8cbdd90..3c5c7000c 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -30,7 +30,7 @@ namespace Flow.Launcher.Storage { Title = Localize.executeQuery(item.Query), IcoPath = Constant.HistoryIcon, - OriginQuery = new Query { RawQuery = item.Query }, + OriginQuery = new Query { TrimmedQuery = item.Query }, Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C"), Query = item.Query, Action = _ => diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 650c0a34c..844adf4c4 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1367,7 +1367,7 @@ namespace Flow.Launcher.ViewModel /// TODO COMMENT- Requires the plugins to have initialized first because /// it needs the plugin directory paths for initialization /// - internal void RefreshLastOpenedHistoryResult() + internal void RefreshLastOpenedHistoryResults() { _history.PopulateHistoryFromLegacyHistory(); _history.UpdateIcoPathAbsolute(); From 9c2f2398f1bf1d77430b7790de43ef3d189df28a Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 1 Jan 2026 23:11:28 +1100 Subject: [PATCH 066/124] add method comments for LastOpenedHistoryResult --- .../Storage/LastOpenedHistoryResult.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs index 7d49df44b..90d47a4d7 100644 --- a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs +++ b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs @@ -5,17 +5,37 @@ using Flow.Launcher.Plugin; namespace Flow.Launcher.Storage; +/// +/// A serializable result used to record the last opened history for reopening results. +/// Inherits common result fields from and adds the original query and execution time. +/// public class LastOpenedHistoryResult : Result { + /// + /// The query string from Query.TrimmedQuery property, it is stored as a string instead of the entire Query class . + /// This is used so results can be reopened or re-run using the serialized query string. + /// public string Query { get; set; } = string.Empty; + /// + /// The UTC date and time when this result was executed/opened. + /// public DateTime ExecutedDateTime { get; set; } + /// + /// Initializes a new instance of . + /// Sets using the current value, because OriginQuery is not serialized. + /// public LastOpenedHistoryResult() { this.OriginQuery = new Query { TrimmedQuery = Query }; } + /// + /// Creates a from an existing . + /// Copies required fields and sets up default reopening actions. + /// + /// The original result to create history from. public LastOpenedHistoryResult(Result result) { Title = result.Title; @@ -39,6 +59,10 @@ public class LastOpenedHistoryResult : Result AsyncAction = null; } + /// + /// Creates a deep copy of . + /// + /// A new containing the same required data. public LastOpenedHistoryResult Copy() { @@ -59,6 +83,12 @@ public class LastOpenedHistoryResult : Result }; } + /// + /// Determines whether the specified is equivalent to this history result. + /// Comparison uses when available; otherwise falls back to title/subtitle/plugin id and query. + /// + /// The result to compare to. + /// true if the results are considered equal; otherwise false. public bool Equals(Result r) { if (string.IsNullOrEmpty(RecordKey) || string.IsNullOrEmpty(r.RecordKey)) From 3e32fca356df6189badc0ee7338e42e8c7f70853 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 2 Jan 2026 01:47:44 +0800 Subject: [PATCH 067/124] Fix localized name get failure --- .../NativeMethods.txt | 5 +- .../Programs/ShellLocalization.cs | 48 ++++--------------- 2 files changed, 13 insertions(+), 40 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/NativeMethods.txt b/Plugins/Flow.Launcher.Plugin.Program/NativeMethods.txt index ecd547dff..a8fe178c7 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/NativeMethods.txt +++ b/Plugins/Flow.Launcher.Plugin.Program/NativeMethods.txt @@ -7,4 +7,7 @@ S_OK SLGP_FLAGS WIN32_FIND_DATAW SLR_FLAGS -IShellLinkW \ No newline at end of file +IShellItem +SHCreateItemFromParsingName +IShellLinkW +CoTaskMemFree \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLocalization.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLocalization.cs index 5c2f6f976..6f2118af8 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLocalization.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLocalization.cs @@ -1,9 +1,7 @@ using System; using System.IO; -using System.Runtime.InteropServices; using Windows.Win32; using Windows.Win32.Foundation; -using Windows.Win32.System.LibraryLoader; namespace Flow.Launcher.Plugin.Program.Programs { @@ -21,46 +19,18 @@ namespace Flow.Launcher.Plugin.Program.Programs /// The localized name as string or . public static unsafe string GetLocalizedName(string path) { - const int capacity = 1024; - Span buffer = new char[capacity]; - - // If there is no resource to localize a file name the method returns a non zero value. - fixed (char* bufferPtr = buffer) + int retCode = PInvoke.SHCreateItemFromParsingName(path, null, typeof(Windows.Win32.UI.Shell.IShellItem).GUID, out object shellItemObj); + if (retCode != 0 || shellItemObj is not Windows.Win32.UI.Shell.IShellItem shellItem) { - int id; - fixed (char* pathPtr = path) - { - var result = PInvoke.SHGetLocalizedName(new PCWSTR(pathPtr), bufferPtr, capacity, &id); - - if (result != HRESULT.S_OK) - { - return string.Empty; - } - - var resourcePathStr = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(bufferPtr).ToString(); - fixed (char* resourcePathPtr = resourcePathStr) - { - _ = PInvoke.ExpandEnvironmentStrings(new PCWSTR(resourcePathPtr), bufferPtr, capacity); - using var handle = PInvoke.LoadLibraryEx(resourcePathStr, - LOAD_LIBRARY_FLAGS.DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_FLAGS.LOAD_LIBRARY_AS_DATAFILE); - if (handle.IsInvalid) - { - return string.Empty; - } - - // not sure about the behavior of Pinvoke.LoadString, so we clear the buffer before using it (so it must be a null-terminated string) - buffer.Clear(); - - if (PInvoke.LoadString(handle, (uint)id, buffer, capacity) != 0) - { - var lString = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(bufferPtr).ToString(); - return lString; - } - } - } + return string.Empty; } - return string.Empty; + PWSTR displayName; + shellItem.GetDisplayName(Windows.Win32.UI.Shell.SIGDN.SIGDN_NORMALDISPLAY, &displayName); + string filename = displayName.ToString(); + PInvoke.CoTaskMemFree(displayName); + + return filename; } /// From b062fc056fab72e6fb91f17f805f6f341f8b4dd0 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Fri, 2 Jan 2026 12:23:05 +0800 Subject: [PATCH 068/124] Catch exceptions and release com objects --- .../Programs/ShellLocalization.cs | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLocalization.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLocalization.cs index 6f2118af8..815b74b96 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLocalization.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/ShellLocalization.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Runtime.InteropServices; using Windows.Win32; using Windows.Win32.Foundation; @@ -25,12 +26,22 @@ namespace Flow.Launcher.Plugin.Program.Programs return string.Empty; } - PWSTR displayName; - shellItem.GetDisplayName(Windows.Win32.UI.Shell.SIGDN.SIGDN_NORMALDISPLAY, &displayName); - string filename = displayName.ToString(); - PInvoke.CoTaskMemFree(displayName); - - return filename; + try + { + PWSTR displayName; + shellItem.GetDisplayName(Windows.Win32.UI.Shell.SIGDN.SIGDN_NORMALDISPLAY, &displayName); + string filename = displayName.ToString(); + PInvoke.CoTaskMemFree(displayName); + return filename; + } + catch + { + return string.Empty; + } + finally + { + Marshal.ReleaseComObject(shellItem); + } } /// From 024eeaf6bfa40428a67035a8a1f91c8f6501d94e Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 2 Jan 2026 22:30:09 +1100 Subject: [PATCH 069/124] changed LastOpenHistoryResult's Copy to DeepCopy to clarify intent --- .../Storage/LastOpenedHistoryResult.cs | 25 +++++++++++++------ Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs index 90d47a4d7..4a4257048 100644 --- a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs +++ b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs @@ -60,26 +60,37 @@ public class LastOpenedHistoryResult : Result } /// - /// Creates a deep copy of . + /// Selectively creates a deep copy of the required properties for . + /// This copy should be independent of original and full isolated. /// /// A new containing the same required data. - public LastOpenedHistoryResult Copy() + public LastOpenedHistoryResult DeepCopy() { - + // queryValue and glyphValue are captured to ensure they are correctly referenced in the Action delegate. + var queryValue = Query; + var glyphValue = this.Glyph; return new LastOpenedHistoryResult { Title = this.Title, SubTitle = this.SubTitle, PluginID = this.PluginID, Query = this.Query, - OriginQuery = this.OriginQuery, + OriginQuery = new Query { TrimmedQuery = Query }, RecordKey = this.RecordKey, IcoPath = this.IcoPath, PluginDirectory = this.PluginDirectory, - Action = this.Action, - AsyncAction = this.AsyncAction, - Glyph = this.Glyph, + // Used for Query History style reopening + Action = _ => + { + App.API.BackToQueryResults(); + App.API.ChangeQuery(queryValue); + return false; + }, + //Used for Last Opened History style reopening, currently need to be assigned at MainViewModel.cs + AsyncAction = null, + Glyph = new GlyphInfo(this.Glyph.FontFamily, this.Glyph.Glyph), ExecutedDateTime = this.ExecutedDateTime + // Note: Other properties are left as default — copy if needed. }; } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 844adf4c4..53ee68e01 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1333,7 +1333,7 @@ namespace Flow.Launcher.ViewModel foreach (var item in historyItems) { - var copiedItem = item.Copy(); + var copiedItem = item.DeepCopy(); // 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. From 2176553b26f4e4f97f95d107295aee8555456888 Mon Sep 17 00:00:00 2001 From: Nilvan Lopes Date: Fri, 2 Jan 2026 14:17:29 -0300 Subject: [PATCH 070/124] Add max suggestions setting for web search plugins Introduced a MaxSuggestions property (min 1, max 10) to control the number of autocomplete suggestions shown in web search plugins. Updated the UI to allow user configuration and added localized labels for the new setting in all supported languages. Suggestions in results are now limited according to this setting. --- .../Languages/de.xaml | 1 + .../Languages/en.xaml | 1 + .../Languages/es.xaml | 1 + .../Languages/fr.xaml | 1 + .../Languages/pt-br.xaml | 1 + Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs | 5 +++-- Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs | 14 ++++++++++++++ .../SettingsControl.xaml | 14 ++++++++++++++ 8 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml index ed9f35454..6a8a3e471 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml @@ -19,6 +19,7 @@ URL Suche Autovervollständigung von Suchanfragen verwenden + Max. Vorschläge: Autovervollständigung der Daten aus: Bitte wählen Sie eine Websuche aus Sind Sie sicher, dass Sie {0} löschen wollen? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml index 5d65e4462..b3d19d8ae 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/en.xaml @@ -21,6 +21,7 @@ URL Search Use Search Query Autocomplete + Max Suggestions: Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml index 41a6325b3..c41ae2413 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml @@ -19,6 +19,7 @@ URL Busca en Usar autocompletado en consultas de búsqueda + Max sugerencias: Autocompletar datos desde: Por favor, seleccione una búsqueda web ¿Está seguro de que desea eliminar {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml index f185a4b50..e9ba6b205 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml @@ -19,6 +19,7 @@ URL Rechercher sur Utiliser la fonction d'auto-complétion des requêtes de recherche + Max suggestions : Saisir automatiquement les données à partir de : Veuillez sélectionner une recherche web Êtes-vous sûr de vouloir supprimer {0} ? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml index 6a6704b95..2d4384e8c 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml @@ -19,6 +19,7 @@ URL Search Use Search Query Autocomplete + Qtd Sugestões: Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs index b9b8a0b19..299e27499 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -91,6 +91,7 @@ namespace Flow.Launcher.Plugin.WebSearch if (token.IsCancellationRequested) return null; + } return results; @@ -126,7 +127,7 @@ namespace Flow.Launcher.Plugin.WebSearch token.ThrowIfCancellationRequested(); - var resultsFromSuggestion = suggestions?.Select(o => new Result + var resultsFromSuggestion = suggestions?.Take(_settings.MaxSuggestions).Select(o => new Result { Title = o, SubTitle = subtitle, diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs index 0c0ac4b84..d6f7b3012 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs @@ -205,6 +205,20 @@ namespace Flow.Launcher.Plugin.WebSearch } } + private int maxSuggestions = 1; + public int MaxSuggestions + { + get => maxSuggestions; + set + { + if (maxSuggestions != value) + { + maxSuggestions = Math.Max(1, Math.Min(value, 10)); + OnPropertyChanged(nameof(MaxSuggestions)); + } + } + } + [JsonIgnore] public SuggestionSource[] Suggestions { get; set; } = { new Google(), diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml index 152558e81..d046f101b 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml @@ -154,6 +154,20 @@ + [Obsolete("For backwards comaptibility. Remove after release v2.3.0")] public void PopulateHistoryFromLegacyHistory() { if (Items.Count == 0) return; diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 68ddada00..7c0cadb67 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1386,7 +1386,6 @@ namespace Flow.Launcher.ViewModel /// internal void RefreshLastOpenedHistoryResults() { - // TODO: remove after release v2.3.0 _history.PopulateHistoryFromLegacyHistory(); _history.UpdateIcoPathAbsolute(); From 19fa107feab66d4d3eea15268300fff21d8834c8 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 4 Jan 2026 22:05:39 +1100 Subject: [PATCH 079/124] minor fixes and adjustments for code quality --- Flow.Launcher.Plugin/Result.cs | 2 +- Flow.Launcher/Storage/LastOpenedHistoryResult.cs | 4 +--- Flow.Launcher/Storage/QueryHistory.cs | 2 +- Flow.Launcher/ViewModel/MainViewModel.cs | 7 +++++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 1894e0eda..78fa31974 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -10,7 +10,7 @@ namespace Flow.Launcher.Plugin { /// /// Describes a result of a executed by a plugin. - /// This or its child classses is serializable. + /// This or its child classes is serializable. /// public class Result { diff --git a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs index 51fba5849..032d24498 100644 --- a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs +++ b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs @@ -18,17 +18,15 @@ public class LastOpenedHistoryResult : Result public string Query { get; set; } = string.Empty; /// - /// The UTC date and time when this result was executed/opened. + /// The local date and time when this result was executed/opened. /// public DateTime ExecutedDateTime { get; set; } /// /// Initializes a new instance of . - /// Sets using the current value, because OriginQuery is not serialized. /// public LastOpenedHistoryResult() { - this.OriginQuery = new Query { TrimmedQuery = Query }; } /// diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 015b33399..21e78f8c7 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -25,7 +25,7 @@ namespace Flow.Launcher.Storage /// format and append them to /// . /// - [Obsolete("For backwards comaptibility. Remove after release v2.3.0")] + [Obsolete("For backwards compatibility. Remove after release v2.3.0")] public void PopulateHistoryFromLegacyHistory() { if (Items.Count == 0) return; diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 7c0cadb67..e91533dfe 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -356,8 +356,11 @@ namespace Flow.Launcher.ViewModel { SelectedResults = History; - SelectedResults.SelectedIndex = 0; - SelectedResults.SelectedItem = SelectedResults.Results[0]; + if (SelectedResults.Results.Count > 0) + { + SelectedResults.SelectedIndex = 0; + SelectedResults.SelectedItem = SelectedResults.Results[0]; + } } else { From 590b4c82d2c0d935a3c2657a307264e864d61775 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 4 Jan 2026 23:00:24 +0800 Subject: [PATCH 080/124] Try NumberBox --- .../Flow.Launcher.Plugin.WebSearch.csproj | 6 ++ .../Settings.cs | 4 +- .../SettingsControl.xaml | 57 ++++++++++--------- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj index 42176376b..a743c929f 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj @@ -50,6 +50,12 @@ + + + all + + + diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs index d6f7b3012..d08e14aaf 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs @@ -213,8 +213,8 @@ namespace Flow.Launcher.Plugin.WebSearch { if (maxSuggestions != value) { - maxSuggestions = Math.Max(1, Math.Min(value, 10)); - OnPropertyChanged(nameof(MaxSuggestions)); + maxSuggestions = value; + OnPropertyChanged(); } } } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml index d046f101b..963652b13 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml @@ -3,7 +3,9 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern" xmlns:vm="clr-namespace:Flow.Launcher.Plugin.WebSearch" d:DataContext="{d:DesignInstance vm:SettingsViewModel}" d:DesignHeight="300" @@ -45,17 +47,17 @@ x:Name="SearchSourcesListView" Grid.Row="0" Margin="{StaticResource SettingPanelItemTopBottomMargin}" + AllowDrop="True" BorderBrush="DarkGray" BorderThickness="1" + Drop="ListView_Drop" GridViewColumnHeader.Click="SortByColumn" ItemsSource="{Binding Settings.SearchSources}" MouseDoubleClick="MouseDoubleClickItem" - SelectedItem="{Binding Settings.SelectedSearchSource}" - SizeChanged="ListView_SizeChanged" PreviewMouseLeftButtonDown="ListView_PreviewMouseLeftButtonDown" PreviewMouseMove="ListView_PreviewMouseMove" - AllowDrop="True" - Drop="ListView_Drop" + SelectedItem="{Binding Settings.SelectedSearchSource}" + SizeChanged="ListView_SizeChanged" Style="{StaticResource {x:Static GridView.GridViewStyleKey}}"> @@ -146,45 +148,48 @@ - - - + \ No newline at end of file From 4c46e161609e661d7c2c62df735c03cd3f54ce72 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 4 Jan 2026 23:19:12 +0800 Subject: [PATCH 081/124] Fix possible convert issue --- .../Flow.Launcher.Plugin.WebSearch.csproj | 1 + Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs | 9 ++++++--- .../SettingsControl.xaml | 3 ++- .../SettingsControl.xaml.cs | 10 ++++++++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj index a743c929f..edf6fe9d6 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj @@ -51,6 +51,7 @@ + all diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs index d08e14aaf..31540ad92 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs @@ -211,10 +211,13 @@ namespace Flow.Launcher.Plugin.WebSearch get => maxSuggestions; set { - if (maxSuggestions != value) + if (value > 0 && value <= 1000) { - maxSuggestions = value; - OnPropertyChanged(); + if (maxSuggestions != value) + { + maxSuggestions = value; + OnPropertyChanged(); + } } } } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml index 963652b13..06afd72f5 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml @@ -167,7 +167,8 @@ SmallChange="10" SpinButtonPlacementMode="Compact" ValidationMode="InvalidInputOverwritten" - Value="{Binding Settings.MaxSuggestions, Mode=TwoWay}" /> + ValueChanged="NumberBox_ValueChanged" + Value="{Binding Settings.MaxSuggestions, Mode=OneWay}" /> Date: Sun, 4 Jan 2026 23:19:41 +0800 Subject: [PATCH 082/124] Test no PrivateAssets --- .../Flow.Launcher.Plugin.WebSearch.csproj | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj index edf6fe9d6..3b3add106 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj @@ -51,10 +51,7 @@ - - - all - + From 6c1c9fe6008760c4caa60bbc44a3b3f6c819c231 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 4 Jan 2026 23:45:13 +0800 Subject: [PATCH 083/124] Use wrap panel --- .../SettingsControl.xaml | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml index 06afd72f5..e4f3485cd 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml @@ -148,20 +148,16 @@ - + + - - + \ No newline at end of file From a9e6a68369c5e9298cb9659de10f6148283347a9 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Sun, 4 Jan 2026 23:47:42 +0800 Subject: [PATCH 084/124] Revert "Upgrade iNKORE.UI.WPF.Modern and refactor scroll logic" --- Flow.Launcher/Flow.Launcher.csproj | 2 +- .../Controls/CustomScrollViewerEx.cs | 253 ++++++++++++++++++ Flow.Launcher/Themes/Base.xaml | 12 +- Flow.Launcher/packages.lock.json | 10 +- 4 files changed, 264 insertions(+), 13 deletions(-) create mode 100644 Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index f3c614702..576bf6f2f 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -138,7 +138,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs b/Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs new file mode 100644 index 000000000..78985108c --- /dev/null +++ b/Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs @@ -0,0 +1,253 @@ +using iNKORE.UI.WPF.Modern.Controls; +using iNKORE.UI.WPF.Modern.Controls.Helpers; +using iNKORE.UI.WPF.Modern.Controls.Primitives; +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +namespace Flow.Launcher.Resources.Controls +{ + // TODO: Use IsScrollAnimationEnabled property in future: https://github.com/iNKORE-NET/UI.WPF.Modern/pull/347 + public class CustomScrollViewerEx : ScrollViewer + { + private double LastVerticalLocation = 0; + private double LastHorizontalLocation = 0; + + public CustomScrollViewerEx() + { + Loaded += OnLoaded; + var valueSource = DependencyPropertyHelper.GetValueSource(this, AutoPanningMode.IsEnabledProperty).BaseValueSource; + if (valueSource == BaseValueSource.Default) + { + AutoPanningMode.SetIsEnabled(this, true); + } + } + + #region Orientation + + public static readonly DependencyProperty OrientationProperty = + DependencyProperty.Register( + nameof(Orientation), + typeof(Orientation), + typeof(CustomScrollViewerEx), + new PropertyMetadata(Orientation.Vertical)); + + public Orientation Orientation + { + get => (Orientation)GetValue(OrientationProperty); + set => SetValue(OrientationProperty, value); + } + + #endregion + + #region AutoHideScrollBars + + public static readonly DependencyProperty AutoHideScrollBarsProperty = + ScrollViewerHelper.AutoHideScrollBarsProperty + .AddOwner( + typeof(CustomScrollViewerEx), + new PropertyMetadata(true, OnAutoHideScrollBarsChanged)); + + public bool AutoHideScrollBars + { + get => (bool)GetValue(AutoHideScrollBarsProperty); + set => SetValue(AutoHideScrollBarsProperty, value); + } + + private static void OnAutoHideScrollBarsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is CustomScrollViewerEx sv) + { + sv.UpdateVisualState(); + } + } + + #endregion + + private void OnLoaded(object sender, RoutedEventArgs e) + { + LastVerticalLocation = VerticalOffset; + LastHorizontalLocation = HorizontalOffset; + UpdateVisualState(false); + } + + /// + protected override void OnInitialized(EventArgs e) + { + base.OnInitialized(e); + + if (Style == null && ReadLocalValue(StyleProperty) == DependencyProperty.UnsetValue) + { + SetResourceReference(StyleProperty, typeof(ScrollViewer)); + } + } + + /// + protected override void OnMouseWheel(MouseWheelEventArgs e) + { + var Direction = GetDirection(); + ScrollViewerBehavior.SetIsAnimating(this, true); + + if (Direction == Orientation.Vertical) + { + if (ScrollableHeight > 0) + { + e.Handled = true; + } + + var WheelChange = e.Delta * (ViewportHeight / 1.5) / ActualHeight; + var newOffset = LastVerticalLocation - WheelChange; + + if (newOffset < 0) + { + newOffset = 0; + } + + if (newOffset > ScrollableHeight) + { + newOffset = ScrollableHeight; + } + + if (newOffset == LastVerticalLocation) + { + return; + } + + ScrollToVerticalOffset(LastVerticalLocation); + + ScrollToValue(newOffset, Direction); + LastVerticalLocation = newOffset; + } + else + { + if (ScrollableWidth > 0) + { + e.Handled = true; + } + + var WheelChange = e.Delta * (ViewportWidth / 1.5) / ActualWidth; + var newOffset = LastHorizontalLocation - WheelChange; + + if (newOffset < 0) + { + newOffset = 0; + } + + if (newOffset > ScrollableWidth) + { + newOffset = ScrollableWidth; + } + + if (newOffset == LastHorizontalLocation) + { + return; + } + + ScrollToHorizontalOffset(LastHorizontalLocation); + + ScrollToValue(newOffset, Direction); + LastHorizontalLocation = newOffset; + } + } + + /// + protected override void OnScrollChanged(ScrollChangedEventArgs e) + { + base.OnScrollChanged(e); + if (!ScrollViewerBehavior.GetIsAnimating(this)) + { + LastVerticalLocation = VerticalOffset; + LastHorizontalLocation = HorizontalOffset; + } + } + + private Orientation GetDirection() + { + var isShiftDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift); + + if (Orientation == Orientation.Horizontal) + { + return isShiftDown ? Orientation.Vertical : Orientation.Horizontal; + } + else + { + return isShiftDown ? Orientation.Horizontal : Orientation.Vertical; + } + } + + /// + /// Causes the to load a new view into the viewport using the specified offsets and zoom factor. + /// + /// A value between 0 and that specifies the distance the content should be scrolled horizontally. + /// A value between 0 and that specifies the distance the content should be scrolled vertically. + /// A value between MinZoomFactor and MaxZoomFactor that specifies the required target ZoomFactor. + /// if the view is changed; otherwise, . + public bool ChangeView(double? horizontalOffset, double? verticalOffset, float? zoomFactor) + { + return ChangeView(horizontalOffset, verticalOffset, zoomFactor, false); + } + + /// + /// Causes the to load a new view into the viewport using the specified offsets and zoom factor, and optionally disables scrolling animation. + /// + /// A value between 0 and that specifies the distance the content should be scrolled horizontally. + /// A value between 0 and that specifies the distance the content should be scrolled vertically. + /// A value between MinZoomFactor and MaxZoomFactor that specifies the required target ZoomFactor. + /// to disable zoom/pan animations while changing the view; otherwise, . The default is false. + /// if the view is changed; otherwise, . + public bool ChangeView(double? horizontalOffset, double? verticalOffset, float? zoomFactor, bool disableAnimation) + { + if (disableAnimation) + { + if (horizontalOffset.HasValue) + { + ScrollToHorizontalOffset(horizontalOffset.Value); + } + + if (verticalOffset.HasValue) + { + ScrollToVerticalOffset(verticalOffset.Value); + } + } + else + { + if (horizontalOffset.HasValue) + { + ScrollToHorizontalOffset(LastHorizontalLocation); + ScrollToValue(Math.Min(ScrollableWidth, horizontalOffset.Value), Orientation.Horizontal); + LastHorizontalLocation = horizontalOffset.Value; + } + + if (verticalOffset.HasValue) + { + ScrollToVerticalOffset(LastVerticalLocation); + ScrollToValue(Math.Min(ScrollableHeight, verticalOffset.Value), Orientation.Vertical); + LastVerticalLocation = verticalOffset.Value; + } + } + + return true; + } + + private void ScrollToValue(double value, Orientation Direction) + { + if (Direction == Orientation.Vertical) + { + ScrollToVerticalOffset(value); + } + else + { + ScrollToHorizontalOffset(value); + } + + ScrollViewerBehavior.SetIsAnimating(this, false); + } + + private void UpdateVisualState(bool useTransitions = true) + { + var stateName = AutoHideScrollBars ? "NoIndicator" : "MouseIndicator"; + VisualStateManager.GoToState(this, stateName, useTransitions); + } + } +} diff --git a/Flow.Launcher/Themes/Base.xaml b/Flow.Launcher/Themes/Base.xaml index c3831e68f..c5b45890b 100644 --- a/Flow.Launcher/Themes/Base.xaml +++ b/Flow.Launcher/Themes/Base.xaml @@ -252,14 +252,12 @@ - - - - + - + diff --git a/Flow.Launcher/packages.lock.json b/Flow.Launcher/packages.lock.json index 8c3a16e5e..b4b929d19 100644 --- a/Flow.Launcher/packages.lock.json +++ b/Flow.Launcher/packages.lock.json @@ -28,9 +28,9 @@ }, "iNKORE.UI.WPF.Modern": { "type": "Direct", - "requested": "[0.10.2.1, )", - "resolved": "0.10.2.1", - "contentHash": "nGwuuVul+TcLCTgPmaAZCc0fYFqUpCNZ8PiulVT3gZnsWt/AvxMZ0DSPpuyI/iRPc/NhFIg9lSIR7uaHWV0I/Q==", + "requested": "[0.10.1, )", + "resolved": "0.10.1", + "contentHash": "nRYmBosiL+42eUpLbHeqP7qJqtp5EpzuIMZTpvq4mFV33VB/JjkFg1y82gk50pjkXlAQWDvRyrfSAmPR5AM+3g==", "dependencies": { "iNKORE.UI.WPF": "1.2.8" } @@ -1619,7 +1619,7 @@ "FSharp.Core": "[9.0.303, )", "Flow.Launcher.Infrastructure": "[1.0.0, )", "Flow.Launcher.Localization": "[0.0.6, )", - "Flow.Launcher.Plugin": "[5.1.0, )", + "Flow.Launcher.Plugin": "[5.0.0, )", "Meziantou.Framework.Win32.Jobs": "[3.4.5, )", "Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )", "SemanticVersioning": "[3.0.0, )", @@ -1634,7 +1634,7 @@ "BitFaster.Caching": "[2.5.4, )", "CommunityToolkit.Mvvm": "[8.4.0, )", "Flow.Launcher.Localization": "[0.0.6, )", - "Flow.Launcher.Plugin": "[5.1.0, )", + "Flow.Launcher.Plugin": "[5.0.0, )", "InputSimulator": "[1.0.4, )", "MemoryPack": "[1.21.4, )", "Microsoft.VisualStudio.Threading": "[17.14.15, )", From 216b6f536f6d748e004d14fedacf7762ed0f63d0 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 5 Jan 2026 13:07:02 +0800 Subject: [PATCH 085/124] Code cleanup --- .../Storage/LastOpenedHistoryResult.cs | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs index 032d24498..482502776 100644 --- a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs +++ b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs @@ -1,6 +1,4 @@ using System; -using System.DirectoryServices.ActiveDirectory; -using Flow.Launcher.Helper; using Flow.Launcher.Plugin; namespace Flow.Launcher.Storage; @@ -53,7 +51,7 @@ public class LastOpenedHistoryResult : Result App.API.ChangeQuery(result.OriginQuery.TrimmedQuery); return false; }; - //Used for Last Opened History style reopening, currently need to be assigned at MainViewModel.cs + // Used for Last Opened History style reopening, currently need to be assigned at MainViewModel.cs AsyncAction = null; } @@ -66,17 +64,17 @@ public class LastOpenedHistoryResult : Result { // queryValue and glyphValue are captured to ensure they are correctly referenced in the Action delegate. var queryValue = Query; - var glyphValue = this.Glyph; + var glyphValue = Glyph; return new LastOpenedHistoryResult { - Title = this.Title, - SubTitle = this.SubTitle, - PluginID = this.PluginID, - Query = this.Query, + Title = Title, + SubTitle = SubTitle, + PluginID = PluginID, + Query = Query, OriginQuery = new Query { TrimmedQuery = Query }, - RecordKey = this.RecordKey, - IcoPath = this.IcoPath, - PluginDirectory = this.PluginDirectory, + RecordKey = RecordKey, + IcoPath = IcoPath, + PluginDirectory = PluginDirectory, // Used for Query History style reopening Action = _ => { @@ -84,12 +82,12 @@ public class LastOpenedHistoryResult : Result App.API.ChangeQuery(queryValue); return false; }, - //Used for Last Opened History style reopening, currently need to be assigned at MainViewModel.cs + // Used for Last Opened History style reopening, currently need to be assigned at MainViewModel.cs AsyncAction = null, Glyph = glyphValue != null - ? new GlyphInfo(this.Glyph.FontFamily, this.Glyph.Glyph) + ? new GlyphInfo(Glyph.FontFamily, Glyph.Glyph) : null, - ExecutedDateTime = this.ExecutedDateTime + ExecutedDateTime = ExecutedDateTime // Note: Other properties are left as default — copy if needed. }; } From 5f992352eec0028f65c54042697af8020591a5cc Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 5 Jan 2026 13:48:58 +0800 Subject: [PATCH 086/124] Code cleanup --- Flow.Launcher/Storage/QueryHistory.cs | 13 ++++++------- Flow.Launcher/ViewModel/MainViewModel.cs | 16 ++++++++++------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 21e78f8c7..d612c81d0 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -70,13 +70,15 @@ namespace Flow.Launcher.Storage LastOpenedHistoryItems.RemoveAt(0); } + // If the last item is the same as the current result, just update the timestamp and the icon path if (LastOpenedHistoryItems.Count > 0 && TryGetLastOpenedHistoryResult(result, out var existingHistoryItem)) { existingHistoryItem.ExecutedDateTime = DateTime.Now; - if (existingHistoryItem.IcoPath != result.IcoPath) + { existingHistoryItem.IcoPath = result.IcoPath; + } } else { @@ -102,17 +104,14 @@ namespace Flow.Launcher.Storage /// Call this after plugins are loaded/initialized. public void UpdateIcoPathAbsolute() { - if (LastOpenedHistoryItems.Count == 0) - return; + if (LastOpenedHistoryItems.Count == 0) return; foreach (var item in LastOpenedHistoryItems) { - if (string.IsNullOrEmpty(item.PluginID)) - continue; + if (string.IsNullOrEmpty(item.PluginID)) continue; var pluginPair = PluginManager.GetPluginForId(item.PluginID); - if (pluginPair == null) - continue; + if (pluginPair == null) continue; item.PluginDirectory = pluginPair.Metadata.PluginDirectory; } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index e91533dfe..c3eeada11 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -355,11 +355,10 @@ namespace Flow.Launcher.ViewModel if (QueryResultsSelected()) { SelectedResults = History; - - if (SelectedResults.Results.Count > 0) + if (History.Results.Count > 0) { - SelectedResults.SelectedIndex = 0; - SelectedResults.SelectedItem = SelectedResults.Results[0]; + History.SelectedIndex = 0; + History.SelectedItem = History.Results[0]; } } else @@ -1331,8 +1330,8 @@ namespace Flow.Launcher.ViewModel { // Items saved to disk are differentiated by Query also, but LastOpened style only cares about unique results historyItems = historyItems - .GroupBy(r => new { r.Title, r.SubTitle, r.PluginID, r.RecordKey }) - .Select(g => g.First()); + .GroupBy(r => new { r.Title, r.SubTitle, r.PluginID, r.RecordKey }) + .Select(g => g.First()); } foreach (var item in historyItems) @@ -1340,11 +1339,16 @@ namespace Flow.Launcher.ViewModel var copiedItem = item.DeepCopy(); if (Settings.HistoryStyle == HistoryStyle.Query) + { copiedItem.Title = Localize.executeQuery(copiedItem.Query); + } + // Subtitle has datetime which can cause duplicates when saving. copiedItem.SubTitle = Localize.lastExecuteTime(copiedItem.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; + if (Settings.HistoryStyle == HistoryStyle.LastOpened) { copiedItem.AsyncAction = async c => From 177e60739c7a65536e38387872ea1d00fa63a776 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 5 Jan 2026 14:34:57 +0800 Subject: [PATCH 087/124] Add code comments --- Flow.Launcher/App.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 1d6130c48..da11380b8 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -259,6 +259,7 @@ namespace Flow.Launcher await PluginManager.InitializePluginsAsync(_mainVM); + // Refresh the history results after plugins are initialized so that we can parse the absolute icon paths _mainVM.RefreshLastOpenedHistoryResults(); // Refresh home page after plugins are initialized because users may open main window during plugin initialization From 11645fdc9a9e22ef39f19a63cf1733bd5835bfb8 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 5 Jan 2026 19:27:11 +1100 Subject: [PATCH 088/124] ensure history results ordered by ExecutedDateTime --- Flow.Launcher/ViewModel/MainViewModel.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index c3eeada11..6be88ced5 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -357,8 +357,8 @@ namespace Flow.Launcher.ViewModel SelectedResults = History; if (History.Results.Count > 0) { - History.SelectedIndex = 0; - History.SelectedItem = History.Results[0]; + SelectedResults.SelectedIndex = 0; + SelectedResults.SelectedItem = History.Results[0]; } } else @@ -1326,6 +1326,8 @@ namespace Flow.Launcher.ViewModel { var results = new List(); + historyItems = historyItems.OrderByDescending(x => x.ExecutedDateTime); + if (Settings.HistoryStyle == HistoryStyle.LastOpened) { // Items saved to disk are differentiated by Query also, but LastOpened style only cares about unique results From 58d910dc572a399a7fd10604f3327c7a92ed8f05 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 5 Jan 2026 19:37:05 +1100 Subject: [PATCH 089/124] fix deep copy Glyph on LastOpenHistoryResult --- Flow.Launcher/Storage/LastOpenedHistoryResult.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs index 482502776..b71282f14 100644 --- a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs +++ b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs @@ -85,7 +85,7 @@ public class LastOpenedHistoryResult : Result // Used for Last Opened History style reopening, currently need to be assigned at MainViewModel.cs AsyncAction = null, Glyph = glyphValue != null - ? new GlyphInfo(Glyph.FontFamily, Glyph.Glyph) + ? new GlyphInfo(glyphValue.FontFamily, glyphValue.Glyph) : null, ExecutedDateTime = ExecutedDateTime // Note: Other properties are left as default — copy if needed. From f22b6449d4a929950d608fccd07aafc7188ef415 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 5 Jan 2026 19:18:47 +0800 Subject: [PATCH 090/124] Fix issue when querying history items in home page --- Flow.Launcher/ViewModel/MainViewModel.cs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 6be88ced5..65a382447 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1322,12 +1322,19 @@ namespace Flow.Launcher.ViewModel } } - private List GetHistoryItems(IEnumerable historyItems) + private List GetHistoryItems(IEnumerable historyItems, int? selectLast = null) { var results = new List(); + // Order by executed time descending: Latest -> Oldest historyItems = historyItems.OrderByDescending(x => x.ExecutedDateTime); + // Select the last N items if specified + if (selectLast.HasValue) + { + historyItems = historyItems.Take(selectLast.Value); + } + if (Settings.HistoryStyle == HistoryStyle.LastOpened) { // Items saved to disk are differentiated by Query also, but LastOpened style only cares about unique results @@ -1637,10 +1644,8 @@ namespace Flow.Launcher.ViewModel void QueryHistoryTask(CancellationToken token) { - // Select last history results and revert its order to make sure last history results are on top - var historyItems = _history.LastOpenedHistoryItems.TakeLast(Settings.MaxHistoryResultsToShowForHomePage).Reverse(); - - var results = GetHistoryItems(historyItems); + // Select last history results + var results = GetHistoryItems(_history.LastOpenedHistoryItems, Settings.MaxHistoryResultsToShowForHomePage); if (token.IsCancellationRequested) return; From e6a91a9959d3e07d6d8f315f1ee781b93f6935f1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 5 Jan 2026 20:17:12 +0800 Subject: [PATCH 091/124] Ensure history items have valid icons in QueryHistory Added CheckIcoPathValidity to QueryHistory to set default icons for history items missing IcoPath, addressing legacy data issues. Integrated this check into MainViewModel's RefreshLastOpenedHistoryResults to guarantee icon validity before updating absolute paths. --- Flow.Launcher/Storage/QueryHistory.cs | 18 ++++++++++++++++++ Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index d612c81d0..0622248fb 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -51,6 +51,24 @@ namespace Flow.Launcher.Storage Items.Clear(); } + /// + /// Checks all items in for empty IcoPath. + /// If found, updates it using the history icon. + /// + /// + /// We need this because some prereleased version of Flow did not set the IcoPath when adding. + /// + public void CheckIcoPathValidity() + { + foreach (var item in LastOpenedHistoryItems) + { + if (string.IsNullOrEmpty(item.IcoPath)) + { + item.IcoPath = Constant.HistoryIcon; + } + } + } + /// /// Records a result into the last-opened history list (). /// This will also update the IcoPath if existing history item has one that is different. diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 65a382447..4a1a826ce 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1403,7 +1403,7 @@ namespace Flow.Launcher.ViewModel internal void RefreshLastOpenedHistoryResults() { _history.PopulateHistoryFromLegacyHistory(); - + _history.CheckIcoPathValidity(); _history.UpdateIcoPathAbsolute(); } From cf4268d1c32ba70860d6e5a1a762b8910bd45ac4 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 5 Jan 2026 21:30:06 +0800 Subject: [PATCH 092/124] Fix preview panel blank issue --- Flow.Launcher/ViewModel/MainViewModel.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 4a1a826ce..e9f902f13 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -646,6 +646,8 @@ namespace Flow.Launcher.ViewModel if (!QueryResultsSelected()) { SelectedResults = Results; + PreviewSelectedItem = Results.SelectedItem; + _ = UpdatePreviewAsync(); } else { From 5b2fb1fb3875900e8bb692d604f5319e20b190be Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 5 Jan 2026 22:26:39 +0800 Subject: [PATCH 093/124] Revert "Ensure history items have valid icons in QueryHistory" This reverts commit e6a91a9959d3e07d6d8f315f1ee781b93f6935f1. --- Flow.Launcher/Storage/QueryHistory.cs | 18 ------------------ Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 0622248fb..d612c81d0 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -51,24 +51,6 @@ namespace Flow.Launcher.Storage Items.Clear(); } - /// - /// Checks all items in for empty IcoPath. - /// If found, updates it using the history icon. - /// - /// - /// We need this because some prereleased version of Flow did not set the IcoPath when adding. - /// - public void CheckIcoPathValidity() - { - foreach (var item in LastOpenedHistoryItems) - { - if (string.IsNullOrEmpty(item.IcoPath)) - { - item.IcoPath = Constant.HistoryIcon; - } - } - } - /// /// Records a result into the last-opened history list (). /// This will also update the IcoPath if existing history item has one that is different. diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index e9f902f13..7de29232e 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1405,7 +1405,7 @@ namespace Flow.Launcher.ViewModel internal void RefreshLastOpenedHistoryResults() { _history.PopulateHistoryFromLegacyHistory(); - _history.CheckIcoPathValidity(); + _history.UpdateIcoPathAbsolute(); } From e403c41530a94267fd4a90037a6a473333290170 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 5 Jan 2026 22:55:09 +0800 Subject: [PATCH 094/124] Change copied icon logic as origin --- Flow.Launcher/Storage/QueryHistory.cs | 4 ++-- Flow.Launcher/ViewModel/MainViewModel.cs | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index d612c81d0..6af2a5908 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -35,9 +35,9 @@ namespace Flow.Launcher.Storage LastOpenedHistoryItems.Add(new LastOpenedHistoryResult { Title = Localize.executeQuery(item.Query), - IcoPath = Constant.HistoryIcon, + IcoPath = null, OriginQuery = new Query { TrimmedQuery = item.Query }, - Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C"), + Glyph = null, Query = item.Query, Action = _ => { diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 7de29232e..7e5869b65 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1352,6 +1352,18 @@ namespace Flow.Launcher.ViewModel if (Settings.HistoryStyle == HistoryStyle.Query) { copiedItem.Title = Localize.executeQuery(copiedItem.Query); + copiedItem.IcoPath = Constant.HistoryIcon; + // TODO: Add Glyph here + // copiedItem.Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C"); + } + else + { + if (string.IsNullOrEmpty(copiedItem.IcoPath)) // Must manually set missing image icon here + { + copiedItem.IcoPath = Constant.MissingImgIcon; + } + copiedItem.ShowBadge = true; + copiedItem.BadgeIcoPath = Constant.HistoryIcon; } // Subtitle has datetime which can cause duplicates when saving. From 77b631be87f188feba00833b8c05ebe0c94d89d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jan 2026 22:08:44 +0000 Subject: [PATCH 095/124] Bump Svg.Skia from 3.2.1 to 3.4.0 --- updated-dependencies: - dependency-name: Svg.Skia dependency-version: 3.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../Flow.Launcher.Plugin.BrowserBookmark.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index ed121375b..1df65c2eb 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -106,7 +106,7 @@ - + From c610100c13fb50f74522d5d7c6a874922ed154e1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 6 Jan 2026 15:07:00 +0800 Subject: [PATCH 096/124] Use QueryManager function --- Flow.Launcher/Helper/ResultHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Helper/ResultHelper.cs b/Flow.Launcher/Helper/ResultHelper.cs index 82211242b..017651fdf 100644 --- a/Flow.Launcher/Helper/ResultHelper.cs +++ b/Flow.Launcher/Helper/ResultHelper.cs @@ -24,7 +24,7 @@ public static class ResultHelper if (query == null) return null; try { - var freshResults = await plugin.Plugin.QueryAsync(query, CancellationToken.None); + var freshResults = await PluginManager.QueryForPluginAsync(plugin, query, CancellationToken.None); // Try to match by record key first if it is valid, otherwise fall back to title + subtitle match if (string.IsNullOrEmpty(recordKey)) { From e404d02965abeea1cccf522577a841d56fd54d52 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 6 Jan 2026 15:13:37 +0800 Subject: [PATCH 097/124] Update the result when executing history item --- Flow.Launcher/Storage/QueryHistory.cs | 22 ++++++++++++++++++++++ Flow.Launcher/ViewModel/MainViewModel.cs | 3 +++ 2 files changed, 25 insertions(+) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 6af2a5908..20e295f02 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -86,6 +86,28 @@ namespace Flow.Launcher.Storage } } + /// + /// Update a result into the last-opened history list (). + /// + public void Update(Result result) + { + if (string.IsNullOrEmpty(result.OriginQuery.TrimmedQuery)) return; + // History results triggered from homepage do not contain PluginID, + // these are intentionally not saved otherwise cause duplicates due to subtitle + // containing datetime string. + if (string.IsNullOrEmpty(result.PluginID)) return; + + // If the last item is the same as the current result, just update the icon path + if (LastOpenedHistoryItems.Count > 0 && + TryGetLastOpenedHistoryResult(result, out var existingHistoryItem)) + { + if (existingHistoryItem.IcoPath != result.IcoPath) + { + existingHistoryItem.IcoPath = result.IcoPath; + } + } + } + /// /// Attempts to find an existing in /// that is considered equal to the supplied . diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 7e5869b65..1aee20e5b 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1383,6 +1383,9 @@ namespace Flow.Launcher.ViewModel // Record the user selected record for result ranking _userSelectedRecord.Add(reflectResult); + // Update the history with the reflected result + _history.Update(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); From 26e4529f27b493b878401a517c95c1e557877e81 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 6 Jan 2026 15:45:49 +0800 Subject: [PATCH 098/124] Update the result when executing history item --- Flow.Launcher/Storage/QueryHistory.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 20e295f02..38bfe0c49 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -101,6 +101,7 @@ namespace Flow.Launcher.Storage if (LastOpenedHistoryItems.Count > 0 && TryGetLastOpenedHistoryResult(result, out var existingHistoryItem)) { + existingHistoryItem.ExecutedDateTime = DateTime.Now; if (existingHistoryItem.IcoPath != result.IcoPath) { existingHistoryItem.IcoPath = result.IcoPath; From 583bf74724fe9a94ac634f9564495e5090ab5b20 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 6 Jan 2026 15:46:08 +0800 Subject: [PATCH 099/124] Update code comments --- Flow.Launcher/Storage/QueryHistory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 38bfe0c49..803591662 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -97,7 +97,7 @@ namespace Flow.Launcher.Storage // containing datetime string. if (string.IsNullOrEmpty(result.PluginID)) return; - // If the last item is the same as the current result, just update the icon path + // If the last item is the same as the current result, just update the timestamp and the icon path if (LastOpenedHistoryItems.Count > 0 && TryGetLastOpenedHistoryResult(result, out var existingHistoryItem)) { From 938a87ceca9973ea8dceeb95edc39ac434c4c3eb Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 6 Jan 2026 18:31:15 +0800 Subject: [PATCH 100/124] Fix preview panel blank issue --- Flow.Launcher/ViewModel/MainViewModel.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 1aee20e5b..876026e55 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -443,6 +443,8 @@ namespace Flow.Launcher.ViewModel else { SelectedResults = Results; + PreviewSelectedItem = Results.SelectedItem; + _ = UpdatePreviewAsync(); } } From 9d9ab1ffd2030998a09c944ab71ad1156b175cf3 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 6 Jan 2026 18:35:53 +0800 Subject: [PATCH 101/124] Do not allow context menu for history items --- Flow.Launcher/ViewModel/MainViewModel.cs | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 876026e55..3d5c99edc 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -435,7 +435,8 @@ namespace Flow.Launcher.ViewModel { // When switch to ContextMenu from QueryResults, but no item being chosen, should do nothing // i.e. Shift+Enter/Ctrl+O right after Alt + Space should do nothing - if (SelectedResults.SelectedItem != null) + if (SelectedResults.SelectedItem?.Result != null && + !string.IsNullOrEmpty(SelectedResults.SelectedItem.Result.PluginID)) // Do not show context menu for history items { SelectedResults = ContextMenu; } @@ -1260,22 +1261,12 @@ namespace Flow.Launcher.ViewModel var selected = Results.SelectedItem?.Result; - if (selected != null) // SelectedItem returns null if selection is empty. + if (selected != null && // SelectedItem returns null if selection is empty. + !string.IsNullOrEmpty(selected.PluginID)) // SelectedItem must have a valid PluginID { - List results; - if (selected.PluginID == null) // SelectedItem from history in home page. - { - results = new() - { - ContextMenuTopMost(selected) - }; - } - else - { - results = PluginManager.GetContextMenusForPlugin(selected); - results.Add(ContextMenuTopMost(selected)); - results.Add(ContextMenuPluginInfo(selected)); - } + List results = PluginManager.GetContextMenusForPlugin(selected); + results.Add(ContextMenuTopMost(selected)); + results.Add(ContextMenuPluginInfo(selected)); if (!string.IsNullOrEmpty(query)) { From 3745c444556c2edd818d11fc0a779b1e5215612f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 6 Jan 2026 20:11:36 +0800 Subject: [PATCH 102/124] Revert `Update the result when executing history item` --- Flow.Launcher/Storage/QueryHistory.cs | 23 ----------------------- Flow.Launcher/ViewModel/MainViewModel.cs | 6 ------ 2 files changed, 29 deletions(-) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 803591662..6af2a5908 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -86,29 +86,6 @@ namespace Flow.Launcher.Storage } } - /// - /// Update a result into the last-opened history list (). - /// - public void Update(Result result) - { - if (string.IsNullOrEmpty(result.OriginQuery.TrimmedQuery)) return; - // History results triggered from homepage do not contain PluginID, - // these are intentionally not saved otherwise cause duplicates due to subtitle - // containing datetime string. - if (string.IsNullOrEmpty(result.PluginID)) return; - - // If the last item is the same as the current result, just update the timestamp and the icon path - if (LastOpenedHistoryItems.Count > 0 && - TryGetLastOpenedHistoryResult(result, out var existingHistoryItem)) - { - existingHistoryItem.ExecutedDateTime = DateTime.Now; - if (existingHistoryItem.IcoPath != result.IcoPath) - { - existingHistoryItem.IcoPath = result.IcoPath; - } - } - } - /// /// Attempts to find an existing in /// that is considered equal to the supplied . diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 3d5c99edc..63710b5fc 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1373,12 +1373,6 @@ namespace Flow.Launcher.ViewModel var reflectResult = await ResultHelper.PopulateResultsAsync(item); if (reflectResult != null) { - // Record the user selected record for result ranking - _userSelectedRecord.Add(reflectResult); - - // Update the history with the reflected result - _history.Update(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); From 382a77d2c52ac6511a93b45ad0f0c1c608663d65 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 7 Jan 2026 13:40:13 +0800 Subject: [PATCH 103/124] Fix ShellPath directory for shell path selection Updated OpenShellPath to use Settings.ShellPath directory when prompting for a file path, ensuring the dialog opens in the relevant location instead of the editor path directory. --- .../ViewModels/SettingsViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 956c84db2..30c2c7f14 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -532,7 +532,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels [RelayCommand] private void OpenShellPath() { - var path = PromptUserSelectPath(ResultType.File, Settings.EditorPath != null ? Path.GetDirectoryName(Settings.EditorPath) : null); + var path = PromptUserSelectPath(ResultType.File, Settings.ShellPath != null ? Path.GetDirectoryName(Settings.ShellPath) : null); if (path is null) return; From 34257cad6077e0203bea23dee8a7ef225ca61518 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 06:27:26 +0000 Subject: [PATCH 104/124] Initial plan From 649b142b46b3c8f49b3c92f2a2b71a993e7e1f0b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 06:30:57 +0000 Subject: [PATCH 105/124] Add UseThousandsSeparator setting to Calculator plugin Co-authored-by: Jack251970 <53996452+Jack251970@users.noreply.github.com> --- Flow.Launcher.Test/Plugins/CalculatorTest.cs | 35 ++++++++++++++++++- .../Languages/en.xaml | 1 + .../Flow.Launcher.Plugin.Calculator/Main.cs | 2 +- .../Settings.cs | 2 ++ .../Views/CalculatorSettings.xaml | 11 ++++++ 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Test/Plugins/CalculatorTest.cs b/Flow.Launcher.Test/Plugins/CalculatorTest.cs index b075813db..8178cb712 100644 --- a/Flow.Launcher.Test/Plugins/CalculatorTest.cs +++ b/Flow.Launcher.Test/Plugins/CalculatorTest.cs @@ -16,7 +16,8 @@ namespace Flow.Launcher.Test.Plugins { DecimalSeparator = DecimalSeparator.UseSystemLocale, MaxDecimalPlaces = 10, - ShowErrorMessage = false // Make sure we return the empty results when error occurs + ShowErrorMessage = false, // Make sure we return the empty results when error occurs + UseThousandsSeparator = true // Default value }; private readonly Engine _engine = new(new Configuration { @@ -41,6 +42,38 @@ namespace Flow.Launcher.Test.Plugins engineField.SetValue(null, _engine); } + [Test] + public void ThousandsSeparatorTest_Enabled() + { + _settings.UseThousandsSeparator = true; + _settings.DecimalSeparator = DecimalSeparator.Dot; + + var result = GetCalculationResult("1000+234"); + // When thousands separator is enabled, the result should contain a separator (comma in this case) + ClassicAssert.IsTrue(result.Contains(",") || result == "1234", + "Expected result to contain thousands separator or be without one if system doesn't use it"); + } + + [Test] + public void ThousandsSeparatorTest_Disabled() + { + _settings.UseThousandsSeparator = false; + _settings.DecimalSeparator = DecimalSeparator.Dot; + + var result = GetCalculationResult("1000+234"); + ClassicAssert.AreEqual("1234", result); + } + + [Test] + public void ThousandsSeparatorTest_LargeNumber() + { + _settings.UseThousandsSeparator = false; + _settings.DecimalSeparator = DecimalSeparator.Dot; + + var result = GetCalculationResult("1000000+234567"); + ClassicAssert.AreEqual("1234567", result); + } + // Basic operations [TestCase(@"1+1", "2")] [TestCase(@"2-1", "1")] diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml index b12972b1b..4b9fd92b1 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml @@ -14,6 +14,7 @@ Comma (,) Dot (.) Max. decimal places + Use thousands separator Copy failed, please try later Show error message when calculation fails \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs index a20a1ad5d..1b9a38e18 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs @@ -363,7 +363,7 @@ namespace Flow.Launcher.Plugin.Calculator string integerPart = parts[0]; string fractionalPart = parts.Length > 1 ? parts[1] : string.Empty; - if (integerPart.Length > 3) + if (_settings.UseThousandsSeparator && integerPart.Length > 3) { integerPart = ThousandGroupRegex.Replace(integerPart, groupSeparator); } diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs index 1544dc41f..69cd17ed2 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs @@ -7,4 +7,6 @@ public class Settings public int MaxDecimalPlaces { get; set; } = 10; public bool ShowErrorMessage { get; set; } = false; + + public bool UseThousandsSeparator { get; set; } = true; } diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml index 9e7549b2d..82f8eec60 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml @@ -16,6 +16,7 @@ + @@ -66,6 +67,16 @@ Margin="{StaticResource SettingPanelItemTopBottomMargin}" HorizontalAlignment="Left" VerticalAlignment="Center" + Content="{DynamicResource flowlauncher_plugin_calculator_use_thousands_separator}" + IsChecked="{Binding Settings.UseThousandsSeparator, Mode=TwoWay}" /> + + From fb4da697a20aebb5c07ef88d765a7d0e509ee898 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 12 Jan 2026 11:37:06 +0800 Subject: [PATCH 106/124] Improve calculator thousands separator test --- Flow.Launcher.Test/Plugins/CalculatorTest.cs | 22 +++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Test/Plugins/CalculatorTest.cs b/Flow.Launcher.Test/Plugins/CalculatorTest.cs index 8178cb712..563bfa615 100644 --- a/Flow.Launcher.Test/Plugins/CalculatorTest.cs +++ b/Flow.Launcher.Test/Plugins/CalculatorTest.cs @@ -46,20 +46,26 @@ namespace Flow.Launcher.Test.Plugins public void ThousandsSeparatorTest_Enabled() { _settings.UseThousandsSeparator = true; + _settings.DecimalSeparator = DecimalSeparator.Dot; - var result = GetCalculationResult("1000+234"); - // When thousands separator is enabled, the result should contain a separator (comma in this case) - ClassicAssert.IsTrue(result.Contains(",") || result == "1234", - "Expected result to contain thousands separator or be without one if system doesn't use it"); + // When thousands separator is enabled, the result should contain a separator + // Since decimal separator is dot, thousands separator should be comma + ClassicAssert.AreEqual("1,234", result); + + _settings.DecimalSeparator = DecimalSeparator.Comma; + var result2 = GetCalculationResult("1000+234"); + // When thousands separator is enabled, the result should contain a separator + // Since decimal separator is comma, thousands separator should be dot + ClassicAssert.AreEqual("1.234", result2); } [Test] public void ThousandsSeparatorTest_Disabled() { _settings.UseThousandsSeparator = false; - _settings.DecimalSeparator = DecimalSeparator.Dot; - + _settings.DecimalSeparator = DecimalSeparator.UseSystemLocale; + var result = GetCalculationResult("1000+234"); ClassicAssert.AreEqual("1234", result); } @@ -68,8 +74,8 @@ namespace Flow.Launcher.Test.Plugins public void ThousandsSeparatorTest_LargeNumber() { _settings.UseThousandsSeparator = false; - _settings.DecimalSeparator = DecimalSeparator.Dot; - + _settings.DecimalSeparator = DecimalSeparator.UseSystemLocale; + var result = GetCalculationResult("1000000+234567"); ClassicAssert.AreEqual("1234567", result); } From 013622a2a784d19d7009e7238db61f7ed47a92fa Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 12 Jan 2026 11:37:47 +0800 Subject: [PATCH 107/124] Restore to default in calculator tests --- Flow.Launcher.Test/Plugins/CalculatorTest.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Test/Plugins/CalculatorTest.cs b/Flow.Launcher.Test/Plugins/CalculatorTest.cs index 563bfa615..40c7ab29c 100644 --- a/Flow.Launcher.Test/Plugins/CalculatorTest.cs +++ b/Flow.Launcher.Test/Plugins/CalculatorTest.cs @@ -22,9 +22,9 @@ namespace Flow.Launcher.Test.Plugins private readonly Engine _engine = new(new Configuration { Scope = new Dictionary - { - { "e", Math.E }, // e is not contained in the default mages engine - } + { + { "e", Math.E }, // e is not contained in the default mages engine + } }); public CalculatorPluginTest() @@ -116,6 +116,9 @@ namespace Flow.Launcher.Test.Plugins [TestCase(@"invalid_expression", "")] public void CalculatorTest(string expression, string result) { + _settings.UseThousandsSeparator = false; + _settings.DecimalSeparator = DecimalSeparator.UseSystemLocale; + ClassicAssert.AreEqual(GetCalculationResult(expression), result); } From 7e7f85352b23e68e82da7e46683bea2f1f2dc7fe Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Mon, 12 Jan 2026 14:13:01 +0800 Subject: [PATCH 108/124] Fix potential locale-dependent test failure Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Flow.Launcher.Test/Plugins/CalculatorTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Test/Plugins/CalculatorTest.cs b/Flow.Launcher.Test/Plugins/CalculatorTest.cs index 40c7ab29c..4e40d3645 100644 --- a/Flow.Launcher.Test/Plugins/CalculatorTest.cs +++ b/Flow.Launcher.Test/Plugins/CalculatorTest.cs @@ -117,7 +117,7 @@ namespace Flow.Launcher.Test.Plugins public void CalculatorTest(string expression, string result) { _settings.UseThousandsSeparator = false; - _settings.DecimalSeparator = DecimalSeparator.UseSystemLocale; + _settings.DecimalSeparator = DecimalSeparator.Dot; ClassicAssert.AreEqual(GetCalculationResult(expression), result); } From ed83da56690ce35ddacaed286082657a9b81d80f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 03:05:02 +0000 Subject: [PATCH 109/124] Bump Svg.Skia from 3.4.0 to 3.4.1 --- updated-dependencies: - dependency-name: Svg.Skia dependency-version: 3.4.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../Flow.Launcher.Plugin.BrowserBookmark.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 1df65c2eb..8c41f200e 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -106,7 +106,7 @@ - + From e970bb4d4e6764ad669ba2bb11776bb0d2fb2d4a Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 13 Jan 2026 23:32:13 +1100 Subject: [PATCH 110/124] fix icon & glyph display based on selected history style results --- .../Storage/LastOpenedHistoryResult.cs | 47 +++++++++++++++---- Flow.Launcher/Storage/QueryHistory.cs | 3 -- Flow.Launcher/ViewModel/MainViewModel.cs | 26 +--------- 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs index b71282f14..7f571b768 100644 --- a/Flow.Launcher/Storage/LastOpenedHistoryResult.cs +++ b/Flow.Launcher/Storage/LastOpenedHistoryResult.cs @@ -1,4 +1,5 @@ using System; +using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin; namespace Flow.Launcher.Storage; @@ -56,24 +57,54 @@ public class LastOpenedHistoryResult : Result } /// - /// Selectively creates a deep copy of the required properties for . + /// Selectively creates a deep copy of the required properties for + /// based on the style of history- Last Opened or Query. /// This copy should be independent of original and full isolated. /// /// A new containing the same required data. - public LastOpenedHistoryResult DeepCopy() + public LastOpenedHistoryResult DeepCopyForHistoryStyle(bool isHistoryStyleLastOpened) { // queryValue and glyphValue are captured to ensure they are correctly referenced in the Action delegate. var queryValue = Query; var glyphValue = Glyph; + + var title = string.Empty; + var showBadge = false; + var badgeIcoPath = string.Empty; + var icoPath = string.Empty; + var glyph = null as GlyphInfo; + + if (isHistoryStyleLastOpened) + { + title = Title; + icoPath = IcoPath; + glyph = glyphValue != null + ? new GlyphInfo(glyphValue.FontFamily, glyphValue.Glyph) + : null; + showBadge = true; + badgeIcoPath = Constant.HistoryIcon; + } + else + { + title = Localize.executeQuery(Query); + icoPath = Constant.HistoryIcon; + glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C"); + showBadge = false; + } + return new LastOpenedHistoryResult { - Title = Title, - SubTitle = SubTitle, - PluginID = PluginID, + Title = title, + // Subtitle has datetime which can cause duplicates when saving. + SubTitle = Localize.lastExecuteTime(ExecutedDateTime), + // Empty PluginID so the source of last opened history results won't be updated, this copy is meant to be temporary. + PluginID = string.Empty, Query = Query, OriginQuery = new Query { TrimmedQuery = Query }, RecordKey = RecordKey, - IcoPath = IcoPath, + IcoPath = icoPath, + ShowBadge = showBadge, + BadgeIcoPath = badgeIcoPath, PluginDirectory = PluginDirectory, // Used for Query History style reopening Action = _ => @@ -84,9 +115,7 @@ public class LastOpenedHistoryResult : Result }, // Used for Last Opened History style reopening, currently need to be assigned at MainViewModel.cs AsyncAction = null, - Glyph = glyphValue != null - ? new GlyphInfo(glyphValue.FontFamily, glyphValue.Glyph) - : null, + Glyph = glyph, ExecutedDateTime = ExecutedDateTime // Note: Other properties are left as default — copy if needed. }; diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 6af2a5908..91dee90df 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Text.Json.Serialization; using Flow.Launcher.Core.Plugin; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin; namespace Flow.Launcher.Storage @@ -35,9 +34,7 @@ namespace Flow.Launcher.Storage LastOpenedHistoryItems.Add(new LastOpenedHistoryResult { Title = Localize.executeQuery(item.Query), - IcoPath = null, OriginQuery = new Query { TrimmedQuery = item.Query }, - Glyph = null, Query = item.Query, Action = _ => { diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 63710b5fc..504ede103 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; @@ -1340,30 +1339,7 @@ namespace Flow.Launcher.ViewModel foreach (var item in historyItems) { - var copiedItem = item.DeepCopy(); - - if (Settings.HistoryStyle == HistoryStyle.Query) - { - copiedItem.Title = Localize.executeQuery(copiedItem.Query); - copiedItem.IcoPath = Constant.HistoryIcon; - // TODO: Add Glyph here - // copiedItem.Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uE81C"); - } - else - { - if (string.IsNullOrEmpty(copiedItem.IcoPath)) // Must manually set missing image icon here - { - copiedItem.IcoPath = Constant.MissingImgIcon; - } - copiedItem.ShowBadge = true; - copiedItem.BadgeIcoPath = Constant.HistoryIcon; - } - - // Subtitle has datetime which can cause duplicates when saving. - copiedItem.SubTitle = Localize.lastExecuteTime(copiedItem.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; + var copiedItem = item.DeepCopyForHistoryStyle(Settings.HistoryStyle == HistoryStyle.LastOpened); if (Settings.HistoryStyle == HistoryStyle.LastOpened) { From 98bb98c2650672f9d19d7ded72c29c1a180df46f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 22:45:07 +0000 Subject: [PATCH 111/124] Bump Microsoft.Data.Sqlite from 10.0.1 to 10.0.2 --- updated-dependencies: - dependency-name: Microsoft.Data.Sqlite dependency-version: 10.0.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../Flow.Launcher.Plugin.BrowserBookmark.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 1df65c2eb..ed956cb18 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -105,7 +105,7 @@ - + From 91cd27298d341cc3277f5daf72e3de08cbdcd733 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 22:45:22 +0000 Subject: [PATCH 112/124] Bump Microsoft.SourceLink.GitHub from 8.0.0 to 10.0.102 --- updated-dependencies: - dependency-name: Microsoft.SourceLink.GitHub dependency-version: 10.0.102 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .../Flow.Launcher.Plugin.csproj | 2 +- Flow.Launcher.Plugin/packages.lock.json | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj index 649d59ad7..103a72113 100644 --- a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj +++ b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj @@ -72,7 +72,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all diff --git a/Flow.Launcher.Plugin/packages.lock.json b/Flow.Launcher.Plugin/packages.lock.json index 70f71f20d..3240b3981 100644 --- a/Flow.Launcher.Plugin/packages.lock.json +++ b/Flow.Launcher.Plugin/packages.lock.json @@ -16,12 +16,12 @@ }, "Microsoft.SourceLink.GitHub": { "type": "Direct", - "requested": "[8.0.0, )", - "resolved": "8.0.0", - "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", + "requested": "[10.0.102, )", + "resolved": "10.0.102", + "contentHash": "Oxq3RCIJSdtpIU4hLqO7XaDe/Ra3HS9Wi8rJl838SAg6Zu1iQjerA0+xXWBgUFYbgknUGCLOU0T+lzMLkvY9Qg==", "dependencies": { - "Microsoft.Build.Tasks.Git": "8.0.0", - "Microsoft.SourceLink.Common": "8.0.0" + "Microsoft.Build.Tasks.Git": "10.0.102", + "Microsoft.SourceLink.Common": "10.0.102" } }, "Microsoft.Windows.CsWin32": { @@ -46,13 +46,13 @@ }, "Microsoft.Build.Tasks.Git": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" + "resolved": "10.0.102", + "contentHash": "0i81LYX31U6UiXz4NOLbvc++u+/mVDmOt+PskrM/MygpDxkv9THKQyRUmavBpLK6iBV0abNWnn+CQgSRz//Pwg==" }, "Microsoft.SourceLink.Common": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" + "resolved": "10.0.102", + "contentHash": "Mk1IMb9q5tahC2NltxYXFkLBtuBvfBoCQ3pIxYQWfzbCE9o1OB9SsHe0hnNGo7lWgTA/ePbFAJLWu6nLL9K17A==" }, "Microsoft.Windows.SDK.Win32Docs": { "type": "Transitive", From befcc9b37c40e469120483ee296eaad2950e4626 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 17 Jan 2026 19:59:47 +0800 Subject: [PATCH 113/124] Update Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml --- Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml index 4b9fd92b1..5f9a3ca5a 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml @@ -14,7 +14,7 @@ Comma (,) Dot (.) Max. decimal places - Use thousands separator + Show thousands separator in results Copy failed, please try later Show error message when calculation fails \ No newline at end of file From 90360022a4772b742ad4d86e1f629697dd981692 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Jan 2026 21:26:04 +1100 Subject: [PATCH 114/124] update glyph when history result exists --- Flow.Launcher.Plugin/Result.cs | 4 ++-- Flow.Launcher/Storage/QueryHistory.cs | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 78fa31974..1682c4d79 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -167,7 +167,7 @@ namespace Flow.Launcher.Plugin /// /// Information for Glyph Icon (Prioritized than IcoPath/Icon if user enable Glyph Icons) /// - public GlyphInfo Glyph { get; init; } + public GlyphInfo Glyph { get; set; } /// /// An action to take in the form of a function call when the result has been selected. diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 91dee90df..093db0a58 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text.Json.Serialization; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Plugin; +using Svg; namespace Flow.Launcher.Storage { @@ -72,10 +73,13 @@ namespace Flow.Launcher.Storage TryGetLastOpenedHistoryResult(result, out var existingHistoryItem)) { existingHistoryItem.ExecutedDateTime = DateTime.Now; + if (existingHistoryItem.IcoPath != result.IcoPath) - { existingHistoryItem.IcoPath = result.IcoPath; - } + + if (existingHistoryItem.Glyph.Glyph != result.Glyph.Glyph + || existingHistoryItem.Glyph.FontFamily != result.Glyph.FontFamily) + existingHistoryItem.Glyph = result.Glyph; } else { From 5c241d7491f4d638dff327ea4c1bf3ff9a513db8 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Jan 2026 21:47:38 +1100 Subject: [PATCH 115/124] fix to respect max history result shown setting --- Flow.Launcher/ViewModel/MainViewModel.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 504ede103..b51a8f8cf 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1316,19 +1316,13 @@ namespace Flow.Launcher.ViewModel } } - private List GetHistoryItems(IEnumerable historyItems, int? selectLast = null) + private List GetHistoryItems(IEnumerable historyItems, int? maxResult = null) { var results = new List(); // Order by executed time descending: Latest -> Oldest historyItems = historyItems.OrderByDescending(x => x.ExecutedDateTime); - // Select the last N items if specified - if (selectLast.HasValue) - { - historyItems = historyItems.Take(selectLast.Value); - } - if (Settings.HistoryStyle == HistoryStyle.LastOpened) { // Items saved to disk are differentiated by Query also, but LastOpened style only cares about unique results @@ -1337,6 +1331,10 @@ namespace Flow.Launcher.ViewModel .Select(g => g.First()); } + // Max history results to return for display + if (maxResult.HasValue) + historyItems = historyItems.Take(maxResult.Value); + foreach (var item in historyItems) { var copiedItem = item.DeepCopyForHistoryStyle(Settings.HistoryStyle == HistoryStyle.LastOpened); From 4ddb164bbdd18b33ac44c0eb1d9266af1a87f44d Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Jan 2026 22:48:11 +1100 Subject: [PATCH 116/124] adjusted context menu call to exit early when history result selected --- Flow.Launcher/ViewModel/MainViewModel.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index b51a8f8cf..f6e289a31 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -429,16 +429,17 @@ namespace Flow.Launcher.ViewModel return; } + // Do not show context menu for history results, they will have no PluginID set. + if (string.IsNullOrEmpty(SelectedResults.SelectedItem?.Result?.PluginID)) + return; + // For query mode, we load context menu if (QueryResultsSelected()) { // When switch to ContextMenu from QueryResults, but no item being chosen, should do nothing // i.e. Shift+Enter/Ctrl+O right after Alt + Space should do nothing - if (SelectedResults.SelectedItem?.Result != null && - !string.IsNullOrEmpty(SelectedResults.SelectedItem.Result.PluginID)) // Do not show context menu for history items - { + if (SelectedResults.SelectedItem?.Result != null) SelectedResults = ContextMenu; - } } else { @@ -1260,8 +1261,7 @@ namespace Flow.Launcher.ViewModel var selected = Results.SelectedItem?.Result; - if (selected != null && // SelectedItem returns null if selection is empty. - !string.IsNullOrEmpty(selected.PluginID)) // SelectedItem must have a valid PluginID + if (selected != null) // SelectedItem returns null if selection is empty. { List results = PluginManager.GetContextMenusForPlugin(selected); results.Add(ContextMenuTopMost(selected)); From 657e6ae7d3d7fdb9a1fbba3305b91308e076bee4 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Jan 2026 22:55:04 +1100 Subject: [PATCH 117/124] add null-safe comparison for glyph --- Flow.Launcher/Storage/QueryHistory.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 093db0a58..26dead008 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -77,8 +77,8 @@ namespace Flow.Launcher.Storage if (existingHistoryItem.IcoPath != result.IcoPath) existingHistoryItem.IcoPath = result.IcoPath; - if (existingHistoryItem.Glyph.Glyph != result.Glyph.Glyph - || existingHistoryItem.Glyph.FontFamily != result.Glyph.FontFamily) + if (existingHistoryItem.Glyph?.Glyph != result.Glyph?.Glyph + || existingHistoryItem.Glyph?.FontFamily != result.Glyph?.FontFamily) existingHistoryItem.Glyph = result.Glyph; } else From bf44637400f9551758754f3cd71edf8a8e55df5a Mon Sep 17 00:00:00 2001 From: Jeremy Date: Tue, 20 Jan 2026 23:18:00 +1100 Subject: [PATCH 118/124] revert context menu early exit when history result --- Flow.Launcher/ViewModel/MainViewModel.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index f6e289a31..f93aef5a6 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -429,17 +429,16 @@ namespace Flow.Launcher.ViewModel return; } - // Do not show context menu for history results, they will have no PluginID set. - if (string.IsNullOrEmpty(SelectedResults.SelectedItem?.Result?.PluginID)) - return; - // For query mode, we load context menu if (QueryResultsSelected()) { // When switch to ContextMenu from QueryResults, but no item being chosen, should do nothing // i.e. Shift+Enter/Ctrl+O right after Alt + Space should do nothing - if (SelectedResults.SelectedItem?.Result != null) + if (SelectedResults.SelectedItem?.Result != null && + !string.IsNullOrEmpty(SelectedResults.SelectedItem.Result.PluginID)) // Do not show context menu for history results + { SelectedResults = ContextMenu; + } } else { @@ -1261,7 +1260,8 @@ namespace Flow.Launcher.ViewModel var selected = Results.SelectedItem?.Result; - if (selected != null) // SelectedItem returns null if selection is empty. + if (selected != null && // SelectedItem returns null if selection is empty. + !string.IsNullOrEmpty(selected.PluginID)) // SelectedItem must have a valid PluginID, history results do not. { List results = PluginManager.GetContextMenusForPlugin(selected); results.Add(ContextMenuTopMost(selected)); From 8e127d033955013517ed57cb32777e1579146181 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 21 Jan 2026 18:13:27 +0800 Subject: [PATCH 119/124] Code cleanup --- Flow.Launcher/Storage/QueryHistory.cs | 1 - Flow.Launcher/ViewModel/MainViewModel.cs | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 26dead008..0f4d97677 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Text.Json.Serialization; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Plugin; -using Svg; namespace Flow.Launcher.Storage { diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index f93aef5a6..3b04d6f12 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1333,7 +1333,9 @@ namespace Flow.Launcher.ViewModel // Max history results to return for display if (maxResult.HasValue) + { historyItems = historyItems.Take(maxResult.Value); + } foreach (var item in historyItems) { From b703bcdd52c72103b7dbe794fe171dfd8a8c08f7 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 23 Jan 2026 15:51:24 +0800 Subject: [PATCH 120/124] Try to fix combability issue --- Flow.Launcher.Plugin/Result.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 1682c4d79..137ec4892 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -164,10 +164,16 @@ namespace Flow.Launcher.Plugin [JsonIgnore] public IconDelegate BadgeIcon = null; + private GlyphInfo _glyph; + /// /// Information for Glyph Icon (Prioritized than IcoPath/Icon if user enable Glyph Icons) /// - public GlyphInfo Glyph { get; set; } + public GlyphInfo Glyph + { + get => _glyph; + set => _glyph = value; + } /// /// An action to take in the form of a function call when the result has been selected. From 0f0ee9ffde013b3598b8ea83f304a9b5701ccc45 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 23 Jan 2026 16:05:03 +0800 Subject: [PATCH 121/124] Revert "Try to fix combability issue" This reverts commit b703bcdd52c72103b7dbe794fe171dfd8a8c08f7. --- Flow.Launcher.Plugin/Result.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 137ec4892..1682c4d79 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -164,16 +164,10 @@ namespace Flow.Launcher.Plugin [JsonIgnore] public IconDelegate BadgeIcon = null; - private GlyphInfo _glyph; - /// /// Information for Glyph Icon (Prioritized than IcoPath/Icon if user enable Glyph Icons) /// - public GlyphInfo Glyph - { - get => _glyph; - set => _glyph = value; - } + public GlyphInfo Glyph { get; set; } /// /// An action to take in the form of a function call when the result has been selected. From 935d41dc265972c433f599a5fbfdff0acd798542 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 23 Jan 2026 16:10:01 +0800 Subject: [PATCH 122/124] Ensure combability of glyph setter --- Flow.Launcher.Plugin/Result.cs | 19 +++++++++++++++++-- Flow.Launcher/Storage/QueryHistory.cs | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 1682c4d79..e944081f9 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -164,10 +164,25 @@ namespace Flow.Launcher.Plugin [JsonIgnore] public IconDelegate BadgeIcon = null; + private GlyphInfo _glyph; + /// /// Information for Glyph Icon (Prioritized than IcoPath/Icon if user enable Glyph Icons) /// - public GlyphInfo Glyph { get; set; } + public GlyphInfo Glyph + { + get => _glyph; + init => _glyph = value; + } + + /// + /// Set the Glyph Icon + /// + /// + public void SetGlyph(GlyphInfo glyph) + { + _glyph = glyph; + } /// /// An action to take in the form of a function call when the result has been selected. diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index 0f4d97677..7bf948399 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -78,7 +78,7 @@ namespace Flow.Launcher.Storage if (existingHistoryItem.Glyph?.Glyph != result.Glyph?.Glyph || existingHistoryItem.Glyph?.FontFamily != result.Glyph?.FontFamily) - existingHistoryItem.Glyph = result.Glyph; + existingHistoryItem.SetGlyph(result.Glyph); } else { From e9dcd8b7ba36f51a0690de9d500e6f3f241ea289 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Fri, 23 Jan 2026 16:15:25 +0800 Subject: [PATCH 123/124] Fix code comments Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Flow.Launcher.Plugin/Result.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index e944081f9..e0c5d494e 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -69,7 +69,7 @@ namespace Flow.Launcher.Plugin /// /// Path or URI to the icon image for this result. - /// Updates appropriately when set. + /// Updates appropriately when set. /// /// /// Preferred usage: provide a path relative to the plugin directory (for example: "Images\icon.png"). From 248da93d05120dbe8b99db9afca35eff893f3d9b Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 26 Jan 2026 16:57:47 +1100 Subject: [PATCH 124/124] fix preview when toggle history mode via Ctrl + H --- Flow.Launcher.Plugin/Result.cs | 2 +- Flow.Launcher/ViewModel/MainViewModel.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index e0c5d494e..9404d1107 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -176,7 +176,7 @@ namespace Flow.Launcher.Plugin } /// - /// Set the Glyph Icon + /// Set the Glyph Icon after initialization /// /// public void SetGlyph(GlyphInfo glyph) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 3b04d6f12..ba170feb0 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -363,6 +363,8 @@ namespace Flow.Launcher.ViewModel else { SelectedResults = Results; + PreviewSelectedItem = Results.SelectedItem; + _ = UpdatePreviewAsync(); } }