// 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);
}
}
}
}