diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index 4fed10d25..ba332d0a4 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Flow.Launcher.Plugin; -using Flow.Launcher.Infrastructure; +using Flow.Launcher.Core.Plugin; namespace Flow.Launcher.Core.ExternalPlugins { @@ -41,11 +41,10 @@ namespace Flow.Launcher.Core.ExternalPlugins return false; var updatedPluginResults = new List(); - var appVersion = SemanticVersioning.Version.Parse(Constant.Version); for (int i = 0; i < results.Count; i++) { - if (IsMinimumAppVersionSatisfied(results[i], appVersion)) + if (PluginManager.IsMinimumAppVersionSatisfied(results[i].Name, results[i].MinimumAppVersion)) updatedPluginResults.Add(results[i]); } @@ -72,28 +71,5 @@ namespace Flow.Launcher.Core.ExternalPlugins return false; } - - private static bool IsMinimumAppVersionSatisfied(UserPlugin plugin, SemanticVersioning.Version appVersion) - { - if (string.IsNullOrEmpty(plugin.MinimumAppVersion)) - return true; - - try - { - if (appVersion >= SemanticVersioning.Version.Parse(plugin.MinimumAppVersion)) - return true; - } - catch (Exception e) - { - PublicApi.Instance.LogException(ClassName, $"Failed to parse the minimum app version {plugin.MinimumAppVersion} for plugin {plugin.Name}. " - + "Plugin excluded from manifest", e); - return false; - } - - PublicApi.Instance.LogInfo(ClassName, $"Plugin {plugin.Name} requires minimum Flow Launcher version {plugin.MinimumAppVersion}, " - + $"but current version is {Constant.Version}. Plugin excluded from manifest."); - - return false; - } } } diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index b808e2a7f..5e5706656 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using System.Windows; using Flow.Launcher.Core.ExternalPlugins; using Flow.Launcher.Core.Resource; using Flow.Launcher.Infrastructure; @@ -813,15 +814,13 @@ namespace Flow.Launcher.Core.Plugin return string.Empty; } - private static bool SameOrLesserPluginVersionExists(string metadataPath) + private static bool SameOrLesserPluginVersionExists(PluginMetadata metadata) { - var newMetadata = JsonSerializer.Deserialize(File.ReadAllText(metadataPath)); - - if (!Version.TryParse(newMetadata.Version, out var newVersion)) + if (!Version.TryParse(metadata.Version, out var newVersion)) return true; // If version is not valid, we assume it is lesser than any existing version // Get all plugins even if initialization failed so that we can check if the plugin with the same ID exists - return GetAllInitializedPlugins(includeFailed: true).Any(x => x.Metadata.ID == newMetadata.ID + return GetAllInitializedPlugins(includeFailed: true).Any(x => x.Metadata.ID == metadata.ID && Version.TryParse(x.Metadata.Version, out var version) && newVersion <= version); } @@ -897,13 +896,27 @@ namespace Flow.Launcher.Core.Plugin return false; } - if (SameOrLesserPluginVersionExists(metadataJsonFilePath)) + var newMetadata = JsonSerializer.Deserialize(File.ReadAllText(metadataJsonFilePath)); + + if (SameOrLesserPluginVersionExists(newMetadata)) { PublicApi.Instance.ShowMsgError(Localize.failedToInstallPluginTitle(plugin.Name), Localize.pluginExistAlreadyMessage()); return false; } + if (!IsMinimumAppVersionSatisfied(newMetadata.Name, newMetadata.MinimumAppVersion)) + { + // Ask users if they want to install the plugin that doesn't satisfy the minimum app version requirement + if (PublicApi.Instance.ShowMsgBox( + Localize.pluginMinimumAppVersionUnsatisfiedMessage(newMetadata.Name), + Localize.pluginMinimumAppVersionUnsatisfiedTitle(newMetadata.Name, newMetadata.MinimumAppVersion), + MessageBoxButton.YesNo) == MessageBoxResult.No) + { + return false; + } + } + var folderName = string.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}-{Guid.NewGuid()}" : $"{plugin.Name}-{plugin.Version}"; var defaultPluginIDs = new List @@ -1050,6 +1063,31 @@ namespace Flow.Launcher.Core.Plugin return true; } + internal static bool IsMinimumAppVersionSatisfied(string pluginName, string minimumAppVersion) + { + if (string.IsNullOrEmpty(minimumAppVersion)) + return true; + + var appVersion = Version.Parse(Constant.Version); + + try + { + if (appVersion >= Version.Parse(minimumAppVersion)) + return true; + } + catch (Exception e) + { + PublicApi.Instance.LogException(ClassName, $"Failed to parse the minimum app version {minimumAppVersion} for plugin {pluginName}. " + + "Plugin excluded from manifest", e); + return false; + } + + PublicApi.Instance.LogInfo(ClassName, $"Plugin {pluginName} requires minimum Flow Launcher version {minimumAppVersion}, " + + $"but current version is {Constant.Version}. Plugin excluded from manifest."); + + return false; + } + #endregion #endregion diff --git a/Flow.Launcher.Plugin/PluginMetadata.cs b/Flow.Launcher.Plugin/PluginMetadata.cs index 09803cbd7..253573910 100644 --- a/Flow.Launcher.Plugin/PluginMetadata.cs +++ b/Flow.Launcher.Plugin/PluginMetadata.cs @@ -137,6 +137,11 @@ namespace Flow.Launcher.Plugin [JsonIgnore] public int QueryCount { get; set; } + /// + /// The minimum Flow Launcher version required for this plugin. Default is "". + /// + public string MinimumAppVersion { get; set; } = string.Empty; + /// /// The path to the plugin settings directory which is not validated. /// It is used to store plugin settings files and data files. diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 145e1883d..a271ca484 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -232,6 +232,8 @@ Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin Error creating setting panel for plugin {0}:{1}{2} + {0} requires Flow {1}+ version to run + Flow does not meet the minimum version requirements for {0} to run. Do you want to continue installing it? Note that you'd better update Flow to the latest version to ensure that {0} works without issues Plugin Store