mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge pull request #3219 from Jack251970/delete_plugin_settings
Support deleting plugin settings when uninstalling plugins
This commit is contained in:
commit
2bc9203be6
7 changed files with 118 additions and 21 deletions
|
|
@ -44,8 +44,10 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
private string SettingConfigurationPath =>
|
private string SettingConfigurationPath =>
|
||||||
Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "SettingsTemplate.yaml");
|
Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "SettingsTemplate.yaml");
|
||||||
|
|
||||||
private string SettingPath => Path.Combine(DataLocation.PluginSettingsDirectory,
|
private string SettingDirectory => Path.Combine(DataLocation.PluginSettingsDirectory,
|
||||||
Context.CurrentPluginMetadata.Name, "Settings.json");
|
Context.CurrentPluginMetadata.Name);
|
||||||
|
|
||||||
|
private string SettingPath => Path.Combine(SettingDirectory, "Settings.json");
|
||||||
|
|
||||||
public abstract List<Result> LoadContextMenus(Result selectedResult);
|
public abstract List<Result> LoadContextMenus(Result selectedResult);
|
||||||
|
|
||||||
|
|
@ -159,5 +161,13 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
{
|
{
|
||||||
return Settings.CreateSettingPanel();
|
return Settings.CreateSettingPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DeletePluginSettingsDirectory()
|
||||||
|
{
|
||||||
|
if (Directory.Exists(SettingDirectory))
|
||||||
|
{
|
||||||
|
Directory.Delete(SettingDirectory, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,9 +210,9 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
{
|
{
|
||||||
var failed = string.Join(",", failedPlugins.Select(x => x.Metadata.Name));
|
var failed = string.Join(",", failedPlugins.Select(x => x.Metadata.Name));
|
||||||
API.ShowMsg(
|
API.ShowMsg(
|
||||||
InternationalizationManager.Instance.GetTranslation("failedToInitializePluginsTitle"),
|
API.GetTranslation("failedToInitializePluginsTitle"),
|
||||||
string.Format(
|
string.Format(
|
||||||
InternationalizationManager.Instance.GetTranslation("failedToInitializePluginsMessage"),
|
API.GetTranslation("failedToInitializePluginsMessage"),
|
||||||
failed
|
failed
|
||||||
),
|
),
|
||||||
"",
|
"",
|
||||||
|
|
@ -439,7 +439,7 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
public static void UpdatePlugin(PluginMetadata existingVersion, UserPlugin newVersion, string zipFilePath)
|
public static void UpdatePlugin(PluginMetadata existingVersion, UserPlugin newVersion, string zipFilePath)
|
||||||
{
|
{
|
||||||
InstallPlugin(newVersion, zipFilePath, checkModified:false);
|
InstallPlugin(newVersion, zipFilePath, checkModified:false);
|
||||||
UninstallPlugin(existingVersion, removeSettings:false, checkModified:false);
|
UninstallPlugin(existingVersion, removePluginFromSettings:false, removePluginSettings:false, checkModified: false);
|
||||||
_modifiedPlugins.Add(existingVersion.ID);
|
_modifiedPlugins.Add(existingVersion.ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -454,9 +454,9 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Uninstall a plugin.
|
/// Uninstall a plugin.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void UninstallPlugin(PluginMetadata plugin, bool removeSettings = true)
|
public static void UninstallPlugin(PluginMetadata plugin, bool removePluginFromSettings = true, bool removePluginSettings = false)
|
||||||
{
|
{
|
||||||
UninstallPlugin(plugin, removeSettings, true);
|
UninstallPlugin(plugin, removePluginFromSettings, removePluginSettings, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
@ -521,7 +521,15 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
|
|
||||||
FilesFolders.CopyAll(pluginFolderPath, newPluginPath, MessageBoxEx.Show);
|
FilesFolders.CopyAll(pluginFolderPath, newPluginPath, MessageBoxEx.Show);
|
||||||
|
|
||||||
Directory.Delete(tempFolderPluginPath, true);
|
try
|
||||||
|
{
|
||||||
|
if (Directory.Exists(tempFolderPluginPath))
|
||||||
|
Directory.Delete(tempFolderPluginPath, true);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception($"|PluginManager.InstallPlugin|Failed to delete temp folder {tempFolderPluginPath}", e);
|
||||||
|
}
|
||||||
|
|
||||||
if (checkModified)
|
if (checkModified)
|
||||||
{
|
{
|
||||||
|
|
@ -529,14 +537,62 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void UninstallPlugin(PluginMetadata plugin, bool removeSettings, bool checkModified)
|
internal static void UninstallPlugin(PluginMetadata plugin, bool removePluginFromSettings, bool removePluginSettings, bool checkModified)
|
||||||
{
|
{
|
||||||
if (checkModified && PluginModified(plugin.ID))
|
if (checkModified && PluginModified(plugin.ID))
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Plugin {plugin.Name} has been modified");
|
throw new ArgumentException($"Plugin {plugin.Name} has been modified");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removeSettings)
|
if (removePluginSettings)
|
||||||
|
{
|
||||||
|
if (AllowedLanguage.IsDotNet(plugin.Language)) // for the plugin in .NET, we can use assembly loader
|
||||||
|
{
|
||||||
|
var assemblyLoader = new PluginAssemblyLoader(plugin.ExecuteFilePath);
|
||||||
|
var assembly = assemblyLoader.LoadAssemblyAndDependencies();
|
||||||
|
var assemblyName = assembly.GetName().Name;
|
||||||
|
|
||||||
|
// if user want to remove the plugin settings, we cannot call save method for the plugin json storage instance of this plugin
|
||||||
|
// so we need to remove it from the api instance
|
||||||
|
var method = API.GetType().GetMethod("RemovePluginSettings");
|
||||||
|
var pluginJsonStorage = method?.Invoke(API, new object[] { assemblyName });
|
||||||
|
|
||||||
|
// if there exists a json storage for current plugin, we need to delete the directory path
|
||||||
|
if (pluginJsonStorage != null)
|
||||||
|
{
|
||||||
|
var deleteMethod = pluginJsonStorage.GetType().GetMethod("DeleteDirectory");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
deleteMethod?.Invoke(pluginJsonStorage, null);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin json folder for {plugin.Name}", e);
|
||||||
|
API.ShowMsg(API.GetTranslation("failedToRemovePluginSettingsTitle"),
|
||||||
|
string.Format(API.GetTranslation("failedToRemovePluginSettingsMessage"), plugin.Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // the plugin with json prc interface
|
||||||
|
{
|
||||||
|
var pluginPair = AllPlugins.FirstOrDefault(p => p.Metadata.ID == plugin.ID);
|
||||||
|
if (pluginPair != null && pluginPair.Plugin is JsonRPCPlugin jsonRpcPlugin)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
jsonRpcPlugin.DeletePluginSettingsDirectory();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin json folder for {plugin.Name}", e);
|
||||||
|
API.ShowMsg(API.GetTranslation("failedToRemovePluginSettingsTitle"),
|
||||||
|
string.Format(API.GetTranslation("failedToRemovePluginSettingsMessage"), plugin.Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removePluginFromSettings)
|
||||||
{
|
{
|
||||||
Settings.Plugins.Remove(plugin.ID);
|
Settings.Plugins.Remove(plugin.ID);
|
||||||
AllPlugins.RemoveAll(p => p.Metadata.ID == plugin.ID);
|
AllPlugins.RemoveAll(p => p.Metadata.ID == plugin.ID);
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,17 @@ using Flow.Launcher.Infrastructure.UserSettings;
|
||||||
|
|
||||||
namespace Flow.Launcher.Infrastructure.Storage
|
namespace Flow.Launcher.Infrastructure.Storage
|
||||||
{
|
{
|
||||||
public class PluginJsonStorage<T> :JsonStorage<T> where T : new()
|
public class PluginJsonStorage<T> : JsonStorage<T> where T : new()
|
||||||
{
|
{
|
||||||
|
// Use assembly name to check which plugin is using this storage
|
||||||
|
public readonly string AssemblyName;
|
||||||
|
|
||||||
public PluginJsonStorage()
|
public PluginJsonStorage()
|
||||||
{
|
{
|
||||||
// C# related, add python related below
|
// C# related, add python related below
|
||||||
var dataType = typeof(T);
|
var dataType = typeof(T);
|
||||||
var assemblyName = dataType.Assembly.GetName().Name;
|
AssemblyName = dataType.Assembly.GetName().Name;
|
||||||
DirectoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName, Constant.Plugins, assemblyName);
|
DirectoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName, Constant.Plugins, AssemblyName);
|
||||||
Helper.ValidateDirectory(DirectoryPath);
|
Helper.ValidateDirectory(DirectoryPath);
|
||||||
|
|
||||||
FilePath = Path.Combine(DirectoryPath, $"{dataType.Name}{FileSuffix}");
|
FilePath = Path.Combine(DirectoryPath, $"{dataType.Name}{FileSuffix}");
|
||||||
|
|
@ -20,6 +23,13 @@ namespace Flow.Launcher.Infrastructure.Storage
|
||||||
{
|
{
|
||||||
Data = data;
|
Data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DeleteDirectory()
|
||||||
|
{
|
||||||
|
if (Directory.Exists(DirectoryPath))
|
||||||
|
{
|
||||||
|
Directory.Delete(DirectoryPath, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,8 @@
|
||||||
<system:String x:Key="plugin_query_version">Version</system:String>
|
<system:String x:Key="plugin_query_version">Version</system:String>
|
||||||
<system:String x:Key="plugin_query_web">Website</system:String>
|
<system:String x:Key="plugin_query_web">Website</system:String>
|
||||||
<system:String x:Key="plugin_uninstall">Uninstall</system:String>
|
<system:String x:Key="plugin_uninstall">Uninstall</system:String>
|
||||||
|
<system:String x:Key="failedToRemovePluginSettingsTitle">Fail to remove plugin settings</system:String>
|
||||||
|
<system:String x:Key="failedToRemovePluginSettingsMessage">Plugins: {0} - Fail to remove plugin settings files, please remove them manually</system:String>
|
||||||
|
|
||||||
<!-- Setting Plugin Store -->
|
<!-- Setting Plugin Store -->
|
||||||
<system:String x:Key="pluginStore">Plugin Store</system:String>
|
<system:String x:Key="pluginStore">Plugin Store</system:String>
|
||||||
|
|
@ -146,8 +147,6 @@
|
||||||
<system:String x:Key="LabelNewToolTip">This plugin has been updated within the last 7 days</system:String>
|
<system:String x:Key="LabelNewToolTip">This plugin has been updated within the last 7 days</system:String>
|
||||||
<system:String x:Key="LabelUpdateToolTip">New Update is Available</system:String>
|
<system:String x:Key="LabelUpdateToolTip">New Update is Available</system:String>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Setting Theme -->
|
<!-- Setting Theme -->
|
||||||
<system:String x:Key="theme">Theme</system:String>
|
<system:String x:Key="theme">Theme</system:String>
|
||||||
<system:String x:Key="appearance">Appearance</system:String>
|
<system:String x:Key="appearance">Appearance</system:String>
|
||||||
|
|
@ -197,7 +196,6 @@
|
||||||
<system:String x:Key="TypeIsDarkToolTip">This theme supports two(light/dark) modes.</system:String>
|
<system:String x:Key="TypeIsDarkToolTip">This theme supports two(light/dark) modes.</system:String>
|
||||||
<system:String x:Key="TypeHasBlurToolTip">This theme supports Blur Transparent Background.</system:String>
|
<system:String x:Key="TypeHasBlurToolTip">This theme supports Blur Transparent Background.</system:String>
|
||||||
|
|
||||||
|
|
||||||
<!-- Setting Hotkey -->
|
<!-- Setting Hotkey -->
|
||||||
<system:String x:Key="hotkey">Hotkey</system:String>
|
<system:String x:Key="hotkey">Hotkey</system:String>
|
||||||
<system:String x:Key="hotkeys">Hotkeys</system:String>
|
<system:String x:Key="hotkeys">Hotkeys</system:String>
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,23 @@ namespace Flow.Launcher
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<Type, object> _pluginJsonStorages = new();
|
private readonly ConcurrentDictionary<Type, object> _pluginJsonStorages = new();
|
||||||
|
|
||||||
|
public object RemovePluginSettings(string assemblyName)
|
||||||
|
{
|
||||||
|
foreach (var keyValuePair in _pluginJsonStorages)
|
||||||
|
{
|
||||||
|
var key = keyValuePair.Key;
|
||||||
|
var value = keyValuePair.Value;
|
||||||
|
var name = value.GetType().GetField("AssemblyName")?.GetValue(value)?.ToString();
|
||||||
|
if (name == assemblyName)
|
||||||
|
{
|
||||||
|
_pluginJsonStorages.Remove(key, out var pluginJsonStorage);
|
||||||
|
return pluginJsonStorage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Save plugin settings.
|
/// Save plugin settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
<system:String x:Key="plugin_pluginsmanager_installing_plugin">Installing Plugin</system:String>
|
<system:String x:Key="plugin_pluginsmanager_installing_plugin">Installing Plugin</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_install_from_web">Download and install {0}</system:String>
|
<system:String x:Key="plugin_pluginsmanager_install_from_web">Download and install {0}</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_uninstall_title">Plugin Uninstall</system:String>
|
<system:String x:Key="plugin_pluginsmanager_uninstall_title">Plugin Uninstall</system:String>
|
||||||
|
<system:String x:Key="plugin_pluginsmanager_keep_plugin_settings_title">Keep plugin settings</system:String>
|
||||||
|
<system:String x:Key="plugin_pluginsmanager_keep_plugin_settings_subtitle">Do you want to keep the settings of the plugin for the next usage?</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_install_success_restart">Plugin {0} successfully installed. Restarting Flow, please wait...</system:String>
|
<system:String x:Key="plugin_pluginsmanager_install_success_restart">Plugin {0} successfully installed. Restarting Flow, please wait...</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_install_errormetadatafile">Unable to find the plugin.json metadata file from the extracted zip file.</system:String>
|
<system:String x:Key="plugin_pluginsmanager_install_errormetadatafile">Unable to find the plugin.json metadata file from the extracted zip file.</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_install_error_duplicate">Error: A plugin which has the same or greater version with {0} already exists.</system:String>
|
<system:String x:Key="plugin_pluginsmanager_install_error_duplicate">Error: A plugin which has the same or greater version with {0} already exists.</system:String>
|
||||||
|
|
@ -37,13 +39,13 @@
|
||||||
<system:String x:Key="plugin_pluginsmanager_update_success_restart">Plugin {0} successfully updated. Restarting Flow, please wait...</system:String>
|
<system:String x:Key="plugin_pluginsmanager_update_success_restart">Plugin {0} successfully updated. Restarting Flow, please wait...</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_install_unknown_source_warning_title">Installing from an unknown source</system:String>
|
<system:String x:Key="plugin_pluginsmanager_install_unknown_source_warning_title">Installing from an unknown source</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_install_unknown_source_warning">You are installing this plugin from an unknown source and it may contain potential risks!{0}{0}Please ensure you understand where this plugin is from and that it is safe.{0}{0}Would you like to continue still?{0}{0}(You can switch off this warning via settings)</system:String>
|
<system:String x:Key="plugin_pluginsmanager_install_unknown_source_warning">You are installing this plugin from an unknown source and it may contain potential risks!{0}{0}Please ensure you understand where this plugin is from and that it is safe.{0}{0}Would you like to continue still?{0}{0}(You can switch off this warning via settings)</system:String>
|
||||||
|
|
||||||
<system:String x:Key="plugin_pluginsmanager_install_success_no_restart">Plugin {0} successfully installed. Please restart Flow.</system:String>
|
<system:String x:Key="plugin_pluginsmanager_install_success_no_restart">Plugin {0} successfully installed. Please restart Flow.</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_uninstall_success_no_restart">Plugin {0} successfully uninstalled. Please restart Flow.</system:String>
|
<system:String x:Key="plugin_pluginsmanager_uninstall_success_no_restart">Plugin {0} successfully uninstalled. Please restart Flow.</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_update_success_no_restart">Plugin {0} successfully updated. Please restart Flow.</system:String>
|
<system:String x:Key="plugin_pluginsmanager_update_success_no_restart">Plugin {0} successfully updated. Please restart Flow.</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_update_all_success_no_restart">{0} plugins successfully updated. Please restart Flow.</system:String>
|
<system:String x:Key="plugin_pluginsmanager_update_all_success_no_restart">{0} plugins successfully updated. Please restart Flow.</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_plugin_modified_error">Plugin {0} has already been modified. Please restart Flow before making any further changes.</system:String>
|
<system:String x:Key="plugin_pluginsmanager_plugin_modified_error">Plugin {0} has already been modified. Please restart Flow before making any further changes.</system:String>
|
||||||
|
|
||||||
<!-- Plugin Infos -->
|
<!-- Plugin Infos -->
|
||||||
<system:String x:Key="plugin_pluginsmanager_plugin_name">Plugins Manager</system:String>
|
<system:String x:Key="plugin_pluginsmanager_plugin_name">Plugins Manager</system:String>
|
||||||
<system:String x:Key="plugin_pluginsmanager_plugin_description">Management of installing, uninstalling or updating Flow Launcher plugins</system:String>
|
<system:String x:Key="plugin_pluginsmanager_plugin_description">Management of installing, uninstalling or updating Flow Launcher plugins</system:String>
|
||||||
|
|
|
||||||
|
|
@ -733,7 +733,11 @@ namespace Flow.Launcher.Plugin.PluginsManager
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PluginManager.UninstallPlugin(plugin, removeSettings: true);
|
var removePluginSettings = Context.API.ShowMsgBox(
|
||||||
|
Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_subtitle"),
|
||||||
|
Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_title"),
|
||||||
|
button: MessageBoxButton.YesNo) == MessageBoxResult.No;
|
||||||
|
PluginManager.UninstallPlugin(plugin, removePluginFromSettings: true, removePluginSettings: removePluginSettings);
|
||||||
}
|
}
|
||||||
catch (ArgumentException e)
|
catch (ArgumentException e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue