Add MinimumAppVersion support for plugins

Introduced MinimumAppVersion property to PluginMetadata, enabling plugins to specify required Flow Launcher version. Plugin installation now checks this requirement and prompts users if unsatisfied. Minimum app version logic moved to PluginManager and applied to manifest updates. Added localized strings for user prompts. Refactored SameOrLesserPluginVersionExists to accept PluginMetadata.
This commit is contained in:
Jack251970 2026-02-27 18:30:29 +08:00
parent 54dc790cb6
commit 2e0db3b90f
4 changed files with 53 additions and 32 deletions

View file

@ -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<UserPlugin>();
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;
}
}
}

View file

@ -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<PluginMetadata>(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<PluginMetadata>(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<string>
@ -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

View file

@ -137,6 +137,11 @@ namespace Flow.Launcher.Plugin
[JsonIgnore]
public int QueryCount { get; set; }
/// <summary>
/// The minimum Flow Launcher version required for this plugin. Default is "".
/// </summary>
public string MinimumAppVersion { get; set; } = string.Empty;
/// <summary>
/// The path to the plugin settings directory which is not validated.
/// It is used to store plugin settings files and data files.

View file

@ -232,6 +232,8 @@
<system:String x:Key="fileNotFoundMessage">Unable to find plugin.json from the extracted zip file, or this path {0} does not exist</system:String>
<system:String x:Key="pluginExistAlreadyMessage">A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin</system:String>
<system:String x:Key="errorCreatingSettingPanel">Error creating setting panel for plugin {0}:{1}{2}</system:String>
<system:String x:Key="pluginMinimumAppVersionUnsatisfiedTitle">{0} requires Flow {1}+ version to run</system:String>
<system:String x:Key="pluginMinimumAppVersionUnsatisfiedMessage">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</system:String>
<!-- Setting Plugin Store -->
<system:String x:Key="pluginStore">Plugin Store</system:String>