From 28eb4c80f6ab6c1120cad27fc901d33d98dad5ee Mon Sep 17 00:00:00 2001 From: Union Palenshus Date: Wed, 29 Jun 2022 06:56:55 -0700 Subject: [PATCH] [PTRun][OneNote]Add query caching and delayedExecution (#18919) * Adding OneNote plugin for PowerToys Run * Updating to 3.0.1 dependency, updating md, spellcheck, ready for PR * Updating spelling and using localized string * Adding OneNote link to readme * Adding OneNote requirement to description * removing 'open' from description * Updating interop version, PR feedback * Adding query caching and delayedExecution to PT Run OneNote plugin * Adding binaries to signing, and updating doc * Adding dependency nuget package binaries to installer * PR feedback and .editorconfig fix to ignore IDE rules that conflict with repo styling * Fixing spelling --- .github/actions/spell-check/expect.txt | 1 + .pipelines/ESRPSigning_core.json | 1 + .../modules/launcher/plugins/onenote.md | 4 +- installer/PowerToysSetup/Product.wxs | 2 +- src/.editorconfig | 90 ++++++++++++++++++- .../Main.cs | 75 ++++++++++++---- ...rosoft.PowerToys.Run.Plugin.OneNote.csproj | 1 + .../PowerLauncher/PowerLauncher.csproj | 1 + 8 files changed, 156 insertions(+), 19 deletions(-) diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index cb2563c8a8..d760cc1620 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -929,6 +929,7 @@ IObservable IOle iolewindowcontextsensitivehelp iomanip +IOne iostream IPackage IPath diff --git a/.pipelines/ESRPSigning_core.json b/.pipelines/ESRPSigning_core.json index b8a7fedff5..9c1625f529 100644 --- a/.pipelines/ESRPSigning_core.json +++ b/.pipelines/ESRPSigning_core.json @@ -188,6 +188,7 @@ "modules\\FileExplorerPreview\\Microsoft.Web.WebView2.Wpf.dll", "modules\\FileExplorerPreview\\WebView2Loader.dll", "modules\\launcher\\e_sqlite3.dll", + "modules\\launcher\\LazyCache.dll", "modules\\launcher\\SQLitePCLRaw.batteries_v2.dll", "modules\\launcher\\SQLitePCLRaw.core.dll", "modules\\launcher\\SQLitePCLRaw.provider.e_sqlite3.dll", diff --git a/doc/devdocs/modules/launcher/plugins/onenote.md b/doc/devdocs/modules/launcher/plugins/onenote.md index 08e96676a8..b0c50ebba1 100644 --- a/doc/devdocs/modules/launcher/plugins/onenote.md +++ b/doc/devdocs/modules/launcher/plugins/onenote.md @@ -9,6 +9,8 @@ The code itself is very simple, basically just a call into OneNote interop via t var pages = OneNoteProvider.FindPages(query.Search); ``` +The query results will be cached for 1 day, and if cached results are found they'll be returned in the initial `Query()` call, otherwise OneNote itself will be queried in the `delayedExecution:true` overload. + If the user actions on a result, it'll open it in the OneNote app, and restore and/or focus the app as well if necessary. ```csharp @@ -33,4 +35,4 @@ catch (COMException) // OneNote isn't installed, plugin won't do anything. _oneNoteInstalled = false; } -``` \ No newline at end of file +``` diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index d61ba8bb5a..abf7d2ca2a 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -1697,7 +1697,7 @@ - + diff --git a/src/.editorconfig b/src/.editorconfig index d0aa049c64..6f461f661f 100644 --- a/src/.editorconfig +++ b/src/.editorconfig @@ -7,4 +7,92 @@ dotnet_diagnostic.SA1201.severity = none dotnet_diagnostic.CA1303.severity = suggestion # CA1051: Do not declare visible instance fields -dotnet_code_quality.ca1051.exclude_structs = true \ No newline at end of file +dotnet_code_quality.ca1051.exclude_structs = true +csharp_using_directive_placement = inside_namespace:warning +csharp_prefer_simple_using_statement = true:suggestion +csharp_prefer_braces = true:silent +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = when_on_single_line:suggestion +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_throw_expression = true:suggestion +csharp_indent_labels = one_less_than_current +csharp_style_prefer_null_check_over_type_check = true:suggestion +[*.{cs,vb}] +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_object_initializer = false:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_return = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +dotnet_style_namespace_match_folder = true:suggestion +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +indent_size = 4 +end_of_line = crlf + +# IDE0065: using directive placement +dotnet_diagnostic.IDE0065.severity = none + +# IDE0009: Add this or Me qualification +dotnet_diagnostic.IDE0009.severity = none 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 87601357b5..0e45d6063a 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 @@ -5,6 +5,7 @@ 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; @@ -18,13 +19,18 @@ namespace Microsoft.PowerToys.Run.Plugin.OneNote /// /// A power launcher plugin to search across time zones. /// - public class Main : IPlugin, IPluginI18n + 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) /// @@ -65,6 +71,9 @@ namespace Microsoft.PowerToys.Run.Plugin.OneNote { _ = OneNoteProvider.PageItems.Any(); _oneNoteInstalled = true; + + _cache = new CachingService(); + _cache.DefaultCachePolicy.DefaultCacheDurationSeconds = (int)TimeSpan.FromDays(1).TotalSeconds; } catch (COMException) { @@ -83,28 +92,47 @@ namespace Microsoft.PowerToys.Run.Plugin.OneNote /// A filtered list, can be empty when nothing was found public List Query(Query query) { - if (!_oneNoteInstalled || query is null || string.IsNullOrWhiteSpace(query.Search)) + if (!_oneNoteInstalled || query is null || string.IsNullOrWhiteSpace(query.Search) || _cache is null) { return new List(0); } - var pages = OneNoteProvider.FindPages(query.Search); + // 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 pages.Select(p => new Result + /// + /// 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) { - IcoPath = _iconPath, - Title = p.Name, - QueryTextDisplay = p.Name, - SubTitle = @$"{p.Notebook.Name}\{p.Section.Name}", - Action = (_) => + 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 { - p.OpenInOneNote(); - ShowOneNote(); - return true; - }, - ContextData = p, - ToolTipData = new ToolTipData(Name, @$"{p.Notebook.Name}\{p.Section.Name}\{p.Name}"), - }).ToList(); + 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; } /// @@ -130,6 +158,21 @@ namespace Microsoft.PowerToys.Run.Plugin.OneNote _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. /// 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 c988c975af..18a0b87fcb 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 @@ -52,6 +52,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/modules/launcher/PowerLauncher/PowerLauncher.csproj b/src/modules/launcher/PowerLauncher/PowerLauncher.csproj index 578dca1f85..ff472f28c4 100644 --- a/src/modules/launcher/PowerLauncher/PowerLauncher.csproj +++ b/src/modules/launcher/PowerLauncher/PowerLauncher.csproj @@ -81,6 +81,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive