Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
<system:String x:Key="plugin_pluginsmanager_install_title">Plugin Install</system:String>
<system:String x:Key="plugin_pluginsmanager_uninstall_title">Plugin Uninstall</system:String>
<system:String x:Key="plugin_pluginsmanager_install_errormetadatafile">Install failed: unable to find the plugin.json metadata file from the new plugin</system:String>
<system:String x:Key="plugin_pluginsmanager_update_noresult_title">No update available</system:String>
<system:String x:Key="plugin_pluginsmanager_update_noresult_subtitle">All plugins are up to date</system:String>
<system:String x:Key="plugin_pluginsmanager_update_prompt">{0} by {1} {2}{3}Would you like to update this plugin? After the update Flow will automatically restart.</system:String>
<system:String x:Key="plugin_pluginsmanager_update_title">Plugin Update</system:String>
<system:String x:Key="plugin_pluginsmanager_update_exists">This plugin has an update, would you like to see it?</system:String>
<system:String x:Key="plugin_pluginsmanager_update_alreadyexists">This plugin is already installed</system:String>

<!--Controls-->

<!--Plugin Infos-->
Expand Down
8 changes: 6 additions & 2 deletions Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@ public List<Result> Query(Query query)
var pluginManager = new PluginsManager(Context, Settings);

if (!string.IsNullOrEmpty(search)
&& ($"{Settings.UninstallHotkey} ".StartsWith(search) || search.StartsWith($"{Settings.UninstallHotkey} ")))
&& ($"{Settings.HotkeyUninstall} ".StartsWith(search) || search.StartsWith($"{Settings.HotkeyUninstall} ")))
return pluginManager.RequestUninstall(search);


if (!string.IsNullOrEmpty(search)
&& ($"{Settings.HotkeyUpdate} ".StartsWith(search) || search.StartsWith($"{Settings.HotkeyUpdate} ")))
return pluginManager.RequestUpdate(search);

return pluginManager.RequestInstallOrUpdate(search);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;


namespace Flow.Launcher.Plugin.PluginsManager.Models
{
public class UserPlugin
Expand Down
216 changes: 160 additions & 56 deletions Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ internal class PluginsManager

private Settings Settings { get; set; }

private bool shouldHideWindow = true;
private bool ShouldHideWindow
{
set { shouldHideWindow = value; }
get
{
var setValue = shouldHideWindow;
// Default value for hide main window is true. Revert after get call.
// This ensures when set by another method to false, it is only used once.
shouldHideWindow = true;

return setValue;
}
}

private readonly string icoPath = "Images\\pluginsmanager.png";

internal PluginsManager(PluginInitContext context, Settings settings)
Expand All @@ -31,7 +46,22 @@ internal void InstallOrUpdate(UserPlugin plugin)
{
if (PluginExists(plugin.ID))
{
Context.API.ShowMsg("Plugin already installed");
if (Context.API.GetAllPlugins().Any(x => x.Metadata.ID == plugin.ID && x.Metadata.Version != plugin.Version))
{
if (MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_update_exists"),
Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
Context
.API
.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {Settings.HotkeyUpdate} {plugin.Name}");

Application.Current.MainWindow.Show();
shouldHideWindow = false;

return;
}

Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_alreadyexists"));
return;
}

Expand All @@ -42,7 +72,7 @@ internal void InstallOrUpdate(UserPlugin plugin)
if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_install_title"), MessageBoxButton.YesNo) == MessageBoxResult.No)
return;

var filePath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}{plugin.ID}.zip");
var filePath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}-{plugin.Version}.zip");

try
{
Expand All @@ -62,29 +92,92 @@ internal void InstallOrUpdate(UserPlugin plugin)
Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "PluginDownload");
}

Application.Current.Dispatcher.Invoke(() => Install(plugin, filePath));
Application.Current.Dispatcher.Invoke(() => { Install(plugin, filePath); Context.API.RestartApp(); });
}

internal void Update()
internal List<Result> RequestUpdate(string search)
{
throw new NotImplementedException();
var autocompletedResults = AutoCompleteReturnAllResults(search,
Settings.HotkeyUpdate,
"Update",
"Select a plugin to update");

if (autocompletedResults.Any())
return autocompletedResults;

var uninstallSearch = search.Replace(Settings.HotkeyUpdate, string.Empty).TrimStart();


var resultsForUpdate =
from existingPlugin in Context.API.GetAllPlugins()
join pluginFromManifest in pluginsManifest.UserPlugins
on existingPlugin.Metadata.ID equals pluginFromManifest.ID
where existingPlugin.Metadata.Version != pluginFromManifest.Version
select
new
{
pluginFromManifest.Name,
pluginFromManifest.Author,
CurrentVersion = existingPlugin.Metadata.Version,
NewVersion = pluginFromManifest.Version,
existingPlugin.Metadata.IcoPath,
PluginExistingMetadata = existingPlugin.Metadata,
PluginNewUserPlugin = pluginFromManifest
};

if (!resultsForUpdate.Any())
return new List<Result> {
new Result
{
Title = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_title"),
SubTitle = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_subtitle"),
IcoPath = icoPath
}};


var results = resultsForUpdate
.Select(x =>
new Result
{
Title = $"{x.Name} by {x.Author}",
SubTitle = $"Update from version {x.CurrentVersion} to {x.NewVersion}",
IcoPath = x.IcoPath,
Action = e =>
{
string message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_update_prompt"),
x.Name, x.Author,
Environment.NewLine, Environment.NewLine);

if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_update_title"),
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
Uninstall(x.PluginExistingMetadata);

var downloadToFilePath = Path.Combine(DataLocation.PluginsDirectory, $"{x.Name}-{x.NewVersion}.zip");
Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath);
Install(x.PluginNewUserPlugin, downloadToFilePath);

Context.API.RestartApp();

return true;
}

return false;
}
});

