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; } }