mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge branch 'dev' into 250412-ImportThemePreset
This commit is contained in:
commit
b2a3782f63
50 changed files with 285 additions and 301 deletions
|
|
@ -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 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.Infrastructure;
|
||||
using Flow.Launcher.Infrastructure.UserSettings;
|
||||
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<IPublicAPI>();
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -51,7 +52,7 @@ namespace Flow.Launcher.Core.Configuration
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Configuration
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Exception("|Portable.EnablePortableMode|Error occurred while enabling portable mode", e);
|
||||
API.LogException(ClassName, "Error occurred while enabling portable mode", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<IPublicAPI>();
|
||||
|
||||
private static readonly string ClassName = nameof(CommunityPluginSource);
|
||||
|
||||
private string latestEtag = "";
|
||||
|
||||
private List<UserPlugin> plugins = new();
|
||||
|
||||
private static JsonSerializerOptions PluginStoreItemSerializationOption = new JsonSerializerOptions()
|
||||
private static readonly JsonSerializerOptions PluginStoreItemSerializationOption = new()
|
||||
{
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
|
||||
};
|
||||
|
|
@ -34,35 +41,49 @@ namespace Flow.Launcher.Core.ExternalPlugins
|
|||
/// </remarks>
|
||||
public async Task<List<UserPlugin>> 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<List<UserPlugin>>(PluginStoreItemSerializationOption, cancellationToken: token)
|
||||
.ConfigureAwait(false);
|
||||
this.latestEtag = response.Headers.ETag?.Tag;
|
||||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
plugins = await response.Content
|
||||
.ReadFromJsonAsync<List<UserPlugin>>(PluginStoreItemSerializationOption, cancellationToken: token)
|
||||
.ConfigureAwait(false);
|
||||
latestEtag = response.Headers.ETag?.Tag;
|
||||
|
||||
Log.Info(nameof(CommunityPluginSource), $"Loaded {this.plugins.Count} plugins from {ManifestFileUrl}");
|
||||
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 if (response.StatusCode == HttpStatusCode.NotModified)
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Info(nameof(CommunityPluginSource), $"Resource {ManifestFileUrl} has not been modified.");
|
||||
return this.plugins;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System.Linq;
|
|||
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<IPublicAPI>();
|
||||
|
||||
internal abstract string Language { get; }
|
||||
|
|
@ -120,7 +121,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
|||
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");
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ using Flow.Launcher.Plugin;
|
|||
|
||||
namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
||||
{
|
||||
|
||||
internal class JavaScriptEnvironment : TypeScriptEnvironment
|
||||
{
|
||||
internal override string Language => AllowedLanguage.JavaScript;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ using Flow.Launcher.Plugin;
|
|||
|
||||
namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
||||
{
|
||||
|
||||
internal class JavaScriptV2Environment : TypeScriptV2Environment
|
||||
{
|
||||
internal override string Language => AllowedLanguage.JavaScriptV2;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using Flow.Launcher.Core.Plugin;
|
|||
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 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
|||
|
||||
internal PythonEnvironment(List<PluginMetadata> 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using Flow.Launcher.Core.Plugin;
|
|||
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 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
|||
|
||||
internal TypeScriptEnvironment(List<PluginMetadata> 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using Flow.Launcher.Core.Plugin;
|
|||
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 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments
|
|||
|
||||
internal TypeScriptV2Environment(List<PluginMetadata> 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 @@ namespace Flow.Launcher.Core.ExternalPlugins
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Ioc.Default.GetRequiredService<IPublicAPI>().LogException(nameof(PluginsManifest), "Http request failed", e);
|
||||
Ioc.Default.GetRequiredService<IPublicAPI>().LogException(ClassName, "Http request failed", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,14 +3,20 @@ using System.Collections.Generic;
|
|||
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<IPublicAPI>();
|
||||
|
||||
/// <summary>
|
||||
/// Parse plugin metadata in the given directories
|
||||
/// </summary>
|
||||
|
|
@ -32,7 +38,7 @@ namespace Flow.Launcher.Core.Plugin
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Plugin
|
|||
|
||||
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 @@ namespace Flow.Launcher.Core.Plugin
|
|||
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 @@ namespace Flow.Launcher.Core.Plugin
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ using System.Threading.Tasks;
|
|||
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 @@ namespace Flow.Launcher.Core.Plugin
|
|||
() => 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 @@ namespace Flow.Launcher.Core.Plugin
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Plugin
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Plugin
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Plugin
|
|||
}
|
||||
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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,19 +89,19 @@ namespace Flow.Launcher.Core.Plugin
|
|||
#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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 @@ namespace Flow.Launcher.Core.Plugin
|
|||
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 @@ namespace Flow.Launcher.Core.Plugin
|
|||
oldProcess.Dispose();
|
||||
}
|
||||
|
||||
|
||||
public override async ValueTask DisposeAsync()
|
||||
{
|
||||
await base.DisposeAsync();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using System.Reflection;
|
|||
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<IPublicAPI>();
|
||||
|
||||
private const string Folder = "Languages";
|
||||
private const string DefaultLanguageCode = "en";
|
||||
private const string DefaultFile = "en.xaml";
|
||||
|
|
@ -80,7 +85,7 @@ namespace Flow.Launcher.Core.Resource
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ using System.Windows.Media.Effects;
|
|||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private readonly string ClassName = nameof(Theme);
|
||||
|
||||
public bool BlurEnabled { get; private set; }
|
||||
|
||||
private const string ThemeMetadataNamePrefix = "Name:";
|
||||
|
|
@ -73,7 +74,7 @@ namespace Flow.Launcher.Core.Resource
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Core.Resource
|
|||
}
|
||||
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));
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ using System.Windows;
|
|||
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 @@ namespace Flow.Launcher.Core
|
|||
{
|
||||
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 @@ namespace Flow.Launcher.Core
|
|||
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 @@ namespace Flow.Launcher.Core
|
|||
|
||||
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 @@ namespace Flow.Launcher.Core
|
|||
}
|
||||
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"),
|
||||
|
|
|
|||
|
|
@ -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 @@ namespace Flow.Launcher.Infrastructure.Http
|
|||
|
||||
public static HttpProxy Proxy
|
||||
{
|
||||
private get { return proxy; }
|
||||
private get => proxy;
|
||||
set
|
||||
{
|
||||
proxy = value;
|
||||
|
|
@ -72,13 +73,13 @@ namespace Flow.Launcher.Infrastructure.Http
|
|||
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<IPublicAPI>().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 @@ namespace Flow.Launcher.Infrastructure.Http
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Infrastructure.Http
|
|||
/// <returns>The Http result as string. Null if cancellation requested</returns>
|
||||
public static Task<string> 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 @@ namespace Flow.Launcher.Infrastructure.Http
|
|||
/// <returns>The Http result as string. Null if cancellation requested</returns>
|
||||
public static async Task<string> 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 @@ namespace Flow.Launcher.Infrastructure.Http
|
|||
public static async Task<Stream> 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 @@ namespace Flow.Launcher.Infrastructure.Http
|
|||
public static async Task<HttpResponseMessage> 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ using System.Threading;
|
|||
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<IPublicAPI>();
|
||||
|
||||
private static readonly string ClassName = nameof(ImageLoader);
|
||||
|
||||
private static readonly ImageCache ImageCache = new();
|
||||
|
|
@ -58,14 +53,14 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
|
||||
_ = 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 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
{
|
||||
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 @@ namespace Flow.Launcher.Infrastructure.Image
|
|||
{
|
||||
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
|
||||
|
|
|
|||
|
|
@ -94,13 +94,6 @@ namespace Flow.Launcher.Infrastructure.Logger
|
|||
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 @@ namespace Flow.Launcher.Infrastructure.Logger
|
|||
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"
|
||||
/// <param name="message">Example: "|ClassName.MethodName|Message" </param>
|
||||
/// <param name="e">Exception</param>
|
||||
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 @@ namespace Flow.Launcher.Infrastructure.Logger
|
|||
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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Flow.Launcher.Infrastructure.Logger;
|
||||
|
||||
|
|
@ -9,54 +10,50 @@ namespace Flow.Launcher.Infrastructure
|
|||
/// <summary>
|
||||
/// This stopwatch will appear only in Debug mode
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This stopwatch will appear only in Debug mode
|
||||
/// </summary>
|
||||
public static async Task<long> DebugAsync(string message, Func<Task> action)
|
||||
public static async Task<long> DebugAsync(string className, string message, Func<Task> 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<long> NormalAsync(string message, Func<Task> action)
|
||||
public static async Task<long> InfoAsync(string className, string message, Func<Task> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ namespace Flow.Launcher.Infrastructure.Storage
|
|||
/// </remarks>
|
||||
public class BinaryStorage<T> : ISavable
|
||||
{
|
||||
private static readonly string ClassName = "BinaryStorage";
|
||||
|
||||
protected T? Data;
|
||||
|
||||
public const string FileSuffix = ".cache";
|
||||
|
|
@ -59,7 +61,7 @@ namespace Flow.Launcher.Infrastructure.Storage
|
|||
{
|
||||
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 @@ namespace Flow.Launcher.Infrastructure.Storage
|
|||
}
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<IPublicAPI>();
|
||||
|
||||
public FlowLauncherJsonStorage()
|
||||
{
|
||||
DirectoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName);
|
||||
|
|
@ -32,7 +27,7 @@ namespace Flow.Launcher.Infrastructure.Storage
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Infrastructure.Storage
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ namespace Flow.Launcher.Infrastructure.Storage
|
|||
/// </summary>
|
||||
public class JsonStorage<T> : ISavable where T : new()
|
||||
{
|
||||
private static readonly string ClassName = "JsonStorage";
|
||||
|
||||
protected T? Data;
|
||||
|
||||
// need a new directory name
|
||||
|
|
@ -104,7 +106,7 @@ namespace Flow.Launcher.Infrastructure.Storage
|
|||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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<IPublicAPI>();
|
||||
|
||||
public PluginBinaryStorage(string cacheName, string cacheDirectory)
|
||||
{
|
||||
DirectoryPath = cacheDirectory;
|
||||
|
|
@ -30,7 +25,7 @@ namespace Flow.Launcher.Infrastructure.Storage
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Infrastructure.Storage
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<IPublicAPI>();
|
||||
|
||||
public PluginJsonStorage()
|
||||
{
|
||||
// C# related, add python related below
|
||||
|
|
@ -42,7 +37,7 @@ namespace Flow.Launcher.Infrastructure.Storage
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Infrastructure.Storage
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,7 +376,8 @@ namespace Flow.Launcher.Infrastructure
|
|||
if (!IsForegroundWindow(hwnd))
|
||||
{
|
||||
var result = PInvoke.SetForegroundWindow(hwnd);
|
||||
if (!result) throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||
// If we cannot set the foreground window, we can use the foreground window and switch the layout
|
||||
if (!result) hwnd = PInvoke.GetForegroundWindow();
|
||||
}
|
||||
|
||||
// Get the current foreground window thread ID
|
||||
|
|
|
|||
|
|
@ -148,8 +148,8 @@ namespace Flow.Launcher
|
|||
|
||||
Ioc.Default.GetRequiredService<Portable>().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 @@ namespace Flow.Launcher
|
|||
|
||||
_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 @@ namespace Flow.Launcher
|
|||
AutoUpdates();
|
||||
|
||||
API.SaveAppAllSettings();
|
||||
Log.Info("|App.OnStartup|End Flow Launcher startup ----------------------------------------------------");
|
||||
API.LogInfo(ClassName, "End Flow Launcher startup ----------------------------------------------------");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -250,19 +250,19 @@ namespace Flow.Launcher
|
|||
{
|
||||
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 @@ namespace Flow.Launcher
|
|||
|
||||
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 @@ namespace Flow.Launcher
|
|||
_mainVM?.Dispose();
|
||||
}
|
||||
|
||||
Log.Info("|App.Dispose|End Flow Launcher dispose ----------------------------------------------------");
|
||||
API.LogInfo(ClassName, "End Flow Launcher dispose ----------------------------------------------------");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,14 @@ using System.Windows;
|
|||
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 @@ public class QuerySuggestionBoxConverter : IMultiValueConverter
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 class AutoStartup
|
|||
}
|
||||
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 @@ public class AutoStartup
|
|||
}
|
||||
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 @@ public class AutoStartup
|
|||
}
|
||||
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 @@ public class AutoStartup
|
|||
}
|
||||
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 @@ public class AutoStartup
|
|||
}
|
||||
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 @@ public class AutoStartup
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("AutoStartup", $"Failed to unschedule logon task: {e}");
|
||||
App.API.LogError(ClassName, $"Failed to unschedule logon task: {e}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 @@ internal static class HotKeyMapper
|
|||
}
|
||||
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 class HotKeyMapper
|
|||
}
|
||||
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 class HotKeyMapper
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(
|
||||
App.API.LogError(ClassName,
|
||||
string.Format("|HotkeyMapper.RemoveHotkey|Error removing hotkey: {0} \nStackTrace:{1}",
|
||||
e.Message,
|
||||
e.StackTrace));
|
||||
|
|
|
|||
|
|
@ -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 class WallpaperPathRetrieval
|
|||
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 class WallpaperPathRetrieval
|
|||
|
||||
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 class WallpaperPathRetrieval
|
|||
}
|
||||
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 @@ public static class WallpaperPathRetrieval
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
App.API.LogException(nameof(WallpaperPathRetrieval), "Error parsing wallpaper color", ex);
|
||||
App.API.LogException(ClassName, "Error parsing wallpaper color", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ using System.Threading.Tasks;
|
|||
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 @@ namespace Flow.Launcher
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System.Windows.Forms;
|
|||
using System.Windows.Input;
|
||||
using System.Windows.Media.Animation;
|
||||
using Flow.Launcher.Infrastructure;
|
||||
using Flow.Launcher.Infrastructure.Image;
|
||||
|
||||
namespace Flow.Launcher
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 @@ namespace Flow.Launcher
|
|||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 @@ namespace Flow.Launcher
|
|||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -435,16 +435,16 @@ namespace Flow.Launcher
|
|||
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<long> StopwatchLogDebugAsync(string className, string message, Func<Task> 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<long> StopwatchLogInfoAsync(string className, string message, Func<Task> action, [CallerMemberName] string methodName = "") =>
|
||||
Stopwatch.NormalAsync($"|{className}.{methodName}|{message}", action);
|
||||
Stopwatch.InfoAsync(className, message, action, methodName);
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,15 @@ using System.Windows;
|
|||
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 @@ namespace Flow.Launcher
|
|||
|
||||
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();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using System.Windows.Interop;
|
|||
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 partial class SettingWindow
|
|||
_settings = Ioc.Default.GetRequiredService<Settings>();
|
||||
DataContext = viewModel;
|
||||
_viewModel = viewModel;
|
||||
_api = Ioc.Default.GetRequiredService<IPublicAPI>();
|
||||
InitializePosition();
|
||||
InitializeComponent();
|
||||
}
|
||||
|
|
@ -49,7 +46,7 @@ public partial class SettingWindow
|
|||
_settings.SettingWindowTop = Top;
|
||||
_settings.SettingWindowLeft = Left;
|
||||
_viewModel.Save();
|
||||
_api.SavePluginSettings();
|
||||
App.API.SavePluginSettings();
|
||||
}
|
||||
|
||||
private void OnCloseExecuted(object sender, ExecutedRoutedEventArgs e)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ using CommunityToolkit.Mvvm.Input;
|
|||
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 @@ namespace Flow.Launcher.ViewModel
|
|||
{
|
||||
#region Private Fields
|
||||
|
||||
private static readonly string ClassName = nameof(MainViewModel);
|
||||
|
||||
private bool _isQueryRunning;
|
||||
private Query _lastQuery;
|
||||
private string _queryTextBeforeLeaveResults;
|
||||
|
|
@ -213,7 +214,7 @@ namespace Flow.Launcher.ViewModel
|
|||
}
|
||||
|
||||
if (!_disposed)
|
||||
Log.Error("MainViewModel", "Unexpected ResultViewUpdate ends");
|
||||
App.API.LogError(ClassName, "Unexpected ResultViewUpdate ends");
|
||||
}
|
||||
|
||||
void continueAction(Task t)
|
||||
|
|
@ -221,7 +222,7 @@ namespace Flow.Launcher.ViewModel
|
|||
#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 @@ namespace Flow.Launcher.ViewModel
|
|||
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 @@ namespace Flow.Launcher.ViewModel
|
|||
#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 @@ namespace Flow.Launcher.ViewModel
|
|||
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 @@ namespace Flow.Launcher.ViewModel
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.Threading.Tasks;
|
|||
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<string, string> Fonts = new();
|
||||
|
||||
|
|
@ -232,8 +232,8 @@ namespace Flow.Launcher.ViewModel
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex
|
|||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 @@ namespace Flow.Launcher.Plugin.Explorer
|
|||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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<SearchResult> TopLevelDirectorySearch(Query query, string search, CancellationToken token)
|
||||
{
|
||||
var criteria = ConstructSearchCriteria(search);
|
||||
|
|
@ -75,7 +77,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ namespace Flow.Launcher.Plugin.ProcessKiller
|
|||
{
|
||||
internal class ProcessHelper
|
||||
{
|
||||
private static readonly string ClassName = nameof(ProcessHelper);
|
||||
|
||||
private readonly HashSet<string> _systemProcessList = new()
|
||||
{
|
||||
"conhost",
|
||||
|
|
@ -131,7 +133,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,6 @@ namespace Flow.Launcher.Plugin.Program
|
|||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
Context.API.LogDebug(ClassName, "Query operation cancelled");
|
||||
return emptyResults;
|
||||
}
|
||||
finally
|
||||
|
|
|
|||
|
|
@ -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<List<string>> SuggestionsAsync(string query, CancellationToken token)
|
||||
|
|
@ -24,7 +26,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
}
|
||||
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 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
}
|
||||
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<string>();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<List<string>> SuggestionsAsync(string query, CancellationToken token)
|
||||
{
|
||||
try
|
||||
|
|
@ -33,12 +35,12 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
}
|
||||
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<string>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<List<string>> 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 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
}
|
||||
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<string>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<List<string>> SuggestionsAsync(string query, CancellationToken token)
|
||||
{
|
||||
try
|
||||
|
|
@ -27,12 +29,12 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
|||
}
|
||||
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<string>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,12 @@ namespace Flow.Launcher.Plugin.WindowsSettings
|
|||
{
|
||||
_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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue