// 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.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using LazyCache; using ManagedCommon; 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 Wox.Plugin; namespace Microsoft.PowerToys.Run.Plugin.OneNote { /// /// A power launcher plugin to search across time zones. /// public class Main : IPlugin, IDelayedExecutionPlugin, IPluginI18n { /// /// 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; /// /// Initializes a new instance of the class. /// public Main() { UpdateIconPath(Theme.Light); } /// /// Gets the localized name. /// public string Name => Resources.PluginTitle; /// /// Gets the localized description. /// public string Description => Resources.PluginDescription; /// /// Initialize the plugin with the given /// /// The for this plugin 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; } catch (COMException) { // OneNote isn't installed, plugin won't do anything. _oneNoteInstalled = false; } _context.API.ThemeChanged += OnThemeChanged; UpdateIconPath(_context.API.GetCurrentTheme()); } /// /// Return a filtered list, based on the given query /// /// The query to filter the list /// 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) { return new List(0); } // 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 a filtered list, based on the given query /// /// The query to filter the list /// False if this is the first pass through plugins, true otherwise. Slow plugins should run delayed. /// 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) { return new List(0); } // 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, () => { var pages = OneNoteProvider.FindPages(query.Search); 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; } /// /// Return the translated plugin title. /// /// A translated plugin title. public string GetTranslatedPluginTitle() => Resources.PluginTitle; /// /// Return the translated plugin description. /// /// A translated plugin description. public string GetTranslatedPluginDescription() => Resources.PluginDescription; private void OnThemeChanged(Theme currentTheme, Theme newTheme) { UpdateIconPath(newTheme); } [MemberNotNull(nameof(_iconPath))] private void UpdateIconPath(Theme theme) { _iconPath = theme == Theme.Light || theme == Theme.HighContrastWhite ? "Images/oneNote.light.png" : "Images/oneNote.dark.png"; } private bool OpenPageInOneNote(IOneNoteExtPage page) { try { page.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. /// private 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); } } } }