From 4ea5dd5ad2ad6d4869d57c8aed1e187d81662135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 13 Oct 2020 20:54:00 +0800 Subject: [PATCH 01/95] Move Old HttpWebRequest to HttpClient Instance (solve connection timeout) --- Flow.Launcher.Core/Updater.cs | 2 +- Flow.Launcher.Infrastructure/Http/Http.cs | 77 ++++++++++++++--------- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 99d48275a..4ad8b19be 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -139,7 +139,7 @@ namespace Flow.Launcher.Core var latest = releases.Where(r => !r.Prerelease).OrderByDescending(r => r.PublishedAt).First(); var latestUrl = latest.HtmlUrl.Replace("/tag/", "/download/"); - var client = new WebClient { Proxy = Http.WebProxy() }; + var client = new WebClient { Proxy = Http.WebProxy }; var downloader = new FileDownloader(client); var manager = new UpdateManager(latestUrl, urlDownloader: downloader); diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index b7d274205..038362a0d 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -13,6 +13,13 @@ namespace Flow.Launcher.Infrastructure.Http { private const string UserAgent = @"Mozilla/5.0 (Trident/7.0; rv:11.0) like Gecko"; + private static HttpClient client; + private static SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler() + { + UseProxy = true, + Proxy = WebProxy + }; + static Http() { // need to be added so it would work on a win10 machine @@ -20,36 +27,55 @@ namespace Flow.Launcher.Infrastructure.Http ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; + + client.DefaultRequestHeaders.Add("User-Agent", UserAgent); + + } + private static HttpProxy proxy; + public static HttpProxy Proxy + { + private get + { + return proxy; + } + set + { + proxy = value; + UpdateProxy(); + } } - public static HttpProxy Proxy { private get; set; } - public static IWebProxy WebProxy() + public static WebProxy WebProxy { get; private set; } + + /// + /// Update the Address of the Proxy to modify the client Proxy + /// + public static void UpdateProxy() + // TODO: need test with a proxy { if (Proxy != null && Proxy.Enabled && !string.IsNullOrEmpty(Proxy.Server)) { if (string.IsNullOrEmpty(Proxy.UserName) || string.IsNullOrEmpty(Proxy.Password)) { - var webProxy = new WebProxy(Proxy.Server, Proxy.Port); - return webProxy; + WebProxy.Address = new Uri($"http://{Proxy.Server}:{Proxy.Port}"); + WebProxy.Credentials = null; } else { - var webProxy = new WebProxy(Proxy.Server, Proxy.Port) - { - Credentials = new NetworkCredential(Proxy.UserName, Proxy.Password) - }; - return webProxy; + WebProxy.Address = new Uri($"http://{Proxy.Server}:{Proxy.Port}"); + WebProxy.Credentials = new NetworkCredential(Proxy.UserName, Proxy.Password); } } else { - return WebRequest.GetSystemWebProxy(); + WebProxy.Address = new WebProxy().Address; + WebProxy.Credentials = null; } } public static void Download([NotNull] string url, [NotNull] string filePath) { - var client = new WebClient { Proxy = WebProxy() }; + var client = new WebClient { Proxy = WebProxy }; client.Headers.Add("user-agent", UserAgent); client.DownloadFile(url, filePath); } @@ -57,26 +83,17 @@ namespace Flow.Launcher.Infrastructure.Http public static async Task Get([NotNull] string url, string encoding = "UTF-8") { Log.Debug($"|Http.Get|Url <{url}>"); - var request = WebRequest.CreateHttp(url); - request.Method = "GET"; - request.Timeout = 1000; - request.Proxy = WebProxy(); - request.UserAgent = UserAgent; - var response = await request.GetResponseAsync() as HttpWebResponse; - response = response.NonNull(); - var stream = response.GetResponseStream().NonNull(); - - using (var reader = new StreamReader(stream, Encoding.GetEncoding(encoding))) + var response = await client.GetAsync(url); + using var stream = await response.Content.ReadAsStreamAsync(); + using var reader = new StreamReader(stream, Encoding.GetEncoding(encoding)); + var content = await reader.ReadToEndAsync(); + if (response.StatusCode == HttpStatusCode.OK) { - var content = await reader.ReadToEndAsync(); - if (response.StatusCode == HttpStatusCode.OK) - { - return content; - } - else - { - throw new HttpRequestException($"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); - } + return content; + } + else + { + throw new HttpRequestException($"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); } } } From a16cc5be8db3b5d52acf12565b029439c8d1a921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 13 Oct 2020 20:54:00 +0800 Subject: [PATCH 02/95] Move Old HttpWebRequest to HttpClient Instance (solve connection timeout) --- Flow.Launcher.Core/Updater.cs | 2 +- Flow.Launcher.Infrastructure/Http/Http.cs | 78 ++++++++++++++--------- 2 files changed, 49 insertions(+), 31 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 99d48275a..4ad8b19be 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -139,7 +139,7 @@ namespace Flow.Launcher.Core var latest = releases.Where(r => !r.Prerelease).OrderByDescending(r => r.PublishedAt).First(); var latestUrl = latest.HtmlUrl.Replace("/tag/", "/download/"); - var client = new WebClient { Proxy = Http.WebProxy() }; + var client = new WebClient { Proxy = Http.WebProxy }; var downloader = new FileDownloader(client); var manager = new UpdateManager(latestUrl, urlDownloader: downloader); diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index b7d274205..81c07eff7 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using JetBrains.Annotations; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; +using System; namespace Flow.Launcher.Infrastructure.Http { @@ -13,6 +14,13 @@ namespace Flow.Launcher.Infrastructure.Http { private const string UserAgent = @"Mozilla/5.0 (Trident/7.0; rv:11.0) like Gecko"; + private static HttpClient client; + private static SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler() + { + UseProxy = true, + Proxy = WebProxy + }; + static Http() { // need to be added so it would work on a win10 machine @@ -20,36 +28,55 @@ namespace Flow.Launcher.Infrastructure.Http ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; + + client.DefaultRequestHeaders.Add("User-Agent", UserAgent); + + } + private static HttpProxy proxy; + public static HttpProxy Proxy + { + private get + { + return proxy; + } + set + { + proxy = value; + UpdateProxy(); + } } - public static HttpProxy Proxy { private get; set; } - public static IWebProxy WebProxy() + public static WebProxy WebProxy { get; private set; } + + /// + /// Update the Address of the Proxy to modify the client Proxy + /// + public static void UpdateProxy() + // TODO: need test with a proxy { if (Proxy != null && Proxy.Enabled && !string.IsNullOrEmpty(Proxy.Server)) { if (string.IsNullOrEmpty(Proxy.UserName) || string.IsNullOrEmpty(Proxy.Password)) { - var webProxy = new WebProxy(Proxy.Server, Proxy.Port); - return webProxy; + WebProxy.Address = new Uri($"http://{Proxy.Server}:{Proxy.Port}"); + WebProxy.Credentials = null; } else { - var webProxy = new WebProxy(Proxy.Server, Proxy.Port) - { - Credentials = new NetworkCredential(Proxy.UserName, Proxy.Password) - }; - return webProxy; + WebProxy.Address = new Uri($"http://{Proxy.Server}:{Proxy.Port}"); + WebProxy.Credentials = new NetworkCredential(Proxy.UserName, Proxy.Password); } } else { - return WebRequest.GetSystemWebProxy(); + WebProxy.Address = new WebProxy().Address; + WebProxy.Credentials = null; } } public static void Download([NotNull] string url, [NotNull] string filePath) { - var client = new WebClient { Proxy = WebProxy() }; + var client = new WebClient { Proxy = WebProxy }; client.Headers.Add("user-agent", UserAgent); client.DownloadFile(url, filePath); } @@ -57,26 +84,17 @@ namespace Flow.Launcher.Infrastructure.Http public static async Task Get([NotNull] string url, string encoding = "UTF-8") { Log.Debug($"|Http.Get|Url <{url}>"); - var request = WebRequest.CreateHttp(url); - request.Method = "GET"; - request.Timeout = 1000; - request.Proxy = WebProxy(); - request.UserAgent = UserAgent; - var response = await request.GetResponseAsync() as HttpWebResponse; - response = response.NonNull(); - var stream = response.GetResponseStream().NonNull(); - - using (var reader = new StreamReader(stream, Encoding.GetEncoding(encoding))) + var response = await client.GetAsync(url); + using var stream = await response.Content.ReadAsStreamAsync(); + using var reader = new StreamReader(stream, Encoding.GetEncoding(encoding)); + var content = await reader.ReadToEndAsync(); + if (response.StatusCode == HttpStatusCode.OK) { - var content = await reader.ReadToEndAsync(); - if (response.StatusCode == HttpStatusCode.OK) - { - return content; - } - else - { - throw new HttpRequestException($"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); - } + return content; + } + else + { + throw new HttpRequestException($"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); } } } From c55e889f4fb37aa2624eec4523cbcd94cadc3293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 14 Oct 2020 11:29:12 +0800 Subject: [PATCH 03/95] Change Download to HttpClient as well (which change it to async as well) --- Flow.Launcher.Infrastructure/Http/Http.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 81c07eff7..34665217c 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -29,6 +29,7 @@ namespace Flow.Launcher.Infrastructure.Http | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; + client = new HttpClient(socketsHttpHandler, false); client.DefaultRequestHeaders.Add("User-Agent", UserAgent); } @@ -46,7 +47,7 @@ namespace Flow.Launcher.Infrastructure.Http } } - public static WebProxy WebProxy { get; private set; } + public static WebProxy WebProxy { get; private set; } = new WebProxy(); /// /// Update the Address of the Proxy to modify the client Proxy @@ -74,11 +75,18 @@ namespace Flow.Launcher.Infrastructure.Http } } - public static void Download([NotNull] string url, [NotNull] string filePath) + public async static Task Download([NotNull] string url, [NotNull] string filePath) { - var client = new WebClient { Proxy = WebProxy }; - client.Headers.Add("user-agent", UserAgent); - client.DownloadFile(url, filePath); + using var response = await client.GetAsync(url); + if (response.StatusCode == HttpStatusCode.OK) + { + using var fileStream = new FileStream(filePath, FileMode.CreateNew); + await response.Content.CopyToAsync(fileStream); + } + else + { + throw new WebException($"Error code <{response.StatusCode}> returned from <{url}>"); + } } public static async Task Get([NotNull] string url, string encoding = "UTF-8") From 424d757add58ccb38b50332b8a7597e8768b84bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 14 Oct 2020 11:29:38 +0800 Subject: [PATCH 04/95] Add Task.Run due to the change of async download --- .../Main.cs | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginManagement/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginManagement/Main.cs index e1b631517..0255216a0 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginManagement/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginManagement/Main.cs @@ -144,7 +144,7 @@ namespace Flow.Launcher.Plugin.PluginManagement IcoPath = "Images\\plugin.png", TitleHighlightData = StringMatcher.FuzzySearch(query.SecondSearch, r.name).MatchData, SubTitleHighlightData = StringMatcher.FuzzySearch(query.SecondSearch, r.description).MatchData, - Action = c => + Action = _ => { MessageBoxResult result = MessageBox.Show("Are you sure you wish to install the \'" + r.name + "\' plugin", "Install plugin", MessageBoxButton.YesNo); @@ -157,17 +157,19 @@ namespace Flow.Launcher.Plugin.PluginManagement string pluginUrl = APIBASE + "/media/" + r1.plugin_file; - try + Task.Run(async () => { - Http.Download(pluginUrl, filePath); - } - catch (WebException e) - { - context.API.ShowMsg($"PluginManagement.ResultForInstallPlugin: download failed for <{r.name}>"); - Log.Exception($"|PluginManagement.ResultForInstallPlugin|download failed for <{r.name}>", e); - return false; - } - context.API.InstallPlugin(filePath); + try + { + await Http.Download(pluginUrl, filePath); + context.API.InstallPlugin(filePath); + } + catch (WebException e) + { + context.API.ShowMsg($"PluginManagement.ResultForInstallPlugin: download failed for <{r.name}>"); + Log.Exception($"|PluginManagement.ResultForInstallPlugin|download failed for <{r.name}>", e); + } + }); } return false; } From cbfa3f354dc5c19cd84d1573853792db0b93cb41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Sun, 20 Dec 2020 17:44:46 +0800 Subject: [PATCH 05/95] Inform user when checking update fail or update fail, and wrap all code in one try catch instead of catch each exception seperately since they are all same kind of exception. Use using instead of manually dispose. --- Flow.Launcher.Core/Updater.cs | 110 ++++++++++++++-------------------- 1 file changed, 45 insertions(+), 65 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 20df23e40..3369526e0 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -29,89 +29,69 @@ namespace Flow.Launcher.Core GitHubRepository = gitHubRepository; } - public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true) + public async Task UpdateApp(IPublicAPI api, bool silentUpdate = true) { - UpdateManager updateManager; - UpdateInfo newUpdateInfo; - - if (!silentUpdate) - api.ShowMsg("Please wait...", "Checking for new update"); - try { - updateManager = await GitHubUpdateManager(GitHubRepository); - } - catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException) - { - Log.Exception($"|Updater.UpdateApp|Please check your connection and proxy settings to api.github.com.", e); - return; - } + UpdateInfo newUpdateInfo; + + if (!silentUpdate) + api.ShowMsg("Please wait...", "Checking for new update"); + + using var updateManager = await GitHubUpdateManager(GitHubRepository); + - try - { // UpdateApp CheckForUpdate will return value only if the app is squirrel installed newUpdateInfo = await updateManager.CheckForUpdate().NonNull(); - } - catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException) - { - Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to api.github.com.", e); - updateManager.Dispose(); - return; - } - var newReleaseVersion = Version.Parse(newUpdateInfo.FutureReleaseEntry.Version.ToString()); - var currentVersion = Version.Parse(Constant.Version); + var newReleaseVersion = Version.Parse(newUpdateInfo.FutureReleaseEntry.Version.ToString()); + var currentVersion = Version.Parse(Constant.Version); - Log.Info($"|Updater.UpdateApp|Future Release <{newUpdateInfo.FutureReleaseEntry.Formatted()}>"); + Log.Info($"|Updater.UpdateApp|Future Release <{newUpdateInfo.FutureReleaseEntry.Formatted()}>"); + + if (newReleaseVersion <= currentVersion) + { + if (!silentUpdate) + MessageBox.Show("You already have the latest Flow Launcher version"); + updateManager.Dispose(); + return; + } - if (newReleaseVersion <= currentVersion) - { if (!silentUpdate) - MessageBox.Show("You already have the latest Flow Launcher version"); - updateManager.Dispose(); - return; - } + api.ShowMsg("Update found", "Updating..."); - if (!silentUpdate) - api.ShowMsg("Update found", "Updating..."); - - try - { await updateManager.DownloadReleases(newUpdateInfo.ReleasesToApply); + + await updateManager.ApplyReleases(newUpdateInfo); + + if (DataLocation.PortableDataLocationInUse()) + { + var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}"; + FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination); + if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination)) + MessageBox.Show("Flow Launcher was not able to move your user profile data to the new update version. Please manually " + + $"move your profile data folder from {DataLocation.PortableDataPath} to {targetDestination}"); + } + else + { + await updateManager.CreateUninstallerRegistryEntry(); + } + + var newVersionTips = NewVersinoTips(newReleaseVersion.ToString()); + + Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); + + if (MessageBox.Show(newVersionTips, "New Update", MessageBoxButton.YesNo) == MessageBoxResult.Yes) + { + UpdateManager.RestartApp(Constant.ApplicationFileName); + } } catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException) { Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e); - updateManager.Dispose(); + api.ShowMsg("Update Fail!", "Check your connection and proxy settings to github-cloud.s3.amazonaws.com."); return; } - - await updateManager.ApplyReleases(newUpdateInfo); - - if (DataLocation.PortableDataLocationInUse()) - { - var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}"; - FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination); - if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination)) - MessageBox.Show("Flow Launcher was not able to move your user profile data to the new update version. Please manually " + - $"move your profile data folder from {DataLocation.PortableDataPath} to {targetDestination}"); - } - else - { - await updateManager.CreateUninstallerRegistryEntry(); - } - - var newVersionTips = NewVersinoTips(newReleaseVersion.ToString()); - - Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); - - // always dispose UpdateManager - updateManager.Dispose(); - - if (MessageBox.Show(newVersionTips, "New Update", MessageBoxButton.YesNo) == MessageBoxResult.Yes) - { - UpdateManager.RestartApp(Constant.ApplicationFileName); - } } [UsedImplicitly] From adad5ae83bd8e036bcf93e2df174d4dbe7d2380e Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sun, 20 Dec 2020 21:10:55 +1100 Subject: [PATCH 06/95] add url website in Settings --- Flow.Launcher.Infrastructure/Constant.cs | 2 ++ Flow.Launcher/SettingWindow.xaml | 4 ++-- Flow.Launcher/ViewModel/SettingWindowViewModel.cs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Constant.cs b/Flow.Launcher.Infrastructure/Constant.cs index df1464048..3dba35f8d 100644 --- a/Flow.Launcher.Infrastructure/Constant.cs +++ b/Flow.Launcher.Infrastructure/Constant.cs @@ -35,5 +35,7 @@ namespace Flow.Launcher.Infrastructure public const string DefaultTheme = "Darker"; public const string Themes = "Themes"; + + public const string Website = "https://flow-launcher.github.io"; } } diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 32f9e9a6e..e47f0e779 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -429,8 +429,8 @@ - - + + diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index 853925852..96ee5a052 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -450,7 +450,7 @@ namespace Flow.Launcher.ViewModel #region about - public string Github => _updater.GitHubRepository; + public string Website => Constant.Website; public string ReleaseNotes => _updater.GitHubRepository + @"/releases/latest"; public static string Version => Constant.Version; public string ActivatedTimes => string.Format(_translater.GetTranslation("about_activate_times"), Settings.ActivateTimes); From acd631be081c2fd044672c997eeb8998246b773d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?= Date: Mon, 21 Dec 2020 19:09:18 +0800 Subject: [PATCH 07/95] Change wording --- Flow.Launcher.Core/Updater.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 3369526e0..4e211c3ac 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -89,7 +89,7 @@ namespace Flow.Launcher.Core catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException) { Log.Exception($"|Updater.UpdateApp|Check your connection and proxy settings to github-cloud.s3.amazonaws.com.", e); - api.ShowMsg("Update Fail!", "Check your connection and proxy settings to github-cloud.s3.amazonaws.com."); + api.ShowMsg("Update Failed", "Check your connection and try updating proxy settings to github-cloud.s3.amazonaws.com."); return; } } From 85f5766022ec2282dd7cf2595c48785964e3433f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?= Date: Mon, 21 Dec 2020 19:30:18 +0800 Subject: [PATCH 08/95] Optimize a few code --- Flow.Launcher.Infrastructure/Http/Http.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 34665217c..4ec4f887f 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -75,12 +75,12 @@ namespace Flow.Launcher.Infrastructure.Http } } - public async static Task Download([NotNull] string url, [NotNull] string filePath) + public static async Task Download([NotNull] string url, [NotNull] string filePath) { using var response = await client.GetAsync(url); if (response.StatusCode == HttpStatusCode.OK) { - using var fileStream = new FileStream(filePath, FileMode.CreateNew); + await using var fileStream = new FileStream(filePath, FileMode.CreateNew); await response.Content.CopyToAsync(fileStream); } else @@ -93,7 +93,7 @@ namespace Flow.Launcher.Infrastructure.Http { Log.Debug($"|Http.Get|Url <{url}>"); var response = await client.GetAsync(url); - using var stream = await response.Content.ReadAsStreamAsync(); + await using var stream = await response.Content.ReadAsStreamAsync(); using var reader = new StreamReader(stream, Encoding.GetEncoding(encoding)); var content = await reader.ReadToEndAsync(); if (response.StatusCode == HttpStatusCode.OK) From 96609f797e672021664c788f1d0acde1afec40ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?= Date: Mon, 21 Dec 2020 19:42:50 +0800 Subject: [PATCH 09/95] Change the place of Wait in PluginManifest to make code more elegent --- .../Models/PluginsManifest.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs index 290221710..13a5ae2ca 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs @@ -10,21 +10,19 @@ namespace Flow.Launcher.Plugin.PluginsManager.Models internal class PluginsManifest { internal List UserPlugins { get; private set; } + internal PluginsManifest() { - DownloadManifest(); + DownloadManifest().Wait(); } - private void DownloadManifest() + private async Task DownloadManifest() { var json = string.Empty; try { - var t = Task.Run( - async () => - json = await Http.Get("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/main/plugins.json")); - - t.Wait(); + json = await Http.Get( + "https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/main/plugins.json"); UserPlugins = JsonConvert.DeserializeObject>(json); } @@ -34,7 +32,6 @@ namespace Flow.Launcher.Plugin.PluginsManager.Models UserPlugins = new List(); } - } } -} +} \ No newline at end of file From 5ab8c4faa3bc858af489096e3b8f4e9f9e290d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?= Date: Mon, 21 Dec 2020 20:55:28 +0800 Subject: [PATCH 10/95] Update Proxy every time calling a http request method since the proxy setting won't update automatically without action --- Flow.Launcher.Infrastructure/Http/Http.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 4ec4f887f..a88d868a6 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -47,7 +47,14 @@ namespace Flow.Launcher.Infrastructure.Http } } - public static WebProxy WebProxy { get; private set; } = new WebProxy(); + private static WebProxy _proxy = new WebProxy(); + public static WebProxy WebProxy { + get + { + UpdateProxy(); + return _proxy; + } + } /// /// Update the Address of the Proxy to modify the client Proxy @@ -77,6 +84,7 @@ namespace Flow.Launcher.Infrastructure.Http public static async Task Download([NotNull] string url, [NotNull] string filePath) { + UpdateProxy(); using var response = await client.GetAsync(url); if (response.StatusCode == HttpStatusCode.OK) { @@ -91,6 +99,7 @@ namespace Flow.Launcher.Infrastructure.Http public static async Task Get([NotNull] string url, string encoding = "UTF-8") { + UpdateProxy(); Log.Debug($"|Http.Get|Url <{url}>"); var response = await client.GetAsync(url); await using var stream = await response.Content.ReadAsStreamAsync(); From 88fa862277eeff5a49058e72f3ec157ec817aa0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?= Date: Tue, 22 Dec 2020 00:31:00 +0800 Subject: [PATCH 11/95] Use event triggered update method instead of checking Proxy every time doing Http request --- Flow.Launcher.Infrastructure/Http/Http.cs | 64 +++++++-------- .../UserSettings/HttpProxy.cs | 81 +++++++++++++++++-- 2 files changed, 105 insertions(+), 40 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index a88d868a6..8fe910c0c 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -7,6 +7,7 @@ using JetBrains.Annotations; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using System; +using System.ComponentModel; namespace Flow.Launcher.Infrastructure.Http { @@ -15,6 +16,7 @@ namespace Flow.Launcher.Infrastructure.Http private const string UserAgent = @"Mozilla/5.0 (Trident/7.0; rv:11.0) like Gecko"; private static HttpClient client; + private static SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler() { UseProxy = true, @@ -31,60 +33,54 @@ namespace Flow.Launcher.Infrastructure.Http client = new HttpClient(socketsHttpHandler, false); client.DefaultRequestHeaders.Add("User-Agent", UserAgent); - } + private static HttpProxy proxy; + public static HttpProxy Proxy { - private get - { - return proxy; - } + private get { return proxy; } set { proxy = value; - UpdateProxy(); + proxy.PropertyChanged += UpdateProxy; } } - private static WebProxy _proxy = new WebProxy(); - public static WebProxy WebProxy { - get - { - UpdateProxy(); - return _proxy; - } + private static readonly WebProxy _proxy = new WebProxy(); + + public static WebProxy WebProxy + { + get { return _proxy; } } /// /// Update the Address of the Proxy to modify the client Proxy /// - public static void UpdateProxy() - // TODO: need test with a proxy + public static void UpdateProxy(ProxyProperty property) { - if (Proxy != null && Proxy.Enabled && !string.IsNullOrEmpty(Proxy.Server)) + (_proxy.Address, _proxy.Credentials) = property switch { - if (string.IsNullOrEmpty(Proxy.UserName) || string.IsNullOrEmpty(Proxy.Password)) + ProxyProperty.Enabled => (Proxy.Enabled) switch { - WebProxy.Address = new Uri($"http://{Proxy.Server}:{Proxy.Port}"); - WebProxy.Credentials = null; - } - else - { - WebProxy.Address = new Uri($"http://{Proxy.Server}:{Proxy.Port}"); - WebProxy.Credentials = new NetworkCredential(Proxy.UserName, Proxy.Password); - } - } - else - { - WebProxy.Address = new WebProxy().Address; - WebProxy.Credentials = null; - } + true => Proxy.UserName switch + { + var userName when !string.IsNullOrEmpty(userName) => + (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), null), + _ => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), + new NetworkCredential(Proxy.UserName, Proxy.Password)) + }, + false => (null, null) + }, + ProxyProperty.Server => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), _proxy.Credentials), + ProxyProperty.Port => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), _proxy.Credentials), + ProxyProperty.UserName => (_proxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)), + ProxyProperty.Password => (_proxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)) + }; } public static async Task Download([NotNull] string url, [NotNull] string filePath) { - UpdateProxy(); using var response = await client.GetAsync(url); if (response.StatusCode == HttpStatusCode.OK) { @@ -99,7 +95,6 @@ namespace Flow.Launcher.Infrastructure.Http public static async Task Get([NotNull] string url, string encoding = "UTF-8") { - UpdateProxy(); Log.Debug($"|Http.Get|Url <{url}>"); var response = await client.GetAsync(url); await using var stream = await response.Content.ReadAsStreamAsync(); @@ -111,7 +106,8 @@ namespace Flow.Launcher.Infrastructure.Http } else { - throw new HttpRequestException($"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); + throw new HttpRequestException( + $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); } } } diff --git a/Flow.Launcher.Infrastructure/UserSettings/HttpProxy.cs b/Flow.Launcher.Infrastructure/UserSettings/HttpProxy.cs index c1b0c1dd7..213193526 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/HttpProxy.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/HttpProxy.cs @@ -1,11 +1,80 @@ -namespace Flow.Launcher.Infrastructure.UserSettings +using System.ComponentModel; + +namespace Flow.Launcher.Infrastructure.UserSettings { + public enum ProxyProperty + { + Enabled, + Server, + Port, + UserName, + Password + } + public class HttpProxy { - public bool Enabled { get; set; } = false; - public string Server { get; set; } - public int Port { get; set; } - public string UserName { get; set; } - public string Password { get; set; } + private bool _enabled = false; + private string _server; + private int _port; + private string _userName; + private string _password; + + public bool Enabled + { + get => _enabled; + set + { + _enabled = value; + OnPropertyChanged(ProxyProperty.Enabled); + } + } + + public string Server + { + get => _server; + set + { + _server = value; + OnPropertyChanged(ProxyProperty.Server); + } + } + + public int Port + { + get => _port; + set + { + _port = value; + OnPropertyChanged(ProxyProperty.Port); + } + } + + public string UserName + { + get => _userName; + set + { + _userName = value; + OnPropertyChanged(ProxyProperty.UserName); + } + } + + public string Password + { + get => _password; + set + { + _password = value; + OnPropertyChanged(ProxyProperty.Password); + } + } + + public delegate void ProxyPropertyChangedHandler(ProxyProperty property); + public event ProxyPropertyChangedHandler PropertyChanged; + + private void OnPropertyChanged(ProxyProperty property) + { + PropertyChanged?.Invoke(property); + } } } \ No newline at end of file From 93486783e5fdb5f5e14abc1df1b4c5e8adccb1eb Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Wed, 23 Dec 2020 06:28:59 +1100 Subject: [PATCH 12/95] update plugin repo url --- Flow.Launcher/ViewModel/SettingWindowViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index 96ee5a052..c122f8037 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -213,7 +213,7 @@ namespace Flow.Launcher.ViewModel #region plugin - public static string Plugin => "http://www.wox.one/plugin"; + public static string Plugin => @"https://github.com/Flow-Launcher/Flow.Launcher.PluginsManifest"; public PluginViewModel SelectedPlugin { get; set; } public IList PluginViewModels From 34f51927cf5955d49174a45cbb0eee60802b7466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?= Date: Sun, 27 Dec 2020 21:13:25 +0800 Subject: [PATCH 13/95] 1. Move PluginsManager constuction to Init(). 2. Return HotKeys list when query is like "pm *" --- Flow.Launcher.Infrastructure/Http/Http.cs | 2 +- .../Main.cs | 34 ++- .../PluginsManager.cs | 250 ++++++++++-------- .../Settings.cs | 46 +++- 4 files changed, 201 insertions(+), 131 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 1d5f240e1..2d798ec11 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -59,7 +59,7 @@ namespace Flow.Launcher.Infrastructure.Http Log.Debug($"|Http.Get|Url <{url}>"); var request = WebRequest.CreateHttp(url); request.Method = "GET"; - request.Timeout = 1000; + request.Timeout = 6000; request.Proxy = WebProxy(); request.UserAgent = UserAgent; var response = await request.GetResponseAsync() as HttpWebResponse; diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 43f92e7b9..6cf9e1608 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -3,13 +3,15 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.PluginsManager.ViewModels; using Flow.Launcher.Plugin.PluginsManager.Views; using System.Collections.Generic; +using System.Linq; using System.Windows.Controls; +using Flow.Launcher.Infrastructure; namespace Flow.Launcher.Plugin.PluginsManager { public class Main : ISettingProvider, IPlugin, ISavable, IContextMenu, IPluginI18n { - internal PluginInitContext Context { get; set; } + internal static PluginInitContext Context { get; set; } internal Settings Settings; @@ -17,6 +19,8 @@ namespace Flow.Launcher.Plugin.PluginsManager private IContextMenu contextMenu; + internal PluginsManager pluginManager; + public Control CreateSettingPanel() { return new PluginsManagerSettings(viewModel); @@ -28,6 +32,7 @@ namespace Flow.Launcher.Plugin.PluginsManager viewModel = new SettingsViewModel(context); Settings = viewModel.Settings; contextMenu = new ContextMenu(Context, Settings); + pluginManager = new PluginsManager(Context, Settings); } public List LoadContextMenus(Result selectedResult) @@ -38,18 +43,21 @@ namespace Flow.Launcher.Plugin.PluginsManager public List Query(Query query) { var search = query.Search.ToLower(); + + if (string.IsNullOrWhiteSpace(search)) + return Settings.HotKeys; - var pluginManager = new PluginsManager(Context, Settings); - - if (!string.IsNullOrEmpty(search) - && ($"{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); + return search switch + { + var s when s.StartsWith(Settings.HotKeyInstall) => pluginManager.RequestInstallOrUpdate(s), + var s when s.StartsWith(Settings.HotkeyUninstall) => pluginManager.RequestUninstall(s), + var s when s.StartsWith(Settings.HotkeyUpdate) => pluginManager.RequestUpdate(s), + _ => Settings.HotKeys.Where(hotkey => + { + hotkey.Score = StringMatcher.FuzzySearch(search, hotkey.Title).Score; + return hotkey.Score > 0; + }).ToList() + }; } public void Save() @@ -67,4 +75,4 @@ namespace Flow.Launcher.Plugin.PluginsManager return Context.API.GetTranslation("plugin_pluginsmanager_plugin_description"); } } -} +} \ 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 90f3277fb..23d2756ae 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -20,7 +20,8 @@ namespace Flow.Launcher.Plugin.PluginsManager private Settings Settings { get; set; } private bool shouldHideWindow = true; - private bool ShouldHideWindow + + private bool ShouldHideWindow { set { shouldHideWindow = value; } get @@ -42,18 +43,21 @@ namespace Flow.Launcher.Plugin.PluginsManager Context = context; Settings = settings; } + internal void InstallOrUpdate(UserPlugin plugin) { if (PluginExists(plugin.ID)) { - if (Context.API.GetAllPlugins().Any(x => x.Metadata.ID == plugin.ID && x.Metadata.Version != plugin.Version)) + 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}"); + 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; @@ -66,10 +70,11 @@ namespace Flow.Launcher.Plugin.PluginsManager } var message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_prompt"), - plugin.Name, plugin.Author, - Environment.NewLine, Environment.NewLine); + plugin.Name, plugin.Author, + Environment.NewLine, Environment.NewLine); - if (MessageBox.Show(message, Context.API.GetTranslation("plugin_pluginsmanager_install_title"), MessageBoxButton.YesNo) == MessageBoxResult.No) + 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.Version}.zip"); @@ -77,30 +82,34 @@ namespace Flow.Launcher.Plugin.PluginsManager try { Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), - Context.API.GetTranslation("plugin_pluginsmanager_please_wait")); + Context.API.GetTranslation("plugin_pluginsmanager_please_wait")); Http.Download(plugin.UrlDownload, filePath); Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), - Context.API.GetTranslation("plugin_pluginsmanager_download_success")); + Context.API.GetTranslation("plugin_pluginsmanager_download_success")); } catch (Exception e) { Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), - Context.API.GetTranslation("plugin_pluginsmanager_download_success")); + Context.API.GetTranslation("plugin_pluginsmanager_download_success")); Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "PluginDownload"); } - Application.Current.Dispatcher.Invoke(() => { Install(plugin, filePath); Context.API.RestartApp(); }); + Application.Current.Dispatcher.Invoke(() => + { + Install(plugin, filePath); + Context.API.RestartApp(); + }); } internal List RequestUpdate(string search) { var autocompletedResults = AutoCompleteReturnAllResults(search, - Settings.HotkeyUpdate, - "Update", - "Select a plugin to update"); + Settings.HotkeyUpdate, + "Update", + "Select a plugin to update"); if (autocompletedResults.Any()) return autocompletedResults; @@ -108,63 +117,68 @@ namespace Flow.Launcher.Plugin.PluginsManager 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 - }; + 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 { - new Result - { - Title = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_title"), - SubTitle = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_subtitle"), - IcoPath = icoPath - }}; + return new List + { + 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); + .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); + 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); + var downloadToFilePath = Path.Combine(DataLocation.PluginsDirectory, + $"{x.Name}-{x.NewVersion}.zip"); + Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath); + Install(x.PluginNewUserPlugin, downloadToFilePath); - Context.API.RestartApp(); + Context.API.RestartApp(); - return true; - } + return true; + } - return false; - } - }); + return false; + } + }); return Search(results, uninstallSearch); } @@ -180,37 +194,37 @@ namespace Flow.Launcher.Plugin.PluginsManager return results.ToList(); return results - .Where(x => - { - var matchResult = StringMatcher.FuzzySearch(searchName, x.Title); - if (matchResult.IsSearchPrecisionScoreMet()) - x.Score = matchResult.Score; + .Where(x => + { + var matchResult = StringMatcher.FuzzySearch(searchName, x.Title); + if (matchResult.IsSearchPrecisionScoreMet()) + x.Score = matchResult.Score; - return matchResult.IsSearchPrecisionScoreMet(); - }) - .ToList(); + return matchResult.IsSearchPrecisionScoreMet(); + }) + .ToList(); } internal List RequestInstallOrUpdate(string searchName) { var results = pluginsManifest - .UserPlugins - .Select(x => - new Result - { - Title = $"{x.Name} by {x.Author}", - SubTitle = x.Description, - IcoPath = icoPath, - Action = e => + .UserPlugins + .Select(x => + new Result { - Application.Current.MainWindow.Hide(); - InstallOrUpdate(x); + Title = $"{x.Name} by {x.Author}", + SubTitle = x.Description, + IcoPath = icoPath, + Action = e => + { + Application.Current.MainWindow.Hide(); + InstallOrUpdate(x); - return ShouldHideWindow; - }, - ContextData = x - }); + return ShouldHideWindow; + }, + ContextData = x + }); return Search(results, searchName); } @@ -253,10 +267,10 @@ namespace Flow.Launcher.Plugin.PluginsManager internal List RequestUninstall(string search) { - var autocompletedResults = AutoCompleteReturnAllResults(search, - Settings.HotkeyUninstall, - "Uninstall", - "Select a plugin to uninstall"); + var autocompletedResults = AutoCompleteReturnAllResults(search, + Settings.HotkeyUninstall, + "Uninstall", + "Select a plugin to uninstall"); if (autocompletedResults.Any()) return autocompletedResults; @@ -264,32 +278,34 @@ namespace Flow.Launcher.Plugin.PluginsManager var uninstallSearch = search.Replace(Settings.HotkeyUninstall, string.Empty).TrimStart(); var results = Context.API - .GetAllPlugins() - .Select(x => - new Result - { - Title = $"{x.Metadata.Name} by {x.Metadata.Author}", - SubTitle = x.Metadata.Description, - IcoPath = x.Metadata.IcoPath, - Action = e => - { - string message = string.Format(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_prompt"), - x.Metadata.Name, x.Metadata.Author, - Environment.NewLine, Environment.NewLine); + .GetAllPlugins() + .Select(x => + new Result + { + Title = $"{x.Metadata.Name} by {x.Metadata.Author}", + SubTitle = x.Metadata.Description, + IcoPath = x.Metadata.IcoPath, + Action = e => + { + string message = string.Format( + Context.API.GetTranslation("plugin_pluginsmanager_uninstall_prompt"), + x.Metadata.Name, x.Metadata.Author, + Environment.NewLine, Environment.NewLine); - 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(); + 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 true; + } - return false; - } - }); + return false; + } + }); return Search(results, uninstallSearch); } @@ -300,6 +316,7 @@ namespace Flow.Launcher.Plugin.PluginsManager 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) @@ -317,8 +334,9 @@ namespace Flow.Launcher.Plugin.PluginsManager Action = e => { Context - .API - .ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {hotkey} "); + .API + .ChangeQuery( + $"{Context.CurrentPluginMetadata.ActionKeywords.FirstOrDefault()} {hotkey} "); return false; } @@ -329,4 +347,4 @@ namespace Flow.Launcher.Plugin.PluginsManager return new List(); } } -} +} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs index e2e8d22e5..5fc3916c0 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs @@ -6,8 +6,52 @@ namespace Flow.Launcher.Plugin.PluginsManager { internal class Settings { + internal string HotKeyInstall { get; set; } = "install"; internal string HotkeyUninstall { get; set; } = "uninstall"; internal string HotkeyUpdate { get; set; } = "update"; + + internal readonly string icoPath = "Images\\pluginsmanager.png"; + + + internal List HotKeys + { + get + { + return new List() + { + new Result() + { + Title = HotKeyInstall, + IcoPath = icoPath, + Action = _ => + { + Main.Context.API.ChangeQuery("pm install "); + return false; + } + }, + new Result() + { + Title = HotkeyUninstall, + IcoPath = icoPath, + Action = _ => + { + Main.Context.API.ChangeQuery("pm uninstall "); + return false; + } + }, + new Result() + { + Title = HotkeyUpdate, + IcoPath = icoPath, + Action = _ => + { + Main.Context.API.ChangeQuery("pm update "); + return false; + } + } + }; + } + } } -} +} \ No newline at end of file From deaac1c7e48ff6ef370a4127247fc22cb94a8f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Sun, 27 Dec 2020 22:33:12 +0800 Subject: [PATCH 14/95] replace install from search keyword --- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 23d2756ae..bd998514a 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -207,6 +207,8 @@ namespace Flow.Launcher.Plugin.PluginsManager internal List RequestInstallOrUpdate(string searchName) { + var searchNameWithoutKeyword = searchName.Replace(Settings.HotKeyInstall, string.Empty).Trim(); + var results = pluginsManifest .UserPlugins @@ -226,7 +228,7 @@ namespace Flow.Launcher.Plugin.PluginsManager ContextData = x }); - return Search(results, searchName); + return Search(results, searchNameWithoutKeyword); } private void Install(UserPlugin plugin, string downloadedFilePath) From 5a0358718cd9b76b71da0c885c853f39e7e09b60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 28 Dec 2020 23:06:47 +0800 Subject: [PATCH 15/95] Update PluginManifest if last update time is 12 hours ago --- .../Flow.Launcher.Plugin.PluginsManager/Main.cs | 16 +++++++++++++++- .../Models/PluginsManifest.cs | 10 +++------- .../PluginsManager.cs | 8 +++++++- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 6cf9e1608..9aa024fc8 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Controls; using Flow.Launcher.Infrastructure; +using System; +using System.Threading.Tasks; namespace Flow.Launcher.Plugin.PluginsManager { @@ -21,6 +23,8 @@ namespace Flow.Launcher.Plugin.PluginsManager internal PluginsManager pluginManager; + internal DateTime _lastUpdateTime; + public Control CreateSettingPanel() { return new PluginsManagerSettings(viewModel); @@ -33,6 +37,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Settings = viewModel.Settings; contextMenu = new ContextMenu(Context, Settings); pluginManager = new PluginsManager(Context, Settings); + _lastUpdateTime = DateTime.Now; } public List LoadContextMenus(Result selectedResult) @@ -43,10 +48,19 @@ namespace Flow.Launcher.Plugin.PluginsManager public List Query(Query query) { var search = query.Search.ToLower(); - + if (string.IsNullOrWhiteSpace(search)) return Settings.HotKeys; + if ((DateTime.Now - _lastUpdateTime).TotalSeconds > 43200) // 12 hours + { + Task.Run(async () => + { + await pluginManager.UpdateManifest(); + _lastUpdateTime = DateTime.Now; + }); + } + return search switch { var s when s.StartsWith(Settings.HotKeyInstall) => pluginManager.RequestInstallOrUpdate(s), diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs index 290221710..1c31432b2 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs @@ -12,19 +12,15 @@ namespace Flow.Launcher.Plugin.PluginsManager.Models internal List UserPlugins { get; private set; } internal PluginsManifest() { - DownloadManifest(); + Task.Run(() => DownloadManifest()).Wait(); } - private void DownloadManifest() + internal async Task DownloadManifest() { var json = string.Empty; try { - var t = Task.Run( - async () => - json = await Http.Get("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/main/plugins.json")); - - t.Wait(); + json = await Http.Get("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/main/plugins.json"); UserPlugins = JsonConvert.DeserializeObject>(json); } diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index bd998514a..c6f127387 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -7,13 +7,14 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; using System.Windows; namespace Flow.Launcher.Plugin.PluginsManager { internal class PluginsManager { - private readonly PluginsManifest pluginsManifest; + private PluginsManifest pluginsManifest; private PluginInitContext Context { get; set; } @@ -44,6 +45,11 @@ namespace Flow.Launcher.Plugin.PluginsManager Settings = settings; } + internal async Task UpdateManifest() + { + await pluginsManifest.DownloadManifest(); + } + internal void InstallOrUpdate(UserPlugin plugin) { if (PluginExists(plugin.ID)) From 00457ddc29aad8088eac5439d0be10f2368a82f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 12:08:41 +0800 Subject: [PATCH 16/95] change totalSeconds to Hours --- Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 9aa024fc8..fe11b619e 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -52,7 +52,7 @@ namespace Flow.Launcher.Plugin.PluginsManager if (string.IsNullOrWhiteSpace(search)) return Settings.HotKeys; - if ((DateTime.Now - _lastUpdateTime).TotalSeconds > 43200) // 12 hours + if ((DateTime.Now - _lastUpdateTime).TotalHours > 12) // 12 hours { Task.Run(async () => { From bb9682f7918ec6afa8ef0441dbe09fa8306a3b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 12:14:59 +0800 Subject: [PATCH 17/95] Move get default hotkeys to pluginmanger and make Main.Context non-static --- .../Main.cs | 2 +- .../PluginsManager.cs | 37 +++++++++++++++++ .../Settings.cs | 40 ------------------- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index fe11b619e..8d99bf37d 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -13,7 +13,7 @@ namespace Flow.Launcher.Plugin.PluginsManager { public class Main : ISettingProvider, IPlugin, ISavable, IContextMenu, IPluginI18n { - internal static PluginInitContext Context { get; set; } + internal PluginInitContext Context { get; set; } internal Settings Settings; diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index c6f127387..29ff9cb54 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -50,6 +50,43 @@ namespace Flow.Launcher.Plugin.PluginsManager await pluginsManifest.DownloadManifest(); } + internal List GetDefaultHotKeys() + { + return new List() + { + new Result() + { + Title = Settings.HotKeyInstall, + IcoPath = icoPath, + Action = _ => + { + Context.API.ChangeQuery("pm install "); + return false; + } + }, + new Result() + { + Title = Settings.HotkeyUninstall, + IcoPath = icoPath, + Action = _ => + { + Context.API.ChangeQuery("pm uninstall "); + return false; + } + }, + new Result() + { + Title = Settings.HotkeyUpdate, + IcoPath = icoPath, + Action = _ => + { + Context.API.ChangeQuery("pm update "); + return false; + } + } + }; + } + internal void InstallOrUpdate(UserPlugin plugin) { if (PluginExists(plugin.ID)) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs index 5fc3916c0..3753056f7 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs @@ -12,46 +12,6 @@ namespace Flow.Launcher.Plugin.PluginsManager internal string HotkeyUpdate { get; set; } = "update"; internal readonly string icoPath = "Images\\pluginsmanager.png"; - - - internal List HotKeys - { - get - { - return new List() - { - new Result() - { - Title = HotKeyInstall, - IcoPath = icoPath, - Action = _ => - { - Main.Context.API.ChangeQuery("pm install "); - return false; - } - }, - new Result() - { - Title = HotkeyUninstall, - IcoPath = icoPath, - Action = _ => - { - Main.Context.API.ChangeQuery("pm uninstall "); - return false; - } - }, - new Result() - { - Title = HotkeyUpdate, - IcoPath = icoPath, - Action = _ => - { - Main.Context.API.ChangeQuery("pm update "); - return false; - } - } - }; - } } } } \ No newline at end of file From f32e202746397e6542f5a831b8b675ce5e1878c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 12:20:13 +0800 Subject: [PATCH 18/95] Use System.Text.JsonSerializer.DeserializeAsync instead of Newtonsoft.Json since our plugins.json can be large, so no need to create an extra string to store it. --- Flow.Launcher.Infrastructure/Http/Http.cs | 13 +++++++++++++ .../Models/PluginsManifest.cs | 8 ++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 2d798ec11..62cacc18f 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -73,5 +73,18 @@ namespace Flow.Launcher.Infrastructure.Http return content; } + + public static async Task GetStreamAsync([NotNull] string url, string encoding = "UTF-8") + { + Log.Debug($"|Http.Get|Url <{url}>"); + var request = WebRequest.CreateHttp(url); + request.Method = "GET"; + request.Timeout = 6000; + request.Proxy = WebProxy(); + request.UserAgent = UserAgent; + var response = await request.GetResponseAsync() as HttpWebResponse; + response = response.NonNull(); + return response.GetResponseStream().NonNull(); + } } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs index 1c31432b2..2ab8806bc 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs @@ -1,8 +1,8 @@ using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; -using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.Text.Json; using System.Threading.Tasks; namespace Flow.Launcher.Plugin.PluginsManager.Models @@ -17,12 +17,12 @@ namespace Flow.Launcher.Plugin.PluginsManager.Models internal async Task DownloadManifest() { - var json = string.Empty; try { - json = await Http.Get("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/main/plugins.json"); + var jsonStream = await Http.GetStreamAsync("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/main/plugins.json") + .ConfigureAwait(false); - UserPlugins = JsonConvert.DeserializeObject>(json); + UserPlugins = await JsonSerializer.DeserializeAsync>(jsonStream).ConfigureAwait(false); } catch (Exception e) { From f0267475f520f9bd53981201dabc72e22877e2c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 12:23:15 +0800 Subject: [PATCH 19/95] Change call method for default hotkeys. Remove extra whitespace add await using for stream --- Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 4 ++-- .../Models/PluginsManifest.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 8d99bf37d..607b2e3f5 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -50,7 +50,7 @@ namespace Flow.Launcher.Plugin.PluginsManager var search = query.Search.ToLower(); if (string.IsNullOrWhiteSpace(search)) - return Settings.HotKeys; + return pluginManager.GetDefaultHotKeys(); if ((DateTime.Now - _lastUpdateTime).TotalHours > 12) // 12 hours { @@ -66,7 +66,7 @@ namespace Flow.Launcher.Plugin.PluginsManager var s when s.StartsWith(Settings.HotKeyInstall) => pluginManager.RequestInstallOrUpdate(s), var s when s.StartsWith(Settings.HotkeyUninstall) => pluginManager.RequestUninstall(s), var s when s.StartsWith(Settings.HotkeyUpdate) => pluginManager.RequestUpdate(s), - _ => Settings.HotKeys.Where(hotkey => + _ => pluginManager.GetDefaultHotKeys().Where(hotkey => { hotkey.Score = StringMatcher.FuzzySearch(search, hotkey.Title).Score; return hotkey.Score > 0; diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs index 2ab8806bc..c854b213d 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs @@ -19,7 +19,7 @@ namespace Flow.Launcher.Plugin.PluginsManager.Models { try { - var jsonStream = await Http.GetStreamAsync("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/main/plugins.json") + await using var jsonStream = await Http.GetStreamAsync("https://raw.githubusercontent.com/Flow-Launcher/Flow.Launcher.PluginsManifest/main/plugins.json") .ConfigureAwait(false); UserPlugins = await JsonSerializer.DeserializeAsync>(jsonStream).ConfigureAwait(false); @@ -33,4 +33,4 @@ namespace Flow.Launcher.Plugin.PluginsManager.Models } } -} +} \ No newline at end of file From 5da8259228120ccbfed0662de1131bd3a95fed85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 13:03:38 +0800 Subject: [PATCH 20/95] fix an unintended text error add async await to download manifest task remove unused encoding name for new GetStreamAsync in Http fix unintened text error --- Flow.Launcher.Infrastructure/Http/Http.cs | 2 +- .../Models/PluginsManifest.cs | 2 +- Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 62cacc18f..ea412759e 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -74,7 +74,7 @@ namespace Flow.Launcher.Infrastructure.Http return content; } - public static async Task GetStreamAsync([NotNull] string url, string encoding = "UTF-8") + public static async Task GetStreamAsync([NotNull] string url) { Log.Debug($"|Http.Get|Url <{url}>"); var request = WebRequest.CreateHttp(url); diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs index c854b213d..7b2f8e372 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs @@ -12,7 +12,7 @@ namespace Flow.Launcher.Plugin.PluginsManager.Models internal List UserPlugins { get; private set; } internal PluginsManifest() { - Task.Run(() => DownloadManifest()).Wait(); + Task.Run(async () => await DownloadManifest()).Wait(); } internal async Task DownloadManifest() diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs index 3753056f7..d5d78d28a 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs @@ -12,6 +12,6 @@ namespace Flow.Launcher.Plugin.PluginsManager internal string HotkeyUpdate { get; set; } = "update"; internal readonly string icoPath = "Images\\pluginsmanager.png"; - } + } } \ No newline at end of file From c94a2f4c9599c49ad00b3e524b28ec044eb22868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 13:06:08 +0800 Subject: [PATCH 21/95] Use string.CompareTo instead of equal to check for update --- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 29ff9cb54..2931afe30 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -164,7 +164,7 @@ namespace Flow.Launcher.Plugin.PluginsManager from existingPlugin in Context.API.GetAllPlugins() join pluginFromManifest in pluginsManifest.UserPlugins on existingPlugin.Metadata.ID equals pluginFromManifest.ID - where existingPlugin.Metadata.Version != pluginFromManifest.Version + where existingPlugin.Metadata.Version.CompareTo(pluginFromManifest.Version) > 0 select new { From a1a45a49890001150b8d4c78f8f8b3c763402565 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 29 Dec 2020 17:49:11 +1100 Subject: [PATCH 22/95] add eof --- Flow.Launcher.Infrastructure/Http/Http.cs | 2 +- Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 2 +- .../Models/PluginsManifest.cs | 2 +- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 3 +-- Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index ea412759e..9d2fe7860 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -87,4 +87,4 @@ namespace Flow.Launcher.Infrastructure.Http return response.GetResponseStream().NonNull(); } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 607b2e3f5..2d9a29a2f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -89,4 +89,4 @@ namespace Flow.Launcher.Plugin.PluginsManager return Context.API.GetTranslation("plugin_pluginsmanager_plugin_description"); } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs index 7b2f8e372..ad8185620 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Models/PluginsManifest.cs @@ -33,4 +33,4 @@ namespace Flow.Launcher.Plugin.PluginsManager.Models } } -} \ 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 2931afe30..d06bbf1f9 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -361,7 +361,6 @@ namespace Flow.Launcher.Plugin.PluginsManager 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) @@ -392,4 +391,4 @@ namespace Flow.Launcher.Plugin.PluginsManager return new List(); } } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs index d5d78d28a..a885bfd15 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs @@ -14,4 +14,4 @@ namespace Flow.Launcher.Plugin.PluginsManager internal readonly string icoPath = "Images\\pluginsmanager.png"; } -} \ No newline at end of file +} From f9349a64e96226b725500752755834ff1d493dea Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 29 Dec 2020 17:49:37 +1100 Subject: [PATCH 23/95] fix condition of version compare --- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index d06bbf1f9..9635648d4 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -164,7 +164,7 @@ namespace Flow.Launcher.Plugin.PluginsManager from existingPlugin in Context.API.GetAllPlugins() join pluginFromManifest in pluginsManifest.UserPlugins on existingPlugin.Metadata.ID equals pluginFromManifest.ID - where existingPlugin.Metadata.Version.CompareTo(pluginFromManifest.Version) > 0 + where existingPlugin.Metadata.Version.CompareTo(pluginFromManifest.Version) < 0 // if current version precedes manifest version select new { From e5b67ea10a43527c99e62317f466e2b14c467995 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 29 Dec 2020 18:04:23 +1100 Subject: [PATCH 24/95] remove obsolete icoPath from settings --- Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs index a885bfd15..9c5b0d29f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Settings.cs @@ -10,8 +10,5 @@ namespace Flow.Launcher.Plugin.PluginsManager internal string HotkeyUninstall { get; set; } = "uninstall"; internal string HotkeyUpdate { get; set; } = "update"; - - internal readonly string icoPath = "Images\\pluginsmanager.png"; - } } From 0a47636bc9e0427341d97aa471a67a94fef38b3c Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 29 Dec 2020 18:13:52 +1100 Subject: [PATCH 25/95] remove obsolete settings property in context menu class --- Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs | 7 ++----- Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 3 +-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs index 76cb0f86b..b9bf5ee85 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs @@ -1,4 +1,4 @@ -using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.PluginsManager.Models; using System; using System.Collections.Generic; @@ -10,12 +10,9 @@ namespace Flow.Launcher.Plugin.PluginsManager { private PluginInitContext Context { get; set; } - private Settings Settings { get; set; } - - public ContextMenu(PluginInitContext context, Settings settings) + public ContextMenu(PluginInitContext context) { Context = context; - Settings = settings; } public List LoadContextMenus(Result selectedResult) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 2d9a29a2f..a333b3862 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -1,5 +1,4 @@ using Flow.Launcher.Infrastructure.Storage; -using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.PluginsManager.ViewModels; using Flow.Launcher.Plugin.PluginsManager.Views; using System.Collections.Generic; @@ -35,7 +34,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context = context; viewModel = new SettingsViewModel(context); Settings = viewModel.Settings; - contextMenu = new ContextMenu(Context, Settings); + contextMenu = new ContextMenu(Context); pluginManager = new PluginsManager(Context, Settings); _lastUpdateTime = DateTime.Now; } From a1d1c95eebb83867c4581759076b6167c7c0f65b Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 29 Dec 2020 18:14:22 +1100 Subject: [PATCH 26/95] change to tab in browser --- 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 b9bf5ee85..7bc357be4 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs @@ -1,4 +1,4 @@ -using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.PluginsManager.Models; using System; using System.Collections.Generic; @@ -55,7 +55,7 @@ namespace Flow.Launcher.Plugin.PluginsManager ? pluginManifestInfo.UrlSourceCode.Replace("/tree/master", "/issues/new/choose") : pluginManifestInfo.UrlSourceCode; - SharedCommands.SearchWeb.NewBrowserWindow(link); + SharedCommands.SearchWeb.NewTabInBrowser(link); return true; } }, @@ -66,7 +66,7 @@ namespace Flow.Launcher.Plugin.PluginsManager IcoPath = selectedResult.IcoPath, Action = _ => { - SharedCommands.SearchWeb.NewBrowserWindow("https://github.com/Flow-Launcher/Flow.Launcher.PluginsManifest"); + SharedCommands.SearchWeb.NewTabInBrowser("https://github.com/Flow-Launcher/Flow.Launcher.PluginsManifest"); return true; } } From b106688513f4d463656bd61c43034bcf71288acd Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 29 Dec 2020 18:14:33 +1100 Subject: [PATCH 27/95] version bump --- 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 e970e5a8e..d94af71a1 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.3.0", + "Version": "1.3.1", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll", From 000bafd116910a5e8fcb919640be35f9ccfa2495 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 29 Dec 2020 18:56:51 +1100 Subject: [PATCH 28/95] use camelCase and make last update time variable private --- Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index a333b3862..716a424ff 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -22,7 +22,7 @@ namespace Flow.Launcher.Plugin.PluginsManager internal PluginsManager pluginManager; - internal DateTime _lastUpdateTime; + private DateTime lastUpdateTime; public Control CreateSettingPanel() { @@ -36,7 +36,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Settings = viewModel.Settings; contextMenu = new ContextMenu(Context); pluginManager = new PluginsManager(Context, Settings); - _lastUpdateTime = DateTime.Now; + lastUpdateTime = DateTime.Now; } public List LoadContextMenus(Result selectedResult) @@ -51,12 +51,12 @@ namespace Flow.Launcher.Plugin.PluginsManager if (string.IsNullOrWhiteSpace(search)) return pluginManager.GetDefaultHotKeys(); - if ((DateTime.Now - _lastUpdateTime).TotalHours > 12) // 12 hours + if ((DateTime.Now - lastUpdateTime).TotalHours > 12) // 12 hours { Task.Run(async () => { await pluginManager.UpdateManifest(); - _lastUpdateTime = DateTime.Now; + lastUpdateTime = DateTime.Now; }); } From a47f8b318510db0fe7e5edfacd91c1894e33221b Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 29 Dec 2020 19:06:17 +1100 Subject: [PATCH 29/95] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f3f7e1a7..02f488758 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Windows may complain about security due to code not being signed, this will be c - Open flow's search window: Alt+Space is the default hotkey. - Open context menu: Ctrl+O/Shift+Enter. - Cancel/Return to previous screen: Esc. -- Install/Uninstall/Update plugins: in the search window, type `pm`/`pm uninstall`/`pm update` + the plugin name. +- Install/Uninstall/Update plugins: in the search window, type `pm install`/`pm uninstall`/`pm update` + the plugin name. - Saved user settings are located: - If using roaming: `%APPDATA%\FlowLauncher` - If using portable, by default: `%localappdata%\FlowLauncher\app-\UserData` From cfa93a2cc60808b84a131852a82f3e26ce1a4339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 17:13:31 +0800 Subject: [PATCH 30/95] Add GetStreamAsync method --- Flow.Launcher.Infrastructure/Http/Http.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 74e335d32..11d922aa1 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -110,5 +110,12 @@ namespace Flow.Launcher.Infrastructure.Http $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); } } + + public static async Task GetStreamAsync([NotNull] string url) + { + Log.Debug($"|Http.Get|Url <{url}>"); + var response = await client.GetAsync(url); + return await response.Content.ReadAsStreamAsync(); + } } } From a806f7d05adc9beb7419e555921192e094c10539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 17:14:13 +0800 Subject: [PATCH 31/95] Change exception type --- 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 11d922aa1..a98ead687 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -89,7 +89,7 @@ namespace Flow.Launcher.Infrastructure.Http } else { - throw new WebException($"Error code <{response.StatusCode}> returned from <{url}>"); + throw new HttpRequestException($"Error code <{response.StatusCode}> returned from <{url}>"); } } From 4d5119f17d2f5b307dd7eb33384e63ee31b48c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 17:15:34 +0800 Subject: [PATCH 32/95] Add out of bound exception for pattern matching --- Flow.Launcher.Infrastructure/Http/Http.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index a98ead687..040939e72 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -61,7 +61,7 @@ namespace Flow.Launcher.Infrastructure.Http { (_proxy.Address, _proxy.Credentials) = property switch { - ProxyProperty.Enabled => (Proxy.Enabled) switch + ProxyProperty.Enabled => Proxy.Enabled switch { true => Proxy.UserName switch { @@ -75,7 +75,8 @@ namespace Flow.Launcher.Infrastructure.Http ProxyProperty.Server => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), _proxy.Credentials), ProxyProperty.Port => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), _proxy.Credentials), ProxyProperty.UserName => (_proxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)), - ProxyProperty.Password => (_proxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)) + ProxyProperty.Password => (_proxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)), + _ => throw new ArgumentOutOfRangeException() }; } From e364b84b8458aa8df058fa9cf4507b2699d3224a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 17:16:44 +0800 Subject: [PATCH 33/95] Use auto property --- Flow.Launcher.Infrastructure/Http/Http.cs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 040939e72..3d056b28b 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -47,19 +47,14 @@ namespace Flow.Launcher.Infrastructure.Http } } - private static readonly WebProxy _proxy = new WebProxy(); - - public static WebProxy WebProxy - { - get { return _proxy; } - } + public static WebProxy WebProxy { get; } = new WebProxy(); /// /// Update the Address of the Proxy to modify the client Proxy /// public static void UpdateProxy(ProxyProperty property) { - (_proxy.Address, _proxy.Credentials) = property switch + (WebProxy.Address, WebProxy.Credentials) = property switch { ProxyProperty.Enabled => Proxy.Enabled switch { @@ -72,10 +67,10 @@ namespace Flow.Launcher.Infrastructure.Http }, false => (null, null) }, - ProxyProperty.Server => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), _proxy.Credentials), - ProxyProperty.Port => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), _proxy.Credentials), - ProxyProperty.UserName => (_proxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)), - ProxyProperty.Password => (_proxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)), + ProxyProperty.Server => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), WebProxy.Credentials), + ProxyProperty.Port => (new Uri($"http://{Proxy.Server}:{Proxy.Port}"), WebProxy.Credentials), + ProxyProperty.UserName => (WebProxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)), + ProxyProperty.Password => (WebProxy.Address, new NetworkCredential(Proxy.UserName, Proxy.Password)), _ => throw new ArgumentOutOfRangeException() }; } From 0c97db04d4b89d345ddb7908c5a6d361c11c0ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 17:50:56 +0800 Subject: [PATCH 34/95] 1. Change Get method Name to GetAsync 2. Manually replace "#" with "%23" to solve the similar issue in Explorer plugin 3. Add GetAsync method with Uri as argument 4. Remove unused encoding argument 5. Change exception type for WebSearch Plguin 6. Update Comment --- Flow.Launcher.Core/Updater.cs | 2 +- Flow.Launcher.Infrastructure/Http/Http.cs | 25 +++++++++++++++---- .../SuggestionSources/Baidu.cs | 5 ++-- .../SuggestionSources/Google.cs | 6 ++--- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index d8bc2b6dc..46fb6d977 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -133,7 +133,7 @@ namespace Flow.Launcher.Core var uri = new Uri(repository); var api = $"https://api.github.com/repos{uri.AbsolutePath}/releases"; - var json = await Http.Get(api); + var json = await Http.GetAsync(api); var releases = JsonConvert.DeserializeObject>(json); var latest = releases.Where(r => !r.Prerelease).OrderByDescending(r => r.PublishedAt).First(); diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 3d056b28b..8e2832690 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -89,13 +89,23 @@ namespace Flow.Launcher.Infrastructure.Http } } - public static async Task Get([NotNull] string url, string encoding = "UTF-8") + /// + /// Asynchrously get the result as string from url. + /// When supposing the result is long and large, try using GetStreamAsync to avoid reading as string + /// + /// + /// + public static Task GetAsync([NotNull] string url) { Log.Debug($"|Http.Get|Url <{url}>"); - var response = await client.GetAsync(url); - await using var stream = await response.Content.ReadAsStreamAsync(); - using var reader = new StreamReader(stream, Encoding.GetEncoding(encoding)); - var content = await reader.ReadToEndAsync(); + return GetAsync(new Uri(url.Replace("#", "%23"))); + } + + public static async Task GetAsync([NotNull] Uri url) + { + Log.Debug($"|Http.Get|Url <{url}>"); + using var response = await client.GetAsync(url); + var content = await response.Content.ReadAsStringAsync(); if (response.StatusCode == HttpStatusCode.OK) { return content; @@ -107,6 +117,11 @@ namespace Flow.Launcher.Infrastructure.Http } } + /// + /// Asynchrously get the result as stream from url. + /// + /// + /// public static async Task GetStreamAsync([NotNull] string url) { Log.Debug($"|Http.Get|Url <{url}>"); diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs index 57db223bc..6772acf82 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs @@ -8,6 +8,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; +using System.Net.Http; namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { @@ -22,9 +23,9 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources try { const string api = "http://suggestion.baidu.com/su?json=1&wd="; - result = await Http.Get(api + Uri.EscapeUriString(query), "GB2312"); + result = await Http.GetAsync(api + Uri.EscapeUriString(query)).ConfigureAwait(false); } - catch (WebException e) + catch (HttpRequestException e) { Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e); return new List(); diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs index 81878bd8b..5b9538091 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs @@ -7,6 +7,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; +using System.Net.Http; namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { @@ -18,13 +19,12 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources try { const string api = "https://www.google.com/complete/search?output=chrome&q="; - result = await Http.Get(api + Uri.EscapeUriString(query)); + result = await Http.GetAsync(api + Uri.EscapeUriString(query)).ConfigureAwait(false); } - catch (WebException e) + catch (HttpRequestException e) { Log.Exception("|Google.Suggestions|Can't get suggestion from google", e); return new List(); - ; } if (string.IsNullOrEmpty(result)) return new List(); JContainer json; From efa4908f37636f3fe6122d241a5821d14a4bf6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 17:54:39 +0800 Subject: [PATCH 35/95] Change usage of Http in Updater.cs and adding ConfigureAwait(false) for await in checking update --- Flow.Launcher.Core/Updater.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 46fb6d977..05397e906 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -29,7 +29,7 @@ namespace Flow.Launcher.Core GitHubRepository = gitHubRepository; } - public async Task UpdateApp(IPublicAPI api , bool silentUpdate = true) + public async Task UpdateApp(IPublicAPI api, bool silentUpdate = true) { UpdateManager updateManager; UpdateInfo newUpdateInfo; @@ -39,7 +39,7 @@ namespace Flow.Launcher.Core try { - updateManager = await GitHubUpdateManager(GitHubRepository); + updateManager = await GitHubUpdateManager(GitHubRepository).ConfigureAwait(false); } catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException) { @@ -50,7 +50,7 @@ namespace Flow.Launcher.Core try { // UpdateApp CheckForUpdate will return value only if the app is squirrel installed - newUpdateInfo = await updateManager.CheckForUpdate().NonNull(); + newUpdateInfo = await updateManager.CheckForUpdate().NonNull().ConfigureAwait(false); } catch (Exception e) when (e is HttpRequestException || e is WebException || e is SocketException) { @@ -85,8 +85,8 @@ namespace Flow.Launcher.Core updateManager.Dispose(); return; } - - await updateManager.ApplyReleases(newUpdateInfo); + + await updateManager.ApplyReleases(newUpdateInfo).ConfigureAwait(false); if (DataLocation.PortableDataLocationInUse()) { @@ -98,11 +98,11 @@ namespace Flow.Launcher.Core } else { - await updateManager.CreateUninstallerRegistryEntry(); + await updateManager.CreateUninstallerRegistryEntry().ConfigureAwait(false); } var newVersionTips = NewVersinoTips(newReleaseVersion.ToString()); - + Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); // always dispose UpdateManager @@ -133,9 +133,9 @@ namespace Flow.Launcher.Core var uri = new Uri(repository); var api = $"https://api.github.com/repos{uri.AbsolutePath}/releases"; - var json = await Http.GetAsync(api); + var jsonStream = await Http.GetStreamAsync(api).ConfigureAwait(false); - var releases = JsonConvert.DeserializeObject>(json); + var releases = await System.Text.Json.JsonSerializer.DeserializeAsync>(jsonStream).ConfigureAwait(false); var latest = releases.Where(r => !r.Prerelease).OrderByDescending(r => r.PublishedAt).First(); var latestUrl = latest.HtmlUrl.Replace("/tag/", "/download/"); From d4f94c66acfba5dddf0110b857519feed03eb99c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 18:33:53 +0800 Subject: [PATCH 36/95] Make InstallOrUpdate to async --- Flow.Launcher.Core/Updater.cs | 8 ++++---- Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 2 +- .../Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 7 +++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 05397e906..1e4b0453c 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -8,7 +8,6 @@ using System.Threading.Tasks; using System.Windows; using JetBrains.Annotations; using Squirrel; -using Newtonsoft.Json; using Flow.Launcher.Core.Resource; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Infrastructure; @@ -17,6 +16,7 @@ using Flow.Launcher.Infrastructure.Logger; using System.IO; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; +using System.Text.Json.Serialization; namespace Flow.Launcher.Core { @@ -117,13 +117,13 @@ namespace Flow.Launcher.Core [UsedImplicitly] private class GithubRelease { - [JsonProperty("prerelease")] + [JsonPropertyName("prerelease")] public bool Prerelease { get; [UsedImplicitly] set; } - [JsonProperty("published_at")] + [JsonPropertyName("published_at")] public DateTime PublishedAt { get; [UsedImplicitly] set; } - [JsonProperty("html_url")] + [JsonPropertyName("html_url")] public string HtmlUrl { get; [UsedImplicitly] set; } } diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 716a424ff..d700b9dfd 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -22,7 +22,7 @@ namespace Flow.Launcher.Plugin.PluginsManager internal PluginsManager pluginManager; - private DateTime lastUpdateTime; + private DateTime lastUpdateTime = DateTime.MinValue; public Control CreateSettingPanel() { diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 9635648d4..428610f43 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -87,7 +87,7 @@ namespace Flow.Launcher.Plugin.PluginsManager }; } - internal void InstallOrUpdate(UserPlugin plugin) + internal async Task InstallOrUpdate(UserPlugin plugin) { if (PluginExists(plugin.ID)) { @@ -127,7 +127,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), Context.API.GetTranslation("plugin_pluginsmanager_please_wait")); - Http.Download(plugin.UrlDownload, filePath); + await Http.Download(plugin.UrlDownload, filePath).ConfigureAwait(false); Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), Context.API.GetTranslation("plugin_pluginsmanager_download_success")); @@ -264,8 +264,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Action = e => { Application.Current.MainWindow.Hide(); - InstallOrUpdate(x); - + _ = InstallOrUpdate(x); // No need to wait return ShouldHideWindow; }, ContextData = x From d0743f627668fa5bbd55a3daef37f82064fc3a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 18:48:00 +0800 Subject: [PATCH 37/95] Await Http.Download in Update method --- .../PluginsManager.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 428610f43..f12112382 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -140,11 +140,8 @@ namespace Flow.Launcher.Plugin.PluginsManager Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "PluginDownload"); } - Application.Current.Dispatcher.Invoke(() => - { - Install(plugin, filePath); - Context.API.RestartApp(); - }); + Install(plugin, filePath); + Context.API.RestartApp(); } internal List RequestUpdate(string search) @@ -211,10 +208,14 @@ namespace Flow.Launcher.Plugin.PluginsManager var downloadToFilePath = Path.Combine(DataLocation.PluginsDirectory, $"{x.Name}-{x.NewVersion}.zip"); - Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath); - Install(x.PluginNewUserPlugin, downloadToFilePath); - Context.API.RestartApp(); + Task.Run(async delegate + { + await Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath).ConfigureAwait(false); + Install(x.PluginNewUserPlugin, downloadToFilePath); + + Context.API.RestartApp(); + }); return true; } From c485578cff927a1714344c0eca1ab82870673fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 29 Dec 2020 18:48:55 +0800 Subject: [PATCH 38/95] Use CompareTo to check update for InstallOrUpdate method --- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index f12112382..ac15618ca 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -92,7 +92,7 @@ namespace Flow.Launcher.Plugin.PluginsManager if (PluginExists(plugin.ID)) { if (Context.API.GetAllPlugins() - .Any(x => x.Metadata.ID == plugin.ID && x.Metadata.Version != plugin.Version)) + .Any(x => x.Metadata.ID == plugin.ID && x.Metadata.Version.CompareTo(plugin.Version) < 0)) { if (MessageBox.Show(Context.API.GetTranslation("plugin_pluginsmanager_update_exists"), Context.API.GetTranslation("plugin_pluginsmanager_update_title"), From e2b0386818dca21d0ce9aba69cbb5331d524e676 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 29 Dec 2020 22:32:14 +1100 Subject: [PATCH 39/95] remove Color plugin from Flow as a default plugin --- Flow.Launcher.sln | 16 --- .../Flow.Launcher.Plugin.Color.csproj | 101 --------------- .../Images/color.png | Bin 1856 -> 0 bytes .../Languages/de.xaml | 8 -- .../Languages/en.xaml | 8 -- .../Languages/pl.xaml | 8 -- .../Languages/sk.xaml | 8 -- .../Languages/tr.xaml | 8 -- .../Languages/zh-cn.xaml | 8 -- .../Languages/zh-tw.xaml | 7 - Plugins/Flow.Launcher.Plugin.Color/Main.cs | 121 ------------------ .../Flow.Launcher.Plugin.Color/plugin.json | 12 -- 12 files changed, 305 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.Color/Flow.Launcher.Plugin.Color.csproj delete mode 100644 Plugins/Flow.Launcher.Plugin.Color/Images/color.png delete mode 100644 Plugins/Flow.Launcher.Plugin.Color/Languages/de.xaml delete mode 100644 Plugins/Flow.Launcher.Plugin.Color/Languages/en.xaml delete mode 100644 Plugins/Flow.Launcher.Plugin.Color/Languages/pl.xaml delete mode 100644 Plugins/Flow.Launcher.Plugin.Color/Languages/sk.xaml delete mode 100644 Plugins/Flow.Launcher.Plugin.Color/Languages/tr.xaml delete mode 100644 Plugins/Flow.Launcher.Plugin.Color/Languages/zh-cn.xaml delete mode 100644 Plugins/Flow.Launcher.Plugin.Color/Languages/zh-tw.xaml delete mode 100644 Plugins/Flow.Launcher.Plugin.Color/Main.cs delete mode 100644 Plugins/Flow.Launcher.Plugin.Color/plugin.json diff --git a/Flow.Launcher.sln b/Flow.Launcher.sln index 4d8997177..21c3b47dc 100644 --- a/Flow.Launcher.sln +++ b/Flow.Launcher.sln @@ -20,7 +20,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher", "Flow.Launc {F9C4C081-4CC3-4146-95F1-E102B4E10A5F} = {F9C4C081-4CC3-4146-95F1-E102B4E10A5F} {59BD9891-3837-438A-958D-ADC7F91F6F7E} = {59BD9891-3837-438A-958D-ADC7F91F6F7E} {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0} = {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0} - {F35190AA-4758-4D9E-A193-E3BDF6AD3567} = {F35190AA-4758-4D9E-A193-E3BDF6AD3567} {9B130CC5-14FB-41FF-B310-0A95B6894C37} = {9B130CC5-14FB-41FF-B310-0A95B6894C37} {FDED22C8-B637-42E8-824A-63B5B6E05A3A} = {FDED22C8-B637-42E8-824A-63B5B6E05A3A} {A3DCCBCA-ACC1-421D-B16E-210896234C26} = {A3DCCBCA-ACC1-421D-B16E-210896234C26} @@ -44,8 +43,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Sys", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Url", "Plugins\Flow.Launcher.Plugin.Url\Flow.Launcher.Plugin.Url.csproj", "{A3DCCBCA-ACC1-421D-B16E-210896234C26}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Color", "Plugins\Flow.Launcher.Plugin.Color\Flow.Launcher.Plugin.Color.csproj", "{F35190AA-4758-4D9E-A193-E3BDF6AD3567}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FFD651C7-0546-441F-BC8C-D4EE8FD01EA7}" ProjectSection(SolutionItems) = preProject .gitattributes = .gitattributes @@ -214,18 +211,6 @@ Global {A3DCCBCA-ACC1-421D-B16E-210896234C26}.Release|x64.Build.0 = Release|Any CPU {A3DCCBCA-ACC1-421D-B16E-210896234C26}.Release|x86.ActiveCfg = Release|Any CPU {A3DCCBCA-ACC1-421D-B16E-210896234C26}.Release|x86.Build.0 = Release|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Debug|x64.ActiveCfg = Debug|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Debug|x64.Build.0 = Debug|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Debug|x86.ActiveCfg = Debug|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Debug|x86.Build.0 = Debug|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Release|Any CPU.Build.0 = Release|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Release|x64.ActiveCfg = Release|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Release|x64.Build.0 = Release|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Release|x86.ActiveCfg = Release|Any CPU - {F35190AA-4758-4D9E-A193-E3BDF6AD3567}.Release|x86.Build.0 = Release|Any CPU {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|Any CPU.Build.0 = Debug|Any CPU {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -309,7 +294,6 @@ Global {FDED22C8-B637-42E8-824A-63B5B6E05A3A} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {0B9DE348-9361-4940-ADB6-F5953BFFCCEC} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {A3DCCBCA-ACC1-421D-B16E-210896234C26} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} - {F35190AA-4758-4D9E-A193-E3BDF6AD3567} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {C21BFF9C-2C99-4B5F-B7C9-A5E6DDDB37B0} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {9B130CC5-14FB-41FF-B310-0A95B6894C37} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {59BD9891-3837-438A-958D-ADC7F91F6F7E} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} diff --git a/Plugins/Flow.Launcher.Plugin.Color/Flow.Launcher.Plugin.Color.csproj b/Plugins/Flow.Launcher.Plugin.Color/Flow.Launcher.Plugin.Color.csproj deleted file mode 100644 index c7fe8271a..000000000 --- a/Plugins/Flow.Launcher.Plugin.Color/Flow.Launcher.Plugin.Color.csproj +++ /dev/null @@ -1,101 +0,0 @@ - - - - Library - netcoreapp3.1 - {F35190AA-4758-4D9E-A193-E3BDF6AD3567} - Properties - Flow.Launcher.Plugin.Color - Flow.Launcher.Plugin.Color - true - false - false - - - - true - full - false - ..\..\Output\Debug\Plugins\Flow.Launcher.Plugin.Color\ - DEBUG;TRACE - prompt - 4 - false - - - - pdbonly - true - ..\..\Output\Release\Plugins\Flow.Launcher.Plugin.Color\ - TRACE - prompt - 4 - false - - - - - PreserveNewest - - - - - - PreserveNewest - - - - - - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Color/Images/color.png b/Plugins/Flow.Launcher.Plugin.Color/Images/color.png deleted file mode 100644 index da28583b1c9f174367acef0205f0c47f0a839ecd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1856 zcmV-G2fz4e%OapHR~QiSv}$ z`|SPw_WIV^7ZZNx5B<*d;}3xUcLaZx2=LHTUNG+g(Z&oQa{$CW^yENaxq-_Hz{8y` zB+|nR!VA?35U15cp8n}_fs_|uXnO#l4JE}f2Wac@mfsuz4{qxQDF;jmV{I>O9q2LD zR?=um5#Y|w4k*g=V0Hs=foL4e{dD9=9}hm|1EJlND8>kFJ=QUN>K-pK?EpdaHx2MO zlh)_CKj1Uf4`8m0a%ZOtN@jMwx*aq7cvt)$ve|1)4b15oU;X3{L`HVwUbbm_JuLxg zu9%7dcXjoEXiq6|kv09Hn$25QNg+5rlbrcJJi4~Jxm14)KIqx>MYn81qySml49hy2 zUj05uQO0UEZ)q@u$chKJd33EjSWK!%W+yp-iP;x$0zf>55P9N7J5vBAqF@Ff07I`{ zi%Skb7otG?5&%X#o4)8M6@4=RJ`hQ(OFqCN2&)3&d10G;AtobG7Jyz5J#Qul3fl-f zIUin605=tWXAS^;o=vCqD_^!lc?9Nbzo{fH6q%Za-{!7E#hvx7zX+flNh}8Dt}dyK z3N0kwOI$(_HU;%v>x#A)vIsC(YM+c%OIag&;Dc^J+ri013qF2zlC)Hj6>{%ST?q`? zS0}5TZak9vEOBxEuli?hTNuV4p7nor6^U~o53Ns+qKeaRn9P|e}CKHL8G?1 z0DRzxD+U?{vfE)1g=9QZ3L+Z4;E%;FwSq9_dI$}Q9X0s?iL^TN+E>xA%G5klU+a&q zs4KEnCfW<)Ewwq(3@tYSiO)kIZW0i6?P!i)LCd`5Rz30g5c}H(i*~U^0Q0tC!(C-52vto*rY;921%%@k z_${?a+Z$^s&{$(RIgxD5h+o_2hSj<-yVnHfY;$eq3vI)UUHcy$?9KnY7{Flm^Iwuh zB6jt{$t3+RR(;>B+ws6!92ifX|F6^Oh%T>N$d5(+>DWfk^TJAnQP7FNQI^&Gj90Tc z@#9ZZmoH5xD$}Z#IX)72tiH+_zHL=qL#=D|v%Z(dap;Wg-7mkp8lIS%ZD0+V1}wlbr1=*EsPVa(@V`!kr&FQJ5xP*NQELADt5K+i8pAHE zTX}Kop64Fh5`*>hJMUIce;sxvep*e?GL=k&Ef}qGU!AR6x8fh3^9_}DmhbKW$N@}P zC?_6iRd-AL?Ofddoo!j-RHygm_bM6MmHz*rB2|qltFDD?7In-dL~vi*;QT~oAH5{@ z0{pg-jY^46soKm?EE3iT%@cP&=pS0KK0WSKXzouxS`hoX6~tp$Zf}59DVl9F5T=q? z2sbLDvY9_Nb0wq_no@R0aO|0vHXJ*9PW;dD4QraU$-^NC`v{0t4&BH}Ac|&xKIe3v z%tFSBIO8tVYngaqn{ShItwQ|S9lPAB!%=(m?72+uv5jk>X>$==?w`y+RFNOmcHM={ z03v8j$2&|fWH~0WCNOiSmY8c132Wqe(f*jGetdD=9ge9D4=(sTA0XGK7X9)h(&I7I zr5-o3X%3>ouAL!5|Gr0t3~w-`yHPR7hr368KOiTgfXHDZq){ zqrC+AfkqDi3WW|=sZh1z1C1#FpbtCSukS!(#y%o8MF0wgmi=Yp$~gdsPo17DgfIob z7{Sx+*LNm9@#3ce(%G378fpyd=9h_ z!V~~-5IfsTUT#TqU`a`AAYKo`6hJwWI8#PVMB$KaF5~%}ZH#JGE)uDGEr!R_?7Pz0 zH(ZGe2OsvHaU~tIJ;v3DM-D%6dkfiYrgoG9;+=FrocfIJoBCkUy3yq+&*g3oNZ3gO zyac$J$pv7Xi2EOV{h{6$2I8V#OE18(eT}@at)c_(ed2}2ogj9DX&Quau+l55{rM9t z%>mg0mizvND!5 diff --git a/Plugins/Flow.Launcher.Plugin.Color/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Color/Languages/de.xaml deleted file mode 100644 index 3244dee14..000000000 --- a/Plugins/Flow.Launcher.Plugin.Color/Languages/de.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - - Farben - Stellt eine HEX-Farben Vorschau bereit. (Versuche #000 in Flow Launcher) - - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Color/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Color/Languages/en.xaml deleted file mode 100644 index 85e2830db..000000000 --- a/Plugins/Flow.Launcher.Plugin.Color/Languages/en.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - - Colors - Allows to preview colors using hex values.(Try #000 in Flow Launcher) - - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Color/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.Color/Languages/pl.xaml deleted file mode 100644 index 15525cfe9..000000000 --- a/Plugins/Flow.Launcher.Plugin.Color/Languages/pl.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - - Kolory - Podgląd kolorów po wpisaniu ich kodu szesnastkowego. (Spróbuj wpisać #000 w oknie Flow Launchera) - - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Color/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.Color/Languages/sk.xaml deleted file mode 100644 index 4b208691a..000000000 --- a/Plugins/Flow.Launcher.Plugin.Color/Languages/sk.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - - Farby - Zobrazuje náhľad farieb v HEX formáte. (Skúste #000 vo Flow Launcheri) - - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Color/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.Color/Languages/tr.xaml deleted file mode 100644 index f56e73526..000000000 --- a/Plugins/Flow.Launcher.Plugin.Color/Languages/tr.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - - Renkler - Hex kodunu girdiğiniz renkleri görüntülemeye yarar.(#000 yazmayı deneyin) - - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Color/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.Color/Languages/zh-cn.xaml deleted file mode 100644 index 39ede4844..000000000 --- a/Plugins/Flow.Launcher.Plugin.Color/Languages/zh-cn.xaml +++ /dev/null @@ -1,8 +0,0 @@ - - - 颜色 - 提供在Flow Launcher查询hex颜色。(尝试在Flow Launcher中输入#000) - - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Color/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Color/Languages/zh-tw.xaml deleted file mode 100644 index 4e7062a22..000000000 --- a/Plugins/Flow.Launcher.Plugin.Color/Languages/zh-tw.xaml +++ /dev/null @@ -1,7 +0,0 @@ - - - 顏色 - 提供在 Flow Launcher 查詢 hex 顏色。(試著在 Flow Launcher 中輸入 #000) - diff --git a/Plugins/Flow.Launcher.Plugin.Color/Main.cs b/Plugins/Flow.Launcher.Plugin.Color/Main.cs deleted file mode 100644 index a15483ebc..000000000 --- a/Plugins/Flow.Launcher.Plugin.Color/Main.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Imaging; -using System.IO; -using System.Linq; -using System.Windows; - -namespace Flow.Launcher.Plugin.Color -{ - public sealed class ColorsPlugin : IPlugin, IPluginI18n - { - private string DIR_PATH = Path.Combine(Path.GetTempPath(), @"Plugins\Colors\"); - private PluginInitContext context; - private const int IMG_SIZE = 32; - - private DirectoryInfo ColorsDirectory { get; set; } - - public ColorsPlugin() - { - if (!Directory.Exists(DIR_PATH)) - { - ColorsDirectory = Directory.CreateDirectory(DIR_PATH); - } - else - { - ColorsDirectory = new DirectoryInfo(DIR_PATH); - } - } - - public List Query(Query query) - { - var raw = query.Search; - if (!IsAvailable(raw)) return new List(0); - try - { - var cached = Find(raw); - if (cached.Length == 0) - { - var path = CreateImage(raw); - return new List - { - new Result - { - Title = raw, - IcoPath = path, - Action = _ => - { - Clipboard.SetText(raw); - return true; - } - } - }; - } - return cached.Select(x => new Result - { - Title = raw, - IcoPath = x.FullName, - Action = _ => - { - Clipboard.SetText(raw); - return true; - } - }).ToList(); - } - catch (Exception exception) - { - // todo: log - return new List(0); - } - } - - private bool IsAvailable(string query) - { - // todo: rgb, names - var length = query.Length - 1; // minus `#` sign - return query.StartsWith("#") && (length == 3 || length == 6); - } - - public FileInfo[] Find(string name) - { - var file = string.Format("{0}.png", name.Substring(1)); - return ColorsDirectory.GetFiles(file, SearchOption.TopDirectoryOnly); - } - - private string CreateImage(string name) - { - using (var bitmap = new Bitmap(IMG_SIZE, IMG_SIZE)) - using (var graphics = Graphics.FromImage(bitmap)) - { - var color = ColorTranslator.FromHtml(name); - graphics.Clear(color); - - var path = CreateFileName(name); - bitmap.Save(path, ImageFormat.Png); - return path; - } - } - - private string CreateFileName(string name) - { - return string.Format("{0}{1}.png", ColorsDirectory.FullName, name.Substring(1)); - } - - public void Init(PluginInitContext context) - { - this.context = context; - } - - - public string GetTranslatedPluginTitle() - { - return context.API.GetTranslation("flowlauncher_plugin_color_plugin_name"); - } - - public string GetTranslatedPluginDescription() - { - return context.API.GetTranslation("flowlauncher_plugin_color_plugin_description"); - } - } -} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Color/plugin.json b/Plugins/Flow.Launcher.Plugin.Color/plugin.json deleted file mode 100644 index 8c0c483ba..000000000 --- a/Plugins/Flow.Launcher.Plugin.Color/plugin.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "ID": "9B36CE6181FC47FBB597AA2C29CD9B0A", - "ActionKeyword": "*", - "Name": "Colors", - "Description": "Provide hex color preview.(Try #000 in Flow Launcher)", - "Author": "qianlifeng", - "Version": "1.1.1", - "Language": "csharp", - "Website": "https://github.com/Flow-Launcher/Flow.Launcher", - "ExecuteFileName": "Flow.Launcher.Plugin.Color.dll", - "IcoPath": "Images\\color.png" -} From 85584f40ee51d23e185ee67e4579859017dd1011 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 29 Dec 2020 22:41:21 +1100 Subject: [PATCH 40/95] remove post build script target of JsonRPC folder copy --- Scripts/post_build.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1 index 18ce33c4f..59036842a 100644 --- a/Scripts/post_build.ps1 +++ b/Scripts/post_build.ps1 @@ -36,7 +36,6 @@ function Copy-Resources ($path, $config) { $output = "$path\Output" $target = "$output\$config" Copy-Item -Recurse -Force $project\Images\* $target\Images\ - Copy-Item -Recurse -Force $path\JsonRPC $target\JsonRPC # making version static as multiple versions can exist in the nuget folder and in the case a breaking change is introduced. Copy-Item -Force $env:USERPROFILE\.nuget\packages\squirrel.windows\1.5.2\tools\Squirrel.exe $output\Update.exe } From d28b14ff2d4cb9a8d58d926f9d2542fd22941758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 30 Dec 2020 13:40:42 +0800 Subject: [PATCH 41/95] Replace All use of Json.Net with System.Text.Json --- Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs | 6 ++-- Flow.Launcher.Core/Plugin/PluginConfig.cs | 4 +-- Flow.Launcher.Core/Updater.cs | 1 - Flow.Launcher.Infrastructure/Helper.cs | 28 +++++++++++++------ Flow.Launcher.Infrastructure/Logger/Log.cs | 2 +- .../Storage/JsonStorage.cs | 16 +++++------ .../UserSettings/Settings.cs | 16 ++++++----- Flow.Launcher.Plugin/PluginMetadata.cs | 3 +- Flow.Launcher/Storage/QueryHistory.cs | 1 - Flow.Launcher/Storage/TopMostRecord.cs | 3 +- Flow.Launcher/Storage/UserSelectedRecord.cs | 2 -- .../Search/FolderLinks/FolderLink.cs | 8 +++--- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 8 +----- .../SearchSource.cs | 2 +- .../Settings.cs | 2 +- .../SuggestionSources/Baidu.cs | 20 +++++-------- .../SuggestionSources/Google.cs | 22 ++++++--------- 17 files changed, 67 insertions(+), 77 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs index 31bf04286..3d4522498 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; -using Newtonsoft.Json; using Flow.Launcher.Infrastructure.Exception; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin; @@ -65,7 +65,7 @@ namespace Flow.Launcher.Core.Plugin { List results = new List(); - JsonRPCQueryResponseModel queryResponseModel = JsonConvert.DeserializeObject(output); + JsonRPCQueryResponseModel queryResponseModel = JsonSerializer.Deserialize(output); if (queryResponseModel.Result == null) return null; foreach (JsonRPCResult result in queryResponseModel.Result) @@ -84,7 +84,7 @@ namespace Flow.Launcher.Core.Plugin else { string actionReponse = ExecuteCallback(result1.JsonRPCAction); - JsonRPCRequestModel jsonRpcRequestModel = JsonConvert.DeserializeObject(actionReponse); + JsonRPCRequestModel jsonRpcRequestModel = JsonSerializer.Deserialize(actionReponse); if (jsonRpcRequestModel != null && !String.IsNullOrEmpty(jsonRpcRequestModel.Method) && jsonRpcRequestModel.Method.StartsWith("Flow.Launcher.")) diff --git a/Flow.Launcher.Core/Plugin/PluginConfig.cs b/Flow.Launcher.Core/Plugin/PluginConfig.cs index b946fa44d..46f79c60c 100644 --- a/Flow.Launcher.Core/Plugin/PluginConfig.cs +++ b/Flow.Launcher.Core/Plugin/PluginConfig.cs @@ -2,10 +2,10 @@ using System.Collections.Generic; using System.Linq; using System.IO; -using Newtonsoft.Json; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin; +using System.Text.Json; namespace Flow.Launcher.Core.Plugin { @@ -61,7 +61,7 @@ namespace Flow.Launcher.Core.Plugin PluginMetadata metadata; try { - metadata = JsonConvert.DeserializeObject(File.ReadAllText(configPath)); + metadata = JsonSerializer.Deserialize(File.ReadAllText(configPath)); metadata.PluginDirectory = pluginDirectory; // for plugins which doesn't has ActionKeywords key metadata.ActionKeywords = metadata.ActionKeywords ?? new List { metadata.ActionKeyword }; diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 1e4b0453c..e1aa42730 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -13,7 +13,6 @@ using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; -using System.IO; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using System.Text.Json.Serialization; diff --git a/Flow.Launcher.Infrastructure/Helper.cs b/Flow.Launcher.Infrastructure/Helper.cs index fa7e18533..331b3a823 100644 --- a/Flow.Launcher.Infrastructure/Helper.cs +++ b/Flow.Launcher.Infrastructure/Helper.cs @@ -1,12 +1,19 @@ -using System; +using Newtonsoft.Json.Converters; +using System; using System.IO; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; +using System.Runtime.CompilerServices; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Flow.Launcher.Infrastructure { public static class Helper { + static Helper() + { + jsonFormattedSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + } + /// /// http://www.yinwang.org/blog-cn/2015/11/21/programming-philosophy /// @@ -65,13 +72,18 @@ namespace Flow.Launcher.Infrastructure } } + private static readonly JsonSerializerOptions jsonFormattedSerializerOptions = new JsonSerializerOptions + { + WriteIndented = true + }; + public static string Formatted(this T t) { - var formatted = JsonConvert.SerializeObject( - t, - Formatting.Indented, - new StringEnumConverter() - ); + var formatted = JsonSerializer.Serialize(t, new JsonSerializerOptions + { + WriteIndented = true + }); + return formatted; } } diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs index 289ec5d68..91eeb183d 100644 --- a/Flow.Launcher.Infrastructure/Logger/Log.cs +++ b/Flow.Launcher.Infrastructure/Logger/Log.cs @@ -128,7 +128,7 @@ namespace Flow.Launcher.Infrastructure.Logger public static void Exception(string message, System.Exception e) { #if DEBUG - throw e; + throw e; #else if (FormatValid(message)) { diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs index 784c11110..268dc20b8 100644 --- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs @@ -1,7 +1,7 @@ using System; using System.Globalization; using System.IO; -using Newtonsoft.Json; +using System.Text.Json; using Flow.Launcher.Infrastructure.Logger; namespace Flow.Launcher.Infrastructure.Storage @@ -11,7 +11,7 @@ namespace Flow.Launcher.Infrastructure.Storage /// public class JsonStrorage { - private readonly JsonSerializerSettings _serializerSettings; + private readonly JsonSerializerOptions _serializerSettings; private T _data; // need a new directory name public const string DirectoryName = "Settings"; @@ -24,10 +24,9 @@ namespace Flow.Launcher.Infrastructure.Storage { // use property initialization instead of DefaultValueAttribute // easier and flexible for default value of object - _serializerSettings = new JsonSerializerSettings + _serializerSettings = new JsonSerializerOptions { - ObjectCreationHandling = ObjectCreationHandling.Replace, - NullValueHandling = NullValueHandling.Ignore + IgnoreNullValues = false }; } @@ -56,7 +55,7 @@ namespace Flow.Launcher.Infrastructure.Storage { try { - _data = JsonConvert.DeserializeObject(searlized, _serializerSettings); + _data = JsonSerializer.Deserialize(searlized, _serializerSettings); } catch (JsonException e) { @@ -77,7 +76,7 @@ namespace Flow.Launcher.Infrastructure.Storage BackupOriginFile(); } - _data = JsonConvert.DeserializeObject("{}", _serializerSettings); + _data = JsonSerializer.Deserialize("{}", _serializerSettings); Save(); } @@ -94,7 +93,8 @@ namespace Flow.Launcher.Infrastructure.Storage public void Save() { - string serialized = JsonConvert.SerializeObject(_data, Formatting.Indented); + string serialized = JsonSerializer.Serialize(_data, new JsonSerializerOptions() { WriteIndented = true }); + File.WriteAllText(FilePath, serialized); } } diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 832b6fbfa..bcfe298a9 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -1,8 +1,7 @@ using System; using System.Collections.ObjectModel; using System.Drawing; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; +using System.Text.Json.Serialization; using Flow.Launcher.Plugin; namespace Flow.Launcher.Infrastructure.UserSettings @@ -16,7 +15,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings public bool ShowOpenResultHotkey { get; set; } = true; public string Language { - get => language; set { + get => language; set + { language = value; OnPropertyChanged(); } @@ -73,9 +73,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings public int MaxResultsToShow { get; set; } = 5; public int ActivateTimes { get; set; } - // Order defaults to 0 or -1, so 1 will let this property appear last - [JsonProperty(Order = 1)] - public PluginsSettings PluginSettings { get; set; } = new PluginsSettings(); + public ObservableCollection CustomPluginHotkeys { get; set; } = new ObservableCollection(); public bool DontPromptUpdateMsg { get; set; } @@ -100,8 +98,12 @@ namespace Flow.Launcher.Infrastructure.UserSettings public HttpProxy Proxy { get; set; } = new HttpProxy(); - [JsonConverter(typeof(StringEnumConverter))] + [JsonConverter(typeof(JsonStringEnumConverter))] public LastQueryMode LastQueryMode { get; set; } = LastQueryMode.Selected; + + + // Order defaults to 0 or -1, so 1 will let this property appear last + public PluginsSettings PluginSettings { get; set; } = new PluginsSettings(); } public enum LastQueryMode diff --git a/Flow.Launcher.Plugin/PluginMetadata.cs b/Flow.Launcher.Plugin/PluginMetadata.cs index d81b442e2..4c40be53c 100644 --- a/Flow.Launcher.Plugin/PluginMetadata.cs +++ b/Flow.Launcher.Plugin/PluginMetadata.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; using System.IO; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace Flow.Launcher.Plugin { - [JsonObject(MemberSerialization.OptOut)] public class PluginMetadata : BaseModel { private string _pluginDirectory; diff --git a/Flow.Launcher/Storage/QueryHistory.cs b/Flow.Launcher/Storage/QueryHistory.cs index de3bcaa22..2b2103605 100644 --- a/Flow.Launcher/Storage/QueryHistory.cs +++ b/Flow.Launcher/Storage/QueryHistory.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json; using Flow.Launcher.Plugin; namespace Flow.Launcher.Storage diff --git a/Flow.Launcher/Storage/TopMostRecord.cs b/Flow.Launcher/Storage/TopMostRecord.cs index c110bdf92..09e69f6d8 100644 --- a/Flow.Launcher/Storage/TopMostRecord.cs +++ b/Flow.Launcher/Storage/TopMostRecord.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json; +using System.Text.Json; using Flow.Launcher.Plugin; namespace Flow.Launcher.Storage @@ -8,7 +8,6 @@ namespace Flow.Launcher.Storage // todo this class is not thread safe.... but used from multiple threads. public class TopMostRecord { - [JsonProperty] private Dictionary records = new Dictionary(); internal bool IsTopMost(Result result) diff --git a/Flow.Launcher/Storage/UserSelectedRecord.cs b/Flow.Launcher/Storage/UserSelectedRecord.cs index 1fda04e9b..c7ffe1a1d 100644 --- a/Flow.Launcher/Storage/UserSelectedRecord.cs +++ b/Flow.Launcher/Storage/UserSelectedRecord.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Newtonsoft.Json; using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Plugin; @@ -7,7 +6,6 @@ namespace Flow.Launcher.Storage { public class UserSelectedRecord { - [JsonProperty] private Dictionary records = new Dictionary(); public void Add(Result result) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/FolderLinks/FolderLink.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/FolderLinks/FolderLink.cs index 379b5848f..43ecdad97 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/FolderLinks/FolderLink.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/FolderLinks/FolderLink.cs @@ -1,15 +1,15 @@ -using Newtonsoft.Json; -using System; +using System; using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Flow.Launcher.Plugin.Explorer.Search.FolderLinks { - [JsonObject(MemberSerialization.OptIn)] public class FolderLink { - [JsonProperty] public string Path { get; set; } + [JsonIgnore] public string Nickname { get diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 5b12870c8..e62ea93fc 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -1,28 +1,22 @@ using Flow.Launcher.Plugin.Explorer.Search; using Flow.Launcher.Plugin.Explorer.Search.FolderLinks; -using Newtonsoft.Json; using System.Collections.Generic; +using System.Text.Json.Serialization; namespace Flow.Launcher.Plugin.Explorer { public class Settings { - [JsonProperty] public int MaxResult { get; set; } = 100; - [JsonProperty] public List QuickFolderAccessLinks { get; set; } = new List(); - [JsonProperty] public bool UseWindowsIndexForDirectorySearch { get; set; } = true; - [JsonProperty] public List IndexSearchExcludedSubdirectoryPaths { get; set; } = new List(); - [JsonProperty] public string SearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign; - [JsonProperty] public string FileContentSearchActionKeyword { get; set; } = Constants.DefaultContentSearchActionKeyword; } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs index c7ccb4d51..98e9376fb 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSource.cs @@ -1,10 +1,10 @@ using System.IO; using System.Windows.Media; using JetBrains.Annotations; -using Newtonsoft.Json; using Flow.Launcher.Infrastructure.Image; using Flow.Launcher.Infrastructure; using System.Reflection; +using System.Text.Json.Serialization; namespace Flow.Launcher.Plugin.WebSearch { diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs index 555ee4647..e8881aae9 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs @@ -1,6 +1,6 @@ using System; using System.Collections.ObjectModel; -using Newtonsoft.Json; +using System.Text.Json.Serialization; using Flow.Launcher.Plugin.WebSearch.SuggestionSources; namespace Flow.Launcher.Plugin.WebSearch diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs index 6772acf82..2e385510f 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs @@ -2,10 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Text.Json; using System.Text.RegularExpressions; using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; using System.Net.Http; @@ -35,25 +34,20 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources Match match = _reg.Match(result); if (match.Success) { - JContainer json; + JsonDocument json; try { - json = JsonConvert.DeserializeObject(match.Groups[1].Value) as JContainer; + json = JsonDocument.Parse(match.Groups[1].Value); } - catch (JsonSerializationException e) + catch(JsonException e) { Log.Exception("|Baidu.Suggestions|can't parse suggestions", e); return new List(); } - if (json != null) - { - var results = json["s"] as JArray; - if (results != null) - { - return results.OfType().Select(o => o.Value).OfType().ToList(); - } - } + var results = json?.RootElement.GetProperty("s"); + + return results?.EnumerateArray().Select(o => o.GetString()).ToList() ?? new List(); } return new List(); diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs index 5b9538091..ff0906b87 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs @@ -3,11 +3,10 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; using System.Net.Http; +using System.Text.Json; namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { @@ -27,25 +26,20 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources return new List(); } if (string.IsNullOrEmpty(result)) return new List(); - JContainer json; + JsonDocument json; try { - json = JsonConvert.DeserializeObject(result) as JContainer; + json = JsonDocument.Parse(result); } - catch (JsonSerializationException e) + catch (JsonException e) { Log.Exception("|Google.Suggestions|can't parse suggestions", e); return new List(); } - if (json != null) - { - var results = json[1] as JContainer; - if (results != null) - { - return results.OfType().Select(o => o.Value).OfType().ToList(); - } - } - return new List(); + + var results = json?.RootElement.EnumerateArray().ElementAt(1); + + return results?.EnumerateArray().Select(o => o.GetString()).ToList() ?? new List(); } public override string ToString() From 557842e8d797c3ca0146ed77d0a45906f5c6f3d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 30 Dec 2020 13:48:06 +0800 Subject: [PATCH 42/95] remove dependency --- Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj | 1 - Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj | 1 - 2 files changed, 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index 28d4c0e1f..8153de6c8 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -49,7 +49,6 @@ - diff --git a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj index 70013c274..b7b52ac35 100644 --- a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj +++ b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj @@ -62,7 +62,6 @@ - \ No newline at end of file From 7bbd8c6069ef038186482b50d731cec90396b987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 30 Dec 2020 19:05:02 +0800 Subject: [PATCH 43/95] remove using from Helper.cs --- Flow.Launcher.Infrastructure/Helper.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Helper.cs b/Flow.Launcher.Infrastructure/Helper.cs index 331b3a823..faa4c93b5 100644 --- a/Flow.Launcher.Infrastructure/Helper.cs +++ b/Flow.Launcher.Infrastructure/Helper.cs @@ -1,5 +1,4 @@ -using Newtonsoft.Json.Converters; -using System; +using System; using System.IO; using System.Runtime.CompilerServices; using System.Text.Json; From a0c4cc35756c42d7351bee37c795e063fd933dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 30 Dec 2020 19:09:52 +0800 Subject: [PATCH 44/95] use ParseAsync in Google --- .../SuggestionSources/Google.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs index ff0906b87..f23cb66ff 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs @@ -7,6 +7,7 @@ using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; using System.Net.Http; using System.Text.Json; +using System.IO; namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { @@ -14,22 +15,22 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { public override async Task> Suggestions(string query) { - string result; + Stream resultStream; try { const string api = "https://www.google.com/complete/search?output=chrome&q="; - result = await Http.GetAsync(api + Uri.EscapeUriString(query)).ConfigureAwait(false); + resultStream = await Http.GetStreamAsync(api + Uri.EscapeUriString(query)).ConfigureAwait(false); } catch (HttpRequestException e) { Log.Exception("|Google.Suggestions|Can't get suggestion from google", e); return new List(); } - if (string.IsNullOrEmpty(result)) return new List(); + if (resultStream.Length == 0) return new List(); JsonDocument json; try { - json = JsonDocument.Parse(result); + json = await JsonDocument.ParseAsync(resultStream); } catch (JsonException e) { From a139a040ecc3bca388b77c7c4ba39de35eccd638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 30 Dec 2020 20:24:01 +0800 Subject: [PATCH 45/95] add bing search suggestion --- .../Settings.cs | 3 +- .../SuggestionSources/Bing.cs | 62 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs index 555ee4647..1a3d9e5e5 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Settings.cs @@ -196,7 +196,8 @@ namespace Flow.Launcher.Plugin.WebSearch [JsonIgnore] public SuggestionSource[] Suggestions { get; set; } = { new Google(), - new Baidu() + new Baidu(), + new Bing() }; [JsonIgnore] diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs new file mode 100644 index 000000000..9c4746711 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs @@ -0,0 +1,62 @@ +using Flow.Launcher.Infrastructure.Http; +using Flow.Launcher.Infrastructure.Logger; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Text.Json; +using System.Linq; + +namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources +{ + class Bing : SuggestionSource + { + public override async Task> Suggestions(string query) + { + Stream resultStream; + + try + { + const string api = "https://api.bing.com/qsonhs.aspx?q="; + resultStream = await Http.GetStreamAsync(api + Uri.EscapeUriString(query)).ConfigureAwait(false); + } + catch (HttpRequestException e) + { + Log.Exception("|Bing.Suggestions|Can't get suggestion from Bing", e); + return new List(); + } + + if (resultStream.Length == 0) return new List(); + + JsonElement json; + try + { + json = (await JsonDocument.ParseAsync(resultStream)).RootElement.GetProperty("AS"); + } + catch (JsonException e) + { + Log.Exception("|Bing.Suggestions|can't parse suggestions", e); + return new List(); + } + + if (json.GetProperty("FullResults").GetInt32() == 0) + return new List(); + + return json.GetProperty("Results") + .EnumerateArray() + .SelectMany(r => r.GetProperty("Suggests") + .EnumerateArray() + .Select(s => s.GetProperty("Txt").GetString())) + .ToList(); + + } + + public override string ToString() + { + return "Bing"; + } + } +} From 5c17cb6e9b823482784f7ef0dda0df35f65eb932 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 31 Dec 2020 15:44:57 +1100 Subject: [PATCH 46/95] version bump WebSearch --- Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json index 329f1c41d..99fd2210a 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json @@ -25,7 +25,7 @@ "Name": "Web Searches", "Description": "Provide the web search ability", "Author": "qianlifeng", - "Version": "1.1.2", + "Version": "1.2.0", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.WebSearch.dll", From 27a0b934c612b8d3a482722c53910b7487a973d7 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Fri, 1 Jan 2021 18:39:41 +1100 Subject: [PATCH 47/95] update maintenance badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 02f488758..654877f3a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@

-![Maintenance](https://img.shields.io/maintenance/yes/2020) +![Maintenance](https://img.shields.io/maintenance/yes/2021) [![Build status](https://ci.appveyor.com/api/projects/status/32r7s2skrgm9ubva?svg=true&retina=true)](https://ci.appveyor.com/project/JohnTheGr8/flow-launcher/branch/dev) [![Github All Releases](https://img.shields.io/github/downloads/Flow-Launcher/Flow.Launcher/total.svg)](https://github.com/Flow-Launcher/Flow.Launcher/releases) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/Flow-Launcher/Flow.Launcher)](https://github.com/Flow-Launcher/Flow.Launcher/releases/latest) From a65e17dba00830c32c746d7dea3b737fc518fa7a Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Fri, 1 Jan 2021 18:57:58 +1100 Subject: [PATCH 48/95] fix wrong error message --- Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml | 4 +++- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index 8d24c145c..eaea9783b 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -1,4 +1,4 @@ - @@ -6,6 +6,8 @@ Downloading plugin Please wait... Successfully downloaded + Error downloading plugin + Error occured while trying to download the plugin {0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart. {0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart. Plugin Install diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index ac15618ca..a378a9046 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -134,8 +134,8 @@ namespace Flow.Launcher.Plugin.PluginsManager } catch (Exception e) { - Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), - Context.API.GetTranslation("plugin_pluginsmanager_download_success")); + Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_download_error_title"), + Context.API.GetTranslation("plugin_pluginsmanager_download_error_subtitle")); Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "PluginDownload"); } From 54f6858937fdf3445e8503e7da398bafd0efa4b5 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Fri, 1 Jan 2021 19:03:06 +1100 Subject: [PATCH 49/95] add plugin name to error msg popup --- Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml | 2 +- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index eaea9783b..d0370ddc3 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -7,7 +7,7 @@ Please wait... Successfully downloaded Error downloading plugin - Error occured while trying to download the plugin + Error occured while trying to download {0} {0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart. {0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart. Plugin Install diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index a378a9046..9d9d50902 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -135,7 +135,7 @@ namespace Flow.Launcher.Plugin.PluginsManager catch (Exception e) { Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_download_error_title"), - Context.API.GetTranslation("plugin_pluginsmanager_download_error_subtitle")); + string.Format(Context.API.GetTranslation("plugin_pluginsmanager_download_error_subtitle"), plugin.Name)); Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "PluginDownload"); } From cab1b93183d4a8170f3b589354e1159b8e92cd7c Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Fri, 1 Jan 2021 19:13:14 +1100 Subject: [PATCH 50/95] move install method into try catch --- .../Languages/en.xaml | 4 ++-- .../PluginsManager.cs | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index d0370ddc3..3017f39c3 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -6,13 +6,13 @@ Downloading plugin Please wait... Successfully downloaded - Error downloading plugin - Error occured while trying to download {0} {0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart. {0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart. Plugin Install Plugin Uninstall Install failed: unable to find the plugin.json metadata file from the new plugin + Error installing plugin + Error occured while trying to install {0} No update available All plugins are up to date {0} by {1} {2}{3}Would you like to update this plugin? After the update Flow will automatically restart. diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 9d9d50902..db0327111 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -131,16 +131,17 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), Context.API.GetTranslation("plugin_pluginsmanager_download_success")); + + Install(plugin, filePath); } catch (Exception e) { - Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_download_error_title"), - string.Format(Context.API.GetTranslation("plugin_pluginsmanager_download_error_subtitle"), plugin.Name)); + Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), + string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), plugin.Name)); - Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "PluginDownload"); + Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "InstallOrUpdate"); } - Install(plugin, filePath); Context.API.RestartApp(); } From 878f7bf5dfb154a2bf663deaf9256ce73ba3de1d Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Fri, 1 Jan 2021 19:49:19 +1100 Subject: [PATCH 51/95] version bump for 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 d94af71a1..7e78d65d6 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.3.1", + "Version": "1.3.2", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll", From 81cb20bf91edb292eb35445861a25acec31a2445 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Fri, 1 Jan 2021 21:54:34 +1100 Subject: [PATCH 52/95] add return to continue --- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index db0327111..880157a77 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -140,6 +140,8 @@ namespace Flow.Launcher.Plugin.PluginsManager string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), plugin.Name)); Log.Exception("PluginsManager", "An error occured while downloading plugin", e, "InstallOrUpdate"); + + return; } Context.API.RestartApp(); From 6d66aa3f4415f114f44bb6b962651f5d269783f6 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 2 Jan 2021 00:06:55 +1100 Subject: [PATCH 53/95] fix script to delete with condition dll version is same --- Scripts/post_build.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1 index 59036842a..b20393b02 100644 --- a/Scripts/post_build.ps1 +++ b/Scripts/post_build.ps1 @@ -44,8 +44,9 @@ function Delete-Unused ($path, $config) { $target = "$path\Output\$config" $included = Get-ChildItem $target -Filter "*.dll" foreach ($i in $included){ - Remove-Item -Path $target\Plugins -Include $i -Recurse - Write-Host "Deleting duplicated $i" + $deleteList = Get-ChildItem $target\Plugins -Include $i -Recurse | Where {$_.VersionInfo.FileVersion -eq $i.VersionInfo.FileVersion} + $deleteList | foreach-object{ Write-Host Deleting duplicated $_.Name with version $_.VersionInfo.FileVersion at location $_.Directory.FullName } + $deleteList | Remove-Item } Remove-Item -Path $target -Include "*.xml" -Recurse } From 29a382085fde4f5ac5ea173b5ccf338258d0c029 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 2 Jan 2021 00:09:02 +1100 Subject: [PATCH 54/95] method name update --- Scripts/post_build.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1 index b20393b02..e0868f3bb 100644 --- a/Scripts/post_build.ps1 +++ b/Scripts/post_build.ps1 @@ -45,7 +45,7 @@ function Delete-Unused ($path, $config) { $included = Get-ChildItem $target -Filter "*.dll" foreach ($i in $included){ $deleteList = Get-ChildItem $target\Plugins -Include $i -Recurse | Where {$_.VersionInfo.FileVersion -eq $i.VersionInfo.FileVersion} - $deleteList | foreach-object{ Write-Host Deleting duplicated $_.Name with version $_.VersionInfo.FileVersion at location $_.Directory.FullName } + $deleteList | ForEach-Object{ Write-Host Deleting duplicated $_.Name with version $_.VersionInfo.FileVersion at location $_.Directory.FullName } $deleteList | Remove-Item } Remove-Item -Path $target -Include "*.xml" -Recurse From f1badd6ae20466ab720b516d544a4b5f58b64dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=BC=98=E9=9F=AC?= Date: Fri, 1 Jan 2021 21:19:05 +0800 Subject: [PATCH 55/95] Add Exception Handling for Querying plugins results --- Flow.Launcher/ViewModel/MainViewModel.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 7a3aa9f2f..2a69635bb 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -21,6 +21,7 @@ using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Storage; using System.Windows.Media; using Flow.Launcher.Infrastructure.Image; +using Flow.Launcher.Infrastructure.Logger; namespace Flow.Launcher.ViewModel { @@ -414,8 +415,15 @@ namespace Flow.Launcher.ViewModel { if (!plugin.Metadata.Disabled) { - var results = PluginManager.QueryForPlugin(plugin, query); - UpdateResultView(results, plugin.Metadata, query); + try + { + var results = PluginManager.QueryForPlugin(plugin, query); + UpdateResultView(results, plugin.Metadata, query); + } + catch(Exception e) + { + Log.Exception($"|MainViewModel|Exception when querying {plugin.Metadata.Name}", e); + } } }); } @@ -432,7 +440,10 @@ namespace Flow.Launcher.ViewModel { // update to hidden if this is still the current query ProgressBarVisibility = Visibility.Hidden; } - }, currentCancellationToken); + }, currentCancellationToken).ContinueWith(t => + { + Log.Exception("|MainViewModel|Error when querying plugin", t.Exception?.InnerException); + }, TaskContinuationOptions.OnlyOnFaulted); } } else From f3355c525dfbdaa46ece70cb5197826c1bf354e9 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Fri, 1 Jan 2021 23:15:37 +0200 Subject: [PATCH 56/95] fix: properly include all plugin translation files --- ...low.Launcher.Plugin.BrowserBookmark.csproj | 9 +--- .../Flow.Launcher.Plugin.Calculator.csproj | 44 +----------------- .../Flow.Launcher.Plugin.ControlPanel.csproj | 45 +------------------ .../Flow.Launcher.Plugin.Explorer.csproj | 32 +------------ ...low.Launcher.Plugin.PluginIndicator.csproj | 42 +---------------- .../Flow.Launcher.Plugin.ProcessKiller.csproj | 2 +- .../Flow.Launcher.Plugin.Program.csproj | 27 +---------- .../Flow.Launcher.Plugin.Shell.csproj | 39 ++-------------- .../Flow.Launcher.Plugin.Sys.csproj | 27 +---------- .../Flow.Launcher.Plugin.Url.csproj | 36 +-------------- .../Flow.Launcher.Plugin.WebSearch.csproj | 27 +---------- 11 files changed, 17 insertions(+), 313 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 85b745a6b..f308aa49a 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -43,11 +43,6 @@ Always - - Designer - MSBuild:Compile - PreserveNewest - Always @@ -60,9 +55,9 @@
- + - + MSBuild:Compile Designer PreserveNewest diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj index 9e1fefdb3..983ac160e 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj @@ -49,49 +49,9 @@ PreserveNewest - + - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - + MSBuild:Compile Designer PreserveNewest diff --git a/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj b/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj index 699737634..dce54cb52 100644 --- a/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj +++ b/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj @@ -48,50 +48,7 @@ PreserveNewest - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - + MSBuild:Compile Designer PreserveNewest diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj index a1a08843a..a9f675be8 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -62,37 +62,7 @@ PreserveNewest - - MSBuild:Compile - Designer - PreserveNewest - - - - MSBuild:Compile - Designer - PreserveNewest - - - - MSBuild:Compile - Designer - PreserveNewest - - - - MSBuild:Compile - Designer - PreserveNewest - - - - MSBuild:Compile - Designer - PreserveNewest - - - + MSBuild:Compile Designer PreserveNewest diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj index e6bfa7aa3..6abfc8469 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj @@ -52,47 +52,7 @@ - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - + MSBuild:Compile Designer PreserveNewest diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj index cf9c96294..a393d8510 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj @@ -39,7 +39,7 @@ PreserveNewest - + Designer MSBuild:Compile PreserveNewest diff --git a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj index 3802297c7..7e1b36fc1 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj +++ b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj @@ -68,35 +68,10 @@ Always - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - + MSBuild:Compile Designer PreserveNewest diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj index 178d95010..316742bf6 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj +++ b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj @@ -33,32 +33,6 @@ 4 false - - - - Always - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - @@ -72,18 +46,13 @@ + + Always + PreserveNewest - - - - - MSBuild:Compile - Designer - PreserveNewest - - + MSBuild:Compile Designer PreserveNewest diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj index bdab40457..61635dd08 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj +++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj @@ -52,32 +52,7 @@ PreserveNewest - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - + MSBuild:Compile Designer PreserveNewest diff --git a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj index 7d802d815..fb40c1e17 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj +++ b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj @@ -50,41 +50,9 @@ PreserveNewest - + - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - - MSBuild:Compile - Designer - PreserveNewest - - - - - + MSBuild:Compile Designer PreserveNewest diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj index 431ca9ce8..e3bb4b408 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj @@ -89,32 +89,7 @@ PreserveNewest - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - - MSBuild:Compile - Designer - PreserveNewest - - + MSBuild:Compile Designer PreserveNewest From 8ab528c380acd0515b6576e74f76300763bd3bd6 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Sat, 2 Jan 2021 00:00:12 +0200 Subject: [PATCH 57/95] fix slovak translation --- Flow.Launcher/Languages/sk.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml index bf001d507..85fc1462c 100644 --- a/Flow.Launcher/Languages/sk.xaml +++ b/Flow.Launcher/Languages/sk.xaml @@ -45,8 +45,8 @@ Nová akcia skratky: Priečinok s pluginmi Autor - Príprava: {0}ms - Čas dopytu: {0}ms + Príprava: + Čas dopytu: Motív From 75f5a81a31ead865464f6a11f61f4c8fcf8d7cb6 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 2 Jan 2021 11:55:06 +1100 Subject: [PATCH 58/95] update exception message --- Flow.Launcher/ViewModel/MainViewModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 2a69635bb..eed30f377 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -422,7 +422,7 @@ namespace Flow.Launcher.ViewModel } catch(Exception e) { - Log.Exception($"|MainViewModel|Exception when querying {plugin.Metadata.Name}", e); + Log.Exception("MainViewModel", $"Exception when querying the plugin {plugin.Metadata.Name}", e, "QueryResults"); } } }); @@ -442,7 +442,7 @@ namespace Flow.Launcher.ViewModel } }, currentCancellationToken).ContinueWith(t => { - Log.Exception("|MainViewModel|Error when querying plugin", t.Exception?.InnerException); + Log.Exception("MainViewModel", "Error when querying plugins", t.Exception?.InnerException, "QueryResults"); }, TaskContinuationOptions.OnlyOnFaulted); } } From 041bf4e9c4860b9114a95741fcb036d2f969d208 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 2 Jan 2021 12:10:06 +1100 Subject: [PATCH 59/95] add condition to match name also --- Scripts/post_build.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1 index e0868f3bb..836e27380 100644 --- a/Scripts/post_build.ps1 +++ b/Scripts/post_build.ps1 @@ -44,7 +44,7 @@ function Delete-Unused ($path, $config) { $target = "$path\Output\$config" $included = Get-ChildItem $target -Filter "*.dll" foreach ($i in $included){ - $deleteList = Get-ChildItem $target\Plugins -Include $i -Recurse | Where {$_.VersionInfo.FileVersion -eq $i.VersionInfo.FileVersion} + $deleteList = Get-ChildItem $target\Plugins -Include $i -Recurse | Where { $_.VersionInfo.FileVersion -eq $i.VersionInfo.FileVersion -And $_.Name -eq "$i" } $deleteList | ForEach-Object{ Write-Host Deleting duplicated $_.Name with version $_.VersionInfo.FileVersion at location $_.Directory.FullName } $deleteList | Remove-Item } From be1776fd2153f6bc9fbefbce71b313ea9ab9789e Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 2 Jan 2021 12:47:20 +1100 Subject: [PATCH 60/95] version bump for plugins --- Plugins/Flow.Launcher.Plugin.BrowserBookmark/plugin.json | 2 +- Plugins/Flow.Launcher.Plugin.Calculator/plugin.json | 2 +- Plugins/Flow.Launcher.Plugin.ControlPanel/plugin.json | 2 +- Plugins/Flow.Launcher.Plugin.Explorer/plugin.json | 2 +- Plugins/Flow.Launcher.Plugin.PluginIndicator/plugin.json | 2 +- .../Flow.Launcher.Plugin.PluginsManager.csproj | 2 +- Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json | 2 +- Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json | 2 +- Plugins/Flow.Launcher.Plugin.Program/plugin.json | 2 +- Plugins/Flow.Launcher.Plugin.Shell/plugin.json | 2 +- Plugins/Flow.Launcher.Plugin.Sys/plugin.json | 2 +- Plugins/Flow.Launcher.Plugin.Url/plugin.json | 2 +- Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/plugin.json b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/plugin.json index de4f3849b..b0c3d2e29 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/plugin.json @@ -4,7 +4,7 @@ "Name": "Browser Bookmarks", "Description": "Search your browser bookmarks", "Author": "qianlifeng, Ioannis G.", - "Version": "1.3.1", + "Version": "1.3.2", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.BrowserBookmark.dll", diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json b/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json index 709757d1a..7d9ca58d5 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json @@ -4,7 +4,7 @@ "Name": "Calculator", "Description": "Provide mathematical calculations.(Try 5*3-2 in Flow Launcher)", "Author": "cxfksword", - "Version": "1.1.3", + "Version": "1.1.4", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Caculator.dll", diff --git a/Plugins/Flow.Launcher.Plugin.ControlPanel/plugin.json b/Plugins/Flow.Launcher.Plugin.ControlPanel/plugin.json index 4f552a014..23f35e9ac 100644 --- a/Plugins/Flow.Launcher.Plugin.ControlPanel/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.ControlPanel/plugin.json @@ -4,7 +4,7 @@ "Name": "Control Panel", "Description": "Search within the Control Panel.", "Author": "CoenraadS", - "Version": "1.1.1", + "Version": "1.1.2", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.ControlPanel.dll", diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json index 2c57ac668..aa44c4413 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json @@ -7,7 +7,7 @@ "Name": "Explorer", "Description": "Search and manage files and folders. Explorer utilises Windows Index Search", "Author": "Jeremy Wu", - "Version": "1.2.5", + "Version": "1.2.6", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Explorer.dll", diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/plugin.json b/Plugins/Flow.Launcher.Plugin.PluginIndicator/plugin.json index 80900a445..7f73263a8 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/plugin.json @@ -4,7 +4,7 @@ "Name": "Plugin Indicator", "Description": "Provide plugin actionword suggestion", "Author": "qianlifeng", - "Version": "1.1.1", + "Version": "1.1.2", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.PluginIndicator.dll", diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj index cc1a931ce..7beb8308b 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj @@ -35,7 +35,7 @@ - + PreserveNewest diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json b/Plugins/Flow.Launcher.Plugin.PluginsManager/plugin.json index d94af71a1..7e78d65d6 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.3.1", + "Version": "1.3.2", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll", diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json b/Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json index d769397a8..2bb40c644 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json @@ -4,7 +4,7 @@ "Name":"Process Killer", "Description":"kill running processes from Flow", "Author":"Flow-Launcher", - "Version":"1.2.1", + "Version":"1.2.2", "Language":"csharp", "Website":"https://github.com/Flow-Launcher/Flow.Launcher.Plugin.ProcessKiller", "IcoPath":"Images\\app.png", diff --git a/Plugins/Flow.Launcher.Plugin.Program/plugin.json b/Plugins/Flow.Launcher.Plugin.Program/plugin.json index 7d7a42e03..6c2c18e47 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Program/plugin.json @@ -4,7 +4,7 @@ "Name": "Program", "Description": "Search programs in Flow.Launcher", "Author": "qianlifeng", - "Version": "1.2.2", + "Version": "1.2.3", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Program.dll", diff --git a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json index 63e74d678..4ad572cf6 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Shell/plugin.json @@ -4,7 +4,7 @@ "Name": "Shell", "Description": "Provide executing commands from Flow Launcher. Commands should start with >", "Author": "qianlifeng", - "Version": "1.1.1", + "Version": "1.1.2", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Shell.dll", diff --git a/Plugins/Flow.Launcher.Plugin.Sys/plugin.json b/Plugins/Flow.Launcher.Plugin.Sys/plugin.json index 8d4b9a238..cf8ed6041 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Sys/plugin.json @@ -4,7 +4,7 @@ "Name": "System Commands", "Description": "Provide System related commands. e.g. shutdown,lock,setting etc.", "Author": "qianlifeng", - "Version": "1.1.1", + "Version": "1.1.2", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Sys.dll", diff --git a/Plugins/Flow.Launcher.Plugin.Url/plugin.json b/Plugins/Flow.Launcher.Plugin.Url/plugin.json index be64f6708..89dc20a33 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Url/plugin.json @@ -4,7 +4,7 @@ "Name": "URL", "Description": "Open the typed URL from Flow Launcher", "Author": "qianlifeng", - "Version": "1.1.1", + "Version": "1.1.2", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Url.dll", diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json index 99fd2210a..c036fbf8b 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json @@ -25,7 +25,7 @@ "Name": "Web Searches", "Description": "Provide the web search ability", "Author": "qianlifeng", - "Version": "1.2.0", + "Version": "1.2.1", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.WebSearch.dll", From 08f97f0ef9236e4572d7a707741488cddb568d38 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 2 Jan 2021 12:57:13 +1100 Subject: [PATCH 61/95] change csproj images folder to use wildcard --- ...low.Launcher.Plugin.BrowserBookmark.csproj | 6 +- .../Flow.Launcher.Plugin.Calculator.csproj | 9 +-- .../Flow.Launcher.Plugin.ControlPanel.csproj | 4 +- .../Flow.Launcher.Plugin.Explorer.csproj | 35 +---------- ...low.Launcher.Plugin.PluginIndicator.csproj | 9 +-- ...Flow.Launcher.Plugin.PluginsManager.csproj | 9 +-- .../Flow.Launcher.Plugin.ProcessKiller.csproj | 6 +- .../Flow.Launcher.Plugin.Program.csproj | 21 +------ .../Flow.Launcher.Plugin.Shell.csproj | 9 +-- .../Flow.Launcher.Plugin.Sys.csproj | 50 +-------------- .../Flow.Launcher.Plugin.Url.csproj | 9 +-- .../Flow.Launcher.Plugin.WebSearch.csproj | 63 +------------------ 12 files changed, 33 insertions(+), 197 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index f308aa49a..d2a8736a6 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -40,9 +40,6 @@ - - Always - Always @@ -62,6 +59,9 @@ Designer PreserveNewest + + PreserveNewest + diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj index 983ac160e..06d8dea7d 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj @@ -43,12 +43,6 @@ - - - - PreserveNewest - - @@ -56,6 +50,9 @@ Designer PreserveNewest + + PreserveNewest + diff --git a/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj b/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj index dce54cb52..06969a135 100644 --- a/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj +++ b/Plugins/Flow.Launcher.Plugin.ControlPanel/Flow.Launcher.Plugin.ControlPanel.csproj @@ -45,9 +45,9 @@ - + PreserveNewest - + MSBuild:Compile Designer diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj index a9f675be8..9d9c09a93 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -26,42 +26,9 @@ - - PreserveNewest - - - - PreserveNewest - - - - PreserveNewest - - - - PreserveNewest - - - - Always - - - + PreserveNewest - - - PreserveNewest - - - - PreserveNewest - - - - PreserveNewest - - MSBuild:Compile Designer diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj index 6abfc8469..0140444e1 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj @@ -45,18 +45,15 @@ - - - PreserveNewest - - - MSBuild:Compile Designer PreserveNewest + + PreserveNewest + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj index 7beb8308b..2e352d832 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj @@ -27,17 +27,14 @@ PreserveNewest - - - - PreserveNewest - - PreserveNewest + + PreserveNewest + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj index a393d8510..a643ebf86 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj @@ -36,14 +36,14 @@ - - PreserveNewest - Designer MSBuild:Compile PreserveNewest + + PreserveNewest + Always diff --git a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj index 7e1b36fc1..12e113855 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj +++ b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj @@ -52,30 +52,15 @@ - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - Always - - - MSBuild:Compile Designer PreserveNewest + + PreserveNewest + diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj index 316742bf6..c542dc89b 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj +++ b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj @@ -46,17 +46,14 @@ - - Always - - - PreserveNewest - MSBuild:Compile Designer PreserveNewest + + PreserveNewest + MSBuild:Compile Designer diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj index 61635dd08..8ef4dc0fb 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj +++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj @@ -40,23 +40,14 @@ - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - MSBuild:Compile Designer PreserveNewest + + PreserveNewest + MSBuild:Compile Designer @@ -68,39 +59,4 @@ PreserveNewest - - - - PreserveNewest - - - - - - PreserveNewest - - - - - - PreserveNewest - - - - - - PreserveNewest - - - - - - PreserveNewest - - - - - - - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj index fb40c1e17..671a8b1c2 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj +++ b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj @@ -44,12 +44,6 @@ - - - - PreserveNewest - - @@ -57,6 +51,9 @@ Designer PreserveNewest + + PreserveNewest + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj index e3bb4b408..af86af842 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj @@ -35,65 +35,14 @@ - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - MSBuild:Compile Designer PreserveNewest + + PreserveNewest + MSBuild:Compile Designer @@ -109,12 +58,6 @@ PreserveNewest - - - - PreserveNewest - - From 482988c288392af9b1bf2a911a6eb798c54f11ff Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 2 Jan 2021 12:59:58 +1100 Subject: [PATCH 62/95] use wild card to include images for main project --- Flow.Launcher/Flow.Launcher.csproj | 108 +---------------------------- 1 file changed, 3 insertions(+), 105 deletions(-) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 8548ba39e..39b2087aa 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -60,6 +60,9 @@ Designer PreserveNewest + + PreserveNewest + @@ -87,111 +90,6 @@ - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - From 97ac42751717121f5db1c695b81d5aed98df191f Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 2 Jan 2021 16:58:23 +1100 Subject: [PATCH 63/95] add manual reload of PluginsManifest data --- Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index d700b9dfd..7c1eda3aa 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -10,7 +10,7 @@ using System.Threading.Tasks; namespace Flow.Launcher.Plugin.PluginsManager { - public class Main : ISettingProvider, IPlugin, ISavable, IContextMenu, IPluginI18n + public class Main : ISettingProvider, IPlugin, ISavable, IContextMenu, IPluginI18n, IReloadable { internal PluginInitContext Context { get; set; } @@ -87,5 +87,14 @@ namespace Flow.Launcher.Plugin.PluginsManager { return Context.API.GetTranslation("plugin_pluginsmanager_plugin_description"); } + + public void ReloadData() + { + Task.Run(async () => + { + await pluginManager.UpdateManifest(); + lastUpdateTime = DateTime.Now; + }); + } } } From 661c64b1c21b5e744ac4029b68e70d095a2074e2 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 2 Jan 2021 17:00:10 +1100 Subject: [PATCH 64/95] version bump for 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 7e78d65d6..f5bbf3f6b 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.3.2", + "Version": "1.4.0", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll", From b4b30dd34da9426a6f512966fca780c5d5ef1437 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 2 Jan 2021 18:06:44 +1100 Subject: [PATCH 65/95] wait manifest update before proceeding --- Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 7c1eda3aa..f10f022d7 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -90,11 +90,8 @@ namespace Flow.Launcher.Plugin.PluginsManager public void ReloadData() { - Task.Run(async () => - { - await pluginManager.UpdateManifest(); - lastUpdateTime = DateTime.Now; - }); + Task.Run(() => pluginManager.UpdateManifest()).Wait(); + lastUpdateTime = DateTime.Now; } } } From d369108b0b17d05c300919d7f20e296c5322b731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Sun, 3 Jan 2021 20:40:18 +0800 Subject: [PATCH 66/95] Error handling for plugin update --- .../PluginsManager.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 880157a77..4debf5598 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -214,11 +214,19 @@ namespace Flow.Launcher.Plugin.PluginsManager Task.Run(async delegate { + Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), + Context.API.GetTranslation("plugin_pluginsmanager_please_wait")); + await Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath).ConfigureAwait(false); + + Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), + Context.API.GetTranslation("plugin_pluginsmanager_download_success")); + Install(x.PluginNewUserPlugin, downloadToFilePath); Context.API.RestartApp(); - }); + }).ContinueWith(t => Log.Exception($"|PluginsManager|Update fail for {x.Name}", t.Exception.InnerException), + TaskContinuationOptions.OnlyOnFaulted); return true; } From 8fa1e2e33f4355766282ca6934e3a279b8a3b8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Sun, 3 Jan 2021 20:49:14 +0800 Subject: [PATCH 67/95] add one more message --- .../Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 4debf5598..9cef704a6 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -225,8 +225,12 @@ namespace Flow.Launcher.Plugin.PluginsManager Install(x.PluginNewUserPlugin, downloadToFilePath); Context.API.RestartApp(); - }).ContinueWith(t => Log.Exception($"|PluginsManager|Update fail for {x.Name}", t.Exception.InnerException), - TaskContinuationOptions.OnlyOnFaulted); + }).ContinueWith(t => + { + Log.Exception($"|PluginsManager|Update fail for {x.Name}", t.Exception.InnerException); + Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), + string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), x.Name)); + }, TaskContinuationOptions.OnlyOnFaulted); return true; } From d35a3bb43d05cf19b1fd46ef3577376941b7ed44 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Mon, 4 Jan 2021 06:40:45 +1100 Subject: [PATCH 68/95] version bump for 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 f5bbf3f6b..ef2c1255a 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.4.0", + "Version": "1.4.1", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.PluginsManager.dll", From 6287358275e01457fabf0e2482343836a80bb9dd Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Mon, 4 Jan 2021 06:41:05 +1100 Subject: [PATCH 69/95] update error message --- Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 9cef704a6..724ddf20d 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -227,7 +227,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.RestartApp(); }).ContinueWith(t => { - Log.Exception($"|PluginsManager|Update fail for {x.Name}", t.Exception.InnerException); + Log.Exception("PluginsManager", $"Update failed for {x.Name}", t.Exception.InnerException, "RequestUpdate"); Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), x.Name)); }, TaskContinuationOptions.OnlyOnFaulted); From a8dc1599d746d88c8ce28ac551abb0e02bf6a90d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 4 Jan 2021 10:28:33 +0800 Subject: [PATCH 70/95] Add Http Error Handling --- Flow.Launcher.Infrastructure/Http/Http.cs | 44 +++++++++++++++++------ 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 8e2832690..b796d807c 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -91,7 +91,7 @@ namespace Flow.Launcher.Infrastructure.Http /// /// Asynchrously get the result as string from url. - /// When supposing the result is long and large, try using GetStreamAsync to avoid reading as string + /// When supposing the result larger than 83kb, try using GetStreamAsync to avoid reading as string /// /// /// @@ -101,19 +101,33 @@ namespace Flow.Launcher.Infrastructure.Http return GetAsync(new Uri(url.Replace("#", "%23"))); } + /// + /// Asynchrously get the result as string from url. + /// When supposing the result larger than 83kb, try using GetStreamAsync to avoid reading as string + /// + /// + /// public static async Task GetAsync([NotNull] Uri url) { Log.Debug($"|Http.Get|Url <{url}>"); - using var response = await client.GetAsync(url); - var content = await response.Content.ReadAsStringAsync(); - if (response.StatusCode == HttpStatusCode.OK) + try { - return content; + using var response = await client.GetAsync(url); + var content = await response.Content.ReadAsStringAsync(); + if (response.StatusCode == HttpStatusCode.OK) + { + return content; + } + else + { + throw new HttpRequestException( + $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); + } } - else + catch (HttpRequestException e) { - throw new HttpRequestException( - $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); + Log.Exception("Infrastructure.Http", "Http Request Error", e, "GetAsync"); + throw; } } @@ -124,9 +138,17 @@ namespace Flow.Launcher.Infrastructure.Http /// public static async Task GetStreamAsync([NotNull] string url) { - Log.Debug($"|Http.Get|Url <{url}>"); - var response = await client.GetAsync(url); - return await response.Content.ReadAsStreamAsync(); + try + { + Log.Debug($"|Http.Get|Url <{url}>"); + var response = await client.GetAsync(url); + return await response.Content.ReadAsStreamAsync(); + } + catch (HttpRequestException e) + { + Log.Exception("Infrastructure.Http", "Http Request Error", e, "GetStreamAsync"); + throw; + } } } } From bc63b9ebfa100426176603ba6c7009b72dd3502e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 4 Jan 2021 10:31:05 +0800 Subject: [PATCH 71/95] Change Download to DownloadAsync Add error handling for download as well --- Flow.Launcher.Infrastructure/Http/Http.cs | 22 +++++++++++++------ .../PluginsManager.cs | 4 ++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index b796d807c..78fa099c9 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -75,17 +75,25 @@ namespace Flow.Launcher.Infrastructure.Http }; } - public static async Task Download([NotNull] string url, [NotNull] string filePath) + public static async Task DownloadAsync([NotNull] string url, [NotNull] string filePath) { - using var response = await client.GetAsync(url); - if (response.StatusCode == HttpStatusCode.OK) + try { - await using var fileStream = new FileStream(filePath, FileMode.CreateNew); - await response.Content.CopyToAsync(fileStream); + using var response = await client.GetAsync(url); + if (response.StatusCode == HttpStatusCode.OK) + { + await using var fileStream = new FileStream(filePath, FileMode.CreateNew); + await response.Content.CopyToAsync(fileStream); + } + else + { + throw new HttpRequestException($"Error code <{response.StatusCode}> returned from <{url}>"); + } } - else + catch (HttpRequestException e) { - throw new HttpRequestException($"Error code <{response.StatusCode}> returned from <{url}>"); + Log.Exception("Infrastructure.Http", "Http Request Error", e, "DownloadAsync"); + throw; } } diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 724ddf20d..68df5bc1f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -127,7 +127,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), Context.API.GetTranslation("plugin_pluginsmanager_please_wait")); - await Http.Download(plugin.UrlDownload, filePath).ConfigureAwait(false); + await Http.DownloadAsync(plugin.UrlDownload, filePath).ConfigureAwait(false); Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), Context.API.GetTranslation("plugin_pluginsmanager_download_success")); @@ -217,7 +217,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), Context.API.GetTranslation("plugin_pluginsmanager_please_wait")); - await Http.Download(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath).ConfigureAwait(false); + await Http.DownloadAsync(x.PluginNewUserPlugin.UrlDownload, downloadToFilePath).ConfigureAwait(false); Context.API.ShowMsg(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), Context.API.GetTranslation("plugin_pluginsmanager_download_success")); From fb640b68c8e5a49e105e0666ce77e057c1a43735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 4 Jan 2021 11:05:59 +0800 Subject: [PATCH 72/95] Use ValueTask instead of Task --- Flow.Launcher/ViewModel/ResultViewModel.cs | 25 ++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index 00a0e1ae5..20d32890b 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Media; @@ -12,7 +13,7 @@ namespace Flow.Launcher.ViewModel { public class ResultViewModel : BaseModel { - public class LazyAsync : Lazy> + public class LazyAsync : Lazy> { private T defaultValue; @@ -23,21 +24,27 @@ namespace Flow.Launcher.ViewModel { if (!IsValueCreated) { - base.Value.ContinueWith(_ => - { - _updateCallback(); - }); + _ = Exercute(); return defaultValue; } - + if (!base.Value.IsCompleted || base.Value.IsFaulted) return defaultValue; return base.Value.Result; + + // If none of the variables captured by the local function are captured by other lambdas + // , the compiler can avoid heap allocations. + async ValueTask Exercute() + { + await base.Value.ConfigureAwait(false); + _updateCallback(); + } + } } - public LazyAsync(Func> factory, T defaultValue, Action updateCallback) : base(factory) + public LazyAsync(Func> factory, T defaultValue, Action updateCallback) : base(factory) { if (defaultValue != null) { @@ -55,7 +62,7 @@ namespace Flow.Launcher.ViewModel Result = result; Image = new LazyAsync( - SetImage, + SetImage, ImageLoader.DefaultImage, () => { @@ -82,7 +89,7 @@ namespace Flow.Launcher.ViewModel public LazyAsync Image { get; set; } - private async Task SetImage() + private async ValueTask SetImage() { var imagePath = Result.IcoPath; if (string.IsNullOrEmpty(imagePath) && Result.Icon != null) From 7967844cf381563c362f2d91bcac73342b3f5237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 4 Jan 2021 11:10:02 +0800 Subject: [PATCH 73/95] make defaultValue readonly and edit comment --- Flow.Launcher/ViewModel/ResultViewModel.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index 20d32890b..d1b03f911 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -15,7 +15,7 @@ namespace Flow.Launcher.ViewModel { public class LazyAsync : Lazy> { - private T defaultValue; + private readonly T defaultValue; private readonly Action _updateCallback; public new T Value @@ -24,7 +24,7 @@ namespace Flow.Launcher.ViewModel { if (!IsValueCreated) { - _ = Exercute(); + _ = Exercute(); // manually use callback strategy return defaultValue; } @@ -34,8 +34,8 @@ namespace Flow.Launcher.ViewModel return base.Value.Result; - // If none of the variables captured by the local function are captured by other lambdas - // , the compiler can avoid heap allocations. + // If none of the variables captured by the local function are captured by other lambdas, + // the compiler can avoid heap allocations. async ValueTask Exercute() { await base.Value.ConfigureAwait(false); From fc015245b3392664f4b630a6a10a68b85d05bc2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 4 Jan 2021 16:22:48 +0800 Subject: [PATCH 74/95] Change the way checking successfuly --- Flow.Launcher/ViewModel/ResultViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index d1b03f911..9eece1a97 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -29,7 +29,7 @@ namespace Flow.Launcher.ViewModel return defaultValue; } - if (!base.Value.IsCompleted || base.Value.IsFaulted) + if (!base.Value.IsCompletedSuccessfully) return defaultValue; return base.Value.Result; From 6703e0d137b3fcd03c8fdb16644df7fa5645b24b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Mon, 4 Jan 2021 16:31:48 +0800 Subject: [PATCH 75/95] Return default image when loading UWP icon fail --- Flow.Launcher/ViewModel/ResultViewModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index 9eece1a97..4c65f2b9f 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -68,7 +68,7 @@ namespace Flow.Launcher.ViewModel { OnPropertyChanged(nameof(Image)); }); - } + } Settings = settings; } @@ -101,7 +101,7 @@ namespace Flow.Launcher.ViewModel catch (Exception e) { Log.Exception($"|ResultViewModel.Image|IcoPath is empty and exception when calling Icon() for result <{Result.Title}> of plugin <{Result.PluginDirectory}>", e); - imagePath = Constant.MissingImgIcon; + return ImageLoader.DefaultImage; } } From a2f741b376d5c00da6ad51e0d800e5f3ccf24d5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 6 Jan 2021 09:59:20 +0800 Subject: [PATCH 76/95] change bitmap scaling mode to Fant (High Quality) to make the search icon looks better. --- Flow.Launcher/MainWindow.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 07bb96339..b6782cb60 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -92,7 +92,7 @@ - + Date: Wed, 6 Jan 2021 10:34:08 +0800 Subject: [PATCH 77/95] Use SVG for search icon --- Flow.Launcher.Infrastructure/Constant.cs | 2 +- Flow.Launcher/Flow.Launcher.csproj | 1 + Flow.Launcher/Images/mainsearch.svg | 10 ++++++++++ Flow.Launcher/MainWindow.xaml | 9 +++++---- Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- 5 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 Flow.Launcher/Images/mainsearch.svg diff --git a/Flow.Launcher.Infrastructure/Constant.cs b/Flow.Launcher.Infrastructure/Constant.cs index 3dba35f8d..de6ed1b29 100644 --- a/Flow.Launcher.Infrastructure/Constant.cs +++ b/Flow.Launcher.Infrastructure/Constant.cs @@ -30,7 +30,7 @@ namespace Flow.Launcher.Infrastructure public static string PythonPath; - public static readonly string QueryTextBoxIconImagePath = $"{ProgramDirectory}\\Images\\mainsearch.png"; + public static readonly string QueryTextBoxIconImagePath = $"{ProgramDirectory}\\Images\\mainsearch.svg"; public const string DefaultTheme = "Darker"; diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 39b2087aa..0f8e6a767 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -82,6 +82,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Flow.Launcher/Images/mainsearch.svg b/Flow.Launcher/Images/mainsearch.svg new file mode 100644 index 000000000..5d28abdb3 --- /dev/null +++ b/Flow.Launcher/Images/mainsearch.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index b6782cb60..c9db58385 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -6,6 +6,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:converters="clr-namespace:Flow.Launcher.Converters" + xmlns:svgc="http://sharpvectors.codeplex.com/svgc/" mc:Ignorable="d" Title="Flow Launcher" Topmost="True" @@ -68,8 +69,8 @@ Margin="18,0,56,0"> - - + + @@ -81,7 +82,7 @@ AllowDrop="True" Visibility="Visible" Background="Transparent" - Margin="18,0,56,0"> + Margin="18,1,0,1" HorizontalAlignment="Left" Width="660"> @@ -92,7 +93,7 @@ - + ImageLoader.Load(Constant.QueryTextBoxIconImagePath); + public string Image => Constant.QueryTextBoxIconImagePath; #endregion From 0dd6a982ad93affc9cc2d3aae8dd7a4ba31bc176 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 6 Jan 2021 15:51:52 +0800 Subject: [PATCH 78/95] change setting window to svg as well --- Flow.Launcher/SettingWindow.xaml | 3 ++- Flow.Launcher/ViewModel/SettingWindowViewModel.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index e47f0e779..121b062ee 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -8,6 +8,7 @@ xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:ui="http://schemas.modernwpf.com/2019" + xmlns:svgc="http://sharpvectors.codeplex.com/svgc/" x:Class="Flow.Launcher.SettingWindow" mc:Ignorable="d" Icon="Images\app.png" @@ -252,7 +253,7 @@ Text="{DynamicResource hiThere}" IsReadOnly="True" Style="{DynamicResource QueryBoxStyle}" Margin="18 0 56 0" /> - + diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index c122f8037..c43167e09 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -438,7 +438,7 @@ namespace Flow.Launcher.ViewModel } } - public ImageSource ThemeImage => ImageLoader.Load(Constant.QueryTextBoxIconImagePath); + public string ThemeImage => Constant.QueryTextBoxIconImagePath; #endregion From 3bfd900f054687dee90a9c9670ff55e096000116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 6 Jan 2021 16:10:52 +0800 Subject: [PATCH 79/95] revert change for oneway for mutli binding --- Flow.Launcher/MainWindow.xaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index c9db58385..4373c0f0c 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -69,8 +69,8 @@ Margin="18,0,56,0"> - - + + @@ -93,7 +93,8 @@ - + Date: Wed, 6 Jan 2021 16:46:38 +0800 Subject: [PATCH 80/95] remove unintended change and change the binding mode to default --- Flow.Launcher/MainWindow.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 4373c0f0c..998bc3e9a 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -82,7 +82,7 @@ AllowDrop="True" Visibility="Visible" Background="Transparent" - Margin="18,1,0,1" HorizontalAlignment="Left" Width="660"> + Margin="18,0,56,0" HorizontalAlignment="Left" Width="660"> @@ -93,7 +93,7 @@ - Date: Wed, 6 Jan 2021 17:05:10 +0800 Subject: [PATCH 81/95] remove png file --- Flow.Launcher/Images/mainsearch.png | Bin 63073 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Flow.Launcher/Images/mainsearch.png diff --git a/Flow.Launcher/Images/mainsearch.png b/Flow.Launcher/Images/mainsearch.png deleted file mode 100644 index ac5492fa62dfa1d7bf207c60823b2f9fa6f4b622..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63073 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 From 833eccc25a9ff09f7ec4bbdbecd26904bbb7ee9f Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Wed, 6 Jan 2021 20:09:41 +1100 Subject: [PATCH 82/95] archive mainsearch.png --- Doc/mainsearch.png | Bin 0 -> 63073 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Doc/mainsearch.png diff --git a/Doc/mainsearch.png b/Doc/mainsearch.png new file mode 100644 index 0000000000000000000000000000000000000000..ac5492fa62dfa1d7bf207c60823b2f9fa6f4b622 GIT binary patch literal 63073 zcmeFZiCc~N|37}G)I{{2EQM%>Q#nMDRMKM1$T_Kq7A-mr329N3XgO(U42ru=dzK2V zGL^KQ#*kB}nN&D!IH{z4-@lJnGxPf&e%JMJUGHn&SLeQ8%k%YI9?!?~`MNLfH8ET; zZ}~imq86}r|7b>05?u1XZ^ZEz)!Xdn_>ZLf?t`8bwQ&vkpUBx{eJ_d{Uc~xw$APo& zzc%{ZjCa~GGgIYvl)jW_U{g^t?^pWABm2CP4Mgtzo)_(N^zTT6pRPUrc;TbvVu{6b z>$AR_WaKQK$55}@V`iQ7)k5Upkwq~gH~dmJxZJXdjP{(FKGu81;QLAyC!gX>=gdoo z+)wo#-R7Avpgl6cz-s>Q-~UPA|0M8#68Qh01pLx=QYqa6P^{G_pa!?yU>$1;X~=@|{p*pMtg(iL#0?%c_Yp_@G;&9xn;pRh{$x&pEU zUES-GZD&@_)Hyq6NU)ifQD#d|WHf(0y=`LY(xsX9gye0}$*?HAYl^FO54Xm8?gaL!OZy)AxG$xvI+ovsZ=Ol5}l_xufE z4XgQ^SRuw9wsfvv!bh8+{%JB7dDG0%*l2WAzu*v%J4^V`yZ znc6#d?pWr#6gGP=A+uf*aw$w&Z zHHvDstl6@L&-&b=X3HLH z$e)fA4q&4LSFT*KKPK?nr-awJO+QoOl$^V9O@j)5+`6+-C;oM#bB4ERe@2#$^1(YY zhV2g+1FYe2Grh(xFMT`q*lBvkBkeeOwbp^W`ahezlLb%z_~Vb_um*L$t`T!&v@S8M zVbAv#)q#veqkg{I%$L*K6iP>md#0lA-@l*vBi^MdpW-yD4P#Q4b$Au(TeA-~cbwiT zd>&T3!sFA6LW}Rmc|Xuq%F$W5-K@>_>~~>DN?ZghghXmu+r&8(ch!-0$8VNhB7cbF z;*2;E8pi6h(C|dYNayKoBWbx!s{AQB?%qP-C5FQNT>pFF{kKd~2X4hSem$z7+fy_! z%ofGFy^TbA>+ci{L;swsz zWn2*|lAmH68&dFWgX^hM>rT`L6=k^y+;)?R zq!!_OIl4FE+{-n-4ns)t@R~IpUumO3;gVGDhu=g-40=8#$Dky*Y!7V~){ zYt;?m_Y$RBpL?En*z229H=cm)Czw@~nwXmQ@UP{ElS$fjh%9^hmft@fGZAHGl98*o zoo}jCkfEZsCDW+C+pMCHE*gk&&h#mNCTm}0N+gh^AjcKq-Wthh8}S#kOe8V#EyT6j z#~BI_a!Vf7bQBG}Jsj$n+V&0Eb#VnwSt^;&=b!g3Y~0Ug>f1T{{YVSa=E&c6ri<=` z_q!#B2XuKA&is|vbz22*7^tdIqSQ`@%E%4ghiq*dPWOiQtO<)tpO^ik>+b$cvkDvM z3^y0Sa8RF=10Lr@ki`U^9`8tP_U(F~tG}PEt--&~>du^({X>Zbdo16&(?(WSR`q?Z zbG;>lsEfsK5UkwIdJU-jOp9c5jmIZXUqeR`i-Ve)ditXou#k*;ThCWI8%st%`sLsa zs`44OF_=+fqSN*EaESKjP08Vj#{F*@-uvgapR$ZJYqD_mBNnj2tEb5?n!r4s*=B6R zFZpLS@^#K{L}To zqm(AuVtUNOhYuB2E?f4_%-Mxbw-jr+?psoKZU-~DG27v3sj0E?8AT$(lG%svr5sza(KO+*E>g9dk?W7O+|?n3%IR}=j>iPoTF07I9B29Omf#EFL6GlP)YD)J*C+jmE=OzWE=9W1@oFNsTU&XrVZ`(Hhr*-F| zPthe*aW}+2|3pUHt5>i5b}uATZpV}@+3~X`rlJxTc9+$Eow3rK8h`D}Ox}}O}k`rNv_y79kpKA|s&$fwA@8Dohy+Y|S(-$e>CS%lZnyMJ~s3^Njy5Z6zU;$%d<+? zyK$)AUjLA@p9j6aNC{r&>;2r4qVWETJQvj{V#nu#G|!80e!Y6_T4QQW$K*Ns5#3<> zEfr~?$rl(gtH_{sar21q%^fLmu88-4@iO7&5gS@!?Hu0b@gB1ZBWZc9Ub?Z+JHU>} z-^vH_m)lF?hXB?C_s|B{vzkgz@=Fe%A2#{)<;$0aLOjTgI7~+Ud&{fc8D~71jyANR zV#mEXymb=>bXR9x#`&SKw#0yVc|4k31mUYuueICaY~;1vInEhFmSHFNig8yB=2~|e z88KB|1;YbGQoMe68UqDLs^M*y*UWePAL+x3MUtdXhZPlv_fJMgN7pOfC#S^w8>eKT zFg=}c^X6IKjG+$JDkTZZ@9QGgq3|Q;1$mmY2V_`<1M>SBt10hlEF6iVAteP1F|LS* zPsWgAa=7g8E)$AGms(yRf+Ur@yvu2Q4IpK@K6yKnzhQ|8hufu^T;z4?RG(Yh=g&>+ zCGf1g9*$`6USD5dFd$ZQW^TfbBiB|_QqkVE)-$)lbJAP{Kh2I=4gE|i-?L{=+_~Pd zlF;G8yG3PvDV?^Mi(?$2CC|yoXigCGoz+|5(tA7Qn`~EkSZ&W2D^B`BR z)J3qq6;E<|UST_Fh>JFnX8x&leb}_kx;a#^O90)0pc7S7Q=_1wU7TnAV%cS-e@SGr-7{5v6-tRO|sG7aMa zE@MB-|8QZGGUTOh0r4k5tC~*dFhT_e0?+l$Y0v?_E^xV=I zj&ODn|HC3$*6uMe(R(cDnm#C1N>!U~%*dTS!)&c}5p1l$B6#0HdwAc0H<$jlsFYIMJ^aQxQA0;Zz{VH`rEsLP zVLc%^y!2jfh+@auIh1HeBWv1JkT=86LTz*Ttk>JTd2@tNmQLR%MqT>Drm(SF z;U)2T^YGaCHAKIXVD;BppMLr4ufOzFk|%f3pB5va*KA0B39Y*4A}}TEHYkO8@bZtx zd_I~S-uxhUdIudw9`pW=Ux|R4>ecmrXbI81_A}xfYPUxPGxciIcwN4~2koR(aA!5e z^M0IJHy#QVuPSc2Fh4Vroa`aE2Tr>&^wipUDwd(2DNgl@`sRlBzqIbGe4l4WG>Ur& z*3LP04bCPD&c>KFye~q@r_5yL>K*p-%8Ni4;2r{M<+N`x_KY&CXntc|PM=;ZLWTTM zikQ|M8yh=ueKA%xI0uKg^V49BY3Uf^KOE=SD@HjqQ{{#=JKE05YIMr3(96$+n1)4| zh#WVt9v+6a-_xJU>Q4HG%HETim0QA@nVzaD=>21U)~s&Uaxin!wb0N+GxnH(F=8o7 zS$%JB(x1*ybpfWH9g8Moo$l2xtxC%^8TXT*(&-T>U~_arf`2GkS^8qPUq#jSF4Suq zsWM`g#t@@6kUrap7~pnR4@m*F9{!%kn>1OWpwMj19;-b2T9v9kpQ)NWIiyiBN0cPtU|iBF|)4W>U`{==Jc|cLPSOgb1M*dF(_$#!w=gS#?Y>Y&|>MJThAa zEGh^1C;n9Bx3r?iB zo8iG1liqYH{HYfcPiV{pERid7>5D=MXJ`g7*3~?q!dqS$Eq1?owz^)S!f@l=&l{ zfzN`_t5=J@M*FqyR~MV#W%qkA%jqMV$Znw7{n8LM0sFBi?gwIk?=*}b>1ig6`(XI?^ z4wi46v+G-myX47R)nov}vD}q9Ubav&ig(>^5u4(9xPOtQIJJJa!u!J!GBtNYernqh zgH`VDH_>(+tjjMMstKE9k=ROEooQ1Z>&kP<3Wv^ddf_~+HUoug^3&*(dqt_FRNF)B zcU#rfJp;)~f)Iju`$)e3uV@aQ!dyvF@ufgK_NB8HNybsbI9lrtA3p5eb9!5wvd=wi z%J0LY*Ib+BTntf8>RZ1irgoKpmpfm7N z-Ax0i(UkSP7QW3{0m+H!O?Z@FXU8E{>97o1>&t9aWVxo{APnBxu%oR@{io~+K5oTO z?QS@Yh5WhiF+cH zTJ=Vweqo-Ay(&)CAOK*_JuD?9W!u2OKvjC~^gdbxW+`=TpgzN9Bn_Zv`ivQ79F&EX zH1Dt3l5f;s!3fo#LtKX!8qJY(4qd z%in+6kKmy}31zOxsDg1#`ac0ob1DR;ASm*3aQGnW-P1I6hFIIVSj`cU-84LJ6(ft) zA9eycw65h_=F*>$ z8*IAs9zWKK6^h{1Y^jn1?C3azroP9>=2I9WP*AR;#}$TY!{bw* zrghH`PZkorNqZ{E;fibpPgOAZx6#b)@O}yZ&!SZJg^jyCTuI(W=5t&oN{Jt+*`lnd ztS!_Z=$pLae5j8hp5Wv^EYx%*4C+AX}p@uX;SIK!_U*9W4^VXM> zX==8-ddHg9=0C)Gt3^*_3}wyw=Gm~rZG~ye{SW77+<$=~cmpX&6sxmp^13XOF@P2F zE3QcPzuxHgStmm2el=ok&3Bp5BPSPG{;L=@h1_$~=nuG_tom4N*|SM34k zwv!y4iZ1kI{4EiCgxT~a{wA^(r@X|oA1{|aB3`KG$q3jcIwG^5jqN6yLfBEud zWg|Ei_rYBZs$Kfir%yKYOT~f+oV3)aPmTBb`s7UKYtx*AP{T_vl0lD!HiIr` zyNiuzAxGq{%7xf;u3f!q8!jxtcGZ3(2V$c&E7gsd%;>C;eKaCA55>*GPN;&lnhRkc$j7qoBWHy}cEC%n^FsqEx(|AMGMIw2?eBa+DIc za)fL*vtothV0hAl_o2R{B#$H#oaMU+tQRQy_|X$-_*3xL9Dwvuum&?kS6c!)cT?Hh zVp0m+XzAyp^YK9ER)nmT#x;8g7VRy)hTr=U`%Ib1wsFEbGRwEij5p^&OF9X9=pkCt z@M1%fh{anR%Cg+LdPYI?a>@|-K$^6_UDy#fdIfE3!`80u^2*wntn$XXH2O#Y*wjox z*CCL7Bc+EHN9B+owf~%X9UEa*=U3jmf|=ZKyY3u<-dk`Pgj5a+aNEL{WYsaWr(3FK z7A^E&**WtA_YU}yIwX$aPy-5Qw?sovZ`wIIysdmCfNxC`!;(?(wWYo_w{ATU%n}L1 zhBPClWk6>Yau-W`@5VEh_NV{)seWW&rak3&-A2#?*?_u>;F~0K>lWb^@*g%+SxNhT z-MLtXvclw(S7lkB{3?+|MIG`VYc&P0W3-g$&LvQIoQwWVCVTd5M+y~im%8+F0ZT7R zI6paDRcXwZt^z4mxog+1Oe-s^$FuY>sA02}Pi9kc&C;<~VMfgS?$g`y!9@^m*p^-3 zN$V&Vbe5GSBrR1t(vaq@m-qzt_2Q z|K0!s?(*qs>iuT`OkScoA#7Z2V8w zSE9#fouJZA2GF6Op9hYJN|fro&+F2>>u`T%QT(8El-a85LJ^6XbES;(2cqdY&&(?F zfRmzFFeNEb1VNeQKoiH9t!G#!2SlwLH2BJFW)B3W!0!KW@#014^Se~jIvPBy?7UxT z)Sr}x6z%DWI%|cS!g3&M2`h&yKyQgaZx7*Wcu8;)DmUOSA6j>&g~{I$&z_?fD_p64 zHpjd1$r*)hGm`^ZVHXd1&t_|1Eb_;1m{o|fnbJo6y$z!$9qN^MIUpe2yu5~`BZ&P( zYaRs4Q?n(Ebtw8s#&X_ft34jaGlm+GuIs{2_QV4jWi_1rA}ju3q(wmgz;bse1v3I9+WLl8i}dpKN2Ko+low55oJmFu7~8_4%b3Cg<_v(Y&mHsZNE*#GsD^?$p%Q_UW&noI)0vhuTweYVWXd^b$EhD#NsJ~Km#xzJ( zB?GiVAy7>Xy?uz&7sxS%|{7#JZ(=6l?JNGo&DZwZ9#*G_^9jCX2X63rFJ&M-xMta{dLQe>W z)rqjCUP4&kAT%7L=hNFQ7PJU_*YGbQs4bP1Z7#t9W*N;Xp3wn)mW}G1HPcarztUW! zt=?O4HaqI0X8=oAKX*V^lx%$Rh;au;L-VT=k zfhFJZQ$0ShTB=Cw8e9YUj+}abJauIu{2o@YYk}N}#0RC&=mK z$*-_pr%1Ecd-@k;Mse=>ZFQAEY#(I09itk4fymmHPK@-FYVmj0g7+})?`F8r^NYvk zKW%%dUR6|!C|(s|7Sk}gBm3}yz*_^k2smE`2M3d9WdMcg)s6EX@6go$eDm<3L}BV1 z?ybL!`!gFxi+UP&*|*rd-ahcs=2}QdLZt8|Bh)y@WQp8zdl*J&0<7gR&Ucnu@eO|T zdRwOuHm<2$khol}_XHha3iSR6!JH}CI~8}nyPz|(bb7p;@eX9k7{l2-Fwol^nL-2B z5B8`aMU&(YxDv9m8TD0~8* z>SaSi!+GM!&c$o4r50|R`1;6nJ6yI+ScClnx!soGW=H9wqeqW^Zub1tVb4|kYs;%p zhW12Dz3!60z`-G)g?54#ND|lXi1TE$K@B$y_cYH$GNccPidRfCveI%(ChvxsoU0k` z5=if!qmoZR9jRm856@BLOa8_)C@4Zj%fr>xl`tX(S;%yD_O$Su^Pi~)IP87Ha7)Wg z2za@v+_v|NW$Abgp z$CH*w6Y=Xw%dN9~V_ii^p~vzDst}eJODSyf2U@{WY`n>lwd!47SJCVWz|-yQob|Mg zXX@>40zVlve^J6X1DVCc@8{2!gJ`PQf5FyGn@+JahGglhirN-3?KUWK)*#b51azAe z1?J}#7|vI;?M>kUjU-jSyzqWgtO0a|xi;7TA2S?&?@V}K4gS-`fhB_%8KK};W-YAv z4@ycZK1eyhK34efgn|9RwaH&ia{Q*ohujipwOi^pR9&uvRQIIiQ@29DFp1@9jtG|jR zbzSv1_^hT){R%v|i;YeA?^_v6F?IXEYd1`aQw!N z(+A;~Vcl6k2%2+-OvkqIq0TDebCAzb>Fq<1y<&cSgjcj!I8SAoR)FTq%GaZs=FtW z_T>s|T8WRGx7cDKH$oj5YII`aOo4T0B4dp86X#5=bt*W!#AGqdECaI904a>Gd%nQW zi2hW|H6M7#2mpK06lF*7aHUB0Il@DnAO4EEm#Jz0cRz7z-&l8My?*_=gm4U;0-Smv zT!koIq|4v%hHKteW>)bAGP3W{_NI!R5T$P=htGrw+id6m@!%fIzraNhMdGH4vg{Pk z;3o1X?|i{jK0`T8WPP_jn;8HmXy8f1=yN4XHy!oqNVDmCb=$gQ{%6qu?k4@+yLT3| z^FDqnG2Zkq@7Lr)l?=AssV2Gf%)0jjohIK5y;ni*9l9x=p53nI6VLkzcgB?9G1R+ZsePt^;z~awPRyr(j*efFHnYDQ85Zt z^f9Du9*7vFDEW{;uI|;{Fg914(z;rIv^>fz0hRi5Qf1lUPgqKVym*ouXqn+O+h)sg zK(sRnLX#6b+Q%@pW~}(1oS1vZH-0#dVe0NDX>`;rW9T6Ws2-9kYsqY^4ovX+50C_~ z`VBNVEZb@^7{0H1J(6KpEWE=_8`9y z(to6+q%@7RNWkXpJD8qZk{#ZkP7)bWZYyvoiq&>!YO@r_9x*g6#X>4{vJlAjtCGG3 zqD{eoe{{2jLQBy@8mm=VAPP?o(}|mIA)yha^8X_ zr6%{aw!et#5_|3==XUj;h@o(PZe4RMIOJ=Z^F*v17cE*u8a;LpM$_;sN>qM%V0U=8 z+ILffGz@D3eBGi?s`8gn=XJ`k$?tB0NL|49404eh1qje=Fm)osl_Pbije^8qK>h{~n7e4aNctN;T{n=+|(^H@!{k|`Yfz{k95cSdFpKo`i{ z^Q8#zypc~ARErzfVKzqK?Q}~fjb}O*Nvx}Rj9sx`O+6w zEnb!!b?Dry$w}Wr5HhC1=QX_Yv^o0Kjclf7^CPFKSdzt;gq6*;LIccpHGV0otKyRe zk3fHzHWqlcMI}?5y^zuI@>K{_RVvBbH|S+c>F>=LV&afgEui>iQS%5REbIpI>psbFA6IcoMK<&Bx=#IRs zgO5HZJh!JVy+Y}>l<CFjxGOD%EfdTD~UA z-hV78PW)0&=QL~kd^w8R{ZULU`vOT&kqhRbql??qpUf!zd2}u}7PtV;#fO%_jxy@T zZHP4XLK>F@2>fiV&h$sFHqL&B=|#2No}BZiPY({leMrMnHC;fl=M**#WoB8SxA7Pq z{HI+;O8_%@`?*4^s-GnMsWlSc%3i3GJ>3Ntklt?d2`#%NeB;De4`HvW}?x-(315riH(-<2zk+Nmo4 z_Uc}J*N7wagz`*>Qme&5Hj%aeGPwsOM-}Q(JK_LP%ov%qqAv;TH}U?CtnPI226WK% z!#b7M!xW#Et8)V#)j^JDGcpo2di9$Ugv2en!J$UJPS8EC=NEdu;nOoHm8NR)b~U}P zQY??sq0V}HZGHV2!ZvdrKVB;y`4cJ@CjDg$Z!=L3JGvQtU5TIGs8T9vh)LyUORhMTrFFkO-DV8b-m6wPjA2LBIw#QJ%^VA_v1H!HWJ_ulLaqg ztUK3N=}mlHggl4);RB9U2v?Z`I^u!Y&P*Hj*rP=zS|7A$nFQ2li!h-wCJYy9X~=oF z8TCKTbCD&lmbDec@#qsVpPlF;Ej`X3?h_~IhbYes2TJ=U!IaZO5Q1hVA1X{dY|O0- zRxXHNE%mTa`CuGQmDEE>l`By3kz-|KVXbv@xX?;N?q@eJXH(J8j!=ZIG&h85%k8~^ z(%ant%JbJIZ{PjxrMGJcDr^Ef>`NfE+)0ym5u@A3V{%zdH-v#F)b1{1j7{aaBq~&m z&*dg;!8z^97)oZDm<4@*rWIA>DQ}eLwaNVMXBbrE3;SoImA&Jq>0prk(hwJ-PIPnu zL6#*2eL+{$u9|?Ki`E+zIfPdXu;e==^6#RX%`SXD^qC=zrWu&8L5~0)LY9t0MYJwuFTddlvQWGlAcd_^r^zE&;n)@)?mBf(jH@v zU4lGW0{?;~@)*&^Ir|n|dRYsV8X>E2 znmwJ5ORIU`0>FQocDq_Cm6*RlMdhR#w1IixF%{>;%-I2G}fegr7!A3-(`lhCRXi!6LHLnPGo;PB`tLYNx&)C2SJ?TL4ZoZt->%< ze+y<~u8a8TsfOzIb4kf`+13D3;#kb-Oh#B>y?qi3@ zV-TSJkqQ?67k!_yy6=gLc0XV^L8EptDK2B#iWL(dz?AIRE_<^q|GF?0VLu;Urn+>y zsGQbfM}+K%P1Bo4HyZaFzytSop=)*ed~=DPv`LQ50`Z1pv?VI;Mvzca02EN+7yyPQ zebVfLh-Q@Vd&F3?d8mlko&9jJ{&yFh*$83xlN`ref3#fz@0j|CtM&SUly%*+Iqb-_ zJ?$Q$%Ylz23pDxW${*WWASp4(09hr?FJuRsr)(N!8o`!e_|k?9t1C8gJ5WI~+# znHkDJgTL2}@2P($m2?r&u)3q;cxs~vqyxO+i(Z+5!;_9`rTK}qd0o+1ALnu{T>5?F z!td5gh#vhN6-PLkSOPCe!{MYVf~^zSlYJLN9--6WOPS`;G4D~!XPcJQ~A?^Gkzo~uK{m9|zrO>LXsvZ(!&xJWrPp>286U3we0XFts zS{!tE`0=L@!MP@%wk{}8`w|GtG%HunQd0cSSvU2LI7{Lznox~Y6J{3mS2X|D7bODU z)_NIfR$iYh)vlqgu3kmBAeQ9Q+c{$9 zqCAA=(zCQB;N^mGyMJ=wcs6X*Z4(xGBIYQAUr2A?y9RUhhiTw8it0Z0AuRD@8%|h9- zeS-=0^naMZ54Ay;wsyDrC^H0-*|v|tJO9$!pfiJ)4?Z%hc!#a&gk%4!e6DR2k%|h+ z_xE=KE4M>o0@3PsB=Ft{fP;@-#cDSDBNQ34{P!#ve_L;8XsG%1?ZZ#ba67y&p7W2% zZAK#sBsV?W3iWY^_fY$WFyIl4REAIJ^1+8T@cTtpWPuCT$nbj6Y&Y@2tYQzXaiTg^ zFG6?&3rR%ACbt;IuDQKMMEY$(c6M*rDV<~E^`V*erT*j};qR>Mu)*H7*mxo>zkaUY z7j-CQYM#r)GDv-g=k!>ceLgr5b-L)M1>?iFAB6{?&xxT3ua1@ihuwhXlSgSo=8nWC zr-1;!Cxkwb7BA^Z`|T^4rv0Og!Z%5#ji9c6SVrC{n7c(PFy(l6^pUNuQ+oo&+ks#1 zga1WKk6JqtUs=tQZ`CZFi_bG#^?s`k-ioD8-ysf*kbM@xi+F1C2@3iCDf+LJeZGS4 zzg9}|s$racgnIR$wKdue(O<7MHCW@8DF%`XDWlY5QcY*PyDR3`?kBNO{;btMO%ZZi z2^PA3BqzMzL!*7Cw>6-ueFf|~?app02H`<7xX};_rj<*z^Kzzl(`OE!rZC;JefRWn*+{%KNd)_=xy)_v8Zwz?MUok`1HZ3 z>PQm5-ucHla(j@2N#nwZ>eaC6!Ke}Cv3I27Xw6&-l^kHllm#ocHZb{9wMn53UI-qR z7(WZ3b(jS&-hT z2}Tu7p0~e2i9ZE_<@YgARN`}3gUNz%UMiZ56dq#ls@S!=Fec?->=AD|(L6{m`=)RQ z;-~@9b3N!e7iH(ON3WI+24|tk)fn-Bdk4hBG$V}FbVuBe!{F;b4}{uS4a+teB%)cT zgmq}S!k45GzYO$cq6jgl3eJ4Kv6yE z?FS^!HJr($??&q60%Y!b2qMEB<>4Z<^4C%?xQ1cGOZt?*H@RLIORysusv)v z+8rk7xVpS90@tkk|HG!cJp}7hk1x`=pYph zE7IVg595dzQ9FbqU>`?W-z-s0dO>bw#7z@SM4<1-8caPI$ccniybRL zO+%yg7fCdrf`dmPRd(%;Q0tm5FTa2}xUodm@~+5dz%FdNvE;coPUz(+2jJL&%{F=d zA*nohh}K-UBlO%LT0M?$#_Io4#~aJgDkwm&?GEX2Yud2qUuQm;0;XPJcaAo{ur^5+ zxuyd_TWfI&hDZYZeuf`OrLQt~NI%I#Z3s8Ms^Au?1(?o(URykp|yy5#sY|)mw5+jZa(3@_FwgsjF9W5qd!OsAmJ{sY{2Zf*;k4 zO)%E5tJge1PbI2IBCta78ibot+)pw!A~OEXtb&wP<7~)b2BW7{7d=Mh44-hB!QZSq zJxMVUKtS#!YRw8D1it6rUOxD%;4A7j-o$oyI#HKadG?O&3b-StEBpg#mkAD7O&;$x zT^EK%B%u`LA3*Me5yoZVH9_SMq1t1@u&NEoXNOgbKi(mP-n%yanXw77p;homJ)}*~ zF08?H!8zW0Mt%dRFXUyU&q_>f@H$C1_p_tTF04BB40K_~f1Q+4iHAdVhwJIdV41-S z)}5+o?QgQdDUFuFY<7kq)3i7CkX39K0pYpf-{?*~?I;>}Ezm*NeWY-+M!U$G+`3sr ztZ#LLI`5PU3 zRh>htBDqng4@Tp*m~P7{Fnw&eipR&{Dny*?(#MJ!2k{wg|RQ`SXSwGQ|NpLVd>9I*<#6k{l7^dW^CE?CE+Ahr{QwF%Bt<2Yi z;2M&{`-vNt1AT1uJ#ck^d}_c!0LPgu7ePH}MIM{*9|xGNQ4t&s6!6|MIl!0kSP43i z^evoMT3#^k{otHg@R>w6jv{pNghZ%Xu2jdIsL)TvPql@cp~U2)IM!5RH2#Q|=jOuE?Zc(2pk=1530*0ZLi~Tdp4MzO`|Qyjm)8jv{hy{ zw`R;3N?KIQhE2wh!GrQ#W|;igaL(NLMqCD)Ju>L;WfZl{ZRm!Bk``#guq5{`;ZFuD zjoyN3v1fT)TbzFV2BUO6HuMzz6h_D3Di%T2cI4Kr1g6j0KZoM_=a8bj;@BERs~x6I zB>K*ZAEQgY!bJ>Q`aI5M>^-@VLry@S;MprMRGIYahXH}?a3w@-F--cG6B(||XTO0; zbQ$Sxw6`Qflk#rY>20R09Mc6B?J-l9d9ID;;;=-iZK7%_H_*UwQ@B{s>ia^3w?jmI zrcR>pbC@;#qolarGg*zq*DP>}ha+tt1>dp*tGHBZ+~32_mcbP|2!(i3 zsm&M`X{4(qF_DP9C~+dEGsjYP0NT~Qx~Aa1JxP3hOYn(|SVUXSbtswS8|wgd{w8+z zoFE3M^kg8nT?-*1%SI%_eC@`{a3V?H6I`wfg#=5 zPj5FDx8Rkd)X#(zf=cr z#ID(*N%UX`AkLaCq_K|?y8nWs*BDN`2iSwBb`V!Oh8Z)NVwGR(a_c;a;Bd?G!#CJj z%!))95c=(c(I7GXgd9N_SZ-I;j3XElZ#dCe1^$9uU2F*ypJB^Y+_pneSWMCCXpap> z^&#@QiVQ<_L-J&pjLM@0*j?%iOp3dLPrtQ#bo5miE_I7l9(#yTj%`kmR?aVIinwnOIM6QLcQy%7xGdI#(8BW2MrA{?|R%BR5D z7%CP7%c$I0kLv^15kqJI3ri&*@+SnQzwD7*a(6gja6kg{C00jqOJoS?oJcK z{^xPPE41KTXq{M^W*SeLo3M}>8)mC?n6I5=WZ(I(%yp2{H_)qJO|)CX|1$f{Y0krw zCo-}UfSnmIUY-+`cux;8hBWN*5eG8r$336>y%EW*70d zr)VEVDoV@;rx`Jo$G)TSB1; z{yq+SSXfqOW1zcBGLqkB#0(%lW|D(6VultjU}x`fJ%ipc4Kj2UhW-W)KR}zc??UTd zwh!7wHD}Rr3i96#{0lNFVX5ScD)#p3EULMg;1+n1eHa+`OtVOOzpxRWw45&b0e{Re%JvP%O4311(6^Uc%KMxZy39WvJ-PvEq>;6C|u@;!; zdZ42_x!;&b4#Ut5aVCq^|1Dll#We{-GNh(B=dmP^>Sn%f1ZUY~7vaEHlNA>e+k#$% zbC#hwlrRcOJ+MTj$1e^?+eQkrh@vIq3^PZS85>#!f1-Xvc$A&}XNf!6_8ll|_8`eZ zB7|qy*>4)Ym%^6dGJ0M;TUq&`s!FG)s2Hcs%Ne`Fuv=!uP7d#zZ7+q}t5%ib^{xc! zN)(o1!0GjTBeKv|@MbvR8vH2)TGspvrWl+rs^**TsmQq>VU_@D{x(c1`)gKlVziJe zqtZ7Lp>q*=uqMWHLAMRdBSc2!p>A&7GOU|3hJ=i7-8qKwR&9neeoB;2nmmd&WfKnx zMXQfJX-?aw(BHN`74Afb@2_a}gX57Se@Z+Tq1xwT+s%1wp3M0funQZ>h^=4W=XQD` z=U7{2_8`~Q*bMG7seT#vLlP3&RhDe+{gRPp%vNn!C$9qC5>>`Irjn7>jj<^{*<>@5 zL)XRJ@2qfr{NZ=p?=F)WuYz}}ufVadcSG#AUz;44DrWTcB#wdH9oD)R{&96k@^r%Z zBZfISnw8)}esvOg^t+NN%zhs^97l1^ZjaB=PEG6hRckTg3qV|_8PF5!K#$?G4wm@i zlc5YZzs~)TaZ=PW?)QA8b!TY}cJ_gVdK2{>K-yN0z)9Mt=G{zgUHCKBxkXg%&#uIS z9tw8w$?4>z#|f#72D!9wj%567qcO2>e8l8s^=ze&o`kbOd!M}t`apnixJ`()CiGlI ztJRwJ`L2zG|ENxr;zq7O(RYc;`ieFGK_ma;P+!X4uvwti(4HpxyiXR3O zNDW!h2L^vb18;sJ(_g{#xxhh^OK|1wY~M54o-nwQbNiXCZsr`x(!`=vI1$s$l=@d$ zXPX0@%eJ|o8f3}o6g!hxNf+&ujC{c)5u=!#=5kTBowz-$VATHTx8@iLFXXxC|MMU|u5#p7_{U8fRU*_GL?Pt3%PbbjWHa=C z)LEGyg7jGLchcI(7`r5+5?CJZH~dZ+A~48Oqts6;A(q?_`eWuM9ee;}6%;UO#+K9_ zk!+-h8F5~LY+XeT0NuJTtI^>ZYtFg+*b%n@2OlDOwkaPxa6wT`31Y_sSFdc=+HAkQ z@6SaxWT1eqhJt}dU~w-f_NveJO~Y>{$zpx$kSHkfMI%~{)mqyZk&AR}tf;v(Z$@H? z)tqv|l{gXQCeP;0pLoUkO-4Q$AN7!}#Mw=eD;qRJ!Q#RlbM~q7O*rujA~zih<#g=k zMz%~G1KnIn6gJT3+RSPUr~e3r&cm3RlM6*$j?Vwj8T91u7!jp?XW|9i@d+G_tUdi2 zidyXQ=E={R0l!1w>06-=hhN2Lgc@(YEoRtZhi^7S5#_Sf zS0KMY6&K|Pe7+Z9b|?ucxl{u5Qda5U-V1k%j&9dwAx-Dj9>H0olI>!gaV8AYt0ubt zAz4TqW!WQ={wVnrZO|P>G+g6hGV*eRT6Gj$A?WiI_FumF57)^h(6jLR(((AE~8!= ztXR1cdE>7#@)xh5$k3-j&hRl5_Wm5~xBt<)e@A_i7{^JT=*iZ)NBbtx1N~SfO-%mKLln z+jq8BG0OJiq8SW%m(A?{=FfdFicoW$Lc~$(=yly)b3*<$g4g4IIP=ais(2&cGNNVe zSvMU25+~~UPfLB>dXTuzB8U%X_=-^~Z>+t^uy2^DahpkAx*l>fKoibUmOooEI- zRoH1Iz(SJygj2}ZU{2~M;}zIsc7z$4wl*tj+2&gGIAFGP%vNzR|B7^qy!Cj ze~ho6s3hCo6EkcH&PV611Pqvb+k<@C!<*%ysi-x_1c-++eCd*;ZHA@@SJ4H)olwJX zR&5k992Cv2@yUQu^KLxBcM8#u7t3}RD*|aio~ao*ks)m!xTg0a5W@%w81nbYCpPSv ztqa)hkJ-#7{EhPtk>!^wDZ%%6-}*M&UcXBiUHNO)opaZ@i*=J*qC`~kQoO-j0tBOg zM%={?sp26-%9}#2lzhq!>rPXW$9kwyHT3|1mnM{v;XOT#tBbatmx=oP1;Bu?hzpE34jP>oHZF$juTB9Q5kTPe0e4!~~oB?k!tr17)54dHPI>*kGD< z+7-q^!N-rc@f{t?%7b*v>(I6tV!?OnzC7)MhG>hb`C)GcOSJabN5g6eCgzz5W*Iy; zO9-PG_g9Fs!YATtqDYsv(q)mGPtBbDJn0AUHzX@_I}rHv_sp7(1_GiYX{_sXt+{2R zGJl(*R=UDjd_v9~n~khQyFjdYi#zTBJt5)6sDj#4dX6h5pYp!rbVCT*NUXM^j6ZHm z12sGJlcpm)a`noZOV5&L?;4V&dEmQ!thoyfna|Dx!Kg4r)uz7q%eZTS*qXubDmtMF zAHHdDCih}tKs?$mYPUftI(Gyy_$b4Lr{fN7#*hSO?$_p-nMdAjr@WfZG|uQZckYSY z$}~Q{A}?o6^`3b@EnTwLbNoo+8)A(-#+|7a+|yFv)`8VkT&x6 zy#L48yT?PB{{Q3S5UU*aRwBYSvT`UYrOB~vq{fzzkYv(|4w6HW#FX7kRJIz2YGNoV zghB_3vFS)-wv&=55|UH24mtdu*R=cjd>)VQKfm{1@6FuzeO<5Xb$q@Kmki1tj&TzW zml=F2{pZ3$8f`lCbK0rUy>l{MbxS{AtL`S4h{x=nKRIh|zJvt*f|J^>Tc5dmPUf@N z;s>^nSJ6-A>sgOVl)pc`$!cYKfwcCRz&JiU7bjzq{36#qW)8jE<&d%>nNF}0=QthO zbkiw%^L{^pOn4rOp7n@^NoalQXlgy3(p`5*nNMPze97wBuv(~5w58L#&&z5Ly+bg( z224XU$>u%%woWkh%KGXp0@&;y<=Bxd?>gn>VUO(rIkOE#1tNOb?6%KmaM)Aee%}3Y zZ2a`T0-_mwEu%+=kHg3@I-D0l{dP(y|5rw7p#HRF9TtXISOznJpZ71R3C=E`BzD_LjjSEY6Jvr*_ zd%R;-PFh;HfUYwShugoImTj=}ZRyuMu1BtH;KXiYGD(q!5@G`bTP@1R_0Zl{{sAc+ z8fPDL>r~(aFE884?|O?I<3+L@&1PMFfw#Rg@v2grdU&ehDN)~&l*hI(eHD{mRAfU|#Un*DogVeylccX)1a22(on_q!_RW+r=Y#3D6YUR~Xy zdz`yLp?=`iH4`tKf*J6g$UiJO+uV$dPM!@D+5 z?4I#46s*p^YL$M#v-7jRFJ#Gp*y#&Fwa5a_eEiP(>FW+HzBL`uJbwl!xIH61s#|za z#zC^g$5Rsm>SO?ul#~4B$G>o}y^UJ+t-knx*uzlYe|r7+&6yZvKoN4N%ds`Dm{b?( zHQTVn$N5DGhFHdy7kj#Delf73lxQ3VqR+zRO}&AU2&5hn+p9x)D%5{CgK!`eC$TxM z{O|20ibC=jsay(RMr~54Kj9L2fzSYL|8d$Q_nr{YHy+$+clW?X>G~6)dsoX!Ui~br zo0jdZn}V$cl=6#;rgVk;_m_d#t9O;VO4q=m319zV^W{%eDCCiB;hGtoZO94)K4SP3 z;E!S%{}e;D0N3C;?{Mpl*z(eGdl%_5+Yuo7GpkNxSG=d2iK~-c_VuNg?NsVPl0ZA{ zD7@N@8k}u;Ee{fHf1Olcvh(#dt#yRL-R~-6pHac*Rg3l7M%UuOcAiw~eU_m$b5i|4 ztHqs;)ec}0TI4d(@Sl^5AC*w};#S)IS#i;nW8gWkzxJ zy{RC)KWQCFkLR9Zi4V)~{8u|Jh0Hw?o#5;>@w#3^p0cZbg+$^b?oDTfdNJuy)|~^< zJO|HWhVkYF7Oh<+KcV7Jng`S^H^J0 zeDB6b9GQ-FHE8X~db9{{SPC<9IZmr-SJoX}Uwbmhl@=+wa-(tN5AKr7vVpsgfi;ff z=Q*LX1=`(`KmT1BD}Pb1c?wG`N3@DIRLD9N9%pgGCbt(A#77;tvH`UYvi*z-c5CswHqC?b(vE zivyR=rLS>5^!ftN<|5&+-1yAh*%@v!qrRfnmPo+MO-`35rIX3x#G= zAl-GTvz{D8G1O_l4bT4l+T~s$A|Ir0&}dbiVj7OO80y!tutK=^_a8C#=TU)|JL~U( zECPS;;CpH}R#bVj%(TcZac(VZm)Cv?+=o9tXyp!_RIItL2Mg8?BXl1m$Zm1p7<_Lv z#F%D{2q4dem6nXte1ju79#rx)+w{TPrerWyyQiVP)8b6+{3NUtXvAu((WTGD%Id3d z%4sQ~d#`8w&!3bR4a_G0PV?82dw3d^?HVMnu@|R-98nR=a37gxEbfob1W&zmX#HGN zYvYLXs~>4~mey?FsgO!$CDPjE0WFIb7iZ;nmKfppsG&UOlHB@*doxkBIJkE#2dcrY zz&QS|*N3kcZ@97$o|)iE=wVs&nhsSWuB-77vYrtULod0h>kqyDz^{YCw6nyQ&TVLHLur~d{=U^yo`)laWm?#g|xB=5yhtbpj0=12aNO2rq?50yLNZ|yGg|+->lW;YH+Ux z&hZeD;5Bd?0HJ-1(ntUfnzwNpxL|~5TDHKrZVmXeb8v-1z>j!JdtN*~bl^dX_qMo; z7m>(-1g*ZdQF?1jCd{rl@wQCr;#+%R{t*|OuX2>Ge@8ZlT`p^tYz1)5kIS9tj{kQPZB<96rtM`~ZnXT) zHZy(O7s>sBqAu+|;l2`hS>Wc*g@S4%5vrSCjNHjgnez<$Gj+Es$}cAm$OKUxuV zDPLua^K9@jjncoPgk&e@!cEe$l*ezwd5`L(p3Ym5Oou$5qT_uPF4j4?isiD z=D+9hf4+~v>hL;&QvNwOS|Ez@e3BXfypeZT5b`gR1amX$ZelVmZAquurS0Eeo%%Bt zq^xd_BOAB;v9=~c);#dQy4i3C7t66hK11jd^2g{8)%nGDOW+@Dg&Q%S91!%D)TFJJ!u<1Cz38D5dtEDK1OXzBlajlT-5IIH4v2)s@e#OtWZlPtbic3B9e->6Ilj`|DQuTD!$2DrH5<223 zna}h7m$;pA>zyT(8PIdG^j)tbrS#nb9ES6L>O0~4{M;p0TyUlT4_R}2?>el2@wxP0 za{hVyKiPdc3p&s8J5!vvs6F3Uq9ut;HN!=@OBne7%FZ(lSbF?nOAA&RZ(KwCR-!`o$pT6s>Rba{qO*l*`En)xGH@0i?f=mSN7ani z-;_z+%eR?7|Ghs#PjQgwPYyI{kSiGMwT5%R(VU#E^yZtYHUETmw&+d_9rz8e8L81! zNL|h9*bDXq`9FFW8cqIRrD!h4-iij9q7~$jYQZ{1M)7|UgHkiT z|Gca@!uGxVd0=|6>0&fWOrwyvTMW;{0%9Q%+|YH>TTi)sc|uf25b68ym`bfu*y@bF z-&Q&HcUIeWe5G(_h-e4#mq+dm3=}U^?i$)EiPXpfS3F|qx*c3>WAOb4I2X~9;=9BX zD~3^f7PVY@>sY1RH2)ktK9InBdcaMfbYm4rO$>aejOR2RsV8}#O3TwHtOfY-?7Qnocef_Upm3*^Hynh`uVKdRK79pbY50BwXk&1>{iSBqW~ zH+$eVJl3Ue#Pbq4$m|ohrTu3Kk5m$}h!!ix1GMzQ@d&iZ-*%{)X-T}j=(Vs=N>C;` z6GIPlVN?IdwR_AcBiP}9mCvrM)edNi+fLkQV&HV5t)wJ z^N58)z}@Au@y$qYR!4@B_;3LWXGZq5M)X=wuBnD}qK=}TVj>h|IUcS(k9V8l%#+Xe7}HXDh5CT}9X zKa)Xkm_!`uL>FwgeY42C*bkO47gQxK-s)CsVR6fT$$pbe;bC_?u=+UP0zj~2%dqTw z^9amG>IrGqpH8TX51;*ylpxm%mf->CN%bgpZP7x6WmkJTHFXZX`8`W4*E2DRCeXuK zeVPIfxHR8d4s6@bh*QzEF(9GH;+t?MNu0K%LHx{xrE?l2MXXhuu2u)GY3JhQj~V-6 zCt!>0Nx-PS@0?O#FbSndxO|~BUwc;o;;-+2tG!cR!}1~&3xlht_jX^~IUfm1@-CB{ zN2rzb8D(gW?}64za+v zuaM+RU|j|h)0RP6c^h9x5Q&c3QB3=@8j zli}3lPlmyQO8_pe8nI&7}G<&%K{6 zU$j|In6=~QpMQ?$?vBpzPCo&mBqYou_2`S}yW9`$1tOP+d?^r%&Vq{Z_taIEf+V_^ zEV8>uRjizd$+rX{*mrJnaR-wbwTx^JHo9XMg4SDH(9C?3cU}2yR$2L4w--kVd2kTt zTluzEu-HR{HJ`yP{rpSW#;Nd{cC{%h1T5((&G1%fM8}IKVXxK6p*B8~>OWi#fNBRC zo(=XTV-ow_@W(SbCe<&fz5x9I2Z_QE@}cpHOY@b4Va-uEVvd}p>BfYN)&JscZ+cFu zihsk{vxyL9LzZmUL&p9T;*=MXy{$ zeuD6Pea6&u9yZ2Ex1BBMKpc|qesC`i--+meZBScAVR-GosNId2iE&f=DrcZxv-iL!JkP>`^OK)?;{YHg5A9t-dD&aR{Q-3Reh1DG}dd5!gE*1ohBso{thTQ z=>EO9DG#ysnGfiAi1>wR;(loHK7!W*t;{yKz*7dYdfRIX=%Uy&k+nSS5b&qlz*NuNPy1uxBU zALubwqF}90w>r(ep2f2vY0!QMiT~%Oiiv6}_^fK!?%mNO&gU#tu%@S5?fdd4URnc9 znzr-@`zqUNJNf8Blj>yhrIRy#L&rA*iEYD$DZ5FN7x@|-S%9on2k6aFFlU^5*F)Px zepKH&{dNvXNfiEs%p6Z57LP5uu?hR|4-ZcmFsrtMnxbJJ7*O^skjC)J`p)!qg5|cP zXrl0y3(NL`w6+A9BngT%f-J=>pdU9}CZ9H40{^q;xAN1orM08C5@9j<0Vus62F@AW zweanzdF|(!Mv9~gxh@f!)VW(@XodMEX(^D!?+n^T=c~0dSskazStj_Q!ApS(&Q=Y3 zw*@7yCD^Npe{>d(n8AfeVZ1T6QHU!1&h) zY*JYIL2C%2Tc>RsJ=#HC-H4})b8@sGAM6bLa23Np@nE*zcjH{B!MARI{(w%0g%th* zC+rk)tCoKK03YWZDZ>!2Cegh1Dnp5=Oo0w82w9TpdS$A?no)Arb~iBAc3&V9)o zGA2%e7ffb@NZVfIxal6_PGyOY@SesHUEH3$K6lSD=4}0Trgz=MC9u+zM>zjd3>Z(e zuiC>BXZXWV(!v~_r-^2UeR_zhjEcut)uFW2vjuSn)=DoOXh*jU_BRuFmuqHu;m{-m-#VLEk8@~aKAp8Yt|JiN%RK}Np#dxw(QAsKADEES_ z_7{SCl)?l$0sQ<(&l<=>0)&P4ObJ{3Rp0evbF3=puY@Jle`&3@ok^9bhP8jroRdZ> zUd?=vAMlt#)vi0lkoZn&@09#8;y2aMzTdBz=#rd~nTlas)Ct8fqqb2(pLW1jcP3`d zi;p!jb2yLH(L!z39z8y8$F%ZLSc*WCoa$S!b{iSH;Y#(X>8Hk0#G2hQiuX;JTvMry zy4CxHf`T3XY6|UBdrol}5sz^V+vhiA$r~@=oRSu(>ymbxRiHfi;(=Lhqnp%HW6iCt z51b$@cM(HZ(to5>Tn`;r$uzt}oXAqJlFvhirPchp*c(Bgv2^XTfDx0~Yod;5(>S|u z2I|OjU8Fbvj3r$R0?%F{uYv@f2LT?G4?hWtCizVAqKb!9U-XRB*q6w)kH?Xpm0_Os zVZG+RS)kRek7srqCk~|rc)&m>ql*85f8!EpQJgzxa$?NZ{5Ge8LO_+@{HH6lpO+c> zwvK&#ob-W+h)xc8wpAfj&k03Hf==+_F-*lCY@vdg3Ln|`07l#=e6-ayxpf~ET&`ME zc?8K1Eol38q*D%T@%7C-&Q+OHx$y!|Q3$FQ$-EtKa`!p#^>^I1qIeEYa{=oQ)Ql zwRIdT7lxk*5xwzaA8#bwo=^!Y0n+BFhK}!BVs5?;@yw6%%YD>#+&YJE7>4Yta%Z5qah^0^a_M&4mOa4c-V#211^m8^-NAA ze#Ovwf=WMT_~glk4wT2rtE?f)#TVX1V&g2S&?J|7QmWH?1%qPqz#l_rhMuCCA|F?wD7aQC{NySK*PU*8E+EnJA%TZo>2g{G1mWojbW^SbmH1D35GoA{3+T0*`PPvCPyNZQ)Gjdeq&J zE&J?KG3&n?NE`_8Cyh=I5!qgr4t1OMhr|%wtcYdV*)9!kt}3H9U%+P$;J!tX1lq^! z&wT+*tK|wGbLLF;agnF7gJa~AFcy`RH|S8hZij9?W=#A}zAhGv_1}*ugocliPE%3{ zp72QOaCuT_^x4TZckiQoWvCKoiJCnG9#}xGEa+9b0USOZ>4<2X-|l!%`qJS{GOMT=sd4GYxulLyF`M7-lq0m7d8akmtC1AI zB_IxK%E{UOGrciaw!gO*Q!Xw(#;#-G$Go7fdMbQ;?=7#Q!zY!i_u#)5wDOxWrTa$} z$BtqfW)UtdFFk~OH7!;hXW$n)LW@=CzA8Av&6DjnyM{7MNtu1+$Hgs#vUrU| zoj4Ny%gy;zP4&&!PmO!FK7Zpd>9Y~O)4+()MsDv?jgKwq-M2`UX@UqV?0={~{oTTW z1nf&_cTQ?A_F%g_hU63-;aN2~!gn}bum{5xoJdGB(u9h=kaT{(KFdsZ@b*cpG#QDQ zatkY~(ORl62>;4xOLvz1vajXA0}`~>+^y4VCN&F%>p-_VFe^*jqVUhpUS2b)#qMb% zUaXE=M&!v{fZU|IGYds)Yn6L-WS&G_;c~n1tlflB^%p~`FG4>xk@xg0{ChGIbH=nD zF4xkJofbWdPJAtKIu7)rbbnae)h!PiNsQ)5DgZC#e9Gr8xg^^^aOs-K#98vg7-);V zD_Gldv5peRcZsP0;&uTQRwsANW|zae$pr}p(qV*m9^<<5*ft>|_gv7(Wg%^$*@i1G z&+5^QE3H)e&-;1WFrk0jb>W%VvpU>)?6houxZWg7n}sq)_UFbs-x8=`4~3809`3J% zUapwAG_1YCq3S$-Y7^C(2-ryH)X3o$Hv#v(T00l|;Tw zHg4yNDz7D1*6%2oZ1Q7|0!pEE7Mq(7@VQIu6+Rkg6?;K|H2c3@mQ~EWW)gIi>oBL% zsx@=Y;X!B$a-o#i3kjC1Ul14!MKSZ-V)vDn=j80c$%+95ZT)GVqWP5B2tut$*KWIY zIA$0nn~h)lQT{GZ8Jgej6u!O^{2;9}5L0SW{f$hMyYn?SiaDCCX!85%(=!rd00KFK zIv2?BvnBL$f$S8vAJdB9F74XjUoE|6E0Dqht=ZAP;2+Oaq2lf_qfKT(p6y=nX^HIJYC^E|FL`-5bhkH*zsnJ4cKzq|u&OeOoCM zO!x~-s%uwN-MzqGX0z5Xu)Zw3z_J=Z!DcdaTAoaHTufhosZx5$Mz(ieg080lPYXA)cL4gt;rkhTmZB5(4iN*Cf6QX4H^hxVLrzCtZ*Xsn&w z%R|WQSb#J9$d9pCn9gE#C=m+&CdcM-f!I|O!TRM9qrw9m74SPSnQsq;(u}mwf5v@4 zPh9Rq1=pTGYlHJ`KMmpY1`$1$!unh4b?b08XWYJ$lT$#P2LLVabr@|Hmxa>bv_VC7 z2Y*R$Gpv58stJ$xw3U1`42ydJALO4EC^zx2n>c`}vZNbB*j$FmJ1;NrZhuSpW8j#p zll504LO=Kj4K4A;`8W0HjTy324BJNOU=wzql9H0OMZ;LNG|RB7g1FnHGwK-@VEc&C z<9u+^^nUd*^kCO_T_Q-3s=y0a= za}qLdlE5+2{v@s3+cUY&p=wJK`=E7MPEG|e0Hvf}Ke`uOaFOntrD-AvcX#_rl)Km% zsez_ttd0e0?T2hJqM$bv;C|_a{LUuj7Sk!Ur~ZN*8Xo>(NI66lqlKEgLZJwEbZHVH znZ5~r4eU3%WD3tySDncBae;PuY)(%3ObW%1es|p%Vy2n*u}Iuh;CW?-77<1H7{xQ+RHw=eie^FQp%! zvrK*TA50~7e@K4%QUATB{FI(&Zf*yNiyC?CF4d6WXnJSBgVixvzx_~L-ljVvr2kSl zn&dY;zGkQtK78=42WWqiY=(hvH?SK+|Mn1vIIz`VU)q4XUy_eG?n zEe6@~D0PU<#7s)p{m?v*x7$m8hC|A^Wf|5ko;b?Ic!gi88M>%XF)q(0$Muk=ShUh` z?AYY6M@}hz`_hQ1nh>)@Z%$PWYiUuVVt#^Y21R5U7S#9=m(@t~~UYz`bNPr>9$-u{>N^MFkura*v%CF#zplvtZGpuNYZH6IesC zW@i-}(33A${^DpjR@u2}ury{ZZ1bj8Wp+Sqx})8V3%pIY(6TU#s10jITZ(;^Axk{z z!J0Iy4!5;96*Ni}XXNC-QF2HUIEv5@&{a#QU8Dt{(uK9HOf~G$IJxp-JqbhnaCf7t zXt=;lkdR)GLT1sM3k+*00uUt|bQ(MD9EpUBkpYq0$d$4V==T#3Y?QBa&goPUR^&LqLv5Rs_{#^>mOY8tv zt~9{jd76YdVn2&4d!lwRty~mJ+a1YQUy#>2DGJTxAqcbR%5#>b9D@-cm78W<67Z}M z4ePVSelfwdr^>NhhhpMlcxRW?UfG`FGH`i~^v`m@n^^ZS!YY^V* zK&HU2Wk#)3DE&N((KbQ4)M9_b94ANS&UJ@&J!bSoKReqPM%*cK-{{A1kEoK#Vek%z z(WT}@m~YwIDlA3+rMe4)_=wzD6)ATr3 z9$Oe&?&hWoJtJu<-3MooDSB;j*i+HTwE9aMPEC-G=7uOA(XcyDfYMG=Kq;JPG@9?* z04&0XNp$iL{a$%|{j#{;)}nBJ(^(lB6`I+lhwv7!|I(kN>5S4)(DRM5(fwx7R65ubhkU zs9%2P9QyXFn;uy^Lcf#cES# zXANvu^O&uosi`?4LnKQcV;XEJN((P(KuzK?A{Ulu{r_`M=gT{b=xA+9n3YvrWKxZ* zaA05H+5R8C)zs3`O5jexi#J*`7?So`4OzU`PJ*lP z`*&c0);F*WCSV-NsHQb3ghzgRG4yvOecQdaiHB^+c>KtF zk4_o*Xi+L_57~c7BZorVJ~j&|n>g+~mk}*} zkDBy0Mq9;ebYX3C0jsY=fkDg+3fsB*f$u{q14uvrTg%_Z(@7_C36<#j#+Xt5|CNg2gBs?TMTgn77`9uAh{fXgPu%&zFb24 z6oL_HLE*4}#AvGoQl3mvbs*_}5C1+D0qTY|7W6%II|XF+$a$E^fpjMU!jip?IT6Tb<&y zWLfb6S65dHn68N%+=x_7lWPuFFaoIR{oS}GgGmT${our%ruy99S949S@%wvv;EHxZ z3!6QJi;~dhr&>4-x)OuL59Hv4O%9_grO~u)^#1NA2k#AjMSa33Zo9_Njkx(9vj=Za z8M=d(&ciOOAefFYB7D~XlZ{zW!M27TI~i@Zw?@BI2T5i^U>emu>!YPpQnSAF@}5e_ zXo35DY%J)D(R;dk5SfsMyOx~I6z0K?b@ul5#w2p(bJ3NmqoXrEfFs`n_9+xUzP2&N zrCy7we$G}H{TnDo6NzMR%4kgY77e3S@%O#ZS5_oPH~lF|>1}6zPT;z}U@Jr&82-{) zfWVX1y_I&@o@8~x4~I(?g{@b!4<07Y&Pvji;Ca>eUM{_PBifG({^^EOJ){CDls3$o zxPqIt_B&a26*m!e`G?ukrKS2=1Mtt935?G5{?GSXeGLk0bhoLz<(jW=;4_-L-i zF>k_jmm4H5oPdr^{$k6q?>kGKNJ4gHD}019aJyhC;=tM?++cLFr^EDT;h1~7P$82n z2J=)bu(FDZX5xOTWHEMA7t@7kn2h-4ye5OA7SZ>{?U-zG#pg=SCt?tVH$vsjOzt!t z*d9geiFc z{u4mtd~_+5X|DjS9)H&eJoEs-K=81q~NNp_?A#u14>^ z4I;Zu&?N5~A;?nXE~R09zmL%}nT>zCj5Oi9z3EV8$Fg|Q4j5zr>kW$F<@>>^hc9)G zsE~pRkL^%+*y1h%y>PjZ)Kj62YSb#FN8tJzHSY7V-LWhr8`u?c+X1Hp(>!Dg=`F!E}N4zpv4l)8fJNu!h14DN1O)b zVUj-b{NfsDj~G4r;>*jHTkXM2iS(sl-C2e(x=m=A-OcLgq5J-!X)d&&`-W}b{%H;V zBCrPM%4tGU&vJ(@shTqpuyn!Ylp{}hc_ynE#W#0R!Dlqht9sns_7suz*7 zRgo{Nbj>8I7;&!yG@Cem-tFGMT=kltPL>A=61(`j`1{d zjD_@kG6R;(ITeRLMJ?aNVtU$~NymoQW)E1BfqV0zlm!dnJ6~_&a!)M~|I{`Q0Z1+G za5)S~Y}fVkT*Iuwavwe*Lw0VFRiV?&9HuP&SHm$M{eVWD+4jtY>BnW&WxPdrG2GR8jrc12c>Aajz+Jwm);J?1l$r*`c z-h6WsrQH?4YIHH&NMJ!mh%cb$$8(dmi+_4RZ=NLiIhfW0*1Y^D8Kr0OTnlvOT45wL zr%{4$ek#qUH=8U9I0@GvH)q5hJ7sr+JTf^srN;E==ne%Z|n~dO11Js1pKNr2!%LCT6Mx`jcmN!lk)KZp^GW#?{3}M!FDk z5-VJjD5VkUfOeww%-;+H1bbkA8j45~(FHz19aMEs7Vkb!aL`7FN_hmW*k5;&7D=qO zIyz$RDsp9&czV7Ua&kEMuwPx z^ONu68i?}=nGsG*{$)9(JG$m(IOHE-TDlcTKE?#&IbySAD>I_UVBK+Qa>x~D?T)cSwDqK z9$&lN0|4R;y_woBUdL#Izt{bJI!gqclg*@r!-Y9|P}RJl1Me;|seV9?+S|`F|2P+A zRChGZUs?1FBWXwzPr?HSVy02)Cl4OBw4^sWC$}yqVso4%__2 zP##iI#*H|OryNw2l)A`0=`|97krB-*|qY7V|lwHr-37YM{pE@wF&F(eN-!JOy!3>3<+Z z80HI)Jgh|f32gc;ZYt*I_SJBg6vEj{f;N{DE)gt1rzjqe^H36dXzb5Uew#pO>M+2 z@t6&bYg6odFJ9fgDkVt}H~Q++i`;NY4L{7zV7^IplZa9At3u>MV*)c1;M=CB_I%DOwzImZ~E3a=%m-YRKI)mwN^YaKD^w{Lvxn=Q$V zne@GPk=B^0GikN%kOy-oY{yniNsqop)T_hsnYYa8*DqsI@%5Y>U8Qg`t>+{>EyX_p zx2Pb1%aXPJe1z(2!~j9Q-Xx$PlDxvh6MCmW?eGH&>3a`jdMHg3<+3tAw~aP)hl(-C z_`&rJR|XRi=Hu2#yMi|)R3kZtMO1Kx=D-(5QBF<_2H(-nkf*XGcu~v><`p^X&xo^b zhokdb8=Lm zuLfTAw5Y^$Z#Yyf#RTbac;e&aq8t55Fb8pPrS0aTxZ#Fga{^1;BI0s)fOSgA8eajH zW>9^{&BmX$KmqN*_28V3nDfRdCGkczV}h?baPXO4bD*E+cq$%v27`QQeeTzC?h<#U z$c8usZ6q6h=AyooVm?C0+B}REhT1p4sA8|_lozoVof3PYOcNY|aJ=V6_%p5S@GRVz zWo~Xha7}4v9%u{A-k|_v{4exg;fw1J)Vm5u;USZ^63|yku-{7ut@p)ef@^_4T06Nqq zHu^+pbR)?W!vNCE&q`@U_LCMLIf7G6*xg9 zC@~F%nlPX@D`Mz=8M)EAjSQc_onyjZ07eq>=IZ(4Du-39j#_wr-)54B!;5Fr%3pk~ z^ND$b2&ZBu<@H>kV%>*CV$%en@Fy~TD-}0&L}A+XG%_PJ7j|HZ)9cKMjW@Qx$oWF* z@o|JSu_bgxL+&*bZ0V-zz-1?}_4|L>+Dx5H$vuFUtE-mu#W~A#m#&|7@03JAPljoo zTYe5tqI7#aiW%jsF!KC-XX&_|XR@scg!wXpkC5i7BZGhRrPw5ej%$ z!-L0h5s%Iq!#j2gau2uAo9`0j5=wrc00(q&jgwQ1Ij(Cu?v%}oCe_64rl`&Pm}gRr zdQ`f;hFJ=_qd&J{%F`#yEVKI~~KmxUptJ1jdBexQ`3$8h!wL6gyVhG-cZ)k82 zLV;_nROo(I2N{fC=02I$z8VzLrQDcSEG4;`BsaG}Qmr%M>L|^&$;Xw5( z(l9edXc-X^(F$a(ssC2(f&64yL=dpd6YA7Az2@=lX6$k_;)PXaERVbW6dGoP2LesP zq{ZtNZ5xd$IU@ngo$!}&|F0eHe!kvyl*p7D^XR2Yq_uli8+HNdo(E?{Fag_C_!BB4 z)Tlb+N=_u4<7d|4s!}wiMI=ffkA>p$q1}dAS78D?ll^nC=mSHR6|&GJhzNdho~Fx1 z+-4>mx1vWsc{`0J&MWExc|u)T1-)fPqw22I)vNyoGY7(cNTzwL^z+=6z^zVV3lCh& z@4P}1UJ!4SD-wqv-UG5X{SN!*OxC8kEzzSgF03 z?(qOfSr?o%-4im1H$b5xAe=jxdG0dZFFx^}KE$8jph#!eN%$6#>4Zq(m^PPI8q)e$ z#UA*nS#OLud)>Ju!M<&nz;--Gik7ei6PTBid#)4ons3}yPtWk~mc@k=HfV<~^+hD6 z5?HbU2=T%foSTO9Xm}#I7igSrl%R}qZ<;iGoe~;coZmTx;HE~f;{#}m5HA9+)~+%1 zZuM6hEvu$Ct0QF1o`y(>K(E-8Iy`fvOzCF+E7;(q;1x3jxy0QjkwkA#ej>LEAP9uo zLxUs`?T|1$fUJnj^r|}S_V9ycxNjiHXf~~M8#;m~QGMYoVTGjy-DUxf@Dm`CYAISj zG>8Zw?{bZp&9mMX%!wxskJT!obb(#Sm3E)Re7jm8GB(q~ReXdoH}mJjcafBgI+$K^ z69fTeOzFN%rFPB4SkOZU{rc0%p!=5i%pp5wo{P+Qf+f_#RVWJEM6QWEtp-l`6nb-k zUh}N&c6Iw^nu8h|GG>JV2wbO8?uQ@L-VOhf!5!+z$;k!@dv+2J3UwZ%o}ydWT$1HM zlqff}%EDEB?cjfmGQY+s+v zyDzdHYzW^JGxpU7%t1Tz1S&ssqQS5_B#3#GB{leID%I!uovw1oX2TDw0O#dOIf~8+ zp{-=B4yysfrAIHIE3d+@gQ>m@Xc}8d3q6CTvChx4`*z#liWXDzyJs@zG-9077s)kJ zw_yHEj$AXTyZ5%o%6hfZP`=Ijy01>qUeUiyhJy_dpvMB(U48F!jewj2aQV^yxV#@m zUmqtmi3(mFq06YrKF+P!ghbO6Ni+5bnjkU8b|>&UAYjd0kE|ce&q&UG`3!H4J}zVa z`Whj07Vjx&RK}wEs?hC_KrXEUhh45+DQ#CVLs!=)Jv8ko7n2fN{uVasZJ3qrCSCszxgemen^bJz7SYam7}fQS)Ji1MoBipTYh@#kOO9!? z^+VmWO=&p@}WZu26B?1 zT*xBM!S@(*|3IRfHja|{U&yZ1&P1Y$&5TOa6rXTnR@I`QU>Pn|RU={$05J$;T6rn8 zYe@w3FbZ*xAxKAJLWN*$;u9U*h_{F-4TyWNPMLOQ`+t%R)0c%>54t#f7aE)#Age0G zv^nDP4|A4hvO2S>$)V~`P4QJds_*GpIH-Fh)p#YGHA_OQ~V3Afqg$n7qHTtwOpKy=z zh9Us=D$J@|+l9Bak8^zraz0(b;m(DDQl};i=+Wzx-sxC?G4-IFmiB(IP0#lhT^RnJ$Xww{MWLM&1o>^MOQ{k4@N>?jP?VXg z8)l^-*Qmsx1=JDjlK5L~%qpnoU+p=IXGlH%QJBSJ()`KZ4kpl1|mj|w4*6Ka(0461sXRA~+2iYa6tdHd(Bi8iC_WXgrT1rr7` zZ|A|{K9my2EDo#>BjxKci?RlCsbF1uj{OG-r8$JsxN0WmH}5*Eu4KC~^O7s;6u^Fn z*eV7svWcjv@Gl=8se=uTQ2!%sLWN_kLh1RqF*yjhQCx^9C;_Hln8~216vWWBuYk6- zeSk#)Bc-`SZbH@^L5Mv^Zns2EXpj?i@O|3p&}c_y-ddUIZs%Oi@K2xK_XwUB?xr^P z@k}191+L2KxTxowM7O(p6UY-z0DC-k%>;;BBUb~g=Z(jpxeAat+Gr|o*H3buQufZH z+3(fcrHF{7%Hvb+u%Nq`w^t~5EHDTa1p$&j;V>v={&Dd9w>Ex^VHT-R^ri$35yUXn zoWPk`lDM>*QL#b6BV^)Fm&jqc`9@6VTRk63y7e#7;Oo3-_vwE70FT89K>Ue zkh_X>mq@fT{*eBVQSqgG@J^2!fb*q>@^<0Kuz072MsH?XtyU7K5YZ4UhXM#9S!4un z!z{ZkQ8rlvBufmZOe=(D!pD7Niioc~QE*V3$TgTFJupL$@RbmBxPmSP3c=Hg7n~Kt zH&7aalA7TZ(rk4lgjVyGB=Qi7Y)4^49o^T15+v>;v@a$kEWwoSd6p=F8s|n_*Ay>7 z^?lG9)SQsmY_`1JH_!{tY@G|slHP0+Pm}peVh1r$Mm+fVnw35Y2NqwFI`&lsSsuu; zyW1i?d13fs;wSQ+2H95?5qqFvCpiG5*EN11B?)H`j@~i8JyqpQH&Q1rkQG>u!mODz zilFNVMbPZguh)D!o+delC<{3@n=KiWg>t`e;-T5Kyj7)QUT-fM427sXp?< znN?fVqyo+o1yW9S2v;^un*yl2d6A&)In{^BRry}KZnZupl{b#k135^4_gv{58K#_9 zRI%)79|_t>n}B}M@KE=O>Wf7&aN|@;#a$-yr4l~731Nm789-F%LZUBRHC3cN;{FX=pf$Cxh>jWIPm6)9PdhMjwB~9lFX5 zxGY_G$x2xh(}B0rD?FQ2F`7Pdm|c-=RNg8w#HGFJqve_PlF$4yRq&o zH1|qGziJ$PKX~12Hs*+opCX~bW`qWSR^oD{4s?1jH=Yg6ClmZ1VSe*xfEX7FRQzvOf z=Q2Ri4We7O+txJ6uaXuANVa}lO5>d+%HxTiBwxQICDY<)m<4?35i;E5;;-i?X%kMK z$>{v{a$%vUcn!r#YYrBpNMM?bnefh>>M!F|pNQ*mQBIK$cOseJ|KcL1m^JPH)m$+R z1@FzsBs<-~M-%=^`HL2Lj#wKF4LLTa$M?U0crpEDu9Qrth#TQ9xDRS{6>O~qRwmdJ-@$5uQ`*u#6gWy{*f$xz*@%4PKy-6--id)q(eEm$P77Uqu%=> zud(?~rPxwZiBM|R7PXlf<-=6GEN!;7K>CkYn);MIlZ56>d;DjdB^3@f%!{ic*I* zsO0y*2^ID9a+i5T!3AVooD+`#;}Gv@;)<%%Ikeun5|%4RWYR9SPK+Hd;|@tJ;w(M@ zQ0;i;oct#YA1`2N?BcF16c$1d8Ci~^ii8pBDn?7Xt{75zFQq?>uwlbmpfEs8& zGs*AuV@3ruyX_0w$IU;}fpqlLGJGuI>*Y%d8$I8>8E>#gA`*Sa>8D*Hw=%8fDVEbr zX7+&bN%@@A$KlXolWN-|T%TlV54-eZ+#R8!I;3zvza?|6=AJYQ`0kEF4&ypYqwB3> zds+bO&7hS&gr2eUfvlSdYoEf)u@y0FeI^U0Wa~AjV>2i&ybDL}w~6tw^proMi%2OD zyh&GjvmtUZNNnjfuk)jM{64Wne>~iT=L4}T&Fg^t;@7~wg9VY zjo0T5rBs_%j4s~hu^l?ZG~V}sXm}J9LH2^hiYHzLgu1j2Lcut+d*~1l_iYWvl4cfrz zv%q%l!(bvL1P;GDSWe&wc>DzS<^l}WloRh>NCj_UV%jR8UKQY;H}gB4kQ@Cat#Z-) z`OX^w2deBS*?=6%d*0I#et#)6NBDg_=E$E;dJkYhn&4YNvJulYW|-yenD^XcOy`JJX{Gqy!NnOl$MuIK6Y7^Bno zt~4KIF>x1pI&j;VOsfUm(L0OWr(@EKgx86lp_6OIW{@(hQ0AyWQ^;8|gYr4THO=PP zq=%0CvN{~8zCU{tq zU32059&aC9K|Sn@d~N`W-G!=>0++VY?A}c)5V~z5c2p1y)^a4*pMUEtEjQ|pzM+SQ z?~uUK4nx$Wl3&3>kCf&kYZ7-Ek+AsGZ6Y)G=gg*gY#7}5Q-m+`wjZPe$*WqImaz*5!^(ThtK@3!zz)-3l{-lLcHSS)3shwMWzG<0~aEEy|t~Ux9$g z$8-|jP^m4XS)=-R;5ABiS5$RKUOtV)KcwxFW}PiT*MT+VN#1;q(6J5!Tz zSImtlll;YRwez$dK}th_T8Xb;xe>^fwSIpqS+aL4C8k;L!UvmqPdlM~ zfz8q)CCHu_t;HN0)HV-O!Ei5rm8^C%Awebipe}-j7FbEAfi0N1BNHLM2pk3AZI6>-*Z1G# zUG5y|YH4Y4N|r_!1Ijjpw9!0WASh@B8HAxy1_RtLyF4e}pWL|oC!r8>#%4c}l-jy! z_ZqnoHwh7swGoe`<_P8(DRKdo!Pvt<3GgQqLC{K?_totD&KnqPTtMpO)&MWmmUnFaJT7CbUAnowSS3*y9aG?{Sr#-jKuZzupfQ$QvqRJbor3r9JCU z(b#6BG}AI`;4pW|au9rJ7^+)xb8=vc$(@WDnCkeghu-Xvb&$A|7=!dtWXh2ux1QWU z6~#F%D##5@aLO~|xds3(9#ALr=*pvLCER!7JCgk>1U5A4H;z8EoiR?t{FN<+^@G_>dp4l>%FP*+#X_1JA3Dw=44 z<=aovwLw6+Is2{4R?+O3RS@V?kaao<5D?!qpJlYQkqbYRipESg{hMe)lE&)S#qIIu z5j?lUs*R&Qh*mx|JW}dMiX!OmgVySlm>^b12>5Zx2?b3~+xC{dp^KjjWQFu?f~0&|8Lj*q=nQ1osCTXLijd$BkDD@`cE@xUo+_Ppfx zn}QJvwhMbstYEj#gZ>e6pcUCRBxj*XHJuGbjrj9;n8BBB&@6XXYsB;nTYou>lB?PD z@=v--VfW6I<~P~EQTYuH1!;}BG&Hqlr}s)9P^f5rWO?S1=S&Dr<=tE)>*9EIFDjZ0&2OwvW^q?6uAsL3U& zsJ$SDlDR%&!IMi+%j>igVh@0XeP=P&sF z@IH@ujK}WvTCcVC+H0@9_PXqiC1d`GXp6=|Q(Ix$K*7b%QiK1R)KU==oaH%i3|_U( zXiHJpVkyE=Bn}yEXO9HszZgiIvyD57o}p%Vj{@E^_nvm;#31Bc4uK5YeQJR45d^Ek z`lCO>LHIQyJ-M{sRS< zm-M8IbX_Wm-?1|l2jx|4MoOl&P#u58t>#p3oS1Rt!o9DKF7fs*?}Gho=tp^X(Xq%-y%IuT7}Tq;I>ZRqUv2d*DA6I*M39+ zXVYUOTSURFw!q@Y#rm97os$CR*#@U4Z{8n;jhn9xTx`dw!rbSF5e0S-b_A#WijjP8Eyk<*9Et2;34=5o zZK>Pr>*R<*eR`G{1jImBMw3yRjSX*sqWvb>c|n)lg6qwx2!OG%Lsg_l#I8^-z?_x+ zo=zNRkGY@_284{{7qb`NKV6V7Sh z?Ag_e&1+>T90jsdVCFjPQU>F63O&wzGw+jZCJTOpPP0M zzP+9(B%k5eqaC(l_5>v1_eAeB(q z6TJ)_E9Bg}tS=9vfI>|GStm4Q?CZkLR(ahFpb16MM0`FC31_hEt9L0XiI=go7J(M_E(`>5wbt!n;g;C7M$#38igA5z zseUOE5sF^sT=5Gf6;GC>ci^C9Fen2PS0k+#dlZkj%G6cKgE7L6yl z@nh{$iWz%kgzb8DY4Ooh_GneTkqk$$yhPdkmDzCtuWe-w_GIai^(U{bgHin(B0TAe z_A!uzZ`vzUTaAz!e{o7O%+)7;Q74~qSg&QJ}Q8vQ+pXtIJC=FAiy7MZsInUg@eFPB1Lnj{# zMK4!8fI+(qo4_K3G$G`^8mh$Rbq*J)HX;Mz$G#&5pfEcO>eL z@xmW7dUM7F(YqCcVXus|>}-5j*a~huU4!|uR0v^dH{l&~osH3U#xwxgt`AF5~?WILUFTZ)q2{x@BU~){kbAOP+ z@TcBG!}s;hnYH_Uh-OTU&W41ISw}B;Wn?+!-&Nb5KfUUF;$7LsxpRM*u_Vp+hGpC@ zrw%Sn3eey5m0b8$|4mQC)BnhQzoMx7=Xoi`Bh!jMTxojQ9C=F=7cG1Ja71faVMq65 zEx{uW5rh;u#C3~yDGn{u=j@-UZC@|@zQ?ojjdNJ@n#nQ8 zY!88#JNn@DIkQAKNf2R|>YdFuhbmMHQ(vb)#8LoKF?QswmUK4U6(|1S^ z-HZuU^p=D=*4In>I^BiUTj^R7cwa7TM5vo`Task7tY)tWn*wosOu6c zgn?rQUW(l6TG~+sYy?NW;=w8bXL}6pA4EVNliS}6!$kdrBD3+><8Al>{F;=Tm)G_K zQmtkR;eEdVzNbm8GxBUQ+L{b>9;s}=^=h!_fj&Cuvj+2^9J$}4GLyPdG<#Rb89#}I z%rEox{c!KVfdf;LW2XxM0SiJ4p=X ziA(+bqSoG>)-yqP&|=j|SFT~76AHy&-@|Dp8zpPPDy(@9=9++m;bjpHs9~xaBIx;4 z=qD9$_J4M#wnl?9U;9?3+w}6)3^2dZ6IMJHjC@3>Swtc*2j4edY5Fzkj#Hwd(nnvO zc*$DWU1zb!Vbk+oGn-?2l{u#~@yj&?j<%X~4Y9vS+SC+b)c`^KI34AVw^>QuDD3`# z4OvQT;p^ek%rtf~PQJgtTu13f%3y9|;|lh7J4*`wBjm~+#-P$Q?VAAE3XJPytQ{Ui zLPu(6+PU-(f7xhKdpsmv3ngDJh7`>_JDE)OYyVM%;l!< zXGyv)-n(~Ct3*fC%Qt^`vN;Is{Qsg|Owckno(uW?De`WS zeO`F>?521-X&q2pgIIB+A%QjK2M-=pV~8=g)*(t8&l#(a;T|B1+Sk2CM${ay^xOK% zVqDCL52<5yU6x@Ai6TH-$O?otAHChZ&Y>@&{8K$Uk)87xJFP)F4GE|YS}&}9P24bbf_?LKtvVk5`J{Qibi!{o z$awz+IzYa8xsQ+i)|D$)rjnSF?M)$fG)yFXi?fW5gcTO%y!76$S`n3r5nW40)Nl@G z$W7k>p5B{u@yY9}cAC(+FKU~wO6AjMmjIl~&46Slfq9%MK_dW~6YbaE zeH*5(Q#?S)^il)mz#xU<-N>2SBGzhUM(>duRglt!V4Cz#a(K$!e%P!pn)?D~+atwK zr*uVL>G6t_xZ5#u?b_#7_42o^=tyIuA_A7b&0$@f*$!!&@Rh^J=rDE1Ez68hNx@X% z1s?;YVwjMeD28(dH1+bvP$ry)kTx!$9%YZiaS2!V!nrRdJv%Iu2VO!9zY07iSd8$# zDb*(pj`(_V{P9D-I34u#iBq&%tilmU_y2$lbmNGr=!j3Qez1G-qSJ81InHZk|q`xdLadpd!R1S$}6~SjECrjZ#PMM@DgR&#AKo1zmBOfmJxI zBT=!$RkC)FGOKZy0_k_XP=(rkn|S}7_j7C+6E{J@h}RW-coiId|M;Gnkx_GBbdiu^ zM54Fc1Y;SE+>oHno8P!hoH+4fvcB!XmI&;GFU^ETu*77Q`;k%gAT`MsybvMmg&_AX z#V8zfc1kx~6)R|YZ<(poU(n7zXLCFuHm3<`f@aUq`2mHW$=4 z3tB!u$xUj(xPeRkoZ4$*qa$9OubjDRfYgF5k&$GyA_D^hUm)i~y}Rs%ZE{a})*N|Y3)6ARR>IPEBrQ1N`jBTmXzV-G zOgm||`QDvYdHU3;ZNGdfo+A_`^{l&s`5t~4^W9jDMX&L;d4ZL%&`IdGYM^w)Vw_4L ztj$llQ<~P@mKEJ~_U7cR4?b7zj!v_)!OR~^W`4ux5Ek%;9|RIqcaPfu3GzDtvzzHC9d=1}QU~E9bY$N zn?CT_Ec4Dkx)tp(K~25AKPUOPut>gn=$=xe`FFP=mDbxbqbXj|Dy*H+ zwZY(MbBN>#;>{5_F!D?9&2^~de^VKt6WQFl3uAhdjOmbWl<7I#oz0>2N^veEImzG$y$ot+yWJ|b~ zK--1CROLS%;Wl|IPQV)G_}sYpyL3B@%UUunGHc+HCK73APt`bR9^>L`SK!ia5-$s; zo;7i(pC<^#QhC=hqZ~H+;mp9GlP@FhP2)=I2bjl&!K%+Y2sT&Dnm2FWI=Gl$D<13% zg9|gyBGF;Yt1G{@J#-O-Vo9+Ayrg74ad)=CtJY}!iK=rKH52oQ*;7IMekXA9=>^o0 zz_pYevUN2QPT&CqnYhgb`)cx+KGyU^^Z?vrFH&= z1psl_bkuvEJCcbKU^OCs;}adMI{s2b1W9&(KHU_l9os`c{R`II76g{;hi++tM!QOG z(%XV8p#xh|`bv|T@~WQ;R!GOCnZ>(#dnasCA5Xf2_|5OBtv1~sPK16sXpgXVSkH&O zh2GmHByL;&PIbE{QY19VOlpj`Soy9{aS740nwFj@Xk(R2KgaOu^Ob(@71bNL)ZNq& zQayn(=kls>FyPteF}+6GzPar-YI}WcZS953K%|J-j}>0HzAvJ{+-+405VG09wb_vZu$MEE*z_LVP{e5aKXD#bznNC zk%(IfYmcS27F%YV!Nt!1^7igGeSRxmLh>kbCQtj5?f)+%S!88VEm!s}qi+SF56)t1 zSSW)8m8JX2arW|-Xm9V}RQGY|(@;q_@jxH)#?BLn`B~Jy5wxsbFBTln44j#dW$h`% zDZmvxgp*sutct@}_Ru!;V0J?Qlo)>C_yX7|0kgDkj}}U#$vW5#Oz_aQYo@XZ2WYzw-%gp?;^!p*RSQ{oO+0})tVD0g& z?M~aSZ1Onl&=M@>nY(~YQI1=f#72KL9U2&e+MSuAHav%>*vCBT8;7Sbz z_i?3S)i9NU-)FQ&QtZkD416TTE}O)_*D>(<3|zp#8TLqq-INEX*c*%)cpU||=drWC zs~L8ChJ8N+H=)=YK4;*J(e^xc)^|0-ZqKj}=D`_uzVFW|_DF_Z#`<2xu=_CVhZy)E zhMn*GS_aOr%UIv57Y` z>kOP>Paea-8Fu0-B0|?cW~HG7E*Kr{V=i$3mC3%QS|O|nWncf6el21E<1FPQcBph* ziNl6`t*$=>&;0x_njGh`!C_?4=R#DHXqM^4U2+mueOdV?Jw=zBUTUCKFsa|cXbQqk z$p)HmV_)vUa7xF0CG_6O>_-Cy@0RMtnY)&J4{ORUlanX3lKU@kmwl{8dF;~r;;;%X zcjaU)vC}d z$_Yy_^3o!O>Z7u7Kg^S|n#zfiR($uE-rxe<8SSEllt*Pm=Mx@D<&*)*ri?I^iY`+kH%6FThjCHO z)1k*mH-hTZvdEATauAZBC8UiJGKnZ(LMc-roX>1VNQDL}tkd5tma! zDpv7?jHHAppYwz`GD3RsghVnz5_v+x86hJ+5<;~JXaA9qMU;^6kAx7P8Ga2DctT1U zAuD-8Oc)_`JRu_(A^mtl>=_|xJRy0E5J#R6rdYVh`cOgpnbSJ1yD=Kd42JvIaY1`8 zxG6n}z*VrNsEw>8WYCmM%QQ^oNsMPChVdjGq?$oWYyqw4PonFQO3ag3?@q-_hnJqR zeN=k%$O=dXEtyHa;lFt4=|y>E%oD;Z9IZh@rjN>)&5aPAkRg;;koz0-1xl${qJYDT zV3|Pa;70OjC(zl%rHL8Zg$hcT0}#;ub974Dj^l+kiK5loCR&lqoIsV4?P2Yfy**Z8 zdw1xD!2g6>>z{40g>wCke6x^O+w`bTB z8Fmkb-Gza-GH}-S2G)0`Qn*Nl{UF2c$FN^x;9DrTjP<>N_1%YIk7U>nGVFc~yDI~K z$G}k^C}}^IOS|#y0~&_5<0H4*z2pQWuj#2qQ;he{R=v-HTtam;~La`!;;w# zH*lvqJA39JLDq7ZE?L>xt%xmU&DY5drRD~AUrPM0f>1xQS@8%?sqg2jtG9tTo$$+@ z%|acybLbpX+0!|i+lOz{IhpIs+J@}84&P?aJy?4jdrl%J_-U;Y=$PEutZl}g8?ts1 zZHEltpVRM!=2b*N4l9!op0Pyr3QOQnq|5PW9DkPwPgbyNj$I~X|KoN*#O z3eM~jkri#m5}y=)Wn@X+rBW%W0^+Rb)=RXM5i^_;YfM~0_=(0da0>=bBOEFvLmtM! z%^B^)`~WYEzop<611R`ahCPq=MSO-~pG4Ldp{Qax4^I2i#;{j-GH`}HFIh{x_zc57 ziSGNfzFQD0CN>AKxAEASc0J0lhcoP14EqR%eHp{vi((Jwu`i<7k237x40{&CK7wH% z!oZ240qo&Cc2f$j^#+2vHirEq!|uqi`|#ityVePZ*DJgjIK$q?u%Beu9U1na6kNqo z?0F2ks6Pb{V|_QK*i|bScCA4n6p3tjaEiT*?wC2zLJDrhgH!A(cOIN#7g*jE> zaX30uFv=HdV5Ap^$f{P3LssCuEnj(i7Xk0xAKbw)OvT@Jm)3;|Yf)dc6S4HINP0mm zy(7<3ek%mmNs>2+Wr3n^4e|Rw&&v$#t{5xIWdgvhueFm+P={5hGFdlIk-Y+DOD3b{ zR6K1na{_x8)@IK)FfKE5g4@8@#>@$B1A0ro$IJcymI`B$}BMa6V~uGjC2HZ9&^+>w@%att#Hh z%n2@;>;g<ff6I?w5XG^MlF#~7VmDUuT znG>9BpcecXGbcD7YV7dlgnTizR(Nwld7gnY>@sT#&ddqUXMwh>4Qxr3dr<7WIia+o z;LM!h8q6p-GbcEEhMk!cau14~Hz$pL?ixJZg!#`oQsV&}~XsfdCzbAmIceP7AU z3C@sW=gkSZGsVuE6VhA?&ddqUoc4VsGbcDhianW`6WlEQokNK8gXsoa>L26H33(|s zW_WX=W)A&2GbcD(L&_RvPH>6T7D_%#%?Hl*=az_V9+GXJ3)Q)XW}(57RR791S?)SV z>U7PCLf|}p%z1evJKKH=i63UUmP8#=<$lAo+Nl`$Hf+nCi%Iqf`Q^^ms>R}QOh4qB zur~kPgSHL%=X5PECMg_RcxU?Do`2qlwfX0W@?k$vJd`~b(X@`@q3pTVy@BU*__iy3 zzYpJDOWUEWy%0(m`Xt1db;ykDbcG^^U37Wo45-%M!xXTX?56Q~w*BUa4hMLD23^M4qtm5a=G+i<5f`T1NY`@t&~ zwOdgbRAAXKjBYKtiZ8G~ymk~vS~nqeGC29$!ce+2aFfo%qkkte5Kb~H?EP^>$r;qi zoy=5DVFZci%^$bFe0E8{(tVn*VqVM`FPuCIu}QqZWLGw|+}R~G_&2+rxFHQjJ%Pj( zhoYRzq$Id1Ol_xevD0KIB6hk;^KqBvITSRVc@p{Zw2e=!x+iM7)-lh8#|G=VEczZ% z>wHuip0P3TrOq!-{QW-`H|d{+;keMF=@HJ;yPByy$@kj61ik)AGiCDR!YRWS-C0@4 z`Zl8Oh-%^Q@hDsP>&#Q2?73+czOScEYhrWZNf7ho?{Owg<8Ny=owIBhx5@Ty;}cu zciI`BWy>yKGYj8gB-Oss5JSG8Xn&@-^mwSq`Z3aUH(OPZd@k~9`wm4$en<^X!O9^a+Bk9R^kvU$gCmQnNz0_;-hb{QS-zQ0Gv!vhSlC z)Jck>reHkU;J>QcH4NRxnN|2tE>X zVG|n0XgQ+uY ze^}vzzIh4bm0GEjE07+tLG0)2yZssRqMJkp8=o;QDijvw&Zs}>4C!OM9@ov~tBmt_ z_2E!2(~t6MA16A6%#lfpl`zKUYX^#RI1I$MM%v?4zjHZP-#&74cOJ$ZHC!4T!?^(q zNb;NCM#D$c`_6HRbM$wfpJREos&5`MLb>6Gz=@P?XZpyD=k z1oyZRRuM8Q>lG&T@-p!-rT|qb3RTE9h`^aV-Hp`ShTvEI5mm^F8Sa0-m5)9QzZ*aQ zAAf=5r_JIr2Qq<|x`1m7LJs0Ob+)odtqvYK8?boK+M{Bq9~Y2yJ%oxpR$VQsYMU_mN9QQ=Y9)WpqH`P z{dKIUxNVy0-!FTo#RmM8lKC*mKpV*>4A1n?4^ZF~;{b#D?)Me?+A$FKAs?MK|M=CZ zTcS+qOuvSH>b3sVC)tMaa{{<#tl-L?Fr6(9#m7hMOY3P^646ZzRvWG^kNO9-R%x-B z<%^drY5G~Wl_@9AYOL2CRDWPCUZxx0ONek=ioew)<({}{9|BnC#-EHOs@rokr0fAHj(7jmS`oE9%^7{4bc}NADDOBef zPTI5#rv`kX_i-{c=$AX+oo$)1{5R7(fe;H6 z!bRQfo5!5XTzHyBdHCld9Q9b*loB(Yd2Zx>PzvXM@XRM!bqQl-H0}i_{3qqkR(kz# zmSwSV9*s9cVaI8dmVd>8(&>5|$I?9-cNLWO{SBEt`9ow@jByQP%bmScg;4&1Ruus} zQOhBAaVgo^-3NxqNVXjLHCO}B*inbw$Js!0Qs)#-ZbVM(k?@}aQ~X7GzWj`it+A6$ z|16_zIdZ~!N(Y29_bF$*vv--{lcL<*n#V=qJDJ&H92cy6&Z8)TREDiK%;)uwVW~~b zvg1zi3je8kzC5pEkuvA;BMO!@f9CsH8~pwE=XSEh@fmG1NKVPYkISO8!lBo#soR2( zY|!%`eZf*!UIk(@DZ$AR1m4sEq?zgC2cLs}I(H923 zY!A*2kJTu@x4^B)FY~L`^@(hG|B&hluJj@n>(|I=7$hjaFuUj9NiaJKBkdAb=(uRu zGRE2J98z6 z#$FA`c7sztL4@ZM;0@noN$F@#+^vdrN*!u#Lg?=fhN_ z=NvZ-IoaV~e>f04mIULpr~K6m-v1V=pg1SZ^XkC1FT(|)spO=`}ox%*vFPdBPSP<^^*>FUO} zt|d8S8XLIOF=IylVlK&tz7nP`GEZy?c!iwx5BWJ$tPNbwOR2V&zsSdhp+RI?4)&UR zMY!s=&?ZlUqbC@mNJ1ouZ%S~vX&5-Sw zKD*>HF4kRdwht$0>{2uhj(*mgtyG*<^Zkp3Z?Zh+;!?rtH3=s!;hwy7OuTfFL02>{ zp#e3J*>8fqy>YnC0-x1hC{RDMvAXaBMl|9x{!8Z$fEw7y(Kt#kdA0A%+tY59lMKe| zW+ACPy;if1Jw!pk6x8?ZRw9JTJQu$_ky?j4EPwElec0xU5BM#|tE3sMjsZf}cpom_i-RQ07OA{0mQ!+a;kfFc4D^dQ2|DsO-zWA=ewYfS@vCgC>xMN>x zt2eBOCc=}qGq~ye@+dp8rJ!y^`L?#(Zq)+?J)?zwzZVx>D?-=s->H|K6Qi!JB#EBn zCqMX@WRSPsvMIu?V_Tl5PEjZ}j_7{8EWx7s-G|d8chZ6|;IAd-nQqij*Sk~2&C?f(O;J>u>F literal 0 HcmV?d00001 From e85b766f5781560facc2f3ccb89266f7bab70730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 6 Jan 2021 17:17:24 +0800 Subject: [PATCH 83/95] remove extra width --- Flow.Launcher/MainWindow.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 998bc3e9a..a196f369f 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -82,7 +82,7 @@ AllowDrop="True" Visibility="Visible" Background="Transparent" - Margin="18,0,56,0" HorizontalAlignment="Left" Width="660"> + Margin="18,0,56,0" HorizontalAlignment="Left"> From b2fcd98f2c4fa66ef211522a3a5f0f525d8dd4af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 6 Jan 2021 17:18:21 +0800 Subject: [PATCH 84/95] remove extra horizontalalignment --- Flow.Launcher/MainWindow.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index a196f369f..a2cfe569d 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -82,7 +82,7 @@ AllowDrop="True" Visibility="Visible" Background="Transparent" - Margin="18,0,56,0" HorizontalAlignment="Left"> + Margin="18,0,56,0"> From 8569b44247cbc066b2916c3ea1371a5a44751746 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Wed, 6 Jan 2021 20:23:38 +1100 Subject: [PATCH 85/95] search preview consistent --- Flow.Launcher/SettingWindow.xaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 121b062ee..e467d9a64 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -253,7 +253,8 @@ Text="{DynamicResource hiThere}" IsReadOnly="True" Style="{DynamicResource QueryBoxStyle}" Margin="18 0 56 0" /> - + From 182cdd199a564349df5ed146200514c8b2a80631 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Wed, 6 Jan 2021 20:24:36 +1100 Subject: [PATCH 86/95] fix typo --- Flow.Launcher/Languages/en.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index adb49b65d..6ee28e3ba 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -72,7 +72,7 @@ Are you sure you want to delete {0} plugin hotkey? Query window shadow effect Shadow effect has a substantial usage of GPU. - Not recommended if you computer performance is limited. + Not recommended if your computer performance is limited. HTTP Proxy From 499a0abe7f1e04bd73a87d6f5986bdad2b89c238 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Mon, 4 Jan 2021 17:33:08 +0200 Subject: [PATCH 87/95] bump PropertyChanged.Fody to 3.3.1 --- Flow.Launcher/Flow.Launcher.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 0f8e6a767..cf2719f7e 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -1,4 +1,4 @@ - + WinExe @@ -81,7 +81,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + From bc3dfd4a73a0ac0ebff249bc73e78f90e67bf15a Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 5 Jan 2021 01:50:19 +0200 Subject: [PATCH 88/95] appveyor: publish self-contained --- Flow.Launcher/Flow.Launcher.csproj | 4 ---- Scripts/post_build.ps1 | 30 +++++++++++++++--------------- appveyor.yml | 2 ++ 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index cf2719f7e..c3b56b904 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -94,8 +94,4 @@ - - - - \ No newline at end of file diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1 index 836e27380..1cdcbf12e 100644 --- a/Scripts/post_build.ps1 +++ b/Scripts/post_build.ps1 @@ -1,13 +1,13 @@ param( [string]$config = "Release", - [string]$solution, - [string]$targetpath + [string]$solution = (Join-Path $PSScriptRoot ".." -Resolve) ) Write-Host "Config: $config" function Build-Version { if ([string]::IsNullOrEmpty($env:flowVersion)) { - $v = (Get-Command ${TargetPath}).FileVersionInfo.FileVersion + $targetPath = Join-Path $solution "Output/Release/Flow.Launcher.dll" -Resolve + $v = (Get-Command ${targetPath}).FileVersionInfo.FileVersion } else { $v = $env:flowVersion } @@ -75,6 +75,8 @@ function Pack-Squirrel-Installer ($path, $version, $output) { Write-Host "Packing: $spec" Write-Host "Input path: $input" + # making version static as multiple versions can exist in the nuget folder and in the case a breaking change is introduced. + New-Alias Nuget $env:USERPROFILE\.nuget\packages\NuGet.CommandLine\5.4.0\tools\NuGet.exe -Force # TODO: can we use dotnet pack here? nuget pack $spec -Version $version -BasePath $input -OutputDirectory $output -Properties Configuration=Release @@ -100,13 +102,14 @@ function Pack-Squirrel-Installer ($path, $version, $output) { Write-Host "End pack squirrel installer" } -function IsDotNetCoreAppSelfContainedPublishEvent{ - return Test-Path $solution\Output\Release\coreclr.dll -} +function Publish-Self-Contained ($p) { -function FixPublishLastWriteDateTimeError ($solutionPath) { - #Fix error from publishing self contained app, when nuget tries to pack core dll references throws the error 'The DateTimeOffset specified cannot be converted into a Zip file timestamp' - gci -path "$solutionPath\Output\Release" -rec -file *.dll | Where-Object {$_.LastWriteTime -lt (Get-Date).AddYears(-20)} | % { try { $_.LastWriteTime = '01/01/2000 00:00:00' } catch {} } + $csproj = Join-Path "$p" "Flow.Launcher/Flow.Launcher.csproj" -Resolve + $profile = Join-Path "$p" "Flow.Launcher/Properties/PublishProfiles/NetCore3.1-SelfContained.pubxml" -Resolve + + # we call dotnet publish on the main project. + # The other projects should have been built in Release at this point. + dotnet publish -c Release $csproj /p:PublishProfile=$profile } function Main { @@ -116,15 +119,12 @@ function Main { if ($config -eq "Release"){ - if(IsDotNetCoreAppSelfContainedPublishEvent) { - FixPublishLastWriteDateTimeError $p - } - Delete-Unused $p $config + + Publish-Self-Contained $p + $o = "$p\Output\Packages" Validate-Directory $o - # making version static as multiple versions can exist in the nuget folder and in the case a breaking change is introduced. - New-Alias Nuget $env:USERPROFILE\.nuget\packages\NuGet.CommandLine\5.4.0\tools\NuGet.exe -Force Pack-Squirrel-Installer $p $v $o $isInCI = $env:APPVEYOR diff --git a/appveyor.yml b/appveyor.yml index 1f0937d6d..ce36c2adf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,6 +26,8 @@ before_build: build: project: Flow.Launcher.sln verbosity: minimal +after_build: + - ps: .\Scripts\post_build.ps1 artifacts: - path: 'Output\Packages\Flow-Launcher-*.zip' From 952a57d8587dd80f4d9923b84168f82af6397bb9 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 5 Jan 2021 02:00:37 +0200 Subject: [PATCH 89/95] appveyor: collect squrrel artifacts --- appveyor.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index ce36c2adf..90ff8cacb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,6 +34,12 @@ artifacts: name: Zip - path: 'Output\Release\Flow.Launcher.Plugin.*.nupkg' name: Plugin nupkg +- path: 'Output\Packages\Flow-Launcher-*.exe' + name: Squirrel Installer +- path: 'Output\Packages\FlowLauncher-*-full.nupkg' + name: Squirrel nupkg +- path: 'Output\Packages\RELEASES' + name: Squirrel RELEASES deploy: provider: NuGet From b3b64e1d2e7d150f5f4ff2bd864d6259d688be05 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 5 Jan 2021 03:45:31 +0200 Subject: [PATCH 90/95] set SatelliteResourceLanguages for plugin projects --- .../Flow.Launcher.Plugin.Calculator.csproj | 1 + .../Flow.Launcher.Plugin.Explorer.csproj | 1 + .../Flow.Launcher.Plugin.PluginIndicator.csproj | 1 + 3 files changed, 3 insertions(+) diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj index 06d8dea7d..1090926fc 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj @@ -11,6 +11,7 @@ true false false + en diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj index 9d9c09a93..9f0b46d93 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -7,6 +7,7 @@ true true false + en diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj index 0140444e1..cc280b9a9 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj @@ -10,6 +10,7 @@ true false false + en From 99e0add54f9c9a2a65cdf6c08409cc465653093d Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 5 Jan 2021 03:46:32 +0200 Subject: [PATCH 91/95] appveyor: deploy releases to github --- appveyor.yml | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 90ff8cacb..28412510b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -42,9 +42,30 @@ artifacts: name: Squirrel RELEASES deploy: - provider: NuGet - artifact: /.*\.nupkg/ - api_key: - secure: n80IeWR3pN81p0w4uXq4mO0TdTXoJSHHFL+yTB9YBJ0Wni2DjZGYwOFdaWzW4hRi - on: - branch: master \ No newline at end of file + - provider: NuGet + artifact: Plugin nupkg + api_key: + secure: n80IeWR3pN81p0w4uXq4mO0TdTXoJSHHFL+yTB9YBJ0Wni2DjZGYwOFdaWzW4hRi + on: + branch: master + + - provider: GitHub + release: v$(flowVersion) + auth_token: + secure: ij4UeXUYQBDJxn2YRAAhUOjklOGVKDB87Hn5J8tKIzj13yatoI7sLM666QDQFEgv + artifact: Squirrel Installer, Squirrel nupkg, Squirrel RELEASES + draft: true + force_update: true + on: + branch: master + APPVEYOR_REPO_TAG: false + + - provider: GitHub + release: v$(flowVersion) + auth_token: + secure: ij4UeXUYQBDJxn2YRAAhUOjklOGVKDB87Hn5J8tKIzj13yatoI7sLM666QDQFEgv + artifact: Squirrel Installer, Squirrel nupkg, Squirrel RELEASES + force_update: true + on: + branch: master + APPVEYOR_REPO_TAG: true \ No newline at end of file From ce2d5d247e5763a37d83321a1d04536d55a532d9 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Tue, 5 Jan 2021 21:22:54 +0200 Subject: [PATCH 92/95] appveyor: remove zip of output from artifacts plus some clean-up in post_build.ps1 --- Scripts/post_build.ps1 | 29 +++-------------------------- appveyor.yml | 2 -- 2 files changed, 3 insertions(+), 28 deletions(-) diff --git a/Scripts/post_build.ps1 b/Scripts/post_build.ps1 index 1cdcbf12e..b08fac8f6 100644 --- a/Scripts/post_build.ps1 +++ b/Scripts/post_build.ps1 @@ -31,13 +31,9 @@ function Build-Path { return $p } -function Copy-Resources ($path, $config) { - $project = "$path\Flow.Launcher" - $output = "$path\Output" - $target = "$output\$config" - Copy-Item -Recurse -Force $project\Images\* $target\Images\ +function Copy-Resources ($path) { # making version static as multiple versions can exist in the nuget folder and in the case a breaking change is introduced. - Copy-Item -Force $env:USERPROFILE\.nuget\packages\squirrel.windows\1.5.2\tools\Squirrel.exe $output\Update.exe + Copy-Item -Force $env:USERPROFILE\.nuget\packages\squirrel.windows\1.5.2\tools\Squirrel.exe $path\Output\Update.exe } function Delete-Unused ($path, $config) { @@ -55,17 +51,6 @@ function Validate-Directory ($output) { New-Item $output -ItemType Directory -Force } -function Zip-Release ($path, $version, $output) { - Write-Host "Begin zip release" - - $content = "$path\Output\Release\*" - $zipFile = "$output\Flow-Launcher-v$version.zip" - - Compress-Archive -Force -Path $content -DestinationPath $zipFile - - Write-Host "End zip release" -} - function Pack-Squirrel-Installer ($path, $version, $output) { # msbuild based installer generation is not working in appveyor, not sure why Write-Host "Begin pack squirrel installer" @@ -115,7 +100,7 @@ function Publish-Self-Contained ($p) { function Main { $p = Build-Path $v = Build-Version - Copy-Resources $p $config + Copy-Resources $p if ($config -eq "Release"){ @@ -126,14 +111,6 @@ function Main { $o = "$p\Output\Packages" Validate-Directory $o Pack-Squirrel-Installer $p $v $o - - $isInCI = $env:APPVEYOR - if ($isInCI) { - Zip-Release $p $v $o - } - - Write-Host "List output directory" - Get-ChildItem $o } } diff --git a/appveyor.yml b/appveyor.yml index 28412510b..b8812e7ef 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -30,8 +30,6 @@ after_build: - ps: .\Scripts\post_build.ps1 artifacts: -- path: 'Output\Packages\Flow-Launcher-*.zip' - name: Zip - path: 'Output\Release\Flow.Launcher.Plugin.*.nupkg' name: Plugin nupkg - path: 'Output\Packages\Flow-Launcher-*.exe' From 407d8f0191047d8e82d52538dd9d36e8da5636dc Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Thu, 7 Jan 2021 00:42:38 +0200 Subject: [PATCH 93/95] appveyor: simplify deploy conditions --- appveyor.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b8812e7ef..7d1da7f3f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -56,7 +56,6 @@ deploy: force_update: true on: branch: master - APPVEYOR_REPO_TAG: false - provider: GitHub release: v$(flowVersion) @@ -65,5 +64,4 @@ deploy: artifact: Squirrel Installer, Squirrel nupkg, Squirrel RELEASES force_update: true on: - branch: master APPVEYOR_REPO_TAG: true \ No newline at end of file From e1f715e6d607455bfbdd78f0e626ae1a5089f33f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Thu, 7 Jan 2021 16:52:05 +0800 Subject: [PATCH 94/95] change commnet --- Flow.Launcher.Infrastructure/UserSettings/Settings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index bcfe298a9..769237bcb 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -102,7 +102,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings public LastQueryMode LastQueryMode { get; set; } = LastQueryMode.Selected; - // Order defaults to 0 or -1, so 1 will let this property appear last + // This needs to be loaded last by staying at the bottom public PluginsSettings PluginSettings { get; set; } = new PluginsSettings(); } From 7501a7e7e7ee597a39838ffd57ccc7f959083b62 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 7 Jan 2021 20:40:22 +1100 Subject: [PATCH 95/95] version bump --- SolutionAssemblyInfo.cs | 6 +++--- appveyor.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SolutionAssemblyInfo.cs b/SolutionAssemblyInfo.cs index ccbfef5d0..afd76b5d7 100644 --- a/SolutionAssemblyInfo.cs +++ b/SolutionAssemblyInfo.cs @@ -16,6 +16,6 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.6.0")] -[assembly: AssemblyFileVersion("1.6.0")] -[assembly: AssemblyInformationalVersion("1.6.0")] \ No newline at end of file +[assembly: AssemblyVersion("1.7.0")] +[assembly: AssemblyFileVersion("1.7.0")] +[assembly: AssemblyInformationalVersion("1.7.0")] \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 7d1da7f3f..2c2f43b66 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: '1.6.0.{build}' +version: '1.7.0.{build}' init: - ps: |