Skip to content
1 change: 1 addition & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ WCA_ACCENT_POLICY
HGlobal
dopusrt
firefox
Firefox
msedge
svgc
ime
Expand Down
71 changes: 54 additions & 17 deletions Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.IO;
using System.Threading.Channels;
using System.Threading.Tasks;
using System.Threading;

namespace Flow.Launcher.Plugin.BrowserBookmark
{
Expand All @@ -20,20 +21,39 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex
private static List<Bookmark> cachedBookmarks = new List<Bookmark>();

private static Settings _settings;


private static bool initialized = false;

public void Init(PluginInitContext context)
{
Main.context = context;

_settings = context.API.LoadSettingJsonStorage<Settings>();

cachedBookmarks = BookmarkLoader.LoadAllBookmarks(_settings);
LoadBookmarksIfEnabled();
}

_ = MonitorRefreshQueue();
private static void LoadBookmarksIfEnabled()
{
if (context.CurrentPluginMetadata.Disabled)
{
// Don't load or monitor files if disabled
return;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't call init() when plugin is disabled.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, let's add a flag to indicate whether a plugin is initialized

The issue for now is that if user re-enable the plugin, it won't be initialized

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but it's not the point of this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we call init every time plugin is reenabled?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we call init every time plugin is reenabled?

Technically we should but some plugins may need to update. like if we don't dispose file watchers when disabling plugins, creating new ones after re enabling may lead to some issues.


cachedBookmarks = BookmarkLoader.LoadAllBookmarks(_settings);
_ = MonitorRefreshQueueAsync();
initialized = true;
}

public List<Result> Query(Query query)
{
// For when the plugin being previously disabled and is now renabled
if (!initialized)
{
LoadBookmarksIfEnabled();
}

string param = query.Search.TrimStart();

// Should top results be returned? (true if no search parameters have been passed)
Expand Down Expand Up @@ -86,35 +106,44 @@ public List<Result> Query(Query query)

private static Channel<byte> refreshQueue = Channel.CreateBounded<byte>(1);

private async Task MonitorRefreshQueue()
private static SemaphoreSlim fileMonitorSemaphore = new(1, 1);

private static async Task MonitorRefreshQueueAsync()
{
if (fileMonitorSemaphore.CurrentCount < 1)
{
return;
}
await fileMonitorSemaphore.WaitAsync();
var reader = refreshQueue.Reader;
while (await reader.WaitToReadAsync())
{
await Task.Delay(2000);
if (reader.TryRead(out _))
{
ReloadData();
ReloadAllBookmarks(false);
}
}
fileMonitorSemaphore.Release();
}

private static readonly List<FileSystemWatcher> Watchers = new();

internal static void RegisterBookmarkFile(string path)
{
var directory = Path.GetDirectoryName(path);
if (!Directory.Exists(directory))
if (!Directory.Exists(directory) || !File.Exists(path))
{
return;
var watcher = new FileSystemWatcher(directory!);
if (File.Exists(path))
}
if (Watchers.Any(x => x.Path.Equals(directory, StringComparison.OrdinalIgnoreCase)))
{
var fileName = Path.GetFileName(path);
watcher.Filter = fileName;
return;
}

var watcher = new FileSystemWatcher(directory!);
watcher.Filter = Path.GetFileName(path);

watcher.NotifyFilter = NotifyFilters.FileName |
NotifyFilters.LastAccess |
NotifyFilters.LastWrite |
NotifyFilters.Size;

Expand All @@ -129,7 +158,7 @@ internal static void RegisterBookmarkFile(string path)
};

watcher.EnableRaisingEvents = true;

Watchers.Add(watcher);
}

Expand All @@ -138,11 +167,12 @@ public void ReloadData()
ReloadAllBookmarks();
}

public static void ReloadAllBookmarks()
public static void ReloadAllBookmarks(bool disposeFileWatchers = true)
{
cachedBookmarks.Clear();

cachedBookmarks = BookmarkLoader.LoadAllBookmarks(_settings);
if (disposeFileWatchers)
DisposeFileWatchers();
LoadBookmarksIfEnabled();
}

public string GetTranslatedPluginTitle()
Expand Down Expand Up @@ -196,12 +226,19 @@ internal class BookmarkAttributes
{
internal string Url { get; set; }
}

public void Dispose()
{
DisposeFileWatchers();
}

private static void DisposeFileWatchers()
{
foreach (var watcher in Watchers)
{
watcher.Dispose();
}
Watchers.Clear();
}
}
}