Skip to content

Commit 0eac27a

Browse files
authored
Merge pull request #39 from Odotocodot/dev
Version 3.0.1 - Fix crash on quick note with empty title (Updated to `LinqToOneNote-2.1.1`) - Fix incorrect **scope search** check - Cache OneNote hierarchy when applicable - This brings the performance improvement for Notebook Explorer from last version to **recent pages** and **title search**
2 parents a4abe7d + 5a6d30b commit 0eac27a

13 files changed

Lines changed: 95 additions & 123 deletions

Changelog.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
# Changelog
22

3+
## 3.0.1 - 2026-03-13
4+
5+
- Fix crash on quick note with empty title (Updated to `LinqToOneNote-2.1.1`)
6+
- Fix incorrect **scope search** check
7+
- Cache OneNote hierarchy when applicable
8+
- This brings the performance improvement for Notebook Explorer from last version to **recent pages** and **title search**
9+
310
## 3.0.0 - 2026-03-04
411

5-
- **⚠ Now requires Flow Launcher version 2.1.0 or later.**
12+
- **⚠ Now requires Flow Launcher version `2.1.0` or later.**
613
- Refactored code
714
- Improved Notebook Explorer performance.
815
- Added copy link to clipboard context menu item. ([#32](https://github.com/Odotocodot/Flow.Launcher.Plugin.OneNote/issues/32))

Flow.Launcher.Plugin.OneNote/Flow.Launcher.Plugin.OneNote.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<ItemGroup>
3131
<PackageReference Include="Flow.Launcher.Plugin" Version="5.2.0" />
3232
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
33-
<PackageReference Include="LinqToOneNote" Version="2.1.0" />
33+
<PackageReference Include="LinqToOneNote" Version="2.1.1" />
3434
<PackageReference Include="System.Drawing.Common" Version="8.0.6" />
3535
<PackageReference Include="iNKORE.UI.WPF.Modern" Version="0.10.1" />
3636
</ItemGroup>

Flow.Launcher.Plugin.OneNote/Keywords.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public class Keyword
2626
public int Length => Value.Length;
2727
public static implicit operator string(Keyword keyword) => keyword.Value;
2828
public override string ToString() => Value;
29+
30+
public static Keyword Empty { get; } = new ("");
2931
}
3032

3133
//Needed for legacy as keywords where just saved as a string

Flow.Launcher.Plugin.OneNote/Main.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Flow.Launcher.Plugin.OneNote.Search;
88
using Flow.Launcher.Plugin.OneNote.UI.Views;
99
using OneNoteApp = LinqToOneNote.OneNote;
10+
1011
namespace Flow.Launcher.Plugin.OneNote
1112
{
1213
#nullable disable
@@ -18,7 +19,6 @@ public class Main : IAsyncPlugin, IContextMenu, ISettingProvider, IDisposable
1819
private SearchManager searchManager;
1920
private Settings settings;
2021
private IconProvider iconProvider;
21-
private VisibilityChanged visibilityChanged;
2222

2323
private static SemaphoreSlim semaphore;
2424

@@ -28,17 +28,18 @@ public Task InitAsync(PluginInitContext context)
2828
this.context = context;
2929
settings = context.API.LoadSettingJsonStorage<Settings>();
3030

31-
visibilityChanged = new VisibilityChanged(context);
3231
iconProvider = new IconProvider(context, settings);
3332
resultCreator = new ResultCreator(context, settings, iconProvider);
34-
searchManager = new SearchManager(context, settings, resultCreator, visibilityChanged);
33+
searchManager = new SearchManager(context, settings, resultCreator);
3534
semaphore = new SemaphoreSlim(1, 1);
3635

37-
visibilityChanged.Subscribe(static (isVisible) =>
36+
context.API.VisibilityChanged += (_, args) =>
3837
{
39-
if (!isVisible)
40-
Task.Run(OneNoteApp.ReleaseComObject);
41-
});
38+
if (args.IsVisible)
39+
return;
40+
Task.Run(OneNoteApp.ReleaseComObject);
41+
searchManager.RootCache.SetDirty();
42+
};
4243
return Task.CompletedTask;
4344
}
4445

@@ -84,7 +85,6 @@ public Control CreateSettingPanel()
8485

8586
public void Dispose()
8687
{
87-
visibilityChanged.Dispose();
8888
semaphore.Dispose();
8989
OneNoteApp.ReleaseComObject();
9090
}

Flow.Launcher.Plugin.OneNote/Search/DefaultSearch.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,20 @@
44