return Search(results, uninstallSearch);
}

internal bool PluginExists(string id)
{
return Context.API.GetAllPlugins().Any(x => x.Metadata.ID == id);
}

internal void PluginsManifestSiteOpen()
{
//Open from context menu https://git.vcmq.workers.dev/Flow-Launcher/Flow.Launcher.PluginsManifest
throw new NotImplementedException();
}

internal List<Result> Search(List<Result> results, string searchName)
internal List<Result> Search(IEnumerable<Result> results, string searchName)
{
if (string.IsNullOrEmpty(searchName))
return results;
return results.ToList();

return results
.Where(x =>
Expand Down Expand Up @@ -114,11 +207,10 @@ internal List<Result> RequestInstallOrUpdate(string searchName)
Application.Current.MainWindow.Hide();
InstallOrUpdate(x);

return true;
return ShouldHideWindow;
},
ContextData = x
})
.ToList();
});

return Search(results, searchName);
}
Expand Down Expand Up @@ -154,42 +246,24 @@ private void Install(UserPlugin plugin, string downloadedFilePath)
return;
}

string newPluginPath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}{plugin.ID}");
string newPluginPath = Path.Combine(DataLocation.PluginsDirectory, $"{plugin.Name}-{plugin.Version}");

Directory.Move(pluginFolderPath, newPluginPath);

Context.API.RestartApp();
}

internal List<Result> RequestUninstall(string search)
{
if (!string.IsNullOrEmpty(search)
&& Settings.UninstallHotkey.StartsWith(search)
&& (Settings.UninstallHotkey != search || !search.StartsWith(Settings.UninstallHotkey)))
{
return
new List<Result>
{
new Result
{
Title = "Uninstall",
IcoPath = icoPath,
SubTitle = "Select a plugin to uninstall",
Action = e =>
{
Context
.API
.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {Settings.UninstallHotkey} ");
var autocompletedResults = AutoCompleteReturnAllResults(search,
Settings.HotkeyUninstall,
"Uninstall",
"Select a plugin to uninstall");

return false;
}
}
};
}
if (autocompletedResults.Any())
return autocompletedResults;

var uninstallSearch = search.Replace(Settings.UninstallHotkey, string.Empty).TrimStart();
var uninstallSearch = search.Replace(Settings.HotkeyUninstall, string.Empty).TrimStart();

var results= Context.API
var results = Context.API
.GetAllPlugins()
.Select(x =>
new Result
Expand All @@ -199,30 +273,60 @@ internal List<Result> RequestUninstall(string search)
IcoPath = x.Metadata.IcoPath,
Action = e =>
{
Application.Current.MainWindow.Hide();
Uninstall(x.Metadata);
string message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_prompt"),
x.Metadata.Name, x.Metadata.Author,
Environment.NewLine, Environment.NewLine);

return true;
if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_uninstall_title"),
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
Application.Current.MainWindow.Hide();
Uninstall(x.Metadata);
Context.API.RestartApp();

return true;
}

return false;
}
})
.ToList();
});

return Search(results, uninstallSearch);
}

private void Uninstall(PluginMetadata plugin)
{
string message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_prompt"),
plugin.Name, plugin.Author,
Environment.NewLine, Environment.NewLine);
// Marked for deletion. Will be deleted on next start up
using var _ = File.CreateText(Path.Combine(plugin.PluginDirectory, "NeedDelete.txt"));
}

if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_uninstall_title"),
MessageBoxButton.YesNo) == MessageBoxResult.Yes)
private List<Result> AutoCompleteReturnAllResults(string search, string hotkey, string title, string subtitle)
{
if (!string.IsNullOrEmpty(search)
&& hotkey.StartsWith(search)
&& (hotkey != search || !search.StartsWith(hotkey)))
{
using var _ = File.CreateText(Path.Combine(plugin.PluginDirectory, "NeedDelete.txt"));

Context.API.RestartApp();
return
new List<Result>
{
new Result
{
Title = title,
IcoPath = icoPath,
SubTitle = subtitle,
Action = e =>
{
Context
.API
.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {hotkey} ");

return false;
}
}
};
}

return new List<Result>();
}
}
}
4 changes: 3 additions & 1 deletion Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ namespace Flow.Launcher.Plugin.PluginsManager
{
internal class Settings
{
internal string UninstallHotkey { get; set; } = "uninstall";
internal string HotkeyUninstall { get; set; } = "uninstall";

internal string HotkeyUpdate { get; set; } = "update";
}
}
2 changes: 1 addition & 1 deletion Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"Name": "Plugins Manager",
"Description": "Management of installing, uninstalling or updating Flow Launcher plugins",
"Author": "Jeremy Wu",
"Version": "1.2.0",
"Version": "1.3.0",
"Language": "csharp",
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
"ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll",
Expand Down