Skip to content

Commit bb1dfcd

Browse files
authored
Fix hide item option not working in Program plugin (#4141)
1 parent 1594683 commit bb1dfcd

3 files changed

Lines changed: 73 additions & 43 deletions

File tree

Plugins/Flow.Launcher.Plugin.Program/Main.cs

Lines changed: 70 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ static void WatchProgramUpdate()
334334
}
335335
}
336336

337-
public static async Task IndexWin32ProgramsAsync()
337+
public static async Task IndexWin32ProgramsAsync(bool resetCache)
338338
{
339339
await _win32sLock.WaitAsync();
340340
try
@@ -345,7 +345,10 @@ public static async Task IndexWin32ProgramsAsync()
345345
{
346346
_win32s.Add(win32);
347347
}
348-
ResetCache();
348+
if (resetCache)
349+
{
350+
ResetCache();
351+
}
349352
await Context.API.SaveCacheBinaryStorageAsync<List<Win32>>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
350353
lock (_lastIndexTimeLock)
351354
{
@@ -362,7 +365,7 @@ public static async Task IndexWin32ProgramsAsync()
362365
}
363366
}
364367

365-
public static async Task IndexUwpProgramsAsync()
368+
public static async Task IndexUwpProgramsAsync(bool resetCache)
366369
{
367370
await _uwpsLock.WaitAsync();
368371
try
@@ -373,7 +376,10 @@ public static async Task IndexUwpProgramsAsync()
373376
{
374377
_uwps.Add(uwp);
375378
}
376-
ResetCache();
379+
if (resetCache)
380+
{
381+
ResetCache();
382+
}
377383
await Context.API.SaveCacheBinaryStorageAsync<List<UWPApp>>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath);
378384
lock (_lastIndexTimeLock)
379385
{
@@ -394,22 +400,34 @@ public static async Task IndexProgramsAsync()
394400
{
395401
var win32Task = Task.Run(async () =>
396402
{
397-
await Context.API.StopwatchLogInfoAsync(ClassName, "Win32Program index cost", IndexWin32ProgramsAsync);
403+
await Context.API.StopwatchLogInfoAsync(ClassName, "Win32Program index cost", () => IndexWin32ProgramsAsync(resetCache: true));
398404
});
399405

400406
var uwpTask = Task.Run(async () =>
401407
{
402-
await Context.API.StopwatchLogInfoAsync(ClassName, "UWPProgram index cost", IndexUwpProgramsAsync);
408+
await Context.API.StopwatchLogInfoAsync(ClassName, "UWPProgram index cost", () => IndexUwpProgramsAsync(resetCache: true));
403409
});
404410

405411
await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false);
406412
}
407413

408414
internal static void ResetCache()
409415
{
410-
var oldCache = cache;
411-
cache = new MemoryCache(cacheOptions);
412-
oldCache.Dispose();
416+
var newCache = new MemoryCache(cacheOptions);
417+
418+
// Atomically swap and get the previous cache instance, avoids double-dispose/lost-assignment race
419+
// where each caller receives a distinct prior instance to dispose.
420+
var oldCache = Interlocked.Exchange(ref cache, newCache);
421+
422+
// Dispose the previous instance (if any)- each caller gets a unique prior instance from above
423+
try
424+
{
425+
oldCache?.Dispose();
426+
}
427+
catch (Exception e)
428+
{
429+
Context.API.LogException(ClassName, "Failed to dispose old program cache", e);
430+
}
413431
}
414432

415433
public Control CreateSettingPanel()
@@ -442,12 +460,26 @@ public List<Result> LoadContextMenus(Result selectedResult)
442460
Title = Context.API.GetTranslation("flowlauncher_plugin_program_disable_program"),
443461
Action = c =>
444462
{
445-
_ = DisableProgramAsync(program);
446-
Context.API.ShowMsg(
447-
Context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_success"),
448-
Context.API.GetTranslation(
449-
"flowlauncher_plugin_program_disable_dlgtitle_success_message"));
450-
Context.API.ReQuery();
463+
_ = Task.Run(async () =>
464+
{
465+
try
466+
{
467+
var disabled = await DisableProgramAsync(program);
468+
if (disabled)
469+
{
470+
ResetCache();
471+
Context.API.ShowMsg(
472+
Context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_success"),
473+
Context.API.GetTranslation(
474+
"flowlauncher_plugin_program_disable_dlgtitle_success_message"));
475+
}
476+
Context.API.ReQuery();
477+
}
478+
catch (Exception e)
479+
{
480+
Context.API.LogException(ClassName, "Failed to disable program", e);
481+
}
482+
});
451483
return false;
452484
},
453485
IcoPath = "Images/disable.png",
@@ -458,52 +490,50 @@ public List<Result> LoadContextMenus(Result selectedResult)
458490
return menuOptions;
459491
}
460492

461-
private static async Task DisableProgramAsync(IProgram programToDelete)
493+
private static async Task<bool> DisableProgramAsync(IProgram programToDelete)
462494
{
463495
if (_settings.DisabledProgramSources.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier))
464-
return;
496+
{
497+
return false;
498+
}
465499

466500
await _uwpsLock.WaitAsync();
467-
var reindexUwps = true;
468501
try
469502
{
470-
reindexUwps = _uwps.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier);
471-
var program = _uwps.First(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier);
472-
program.Enabled = false;
473-
_settings.DisabledProgramSources.Add(new ProgramSource(program));
503+
var program = _uwps.FirstOrDefault(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier);
504+
if (program != null)
505+
{
506+
program.Enabled = false;
507+
_settings.DisabledProgramSources.Add(new ProgramSource(program));
508+
// Reindex UWP programs
509+
_ = Task.Run(() => IndexUwpProgramsAsync(resetCache: false));
510+
return true;
511+
}
474512
}
475513
finally
476514
{
477515
_uwpsLock.Release();
478516
}
479517

480-
// Reindex UWP programs
481-
if (reindexUwps)
482-
{
483-
_ = Task.Run(IndexUwpProgramsAsync);
484-
return;
485-
}
486-
487518
await _win32sLock.WaitAsync();
488-
var reindexWin32s = true;
489519
try
490520
{
491-
reindexWin32s = _win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier);
492-
var program = _win32s.First(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier);
493-
program.Enabled = false;
494-
_settings.DisabledProgramSources.Add(new ProgramSource(program));
521+
var program = _win32s.FirstOrDefault(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier);
522+
if (program != null)
523+
{
524+
program.Enabled = false;
525+
_settings.DisabledProgramSources.Add(new ProgramSource(program));
526+
// Reindex Win32 programs
527+
_ = Task.Run(() => IndexWin32ProgramsAsync(resetCache: false));
528+
return true;
529+
}
495530
}
496531
finally
497532
{
498533
_win32sLock.Release();
499534
}
500535

501-
// Reindex Win32 programs
502-
if (reindexWin32s)
503-
{
504-
_ = Task.Run(IndexWin32ProgramsAsync);
505-
return;
506-
}
536+
return false;
507537
}
508538

509539
public static void StartProcess(Func<ProcessStartInfo, Process> runProcess, ProcessStartInfo info)

Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ private static IEnumerable<Package> CurrentUserPackages()
290290
}
291291

292292
private static readonly Channel<byte> PackageChangeChannel = Channel.CreateBounded<byte>(1);
293-
private static PackageCatalog? catalog;
293+
private static PackageCatalog catalog;
294294

295295
public static async Task WatchPackageChangeAsync()
296296
{
@@ -317,7 +317,7 @@ public static async Task WatchPackageChangeAsync()
317317
{
318318
await Task.Delay(3000).ConfigureAwait(false);
319319
PackageChangeChannel.Reader.TryRead(out _);
320-
await Task.Run(Main.IndexUwpProgramsAsync);
320+
await Main.IndexUwpProgramsAsync(resetCache: true).ConfigureAwait(false);
321321
}
322322
}
323323
}

Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ public static async Task MonitorDirectoryChangeAsync()
796796
{
797797
}
798798

799-
await Task.Run(Main.IndexWin32ProgramsAsync);
799+
await Main.IndexWin32ProgramsAsync(resetCache: true).ConfigureAwait(false);
800800
}
801801
}
802802

0 commit comments

Comments
 (0)