55
namespace Flow.Launcher.Plugin.OneNote.Search
66
{
7-
public class DefaultSearch : SearchBase
7+
public class DefaultSearch(PluginInitContext context, Settings settings, ResultCreator resultCreator)
8+
: SearchBase(context, settings, resultCreator, Keyword.Empty)
89
{
9-
public DefaultSearch(PluginInitContext context, Settings settings, ResultCreator resultCreator)
10-
: base(context, settings, resultCreator, null) { }
11-
12-
public override List<Result> GetResults(string query)
10+
public override List<Result> GetResults(Query query)
1311
{
14-
if (!char.IsLetterOrDigit(query[0]))
12+
string search = query.Search;
13+
if (!char.IsLetterOrDigit(search[0]))
1514
{
1615
return resultCreator.InvalidQuery();
1716
}
1817

19-
return OneNoteApp.FindPages(query)
20-
.Select(pg => resultCreator.CreatePageResult(pg, query))
18+
return OneNoteApp.FindPages(search)
19+
.Select(pg => resultCreator.CreatePageResult(pg, search))
2120
.ToList();
22-
2321
}
2422
}
2523
}

Flow.Launcher.Plugin.OneNote/Search/NotebookExplorer.cs

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,12 @@
55
using LinqToOneNote.Abstractions;
66
using OneNoteApp = LinqToOneNote.OneNote;
77

8-
98
namespace Flow.Launcher.Plugin.OneNote.Search
109
{
11-
public class NotebookExplorer : SearchBase
10+
public class NotebookExplorer(PluginInitContext context, Settings settings, ResultCreator resultCreator, TitleSearch titleSearch, RootCache rootCache)
11+
: SearchBase(context, settings, resultCreator, settings.Keywords.NotebookExplorer)
1212
{
13-
private readonly TitleSearch titleSearch;
14-
private Root? cache;
15-
private bool updateCache;
16-
public NotebookExplorer(PluginInitContext context, Settings settings, ResultCreator resultCreator, TitleSearch titleSearch, VisibilityChanged visibilityChanged)
17-
: base(context, settings, resultCreator, settings.Keywords.NotebookExplorer)
18-
{
19-
this.titleSearch = titleSearch;
20-
visibilityChanged.Subscribe(isVisible =>
21-
{
22-
if (!isVisible)
23-
{
24-
updateCache = true;
25-
}
26-
});
27-
}
28-
29-
internal List<Result> GetResults(Query query)
13+
public override List<Result> GetResults(Query query)
3014
{
3115
if (!ValidateSearch(query, out string? search, out IOneNoteItem? parent, out IEnumerable<IOneNoteItem> collection))
3216
return resultCreator.InvalidQuery(false);
@@ -49,19 +33,12 @@ internal List<Result> GetResults(Query query)
4933
return results;
5034
}
5135

52-
public override List<Result> GetResults(string query) => GetResults(query);
53-
5436
private bool ValidateSearch(Query query, out string? lastSearch, out IOneNoteItem? parent, out IEnumerable<IOneNoteItem> collection)
5537
{
5638
lastSearch = null;
5739
parent = null;
58-
if (updateCache || query.IsReQuery || cache == null)
59-
{
60-
cache = OneNoteApp.GetFullHierarchy();
61-
updateCache = false;
62-
}
6340

64-
collection = cache.Notebooks;
41+
collection = rootCache.Root.Notebooks;
6542

6643
string search = query.Search[(query.Search.IndexOf(Keywords.NotebookExplorer, StringComparison.Ordinal) + Keywords.NotebookExplorer.Length)..];
6744
const string separator = Keywords.NotebookExplorerSeparator;
@@ -102,7 +79,7 @@ private List<Result> ScopedSearch(string query, IOneNoteItem parent)
10279
if (!char.IsLetterOrDigit(query[Keywords.ScopedSearch.Length]))
10380
return resultCreator.InvalidQuery();
10481

105-
string currentSearch = query[Keywords.TitleSearch.Length..];
82+
string currentSearch = query[Keywords.ScopedSearch.Length..];
10683

10784
var results = OneNoteApp.FindPages(currentSearch, parent)
10885
.Select(pg => resultCreator.CreatePageResult(pg, currentSearch))
Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,27 @@
11
using System.Collections.Generic;
22
using System.Linq;
33
using LinqToOneNote;
4-
using OneNoteApp = LinqToOneNote.OneNote;
54

65
namespace Flow.Launcher.Plugin.OneNote.Search
76
{
8-
public class RecentPages : SearchBase
7+
public class RecentPages(PluginInitContext context, Settings settings, ResultCreator resultCreator, RootCache rootCache)
8+
: SearchBase(context, settings, resultCreator, settings.Keywords.RecentPages)
99
{
10-
public RecentPages(PluginInitContext context, Settings settings, ResultCreator resultCreator)
11-
: base(context, settings, resultCreator, settings.Keywords.RecentPages) { }
12-
13-
public override List<Result> GetResults(string query)
10+
public override List<Result> GetResults(Query query)
1411
{
1512
int count = settings.DefaultRecentsCount;
16-
17-
if (query.Length > keyword.Length && int.TryParse(query[keyword.Length..], out int userChosenCount))
13+
string search = query.Search;
14+
if (search.Length > keyword.Length && int.TryParse(search[keyword.Length..], out int userChosenCount))
1815
count = userChosenCount;
1916

20-
return OneNoteApp.GetFullHierarchy()
21-
.Notebooks
22-
.GetAllPages()
23-
.FilterBySettings(settings)
24-
.OrderByDescending(pg => pg.LastModified)
25-
.Take(count)
26-
.Select(resultCreator.CreateRecentPageResult)
27-
.ToList();
17+
return rootCache.Root
18+
.Notebooks
19+
.GetAllPages()
20+
.FilterBySettings(settings)
21+
.OrderByDescending(pg => pg.LastModified)
22+
.Take(count)
23+
.Select(resultCreator.CreateRecentPageResult)
24+
.ToList();
2825
}
2926
}
3027
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using LinqToOneNote;
2+
3+
namespace Flow.Launcher.Plugin.OneNote.Search
4+
{
5+
public class RootCache
6+
{
7+
private bool isDirty;
8+
private Root? root;
9+
public Root Root
10+
{
11+
get
12+
{
13+
if (!isDirty && root is not null)
14+
return root;
15+
root = LinqToOneNote.OneNote.GetFullHierarchy();
16+
isDirty = false;
17+
return root;
18+
}
19+
}
20+
public void SetDirty()
21+
{
22+
isDirty = true;
23+
}
24+
}
25+
}

Flow.Launcher.Plugin.OneNote/Search/SearchBase.cs

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,13 @@
22

33
namespace Flow.Launcher.Plugin.OneNote.Search
44
{
5-
public abstract class SearchBase
5+
public abstract class SearchBase(PluginInitContext context, Settings settings, ResultCreator resultCreator, Keyword keyword)
66
{
7-
protected readonly PluginInitContext context;
8-
protected readonly Settings settings;
9-
protected readonly ResultCreator resultCreator;
10-
#nullable disable
11-
public readonly Keyword keyword;
12-
#nullable restore
13-
protected SearchBase(PluginInitContext context, Settings settings, ResultCreator resultCreator, Keyword? keyword)
14-
{
15-
this.context = context;
16-
this.settings = settings;
17-
this.resultCreator = resultCreator;
18-
this.keyword = keyword;
19-
}
7+
protected readonly PluginInitContext context = context;
8+
protected readonly Settings settings = settings;
9+
protected readonly ResultCreator resultCreator = resultCreator;
10+
public readonly Keyword keyword = keyword;
2011
protected Keywords Keywords => settings.Keywords;
21-
public abstract List<Result> GetResults(string query);
12+
public abstract List<Result> GetResults(Query query);
2213
}
2314
}

Flow.Launcher.Plugin.OneNote/Search/SearchManager.cs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,31 @@ public class SearchManager
88
private readonly NotebookExplorer notebookExplorer;
99
private readonly DefaultSearch defaultSearch;
1010
private readonly RecentPages recentPages;
11+
private readonly RootCache rootCache;
12+
public RootCache RootCache => rootCache;
1113

12-
public SearchManager(PluginInitContext context, Settings settings, ResultCreator resultCreator, VisibilityChanged visibilityChanged)
14+
public SearchManager(PluginInitContext context, Settings settings, ResultCreator resultCreator)
1315
{
14-
titleSearch = new TitleSearch(context, settings, resultCreator);
15-
notebookExplorer = new NotebookExplorer(context, settings, resultCreator, titleSearch, visibilityChanged);
16-
recentPages = new RecentPages(context, settings, resultCreator);
16+
rootCache = new RootCache();
17+
titleSearch = new TitleSearch(context, settings, resultCreator, rootCache);
18+
notebookExplorer = new NotebookExplorer(context, settings, resultCreator, titleSearch, rootCache);
19+
recentPages = new RecentPages(context, settings, resultCreator, rootCache);
1720
defaultSearch = new DefaultSearch(context, settings, resultCreator);
1821
}
1922

2023
public List<Result> Query(Query query)
2124
{
25+
if (query.IsReQuery)
26+
{
27+
rootCache.SetDirty();
28+
}
2229
string search = query.Search;
2330
return search switch
2431
{
25-
{ } when search.StartsWithOrd(titleSearch.keyword) => titleSearch.GetResults(search),
32+
{ } when search.StartsWithOrd(titleSearch.keyword) => titleSearch.GetResults(query),
2633
{ } when search.StartsWithOrd(notebookExplorer.keyword) => notebookExplorer.GetResults(query),
27-
{ } when search.StartsWithOrd(recentPages.keyword) => recentPages.GetResults(search),
28-
_ => defaultSearch.GetResults(search!),
34+
{ } when search.StartsWithOrd(recentPages.keyword) => recentPages.GetResults(query),
35+
_ => defaultSearch.GetResults(query),
2936
};
3037
}
3138
}

0 commit comments

Comments
 (0)