From ffbd8fd650d8efa3e5b350ac9b830d32e1167a0f Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Tue, 30 Aug 2022 01:48:05 -0400 Subject: [PATCH 01/33] Add logic for IcoPath's that are web URL's --- .../Image/ImageLoader.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 8c1d7d74fbf..fdf5c8e186e 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net; using System.Threading.Tasks; using System.Windows.Media; using System.Windows.Media.Imaging; @@ -113,7 +114,27 @@ private static ImageResult LoadInternal(string path, bool loadFullImage = false) { return new ImageResult(ImageCache[path], ImageType.Cache); } + if (path.StartsWith("http://") || path.StartsWith("https://")) + { + // Download image from url + using (WebClient client = new WebClient()) + { + using (MemoryStream stream = new MemoryStream(client.DownloadData(path))) + { + var image = new BitmapImage(); + image.BeginInit(); + image.CacheOption = BitmapCacheOption.OnLoad; + image.StreamSource = stream; + image.EndInit(); + image.Freeze(); + ImageCache[path] = image; + return new ImageResult(image, ImageType.Data); + } + + } + + } if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) { var imageSource = new BitmapImage(new Uri(path)); From 03e319e20051197ee2141b907142992b6f8785ff Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Tue, 30 Aug 2022 01:50:59 -0400 Subject: [PATCH 02/33] Remove whitespace --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index fdf5c8e186e..2349ab14d32 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -132,8 +132,6 @@ private static ImageResult LoadInternal(string path, bool loadFullImage = false) } } - - } if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) { From fda155a0baa7da94084099ed693612404019716e Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Tue, 30 Aug 2022 01:51:31 -0400 Subject: [PATCH 03/33] DOn't prepend pluginpath if IcoPath is a web URL --- Flow.Launcher.Plugin/Result.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 35c491d35f8..1fcfd885892 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -131,7 +131,7 @@ public string PluginDirectory set { _pluginDirectory = value; - if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath)) + if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath) && !IcoPath.StartsWith("http://") && !IcoPath.StartsWith("https://")) { IcoPath = Path.Combine(value, IcoPath); } From d62d7108787520187ad34fc8bcd95b462d4141fa Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Wed, 21 Sep 2022 12:01:58 -0400 Subject: [PATCH 04/33] Use URI class to detect web URL --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 5 ++++- Flow.Launcher.Plugin/Result.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 2349ab14d32..a3e9de4b85c 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -114,7 +114,10 @@ private static ImageResult LoadInternal(string path, bool loadFullImage = false) { return new ImageResult(ImageCache[path], ImageType.Cache); } - if (path.StartsWith("http://") || path.StartsWith("https://")) + Uri uriResult; + bool IsUriScheme = Uri.TryCreate(path, UriKind.Absolute, out uriResult) + && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); + if (IsUriScheme) { // Download image from url using (WebClient client = new WebClient()) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 1fcfd885892..c784d60e03d 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -130,8 +130,11 @@ public string PluginDirectory get { return _pluginDirectory; } set { + Uri uriResult; + bool IsUriScheme = Uri.TryCreate(IcoPath, UriKind.Absolute, out uriResult) + && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); _pluginDirectory = value; - if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath) && !IcoPath.StartsWith("http://") && !IcoPath.StartsWith("https://")) + if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath) && !IsUriScheme) { IcoPath = Path.Combine(value, IcoPath); } From 301882dcf9cc866451883a3e0967d93499864105 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Wed, 21 Sep 2022 12:02:39 -0400 Subject: [PATCH 05/33] Switch from WebClient to HTTP --- .../Image/ImageLoader.cs | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index a3e9de4b85c..7a6083706b3 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -120,21 +120,18 @@ private static ImageResult LoadInternal(string path, bool loadFullImage = false) if (IsUriScheme) { // Download image from url - using (WebClient client = new WebClient()) + var resp = Http.Http.GetStreamAsync(path).Result; + if (resp == null) { - using (MemoryStream stream = new MemoryStream(client.DownloadData(path))) - { - var image = new BitmapImage(); - image.BeginInit(); - image.CacheOption = BitmapCacheOption.OnLoad; - image.StreamSource = stream; - image.EndInit(); - image.Freeze(); - ImageCache[path] = image; - return new ImageResult(image, ImageType.Data); - } - + return new ImageResult(ImageCache[Constant.MissingImgIcon], ImageType.Error); } + var image = new BitmapImage(); + image.BeginInit(); + image.StreamSource = resp; + image.EndInit(); + image.Freeze(); + ImageCache[path] = image; + return new ImageResult(image, ImageType.ImageFile); } if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) { From 5c33b0d5902b64ca3513291227b04e628d665ce2 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Fri, 7 Oct 2022 10:47:49 -0400 Subject: [PATCH 06/33] Only convert relative paths if its a valid path --- Flow.Launcher.Plugin/Result.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index c784d60e03d..31ef0125876 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -130,13 +130,16 @@ public string PluginDirectory get { return _pluginDirectory; } set { - Uri uriResult; - bool IsUriScheme = Uri.TryCreate(IcoPath, UriKind.Absolute, out uriResult) - && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); _pluginDirectory = value; - if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath) && !IsUriScheme) + if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath)) { - IcoPath = Path.Combine(value, IcoPath); + string absPath = Path.Combine(value, IcoPath); + // Only convert relative paths if its a valid path + if (File.Exists(absPath)) + { + IcoPath = absPath; + } + } } } From b7900b22b06783fb916e3238a44edfd236a0a656 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Fri, 7 Oct 2022 10:51:21 -0400 Subject: [PATCH 07/33] // Only convert relative paths if its a valid path --- Flow.Launcher.Plugin/Result.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 31ef0125876..79d3635f1a4 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -58,7 +58,13 @@ public string IcoPath { if (!string.IsNullOrEmpty(PluginDirectory) && !Path.IsPathRooted(value)) { - _icoPath = Path.Combine(value, IcoPath); + string absPath = Path.Combine(value, IcoPath); + // Only convert relative paths if its a valid path + if (File.Exists(absPath)) + { + _icoPath = Path.Combine(value, IcoPath); + } + } else { From 57d63cfd37a02613f20f93f71f979c9e8fdd46be Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Tue, 30 Aug 2022 01:48:05 -0400 Subject: [PATCH 08/33] Add logic for IcoPath's that are web URL's --- .../Image/ImageLoader.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 8c1d7d74fbf..fdf5c8e186e 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net; using System.Threading.Tasks; using System.Windows.Media; using System.Windows.Media.Imaging; @@ -113,7 +114,27 @@ private static ImageResult LoadInternal(string path, bool loadFullImage = false) { return new ImageResult(ImageCache[path], ImageType.Cache); } + if (path.StartsWith("http://") || path.StartsWith("https://")) + { + // Download image from url + using (WebClient client = new WebClient()) + { + using (MemoryStream stream = new MemoryStream(client.DownloadData(path))) + { + var image = new BitmapImage(); + image.BeginInit(); + image.CacheOption = BitmapCacheOption.OnLoad; + image.StreamSource = stream; + image.EndInit(); + image.Freeze(); + ImageCache[path] = image; + return new ImageResult(image, ImageType.Data); + } + + } + + } if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) { var imageSource = new BitmapImage(new Uri(path)); From ed107cc31eefc155b5a1579480d3acf8b57dcfa0 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Tue, 30 Aug 2022 01:50:59 -0400 Subject: [PATCH 09/33] Remove whitespace --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index fdf5c8e186e..2349ab14d32 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -132,8 +132,6 @@ private static ImageResult LoadInternal(string path, bool loadFullImage = false) } } - - } if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) { From 7f1b9d058eeb0ae78f66513d900c46ece4de5e5b Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Tue, 30 Aug 2022 01:51:31 -0400 Subject: [PATCH 10/33] DOn't prepend pluginpath if IcoPath is a web URL --- Flow.Launcher.Plugin/Result.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 7633e34a70c..72cd16f4d2f 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -135,7 +135,7 @@ public string PluginDirectory set { _pluginDirectory = value; - if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath)) + if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath) && !IcoPath.StartsWith("http://") && !IcoPath.StartsWith("https://")) { IcoPath = Path.Combine(value, IcoPath); } From 416c44f4c18676ee937d334784e8368964e557ad Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Wed, 21 Sep 2022 12:01:58 -0400 Subject: [PATCH 11/33] Use URI class to detect web URL --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 5 ++++- Flow.Launcher.Plugin/Result.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 2349ab14d32..a3e9de4b85c 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -114,7 +114,10 @@ private static ImageResult LoadInternal(string path, bool loadFullImage = false) { return new ImageResult(ImageCache[path], ImageType.Cache); } - if (path.StartsWith("http://") || path.StartsWith("https://")) + Uri uriResult; + bool IsUriScheme = Uri.TryCreate(path, UriKind.Absolute, out uriResult) + && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); + if (IsUriScheme) { // Download image from url using (WebClient client = new WebClient()) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 72cd16f4d2f..9948d0ba241 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -134,8 +134,11 @@ public string PluginDirectory get { return _pluginDirectory; } set { + Uri uriResult; + bool IsUriScheme = Uri.TryCreate(IcoPath, UriKind.Absolute, out uriResult) + && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); _pluginDirectory = value; - if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath) && !IcoPath.StartsWith("http://") && !IcoPath.StartsWith("https://")) + if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath) && !IsUriScheme) { IcoPath = Path.Combine(value, IcoPath); } From ec1a06108dbf5c56b4aed8c6a06ecf91c3769aad Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Wed, 21 Sep 2022 12:02:39 -0400 Subject: [PATCH 12/33] Switch from WebClient to HTTP --- .../Image/ImageLoader.cs | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index a3e9de4b85c..7a6083706b3 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -120,21 +120,18 @@ private static ImageResult LoadInternal(string path, bool loadFullImage = false) if (IsUriScheme) { // Download image from url - using (WebClient client = new WebClient()) + var resp = Http.Http.GetStreamAsync(path).Result; + if (resp == null) { - using (MemoryStream stream = new MemoryStream(client.DownloadData(path))) - { - var image = new BitmapImage(); - image.BeginInit(); - image.CacheOption = BitmapCacheOption.OnLoad; - image.StreamSource = stream; - image.EndInit(); - image.Freeze(); - ImageCache[path] = image; - return new ImageResult(image, ImageType.Data); - } - + return new ImageResult(ImageCache[Constant.MissingImgIcon], ImageType.Error); } + var image = new BitmapImage(); + image.BeginInit(); + image.StreamSource = resp; + image.EndInit(); + image.Freeze(); + ImageCache[path] = image; + return new ImageResult(image, ImageType.ImageFile); } if (path.StartsWith("data:", StringComparison.OrdinalIgnoreCase)) { From ebd6f177a9cabefa4acef189330d2e637f4549a7 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Fri, 7 Oct 2022 10:47:49 -0400 Subject: [PATCH 13/33] Only convert relative paths if its a valid path --- Flow.Launcher.Plugin/Result.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 9948d0ba241..399e2e13d45 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -134,13 +134,16 @@ public string PluginDirectory get { return _pluginDirectory; } set { - Uri uriResult; - bool IsUriScheme = Uri.TryCreate(IcoPath, UriKind.Absolute, out uriResult) - && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); _pluginDirectory = value; - if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath) && !IsUriScheme) + if (!string.IsNullOrEmpty(IcoPath) && !Path.IsPathRooted(IcoPath)) { - IcoPath = Path.Combine(value, IcoPath); + string absPath = Path.Combine(value, IcoPath); + // Only convert relative paths if its a valid path + if (File.Exists(absPath)) + { + IcoPath = absPath; + } + } } } From eb3f72375276d6982844e38b6672b015944eb0ff Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Fri, 7 Oct 2022 10:51:21 -0400 Subject: [PATCH 14/33] // Only convert relative paths if its a valid path --- Flow.Launcher.Plugin/Result.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 399e2e13d45..6da94d899ac 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -58,7 +58,13 @@ public string IcoPath { if (!string.IsNullOrEmpty(PluginDirectory) && !Path.IsPathRooted(value)) { - _icoPath = Path.Combine(value, IcoPath); + string absPath = Path.Combine(value, IcoPath); + // Only convert relative paths if its a valid path + if (File.Exists(absPath)) + { + _icoPath = Path.Combine(value, IcoPath); + } + } else { From ef575bb5dd4fb2bb6db1420492f543abd4d32bb8 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Wed, 12 Oct 2022 23:26:38 -0500 Subject: [PATCH 15/33] Adjust Http Code --- Flow.Launcher.Infrastructure/Http/Http.cs | 35 +++++++++++++---------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 9f4146b7be3..671b6388f12 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -68,7 +68,7 @@ public static void UpdateProxy(ProxyProperty property) 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)) + new NetworkCredential(Proxy.UserName, Proxy.Password)) }, _ => (null, null) }, @@ -79,7 +79,7 @@ var userName when string.IsNullOrEmpty(userName) => _ => throw new ArgumentOutOfRangeException() }; } - catch(UriFormatException e) + catch (UriFormatException e) { API.ShowMsg("Please try again", "Unable to parse Http Proxy"); Log.Exception("Flow.Launcher.Infrastructure.Http", "Unable to parse Uri", e); @@ -94,7 +94,7 @@ public static async Task DownloadAsync([NotNull] string url, [NotNull] string fi if (response.StatusCode == HttpStatusCode.OK) { await using var fileStream = new FileStream(filePath, FileMode.CreateNew); - await response.Content.CopyToAsync(fileStream); + await response.Content.CopyToAsync(fileStream, token); } else { @@ -117,7 +117,7 @@ public static async Task DownloadAsync([NotNull] string url, [NotNull] string fi public static Task GetAsync([NotNull] string url, CancellationToken token = default) { Log.Debug($"|Http.Get|Url <{url}>"); - return GetAsync(new Uri(url.Replace("#", "%23")), token); + return GetAsync(new Uri(url), token); } /// @@ -130,28 +130,33 @@ public static async Task GetAsync([NotNull] Uri url, CancellationToken t { Log.Debug($"|Http.Get|Url <{url}>"); using var response = await client.GetAsync(url, token); - var content = await response.Content.ReadAsStringAsync(); - if (response.StatusCode == HttpStatusCode.OK) - { - return content; - } - else + var content = await response.Content.ReadAsStringAsync(token); + if (response.StatusCode != HttpStatusCode.OK) { throw new HttpRequestException( $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); } + + return content; } /// - /// Asynchrously get the result as stream from url. + /// Send a GET request to the specified Uri with an HTTP completion option and a cancellation token as an asynchronous operation. /// - /// + /// The Uri the request is sent to. + /// An HTTP completion option value that indicates when the operation should be considered completed. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation /// - public static async Task GetStreamAsync([NotNull] string url, CancellationToken token = default) + public static Task GetStreamAsync([NotNull] string url, + HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead, + CancellationToken token = default) => GetStreamAsync(new Uri(url), completionOption, token); + + + public static async Task GetStreamAsync([NotNull] Uri url, HttpCompletionOption completionOption, CancellationToken token = default) { Log.Debug($"|Http.Get|Url <{url}>"); - var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); - return await response.Content.ReadAsStreamAsync(); + using var response = await client.GetAsync(url, completionOption, token); + return await response.Content.ReadAsStreamAsync(token); } /// From 37084898860e355db2b7acc42737fb180b28ddb5 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Wed, 12 Oct 2022 23:28:55 -0500 Subject: [PATCH 16/33] Adjust Google Code a bit due to http change --- .../SuggestionSources/Google.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs index bde63ab29d5..237944343ea 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs @@ -20,13 +20,10 @@ public override async Task> SuggestionsAsync(string query, Cancella { const string api = "https://www.google.com/complete/search?output=chrome&q="; - using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query)).ConfigureAwait(false); + await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), HttpCompletionOption.ResponseHeadersRead, token: token).ConfigureAwait(false); using var json = await JsonDocument.ParseAsync(resultStream, cancellationToken: token); - if (json == null) - return new List(); - var results = json.RootElement.EnumerateArray().ElementAt(1); return results.EnumerateArray().Select(o => o.GetString()).ToList(); From 191c6af38eb8fbd10e30d3d8feb87cf1d613aca1 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Wed, 12 Oct 2022 23:32:02 -0500 Subject: [PATCH 17/33] Adjust Bing Code a bit due to http change --- .../SuggestionSources/Bing.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs index e01b66df55f..eb9c40c4fae 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs @@ -21,8 +21,8 @@ public override async Task> SuggestionsAsync(string query, Cancella try { const string api = "https://api.bing.com/qsonhs.aspx?q="; - - using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false); + + await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), HttpCompletionOption.ResponseHeadersRead, token).ConfigureAwait(false); using var json = (await JsonDocument.ParseAsync(resultStream, cancellationToken: token)); var root = json.RootElement.GetProperty("AS"); @@ -31,16 +31,16 @@ public override async Task> SuggestionsAsync(string query, Cancella return new List(); return root.GetProperty("Results") - .EnumerateArray() - .SelectMany(r => r.GetProperty("Suggests") - .EnumerateArray() - .Select(s => s.GetProperty("Txt").GetString())) - .ToList(); + .EnumerateArray() + .SelectMany(r => r.GetProperty("Suggests") + .EnumerateArray() + .Select(s => s.GetProperty("Txt").GetString())) + .ToList(); } - catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException}) + catch (Exception e) when (e is HttpRequestException or { InnerException: TimeoutException }) { Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e); return null; @@ -49,7 +49,7 @@ public override async Task> SuggestionsAsync(string query, Cancella { Log.Exception("|Bing.Suggestions|can't parse suggestions", e); return new List(); - } + } } public override string ToString() From 957c4e237c62e505d9d68636e1662b8ce0b84752 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 13 Oct 2022 00:19:50 -0500 Subject: [PATCH 18/33] Adjust Http Design to avoid memory leak --- Flow.Launcher.Infrastructure/Http/Http.cs | 28 +++++++++++++++---- .../SuggestionSources/Bing.cs | 2 +- .../SuggestionSources/Google.cs | 2 +- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 671b6388f12..0be9af5a451 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -136,7 +136,7 @@ public static async Task GetAsync([NotNull] Uri url, CancellationToken t throw new HttpRequestException( $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); } - + return content; } @@ -148,15 +148,31 @@ public static async Task GetAsync([NotNull] Uri url, CancellationToken t /// A cancellation token that can be used by other objects or threads to receive notice of cancellation /// public static Task GetStreamAsync([NotNull] string url, - HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead, - CancellationToken token = default) => GetStreamAsync(new Uri(url), completionOption, token); + CancellationToken token = default) => GetStreamAsync(new Uri(url), token); + + + /// + /// Send a GET request to the specified Uri with an HTTP completion option and a cancellation token as an asynchronous operation. + /// + /// + /// + /// + public static async Task GetStreamAsync([NotNull] Uri url, + CancellationToken token = default) + { + Log.Debug($"|Http.Get|Url <{url}>"); + return await client.GetStreamAsync(url, token); + } + public static async Task GetResponseAsync(string url, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead, + CancellationToken token = default) + => await GetResponseAsync(new Uri(url), completionOption, token); - public static async Task GetStreamAsync([NotNull] Uri url, HttpCompletionOption completionOption, CancellationToken token = default) + public static async Task GetResponseAsync([NotNull] Uri url, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead, + CancellationToken token = default) { Log.Debug($"|Http.Get|Url <{url}>"); - using var response = await client.GetAsync(url, completionOption, token); - return await response.Content.ReadAsStreamAsync(token); + return await client.GetAsync(url, completionOption, token); } /// diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs index eb9c40c4fae..b8ad9a586da 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs @@ -22,7 +22,7 @@ public override async Task> SuggestionsAsync(string query, Cancella { const string api = "https://api.bing.com/qsonhs.aspx?q="; - await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), HttpCompletionOption.ResponseHeadersRead, token).ConfigureAwait(false); + await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false); using var json = (await JsonDocument.ParseAsync(resultStream, cancellationToken: token)); var root = json.RootElement.GetProperty("AS"); diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs index 237944343ea..567e896b588 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs @@ -20,7 +20,7 @@ public override async Task> SuggestionsAsync(string query, Cancella { const string api = "https://www.google.com/complete/search?output=chrome&q="; - await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), HttpCompletionOption.ResponseHeadersRead, token: token).ConfigureAwait(false); + await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), token: token).ConfigureAwait(false); using var json = await JsonDocument.ParseAsync(resultStream, cancellationToken: token); From eb5e33aeb0f9c52cd849f2ac2b7455b35adfc5e9 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 13 Oct 2022 00:32:36 -0500 Subject: [PATCH 19/33] Make ImageLoader Async --- Flow.Launcher.Core/Updater.cs | 3 +- .../Image/ImageLoader.cs | 46 ++++++++++--------- Flow.Launcher/Msg.xaml.cs | 16 +++++-- Flow.Launcher/SettingWindow.xaml | 2 +- Flow.Launcher/ViewModel/PluginViewModel.cs | 22 ++++++++- Flow.Launcher/ViewModel/ResultViewModel.cs | 7 +-- .../Programs/Win32.cs | 2 +- .../SearchSourceSetting.xaml.cs | 10 ++-- .../SearchSourceViewModel.cs | 5 +- 9 files changed, 71 insertions(+), 42 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index bad0344eb30..96dce8ed927 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -120,7 +120,8 @@ private async Task GitHubUpdateManagerAsync(string repository) var uri = new Uri(repository); var api = $"https://api.github.com/repos{uri.AbsolutePath}/releases"; - await using var jsonStream = await Http.GetStreamAsync(api).ConfigureAwait(false); + using var response = await Http.GetResponseAsync(api, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + await using var jsonStream = await response.Content.ReadAsStreamAsync(); var releases = await System.Text.Json.JsonSerializer.DeserializeAsync>(jsonStream).ConfigureAwait(false); var latest = releases.Where(r => !r.Prerelease).OrderByDescending(r => r.PublishedAt).First(); diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 7a6083706b3..204e0463035 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -4,11 +4,13 @@ using System.IO; using System.Linq; using System.Net; +using System.Net.Http; using System.Threading.Tasks; using System.Windows.Media; using System.Windows.Media.Imaging; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; +using static Flow.Launcher.Infrastructure.Http.Http; namespace Flow.Launcher.Infrastructure.Image { @@ -24,13 +26,7 @@ public static class ImageLoader private static readonly string[] ImageExtensions = { - ".png", - ".jpg", - ".jpeg", - ".gif", - ".bmp", - ".tiff", - ".ico" + ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".ico" }; public static void Initialize() @@ -40,21 +36,24 @@ public static void Initialize() var usage = LoadStorageToConcurrentDictionary(); - foreach (var icon in new[] { Constant.DefaultIcon, Constant.MissingImgIcon }) + foreach (var icon in new[] + { + Constant.DefaultIcon, Constant.MissingImgIcon + }) { ImageSource img = new BitmapImage(new Uri(icon)); img.Freeze(); ImageCache[icon] = img; } - _ = Task.Run(() => + _ = Task.Run(async () => { - Stopwatch.Normal("|ImageLoader.Initialize|Preload images cost", () => + await Stopwatch.NormalAsync("|ImageLoader.Initialize|Preload images cost", async () => { - ImageCache.Data.AsParallel().ForAll(x => + foreach (var imageUsage in ImageCache.Data) { - Load(x.Key); - }); + await LoadAsync(imageUsage.Key); + } }); Log.Info($"|ImageLoader.Initialize|Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}"); }); @@ -100,7 +99,7 @@ private enum ImageType Cache } - private static ImageResult LoadInternal(string path, bool loadFullImage = false) + private static async ValueTask LoadInternalAsync(string path, bool loadFullImage = false) { ImageResult imageResult; @@ -114,21 +113,24 @@ private static ImageResult LoadInternal(string path, bool loadFullImage = false) { return new ImageResult(ImageCache[path], ImageType.Cache); } - Uri uriResult; - bool IsUriScheme = Uri.TryCreate(path, UriKind.Absolute, out uriResult) - && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); - if (IsUriScheme) + if (Uri.TryCreate(path, UriKind.RelativeOrAbsolute, out var uriResult) + && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps)) { // Download image from url - var resp = Http.Http.GetStreamAsync(path).Result; + await using var resp = await GetStreamAsync(uriResult); if (resp == null) { return new ImageResult(ImageCache[Constant.MissingImgIcon], ImageType.Error); } + await using var buffer = new MemoryStream(); + await resp.CopyToAsync(buffer); + buffer.Seek(0, SeekOrigin.Begin); var image = new BitmapImage(); image.BeginInit(); - image.StreamSource = resp; + image.CacheOption = BitmapCacheOption.OnLoad; + image.StreamSource = buffer; image.EndInit(); + image.StreamSource = null; image.Freeze(); ImageCache[path] = image; return new ImageResult(image, ImageType.ImageFile); @@ -237,9 +239,9 @@ public static bool CacheContainImage(string path) return ImageCache.ContainsKey(path) && ImageCache[path] != null; } - public static ImageSource Load(string path, bool loadFullImage = false) + public static async ValueTask LoadAsync(string path, bool loadFullImage = false) { - var imageResult = LoadInternal(path, loadFullImage); + var imageResult = await LoadInternalAsync(path, loadFullImage); var img = imageResult.ImageSource; if (imageResult.ImageType != ImageType.Error && imageResult.ImageType != ImageType.Cache) diff --git a/Flow.Launcher/Msg.xaml.cs b/Flow.Launcher/Msg.xaml.cs index 6bb2fc2dc6f..1be89d71604 100644 --- a/Flow.Launcher/Msg.xaml.cs +++ b/Flow.Launcher/Msg.xaml.cs @@ -38,10 +38,16 @@ public Msg() Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath(TopProperty)); fadeOutStoryboard.Children.Add(fadeOutAnimation); - imgClose.Source = ImageLoader.Load(Path.Combine(Infrastructure.Constant.ProgramDirectory, "Images\\close.png")); + _ = LoadImageAsync(); + imgClose.MouseUp += imgClose_MouseUp; } + private async System.Threading.Tasks.Task LoadImageAsync() + { + imgClose.Source = await ImageLoader.LoadAsync(Path.Combine(Infrastructure.Constant.ProgramDirectory, "Images\\close.png")); + } + void imgClose_MouseUp(object sender, MouseButtonEventArgs e) { if (!closing) @@ -56,7 +62,7 @@ private void fadeOutStoryboard_Completed(object sender, EventArgs e) Close(); } - public void Show(string title, string subTitle, string iconPath) + public async void Show(string title, string subTitle, string iconPath) { tbTitle.Text = title; tbSubTitle.Text = subTitle; @@ -66,15 +72,15 @@ public void Show(string title, string subTitle, string iconPath) } if (!File.Exists(iconPath)) { - imgIco.Source = ImageLoader.Load(Path.Combine(Constant.ProgramDirectory, "Images\\app.png")); + imgIco.Source = await ImageLoader.LoadAsync(Path.Combine(Constant.ProgramDirectory, "Images\\app.png")); } else { - imgIco.Source = ImageLoader.Load(iconPath); + imgIco.Source = await ImageLoader.LoadAsync(iconPath); } Show(); - Dispatcher.InvokeAsync(async () => + await Dispatcher.InvokeAsync(async () => { if (!closing) { diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index 0a63b3a6cfb..9c9859946e1 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -1068,7 +1068,7 @@ Height="32" Margin="32,0,0,0" FlowDirection="LeftToRight" - Source="{Binding Image, IsAsync=True}" /> + Source="{Binding Image, Mode=OneWay}" /> ImageLoader.Load(PluginPair.Metadata.IcoPath); + + private async void LoadIconAsync() + { + Image = await ImageLoader.LoadAsync(PluginPair.Metadata.IcoPath); + } + + public ImageSource Image + { + get + { + if (_image == ImageLoader.DefaultImage) + LoadIconAsync(); + + return _image; + } + set => _image = value; + } public bool PluginState { get => !PluginPair.Metadata.Disabled; @@ -50,6 +67,7 @@ public Control SettingControl ? new Control() : settingProvider.CreateSettingPanel() : null; + private ImageSource _image = ImageLoader.DefaultImage; public Visibility ActionKeywordsVisibility => PluginPair.Metadata.ActionKeywords.Count == 1 ? Visibility.Visible : Visibility.Collapsed; public string InitilizaTime => PluginPair.Metadata.InitTime + "ms"; diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index a188cd357e1..1fd19e3bfb2 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -145,7 +145,7 @@ public ImageSource Image public GlyphInfo Glyph { get; set; } - private async ValueTask LoadImageAsync() + private async Task LoadImageAsync() { var imagePath = Result.IcoPath; if (string.IsNullOrEmpty(imagePath) && Result.Icon != null) @@ -166,12 +166,13 @@ private async ValueTask LoadImageAsync() if (ImageLoader.CacheContainImage(imagePath)) { // will get here either when icoPath has value\icon delegate is null\when had exception in delegate - image = ImageLoader.Load(imagePath); + image = await ImageLoader.LoadAsync(imagePath); return; } // We need to modify the property not field here to trigger the OnPropertyChanged event - Image = await Task.Run(() => ImageLoader.Load(imagePath)).ConfigureAwait(false); + var i = await Task.Run(async () => await ImageLoader.LoadAsync(imagePath)); + Image = i; } public Result Result { get; } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 6a8b232e94e..e2c0bf9ef45 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -100,7 +100,7 @@ public Result Result(string query, IPublicAPI api) { Title = title, SubTitle = Main._settings.HideAppsPath ? string.Empty : LnkResolvedPath ?? FullPath, - IcoPath = IcoPath, + IcoPath = "https://media.wired.com/photos/598e35fb99d76447c4eb1f28/master/pass/phonepicutres-TA.jpg", Score = matchResult.Score, TitleHighlightData = matchResult.MatchData, ContextData = this, diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs index fd0701c012a..c19396da0dc 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs @@ -30,7 +30,7 @@ public SearchSourceSettingWindow(IList sources, PluginInitContext Initilize(sources, context, Action.Add); } - private void Initilize(IList sources, PluginInitContext context, Action action) + private async void Initilize(IList sources, PluginInitContext context, Action action) { InitializeComponent(); DataContext = _viewModel; @@ -42,7 +42,7 @@ private void Initilize(IList sources, PluginInitContext context, A _viewModel.SetupCustomImagesDirectory(); - imgPreviewIcon.Source = _viewModel.LoadPreviewIcon(_searchSource.IconPath); + imgPreviewIcon.Source = await _viewModel.LoadPreviewIconAsync(_searchSource.IconPath); } private void OnCancelButtonClick(object sender, RoutedEventArgs e) @@ -125,7 +125,7 @@ private void EditSearchSource() } } - private void OnSelectIconClick(object sender, RoutedEventArgs e) + private async void OnSelectIconClick(object sender, RoutedEventArgs e) { const string filter = "Image files (*.jpg, *.jpeg, *.gif, *.png, *.bmp) |*.jpg; *.jpeg; *.gif; *.png; *.bmp"; var dialog = new OpenFileDialog {InitialDirectory = Main.CustomImagesDirectory, Filter = filter}; @@ -140,7 +140,7 @@ private void OnSelectIconClick(object sender, RoutedEventArgs e) if (_viewModel.ShouldProvideHint(selectedNewIconImageFullPath)) MessageBox.Show(_api.GetTranslation("flowlauncher_plugin_websearch_iconpath_hint")); - imgPreviewIcon.Source = _viewModel.LoadPreviewIcon(selectedNewIconImageFullPath); + imgPreviewIcon.Source = await _viewModel.LoadPreviewIconAsync(selectedNewIconImageFullPath); } } } @@ -151,4 +151,4 @@ public enum Action Add, Edit } -} \ No newline at end of file +} diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs index 372e601e049..1b42bf788ee 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs @@ -2,6 +2,7 @@ using System; using System.Drawing; using System.IO; +using System.Threading.Tasks; using System.Windows; using System.Windows.Media; @@ -57,9 +58,9 @@ internal bool ShouldProvideHint(string fullPathToSelectedImage) return Directory.GetParent(fullPathToSelectedImage).ToString() == Main.DefaultImagesDirectory; } - internal ImageSource LoadPreviewIcon(string pathToPreviewIconImage) + internal async ValueTask LoadPreviewIconAsync(string pathToPreviewIconImage) { - return ImageLoader.Load(pathToPreviewIconImage); + return await ImageLoader.LoadAsync(pathToPreviewIconImage); } } } From c39a727e3b6264781e7eae1f12afa4e693cb87cc Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 13 Oct 2022 11:36:43 -0500 Subject: [PATCH 20/33] Revert back some unnecessary change --- Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs | 4 ++-- Flow.Launcher.Core/Updater.cs | 11 +++++------ Flow.Launcher.Infrastructure/Http/Http.cs | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index fab1b3e8f00..b735e95e7e5 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -29,7 +29,7 @@ public static async Task UpdateManifestAsync(CancellationToken token = default) var request = new HttpRequestMessage(HttpMethod.Get, manifestFileUrl); request.Headers.Add("If-None-Match", latestEtag); - var response = await Http.SendAsync(request, token).ConfigureAwait(false); + using var response = await Http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token).ConfigureAwait(false); if (response.StatusCode == HttpStatusCode.OK) { @@ -56,4 +56,4 @@ public static async Task UpdateManifestAsync(CancellationToken token = default) } } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 96dce8ed927..44c47cf289d 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -79,7 +79,7 @@ public async Task UpdateAppAsync(IPublicAPI api, bool silentUpdate = true) await updateManager.CreateUninstallerRegistryEntry().ConfigureAwait(false); } - var newVersionTips = NewVersinoTips(newReleaseVersion.ToString()); + var newVersionTips = NewVersionTips(newReleaseVersion.ToString()); Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); @@ -120,8 +120,7 @@ private async Task GitHubUpdateManagerAsync(string repository) var uri = new Uri(repository); var api = $"https://api.github.com/repos{uri.AbsolutePath}/releases"; - using var response = await Http.GetResponseAsync(api, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); - await using var jsonStream = await response.Content.ReadAsStreamAsync(); + await using var jsonStream = await Http.GetStreamAsync(api).ConfigureAwait(false); var releases = await System.Text.Json.JsonSerializer.DeserializeAsync>(jsonStream).ConfigureAwait(false); var latest = releases.Where(r => !r.Prerelease).OrderByDescending(r => r.PublishedAt).First(); @@ -138,10 +137,10 @@ private async Task GitHubUpdateManagerAsync(string repository) return manager; } - public string NewVersinoTips(string version) + public string NewVersionTips(string version) { - var translater = InternationalizationManager.Instance; - var tips = string.Format(translater.GetTranslation("newVersionTips"), version); + var translator = InternationalizationManager.Instance; + var tips = string.Format(translator.GetTranslation("newVersionTips"), version); return tips; } diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 0be9af5a451..e5be0701f2d 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -178,9 +178,9 @@ public static async Task GetResponseAsync([NotNull] Uri url /// /// Asynchrously send an HTTP request. /// - public static async Task SendAsync(HttpRequestMessage request, CancellationToken token = default) + public static async Task SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead, CancellationToken token = default) { - return await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token); + return await client.SendAsync(request, completionOption, token); } } } From 99fd8d123214a25ca2c8f99805ab870011d58431 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 27 Oct 2022 11:38:05 -0500 Subject: [PATCH 21/33] Dispose Stream (though it maybe already disposed by disposed the response) --- Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index b735e95e7e5..e3f0e2a2f28 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -35,7 +35,7 @@ public static async Task UpdateManifestAsync(CancellationToken token = default) { Log.Info($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Fetched plugins from manifest repo"); - var json = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false); + await using var json = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false); UserPlugins = await JsonSerializer.DeserializeAsync>(json, cancellationToken: token).ConfigureAwait(false); From 2507d1abed3a470aa17c2d55520046d6f4d2ac78 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Sun, 30 Oct 2022 10:56:34 -0500 Subject: [PATCH 22/33] remove testing code --- Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index e2c0bf9ef45..6a8b232e94e 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -100,7 +100,7 @@ public Result Result(string query, IPublicAPI api) { Title = title, SubTitle = Main._settings.HideAppsPath ? string.Empty : LnkResolvedPath ?? FullPath, - IcoPath = "https://media.wired.com/photos/598e35fb99d76447c4eb1f28/master/pass/phonepicutres-TA.jpg", + IcoPath = IcoPath, Score = matchResult.Score, TitleHighlightData = matchResult.MatchData, ContextData = this, From ba0aee14ba5b45f1cbd4d5427da886b229a51469 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Sun, 30 Oct 2022 11:11:15 -0500 Subject: [PATCH 23/33] resize bitmapimage when not loading full image --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 204e0463035..96909389148 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -22,6 +22,7 @@ public static class ImageLoader private static IImageHashGenerator _hashGenerator; private static readonly bool EnableImageHash = true; public static ImageSource DefaultImage { get; } = new BitmapImage(new Uri(Constant.MissingImgIcon)); + public const int SmallIconSize = 32; private static readonly string[] ImageExtensions = @@ -128,6 +129,11 @@ private static async ValueTask LoadInternalAsync(string path, bool var image = new BitmapImage(); image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; + if (!loadFullImage) + { + image.DecodePixelHeight = SmallIconSize; + image.DecodePixelWidth = SmallIconSize; + } image.StreamSource = buffer; image.EndInit(); image.StreamSource = null; From e9bf62ed08e30216df0575d5052408474f3c00d7 Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Sun, 30 Oct 2022 14:23:04 -0500 Subject: [PATCH 24/33] Revert "Merge branch 'handle-icon-urls' of https://github.com/Flow-Launcher/Flow.Launcher into handle-icon-urls" This reverts commit cae0b7be77311cc28ed3fbed85cd3081c120bb81, reversing changes made to ba0aee14ba5b45f1cbd4d5427da886b229a51469. --- .github/dependabot.yml | 17 + .../ExternalPlugins/PluginsManifest.cs | 6 +- Flow.Launcher.Core/Flow.Launcher.Core.csproj | 2 +- Flow.Launcher.Core/Plugin/PluginManager.cs | 22 +- Flow.Launcher.Core/Resource/Theme.cs | 11 +- Flow.Launcher.Core/Updater.cs | 9 +- .../Flow.Launcher.Infrastructure.csproj | 2 +- Flow.Launcher.Infrastructure/Http/Http.cs | 53 ++- .../Image/ImageLoader.cs | 52 ++- .../UserSettings/Settings.cs | 9 +- Flow.Launcher.Plugin/Result.cs | 15 + Flow.Launcher.sln | 4 +- Flow.Launcher/ActionKeywords.xaml | 1 - .../OpenResultHotkeyVisibilityConverter.cs | 8 +- Flow.Launcher/Converters/OrdinalConverter.cs | 5 +- Flow.Launcher/CustomQueryHotkeySetting.xaml | 1 - Flow.Launcher/Languages/da.xaml | 7 +- Flow.Launcher/Languages/de.xaml | 7 +- Flow.Launcher/Languages/en.xaml | 9 + Flow.Launcher/Languages/es-419.xaml | 5 + Flow.Launcher/Languages/es.xaml | 9 +- Flow.Launcher/Languages/fr.xaml | 7 +- Flow.Launcher/Languages/it.xaml | 169 ++++---- Flow.Launcher/Languages/ja.xaml | 7 +- Flow.Launcher/Languages/ko.xaml | 7 +- Flow.Launcher/Languages/nb.xaml | 5 + Flow.Launcher/Languages/nl.xaml | 7 +- Flow.Launcher/Languages/pl.xaml | 7 +- Flow.Launcher/Languages/pt-br.xaml | 5 + Flow.Launcher/Languages/pt-pt.xaml | 5 + Flow.Launcher/Languages/ru.xaml | 5 + Flow.Launcher/Languages/sk.xaml | 5 + Flow.Launcher/Languages/sr.xaml | 7 +- Flow.Launcher/Languages/tr.xaml | 7 +- Flow.Launcher/Languages/uk-UA.xaml | 5 + Flow.Launcher/Languages/zh-cn.xaml | 27 +- Flow.Launcher/Languages/zh-tw.xaml | 9 +- Flow.Launcher/MainWindow.xaml | 6 + Flow.Launcher/MainWindow.xaml.cs | 23 +- Flow.Launcher/Msg.xaml.cs | 16 +- Flow.Launcher/PriorityChangeWindow.xaml | 1 - Flow.Launcher/ReportWindow.xaml.cs | 1 - .../Resources/CustomControlTemplate.xaml | 4 +- Flow.Launcher/ResultListBox.xaml | 37 +- Flow.Launcher/SelectBrowserWindow.xaml | 1 - Flow.Launcher/SelectFileManagerWindow.xaml | 1 - Flow.Launcher/SettingWindow.xaml | 378 ++++++++++++++---- Flow.Launcher/SettingWindow.xaml.cs | 151 ++++++- Flow.Launcher/Themes/Base.xaml | 12 +- Flow.Launcher/Themes/BlurBlack Darker.xaml | 111 +++-- Flow.Launcher/Themes/BlurBlack.xaml | 110 +++-- Flow.Launcher/Themes/BlurWhite.xaml | 122 ++++-- Flow.Launcher/Themes/League.xaml | 90 +++-- Flow.Launcher/Themes/Win11Light.xaml | 146 +++++-- Flow.Launcher/ViewModel/PluginViewModel.cs | 39 +- Flow.Launcher/ViewModel/ResultViewModel.cs | 32 +- .../ViewModel/SettingWindowViewModel.cs | 106 ++++- .../Languages/es.xaml | 2 +- .../Languages/it.xaml | 26 +- .../Views/CustomBrowserSetting.xaml | 1 - .../Languages/it.xaml | 20 +- .../Flow.Launcher.Plugin.Calculator/Main.cs | 2 +- .../plugin.json | 2 +- .../Images/deletefilefolder.png | Bin 2407 -> 4544 bytes .../Languages/pt-pt.xaml | 4 +- .../Languages/sk.xaml | 2 +- .../Languages/zh-cn.xaml | 6 +- .../Search/ResultManager.cs | 88 +++- .../Search/SearchManager.cs | 9 +- .../Search/WindowsIndex/IndexSearch.cs | 6 +- .../Views/ActionKeywordSetting.xaml | 1 - .../Languages/it.xaml | 4 +- .../Main.cs | 2 +- .../plugin.json | 2 +- .../Languages/it.xaml | 36 +- .../Languages/ko.xaml | 2 +- .../Languages/sk.xaml | 2 +- .../Languages/es.xaml | 2 +- .../AddProgramSource.xaml | 1 - .../Languages/ko.xaml | 2 +- .../Languages/zh-cn.xaml | 14 +- .../ProgramSuffixes.xaml | 1 - .../Flow.Launcher.Plugin.Shell/plugin.json | 2 +- .../Images/indexoption.png | Bin 0 -> 2841 bytes .../Images/openrecyclebin.png | Bin 0 -> 5557 bytes .../Images/recyclebin.png | Bin 2667 -> 4544 bytes .../Languages/da.xaml | 8 +- .../Languages/de.xaml | 8 +- .../Languages/en.xaml | 15 +- .../Languages/es-419.xaml | 8 +- .../Languages/es.xaml | 36 +- .../Languages/fr.xaml | 8 +- .../Languages/it.xaml | 8 +- .../Languages/ja.xaml | 6 +- .../Languages/ko.xaml | 13 +- .../Languages/nb.xaml | 8 +- .../Languages/nl.xaml | 8 +- .../Languages/pl.xaml | 6 +- .../Languages/pt-br.xaml | 8 +- .../Languages/pt-pt.xaml | 8 +- .../Languages/ru.xaml | 8 +- .../Languages/sk.xaml | 8 +- .../Languages/sr.xaml | 8 +- .../Languages/tr.xaml | 6 +- .../Languages/uk-UA.xaml | 8 +- .../Languages/zh-cn.xaml | 8 +- .../Languages/zh-tw.xaml | 6 +- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 30 ++ Plugins/Flow.Launcher.Plugin.Sys/plugin.json | 2 +- .../Languages/it.xaml | 2 +- Plugins/Flow.Launcher.Plugin.Url/plugin.json | 2 +- .../Languages/da.xaml | 19 +- .../Languages/de.xaml | 19 +- .../Languages/en.xaml | 26 +- .../Languages/es-419.xaml | 19 +- .../Languages/es.xaml | 19 +- .../Languages/fr.xaml | 19 +- .../Languages/it.xaml | 23 +- .../Languages/ja.xaml | 19 +- .../Languages/ko.xaml | 19 +- .../Languages/nb.xaml | 19 +- .../Languages/nl.xaml | 19 +- .../Languages/pl.xaml | 19 +- .../Languages/pt-br.xaml | 19 +- .../Languages/pt-pt.xaml | 19 +- .../Languages/ru.xaml | 19 +- .../Languages/sk.xaml | 19 +- .../Languages/sr.xaml | 19 +- .../Languages/tr.xaml | 19 +- .../Languages/uk-UA.xaml | 19 +- .../Languages/zh-cn.xaml | 19 +- .../Languages/zh-tw.xaml | 19 +- .../SearchSourceSetting.xaml | 4 +- .../SearchSourceSetting.xaml.cs | 10 +- .../SearchSourceViewModel.cs | 5 +- .../SuggestionSources/Bing.cs | 18 +- .../SuggestionSources/Google.cs | 5 +- .../plugin.json | 2 +- .../Helper/ResultHelper.cs | 4 +- .../Properties/Resources.it-IT.resx | 4 +- .../Properties/Resources.pt-PT.resx | 90 ++--- .../Properties/Resources.sk-SK.resx | 22 +- .../Properties/Resources.zh-cn.resx | 4 +- README.md | 7 +- appveyor.yml | 2 +- 145 files changed, 2129 insertions(+), 858 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 Plugins/Flow.Launcher.Plugin.Sys/Images/indexoption.png create mode 100644 Plugins/Flow.Launcher.Plugin.Sys/Images/openrecyclebin.png diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..454c4e976f3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,17 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "nuget" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" + ignore: + - dependency-name: "squirrel-windows" + reviewers: + - "jjw24" + - "taooceros" + - "JohnTheGr8" diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index fab1b3e8f00..e3f0e2a2f28 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -29,13 +29,13 @@ public static async Task UpdateManifestAsync(CancellationToken token = default) var request = new HttpRequestMessage(HttpMethod.Get, manifestFileUrl); request.Headers.Add("If-None-Match", latestEtag); - var response = await Http.SendAsync(request, token).ConfigureAwait(false); + using var response = await Http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token).ConfigureAwait(false); if (response.StatusCode == HttpStatusCode.OK) { Log.Info($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Fetched plugins from manifest repo"); - var json = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false); + await using var json = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false); UserPlugins = await JsonSerializer.DeserializeAsync>(json, cancellationToken: token).ConfigureAwait(false); @@ -56,4 +56,4 @@ public static async Task UpdateManifestAsync(CancellationToken token = default) } } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj index 9f9fa8ff52b..7d18c467bc6 100644 --- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj +++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj @@ -54,7 +54,7 @@ - + diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 383689c83c1..3b4a6e445fc 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -166,18 +166,18 @@ public static async Task InitializePluginsAsync(IPublicAPI api) public static ICollection ValidPluginsForQuery(Query query) { - if (NonGlobalPlugins.ContainsKey(query.ActionKeyword)) - { - var plugin = NonGlobalPlugins[query.ActionKeyword]; - return new List - { - plugin - }; - } - else - { + if (query is null) + return Array.Empty(); + + if (!NonGlobalPlugins.ContainsKey(query.ActionKeyword)) return GlobalPlugins; - } + + + var plugin = NonGlobalPlugins[query.ActionKeyword]; + return new List + { + plugin + }; } public static async Task> QueryForPluginAsync(PluginPair pair, Query query, CancellationToken token) diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index 205abcd34e0..872c4543edb 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -17,7 +17,7 @@ namespace Flow.Launcher.Core.Resource { public class Theme { - private const int ShadowExtraMargin = 12; + private const int ShadowExtraMargin = 32; private readonly List _themeDirectories = new List(); private ResourceDictionary _oldResource; @@ -238,9 +238,10 @@ public void AddDropShadowEffectToCurrentTheme() Property = Border.EffectProperty, Value = new DropShadowEffect { - Opacity = 0.4, - ShadowDepth = 2, - BlurRadius = 15 + Opacity = 0.3, + ShadowDepth = 12, + Direction = 270, + BlurRadius = 30 } }; @@ -250,7 +251,7 @@ public void AddDropShadowEffectToCurrentTheme() marginSetter = new Setter() { Property = Border.MarginProperty, - Value = new Thickness(ShadowExtraMargin), + Value = new Thickness(ShadowExtraMargin, 12, ShadowExtraMargin, ShadowExtraMargin), }; windowBorderStyle.Setters.Add(marginSetter); } diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 976c4eec15b..44c47cf289d 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -79,7 +79,7 @@ public async Task UpdateAppAsync(IPublicAPI api, bool silentUpdate = true) await updateManager.CreateUninstallerRegistryEntry().ConfigureAwait(false); } - var newVersionTips = NewVersinoTips(newReleaseVersion.ToString()); + var newVersionTips = NewVersionTips(newReleaseVersion.ToString()); Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); @@ -137,10 +137,11 @@ private async Task GitHubUpdateManagerAsync(string repository) return manager; } - public string NewVersinoTips(string version) + public string NewVersionTips(string version) { - var translater = InternationalizationManager.Instance; - var tips = string.Format(translater.GetTranslation("newVersionTips"), version); + var translator = InternationalizationManager.Instance; + var tips = string.Format(translator.GetTranslation("newVersionTips"), version); + return tips; } diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index 930cf0b918a..4a7bc20e322 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -53,7 +53,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 9f4146b7be3..e5be0701f2d 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -68,7 +68,7 @@ public static void UpdateProxy(ProxyProperty property) 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)) + new NetworkCredential(Proxy.UserName, Proxy.Password)) }, _ => (null, null) }, @@ -79,7 +79,7 @@ var userName when string.IsNullOrEmpty(userName) => _ => throw new ArgumentOutOfRangeException() }; } - catch(UriFormatException e) + catch (UriFormatException e) { API.ShowMsg("Please try again", "Unable to parse Http Proxy"); Log.Exception("Flow.Launcher.Infrastructure.Http", "Unable to parse Uri", e); @@ -94,7 +94,7 @@ public static async Task DownloadAsync([NotNull] string url, [NotNull] string fi if (response.StatusCode == HttpStatusCode.OK) { await using var fileStream = new FileStream(filePath, FileMode.CreateNew); - await response.Content.CopyToAsync(fileStream); + await response.Content.CopyToAsync(fileStream, token); } else { @@ -117,7 +117,7 @@ public static async Task DownloadAsync([NotNull] string url, [NotNull] string fi public static Task GetAsync([NotNull] string url, CancellationToken token = default) { Log.Debug($"|Http.Get|Url <{url}>"); - return GetAsync(new Uri(url.Replace("#", "%23")), token); + return GetAsync(new Uri(url), token); } /// @@ -130,36 +130,57 @@ public static async Task GetAsync([NotNull] Uri url, CancellationToken t { Log.Debug($"|Http.Get|Url <{url}>"); using var response = await client.GetAsync(url, token); - var content = await response.Content.ReadAsStringAsync(); - if (response.StatusCode == HttpStatusCode.OK) - { - return content; - } - else + var content = await response.Content.ReadAsStringAsync(token); + if (response.StatusCode != HttpStatusCode.OK) { throw new HttpRequestException( $"Error code <{response.StatusCode}> with content <{content}> returned from <{url}>"); } + + return content; } /// - /// Asynchrously get the result as stream from url. + /// Send a GET request to the specified Uri with an HTTP completion option and a cancellation token as an asynchronous operation. + /// + /// The Uri the request is sent to. + /// An HTTP completion option value that indicates when the operation should be considered completed. + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation + /// + public static Task GetStreamAsync([NotNull] string url, + CancellationToken token = default) => GetStreamAsync(new Uri(url), token); + + + /// + /// Send a GET request to the specified Uri with an HTTP completion option and a cancellation token as an asynchronous operation. /// /// + /// /// - public static async Task GetStreamAsync([NotNull] string url, CancellationToken token = default) + public static async Task GetStreamAsync([NotNull] Uri url, + CancellationToken token = default) + { + Log.Debug($"|Http.Get|Url <{url}>"); + return await client.GetStreamAsync(url, token); + } + + public static async Task GetResponseAsync(string url, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead, + CancellationToken token = default) + => await GetResponseAsync(new Uri(url), completionOption, token); + + public static async Task GetResponseAsync([NotNull] Uri url, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead, + CancellationToken token = default) { Log.Debug($"|Http.Get|Url <{url}>"); - var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token); - return await response.Content.ReadAsStreamAsync(); + return await client.GetAsync(url, completionOption, token); } /// /// Asynchrously send an HTTP request. /// - public static async Task SendAsync(HttpRequestMessage request, CancellationToken token = default) + public static async Task SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead, CancellationToken token = default) { - return await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token); + return await client.SendAsync(request, completionOption, token); } } } diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 7a6083706b3..96909389148 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -4,11 +4,13 @@ using System.IO; using System.Linq; using System.Net; +using System.Net.Http; using System.Threading.Tasks; using System.Windows.Media; using System.Windows.Media.Imaging; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; +using static Flow.Launcher.Infrastructure.Http.Http; namespace Flow.Launcher.Infrastructure.Image { @@ -20,17 +22,12 @@ public static class ImageLoader private static IImageHashGenerator _hashGenerator; private static readonly bool EnableImageHash = true; public static ImageSource DefaultImage { get; } = new BitmapImage(new Uri(Constant.MissingImgIcon)); + public const int SmallIconSize = 32; private static readonly string[] ImageExtensions = { - ".png", - ".jpg", - ".jpeg", - ".gif", - ".bmp", - ".tiff", - ".ico" + ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".ico" }; public static void Initialize() @@ -40,21 +37,24 @@ public static void Initialize() var usage = LoadStorageToConcurrentDictionary(); - foreach (var icon in new[] { Constant.DefaultIcon, Constant.MissingImgIcon }) + foreach (var icon in new[] + { + Constant.DefaultIcon, Constant.MissingImgIcon + }) { ImageSource img = new BitmapImage(new Uri(icon)); img.Freeze(); ImageCache[icon] = img; } - _ = Task.Run(() => + _ = Task.Run(async () => { - Stopwatch.Normal("|ImageLoader.Initialize|Preload images cost", () => + await Stopwatch.NormalAsync("|ImageLoader.Initialize|Preload images cost", async () => { - ImageCache.Data.AsParallel().ForAll(x => + foreach (var imageUsage in ImageCache.Data) { - Load(x.Key); - }); + await LoadAsync(imageUsage.Key); + } }); Log.Info($"|ImageLoader.Initialize|Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}"); }); @@ -100,7 +100,7 @@ private enum ImageType Cache } - private static ImageResult LoadInternal(string path, bool loadFullImage = false) + private static async ValueTask LoadInternalAsync(string path, bool loadFullImage = false) { ImageResult imageResult; @@ -114,21 +114,29 @@ private static ImageResult LoadInternal(string path, bool loadFullImage = false) { return new ImageResult(ImageCache[path], ImageType.Cache); } - Uri uriResult; - bool IsUriScheme = Uri.TryCreate(path, UriKind.Absolute, out uriResult) - && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); - if (IsUriScheme) + if (Uri.TryCreate(path, UriKind.RelativeOrAbsolute, out var uriResult) + && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps)) { // Download image from url - var resp = Http.Http.GetStreamAsync(path).Result; + await using var resp = await GetStreamAsync(uriResult); if (resp == null) { return new ImageResult(ImageCache[Constant.MissingImgIcon], ImageType.Error); } + await using var buffer = new MemoryStream(); + await resp.CopyToAsync(buffer); + buffer.Seek(0, SeekOrigin.Begin); var image = new BitmapImage(); image.BeginInit(); - image.StreamSource = resp; + image.CacheOption = BitmapCacheOption.OnLoad; + if (!loadFullImage) + { + image.DecodePixelHeight = SmallIconSize; + image.DecodePixelWidth = SmallIconSize; + } + image.StreamSource = buffer; image.EndInit(); + image.StreamSource = null; image.Freeze(); ImageCache[path] = image; return new ImageResult(image, ImageType.ImageFile); @@ -237,9 +245,9 @@ public static bool CacheContainImage(string path) return ImageCache.ContainsKey(path) && ImageCache[path] != null; } - public static ImageSource Load(string path, bool loadFullImage = false) + public static async ValueTask LoadAsync(string path, bool loadFullImage = false) { - var imageResult = LoadInternal(path, loadFullImage); + var imageResult = await LoadInternalAsync(path, loadFullImage); var img = imageResult.ImageSource; if (imageResult.ImageType != ImageType.Error && imageResult.ImageType != ImageType.Cache) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 8ecd6dc4b76..211bc179876 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; @@ -43,6 +43,11 @@ public string Language public bool UseSound { get; set; } = true; public bool FirstLaunch { get; set; } = true; + public double SettingWindowWidth { get; set; } = 1000; + public double SettingWindowHeight { get; set; } = 700; + public double SettingWindowTop { get; set; } + public double SettingWindowLeft { get; set; } + public int CustomExplorerIndex { get; set; } = 0; [JsonIgnore] @@ -220,4 +225,4 @@ public enum ColorSchemes Light, Dark } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Plugin/Result.cs b/Flow.Launcher.Plugin/Result.cs index 79d3635f1a4..6da94d899ac 100644 --- a/Flow.Launcher.Plugin/Result.cs +++ b/Flow.Launcher.Plugin/Result.cs @@ -72,6 +72,10 @@ public string IcoPath } } } + /// + /// Determines if Icon has a border radius + /// + public bool RoundedIcon { get; set; } = false; /// /// Delegate function, see @@ -209,5 +213,16 @@ public ValueTask ExecuteAsync(ActionContext context) { return AsyncAction?.Invoke(context) ?? ValueTask.FromResult(Action?.Invoke(context) ?? false); } + + /// + /// Progress bar display. Providing an int value between 0-100 will trigger the progress bar to be displayed on the result + /// + public int? ProgressBar { get; set; } + + /// + /// Optionally set the color of the progress bar + /// + /// #26a0da (blue) + public string ProgressBarColor { get; set; } = "#26a0da"; } } diff --git a/Flow.Launcher.sln b/Flow.Launcher.sln index ec4a29ee78d..f59d3d26fb7 100644 --- a/Flow.Launcher.sln +++ b/Flow.Launcher.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29806.167 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32901.215 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Test", "Flow.Launcher.Test\Flow.Launcher.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}" ProjectSection(ProjectDependencies) = postProject diff --git a/Flow.Launcher/ActionKeywords.xaml b/Flow.Launcher/ActionKeywords.xaml index e94aac9f6d7..740b0d40254 100644 --- a/Flow.Launcher/ActionKeywords.xaml +++ b/Flow.Launcher/ActionKeywords.xaml @@ -58,7 +58,6 @@ throw new System.InvalidOperationException(); diff --git a/Flow.Launcher/Converters/OrdinalConverter.cs b/Flow.Launcher/Converters/OrdinalConverter.cs index f9fa220e324..0c716ac7e87 100644 --- a/Flow.Launcher/Converters/OrdinalConverter.cs +++ b/Flow.Launcher/Converters/OrdinalConverter.cs @@ -10,7 +10,10 @@ public object Convert(object value, System.Type targetType, object parameter, Cu { if (value is ListBoxItem listBoxItem && ItemsControl.ItemsControlFromItemContainer(listBoxItem) is ListBox listBox) - return listBox.ItemContainerGenerator.IndexFromContainer(listBoxItem) + 1; + { + var res = listBox.ItemContainerGenerator.IndexFromContainer(listBoxItem) + 1; + return res == 10 ? 0 : res; // 10th item => HOTKEY+0 + } return 0; } diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml b/Flow.Launcher/CustomQueryHotkeySetting.xaml index 187f99d1823..ddf0d0e454a 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml @@ -64,7 +64,6 @@ Vælg Skjul Flow Launcher ved opstart Hide tray icon + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Query Search Precision Changes minimum match score required for results. Should Use Pinyin @@ -69,12 +70,14 @@ Current Priority New Priority Priority + Change Plugin Results Priority Plugin bibliotek af Initaliseringstid: Søgetid: | Version Website + Uninstall @@ -155,11 +158,13 @@ Download updates failed, please check your connection and proxy settings to github-cloud.s3.amazonaws.com, or go to https://github.com/Flow-Launcher/Flow.Launcher/releases to download updates manually. - Release Notes: + Release Notes Usage Tips DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/de.xaml b/Flow.Launcher/Languages/de.xaml index cf73baa221e..a1b0b3b9b37 100644 --- a/Flow.Launcher/Languages/de.xaml +++ b/Flow.Launcher/Languages/de.xaml @@ -50,6 +50,7 @@ Auswählen Verstecke Flow Launcher bei Systemstart Statusleistensymbol ausblenden + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Suchgenauigkeit abfragen Erforderliche Suchergebnisse. Pinyin aktivieren @@ -69,12 +70,14 @@ Aktuelle Priorität Neue Priorität Priorität + Change Plugin Results Priority Pluginordner von Initialisierungszeit: Abfragezeit: Version Webseite + Deinstallieren @@ -155,11 +158,13 @@ Download updates failed, please check your connection and proxy settings to github-cloud.s3.amazonaws.com, or go to https://github.com/Flow-Launcher/Flow.Launcher/releases to download updates manually. - Versionshinweise: + Versionshinweise Usage Tips DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index bdf7450525c..2019c1b6629 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -52,6 +52,7 @@ Select Hide Flow Launcher on startup Hide tray icon + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Query Search Precision Changes minimum match score required for results. Should Use Pinyin @@ -59,6 +60,10 @@ Shadow effect is not allowed while current theme has blur effect enabled + Search Plugin + Ctrl+F to search plugins + No results found + Please try a different search. Plugin Find more plugins On @@ -71,12 +76,14 @@ Current Priority New Priority Priority + Change Plugin Results Priority Plugin Directory by Init time: Query time: | Version Website + Uninstall @@ -162,6 +169,8 @@ DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/es-419.xaml b/Flow.Launcher/Languages/es-419.xaml index 8ce9f12cf11..84a492d1553 100644 --- a/Flow.Launcher/Languages/es-419.xaml +++ b/Flow.Launcher/Languages/es-419.xaml @@ -50,6 +50,7 @@ Seleccionar Ocultar Flow Launcher al arrancar el sistema Ocultar icono de la bandeja + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Precisión de la búsqueda Cambia la puntuación mínima de similitud requerida para resultados. Debe usar Pinyin @@ -69,12 +70,14 @@ Prioridad Actual Nueva Prioridad Prioridad + Cambiar la prioridad del resultado del plugin Directorio de Plugins por Tiempo de inicio: Tiempo de consulta: | Versión Sitio web + Uninstall @@ -160,6 +163,8 @@ Herramientas de desarrollo Carpeta de Configuración Carpeta de registros + Clear Logs + Are you sure you want to delete all logs? Asistente diff --git a/Flow.Launcher/Languages/es.xaml b/Flow.Launcher/Languages/es.xaml index d30cd16c91e..0950595fa4a 100644 --- a/Flow.Launcher/Languages/es.xaml +++ b/Flow.Launcher/Languages/es.xaml @@ -50,6 +50,7 @@ Seleccionar Ocultar Flow Launcher al inicio Ocultar icono de la bandeja del sistema + Cuando el icono está oculto en la bandeja del sistema, se puede abrir el menú de configuración haciendo clic con el botón derecho en la ventana de búsqueda. Precisión en la búsqueda de consultas Cambia la puntuación mínima requerida para la coincidencia de los resultados. Utilizar Pinyin @@ -57,7 +58,7 @@ El efecto de sombra no está permitido mientras el tema actual tenga el efecto de desenfoque activado - Complemento + Complementos Buscar más complementos Activado Desactivado @@ -69,12 +70,14 @@ Prioridad actual Nueva prioridad Prioridad + Cambiar la prioridad de los resultados del complemento Carpeta de complementos por Tiempo de inicio: Tiempo de consulta: | Versión Sitio web + Desinstalar @@ -157,9 +160,11 @@ Notas de la versión Consejos de uso - Herramientas de desarrolador + Herramientas de desarrollador Carpeta de configuración Carpeta de registros + Eliminar registros + ¿Está seguro que desea eliminar todos los registros? Asistente diff --git a/Flow.Launcher/Languages/fr.xaml b/Flow.Launcher/Languages/fr.xaml index cbcd84307f2..141d868a2d9 100644 --- a/Flow.Launcher/Languages/fr.xaml +++ b/Flow.Launcher/Languages/fr.xaml @@ -50,6 +50,7 @@ Sélectionner Cacher Flow Launcher au démarrage Masquer icône du plateau + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Query Search Precision Changes minimum match score required for results. Devrait utiliser le pinyin @@ -69,12 +70,14 @@ Current Priority New Priority Priority + Change Plugin Results Priority Répertoire by Chargement : Utilisation : | Version Website + Désinstaller @@ -154,11 +157,13 @@ Échec du téléchargement de la mise à jour, vérifiez votre connexion et vos paramètres de configuration proxy pour pouvoir acceder à github-cloud.s3.amazonaws.com, ou téléchargez manuelement la mise à jour sur https://github.com/Flow-Launcher/Flow.Launcher/releases. - Notes de changement : + Notes de changement Usage Tips DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/it.xaml b/Flow.Launcher/Languages/it.xaml index 04655c2263d..4304aead83e 100644 --- a/Flow.Launcher/Languages/it.xaml +++ b/Flow.Launcher/Languages/it.xaml @@ -10,23 +10,23 @@ Ultima esecuzione: {0} Apri Impostazioni - About + Informazioni Esci - Close - Copy - Cut - Paste + Chiudi + Copia + Taglia + Incolla File - Folder - Text - Game Mode - Suspend the use of Hotkeys. + Cartella + Testo + Modalità gioco + Sospendere l'uso dei tasti di scelta rapida. Impostaizoni Flow Launcher Generale - Portable Mode - Store all settings and user data in one folder (Useful when used with removable drives or cloud services). + Modalità portatile + Memorizzare tutte le impostazioni e i dati dell'utente in un'unica cartella (utile se utilizzato con unità rimovibili o servizi cloud). Avvia Wow all'avvio di Windows Error setting launch on startup Nascondi Flow Launcher quando perde il focus @@ -34,80 +34,83 @@ Ricorda l'ultima posizione di avvio del launcher Lingua Comportamento ultima ricerca - Show/Hide previous results when Flow Launcher is reactivated. + Mostra/nasconde i risultati precedenti quando Flow Launcher viene riattivato. Conserva ultima ricerca Seleziona ultima ricerca Cancella ultima ricerca Numero massimo di risultati mostrati Ignora i tasti di scelta rapida in applicazione a schermo pieno - Disable Flow Launcher activation when a full screen application is active (Recommended for games). - Default File Manager - Select the file manager to use when opening the folder. - Default Web Browser - Setting for New Tab, New Window, Private Mode. + Disattivare l'attivazione di Flow Launcher quando è attiva un'applicazione a schermo intero (consigliato per i giochi). + Gestore File predefinito + Selezionare il Gestore file da usare all'apertura della cartella. + Browser predefinito + Impostazione per Nuova scheda, Nuova finestra, Modalità privata. Cartella Python Aggiornamento automatico Seleziona Nascondi Flow Launcher all'avvio - Hide tray icon - Query Search Precision - Changes minimum match score required for results. - Should Use Pinyin - Allows using Pinyin to search. Pinyin is the standard system of romanized spelling for translating Chinese - Shadow effect is not allowed while current theme has blur effect enabled + Nascondi Icona nell'Area di Notifica + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. + Precisione di ricerca delle query + Modifica il punteggio minimo richiesto per i risultati. + Dovrebbe usare il Pinyin + Consente di utilizzare il Pinyin per la ricerca. Il Pinyin è il sistema standard di ortografia romanizzata per la traduzione del cinese + L'effetto ombra non è consentito mentre il tema corrente ha un effetto di sfocatura abilitato Plugin Cerca altri plugins - On + Attivo Disabilita - Action keyword Setting + Impostazioni parola chiave Azione Parole chiave - Current action keyword - New action keyword - Change Action Keywords - Current Priority - New Priority - Priority + Parola chiave di azione corrente + Nuova parola chiave d'azione + Cambia Keywords Azione + Priorità Attuale + Nuova Priorità + Priorità + Change Plugin Results Priority Cartella Plugin - by + da Tempo di avvio: Tempo ricerca: - | Version - Website + | Versione + Sito Web + Disinstalla - Plugin Store - Refresh - Install + Negozio dei Plugin + Aggiorna + Installa Tema Sfoglia per altri temi - How to create a theme - Hi There + Come creare un tema + Ciao Font campo di ricerca Font campo risultati Modalità finestra Opacità - Theme {0} not exists, fallback to default theme - Fail to load theme {0}, fallback to default theme - Theme Folder - Open Theme Folder - Color Scheme - System Default - Light - Dark - Sound Effect - Play a small sound when the search window opens - Animation - Use Animation in UI + Il tema {0} non esiste, si ritorna al tema predefinito + Impossibile caricare il tema {0}, si torna al tema predefinito + Cartella temi + Apri cartella del tema + Schema di colore + Sistema predefinito + Chiaro + Scuro + Effetto sonoro + Riproduce un piccolo suono all'apertura della finestra di ricerca + Animazione + Usa l'animazione nell'interfaccia utente Tasti scelta rapida Tasto scelta rapida Flow Launcher - Enter shortcut to show/hide Flow Launcher. + Immettere la scorciatoia per mostrare/nascondere Flow Launcher. Apri modificatori di risultato Select a modifier key to open selected result via keyboard. Mostra tasto di scelta rapida @@ -130,7 +133,7 @@ Abilita Proxy HTTP Server HTTP Porta - User Name + Nome utente Password Proxy Test Salva @@ -142,10 +145,10 @@ Connessione Proxy fallita - About - Website + Informazioni + Sito web Github - Docs + Documentazione Versione Hai usato Flow Launcher {0} volte Cerca aggiornamenti @@ -155,11 +158,13 @@ Download degli aggiornamenti fallito, per favore controlla la tua connessione ed eventuali impostazioni proxy per github-cloud.s3.amazonaws.com, oppure vai su https://github.com/Flow-Launcher/Flow.Launcher/releases per scaricare gli aggiornamenti manualmente. - Note di rilascio: + Note di rilascio Usage Tips DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard @@ -173,10 +178,10 @@ Arg For File - Default Web Browser + Browser predefinito The default setting follows the OS default browser setting. If specified separately, flow uses that browser. Browser - Browser Name + Nome del browser Browser Path New Window New Tab @@ -251,37 +256,37 @@ Descrizione aggiornamento - Skip + Salta Welcome to Flow Launcher Hello, this is the first time you are running Flow Launcher! Before starting, this wizard will assist in setting up Flow Launcher. You can skip this if you wish. Please choose a language - Search and run all files and applications on your PC - Search everything from applications, files, bookmarks, YouTube, Twitter and more. All from the comfort of your keyboard without ever touching the mouse. - Flow Launcher starts with the hotkey below, go ahead and try it out now. To change it, click on the input and press the desired hotkey on the keyboard. - Hotkeys - Action Keyword and Commands - Search the web, launch applications or run various functions through Flow Launcher plugins. Certain functions start with an action keyword, and if necessary, they can be used without action keywords. Try the queries below in Flow Launcher. - Let's Start Flow Launcher - Finished. Enjoy Flow Launcher. Don't forget the hotkey to start :) + Cerca ed esegue tutti i file e le applicazioni presenti sul PC + Cerca tutto da applicazioni, file, segnalibri, YouTube, Twitter e altro ancora. Tutto dalla comodità della tastiera senza mai toccare il mouse. + Flow Launcher si avvia con il tasto di scelta rapida qui sotto, provatelo subito. Per cambiarlo, fate clic sull'input e premete il tasto di scelta rapida desiderato sulla tastiera. + Scorciatoie + Scorciatoie e comandi + Cercate sul web, avviate applicazioni o eseguite varie funzioni tramite i plugin di Flow Launcher. Alcune funzioni iniziano con una parola chiave di azione e, se necessario, possono essere utilizzate senza parole chiave di azione. Provate le query seguenti in Flow Launcher. + Avviamo Flow Launcher + Finito. Goditi Flow Launcher. Non dimenticare il tasto di scelta rapida per iniziare :) - Back / Context Menu - Item Navigation - Open Context Menu - Open Contaning Folder - Run as Admin - Query History - Back to Result in Context Menu - Autocomplete - Open / Run Selected Item - Open Setting Window - Reload Plugin Data + Indietro / Menu contestuale + Navigazione tra le voci + Apri il menu di scelta rapida + Apri la cartella Contaning + Esegui come amministratore + Cronologia Query + Torna al risultato nel menu contestuale + Autocompleta + Apri / Esegui Elemento Selezionato + Aprire la finestra delle impostazioni + Ricarica i dati del plugin - Weather - Weather in Google Result + Meteo + Meteo nel risultato di Google > ping 8.8.8.8 - Shell Command + Comando Della shell Bluetooth Bluetooth in Windows Settings sn diff --git a/Flow.Launcher/Languages/ja.xaml b/Flow.Launcher/Languages/ja.xaml index e34c615b7a9..8c13863710c 100644 --- a/Flow.Launcher/Languages/ja.xaml +++ b/Flow.Launcher/Languages/ja.xaml @@ -50,6 +50,7 @@ 選択 起動時にFlow Launcherを隠す トレイアイコンを隠す + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Query Search Precision Changes minimum match score required for results. Should Use Pinyin @@ -69,12 +70,14 @@ Current Priority New Priority 重要度 + Change Plugin Results Priority プラグイン・ディレクトリ by 初期化時間: クエリ時間: | バージョン ウェブサイト + アンインストール @@ -155,11 +158,13 @@ 更新のダウンロードに失敗しました、github-cloud.s3.amazonaws.com への接続とプロキシ設定を確認するか、 https://github.com/Flow-Launcher/Flow.Launcher/releases から手動でアップデートをダウンロードしてください。 - リリースノート: + リリースノート Usage Tips DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml index a5ad2647fc2..809c5ccf817 100644 --- a/Flow.Launcher/Languages/ko.xaml +++ b/Flow.Launcher/Languages/ko.xaml @@ -50,6 +50,7 @@ 선택 시작 시 Flow Launcher 숨김 트레이 아이콘 숨기기 + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. 쿼리 검색 정밀도 검색 결과에 필요한 최소 매치 점수를 변경합니다. 항상 Pinyin 사용 @@ -69,12 +70,14 @@ 현재 중요도: 새 중요도: 중요도 + 플러그인 결과 우선 순위 변경 플러그인 폴더 제작자 초기화 시간: 쿼리 시간: | 버전 웹사이트 + 제거 @@ -86,7 +89,7 @@ 테마 테마 갤러리 테마 제작 안내 - 안녕하세요. + 안녕하세요! 쿼리 상자 글꼴 결과 항목 글꼴 윈도우 모드 @@ -160,6 +163,8 @@ 개발자도구 설정 폴더 로그 폴더 + Clear Logs + Are you sure you want to delete all logs? 마법사 diff --git a/Flow.Launcher/Languages/nb.xaml b/Flow.Launcher/Languages/nb.xaml index 52885ea473b..e90a32347a5 100644 --- a/Flow.Launcher/Languages/nb.xaml +++ b/Flow.Launcher/Languages/nb.xaml @@ -50,6 +50,7 @@ Select Hide Flow Launcher on startup Hide tray icon + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Query Search Precision Changes minimum match score required for results. Should Use Pinyin @@ -69,12 +70,14 @@ Current Priority New Priority Priority + Change Plugin Results Priority Plugin Directory by Init time: Query time: | Version Website + Uninstall @@ -160,6 +163,8 @@ DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/nl.xaml b/Flow.Launcher/Languages/nl.xaml index 1223df76f73..77a8e9e2902 100644 --- a/Flow.Launcher/Languages/nl.xaml +++ b/Flow.Launcher/Languages/nl.xaml @@ -50,6 +50,7 @@ Selecteer Verberg Flow Launcher als systeem opstart Systeemvakpictogram verbergen + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Zoekopdracht nauwkeurigheid Wijzigt de minimale overeenkomst-score die vereist is voor resultaten. Zou Pinyin moeten gebruiken @@ -69,12 +70,14 @@ Huidige Prioriteit Nieuwe Prioriteit Prioriteit + Change Plugin Results Priority Plugin map door Init tijd: Query tijd: | Versie Website + Uninstall @@ -155,11 +158,13 @@ Download updates failed, please check your connection and proxy settings to github-cloud.s3.amazonaws.com, or go to https://github.com/Flow-Launcher/Flow.Launcher/releases to download updates manually. - Release Notes: + Release Notes Usage Tips DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/pl.xaml b/Flow.Launcher/Languages/pl.xaml index 901083f075f..bd7acd4e88b 100644 --- a/Flow.Launcher/Languages/pl.xaml +++ b/Flow.Launcher/Languages/pl.xaml @@ -50,6 +50,7 @@ Wybierz Uruchamiaj Flow Launcher zminimalizowany Ukryj ikonę zasobnika + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Query Search Precision Changes minimum match score required for results. Should Use Pinyin @@ -69,12 +70,14 @@ Current Priority New Priority Priority + Change Plugin Results Priority Folder wtyczki by Czas ładowania: Czas zapytania: | Version Website + Odinstalowywanie @@ -155,11 +158,13 @@ Download updates failed, please check your connection and proxy settings to github-cloud.s3.amazonaws.com, or go to https://github.com/Flow-Launcher/Flow.Launcher/releases to download updates manually. - Zmiany: + Zmiany Usage Tips DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/pt-br.xaml b/Flow.Launcher/Languages/pt-br.xaml index d23c24e7f15..28ed3091674 100644 --- a/Flow.Launcher/Languages/pt-br.xaml +++ b/Flow.Launcher/Languages/pt-br.xaml @@ -50,6 +50,7 @@ Selecionar Esconder Flow Launcher na inicialização Hide tray icon + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Query Search Precision Changes minimum match score required for results. Should Use Pinyin @@ -69,12 +70,14 @@ Current Priority New Priority Priority + Change Plugin Results Priority Diretório de Plugins by Tempo de inicialização: Tempo de consulta: | Version Website + Desinstalar @@ -160,6 +163,8 @@ DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/pt-pt.xaml b/Flow.Launcher/Languages/pt-pt.xaml index c785199665e..e7179e6e873 100644 --- a/Flow.Launcher/Languages/pt-pt.xaml +++ b/Flow.Launcher/Languages/pt-pt.xaml @@ -50,6 +50,7 @@ Selecionar Ocultar Flow Launcher ao arrancar Ocultar ícone na bandeja + Se o ícone da bandeja estiver oculto, pode abrir as Definições com um clique com o botão direito do rato na caixa de pesquisa. Precisão da consulta Altera a precisão mínima necessário para obter resultados Utilizar Pinyin @@ -69,12 +70,14 @@ Prioridade atual Nova prioridade Prioridade + Alterar prioridade dos resultados do plugin Diretório de plugins de Tempo de arranque: Tempo de consulta: | Versão Site + Desinstalar @@ -159,6 +162,8 @@ DevTools Pasta de definições Pasta de registos + Clear Logs + Are you sure you want to delete all logs? Assistente diff --git a/Flow.Launcher/Languages/ru.xaml b/Flow.Launcher/Languages/ru.xaml index 691d3753891..2c8ca9fa3d7 100644 --- a/Flow.Launcher/Languages/ru.xaml +++ b/Flow.Launcher/Languages/ru.xaml @@ -50,6 +50,7 @@ Select Hide Flow Launcher on startup Hide tray icon + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Query Search Precision Changes minimum match score required for results. Should Use Pinyin @@ -69,12 +70,14 @@ Current Priority New Priority Priority + Change Plugin Results Priority Директория плагинов by Инициализация: Запрос: | Version Website + Удалить @@ -160,6 +163,8 @@ DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml index 20b259f9fa7..c4d5de6bf29 100644 --- a/Flow.Launcher/Languages/sk.xaml +++ b/Flow.Launcher/Languages/sk.xaml @@ -50,6 +50,7 @@ Vybrať Schovať Flow Launcher po spustení Schovať ikonu z oblasti oznámení + Keď je ikona skrytá z oblasti oznámení, nastavenia možno otvoriť kliknutím pravým tlačidlom myši na okno vyhľadávania. Presnosť vyhľadávania Mení minimálne skóre zhody potrebné na zobrazenie výsledkov. Použiť Pinyin @@ -69,12 +70,14 @@ Aktuálna priorita Nová priorita Priorita + Zmena priority výsledkov pluginu Priečinok s pluginmi od Inicializácia: Trvanie dopytu: | Verzia Webstránka + Odinštalovať @@ -160,6 +163,8 @@ Nástroje pre vývojárov Priečinok s nastaveniami Priečinok s logmi + Vymazať logy + Naozaj chcete odstrániť všetky logy? Sprievodca diff --git a/Flow.Launcher/Languages/sr.xaml b/Flow.Launcher/Languages/sr.xaml index b15bbc194d6..61f619fd038 100644 --- a/Flow.Launcher/Languages/sr.xaml +++ b/Flow.Launcher/Languages/sr.xaml @@ -50,6 +50,7 @@ Izaberi Sakrij Flow Launcher pri podizanju sistema Hide tray icon + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Query Search Precision Changes minimum match score required for results. Should Use Pinyin @@ -69,12 +70,14 @@ Current Priority New Priority Priority + Change Plugin Results Priority Plugin direktorijum by Vreme inicijalizacije: Vreme upita: | Version Website + Uninstall @@ -155,11 +158,13 @@ Neuspešno preuzimanje ažuriranja, molim Vas proverite vašu vezu i podešavanja za proksi prema github-cloud.s3.amazonaws.com, ili posetite https://github.com/Flow-Launcher/Flow.Launcher/releases da preuzmete ažuriranja ručno. - U novoj verziji: + U novoj verziji Usage Tips DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/tr.xaml b/Flow.Launcher/Languages/tr.xaml index ec609de371f..fb8e1d6f621 100644 --- a/Flow.Launcher/Languages/tr.xaml +++ b/Flow.Launcher/Languages/tr.xaml @@ -50,6 +50,7 @@ Seç Başlangıçta Flow Launcher'u gizle Sistem çekmecesi simgesini gizle + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Sorgu Arama Hassasiyeti Sonuçlar için gereken minimum maç puanını değiştirir. Pinyin kullanılmalı @@ -69,12 +70,14 @@ Mevcut öncelik Yeni Öncelik Öncelik + Change Plugin Results Priority Eklenti Klasörü Yapımcı: Açılış Süresi: Sorgu Süresi: Sürüm İnternet Sitesi + Kaldır @@ -155,11 +158,13 @@ Güncellemenin yüklenmesi başarısız oldu. Lütfen bağlantınız ve vekil sunucu ayarlarınızın github-cloud.s3.amazonaws.com adresine ulaşabilir olduğunu kontrol edin ya da https://github.com/Flow-Launcher/Flow.Launcher/releases adresinden güncellemeyi elle indirin. - Sürüm Notları: + Sürüm Notları Usage Tips DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/uk-UA.xaml b/Flow.Launcher/Languages/uk-UA.xaml index c2d5302a6d8..8115a5dd1a8 100644 --- a/Flow.Launcher/Languages/uk-UA.xaml +++ b/Flow.Launcher/Languages/uk-UA.xaml @@ -50,6 +50,7 @@ Вибрати Сховати Flow Launcher при запуску системи Приховати значок в системному лотку + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. Точність пошуку запитів Змінює мінімальний бал збігів, необхідних для результатів. Використовувати піньїнь @@ -69,12 +70,14 @@ Поточний пріоритет Новий пріоритет Пріоритет + Change Plugin Results Priority Директорія плагінів за Ініціалізація: Запит: | Версія Сайт + Uninstall @@ -160,6 +163,8 @@ DevTools Setting Folder Log Folder + Clear Logs + Are you sure you want to delete all logs? Wizard diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index b3bd5fd1f82..d80bfdaf66a 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -28,7 +28,7 @@ 便携模式 将所有设置和用户数据存储在一个文件夹中 (可用于可移除驱动器或云服务)。 开机自启 - Error setting launch on startup + 设置开机自启时出错 失去焦点时自动隐藏 Flow Launcher 不显示新版本提示 记住上次启动位置 @@ -40,7 +40,7 @@ 清空上次搜索关键字 最大结果显示个数 全屏模式下忽略热键 - 当全屏应用程序激活时禁用快捷键(建议游戏时打开)。 + 当全屏应用程序激活时禁用快捷键 (建议游戏时打开) 。 默认文件管理器 选择打开文件夹时要使用的文件管理器。 默认浏览器 @@ -50,6 +50,7 @@ 选择 系统启动时不显示主窗口 隐藏任务栏图标 + 任务栏图标被隐藏时,右键点击搜索窗口即可打开设置菜单。 查询搜索精度 更改匹配成功所需的最低分数。 启动拼音搜索 @@ -69,12 +70,14 @@ 当前优先级 新优先级 优先级 + 更改插件结果优先级 插件目录 出自 加载耗时: 查询耗时: | 版本 官方网站 + 卸载 @@ -108,10 +111,10 @@ 热键 Flow Launcher 激活热键 输入显示/隐藏 Flow Launcher 的快捷键。 - 开放结果修饰符 - 指定修饰符用于打开指定的选项。 + 打开结果快捷键修饰符 + 选择一个用以打开搜索结果的按键修饰符。 显示热键 - 显示热键用于快速选择选项。 + 显示用于打开结果的快捷键。 自定义查询热键 查询 删除 @@ -155,11 +158,13 @@ 下载更新失败,请检查您与 github-cloud.s3.amazonaws.com 的连接状态或检查代理设置, 或访问 https://github.com/Flow-Launcher/Flow.Launcher/releases 手动下载更新 - 更新说明: - 使用技巧: + 更新说明 + 使用技巧 开发工具 设置目录 日志目录 + 清除日志 + 你确定要删除所有的日志吗? 向导 @@ -256,11 +261,11 @@ 你好,这是你第一次运行 Flow Launcher! 在启动前,这个向导将有助于设置 Flow Launcher。如果您愿意,您可以跳过。请选择一种语言 搜索并运行您PC上的文件和应用程序 - 搜索所有应用程序、 文件、 书签、 YouTube、 Twitter等。所有都只需要键盘而不需要触摸鼠标。 + 搜索所有应用程序、 文件、 书签、 YouTube、 Twitter等。所有都只需要键盘而不需要鼠标。 Flow Launcher 默认使用下面的快捷键激活。 要更改它,请点击输入并按键盘上所需的热键。 快捷键 动作关键词和命令 - 通过 Flow Launcher 插件搜索网站、启动应用程序或运行各种功能。 某些函数起始于一个动作关键词,如有必要,它们可以在没有动作关键词的情况下使用。欢迎尝试一下的查询语句。 + 通过 Flow Launcher 插件搜索网站、启动应用程序或运行各种功能。某些功能使用一个动作关键词激活,如有必要,它们也可以在没有动作关键词的情况下使用。欢迎尝试以下的查询语句。 开始使用 Flow Launcher 完成了!享受 Flow Launcher。不要忘记激活快捷键 :) @@ -268,7 +273,7 @@ 返回/上下文菜单 选项导航 - 打开菜单目录 + 打开上下文菜单 打开所在目录 以管理员身份运行 查询历史 @@ -285,6 +290,6 @@ Bluetooth Windows 设置中的蓝牙 sn - Sticky Notes + 便笺 diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index fea5055260b..71cc887cf8f 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -42,7 +42,7 @@ 全螢幕模式下忽略快捷鍵 全螢幕模式下停用快捷鍵(推薦用於遊戲時)。 預設檔案管理器 - 選擇打開資料夾時要使用的檔案管理器。 + 選擇開啟資料夾時要使用的檔案管理器。 預設瀏覽器 設定新增分頁、視窗和無痕模式。 Python 路徑 @@ -50,6 +50,7 @@ 選擇 啟動時不顯示主視窗 隱藏任務欄圖標 + When the icon is hidden from the tray, the Settings menu can be opened by right-clicking on the search window. 查詢搜索精確度 Changes minimum match score required for results. 拼音搜索 @@ -69,12 +70,14 @@ 目前優先 新增優先 優先 + 更改插件結果優先順序 外掛資料夾 作者 載入耗時: 查詢耗時: | 版本 官方網站 + 解除安裝 @@ -155,11 +158,13 @@ 下載更新失敗,請檢查您對 github-cloud.s3.amazonaws.com 的連線和代理設定, 或是到 https://github.com/Flow-Launcher/Flow.Launcher/releases 手動下載更新。 - 更新說明: + 更新說明 使用技巧 開發工具 設定資料夾 日誌資料夾 + Clear Logs + Are you sure you want to delete all logs? 嚮導 diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 714fcc53fa1..dc3b3f1454b 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -150,6 +150,11 @@ Command="{Binding OpenResultCommand}" CommandParameter="8" Modifiers="{Binding OpenResultCommandModifiers}" /> + @@ -174,6 +179,7 @@ PreviewDragOver="OnPreviewDragOver" Style="{DynamicResource QueryBoxStyle}" Text="{Binding QueryText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" + PreviewKeyUp="QueryTextBox_KeyUp" Visibility="Visible"> diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 2b7db38cff2..332e0f5024a 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Threading.Tasks; using System.Windows; @@ -20,6 +20,8 @@ using System.Windows.Media; using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Plugin.SharedCommands; +using System.Windows.Data; +using System.Diagnostics; namespace Flow.Launcher { @@ -136,22 +138,20 @@ private void OnLoaded(object sender, RoutedEventArgs _) } case nameof(MainViewModel.ProgressBarVisibility): { - Dispatcher.Invoke(async () => + Dispatcher.Invoke(() => { if (_viewModel.ProgressBarVisibility == Visibility.Hidden && !isProgressBarStoryboardPaused) { - await Task.Delay(50); _progressBarStoryboard.Stop(ProgressBar); isProgressBarStoryboardPaused = true; } else if (_viewModel.MainWindowVisibilityStatus && - isProgressBarStoryboardPaused) + isProgressBarStoryboardPaused) { _progressBarStoryboard.Begin(ProgressBar, true); isProgressBarStoryboardPaused = false; } - }, System.Windows.Threading.DispatcherPriority.Render); - + }); break; } case nameof(MainViewModel.QueryTextCursorMovedToEnd): @@ -555,5 +555,14 @@ public void InitializeColorScheme() ModernWpf.ThemeManager.Current.ApplicationTheme = ModernWpf.ApplicationTheme.Dark; } } + + private void QueryTextBox_KeyUp(object sender, KeyEventArgs e) + { + if(_viewModel.QueryText != QueryTextBox.Text) + { + BindingExpression be = QueryTextBox.GetBindingExpression(System.Windows.Controls.TextBox.TextProperty); + be.UpdateSource(); + } + } } -} \ No newline at end of file +} diff --git a/Flow.Launcher/Msg.xaml.cs b/Flow.Launcher/Msg.xaml.cs index 6bb2fc2dc6f..1be89d71604 100644 --- a/Flow.Launcher/Msg.xaml.cs +++ b/Flow.Launcher/Msg.xaml.cs @@ -38,10 +38,16 @@ public Msg() Storyboard.SetTargetProperty(fadeOutAnimation, new PropertyPath(TopProperty)); fadeOutStoryboard.Children.Add(fadeOutAnimation); - imgClose.Source = ImageLoader.Load(Path.Combine(Infrastructure.Constant.ProgramDirectory, "Images\\close.png")); + _ = LoadImageAsync(); + imgClose.MouseUp += imgClose_MouseUp; } + private async System.Threading.Tasks.Task LoadImageAsync() + { + imgClose.Source = await ImageLoader.LoadAsync(Path.Combine(Infrastructure.Constant.ProgramDirectory, "Images\\close.png")); + } + void imgClose_MouseUp(object sender, MouseButtonEventArgs e) { if (!closing) @@ -56,7 +62,7 @@ private void fadeOutStoryboard_Completed(object sender, EventArgs e) Close(); } - public void Show(string title, string subTitle, string iconPath) + public async void Show(string title, string subTitle, string iconPath) { tbTitle.Text = title; tbSubTitle.Text = subTitle; @@ -66,15 +72,15 @@ public void Show(string title, string subTitle, string iconPath) } if (!File.Exists(iconPath)) { - imgIco.Source = ImageLoader.Load(Path.Combine(Constant.ProgramDirectory, "Images\\app.png")); + imgIco.Source = await ImageLoader.LoadAsync(Path.Combine(Constant.ProgramDirectory, "Images\\app.png")); } else { - imgIco.Source = ImageLoader.Load(iconPath); + imgIco.Source = await ImageLoader.LoadAsync(iconPath); } Show(); - Dispatcher.InvokeAsync(async () => + await Dispatcher.InvokeAsync(async () => { if (!closing) { diff --git a/Flow.Launcher/PriorityChangeWindow.xaml b/Flow.Launcher/PriorityChangeWindow.xaml index d50bf82db4c..d6aadead9b1 100644 --- a/Flow.Launcher/PriorityChangeWindow.xaml +++ b/Flow.Launcher/PriorityChangeWindow.xaml @@ -63,7 +63,6 @@ SearchWeb.OpenInBrowserTab(e.Uri.ToString()); link.Click += (s, e) => SearchWeb.OpenInBrowserTab(url); paragraph.Inlines.Add(textBeforeUrl); diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index b4d7e78a7b6..6ab7ab5ad68 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -29,7 +29,6 @@ @@ -2724,7 +2723,8 @@ Background="{DynamicResource CustomContextBackground}" BorderBrush="{DynamicResource CustomContextBorder}" BorderThickness="1" - CornerRadius="8"> + CornerRadius="8" + UseLayoutRounding="True"> -