diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs index 68be746f28e..e9713564ec7 100644 --- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs +++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs @@ -1,5 +1,6 @@ using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Plugin; using System; using System.Collections.Generic; using System.Net; diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs index affd7c31207..1f23c2f6619 100644 --- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs +++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.ExternalPlugins { diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index ac8abcdcce8..44d3ef0ff7b 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -1,8 +1,9 @@ -using Flow.Launcher.Infrastructure.Logger; -using System; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.ExternalPlugins { @@ -17,11 +18,11 @@ public static class PluginsManifest private static readonly SemaphoreSlim manifestUpdateLock = new(1); private static DateTime lastFetchedAt = DateTime.MinValue; - private static TimeSpan fetchTimeout = TimeSpan.FromMinutes(2); + private static readonly TimeSpan fetchTimeout = TimeSpan.FromMinutes(2); public static List UserPlugins { get; private set; } - public static async Task UpdateManifestAsync(CancellationToken token = default, bool usePrimaryUrlOnly = false) + public static async Task UpdateManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default) { try { @@ -43,7 +44,7 @@ public static async Task UpdateManifestAsync(CancellationToken token = def } catch (Exception e) { - Log.Exception($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Http request failed", e); + Ioc.Default.GetRequiredService().LogException(nameof(PluginsManifest), "Http request failed", e); } finally { diff --git a/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs b/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs deleted file mode 100644 index 79d6d7605e3..00000000000 --- a/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace Flow.Launcher.Core.ExternalPlugins -{ - public record UserPlugin - { - public string ID { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Author { get; set; } - public string Version { get; set; } - public string Language { get; set; } - public string Website { get; set; } - public string UrlDownload { get; set; } - public string UrlSourceCode { get; set; } - public string LocalInstallPath { get; set; } - public string IcoPath { get; set; } - public DateTime? LatestReleaseDate { get; set; } - public DateTime? DateAdded { get; set; } - - public bool IsFromLocalInstallPath => !string.IsNullOrEmpty(LocalInstallPath); - } -} diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 17517832bd8..aa6c54a9434 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -454,16 +454,11 @@ private static bool SameOrLesserPluginVersionExists(string metadataPath) #region Public functions - public static bool PluginModified(string uuid) + public static bool PluginModified(string id) { - return _modifiedPlugins.Contains(uuid); + return _modifiedPlugins.Contains(id); } - - /// - /// Update a plugin to new version, from a zip file. By default will remove the zip file if update is via url, - /// unless it's a local path installation - /// public static async Task UpdatePluginAsync(PluginMetadata existingVersion, UserPlugin newVersion, string zipFilePath) { InstallPlugin(newVersion, zipFilePath, checkModified:false); @@ -471,17 +466,11 @@ public static async Task UpdatePluginAsync(PluginMetadata existingVersion, UserP _modifiedPlugins.Add(existingVersion.ID); } - /// - /// Install a plugin. By default will remove the zip file if installation is from url, unless it's a local path installation - /// public static void InstallPlugin(UserPlugin plugin, string zipFilePath) { InstallPlugin(plugin, zipFilePath, checkModified: true); } - /// - /// Uninstall a plugin. - /// public static async Task UninstallPluginAsync(PluginMetadata plugin, bool removePluginFromSettings = true, bool removePluginSettings = false) { await UninstallPluginAsync(plugin, removePluginFromSettings, removePluginSettings, true); @@ -525,20 +514,20 @@ internal static void InstallPlugin(UserPlugin plugin, string zipFilePath, bool c var folderName = string.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}-{Guid.NewGuid()}" : $"{plugin.Name}-{plugin.Version}"; var defaultPluginIDs = new List - { - "0ECADE17459B49F587BF81DC3A125110", // BrowserBookmark - "CEA0FDFC6D3B4085823D60DC76F28855", // Calculator - "572be03c74c642baae319fc283e561a8", // Explorer - "6A122269676E40EB86EB543B945932B9", // PluginIndicator - "9f8f9b14-2518-4907-b211-35ab6290dee7", // PluginsManager - "b64d0a79-329a-48b0-b53f-d658318a1bf6", // ProcessKiller - "791FC278BA414111B8D1886DFE447410", // Program - "D409510CD0D2481F853690A07E6DC426", // Shell - "CEA08895D2544B019B2E9C5009600DF4", // Sys - "0308FD86DE0A4DEE8D62B9B535370992", // URL - "565B73353DBF4806919830B9202EE3BF", // WebSearch - "5043CETYU6A748679OPA02D27D99677A" // WindowsSettings - }; + { + "0ECADE17459B49F587BF81DC3A125110", // BrowserBookmark + "CEA0FDFC6D3B4085823D60DC76F28855", // Calculator + "572be03c74c642baae319fc283e561a8", // Explorer + "6A122269676E40EB86EB543B945932B9", // PluginIndicator + "9f8f9b14-2518-4907-b211-35ab6290dee7", // PluginsManager + "b64d0a79-329a-48b0-b53f-d658318a1bf6", // ProcessKiller + "791FC278BA414111B8D1886DFE447410", // Program + "D409510CD0D2481F853690A07E6DC426", // Shell + "CEA08895D2544B019B2E9C5009600DF4", // Sys + "0308FD86DE0A4DEE8D62B9B535370992", // URL + "565B73353DBF4806919830B9202EE3BF", // WebSearch + "5043CETYU6A748679OPA02D27D99677A" // WindowsSettings + }; // Treat default plugin differently, it needs to be removable along with each flow release var installDirectory = !defaultPluginIDs.Any(x => x == plugin.ID) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index f178ebb90d4..eeb3f5de3ae 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -344,5 +344,62 @@ public interface IPublicAPI /// Stop the loading bar in main window /// public void StopLoadingBar(); + + /// + /// Update the plugin manifest + /// + /// + /// FL has multiple urls to download the plugin manifest. Set this to true to only use the primary url. + /// + /// + /// True if the manifest is updated successfully, false otherwise + public Task UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default); + + /// + /// Get the plugin manifest + /// + /// + public IReadOnlyList GetPluginManifest(); + + /// + /// Check if the plugin has been modified. + /// If this plugin is updated, installed or uninstalled and users do not restart the app, + /// it will be marked as modified + /// + /// Plugin id + /// + public bool PluginModified(string id); + + /// + /// Update a plugin to new version, from a zip file. By default will remove the zip file if update is via url, + /// unless it's a local path installation + /// + /// The metadata of the old plugin to update + /// The new plugin to update + /// + /// Path to the zip file containing the plugin. It will be unzipped to the temporary directory, removed and installed. + /// + /// + public Task UpdatePluginAsync(PluginMetadata pluginMetadata, UserPlugin plugin, string zipFilePath); + + /// + /// Install a plugin. By default will remove the zip file if installation is from url, + /// unless it's a local path installation + /// + /// The plugin to install + /// + /// Path to the zip file containing the plugin. It will be unzipped to the temporary directory, removed and installed. + /// + public void InstallPlugin(UserPlugin plugin, string zipFilePath); + + /// + /// Uninstall a plugin + /// + /// The metadata of the plugin to uninstall + /// + /// Plugin has their own settings. If this is set to true, the plugin settings will be removed. + /// + /// + public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false); } } diff --git a/Flow.Launcher.Plugin/UserPlugin.cs b/Flow.Launcher.Plugin/UserPlugin.cs new file mode 100644 index 00000000000..74a16b83d80 --- /dev/null +++ b/Flow.Launcher.Plugin/UserPlugin.cs @@ -0,0 +1,80 @@ +using System; + +namespace Flow.Launcher.Plugin +{ + /// + /// User Plugin Model for Flow Launcher + /// + public record UserPlugin + { + /// + /// Unique identifier of the plugin + /// + public string ID { get; set; } + + /// + /// Name of the plugin + /// + public string Name { get; set; } + + /// + /// Description of the plugin + /// + public string Description { get; set; } + + /// + /// Author of the plugin + /// + public string Author { get; set; } + + /// + /// Version of the plugin + /// + public string Version { get; set; } + + /// + /// Allow language of the plugin + /// + public string Language { get; set; } + + /// + /// Website of the plugin + /// + public string Website { get; set; } + + /// + /// URL to download the plugin + /// + public string UrlDownload { get; set; } + + /// + /// URL to the source code of the plugin + /// + public string UrlSourceCode { get; set; } + + /// + /// Local path where the plugin is installed + /// + public string LocalInstallPath { get; set; } + + /// + /// Icon path of the plugin + /// + public string IcoPath { get; set; } + + /// + /// The date when the plugin was last updated + /// + public DateTime? LatestReleaseDate { get; set; } + + /// + /// The date when the plugin was added to the local system + /// + public DateTime? DateAdded { get; set; } + + /// + /// Indicates whether the plugin is installed from a local path + /// + public bool IsFromLocalInstallPath => !string.IsNullOrEmpty(LocalInstallPath); + } +} diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index d88eeb7c9e3..c40e40ebbae 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -28,6 +28,7 @@ using Flow.Launcher.ViewModel; using JetBrains.Annotations; using Flow.Launcher.Core.Resource; +using Flow.Launcher.Core.ExternalPlugins; namespace Flow.Launcher { @@ -354,6 +355,22 @@ public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", M public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress); + public Task UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default) => + PluginsManifest.UpdateManifestAsync(usePrimaryUrlOnly, token); + + public IReadOnlyList GetPluginManifest() => PluginsManifest.UserPlugins; + + public bool PluginModified(string id) => PluginManager.PluginModified(id); + + public Task UpdatePluginAsync(PluginMetadata pluginMetadata, UserPlugin plugin, string zipFilePath) => + PluginManager.UpdatePluginAsync(pluginMetadata, plugin, zipFilePath); + + public void InstallPlugin(UserPlugin plugin, string zipFilePath) => + PluginManager.InstallPlugin(plugin, zipFilePath); + + public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false) => + PluginManager.UninstallPluginAsync(pluginMetadata, removePluginSettings); + #endregion #region Private Methods diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs index 15579a61da0..84d8a2ff926 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; using CommunityToolkit.Mvvm.Input; -using Flow.Launcher.Core.ExternalPlugins; using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; @@ -14,7 +13,7 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel public string FilterText { get; set; } = string.Empty; public IList ExternalPlugins => - PluginsManifest.UserPlugins?.Select(p => new PluginStoreItemViewModel(p)) + App.API.GetPluginManifest()?.Select(p => new PluginStoreItemViewModel(p)) .OrderByDescending(p => p.Category == PluginStoreItemViewModel.NewRelease) .ThenByDescending(p => p.Category == PluginStoreItemViewModel.RecentlyUpdated) .ThenByDescending(p => p.Category == PluginStoreItemViewModel.None) @@ -24,7 +23,7 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel [RelayCommand] private async Task RefreshExternalPluginsAsync() { - if (await PluginsManifest.UpdateManifestAsync()) + if (await App.API.UpdatePluginManifestAsync()) { OnPropertyChanged(nameof(ExternalPlugins)); } diff --git a/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs b/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs index 38b5bec6561..d1cf7450121 100644 --- a/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs @@ -1,10 +1,8 @@ using System; using System.Linq; using CommunityToolkit.Mvvm.Input; -using Flow.Launcher.Core.ExternalPlugins; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Plugin; -using SemanticVersioning; using Version = SemanticVersioning.Version; namespace Flow.Launcher.ViewModel diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs index 482e821dc4c..265657ef45d 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs @@ -1,5 +1,4 @@ -using Flow.Launcher.Core.ExternalPlugins; -using System.Collections.Generic; +using System.Collections.Generic; using System.Text.RegularExpressions; namespace Flow.Launcher.Plugin.PluginsManager diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj index c33c428890b..8ff41a7add9 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj @@ -18,8 +18,6 @@ - - @@ -37,4 +35,8 @@ PreserveNewest + + + + diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 156135f813d..742d85fc1d4 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -1,18 +1,16 @@ -using Flow.Launcher.Core.ExternalPlugins; -using Flow.Launcher.Plugin.PluginsManager.ViewModels; -using Flow.Launcher.Plugin.PluginsManager.Views; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Windows.Controls; -using Flow.Launcher.Infrastructure; using System.Threading.Tasks; using System.Threading; +using Flow.Launcher.Plugin.PluginsManager.ViewModels; +using Flow.Launcher.Plugin.PluginsManager.Views; namespace Flow.Launcher.Plugin.PluginsManager { public class Main : ISettingProvider, IAsyncPlugin, IContextMenu, IPluginI18n { - internal PluginInitContext Context { get; set; } + internal static PluginInitContext Context { get; set; } internal Settings Settings; @@ -35,7 +33,7 @@ public async Task InitAsync(PluginInitContext context) contextMenu = new ContextMenu(Context); pluginManager = new PluginsManager(Context, Settings); - await PluginsManifest.UpdateManifestAsync(); + await Context.API.UpdatePluginManifestAsync(); } public List LoadContextMenus(Result selectedResult) @@ -56,7 +54,7 @@ public async Task> QueryAsync(Query query, CancellationToken token) Settings.UpdateCommand => await pluginManager.RequestUpdateAsync(query.SecondToEndSearch, token, query.IsReQuery), _ => pluginManager.GetDefaultHotKeys().Where(hotkey => { - hotkey.Score = StringMatcher.FuzzySearch(query.Search, hotkey.Title).Score; + hotkey.Score = Context.API.FuzzySearch(query.Search, hotkey.Title).Score; return hotkey.Score > 0; }).ToList() }; diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 79d6aedd5a9..a16778ff461 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -1,10 +1,4 @@ -using Flow.Launcher.Core.ExternalPlugins; -using Flow.Launcher.Core.Plugin; -using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Http; -using Flow.Launcher.Infrastructure.Logger; -using Flow.Launcher.Plugin.SharedCommands; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -12,12 +6,15 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Plugin.PluginsManager { internal class PluginsManager { - private const string zip = "zip"; + private const string ZipSuffix = "zip"; + + private static readonly string ClassName = nameof(PluginsManager); private PluginInitContext Context { get; set; } @@ -51,7 +48,7 @@ internal List GetDefaultHotKeys() { return new List() { - new Result() + new() { Title = Settings.InstallCommand, IcoPath = icoPath, @@ -63,7 +60,7 @@ internal List GetDefaultHotKeys() return false; } }, - new Result() + new() { Title = Settings.UninstallCommand, IcoPath = icoPath, @@ -75,7 +72,7 @@ internal List GetDefaultHotKeys() return false; } }, - new Result() + new() { Title = Settings.UpdateCommand, IcoPath = icoPath, @@ -169,7 +166,7 @@ await DownloadFileAsync( Context.API.ShowMsgError( string.Format(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), plugin.Name), Context.API.GetTranslation("plugin_pluginsmanager_download_error")); - Log.Exception("PluginsManager", "An error occurred while downloading plugin", e); + Context.API.LogException(ClassName, "An error occurred while downloading plugin", e); return; } @@ -179,7 +176,7 @@ await DownloadFileAsync( Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), plugin.Name)); - Log.Exception("PluginsManager", "An error occurred while downloading plugin", e); + Context.API.LogException(ClassName, "An error occurred while downloading plugin", e); return; } @@ -237,7 +234,7 @@ await Context.API.ShowProgressBoxAsync(prgBoxTitle, internal async ValueTask> RequestUpdateAsync(string search, CancellationToken token, bool usePrimaryUrlOnly = false) { - await PluginsManifest.UpdateManifestAsync(token, usePrimaryUrlOnly); + await Context.API.UpdatePluginManifestAsync(usePrimaryUrlOnly, token); var pluginFromLocalPath = null as UserPlugin; var updateFromLocalPath = false; @@ -250,7 +247,7 @@ internal async ValueTask> RequestUpdateAsync(string search, Cancell } var updateSource = !updateFromLocalPath - ? PluginsManifest.UserPlugins + ? Context.API.GetPluginManifest() : new List { pluginFromLocalPath }; var resultsForUpdate = ( @@ -260,7 +257,7 @@ on existingPlugin.Metadata.ID equals pluginUpdateSource.ID where string.Compare(existingPlugin.Metadata.Version, pluginUpdateSource.Version, StringComparison.InvariantCulture) < 0 // if current version precedes version of the plugin from update source (e.g. PluginsManifest) - && !PluginManager.PluginModified(existingPlugin.Metadata.ID) + && !Context.API.PluginModified(existingPlugin.Metadata.ID) select new { @@ -276,7 +273,7 @@ where string.Compare(existingPlugin.Metadata.Version, pluginUpdateSource.Version if (!resultsForUpdate.Any()) return new List { - new Result + new() { Title = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_title"), SubTitle = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_subtitle"), @@ -341,7 +338,7 @@ await DownloadFileAsync( } else { - await PluginManager.UpdatePluginAsync(x.PluginExistingMetadata, x.PluginNewUserPlugin, + await Context.API.UpdatePluginAsync(x.PluginExistingMetadata, x.PluginNewUserPlugin, downloadToFilePath); if (Settings.AutoRestartAfterChanging) @@ -366,7 +363,7 @@ await PluginManager.UpdatePluginAsync(x.PluginExistingMetadata, x.PluginNewUserP } }).ContinueWith(t => { - Log.Exception("PluginsManager", $"Update failed for {x.Name}", + Context.API.LogException(ClassName, $"Update failed for {x.Name}", t.Exception.InnerException); Context.API.ShowMsg( Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), @@ -433,12 +430,12 @@ await DownloadFileAsync( if (cts.IsCancellationRequested) return; else - await PluginManager.UpdatePluginAsync(plugin.PluginExistingMetadata, plugin.PluginNewUserPlugin, + await Context.API.UpdatePluginAsync(plugin.PluginExistingMetadata, plugin.PluginNewUserPlugin, downloadToFilePath); } catch (Exception ex) { - Log.Exception("PluginsManager", $"Update failed for {plugin.Name}", ex.InnerException); + Context.API.LogException(ClassName, $"Update failed for {plugin.Name}", ex.InnerException); Context.API.ShowMsg( Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format( @@ -486,7 +483,7 @@ internal List Search(IEnumerable results, string searchName) return results .Where(x => { - var matchResult = StringMatcher.FuzzySearch(searchName, x.Title); + var matchResult = Context.API.FuzzySearch(searchName, x.Title); if (matchResult.IsSearchPrecisionScoreMet()) x.Score = matchResult.Score; @@ -498,7 +495,7 @@ internal List Search(IEnumerable results, string searchName) internal List InstallFromWeb(string url) { var filename = url.Split("/").Last(); - var name = filename.Split(string.Format(".{0}", zip)).First(); + var name = filename.Split(string.Format(".{0}", ZipSuffix)).First(); var plugin = new UserPlugin { @@ -552,7 +549,7 @@ internal List InstallFromLocalPath(string localPath) return new List { - new Result + new() { Title = $"{plugin.Name} by {plugin.Author}", SubTitle = plugin.Description, @@ -602,19 +599,18 @@ private bool InstallSourceKnown(string url) internal async ValueTask> RequestInstallOrUpdateAsync(string search, CancellationToken token, bool usePrimaryUrlOnly = false) { - await PluginsManifest.UpdateManifestAsync(token, usePrimaryUrlOnly); + await Context.API.UpdatePluginManifestAsync(usePrimaryUrlOnly, token); if (Uri.IsWellFormedUriString(search, UriKind.Absolute) - && search.Split('.').Last() == zip) + && search.Split('.').Last() == ZipSuffix) return InstallFromWeb(search); if (FilesFolders.IsZipFilePath(search, checkFileExists: true)) return InstallFromLocalPath(search); var results = - PluginsManifest - .UserPlugins - .Where(x => !PluginExists(x.ID) && !PluginManager.PluginModified(x.ID)) + Context.API.GetPluginManifest() + .Where(x => !PluginExists(x.ID) && !Context.API.PluginModified(x.ID)) .Select(x => new Result { @@ -647,7 +643,7 @@ private void Install(UserPlugin plugin, string downloadedFilePath) try { - PluginManager.InstallPlugin(plugin, downloadedFilePath); + Context.API.InstallPlugin(plugin, downloadedFilePath); if (!plugin.IsFromLocalInstallPath) File.Delete(downloadedFilePath); @@ -656,21 +652,21 @@ private void Install(UserPlugin plugin, string downloadedFilePath) { Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile")); - Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); + Context.API.LogException(ClassName, e.Message, e); } catch (InvalidOperationException e) { Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_duplicate"), plugin.Name)); - Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); + Context.API.LogException(ClassName, e.Message, e); } catch (ArgumentException e) { Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_plugin_modified_error"), plugin.Name)); - Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); + Context.API.LogException(ClassName, e.Message, e); } } @@ -740,11 +736,11 @@ private async Task UninstallAsync(PluginMetadata plugin) Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_subtitle"), Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_title"), button: MessageBoxButton.YesNo) == MessageBoxResult.No; - await PluginManager.UninstallPluginAsync(plugin, removePluginFromSettings: true, removePluginSettings: removePluginSettings); + await Context.API.UninstallPluginAsync(plugin, removePluginSettings); } catch (ArgumentException e) { - Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); + Context.API.LogException(ClassName, e.Message, e); Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_error_title"), Context.API.GetTranslation("plugin_pluginsmanager_plugin_modified_error")); } diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Utilities.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Utilities.cs index 743f5b25bff..4bb78f6ff8d 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Utilities.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Utilities.cs @@ -1,5 +1,4 @@ -using Flow.Launcher.Core.ExternalPlugins; -using ICSharpCode.SharpZipLib.Zip; +using ICSharpCode.SharpZipLib.Zip; using System.IO; using System.IO.Compression; using System.Linq;