Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Plugin Metadata & Path Management #3272

Open
wants to merge 31 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
89bca3b
Add plugin cache path
Jack251970 Feb 23, 2025
5919418
Add assembly name & plugin settings path & plugin cache path in meta …
Jack251970 Feb 23, 2025
f1b5e68
Remove reflection codes for deleting csharp plugin settings
Jack251970 Feb 23, 2025
1aaba46
Use constants & data location for code quality
Jack251970 Feb 23, 2025
9cd3011
Add documents for plugin metadata
Jack251970 Feb 23, 2025
8f7ad27
Remove useless usings
Jack251970 Feb 23, 2025
d07b304
Improve code quality
Jack251970 Feb 24, 2025
b50db58
Add assembly name & plugin settings path & plugin cache path in meta …
Jack251970 Feb 24, 2025
6012111
Add log directory & version log directory & themes directory in data …
Jack251970 Feb 24, 2025
3efe550
Use context plugin settings path
Jack251970 Feb 24, 2025
126153b
Improve plugin settings directory clean & Support plugin cache direct…
Jack251970 Feb 24, 2025
3106b02
Support plugin directory update & validate
Jack251970 Feb 24, 2025
012ef49
Fix log directory fetch issue
Jack251970 Feb 24, 2025
58de625
Do not validate plugin settings & cache path
Jack251970 Feb 24, 2025
47adfd1
Improve code quality
Jack251970 Feb 24, 2025
a0c2a42
Let Program plugin use plugin cache path
Jack251970 Feb 24, 2025
a29ed64
Use metadata for plugin settings directory
Jack251970 Feb 24, 2025
65ae342
Add documents for Flow.Launcher.Plugin
Jack251970 Feb 24, 2025
6622815
Fix typos
Jack251970 Feb 24, 2025
fe86e23
Add exception handles
Jack251970 Feb 24, 2025
f8d0981
Update json rpc plugin directory before loading plugins
Jack251970 Feb 25, 2025
7975ab5
Merge branch 'dev' into plugin_settings_cache_path
Jack251970 Mar 1, 2025
ce3a3e9
Fix plugin settings delete issue
Jack251970 Mar 6, 2025
486cc6a
Fix async task issue
Jack251970 Mar 6, 2025
af3b391
Fix dispose
Jack251970 Mar 6, 2025
c690e59
Merge branch 'dev' into plugin_settings_cache_path
Jack251970 Mar 16, 2025
b0b1a26
Fix build issue & Cleanup codes
Jack251970 Mar 16, 2025
e3af882
Merge branch 'dev' into plugin_settings_cache_path
Jack251970 Mar 20, 2025
c87b731
Merge branch 'dev' into plugin_settings_cache_path
Jack251970 Mar 20, 2025
ee0b039
Merge update plugin directory functions
Jack251970 Mar 23, 2025
5f976b9
Remove useless assignment
Jack251970 Mar 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Flow.Launcher.Plugin.SharedCommands;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
Expand Down Expand Up @@ -113,7 +114,10 @@ private IEnumerable<PluginPair> SetPathForPluginPairs(string filePath, string la
foreach (var metadata in PluginMetadataList)
{
if (metadata.Language.Equals(languageToSet, StringComparison.OrdinalIgnoreCase))
{
metadata.AssemblyName = string.Empty;
pluginPairs.Add(CreatePluginPair(filePath, metadata));
}
}

return pluginPairs;
Expand Down
14 changes: 1 addition & 13 deletions Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,16 @@
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Infrastructure;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Microsoft.IO;
using System.Windows;
using System.Windows.Controls;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using CheckBox = System.Windows.Controls.CheckBox;
using Control = System.Windows.Controls.Control;
using Orientation = System.Windows.Controls.Orientation;
using TextBox = System.Windows.Controls.TextBox;
using UserControl = System.Windows.Controls.UserControl;
using System.Windows.Documents;

namespace Flow.Launcher.Core.Plugin
{
Expand All @@ -42,7 +30,7 @@ internal abstract class JsonRPCPlugin : JsonRPCPluginBase
private int RequestId { get; set; }

private string SettingConfigurationPath => Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "SettingsTemplate.yaml");
private string SettingPath => Path.Combine(DataLocation.PluginSettingsDirectory, Context.CurrentPluginMetadata.Name, "Settings.json");
private string SettingPath => Path.Combine(Context.CurrentPluginMetadata.PluginSettingsDirectoryPath, "Settings.json");

public override List<Result> LoadContextMenus(Result selectedResult)
{
Expand Down
28 changes: 1 addition & 27 deletions Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs
Original file line number Diff line number Diff line change
@@ -1,32 +1,15 @@
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Infrastructure;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin;
using Microsoft.IO;
using System.Windows;
using System.Windows.Controls;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using CheckBox = System.Windows.Controls.CheckBox;
using Control = System.Windows.Controls.Control;
using Orientation = System.Windows.Controls.Orientation;
using TextBox = System.Windows.Controls.TextBox;
using UserControl = System.Windows.Controls.UserControl;
using System.Windows.Documents;
using static System.Windows.Forms.LinkLabel;
using Droplex;
using System.Windows.Forms;
using Microsoft.VisualStudio.Threading;

namespace Flow.Launcher.Core.Plugin
{
Expand All @@ -44,8 +27,7 @@ internal abstract class JsonRPCPluginBase : IAsyncPlugin, IContextMenu, ISetting
private string SettingConfigurationPath =>
Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "SettingsTemplate.yaml");

private string SettingDirectory => Path.Combine(DataLocation.PluginSettingsDirectory,
Context.CurrentPluginMetadata.Name);
private string SettingDirectory => Context.CurrentPluginMetadata.PluginSettingsDirectoryPath;

private string SettingPath => Path.Combine(SettingDirectory, "Settings.json");

Expand Down Expand Up @@ -161,13 +143,5 @@ public Control CreateSettingPanel()
{
return Settings.CreateSettingPanel();
}

public void DeletePluginSettingsDirectory()
{
if (Directory.Exists(SettingDirectory))
{
Directory.Delete(SettingDirectory, true);
}
}
}
}
7 changes: 3 additions & 4 deletions Flow.Launcher.Core/Plugin/PluginConfig.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
Expand All @@ -9,7 +9,6 @@

namespace Flow.Launcher.Core.Plugin
{

internal abstract class PluginConfig
{
/// <summary>
Expand Down Expand Up @@ -112,7 +111,7 @@ private static PluginMetadata GetPluginMetadata(string pluginDirectory)
metadata = JsonSerializer.Deserialize<PluginMetadata>(File.ReadAllText(configPath));
metadata.PluginDirectory = pluginDirectory;
// for plugins which doesn't has ActionKeywords key
metadata.ActionKeywords = metadata.ActionKeywords ?? new List<string> { metadata.ActionKeyword };
metadata.ActionKeywords ??= new List<string> { metadata.ActionKeyword };
// for plugin still use old ActionKeyword
metadata.ActionKeyword = metadata.ActionKeywords?[0];
}
Expand All @@ -137,4 +136,4 @@ private static PluginMetadata GetPluginMetadata(string pluginDirectory)
return metadata;
}
}
}
}
87 changes: 45 additions & 42 deletions Flow.Launcher.Core/Plugin/PluginManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static class PluginManager

private static PluginsSettings Settings;
private static List<PluginMetadata> _metadatas;
private static List<string> _modifiedPlugins = new List<string>();
private static List<string> _modifiedPlugins = new();

/// <summary>
/// Directories that will hold Flow Launcher plugin directory
Expand Down Expand Up @@ -152,6 +152,24 @@ public static void LoadPlugins(PluginsSettings settings)
Settings = settings;
Settings.UpdatePluginSettings(_metadatas);
AllPlugins = PluginsLoader.Plugins(_metadatas, Settings);
UpdatePluginDirectory(_metadatas);
}

private static void UpdatePluginDirectory(List<PluginMetadata> metadatas)
{
foreach (var metadata in metadatas)
{
if (AllowedLanguage.IsDotNet(metadata.Language))
{
metadata.PluginSettingsDirectoryPath = Path.Combine(DataLocation.PluginSettingsDirectory, metadata.AssemblyName);
metadata.PluginCacheDirectoryPath = Path.Combine(DataLocation.PluginCacheDirectory, metadata.AssemblyName);
}
else
{
metadata.PluginSettingsDirectoryPath = Path.Combine(DataLocation.PluginSettingsDirectory, metadata.Name);
metadata.PluginCacheDirectoryPath = Path.Combine(DataLocation.PluginCacheDirectory, metadata.Name);
}
}
}

/// <summary>
Expand Down Expand Up @@ -226,11 +244,9 @@ public static ICollection<PluginPair> ValidPluginsForQuery(Query query)
if (query is null)
return Array.Empty<PluginPair>();

if (!NonGlobalPlugins.ContainsKey(query.ActionKeyword))
if (!NonGlobalPlugins.TryGetValue(query.ActionKeyword, out var plugin))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code quality improvement

return GlobalPlugins;


var plugin = NonGlobalPlugins[query.ActionKeyword];
return new List<PluginPair>
{
plugin
Expand Down Expand Up @@ -546,54 +562,41 @@ internal static void UninstallPlugin(PluginMetadata plugin, bool removePluginFro

if (removePluginSettings)
{
if (AllowedLanguage.IsDotNet(plugin.Language)) // for the plugin in .NET, we can use assembly loader
// For dotnet plugins, we need to remove their PluginJsonStorage instance
if (AllowedLanguage.IsDotNet(plugin.Language))
{
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 });
method?.Invoke(API, new object[] { plugin.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));
}
}
try
{
var pluginSettingsDirectory = plugin.PluginSettingsDirectoryPath;
if (Directory.Exists(pluginSettingsDirectory))
Directory.Delete(pluginSettingsDirectory, true);
}
else // the plugin with json prc interface
catch (Exception e)
{
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));
}
}
Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin settings folder for {plugin.Name}", e);
API.ShowMsg(API.GetTranslation("failedToRemovePluginSettingsTitle"),
string.Format(API.GetTranslation("failedToRemovePluginSettingsMessage"), plugin.Name));
}
}

if (removePluginFromSettings)
{
try
{
var pluginCacheDirectory = plugin.PluginCacheDirectoryPath;
if (Directory.Exists(pluginCacheDirectory))
Directory.Delete(pluginCacheDirectory, true);
}
catch (Exception e)
{
Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin cache folder for {plugin.Name}", e);
API.ShowMsg(API.GetTranslation("failedToRemovePluginCacheTitle"),
string.Format(API.GetTranslation("failedToRemovePluginCacheMessage"), plugin.Name));
}
Settings.Plugins.Remove(plugin.ID);
AllPlugins.RemoveAll(p => p.Metadata.ID == plugin.ID);
}
Expand Down
31 changes: 25 additions & 6 deletions Flow.Launcher.Core/Plugin/PluginsLoader.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
Expand Down Expand Up @@ -73,9 +74,11 @@ public static IEnumerable<PluginPair> DotNetPlugins(List<PluginMetadata> source)
typeof(IAsyncPlugin));

plugin = Activator.CreateInstance(type) as IAsyncPlugin;

metadata.AssemblyName = assembly.GetName().Name;
}
#if DEBUG
catch (Exception e)
catch (Exception)
{
throw;
}
Expand Down Expand Up @@ -111,7 +114,7 @@ public static IEnumerable<PluginPair> DotNetPlugins(List<PluginMetadata> source)

if (erroredPlugins.Count > 0)
{
var errorPluginString = String.Join(Environment.NewLine, erroredPlugins);
var errorPluginString = string.Join(Environment.NewLine, erroredPlugins);

var errorMessage = "The following "
+ (erroredPlugins.Count > 1 ? "plugins have " : "plugin has ")
Expand All @@ -133,19 +136,35 @@ public static IEnumerable<PluginPair> ExecutablePlugins(IEnumerable<PluginMetada
{
return source
.Where(o => o.Language.Equals(AllowedLanguage.Executable, StringComparison.OrdinalIgnoreCase))
.Select(metadata => new PluginPair
.Select(metadata =>
{
Plugin = new ExecutablePlugin(metadata.ExecuteFilePath), Metadata = metadata
var plugin = new PluginPair
{
Plugin = new ExecutablePlugin(metadata.ExecuteFilePath),
Metadata = metadata
};

plugin.Metadata.AssemblyName = string.Empty;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to manually set this? isn't the default is either empty or null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we can remove that


return plugin;
});
}

public static IEnumerable<PluginPair> ExecutableV2Plugins(IEnumerable<PluginMetadata> source)
{
return source
.Where(o => o.Language.Equals(AllowedLanguage.ExecutableV2, StringComparison.OrdinalIgnoreCase))
.Select(metadata => new PluginPair
.Select(metadata =>
{
Plugin = new ExecutablePluginV2(metadata.ExecuteFilePath), Metadata = metadata
var plugin = new PluginPair
{
Plugin = new ExecutablePlugin(metadata.ExecuteFilePath),
Metadata = metadata
};

plugin.Metadata.AssemblyName = string.Empty;

return plugin;
});
}
}
Expand Down
1 change: 1 addition & 0 deletions Flow.Launcher.Infrastructure/Constant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public static class Constant
public const string Themes = "Themes";
public const string Settings = "Settings";
public const string Logs = "Logs";
public const string Cache = "Cache";

public const string Website = "https://flowlauncher.com";
public const string SponsorPage = "https://github.com/sponsors/Flow-Launcher";
Expand Down
4 changes: 2 additions & 2 deletions Flow.Launcher.Infrastructure/Logger/Log.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ namespace Flow.Launcher.Infrastructure.Logger
{
public static class Log
{
public const string DirectoryName = "Logs";
public const string DirectoryName = Constant.Logs;

public static string CurrentLogDirectory { get; }

static Log()
{
CurrentLogDirectory = Path.Combine(DataLocation.DataDirectory(), DirectoryName, Constant.Version);
CurrentLogDirectory = DataLocation.VersionLogDirectory;
if (!Directory.Exists(CurrentLogDirectory))
{
Directory.CreateDirectory(CurrentLogDirectory);
Expand Down
Loading
Loading