From 33fb0ddee668651ef441c557d7354ab0620041b1 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 11 Jan 2022 06:00:14 +0200 Subject: [PATCH 01/12] refactor PluginsManifest to use conditional requests --- .../ExternalPlugins/PluginsManifest.cs | 49 ++++++++++--------- .../Main.cs | 19 ------- .../PluginsManager.cs | 12 ++--- 3 files changed, 29 insertions(+), 51 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index a9585f6a4f9..dc1c0cc21a2 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -1,7 +1,8 @@ -using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; using System; using System.Collections.Generic; +using System.Net; +using System.Net.Http; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -10,43 +11,45 @@ namespace Flow.Launcher.Core.ExternalPlugins { public static class PluginsManifest { - static PluginsManifest() - { - UpdateTask = UpdateManifestAsync(); - } - - public static List UserPlugins { get; private set; } = new List(); + private const string manifestFileUrl = "https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/plugin_api_v2/plugins.json"; - public static Task UpdateTask { get; private set; } + private static HttpClient httpClient = new HttpClient(); private static readonly SemaphoreSlim manifestUpdateLock = new(1); - public static Task UpdateManifestAsync() - { - if (manifestUpdateLock.CurrentCount == 0) - { - return UpdateTask; - } + private static string latestEtag = ""; - return UpdateTask = DownloadManifestAsync(); - } + public static List UserPlugins { get; private set; } = new List(); - private static async Task DownloadManifestAsync() + public static async Task UpdateManifestAsync() { try { await manifestUpdateLock.WaitAsync().ConfigureAwait(false); - await using var jsonStream = await Http.GetStreamAsync("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/plugin_api_v2/plugins.json") - .ConfigureAwait(false); + var request = new HttpRequestMessage(HttpMethod.Get, manifestFileUrl); + request.Headers.Add("If-None-Match", latestEtag); + + var response = await httpClient.SendAsync(request).ConfigureAwait(false); + + if (response.StatusCode == HttpStatusCode.OK) + { + Log.Info($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Fetched plugins from manifest repo"); - UserPlugins = await JsonSerializer.DeserializeAsync>(jsonStream).ConfigureAwait(false); + var json = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + + UserPlugins = await JsonSerializer.DeserializeAsync>(json).ConfigureAwait(false); + + latestEtag = response.Headers.ETag.Tag; + } + else if (response.StatusCode != HttpStatusCode.NotModified) + { + Log.Warn($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Http response for manifest file was {response.StatusCode}"); + } } catch (Exception e) { - Log.Exception("|PluginManagement.GetManifest|Encountered error trying to download plugins manifest", e); - - UserPlugins = new List(); + Log.Exception($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Http request failed", e); } finally { diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 8aaae95d65c..3d3f9307e35 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -24,8 +24,6 @@ public class Main : ISettingProvider, IAsyncPlugin, IContextMenu, IPluginI18n, I internal PluginsManager pluginManager; - private DateTime lastUpdateTime = DateTime.MinValue; - public Control CreateSettingPanel() { return new PluginsManagerSettings(viewModel); @@ -38,12 +36,6 @@ public Task InitAsync(PluginInitContext context) viewModel = new SettingsViewModel(context, Settings); contextMenu = new ContextMenu(Context); pluginManager = new PluginsManager(Context, Settings); - _manifestUpdateTask = pluginManager - .UpdateManifestAsync(true) - .ContinueWith(_ => - { - lastUpdateTime = DateTime.Now; - }, TaskContinuationOptions.OnlyOnRanToCompletion); return Task.CompletedTask; } @@ -53,8 +45,6 @@ public List LoadContextMenus(Result selectedResult) return contextMenu.LoadContextMenus(selectedResult); } - private Task _manifestUpdateTask = Task.CompletedTask; - public async Task> QueryAsync(Query query, CancellationToken token) { var search = query.Search; @@ -62,14 +52,6 @@ public async Task> QueryAsync(Query query, CancellationToken token) if (string.IsNullOrWhiteSpace(search)) return pluginManager.GetDefaultHotKeys(); - if ((DateTime.Now - lastUpdateTime).TotalHours > 12 && _manifestUpdateTask.IsCompleted) // 12 hours - { - _manifestUpdateTask = pluginManager.UpdateManifestAsync().ContinueWith(t => - { - lastUpdateTime = DateTime.Now; - }, TaskContinuationOptions.OnlyOnRanToCompletion); - } - return search switch { //search could be url, no need ToLower() when passed in @@ -100,7 +82,6 @@ public string GetTranslatedPluginDescription() public async Task ReloadDataAsync() { await pluginManager.UpdateManifestAsync(); - lastUpdateTime = DateTime.Now; } } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 53e994d3423..aed5f5e2f84 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -59,7 +59,7 @@ internal Task UpdateManifestAsync(bool silent = false) } else { - _downloadManifestTask = PluginsManifest.UpdateTask; + _downloadManifestTask = PluginsManifest.UpdateManifestAsync(); if (!silent) _downloadManifestTask.ContinueWith(_ => Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_failed_title"), @@ -181,10 +181,7 @@ internal async Task InstallOrUpdate(UserPlugin plugin) internal async ValueTask> RequestUpdate(string search, CancellationToken token) { - if (!PluginsManifest.UserPlugins.Any()) - { - await UpdateManifestAsync(); - } + await UpdateManifestAsync(); token.ThrowIfCancellationRequested(); @@ -371,10 +368,7 @@ private bool InstallSourceKnown(string url) internal async ValueTask> RequestInstallOrUpdate(string searchName, CancellationToken token) { - if (!PluginsManifest.UserPlugins.Any()) - { - await UpdateManifestAsync(); - } + await UpdateManifestAsync(); token.ThrowIfCancellationRequested(); From 35e043859ca61c04640d37f5b99e24541d12feb9 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 11 Jan 2022 06:12:10 +0200 Subject: [PATCH 02/12] pass CancellationToken to PluginsManifest.UpdateManifestAsync --- .../ExternalPlugins/PluginsManifest.cs | 12 ++++++------ .../PluginsManager.cs | 12 ++++-------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index dc1c0cc21a2..d3b9c5a8eae 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -1,4 +1,4 @@ -using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Infrastructure.Logger; using System; using System.Collections.Generic; using System.Net; @@ -21,24 +21,24 @@ public static class PluginsManifest public static List UserPlugins { get; private set; } = new List(); - public static async Task UpdateManifestAsync() + public static async Task UpdateManifestAsync(CancellationToken token = default) { try { - await manifestUpdateLock.WaitAsync().ConfigureAwait(false); + await manifestUpdateLock.WaitAsync(token).ConfigureAwait(false); var request = new HttpRequestMessage(HttpMethod.Get, manifestFileUrl); request.Headers.Add("If-None-Match", latestEtag); - var response = await httpClient.SendAsync(request).ConfigureAwait(false); + var response = await httpClient.SendAsync(request, token).ConfigureAwait(false); if (response.StatusCode == HttpStatusCode.OK) { Log.Info($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Fetched plugins from manifest repo"); - var json = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); + var json = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false); - UserPlugins = await JsonSerializer.DeserializeAsync>(json).ConfigureAwait(false); + UserPlugins = await JsonSerializer.DeserializeAsync>(json, cancellationToken: token).ConfigureAwait(false); latestEtag = response.Headers.ETag.Tag; } diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index aed5f5e2f84..17f220b7040 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -51,7 +51,7 @@ internal PluginsManager(PluginInitContext context, Settings settings) private Task _downloadManifestTask = Task.CompletedTask; - internal Task UpdateManifestAsync(bool silent = false) + internal Task UpdateManifestAsync(CancellationToken token = default, bool silent = false) { if (_downloadManifestTask.Status == TaskStatus.Running) { @@ -59,7 +59,7 @@ internal Task UpdateManifestAsync(bool silent = false) } else { - _downloadManifestTask = PluginsManifest.UpdateManifestAsync(); + _downloadManifestTask = PluginsManifest.UpdateManifestAsync(token); if (!silent) _downloadManifestTask.ContinueWith(_ => Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_update_failed_title"), @@ -181,9 +181,7 @@ internal async Task InstallOrUpdate(UserPlugin plugin) internal async ValueTask> RequestUpdate(string search, CancellationToken token) { - await UpdateManifestAsync(); - - token.ThrowIfCancellationRequested(); + await UpdateManifestAsync(token); var autocompletedResults = AutoCompleteReturnAllResults(search, Settings.HotkeyUpdate, @@ -368,9 +366,7 @@ private bool InstallSourceKnown(string url) internal async ValueTask> RequestInstallOrUpdate(string searchName, CancellationToken token) { - await UpdateManifestAsync(); - - token.ThrowIfCancellationRequested(); + await UpdateManifestAsync(token); var searchNameWithoutKeyword = searchName.Replace(Settings.HotKeyInstall, string.Empty, StringComparison.OrdinalIgnoreCase).Trim(); From daedc030083c7e38c5fb2f3a01ae64ab027cff71 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 11 Jan 2022 06:49:56 +0200 Subject: [PATCH 03/12] PluginsManager: fix "new issue" URL for some plugins since the `UrlSourceCode` field is inconsistent in the manifest file --- Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs index a20e5a26731..37f0a126efd 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs @@ -2,7 +2,7 @@ using Flow.Launcher.Infrastructure.UserSettings; using System; using System.Collections.Generic; -using System.Text; +using System.Text.RegularExpressions; namespace Flow.Launcher.Plugin.PluginsManager { @@ -53,8 +53,8 @@ public List LoadContextMenus(Result selectedResult) { // standard UrlSourceCode format in PluginsManifest's plugins.json file: https://github.com/jjw24/Flow.Launcher.Plugin.Putty/tree/master var link = pluginManifestInfo.UrlSourceCode.StartsWith("https://github.com") - ? pluginManifestInfo.UrlSourceCode.Replace("/tree/master", "/issues/new/choose") - : pluginManifestInfo.UrlSourceCode; + ? Regex.Replace(pluginManifestInfo.UrlSourceCode, @"\/tree\/\w+$", "") + "/issues/new/choose" + : pluginManifestInfo.UrlSourceCode; Context.API.OpenUrl(link); return true; From 658ddb2cf6ca1deef968f77b6d5b6e5dc2a556b1 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 11 Jan 2022 08:21:15 +0200 Subject: [PATCH 04/12] PluginsManager: improve query navigation --- .../PluginsManager.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 17f220b7040..b85a80f11aa 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -77,9 +77,10 @@ internal List GetDefaultHotKeys() { Title = Settings.HotKeyInstall, IcoPath = icoPath, + AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotKeyInstall} ", Action = _ => { - Context.API.ChangeQuery("pm install "); + Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotKeyInstall} "); return false; } }, @@ -87,9 +88,10 @@ internal List GetDefaultHotKeys() { Title = Settings.HotkeyUninstall, IcoPath = icoPath, + AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotkeyUninstall} ", Action = _ => { - Context.API.ChangeQuery("pm uninstall "); + Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotkeyUninstall} "); return false; } }, @@ -97,9 +99,10 @@ internal List GetDefaultHotKeys() { Title = Settings.HotkeyUpdate, IcoPath = icoPath, + AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotkeyUpdate} ", Action = _ => { - Context.API.ChangeQuery("pm update "); + Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotkeyUpdate} "); return false; } } From d95010697dea1074b19e6d547379838f9cacec28 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 11 Jan 2022 08:55:59 +0200 Subject: [PATCH 05/12] PluginsManager: simplify passing down of queries --- .../Main.cs | 20 +++--- .../PluginsManager.cs | 66 ++----------------- 2 files changed, 16 insertions(+), 70 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 3d3f9307e35..2cd8a751128 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -47,23 +47,21 @@ public List LoadContextMenus(Result selectedResult) public async Task> QueryAsync(Query query, CancellationToken token) { - var search = query.Search; - - if (string.IsNullOrWhiteSpace(search)) + if (string.IsNullOrWhiteSpace(query.Search)) return pluginManager.GetDefaultHotKeys(); - return search switch + return query.FirstSearch switch { //search could be url, no need ToLower() when passed in - var s when s.StartsWith(Settings.HotKeyInstall, StringComparison.OrdinalIgnoreCase) - => await pluginManager.RequestInstallOrUpdate(search, token), - var s when s.StartsWith(Settings.HotkeyUninstall, StringComparison.OrdinalIgnoreCase) - => pluginManager.RequestUninstall(search), - var s when s.StartsWith(Settings.HotkeyUpdate, StringComparison.OrdinalIgnoreCase) - => await pluginManager.RequestUpdate(search, token), + var s when s.Equals(Settings.HotKeyInstall, StringComparison.OrdinalIgnoreCase) + => await pluginManager.RequestInstallOrUpdate(query.SecondToEndSearch, token), + var s when s.Equals(Settings.HotkeyUninstall, StringComparison.OrdinalIgnoreCase) + => pluginManager.RequestUninstall(query.SecondToEndSearch), + var s when s.Equals(Settings.HotkeyUpdate, StringComparison.OrdinalIgnoreCase) + => await pluginManager.RequestUpdate(query.SecondToEndSearch, token), _ => pluginManager.GetDefaultHotKeys().Where(hotkey => { - hotkey.Score = StringMatcher.FuzzySearch(search, hotkey.Title).Score; + hotkey.Score = StringMatcher.FuzzySearch(query.Search, hotkey.Title).Score; return hotkey.Score > 0; }).ToList() }; diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index b85a80f11aa..1395325d90f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -186,16 +186,6 @@ internal async ValueTask> RequestUpdate(string search, Cancellation { await UpdateManifestAsync(token); - 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, StringComparison.OrdinalIgnoreCase).TrimStart(); - var resultsForUpdate = from existingPlugin in Context.API.GetAllPlugins() join pluginFromManifest in PluginsManifest.UserPlugins @@ -283,7 +273,7 @@ await Http.DownloadAsync(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath) } }); - return Search(results, uninstallSearch); + return Search(results, search); } internal bool PluginExists(string id) @@ -367,15 +357,13 @@ private bool InstallSourceKnown(string url) return url.StartsWith(acceptedSource) && Context.API.GetAllPlugins().Any(x => x.Metadata.Website.StartsWith(contructedUrlPart)); } - internal async ValueTask> RequestInstallOrUpdate(string searchName, CancellationToken token) + internal async ValueTask> RequestInstallOrUpdate(string search, CancellationToken token) { await UpdateManifestAsync(token); - var searchNameWithoutKeyword = searchName.Replace(Settings.HotKeyInstall, string.Empty, StringComparison.OrdinalIgnoreCase).Trim(); - - if (Uri.IsWellFormedUriString(searchNameWithoutKeyword, UriKind.Absolute) - && searchNameWithoutKeyword.Split('.').Last() == zip) - return InstallFromWeb(searchNameWithoutKeyword); + if (Uri.IsWellFormedUriString(search, UriKind.Absolute) + && search.Split('.').Last() == zip) + return InstallFromWeb(search); var results = PluginsManifest @@ -401,7 +389,7 @@ internal async ValueTask> RequestInstallOrUpdate(string searchName, ContextData = x }); - return Search(results, searchNameWithoutKeyword); + return Search(results, search); } private void Install(UserPlugin plugin, string downloadedFilePath) @@ -461,16 +449,6 @@ private void Install(UserPlugin plugin, string downloadedFilePath) internal List RequestUninstall(string search) { - var autocompletedResults = AutoCompleteReturnAllResults(search, - Settings.HotkeyUninstall, - "Uninstall", - "Select a plugin to uninstall"); - - if (autocompletedResults.Any()) - return autocompletedResults; - - var uninstallSearch = search.Replace(Settings.HotkeyUninstall, string.Empty, StringComparison.OrdinalIgnoreCase).TrimStart(); - var results = Context.API .GetAllPlugins() .Select(x => @@ -501,7 +479,7 @@ internal List RequestUninstall(string search) } }); - return Search(results, uninstallSearch); + return Search(results, search); } private void Uninstall(PluginMetadata plugin, bool removedSetting = true) @@ -516,36 +494,6 @@ private void Uninstall(PluginMetadata plugin, bool removedSetting = true) using var _ = File.CreateText(Path.Combine(plugin.PluginDirectory, "NeedDelete.txt")); } - private List AutoCompleteReturnAllResults(string search, string hotkey, string title, string subtitle) - { - if (!string.IsNullOrEmpty(search) - && hotkey.StartsWith(search) - && (hotkey != search || !search.StartsWith(hotkey))) - { - return - new List - { - new Result - { - Title = title, - IcoPath = icoPath, - SubTitle = subtitle, - Action = e => - { - Context - .API - .ChangeQuery( - $"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {hotkey} "); - - return false; - } - } - }; - } - - return new List(); - } - private bool SameOrLesserPluginVersionExists(string metadataPath) { var newMetadata = JsonSerializer.Deserialize(File.ReadAllText(metadataPath)); From 4d0c57f52fb0096fe1213db7083d3277c088966f Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 11 Jan 2022 15:14:11 +0200 Subject: [PATCH 06/12] pull plugin manifest file from jsdelivr CDN --- Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index d3b9c5a8eae..fb5e3ad8780 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -1,4 +1,4 @@ -using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Infrastructure.Logger; using System; using System.Collections.Generic; using System.Net; @@ -11,7 +11,7 @@ namespace Flow.Launcher.Core.ExternalPlugins { public static class PluginsManifest { - private const string manifestFileUrl = "https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/plugin_api_v2/plugins.json"; + private const string manifestFileUrl = "https://cdn.jsdelivr.net/gh/Flow-Launcher/Flow.Launcher.PluginsManifest@plugin_api_v2/plugins.json"; private static HttpClient httpClient = new HttpClient(); From a5b8b0dcb236ab0392e312bba05c02faaed976e5 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 11 Jan 2022 16:07:25 +0200 Subject: [PATCH 07/12] add Http.SendAsync, refactor PluginsManifest to use it --- Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs | 5 ++--- Flow.Launcher.Infrastructure/Http/Http.cs | 8 ++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index fb5e3ad8780..fab1b3e8f00 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -1,3 +1,4 @@ +using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; using System; using System.Collections.Generic; @@ -13,8 +14,6 @@ public static class PluginsManifest { private const string manifestFileUrl = "https://cdn.jsdelivr.net/gh/Flow-Launcher/Flow.Launcher.PluginsManifest@plugin_api_v2/plugins.json"; - private static HttpClient httpClient = new HttpClient(); - private static readonly SemaphoreSlim manifestUpdateLock = new(1); private static string latestEtag = ""; @@ -30,7 +29,7 @@ public static async Task UpdateManifestAsync(CancellationToken token = default) var request = new HttpRequestMessage(HttpMethod.Get, manifestFileUrl); request.Headers.Add("If-None-Match", latestEtag); - var response = await httpClient.SendAsync(request, token).ConfigureAwait(false); + var response = await Http.SendAsync(request, token).ConfigureAwait(false); if (response.StatusCode == HttpStatusCode.OK) { diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index b45b6adcde1..c4c8eb5b18f 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -153,5 +153,13 @@ public static async Task GetStreamAsync([NotNull] string url, Cancellati var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); return await response.Content.ReadAsStreamAsync(); } + + /// + /// Asynchrously send an HTTP request. + /// + public static async Task SendAsync(HttpRequestMessage request, CancellationToken token = default) + { + return await client.SendAsync(request, token); + } } } From bc5a9710b3c4462cab83069bbd394ab9d6816c7e Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Wed, 12 Jan 2022 19:22:55 +0200 Subject: [PATCH 08/12] PluginsManager: fetch plugins on init --- Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 2cd8a751128..d0b4b005e6b 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -29,7 +29,7 @@ public Control CreateSettingPanel() return new PluginsManagerSettings(viewModel); } - public Task InitAsync(PluginInitContext context) + public async Task InitAsync(PluginInitContext context) { Context = context; Settings = context.API.LoadSettingJsonStorage(); @@ -37,7 +37,7 @@ public Task InitAsync(PluginInitContext context) contextMenu = new ContextMenu(Context); pluginManager = new PluginsManager(Context, Settings); - return Task.CompletedTask; + await pluginManager.UpdateManifestAsync(); } public List LoadContextMenus(Result selectedResult) From d6bca894ffa2250a87f796c554592503c2d499d1 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Wed, 12 Jan 2022 19:25:42 +0200 Subject: [PATCH 09/12] PluginsManager: remove IAsyncReloadable no point for it, anymore --- Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index d0b4b005e6b..00bda879d56 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -12,7 +12,7 @@ namespace Flow.Launcher.Plugin.PluginsManager { - public class Main : ISettingProvider, IAsyncPlugin, IContextMenu, IPluginI18n, IAsyncReloadable + public class Main : ISettingProvider, IAsyncPlugin, IContextMenu, IPluginI18n { internal PluginInitContext Context { get; set; } @@ -76,10 +76,5 @@ public string GetTranslatedPluginDescription() { return Context.API.GetTranslation("plugin_pluginsmanager_plugin_description"); } - - public async Task ReloadDataAsync() - { - await pluginManager.UpdateManifestAsync(); - } } } \ No newline at end of file From a0bb99564387ca06ed960e78fdb36c780d1d81ce Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Wed, 12 Jan 2022 23:48:16 +0200 Subject: [PATCH 10/12] PluginsManager: refactor sub-commands Rename them to something more accurate, switch them to be const --- .../Main.cs | 11 ++++------ .../PluginsManager.cs | 20 +++++++++---------- .../Settings.cs | 6 +++--- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 00bda879d56..57c8574039f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -50,15 +50,12 @@ public async Task> QueryAsync(Query query, CancellationToken token) if (string.IsNullOrWhiteSpace(query.Search)) return pluginManager.GetDefaultHotKeys(); - return query.FirstSearch switch + return query.FirstSearch.ToLower() switch { //search could be url, no need ToLower() when passed in - var s when s.Equals(Settings.HotKeyInstall, StringComparison.OrdinalIgnoreCase) - => await pluginManager.RequestInstallOrUpdate(query.SecondToEndSearch, token), - var s when s.Equals(Settings.HotkeyUninstall, StringComparison.OrdinalIgnoreCase) - => pluginManager.RequestUninstall(query.SecondToEndSearch), - var s when s.Equals(Settings.HotkeyUpdate, StringComparison.OrdinalIgnoreCase) - => await pluginManager.RequestUpdate(query.SecondToEndSearch, token), + Settings.InstallCommand => await pluginManager.RequestInstallOrUpdate(query.SecondToEndSearch, token), + Settings.UninstallCommand => pluginManager.RequestUninstall(query.SecondToEndSearch), + Settings.UpdateCommand => await pluginManager.RequestUpdate(query.SecondToEndSearch, token), _ => pluginManager.GetDefaultHotKeys().Where(hotkey => { hotkey.Score = StringMatcher.FuzzySearch(query.Search, hotkey.Title).Score; diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 1395325d90f..bbf155e23c8 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -75,34 +75,34 @@ internal List GetDefaultHotKeys() { new Result() { - Title = Settings.HotKeyInstall, + Title = Settings.InstallCommand, IcoPath = icoPath, - AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotKeyInstall} ", + AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.InstallCommand} ", Action = _ => { - Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotKeyInstall} "); + Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.InstallCommand} "); return false; } }, new Result() { - Title = Settings.HotkeyUninstall, + Title = Settings.UninstallCommand, IcoPath = icoPath, - AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotkeyUninstall} ", + AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UninstallCommand} ", Action = _ => { - Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotkeyUninstall} "); + Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UninstallCommand} "); return false; } }, new Result() { - Title = Settings.HotkeyUpdate, + Title = Settings.UpdateCommand, IcoPath = icoPath, - AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotkeyUpdate} ", + AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UpdateCommand} ", Action = _ => { - Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.HotkeyUpdate} "); + Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeyword} {Settings.UpdateCommand} "); return false; } } @@ -122,7 +122,7 @@ internal async Task InstallOrUpdate(UserPlugin plugin) Context .API .ChangeQuery( - $"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {Settings.HotkeyUpdate} {plugin.Name}"); + $"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {Settings.UpdateCommand} {plugin.Name}"); var mainWindow = Application.Current.MainWindow; mainWindow.Show(); diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs index a951010c0b1..6fd4e51acfd 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs @@ -6,11 +6,11 @@ namespace Flow.Launcher.Plugin.PluginsManager { internal class Settings { - internal string HotKeyInstall { get; set; } = "install"; + internal const string InstallCommand = "install"; - internal string HotkeyUninstall { get; set; } = "uninstall"; + internal const string UninstallCommand = "uninstall"; - internal string HotkeyUpdate { get; set; } = "update"; + internal const string UpdateCommand = "update"; public bool WarnFromUnknownSource { get; set; } = true; } From 835b925342d7e3217c638ebcccd128b1cfbca995 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Thu, 13 Jan 2022 00:36:14 +0200 Subject: [PATCH 11/12] set HttpCompletionOption in Http.SendAsync --- Flow.Launcher.Infrastructure/Http/Http.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index c4c8eb5b18f..9f4146b7be3 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -159,7 +159,7 @@ public static async Task GetStreamAsync([NotNull] string url, Cancellati /// public static async Task SendAsync(HttpRequestMessage request, CancellationToken token = default) { - return await client.SendAsync(request, token); + return await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token); } } } From deb4bee786e57340a1f7c6cbab1e16df43fee886 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 14 Jan 2022 07:58:46 +1100 Subject: [PATCH 12/12] version bump PluginsManager --- Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json index 0900ddb6ca1..c8d5bd8a331 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json @@ -6,7 +6,7 @@ "Name": "Plugins Manager", "Description": "Management of installing, uninstalling or updating Flow Launcher plugins", "Author": "Jeremy Wu", - "Version": "1.11.2", + "Version": "1.12.0", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll",