mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Add locks for win32s & uwps
This commit is contained in:
parent
9f84a2d50a
commit
7da2884e84
3 changed files with 83 additions and 30 deletions
|
|
@ -27,6 +27,9 @@ namespace Flow.Launcher.Plugin.Program
|
|||
internal static List<UWPApp> _uwps { get; private set; }
|
||||
internal static Settings _settings { get; private set; }
|
||||
|
||||
internal static SemaphoreSlim _win32sLock = new(1, 1);
|
||||
internal static SemaphoreSlim _uwpsLock = new(1, 1);
|
||||
|
||||
internal static PluginInitContext Context { get; private set; }
|
||||
|
||||
private static readonly List<Result> emptyResults = new();
|
||||
|
|
@ -82,8 +85,11 @@ namespace Flow.Launcher.Plugin.Program
|
|||
{
|
||||
var result = await cache.GetOrCreateAsync(query.Search, async entry =>
|
||||
{
|
||||
var resultList = await Task.Run(() =>
|
||||
var resultList = await Task.Run(async () =>
|
||||
{
|
||||
await _win32sLock.WaitAsync(token);
|
||||
await _uwpsLock.WaitAsync(token);
|
||||
|
||||
try
|
||||
{
|
||||
// Collect all UWP Windows app directories
|
||||
|
|
@ -95,22 +101,26 @@ namespace Flow.Launcher.Plugin.Program
|
|||
.ToArray() : null;
|
||||
|
||||
return _win32s.Cast<IProgram>()
|
||||
.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 => r?.Score > 0)
|
||||
.ToList();
|
||||
.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 => r?.Score > 0)
|
||||
.ToList();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
Log.Debug("|Flow.Launcher.Plugin.Program.Main|Query operation cancelled");
|
||||
return emptyResults;
|
||||
}
|
||||
|
||||
finally
|
||||
{
|
||||
_uwpsLock.Release();
|
||||
_win32sLock.Release();
|
||||
}
|
||||
}, token);
|
||||
|
||||
resultList = resultList.Any() ? resultList : emptyResults;
|
||||
|
|
@ -236,14 +246,25 @@ namespace Flow.Launcher.Plugin.Program
|
|||
var newUWPCacheFile = Path.Combine(pluginCachePath, $"{UwpCacheName}.cache");
|
||||
MoveFile(oldUWPCacheFile, newUWPCacheFile);
|
||||
|
||||
await _win32sLock.WaitAsync();
|
||||
_win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List<Win32>());
|
||||
_win32sLock.Release();
|
||||
|
||||
await _uwpsLock.WaitAsync();
|
||||
_uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List<UWPApp>());
|
||||
_uwpsLock.Release();
|
||||
});
|
||||
await _win32sLock.WaitAsync();
|
||||
await _uwpsLock.WaitAsync();
|
||||
|
||||
Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Count}>");
|
||||
Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Count}>");
|
||||
|
||||
bool cacheEmpty = !_win32s.Any() || !_uwps.Any();
|
||||
|
||||
_win32sLock.Release();
|
||||
_uwpsLock.Release();
|
||||
|
||||
if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now)
|
||||
{
|
||||
_ = Task.Run(async () =>
|
||||
|
|
@ -267,11 +288,13 @@ namespace Flow.Launcher.Plugin.Program
|
|||
public static async Task IndexWin32ProgramsAsync()
|
||||
{
|
||||
var win32S = Win32.All(_settings);
|
||||
await _win32sLock.WaitAsync();
|
||||
_win32s.Clear();
|
||||
foreach (var win32 in win32S)
|
||||
{
|
||||
_win32s.Add(win32);
|
||||
}
|
||||
_win32sLock.Release();
|
||||
ResetCache();
|
||||
await Context.API.SaveCacheBinaryStorageAsync<List<Win32>>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
|
||||
_settings.LastIndexTime = DateTime.Now;
|
||||
|
|
@ -280,11 +303,13 @@ namespace Flow.Launcher.Plugin.Program
|
|||
public static async Task IndexUwpProgramsAsync()
|
||||
{
|
||||
var uwps = UWPPackage.All(_settings);
|
||||
await _uwpsLock.WaitAsync();
|
||||
_uwps.Clear();
|
||||
foreach (var uwp in uwps)
|
||||
{
|
||||
_uwps.Add(uwp);
|
||||
}
|
||||
_uwpsLock.Release();
|
||||
ResetCache();
|
||||
await Context.API.SaveCacheBinaryStorageAsync<List<UWPApp>>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
|
||||
_settings.LastIndexTime = DateTime.Now;
|
||||
|
|
@ -358,26 +383,36 @@ namespace Flow.Launcher.Plugin.Program
|
|||
return menuOptions;
|
||||
}
|
||||
|
||||
private static void DisableProgram(IProgram programToDelete)
|
||||
private static async Task DisableProgram(IProgram programToDelete)
|
||||
{
|
||||
if (_settings.DisabledProgramSources.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
|
||||
return;
|
||||
|
||||
await _uwpsLock.WaitAsync();
|
||||
if (_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));
|
||||
_uwpsLock.Release();
|
||||
|
||||
// Reindex UWP programs
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
_ = IndexUwpProgramsAsync();
|
||||
});
|
||||
return;
|
||||
}
|
||||
else if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
|
||||
|
||||
await _win32sLock.WaitAsync();
|
||||
if (_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));
|
||||
_win32sLock.Release();
|
||||
|
||||
// Reindex Win32 programs
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
_ = IndexWin32ProgramsAsync();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Flow.Launcher.Plugin.Program.Views.Models;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Program.Views.Commands
|
||||
|
|
@ -15,21 +16,24 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands
|
|||
.ToList();
|
||||
}
|
||||
|
||||
internal static void DisplayAllPrograms()
|
||||
internal static async Task DisplayAllProgramsAsync()
|
||||
{
|
||||
await Main._win32sLock.WaitAsync();
|
||||
var win32 = Main._win32s
|
||||
.Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
|
||||
.Select(x => new ProgramSource(x));
|
||||
ProgramSetting.ProgramSettingDisplayList.AddRange(win32);
|
||||
Main._win32sLock.Release();
|
||||
|
||||
await Main._uwpsLock.WaitAsync();
|
||||
var uwp = Main._uwps
|
||||
.Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier))
|
||||
.Select(x => new ProgramSource(x));
|
||||
|
||||
ProgramSetting.ProgramSettingDisplayList.AddRange(win32);
|
||||
ProgramSetting.ProgramSettingDisplayList.AddRange(uwp);
|
||||
Main._uwpsLock.Release();
|
||||
}
|
||||
|
||||
internal static void SetProgramSourcesStatus(List<ProgramSource> selectedProgramSourcesToDisable, bool status)
|
||||
internal static async Task SetProgramSourcesStatusAsync(List<ProgramSource> selectedProgramSourcesToDisable, bool status)
|
||||
{
|
||||
foreach(var program in ProgramSetting.ProgramSettingDisplayList)
|
||||
{
|
||||
|
|
@ -39,14 +43,17 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands
|
|||
}
|
||||
}
|
||||
|
||||
foreach(var program in Main._win32s)
|
||||
await Main._win32sLock.WaitAsync();
|
||||
foreach (var program in Main._win32s)
|
||||
{
|
||||
if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status))
|
||||
{
|
||||
program.Enabled = status;
|
||||
}
|
||||
}
|
||||
Main._win32sLock.Release();
|
||||
|
||||
await Main._uwpsLock.WaitAsync();
|
||||
foreach (var program in Main._uwps)
|
||||
{
|
||||
if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status))
|
||||
|
|
@ -54,6 +61,7 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands
|
|||
program.Enabled = status;
|
||||
}
|
||||
}
|
||||
Main._uwpsLock.Release();
|
||||
}
|
||||
|
||||
internal static void StoreDisabledInSettings()
|
||||
|
|
@ -72,12 +80,22 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands
|
|||
Main._settings.DisabledProgramSources.RemoveAll(t1 => t1.Enabled);
|
||||
}
|
||||
|
||||
internal static bool IsReindexRequired(this List<ProgramSource> selectedItems)
|
||||
internal static async Task<bool> IsReindexRequiredAsync(this List<ProgramSource> selectedItems)
|
||||
{
|
||||
// Not in cache
|
||||
if (selectedItems.Any(t1 => t1.Enabled && !Main._uwps.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier))
|
||||
await Main._win32sLock.WaitAsync();
|
||||
await Main._uwpsLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
if (selectedItems.Any(t1 => t1.Enabled && !Main._uwps.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier))
|
||||
&& selectedItems.Any(t1 => t1.Enabled && !Main._win32s.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier)))
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Main._win32sLock.Release();
|
||||
Main._uwpsLock.Release();
|
||||
}
|
||||
|
||||
// ProgramSources holds list of user added directories,
|
||||
// so when we enable/disable we need to reindex to show/not show the programs
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
EditProgramSource(selectedProgramSource);
|
||||
}
|
||||
|
||||
private void EditProgramSource(ProgramSource selectedProgramSource)
|
||||
private async void EditProgramSource(ProgramSource selectedProgramSource)
|
||||
{
|
||||
if (selectedProgramSource == null)
|
||||
{
|
||||
|
|
@ -202,13 +202,13 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
{
|
||||
if (selectedProgramSource.Enabled)
|
||||
{
|
||||
ProgramSettingDisplay.SetProgramSourcesStatus(new List<ProgramSource> { selectedProgramSource },
|
||||
await ProgramSettingDisplay.SetProgramSourcesStatusAsync(new List<ProgramSource> { selectedProgramSource },
|
||||
true); // sync status in win32, uwp and disabled
|
||||
ProgramSettingDisplay.RemoveDisabledFromSettings();
|
||||
}
|
||||
else
|
||||
{
|
||||
ProgramSettingDisplay.SetProgramSourcesStatus(new List<ProgramSource> { selectedProgramSource },
|
||||
await ProgramSettingDisplay.SetProgramSourcesStatusAsync(new List<ProgramSource> { selectedProgramSource },
|
||||
false);
|
||||
ProgramSettingDisplay.StoreDisabledInSettings();
|
||||
}
|
||||
|
|
@ -277,14 +277,14 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
}
|
||||
}
|
||||
|
||||
private void btnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e)
|
||||
private async void btnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ProgramSettingDisplay.DisplayAllPrograms();
|
||||
await ProgramSettingDisplay.DisplayAllProgramsAsync();
|
||||
|
||||
ViewRefresh();
|
||||
}
|
||||
|
||||
private void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e)
|
||||
private async void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var selectedItems = programSourceView
|
||||
.SelectedItems.Cast<ProgramSource>()
|
||||
|
|
@ -311,18 +311,18 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
}
|
||||
else if (HasMoreOrEqualEnabledItems(selectedItems))
|
||||
{
|
||||
ProgramSettingDisplay.SetProgramSourcesStatus(selectedItems, false);
|
||||
await ProgramSettingDisplay.SetProgramSourcesStatusAsync(selectedItems, false);
|
||||
|
||||
ProgramSettingDisplay.StoreDisabledInSettings();
|
||||
}
|
||||
else
|
||||
{
|
||||
ProgramSettingDisplay.SetProgramSourcesStatus(selectedItems, true);
|
||||
await ProgramSettingDisplay.SetProgramSourcesStatusAsync(selectedItems, true);
|
||||
|
||||
ProgramSettingDisplay.RemoveDisabledFromSettings();
|
||||
}
|
||||
|
||||
if (selectedItems.IsReindexRequired())
|
||||
if (await selectedItems.IsReindexRequiredAsync())
|
||||
ReIndexing();
|
||||
|
||||
programSourceView.SelectedItems.Clear();
|
||||
|
|
|
|||
Loading…
Reference in a new issue