diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index 2b570d2c088..7f02cef0990 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -1,21 +1,22 @@ -using Microsoft.Win32; -using Squirrel; -using System; +using System; using System.IO; +using System.Linq; using System.Reflection; using System.Windows; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; -using Flow.Launcher.Plugin.SharedCommands; -using System.Linq; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedCommands; +using Microsoft.Win32; +using Squirrel; namespace Flow.Launcher.Core.Configuration { public class Portable : IPortable { + private static readonly string ClassName = nameof(Portable); + private readonly IPublicAPI API = Ioc.Default.GetRequiredService(); /// @@ -51,7 +52,7 @@ public void DisablePortableMode() } catch (Exception e) { - Log.Exception("|Portable.DisablePortableMode|Error occurred while disabling portable mode", e); + API.LogException(ClassName, "Error occurred while disabling portable mode", e); } } @@ -75,7 +76,7 @@ public void EnablePortableMode() } catch (Exception e) { - Log.Exception("|Portable.EnablePortableMode|Error occurred while enabling portable mode", e); + API.LogException(ClassName, "Error occurred while enabling portable mode", e); } } diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs index e9713564ec7..ac27c523c7e 100644 --- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs +++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs @@ -1,25 +1,32 @@ -using Flow.Launcher.Infrastructure.Http; -using Flow.Launcher.Infrastructure.Logger; -using Flow.Launcher.Plugin; -using System; +using System; using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Net.Http.Json; +using System.Net.Sockets; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Infrastructure.Http; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.ExternalPlugins { public record CommunityPluginSource(string ManifestFileUrl) { + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + + private static readonly string ClassName = nameof(CommunityPluginSource); + private string latestEtag = ""; private List plugins = new(); - private static JsonSerializerOptions PluginStoreItemSerializationOption = new JsonSerializerOptions() + private static readonly JsonSerializerOptions PluginStoreItemSerializationOption = new() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }; @@ -34,35 +41,49 @@ public record CommunityPluginSource(string ManifestFileUrl) /// public async Task> FetchAsync(CancellationToken token) { - Log.Info(nameof(CommunityPluginSource), $"Loading plugins from {ManifestFileUrl}"); + API.LogInfo(ClassName, $"Loading plugins from {ManifestFileUrl}"); var request = new HttpRequestMessage(HttpMethod.Get, ManifestFileUrl); request.Headers.Add("If-None-Match", latestEtag); - using var response = await Http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token) + try + { + using var response = await Http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token) .ConfigureAwait(false); - if (response.StatusCode == HttpStatusCode.OK) - { - this.plugins = await response.Content - .ReadFromJsonAsync>(PluginStoreItemSerializationOption, cancellationToken: token) - .ConfigureAwait(false); - this.latestEtag = response.Headers.ETag?.Tag; + if (response.StatusCode == HttpStatusCode.OK) + { + plugins = await response.Content + .ReadFromJsonAsync>(PluginStoreItemSerializationOption, cancellationToken: token) + .ConfigureAwait(false); + latestEtag = response.Headers.ETag?.Tag; - Log.Info(nameof(CommunityPluginSource), $"Loaded {this.plugins.Count} plugins from {ManifestFileUrl}"); - return this.plugins; - } - else if (response.StatusCode == HttpStatusCode.NotModified) - { - Log.Info(nameof(CommunityPluginSource), $"Resource {ManifestFileUrl} has not been modified."); - return this.plugins; + API.LogInfo(ClassName, $"Loaded {plugins.Count} plugins from {ManifestFileUrl}"); + return plugins; + } + else if (response.StatusCode == HttpStatusCode.NotModified) + { + API.LogInfo(ClassName, $"Resource {ManifestFileUrl} has not been modified."); + return plugins; + } + else + { + API.LogWarn(ClassName, $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}"); + return plugins; + } } - else + catch (Exception e) { - Log.Warn(nameof(CommunityPluginSource), - $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}"); - throw new Exception($"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}"); + if (e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException) + { + API.LogException(ClassName, $"Check your connection and proxy settings to {ManifestFileUrl}.", e); + } + else + { + API.LogException(ClassName, "Error Occurred", e); + } + return plugins; } } } diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs index bbb6cf63870..14796a87a93 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs @@ -5,7 +5,6 @@ using System.Windows; using System.Windows.Forms; using CommunityToolkit.Mvvm.DependencyInjection; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; @@ -14,6 +13,8 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments { public abstract class AbstractPluginEnvironment { + private static readonly string ClassName = nameof(AbstractPluginEnvironment); + protected readonly IPublicAPI API = Ioc.Default.GetRequiredService(); internal abstract string Language { get; } @@ -120,7 +121,7 @@ internal IEnumerable Setup() else { API.ShowMsgBox(string.Format(API.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language)); - Log.Error("PluginsLoader", + API.LogError(ClassName, $"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.", $"{Language}Environment"); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptEnvironment.cs index b67059b1b6b..62d2d3e9181 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptEnvironment.cs @@ -4,7 +4,6 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments { - internal class JavaScriptEnvironment : TypeScriptEnvironment { internal override string Language => AllowedLanguage.JavaScript; diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptV2Environment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptV2Environment.cs index 6c8c5aa57c8..726bc4cd4e2 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptV2Environment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/JavaScriptV2Environment.cs @@ -4,7 +4,6 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments { - internal class JavaScriptV2Environment : TypeScriptV2Environment { internal override string Language => AllowedLanguage.JavaScriptV2; diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs index fab5738de3b..455ee096da6 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs @@ -5,6 +5,7 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; +using Microsoft.VisualStudio.Threading; namespace Flow.Launcher.Core.ExternalPlugins.Environments { @@ -30,13 +31,15 @@ internal override string PluginsSettingsFilePath internal PythonEnvironment(List pluginMetadataList, PluginsSettings pluginSettings) : base(pluginMetadataList, pluginSettings) { } + private JoinableTaskFactory JTF { get; } = new JoinableTaskFactory(new JoinableTaskContext()); + internal override void InstallEnvironment() { FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s)); // Python 3.11.4 is no longer Windows 7 compatible. If user is on Win 7 and // uses Python plugin they need to custom install and use v3.8.9 - DroplexPackage.Drop(App.python_3_11_4_embeddable, InstallPath).Wait(); + JTF.Run(() => DroplexPackage.Drop(App.python_3_11_4_embeddable, InstallPath)); PluginsSettingsFilePath = ExecutablePath; } diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs index 8a4f527ba83..12965286f47 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs @@ -5,6 +5,7 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; +using Microsoft.VisualStudio.Threading; namespace Flow.Launcher.Core.ExternalPlugins.Environments { @@ -27,11 +28,13 @@ internal override string PluginsSettingsFilePath internal TypeScriptEnvironment(List pluginMetadataList, PluginsSettings pluginSettings) : base(pluginMetadataList, pluginSettings) { } + private JoinableTaskFactory JTF { get; } = new JoinableTaskFactory(new JoinableTaskContext()); + internal override void InstallEnvironment() { FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s)); - DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait(); + JTF.Run(() => DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath)); PluginsSettingsFilePath = ExecutablePath; } diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs index 61fd2837677..6960b79c9a7 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs @@ -5,6 +5,7 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; +using Microsoft.VisualStudio.Threading; namespace Flow.Launcher.Core.ExternalPlugins.Environments { @@ -27,11 +28,13 @@ internal override string PluginsSettingsFilePath internal TypeScriptV2Environment(List pluginMetadataList, PluginsSettings pluginSettings) : base(pluginMetadataList, pluginSettings) { } + private JoinableTaskFactory JTF { get; } = new JoinableTaskFactory(new JoinableTaskContext()); + internal override void InstallEnvironment() { FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s)); - DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait(); + JTF.Run(() => DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath)); PluginsSettingsFilePath = ExecutablePath; } diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index 44d3ef0ff7b..7ca91eaecde 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -9,6 +9,8 @@ namespace Flow.Launcher.Core.ExternalPlugins { public static class PluginsManifest { + private static readonly string ClassName = nameof(PluginsManifest); + private static readonly CommunityPluginStore mainPluginStore = new("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/plugin_api_v2/plugins.json", "https://fastly.jsdelivr.net/gh/Flow-Launcher/Flow.Launcher.PluginsManifest@plugin_api_v2/plugins.json", @@ -44,7 +46,7 @@ public static async Task UpdateManifestAsync(bool usePrimaryUrlOnly = fals } catch (Exception e) { - Ioc.Default.GetRequiredService().LogException(nameof(PluginsManifest), "Http request failed", e); + Ioc.Default.GetRequiredService().LogException(ClassName, "Http request failed", e); } finally { diff --git a/Flow.Launcher.Core/Plugin/PluginConfig.cs b/Flow.Launcher.Core/Plugin/PluginConfig.cs index 163f970469d..f7457b4e1b1 100644 --- a/Flow.Launcher.Core/Plugin/PluginConfig.cs +++ b/Flow.Launcher.Core/Plugin/PluginConfig.cs @@ -3,14 +3,20 @@ using System.Linq; using System.IO; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin; using System.Text.Json; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Core.Plugin { internal abstract class PluginConfig { + private static readonly string ClassName = nameof(PluginConfig); + + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + /// /// Parse plugin metadata in the given directories /// @@ -32,7 +38,7 @@ public static List Parse(string[] pluginDirectories) } catch (Exception e) { - Log.Exception($"|PluginConfig.ParsePLuginConfigs|Can't delete <{directory}>", e); + API.LogException(ClassName, $"Can't delete <{directory}>", e); } } else @@ -49,11 +55,11 @@ public static List Parse(string[] pluginDirectories) duplicateList .ForEach( - x => Log.Warn("PluginConfig", - string.Format("Duplicate plugin name: {0}, id: {1}, version: {2} " + - "not loaded due to version not the highest of the duplicates", - x.Name, x.ID, x.Version), - "GetUniqueLatestPluginMetadata")); + x => API.LogWarn(ClassName, + string.Format("Duplicate plugin name: {0}, id: {1}, version: {2} " + + "not loaded due to version not the highest of the duplicates", + x.Name, x.ID, x.Version), + "GetUniqueLatestPluginMetadata")); return uniqueList; } @@ -101,7 +107,7 @@ private static PluginMetadata GetPluginMetadata(string pluginDirectory) string configPath = Path.Combine(pluginDirectory, Constant.PluginMetadataFileName); if (!File.Exists(configPath)) { - Log.Error($"|PluginConfig.GetPluginMetadata|Didn't find config file <{configPath}>"); + API.LogError(ClassName, $"Didn't find config file <{configPath}>"); return null; } @@ -117,19 +123,19 @@ private static PluginMetadata GetPluginMetadata(string pluginDirectory) } catch (Exception e) { - Log.Exception($"|PluginConfig.GetPluginMetadata|invalid json for config <{configPath}>", e); + API.LogException(ClassName, $"Invalid json for config <{configPath}>", e); return null; } if (!AllowedLanguage.IsAllowed(metadata.Language)) { - Log.Error($"|PluginConfig.GetPluginMetadata|Invalid language <{metadata.Language}> for config <{configPath}>"); + API.LogError(ClassName, $"Invalid language <{metadata.Language}> for config <{configPath}>"); return null; } if (!File.Exists(metadata.ExecuteFilePath)) { - Log.Error($"|PluginConfig.GetPluginMetadata|execute file path didn't exist <{metadata.ExecuteFilePath}> for conifg <{configPath}"); + API.LogError(ClassName, $"Execute file path didn't exist <{metadata.ExecuteFilePath}> for conifg <{configPath}"); return null; } diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 52d6fd736db..72303c8b754 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -9,7 +9,6 @@ using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core.ExternalPlugins; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; @@ -214,12 +213,12 @@ public static async Task InitializePluginsAsync() () => pair.Plugin.InitAsync(new PluginInitContext(pair.Metadata, API))); pair.Metadata.InitTime += milliseconds; - Log.Info( - $"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>"); + API.LogInfo(ClassName, + $"Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>"); } catch (Exception e) { - Log.Exception(ClassName, $"Fail to Init plugin: {pair.Metadata.Name}", e); + API.LogException(ClassName, $"Fail to Init plugin: {pair.Metadata.Name}", e); pair.Metadata.Disabled = true; failedPlugins.Enqueue(pair); } @@ -370,8 +369,8 @@ public static List GetContextMenusForPlugin(Result result) } catch (Exception e) { - Log.Exception( - $"|PluginManager.GetContextMenusForPlugin|Can't load context menus for plugin <{pluginPair.Metadata.Name}>", + API.LogException(ClassName, + $"Can't load context menus for plugin <{pluginPair.Metadata.Name}>", e); } } @@ -563,7 +562,7 @@ internal static void InstallPlugin(UserPlugin plugin, string zipFilePath, bool c } catch (Exception e) { - Log.Exception($"|PluginManager.InstallPlugin|Failed to delete temp folder {tempFolderPluginPath}", e); + API.LogException(ClassName, $"Failed to delete temp folder {tempFolderPluginPath}", e); } if (checkModified) @@ -608,7 +607,7 @@ internal static async Task UninstallPluginAsync(PluginMetadata plugin, bool remo } catch (Exception e) { - Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin settings folder for {plugin.Name}", e); + API.LogException(ClassName, $"Failed to delete plugin settings folder for {plugin.Name}", e); API.ShowMsg(API.GetTranslation("failedToRemovePluginSettingsTitle"), string.Format(API.GetTranslation("failedToRemovePluginSettingsMessage"), plugin.Name)); } @@ -624,7 +623,7 @@ internal static async Task UninstallPluginAsync(PluginMetadata plugin, bool remo } catch (Exception e) { - Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin cache folder for {plugin.Name}", e); + API.LogException(ClassName, $"Failed to delete plugin cache folder for {plugin.Name}", e); API.ShowMsg(API.GetTranslation("failedToRemovePluginCacheTitle"), string.Format(API.GetTranslation("failedToRemovePluginCacheMessage"), plugin.Name)); } diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs index 1010d9f083b..256c36065a9 100644 --- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs @@ -89,19 +89,19 @@ private static IEnumerable DotNetPlugins(List source #else catch (Exception e) when (assembly == null) { - Log.Exception($"|PluginsLoader.DotNetPlugins|Couldn't load assembly for the plugin: {metadata.Name}", e); + Log.Exception(ClassName, $"Couldn't load assembly for the plugin: {metadata.Name}", e); } catch (InvalidOperationException e) { - Log.Exception($"|PluginsLoader.DotNetPlugins|Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e); + Log.Exception(ClassName, $"Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e); } catch (ReflectionTypeLoadException e) { - Log.Exception($"|PluginsLoader.DotNetPlugins|The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e); + Log.Exception(ClassName, $"The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e); } catch (Exception e) { - Log.Exception($"|PluginsLoader.DotNetPlugins|The following plugin has errored and can not be loaded: <{metadata.Name}>", e); + Log.Exception(ClassName, $"The following plugin has errored and can not be loaded: <{metadata.Name}>", e); } #endif diff --git a/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs b/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs index bae2631573d..7a6bf07e2e3 100644 --- a/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/ProcessStreamPluginV2.cs @@ -1,21 +1,19 @@ -#nullable enable - -using System; -using System.Collections.Generic; +using System; using System.Diagnostics; using System.IO.Pipelines; using System.Threading.Tasks; using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin; using Meziantou.Framework.Win32; -using Microsoft.VisualBasic.ApplicationServices; using Nerdbank.Streams; +#nullable enable + namespace Flow.Launcher.Core.Plugin { internal abstract class ProcessStreamPluginV2 : JsonRPCPluginV2 { - private static JobObject _jobObject = new JobObject(); + private static readonly JobObject _jobObject = new(); static ProcessStreamPluginV2() { @@ -66,11 +64,10 @@ private void SetupPipe(Process process) ClientPipe = new DuplexPipe(reader, writer); } - public override async Task ReloadDataAsync() { var oldProcess = ClientProcess; - ClientProcess = Process.Start(StartInfo); + ClientProcess = Process.Start(StartInfo)!; ArgumentNullException.ThrowIfNull(ClientProcess); SetupPipe(ClientProcess); await base.ReloadDataAsync(); @@ -79,7 +76,6 @@ public override async Task ReloadDataAsync() oldProcess.Dispose(); } - public override async ValueTask DisposeAsync() { await base.DisposeAsync(); diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index df841dbbe0e..b32b09e8fc8 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -6,7 +6,6 @@ using System.Windows; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using System.Globalization; @@ -17,6 +16,12 @@ namespace Flow.Launcher.Core.Resource { public class Internationalization { + private static readonly string ClassName = nameof(Internationalization); + + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + private const string Folder = "Languages"; private const string DefaultLanguageCode = "en"; private const string DefaultFile = "en.xaml"; @@ -80,7 +85,7 @@ private void AddPluginLanguageDirectories() } else { - Log.Error($"|Internationalization.AddPluginLanguageDirectories|Can't find plugin path <{location}> for <{plugin.Metadata.Name}>"); + API.LogError(ClassName, $"Can't find plugin path <{location}> for <{plugin.Metadata.Name}>"); } } @@ -150,7 +155,7 @@ private static Language GetLanguageByLanguageCode(string languageCode) var language = AvailableLanguages.GetAvailableLanguages().FirstOrDefault(o => o.LanguageCode.ToLower() == lowercase); if (language == null) { - Log.Error($"|Internationalization.GetLanguageByLanguageCode|Language code can't be found <{languageCode}>"); + API.LogError(ClassName, $"Language code can't be found <{languageCode}>"); return AvailableLanguages.English; } else @@ -248,7 +253,7 @@ public static string GetTranslation(string key) } else { - Log.Error($"|Internationalization.GetTranslation|No Translation for key {key}"); + API.LogError(ClassName, $"No Translation for key {key}"); return $"No Translation for key {key}"; } } @@ -266,7 +271,7 @@ private void UpdatePluginMetadataTranslations() } catch (Exception e) { - Log.Exception($"|Internationalization.UpdatePluginMetadataTranslations|Failed for <{p.Metadata.Name}>", e); + API.LogException(ClassName, $"Failed for <{p.Metadata.Name}>", e); } } } @@ -282,7 +287,7 @@ private static string LanguageFile(string folder, string language) } else { - Log.Error($"|Internationalization.LanguageFile|Language path can't be found <{path}>"); + API.LogError(ClassName, $"Language path can't be found <{path}>"); var english = Path.Combine(folder, DefaultFile); if (File.Exists(english)) { @@ -290,7 +295,7 @@ private static string LanguageFile(string folder, string language) } else { - Log.Error($"|Internationalization.LanguageFile|Default English Language path can't be found <{path}>"); + API.LogError(ClassName, $"Default English Language path can't be found <{path}>"); return string.Empty; } } diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index 59e76e2d2e9..64ffec907d9 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -13,7 +13,6 @@ using System.Windows.Shell; using System.Windows.Threading; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels; @@ -25,6 +24,8 @@ public class Theme { #region Properties & Fields + private readonly string ClassName = nameof(Theme); + public bool BlurEnabled { get; private set; } private const string ThemeMetadataNamePrefix = "Name:"; @@ -73,7 +74,7 @@ public Theme(IPublicAPI publicAPI, Settings settings) } else { - Log.Error("Current theme resource not found. Initializing with default theme."); + _api.LogError(ClassName, "Current theme resource not found. Initializing with default theme."); _oldTheme = Constant.DefaultTheme; }; } @@ -92,7 +93,7 @@ private void MakeSureThemeDirectoriesExist() } catch (Exception e) { - Log.Exception($"|Theme.MakesureThemeDirectoriesExist|Exception when create directory <{dir}>", e); + _api.LogException(ClassName, $"Exception when create directory <{dir}>", e); } } } @@ -135,7 +136,7 @@ public void UpdateFonts() } catch (Exception e) { - Log.Exception("Error occurred while updating theme fonts", e); + _api.LogException(ClassName, "Error occurred while updating theme fonts", e); } } @@ -387,7 +388,7 @@ public ThemeData GetCurrentTheme() var matchingTheme = themes.FirstOrDefault(t => t.FileNameWithoutExtension == _settings.Theme); if (matchingTheme == null) { - Log.Warn($"No matching theme found for '{_settings.Theme}'. Falling back to the first available theme."); + _api.LogWarn(ClassName, $"No matching theme found for '{_settings.Theme}'. Falling back to the first available theme."); } return matchingTheme ?? themes.FirstOrDefault(); } @@ -440,7 +441,7 @@ public bool ChangeTheme(string theme = null) } catch (DirectoryNotFoundException) { - Log.Error($"|Theme.ChangeTheme|Theme <{theme}> path can't be found"); + _api.LogError(ClassName, $"Theme <{theme}> path can't be found"); if (theme != Constant.DefaultTheme) { _api.ShowMsgBox(string.Format(_api.GetTranslation("theme_load_failure_path_not_exists"), theme)); @@ -450,7 +451,7 @@ public bool ChangeTheme(string theme = null) } catch (XamlParseException) { - Log.Error($"|Theme.ChangeTheme|Theme <{theme}> fail to parse"); + _api.LogError(ClassName, $"Theme <{theme}> fail to parse"); if (theme != Constant.DefaultTheme) { _api.ShowMsgBox(string.Format(_api.GetTranslation("theme_load_failure_parse_error"), theme)); diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 83d4fd9e0a7..bc3655f69e7 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -12,7 +12,6 @@ using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Http; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using JetBrains.Annotations; @@ -24,6 +23,8 @@ public class Updater { public string GitHubRepository { get; init; } + private static readonly string ClassName = nameof(Updater); + private readonly IPublicAPI _api; public Updater(IPublicAPI publicAPI, string gitHubRepository) @@ -51,7 +52,7 @@ public async Task UpdateAppAsync(bool silentUpdate = true) var newReleaseVersion = Version.Parse(newUpdateInfo.FutureReleaseEntry.Version.ToString()); var currentVersion = Version.Parse(Constant.Version); - Log.Info($"|Updater.UpdateApp|Future Release <{Formatted(newUpdateInfo.FutureReleaseEntry)}>"); + _api.LogInfo(ClassName, $"Future Release <{Formatted(newUpdateInfo.FutureReleaseEntry)}>"); if (newReleaseVersion <= currentVersion) { @@ -84,7 +85,7 @@ public async Task UpdateAppAsync(bool silentUpdate = true) var newVersionTips = NewVersionTips(newReleaseVersion.ToString()); - Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); + _api.LogInfo(ClassName, $"Update success:{newVersionTips}"); if (_api.ShowMsgBox(newVersionTips, _api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) { @@ -93,10 +94,14 @@ public async Task UpdateAppAsync(bool silentUpdate = true) } catch (Exception e) { - if ((e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException)) - Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e); + if (e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException) + { + _api.LogException(ClassName, $"Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e); + } else - Log.Exception($"|Updater.UpdateApp|Error Occurred", e); + { + _api.LogException(ClassName, $"Error Occurred", e); + } if (!silentUpdate) _api.ShowMsg(_api.GetTranslation("update_flowlauncher_fail"), diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 030aff7cfc0..12edf34a432 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -1,30 +1,31 @@ -using System.IO; +using System; +using System.IO; using System.Net; using System.Net.Http; +using System.Threading; using System.Threading.Tasks; -using JetBrains.Annotations; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; -using System; -using System.Threading; using Flow.Launcher.Plugin; -using CommunityToolkit.Mvvm.DependencyInjection; +using JetBrains.Annotations; namespace Flow.Launcher.Infrastructure.Http { public static class Http { + private static readonly string ClassName = nameof(Http); + private const string UserAgent = @"Mozilla/5.0 (Trident/7.0; rv:11.0) like Gecko"; - private static HttpClient client = new HttpClient(); + private static readonly HttpClient client = new(); static Http() { // need to be added so it would work on a win10 machine ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls - | SecurityProtocolType.Tls11 - | SecurityProtocolType.Tls12; + | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; client.DefaultRequestHeaders.Add("User-Agent", UserAgent); HttpClient.DefaultProxy = WebProxy; @@ -34,7 +35,7 @@ static Http() public static HttpProxy Proxy { - private get { return proxy; } + private get => proxy; set { proxy = value; @@ -72,13 +73,13 @@ var userName when string.IsNullOrEmpty(userName) => ProxyProperty.Port => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), WebProxy.Credentials), ProxyProperty.UserName => (WebProxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)), ProxyProperty.Password => (WebProxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)), - _ => throw new ArgumentOutOfRangeException() + _ => throw new ArgumentOutOfRangeException(null) }; } catch (UriFormatException e) { Ioc.Default.GetRequiredService().ShowMsg("Please try again", "Unable to parse Http Proxy"); - Log.Exception("Flow.Launcher.Infrastructure.Http", "Unable to parse Uri", e); + Log.Exception(ClassName, "Unable to parse Uri", e); } } @@ -134,7 +135,7 @@ public static async Task DownloadAsync([NotNull] string url, [NotNull] string fi } catch (HttpRequestException e) { - Log.Exception("Infrastructure.Http", "Http Request Error", e, "DownloadAsync"); + Log.Exception(ClassName, "Http Request Error", e, "DownloadAsync"); throw; } } @@ -147,7 +148,7 @@ public static async Task DownloadAsync([NotNull] string url, [NotNull] string fi /// The Http result as string. Null if cancellation requested public static Task GetAsync([NotNull] string url, CancellationToken token = default) { - Log.Debug($"|Http.Get|Url <{url}>"); + Log.Debug(ClassName, $"Url <{url}>"); return GetAsync(new Uri(url), token); } @@ -159,7 +160,7 @@ public static Task GetAsync([NotNull] string url, CancellationToken toke /// The Http result as string. Null if cancellation requested public static async Task GetAsync([NotNull] Uri url, CancellationToken token = default) { - Log.Debug($"|Http.Get|Url <{url}>"); + Log.Debug(ClassName, $"Url <{url}>"); using var response = await client.GetAsync(url, token); var content = await response.Content.ReadAsStringAsync(token); if (response.StatusCode != HttpStatusCode.OK) @@ -191,7 +192,7 @@ public static Task GetStreamAsync([NotNull] string url, public static async Task GetStreamAsync([NotNull] Uri url, CancellationToken token = default) { - Log.Debug($"|Http.Get|Url <{url}>"); + Log.Debug(ClassName, $"Url <{url}>"); return await client.GetStreamAsync(url, token); } @@ -202,7 +203,7 @@ public static async Task GetResponseAsync(string url, HttpC public static async Task GetResponseAsync([NotNull] Uri url, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead, CancellationToken token = default) { - Log.Debug($"|Http.Get|Url <{url}>"); + Log.Debug(ClassName, $"Url <{url}>"); return await client.GetAsync(url, completionOption, token); } diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 9e31d2b4ebf..a49385a02b1 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -7,9 +7,8 @@ using System.Threading.Tasks; using System.Windows.Media; using System.Windows.Media.Imaging; -using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; -using Flow.Launcher.Plugin; using SharpVectors.Converters; using SharpVectors.Renderers.Wpf; @@ -17,10 +16,6 @@ namespace Flow.Launcher.Infrastructure.Image { public static class ImageLoader { - // We should not initialize API in static constructor because it will create another API instance - private static IPublicAPI api = null; - private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); - private static readonly string ClassName = nameof(ImageLoader); private static readonly ImageCache ImageCache = new(); @@ -58,14 +53,14 @@ public static async Task InitializeAsync() _ = Task.Run(async () => { - await API.StopwatchLogInfoAsync(ClassName, "Preload images cost", async () => + await Stopwatch.InfoAsync(ClassName, "Preload images cost", async () => { foreach (var (path, isFullImage) in usage) { await LoadAsync(path, isFullImage); } }); - API.LogInfo(ClassName, $"Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}"); + Log.Info(ClassName, $"Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}"); }); } @@ -81,7 +76,7 @@ await _storage.SaveAsync(ImageCache.EnumerateEntries() } catch (System.Exception e) { - API.LogException(ClassName, "Failed to save image cache to file", e); + Log.Exception(ClassName, "Failed to save image cache to file", e); } finally { @@ -176,8 +171,8 @@ private static async ValueTask LoadInternalAsync(string path, bool } catch (System.Exception e2) { - API.LogException(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e); - API.LogException(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2); + Log.Exception(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e); + Log.Exception(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2); ImageSource image = ImageCache[Constant.MissingImgIcon, false]; ImageCache[path, false] = image; @@ -243,7 +238,7 @@ private static ImageResult GetThumbnailResult(ref string path, bool loadFullImag { image = Image; type = ImageType.Error; - API.LogException(ClassName, $"Failed to load image file from path {path}: {ex.Message}", ex); + Log.Exception(ClassName, $"Failed to load image file from path {path}: {ex.Message}", ex); } } else @@ -267,7 +262,7 @@ private static ImageResult GetThumbnailResult(ref string path, bool loadFullImag { image = Image; type = ImageType.Error; - API.LogException(ClassName, $"Failed to load SVG image from path {path}: {ex.Message}", ex); + Log.Exception(ClassName, $"Failed to load SVG image from path {path}: {ex.Message}", ex); } } else diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs index 807d631c704..09eb98f46be 100644 --- a/Flow.Launcher.Infrastructure/Logger/Log.cs +++ b/Flow.Launcher.Infrastructure/Logger/Log.cs @@ -94,13 +94,6 @@ private static void LogFaultyFormat(string message) logger.Fatal(message); } - private static bool FormatValid(string message) - { - var parts = message.Split('|'); - var valid = parts.Length == 3 && !string.IsNullOrWhiteSpace(parts[1]) && !string.IsNullOrWhiteSpace(parts[2]); - return valid; - } - public static void Exception(string className, string message, System.Exception exception, [CallerMemberName] string methodName = "") { exception = exception.Demystify(); @@ -135,57 +128,14 @@ private static string CheckClassAndMessageAndReturnFullClassWithMethod(string cl return className; } +#if !DEBUG private static void ExceptionInternal(string classAndMethod, string message, System.Exception e) { var logger = LogManager.GetLogger(classAndMethod); logger.Error(e, message); } - - private static void LogInternal(string message, LogLevel level) - { - if (FormatValid(message)) - { - var parts = message.Split('|'); - var prefix = parts[1]; - var unprefixed = parts[2]; - var logger = LogManager.GetLogger(prefix); - logger.Log(level, unprefixed); - } - else - { - LogFaultyFormat(message); - } - } - - /// Example: "|ClassName.MethodName|Message" - /// Example: "|ClassName.MethodName|Message" - /// Exception - public static void Exception(string message, System.Exception e) - { - e = e.Demystify(); -#if DEBUG - ExceptionDispatchInfo.Capture(e).Throw(); -#else - if (FormatValid(message)) - { - var parts = message.Split('|'); - var prefix = parts[1]; - var unprefixed = parts[2]; - ExceptionInternal(prefix, unprefixed, e); - } - else - { - LogFaultyFormat(message); - } #endif - } - - /// Example: "|ClassName.MethodName|Message" - public static void Error(string message) - { - LogInternal(message, LogLevel.Error); - } public static void Error(string className, string message, [CallerMemberName] string methodName = "") { @@ -206,33 +156,15 @@ public static void Debug(string className, string message, [CallerMemberName] st LogInternal(LogLevel.Debug, className, message, methodName); } - /// Example: "|ClassName.MethodName|Message"" - public static void Debug(string message) - { - LogInternal(message, LogLevel.Debug); - } - public static void Info(string className, string message, [CallerMemberName] string methodName = "") { LogInternal(LogLevel.Info, className, message, methodName); } - /// Example: "|ClassName.MethodName|Message" - public static void Info(string message) - { - LogInternal(message, LogLevel.Info); - } - public static void Warn(string className, string message, [CallerMemberName] string methodName = "") { LogInternal(LogLevel.Warn, className, message, methodName); } - - /// Example: "|ClassName.MethodName|Message" - public static void Warn(string message) - { - LogInternal(message, LogLevel.Warn); - } } public enum LOGLEVEL diff --git a/Flow.Launcher.Infrastructure/Stopwatch.cs b/Flow.Launcher.Infrastructure/Stopwatch.cs index 784d323fe52..870e0fe263a 100644 --- a/Flow.Launcher.Infrastructure/Stopwatch.cs +++ b/Flow.Launcher.Infrastructure/Stopwatch.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using Flow.Launcher.Infrastructure.Logger; @@ -9,54 +10,50 @@ public static class Stopwatch /// /// This stopwatch will appear only in Debug mode /// - public static long Debug(string message, Action action) + public static long Debug(string className, string message, Action action, [CallerMemberName] string methodName = "") { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); action(); stopWatch.Stop(); var milliseconds = stopWatch.ElapsedMilliseconds; - string info = $"{message} <{milliseconds}ms>"; - Log.Debug(info); + Log.Debug(className, $"{message} <{milliseconds}ms>", methodName); return milliseconds; } /// /// This stopwatch will appear only in Debug mode /// - public static async Task DebugAsync(string message, Func action) + public static async Task DebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); await action(); stopWatch.Stop(); var milliseconds = stopWatch.ElapsedMilliseconds; - string info = $"{message} <{milliseconds}ms>"; - Log.Debug(info); + Log.Debug(className, $"{message} <{milliseconds}ms>", methodName); return milliseconds; } - public static long Normal(string message, Action action) + public static long Info(string className, string message, Action action, [CallerMemberName] string methodName = "") { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); action(); stopWatch.Stop(); var milliseconds = stopWatch.ElapsedMilliseconds; - string info = $"{message} <{milliseconds}ms>"; - Log.Info(info); + Log.Info(className, $"{message} <{milliseconds}ms>", methodName); return milliseconds; } - public static async Task NormalAsync(string message, Func action) + public static async Task InfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); await action(); stopWatch.Stop(); var milliseconds = stopWatch.ElapsedMilliseconds; - string info = $"{message} <{milliseconds}ms>"; - Log.Info(info); + Log.Info(className, $"{message} <{milliseconds}ms>", methodName); return milliseconds; } } diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs index 8ff10816cca..48e6b55238c 100644 --- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs @@ -20,6 +20,8 @@ namespace Flow.Launcher.Infrastructure.Storage /// public class BinaryStorage : ISavable { + private static readonly string ClassName = "BinaryStorage"; + protected T? Data; public const string FileSuffix = ".cache"; @@ -59,7 +61,7 @@ public async ValueTask TryLoadAsync(T defaultData) { if (new FileInfo(FilePath).Length == 0) { - Log.Error($"|BinaryStorage.TryLoad|Zero length cache file <{FilePath}>"); + Log.Error(ClassName, $"Zero length cache file <{FilePath}>"); Data = defaultData; await SaveAsync(); } @@ -69,7 +71,7 @@ public async ValueTask TryLoadAsync(T defaultData) } else { - Log.Info("|BinaryStorage.TryLoad|Cache file not exist, load default data"); + Log.Info(ClassName, "Cache file not exist, load default data"); Data = defaultData; await SaveAsync(); } diff --git a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs index ca78b2f200a..158e0cdf58c 100644 --- a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs @@ -1,8 +1,7 @@ using System.IO; using System.Threading.Tasks; -using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; -using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage @@ -11,10 +10,6 @@ namespace Flow.Launcher.Infrastructure.Storage { private static readonly string ClassName = "FlowLauncherJsonStorage"; - // We should not initialize API in static constructor because it will create another API instance - private static IPublicAPI api = null; - private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); - public FlowLauncherJsonStorage() { DirectoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName); @@ -32,7 +27,7 @@ public FlowLauncherJsonStorage() } catch (System.Exception e) { - API.LogException(ClassName, $"Failed to save FL settings to path: {FilePath}", e); + Log.Exception(ClassName, $"Failed to save FL settings to path: {FilePath}", e); } } @@ -44,7 +39,7 @@ public FlowLauncherJsonStorage() } catch (System.Exception e) { - API.LogException(ClassName, $"Failed to save FL settings to path: {FilePath}", e); + Log.Exception(ClassName, $"Failed to save FL settings to path: {FilePath}", e); } } } diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs index f283be59e18..0b10382ee9b 100644 --- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs @@ -16,6 +16,8 @@ namespace Flow.Launcher.Infrastructure.Storage /// public class JsonStorage : ISavable where T : new() { + private static readonly string ClassName = "JsonStorage"; + protected T? Data; // need a new directory name @@ -104,7 +106,7 @@ private async ValueTask LoadBackupOrDefaultAsync() private void RestoreBackup() { - Log.Info($"|JsonStorage.Load|Failed to load settings.json, {BackupFilePath} restored successfully"); + Log.Info(ClassName, $"Failed to load settings.json, {BackupFilePath} restored successfully"); if (File.Exists(FilePath)) File.Replace(BackupFilePath, FilePath, null); diff --git a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs index d18060e3df0..01da96d6259 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs @@ -1,7 +1,6 @@ using System.IO; using System.Threading.Tasks; -using CommunityToolkit.Mvvm.DependencyInjection; -using Flow.Launcher.Plugin; +using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage @@ -10,10 +9,6 @@ namespace Flow.Launcher.Infrastructure.Storage { private static readonly string ClassName = "PluginBinaryStorage"; - // We should not initialize API in static constructor because it will create another API instance - private static IPublicAPI api = null; - private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); - public PluginBinaryStorage(string cacheName, string cacheDirectory) { DirectoryPath = cacheDirectory; @@ -30,7 +25,7 @@ public PluginBinaryStorage(string cacheName, string cacheDirectory) } catch (System.Exception e) { - API.LogException(ClassName, $"Failed to save plugin caches to path: {FilePath}", e); + Log.Exception(ClassName, $"Failed to save plugin caches to path: {FilePath}", e); } } @@ -42,7 +37,7 @@ public PluginBinaryStorage(string cacheName, string cacheDirectory) } catch (System.Exception e) { - API.LogException(ClassName, $"Failed to save plugin caches to path: {FilePath}", e); + Log.Exception(ClassName, $"Failed to save plugin caches to path: {FilePath}", e); } } } diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs index e8cbd70fb98..14715294958 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs @@ -1,8 +1,7 @@ using System.IO; using System.Threading.Tasks; -using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; -using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage @@ -14,10 +13,6 @@ namespace Flow.Launcher.Infrastructure.Storage private static readonly string ClassName = "PluginJsonStorage"; - // We should not initialize API in static constructor because it will create another API instance - private static IPublicAPI api = null; - private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); - public PluginJsonStorage() { // C# related, add python related below @@ -42,7 +37,7 @@ public PluginJsonStorage(T data) : this() } catch (System.Exception e) { - API.LogException(ClassName, $"Failed to save plugin settings to path: {FilePath}", e); + Log.Exception(ClassName, $"Failed to save plugin settings to path: {FilePath}", e); } } @@ -54,7 +49,7 @@ public PluginJsonStorage(T data) : this() } catch (System.Exception e) { - API.LogException(ClassName, $"Failed to save plugin settings to path: {FilePath}", e); + Log.Exception(ClassName, $"Failed to save plugin settings to path: {FilePath}", e); } } } diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index a9cd1a8b986..87677f58a67 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -148,8 +148,8 @@ await API.StopwatchLogInfoAsync(ClassName, "Startup cost", async () => Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate(); - Log.Info("|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------"); - Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}"); + API.LogInfo(ClassName, "Begin Flow Launcher startup ----------------------------------------------------"); + API.LogInfo(ClassName, "Runtime info:{ErrorReporting.RuntimeInfo()}"); RegisterAppDomainExceptions(); RegisterDispatcherUnhandledException(); @@ -176,7 +176,7 @@ await API.StopwatchLogInfoAsync(ClassName, "Startup cost", async () => _mainWindow = new MainWindow(); - Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}"); + API.LogInfo(ClassName, "Dependencies Info:{ErrorReporting.DependenciesInfo()}"); Current.MainWindow = _mainWindow; Current.MainWindow.Title = Constant.FlowLauncher; @@ -192,7 +192,7 @@ await API.StopwatchLogInfoAsync(ClassName, "Startup cost", async () => AutoUpdates(); API.SaveAppAllSettings(); - Log.Info("|App.OnStartup|End Flow Launcher startup ----------------------------------------------------"); + API.LogInfo(ClassName, "End Flow Launcher startup ----------------------------------------------------"); }); } @@ -250,19 +250,19 @@ private void RegisterExitEvents() { AppDomain.CurrentDomain.ProcessExit += (s, e) => { - Log.Info("|App.RegisterExitEvents|Process Exit"); + API.LogInfo(ClassName, "Process Exit"); Dispose(); }; Current.Exit += (s, e) => { - Log.Info("|App.RegisterExitEvents|Application Exit"); + API.LogInfo(ClassName, "Application Exit"); Dispose(); }; Current.SessionEnding += (s, e) => { - Log.Info("|App.RegisterExitEvents|Session Ending"); + API.LogInfo(ClassName, "Session Ending"); Dispose(); }; } @@ -326,7 +326,7 @@ protected virtual void Dispose(bool disposing) API.StopwatchLogInfo(ClassName, "Dispose cost", () => { - Log.Info("|App.Dispose|Begin Flow Launcher dispose ----------------------------------------------------"); + API.LogInfo(ClassName, "Begin Flow Launcher dispose ----------------------------------------------------"); if (disposing) { @@ -336,7 +336,7 @@ protected virtual void Dispose(bool disposing) _mainVM?.Dispose(); } - Log.Info("|App.Dispose|End Flow Launcher dispose ----------------------------------------------------"); + API.LogInfo(ClassName, "End Flow Launcher dispose ----------------------------------------------------"); }); } diff --git a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs index 0d6f2e469aa..eb492e3344e 100644 --- a/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs +++ b/Flow.Launcher/Converters/QuerySuggestionBoxConverter.cs @@ -4,13 +4,14 @@ using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.ViewModel; namespace Flow.Launcher.Converters; public class QuerySuggestionBoxConverter : IMultiValueConverter { + private static readonly string ClassName = nameof(QuerySuggestionBoxConverter); + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { // values[0] is TextBox: The textbox displaying the autocomplete suggestion @@ -64,7 +65,7 @@ values[2] is not string queryText || } catch (Exception e) { - Log.Exception(nameof(QuerySuggestionBoxConverter), "fail to convert text for suggestion box", e); + App.API.LogException(ClassName, "fail to convert text for suggestion box", e); return string.Empty; } } diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher/Helper/AutoStartup.cs index c5e20504b7d..568ea794446 100644 --- a/Flow.Launcher/Helper/AutoStartup.cs +++ b/Flow.Launcher/Helper/AutoStartup.cs @@ -11,6 +11,8 @@ namespace Flow.Launcher.Helper; public class AutoStartup { + private static readonly string ClassName = nameof(AutoStartup); + private const string StartupPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; private const string LogonTaskName = $"{Constant.FlowLauncher} Startup"; private const string LogonTaskDesc = $"{Constant.FlowLauncher} Auto Startup"; @@ -34,7 +36,7 @@ public static bool IsEnabled } catch (Exception e) { - Log.Error("AutoStartup", $"Ignoring non-critical registry error (querying if enabled): {e}"); + App.API.LogError(ClassName, $"Ignoring non-critical registry error (querying if enabled): {e}"); } return false; @@ -61,7 +63,7 @@ private static bool CheckLogonTask() } catch (Exception e) { - Log.Error("AutoStartup", $"Failed to check logon task: {e}"); + App.API.LogError(ClassName, $"Failed to check logon task: {e}"); } } @@ -112,7 +114,7 @@ private static void Disable(bool logonTask) } catch (Exception e) { - Log.Error("AutoStartup", $"Failed to disable auto-startup: {e}"); + App.API.LogError(ClassName, $"Failed to disable auto-startup: {e}"); throw; } } @@ -133,7 +135,7 @@ private static void Enable(bool logonTask) } catch (Exception e) { - Log.Error("AutoStartup", $"Failed to enable auto-startup: {e}"); + App.API.LogError(ClassName, $"Failed to enable auto-startup: {e}"); throw; } } @@ -161,7 +163,7 @@ private static bool ScheduleLogonTask() } catch (Exception e) { - Log.Error("AutoStartup", $"Failed to schedule logon task: {e}"); + App.API.LogError(ClassName, $"Failed to schedule logon task: {e}"); return false; } } @@ -176,7 +178,7 @@ private static bool UnscheduleLogonTask() } catch (Exception e) { - Log.Error("AutoStartup", $"Failed to unschedule logon task: {e}"); + App.API.LogError(ClassName, $"Failed to unschedule logon task: {e}"); return false; } } diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index 0771a60749a..1e83415cc46 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -12,6 +12,8 @@ namespace Flow.Launcher.Helper; internal static class HotKeyMapper { + private static readonly string ClassName = nameof(HotKeyMapper); + private static Settings _settings; private static MainViewModel _mainViewModel; @@ -51,7 +53,7 @@ private static void SetWithChefKeys(string hotkeyStr) } catch (Exception e) { - Log.Error( + App.API.LogError(ClassName, string.Format("|HotkeyMapper.SetWithChefKeys|Error registering hotkey: {0} \nStackTrace:{1}", e.Message, e.StackTrace)); @@ -76,7 +78,7 @@ internal static void SetHotkey(HotkeyModel hotkey, EventHandler } catch (Exception e) { - Log.Error( + App.API.LogError(ClassName, string.Format("|HotkeyMapper.SetHotkey|Error registering hotkey {2}: {0} \nStackTrace:{1}", e.Message, e.StackTrace, @@ -102,7 +104,7 @@ internal static void RemoveHotkey(string hotkeyStr) } catch (Exception e) { - Log.Error( + App.API.LogError(ClassName, string.Format("|HotkeyMapper.RemoveHotkey|Error removing hotkey: {0} \nStackTrace:{1}", e.Message, e.StackTrace)); diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index 77bebe2d37d..93b9a8aaa23 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -12,6 +12,8 @@ namespace Flow.Launcher.Helper; public static class WallpaperPathRetrieval { + private static readonly string ClassName = nameof(WallpaperPathRetrieval); + private const int MaxCacheSize = 3; private static readonly Dictionary<(string, DateTime), ImageBrush> WallpaperCache = new(); private static readonly object CacheLock = new(); @@ -29,7 +31,7 @@ public static Brush GetWallpaperBrush() var wallpaperPath = Win32Helper.GetWallpaperPath(); if (string.IsNullOrEmpty(wallpaperPath) || !File.Exists(wallpaperPath)) { - App.API.LogInfo(nameof(WallpaperPathRetrieval), $"Wallpaper path is invalid: {wallpaperPath}"); + App.API.LogInfo(ClassName, $"Wallpaper path is invalid: {wallpaperPath}"); var wallpaperColor = GetWallpaperColor(); return new SolidColorBrush(wallpaperColor); } @@ -54,7 +56,7 @@ public static Brush GetWallpaperBrush() if (originalWidth == 0 || originalHeight == 0) { - App.API.LogInfo(nameof(WallpaperPathRetrieval), $"Failed to load bitmap: Width={originalWidth}, Height={originalHeight}"); + App.API.LogInfo(ClassName, $"Failed to load bitmap: Width={originalWidth}, Height={originalHeight}"); return new SolidColorBrush(Colors.Transparent); } @@ -95,7 +97,7 @@ public static Brush GetWallpaperBrush() } catch (Exception ex) { - App.API.LogException(nameof(WallpaperPathRetrieval), "Error retrieving wallpaper", ex); + App.API.LogException(ClassName, "Error retrieving wallpaper", ex); return new SolidColorBrush(Colors.Transparent); } } @@ -113,7 +115,7 @@ private static Color GetWallpaperColor() } catch (Exception ex) { - App.API.LogException(nameof(WallpaperPathRetrieval), "Error parsing wallpaper color", ex); + App.API.LogException(ClassName, "Error parsing wallpaper color", ex); } } diff --git a/Flow.Launcher/MessageBoxEx.xaml.cs b/Flow.Launcher/MessageBoxEx.xaml.cs index 3d94769d002..a55aeb81118 100644 --- a/Flow.Launcher/MessageBoxEx.xaml.cs +++ b/Flow.Launcher/MessageBoxEx.xaml.cs @@ -4,13 +4,13 @@ using System.Windows; using System.Windows.Input; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Image; -using Flow.Launcher.Infrastructure.Logger; namespace Flow.Launcher { public partial class MessageBoxEx : Window { + private static readonly string ClassName = nameof(MessageBoxEx); + private static MessageBoxEx msgBox; private static MessageBoxResult _result = MessageBoxResult.None; @@ -59,7 +59,7 @@ public static MessageBoxResult Show( } catch (Exception e) { - Log.Error($"|MessageBoxEx.Show|An error occurred: {e.Message}"); + App.API.LogError(ClassName, $"An error occurred: {e.Message}"); msgBox = null; return MessageBoxResult.None; } diff --git a/Flow.Launcher/Msg.xaml.cs b/Flow.Launcher/Msg.xaml.cs index ff9accd62f2..110235cb5ac 100644 --- a/Flow.Launcher/Msg.xaml.cs +++ b/Flow.Launcher/Msg.xaml.cs @@ -5,7 +5,6 @@ using System.Windows.Input; using System.Windows.Media.Animation; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Image; namespace Flow.Launcher { diff --git a/Flow.Launcher/Notification.cs b/Flow.Launcher/Notification.cs index 30b3a067334..be81e6ec6ef 100644 --- a/Flow.Launcher/Notification.cs +++ b/Flow.Launcher/Notification.cs @@ -1,5 +1,4 @@ using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Logger; using Microsoft.Toolkit.Uwp.Notifications; using System; using System.IO; @@ -9,6 +8,8 @@ namespace Flow.Launcher { internal static class Notification { + private static readonly string ClassName = nameof(Notification); + internal static bool legacy = !Win32Helper.IsNotificationSupported(); internal static void Uninstall() @@ -51,12 +52,12 @@ private static void ShowInternal(string title, string subTitle, string iconPath { // Temporary fix for the Windows 11 notification issue // Possibly from 22621.1413 or 22621.1485, judging by post time of #2024 - Log.Exception("Flow.Launcher.Notification|Notification InvalidOperationException Error", e); + App.API.LogException(ClassName, "Notification InvalidOperationException Error", e); LegacyShow(title, subTitle, iconPath); } catch (Exception e) { - Log.Exception("Flow.Launcher.Notification|Notification Error", e); + App.API.LogException(ClassName, "Notification Error", e); LegacyShow(title, subTitle, iconPath); } } diff --git a/Flow.Launcher/ProgressBoxEx.xaml.cs b/Flow.Launcher/ProgressBoxEx.xaml.cs index 2395bdf3497..840c8bade87 100644 --- a/Flow.Launcher/ProgressBoxEx.xaml.cs +++ b/Flow.Launcher/ProgressBoxEx.xaml.cs @@ -2,12 +2,13 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Input; -using Flow.Launcher.Infrastructure.Logger; namespace Flow.Launcher { public partial class ProgressBoxEx : Window { + private static readonly string ClassName = nameof(ProgressBoxEx); + private readonly Action _cancelProgress; private ProgressBoxEx(Action cancelProgress) @@ -47,7 +48,7 @@ await Application.Current.Dispatcher.InvokeAsync(() => } catch (Exception e) { - Log.Error($"|ProgressBoxEx.Show|An error occurred: {e.Message}"); + App.API.LogError(ClassName, $"An error occurred: {e.Message}"); await reportProgressAsync(null).ConfigureAwait(false); } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 5438eac7dac..3abc57b8a81 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -435,16 +435,16 @@ public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePlugi PluginManager.UninstallPluginAsync(pluginMetadata, removePluginSettings); public long StopwatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = "") => - Stopwatch.Debug($"|{className}.{methodName}|{message}", action); + Stopwatch.Debug(className, message, action, methodName); public Task StopwatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => - Stopwatch.DebugAsync($"|{className}.{methodName}|{message}", action); + Stopwatch.DebugAsync(className, message, action, methodName); public long StopwatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = "") => - Stopwatch.Normal($"|{className}.{methodName}|{message}", action); + Stopwatch.Info(className, message, action, methodName); public Task StopwatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => - Stopwatch.NormalAsync($"|{className}.{methodName}|{message}", action); + Stopwatch.InfoAsync(className, message, action, methodName); #endregion diff --git a/Flow.Launcher/ReportWindow.xaml.cs b/Flow.Launcher/ReportWindow.xaml.cs index 6fe90783ec9..0ab785a17b6 100644 --- a/Flow.Launcher/ReportWindow.xaml.cs +++ b/Flow.Launcher/ReportWindow.xaml.cs @@ -8,13 +8,15 @@ using System.Windows.Documents; using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.SharedCommands; +using Flow.Launcher.Infrastructure.UserSettings; namespace Flow.Launcher { internal partial class ReportWindow { + private static readonly string ClassName = nameof(ReportWindow); + public ReportWindow(Exception exception) { InitializeComponent(); @@ -38,7 +40,7 @@ private static string GetIssuesUrl(string website) private void SetException(Exception exception) { - string path = Log.CurrentLogDirectory; + var path = DataLocation.VersionLogDirectory; var directory = new DirectoryInfo(path); var log = directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First(); diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index 28140f0245c..b4a3ae47a92 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -6,7 +6,6 @@ using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.UserSettings; -using Flow.Launcher.Plugin; using Flow.Launcher.SettingPages.Views; using Flow.Launcher.ViewModel; using ModernWpf.Controls; @@ -16,7 +15,6 @@ namespace Flow.Launcher; public partial class SettingWindow { - private readonly IPublicAPI _api; private readonly Settings _settings; private readonly SettingWindowViewModel _viewModel; @@ -26,7 +24,6 @@ public SettingWindow() _settings = Ioc.Default.GetRequiredService(); DataContext = viewModel; _viewModel = viewModel; - _api = Ioc.Default.GetRequiredService(); InitializePosition(); InitializeComponent(); } @@ -49,7 +46,7 @@ private void OnClosed(object sender, EventArgs e) _settings.SettingWindowTop = Top; _settings.SettingWindowLeft = Left; _viewModel.Save(); - _api.SavePluginSettings(); + App.API.SavePluginSettings(); } private void OnCloseExecuted(object sender, ExecutedRoutedEventArgs e) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index f6b9aa67c94..00675149b41 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -16,7 +16,6 @@ using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Hotkey; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; @@ -30,6 +29,8 @@ public partial class MainViewModel : BaseModel, ISavable, IDisposable { #region Private Fields + private static readonly string ClassName = nameof(MainViewModel); + private bool _isQueryRunning; private Query _lastQuery; private string _queryTextBeforeLeaveResults; @@ -213,7 +214,7 @@ async Task UpdateActionAsync() } if (!_disposed) - Log.Error("MainViewModel", "Unexpected ResultViewUpdate ends"); + App.API.LogError(ClassName, "Unexpected ResultViewUpdate ends"); } void continueAction(Task t) @@ -221,7 +222,7 @@ void continueAction(Task t) #if DEBUG throw t.Exception; #else - Log.Error($"Error happen in task dealing with viewupdate for results. {t.Exception}"); + App.API.LogError(ClassName, $"Error happen in task dealing with viewupdate for results. {t.Exception}"); _resultsViewUpdateTask = Task.Run(UpdateActionAsync).ContinueWith(continueAction, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.Default); #endif @@ -257,7 +258,7 @@ public void RegisterResultsUpdatedEvent() if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, pair.Metadata, e.Query, token))) { - Log.Error("MainViewModel", "Unable to add item to Result Update Queue"); + App.API.LogError(ClassName, "Unable to add item to Result Update Queue"); } }; } @@ -891,7 +892,7 @@ public bool InternalPreviewVisible #if DEBUG throw new NotImplementedException("ResultAreaColumn should match ResultAreaColumnPreviewShown/ResultAreaColumnPreviewHidden value"); #else - Log.Error("MainViewModel", "ResultAreaColumnPreviewHidden/ResultAreaColumnPreviewShown int value not implemented", "InternalPreviewVisible"); + App.API.LogError(ClassName, "ResultAreaColumnPreviewHidden/ResultAreaColumnPreviewShown int value not implemented", "InternalPreviewVisible"); return false; #endif } @@ -1303,7 +1304,7 @@ async Task QueryTaskAsync(PluginPair plugin, CancellationToken token) if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, plugin.Metadata, query, token, reSelect))) { - Log.Error("MainViewModel", "Unable to add item to Result Update Queue"); + App.API.LogError(ClassName, "Unable to add item to Result Update Queue"); } } } @@ -1347,8 +1348,8 @@ private Query ConstructQuery(string queryText, IEnumerable } catch (Exception e) { - Log.Exception( - $"{nameof(MainViewModel)}.{nameof(ConstructQuery)}|Error when expanding shortcut {shortcut.Key}", + App.API.LogException(ClassName, + $"Error when expanding shortcut {shortcut.Key}", e); } } diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index 8d7569dc1e7..648ac49bbf2 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Drawing.Text; using System.IO; @@ -7,7 +6,6 @@ using System.Windows; using System.Windows.Media; using Flow.Launcher.Infrastructure.Image; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; @@ -15,6 +13,8 @@ namespace Flow.Launcher.ViewModel { public class ResultViewModel : BaseModel { + private static readonly string ClassName = nameof(ResultViewModel); + private static readonly PrivateFontCollection FontCollection = new(); private static readonly Dictionary Fonts = new(); @@ -232,8 +232,8 @@ private async Task LoadImageInternalAsync(string imagePath, Result. } catch (Exception e) { - Log.Exception( - $"|ResultViewModel.LoadImageInternalAsync|IcoPath is empty and exception when calling IconDelegate for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", + App.API.LogException(ClassName, + $"IcoPath is empty and exception when calling IconDelegate for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", e); } } diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index 3bee49bf20a..9ad31ad1401 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -15,6 +15,8 @@ namespace Flow.Launcher.Plugin.BrowserBookmark; public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContextMenu, IDisposable { + private static readonly string ClassName = nameof(Main); + internal static string _faviconCacheDir; internal static PluginInitContext _context; @@ -221,7 +223,7 @@ public List LoadContextMenus(Result selectedResult) catch (Exception e) { var message = "Failed to set url in clipboard"; - _context.API.LogException(nameof(Main), message, e); + _context.API.LogException(ClassName, message, e); _context.API.ShowMsg(message); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs index f479078242e..633af7b6ba2 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs @@ -15,6 +15,8 @@ namespace Flow.Launcher.Plugin.Explorer { internal class ContextMenu : IContextMenu { + private static readonly string ClassName = nameof(ContextMenu); + private PluginInitContext Context { get; set; } private Settings Settings { get; set; } @@ -469,7 +471,7 @@ private Result CreateOpenWithMenu(SearchResult record) private void LogException(string message, Exception e) { - Context.API.LogException(nameof(ContextMenu), message, e); + Context.API.LogException(ClassName, message, e); } private static bool CanRunAsDifferentUser(string path) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs index 1a0d3bd15d4..63174425282 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs @@ -9,6 +9,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo { public static class DirectoryInfoSearch { + private static readonly string ClassName = nameof(DirectoryInfoSearch); + internal static IEnumerable TopLevelDirectorySearch(Query query, string search, CancellationToken token) { var criteria = ConstructSearchCriteria(search); @@ -75,7 +77,7 @@ private static IEnumerable DirectorySearch(EnumerationOptions enum } catch (Exception e) { - Main.Context.API.LogException(nameof(DirectoryInfoSearch), "Error occurred while searching path", e); + Main.Context.API.LogException(ClassName, "Error occurred while searching path", e); throw; } diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs index 4c07341ec2a..d7f44ccce51 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs @@ -12,6 +12,8 @@ namespace Flow.Launcher.Plugin.ProcessKiller { internal class ProcessHelper { + private static readonly string ClassName = nameof(ProcessHelper); + private readonly HashSet _systemProcessList = new() { "conhost", @@ -131,7 +133,7 @@ public void TryKill(PluginInitContext context, Process p) } catch (Exception e) { - context.API.LogException($"{nameof(ProcessHelper)}", $"Failed to kill process {p.ProcessName}", e); + context.API.LogException(ClassName, $"Failed to kill process {p.ProcessName}", e); } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 16b6bcab203..d2884599467 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -109,7 +109,6 @@ public async Task> QueryAsync(Query query, CancellationToken token) } catch (OperationCanceledException) { - Context.API.LogDebug(ClassName, "Query operation cancelled"); return emptyResults; } finally diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs index 65be06b53ee..681c8b64967 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs @@ -11,6 +11,8 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { public class Baidu : SuggestionSource { + private static readonly string ClassName = nameof(Baidu); + private readonly Regex _reg = new Regex("window.baidu.sug\\((.*)\\)"); public override async Task> SuggestionsAsync(string query, CancellationToken token) @@ -24,7 +26,7 @@ public override async Task> SuggestionsAsync(string query, Cancella } catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException}) { - Main._context.API.LogException(nameof(Baidu), "Can't get suggestion from Baidu", e); + Main._context.API.LogException(ClassName, "Can't get suggestion from Baidu", e); return null; } @@ -39,7 +41,7 @@ public override async Task> SuggestionsAsync(string query, Cancella } catch (JsonException e) { - Main._context.API.LogException(nameof(Baidu), "Can't parse suggestions", e); + Main._context.API.LogException(ClassName, "Can't parse suggestions", e); return new List(); } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs index 9efc36263c2..ccfa5dcc8a3 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs @@ -10,6 +10,8 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { public class Bing : SuggestionSource { + private static readonly string ClassName = nameof(Bing); + public override async Task> SuggestionsAsync(string query, CancellationToken token) { try @@ -33,12 +35,12 @@ public override async Task> SuggestionsAsync(string query, Cancella } catch (Exception e) when (e is HttpRequestException or { InnerException: TimeoutException }) { - Main._context.API.LogException(nameof(Bing), "Can't get suggestion from Bing", e); + Main._context.API.LogException(ClassName, "Can't get suggestion from Bing", e); return null; } catch (JsonException e) { - Main._context.API.LogException(nameof(Bing), "Can't parse suggestions", e); + Main._context.API.LogException(ClassName, "Can't parse suggestions", e); return new List(); } } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs index 1d248caf37a..0627f722099 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs @@ -10,6 +10,8 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { public class DuckDuckGo : SuggestionSource { + private static readonly string ClassName = nameof(DuckDuckGo); + public override async Task> SuggestionsAsync(string query, CancellationToken token) { // When the search query is empty, DuckDuckGo returns `[]`. When it's not empty, it returns data @@ -34,12 +36,12 @@ public override async Task> SuggestionsAsync(string query, Cancella } catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException}) { - Main._context.API.LogException(nameof(DuckDuckGo), "Can't get suggestion from DuckDuckGo", e); + Main._context.API.LogException(ClassName, "Can't get suggestion from DuckDuckGo", e); return null; } catch (JsonException e) { - Main._context.API.LogException(nameof(DuckDuckGo), "Can't parse suggestions", e); + Main._context.API.LogException(ClassName, "Can't parse suggestions", e); return new List(); } } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs index ad8fb508f09..f28212524ae 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs @@ -10,6 +10,8 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { public class Google : SuggestionSource { + private static readonly string ClassName = nameof(Google); + public override async Task> SuggestionsAsync(string query, CancellationToken token) { try @@ -27,12 +29,12 @@ public override async Task> SuggestionsAsync(string query, Cancella } catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException}) { - Main._context.API.LogException(nameof(Google), "Can't get suggestion from Google", e); + Main._context.API.LogException(ClassName, "Can't get suggestion from Google", e); return null; } catch (JsonException e) { - Main._context.API.LogException(nameof(Google), "Can't parse suggestions", e); + Main._context.API.LogException(ClassName, "Can't parse suggestions", e); return new List(); } } diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Log.cs b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Log.cs index 257b0fa8b8d..c72230f2bfc 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Log.cs +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Log.cs @@ -11,10 +11,12 @@ public static void Init(IPublicAPI api) { _api = api; } + public static void Exception(string message, Exception exception, Type type, [CallerMemberName] string methodName = "") { _api?.LogException(type.FullName, message, exception, methodName); } + public static void Warn(string message, Type type, [CallerMemberName] string methodName = "") { _api?.LogWarn(type.FullName, message, methodName);