Skip to content

Commit 2bc9203

Browse files
authored
Merge pull request #3219 from Jack251970/delete_plugin_settings
Support deleting plugin settings when uninstalling plugins
2 parents cc463c8 + 58f8aaa commit 2bc9203

File tree

7 files changed

+118
-21
lines changed

7 files changed

+118
-21
lines changed

Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ internal abstract class JsonRPCPluginBase : IAsyncPlugin, IContextMenu, ISetting
4444
private string SettingConfigurationPath =>
4545
Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "SettingsTemplate.yaml");
4646

47-
private string SettingPath => Path.Combine(DataLocation.PluginSettingsDirectory,
48-
Context.CurrentPluginMetadata.Name, "Settings.json");
47+
private string SettingDirectory => Path.Combine(DataLocation.PluginSettingsDirectory,
48+
Context.CurrentPluginMetadata.Name);
49+
50+
private string SettingPath => Path.Combine(SettingDirectory, "Settings.json");
4951

5052
public abstract List<Result> LoadContextMenus(Result selectedResult);
5153

@@ -159,5 +161,13 @@ public Control CreateSettingPanel()
159161
{
160162
return Settings.CreateSettingPanel();
161163
}
164+
165+
public void DeletePluginSettingsDirectory()
166+
{
167+
if (Directory.Exists(SettingDirectory))
168+
{
169+
Directory.Delete(SettingDirectory, true);
170+
}
171+
}
162172
}
163173
}

Flow.Launcher.Core/Plugin/PluginManager.cs

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,9 @@ public static async Task InitializePluginsAsync(IPublicAPI api)
210210
{
211211
var failed = string.Join(",", failedPlugins.Select(x => x.Metadata.Name));
212212
API.ShowMsg(
213-
InternationalizationManager.Instance.GetTranslation("failedToInitializePluginsTitle"),
213+
API.GetTranslation("failedToInitializePluginsTitle"),
214214
string.Format(
215-
InternationalizationManager.Instance.GetTranslation("failedToInitializePluginsMessage"),
215+
API.GetTranslation("failedToInitializePluginsMessage"),
216216
failed
217217
),
218218
"",
@@ -439,7 +439,7 @@ public static bool PluginModified(string uuid)
439439
public static void UpdatePlugin(PluginMetadata existingVersion, UserPlugin newVersion, string zipFilePath)
440440
{
441441
InstallPlugin(newVersion, zipFilePath, checkModified:false);
442-
UninstallPlugin(existingVersion, removeSettings:false, checkModified:false);
442+
UninstallPlugin(existingVersion, removePluginFromSettings:false, removePluginSettings:false, checkModified: false);
443443
_modifiedPlugins.Add(existingVersion.ID);
444444
}
445445

@@ -454,9 +454,9 @@ public static void InstallPlugin(UserPlugin plugin, string zipFilePath)
454454
/// <summary>
455455
/// Uninstall a plugin.
456456
/// </summary>
457-
public static void UninstallPlugin(PluginMetadata plugin, bool removeSettings = true)
457+
public static void UninstallPlugin(PluginMetadata plugin, bool removePluginFromSettings = true, bool removePluginSettings = false)
458458
{
459-
UninstallPlugin(plugin, removeSettings, true);
459+
UninstallPlugin(plugin, removePluginFromSettings, removePluginSettings, true);
460460
}
461461

462462
#endregion
@@ -521,22 +521,78 @@ internal static void InstallPlugin(UserPlugin plugin, string zipFilePath, bool c
521521

522522
FilesFolders.CopyAll(pluginFolderPath, newPluginPath, MessageBoxEx.Show);
523523

524-
Directory.Delete(tempFolderPluginPath, true);
524+
try
525+
{
526+
if (Directory.Exists(tempFolderPluginPath))
527+
Directory.Delete(tempFolderPluginPath, true);
528+
}
529+
catch (Exception e)
530+
{
531+
Log.Exception($"|PluginManager.InstallPlugin|Failed to delete temp folder {tempFolderPluginPath}", e);
532+
}
525533

526534
if (checkModified)
527535
{
528536
_modifiedPlugins.Add(plugin.ID);
529537
}
530538
}
531539

532-
internal static void UninstallPlugin(PluginMetadata plugin, bool removeSettings, bool checkModified)
540+
internal static void UninstallPlugin(PluginMetadata plugin, bool removePluginFromSettings, bool removePluginSettings, bool checkModified)
533541
{
534542
if (checkModified && PluginModified(plugin.ID))
535543
{
536544
throw new ArgumentException($"Plugin {plugin.Name} has been modified");
537545
}
538546

539-
if (removeSettings)
547+
if (removePluginSettings)
548+
{
549+
if (AllowedLanguage.IsDotNet(plugin.Language)) // for the plugin in .NET, we can use assembly loader
550+
{
551+
var assemblyLoader = new PluginAssemblyLoader(plugin.ExecuteFilePath);
552+
var assembly = assemblyLoader.LoadAssemblyAndDependencies();
553+
var assemblyName = assembly.GetName().Name;
554+
555+
// if user want to remove the plugin settings, we cannot call save method for the plugin json storage instance of this plugin
556+
// so we need to remove it from the api instance
557+
var method = API.GetType().GetMethod("RemovePluginSettings");
558+
var pluginJsonStorage = method?.Invoke(API, new object[] { assemblyName });
559+
560+
// if there exists a json storage for current plugin, we need to delete the directory path
561+
if (pluginJsonStorage != null)
562+
{
563+
var deleteMethod = pluginJsonStorage.GetType().GetMethod("DeleteDirectory");
564+
try
565+
{
566+
deleteMethod?.Invoke(pluginJsonStorage, null);
567+
}
568+
catch (Exception e)
569+
{
570+
Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin json folder for {plugin.Name}", e);
571+
API.ShowMsg(API.GetTranslation("failedToRemovePluginSettingsTitle"),
572+
string.Format(API.GetTranslation("failedToRemovePluginSettingsMessage"), plugin.Name));
573+
}
574+
}
575+
}
576+
else // the plugin with json prc interface
577+
{
578+
var pluginPair = AllPlugins.FirstOrDefault(p => p.Metadata.ID == plugin.ID);
579+
if (pluginPair != null && pluginPair.Plugin is JsonRPCPlugin jsonRpcPlugin)
580+
{
581+
try
582+
{
583+
jsonRpcPlugin.DeletePluginSettingsDirectory();
584+
}
585+
catch (Exception e)
586+
{
587+
Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin json folder for {plugin.Name}", e);
588+
API.ShowMsg(API.GetTranslation("failedToRemovePluginSettingsTitle"),
589+
string.Format(API.GetTranslation("failedToRemovePluginSettingsMessage"), plugin.Name));
590+
}
591+
}
592+
}
593+
}
594+
595+
if (removePluginFromSettings)
540596
{
541597
Settings.Plugins.Remove(plugin.ID);
542598
AllPlugins.RemoveAll(p => p.Metadata.ID == plugin.ID);

Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33

44
namespace Flow.Launcher.Infrastructure.Storage
55
{
6-
public class PluginJsonStorage<T> :JsonStorage<T> where T : new()
6+
public class PluginJsonStorage<T> : JsonStorage<T> where T : new()
77
{
8+
// Use assembly name to check which plugin is using this storage
9+
public readonly string AssemblyName;
10+
811
public PluginJsonStorage()
912
{
1013
// C# related, add python related below
1114
var dataType = typeof(T);
12-
var assemblyName = dataType.Assembly.GetName().Name;
13-
DirectoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName, Constant.Plugins, assemblyName);
15+
AssemblyName = dataType.Assembly.GetName().Name;
16+
DirectoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName, Constant.Plugins, AssemblyName);
1417
Helper.ValidateDirectory(DirectoryPath);
1518

1619
FilePath = Path.Combine(DirectoryPath, $"{dataType.Name}{FileSuffix}");
@@ -20,6 +23,13 @@ public PluginJsonStorage(T data) : this()
2023
{
2124
Data = data;
2225
}
26+
27+
public void DeleteDirectory()
28+
{
29+
if (Directory.Exists(DirectoryPath))
30+
{
31+
Directory.Delete(DirectoryPath, true);
32+
}
33+
}
2334
}
2435
}
25-

Flow.Launcher/Languages/en.xaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@
129129
<system:String x:Key="plugin_query_version">Version</system:String>
130130
<system:String x:Key="plugin_query_web">Website</system:String>
131131
<system:String x:Key="plugin_uninstall">Uninstall</system:String>
132-
132+
<system:String x:Key="failedToRemovePluginSettingsTitle">Fail to remove plugin settings</system:String>
133+
<system:String x:Key="failedToRemovePluginSettingsMessage">Plugins: {0} - Fail to remove plugin settings files, please remove them manually</system:String>
133134

134135
<!-- Setting Plugin Store -->
135136
<system:String x:Key="pluginStore">Plugin Store</system:String>
@@ -146,8 +147,6 @@
146147
<system:String x:Key="LabelNewToolTip">This plugin has been updated within the last 7 days</system:String>
147148
<system:String x:Key="LabelUpdateToolTip">New Update is Available</system:String>
148149

149-
150-
151150
<!-- Setting Theme -->
152151
<system:String x:Key="theme">Theme</system:String>
153152
<system:String x:Key="appearance">Appearance</system:String>
@@ -197,7 +196,6 @@
197196
<system:String x:Key="TypeIsDarkToolTip">This theme supports two(light/dark) modes.</system:String>
198197
<system:String x:Key="TypeHasBlurToolTip">This theme supports Blur Transparent Background.</system:String>
199198

200-
201199
<!-- Setting Hotkey -->
202200
<system:String x:Key="hotkey">Hotkey</system:String>
203201
<system:String x:Key="hotkeys">Hotkeys</system:String>

Flow.Launcher/PublicAPIInstance.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,23 @@ public void LogException(string className, string message, Exception e,
189189

190190
private readonly ConcurrentDictionary<Type, object> _pluginJsonStorages = new();
191191

192+
public object RemovePluginSettings(string assemblyName)
193+
{
194+
foreach (var keyValuePair in _pluginJsonStorages)
195+
{
196+
var key = keyValuePair.Key;
197+
var value = keyValuePair.Value;
198+
var name = value.GetType().GetField("AssemblyName")?.GetValue(value)?.ToString();
199+
if (name == assemblyName)
200+
{
201+
_pluginJsonStorages.Remove(key, out var pluginJsonStorage);
202+
return pluginJsonStorage;
203+
}
204+
}
205+
206+
return null;
207+
}
208+
192209
/// <summary>
193210
/// Save plugin settings.
194211
/// </summary>

Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
<system:String x:Key="plugin_pluginsmanager_installing_plugin">Installing Plugin</system:String>
1616
<system:String x:Key="plugin_pluginsmanager_install_from_web">Download and install {0}</system:String>
1717
<system:String x:Key="plugin_pluginsmanager_uninstall_title">Plugin Uninstall</system:String>
18+
<system:String x:Key="plugin_pluginsmanager_keep_plugin_settings_title">Keep plugin settings</system:String>
19+
<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>
1820
<system:String x:Key="plugin_pluginsmanager_install_success_restart">Plugin {0} successfully installed. Restarting Flow, please wait...</system:String>
1921
<system:String x:Key="plugin_pluginsmanager_install_errormetadatafile">Unable to find the plugin.json metadata file from the extracted zip file.</system:String>
2022
<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 @@
3739
<system:String x:Key="plugin_pluginsmanager_update_success_restart">Plugin {0} successfully updated. Restarting Flow, please wait...</system:String>
3840
<system:String x:Key="plugin_pluginsmanager_install_unknown_source_warning_title">Installing from an unknown source</system:String>
3941
<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>
40-
42+
4143
<system:String x:Key="plugin_pluginsmanager_install_success_no_restart">Plugin {0} successfully installed. Please restart Flow.</system:String>
4244
<system:String x:Key="plugin_pluginsmanager_uninstall_success_no_restart">Plugin {0} successfully uninstalled. Please restart Flow.</system:String>
4345
<system:String x:Key="plugin_pluginsmanager_update_success_no_restart">Plugin {0} successfully updated. Please restart Flow.</system:String>
4446
<system:String x:Key="plugin_pluginsmanager_update_all_success_no_restart">{0} plugins successfully updated. Please restart Flow.</system:String>
4547
<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>
46-
48+
4749
<!-- Plugin Infos -->
4850
<system:String x:Key="plugin_pluginsmanager_plugin_name">Plugins Manager</system:String>
4951
<system:String x:Key="plugin_pluginsmanager_plugin_description">Management of installing, uninstalling or updating Flow Launcher plugins</system:String>

Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,11 @@ private void Uninstall(PluginMetadata plugin)
733733
{
734734
try
735735
{
736-
PluginManager.UninstallPlugin(plugin, removeSettings: true);
736+
var removePluginSettings = Context.API.ShowMsgBox(
737+
Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_subtitle"),
738+
Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_title"),
739+
button: MessageBoxButton.YesNo) == MessageBoxResult.No;
740+
PluginManager.UninstallPlugin(plugin, removePluginFromSettings: true, removePluginSettings: removePluginSettings);
737741
}
738742
catch (ArgumentException e)
739743
{

0 commit comments

Comments
 (0)