Skip to content

Commit 2e0db3b

Browse files
committed
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.
1 parent 54dc790 commit 2e0db3b

4 files changed

Lines changed: 53 additions & 32 deletions

File tree

Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using System.Threading;
44
using System.Threading.Tasks;
55
using Flow.Launcher.Plugin;
6-
using Flow.Launcher.Infrastructure;
6+
using Flow.Launcher.Core.Plugin;
77

88
namespace Flow.Launcher.Core.ExternalPlugins
99
{
@@ -41,11 +41,10 @@ public static async Task<bool> UpdateManifestAsync(bool usePrimaryUrlOnly = fals
4141
return false;
4242

4343
var updatedPluginResults = new List<UserPlugin>();
44-
var appVersion = SemanticVersioning.Version.Parse(Constant.Version);
4544

4645
for (int i = 0; i < results.Count; i++)
4746
{
48-
if (IsMinimumAppVersionSatisfied(results[i], appVersion))
47+
if (PluginManager.IsMinimumAppVersionSatisfied(results[i].Name, results[i].MinimumAppVersion))
4948
updatedPluginResults.Add(results[i]);
5049
}
5150

@@ -72,28 +71,5 @@ public static async Task<bool> UpdateManifestAsync(bool usePrimaryUrlOnly = fals
7271

7372
return false;
7473
}
75-
76-
private static bool IsMinimumAppVersionSatisfied(UserPlugin plugin, SemanticVersioning.Version appVersion)
77-
{
78-
if (string.IsNullOrEmpty(plugin.MinimumAppVersion))
79-
return true;
80-
81-
try
82-
{
83-
if (appVersion >= SemanticVersioning.Version.Parse(plugin.MinimumAppVersion))
84-
return true;
85-
}
86-
catch (Exception e)
87-
{
88-
PublicApi.Instance.LogException(ClassName, $"Failed to parse the minimum app version {plugin.MinimumAppVersion} for plugin {plugin.Name}. "
89-
+ "Plugin excluded from manifest", e);
90-
return false;
91-
}
92-
93-
PublicApi.Instance.LogInfo(ClassName, $"Plugin {plugin.Name} requires minimum Flow Launcher version {plugin.MinimumAppVersion}, "
94-
+ $"but current version is {Constant.Version}. Plugin excluded from manifest.");
95-
96-
return false;
97-
}
9874
}
9975
}

Flow.Launcher.Core/Plugin/PluginManager.cs

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Text.Json;
77
using System.Threading;
88
using System.Threading.Tasks;
9+
using System.Windows;
910
using Flow.Launcher.Core.ExternalPlugins;
1011
using Flow.Launcher.Core.Resource;
1112
using Flow.Launcher.Infrastructure;
@@ -813,15 +814,13 @@ private static string GetContainingFolderPathAfterUnzip(string unzippedParentFol
813814
return string.Empty;
814815
}
815816

