diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..11a0bcdf62c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,146 @@ +# To learn more about .editorconfig see https://aka.ms/editorconfigdocs +############################### +# Core EditorConfig Options # +############################### +# All files +[*] +indent_style = space + +# XML project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 + +# XML config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 + +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 +insert_final_newline = true +charset = utf-8-bom +############################### +# .NET Coding Conventions # +############################### +[*.{cs,vb}] +# Organize usings +dotnet_sort_system_directives_first = true +# this. preferences +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_event = false:silent +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_readonly_field = true:suggestion +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +############################### +# Naming Conventions # +############################### +# Style Definitions +dotnet_naming_style.pascal_case_style.capitalization = pascal_case +# Use PascalCase for constant fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.applicable_accessibilities = * +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 2 +end_of_line = crlf +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_diagnostic.CA1416.severity = silent +############################### +# C# Coding Conventions # +############################### +[*.cs] +dotnet_diagnostics.VSTHRD200.severity = none # VSTHRD200: Use "Async" suffix for async methods +dotnet_analyzer_diagnostic.VSTHRD200.severity = none # VSTHRD200: Use "Async" suffix for async methods +# var preferences +csharp_style_var_for_built_in_types = true:silent +csharp_style_var_when_type_is_apparent = true:silent +csharp_style_var_elsewhere = true:silent +# Expression-bodied members +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 = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +# Pattern matching preferences +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +# Null-checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion +# Expression-level preferences +csharp_prefer_braces = true:silent +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +############################### +# C# Formatting Rules # +############################### +# New line preferences +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true +# Indentation preferences +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left +# Space preferences +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +# Wrapping preferences +csharp_preserve_single_line_statements = true +csharp_preserve_single_line_blocks = true +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_style_namespace_declarations = block_scoped:silent +csharp_style_prefer_method_group_conversion = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +############################### +# VB Coding Conventions # +############################### +[*.vb] +# Modifier preferences +visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index 5bca087b879..bd77ea7cf08 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -1,4 +1,4 @@ -using Microsoft.Win32; +using Microsoft.Win32; using Squirrel; using System; using System.IO; @@ -127,7 +127,7 @@ public void CreateUninstallerEntry() using (var portabilityUpdater = NewUpdateManager()) { - portabilityUpdater.CreateUninstallerRegistryEntry(); + _ = portabilityUpdater.CreateUninstallerRegistryEntry(); } } diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj index fdd23a0d2cc..9f9fa8ff52b 100644 --- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj +++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj @@ -56,7 +56,7 @@ - + diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs index 1c0013db18c..ffba6ce61ea 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs @@ -69,7 +69,13 @@ public List LoadContextMenus(Result selectedResult) private static readonly JsonSerializerOptions options = new() { PropertyNameCaseInsensitive = true, +#pragma warning disable SYSLIB0020 + // IgnoreNullValues is obsolete, but the replacement JsonIgnoreCondition.WhenWritingNull still + // deserializes null, instead of ignoring it and leaving the default (empty list). We can change the behaviour + // to accept null and fallback to a default etc, or just keep IgnoreNullValues for now + // see: https://github.com/dotnet/runtime/issues/39152 IgnoreNullValues = true, +#pragma warning restore SYSLIB0020 // Type or member is obsolete Converters = { new JsonObjectConverter() @@ -82,7 +88,7 @@ public List LoadContextMenus(Result selectedResult) }; private Dictionary Settings { get; set; } - private Dictionary _settingControls = new(); + private readonly Dictionary _settingControls = new(); private async Task> DeserializedResultAsync(Stream output) { @@ -535,4 +541,4 @@ public void UpdateSettings(Dictionary settings) } } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 134c3c002dc..7f8eb024a16 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -74,7 +74,7 @@ public static async ValueTask DisposePluginsAsync() } } - public static async Task ReloadData() + public static async Task ReloadDataAsync() { await Task.WhenAll(AllPlugins.Select(plugin => plugin.Plugin switch { @@ -109,7 +109,7 @@ public static void LoadPlugins(PluginsSettings settings) /// Call initialize for all plugins /// /// return the list of failed to init plugins or null for none - public static async Task InitializePlugins(IPublicAPI api) + public static async Task InitializePluginsAsync(IPublicAPI api) { API = api; var failedPlugins = new ConcurrentQueue(); @@ -327,4 +327,4 @@ public static void ReplaceActionKeyword(string id, string oldActionKeyword, stri } } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs index b3d56221a71..7521742636a 100644 --- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -11,7 +11,6 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; -using System.Diagnostics; using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher.Core.Plugin @@ -41,14 +40,6 @@ public static IEnumerable DotNetPlugins(List source) var milliseconds = Stopwatch.Debug( $"|PluginsLoader.DotNetPlugins|Constructor init cost for {metadata.Name}", () => { -#if DEBUG - var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath); - var assembly = assemblyLoader.LoadAssemblyAndDependencies(); - var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, - typeof(IAsyncPlugin)); - - var plugin = Activator.CreateInstance(type) as IAsyncPlugin; -#else Assembly assembly = null; IAsyncPlugin plugin = null; @@ -62,6 +53,12 @@ public static IEnumerable DotNetPlugins(List source) plugin = Activator.CreateInstance(type) as IAsyncPlugin; } +#if DEBUG + catch (Exception e) + { + throw; + } +#else catch (Exception e) when (assembly == null) { Log.Exception($"|PluginsLoader.DotNetPlugins|Couldn't load assembly for the plugin: {metadata.Name}", e); @@ -79,6 +76,7 @@ public static IEnumerable DotNetPlugins(List source) Log.Exception($"|PluginsLoader.DotNetPlugins|The following plugin has errored and can not be loaded: <{metadata.Name}>", e); } #endif + if (plugin == null) { erroredPlugins.Add(metadata.Name); @@ -98,7 +96,7 @@ public static IEnumerable DotNetPlugins(List source) + (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ") + "errored and cannot be loaded:"; - Task.Run(() => + _ = Task.Run(() => { MessageBox.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + $"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" + diff --git a/Flow.Launcher.Core/Properties/AssemblyInfo.cs b/Flow.Launcher.Core/Properties/AssemblyInfo.cs index 40017c46c7c..ad60e2c9f53 100644 --- a/Flow.Launcher.Core/Properties/AssemblyInfo.cs +++ b/Flow.Launcher.Core/Properties/AssemblyInfo.cs @@ -1,3 +1,3 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("Flow.Launcher.Test")] \ No newline at end of file +[assembly: InternalsVisibleTo("Flow.Launcher.Test")] diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index 21892303a90..205abcd34e0 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -102,7 +102,7 @@ public bool ChangeTheme(string theme) SetBlurForWindow(); } - catch (DirectoryNotFoundException e) + catch (DirectoryNotFoundException) { Log.Error($"|Theme.ChangeTheme|Theme <{theme}> path can't be found"); if (theme != defaultTheme) @@ -112,7 +112,7 @@ public bool ChangeTheme(string theme) } return false; } - catch (XamlParseException e) + catch (XamlParseException) { Log.Error($"|Theme.ChangeTheme|Theme <{theme}> fail to parse"); if (theme != defaultTheme) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 69b537b3914..976c4eec15b 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Net; using System.Net.Http; @@ -40,7 +40,7 @@ public async Task UpdateAppAsync(IPublicAPI api, bool silentUpdate = true) api.ShowMsg(api.GetTranslation("pleaseWait"), api.GetTranslation("update_flowlauncher_update_check")); - using var updateManager = await GitHubUpdateManager(GitHubRepository).ConfigureAwait(false); + using var updateManager = await GitHubUpdateManagerAsync(GitHubRepository).ConfigureAwait(false); // UpdateApp CheckForUpdate will return value only if the app is squirrel installed var newUpdateInfo = await updateManager.CheckForUpdate().NonNull().ConfigureAwait(false); @@ -115,7 +115,7 @@ private class GithubRelease } /// https://github.com/Squirrel/Squirrel.Windows/blob/master/src/Squirrel/UpdateManager.Factory.cs - private async Task GitHubUpdateManager(string repository) + private async Task GitHubUpdateManagerAsync(string repository) { var uri = new Uri(repository); var api = $"https://api.github.com/repos{uri.AbsolutePath}/releases"; @@ -145,4 +145,4 @@ public string NewVersinoTips(string version) } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Infrastructure/Exception/ExceptionFormatter.cs b/Flow.Launcher.Infrastructure/Exception/ExceptionFormatter.cs index 3849f6e30b0..40ac6b1216d 100644 --- a/Flow.Launcher.Infrastructure/Exception/ExceptionFormatter.cs +++ b/Flow.Launcher.Infrastructure/Exception/ExceptionFormatter.cs @@ -78,7 +78,7 @@ private static string CreateExceptionReport(System.Exception ex) sb.AppendLine(); sb.AppendLine("## Assemblies - " + AppDomain.CurrentDomain.FriendlyName); sb.AppendLine(); - foreach (var ass in AppDomain.CurrentDomain.GetAssemblies().OrderBy(o => o.GlobalAssemblyCache ? 50 : 0)) + foreach (var ass in AppDomain.CurrentDomain.GetAssemblies()) { sb.Append("* "); sb.Append(ass.FullName); @@ -166,7 +166,7 @@ private static List GetFrameworkVersionFromRegistry() } return result; } - catch (System.Exception e) + catch { return new List(); } diff --git a/Flow.Launcher.Infrastructure/Image/ImageHashGenerator.cs b/Flow.Launcher.Infrastructure/Image/ImageHashGenerator.cs index 7361330528a..2611e99e865 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageHashGenerator.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageHashGenerator.cs @@ -14,30 +14,23 @@ public class ImageHashGenerator : IImageHashGenerator { public string GetHashFromImage(ImageSource imageSource) { - if (!(imageSource is BitmapSource image)) + if (imageSource is not BitmapSource image) { return null; } try { - using (var outStream = new MemoryStream()) - { - // PngBitmapEncoder enc2 = new PngBitmapEncoder(); - // enc2.Frames.Add(BitmapFrame.Create(tt)); - - var enc = new JpegBitmapEncoder(); - var bitmapFrame = BitmapFrame.Create(image); - bitmapFrame.Freeze(); - enc.Frames.Add(bitmapFrame); - enc.Save(outStream); - var byteArray = outStream.GetBuffer(); - using (var sha1 = new SHA1CryptoServiceProvider()) - { - var hash = Convert.ToBase64String(sha1.ComputeHash(byteArray)); - return hash; - } - } + using var outStream = new MemoryStream(); + var enc = new JpegBitmapEncoder(); + var bitmapFrame = BitmapFrame.Create(image); + bitmapFrame.Freeze(); + enc.Frames.Add(bitmapFrame); + enc.Save(outStream); + var byteArray = outStream.GetBuffer(); + using var sha1 = SHA1.Create(); + var hash = Convert.ToBase64String(sha1.ComputeHash(byteArray)); + return hash; } catch { @@ -46,4 +39,4 @@ public string GetHashFromImage(ImageSource imageSource) } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index ac333d567b8..8c1d7d74fbf 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; @@ -13,11 +13,11 @@ namespace Flow.Launcher.Infrastructure.Image { public static class ImageLoader { - private static readonly ImageCache ImageCache = new ImageCache(); + private static readonly ImageCache ImageCache = new(); private static BinaryStorage> _storage; - private static readonly ConcurrentDictionary GuidToKey = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary GuidToKey = new(); private static IImageHashGenerator _hashGenerator; - private static bool EnableImageHash = true; + private static readonly bool EnableImageHash = true; public static ImageSource DefaultImage { get; } = new BitmapImage(new Uri(Constant.MissingImgIcon)); @@ -46,7 +46,7 @@ public static void Initialize() ImageCache[icon] = img; } - Task.Run(() => + _ = Task.Run(() => { Stopwatch.Normal("|ImageLoader.Initialize|Preload images cost", () => { @@ -243,7 +243,6 @@ public static ImageSource Load(string path, bool loadFullImage = false) ImageCache[path] = img; } - return img; } diff --git a/Flow.Launcher.Infrastructure/Properties/AssemblyInfo.cs b/Flow.Launcher.Infrastructure/Properties/AssemblyInfo.cs index 4cdadffc9c2..3c29d0dcb58 100644 --- a/Flow.Launcher.Infrastructure/Properties/AssemblyInfo.cs +++ b/Flow.Launcher.Infrastructure/Properties/AssemblyInfo.cs @@ -2,4 +2,5 @@ [assembly: InternalsVisibleTo("Flow.Launcher")] [assembly: InternalsVisibleTo("Flow.Launcher.Core")] -[assembly: InternalsVisibleTo("Flow.Launcher.Test")] \ No newline at end of file +[assembly: InternalsVisibleTo("Flow.Launcher.Test")] +[assembly: System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.19041.0")] diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs index 5205543b1d3..ea2d42773ea 100644 --- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs @@ -9,6 +9,7 @@ namespace Flow.Launcher.Infrastructure.Storage { +#pragma warning disable SYSLIB0011 // BinaryFormatter is obsolete. /// /// Stroage object using binary data /// Normally, it has better performance, but not readable @@ -113,4 +114,5 @@ public void Save(T data) } } } +#pragma warning restore SYSLIB0011 } diff --git a/Flow.Launcher.Plugin/AllowedLanguage.cs b/Flow.Launcher.Plugin/AllowedLanguage.cs index 827958a7b38..94c645d2761 100644 --- a/Flow.Launcher.Plugin/AllowedLanguage.cs +++ b/Flow.Launcher.Plugin/AllowedLanguage.cs @@ -1,33 +1,58 @@ namespace Flow.Launcher.Plugin { + /// + /// Allowed plugin languages + /// public static class AllowedLanguage { + /// + /// Python + /// public static string Python { get { return "PYTHON"; } } + /// + /// C# + /// public static string CSharp { get { return "CSHARP"; } } + /// + /// F# + /// public static string FSharp { get { return "FSHARP"; } } + /// + /// Standard .exe + /// public static string Executable { get { return "EXECUTABLE"; } } + /// + /// Determines if this language is a .NET language + /// + /// + /// public static bool IsDotNet(string language) { return language.ToUpper() == CSharp || language.ToUpper() == FSharp; } + /// + /// Determines if this language is supported + /// + /// + /// public static bool IsAllowed(string language) { return IsDotNet(language) @@ -35,4 +60,4 @@ public static bool IsAllowed(string language) || language.ToUpper() == Executable.ToUpper(); } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Plugin/BaseModel.cs b/Flow.Launcher.Plugin/BaseModel.cs index 5bb558702af..a4d666cedaf 100644 --- a/Flow.Launcher.Plugin/BaseModel.cs +++ b/Flow.Launcher.Plugin/BaseModel.cs @@ -4,14 +4,24 @@ namespace Flow.Launcher.Plugin { + /// + /// Base model for plugin classes + /// public class BaseModel : INotifyPropertyChanged { + /// + /// Property changed event handler + /// public event PropertyChangedEventHandler PropertyChanged; + /// + /// Invoked when a property changes + /// + /// [NotifyPropertyChangedInvocator] protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Plugin/EventHandler.cs b/Flow.Launcher.Plugin/EventHandler.cs index 4766685845a..009e1721c42 100644 --- a/Flow.Launcher.Plugin/EventHandler.cs +++ b/Flow.Launcher.Plugin/EventHandler.cs @@ -3,9 +3,24 @@ namespace Flow.Launcher.Plugin { + /// + /// Delegate for key down event + /// + /// public delegate void FlowLauncherKeyDownEventHandler(FlowLauncherKeyDownEventArgs e); + + /// + /// Delegate for query event + /// + /// public delegate void AfterFlowLauncherQueryEventHandler(FlowLauncherQueryEventArgs e); + /// + /// Delegate for drop events [unused?] + /// + /// + /// + /// public delegate void ResultItemDropEventHandler(Result result, IDataObject dropObject, DragEventArgs e); /// @@ -17,14 +32,30 @@ namespace Flow.Launcher.Plugin /// return true to continue handling, return false to intercept system handling public delegate bool FlowLauncherGlobalKeyboardEventHandler(int keyevent, int vkcode, SpecialKeyState state); + /// + /// Arguments container for the Key Down event + /// public class FlowLauncherKeyDownEventArgs { + /// + /// The actual query + /// public string Query { get; set; } + + /// + /// Relevant key events for this event + /// public KeyEventArgs keyEventArgs { get; set; } } + /// + /// Arguments container for the Query event + /// public class FlowLauncherQueryEventArgs { + /// + /// The actual query + /// public Query Query { get; set; } } } diff --git a/Flow.Launcher.Plugin/Interfaces/IAsyncReloadable.cs b/Flow.Launcher.Plugin/Interfaces/IAsyncReloadable.cs index bd4500a7ef6..3d5f44a0d2f 100644 --- a/Flow.Launcher.Plugin/Interfaces/IAsyncReloadable.cs +++ b/Flow.Launcher.Plugin/Interfaces/IAsyncReloadable.cs @@ -15,6 +15,10 @@ namespace Flow.Launcher.Plugin /// public interface IAsyncReloadable : IFeatures { + /// + /// Reload plugin data + /// + /// Task ReloadDataAsync(); } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 69057820ef8..41d062570f8 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -1,7 +1,8 @@ -using Flow.Launcher.Plugin.SharedModels; +using Flow.Launcher.Plugin.SharedModels; using JetBrains.Annotations; using System; using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Runtime.CompilerServices; using System.Threading; @@ -41,7 +42,7 @@ public interface IPublicAPI /// /// Copy Text to clipboard /// - /// Text to save on clipboard + /// Text to save on clipboard public void CopyToClipboard(string text); /// @@ -163,6 +164,7 @@ public interface IPublicAPI /// Download the specific url to a cretain file path /// /// URL to download file + /// path to save downloaded file /// place to store file /// Task showing the progress Task HttpDownloadAsync([NotNull] string url, [NotNull] string filePath, CancellationToken token = default); @@ -178,7 +180,7 @@ public interface IPublicAPI /// Remove ActionKeyword for specific plugin /// /// ID for plugin that needs to remove action keyword - /// The actionkeyword that is supposed to be removed + /// The actionkeyword that is supposed to be removed void RemoveActionKeyword(string pluginId, string oldActionKeyword); /// diff --git a/Flow.Launcher.Plugin/Interfaces/IReloadable.cs b/Flow.Launcher.Plugin/Interfaces/IReloadable.cs index bd1ad406efd..707f8d92c06 100644 --- a/Flow.Launcher.Plugin/Interfaces/IReloadable.cs +++ b/Flow.Launcher.Plugin/Interfaces/IReloadable.cs @@ -17,6 +17,9 @@ /// public interface IReloadable : IFeatures { + /// + /// Synchronously reload plugin data + /// void ReloadData(); } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Plugin/Properties/AssemblyInfo.cs b/Flow.Launcher.Plugin/Properties/AssemblyInfo.cs index 4cdadffc9c2..0a602a47293 100644 --- a/Flow.Launcher.Plugin/Properties/AssemblyInfo.cs +++ b/Flow.Launcher.Plugin/Properties/AssemblyInfo.cs @@ -2,4 +2,4 @@ [assembly: InternalsVisibleTo("Flow.Launcher")] [assembly: InternalsVisibleTo("Flow.Launcher.Core")] -[assembly: InternalsVisibleTo("Flow.Launcher.Test")] \ No newline at end of file +[assembly: InternalsVisibleTo("Flow.Launcher.Test")] diff --git a/Flow.Launcher.Plugin/Query.cs b/Flow.Launcher.Plugin/Query.cs index 3fcf3c1d78c..95547d27350 100644 --- a/Flow.Launcher.Plugin/Query.cs +++ b/Flow.Launcher.Plugin/Query.cs @@ -16,7 +16,9 @@ public Query(string rawQuery, string search, string[] terms, string[] searchTerm { Search = search; RawQuery = rawQuery; +#pragma warning disable CS0618 Terms = terms; +#pragma warning restore CS0618 SearchTerms = searchTerms; ActionKeyword = actionKeyword; } @@ -98,4 +100,4 @@ private string SplitSearch(int index) public override string ToString() => RawQuery; } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index f80b6c02846..35c491d35f8 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -6,7 +6,9 @@ namespace Flow.Launcher.Plugin { - + /// + /// Describes the result of a plugin + /// public class Result { @@ -65,6 +67,10 @@ public string IcoPath } } + /// + /// Delegate function, see + /// + /// public delegate ImageSource IconDelegate(); /// @@ -105,6 +111,9 @@ public string IcoPath /// public IList TitleHighlightData { get; set; } + /// + /// Deprecated as of Flow Launcher v1.9.1. Subtitle highlighting is no longer offered + /// [Obsolete("Deprecated as of Flow Launcher v1.9.1. Subtitle highlighting is no longer offered")] public IList SubTitleHighlightData { get; set; } @@ -178,10 +187,15 @@ public override string ToString() /// Show message as ToolTip on result SubTitle hover over /// public string SubTitleToolTip { get; set; } - + + /// + /// Run this result, asynchronously + /// + /// + /// public ValueTask ExecuteAsync(ActionContext context) { return AsyncAction?.Invoke(context) ?? ValueTask.FromResult(Action?.Invoke(context) ?? false); } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs index be33bd86c98..5cb3a171a67 100644 --- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs +++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs @@ -5,6 +5,9 @@ namespace Flow.Launcher.Plugin.SharedCommands { + /// + /// Commands that are useful to run on files... and folders! + /// public static class FilesFolders { private const string FileExplorerProgramName = "explorer"; @@ -53,10 +56,10 @@ public static void CopyAll(this string sourcePath, string targetPath) CopyAll(subdir.FullName, temppath); } } - catch (Exception e) + catch (Exception) { #if DEBUG - throw e; + throw; #else MessageBox.Show(string.Format("Copying path {0} has failed, it will now be deleted for consistency", targetPath)); RemoveFolderIfExists(targetPath); @@ -65,6 +68,13 @@ public static void CopyAll(this string sourcePath, string targetPath) } + /// + /// Check if the files and directories are identical between + /// and + /// + /// + /// + /// public static bool VerifyBothFolderFilesEqual(this string fromPath, string toPath) { try @@ -80,10 +90,10 @@ public static bool VerifyBothFolderFilesEqual(this string fromPath, string toPat return true; } - catch (Exception e) + catch (Exception) { #if DEBUG - throw e; + throw; #else MessageBox.Show(string.Format("Unable to verify folders and files between {0} and {1}", fromPath, toPath)); return false; @@ -92,6 +102,10 @@ public static bool VerifyBothFolderFilesEqual(this string fromPath, string toPat } + /// + /// Deletes a folder if it exists + /// + /// public static void RemoveFolderIfExists(this string path) { try @@ -99,26 +113,40 @@ public static void RemoveFolderIfExists(this string path) if (Directory.Exists(path)) Directory.Delete(path, true); } - catch (Exception e) + catch (Exception) { #if DEBUG - throw e; + throw; #else MessageBox.Show(string.Format("Not able to delete folder {0}, please go to the location and manually delete it", path)); #endif } } + /// + /// Checks if a directory exists + /// + /// + /// public static bool LocationExists(this string path) { return Directory.Exists(path); } + /// + /// Checks if a file exists + /// + /// + /// public static bool FileExists(this string filePath) { return File.Exists(filePath); } + /// + /// Open a directory window (using the OS's default handler, usually explorer) + /// + /// public static void OpenPath(string fileOrFolderPath) { var psi = new ProcessStartInfo { FileName = FileExplorerProgramName, UseShellExecute = true, Arguments = '"' + fileOrFolderPath + '"' }; @@ -127,16 +155,20 @@ public static void OpenPath(string fileOrFolderPath) if (LocationExists(fileOrFolderPath) || FileExists(fileOrFolderPath)) Process.Start(psi); } - catch (Exception e) + catch (Exception) { #if DEBUG - throw e; + throw; #else MessageBox.Show(string.Format("Unable to open the path {0}, please check if it exists", fileOrFolderPath)); #endif } } + /// + /// Open the folder that contains + /// + /// public static void OpenContainingFolder(string path) { Process.Start(FileExplorerProgramEXE, $" /select,\"{path}\""); diff --git a/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs b/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs index a2eea19a720..c18f8b90c69 100644 --- a/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs +++ b/Flow.Launcher.Plugin/SharedCommands/ShellCommand.cs @@ -1,6 +1,8 @@ -using System; +using System; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; +using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; @@ -87,7 +89,8 @@ public static void Execute(ProcessStartInfo info) /// /// Runs a windows command using the provided ProcessStartInfo using a custom execute command function /// - /// allows you to pass in a custom command execution function + /// allows you to pass in a custom command execution function + /// allows you to pass in the info that will be passed to startProcess /// Thrown when unable to find the file specified in the command /// Thrown when error occurs during the execution of the command public static void Execute(Func startProcess, ProcessStartInfo info) diff --git a/Flow.Launcher.Test/Plugins/ExplorerTest.cs b/Flow.Launcher.Test/Plugins/ExplorerTest.cs index 9d7fccad9d6..78be463e4da 100644 --- a/Flow.Launcher.Test/Plugins/ExplorerTest.cs +++ b/Flow.Launcher.Test/Plugins/ExplorerTest.cs @@ -1,4 +1,4 @@ -using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.Explorer; using Flow.Launcher.Plugin.Explorer.Search; using Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo; @@ -19,10 +19,12 @@ namespace Flow.Launcher.Test.Plugins [TestFixture] public class ExplorerTest { +#pragma warning disable CS1998 // async method with no await (more readable to leave it async to match the tested signature) private async Task> MethodWindowsIndexSearchReturnsZeroResultsAsync(Query dummyQuery, string dummyString, CancellationToken dummyToken) { return new List(); } +#pragma warning restore CS1998 private List MethodDirectoryInfoClassSearchReturnsTwoResults(Query dummyQuery, string dummyString, CancellationToken token) { @@ -151,7 +153,7 @@ public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryShould } [TestCase] - public async Task GivenTopLevelDirectorySearch_WhenIndexSearchNotRequired_ThenSearchMethodShouldContinueDirectoryInfoClassSearch() + public async Task GivenTopLevelDirectorySearch_WhenIndexSearchNotRequired_ThenSearchMethodShouldContinueDirectoryInfoClassSearchAsync() { // Given var searchManager = new SearchManager(new Settings(), new PluginInitContext()); @@ -172,7 +174,7 @@ public async Task GivenTopLevelDirectorySearch_WhenIndexSearchNotRequired_ThenSe } [TestCase] - public async Task GivenTopLevelDirectorySearch_WhenIndexSearchNotRequired_ThenSearchMethodShouldNotContinueDirectoryInfoClassSearch() + public async Task GivenTopLevelDirectorySearch_WhenIndexSearchNotRequired_ThenSearchMethodShouldNotContinueDirectoryInfoClassSearchAsync() { // Given var searchManager = new SearchManager(new Settings(), new PluginInitContext()); diff --git a/Flow.Launcher.sln b/Flow.Launcher.sln index b8deae5530a..ec4a29ee78d 100644 --- a/Flow.Launcher.sln +++ b/Flow.Launcher.sln @@ -43,6 +43,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Url", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FFD651C7-0546-441F-BC8C-D4EE8FD01EA7}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig .gitattributes = .gitattributes .gitignore = .gitignore appveyor.yml = appveyor.yml diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 8c970edddf6..cb8e79d6347 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -74,7 +74,7 @@ await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () => Http.API = API; Http.Proxy = _settings.Proxy; - await PluginManager.InitializePlugins(API); + await PluginManager.InitializePluginsAsync(API); var window = new MainWindow(_settings, _mainVM); Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}"); diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index ab4047cecaf..110beeded93 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -81,7 +81,7 @@ public void UpdateItem(CustomPluginHotkey item) } tbAction.Text = updateCustomHotkey.ActionKeyword; - ctlHotkey.SetHotkey(updateCustomHotkey.Hotkey, false); + _ = ctlHotkey.SetHotkeyAsync(updateCustomHotkey.Hotkey, false); update = true; lblAdd.Text = InternationalizationManager.Instance.GetTranslation("update"); } diff --git a/Flow.Launcher/Helper/SingleInstance.cs b/Flow.Launcher/Helper/SingleInstance.cs index 1a1e6ec3cc3..d684596bebd 100644 --- a/Flow.Launcher/Helper/SingleInstance.cs +++ b/Flow.Launcher/Helper/SingleInstance.cs @@ -385,27 +385,5 @@ private static void ActivateFirstInstance() } #endregion - - #region Private Classes - - /// - /// Remoting service class which is exposed by the server i.e the first instance and called by the second instance - /// to pass on the command line arguments to the first instance and cause it to activate itself. - /// - private class IPCRemoteService : MarshalByRefObject - { - - /// - /// Remoting Object's ease expires after every 5 minutes by default. We need to override the InitializeLifetimeService class - /// to ensure that lease never expires. - /// - /// Always null. - public override object InitializeLifetimeService() - { - return null; - } - } - - #endregion } } diff --git a/Flow.Launcher/Helper/WindowsInteropHelper.cs b/Flow.Launcher/Helper/WindowsInteropHelper.cs index f1e8b209918..4811eb224ef 100644 --- a/Flow.Launcher/Helper/WindowsInteropHelper.cs +++ b/Flow.Launcher/Helper/WindowsInteropHelper.cs @@ -69,7 +69,7 @@ public static bool IsWindowFullscreen() //get current active window IntPtr hWnd = GetForegroundWindow(); - if (hWnd != null && !hWnd.Equals(IntPtr.Zero)) + if (!hWnd.Equals(IntPtr.Zero)) { //if current active window is NOT desktop or shell if (!(hWnd.Equals(HWND_DESKTOP) || hWnd.Equals(HWND_SHELL))) @@ -98,7 +98,7 @@ public static bool IsWindowFullscreen() { IntPtr hWndDesktop = FindWindowEx(hWnd, IntPtr.Zero, "SHELLDLL_DefView", null); hWndDesktop = FindWindowEx(hWndDesktop, IntPtr.Zero, "SysListView32", "FolderView"); - if (hWndDesktop != null && !hWndDesktop.Equals(IntPtr.Zero)) + if (!hWndDesktop.Equals(IntPtr.Zero)) { return false; } @@ -160,4 +160,4 @@ public struct RECT public int Bottom; } } -} \ No newline at end of file +} diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs index bc437d8628b..7e07695d8da 100644 --- a/Flow.Launcher/HotkeyControl.xaml.cs +++ b/Flow.Launcher/HotkeyControl.xaml.cs @@ -65,11 +65,11 @@ private void TbHotkey_OnPreviewKeyDown(object sender, KeyEventArgs e) { await Task.Delay(500, token); if (!token.IsCancellationRequested) - await SetHotkey(hotkeyModel); + await SetHotkeyAsync(hotkeyModel); }); } - public async Task SetHotkey(HotkeyModel keyModel, bool triggerValidate = true) + public async Task SetHotkeyAsync(HotkeyModel keyModel, bool triggerValidate = true) { CurrentHotkey = keyModel; @@ -101,9 +101,9 @@ public async Task SetHotkey(HotkeyModel keyModel, bool triggerValidate = true) } } - public void SetHotkey(string keyStr, bool triggerValidate = true) + public Task SetHotkeyAsync(string keyStr, bool triggerValidate = true) { - SetHotkey(new HotkeyModel(keyStr), triggerValidate); + return SetHotkeyAsync(new HotkeyModel(keyStr), triggerValidate); } private bool CheckHotkeyAvailability() => HotKeyMapper.CheckAvailability(CurrentHotkey); @@ -116,4 +116,4 @@ private void tbHotkey_LostFocus(object sender, RoutedEventArgs e) tbMsg.Foreground = tbMsgForegroundColorOriginal; } } -} \ No newline at end of file +} diff --git a/Flow.Launcher/Properties/AssemblyInfo.cs b/Flow.Launcher/Properties/AssemblyInfo.cs index 332bfac3fcf..b557656b12c 100644 --- a/Flow.Launcher/Properties/AssemblyInfo.cs +++ b/Flow.Launcher/Properties/AssemblyInfo.cs @@ -4,4 +4,4 @@ [assembly: ThemeInfo( ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly -)] \ No newline at end of file +)] diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index e698ae5974b..5fef5499b84 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -23,7 +23,6 @@ using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; using System.Collections.Concurrent; -using Flow.Launcher.Plugin.SharedCommands; using System.Diagnostics; namespace Flow.Launcher @@ -83,7 +82,7 @@ public void SaveAppAllSettings() ImageLoader.Save(); } - public Task ReloadAllPluginData() => PluginManager.ReloadData(); + public Task ReloadAllPluginData() => PluginManager.ReloadDataAsync(); public void ShowMsgError(string title, string subTitle = "") => ShowMsg(title, subTitle, Constant.ErrorIcon, true); diff --git a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs index a433611f605..4f8d653781c 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs @@ -27,7 +27,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) tbMsgTextOriginal = HotkeyControl.tbMsg.Text; tbMsgForegroundColorOriginal = HotkeyControl.tbMsg.Foreground; - HotkeyControl.SetHotkey(new Infrastructure.Hotkey.HotkeyModel(Settings.Hotkey), false); + HotkeyControl.SetHotkeyAsync(new Infrastructure.Hotkey.HotkeyModel(Settings.Hotkey), false); } private void HotkeyControl_OnGotFocus(object sender, RoutedEventArgs args) { diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index c7b4baf2e3b..10c9aeffeec 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -34,7 +34,6 @@ public partial class SettingWindow public readonly IPublicAPI API; private Settings settings; private SettingWindowViewModel viewModel; - private static MainViewModel mainViewModel; public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel) { @@ -102,7 +101,7 @@ private void OnSelectDefaultBrowserClick(object sender, RoutedEventArgs e) private void OnHotkeyControlLoaded(object sender, RoutedEventArgs e) { - HotkeyControl.SetHotkey(viewModel.Settings.Hotkey, false); + _ = HotkeyControl.SetHotkeyAsync(viewModel.Settings.Hotkey, false); } private void OnHotkeyControlFocused(object sender, RoutedEventArgs e) @@ -230,7 +229,7 @@ private void OnTestProxyClick(object sender, RoutedEventArgs e) #endregion - private async void OnCheckUpdates(object sender, RoutedEventArgs e) + private void OnCheckUpdates(object sender, RoutedEventArgs e) { viewModel.UpdateApp(); // TODO: change to command } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index ab0e67519a1..e6289926104 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -299,8 +299,8 @@ private void InitializeKeyCommands() { Hide(); - PluginManager - .ReloadData() + _ = PluginManager + .ReloadDataAsync() .ContinueWith(_ => Application.Current.Dispatcher.Invoke(() => { @@ -308,7 +308,7 @@ private void InitializeKeyCommands() InternationalizationManager.Instance.GetTranslation("success"), InternationalizationManager.Instance.GetTranslation("completedSuccessfully") ); - })) + }), TaskScheduler.Default) .ConfigureAwait(false); }); } diff --git a/Flow.Launcher/ViewModel/RelayCommand.cs b/Flow.Launcher/ViewModel/RelayCommand.cs index ee4140ed5a8..e8d4af8b526 100644 --- a/Flow.Launcher/ViewModel/RelayCommand.cs +++ b/Flow.Launcher/ViewModel/RelayCommand.cs @@ -5,7 +5,7 @@ namespace Flow.Launcher.ViewModel { public class RelayCommand : ICommand { - private Action _action; + private readonly Action _action; public RelayCommand(Action action) { @@ -17,7 +17,9 @@ public virtual bool CanExecute(object parameter) return true; } +#pragma warning disable CS0067 // the event is never used public event EventHandler CanExecuteChanged; +#pragma warning restore CS0067 public virtual void Execute(object parameter) { diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs index ea278b49bfe..5473a6b91f4 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Runtime.InteropServices; @@ -98,7 +98,7 @@ public List Query(Query query) Clipboard.SetDataObject(newResult); return true; } - catch (ExternalException e) + catch (ExternalException) { MessageBox.Show("Copy failed, please try later"); return false; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs index f499274a96e..4bc6705f429 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -202,7 +202,7 @@ public List LoadContextMenus(Result selectedResult) { try { - Task.Run(() => ShellCommand.RunAsDifferentUser(record.FullPath.SetProcessStartInfo())); + _ = Task.Run(() => ShellCommand.RunAsDifferentUser(record.FullPath.SetProcessStartInfo())); } catch (FileNotFoundException e) { diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 8ce627a44f0..2b56cdf6ea5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -93,7 +93,8 @@ private bool ActionKeywordMatch(Query query, Settings.ActionKeyword allowedActio Settings.ActionKeyword.IndexSearchActionKeyword => Settings.IndexSearchKeywordEnabled && keyword == Settings.IndexSearchActionKeyword, Settings.ActionKeyword.QuickAccessActionKeyword => Settings.QuickAccessKeywordEnabled && - keyword == Settings.QuickAccessActionKeyword + keyword == Settings.QuickAccessActionKeyword, + _ => throw new NotImplementedException() }; } @@ -224,4 +225,4 @@ private bool UseWindowsIndexForDirectorySearch(string locationPath) return IndexSearch.PathIsIndexed(pathToDirectory); } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 57c8574039f..dddb7cf6863 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -55,7 +55,7 @@ public async Task> QueryAsync(Query query, CancellationToken token) //search could be url, no need ToLower() when passed in Settings.InstallCommand => await pluginManager.RequestInstallOrUpdate(query.SecondToEndSearch, token), Settings.UninstallCommand => pluginManager.RequestUninstall(query.SecondToEndSearch), - Settings.UpdateCommand => await pluginManager.RequestUpdate(query.SecondToEndSearch, token), + Settings.UpdateCommand => await pluginManager.RequestUpdateAsync(query.SecondToEndSearch, token), _ => pluginManager.GetDefaultHotKeys().Where(hotkey => { hotkey.Score = StringMatcher.FuzzySearch(query.Search, hotkey.Title).Score; diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index bbf155e23c8..4ca98aeae3c 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -1,4 +1,4 @@ -using Flow.Launcher.Core.ExternalPlugins; +using Flow.Launcher.Core.ExternalPlugins; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Http; @@ -109,7 +109,7 @@ internal List GetDefaultHotKeys() }; } - internal async Task InstallOrUpdate(UserPlugin plugin) + internal async Task InstallOrUpdateAsync(UserPlugin plugin) { if (PluginExists(plugin.ID)) { @@ -182,7 +182,7 @@ internal async Task InstallOrUpdate(UserPlugin plugin) Context.API.RestartApp(); } - internal async ValueTask> RequestUpdate(string search, CancellationToken token) + internal async ValueTask> RequestUpdateAsync(string search, CancellationToken token) { await UpdateManifestAsync(token); @@ -336,7 +336,7 @@ internal List InstallFromWeb(string url) } Application.Current.MainWindow.Hide(); - _ = InstallOrUpdate(plugin); + _ = InstallOrUpdateAsync(plugin); return ShouldHideWindow; } @@ -383,7 +383,7 @@ internal async ValueTask> RequestInstallOrUpdate(string search, Can } Application.Current.MainWindow.Hide(); - _ = InstallOrUpdate(x); // No need to wait + _ = InstallOrUpdateAsync(x); // No need to wait return ShouldHideWindow; }, ContextData = x @@ -502,4 +502,4 @@ private bool SameOrLesserPluginVersionExists(string metadataPath) && newMetadata.Version.CompareTo(x.Metadata.Version) <= 0); } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 6343821090e..c4cd19eec0c 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; @@ -53,7 +53,7 @@ public async Task> QueryAsync(Query query, CancellationToken token) { if (IsStartupIndexProgramsRequired) - _ = IndexPrograms(); + _ = IndexProgramsAsync(); var result = await cache.GetOrCreateAsync(query.Search, async entry => { @@ -122,7 +122,7 @@ public async Task InitAsync(PluginInitContext context) { if (indexedWinApps && indexedUWPApps) _settings.LastIndexTime = DateTime.Today; - }); + }, TaskScheduler.Current); if (!(_win32s.Any() && _uwps.Any())) await indexTask; @@ -142,7 +142,7 @@ public static void IndexUwpPrograms() _uwps = applications; } - public static async Task IndexPrograms() + public static async Task IndexProgramsAsync() { var t1 = Task.Run(IndexWin32Programs); var t2 = Task.Run(IndexUwpPrograms); @@ -246,7 +246,7 @@ public static void StartProcess(Func runProcess, Proc public async Task ReloadDataAsync() { - await IndexPrograms(); + await IndexProgramsAsync(); } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWP.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWP.cs index 2a04b2b2ee4..39a3589e328 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWP.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWP.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -157,9 +157,8 @@ public static Application[] All() #if !DEBUG catch (Exception e) { - ProgramLogger.LogException($"|UWP|All|{p.InstalledLocation}|An unexpected error occured and " - + $"unable to convert Package to UWP for {p.Id.FullName}", e); - return new Application[] { }; + ProgramLogger.LogException($"|UWP|All|{p.InstalledLocation}|An unexpected error occured and unable to convert Package to UWP for {p.Id.FullName}", e); + return Array.Empty(); } #endif #if DEBUG //make developer aware and implement handling @@ -397,7 +396,7 @@ await Task.Run(() => { try { - appManager.ActivateApplication(UserModelId, noArgs, noFlags, out _); + _ = appManager.ActivateApplication(UserModelId, noArgs, noFlags, out _); } catch (Exception) { @@ -408,7 +407,7 @@ await Task.Run(() => }); } - private async void LaunchElevated() + private void LaunchElevated() { string command = "shell:AppsFolder\\" + UniqueIdentifier; command = Environment.ExpandEnvironmentVariables(command.Trim()); @@ -540,7 +539,7 @@ internal string LogoUriFromManifest(AppxPackageHelper.IAppxManifestApplication a if (logoKeyFromVersion.ContainsKey(Package.Version)) { var key = logoKeyFromVersion[Package.Version]; - app.GetStringValue(key, out string logoUri); + _ = app.GetStringValue(key, out string logoUri); return logoUri; } else @@ -729,4 +728,4 @@ private static extern Hresult SHCreateStreamOnFileEx(string fileName, Stgm grfMo private static extern Hresult SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, uint cchOutBuf, IntPtr ppvReserved); } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 1464bd785ca..ba6ada3b687 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -517,9 +517,9 @@ public static Win32[] All(Settings settings) return programs.Concat(autoIndexPrograms).Distinct().ToArray(); } #if DEBUG //This is to make developer aware of any unhandled exception and add in handling. - catch (Exception e) + catch (Exception) { - throw e; + throw; } #endif @@ -546,4 +546,4 @@ public bool Equals([AllowNull] Win32 other) return UniqueIdentifier == other.UniqueIdentifier; } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs index a8d6c25e7cd..1a31e8c2833 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs @@ -119,7 +119,7 @@ private async void ReIndexing() { ViewRefresh(); indexingPanel.Visibility = Visibility.Visible; - await Main.IndexPrograms(); + await Main.IndexProgramsAsync(); indexingPanel.Visibility = Visibility.Hidden; } diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj index 5ebfd6d54ef..d1da7327d1d 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj +++ b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj @@ -61,7 +61,7 @@ - + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index dd8a05b0f75..9f822ea47b2 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; @@ -376,9 +376,9 @@ public List LoadContextMenus(Result selectedResult) new Result { Title = context.API.GetTranslation("flowlauncher_plugin_cmd_run_as_different_user"), - Action = c => + AsyncAction = async c => { - Task.Run(() => Execute(ShellCommand.RunAsDifferentUser, PrepareProcessStartInfo(selectedResult.Title))); + Execute(ShellCommand.RunAsDifferentUser, PrepareProcessStartInfo(selectedResult.Title)); return true; }, IcoPath = "Images/user.png" @@ -408,4 +408,4 @@ public List LoadContextMenus(Result selectedResult) return resultlist; } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 78e4893a5a3..808f8ef198a 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -270,11 +270,12 @@ private List Commands() // Hide the window first then show msg after done because sometimes the reload could take a while, so not to make user think it's frozen. Application.Current.MainWindow.Hide(); - context.API.ReloadAllPluginData().ContinueWith(_ => + _ = context.API.ReloadAllPluginData().ContinueWith(_ => context.API.ShowMsg( context.API.GetTranslation("flowlauncher_plugin_sys_dlgtitle_success"), context.API.GetTranslation( - "flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded"))); + "flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded")), + System.Threading.Tasks.TaskScheduler.Current); return true; } @@ -340,4 +341,4 @@ public string GetTranslatedPluginDescription() return context.API.GetTranslation("flowlauncher_plugin_sys_plugin_description"); } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.Url/Main.cs b/Plugins/Flow.Launcher.Plugin.Url/Main.cs index 9d5b528ec68..c507f0b1ce5 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Url/Main.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Windows.Controls; @@ -72,7 +72,7 @@ public List Query(Query query) return true; } - catch(Exception ex) + catch(Exception) { context.API.ShowMsg(string.Format(context.API.GetTranslation("flowlauncher_plugin_url_canot_open_url"), raw)); return false; @@ -124,4 +124,4 @@ public string GetTranslatedPluginDescription() return context.API.GetTranslation("flowlauncher_plugin_url_plugin_description"); } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs index 98e9376fb05..caed3f16c31 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.IO; using System.Windows.Media; using JetBrains.Annotations; using Flow.Launcher.Infrastructure.Image; @@ -41,14 +41,14 @@ public SearchSource DeepCopy() { var webSearch = new SearchSource { - Title = string.Copy(Title), - ActionKeyword = string.Copy(ActionKeyword), - Url = string.Copy(Url), - Icon = string.Copy(Icon), + Title = Title, + ActionKeyword = ActionKeyword, + Url = Url, + Icon = Icon, CustomIcon = CustomIcon, Enabled = Enabled }; return webSearch; } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs index 2495abe668b..372e601e049 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs @@ -1,4 +1,4 @@ -using Flow.Launcher.Infrastructure.Image; +using Flow.Launcher.Infrastructure.Image; using System; using System.Drawing; using System.IO; @@ -34,10 +34,10 @@ public void CopyNewImageToUserDataDirectoryIfRequired( { File.Copy(fullpathToSelectedImage, destinationFileNameFullPath); } - catch (Exception e) + catch (Exception) { #if DEBUG - throw e; + throw; #else MessageBox.Show(string.Format("Copying the selected image file to {0} has failed, changes will now be reverted", destinationFileNameFullPath)); UpdateIconAttributes(selectedSearchSource, fullPathToOriginalImage); diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs index d1fbd4ac5ed..40379b1ed9a 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs @@ -23,7 +23,7 @@ public override async Task> SuggestionsAsync(string query, Cancella try { const string api = "http://suggestion.baidu.com/su?json=1&wd="; - result = await Http.GetAsync(api + Uri.EscapeUriString(query), token).ConfigureAwait(false); + result = await Http.GetAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false); } catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException}) { @@ -59,4 +59,4 @@ public override string ToString() return "Baidu"; } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs index 971fc079cf1..e01b66df55f 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs @@ -22,7 +22,7 @@ public override async Task> SuggestionsAsync(string query, Cancella { const string api = "https://api.bing.com/qsonhs.aspx?q="; - using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeUriString(query), token).ConfigureAwait(false); + using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false); using var json = (await JsonDocument.ParseAsync(resultStream, cancellationToken: token)); var root = json.RootElement.GetProperty("AS"); diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs index a6c18b1ef2b..bde63ab29d5 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs @@ -20,7 +20,7 @@ public override async Task> SuggestionsAsync(string query, Cancella { const string api = "https://www.google.com/complete/search?output=chrome&q="; - using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeUriString(query)).ConfigureAwait(false); + using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query)).ConfigureAwait(false); using var json = await JsonDocument.ParseAsync(resultStream, cancellationToken: token); @@ -49,4 +49,4 @@ public override string ToString() return "Google"; } } -} \ No newline at end of file +} diff --git a/SolutionAssemblyInfo.cs b/SolutionAssemblyInfo.cs index 1482bce9e67..2938bcbbedd 100644 --- a/SolutionAssemblyInfo.cs +++ b/SolutionAssemblyInfo.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using System.Runtime.InteropServices; #if DEBUG @@ -18,4 +18,4 @@ [assembly: ComVisible(false)] [assembly: AssemblyVersion("1.0.0")] [assembly: AssemblyFileVersion("1.0.0")] -[assembly: AssemblyInformationalVersion("1.0.0")] \ No newline at end of file +[assembly: AssemblyInformationalVersion("1.0.0")]