Move PluginManager public function to api

This commit is contained in:
Jack251970 2025-04-04 16:33:03 +08:00
parent 55d1754ed6
commit 4744ff780e
5 changed files with 87 additions and 49 deletions

View file

@ -454,16 +454,11 @@ namespace Flow.Launcher.Core.Plugin
#region Public functions #region Public functions
public static bool PluginModified(string uuid) public static bool PluginModified(string id)
{ {
return _modifiedPlugins.Contains(uuid); return _modifiedPlugins.Contains(id);
} }
/// <summary>
/// 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
/// </summary>
public static async Task UpdatePluginAsync(PluginMetadata existingVersion, UserPlugin newVersion, string zipFilePath) public static async Task UpdatePluginAsync(PluginMetadata existingVersion, UserPlugin newVersion, string zipFilePath)
{ {
InstallPlugin(newVersion, zipFilePath, checkModified:false); InstallPlugin(newVersion, zipFilePath, checkModified:false);
@ -471,17 +466,11 @@ namespace Flow.Launcher.Core.Plugin
_modifiedPlugins.Add(existingVersion.ID); _modifiedPlugins.Add(existingVersion.ID);
} }
/// <summary>
/// Install a plugin. By default will remove the zip file if installation is from url, unless it's a local path installation
/// </summary>
public static void InstallPlugin(UserPlugin plugin, string zipFilePath) public static void InstallPlugin(UserPlugin plugin, string zipFilePath)
{ {
InstallPlugin(plugin, zipFilePath, checkModified: true); InstallPlugin(plugin, zipFilePath, checkModified: true);
} }
/// <summary>
/// Uninstall a plugin.
/// </summary>
public static async Task UninstallPluginAsync(PluginMetadata plugin, bool removePluginFromSettings = true, bool removePluginSettings = false) public static async Task UninstallPluginAsync(PluginMetadata plugin, bool removePluginFromSettings = true, bool removePluginSettings = false)
{ {
await UninstallPluginAsync(plugin, removePluginFromSettings, removePluginSettings, true); await UninstallPluginAsync(plugin, removePluginFromSettings, removePluginSettings, true);
@ -525,20 +514,20 @@ namespace Flow.Launcher.Core.Plugin
var folderName = string.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}-{Guid.NewGuid()}" : $"{plugin.Name}-{plugin.Version}"; var folderName = string.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}-{Guid.NewGuid()}" : $"{plugin.Name}-{plugin.Version}";
var defaultPluginIDs = new List<string> var defaultPluginIDs = new List<string>
{ {
"0ECADE17459B49F587BF81DC3A125110", // BrowserBookmark "0ECADE17459B49F587BF81DC3A125110", // BrowserBookmark
"CEA0FDFC6D3B4085823D60DC76F28855", // Calculator "CEA0FDFC6D3B4085823D60DC76F28855", // Calculator
"572be03c74c642baae319fc283e561a8", // Explorer "572be03c74c642baae319fc283e561a8", // Explorer
"6A122269676E40EB86EB543B945932B9", // PluginIndicator "6A122269676E40EB86EB543B945932B9", // PluginIndicator
"9f8f9b14-2518-4907-b211-35ab6290dee7", // PluginsManager "9f8f9b14-2518-4907-b211-35ab6290dee7", // PluginsManager
"b64d0a79-329a-48b0-b53f-d658318a1bf6", // ProcessKiller "b64d0a79-329a-48b0-b53f-d658318a1bf6", // ProcessKiller
"791FC278BA414111B8D1886DFE447410", // Program "791FC278BA414111B8D1886DFE447410", // Program
"D409510CD0D2481F853690A07E6DC426", // Shell "D409510CD0D2481F853690A07E6DC426", // Shell
"CEA08895D2544B019B2E9C5009600DF4", // Sys "CEA08895D2544B019B2E9C5009600DF4", // Sys
"0308FD86DE0A4DEE8D62B9B535370992", // URL "0308FD86DE0A4DEE8D62B9B535370992", // URL
"565B73353DBF4806919830B9202EE3BF", // WebSearch "565B73353DBF4806919830B9202EE3BF", // WebSearch
"5043CETYU6A748679OPA02D27D99677A" // WindowsSettings "5043CETYU6A748679OPA02D27D99677A" // WindowsSettings
}; };
// Treat default plugin differently, it needs to be removable along with each flow release // Treat default plugin differently, it needs to be removable along with each flow release
var installDirectory = !defaultPluginIDs.Any(x => x == plugin.ID) var installDirectory = !defaultPluginIDs.Any(x => x == plugin.ID)

View file

@ -352,15 +352,54 @@ namespace Flow.Launcher.Plugin
/// FL has multiple urls to download the plugin manifest. Set this to true to only use the primary url. /// FL has multiple urls to download the plugin manifest. Set this to true to only use the primary url.
/// </param> /// </param>
/// <param name="token"></param> /// <param name="token"></param>
/// <returns> /// <returns>True if the manifest is updated successfully, false otherwise</returns>
/// True if the manifest is updated successfully, false otherwise.
/// </returns>
public Task<bool> UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default); public Task<bool> UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default);
/// <summary> /// <summary>
/// Get the plugin manifest /// Get the plugin manifest
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public IReadOnlyList<UserPlugin> GetUserPlugins(); public IReadOnlyList<UserPlugin> GetPluginManifest();
/// <summary>
/// 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
/// </summary>
/// <param name="id">Plugin id</param>
/// <returns></returns>
public bool PluginModified(string id);
/// <summary>
/// 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
/// </summary>
/// <param name="pluginMetadata">The metadata of the old plugin to update</param>
/// <param name="plugin">The new plugin to update</param>
/// <param name="zipFilePath">
/// Path to the zip file containing the plugin. It will be unzipped to the temporary directory, removed and installed.
/// </param>
/// <returns></returns>
public Task UpdatePluginAsync(PluginMetadata pluginMetadata, UserPlugin plugin, string zipFilePath);
/// <summary>
/// Install a plugin. By default will remove the zip file if installation is from url,
/// unless it's a local path installation
/// </summary>
/// <param name="plugin">The plugin to install</param>
/// <param name="zipFilePath">
/// Path to the zip file containing the plugin. It will be unzipped to the temporary directory, removed and installed.
/// </param>
public void InstallPlugin(UserPlugin plugin, string zipFilePath);
/// <summary>
/// Uninstall a plugin
/// </summary>
/// <param name="pluginMetadata">The metadata of the plugin to uninstall</param>
/// <param name="removePluginSettings">
/// Plugin has their own settings. If this is set to true, the plugin settings will be removed.
/// </param>
/// <returns></returns>
public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false);
} }
} }