816-
private static bool SameOrLesserPluginVersionExists(string metadataPath)
817+
private static bool SameOrLesserPluginVersionExists(PluginMetadata metadata)
817818
{
818-
var newMetadata = JsonSerializer.Deserialize<PluginMetadata>(File.ReadAllText(metadataPath));
819-
820-
if (!Version.TryParse(newMetadata.Version, out var newVersion))
819+
if (!Version.TryParse(metadata.Version, out var newVersion))
821820
return true; // If version is not valid, we assume it is lesser than any existing version
822821

823822
// Get all plugins even if initialization failed so that we can check if the plugin with the same ID exists
824-
return GetAllInitializedPlugins(includeFailed: true).Any(x => x.Metadata.ID == newMetadata.ID
823+
return GetAllInitializedPlugins(includeFailed: true).Any(x => x.Metadata.ID == metadata.ID
825824
&& Version.TryParse(x.Metadata.Version, out var version)
826825
&& newVersion <= version);
827826
}
@@ -897,13 +896,27 @@ internal static bool InstallPlugin(UserPlugin plugin, string zipFilePath, bool c
897896
return false;
898897
}
899898

900-
if (SameOrLesserPluginVersionExists(metadataJsonFilePath))
899+
var newMetadata = JsonSerializer.Deserialize<PluginMetadata>(File.ReadAllText(metadataJsonFilePath));
900+
901+
if (SameOrLesserPluginVersionExists(newMetadata))
901902
{
902903
PublicApi.Instance.ShowMsgError(Localize.failedToInstallPluginTitle(plugin.Name),
903904
Localize.pluginExistAlreadyMessage());
904905
return false;
905906
}
906907

908+
if (!IsMinimumAppVersionSatisfied(newMetadata.Name, newMetadata.MinimumAppVersion))
909+
{
910+
// Ask users if they want to install the plugin that doesn't satisfy the minimum app version requirement
911+
if (PublicApi.Instance.ShowMsgBox(
912+
Localize.pluginMinimumAppVersionUnsatisfiedMessage(newMetadata.Name),
913+
Localize.pluginMinimumAppVersionUnsatisfiedTitle(newMetadata.Name, newMetadata.MinimumAppVersion),
914+
MessageBoxButton.YesNo) == MessageBoxResult.No)
915+
{
916+
return false;
917+
}
918+
}
919+
907920
var folderName = string.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}-{Guid.NewGuid()}" : $"{plugin.Name}-{plugin.Version}";
908921

909922
var defaultPluginIDs = new List<string>
@@ -1050,6 +1063,31 @@ internal static async Task<bool> UninstallPluginAsync(PluginMetadata plugin, boo
10501063
return true;
10511064
}
10521065

1066+
internal static bool IsMinimumAppVersionSatisfied(string pluginName, string minimumAppVersion)
1067+
{
1068+
if (string.IsNullOrEmpty(minimumAppVersion))
1069+
return true;
1070+
1071+
var appVersion = Version.Parse(Constant.Version);
1072+
1073+
try
1074+
{
1075+
if (appVersion >= Version.Parse(minimumAppVersion))
1076+
return true;
1077+
}
1078+
catch (Exception e)
1079+
{
1080+
PublicApi.Instance.LogException(ClassName, $"Failed to parse the minimum app version {minimumAppVersion} for plugin {pluginName}. "
1081+
+ "Plugin excluded from manifest", e);
1082+
return false;
1083+
}
1084+
1085+
PublicApi.Instance.LogInfo(ClassName, $"Plugin {pluginName} requires minimum Flow Launcher version {minimumAppVersion}, "
1086+
+ $"but current version is {Constant.Version}. Plugin excluded from manifest.");
1087+
1088+
return false;
1089+
}
1090+
10531091
#endregion
10541092

10551093
#endregion

Flow.Launcher.Plugin/PluginMetadata.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@ internal set
137137
[JsonIgnore]
138138
public int QueryCount { get; set; }
139139

140+
/// <summary>
141+
/// The minimum Flow Launcher version required for this plugin. Default is "".
142+
/// </summary>
143+
public string MinimumAppVersion { get; set; } = string.Empty;
144+
140145
/// <summary>
141146
/// The path to the plugin settings directory which is not validated.
142147
/// It is used to store plugin settings files and data files.

Flow.Launcher/Languages/en.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@
232232
<system:String x:Key="fileNotFoundMessage">Unable to find plugin.json from the extracted zip file, or this path {0} does not exist</system:String>
233233
<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>
234234
<system:String x:Key="errorCreatingSettingPanel">Error creating setting panel for plugin {0}:{1}{2}</system:String>
235+
<system:String x:Key="pluginMinimumAppVersionUnsatisfiedTitle">{0} requires Flow {1}+ version to run</system:String>
236+
<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>
235237

236238
<!-- Setting Plugin Store -->
237239
<system:String x:Key="pluginStore">Plugin Store</system:String>

0 commit comments

Comments
 (0)