diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index efebf0ae9da4..7db7d11919ce 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -1059,9 +1059,13 @@ NULLCURSOR
nullonfailure
numberbox
nwc
+Objbase
+objidl
+ocid
ocr
Ocrsettings
odbccp
+Odotocodot
OEMCONVERT
officehubintl
OFN
@@ -1128,6 +1132,7 @@ PDEVMODE
pdisp
PDLL
pdo
+pdpshare
pdto
pdtobj
pdw
@@ -1881,6 +1886,7 @@ XDocument
XElement
xfd
XFile
+XIn
XIncrement
XNamespace
Xoshiro
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 4b681c95c4cb..863a33215db4 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -19,9 +19,8 @@
+
-
-
@@ -47,7 +46,7 @@
+ -->
@@ -60,9 +59,9 @@
+
-
@@ -98,4 +97,4 @@
-
+
\ No newline at end of file
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/IconProvider.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/IconProvider.cs
new file mode 100644
index 000000000000..cd36a5eec56c
--- /dev/null
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/IconProvider.cs
@@ -0,0 +1,204 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Concurrent;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Windows.Media.Imaging;
+using ManagedCommon;
+using Odotocodot.OneNote.Linq;
+using Wox.Infrastructure.Image;
+using Wox.Plugin;
+using Wox.Plugin.Logger;
+
+namespace Microsoft.PowerToys.Run.Plugin.OneNote.Components
+{
+ public class IconProvider
+ {
+ private readonly PluginInitContext _context;
+ private readonly OneNoteSettings _settings;
+ private readonly string _imagesDirectory;
+ private readonly string _generatedImagesDirectory;
+ private readonly ConcurrentDictionary _imageCache = new();
+
+ private bool _deleteColoredIconsOnCleanup;
+
+ private string _powerToysTheme;
+ private string _pluginTheme;
+
+ internal string NewPage => $"Images/page_new.{_pluginTheme}.png";
+
+ internal string NewSection => $"Images/section_new.{_pluginTheme}.png";
+
+ internal string NewSectionGroup => $"Images/section_group_new.{_pluginTheme}.png";
+
+ internal string NewNotebook => $"Images/notebook_new.{_pluginTheme}.png";
+
+ internal string Page => $"Images/page.{_pluginTheme}.png";
+
+ internal string Recent => $"Images/page_recent.{_pluginTheme}.png";
+
+ internal string Sync => $"Images/sync.{_pluginTheme}.png";
+
+ internal string Search => $"Images/search.{_pluginTheme}.png";
+
+ internal string NotebookExplorer => $"Images/notebook_explorer.{_pluginTheme}.png";
+
+ internal string Warning => $"Images/warning.{_powerToysTheme}.png";
+
+ internal string QuickNote => NewPage;
+
+ internal IconProvider(PluginInitContext context, OneNoteSettings settings)
+ {
+ _settings = settings;
+ _context = context;
+ _settings.ColoredIconsSettingChanged += OnColoredIconsSettingChanged;
+ _context.API.ThemeChanged += OnThemeChanged;
+
+ _imagesDirectory = $"{_context.CurrentPluginMetadata.PluginDirectory}/Images/";
+ _generatedImagesDirectory = $"{_context.CurrentPluginMetadata.PluginDirectory}/Images/Generated/";
+
+ if (!Directory.Exists(_generatedImagesDirectory))
+ {
+ Directory.CreateDirectory(_generatedImagesDirectory);
+ }
+
+ foreach (var imagePath in Directory.EnumerateFiles(_generatedImagesDirectory))
+ {
+ _imageCache.TryAdd(Path.GetFileNameWithoutExtension(imagePath), Path2Bitmap(imagePath));
+ }
+
+ UpdatePowerToysTheme(_context.API.GetCurrentTheme());
+ }
+
+ private void OnColoredIconsSettingChanged()
+ {
+ _deleteColoredIconsOnCleanup = !_settings.ColoredIcons;
+ UpdatePluginTheme();
+ }
+
+ private void OnThemeChanged(Theme oldTheme, Theme newTheme) => UpdatePowerToysTheme(newTheme);
+
+ [MemberNotNull(nameof(_powerToysTheme))]
+ [MemberNotNull(nameof(_pluginTheme))]
+ private void UpdatePowerToysTheme(Theme theme)
+ {
+ _powerToysTheme = theme == Theme.Light || theme == Theme.HighContrastWhite ? "light" : "dark";
+ UpdatePluginTheme();
+ }
+
+ [MemberNotNull(nameof(_pluginTheme))]
+ private void UpdatePluginTheme() => _pluginTheme = _settings.ColoredIcons ? "color" : _powerToysTheme;
+
+ private BitmapSource GetColoredIcon(string itemType, Color itemColor)
+ {
+ return _imageCache.GetOrAdd($"{itemType}.{itemColor.ToArgb()}", key =>
+ {
+ var color = itemColor;
+ using var bitmap = new Bitmap($"{_imagesDirectory}{itemType}.dark.png");
+ BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
+
+ int bytesPerPixel = Image.GetPixelFormatSize(bitmap.PixelFormat) / 8;
+ byte[] pixels = new byte[bitmapData.Stride * bitmap.Height];
+ IntPtr pointer = bitmapData.Scan0;
+ Marshal.Copy(pointer, pixels, 0, pixels.Length);
+ int bytesWidth = bitmapData.Width * bytesPerPixel;
+
+ for (int j = 0; j < bitmapData.Height; j++)
+ {
+ int line = j * bitmapData.Stride;
+ for (int i = 0; i < bytesWidth; i += bytesPerPixel)
+ {
+ pixels[line + i] = color.B;
+ pixels[line + i + 1] = color.G;
+ pixels[line + i + 2] = color.R;
+ }
+ }
+
+ Marshal.Copy(pixels, 0, pointer, pixels.Length);
+ bitmap.UnlockBits(bitmapData);
+
+ var filePath = $"{_generatedImagesDirectory}{key}.png";
+ bitmap.Save(filePath, ImageFormat.Png);
+ return Path2Bitmap(filePath);
+ });
+ }
+
+ private BitmapSource Path2Bitmap(string path) => WindowsThumbnailProvider.GetThumbnail(path, Constant.ThumbnailSize, Constant.ThumbnailSize, ThumbnailOptions.ThumbnailOnly);
+
+ internal System.Windows.Media.ImageSource GetIcon(IOneNoteItem item)
+ {
+ string key;
+ switch (item)
+ {
+ case OneNoteNotebook notebook:
+ if (!_settings.ColoredIcons || notebook.Color is null)
+ {
+ key = $"{nameof(notebook)}.{_powerToysTheme}";
+ break;
+ }
+ else
+ {
+ return GetColoredIcon(nameof(notebook), notebook.Color.Value);
+ }
+
+ case OneNoteSectionGroup sectionGroup:
+ key = $"{(sectionGroup.IsRecycleBin ? $"recycle_bin" : $"section_group")}.{_pluginTheme}";
+ break;
+
+ case OneNoteSection section:
+ if (!_settings.ColoredIcons || section.Color is null)
+ {
+ key = $"{nameof(section)}.{_powerToysTheme}";
+ break;
+ }
+ else
+ {
+ return GetColoredIcon(nameof(section), section.Color.Value);
+ }
+
+ case OneNotePage:
+ key = Path.GetFileNameWithoutExtension(Page);
+ break;
+
+ default:
+ throw new NotImplementedException();
+ }
+
+ return _imageCache.GetOrAdd(key, key => Path2Bitmap($"{_imagesDirectory}{key}.png"));
+ }
+
+ internal void Cleanup()
+ {
+ _imageCache.Clear();
+ if (_deleteColoredIconsOnCleanup)
+ {
+ foreach (var file in new DirectoryInfo(_generatedImagesDirectory).EnumerateFiles())
+ {
+ try
+ {
+ file.Delete();
+ }
+ catch (Exception ex) when (ex is DirectoryNotFoundException || ex is IOException)
+ {
+ Log.Error($"Failed to delete icon at \"{file}\"", GetType());
+ }
+ }
+ }
+
+ if (_settings != null)
+ {
+ _settings.ColoredIconsSettingChanged -= OnColoredIconsSettingChanged;
+ }
+
+ if (_context != null && _context.API != null)
+ {
+ _context.API.ThemeChanged -= OnThemeChanged;
+ }
+ }
+ }
+}
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/Keywords.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/Keywords.cs
new file mode 100644
index 000000000000..ba1a3f95888c
--- /dev/null
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/Keywords.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.PowerToys.Run.Plugin.OneNote.Components
+{
+ public class Keywords
+ {
+ internal const string NotebookExplorerSeparator = @"\";
+
+ internal const string NotebookExplorer = $"nb:{NotebookExplorerSeparator}";
+
+ internal const string RecentPages = "rp:";
+
+ internal const string ScopedSearch = ">";
+
+ internal const string TitleSearch = "*";
+ }
+}
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/OneNoteItemExtensions.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/OneNoteItemExtensions.cs
new file mode 100644
index 000000000000..6d13c62d6f64
--- /dev/null
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/OneNoteItemExtensions.cs
@@ -0,0 +1,49 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using Odotocodot.OneNote.Linq;
+using Windows.Win32;
+using Windows.Win32.Foundation;
+using Windows.Win32.UI.WindowsAndMessaging;
+
+namespace Microsoft.PowerToys.Run.Plugin.OneNote.Components
+{
+ internal static class OneNoteItemExtensions
+ {
+ internal static bool OpenItemInOneNote(this IOneNoteItem item)
+ {
+ try
+ {
+ item.OpenInOneNote();
+ ShowOneNote();
+ return true;
+ }
+ catch (COMException)
+ {
+ // The page, section or even notebook may no longer exist, ignore and do nothing.
+ return false;
+ }
+ }
+
+ ///
+ /// Brings OneNote to the foreground and restores it if minimized.
+ ///
+ internal static void ShowOneNote()
+ {
+ using var process = Process.GetProcessesByName("onenote").FirstOrDefault();
+ if (process?.MainWindowHandle != null)
+ {
+ HWND handle = (HWND)process.MainWindowHandle;
+ if (PInvoke.IsIconic(handle))
+ {
+ PInvoke.ShowWindow(handle, SHOW_WINDOW_CMD.SW_RESTORE);
+ }
+
+ PInvoke.SetForegroundWindow(handle);
+ }
+ }
+ }
+}
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/OneNoteSettings.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/OneNoteSettings.cs
new file mode 100644
index 000000000000..e3cabae64c02
--- /dev/null
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/OneNoteSettings.cs
@@ -0,0 +1,114 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Globalization;
+using System.Text;
+using System.Windows.Controls;
+using Microsoft.PowerToys.Run.Plugin.OneNote.Properties;
+using Microsoft.PowerToys.Settings.UI.Library;
+using Wox.Plugin;
+
+namespace Microsoft.PowerToys.Run.Plugin.OneNote.Components
+{
+ public class OneNoteSettings : ISettingProvider
+ {
+ private bool coloredIcons;
+ private static readonly CompositeFormat ShowEncryptedSectionsDescription = CompositeFormat.Parse(Resources.ShowEncryptedSectionsDescription);
+ private static readonly CompositeFormat ShowRecycleBinDescription = CompositeFormat.Parse(Resources.ShowRecycleBinDescription);
+
+ internal bool ShowUnreadItems { get; private set; }
+
+ internal bool ShowEncryptedSections { get; private set; }
+
+ internal bool ShowRecycleBins { get; private set; }
+
+ // A timeout value is required as there currently no way to know if the Run window is visible.
+ internal double ComObjectTimeout { get; private set; }
+
+ internal bool ColoredIcons
+ {
+ get => coloredIcons;
+ private set
+ {
+ coloredIcons = value;
+ ColoredIconsSettingChanged?.Invoke();
+ }
+ }
+
+ internal event Action? ColoredIconsSettingChanged;
+
+ public IEnumerable AdditionalOptions => new List()
+ {
+ new PluginAdditionalOption()
+ {
+ Key = nameof(ShowUnreadItems),
+ PluginOptionType = PluginAdditionalOption.AdditionalOptionType.Checkbox,
+ DisplayLabel = Resources.DisplayUnreadIcon,
+ DisplayDescription = Resources.DisplayUnreadIconDescription,
+ Value = true,
+ },
+ new PluginAdditionalOption()
+ {
+ Key = nameof(ShowEncryptedSections),
+ PluginOptionType = PluginAdditionalOption.AdditionalOptionType.Checkbox,
+ DisplayLabel = Resources.ShowEncryptedSections,
+ DisplayDescription = string.Format(CultureInfo.CurrentCulture, ShowEncryptedSectionsDescription, Keywords.NotebookExplorer),
+ Value = true,
+ },
+ new PluginAdditionalOption()
+ {
+ Key = nameof(ShowRecycleBins),
+ PluginOptionType = PluginAdditionalOption.AdditionalOptionType.Checkbox,
+ DisplayLabel = Resources.ShowRecycleBin,
+ DisplayDescription = string.Format(CultureInfo.CurrentCulture, ShowRecycleBinDescription, Keywords.NotebookExplorer),
+ Value = true,
+ },
+ new PluginAdditionalOption()
+ {
+ Key = nameof(ComObjectTimeout),
+ PluginOptionType = PluginAdditionalOption.AdditionalOptionType.Numberbox,
+ DisplayLabel = Resources.OneNoteComObjectTimeout,
+ DisplayDescription = Resources.OneNoteComObjectTimeoutDescription,
+ NumberValue = 10000,
+ NumberBoxMin = 1000,
+ NumberBoxMax = 120000,
+ NumberBoxSmallChange = 1000,
+ NumberBoxLargeChange = 50000,
+ },
+ new PluginAdditionalOption()
+ {
+ Key = nameof(ColoredIcons),
+ PluginOptionType = PluginAdditionalOption.AdditionalOptionType.Checkbox,
+ DisplayLabel = Resources.CreateColoredIconsForNotebooksSections,
+ DisplayDescription = string.Empty,
+ Value = true,
+ },
+ };
+
+ public Control CreateSettingPanel() => throw new NotImplementedException();
+
+ public void UpdateSettings(PowerLauncherPluginSettings? settings)
+ {
+ if (settings?.AdditionalOptions == null)
+ {
+ return;
+ }
+
+ ShowUnreadItems = GetBoolSettingOrDefault(settings, nameof(ShowUnreadItems));
+ ShowEncryptedSections = GetBoolSettingOrDefault(settings, nameof(ShowEncryptedSections));
+ ShowRecycleBins = GetBoolSettingOrDefault(settings, nameof(ShowRecycleBins));
+
+ var comObjectTimeout = settings.AdditionalOptions.FirstOrDefault(x => x.Key == nameof(ComObjectTimeout))?.NumberValue;
+ ComObjectTimeout = comObjectTimeout ?? AdditionalOptions.First(x => x.Key == nameof(ComObjectTimeout)).NumberValue;
+
+ ColoredIcons = GetBoolSettingOrDefault(settings, nameof(ColoredIcons));
+ }
+
+ private bool GetBoolSettingOrDefault(PowerLauncherPluginSettings settings, string settingName)
+ {
+ var value = settings.AdditionalOptions.FirstOrDefault(x => x.Key == settingName)?.Value;
+ return value ?? AdditionalOptions.First(x => x.Key == settingName).Value;
+ }
+ }
+}
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/ResultCreator.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/ResultCreator.cs
new file mode 100644
index 000000000000..776cbaf444a9
--- /dev/null
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/ResultCreator.cs
@@ -0,0 +1,476 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.Globalization;
+using System.Reflection;
+using System.Text;
+using System.Windows.Input;
+using Humanizer;
+using Microsoft.PowerToys.Run.Plugin.OneNote.Properties;
+using Odotocodot.OneNote.Linq;
+using Wox.Infrastructure;
+using Wox.Plugin;
+using Wox.Plugin.Logger;
+
+namespace Microsoft.PowerToys.Run.Plugin.OneNote.Components
+{
+ public class ResultCreator
+ {
+ private readonly PluginInitContext _context;
+ private readonly OneNoteSettings _settings;
+ private readonly IconProvider _iconProvider;
+
+ private const string PathSeparator = " > ";
+ private static readonly string _oldSeparator = OneNoteApplication.RelativePathSeparator.ToString();
+
+ private static readonly CompositeFormat ViewNotebookExplorerDescription = CompositeFormat.Parse(Resources.ViewNotebookExplorerDescription);
+ private static readonly CompositeFormat ViewRecentPagesDescription = CompositeFormat.Parse(Resources.ViewRecentPagesDescription);
+ private static readonly CompositeFormat CreatePage = CompositeFormat.Parse(Resources.CreatePage);
+ private static readonly CompositeFormat CreateSection = CompositeFormat.Parse(Resources.CreateSection);
+ private static readonly CompositeFormat CreateSectionGroup = CompositeFormat.Parse(Resources.CreateSectionGroup);
+ private static readonly CompositeFormat CreateNotebook = CompositeFormat.Parse(Resources.CreateNotebook);
+ private static readonly CompositeFormat Path = CompositeFormat.Parse(Resources.Path);
+ private static readonly CompositeFormat LastModified = CompositeFormat.Parse(Resources.LastModified);
+ private static readonly CompositeFormat SectionNamesCannotContain = CompositeFormat.Parse(Resources.SectionNamesCannotContain);
+ private static readonly CompositeFormat SectionGroupNamesCannotContain = CompositeFormat.Parse(Resources.SectionGroupNamesCannotContain);
+ private static readonly CompositeFormat NotebookNamesCannotContain = CompositeFormat.Parse(Resources.NotebookNamesCannotContain);
+
+ internal ResultCreator(PluginInitContext context, OneNoteSettings settings, IconProvider iconProvider)
+ {
+ _settings = settings;
+ _context = context;
+ _iconProvider = iconProvider;
+ }
+
+ private static string GetNicePath(IOneNoteItem item, string separator = PathSeparator) => item.RelativePath.Replace(_oldSeparator, separator);
+
+ private string GetTitle(IOneNoteItem item, List? highlightData)
+ {
+ string title = item.Name;
+
+ if (!item.IsUnread || !_settings.ShowUnreadItems)
+ {
+ return title;
+ }
+
+ const string unread = "\u2022 ";
+ title = title.Insert(0, unread);
+
+ if (highlightData == null)
+ {
+ return title;
+ }
+
+ for (int i = 0; i < highlightData.Count; i++)
+ {
+ highlightData[i] += unread.Length;
+ }
+
+ return title;
+ }
+
+ private static string GetQueryTextDisplay(IOneNoteItem? parent)
+ {
+ return parent is null
+ ? $"{Keywords.NotebookExplorer}"
+ : $"{Keywords.NotebookExplorer}{GetNicePath(parent, Keywords.NotebookExplorerSeparator)}{Keywords.NotebookExplorerSeparator}";
+ }
+
+ internal List EmptyQuery(Query query)
+ {
+ if (_context.CurrentPluginMetadata.IsGlobal && !query.RawUserQuery.StartsWith(query.ActionKeyword, StringComparison.Ordinal))
+ {
+ return [];
+ }
+
+ return new List
+ {
+ new Result
+ {
+ Title = Resources.SearchOneNotePages,
+ IcoPath = _iconProvider.Search,
+ Score = 5000,
+ },
+ new Result
+ {
+ Title = Resources.ViewNotebookExplorer,
+ SubTitle = string.Format(CultureInfo.CurrentCulture, ViewNotebookExplorerDescription, Keywords.NotebookExplorer),
+ QueryTextDisplay = Keywords.NotebookExplorer,
+ IcoPath = _iconProvider.NotebookExplorer,
+ Score = 2000,
+ Action = ResultAction(() =>
+ {
+ _context.API.ChangeQuery($"{_context.CurrentPluginMetadata.ActionKeyword} {Keywords.NotebookExplorer}", true);
+ return false;
+ }),
+ },
+ new Result
+ {
+ Title = Resources.ViewRecentPages,
+ SubTitle = string.Format(CultureInfo.CurrentCulture, ViewRecentPagesDescription, Keywords.RecentPages),
+ QueryTextDisplay = Keywords.RecentPages,
+ IcoPath = _iconProvider.Recent,
+ Score = -1000,
+ Action = ResultAction(() =>
+ {
+ _context.API.ChangeQuery($"{_context.CurrentPluginMetadata.ActionKeyword} {Keywords.RecentPages}", true);
+ return false;
+ }),
+ },
+ new Result
+ {
+ Title = Resources.NewQuickNote,
+ IcoPath = _iconProvider.QuickNote,
+ Score = -4000,
+ Action = ResultAction(() =>
+ {
+ OneNoteApplication.CreateQuickNote(true);
+ return true;
+ }),
+ },
+ new Result
+ {
+ Title = Resources.OpenSyncNotebooks,
+ IcoPath = _iconProvider.Sync,
+ Score = int.MinValue,
+ Action = ResultAction(() =>
+ {
+ foreach (var notebook in OneNoteApplication.GetNotebooks())
+ {
+ notebook.Sync();
+ }
+
+ OneNoteApplication.GetNotebooks()
+ .GetPages()
+ .Where(i => !i.IsInRecycleBin)
+ .OrderByDescending(pg => pg.LastModified)
+ .First()
+ .OpenItemInOneNote();
+ return true;
+ }),
+ },
+ };
+ }
+
+ internal Result CreateOneNoteItemResult(IOneNoteItem item, bool actionIsAutoComplete, List? highlightData = null, int score = 0)
+ {
+ string title = GetTitle(item, highlightData);
+ string subTitle = GetNicePath(item);
+ string queryTextDisplay = GetQueryTextDisplay(item);
+
+ // TODO: Potential improvement would be to show the children of the OneNote item in its tooltip.
+ // E.g. for a notebook, it would display the number of section groups, sections and pages.
+ // Would require even more localisation.
+ // An example: https://github.com/Odotocodot/Flow.Launcher.Plugin.OneNote/blob/5f56aa81a19641197d4ea4a97dc22cf1aa21f5e6/Flow.Launcher.Plugin.OneNote/ResultCreator.cs#L145
+ switch (item)
+ {
+ case OneNoteNotebook notebook:
+ subTitle = string.Empty;
+ break;
+ case OneNoteSection section:
+ if (section.Encrypted)
+ {
+ // potentially replace with glyphs when/if supported
+ title += string.Format(CultureInfo.CurrentCulture, " [{0}]", section.Locked ? Resources.Locked : Resources.Unlocked);
+ }
+
+ break;
+ case OneNotePage page:
+ queryTextDisplay = !actionIsAutoComplete ? page.Name : queryTextDisplay[..^1];
+
+ actionIsAutoComplete = false;
+
+ subTitle = subTitle[..^(page.Name.Length + PathSeparator.Length)];
+ break;
+ }
+
+ var toolTip = string.Format(CultureInfo.CurrentCulture, LastModified, item.LastModified);
+ if (item is not OneNoteNotebook)
+ {
+ toolTip = toolTip.Insert(0, string.Format(CultureInfo.CurrentCulture, Path, subTitle) + "\n");
+ }
+
+ return new Result
+ {
+ Title = title,
+ ToolTipData = new ToolTipData(item.Name, toolTip),
+ TitleHighlightData = highlightData,
+ QueryTextDisplay = queryTextDisplay,
+ SubTitle = subTitle,
+ Score = score,
+ Icon = () => _iconProvider.GetIcon(item),
+ ContextData = item,
+ Action = ResultAction(() =>
+ {
+ if (actionIsAutoComplete)
+ {
+ _context.API.ChangeQuery($"{_context.CurrentPluginMetadata.ActionKeyword} {queryTextDisplay}", true);
+ return false;
+ }
+
+ item.Sync();
+ item.OpenItemInOneNote();
+ return true;
+ }),
+ };
+ }
+
+ internal Result CreatePageResult(OneNotePage page, string? query)
+ {
+ return CreateOneNoteItemResult(page, false, string.IsNullOrWhiteSpace(query) ? null : StringMatcher.FuzzySearch(query, page.Name).MatchData);
+ }
+
+ internal Result CreateRecentPageResult(OneNotePage page)
+ {
+ var result = CreateOneNoteItemResult(page, false, null);
+ result.IcoPath = _iconProvider.Recent;
+ result.SubTitle = $"{page.LastModified.Humanize(culture: CultureInfo.CurrentCulture)} | {result.SubTitle}";
+ return result;
+ }
+
+ private Result CreateNewOneNoteItemResult(string newItemName, IOneNoteItem? parent, CompositeFormat titleFormat, ImmutableArray invalidCharacters, CompositeFormat subTitleFormat, string iconPath, Action createItemAction)
+ {
+ newItemName = newItemName.Trim();
+
+ bool validTitle = !string.IsNullOrWhiteSpace(newItemName) && !invalidCharacters.Any(newItemName.Contains);
+
+ string subTitle = parent == null
+ ? OneNoteApplication.GetDefaultNotebookLocation() + System.IO.Path.DirectorySeparatorChar + newItemName
+ : GetNicePath(parent) + PathSeparator + newItemName;
+
+ return new Result
+ {
+ Title = string.Format(CultureInfo.CurrentCulture, titleFormat, newItemName),
+ SubTitle = validTitle
+ ? string.Format(CultureInfo.CurrentCulture, Path, subTitle)
+ : string.Format(CultureInfo.CurrentCulture, subTitleFormat, string.Join(' ', invalidCharacters)),
+ QueryTextDisplay = $"{GetQueryTextDisplay(parent)}{newItemName}",
+ IcoPath = iconPath,
+ Action = ResultAction(() =>
+ {
+ if (!validTitle)
+ {
+ return false;
+ }
+
+ createItemAction();
+
+ OneNoteItemExtensions.ShowOneNote();
+ _context.API.ChangeQuery($"{GetQueryTextDisplay(parent)}{newItemName}", true);
+ return true;
+ }),
+ };
+ }
+
+ internal Result CreateNewPageResult(string newPageName, OneNoteSection section)
+ {
+ return CreateNewOneNoteItemResult(newPageName, section, CreatePage, [], SectionNamesCannotContain, _iconProvider.NewPage, () => OneNoteApplication.CreatePage(section, newPageName, true));
+ }
+
+ internal Result CreateNewSectionResult(string newSectionName, IOneNoteItem parent)
+ {
+ return CreateNewOneNoteItemResult(newSectionName, parent, CreateSection, OneNoteApplication.InvalidSectionChars, SectionNamesCannotContain, _iconProvider.NewSection, () =>
+ {
+ switch (parent)
+ {
+ case OneNoteNotebook notebook:
+ OneNoteApplication.CreateSection(notebook, newSectionName, true);
+ break;
+ case OneNoteSectionGroup sectionGroup:
+ OneNoteApplication.CreateSection(sectionGroup, newSectionName, true);
+ break;
+ default:
+ break;
+ }
+ });
+ }
+
+ internal Result CreateNewSectionGroupResult(string newSectionGroupName, IOneNoteItem parent)
+ {
+ return CreateNewOneNoteItemResult(newSectionGroupName, parent, CreateSectionGroup, OneNoteApplication.InvalidSectionGroupChars, SectionGroupNamesCannotContain, _iconProvider.NewSectionGroup, () =>
+ {
+ switch (parent)
+ {
+ case OneNoteNotebook notebook:
+ OneNoteApplication.CreateSectionGroup(notebook, newSectionGroupName, true);
+ break;
+ case OneNoteSectionGroup sectionGroup:
+ OneNoteApplication.CreateSectionGroup(sectionGroup, newSectionGroupName, true);
+ break;
+ default:
+ break;
+ }
+ });
+ }
+
+ internal Result CreateNewNotebookResult(string newNotebookName)
+ {
+ return CreateNewOneNoteItemResult(newNotebookName, null, CreateNotebook, OneNoteApplication.InvalidNotebookChars, NotebookNamesCannotContain, _iconProvider.NewNotebook, () => OneNoteApplication.CreateNotebook(newNotebookName, true));
+ }
+
+ internal List LoadContextMenu(Result selectedResult)
+ {
+ var results = new List();
+ if (selectedResult.ContextData is IOneNoteItem item)
+ {
+ results.Add(new ContextMenuResult
+ {
+ PluginName = Assembly.GetExecutingAssembly().GetName().Name,
+ Title = Resources.OpenAndSync,
+ Glyph = "\xE8A7",
+ FontFamily = "Segoe MDL2 Assets",
+ AcceleratorKey = Key.Enter,
+ AcceleratorModifiers = ModifierKeys.Shift,
+ Action = ResultAction(() =>
+ {
+ item.Sync();
+ item.OpenItemInOneNote();
+ return true;
+ }),
+ });
+
+ if (item is not OneNotePage)
+ {
+ results.Add(new ContextMenuResult
+ {
+ PluginName = Assembly.GetExecutingAssembly().GetName().Name,
+ Title = Resources.OpenInNotebookExplorer,
+ Glyph = "\xEC50",
+ FontFamily = "Segoe MDL2 Assets",
+ AcceleratorKey = Key.Enter,
+ AcceleratorModifiers = ModifierKeys.Control | ModifierKeys.Shift,
+ Action = ResultAction(() =>
+ {
+ _context.API.ChangeQuery(selectedResult.QueryTextDisplay, true);
+ return false;
+ }),
+ });
+ }
+ }
+
+ if (selectedResult.ContextData is string url)
+ {
+ results.Add(new ContextMenuResult
+ {
+ PluginName = Assembly.GetExecutingAssembly().GetName().Name,
+ Title = Resources.VisitMicrosoftStore,
+ Glyph = "\xE8A7",
+ FontFamily = "Segoe MDL2 Assets",
+ AcceleratorKey = Key.Enter,
+ AcceleratorModifiers = ModifierKeys.Shift,
+ Action = ResultAction(() =>
+ {
+ try
+ {
+ Process.Start(url);
+ }
+ catch (Exception ex)
+ {
+ Log.Exception(ex.Message, ex, GetType());
+ }
+
+ return true;
+ }),
+ });
+ }
+
+ return results;
+ }
+
+ internal List NoItemsInCollection(IOneNoteItem? parent, List results)
+ {
+ // parent can be null if the collection only contains notebooks.
+ switch (parent)
+ {
+ case OneNoteNotebook:
+ case OneNoteSectionGroup:
+ // Can create section/section group
+ results.Add(NoItemsInCollectionResult(Resources.CreateSection, _iconProvider.NewSection));
+ results.Add(NoItemsInCollectionResult(Resources.CreateSectionGroup, _iconProvider.NewSectionGroup));
+ break;
+ case OneNoteSection section when !section.IsDeletedPages && !section.Locked:
+ // Can create page
+ results.Add(NoItemsInCollectionResult(Resources.CreatePage, _iconProvider.NewPage));
+ break;
+ default:
+ break;
+ }
+
+ return results;
+
+ Result NoItemsInCollectionResult(string title, string iconPath)
+ {
+ return new Result
+ {
+ Title = string.Format(CultureInfo.CurrentCulture, title, string.Empty),
+ QueryTextDisplay = $"{GetQueryTextDisplay(parent)}",
+ SubTitle = Resources.NoItemsFoundTypeValidName,
+ IcoPath = iconPath,
+ };
+ }
+ }
+
+ internal List NoMatchesFound(bool show)
+ {
+ return show
+ ? SingleResult(
+ Resources.NoMatchesFound,
+ Resources.NoMatchesFoundDescription,
+ _iconProvider.Search)
+ : [];
+ }
+
+ internal List InvalidQuery(bool show)
+ {
+ return show
+ ? SingleResult(
+ Resources.InvalidQuery,
+ Resources.InvalidQueryDescription,
+ _iconProvider.Warning)
+ : [];
+ }
+
+ internal List OneNoteNotInstalled()
+ {
+ var results = SingleResult(
+ Resources.OneNoteNotInstalled,
+ Resources.OneNoteNotInstalledDescription,
+ _iconProvider.Warning);
+
+ results[0].ContextData = "https://apps.microsoft.com/store/detail/XPFFZHVGQWWLHB?ocid=pdpshare";
+ return results;
+ }
+
+ internal static List SingleResult(string title, string? subTitle, string iconPath)
+ {
+ return new List
+ {
+ new Result
+ {
+ Title = title,
+ SubTitle = subTitle,
+ IcoPath = iconPath,
+ },
+ };
+ }
+
+ internal static Func ResultAction(Func func)
+ {
+ return _ =>
+ {
+ bool result = func();
+
+ // Closing the Run window, so can release the COM Object
+ if (result)
+ {
+ Task.Run(OneNoteApplication.ReleaseComObject);
+ }
+
+ return result;
+ };
+ }
+ }
+}
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/SearchManager.NotebookExplorer.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/SearchManager.NotebookExplorer.cs
new file mode 100644
index 000000000000..7d34be43522e
--- /dev/null
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/SearchManager.NotebookExplorer.cs
@@ -0,0 +1,179 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Globalization;
+using System.Text;
+using Microsoft.PowerToys.Run.Plugin.OneNote.Properties;
+using Odotocodot.OneNote.Linq;
+using Wox.Plugin;
+
+namespace Microsoft.PowerToys.Run.Plugin.OneNote.Components
+{
+ public partial class SearchManager
+ {
+ private sealed class NotebookExplorer
+ {
+ private readonly SearchManager _searchManager;
+ private readonly ResultCreator _resultCreator;
+ private static readonly CompositeFormat OpenXInOneNote = CompositeFormat.Parse(Resources.OpenXInOneNote);
+ private static readonly CompositeFormat SearchingByTitleInX = CompositeFormat.Parse(Resources.SearchingByTitleInX);
+ private static readonly CompositeFormat SearchingPagesInX = CompositeFormat.Parse(Resources.SearchingPagesInX);
+ private static readonly CompositeFormat SearchInItemInfo = CompositeFormat.Parse(Resources.SearchInItemInfo);
+
+ internal NotebookExplorer(SearchManager searchManager, ResultCreator resultCreator)
+ {
+ _searchManager = searchManager;
+ _resultCreator = resultCreator;
+ }
+
+ internal List Query(Query query)
+ {
+ var results = new List();
+
+ string fullSearch = query.Search[(query.Search.IndexOf(Keywords.NotebookExplorer, StringComparison.Ordinal) + Keywords.NotebookExplorer.Length)..];
+
+ IOneNoteItem? parent = null;
+ IEnumerable collection = OneNoteApplication.GetNotebooks();
+
+ string[] searches = fullSearch.Split(Keywords.NotebookExplorerSeparator, StringSplitOptions.None);
+
+ for (int i = -1; i < searches.Length - 1; i++)
+ {
+ if (i < 0)
+ {
+ continue;
+ }
+
+ parent = collection.FirstOrDefault(item => item.Name.Equals(searches[i], StringComparison.Ordinal));
+ if (parent == null)
+ {
+ return results;
+ }
+
+ collection = parent.Children;
+ }
+
+ string lastSearch = searches[^1];
+
+ results = lastSearch switch
+ {
+ // Empty search so show all in collection
+ string search when string.IsNullOrWhiteSpace(search)
+ => EmptySearch(parent, collection),
+
+ // Search by title
+ string search when search.StartsWith(Keywords.TitleSearch, StringComparison.Ordinal) && parent is not OneNotePage
+ => _searchManager.TitleSearch(search, parent, collection),
+
+ // Scoped search
+ string search when search.StartsWith(Keywords.ScopedSearch, StringComparison.Ordinal) && (parent is OneNoteNotebook || parent is OneNoteSectionGroup)
+ => ScopedSearch(search, parent),
+
+ // Default search
+ _ => Explorer(lastSearch, parent, collection),
+ };
+
+ if (parent != null)
+ {
+ var result = _resultCreator.CreateOneNoteItemResult(parent, false, score: 4000);
+ result.Title = string.Format(CultureInfo.CurrentCulture, OpenXInOneNote, parent.Name);
+ result.SubTitle = lastSearch switch
+ {
+ string search when search.StartsWith(Keywords.TitleSearch, StringComparison.Ordinal)
+ => string.Format(CultureInfo.CurrentCulture, SearchingByTitleInX, parent.Name),
+
+ string search when search.StartsWith(Keywords.ScopedSearch, StringComparison.Ordinal)
+ => string.Format(CultureInfo.CurrentCulture, SearchingPagesInX, parent.Name),
+
+ _ => string.Format(CultureInfo.CurrentCulture, SearchInItemInfo, Keywords.ScopedSearch, Keywords.TitleSearch),
+ };
+
+ results.Add(result);
+ }
+
+ return results;
+ }
+
+ private List EmptySearch(IOneNoteItem? parent, IEnumerable collection)
+ {
+ List results = collection.Where(_searchManager.SettingsCheck)
+ .Select(item => _resultCreator.CreateOneNoteItemResult(item, true))
+ .ToList();
+
+ return results.Count == 0 ? _resultCreator.NoItemsInCollection(parent, results) : results;
+ }
+
+ private List ScopedSearch(string query, IOneNoteItem parent)
+ {
+ if (query.Length == Keywords.ScopedSearch.Length)
+ {
+ return _resultCreator.NoMatchesFound(_searchManager.showSingleResults);
+ }
+
+ if (!char.IsLetterOrDigit(query[Keywords.ScopedSearch.Length]))
+ {
+ return _resultCreator.InvalidQuery(_searchManager.showSingleResults);
+ }
+
+ string currentSearch = query[Keywords.TitleSearch.Length..];
+ var results = new List();
+
+ results = OneNoteApplication.FindPages(currentSearch, parent)
+ .Select(pg => _resultCreator.CreatePageResult(pg, currentSearch))
+ .ToList();
+
+ if (results.Count == 0)
+ {
+ results = _resultCreator.NoMatchesFound(_searchManager.showSingleResults);
+ }
+
+ return results;
+ }
+
+ private List Explorer(string search, IOneNoteItem? parent, IEnumerable collection)
+ {
+ List? highlightData = null;
+ int score = 0;
+
+ var results = collection.Where(_searchManager.SettingsCheck)
+ .Where(item => _searchManager.FuzzySearch(item.Name, search, out highlightData, out score))
+ .Select(item => _resultCreator.CreateOneNoteItemResult(item, true, highlightData, score))
+ .ToList();
+
+ AddCreateNewOneNoteItemResults(search, parent, results);
+ return results;
+ }
+
+ private void AddCreateNewOneNoteItemResults(string newItemName, IOneNoteItem? parent, List results)
+ {
+ if (results.Any(result => string.Equals(newItemName.Trim(), result.Title, StringComparison.OrdinalIgnoreCase)))
+ {
+ return;
+ }
+
+ if (parent?.IsInRecycleBin() == true)
+ {
+ return;
+ }
+
+ switch (parent)
+ {
+ case null:
+ results.Add(_resultCreator.CreateNewNotebookResult(newItemName));
+ break;
+ case OneNoteNotebook:
+ case OneNoteSectionGroup:
+ results.Add(_resultCreator.CreateNewSectionResult(newItemName, parent));
+ results.Add(_resultCreator.CreateNewSectionGroupResult(newItemName, parent));
+ break;
+ case OneNoteSection section when !section.Locked:
+ results.Add(_resultCreator.CreateNewPageResult(newItemName, section));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/SearchManager.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/SearchManager.cs
new file mode 100644
index 000000000000..93a213b06aa0
--- /dev/null
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Components/SearchManager.cs
@@ -0,0 +1,131 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.PowerToys.Run.Plugin.OneNote.Properties;
+using Odotocodot.OneNote.Linq;
+using Wox.Infrastructure;
+using Wox.Plugin;
+
+namespace Microsoft.PowerToys.Run.Plugin.OneNote.Components
+{
+ public partial class SearchManager
+ {
+ private readonly PluginInitContext _context;
+ private readonly OneNoteSettings _settings;
+ private readonly IconProvider _iconProvider;
+ private readonly ResultCreator _resultCreator;
+ private readonly NotebookExplorer _notebookExplorer;
+
+ // If the plugin is in global mode and does not start with the action keyword, do not show single results like invalid query.
+ private bool showSingleResults = true;
+
+ internal SearchManager(PluginInitContext context, OneNoteSettings settings, IconProvider iconProvider, ResultCreator resultCreator)
+ {
+ _context = context;
+ _settings = settings;
+ _resultCreator = resultCreator;
+ _iconProvider = iconProvider;
+ _notebookExplorer = new NotebookExplorer(this, resultCreator);
+ }
+
+ internal List Query(Query query)
+ {
+ if (_context.CurrentPluginMetadata.IsGlobal)
+ {
+ showSingleResults = query.RawUserQuery.StartsWith(_context.CurrentPluginMetadata.ActionKeyword, StringComparison.Ordinal);
+ }
+
+ return query.Search switch
+ {
+ string s when s.StartsWith(Keywords.RecentPages, StringComparison.Ordinal)
+ => RecentPages(s),
+
+ string s when s.StartsWith(Keywords.NotebookExplorer, StringComparison.Ordinal)
+ => _notebookExplorer.Query(query),
+
+ string s when s.StartsWith(Keywords.TitleSearch, StringComparison.Ordinal)
+ => TitleSearch(s, null, OneNoteApplication.GetNotebooks()),
+
+ _ => DefaultSearch(query.Search),
+ };
+ }
+
+ private List DefaultSearch(string query)
+ {
+ // Check for invalid start of query i.e. symbols
+ if (!char.IsLetterOrDigit(query[0]))
+ {
+ return _resultCreator.InvalidQuery(showSingleResults);
+ }
+
+ var results = OneNoteApplication.FindPages(query)
+ .Select(pg => _resultCreator.CreatePageResult(pg, query))
+ .ToList();
+
+ return results.Count != 0 ? results : _resultCreator.NoMatchesFound(showSingleResults);
+ }
+
+ private List TitleSearch(string query, IOneNoteItem? parent, IEnumerable currentCollection)
+ {
+ if (query.Length == Keywords.TitleSearch.Length && parent == null)
+ {
+ return ResultCreator.SingleResult(Resources.SearchingByTitle, null, _iconProvider.Search);
+ }
+
+ List? highlightData = null;
+ int score = 0;
+
+ var currentSearch = query[Keywords.TitleSearch.Length..];
+
+ var results = currentCollection.Traverse(item => SettingsCheck(item) && FuzzySearch(item.Name, currentSearch, out highlightData, out score))
+ .Select(item => _resultCreator.CreateOneNoteItemResult(item, false, highlightData, score))
+ .ToList();
+
+ return results.Count != 0 ? results : _resultCreator.NoMatchesFound(showSingleResults);
+ }
+
+ private List RecentPages(string query)
+ {
+ int count = 10; // TODO: Ideally this should match PowerToysRunSettings.MaxResultsToShow
+ /* var settingsUtils = new SettingsUtils();
+ var generalSettings = settingsUtils.GetSettings();*/
+ if (query.Length > Keywords.RecentPages.Length && int.TryParse(query[Keywords.RecentPages.Length..], out int userChosenCount))
+ {
+ count = userChosenCount;
+ }
+
+ return OneNoteApplication.GetNotebooks()
+ .GetPages()
+ .Where(SettingsCheck)
+ .OrderByDescending(pg => pg.LastModified)
+ .Take(count)
+ .Select(_resultCreator.CreateRecentPageResult)
+ .ToList();
+ }
+
+ private bool FuzzySearch(string itemName, string search, out List highlightData, out int score)
+ {
+ var matchResult = StringMatcher.FuzzySearch(search, itemName);
+ highlightData = matchResult.MatchData;
+ score = matchResult.Score;
+ return matchResult.IsSearchPrecisionScoreMet();
+ }
+
+ private bool SettingsCheck(IOneNoteItem item)
+ {
+ bool success = true;
+ if (!_settings.ShowEncryptedSections && item is OneNoteSection section)
+ {
+ success = !section.Encrypted;
+ }
+
+ if (!_settings.ShowRecycleBins && item.IsInRecycleBin())
+ {
+ success = false;
+ }
+
+ return success;
+ }
+ }
+}
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook.color.png
new file mode 100644
index 000000000000..41c09e09b430
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook.dark.png
new file mode 100644
index 000000000000..243267b0a9e0
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook.light.png
new file mode 100644
index 000000000000..0b7aa0fee611
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_explorer.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_explorer.color.png
new file mode 100644
index 000000000000..50b77c223c77
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_explorer.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_explorer.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_explorer.dark.png
new file mode 100644
index 000000000000..ccf8eaeb4dd6
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_explorer.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_explorer.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_explorer.light.png
new file mode 100644
index 000000000000..1cc20b2847d8
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_explorer.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_new.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_new.color.png
new file mode 100644
index 000000000000..184e66695134
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_new.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_new.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_new.dark.png
new file mode 100644
index 000000000000..044399eb07e8
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_new.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_new.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_new.light.png
new file mode 100644
index 000000000000..7e45f313887e
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/notebook_new.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page.color.png
new file mode 100644
index 000000000000..475f806c9da4
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page.dark.png
new file mode 100644
index 000000000000..b6ab3493870a
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page.light.png
new file mode 100644
index 000000000000..d1e4c3914e8a
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_new.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_new.color.png
new file mode 100644
index 000000000000..bd209be1d453
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_new.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_new.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_new.dark.png
new file mode 100644
index 000000000000..990c51d379c4
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_new.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_new.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_new.light.png
new file mode 100644
index 000000000000..01400e4c6c66
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_new.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_recent.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_recent.color.png
new file mode 100644
index 000000000000..ed53432cc9b6
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_recent.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_recent.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_recent.dark.png
new file mode 100644
index 000000000000..68c9ea5248a3
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_recent.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_recent.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_recent.light.png
new file mode 100644
index 000000000000..400e969bf4ec
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/page_recent.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/recycle_bin.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/recycle_bin.color.png
new file mode 100644
index 000000000000..b79e0a85b372
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/recycle_bin.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/recycle_bin.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/recycle_bin.dark.png
new file mode 100644
index 000000000000..080cee64d2ea
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/recycle_bin.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/recycle_bin.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/recycle_bin.light.png
new file mode 100644
index 000000000000..b032988d4b72
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/recycle_bin.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/search.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/search.color.png
new file mode 100644
index 000000000000..a8c3c76d2879
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/search.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/search.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/search.dark.png
new file mode 100644
index 000000000000..b960dea2beb2
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/search.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/search.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/search.light.png
new file mode 100644
index 000000000000..c64d7cd7688e
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/search.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section.color.png
new file mode 100644
index 000000000000..2c5e32055f89
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section.dark.png
new file mode 100644
index 000000000000..f10d2cdc86ca
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section.light.png
new file mode 100644
index 000000000000..f2939d998a20
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group.color.png
new file mode 100644
index 000000000000..96586e9967cd
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group.dark.png
new file mode 100644
index 000000000000..c20ca77fb1f6
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group.light.png
new file mode 100644
index 000000000000..4abcbb7460fc
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group_new.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group_new.color.png
new file mode 100644
index 000000000000..3ab0ac75125b
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group_new.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group_new.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group_new.dark.png
new file mode 100644
index 000000000000..727503860a37
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group_new.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group_new.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group_new.light.png
new file mode 100644
index 000000000000..ef4059ba5434
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_group_new.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_new.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_new.color.png
new file mode 100644
index 000000000000..4d9edb8fdd54
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_new.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_new.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_new.dark.png
new file mode 100644
index 000000000000..193ba2109137
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_new.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_new.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_new.light.png
new file mode 100644
index 000000000000..4e172bf693c6
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/section_new.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/sync.color.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/sync.color.png
new file mode 100644
index 000000000000..e09b7a6a5a5d
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/sync.color.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/sync.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/sync.dark.png
new file mode 100644
index 000000000000..30d68e57d252
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/sync.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/sync.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/sync.light.png
new file mode 100644
index 000000000000..39a386162401
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/sync.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/warning.dark.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/warning.dark.png
new file mode 100644
index 000000000000..017f2a089f01
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/warning.dark.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/warning.light.png b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/warning.light.png
new file mode 100644
index 000000000000..ab87991340d2
Binary files /dev/null and b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Images/warning.light.png differ
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Main.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Main.cs
index 129350f51c7f..9c132d5858b2 100644
--- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Main.cs
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Main.cs
@@ -2,53 +2,41 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
-
-using LazyCache;
-using ManagedCommon;
+using System.Windows.Controls;
+using Microsoft.PowerToys.Run.Plugin.OneNote.Components;
using Microsoft.PowerToys.Run.Plugin.OneNote.Properties;
-using ScipBe.Common.Office.OneNote;
-using Windows.Win32;
-using Windows.Win32.Foundation;
-using Windows.Win32.UI.WindowsAndMessaging;
+using Microsoft.PowerToys.Settings.UI.Library;
+using Odotocodot.OneNote.Linq;
using Wox.Plugin;
+using Timer = System.Timers.Timer;
namespace Microsoft.PowerToys.Run.Plugin.OneNote
{
///
/// A power launcher plugin to search across time zones.
///
- public class Main : IPlugin, IDelayedExecutionPlugin, IPluginI18n
+ public class Main : IPlugin, IDelayedExecutionPlugin, IPluginI18n, ISettingProvider, IContextMenu, IDisposable
{
+ private readonly Timer _comObjectTimeout = new();
+
+ private readonly OneNoteSettings _settings = new();
+
///
/// A value indicating if the OneNote interop library was able to successfully initialize.
///
private bool _oneNoteInstalled;
- ///
- /// LazyCache CachingService instance to speed up repeated queries.
- ///
- private CachingService? _cache;
-
///
/// The initial context for this plugin (contains API and meta-data)
///
private PluginInitContext? _context;
- ///
- /// The path to the icon for each result
- ///
- private string _iconPath;
+ private SearchManager? _searchManager;
+ private IconProvider? _iconProvider;
+ private ResultCreator? _resultCreator;
- ///
- /// Initializes a new instance of the class.
- ///
- public Main()
- {
- UpdateIconPath(Theme.Light);
- }
+ private bool _disposed;
///
/// Gets the localized name.
@@ -65,6 +53,8 @@ public Main()
///
public static string PluginID => "0778F0C264114FEC8A3DF59447CF0A74";
+ public IEnumerable AdditionalOptions => _settings.AdditionalOptions;
+
///
/// Initialize the plugin with the given
///
@@ -72,14 +62,11 @@ public Main()
public void Init(PluginInitContext context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
-
try
{
- _ = OneNoteProvider.PageItems.Any();
- _oneNoteInstalled = true;
-
- _cache = new CachingService();
- _cache.DefaultCachePolicy.DefaultCacheDurationSeconds = (int)TimeSpan.FromDays(1).TotalSeconds;
+ OneNoteApplication.InitComObject();
+ _oneNoteInstalled = OneNoteApplication.HasComObject;
+ OneNoteApplication.ReleaseComObject();
}
catch (COMException)
{
@@ -87,8 +74,13 @@ public void Init(PluginInitContext context)
_oneNoteInstalled = false;
}
- _context.API.ThemeChanged += OnThemeChanged;
- UpdateIconPath(_context.API.GetCurrentTheme());
+ _comObjectTimeout.Elapsed += ComObjectTimer_Elapsed;
+ _comObjectTimeout.AutoReset = false;
+ _comObjectTimeout.Enabled = false;
+
+ _iconProvider = new IconProvider(_context, _settings);
+ _resultCreator = new ResultCreator(_context, _settings, _iconProvider);
+ _searchManager = new SearchManager(_context, _settings, _iconProvider, _resultCreator);
}
///
@@ -98,14 +90,29 @@ public void Init(PluginInitContext context)
/// A filtered list, can be empty when nothing was found
public List Query(Query query)
{
- if (!_oneNoteInstalled || query is null || string.IsNullOrWhiteSpace(query.Search) || _cache is null)
+ if (_resultCreator is null)
+ {
+ return [];
+ }
+
+ if (!_oneNoteInstalled)
+ {
+ return _resultCreator.OneNoteNotInstalled();
+ }
+
+ if (string.IsNullOrWhiteSpace(query.Search))
+ {
+ return _resultCreator.EmptyQuery(query);
+ }
+
+ // If a COM Object has been acquired results return faster
+ if (OneNoteApplication.HasComObject)
{
- return new List(0);
+ ResetTimeout();
+ return _searchManager is null ? [] : _searchManager.Query(query);
}
- // If there's cached results for this query, return immediately, otherwise wait for delayedExecution.
- var results = _cache.Get>(query.Search);
- return results ?? Query(query, false);
+ return [];
}
///
@@ -116,29 +123,28 @@ public List Query(Query query)
/// A filtered list, can be empty when nothing was found
public List Query(Query query, bool delayedExecution)
{
- if (!delayedExecution || !_oneNoteInstalled || query is null || string.IsNullOrWhiteSpace(query.Search) || _cache is null)
+ if (_resultCreator is null)
{
- return new List(0);
+ return [];
}
- // Get results from cache if they already exist for this query, otherwise query OneNote. Results will be cached for 1 day.
- var results = _cache.GetOrAdd(query.Search, () =>
+ if (!_oneNoteInstalled)
{
- var pages = OneNoteProvider.FindPages(query.Search);
+ return _resultCreator.OneNoteNotInstalled();
+ }
- return pages.Select(p => new Result
- {
- IcoPath = _iconPath,
- Title = p.Name,
- QueryTextDisplay = p.Name,
- SubTitle = @$"{p.Notebook.Name}\{p.Section.Name}",
- Action = (_) => OpenPageInOneNote(p),
- ContextData = p,
- ToolTipData = new ToolTipData(Name, @$"{p.Notebook.Name}\{p.Section.Name}\{p.Name}"),
- }).ToList();
- });
-
- return results;
+ if (string.IsNullOrWhiteSpace(query.Search))
+ {
+ return _resultCreator.EmptyQuery(query);
+ }
+
+ if (OneNoteApplication.HasComObject)
+ {
+ return [];
+ }
+
+ ResetTimeout();
+ return _searchManager is null ? [] : _searchManager.Query(query);
}
///
@@ -153,48 +159,46 @@ public List Query(Query query, bool delayedExecution)
/// A translated plugin description.
public string GetTranslatedPluginDescription() => Resources.PluginDescription;
- private void OnThemeChanged(Theme currentTheme, Theme newTheme)
+ private void ComObjectTimer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
{
- UpdateIconPath(newTheme);
+ OneNoteApplication.ReleaseComObject();
}
- [MemberNotNull(nameof(_iconPath))]
- private void UpdateIconPath(Theme theme)
+ private void ResetTimeout()
{
- _iconPath = theme == Theme.Light || theme == Theme.HighContrastWhite ? "Images/oneNote.light.png" : "Images/oneNote.dark.png";
+ _comObjectTimeout.Interval = _settings.ComObjectTimeout;
+ _comObjectTimeout.Enabled = true;
}
- private bool OpenPageInOneNote(IOneNoteExtPage page)
+ public List LoadContextMenus(Result selectedResult)
{
- try
- {
- page.OpenInOneNote();
- ShowOneNote();
- return true;
- }
- catch (COMException)
- {
- // The page, section or even notebook may no longer exist, ignore and do nothing.
- return false;
- }
+ return _resultCreator is null ? [] : _resultCreator.LoadContextMenu(selectedResult);
}
- ///
- /// Brings OneNote to the foreground and restores it if minimized.
- ///
- private void ShowOneNote()
+ public Control CreateSettingPanel() => throw new NotImplementedException();
+
+ public void UpdateSettings(PowerLauncherPluginSettings settings) => _settings.UpdateSettings(settings);
+
+ protected virtual void Dispose(bool disposing)
{
- using var process = Process.GetProcessesByName("onenote").FirstOrDefault();
- if (process?.MainWindowHandle != null)
+ if (!_disposed)
{
- HWND handle = (HWND)process.MainWindowHandle;
- if (PInvoke.IsIconic(handle))
+ if (disposing)
{
- PInvoke.ShowWindow(handle, SHOW_WINDOW_CMD.SW_RESTORE);
+ _iconProvider?.Cleanup();
+ _comObjectTimeout?.Dispose();
+ OneNoteApplication.ReleaseComObject();
}
- PInvoke.SetForegroundWindow(handle);
+ _disposed = true;
}
}
+
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
}
}
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Microsoft.PowerToys.Run.Plugin.OneNote.csproj b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Microsoft.PowerToys.Run.Plugin.OneNote.csproj
index 4cc88d06e631..f478f2100aa0 100644
--- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Microsoft.PowerToys.Run.Plugin.OneNote.csproj
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Microsoft.PowerToys.Run.Plugin.OneNote.csproj
@@ -17,7 +17,7 @@
8981
-
+
false
@@ -34,13 +34,12 @@
-
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
@@ -68,10 +67,7 @@
-
- PreserveNewest
-
-
+
PreserveNewest
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Properties/Resources.Designer.cs b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Properties/Resources.Designer.cs
index f8a926537641..20b7a89eec89 100644
--- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Properties/Resources.Designer.cs
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Properties/Resources.Designer.cs
@@ -60,6 +60,231 @@ internal Resources() {
}
}
+ ///
+ /// Looks up a localized string similar to Create colored icons for notebooks and sections.
+ ///
+ internal static string CreateColoredIconsForNotebooksSections {
+ get {
+ return ResourceManager.GetString("CreateColoredIconsForNotebooksSections", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Create notebook: "{0}".
+ ///
+ internal static string CreateNotebook {
+ get {
+ return ResourceManager.GetString("CreateNotebook", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Create page: "{0}".
+ ///
+ internal static string CreatePage {
+ get {
+ return ResourceManager.GetString("CreatePage", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Create section: "{0}".
+ ///
+ internal static string CreateSection {
+ get {
+ return ResourceManager.GetString("CreateSection", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Create section group: "{0}".
+ ///
+ internal static string CreateSectionGroup {
+ get {
+ return ResourceManager.GetString("CreateSectionGroup", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Display unread icon.
+ ///
+ internal static string DisplayUnreadIcon {
+ get {
+ return ResourceManager.GetString("DisplayUnreadIcon", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Indicate an item has unread changes with: •.
+ ///
+ internal static string DisplayUnreadIconDescription {
+ get {
+ return ResourceManager.GetString("DisplayUnreadIconDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invalid query.
+ ///
+ internal static string InvalidQuery {
+ get {
+ return ResourceManager.GetString("InvalidQuery", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The first character of the search must be a letter or a digit.
+ ///
+ internal static string InvalidQueryDescription {
+ get {
+ return ResourceManager.GetString("InvalidQueryDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Last Modified: {0:F}.
+ ///
+ internal static string LastModified {
+ get {
+ return ResourceManager.GetString("LastModified", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Locked.
+ ///
+ internal static string Locked {
+ get {
+ return ResourceManager.GetString("Locked", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to New quick note.
+ ///
+ internal static string NewQuickNote {
+ get {
+ return ResourceManager.GetString("NewQuickNote", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to No items found. Type a valid name to create one.
+ ///
+ internal static string NoItemsFoundTypeValidName {
+ get {
+ return ResourceManager.GetString("NoItemsFoundTypeValidName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to No matches found.
+ ///
+ internal static string NoMatchesFound {
+ get {
+ return ResourceManager.GetString("NoMatchesFound", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Try searching something else, or syncing your notebooks..
+ ///
+ internal static string NoMatchesFoundDescription {
+ get {
+ return ResourceManager.GetString("NoMatchesFoundDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Notebook names cannot contain: {0}.
+ ///
+ internal static string NotebookNamesCannotContain {
+ get {
+ return ResourceManager.GetString("NotebookNamesCannotContain", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to OneNote COM object timeout.
+ ///
+ internal static string OneNoteComObjectTimeout {
+ get {
+ return ResourceManager.GetString("OneNoteComObjectTimeout", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The delay in milliseconds before the OneNote COM object is removed from memory after user input. Higher values reduce the chances needed for performing the slow action of getting the COM object, but keep the COM object in memory for longer..
+ ///
+ internal static string OneNoteComObjectTimeoutDescription {
+ get {
+ return ResourceManager.GetString("OneNoteComObjectTimeoutDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to OneNote is not installed.
+ ///
+ internal static string OneNoteNotInstalled {
+ get {
+ return ResourceManager.GetString("OneNoteNotInstalled", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Please install OneNote to use this plugin.
+ ///
+ internal static string OneNoteNotInstalledDescription {
+ get {
+ return ResourceManager.GetString("OneNoteNotInstalledDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Open and sync.
+ ///
+ internal static string OpenAndSync {
+ get {
+ return ResourceManager.GetString("OpenAndSync", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Open in notebook explorer.
+ ///
+ internal static string OpenInNotebookExplorer {
+ get {
+ return ResourceManager.GetString("OpenInNotebookExplorer", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Open and sync notebooks.
+ ///
+ internal static string OpenSyncNotebooks {
+ get {
+ return ResourceManager.GetString("OpenSyncNotebooks", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Open "{0}" in OneNote.
+ ///
+ internal static string OpenXInOneNote {
+ get {
+ return ResourceManager.GetString("OpenXInOneNote", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Path: {0}.
+ ///
+ internal static string Path {
+ get {
+ return ResourceManager.GetString("Path", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Searches your local OneNote notebooks. This plugin requires the OneNote desktop app which is included in Microsoft Office.
///
@@ -77,5 +302,158 @@ internal static string PluginTitle {
return ResourceManager.GetString("PluginTitle", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to Now searching by title..
+ ///
+ internal static string SearchingByTitle {
+ get {
+ return ResourceManager.GetString("SearchingByTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Now searching by title in "{0}".
+ ///
+ internal static string SearchingByTitleInX {
+ get {
+ return ResourceManager.GetString("SearchingByTitleInX", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Now searching all pages in "{0}".
+ ///
+ internal static string SearchingPagesInX {
+ get {
+ return ResourceManager.GetString("SearchingPagesInX", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Use '{0}' to search this item. Use '{1}' to search by title in this item.
+ ///
+ internal static string SearchInItemInfo {
+ get {
+ return ResourceManager.GetString("SearchInItemInfo", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Search OneNote pages.
+ ///
+ internal static string SearchOneNotePages {
+ get {
+ return ResourceManager.GetString("SearchOneNotePages", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Section group names cannot contain: {0}.
+ ///
+ internal static string SectionGroupNamesCannotContain {
+ get {
+ return ResourceManager.GetString("SectionGroupNamesCannotContain", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Section names cannot contain: {0}.
+ ///
+ internal static string SectionNamesCannotContain {
+ get {
+ return ResourceManager.GetString("SectionNamesCannotContain", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Show encrypted sections.
+ ///
+ internal static string ShowEncryptedSections {
+ get {
+ return ResourceManager.GetString("ShowEncryptedSections", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to When using "{0}" show encrypted sections, if the section has been unlocked, allow temporary access..
+ ///
+ internal static string ShowEncryptedSectionsDescription {
+ get {
+ return ResourceManager.GetString("ShowEncryptedSectionsDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Show recycle bin.
+ ///
+ internal static string ShowRecycleBin {
+ get {
+ return ResourceManager.GetString("ShowRecycleBin", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to When using "{0}" show items that are in the recycle bin..
+ ///
+ internal static string ShowRecycleBinDescription {
+ get {
+ return ResourceManager.GetString("ShowRecycleBinDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Unlocked.
+ ///
+ internal static string Unlocked {
+ get {
+ return ResourceManager.GetString("Unlocked", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to View notebook explorer.
+ ///
+ internal static string ViewNotebookExplorer {
+ get {
+ return ResourceManager.GetString("ViewNotebookExplorer", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Type "{0}" or select this option to search by notebook structure.
+ ///
+ internal static string ViewNotebookExplorerDescription {
+ get {
+ return ResourceManager.GetString("ViewNotebookExplorerDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to View recent pages.
+ ///
+ internal static string ViewRecentPages {
+ get {
+ return ResourceManager.GetString("ViewRecentPages", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Type "{0}" or select this option to see recently modified pages.
+ ///
+ internal static string ViewRecentPagesDescription {
+ get {
+ return ResourceManager.GetString("ViewRecentPagesDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Visit the Microsoft Store.
+ ///
+ internal static string VisitMicrosoftStore {
+ get {
+ return ResourceManager.GetString("VisitMicrosoftStore", resourceCulture);
+ }
+ }
}
}
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Properties/Resources.resx b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Properties/Resources.resx
index 0419897f3d2a..bb3d78f06e36 100644
--- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Properties/Resources.resx
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/Properties/Resources.resx
@@ -123,4 +123,138 @@
Searches your local OneNote notebooks. This plugin requires the OneNote desktop app which is included in Microsoft Office
+
+ Now searching by title.
+
+
+ Open "{0}" in OneNote
+
+
+ Now searching by title in "{0}"
+
+
+ Now searching all pages in "{0}"
+
+
+ Use '{0}' to search this item. Use '{1}' to search by title in this item
+ 0 and 1 are static keywords used by then plugin.
+
+
+ Display unread icon
+
+
+ Indicate an item has unread changes with: •
+
+
+ Show encrypted sections
+
+
+ When using "{0}" show encrypted sections, if the section has been unlocked, allow temporary access.
+ 0 is the NotebookExplorer static keyword
+
+
+ Show recycle bin
+
+
+ When using "{0}" show items that are in the recycle bin.
+ 0 is the NotebookExplorer static keyword
+
+
+ OneNote COM object timeout
+
+
+ The delay in milliseconds before the OneNote COM object is removed from memory after user input. Higher values reduce the chances needed for performing the slow action of getting the COM object, but keep the COM object in memory for longer.
+
+
+ Create colored icons for notebooks and sections
+
+
+ Search OneNote pages
+
+
+ View notebook explorer
+
+
+ Type "{0}" or select this option to search by notebook structure
+ 0 is the NotebookExplorer static keyword
+
+
+ View recent pages
+
+
+ Type "{0}" or select this option to see recently modified pages
+
+
+ New quick note
+
+
+ Open and sync notebooks
+
+
+ Create page: "{0}"
+ 0 is a user typed name
+
+
+ Path: {0}
+
+
+ Create section: "{0}"
+ 0 is a user typed name
+
+
+ Section names cannot contain: {0}
+
+
+ Create section group: "{0}"
+ 0 is a user typed name
+
+
+ Section group names cannot contain: {0}
+
+
+ Create notebook: "{0}"
+ 0 is a user typed name
+
+
+ Notebook names cannot contain: {0}
+
+
+ Open and sync
+
+
+ Open in notebook explorer
+
+
+ Visit the Microsoft Store
+
+
+ No matches found
+
+
+ Try searching something else, or syncing your notebooks.
+
+
+ Invalid query
+
+
+ The first character of the search must be a letter or a digit
+
+
+ OneNote is not installed
+
+
+ Please install OneNote to use this plugin
+
+
+ No items found. Type a valid name to create one
+
+
+ Last Modified: {0:F}
+
+
+ Locked
+
+
+ Unlocked
+
\ No newline at end of file
diff --git a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/plugin.json b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/plugin.json
index 88874001b66c..f7853b8e4621 100644
--- a/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/plugin.json
+++ b/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.OneNote/plugin.json
@@ -4,8 +4,8 @@
"ActionKeyword": "o:",
"IsGlobal": true,
"Name": "OneNote",
- "Author": "palenshus",
- "Version": "1.0.0",
+ "Author": "palenshus and Odotocodot",
+ "Version": "2.0.0",
"Language": "csharp",
"Website": "https://aka.ms/PowerToys",
"ExecuteFileName": "Microsoft.PowerToys.Run.Plugin.OneNote.dll",
diff --git a/src/modules/launcher/PowerLauncher/PowerLauncher.csproj b/src/modules/launcher/PowerLauncher/PowerLauncher.csproj
index 07852dc804c0..4d507fa2ed96 100644
--- a/src/modules/launcher/PowerLauncher/PowerLauncher.csproj
+++ b/src/modules/launcher/PowerLauncher/PowerLauncher.csproj
@@ -1,6 +1,6 @@
-
+
@@ -44,15 +44,14 @@
-
+
-
-
+
- runtime
+ runtime
diff --git a/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj b/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj
index e9179e6ddf90..cbda9a5adc7c 100644
--- a/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj
+++ b/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj
@@ -31,6 +31,7 @@
+