View file

@ -358,7 +358,18 @@ namespace Flow.Launcher
public Task<bool> UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default) => public Task<bool> UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default) =>
PluginsManifest.UpdateManifestAsync(usePrimaryUrlOnly, token); PluginsManifest.UpdateManifestAsync(usePrimaryUrlOnly, token);
public IReadOnlyList<UserPlugin> GetUserPlugins() => PluginsManifest.UserPlugins; public IReadOnlyList<UserPlugin> 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 #endregion

View file

@ -13,7 +13,7 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel
public string FilterText { get; set; } = string.Empty; public string FilterText { get; set; } = string.Empty;
public IList<PluginStoreItemViewModel> ExternalPlugins => public IList<PluginStoreItemViewModel> ExternalPlugins =>
App.API.GetUserPlugins()?.Select(p => new PluginStoreItemViewModel(p)) App.API.GetPluginManifest()?.Select(p => new PluginStoreItemViewModel(p))
.OrderByDescending(p => p.Category == PluginStoreItemViewModel.NewRelease) .OrderByDescending(p => p.Category == PluginStoreItemViewModel.NewRelease)
.ThenByDescending(p => p.Category == PluginStoreItemViewModel.RecentlyUpdated) .ThenByDescending(p => p.Category == PluginStoreItemViewModel.RecentlyUpdated)
.ThenByDescending(p => p.Category == PluginStoreItemViewModel.None) .ThenByDescending(p => p.Category == PluginStoreItemViewModel.None)

View file

@ -1,6 +1,4 @@
using Flow.Launcher.Core.Plugin; using System;
using Flow.Launcher.Plugin.SharedCommands;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -8,6 +6,7 @@ using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using Flow.Launcher.Plugin.SharedCommands;
namespace Flow.Launcher.Plugin.PluginsManager namespace Flow.Launcher.Plugin.PluginsManager
{ {
@ -49,7 +48,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
{ {
return new List<Result>() return new List<Result>()
{ {
new Result() new()
{ {
Title = Settings.InstallCommand, Title = Settings.InstallCommand,
IcoPath = icoPath, IcoPath = icoPath,
@ -61,7 +60,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
return false; return false;
} }
}, },
new Result() new()
{ {
Title = Settings.UninstallCommand, Title = Settings.UninstallCommand,
IcoPath = icoPath, IcoPath = icoPath,
@ -73,7 +72,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
return false; return false;
} }
}, },
new Result() new()
{ {
Title = Settings.UpdateCommand, Title = Settings.UpdateCommand,
IcoPath = icoPath, IcoPath = icoPath,
@ -248,7 +247,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
} }
var updateSource = !updateFromLocalPath var updateSource = !updateFromLocalPath
? Context.API.GetUserPlugins() ? Context.API.GetPluginManifest()
: new List<UserPlugin> { pluginFromLocalPath }; : new List<UserPlugin> { pluginFromLocalPath };
var resultsForUpdate = ( var resultsForUpdate = (
@ -258,7 +257,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
where string.Compare(existingPlugin.Metadata.Version, pluginUpdateSource.Version, where string.Compare(existingPlugin.Metadata.Version, pluginUpdateSource.Version,
StringComparison.InvariantCulture) < StringComparison.InvariantCulture) <
0 // if current version precedes version of the plugin from update source (e.g. PluginsManifest) 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 select
new new
{ {
@ -274,7 +273,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (!resultsForUpdate.Any()) if (!resultsForUpdate.Any())
return new List<Result> return new List<Result>
{ {
new Result new()
{ {
Title = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_title"), Title = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_title"),
SubTitle = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_subtitle"), SubTitle = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_subtitle"),
@ -339,7 +338,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
} }
else else
{ {
await PluginManager.UpdatePluginAsync(x.PluginExistingMetadata, x.PluginNewUserPlugin, await Context.API.UpdatePluginAsync(x.PluginExistingMetadata, x.PluginNewUserPlugin,
downloadToFilePath); downloadToFilePath);
if (Settings.AutoRestartAfterChanging) if (Settings.AutoRestartAfterChanging)
@ -431,7 +430,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
if (cts.IsCancellationRequested) if (cts.IsCancellationRequested)
return; return;
else else
await PluginManager.UpdatePluginAsync(plugin.PluginExistingMetadata, plugin.PluginNewUserPlugin, await Context.API.UpdatePluginAsync(plugin.PluginExistingMetadata, plugin.PluginNewUserPlugin,
downloadToFilePath); downloadToFilePath);
} }
catch (Exception ex) catch (Exception ex)
@ -550,7 +549,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
return new List<Result> return new List<Result>
{ {
new Result new()
{ {
Title = $"{plugin.Name} by {plugin.Author}", Title = $"{plugin.Name} by {plugin.Author}",
SubTitle = plugin.Description, SubTitle = plugin.Description,
@ -610,8 +609,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
return InstallFromLocalPath(search); return InstallFromLocalPath(search);
var results = var results =
Context.API.GetUserPlugins() Context.API.GetPluginManifest()
.Where(x => !PluginExists(x.ID) && !PluginManager.PluginModified(x.ID)) .Where(x => !PluginExists(x.ID) && !Context.API.PluginModified(x.ID))
.Select(x => .Select(x =>
new Result new Result
{ {
@ -644,7 +643,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
try try
{ {
PluginManager.InstallPlugin(plugin, downloadedFilePath); Context.API.InstallPlugin(plugin, downloadedFilePath);
if (!plugin.IsFromLocalInstallPath) if (!plugin.IsFromLocalInstallPath)
File.Delete(downloadedFilePath); File.Delete(downloadedFilePath);
@ -737,7 +736,7 @@ namespace Flow.Launcher.Plugin.PluginsManager
Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_subtitle"), Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_subtitle"),
Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_title"), Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_title"),
button: MessageBoxButton.YesNo) == MessageBoxResult.No; button: MessageBoxButton.YesNo) == MessageBoxResult.No;
await PluginManager.UninstallPluginAsync(plugin, removePluginFromSettings: true, removePluginSettings: removePluginSettings); await Context.API.UninstallPluginAsync(plugin, removePluginSettings);
} }
catch (ArgumentException e) catch (ArgumentException e)
{ {