From 5481a6aa437aa782563d59c8d3b9c6d1f760730c Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 20 Mar 2025 05:04:19 +0900 Subject: [PATCH 001/125] Add local favicon load --- Flow.Launcher.Core/Flow.Launcher.Core.csproj | 1 + .../Flow.Launcher.Infrastructure.csproj | 1 + .../Flow.Launcher.Plugin.csproj | 1 + Flow.Launcher.Test/Flow.Launcher.Test.csproj | 1 + Flow.Launcher/Flow.Launcher.csproj | 1 + .../ChromiumBookmarkLoader.cs | 144 +++++++++++- .../FirefoxBookmarkLoader.cs | 205 ++++++++++++++---- ...low.Launcher.Plugin.BrowserBookmark.csproj | 3 + .../Main.cs | 8 +- .../Models/Bookmark.cs | 1 + .../Flow.Launcher.Plugin.Calculator.csproj | 1 + .../Flow.Launcher.Plugin.Explorer.csproj | 1 + ...low.Launcher.Plugin.PluginIndicator.csproj | 4 + ...Flow.Launcher.Plugin.PluginsManager.csproj | 4 + .../Flow.Launcher.Plugin.ProcessKiller.csproj | 1 + .../Flow.Launcher.Plugin.Program.csproj | 1 + .../Flow.Launcher.Plugin.Shell.csproj | 1 + .../Flow.Launcher.Plugin.Sys.csproj | 1 + .../Flow.Launcher.Plugin.Url.csproj | 4 + .../Flow.Launcher.Plugin.WebSearch.csproj | 4 + ...low.Launcher.Plugin.WindowsSettings.csproj | 3 + 21 files changed, 338 insertions(+), 53 deletions(-) diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj index e9f199d00..d10a0313d 100644 --- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj +++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj @@ -57,6 +57,7 @@ + diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index b91da7114..ae94afdab 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -67,6 +67,7 @@ + diff --git a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj index 1472813b8..027fac7eb 100644 --- a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj +++ b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj @@ -77,6 +77,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Flow.Launcher.Test/Flow.Launcher.Test.csproj b/Flow.Launcher.Test/Flow.Launcher.Test.csproj index 0241a374e..98f25a5f4 100644 --- a/Flow.Launcher.Test/Flow.Launcher.Test.csproj +++ b/Flow.Launcher.Test/Flow.Launcher.Test.csproj @@ -55,6 +55,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + \ No newline at end of file diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 1e305d3d9..0a792ef72 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -104,6 +104,7 @@ + diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 48acf6109..acf863bf0 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -3,11 +3,24 @@ using System.Collections.Generic; using System.IO; using System.Text.Json; using Flow.Launcher.Infrastructure.Logger; +using System; +using System.Data.SQLite; +using SkiaSharp; namespace Flow.Launcher.Plugin.BrowserBookmark; public abstract class ChromiumBookmarkLoader : IBookmarkLoader { + private readonly string _faviconCacheDir; + + protected ChromiumBookmarkLoader() + { + _faviconCacheDir = Path.Combine( + Path.GetDirectoryName(typeof(ChromiumBookmarkLoader).Assembly.Location), + "FaviconCache"); + Directory.CreateDirectory(_faviconCacheDir); + } + public abstract List GetBookmarks(); protected List LoadBookmarks(string browserDataPath, string name) @@ -22,10 +35,30 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader if (!File.Exists(bookmarkPath)) continue; - Main.RegisterBookmarkFile(bookmarkPath); + // Register bookmark file monitoring (direct call to Main.RegisterBookmarkFile) + try + { + if (File.Exists(bookmarkPath)) + { + //Main.RegisterBookmarkFile(bookmarkPath); + } + } + catch (Exception ex) + { + Log.Exception($"Failed to register bookmark file monitoring: {bookmarkPath}", ex); + } var source = name + (Path.GetFileName(profile) == "Default" ? "" : $" ({Path.GetFileName(profile)})"); - bookmarks.AddRange(LoadBookmarksFromFile(bookmarkPath, source)); + var profileBookmarks = LoadBookmarksFromFile(bookmarkPath, source); + + // Load favicons after loading bookmarks + var faviconDbPath = Path.Combine(profile, "Favicons"); + if (File.Exists(faviconDbPath)) + { + LoadFaviconsFromDb(faviconDbPath, profileBookmarks); + } + + bookmarks.AddRange(profileBookmarks); } return bookmarks; @@ -52,8 +85,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader if (folder.Value.ValueKind != JsonValueKind.Object) continue; - // Fix for Opera. It stores bookmarks slightly different than chrome. See PR and bug report for this change for details. - // If various exceptions start to build up here consider splitting this Loader into multiple separate ones. + // Fix for Opera. It stores bookmarks slightly different than chrome. if (folder.Name == "custom_root") EnumerateRoot(folder.Value, bookmarks, source); else @@ -91,4 +123,108 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } } } + + private void LoadFaviconsFromDb(string dbPath, List bookmarks) + { + try + { + // Use a copy to avoid lock issues with the original file + var tempDbPath = Path.Combine(_faviconCacheDir, $"tempfavicons_{Guid.NewGuid()}.db"); + + try + { + File.Copy(dbPath, tempDbPath, true); + } + catch (Exception ex) + { + Log.Exception($"Failed to copy favicon DB: {dbPath}", ex); + return; + } + + try + { + using var connection = new SQLiteConnection($"Data Source={tempDbPath};Version=3;Read Only=True;"); + connection.Open(); + + foreach (var bookmark in bookmarks) + { + try + { + var url = bookmark.Url; + if (string.IsNullOrEmpty(url)) continue; + + // Extract domain from URL + if (!Uri.TryCreate(url, UriKind.Absolute, out Uri uri)) + continue; + + var domain = uri.Host; + + using var cmd = connection.CreateCommand(); + cmd.CommandText = @" + SELECT f.id, b.image_data + FROM favicons f + JOIN favicon_bitmaps b ON f.id = b.icon_id + JOIN icon_mapping m ON f.id = m.icon_id + WHERE m.page_url LIKE @url + ORDER BY b.width DESC + LIMIT 1"; + + cmd.Parameters.AddWithValue("@url", $"%{domain}%"); + + using var reader = cmd.ExecuteReader(); + if (reader.Read() && !reader.IsDBNull(1)) + { + var iconId = reader.GetInt64(0).ToString(); + var imageData = (byte[])reader["image_data"]; + + if (imageData != null && imageData.Length > 0) + { + var faviconPath = Path.Combine(_faviconCacheDir, $"{domain}_{iconId}.png"); + if (!File.Exists(faviconPath)) + { + SaveBitmapData(imageData, faviconPath); + } + bookmark.FaviconPath = faviconPath; + } + } + } + catch (Exception ex) + { + Log.Exception($"Failed to extract bookmark favicon: {bookmark.Url}", ex); + } + } + } + catch (Exception ex) + { + Log.Exception($"Failed to connect to SQLite: {tempDbPath}", ex); + } + + // Delete temporary file + try { File.Delete(tempDbPath); } catch { /* Ignore */ } + } + catch (Exception ex) + { + Log.Exception($"Failed to load favicon DB: {dbPath}", ex); + } + } + + private void SaveBitmapData(byte[] imageData, string outputPath) + { + try + { + using var ms = new MemoryStream(imageData); + using var bitmap = SKBitmap.Decode(ms); + if (bitmap != null) + { + using var image = SKImage.FromBitmap(bitmap); + using var data = image.Encode(SKEncodedImageFormat.Png, 100); + using var fs = File.OpenWrite(outputPath); + data.SaveTo(fs); + } + } + catch (Exception ex) + { + Log.Exception($"Failed to save image: {outputPath}", ex); + } + } } diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 35ad32fb3..84c343707 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -4,13 +4,26 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Flow.Launcher.Infrastructure.Logger; +using SkiaSharp; namespace Flow.Launcher.Plugin.BrowserBookmark; public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader { + private readonly string _faviconCacheDir; + + protected FirefoxBookmarkLoaderBase() + { + _faviconCacheDir = Path.Combine( + Path.GetDirectoryName(typeof(FirefoxBookmarkLoaderBase).Assembly.Location), + "FaviconCache"); + Directory.CreateDirectory(_faviconCacheDir); + } + public abstract List GetBookmarks(); + // Updated query - removed favicon_id column private const string QueryAllBookmarks = """ SELECT moz_places.url, moz_bookmarks.title FROM moz_places @@ -20,36 +33,161 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader ORDER BY moz_places.visit_count DESC """; - private const string DbPathFormat = "Data Source ={0}"; + private const string DbPathFormat = "Data Source={0}"; - protected static List GetBookmarksFromPath(string placesPath) + protected List GetBookmarksFromPath(string placesPath) { - // Return empty list if the places.sqlite file cannot be found + // Variable to store bookmark list + var bookmarks = new List(); + + // Return empty list if places.sqlite file doesn't exist if (string.IsNullOrEmpty(placesPath) || !File.Exists(placesPath)) - return new List(); + return bookmarks; - Main.RegisterBookmarkFile(placesPath); + try + { + // Try to register file monitoring + try + { + Main.RegisterBookmarkFile(placesPath); + } + catch (Exception ex) + { + Log.Exception($"Failed to register Firefox bookmark file monitoring: {placesPath}", ex); + } - // create the connection string and init the connection - string dbPath = string.Format(DbPathFormat, placesPath); - using var dbConnection = new SqliteConnection(dbPath); - // Open connection to the database file and execute the query - dbConnection.Open(); - var reader = new SqliteCommand(QueryAllBookmarks, dbConnection).ExecuteReader(); + // Use a copy to avoid lock issues with the original file + var tempDbPath = Path.Combine(_faviconCacheDir, $"tempplaces_{Guid.NewGuid()}.sqlite"); + File.Copy(placesPath, tempDbPath, true); - // return results in List format - return reader - .Select( - x => new Bookmark( - x["title"] is DBNull ? string.Empty : x["title"].ToString(), - x["url"].ToString() + // Connect to database and execute query + string dbPath = string.Format(DbPathFormat, tempDbPath); + using var dbConnection = new SqliteConnection(dbPath); + dbConnection.Open(); + var reader = new SqliteCommand(QueryAllBookmarks, dbConnection).ExecuteReader(); + + // Create bookmark list + bookmarks = reader + .Select( + x => new Bookmark( + x["title"] is DBNull ? string.Empty : x["title"].ToString(), + x["url"].ToString(), + "Firefox" + ) ) - ) - .ToList(); + .ToList(); + + // Path to favicon database + var faviconDbPath = Path.Combine(Path.GetDirectoryName(placesPath), "favicons.sqlite"); + if (File.Exists(faviconDbPath)) + { + LoadFaviconsFromDb(faviconDbPath, bookmarks); + } + + // Delete temporary file + try { File.Delete(tempDbPath); } catch { /* Ignore */ } + } + catch (Exception ex) + { + Log.Exception($"Failed to load Firefox bookmarks: {placesPath}", ex); + } + + return bookmarks; + } + + private void LoadFaviconsFromDb(string faviconDbPath, List bookmarks) + { + try + { + // Use a copy to avoid lock issues with the original file + var tempDbPath = Path.Combine(_faviconCacheDir, $"tempfavicons_{Guid.NewGuid()}.sqlite"); + File.Copy(faviconDbPath, tempDbPath, true); + + string dbPath = string.Format(DbPathFormat, tempDbPath); + using var connection = new SqliteConnection(dbPath); + connection.Open(); + + // Get favicons based on bookmark URLs + foreach (var bookmark in bookmarks) + { + try + { + if (string.IsNullOrEmpty(bookmark.Url)) + continue; + + // Extract domain from URL + if (!Uri.TryCreate(bookmark.Url, UriKind.Absolute, out Uri uri)) + continue; + + var domain = uri.Host; + + // Query for latest Firefox version favicon structure + using var cmd = connection.CreateCommand(); + cmd.CommandText = @" + SELECT i.data + FROM moz_icons i + JOIN moz_icons_to_pages ip ON i.id = ip.icon_id + JOIN moz_pages_w_icons p ON ip.page_id = p.id + WHERE p.page_url LIKE @url + AND i.data IS NOT NULL + ORDER BY i.width DESC -- Select largest icon available + LIMIT 1"; + + cmd.Parameters.AddWithValue("@url", $"%{domain}%"); + + using var reader = cmd.ExecuteReader(); + if (reader.Read() && !reader.IsDBNull(0)) + { + var imageData = (byte[])reader["data"]; + + if (imageData != null && imageData.Length > 0) + { + var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.png"); + + if (!File.Exists(faviconPath)) + { + SaveBitmapData(imageData, faviconPath); + } + bookmark.FaviconPath = faviconPath; + } + } + } + catch (Exception ex) + { + Log.Exception($"Failed to extract Firefox favicon: {bookmark.Url}", ex); + } + } + + // Delete temporary file + try { File.Delete(tempDbPath); } catch { /* Ignore */ } + } + catch (Exception ex) + { + Log.Exception($"Failed to load Firefox favicon DB: {faviconDbPath}", ex); + } + } + + private void SaveBitmapData(byte[] imageData, string outputPath) + { + try + { + using var ms = new MemoryStream(imageData); + using var bitmap = SKBitmap.Decode(ms); + if (bitmap != null) + { + using var image = SKImage.FromBitmap(bitmap); + using var data = image.Encode(SKEncodedImageFormat.Png, 100); + using var fs = File.OpenWrite(outputPath); + data.SaveTo(fs); + } + } + catch (Exception ex) + { + Log.Exception($"Failed to save image: {outputPath}", ex); + } } } - public class FirefoxBookmarkLoader : FirefoxBookmarkLoaderBase { /// @@ -77,33 +215,6 @@ public class FirefoxBookmarkLoader : FirefoxBookmarkLoaderBase using var sReader = new StreamReader(profileIni); var ini = sReader.ReadToEnd(); - /* - Current profiles.ini structure example as of Firefox version 69.0.1 - - [Install736426B0AF4A39CB] - Default=Profiles/7789f565.default-release <== this is the default profile this plugin will get the bookmarks from. When opened Firefox will load the default profile - Locked=1 - - [Profile2] - Name=newblahprofile - IsRelative=0 - Path=C:\t6h2yuq8.newblahprofile <== Note this is a custom location path for the profile user can set, we need to cater for this in code. - - [Profile1] - Name=default - IsRelative=1 - Path=Profiles/cydum7q4.default - Default=1 - - [Profile0] - Name=default-release - IsRelative=1 - Path=Profiles/7789f565.default-release - - [General] - StartWithLastProfile=1 - Version=2 - */ var lines = ini.Split("\r\n").ToList(); var defaultProfileFolderNameRaw = lines.FirstOrDefault(x => x.Contains("Default=") && x != "Default=1") ?? string.Empty; diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index b4e42fbcd..4ac1e68b6 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -96,6 +96,9 @@ + + + diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index a48d70f2d..9d9b9e505 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -68,7 +68,9 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex { Title = c.Name, SubTitle = c.Url, - IcoPath = @"Images\bookmark.png", + IcoPath = !string.IsNullOrEmpty(c.FaviconPath) && File.Exists(c.FaviconPath) + ? c.FaviconPath + : @"Images\bookmark.png", Score = BookmarkLoader.MatchProgram(c, param).Score, Action = _ => { @@ -90,7 +92,9 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex { Title = c.Name, SubTitle = c.Url, - IcoPath = @"Images\bookmark.png", + IcoPath = !string.IsNullOrEmpty(c.FaviconPath) && File.Exists(c.FaviconPath) + ? c.FaviconPath + : @"Images\bookmark.png", Score = 5, Action = _ => { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/Bookmark.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/Bookmark.cs index c738da389..caab16b65 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/Bookmark.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Models/Bookmark.cs @@ -18,4 +18,5 @@ public record Bookmark(string Name, string Url, string Source = "") } public List CustomBrowsers { get; set; } = new(); + public string FaviconPath { get; set; } = string.Empty; } diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj index 1b985acf9..0bac1040e 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj @@ -63,6 +63,7 @@ + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj index 549217027..5b326b524 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -46,6 +46,7 @@ + diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj index 21d964c11..bb23eeed8 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj @@ -56,5 +56,9 @@ PreserveNewest + + + + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj index b438305d6..f3f5f268b 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj @@ -37,4 +37,8 @@ PreserveNewest + + + + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj index 4e216b7b2..628e349c4 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj @@ -55,6 +55,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj index 99c1a12e9..ff538828a 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj +++ b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj @@ -69,6 +69,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj index 8f443214b..deef21944 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj +++ b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj @@ -60,6 +60,7 @@ + diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj index 266c24170..f59d596c8 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj +++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj @@ -64,5 +64,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj index 6d338733e..ec0d3c1ca 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj +++ b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj @@ -56,4 +56,8 @@ + + + + diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj index 55d69d526..5500096cd 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj @@ -56,4 +56,8 @@ + + + + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Flow.Launcher.Plugin.WindowsSettings.csproj b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Flow.Launcher.Plugin.WindowsSettings.csproj index 73fcd9f83..512665753 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Flow.Launcher.Plugin.WindowsSettings.csproj +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Flow.Launcher.Plugin.WindowsSettings.csproj @@ -68,5 +68,8 @@ + + + From 1f6d7713cdbcc122d698502b13574d0f3d1d8d95 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 20 Mar 2025 09:48:32 +0800 Subject: [PATCH 002/125] Remove useless NuGet package & Downgrade System.Drawing.Common package --- Flow.Launcher.Core/Flow.Launcher.Core.csproj | 1 - .../Flow.Launcher.Infrastructure.csproj | 1 - .../Flow.Launcher.Plugin.csproj | 1 - Flow.Launcher.Test/Flow.Launcher.Test.csproj | 1 - Flow.Launcher/Flow.Launcher.csproj | 1 - ...low.Launcher.Plugin.BrowserBookmark.csproj | 36 ++----------------- .../Flow.Launcher.Plugin.Calculator.csproj | 1 - .../Flow.Launcher.Plugin.Explorer.csproj | 1 - ...low.Launcher.Plugin.PluginIndicator.csproj | 4 --- ...Flow.Launcher.Plugin.PluginsManager.csproj | 4 --- .../Flow.Launcher.Plugin.ProcessKiller.csproj | 1 - .../Flow.Launcher.Plugin.Program.csproj | 1 - .../Flow.Launcher.Plugin.Shell.csproj | 1 - .../Flow.Launcher.Plugin.Sys.csproj | 1 - .../Flow.Launcher.Plugin.Url.csproj | 4 --- .../Flow.Launcher.Plugin.WebSearch.csproj | 4 --- ...low.Launcher.Plugin.WindowsSettings.csproj | 3 -- 17 files changed, 3 insertions(+), 63 deletions(-) diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj index d10a0313d..e9f199d00 100644 --- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj +++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj @@ -57,7 +57,6 @@ - diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index ae94afdab..b91da7114 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -67,7 +67,6 @@ - diff --git a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj index 027fac7eb..1472813b8 100644 --- a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj +++ b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj @@ -77,7 +77,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/Flow.Launcher.Test/Flow.Launcher.Test.csproj b/Flow.Launcher.Test/Flow.Launcher.Test.csproj index 98f25a5f4..0241a374e 100644 --- a/Flow.Launcher.Test/Flow.Launcher.Test.csproj +++ b/Flow.Launcher.Test/Flow.Launcher.Test.csproj @@ -55,7 +55,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - \ No newline at end of file diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 0a792ef72..1e305d3d9 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -104,7 +104,6 @@ - diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 4ac1e68b6..09026200c 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -37,41 +37,11 @@ - + - + @@ -98,7 +68,7 @@ - + diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj index 0bac1040e..1b985acf9 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj @@ -63,7 +63,6 @@ - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj index 5b326b524..549217027 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -46,7 +46,6 @@ - diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj index bb23eeed8..21d964c11 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj @@ -56,9 +56,5 @@ PreserveNewest - - - - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj index f3f5f268b..b438305d6 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj @@ -37,8 +37,4 @@ PreserveNewest - - - - diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj index 628e349c4..4e216b7b2 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj @@ -55,7 +55,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj index ff538828a..99c1a12e9 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj +++ b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj @@ -69,7 +69,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj index deef21944..8f443214b 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj +++ b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj @@ -60,7 +60,6 @@ - diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj index f59d596c8..266c24170 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj +++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj @@ -64,6 +64,5 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj index ec0d3c1ca..6d338733e 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj +++ b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj @@ -56,8 +56,4 @@ - - - - diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj index 5500096cd..55d69d526 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj @@ -56,8 +56,4 @@ - - - - \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Flow.Launcher.Plugin.WindowsSettings.csproj b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Flow.Launcher.Plugin.WindowsSettings.csproj index 512665753..73fcd9f83 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Flow.Launcher.Plugin.WindowsSettings.csproj +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Flow.Launcher.Plugin.WindowsSettings.csproj @@ -68,8 +68,5 @@ - - - From f6740bce59a8098117d53dbd183dad0010dfebaf Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 20 Mar 2025 09:53:00 +0800 Subject: [PATCH 003/125] Revert style --- ...low.Launcher.Plugin.BrowserBookmark.csproj | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 09026200c..16f3f475d 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -37,11 +37,41 @@ - + - + From cab0cb8e5a2ffd55ea4839430405b8f78828e438 Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 20 Mar 2025 14:40:59 +0900 Subject: [PATCH 004/125] Add SVG favicon support --- .../ChromiumBookmarkLoader.cs | 57 ++++++++++++++----- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index acf863bf0..12b00375a 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -161,13 +161,13 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader using var cmd = connection.CreateCommand(); cmd.CommandText = @" - SELECT f.id, b.image_data - FROM favicons f - JOIN favicon_bitmaps b ON f.id = b.icon_id - JOIN icon_mapping m ON f.id = m.icon_id - WHERE m.page_url LIKE @url - ORDER BY b.width DESC - LIMIT 1"; + SELECT f.id, b.image_data + FROM favicons f + JOIN favicon_bitmaps b ON f.id = b.icon_id + JOIN icon_mapping m ON f.id = m.icon_id + WHERE m.page_url LIKE @url + ORDER BY b.width DESC + LIMIT 1"; cmd.Parameters.AddWithValue("@url", $"%{domain}%"); @@ -212,14 +212,29 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader { try { - using var ms = new MemoryStream(imageData); - using var bitmap = SKBitmap.Decode(ms); - if (bitmap != null) + // SVG 파일 시그니처 확인 (SVG XML 헤더 또는 특수 마커 검사) + bool isSvg = IsSvgData(imageData); + + if (isSvg) { - using var image = SKImage.FromBitmap(bitmap); - using var data = image.Encode(SKEncodedImageFormat.Png, 100); - using var fs = File.OpenWrite(outputPath); - data.SaveTo(fs); + // SVG 데이터는 있는 그대로 저장 (.svg 확장자 사용) + string svgOutputPath = Path.ChangeExtension(outputPath, ".svg"); + File.WriteAllBytes(svgOutputPath, imageData); + // 원래 경로 대신 SVG 경로를 반환하도록 outputPath 변수를 업데이트 + File.Copy(svgOutputPath, outputPath, true); + } + else + { + // 기존 비트맵 처리 코드 + using var ms = new MemoryStream(imageData); + using var bitmap = SKBitmap.Decode(ms); + if (bitmap != null) + { + using var image = SKImage.FromBitmap(bitmap); + using var data = image.Encode(SKEncodedImageFormat.Png, 100); + using var fs = File.OpenWrite(outputPath); + data.SaveTo(fs); + } } } catch (Exception ex) @@ -227,4 +242,18 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader Log.Exception($"Failed to save image: {outputPath}", ex); } } + + private bool IsSvgData(byte[] data) + { + if (data == null || data.Length < 5) + return false; + + // SVG 파일 시그니처 확인 + // ASCII로 시작하는 SVG XML 헤더 확인 + string header = System.Text.Encoding.ASCII.GetString(data, 0, Math.Min(data.Length, 200)).ToLower(); + + return header.Contains(" Date: Thu, 20 Mar 2025 15:58:30 +0900 Subject: [PATCH 005/125] Added SVG for firefox --- .../FirefoxBookmarkLoader.cs | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 84c343707..e638fa825 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -167,18 +167,47 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } } + private bool IsSvgData(byte[] data) + { + if (data == null || data.Length < 5) + return false; + + // SVG 파일 시그니처 확인 + // ASCII로 시작하는 SVG XML 헤더 확인 + string header = System.Text.Encoding.ASCII.GetString(data, 0, Math.Min(data.Length, 200)).ToLower(); + + return header.Contains(" Date: Thu, 20 Mar 2025 13:16:46 +0600 Subject: [PATCH 006/125] Revert "Add SVG favicon support" This reverts commit cab0cb8e5a2ffd55ea4839430405b8f78828e438. --- .../ChromiumBookmarkLoader.cs | 57 +++++-------------- 1 file changed, 14 insertions(+), 43 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 12b00375a..acf863bf0 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -161,13 +161,13 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader using var cmd = connection.CreateCommand(); cmd.CommandText = @" - SELECT f.id, b.image_data - FROM favicons f - JOIN favicon_bitmaps b ON f.id = b.icon_id - JOIN icon_mapping m ON f.id = m.icon_id - WHERE m.page_url LIKE @url - ORDER BY b.width DESC - LIMIT 1"; + SELECT f.id, b.image_data + FROM favicons f + JOIN favicon_bitmaps b ON f.id = b.icon_id + JOIN icon_mapping m ON f.id = m.icon_id + WHERE m.page_url LIKE @url + ORDER BY b.width DESC + LIMIT 1"; cmd.Parameters.AddWithValue("@url", $"%{domain}%"); @@ -212,29 +212,14 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader { try { - // SVG 파일 시그니처 확인 (SVG XML 헤더 또는 특수 마커 검사) - bool isSvg = IsSvgData(imageData); - - if (isSvg) + using var ms = new MemoryStream(imageData); + using var bitmap = SKBitmap.Decode(ms); + if (bitmap != null) { - // SVG 데이터는 있는 그대로 저장 (.svg 확장자 사용) - string svgOutputPath = Path.ChangeExtension(outputPath, ".svg"); - File.WriteAllBytes(svgOutputPath, imageData); - // 원래 경로 대신 SVG 경로를 반환하도록 outputPath 변수를 업데이트 - File.Copy(svgOutputPath, outputPath, true); - } - else - { - // 기존 비트맵 처리 코드 - using var ms = new MemoryStream(imageData); - using var bitmap = SKBitmap.Decode(ms); - if (bitmap != null) - { - using var image = SKImage.FromBitmap(bitmap); - using var data = image.Encode(SKEncodedImageFormat.Png, 100); - using var fs = File.OpenWrite(outputPath); - data.SaveTo(fs); - } + using var image = SKImage.FromBitmap(bitmap); + using var data = image.Encode(SKEncodedImageFormat.Png, 100); + using var fs = File.OpenWrite(outputPath); + data.SaveTo(fs); } } catch (Exception ex) @@ -242,18 +227,4 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader Log.Exception($"Failed to save image: {outputPath}", ex); } } - - private bool IsSvgData(byte[] data) - { - if (data == null || data.Length < 5) - return false; - - // SVG 파일 시그니처 확인 - // ASCII로 시작하는 SVG XML 헤더 확인 - string header = System.Text.Encoding.ASCII.GetString(data, 0, Math.Min(data.Length, 200)).ToLower(); - - return header.Contains(" Date: Thu, 20 Mar 2025 15:35:16 +0800 Subject: [PATCH 007/125] Adjust code format --- .../Flow.Launcher.Plugin.BrowserBookmark/Main.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index 9d9b9e505..3acf94bf6 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -58,7 +58,6 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex // Should top results be returned? (true if no search parameters have been passed) var topResults = string.IsNullOrEmpty(param); - if (!topResults) { // Since we mixed chrome and firefox bookmarks, we should order them again @@ -68,9 +67,9 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex { Title = c.Name, SubTitle = c.Url, - IcoPath = !string.IsNullOrEmpty(c.FaviconPath) && File.Exists(c.FaviconPath) - ? c.FaviconPath - : @"Images\bookmark.png", + IcoPath = !string.IsNullOrEmpty(c.FaviconPath) && File.Exists(c.FaviconPath) + ? c.FaviconPath + : @"Images\bookmark.png", Score = BookmarkLoader.MatchProgram(c, param).Score, Action = _ => { @@ -92,9 +91,9 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex { Title = c.Name, SubTitle = c.Url, - IcoPath = !string.IsNullOrEmpty(c.FaviconPath) && File.Exists(c.FaviconPath) - ? c.FaviconPath - : @"Images\bookmark.png", + IcoPath = !string.IsNullOrEmpty(c.FaviconPath) && File.Exists(c.FaviconPath) + ? c.FaviconPath + : @"Images\bookmark.png", Score = 5, Action = _ => { @@ -108,7 +107,6 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex } } - private static Channel _refreshQueue = Channel.CreateBounded(1); private static SemaphoreSlim _fileMonitorSemaphore = new(1, 1); From d2c185ee9205cb0ba5f0361395fbd995ff67697b Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Thu, 20 Mar 2025 14:03:08 +0600 Subject: [PATCH 008/125] Remove unnecessary dependencies --- .../ChromiumBookmarkLoader.cs | 15 ++------- .../FirefoxBookmarkLoader.cs | 33 +++---------------- ...low.Launcher.Plugin.BrowserBookmark.csproj | 3 -- 3 files changed, 8 insertions(+), 43 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index acf863bf0..1198444bb 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -4,8 +4,7 @@ using System.IO; using System.Text.Json; using Flow.Launcher.Infrastructure.Logger; using System; -using System.Data.SQLite; -using SkiaSharp; +using Microsoft.Data.Sqlite; namespace Flow.Launcher.Plugin.BrowserBookmark; @@ -143,7 +142,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader try { - using var connection = new SQLiteConnection($"Data Source={tempDbPath};Version=3;Read Only=True;"); + using var connection = new SqliteConnection($"Data Source={tempDbPath}"); connection.Open(); foreach (var bookmark in bookmarks) @@ -212,15 +211,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader { try { - using var ms = new MemoryStream(imageData); - using var bitmap = SKBitmap.Decode(ms); - if (bitmap != null) - { - using var image = SKImage.FromBitmap(bitmap); - using var data = image.Encode(SKEncodedImageFormat.Png, 100); - using var fs = File.OpenWrite(outputPath); - data.SaveTo(fs); - } + File.WriteAllBytes(outputPath, imageData); } catch (Exception ex) { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index e638fa825..134524b6e 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Flow.Launcher.Infrastructure.Logger; -using SkiaSharp; namespace Flow.Launcher.Plugin.BrowserBookmark; @@ -142,7 +141,8 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader if (imageData != null && imageData.Length > 0) { - var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.png"); + var ext = IsSvgData(imageData) ? "svg" : "png"; + var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.{ext}"); if (!File.Exists(faviconPath)) { @@ -171,12 +171,12 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader { if (data == null || data.Length < 5) return false; - + // SVG 파일 시그니처 확인 // ASCII로 시작하는 SVG XML 헤더 확인 string header = System.Text.Encoding.ASCII.GetString(data, 0, Math.Min(data.Length, 200)).ToLower(); - return header.Contains(" - - - From 977a8f8c47f608ed7ba23f240610fd32e664a92c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 20 Mar 2025 16:03:41 +0800 Subject: [PATCH 009/125] Log exception when deleting failed --- .../ChromiumBookmarkLoader.cs | 9 ++++++++- .../FirefoxBookmarkLoader.cs | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index acf863bf0..d1551c598 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -200,7 +200,14 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } // Delete temporary file - try { File.Delete(tempDbPath); } catch { /* Ignore */ } + try + { + File.Delete(tempDbPath); + } + catch (Exception ex) + { + Log.Exception($"Failed to delete temporary favicon DB: {tempDbPath}", ex); + } } catch (Exception ex) { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index e638fa825..59fca63ce 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -85,7 +85,14 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } // Delete temporary file - try { File.Delete(tempDbPath); } catch { /* Ignore */ } + try + { + File.Delete(tempDbPath); + } + catch (Exception ex) + { + Log.Exception($"Failed to delete temporary favicon DB: {tempDbPath}", ex); + } } catch (Exception ex) { @@ -159,7 +166,14 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } // Delete temporary file - try { File.Delete(tempDbPath); } catch { /* Ignore */ } + try + { + File.Delete(tempDbPath); + } + catch (Exception ex) + { + Log.Exception($"Failed to delete temporary favicon DB: {tempDbPath}", ex); + } } catch (Exception ex) { From a87211bfb494a26dfdd414522c622f1cd04a89c5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 20 Mar 2025 16:11:22 +0800 Subject: [PATCH 010/125] Fix sqlite file lock issue & Add static --- .../ChromiumBookmarkLoader.cs | 10 ++++++---- .../FirefoxBookmarkLoader.cs | 10 +++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 83f794f5d..7aabc4190 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -63,7 +63,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader return bookmarks; } - protected List LoadBookmarksFromFile(string path, string source) + protected static List LoadBookmarksFromFile(string path, string source) { var bookmarks = new List(); @@ -77,7 +77,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader return bookmarks; } - private void EnumerateRoot(JsonElement rootElement, ICollection bookmarks, string source) + private static void EnumerateRoot(JsonElement rootElement, ICollection bookmarks, string source) { foreach (var folder in rootElement.EnumerateObject()) { @@ -92,7 +92,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } } - private void EnumerateFolderBookmark(JsonElement folderElement, ICollection bookmarks, + private static void EnumerateFolderBookmark(JsonElement folderElement, ICollection bookmarks, string source) { if (!folderElement.TryGetProperty("children", out var childrenElement)) @@ -201,6 +201,8 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader // Delete temporary file try { + // https://github.com/dotnet/efcore/issues/26580 + SqliteConnection.ClearAllPools(); File.Delete(tempDbPath); } catch (Exception ex) @@ -214,7 +216,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } } - private void SaveBitmapData(byte[] imageData, string outputPath) + private static void SaveBitmapData(byte[] imageData, string outputPath) { try { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index df2fc028c..187b77224 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -86,6 +86,8 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader // Delete temporary file try { + // https://github.com/dotnet/efcore/issues/26580 + SqliteConnection.ClearAllPools(); File.Delete(tempDbPath); } catch (Exception ex) @@ -168,6 +170,8 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader // Delete temporary file try { + // https://github.com/dotnet/efcore/issues/26580 + SqliteConnection.ClearAllPools(); File.Delete(tempDbPath); } catch (Exception ex) @@ -181,7 +185,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } } - private bool IsSvgData(byte[] data) + private static bool IsSvgData(byte[] data) { if (data == null || data.Length < 5) return false; @@ -195,7 +199,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader header.Contains("image/svg+xml"); } - private void SaveBitmapData(byte[] imageData, string outputPath) + private static void SaveBitmapData(byte[] imageData, string outputPath) { try { @@ -221,7 +225,7 @@ public class FirefoxBookmarkLoader : FirefoxBookmarkLoaderBase /// /// Path to places.sqlite /// - private string PlacesPath + private static string PlacesPath { get { From 2b08ad65a0424c60b74072afe0a874a2b8a8588f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 20 Mar 2025 16:21:15 +0800 Subject: [PATCH 011/125] Only clear pool for one connection --- .../ChromiumBookmarkLoader.cs | 5 +++-- .../FirefoxBookmarkLoader.cs | 10 ++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 7aabc4190..8fb04d252 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -192,6 +192,9 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader Log.Exception($"Failed to extract bookmark favicon: {bookmark.Url}", ex); } } + + // https://github.com/dotnet/efcore/issues/26580 + SqliteConnection.ClearPool(connection); } catch (Exception ex) { @@ -201,8 +204,6 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader // Delete temporary file try { - // https://github.com/dotnet/efcore/issues/26580 - SqliteConnection.ClearAllPools(); File.Delete(tempDbPath); } catch (Exception ex) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 187b77224..1b0189215 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -83,11 +83,12 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader LoadFaviconsFromDb(faviconDbPath, bookmarks); } + // https://github.com/dotnet/efcore/issues/26580 + SqliteConnection.ClearPool(dbConnection); + // Delete temporary file try { - // https://github.com/dotnet/efcore/issues/26580 - SqliteConnection.ClearAllPools(); File.Delete(tempDbPath); } catch (Exception ex) @@ -165,13 +166,14 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader { Log.Exception($"Failed to extract Firefox favicon: {bookmark.Url}", ex); } + + // https://github.com/dotnet/efcore/issues/26580 + SqliteConnection.ClearPool(connection); } // Delete temporary file try { - // https://github.com/dotnet/efcore/issues/26580 - SqliteConnection.ClearAllPools(); File.Delete(tempDbPath); } catch (Exception ex) From 0c162b1cbe59eeca0c0bd53bc3cefd21dbc7a166 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 20 Mar 2025 16:24:41 +0800 Subject: [PATCH 012/125] Fix call position --- .../FirefoxBookmarkLoader.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 1b0189215..da7780acb 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -166,11 +166,11 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader { Log.Exception($"Failed to extract Firefox favicon: {bookmark.Url}", ex); } - - // https://github.com/dotnet/efcore/issues/26580 - SqliteConnection.ClearPool(connection); } + // https://github.com/dotnet/efcore/issues/26580 + SqliteConnection.ClearPool(connection); + // Delete temporary file try { From 92ef2c76c7d48f4aa3092b323ddffcb33abf7fd6 Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Thu, 20 Mar 2025 14:43:38 +0600 Subject: [PATCH 013/125] Reduce nesting --- .../ChromiumBookmarkLoader.cs | 26 ++++++++--------- .../FirefoxBookmarkLoader.cs | 29 ++++++++++--------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 8fb04d252..aed13c858 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -171,21 +171,21 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader cmd.Parameters.AddWithValue("@url", $"%{domain}%"); using var reader = cmd.ExecuteReader(); - if (reader.Read() && !reader.IsDBNull(1)) - { - var iconId = reader.GetInt64(0).ToString(); - var imageData = (byte[])reader["image_data"]; + if (!reader.Read() || reader.IsDBNull(1)) + continue; - if (imageData != null && imageData.Length > 0) - { - var faviconPath = Path.Combine(_faviconCacheDir, $"{domain}_{iconId}.png"); - if (!File.Exists(faviconPath)) - { - SaveBitmapData(imageData, faviconPath); - } - bookmark.FaviconPath = faviconPath; - } + var iconId = reader.GetInt64(0).ToString(); + var imageData = (byte[])reader["image_data"]; + + if (imageData is not { Length: > 0 }) + continue; + + var faviconPath = Path.Combine(_faviconCacheDir, $"{domain}_{iconId}.png"); + if (!File.Exists(faviconPath)) + { + SaveBitmapData(imageData, faviconPath); } + bookmark.FaviconPath = faviconPath; } catch (Exception ex) { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index da7780acb..7851214e9 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -145,22 +145,23 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader cmd.Parameters.AddWithValue("@url", $"%{domain}%"); using var reader = cmd.ExecuteReader(); - if (reader.Read() && !reader.IsDBNull(0)) + if (!reader.Read() || reader.IsDBNull(0)) + continue; + + var imageData = (byte[])reader["data"]; + + if (imageData is not { Length: > 0 }) + continue; + + var ext = IsSvgData(imageData) ? "svg" : "png"; + var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.{ext}"); + + if (!File.Exists(faviconPath)) { - var imageData = (byte[])reader["data"]; - - if (imageData != null && imageData.Length > 0) - { - var ext = IsSvgData(imageData) ? "svg" : "png"; - var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.{ext}"); - - if (!File.Exists(faviconPath)) - { - SaveBitmapData(imageData, faviconPath); - } - bookmark.FaviconPath = faviconPath; - } + SaveBitmapData(imageData, faviconPath); } + + bookmark.FaviconPath = faviconPath; } catch (Exception ex) { From a837e8e197d4566cd720dde6d75930372b0c041d Mon Sep 17 00:00:00 2001 From: Yusyuriv Date: Thu, 20 Mar 2025 14:47:50 +0600 Subject: [PATCH 014/125] Close bookmarks db connection before trying to delete the file --- .../ChromiumBookmarkLoader.cs | 1 + .../FirefoxBookmarkLoader.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index aed13c858..d9c4e91d0 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -195,6 +195,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader // https://github.com/dotnet/efcore/issues/26580 SqliteConnection.ClearPool(connection); + connection.Close(); } catch (Exception ex) { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 7851214e9..bf076e0ea 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -85,6 +85,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader // https://github.com/dotnet/efcore/issues/26580 SqliteConnection.ClearPool(dbConnection); + dbConnection.Close(); // Delete temporary file try @@ -171,6 +172,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader // https://github.com/dotnet/efcore/issues/26580 SqliteConnection.ClearPool(connection); + connection.Close(); // Delete temporary file try From 443f17dcef2dfbfa79ec0764ad8482cad2ab3828 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 20 Mar 2025 16:54:14 +0800 Subject: [PATCH 015/125] Code quality --- .../Main.cs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index 3acf94bf6..3ae7cfa1d 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -17,7 +17,7 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex { private static PluginInitContext _context; - private static List _cachedBookmarks = new List(); + private static List _cachedBookmarks = new(); private static Settings _settings; @@ -107,9 +107,9 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex } } - private static Channel _refreshQueue = Channel.CreateBounded(1); + private static readonly Channel _refreshQueue = Channel.CreateBounded(1); - private static SemaphoreSlim _fileMonitorSemaphore = new(1, 1); + private static readonly SemaphoreSlim _fileMonitorSemaphore = new(1, 1); private static async Task MonitorRefreshQueueAsync() { @@ -143,12 +143,13 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex return; } - var watcher = new FileSystemWatcher(directory!); - watcher.Filter = Path.GetFileName(path); - - watcher.NotifyFilter = NotifyFilters.FileName | - NotifyFilters.LastWrite | - NotifyFilters.Size; + var watcher = new FileSystemWatcher(directory!) + { + Filter = Path.GetFileName(path), + NotifyFilter = NotifyFilters.FileName | + NotifyFilters.LastWrite | + NotifyFilters.Size + }; watcher.Changed += static (_, _) => { @@ -197,7 +198,7 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex { return new List() { - new Result + new() { Title = _context.API.GetTranslation("flowlauncher_plugin_browserbookmark_copyurl_title"), SubTitle = _context.API.GetTranslation("flowlauncher_plugin_browserbookmark_copyurl_subtitle"), From dfc9d5b84f91bd7daae082beb93582e4f1aad262 Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 20 Mar 2025 19:11:15 +0900 Subject: [PATCH 016/125] - Add SVG convert for firefox - Add remove cache UI --- .../FirefoxBookmarkLoader.cs | 182 +++++++++++------- ...low.Launcher.Plugin.BrowserBookmark.csproj | 1 + .../Main.cs | 10 + .../Views/SettingsControl.xaml | 4 + .../Views/SettingsControl.xaml.cs | 81 +++++++- 5 files changed, 200 insertions(+), 78 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index bf076e0ea..769407683 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -106,89 +106,131 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } private void LoadFaviconsFromDb(string faviconDbPath, List bookmarks) +{ + try { - try + // Use a copy to avoid lock issues with the original file + var tempDbPath = Path.Combine(_faviconCacheDir, $"tempfavicons_{Guid.NewGuid()}.sqlite"); + File.Copy(faviconDbPath, tempDbPath, true); + + string dbPath = string.Format(DbPathFormat, tempDbPath); + using var connection = new SqliteConnection(dbPath); + connection.Open(); + + // Get favicons based on bookmark URLs + foreach (var bookmark in bookmarks) { - // Use a copy to avoid lock issues with the original file - var tempDbPath = Path.Combine(_faviconCacheDir, $"tempfavicons_{Guid.NewGuid()}.sqlite"); - File.Copy(faviconDbPath, tempDbPath, true); - - string dbPath = string.Format(DbPathFormat, tempDbPath); - using var connection = new SqliteConnection(dbPath); - connection.Open(); - - // Get favicons based on bookmark URLs - foreach (var bookmark in bookmarks) - { - try - { - if (string.IsNullOrEmpty(bookmark.Url)) - continue; - - // Extract domain from URL - if (!Uri.TryCreate(bookmark.Url, UriKind.Absolute, out Uri uri)) - continue; - - var domain = uri.Host; - - // Query for latest Firefox version favicon structure - using var cmd = connection.CreateCommand(); - cmd.CommandText = @" - SELECT i.data - FROM moz_icons i - JOIN moz_icons_to_pages ip ON i.id = ip.icon_id - JOIN moz_pages_w_icons p ON ip.page_id = p.id - WHERE p.page_url LIKE @url - AND i.data IS NOT NULL - ORDER BY i.width DESC -- Select largest icon available - LIMIT 1"; - - cmd.Parameters.AddWithValue("@url", $"%{domain}%"); - - using var reader = cmd.ExecuteReader(); - if (!reader.Read() || reader.IsDBNull(0)) - continue; - - var imageData = (byte[])reader["data"]; - - if (imageData is not { Length: > 0 }) - continue; - - var ext = IsSvgData(imageData) ? "svg" : "png"; - var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.{ext}"); - - if (!File.Exists(faviconPath)) - { - SaveBitmapData(imageData, faviconPath); - } - - bookmark.FaviconPath = faviconPath; - } - catch (Exception ex) - { - Log.Exception($"Failed to extract Firefox favicon: {bookmark.Url}", ex); - } - } - - // https://github.com/dotnet/efcore/issues/26580 - SqliteConnection.ClearPool(connection); - connection.Close(); - - // Delete temporary file try { - File.Delete(tempDbPath); + if (string.IsNullOrEmpty(bookmark.Url)) + continue; + + // Extract domain from URL + if (!Uri.TryCreate(bookmark.Url, UriKind.Absolute, out Uri uri)) + continue; + + var domain = uri.Host; + + // Query for latest Firefox version favicon structure + using var cmd = connection.CreateCommand(); + cmd.CommandText = @" + SELECT i.data + FROM moz_icons i + JOIN moz_icons_to_pages ip ON i.id = ip.icon_id + JOIN moz_pages_w_icons p ON ip.page_id = p.id + WHERE p.page_url LIKE @url + AND i.data IS NOT NULL + ORDER BY i.width DESC -- Select largest icon available + LIMIT 1"; + + cmd.Parameters.AddWithValue("@url", $"%{domain}%"); + + using var reader = cmd.ExecuteReader(); + if (!reader.Read() || reader.IsDBNull(0)) + continue; + + var imageData = (byte[])reader["data"]; + + if (imageData is not { Length: > 0 }) + continue; + + var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.png"); + + if (!File.Exists(faviconPath)) + { + if (IsSvgData(imageData)) + { + // SVG를 PNG로 변환 + var pngData = ConvertSvgToPng(imageData); + if (pngData != null) + { + SaveBitmapData(pngData, faviconPath); + } + else + { + // 변환 실패 시 빈 문자열 설정 (기본 아이콘 사용) + bookmark.FaviconPath = string.Empty; + continue; + } + } + else + { + // PNG는 그대로 저장 + SaveBitmapData(imageData, faviconPath); + } + } + + bookmark.FaviconPath = faviconPath; } catch (Exception ex) { - Log.Exception($"Failed to delete temporary favicon DB: {tempDbPath}", ex); + Log.Exception($"Failed to extract Firefox favicon: {bookmark.Url}", ex); } } + + // https://github.com/dotnet/efcore/issues/26580 + SqliteConnection.ClearPool(connection); + connection.Close(); + + // Delete temporary file + try + { + File.Delete(tempDbPath); + } catch (Exception ex) { - Log.Exception($"Failed to load Firefox favicon DB: {faviconDbPath}", ex); + Log.Exception($"Failed to delete temporary favicon DB: {tempDbPath}", ex); } } + catch (Exception ex) + { + Log.Exception($"Failed to load Firefox favicon DB: {faviconDbPath}", ex); + } +} + +private byte[] ConvertSvgToPng(byte[] svgData) +{ + try + { + using var memoryStream = new MemoryStream(); + // 메모리에 SVG 데이터 로드 + using (var image = new ImageMagick.MagickImage(svgData)) + { + // 적절한 크기로 리사이징 (32x32가 일반적인 파비콘 크기) + image.Resize(32, 32); + // PNG 형식으로 변환하여 메모리 스트림에 저장 + image.Format = ImageMagick.MagickFormat.Png; + image.Write(memoryStream); + } + + return memoryStream.ToArray(); + } + catch (Exception ex) + { + Log.Exception("SVG to PNG conversion failed", ex); + return null; + } +} private static bool IsSvgData(byte[] data) { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index b4e42fbcd..5b54ef026 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -95,6 +95,7 @@ + diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index 3acf94bf6..3cef07fff 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -22,6 +22,16 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex private static Settings _settings; private static bool _initialized = false; + + public static PluginInitContext GetContext() + { + return _context; + } + + public static string GetPluginDirectory() + { + return _context?.CurrentPluginMetadata?.PluginDirectory; + } public void Init(PluginInitContext context) { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml index 014deff03..f1bb242ea 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml @@ -31,6 +31,10 @@ Margin="0,0,15,0" Click="Others_Click" Content="{DynamicResource flowlauncher_plugin_browserbookmark_others}" /> + - + --> + + + + + + + + + + OnContent="{DynamicResource enable}" + Visibility="Collapsed" /> From 5fa244c806c430d35325ae30aa1dc22c5c6c4d40 Mon Sep 17 00:00:00 2001 From: DB p Date: Mon, 31 Mar 2025 22:44:34 +0900 Subject: [PATCH 021/125] Add setting filter --- .../Converters/StringEqualityToVisibilityConverter.cs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs diff --git a/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs b/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs new file mode 100644 index 000000000..4757681bc --- /dev/null +++ b/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs @@ -0,0 +1,6 @@ +namespace Flow.Launcher.Converters; + +public class StringEqualityToVisibilityConverter +{ + +} From 0136c570faf3d8cdf4e7094054a1ed0cd62103c5 Mon Sep 17 00:00:00 2001 From: DB p Date: Mon, 31 Mar 2025 22:44:46 +0900 Subject: [PATCH 022/125] Add Setting Filter --- .../StringEqualityToVisibilityConverter.cs | 23 ++++- .../Controls/InstalledPluginDisplay.xaml | 34 +++++-- .../SettingsPanePluginsViewModel.cs | 69 +++++++++++++++ .../Views/SettingsPanePlugins.xaml | 88 ++++++++++--------- Flow.Launcher/ViewModel/PluginViewModel.cs | 14 ++- 5 files changed, 172 insertions(+), 56 deletions(-) diff --git a/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs b/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs index 4757681bc..4e4453636 100644 --- a/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs +++ b/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs @@ -1,6 +1,23 @@ -namespace Flow.Launcher.Converters; +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; -public class StringEqualityToVisibilityConverter +namespace Flow.Launcher.Converters { - + public class StringEqualityToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null || parameter == null) + return Visibility.Collapsed; + + return value.ToString() == parameter.ToString() ? Visibility.Visible : Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } } diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 74edd2dea..ca9f673d8 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -7,10 +7,14 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:viewModel="clr-namespace:Flow.Launcher.ViewModel" + xmlns:converters="clr-namespace:Flow.Launcher.Converters" d:DataContext="{d:DesignInstance viewModel:PluginViewModel}" d:DesignHeight="300" d:DesignWidth="300" mc:Ignorable="d"> + + + + Visibility="{Binding DataContext.CurrentDisplayMode, + RelativeSource={RelativeSource AncestorType=ListBox}, + Converter={StaticResource StringEqualityToVisibilityConverter}, + ConverterParameter=Priority}"> + Margin="0 0 8 0" + VerticalAlignment="Center" + FontSize="13" + Foreground="{DynamicResource Color08B}" + Text="{DynamicResource priority}" /> + + Visibility="{Binding DataContext.CurrentDisplayMode, + RelativeSource={RelativeSource AncestorType=ListBox}, + Converter={StaticResource StringEqualityToVisibilityConverter}, + ConverterParameter=SearchDelay}"> + - + Visibility="{Binding DataContext.CurrentDisplayMode, + RelativeSource={RelativeSource AncestorType=ListBox}, + Converter={StaticResource StringEqualityToVisibilityConverter}, + ConverterParameter=OnOff}" /> + diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index 3c1aba400..5cd14ba7e 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -14,6 +14,75 @@ public class SettingsPanePluginsViewModel : BaseModel { private readonly Settings _settings; + private bool _isOnOffSelected = true; + public bool IsOnOffSelected + { + get => _isOnOffSelected; + set + { + if (_isOnOffSelected != value) + { + _isOnOffSelected = value; + OnPropertyChanged(nameof(IsOnOffSelected)); + UpdateDisplayMode(); + } + } + } + + private bool _isPrioritySelected; + public bool IsPrioritySelected + { + get => _isPrioritySelected; + set + { + if (_isPrioritySelected != value) + { + _isPrioritySelected = value; + OnPropertyChanged(nameof(IsPrioritySelected)); + UpdateDisplayMode(); + } + } + } + + private bool _isSearchDelaySelected; + public bool IsSearchDelaySelected + { + get => _isSearchDelaySelected; + set + { + if (_isSearchDelaySelected != value) + { + _isSearchDelaySelected = value; + OnPropertyChanged(nameof(IsSearchDelaySelected)); + UpdateDisplayMode(); + } + } + } + + private string _currentDisplayMode = "OnOff"; + public string CurrentDisplayMode + { + get => _currentDisplayMode; + set + { + if (_currentDisplayMode != value) + { + _currentDisplayMode = value; + OnPropertyChanged(nameof(CurrentDisplayMode)); + } + } + } + + private void UpdateDisplayMode() + { + if (IsOnOffSelected) + CurrentDisplayMode = "OnOff"; + else if (IsPrioritySelected) + CurrentDisplayMode = "Priority"; + else if (IsSearchDelaySelected) + CurrentDisplayMode = "SearchDelay"; + } + public SettingsPanePluginsViewModel(Settings settings) { _settings = settings; diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml b/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml index 37079a46f..7580a5591 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml @@ -6,6 +6,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:ui="http://schemas.modernwpf.com/2019" + xmlns:converters="clr-namespace:Flow.Launcher.Converters" xmlns:viewModels="clr-namespace:Flow.Launcher.SettingPages.ViewModels" xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls" Title="Plugins" @@ -17,6 +18,7 @@ mc:Ignorable="d"> + @@ -31,51 +33,51 @@ Style="{StaticResource PageTitle}" Text="{DynamicResource plugins}" TextAlignment="Left" /> - - - - - + Orientation="Horizontal" + HorizontalAlignment="Right" + VerticalAlignment="Center"> + + + + + + + string.Join(Query.ActionKeywordSeparator, PluginPair.Metadata.ActionKeywords); - public int Priority => PluginPair.Metadata.Priority; + //public int Priority => PluginPair.Metadata.Priority; + private int _priority; + public int Priority + { + get => PluginPair.Metadata.Priority; + set + { + if (PluginPair.Metadata.Priority != value) + { + ChangePriority(value); + } + } + } public string SearchDelayTimeText => PluginPair.Metadata.SearchDelayTime == null ? App.API.GetTranslation("default") : App.API.GetTranslation($"SearchDelayTime{PluginPair.Metadata.SearchDelayTime}"); From fb50e6d08f6a31e4e43983867bfff3384acad300 Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 1 Apr 2025 05:03:49 +0900 Subject: [PATCH 023/125] Add search delay control --- Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index ca9f673d8..009644fd6 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -120,9 +120,7 @@ RelativeSource={RelativeSource AncestorType=ListBox}, Converter={StaticResource StringEqualityToVisibilityConverter}, ConverterParameter=SearchDelay}"> - From d77400d39bbe1dbc7ae476326dfce66e3748f93f Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 1 Apr 2025 05:36:24 +0900 Subject: [PATCH 024/125] Add customcontrol for searchdelay --- .../Controls/InstalledPluginDisplay.xaml | 5 +- .../InstalledPluginSearchDelayCombobox.xaml | 39 +++++++++ ...InstalledPluginSearchDelayCombobox.xaml.cs | 84 +++++++++++++++++++ 3 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml create mode 100644 Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml.cs diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 009644fd6..cb1d8dbc4 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -92,7 +92,7 @@ - - diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml new file mode 100644 index 000000000..b379b875f --- /dev/null +++ b/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml @@ -0,0 +1,39 @@ + + + + + + + + \ No newline at end of file diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml.cs b/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml.cs new file mode 100644 index 000000000..649913872 --- /dev/null +++ b/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml.cs @@ -0,0 +1,84 @@ +using System.Collections.Generic; +using System.Windows.Controls; +using Flow.Launcher.Plugin; + +namespace Flow.Launcher.Resources.Controls +{ + public partial class InstalledPluginSearchDelayCombobox + { + public InstalledPluginSearchDelayCombobox() + { + InitializeComponent(); + LoadDelayOptions(); + Loaded += InstalledPluginSearchDelayCombobox_Loaded; + } + + private void InstalledPluginSearchDelayCombobox_Loaded(object sender, System.Windows.RoutedEventArgs e) + { + if (DataContext is ViewModel.PluginViewModel viewModel) + { + // 초기 값 설정 + int currentDelayMs = GetCurrentDelayMs(viewModel); + foreach (DelayOption option in cbDelay.Items) + { + if (option.Value == currentDelayMs) + { + cbDelay.SelectedItem = option; + break; + } + } + } + } + + private int GetCurrentDelayMs(ViewModel.PluginViewModel viewModel) + { + // SearchDelayTime enum 값을 int로 변환 + SearchDelayTime? delayTime = viewModel.PluginPair.Metadata.SearchDelayTime; + if (delayTime.HasValue) + { + return (int)delayTime.Value; + } + return 0; // 기본값 + } + + private void LoadDelayOptions() + { + // 검색 지연 시간 옵션들 (SearchDelayTime enum 값에 맞춰야 함) + var delayOptions = new List + { + new DelayOption { Display = "0 ms", Value = 0 }, + new DelayOption { Display = "50 ms", Value = 50 }, + new DelayOption { Display = "100 ms", Value = 100 }, + new DelayOption { Display = "150 ms", Value = 150 }, + new DelayOption { Display = "200 ms", Value = 200 }, + new DelayOption { Display = "250 ms", Value = 250 }, + new DelayOption { Display = "300 ms", Value = 300 }, + new DelayOption { Display = "350 ms", Value = 350 }, + new DelayOption { Display = "400 ms", Value = 400 }, + new DelayOption { Display = "450 ms", Value = 450 }, + new DelayOption { Display = "500 ms", Value = 500 }, + }; + + cbDelay.ItemsSource = delayOptions; + } + + private void CbDelay_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (DataContext is ViewModel.PluginViewModel viewModel && cbDelay.SelectedItem is DelayOption selectedOption) + { + // int 값을 SearchDelayTime enum으로 변환 + int delayValue = selectedOption.Value; + viewModel.PluginPair.Metadata.SearchDelayTime = (SearchDelayTime)delayValue; + + // 설정 저장 + //How to save? + } + } + } + + public class DelayOption + { + public string Display { get; set; } + public int Value { get; set; } + } +} From 6f0126d3ba3f4ab8c6928141287391602d77cf1f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 11:47:18 +0800 Subject: [PATCH 025/125] Add log error api function for csharp and jsonrpc --- .../Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs | 8 ++++++-- Flow.Launcher.Infrastructure/Logger/Log.cs | 11 ++--------- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 5 +++++ Flow.Launcher/PublicAPIInstance.cs | 3 +++ 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs index 8df2ce9ed..102d0089f 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs @@ -12,7 +12,7 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models { public class JsonRPCPublicAPI { - private IPublicAPI _api; + private readonly IPublicAPI _api; public JsonRPCPublicAPI(IPublicAPI api) { @@ -104,7 +104,6 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models return _api.GetAllPlugins(); } - public MatchResult FuzzySearch(string query, string stringToCompare) { return _api.FuzzySearch(query, stringToCompare); @@ -156,6 +155,11 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models _api.LogWarn(className, message, methodName); } + public void LogError(string className, string message, [CallerMemberName] string methodName = "") + { + _api.LogError(className, message, methodName); + } + public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null) { _api.OpenDirectory(DirectoryPath, FileNameOrFilePath); diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs index 9f5d6725e..9e1173f34 100644 --- a/Flow.Launcher.Infrastructure/Logger/Log.cs +++ b/Flow.Launcher.Infrastructure/Logger/Log.cs @@ -1,12 +1,12 @@ using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; +using System.Runtime.ExceptionServices; +using Flow.Launcher.Infrastructure.UserSettings; using NLog; using NLog.Config; using NLog.Targets; -using Flow.Launcher.Infrastructure.UserSettings; using NLog.Targets.Wrappers; -using System.Runtime.ExceptionServices; namespace Flow.Launcher.Infrastructure.Logger { @@ -135,13 +135,6 @@ namespace Flow.Launcher.Infrastructure.Logger return className; } - private static void ExceptionInternal(string classAndMethod, string message, System.Exception e) - { - var logger = LogManager.GetLogger(classAndMethod); - - logger.Error(e, message); - } - private static void LogInternal(string message, LogLevel level) { if (FormatValid(message)) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index f178ebb90..9258e5147 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -227,6 +227,11 @@ namespace Flow.Launcher.Plugin /// void LogWarn(string className, string message, [CallerMemberName] string methodName = ""); + /// + /// Log error message + /// + void LogError(string className, string message, [CallerMemberName] string methodName = ""); + /// /// Log an Exception. Will throw if in debug mode so developer will be aware, /// otherwise logs the eror message. This is the primary logging method used for Flow diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index e19ad2fdc..31307b668 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -187,6 +187,9 @@ namespace Flow.Launcher public void LogWarn(string className, string message, [CallerMemberName] string methodName = "") => Log.Warn(className, message, methodName); + public void LogError(string className, string message, [CallerMemberName] string methodName = "") => + Log.Error(className, message, methodName); + public void LogException(string className, string message, Exception e, [CallerMemberName] string methodName = "") => Log.Exception(className, message, e, methodName); From 1381248e9e71444b56704548167830010f97ac68 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 11:54:18 +0800 Subject: [PATCH 026/125] Adjust code formats --- Flow.Launcher/PublicAPIInstance.cs | 35 ++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 31307b668..2d2713e79 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -11,9 +11,9 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; using CommunityToolkit.Mvvm.DependencyInjection; -using Squirrel; using Flow.Launcher.Core; using Flow.Launcher.Core.Plugin; +using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Http; @@ -27,7 +27,7 @@ using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.ViewModel; using JetBrains.Annotations; -using Flow.Launcher.Core.Resource; +using Squirrel; namespace Flow.Launcher { @@ -78,7 +78,11 @@ namespace Flow.Launcher public bool IsMainWindowVisible() => _mainVM.MainWindowVisibilityStatus; - public event VisibilityChangedEventHandler VisibilityChanged { add => _mainVM.VisibilityChanged += value; remove => _mainVM.VisibilityChanged -= value; } + public event VisibilityChangedEventHandler VisibilityChanged + { + add => _mainVM.VisibilityChanged += value; + remove => _mainVM.VisibilityChanged -= value; + } // Must use Ioc.Default.GetRequiredService() to avoid circular dependency public void CheckForNewUpdate() => _ = Ioc.Default.GetRequiredService().UpdateAppAsync(false); @@ -162,13 +166,14 @@ namespace Flow.Launcher public MatchResult FuzzySearch(string query, string stringToCompare) => StringMatcher.FuzzySearch(query, stringToCompare); - public Task HttpGetStringAsync(string url, CancellationToken token = default) => Http.GetAsync(url, token); + public Task HttpGetStringAsync(string url, CancellationToken token = default) => + Http.GetAsync(url, token); public Task HttpGetStreamAsync(string url, CancellationToken token = default) => Http.GetStreamAsync(url, token); public Task HttpDownloadAsync([NotNull] string url, [NotNull] string filePath, Action reportProgress = null, - CancellationToken token = default) => Http.DownloadAsync(url, filePath, reportProgress, token); + CancellationToken token = default) =>Http.DownloadAsync(url, filePath, reportProgress, token); public void AddActionKeyword(string pluginId, string newActionKeyword) => PluginManager.AddActionKeyword(pluginId, newActionKeyword); @@ -190,8 +195,8 @@ namespace Flow.Launcher public void LogError(string className, string message, [CallerMemberName] string methodName = "") => Log.Error(className, message, methodName); - public void LogException(string className, string message, Exception e, - [CallerMemberName] string methodName = "") => Log.Exception(className, message, e, methodName); + public void LogException(string className, string message, Exception e, [CallerMemberName] string methodName = "") => + Log.Exception(className, message, e, methodName); private readonly ConcurrentDictionary _pluginJsonStorages = new(); @@ -204,7 +209,7 @@ namespace Flow.Launcher var name = value.GetType().GetField("AssemblyName")?.GetValue(value)?.ToString(); if (name == assemblyName) { - _pluginJsonStorages.Remove(key, out var pluginJsonStorage); + _pluginJsonStorages.Remove(key, out var _); } } } @@ -333,17 +338,23 @@ namespace Flow.Launcher private readonly List> _globalKeyboardHandlers = new(); - public void RegisterGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Add(callback); - public void RemoveGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Remove(callback); + public void RegisterGlobalKeyboardCallback(Func callback) => + _globalKeyboardHandlers.Add(callback); + + public void RemoveGlobalKeyboardCallback(Func callback) => + _globalKeyboardHandlers.Remove(callback); public void ReQuery(bool reselect = true) => _mainVM.ReQuery(reselect); public void BackToQueryResults() => _mainVM.BackToQueryResults(); - public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.OK) => + public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", + MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, + MessageBoxResult defaultResult = MessageBoxResult.OK) => MessageBoxEx.Show(messageBoxText, caption, button, icon, defaultResult); - public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress); + public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, + Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress); #endregion From 835e4096c8ec781e6bd319946853060f9de2b493 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 11:56:51 +0800 Subject: [PATCH 027/125] Fix build issue --- Flow.Launcher.Infrastructure/Logger/Log.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs index 9e1173f34..84331ef70 100644 --- a/Flow.Launcher.Infrastructure/Logger/Log.cs +++ b/Flow.Launcher.Infrastructure/Logger/Log.cs @@ -135,6 +135,15 @@ namespace Flow.Launcher.Infrastructure.Logger return className; } +#if !DEBUG + private static void ExceptionInternal(string classAndMethod, string message, System.Exception e) + { + var logger = LogManager.GetLogger(classAndMethod); + + logger.Error(e, message); + } +#endif + private static void LogInternal(string message, LogLevel level) { if (FormatValid(message)) From 24327533c6e165f0cfa02e9a822fcf973c1880df Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 14:16:32 +0800 Subject: [PATCH 028/125] Add plugin json storage --- .../Image/ImageLoader.cs | 1 + .../Storage/BinaryStorage.cs | 62 +++++++++++++++---- .../Storage/PluginBinaryStorage.cs | 15 +++++ .../Storage/PluginJsonStorage.cs | 6 -- 4 files changed, 65 insertions(+), 19 deletions(-) create mode 100644 Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 6f7b1cd90..cca4bd2a4 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -37,6 +37,7 @@ namespace Flow.Launcher.Infrastructure.Image _hashGenerator = new ImageHashGenerator(); var usage = await LoadStorageToConcurrentDictionaryAsync(); + _storage.ClearData(); ImageCache.Initialize(usage); diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs index 5b73faae6..69ac6000b 100644 --- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs @@ -4,6 +4,8 @@ using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using MemoryPack; +#nullable enable + namespace Flow.Launcher.Infrastructure.Storage { /// @@ -15,40 +17,53 @@ namespace Flow.Launcher.Infrastructure.Storage /// public class BinaryStorage { + protected T? Data; + public const string FileSuffix = ".cache"; - // Let the derived class to set the file path - public BinaryStorage(string filename, string directoryPath = null) - { - directoryPath ??= DataLocation.CacheDirectory; - Helper.ValidateDirectory(directoryPath); + protected string FilePath { get; init; } = null!; - FilePath = Path.Combine(directoryPath, $"{filename}{FileSuffix}"); + protected string DirectoryPath { get; init; } = null!; + + // Let the derived class to set the file path + protected BinaryStorage() + { } - public string FilePath { get; } + public BinaryStorage(string filename) + { + DirectoryPath = DataLocation.CacheDirectory; + Helper.ValidateDirectory(DirectoryPath); + + FilePath = Path.Combine(DirectoryPath, $"{filename}{FileSuffix}"); + } public async ValueTask TryLoadAsync(T defaultData) { + if (Data != null) + return Data; + if (File.Exists(FilePath)) { if (new FileInfo(FilePath).Length == 0) { Log.Error($"|BinaryStorage.TryLoad|Zero length cache file <{FilePath}>"); - await SaveAsync(defaultData); - return defaultData; + Data = defaultData; + await SaveAsync(); } await using var stream = new FileStream(FilePath, FileMode.Open); var d = await DeserializeAsync(stream, defaultData); - return d; + Data = d; } else { Log.Info("|BinaryStorage.TryLoad|Cache file not exist, load default data"); - await SaveAsync(defaultData); - return defaultData; + Data = defaultData; + await SaveAsync(); } + + return Data; } private static async ValueTask DeserializeAsync(Stream stream, T defaultData) @@ -56,7 +71,7 @@ namespace Flow.Launcher.Infrastructure.Storage try { var t = await MemoryPackSerializer.DeserializeAsync(stream); - return t; + return t ?? defaultData; } catch (System.Exception) { @@ -65,6 +80,27 @@ namespace Flow.Launcher.Infrastructure.Storage } } + public async ValueTask SaveAsync() + { + await using var stream = new FileStream(FilePath, FileMode.Create); + await MemoryPackSerializer.SerializeAsync(stream, Data); + } + + // For SavePluginSettings function + public void Save() + { + var serialized = MemoryPackSerializer.Serialize(Data); + + File.WriteAllBytes(FilePath, serialized); + } + + // ImageCache need to be converted into concurrent dictionary, so it does not need to cache loading results into Data + public void ClearData() + { + Data = default; + } + + // ImageCache storages data in its class, so it needs to pass it to SaveAsync public async ValueTask SaveAsync(T data) { await using var stream = new FileStream(FilePath, FileMode.Create); diff --git a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs new file mode 100644 index 000000000..87f51d5d7 --- /dev/null +++ b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs @@ -0,0 +1,15 @@ +using System.IO; + +namespace Flow.Launcher.Infrastructure.Storage +{ + public class PluginBinaryStorage : BinaryStorage where T : new() + { + public PluginBinaryStorage(string cacheName, string cacheDirectory) + { + DirectoryPath = cacheDirectory; + Helper.ValidateDirectory(DirectoryPath); + + FilePath = Path.Combine(DirectoryPath, $"{cacheName}{FileSuffix}"); + } + } +} diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs index b377c81aa..9c6547c66 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs @@ -10,7 +10,6 @@ namespace Flow.Launcher.Infrastructure.Storage public PluginJsonStorage() { - // C# related, add python related below var dataType = typeof(T); AssemblyName = dataType.Assembly.GetName().Name; DirectoryPath = Path.Combine(DataLocation.PluginSettingsDirectory, AssemblyName); @@ -18,10 +17,5 @@ namespace Flow.Launcher.Infrastructure.Storage FilePath = Path.Combine(DirectoryPath, $"{dataType.Name}{FileSuffix}"); } - - public PluginJsonStorage(T data) : this() - { - Data = data; - } } } From ca221d710026b3e402873a174696a48e28e5d958 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 14:19:59 +0800 Subject: [PATCH 029/125] Add binary storage api functions --- .../JsonRPCV2Models/JsonRPCPublicAPI.cs | 5 ++ Flow.Launcher.Core/Plugin/PluginManager.cs | 5 +- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 33 ++++++++++++ Flow.Launcher.Plugin/Interfaces/ISavable.cs | 7 +-- Flow.Launcher/PublicAPIInstance.cs | 53 ++++++++++++++++--- 5 files changed, 91 insertions(+), 12 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs index 8df2ce9ed..cf1c57f3e 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs @@ -185,5 +185,10 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models { _api.StopLoadingBar(); } + + public void SavePluginCaches() + { + _api.SavePluginCaches(); + } } } diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 4f869901c..fa4e43e07 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -66,6 +66,7 @@ namespace Flow.Launcher.Core.Plugin } API.SavePluginSettings(); + API.SavePluginCaches(); } public static async ValueTask DisposePluginsAsync() @@ -587,11 +588,13 @@ namespace Flow.Launcher.Core.Plugin if (removePluginSettings) { - // For dotnet plugins, we need to remove their PluginJsonStorage instance + // For dotnet plugins, we need to remove their PluginJsonStorage and PluginBinaryStorage instances if (AllowedLanguage.IsDotNet(plugin.Language)) { var method = API.GetType().GetMethod("RemovePluginSettings"); method?.Invoke(API, new object[] { plugin.AssemblyName }); + var method1 = API.GetType().GetMethod("RemovePluginCache"); + method1?.Invoke(API, new object[] { plugin.PluginCacheDirectoryPath }); } try diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index f178ebb90..be776b068 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -344,5 +344,38 @@ namespace Flow.Launcher.Plugin /// Stop the loading bar in main window /// public void StopLoadingBar(); + + /// + /// Save all Flow's plugins caches + /// + void SavePluginCaches(); + + /// + /// Load BinaryStorage for current plugin's cache. This is the method used to load cache from binary in Flow. + /// When the file is not exist, it will create a new instance for the specific type. + /// + /// Type for deserialization + /// Cache file name + /// Cache directory from plugin metadata + /// Default data to return + /// + /// + /// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable + /// + Task LoadCacheBinaryStorageAsync(string cacheName, string cacheDirectory, T defaultData) where T : new(); + + /// + /// Save BinaryStorage for current plugin's cache. This is the method used to save cache to binary in Flow.Launcher + /// This method will save the original instance loaded with LoadCacheBinaryStorageAsync. + /// This API call is for manually Save. Flow will automatically save all cache type that has called LoadCacheBinaryStorageAsync or SaveCacheBinaryStorageAsync previously. + /// + /// Type for Serialization + /// Cache file name + /// Cache directory from plugin metadata + /// + /// + /// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable + /// + Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new(); } } diff --git a/Flow.Launcher.Plugin/Interfaces/ISavable.cs b/Flow.Launcher.Plugin/Interfaces/ISavable.cs index 77bd304e4..cabd26962 100644 --- a/Flow.Launcher.Plugin/Interfaces/ISavable.cs +++ b/Flow.Launcher.Plugin/Interfaces/ISavable.cs @@ -1,11 +1,12 @@ -namespace Flow.Launcher.Plugin +namespace Flow.Launcher.Plugin { /// /// Inherit this interface if additional data e.g. cache needs to be saved. /// /// /// For storing plugin settings, prefer - /// or . + /// or . + /// or . /// Once called, your settings will be automatically saved by Flow. /// public interface ISavable : IFeatures @@ -15,4 +16,4 @@ namespace Flow.Launcher.Plugin /// void Save(); } -} \ No newline at end of file +} diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index e19ad2fdc..17d7e103e 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -236,14 +236,6 @@ namespace Flow.Launcher ((PluginJsonStorage)_pluginJsonStorages[type]).Save(); } - public void SaveJsonStorage(T settings) where T : new() - { - var type = typeof(T); - _pluginJsonStorages[type] = new PluginJsonStorage(settings); - - ((PluginJsonStorage)_pluginJsonStorages[type]).Save(); - } - public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null) { using var explorer = new Process(); @@ -342,6 +334,51 @@ namespace Flow.Launcher public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress); + private readonly ConcurrentDictionary<(string, string, Type), object> _pluginBinaryStorages = new(); + + public void RemovePluginCache(string cacheDirectory) + { + foreach (var keyValuePair in _pluginBinaryStorages) + { + var key = keyValuePair.Key; + var currentCacheDirectory = key.Item2; + if (cacheDirectory == currentCacheDirectory) + { + _pluginBinaryStorages.Remove(key, out var _); + } + } + } + + /// + /// Save plugin caches. + /// + public void SavePluginCaches() + { + foreach (var value in _pluginBinaryStorages.Values) + { + var method = value.GetType().GetMethod("Save"); + method?.Invoke(value, null); + } + } + + public async Task LoadCacheBinaryStorageAsync(string cacheName, string cacheDirectory, T defaultData) where T : new() + { + var type = typeof(T); + if (!_pluginBinaryStorages.ContainsKey((cacheName, cacheDirectory, type))) + _pluginBinaryStorages[(cacheName, cacheDirectory, type)] = new PluginBinaryStorage(cacheName, cacheDirectory); + + return await ((PluginBinaryStorage)_pluginBinaryStorages[(cacheName, cacheDirectory, type)]).TryLoadAsync(defaultData); + } + + public async Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new() + { + var type = typeof(T); + if (!_pluginBinaryStorages.ContainsKey((cacheName, cacheDirectory, type))) + _pluginBinaryStorages[(cacheName, cacheDirectory, type)] = new PluginBinaryStorage(cacheName, cacheDirectory); + + await ((PluginBinaryStorage)_pluginBinaryStorages[(cacheName, cacheDirectory, type)]).SaveAsync(); + } + #endregion #region Private Methods From 0496d6c04ac2bed323060f41519c41fe1358dc73 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 14:21:29 +0800 Subject: [PATCH 030/125] Use api functions for Program plugin --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 82 +++++++++---------- .../Programs/UWPPackage.cs | 2 +- .../Programs/Win32.cs | 2 +- .../Views/ProgramSetting.xaml.cs | 6 +- 4 files changed, 46 insertions(+), 46 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 3be23214c..5bc518105 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -8,7 +8,6 @@ using System.Threading.Tasks; using System.Windows.Controls; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; -using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.Program.Programs; using Flow.Launcher.Plugin.Program.Views; @@ -19,19 +18,17 @@ using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher.Plugin.Program { - public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, ISavable, IAsyncReloadable, - IDisposable + public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, IAsyncReloadable, IDisposable { - internal static Win32[] _win32s { get; set; } - internal static UWPApp[] _uwps { get; set; } - internal static Settings _settings { get; set; } + private const string Win32CacheName = "Win32"; + private const string UwpCacheName = "UWP"; + internal static List _win32s { get; private set; } + internal static List _uwps { get; private set; } + internal static Settings _settings { get; private set; } internal static PluginInitContext Context { get; private set; } - private static BinaryStorage _win32Storage; - private static BinaryStorage _uwpStorage; - private static readonly List emptyResults = new(); private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; @@ -81,12 +78,6 @@ namespace Flow.Launcher.Plugin.Program { } - public void Save() - { - _win32Storage.SaveAsync(_win32s); - _uwpStorage.SaveAsync(_uwps); - } - public async Task> QueryAsync(Query query, CancellationToken token) { var result = await cache.GetOrCreateAsync(query.Search, async entry => @@ -191,7 +182,9 @@ namespace Flow.Launcher.Plugin.Program await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () => { - Helper.ValidateDirectory(Context.CurrentPluginMetadata.PluginCacheDirectoryPath); + var pluginCachePath = Context.CurrentPluginMetadata.PluginCacheDirectoryPath; + + Helper.ValidateDirectory(pluginCachePath); static void MoveFile(string sourcePath, string destinationPath) { @@ -236,20 +229,18 @@ namespace Flow.Launcher.Plugin.Program } // Move old cache files to the new cache directory - var oldWin32CacheFile = Path.Combine(DataLocation.CacheDirectory, $"Win32.cache"); - var newWin32CacheFile = Path.Combine(Context.CurrentPluginMetadata.PluginCacheDirectoryPath, $"Win32.cache"); + var oldWin32CacheFile = Path.Combine(DataLocation.CacheDirectory, $"{Win32CacheName}.cache"); + var newWin32CacheFile = Path.Combine(pluginCachePath, $"{Win32CacheName}.cache"); MoveFile(oldWin32CacheFile, newWin32CacheFile); - var oldUWPCacheFile = Path.Combine(DataLocation.CacheDirectory, $"UWP.cache"); - var newUWPCacheFile = Path.Combine(Context.CurrentPluginMetadata.PluginCacheDirectoryPath, $"UWP.cache"); + var oldUWPCacheFile = Path.Combine(DataLocation.CacheDirectory, $"{UwpCacheName}.cache"); + var newUWPCacheFile = Path.Combine(pluginCachePath, $"{UwpCacheName}.cache"); MoveFile(oldUWPCacheFile, newUWPCacheFile); - _win32Storage = new BinaryStorage("Win32", Context.CurrentPluginMetadata.PluginCacheDirectoryPath); - _win32s = await _win32Storage.TryLoadAsync(Array.Empty()); - _uwpStorage = new BinaryStorage("UWP", Context.CurrentPluginMetadata.PluginCacheDirectoryPath); - _uwps = await _uwpStorage.TryLoadAsync(Array.Empty()); + _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List()); + _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List()); }); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Length}>"); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Length}>"); + Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Count}>"); + Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Count}>"); bool cacheEmpty = !_win32s.Any() || !_uwps.Any(); @@ -273,36 +264,45 @@ namespace Flow.Launcher.Plugin.Program } } - public static void IndexWin32Programs() + public static async Task IndexWin32ProgramsAsync() { var win32S = Win32.All(_settings); - _win32s = win32S; + _win32s.Clear(); + foreach (var win32 in win32S) + { + _win32s.Add(win32); + } ResetCache(); - _win32Storage.SaveAsync(_win32s); + await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); _settings.LastIndexTime = DateTime.Now; } - public static void IndexUwpPrograms() + public static async Task IndexUwpProgramsAsync() { - var applications = UWPPackage.All(_settings); - _uwps = applications; + var uwps = UWPPackage.All(_settings); + _uwps.Clear(); + foreach (var uwp in uwps) + { + _uwps.Add(uwp); + } ResetCache(); - _uwpStorage.SaveAsync(_uwps); + await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); _settings.LastIndexTime = DateTime.Now; } public static async Task IndexProgramsAsync() { - var a = Task.Run(() => + var win32Task = Task.Run(async () => { - Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexWin32Programs); + await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexWin32ProgramsAsync); }); - var b = Task.Run(() => + var uwpTask = Task.Run(async () => { - Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|UWPProgram index cost", IndexUwpPrograms); + await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|UWPProgram index cost", IndexUwpProgramsAsync); }); - await Task.WhenAll(a, b).ConfigureAwait(false); + + await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false); } internal static void ResetCache() @@ -314,7 +314,7 @@ namespace Flow.Launcher.Plugin.Program public Control CreateSettingPanel() { - return new ProgramSetting(Context, _settings, _win32s, _uwps); + return new ProgramSetting(Context, _settings); } public string GetTranslatedPluginTitle() @@ -370,7 +370,7 @@ namespace Flow.Launcher.Plugin.Program _settings.DisabledProgramSources.Add(new ProgramSource(program)); _ = Task.Run(() => { - IndexUwpPrograms(); + _ = IndexUwpProgramsAsync(); }); } else if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) @@ -380,7 +380,7 @@ namespace Flow.Launcher.Plugin.Program _settings.DisabledProgramSources.Add(new ProgramSource(program)); _ = Task.Run(() => { - IndexWin32Programs(); + _ = IndexWin32ProgramsAsync(); }); } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs index 654897cc5..bf100ed7e 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs @@ -317,7 +317,7 @@ namespace Flow.Launcher.Plugin.Program.Programs { await Task.Delay(3000).ConfigureAwait(false); PackageChangeChannel.Reader.TryRead(out _); - await Task.Run(Main.IndexUwpPrograms); + await Task.Run(Main.IndexUwpProgramsAsync); } } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index a64a708ef..06be2a628 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -797,7 +797,7 @@ namespace Flow.Launcher.Plugin.Program.Programs { } - await Task.Run(Main.IndexWin32Programs); + await Task.Run(Main.IndexWin32ProgramsAsync); } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs index 91864cb68..5ad7fcea3 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs @@ -18,8 +18,8 @@ namespace Flow.Launcher.Plugin.Program.Views /// public partial class ProgramSetting : UserControl { - private PluginInitContext context; - private Settings _settings; + private readonly PluginInitContext context; + private readonly Settings _settings; private GridViewColumnHeader _lastHeaderClicked; private ListSortDirection _lastDirection; @@ -109,7 +109,7 @@ namespace Flow.Launcher.Plugin.Program.Views public bool ShowUWPCheckbox => UWPPackage.SupportUWP(); - public ProgramSetting(PluginInitContext context, Settings settings, Win32[] win32s, UWPApp[] uwps) + public ProgramSetting(PluginInitContext context, Settings settings) { this.context = context; _settings = settings; From 68e1fc28efcc31362193aab4e73aa7459bf1b1af Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 14:35:43 +0800 Subject: [PATCH 031/125] Use try remove for safety --- Flow.Launcher/PublicAPIInstance.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 17d7e103e..770195550 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -201,7 +201,7 @@ namespace Flow.Launcher var name = value.GetType().GetField("AssemblyName")?.GetValue(value)?.ToString(); if (name == assemblyName) { - _pluginJsonStorages.Remove(key, out var pluginJsonStorage); + _pluginJsonStorages.TryRemove(key, out var pluginJsonStorage); } } } @@ -344,7 +344,7 @@ namespace Flow.Launcher var currentCacheDirectory = key.Item2; if (cacheDirectory == currentCacheDirectory) { - _pluginBinaryStorages.Remove(key, out var _); + _pluginBinaryStorages.TryRemove(key, out var _); } } } From 53c12327c0bcce76b770273c6a95f2c15ed0d27b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 11:51:34 +0800 Subject: [PATCH 032/125] Revert changes --- Flow.Launcher.Infrastructure/Logger/Log.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs index 84331ef70..807d631c7 100644 --- a/Flow.Launcher.Infrastructure/Logger/Log.cs +++ b/Flow.Launcher.Infrastructure/Logger/Log.cs @@ -135,14 +135,12 @@ namespace Flow.Launcher.Infrastructure.Logger return className; } -#if !DEBUG private static void ExceptionInternal(string classAndMethod, string message, System.Exception e) { var logger = LogManager.GetLogger(classAndMethod); logger.Error(e, message); } -#endif private static void LogInternal(string message, LogLevel level) { From 0430eea2fd14f208be42d560716319bde2a0362f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 22:25:55 +0800 Subject: [PATCH 033/125] Use api functions instead of project reference for code quality --- .../Commands/BookmarkLoader.cs | 5 ++-- .../FirefoxBookmarkLoader.cs | 23 ++++++++++--------- ...low.Launcher.Plugin.BrowserBookmark.csproj | 1 - .../Main.cs | 15 ++---------- 4 files changed, 16 insertions(+), 28 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/BookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/BookmarkLoader.cs index 3468015eb..758ce68ae 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/BookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/BookmarkLoader.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.BrowserBookmark.Models; using Flow.Launcher.Plugin.SharedModels; @@ -10,11 +9,11 @@ internal static class BookmarkLoader { internal static MatchResult MatchProgram(Bookmark bookmark, string queryString) { - var match = StringMatcher.FuzzySearch(queryString, bookmark.Name); + var match = Main._context.API.FuzzySearch(queryString, bookmark.Name); if (match.IsSearchPrecisionScoreMet()) return match; - return StringMatcher.FuzzySearch(queryString, bookmark.Url); + return Main._context.API.FuzzySearch(queryString, bookmark.Url); } internal static List LoadAllBookmarks(Settings setting) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 3b37bbaed..0e02b2c9e 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -1,15 +1,16 @@ -using Flow.Launcher.Plugin.BrowserBookmark.Models; -using Microsoft.Data.Sqlite; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; -using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Plugin.BrowserBookmark.Models; +using Microsoft.Data.Sqlite; namespace Flow.Launcher.Plugin.BrowserBookmark; public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader { + private static readonly string ClassName = nameof(FirefoxBookmarkLoaderBase); + private readonly string _faviconCacheDir; protected FirefoxBookmarkLoaderBase() @@ -52,7 +53,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to register Firefox bookmark file monitoring: {placesPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to register Firefox bookmark file monitoring: {placesPath}", ex); } // Use a copy to avoid lock issues with the original file @@ -93,12 +94,12 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to delete temporary favicon DB: {tempDbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); } } catch (Exception ex) { - Log.Exception($"Failed to load Firefox bookmarks: {placesPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to load Firefox bookmarks: {placesPath}", ex); } return bookmarks; @@ -177,7 +178,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to extract Firefox favicon: {bookmark.Url}", ex); + Main._context.API.LogException(ClassName, $"Failed to extract Firefox favicon: {bookmark.Url}", ex); } } @@ -192,12 +193,12 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to delete temporary favicon DB: {tempDbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); } } catch (Exception ex) { - Log.Exception($"Failed to load Firefox favicon DB: {faviconDbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to load Firefox favicon DB: {faviconDbPath}", ex); } } @@ -218,7 +219,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to save image: {outputPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to save image: {outputPath}", ex); } } } diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index b4e42fbcd..d09b9e750 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -81,7 +81,6 @@ - diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index ce7f56c34..5ab868ab9 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Controls; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.BrowserBookmark.Commands; using Flow.Launcher.Plugin.BrowserBookmark.Models; using Flow.Launcher.Plugin.BrowserBookmark.Views; @@ -15,7 +14,7 @@ namespace Flow.Launcher.Plugin.BrowserBookmark; public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContextMenu, IDisposable { - private static PluginInitContext _context; + internal static PluginInitContext _context; private static List _cachedBookmarks = new(); @@ -23,16 +22,6 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex private static bool _initialized = false; - public static PluginInitContext GetContext() - { - return _context; - } - - public static string GetPluginDirectory() - { - return _context?.CurrentPluginMetadata?.PluginDirectory; - } - public void Init(PluginInitContext context) { _context = context; @@ -223,7 +212,7 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex catch (Exception e) { var message = "Failed to set url in clipboard"; - Log.Exception("Main", message, e, "LoadContextMenus"); + _context.API.LogException(nameof(Main), message, e); _context.API.ShowMsg(message); From 168f898baf15950ed79fe2e2a26c96a4bd4e89aa Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 22:27:45 +0800 Subject: [PATCH 034/125] Cleanup namespaces --- .../Views/SettingsControl.xaml.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml.cs index 8584a3eb0..3182adfed 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml.cs @@ -3,13 +3,6 @@ using Flow.Launcher.Plugin.BrowserBookmark.Models; using System.Windows.Input; using System.ComponentModel; using System.Threading.Tasks; -using System; -using System.IO; -using System.Windows; -using System.Windows.Input; -using System.ComponentModel; -using System.Threading.Tasks; -using Flow.Launcher.Plugin.BrowserBookmark.Models; namespace Flow.Launcher.Plugin.BrowserBookmark.Views; @@ -23,6 +16,7 @@ public partial class SettingsControl : INotifyPropertyChanged Settings = settings; InitializeComponent(); } + public bool LoadChromeBookmark { get => Settings.LoadChromeBookmark; @@ -62,6 +56,7 @@ public partial class SettingsControl : INotifyPropertyChanged PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(OpenInNewBrowserWindow))); } } + public event PropertyChangedEventHandler PropertyChanged; private void NewCustomBrowser(object sender, RoutedEventArgs e) From b564a39aae1990610a09ccd54531cae9c82e07e4 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 22:31:31 +0800 Subject: [PATCH 035/125] Use api functions instead of project reference for code quality --- .../ChromiumBookmarkLoader.cs | 22 ++++++++++--------- ...low.Launcher.Plugin.BrowserBookmark.csproj | 3 ++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index d9c4e91d0..39bbb73ff 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -1,15 +1,17 @@ -using Flow.Launcher.Plugin.BrowserBookmark.Models; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Text.Json; -using Flow.Launcher.Infrastructure.Logger; using System; +using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Plugin.BrowserBookmark.Models; using Microsoft.Data.Sqlite; namespace Flow.Launcher.Plugin.BrowserBookmark; public abstract class ChromiumBookmarkLoader : IBookmarkLoader { + private readonly static string ClassName = nameof(ChromiumBookmarkLoader); + private readonly string _faviconCacheDir; protected ChromiumBookmarkLoader() @@ -44,7 +46,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to register bookmark file monitoring: {bookmarkPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to register bookmark file monitoring: {bookmarkPath}", ex); } var source = name + (Path.GetFileName(profile) == "Default" ? "" : $" ({Path.GetFileName(profile)})"); @@ -136,7 +138,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to copy favicon DB: {dbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to copy favicon DB: {dbPath}", ex); return; } @@ -189,7 +191,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to extract bookmark favicon: {bookmark.Url}", ex); + Main._context.API.LogException(ClassName, $"Failed to extract bookmark favicon: {bookmark.Url}", ex); } } @@ -199,7 +201,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to connect to SQLite: {tempDbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to connect to SQLite: {tempDbPath}", ex); } // Delete temporary file @@ -209,12 +211,12 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to delete temporary favicon DB: {tempDbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); } } catch (Exception ex) { - Log.Exception($"Failed to load favicon DB: {dbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to load favicon DB: {dbPath}", ex); } } @@ -226,7 +228,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to save image: {outputPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to save image: {outputPath}", ex); } } } diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index d09b9e750..49ae26564 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -1,4 +1,4 @@ - + Library @@ -81,6 +81,7 @@ + From a845e68c98f4ed3c350bd291dc0a5847bc4f4a8c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 22:39:30 +0800 Subject: [PATCH 036/125] Use plugin cache directory --- .../ChromiumBookmarkLoader.cs | 7 ++----- .../FirefoxBookmarkLoader.cs | 5 +---- Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs | 9 +++++++++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 39bbb73ff..282876472 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -10,16 +10,13 @@ namespace Flow.Launcher.Plugin.BrowserBookmark; public abstract class ChromiumBookmarkLoader : IBookmarkLoader { - private readonly static string ClassName = nameof(ChromiumBookmarkLoader); + private static readonly string ClassName = nameof(ChromiumBookmarkLoader); private readonly string _faviconCacheDir; protected ChromiumBookmarkLoader() { - _faviconCacheDir = Path.Combine( - Path.GetDirectoryName(typeof(ChromiumBookmarkLoader).Assembly.Location), - "FaviconCache"); - Directory.CreateDirectory(_faviconCacheDir); + _faviconCacheDir = Main._faviconCacheDir; } public abstract List GetBookmarks(); diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 0e02b2c9e..d2f973329 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -15,10 +15,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader protected FirefoxBookmarkLoaderBase() { - _faviconCacheDir = Path.Combine( - Path.GetDirectoryName(typeof(FirefoxBookmarkLoaderBase).Assembly.Location), - "FaviconCache"); - Directory.CreateDirectory(_faviconCacheDir); + _faviconCacheDir = Main._faviconCacheDir; } public abstract List GetBookmarks(); diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index 5ab868ab9..5dec8b953 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Controls; +using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.BrowserBookmark.Commands; using Flow.Launcher.Plugin.BrowserBookmark.Models; using Flow.Launcher.Plugin.BrowserBookmark.Views; @@ -14,6 +15,8 @@ namespace Flow.Launcher.Plugin.BrowserBookmark; public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContextMenu, IDisposable { + internal static string _faviconCacheDir; + internal static PluginInitContext _context; private static List _cachedBookmarks = new(); @@ -28,6 +31,12 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex _settings = context.API.LoadSettingJsonStorage(); + _faviconCacheDir = Path.Combine( + _context.CurrentPluginMetadata.PluginCacheDirectoryPath, + "FaviconCache"); + + Helper.ValidateDirectory(_faviconCacheDir); + LoadBookmarksIfEnabled(); } From 56536d018891a7a28e1c5916a1426045b3682360 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 16:45:58 +0800 Subject: [PATCH 037/125] Add log for plugin binary storage --- .../Storage/PluginBinaryStorage.cs | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs index 87f51d5d7..d18060e3d 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs @@ -1,15 +1,49 @@ using System.IO; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage { public class PluginBinaryStorage : BinaryStorage where T : new() { + private static readonly string ClassName = "PluginBinaryStorage"; + + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + public PluginBinaryStorage(string cacheName, string cacheDirectory) { DirectoryPath = cacheDirectory; - Helper.ValidateDirectory(DirectoryPath); + FilesFolders.ValidateDirectory(DirectoryPath); FilePath = Path.Combine(DirectoryPath, $"{cacheName}{FileSuffix}"); } + + public new void Save() + { + try + { + base.Save(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin caches to path: {FilePath}", e); + } + } + + public new async Task SaveAsync() + { + try + { + await base.SaveAsync(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin caches to path: {FilePath}", e); + } + } } } From 358b1fd7c875e4e4863227d53ee977872a9bd703 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:10:39 +0800 Subject: [PATCH 038/125] Move theme data and functions into api --- Flow.Launcher.Core/Resource/Theme.cs | 31 ++++---- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 19 +++++ Flow.Launcher.Plugin/ThemeData.cs | 71 +++++++++++++++++++ Flow.Launcher/PublicAPIInstance.cs | 13 ++++ 4 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 Flow.Launcher.Plugin/ThemeData.cs diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index e5980b62f..4cf9ce7a7 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -81,11 +81,6 @@ namespace Flow.Launcher.Core.Resource #region Theme Resources - public string GetCurrentTheme() - { - return _settings.Theme; - } - private void MakeSureThemeDirectoriesExist() { foreach (var dir in _themeDirectories.Where(dir => !Directory.Exists(dir))) @@ -127,7 +122,7 @@ namespace Flow.Launcher.Core.Resource try { // Load a ResourceDictionary for the specified theme. - var themeName = GetCurrentTheme(); + var themeName = _settings.Theme; var dict = GetThemeResourceDictionary(themeName); // Apply font settings to the theme resource. @@ -330,7 +325,7 @@ namespace Flow.Launcher.Core.Resource private ResourceDictionary GetCurrentResourceDictionary() { - return GetResourceDictionary(GetCurrentTheme()); + return GetResourceDictionary(_settings.Theme); } private ThemeData GetThemeDataFromPath(string path) @@ -383,9 +378,15 @@ namespace Flow.Launcher.Core.Resource #endregion - #region Load & Change + #region Get & Change Theme - public List LoadAvailableThemes() + public ThemeData GetCurrentTheme() + { + var themes = GetAvailableThemes(); + return themes.FirstOrDefault(t => t.FileNameWithoutExtension == _settings.Theme) ?? themes.FirstOrDefault(); + } + + public List GetAvailableThemes() { List themes = new List(); foreach (var themeDirectory in _themeDirectories) @@ -403,7 +404,7 @@ namespace Flow.Launcher.Core.Resource public bool ChangeTheme(string theme = null) { if (string.IsNullOrEmpty(theme)) - theme = GetCurrentTheme(); + theme = _settings.Theme; string path = GetThemePath(theme); try @@ -591,7 +592,7 @@ namespace Flow.Launcher.Core.Resource { AutoDropShadow(useDropShadowEffect); } - SetBlurForWindow(GetCurrentTheme(), backdropType); + SetBlurForWindow(_settings.Theme, backdropType); if (!BlurEnabled) { @@ -610,7 +611,7 @@ namespace Flow.Launcher.Core.Resource // Get the actual backdrop type and drop shadow effect settings var (backdropType, _) = GetActualValue(); - SetBlurForWindow(GetCurrentTheme(), backdropType); + SetBlurForWindow(_settings.Theme, backdropType); }, DispatcherPriority.Render); } @@ -898,11 +899,5 @@ namespace Flow.Launcher.Core.Resource } #endregion - - #region Classes - - public record ThemeData(string FileNameWithoutExtension, string Name, bool? IsDark = null, bool? HasBlur = null); - - #endregion } } diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index f178ebb90..bfcc2f9e0 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -344,5 +344,24 @@ namespace Flow.Launcher.Plugin /// Stop the loading bar in main window /// public void StopLoadingBar(); + + /// + /// Get all available themes + /// + /// + public List GetAvailableThemes(); + + /// + /// Get the current theme + /// + /// + public ThemeData GetCurrentTheme(); + + /// + /// Set the current theme + /// + /// + /// + public void SetCurrentTheme(ThemeData theme); } } diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs new file mode 100644 index 000000000..d4a69ef09 --- /dev/null +++ b/Flow.Launcher.Plugin/ThemeData.cs @@ -0,0 +1,71 @@ +namespace Flow.Launcher.Plugin; + +/// +/// Theme data model +/// +public class ThemeData +{ + /// + /// Theme file name without extension + /// + public string FileNameWithoutExtension { get; private init; } + + /// + /// Theme name + /// + public string Name { get; private init; } + + /// + /// Theme file path + /// + public bool? IsDark { get; private init; } + + /// + /// Theme file path + /// + public bool? HasBlur { get; private init; } + + /// + /// Theme data constructor + /// + public ThemeData(string fileNameWithoutExtension, string name, bool? isDark = null, bool? hasBlur = null) + { + FileNameWithoutExtension = fileNameWithoutExtension; + Name = name; + IsDark = isDark; + HasBlur = hasBlur; + } + + /// + public static bool operator ==(ThemeData left, ThemeData right) + { + return left.Equals(right); + } + + /// + public static bool operator !=(ThemeData left, ThemeData right) + { + return !(left == right); + } + + /// + public override bool Equals(object obj) + { + if (obj is not ThemeData other) + return false; + return FileNameWithoutExtension == other.FileNameWithoutExtension && + Name == other.Name; + } + + /// + public override int GetHashCode() + { + return Name?.GetHashCode() ?? 0; + } + + /// + public override string ToString() + { + return Name; + } +} diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index d88eeb7c9..96ccb55c4 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -37,6 +37,9 @@ namespace Flow.Launcher private readonly Internationalization _translater; private readonly MainViewModel _mainVM; + private Theme _theme; + private Theme Theme => _theme ??= Ioc.Default.GetRequiredService(); + private readonly object _saveSettingsLock = new(); #region Constructor @@ -354,6 +357,16 @@ namespace Flow.Launcher public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress); + public List GetAvailableThemes() => Theme.GetAvailableThemes(); + + public ThemeData GetCurrentTheme() => Theme.GetCurrentTheme(); + + public void SetCurrentTheme(ThemeData theme) + { + Theme.ChangeTheme(theme.FileNameWithoutExtension); + _ = _theme.RefreshFrameAsync(); + } + #endregion #region Private Methods From 9b9704e938f1e74584c8bc7688bc333387700c6b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:11:01 +0800 Subject: [PATCH 039/125] Improve settings panel theme page & theme selector --- .../ViewModels/SettingsPaneThemeViewModel.cs | 14 +++--- .../Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 47 +++++-------------- 2 files changed, 17 insertions(+), 44 deletions(-) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index 6e2488fe1..58cf3a314 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -28,25 +28,23 @@ public partial class SettingsPaneThemeViewModel : BaseModel public static string LinkHowToCreateTheme => @"https://www.flowlauncher.com/theme-builder/"; public static string LinkThemeGallery => "https://github.com/Flow-Launcher/Flow.Launcher/discussions/1438"; - private List _themes; - public List Themes => _themes ??= _theme.LoadAvailableThemes(); + private List _themes; + public List Themes => _themes ??= App.API.GetAvailableThemes(); - private Theme.ThemeData _selectedTheme; - public Theme.ThemeData SelectedTheme + private ThemeData _selectedTheme; + public ThemeData SelectedTheme { - get => _selectedTheme ??= Themes.Find(v => v.FileNameWithoutExtension == _theme.GetCurrentTheme()); + get => _selectedTheme ??= Themes.Find(v => v == App.API.GetCurrentTheme()); set { _selectedTheme = value; - _theme.ChangeTheme(value.FileNameWithoutExtension); + App.API.SetCurrentTheme(value); // Update UI state OnPropertyChanged(nameof(BackdropType)); OnPropertyChanged(nameof(IsBackdropEnabled)); OnPropertyChanged(nameof(IsDropShadowEnabled)); OnPropertyChanged(nameof(DropShadowEffect)); - - _ = _theme.RefreshFrameAsync(); } } diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index 31faeba52..84bfa218e 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Linq; -using CommunityToolkit.Mvvm.DependencyInjection; -using Flow.Launcher.Core.Resource; namespace Flow.Launcher.Plugin.Sys { @@ -11,32 +9,6 @@ namespace Flow.Launcher.Plugin.Sys private readonly PluginInitContext _context; - // Do not initialize it in the constructor, because it will cause null reference in - // var dicts = Application.Current.Resources.MergedDictionaries; line of Theme - private Theme theme = null; - private Theme Theme => theme ??= Ioc.Default.GetRequiredService(); - - #region Theme Selection - - // Theme select codes simplified from SettingsPaneThemeViewModel.cs - - private Theme.ThemeData _selectedTheme; - public Theme.ThemeData SelectedTheme - { - get => _selectedTheme ??= Themes.Find(v => v.FileNameWithoutExtension == Theme.GetCurrentTheme()); - set - { - _selectedTheme = value; - Theme.ChangeTheme(value.FileNameWithoutExtension); - - _ = Theme.RefreshFrameAsync(); - } - } - - private List Themes => Theme.LoadAvailableThemes(); - - #endregion - public ThemeSelector(PluginInitContext context) { _context = context; @@ -44,28 +16,31 @@ namespace Flow.Launcher.Plugin.Sys public List Query(Query query) { + var themes = _context.API.GetAvailableThemes(); + var selectedTheme = _context.API.GetCurrentTheme(); + var search = query.SecondToEndSearch; if (string.IsNullOrWhiteSpace(search)) { - return Themes.Select(CreateThemeResult) + return themes.Select(x => CreateThemeResult(x, selectedTheme)) .OrderBy(x => x.Title) .ToList(); } - return Themes.Select(theme => (theme, matchResult: _context.API.FuzzySearch(search, theme.Name))) + return themes.Select(theme => (theme, matchResult: _context.API.FuzzySearch(search, theme.Name))) .Where(x => x.matchResult.IsSearchPrecisionScoreMet()) - .Select(x => CreateThemeResult(x.theme, x.matchResult.Score, x.matchResult.MatchData)) + .Select(x => CreateThemeResult(x.theme, selectedTheme, x.matchResult.Score, x.matchResult.MatchData)) .OrderBy(x => x.Title) .ToList(); } - private Result CreateThemeResult(Theme.ThemeData theme) => CreateThemeResult(theme, 0, null); + private Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme) => CreateThemeResult(theme, selectedTheme, 0, null); - private Result CreateThemeResult(Theme.ThemeData theme, int score, IList highlightData) + private Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme, int score, IList highlightData) { - string themeName = theme.Name; + var themeName = theme.FileNameWithoutExtension; string title; - if (theme == SelectedTheme) + if (theme == selectedTheme) { title = $"{theme.Name} ★"; // Set current theme to the top @@ -101,7 +76,7 @@ namespace Flow.Launcher.Plugin.Sys Score = score, Action = c => { - SelectedTheme = theme; + _context.API.SetCurrentTheme(theme); _context.API.ReQuery(); return false; } From 1611ad37f37fde5ac054529cfa3a136e28fa3168 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:15:47 +0800 Subject: [PATCH 040/125] Fix ThemeData hashcode issue --- Flow.Launcher.Plugin/ThemeData.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs index d4a69ef09..6cbd0fe74 100644 --- a/Flow.Launcher.Plugin/ThemeData.cs +++ b/Flow.Launcher.Plugin/ThemeData.cs @@ -1,4 +1,6 @@ -namespace Flow.Launcher.Plugin; +using System; + +namespace Flow.Launcher.Plugin; /// /// Theme data model @@ -60,7 +62,7 @@ public class ThemeData /// public override int GetHashCode() { - return Name?.GetHashCode() ?? 0; + return HashCode.Combine(FileNameWithoutExtension, Name); } /// From 514fa0037a0f0ad6b78ad6ae17d943764cf696c7 Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:23:07 +0800 Subject: [PATCH 041/125] Improve documents Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Plugin/ThemeData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs index 6cbd0fe74..90a45182c 100644 --- a/Flow.Launcher.Plugin/ThemeData.cs +++ b/Flow.Launcher.Plugin/ThemeData.cs @@ -23,7 +23,7 @@ public class ThemeData public bool? IsDark { get; private init; } /// - /// Theme file path + /// Indicates whether the theme supports blur effects /// public bool? HasBlur { get; private init; } From 28d92c789f181acb2060f7ff0b1c9f226bdb4905 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:23:36 +0800 Subject: [PATCH 042/125] Improve documents --- Flow.Launcher.Plugin/ThemeData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs index 90a45182c..1888be65e 100644 --- a/Flow.Launcher.Plugin/ThemeData.cs +++ b/Flow.Launcher.Plugin/ThemeData.cs @@ -18,7 +18,7 @@ public class ThemeData public string Name { get; private init; } /// - /// Theme file path + /// Indicates whether the theme supports dark mode /// public bool? IsDark { get; private init; } From 2e885ea5ccec4a42de61e1d1fe6ced1e319656ce Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:45:24 +0800 Subject: [PATCH 043/125] Remove useless variable --- Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index 84bfa218e..4b99efe3b 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -38,7 +38,6 @@ namespace Flow.Launcher.Plugin.Sys private Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme, int score, IList highlightData) { - var themeName = theme.FileNameWithoutExtension; string title; if (theme == selectedTheme) { From a65e89b86fbe3e1134c1a098f9af85ed4ea8bf71 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 5 Apr 2025 01:06:06 +0900 Subject: [PATCH 044/125] Adjust advanced control UI --- .../SettingsPanePluginsViewModel.cs | 22 +++++ .../Views/SettingsPaneGeneral.xaml | 21 ++++ .../Views/SettingsPanePlugins.xaml | 97 +++++++++++++------ .../Views/SettingsPanePlugins.xaml.cs | 9 ++ 4 files changed, 117 insertions(+), 32 deletions(-) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index 5cd14ba7e..69d31a98d 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -14,6 +14,28 @@ public class SettingsPanePluginsViewModel : BaseModel { private readonly Settings _settings; + public void UpdateDisplayModeFromSelection() + { + switch (CurrentDisplayMode) + { + case "OnOff": + IsOnOffSelected = true; + IsPrioritySelected = false; + IsSearchDelaySelected = false; + break; + case "Priority": + IsOnOffSelected = false; + IsPrioritySelected = true; + IsSearchDelaySelected = false; + break; + case "SearchDelay": + IsOnOffSelected = false; + IsPrioritySelected = false; + IsSearchDelaySelected = true; + break; + } + } + private bool _isOnOffSelected = true; public bool IsOnOffSelected { diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 3f8272dda..e36c647a2 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -196,6 +196,27 @@ + + + + + + + + + @@ -34,34 +34,35 @@ Text="{DynamicResource plugins}" TextAlignment="Left" /> - + + - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Flow.Launcher/SearchDelayTimeWindow.xaml.cs b/Flow.Launcher/SearchDelayTimeWindow.xaml.cs deleted file mode 100644 index 4a3c9f5a7..000000000 --- a/Flow.Launcher/SearchDelayTimeWindow.xaml.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Linq; -using System.Windows; -using Flow.Launcher.Plugin; -using Flow.Launcher.SettingPages.ViewModels; -using Flow.Launcher.ViewModel; -using static Flow.Launcher.SettingPages.ViewModels.SettingsPaneGeneralViewModel; - -namespace Flow.Launcher; - -public partial class SearchDelayTimeWindow : Window -{ - private readonly PluginViewModel _pluginViewModel; - - public SearchDelayTimeWindow(PluginViewModel pluginViewModel) - { - InitializeComponent(); - _pluginViewModel = pluginViewModel; - } - - private void SearchDelayTimeWindow_OnLoaded(object sender, RoutedEventArgs e) - { - tbSearchDelayTimeTips.Text = string.Format(App.API.GetTranslation("searchDelayTime_tips"), - App.API.GetTranslation("default")); - tbOldSearchDelayTime.Text = _pluginViewModel.SearchDelayTimeText; - var searchDelayTimes = DropdownDataGeneric.GetValues("SearchDelayTime"); - SearchDelayTimeData selected = null; - // Because default value is SearchDelayTime.VeryShort, we need to get selected value before adding default value - if (_pluginViewModel.PluginSearchDelayTime != null) - { - selected = searchDelayTimes.FirstOrDefault(x => x.Value == _pluginViewModel.PluginSearchDelayTime); - } - // Add default value to the beginning of the list - // When _pluginViewModel.PluginSearchDelayTime equals null, we will select this - searchDelayTimes.Insert(0, new SearchDelayTimeData { Display = App.API.GetTranslation("default"), LocalizationKey = "default" }); - selected ??= searchDelayTimes.FirstOrDefault(); - cbDelay.ItemsSource = searchDelayTimes; - cbDelay.SelectedItem = selected; - cbDelay.Focus(); - } - - private void BtnCancel_OnClick(object sender, RoutedEventArgs e) - { - Close(); - } - - private void btnDone_OnClick(object sender, RoutedEventArgs _) - { - // Update search delay time - var selected = cbDelay.SelectedItem as SearchDelayTimeData; - SearchDelayTime? changedValue = selected?.LocalizationKey != "default" ? selected.Value : null; - _pluginViewModel.PluginSearchDelayTime = changedValue; - - // Update search delay time text and close window - _pluginViewModel.OnSearchDelayTimeChanged(); - Close(); - } -} diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index cec8c318c..74e2d8340 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Forms; +using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; @@ -31,7 +32,25 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public class SearchWindowAlignData : DropdownDataGeneric { } public class SearchPrecisionData : DropdownDataGeneric { } public class LastQueryModeData : DropdownDataGeneric { } - public class SearchDelayTimeData : DropdownDataGeneric { } + public class SearchDelayTimeData + { + public string Display { get; set; } + public int Value { get; set; } + + public static List GetValues() + { + var settings = Ioc.Default.GetRequiredService(); + var data = new List(); + + foreach (var value in settings.SearchDelayTimeRange) + { + var display = $"{value}ms"; + data.Add(new SearchDelayTimeData { Display = display, Value = value }); + } + + return data; + } + } public bool StartFlowLauncherOnSystemStartup { @@ -144,19 +163,15 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public List LastQueryModes { get; } = DropdownDataGeneric.GetValues("LastQuery"); - public List SearchDelayTimes { get; } = - DropdownDataGeneric.GetValues("SearchDelayTime"); + public List SearchDelayTimes { get; } = SearchDelayTimeData.GetValues(); public SearchDelayTimeData SearchDelayTime { - get => SearchDelayTimes.FirstOrDefault(x => x.Value == Settings.SearchDelayTime) ?? - SearchDelayTimes.FirstOrDefault(x => x.Value == Plugin.SearchDelayTime.Normal) ?? - SearchDelayTimes.FirstOrDefault(); + get => SearchDelayTimes.FirstOrDefault(x => x.Value == Settings.SearchDelayTime); set { - if (value == null) - return; - + if (value == null) return; + if (Settings.SearchDelayTime != value.Value) { Settings.SearchDelayTime = value.Value; @@ -170,7 +185,6 @@ public partial class SettingsPaneGeneralViewModel : BaseModel DropdownDataGeneric.UpdateLabels(SearchWindowAligns); DropdownDataGeneric.UpdateLabels(SearchPrecisionScores); DropdownDataGeneric.UpdateLabels(LastQueryModes); - DropdownDataGeneric.UpdateLabels(SearchDelayTimes); } public string Language diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index e36c647a2..10e2b549a 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -196,18 +196,21 @@ - + - - + Sub="{DynamicResource searchDelayTimeToolTip}" + Type="InsideFit"> - + 250, - SearchDelayTime.Long => 200, - SearchDelayTime.Normal => 150, - SearchDelayTime.Short => 100, - SearchDelayTime.VeryShort => 50, - _ => 150 - }; + var searchDelayTime = plugin.Metadata.SearchDelayTime ?? Settings.SearchDelayTime; await Task.Delay(searchDelayTime, token); diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 2016d9c98..bf61b1902 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -95,7 +95,7 @@ namespace Flow.Launcher.ViewModel } } - public SearchDelayTime? PluginSearchDelayTime + public int? PluginSearchDelayTime { get => PluginPair.Metadata.SearchDelayTime; set @@ -192,12 +192,5 @@ namespace Flow.Launcher.ViewModel var changeKeywordsWindow = new ActionKeywords(this); changeKeywordsWindow.ShowDialog(); } - - [RelayCommand] - private void SetSearchDelayTime() - { - var searchDelayTimeWindow = new SearchDelayTimeWindow(this); - searchDelayTimeWindow.ShowDialog(); - } } } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json index 64681f803..c8b6310a7 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json @@ -32,5 +32,5 @@ "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.WebSearch.dll", "IcoPath": "Images\\web_search.png", - "SearchDelayTime": "VeryLong" + "SearchDelayTime": 450 } From dfb6b0a3a300386fe668148d0429de9db7ea9b3a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 7 Apr 2025 14:26:35 +0800 Subject: [PATCH 057/125] Fix string resource issue --- .../SettingPages/ViewModels/SettingsPanePluginsViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index af1653c93..46e398eb5 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -141,7 +141,7 @@ public partial class SettingsPanePluginsViewModel : BaseModel }, new TextBlock { - Text = (string)Application.Current.Resources["searchDelayTime_tips"], + Text = (string)Application.Current.Resources["searchDelayTimeTips"], TextWrapping = TextWrapping.Wrap } } From 24bbfcc4139596ac6d3929da44e353508f426974 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 7 Apr 2025 14:27:33 +0800 Subject: [PATCH 058/125] Support numerical box for priority --- Flow.Launcher/PriorityChangeWindow.xaml | 121 ------------------ Flow.Launcher/PriorityChangeWindow.xaml.cs | 67 ---------- .../Controls/InstalledPluginDisplay.xaml | 3 +- Flow.Launcher/ViewModel/PluginViewModel.cs | 20 +-- 4 files changed, 4 insertions(+), 207 deletions(-) delete mode 100644 Flow.Launcher/PriorityChangeWindow.xaml delete mode 100644 Flow.Launcher/PriorityChangeWindow.xaml.cs diff --git a/Flow.Launcher/PriorityChangeWindow.xaml b/Flow.Launcher/PriorityChangeWindow.xaml deleted file mode 100644 index 33ed54bb4..000000000 --- a/Flow.Launcher/PriorityChangeWindow.xaml +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Flow.Launcher/PriorityChangeWindow.xaml.cs b/Flow.Launcher/PriorityChangeWindow.xaml.cs deleted file mode 100644 index fbe2a941d..000000000 --- a/Flow.Launcher/PriorityChangeWindow.xaml.cs +++ /dev/null @@ -1,67 +0,0 @@ -using Flow.Launcher.Core.Plugin; -using Flow.Launcher.Core.Resource; -using Flow.Launcher.Plugin; -using Flow.Launcher.ViewModel; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using Flow.Launcher.Core; - -namespace Flow.Launcher -{ - /// - /// Interaction Logic of PriorityChangeWindow.xaml - /// - public partial class PriorityChangeWindow : Window - { - private readonly PluginPair plugin; - private readonly Internationalization translater = InternationalizationManager.Instance; - private readonly PluginViewModel pluginViewModel; - public PriorityChangeWindow(string pluginId, PluginViewModel pluginViewModel) - { - InitializeComponent(); - plugin = PluginManager.GetPluginForId(pluginId); - this.pluginViewModel = pluginViewModel; - if (plugin == null) - { - App.API.ShowMsgBox(translater.GetTranslation("cannotFindSpecifiedPlugin")); - Close(); - } - } - - private void BtnCancel_OnClick(object sender, RoutedEventArgs e) - { - Close(); - } - - private void btnDone_OnClick(object sender, RoutedEventArgs e) - { - if (int.TryParse(tbAction.Text.Trim(), out var newPriority)) - { - pluginViewModel.ChangePriority(newPriority); - Close(); - } - else - { - string msg = translater.GetTranslation("invalidPriority"); - App.API.ShowMsgBox(msg); - } - - } - - private void PriorityChangeWindow_Loaded(object sender, RoutedEventArgs e) - { - tbAction.Text = pluginViewModel.Priority.ToString(); - tbAction.Focus(); - } - private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */ - { - TextBox textBox = Keyboard.FocusedElement as TextBox; - if (textBox != null) - { - TraversalRequest tRequest = new TraversalRequest(FocusNavigationDirection.Next); - textBox.MoveFocus(tRequest); - } - } - } -} diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 5ba011fed..778f00160 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -70,7 +70,8 @@ Maximum="999" Minimum="-999" SpinButtonPlacementMode="Inline" - ToolTip="{DynamicResource priorityToolTip}" /> + ToolTip="{DynamicResource priorityToolTip}" + Value="{Binding Priority, Mode=TwoWay}" /> PluginPair.Metadata.Priority; set { - if (PluginPair.Metadata.Priority != value) - { - ChangePriority(value); - } + PluginPair.Metadata.Priority = value; + PluginSettingsObject.Priority = value; } } @@ -151,20 +149,6 @@ namespace Flow.Launcher.ViewModel OnPropertyChanged(nameof(SearchDelayTimeText)); } - public void ChangePriority(int newPriority) - { - PluginPair.Metadata.Priority = newPriority; - PluginSettingsObject.Priority = newPriority; - OnPropertyChanged(nameof(Priority)); - } - - [RelayCommand] - private void EditPluginPriority() - { - var priorityChangeWindow = new PriorityChangeWindow(PluginPair. Metadata.ID, this); - priorityChangeWindow.ShowDialog(); - } - [RelayCommand] private void OpenPluginDirectory() { From 67268284e0e4ae612a5395973a58b6674b203c4f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 7 Apr 2025 14:40:27 +0800 Subject: [PATCH 059/125] Support numerical box for search delay --- .../Controls/InstalledPluginDisplay.xaml | 3 ++- Flow.Launcher/ViewModel/PluginViewModel.cs | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 778f00160..f57c0e2d9 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -91,7 +91,8 @@ Maximum="1000" Minimum="0" SpinButtonPlacementMode="Inline" - ToolTip="{DynamicResource searchDelayToolTip}" /> + ToolTip="{DynamicResource searchDelayToolTip}" + Value="{Binding PluginSearchDelayTime, Mode=TwoWay}" /> diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 22a69592b..2dff72ac5 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -93,13 +93,23 @@ namespace Flow.Launcher.ViewModel } } - public int? PluginSearchDelayTime + public double PluginSearchDelayTime { - get => PluginPair.Metadata.SearchDelayTime; + get => PluginPair.Metadata.SearchDelayTime == null ? + double.NaN : + PluginPair.Metadata.SearchDelayTime.Value; set { - PluginPair.Metadata.SearchDelayTime = value; - PluginSettingsObject.SearchDelayTime = value; + if (double.IsNaN(value)) + { + PluginPair.Metadata.SearchDelayTime = null; + PluginSettingsObject.SearchDelayTime = null; + } + else + { + PluginPair.Metadata.SearchDelayTime = (int)value; + PluginSettingsObject.SearchDelayTime = (int)value; + } } } From 65f48e3069c173e3f2be4ff255d405112dd0f29f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 7 Apr 2025 14:54:09 +0800 Subject: [PATCH 060/125] Force priority to 0 when inputing empty --- .../Resources/Controls/InstalledPluginDisplay.xaml | 1 + .../Controls/InstalledPluginDisplay.xaml.cs | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index f57c0e2d9..ece66034c 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -71,6 +71,7 @@ Minimum="-999" SpinButtonPlacementMode="Inline" ToolTip="{DynamicResource priorityToolTip}" + ValueChanged="NumberBox_OnValueChanged" Value="{Binding Priority, Mode=TwoWay}" /> diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs index dfa03a204..ab9496266 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs @@ -1,4 +1,6 @@ -namespace Flow.Launcher.Resources.Controls; +using ModernWpf.Controls; + +namespace Flow.Launcher.Resources.Controls; public partial class InstalledPluginDisplay { @@ -6,4 +8,12 @@ public partial class InstalledPluginDisplay { InitializeComponent(); } + + private void NumberBox_OnValueChanged(NumberBox sender, NumberBoxValueChangedEventArgs args) + { + if (double.IsNaN(args.NewValue)) + { + sender.Value = 0; + } + } } From e955e47e5fafcf54b6aa651dcc04db7ed9355523 Mon Sep 17 00:00:00 2001 From: DB p Date: Mon, 7 Apr 2025 22:47:39 +0900 Subject: [PATCH 061/125] - Change combobox to numberbox - Adjust Numberbox Style - Add small change value(10) - Adjust strings --- .../UserSettings/Settings.cs | 4 --- Flow.Launcher/Languages/en.xaml | 10 ++---- .../Controls/InstalledPluginDisplay.xaml | 7 ++-- .../Resources/CustomControlTemplate.xaml | 28 ++++++++++----- .../SettingsPaneGeneralViewModel.cs | 35 +++++-------------- .../SettingsPanePluginsViewModel.cs | 4 +-- .../Views/SettingsPaneGeneral.xaml | 17 +++++---- 7 files changed, 49 insertions(+), 56 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index d89340e19..e304a1b50 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -321,10 +321,6 @@ namespace Flow.Launcher.Infrastructure.UserSettings public bool HideWhenDeactivated { get; set; } = true; public bool SearchQueryResultsWithDelay { get; set; } - - [JsonIgnore] - public IEnumerable SearchDelayTimeRange = new List { 50, 100, 150, 200, 250, 300, 350, 400, 450, 500 }; - public int SearchDelayTime { get; set; } = 150; [JsonConverter(typeof(JsonStringEnumConverter))] diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 5d9b16e0b..f01d0575a 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -108,14 +108,10 @@ Always open preview panel when Flow activates. Press {0} to toggle preview. Shadow effect is not allowed while current theme has blur effect enabled Search Delay - Delay for a while to search when typing. This reduces interface jumpiness and result load. + Adds a short delay while typing to reduce UI flicker and result load. Recommended if your typing speed is average. Default Search Delay Time - Plugin default delay time after which search results appear when typing is stopped. - Very long - Long - Normal - Short - Very short + Wait time before showing results after typing stops. Higher values wait longer. (ms) + Default Search Plugin diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index ece66034c..9a4e3b7b0 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -88,12 +88,15 @@ Text="{DynamicResource searchDelay}" ToolTip="{DynamicResource searchDelayToolTip}" /> + Value="{Binding PluginSearchDelayTime, Mode=TwoWay}"> + diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index b51e5fec0..157910b4a 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -1503,7 +1503,7 @@ - + @@ -2689,10 +2689,20 @@ MinWidth="{TemplateBinding MinWidth}" MinHeight="{TemplateBinding MinHeight}" ui:ValidationHelper.IsTemplateValidationAdornerSite="True" - Background="{TemplateBinding Background}" - BorderBrush="{TemplateBinding BorderBrush}" - BorderThickness="{TemplateBinding BorderThickness}" - CornerRadius="{TemplateBinding ui:ControlHelper.CornerRadius}" /> + Background="{DynamicResource CustomTextBoxBG}" + BorderBrush="{DynamicResource CustomTextBoxOutline}" + BorderThickness="{DynamicResource CustomTextBoxOutlineThickness}" + CornerRadius="4"> + + - + @@ -2788,8 +2798,10 @@ - - + + + + diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 74e2d8340..35dbab647 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -32,25 +32,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public class SearchWindowAlignData : DropdownDataGeneric { } public class SearchPrecisionData : DropdownDataGeneric { } public class LastQueryModeData : DropdownDataGeneric { } - public class SearchDelayTimeData - { - public string Display { get; set; } - public int Value { get; set; } - - public static List GetValues() - { - var settings = Ioc.Default.GetRequiredService(); - var data = new List(); - - foreach (var value in settings.SearchDelayTimeRange) - { - var display = $"{value}ms"; - data.Add(new SearchDelayTimeData { Display = display, Value = value }); - } - - return data; - } - } + public bool StartFlowLauncherOnSystemStartup { @@ -163,21 +145,20 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public List LastQueryModes { get; } = DropdownDataGeneric.GetValues("LastQuery"); - public List SearchDelayTimes { get; } = SearchDelayTimeData.GetValues(); - - public SearchDelayTimeData SearchDelayTime + public int SearchDelayTimeValue { - get => SearchDelayTimes.FirstOrDefault(x => x.Value == Settings.SearchDelayTime); + get => Settings.SearchDelayTime; set { - if (value == null) return; - - if (Settings.SearchDelayTime != value.Value) + if (Settings.SearchDelayTime != value) { - Settings.SearchDelayTime = value.Value; + Settings.SearchDelayTime = value; + OnPropertyChanged(); + OnPropertyChanged(nameof(SearchDelayTimeDisplay)); } } } + public string SearchDelayTimeDisplay => $"{SearchDelayTimeValue}ms"; private void UpdateEnumDropdownLocalizations() { diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index 46e398eb5..4958bb7b7 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -122,7 +122,7 @@ public partial class SettingsPanePluginsViewModel : BaseModel { new TextBlock { - Text = (string)Application.Current.Resources["changePriorityWindow"], + Text = (string)Application.Current.Resources["priority"], FontSize = 18, Margin = new Thickness(0, 0, 0, 10), TextWrapping = TextWrapping.Wrap @@ -134,7 +134,7 @@ public partial class SettingsPanePluginsViewModel : BaseModel }, new TextBlock { - Text = (string)Application.Current.Resources["searchDelayTimeTitle"], + Text = (string)Application.Current.Resources["searchDelay"], FontSize = 18, Margin = new Thickness(0, 24, 0, 10), TextWrapping = TextWrapping.Wrap diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 10e2b549a..657e97f30 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -211,12 +211,17 @@ Title="{DynamicResource searchDelayTime}" Sub="{DynamicResource searchDelayTimeToolTip}" Type="InsideFit"> - + + + From cbf50317d3cb87bd62dbb42ee39adcd6719bbeee Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 8 Apr 2025 00:02:59 +0900 Subject: [PATCH 062/125] Fix content dialog style --- .../Resources/CustomControlTemplate.xaml | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index 157910b4a..d78829471 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -3587,7 +3587,7 @@ - + - + + + + + + + + From ecd019dd6b0c286a6cf223cf598bc1fc57dd4279 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 15:56:54 +0800 Subject: [PATCH 063/125] Move ThemeData class to SharedModels --- Flow.Launcher.Core/Resource/Theme.cs | 1 + Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 6 +++--- Flow.Launcher.Plugin/{ => SharedModels}/ThemeData.cs | 2 +- .../SettingPages/ViewModels/SettingsPaneThemeViewModel.cs | 1 + Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 1 + 5 files changed, 7 insertions(+), 4 deletions(-) rename Flow.Launcher.Plugin/{ => SharedModels}/ThemeData.cs (97%) diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index 4cf9ce7a7..f3eba7ba7 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -16,6 +16,7 @@ using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedModels; using Microsoft.Win32; namespace Flow.Launcher.Core.Resource diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 64bdcec34..1090a3a1e 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -1,6 +1,4 @@ -using Flow.Launcher.Plugin.SharedModels; -using JetBrains.Annotations; -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; @@ -8,6 +6,8 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using System.Windows; +using Flow.Launcher.Plugin.SharedModels; +using JetBrains.Annotations; namespace Flow.Launcher.Plugin { diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs similarity index 97% rename from Flow.Launcher.Plugin/ThemeData.cs rename to Flow.Launcher.Plugin/SharedModels/ThemeData.cs index 1888be65e..6a5e54f55 100644 --- a/Flow.Launcher.Plugin/ThemeData.cs +++ b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs @@ -1,6 +1,6 @@ using System; -namespace Flow.Launcher.Plugin; +namespace Flow.Launcher.Plugin.SharedModels; /// /// Theme data model diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index 58cf3a314..f78704ef2 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -12,6 +12,7 @@ using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher.ViewModel; using ModernWpf; using ThemeManagerForColorSchemeSwitch = ModernWpf.ThemeManager; diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index 4b99efe3b..feacc3f99 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Flow.Launcher.Plugin.SharedModels; namespace Flow.Launcher.Plugin.Sys { From 6c458828bc9d24a58de29240f1417c253c64a7d6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 16:01:46 +0800 Subject: [PATCH 064/125] Fix possible NullReferenceException --- Flow.Launcher.Plugin/SharedModels/ThemeData.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs index 6a5e54f55..322985f3a 100644 --- a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs +++ b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs @@ -41,12 +41,16 @@ public class ThemeData /// public static bool operator ==(ThemeData left, ThemeData right) { + if (left is null && right is null) + return true; return left.Equals(right); } /// public static bool operator !=(ThemeData left, ThemeData right) { + if (left is null && right is null) + return false; return !(left == right); } From 6c5bb7d184d1f5a1284f94647e6f34ce1f0b2b84 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 8 Apr 2025 18:12:10 +1000 Subject: [PATCH 065/125] update summary --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 30004952e..111bc716c 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -228,7 +228,7 @@ namespace Flow.Launcher.Plugin void LogWarn(string className, string message, [CallerMemberName] string methodName = ""); /// - /// Log error message + /// Log error message. Preferred error logging method for plugins. /// void LogError(string className, string message, [CallerMemberName] string methodName = ""); From 537c03f2d751345176bbeacf1d58a657da3aef31 Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Tue, 8 Apr 2025 16:13:58 +0800 Subject: [PATCH 066/125] Fix null check issue Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Flow.Launcher.Plugin/SharedModels/ThemeData.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs index 322985f3a..093e1ee8e 100644 --- a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs +++ b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs @@ -43,6 +43,8 @@ public class ThemeData { if (left is null && right is null) return true; + if (left is null || right is null) + return false; return left.Equals(right); } From b3aa89773ce1fdfadc9dfd06b13acc596d504265 Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Tue, 8 Apr 2025 16:14:17 +0800 Subject: [PATCH 067/125] Use == for != operator Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Flow.Launcher.Plugin/SharedModels/ThemeData.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs index 093e1ee8e..cb389c21f 100644 --- a/Flow.Launcher.Plugin/SharedModels/ThemeData.cs +++ b/Flow.Launcher.Plugin/SharedModels/ThemeData.cs @@ -51,8 +51,6 @@ public class ThemeData /// public static bool operator !=(ThemeData left, ThemeData right) { - if (left is null && right is null) - return false; return !(left == right); } From a2d99573855b145a4ac68f270494c05f07ea06a6 Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Tue, 8 Apr 2025 16:20:11 +0800 Subject: [PATCH 068/125] Log warning if cannot find matched theme Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Core/Resource/Theme.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index f3eba7ba7..d7c619330 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -384,7 +384,12 @@ namespace Flow.Launcher.Core.Resource public ThemeData GetCurrentTheme() { var themes = GetAvailableThemes(); - return themes.FirstOrDefault(t => t.FileNameWithoutExtension == _settings.Theme) ?? themes.FirstOrDefault(); + var matchingTheme = themes.FirstOrDefault(t => t.FileNameWithoutExtension == _settings.Theme); + if (matchingTheme == null) + { + Log.Warn($"No matching theme found for '{_settings.Theme}'. Falling back to the first available theme."); + } + return matchingTheme ?? themes.FirstOrDefault(); } public List GetAvailableThemes() From 7da2884e84ebd45dc70c16cd3dde6f6ef1e2b4af Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 16:29:03 +0800 Subject: [PATCH 069/125] Add locks for win32s & uwps --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 61 +++++++++++++++---- .../Views/Commands/ProgramSettingDisplay.cs | 34 ++++++++--- .../Views/ProgramSetting.xaml.cs | 18 +++--- 3 files changed, 83 insertions(+), 30 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index d3c50b406..6d2ae70fc 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -27,6 +27,9 @@ namespace Flow.Launcher.Plugin.Program internal static List _uwps { get; private set; } internal static Settings _settings { get; private set; } + internal static SemaphoreSlim _win32sLock = new(1, 1); + internal static SemaphoreSlim _uwpsLock = new(1, 1); + internal static PluginInitContext Context { get; private set; } private static readonly List emptyResults = new(); @@ -82,8 +85,11 @@ namespace Flow.Launcher.Plugin.Program { var result = await cache.GetOrCreateAsync(query.Search, async entry => { - var resultList = await Task.Run(() => + var resultList = await Task.Run(async () => { + await _win32sLock.WaitAsync(token); + await _uwpsLock.WaitAsync(token); + try { // Collect all UWP Windows app directories @@ -95,22 +101,26 @@ namespace Flow.Launcher.Plugin.Program .ToArray() : null; return _win32s.Cast() - .Concat(_uwps) - .AsParallel() - .WithCancellation(token) - .Where(HideUninstallersFilter) - .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories)) - .Where(p => p.Enabled) - .Select(p => p.Result(query.Search, Context.API)) - .Where(r => r?.Score > 0) - .ToList(); + .Concat(_uwps) + .AsParallel() + .WithCancellation(token) + .Where(HideUninstallersFilter) + .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories)) + .Where(p => p.Enabled) + .Select(p => p.Result(query.Search, Context.API)) + .Where(r => r?.Score > 0) + .ToList(); } catch (OperationCanceledException) { Log.Debug("|Flow.Launcher.Plugin.Program.Main|Query operation cancelled"); return emptyResults; } - + finally + { + _uwpsLock.Release(); + _win32sLock.Release(); + } }, token); resultList = resultList.Any() ? resultList : emptyResults; @@ -236,14 +246,25 @@ namespace Flow.Launcher.Plugin.Program var newUWPCacheFile = Path.Combine(pluginCachePath, $"{UwpCacheName}.cache"); MoveFile(oldUWPCacheFile, newUWPCacheFile); + await _win32sLock.WaitAsync(); _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List()); + _win32sLock.Release(); + + await _uwpsLock.WaitAsync(); _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List()); + _uwpsLock.Release(); }); + await _win32sLock.WaitAsync(); + await _uwpsLock.WaitAsync(); + Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Count}>"); Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Count}>"); bool cacheEmpty = !_win32s.Any() || !_uwps.Any(); + _win32sLock.Release(); + _uwpsLock.Release(); + if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now) { _ = Task.Run(async () => @@ -267,11 +288,13 @@ namespace Flow.Launcher.Plugin.Program public static async Task IndexWin32ProgramsAsync() { var win32S = Win32.All(_settings); + await _win32sLock.WaitAsync(); _win32s.Clear(); foreach (var win32 in win32S) { _win32s.Add(win32); } + _win32sLock.Release(); ResetCache(); await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); _settings.LastIndexTime = DateTime.Now; @@ -280,11 +303,13 @@ namespace Flow.Launcher.Plugin.Program public static async Task IndexUwpProgramsAsync() { var uwps = UWPPackage.All(_settings); + await _uwpsLock.WaitAsync(); _uwps.Clear(); foreach (var uwp in uwps) { _uwps.Add(uwp); } + _uwpsLock.Release(); ResetCache(); await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); _settings.LastIndexTime = DateTime.Now; @@ -358,26 +383,36 @@ namespace Flow.Launcher.Plugin.Program return menuOptions; } - private static void DisableProgram(IProgram programToDelete) + private static async Task DisableProgram(IProgram programToDelete) { if (_settings.DisabledProgramSources.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) return; + await _uwpsLock.WaitAsync(); if (_uwps.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) { var program = _uwps.First(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier); program.Enabled = false; _settings.DisabledProgramSources.Add(new ProgramSource(program)); + _uwpsLock.Release(); + + // Reindex UWP programs _ = Task.Run(() => { _ = IndexUwpProgramsAsync(); }); + return; } - else if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) + + await _win32sLock.WaitAsync(); + if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) { var program = _win32s.First(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier); program.Enabled = false; _settings.DisabledProgramSources.Add(new ProgramSource(program)); + _win32sLock.Release(); + + // Reindex Win32 programs _ = Task.Run(() => { _ = IndexWin32ProgramsAsync(); diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs index e4d7c323a..b89a2a6ba 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using Flow.Launcher.Plugin.Program.Views.Models; namespace Flow.Launcher.Plugin.Program.Views.Commands @@ -15,21 +16,24 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands .ToList(); } - internal static void DisplayAllPrograms() + internal static async Task DisplayAllProgramsAsync() { + await Main._win32sLock.WaitAsync(); var win32 = Main._win32s .Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier)) .Select(x => new ProgramSource(x)); + ProgramSetting.ProgramSettingDisplayList.AddRange(win32); + Main._win32sLock.Release(); + await Main._uwpsLock.WaitAsync(); var uwp = Main._uwps .Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier)) .Select(x => new ProgramSource(x)); - - ProgramSetting.ProgramSettingDisplayList.AddRange(win32); ProgramSetting.ProgramSettingDisplayList.AddRange(uwp); + Main._uwpsLock.Release(); } - internal static void SetProgramSourcesStatus(List selectedProgramSourcesToDisable, bool status) + internal static async Task SetProgramSourcesStatusAsync(List selectedProgramSourcesToDisable, bool status) { foreach(var program in ProgramSetting.ProgramSettingDisplayList) { @@ -39,14 +43,17 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands } } - foreach(var program in Main._win32s) + await Main._win32sLock.WaitAsync(); + foreach (var program in Main._win32s) { if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status)) { program.Enabled = status; } } + Main._win32sLock.Release(); + await Main._uwpsLock.WaitAsync(); foreach (var program in Main._uwps) { if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status)) @@ -54,6 +61,7 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands program.Enabled = status; } } + Main._uwpsLock.Release(); } internal static void StoreDisabledInSettings() @@ -72,12 +80,22 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands Main._settings.DisabledProgramSources.RemoveAll(t1 => t1.Enabled); } - internal static bool IsReindexRequired(this List selectedItems) + internal static async Task IsReindexRequiredAsync(this List selectedItems) { // Not in cache - if (selectedItems.Any(t1 => t1.Enabled && !Main._uwps.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier)) + await Main._win32sLock.WaitAsync(); + await Main._uwpsLock.WaitAsync(); + try + { + if (selectedItems.Any(t1 => t1.Enabled && !Main._uwps.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier)) && selectedItems.Any(t1 => t1.Enabled && !Main._win32s.Any(x => t1.UniqueIdentifier == x.UniqueIdentifier))) - return true; + return true; + } + finally + { + Main._win32sLock.Release(); + Main._uwpsLock.Release(); + } // ProgramSources holds list of user added directories, // so when we enable/disable we need to reindex to show/not show the programs diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs index 5ad7fcea3..c42bd4f30 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs @@ -183,7 +183,7 @@ namespace Flow.Launcher.Plugin.Program.Views EditProgramSource(selectedProgramSource); } - private void EditProgramSource(ProgramSource selectedProgramSource) + private async void EditProgramSource(ProgramSource selectedProgramSource) { if (selectedProgramSource == null) { @@ -202,13 +202,13 @@ namespace Flow.Launcher.Plugin.Program.Views { if (selectedProgramSource.Enabled) { - ProgramSettingDisplay.SetProgramSourcesStatus(new List { selectedProgramSource }, + await ProgramSettingDisplay.SetProgramSourcesStatusAsync(new List { selectedProgramSource }, true); // sync status in win32, uwp and disabled ProgramSettingDisplay.RemoveDisabledFromSettings(); } else { - ProgramSettingDisplay.SetProgramSourcesStatus(new List { selectedProgramSource }, + await ProgramSettingDisplay.SetProgramSourcesStatusAsync(new List { selectedProgramSource }, false); ProgramSettingDisplay.StoreDisabledInSettings(); } @@ -277,14 +277,14 @@ namespace Flow.Launcher.Plugin.Program.Views } } - private void btnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e) + private async void btnLoadAllProgramSource_OnClick(object sender, RoutedEventArgs e) { - ProgramSettingDisplay.DisplayAllPrograms(); + await ProgramSettingDisplay.DisplayAllProgramsAsync(); ViewRefresh(); } - private void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e) + private async void btnProgramSourceStatus_OnClick(object sender, RoutedEventArgs e) { var selectedItems = programSourceView .SelectedItems.Cast() @@ -311,18 +311,18 @@ namespace Flow.Launcher.Plugin.Program.Views } else if (HasMoreOrEqualEnabledItems(selectedItems)) { - ProgramSettingDisplay.SetProgramSourcesStatus(selectedItems, false); + await ProgramSettingDisplay.SetProgramSourcesStatusAsync(selectedItems, false); ProgramSettingDisplay.StoreDisabledInSettings(); } else { - ProgramSettingDisplay.SetProgramSourcesStatus(selectedItems, true); + await ProgramSettingDisplay.SetProgramSourcesStatusAsync(selectedItems, true); ProgramSettingDisplay.RemoveDisabledFromSettings(); } - if (selectedItems.IsReindexRequired()) + if (await selectedItems.IsReindexRequiredAsync()) ReIndexing(); programSourceView.SelectedItems.Clear(); From dd210ad41968a1e9112fb6b364a08093534ae136 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 16:41:06 +0800 Subject: [PATCH 070/125] Remove RefreshFrameAsync since ChangeTheme calls this function --- Flow.Launcher.Core/Resource/Theme.cs | 2 +- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 6 ++++-- Flow.Launcher/PublicAPIInstance.cs | 5 +---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index d7c619330..59e76e2d2 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -433,7 +433,7 @@ namespace Flow.Launcher.Core.Resource BlurEnabled = IsBlurTheme(); - // Can only apply blur but here also apply drop shadow effect to avoid possible drop shadow effect issues + // Apply blur and drop shadow effect so that we do not need to call it again _ = RefreshFrameAsync(); return true; diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 056c4a437..7701fcdd0 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -367,8 +367,10 @@ namespace Flow.Launcher.Plugin /// Set the current theme /// /// - /// - public void SetCurrentTheme(ThemeData theme); + /// + /// True if the theme is set successfully, false otherwise. + /// + public bool SetCurrentTheme(ThemeData theme); /// Load image from path. Support local, remote and data:image url. /// If image path is missing, it will return a missing icon. diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index b19b21db1..8cce460d7 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -377,11 +377,8 @@ namespace Flow.Launcher public ThemeData GetCurrentTheme() => Theme.GetCurrentTheme(); - public void SetCurrentTheme(ThemeData theme) - { + public bool SetCurrentTheme(ThemeData theme) => Theme.ChangeTheme(theme.FileNameWithoutExtension); - _ = _theme.RefreshFrameAsync(); - } public ValueTask LoadImageAsync(string path, bool loadFullImage = false, bool cacheImage = true) => ImageLoader.LoadAsync(path, loadFullImage, cacheImage); From a3c7be95597f8c0765f0e62749b7f263749e78cd Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 16:49:29 +0800 Subject: [PATCH 071/125] Handle results from SetCurrentTheme --- Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index feacc3f99..f8aeaeafd 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -76,8 +76,10 @@ namespace Flow.Launcher.Plugin.Sys Score = score, Action = c => { - _context.API.SetCurrentTheme(theme); - _context.API.ReQuery(); + if (_context.API.SetCurrentTheme(theme)) + { + _context.API.ReQuery(); + } return false; } }; From 734c5bb67deb769190fa46572083e64ffcef8cf8 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 16:59:27 +0800 Subject: [PATCH 072/125] Fix lock release issue --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 6d2ae70fc..a5fbc6c70 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -367,7 +367,7 @@ namespace Flow.Launcher.Plugin.Program Title = Context.API.GetTranslation("flowlauncher_plugin_program_disable_program"), Action = c => { - DisableProgram(program); + _ = DisableProgramAsync(program); Context.API.ShowMsg( Context.API.GetTranslation("flowlauncher_plugin_program_disable_dlgtitle_success"), Context.API.GetTranslation( @@ -383,7 +383,7 @@ namespace Flow.Launcher.Plugin.Program return menuOptions; } - private static async Task DisableProgram(IProgram programToDelete) + private static async Task DisableProgramAsync(IProgram programToDelete) { if (_settings.DisabledProgramSources.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) return; @@ -403,7 +403,12 @@ namespace Flow.Launcher.Plugin.Program }); return; } - + else + { + // Release the lock if we cannot find the program + _uwpsLock.Release(); + } + await _win32sLock.WaitAsync(); if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) { @@ -418,6 +423,11 @@ namespace Flow.Launcher.Plugin.Program _ = IndexWin32ProgramsAsync(); }); } + else + { + // Release the lock if we cannot find the program + _win32sLock.Release(); + } } public static void StartProcess(Func runProcess, ProcessStartInfo info) From c11ee2f9e78fa626bd7801fed293d990fdfaf682 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 17:20:57 +0800 Subject: [PATCH 073/125] Improve code quality & comments & Fix lock issue --- .../Storage/BinaryStorage.cs | 6 ++-- .../Storage/PluginJsonStorage.cs | 1 + Flow.Launcher.Plugin/Interfaces/ISavable.cs | 9 ++++-- Flow.Launcher/PublicAPIInstance.cs | 6 ---- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 29 +++++++------------ 5 files changed, 20 insertions(+), 31 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs index f218c5d8d..b5de3b50f 100644 --- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs @@ -42,8 +42,7 @@ namespace Flow.Launcher.Infrastructure.Storage public async ValueTask TryLoadAsync(T defaultData) { - if (Data != null) - return Data; + if (Data != null) return Data; if (File.Exists(FilePath)) { @@ -55,8 +54,7 @@ namespace Flow.Launcher.Infrastructure.Storage } await using var stream = new FileStream(FilePath, FileMode.Open); - var d = await DeserializeAsync(stream, defaultData); - Data = d; + Data = await DeserializeAsync(stream, defaultData); } else { diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs index b63e8c1ef..e8cbd70fb 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs @@ -20,6 +20,7 @@ namespace Flow.Launcher.Infrastructure.Storage public PluginJsonStorage() { + // C# related, add python related below var dataType = typeof(T); AssemblyName = dataType.Assembly.GetName().Name; DirectoryPath = Path.Combine(DataLocation.PluginSettingsDirectory, AssemblyName); diff --git a/Flow.Launcher.Plugin/Interfaces/ISavable.cs b/Flow.Launcher.Plugin/Interfaces/ISavable.cs index cabd26962..0d23c0fc8 100644 --- a/Flow.Launcher.Plugin/Interfaces/ISavable.cs +++ b/Flow.Launcher.Plugin/Interfaces/ISavable.cs @@ -1,18 +1,21 @@ namespace Flow.Launcher.Plugin { /// - /// Inherit this interface if additional data e.g. cache needs to be saved. + /// Inherit this interface if additional data. + /// If you need to save data which is not a setting or cache, + /// please implement this interface. /// /// /// For storing plugin settings, prefer /// or . + /// For storing plugin caches, prefer /// or . - /// Once called, your settings will be automatically saved by Flow. + /// Once called, those settings and caches will be automatically saved by Flow. /// public interface ISavable : IFeatures { /// - /// Save additional plugin data, such as cache. + /// Save additional plugin data. /// void Save(); } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 4dd0268d2..a523f90bb 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -229,9 +229,6 @@ namespace Flow.Launcher } } - /// - /// Save plugin settings. - /// public void SavePluginSettings() { foreach (var value in _pluginJsonStorages.Values) @@ -378,9 +375,6 @@ namespace Flow.Launcher } } - /// - /// Save plugin caches. - /// public void SavePluginCaches() { foreach (var value in _pluginBinaryStorages.Values) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index a5fbc6c70..561044981 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -77,10 +77,6 @@ namespace Flow.Launcher.Plugin.Program private static readonly string WindowsAppPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WindowsApps"); - static Main() - { - } - public async Task> QueryAsync(Query query, CancellationToken token) { var result = await cache.GetOrCreateAsync(query.Search, async entry => @@ -101,15 +97,15 @@ namespace Flow.Launcher.Plugin.Program .ToArray() : null; return _win32s.Cast() - .Concat(_uwps) - .AsParallel() - .WithCancellation(token) - .Where(HideUninstallersFilter) - .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories)) - .Where(p => p.Enabled) - .Select(p => p.Result(query.Search, Context.API)) - .Where(r => r?.Score > 0) - .ToList(); + .Concat(_uwps) + .AsParallel() + .WithCancellation(token) + .Where(HideUninstallersFilter) + .Where(p => HideDuplicatedWindowsAppFilter(p, uwpsDirectories)) + .Where(p => p.Enabled) + .Select(p => p.Result(query.Search, Context.API)) + .Where(r => r?.Score > 0) + .ToList(); } catch (OperationCanceledException) { @@ -193,7 +189,6 @@ namespace Flow.Launcher.Plugin.Program await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () => { var pluginCachePath = Context.CurrentPluginMetadata.PluginCacheDirectoryPath; - FilesFolders.ValidateDirectory(pluginCachePath); static void MoveFile(string sourcePath, string destinationPath) @@ -294,10 +289,10 @@ namespace Flow.Launcher.Plugin.Program { _win32s.Add(win32); } - _win32sLock.Release(); ResetCache(); await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); _settings.LastIndexTime = DateTime.Now; + _win32sLock.Release(); } public static async Task IndexUwpProgramsAsync() @@ -309,10 +304,10 @@ namespace Flow.Launcher.Plugin.Program { _uwps.Add(uwp); } - _uwpsLock.Release(); ResetCache(); await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); _settings.LastIndexTime = DateTime.Now; + _uwpsLock.Release(); } public static async Task IndexProgramsAsync() @@ -405,7 +400,6 @@ namespace Flow.Launcher.Plugin.Program } else { - // Release the lock if we cannot find the program _uwpsLock.Release(); } @@ -425,7 +419,6 @@ namespace Flow.Launcher.Plugin.Program } else { - // Release the lock if we cannot find the program _win32sLock.Release(); } } From 54e7652084245900e06c4513a1c6926ae13cf3b3 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 17:22:32 +0800 Subject: [PATCH 074/125] Fix see cref issue --- Flow.Launcher.Core/Storage/IRemovable.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Core/Storage/IRemovable.cs b/Flow.Launcher.Core/Storage/IRemovable.cs index fc34395e0..bcf1cdd5e 100644 --- a/Flow.Launcher.Core/Storage/IRemovable.cs +++ b/Flow.Launcher.Core/Storage/IRemovable.cs @@ -1,18 +1,18 @@ namespace Flow.Launcher.Core.Storage; /// -/// Remove storage instances from instance +/// Remove storage instances from instance /// public interface IRemovable { /// - /// Remove all instances of one plugin + /// Remove all instances of one plugin /// /// public void RemovePluginSettings(string assemblyName); /// - /// Remove all instances of one plugin + /// Remove all instances of one plugin /// /// public void RemovePluginCaches(string cacheDirectory); From 68268026de3261ea5eb7a28ff09f943adc816d0c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 19:21:03 +0800 Subject: [PATCH 075/125] Improve performance --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 561044981..c235fb587 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -186,6 +186,8 @@ namespace Flow.Launcher.Plugin.Program _settings = context.API.LoadSettingJsonStorage(); + var _win32sCount = 0; + var _uwpsCount = 0; await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () => { var pluginCachePath = Context.CurrentPluginMetadata.PluginCacheDirectoryPath; @@ -243,19 +245,18 @@ namespace Flow.Launcher.Plugin.Program await _win32sLock.WaitAsync(); _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List()); + _win32sCount = _win32s.Count; _win32sLock.Release(); await _uwpsLock.WaitAsync(); _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List()); + _uwpsCount = _uwps.Count; _uwpsLock.Release(); }); - await _win32sLock.WaitAsync(); - await _uwpsLock.WaitAsync(); + Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32sCount}>"); + Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwpsCount}>"); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Count}>"); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Count}>"); - - bool cacheEmpty = !_win32s.Any() || !_uwps.Any(); + var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0; _win32sLock.Release(); _uwpsLock.Release(); From 4c4a6c0e22f65a7c1fd0865c70ad69b86e8a0aea Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 19:27:53 +0800 Subject: [PATCH 076/125] Add log handler for indexing --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 52 ++++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index c235fb587..11deb710d 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -283,32 +283,52 @@ namespace Flow.Launcher.Plugin.Program public static async Task IndexWin32ProgramsAsync() { - var win32S = Win32.All(_settings); await _win32sLock.WaitAsync(); - _win32s.Clear(); - foreach (var win32 in win32S) + try { - _win32s.Add(win32); + var win32S = Win32.All(_settings); + _win32s.Clear(); + foreach (var win32 in win32S) + { + _win32s.Add(win32); + } + ResetCache(); + await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); + _settings.LastIndexTime = DateTime.Now; + } + catch (Exception e) + { + Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Win32 programs", e); + } + finally + { + _win32sLock.Release(); } - ResetCache(); - await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); - _settings.LastIndexTime = DateTime.Now; - _win32sLock.Release(); } public static async Task IndexUwpProgramsAsync() { - var uwps = UWPPackage.All(_settings); await _uwpsLock.WaitAsync(); - _uwps.Clear(); - foreach (var uwp in uwps) + try { - _uwps.Add(uwp); + var uwps = UWPPackage.All(_settings); + _uwps.Clear(); + foreach (var uwp in uwps) + { + _uwps.Add(uwp); + } + ResetCache(); + await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); + _settings.LastIndexTime = DateTime.Now; + } + catch (Exception e) + { + Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Uwp programs", e); + } + finally + { + _uwpsLock.Release(); } - ResetCache(); - await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); - _settings.LastIndexTime = DateTime.Now; - _uwpsLock.Release(); } public static async Task IndexProgramsAsync() From aaadf167777a9374f07a523a11b3c102c403ee5b Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Tue, 8 Apr 2025 19:28:29 +0800 Subject: [PATCH 077/125] Fix typos Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 2f8672e13..85c48f8a4 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -366,7 +366,7 @@ namespace Flow.Launcher.Plugin /// Default data to return /// /// - /// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable + /// BinaryStorage utilizes MemoryPack, which means the object must be MemoryPackSerializable /// Task LoadCacheBinaryStorageAsync(string cacheName, string cacheDirectory, T defaultData) where T : new(); From 4749ca208abe9dbcfeb4f80470e2e6e489300e12 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 19:33:48 +0800 Subject: [PATCH 078/125] Improve code comments --- Flow.Launcher.Plugin/Interfaces/ISavable.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Flow.Launcher.Plugin/Interfaces/ISavable.cs b/Flow.Launcher.Plugin/Interfaces/ISavable.cs index 0d23c0fc8..38cbf8e08 100644 --- a/Flow.Launcher.Plugin/Interfaces/ISavable.cs +++ b/Flow.Launcher.Plugin/Interfaces/ISavable.cs @@ -1,8 +1,7 @@ namespace Flow.Launcher.Plugin { /// - /// Inherit this interface if additional data. - /// If you need to save data which is not a setting or cache, + /// Inherit this interface if you need to save additional data which is not a setting or cache, /// please implement this interface. /// /// From 2ff09cf9b0acb61e3323c80481e6eac5e2873891 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 19:41:02 +0800 Subject: [PATCH 079/125] Improve code quality --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 11deb710d..107673f89 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -413,10 +413,7 @@ namespace Flow.Launcher.Plugin.Program _uwpsLock.Release(); // Reindex UWP programs - _ = Task.Run(() => - { - _ = IndexUwpProgramsAsync(); - }); + _ = Task.Run(IndexUwpProgramsAsync); return; } else @@ -433,10 +430,8 @@ namespace Flow.Launcher.Plugin.Program _win32sLock.Release(); // Reindex Win32 programs - _ = Task.Run(() => - { - _ = IndexWin32ProgramsAsync(); - }); + _ = Task.Run(IndexWin32ProgramsAsync); + return; } else { From 653b8335700290f175b7f9bce369a849d0d48f81 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 19:42:59 +0800 Subject: [PATCH 080/125] Fix typos --- Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs | 2 +- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs index b5de3b50f..43bb8dade 100644 --- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs @@ -15,7 +15,7 @@ namespace Flow.Launcher.Infrastructure.Storage /// Normally, it has better performance, but not readable /// /// - /// It utilize MemoryPack, which means the object must be MemoryPackSerializable + /// It utilizes MemoryPack, which means the object must be MemoryPackSerializable /// public class BinaryStorage : ISavable { diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 85c48f8a4..a3020b607 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -380,7 +380,7 @@ namespace Flow.Launcher.Plugin /// Cache directory from plugin metadata /// /// - /// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable + /// BinaryStorage utilizes MemoryPack, which means the object must be MemoryPackSerializable /// Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new(); From d7ca36e60a39892295fe2c42c9e2f81e56b59a66 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 19:44:30 +0800 Subject: [PATCH 081/125] Change variable name --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 107673f89..745b042e6 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -190,8 +190,8 @@ namespace Flow.Launcher.Plugin.Program var _uwpsCount = 0; await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () => { - var pluginCachePath = Context.CurrentPluginMetadata.PluginCacheDirectoryPath; - FilesFolders.ValidateDirectory(pluginCachePath); + var pluginCacheDirectory = Context.CurrentPluginMetadata.PluginCacheDirectoryPath; + FilesFolders.ValidateDirectory(pluginCacheDirectory); static void MoveFile(string sourcePath, string destinationPath) { @@ -237,19 +237,19 @@ namespace Flow.Launcher.Plugin.Program // Move old cache files to the new cache directory var oldWin32CacheFile = Path.Combine(DataLocation.CacheDirectory, $"{Win32CacheName}.cache"); - var newWin32CacheFile = Path.Combine(pluginCachePath, $"{Win32CacheName}.cache"); + var newWin32CacheFile = Path.Combine(pluginCacheDirectory, $"{Win32CacheName}.cache"); MoveFile(oldWin32CacheFile, newWin32CacheFile); var oldUWPCacheFile = Path.Combine(DataLocation.CacheDirectory, $"{UwpCacheName}.cache"); - var newUWPCacheFile = Path.Combine(pluginCachePath, $"{UwpCacheName}.cache"); + var newUWPCacheFile = Path.Combine(pluginCacheDirectory, $"{UwpCacheName}.cache"); MoveFile(oldUWPCacheFile, newUWPCacheFile); await _win32sLock.WaitAsync(); - _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List()); + _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCacheDirectory, new List()); _win32sCount = _win32s.Count; _win32sLock.Release(); await _uwpsLock.WaitAsync(); - _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List()); + _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCacheDirectory, new List()); _uwpsCount = _uwps.Count; _uwpsLock.Release(); }); From 482e37316a1fee76b924e3b151a4507a42ad2cb7 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 19:46:40 +0800 Subject: [PATCH 082/125] Remove useless releases --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 745b042e6..a50868b69 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -258,9 +258,6 @@ namespace Flow.Launcher.Plugin.Program var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0; - _win32sLock.Release(); - _uwpsLock.Release(); - if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now) { _ = Task.Run(async () => From d30f292e3129aeab196b21380a3076f860a976e3 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 20:19:04 +0800 Subject: [PATCH 083/125] Remove unused string --- Flow.Launcher/Languages/en.xaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index f01d0575a..7e5a554a9 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -149,7 +149,6 @@ Plugins: {0} - Fail to remove plugin settings files, please remove them manually Fail to remove plugin cache Plugins: {0} - Fail to remove plugin cache files, please remove them manually - Default Plugin Store From 970bb3ac1268f8e3e443f48aef77d80324b2da15 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 20:30:40 +0800 Subject: [PATCH 084/125] Add code comments --- Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs index ab9496266..a27a00782 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs @@ -9,6 +9,7 @@ public partial class InstalledPluginDisplay InitializeComponent(); } + // This is used for PriorityControl to force its value to be 0 when the user clears the value private void NumberBox_OnValueChanged(NumberBox sender, NumberBoxValueChangedEventArgs args) { if (double.IsNaN(args.NewValue)) From 61fa4602d529c345616aaea87dd65af14589f77c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:02:42 +0800 Subject: [PATCH 085/125] Disable search delay number box when search delay is disabled --- .../Resources/Controls/InstalledPluginDisplay.xaml | 9 +++++---- Flow.Launcher/ViewModel/PluginViewModel.cs | 5 +++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 9a4e3b7b0..63d1af6b1 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -90,13 +90,14 @@ - + Value="{Binding PluginSearchDelayTime, Mode=TwoWay}" /> diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 2dff72ac5..5f19459c9 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -3,9 +3,11 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; +using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure.Image; +using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Resources.Controls; @@ -13,6 +15,8 @@ namespace Flow.Launcher.ViewModel { public partial class PluginViewModel : BaseModel { + private static readonly Settings Settings = Ioc.Default.GetRequiredService(); + private readonly PluginPair _pluginPair; public PluginPair PluginPair { @@ -148,6 +152,7 @@ namespace Flow.Launcher.ViewModel App.API.GetTranslation("default") : App.API.GetTranslation($"SearchDelayTime{PluginPair.Metadata.SearchDelayTime}"); public Infrastructure.UserSettings.Plugin PluginSettingsObject{ get; init; } + public bool SearchDelayEnabled => Settings.SearchQueryResultsWithDelay; public void OnActionKeywordsChanged() { From ade4fbf7f2a905ef41cdf98e82dcd484d1400367 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:02:56 +0800 Subject: [PATCH 086/125] Adjust number box width --- Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 63d1af6b1..4a89d811f 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -88,7 +88,7 @@ Text="{DynamicResource searchDelay}" ToolTip="{DynamicResource searchDelayToolTip}" /> Date: Tue, 8 Apr 2025 21:04:04 +0800 Subject: [PATCH 087/125] Change default search delay time to value --- Flow.Launcher/Languages/en.xaml | 1 - Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml | 2 +- Flow.Launcher/ViewModel/PluginViewModel.cs | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 7e5a554a9..609859d0d 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -111,7 +111,6 @@ Adds a short delay while typing to reduce UI flicker and result load. Recommended if your typing speed is average. Default Search Delay Time Wait time before showing results after typing stops. Higher values wait longer. (ms) - Default Search Plugin diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 4a89d811f..231036244 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -93,7 +93,7 @@ IsEnabled="{Binding SearchDelayEnabled}" Maximum="1000" Minimum="0" - PlaceholderText="{DynamicResource searchDelayPlaceHolder}" + PlaceholderText="{Binding DefaultSearchDelay}" SmallChange="10" SpinButtonPlacementMode="Compact" ToolTip="{DynamicResource searchDelayToolTip}" diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 5f19459c9..da0ed70fa 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -153,6 +153,7 @@ namespace Flow.Launcher.ViewModel App.API.GetTranslation($"SearchDelayTime{PluginPair.Metadata.SearchDelayTime}"); public Infrastructure.UserSettings.Plugin PluginSettingsObject{ get; init; } public bool SearchDelayEnabled => Settings.SearchQueryResultsWithDelay; + public string DefaultSearchDelay => Settings.SearchDelayTime.ToString(); public void OnActionKeywordsChanged() { From 2589fac0bcb1cd28b0e3074c7bacd3e6baaad27e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:23:02 +0800 Subject: [PATCH 088/125] Remove useless function --- Flow.Launcher.Infrastructure/Stopwatch.cs | 34 ----------------------- 1 file changed, 34 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Stopwatch.cs b/Flow.Launcher.Infrastructure/Stopwatch.cs index dd6edaff9..784d323fe 100644 --- a/Flow.Launcher.Infrastructure/Stopwatch.cs +++ b/Flow.Launcher.Infrastructure/Stopwatch.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using Flow.Launcher.Infrastructure.Logger; @@ -7,8 +6,6 @@ namespace Flow.Launcher.Infrastructure { public static class Stopwatch { - private static readonly Dictionary Count = new Dictionary(); - private static readonly object Locker = new object(); /// /// This stopwatch will appear only in Debug mode /// @@ -62,36 +59,5 @@ namespace Flow.Launcher.Infrastructure Log.Info(info); return milliseconds; } - - - - public static void StartCount(string name, Action action) - { - var stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); - action(); - stopWatch.Stop(); - var milliseconds = stopWatch.ElapsedMilliseconds; - lock (Locker) - { - if (Count.ContainsKey(name)) - { - Count[name] += milliseconds; - } - else - { - Count[name] = 0; - } - } - } - - public static void EndCount() - { - foreach (var key in Count.Keys) - { - string info = $"{key} already cost {Count[key]}ms"; - Log.Debug(info); - } - } } } From d09899e15c32be3d1755b6222cdae4919735d2fd Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 8 Apr 2025 22:31:33 +0900 Subject: [PATCH 089/125] Adjust Placeholder color --- .../Resources/CustomControlTemplate.xaml | 25 +++++++++++-------- Flow.Launcher/Resources/Dark.xaml | 1 + Flow.Launcher/Resources/Light.xaml | 3 +++ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index d78829471..ffa5eea41 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -2777,7 +2777,7 @@ - + @@ -3587,7 +3587,7 @@ - + - + - + diff --git a/Flow.Launcher/Resources/Dark.xaml b/Flow.Launcher/Resources/Dark.xaml index e8629a981..498e96bff 100644 --- a/Flow.Launcher/Resources/Dark.xaml +++ b/Flow.Launcher/Resources/Dark.xaml @@ -106,6 +106,7 @@ #f5f5f5 #464646 #ffffff + #272727 diff --git a/Flow.Launcher/Resources/Light.xaml b/Flow.Launcher/Resources/Light.xaml index aa6da9fb2..0f1e98a6b 100644 --- a/Flow.Launcher/Resources/Light.xaml +++ b/Flow.Launcher/Resources/Light.xaml @@ -97,8 +97,11 @@ #f5f5f5 #878787 #1b1b1b + #f6f6f6 + + From e753bb79b1985de78f21d68dfd02f0b1160f919d Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:32:18 +0800 Subject: [PATCH 090/125] Add public methods --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 26 +++++++++++++++++++ Flow.Launcher/PublicAPIInstance.cs | 13 ++++++++++ 2 files changed, 39 insertions(+) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 273676bfb..6d9e5f755 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -473,5 +473,31 @@ namespace Flow.Launcher.Plugin /// /// public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false); + + /// + /// Log debug message of the time taken to execute a method + /// Message will only be logged in Debug mode + /// + /// The time taken to execute the method in milliseconds + public long StopWatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = ""); + + /// + /// Log debug message of the time taken to execute a method asynchronously + /// Message will only be logged in Debug mode + /// + /// The time taken to execute the method in milliseconds + public Task StopWatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); + + /// + /// Log info message of the time taken to execute a method + /// + /// The time taken to execute the method in milliseconds + public long StopWatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = ""); + + /// + /// Log info message of the time taken to execute a method asynchronously + /// + /// The time taken to execute the method in milliseconds + public Task StopWatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index b67ef6ab6..b7aaef143 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -31,6 +31,7 @@ using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.ViewModel; using JetBrains.Annotations; using Squirrel; +using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher { @@ -431,6 +432,18 @@ namespace Flow.Launcher public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false) => PluginManager.UninstallPluginAsync(pluginMetadata, removePluginSettings); + public long StopWatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = "") => + Stopwatch.Debug($"|{className}.{methodName}|{message}", action); + + public Task StopWatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => + Stopwatch.DebugAsync($"|{className}.{methodName}|{message}", action); + + public long StopWatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = "") => + Stopwatch.Normal($"|{className}.{methodName}|{message}", action); + + public Task StopWatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => + Stopwatch.NormalAsync($"|{className}.{methodName}|{message}", action); + #endregion #region Private Methods From f99859ad1eb4fc5f94077327d60f689b8507b16a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:38:17 +0800 Subject: [PATCH 091/125] Change api function names --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 8 ++++---- Flow.Launcher/PublicAPIInstance.cs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 6d9e5f755..55f09dc3b 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -479,25 +479,25 @@ namespace Flow.Launcher.Plugin /// Message will only be logged in Debug mode /// /// The time taken to execute the method in milliseconds - public long StopWatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = ""); + public long StopwatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = ""); /// /// Log debug message of the time taken to execute a method asynchronously /// Message will only be logged in Debug mode /// /// The time taken to execute the method in milliseconds - public Task StopWatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); + public Task StopwatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); /// /// Log info message of the time taken to execute a method /// /// The time taken to execute the method in milliseconds - public long StopWatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = ""); + public long StopwatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = ""); /// /// Log info message of the time taken to execute a method asynchronously /// /// The time taken to execute the method in milliseconds - public Task StopWatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); + public Task StopwatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index b7aaef143..95ef6c9f3 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -432,16 +432,16 @@ namespace Flow.Launcher public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false) => PluginManager.UninstallPluginAsync(pluginMetadata, removePluginSettings); - public long StopWatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = "") => + public long StopwatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = "") => Stopwatch.Debug($"|{className}.{methodName}|{message}", action); - public Task StopWatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => + public Task StopwatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => Stopwatch.DebugAsync($"|{className}.{methodName}|{message}", action); - public long StopWatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = "") => + public long StopwatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = "") => Stopwatch.Normal($"|{className}.{methodName}|{message}", action); - public Task StopWatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => + public Task StopwatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => Stopwatch.NormalAsync($"|{className}.{methodName}|{message}", action); #endregion From 19aa42314b7d335768abe33733e9394429acdc56 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:38:33 +0800 Subject: [PATCH 092/125] Use api functions in ImageLoader --- .../Image/ImageLoader.cs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 41a33104b..1483c5865 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -7,13 +7,20 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Media; using System.Windows.Media.Imaging; -using Flow.Launcher.Infrastructure.Logger; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.Storage; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Infrastructure.Image { public static class ImageLoader { + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + + private static readonly string ClassName = nameof(ImageLoader); + private static readonly ImageCache ImageCache = new(); private static SemaphoreSlim storageLock { get; } = new SemaphoreSlim(1, 1); private static BinaryStorage> _storage; @@ -47,15 +54,14 @@ namespace Flow.Launcher.Infrastructure.Image _ = Task.Run(async () => { - await Stopwatch.NormalAsync("|ImageLoader.Initialize|Preload images cost", async () => + await API.StopwatchLogInfoAsync(ClassName, "Preload images cost", async () => { foreach (var (path, isFullImage) in usage) { await LoadAsync(path, isFullImage); } }); - Log.Info( - $"|ImageLoader.Initialize|Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}"); + API.LogInfo(ClassName, $"Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}"); }); } @@ -71,7 +77,7 @@ namespace Flow.Launcher.Infrastructure.Image } catch (System.Exception e) { - Log.Exception($"|ImageLoader.SaveAsync|Failed to save image cache to file", e); + API.LogException(ClassName, "Failed to save image cache to file", e); } finally { @@ -166,8 +172,8 @@ namespace Flow.Launcher.Infrastructure.Image } catch (System.Exception e2) { - Log.Exception($"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e); - Log.Exception($"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2); + API.LogException(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e); + API.LogException(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2); ImageSource image = ImageCache[Constant.MissingImgIcon, false]; ImageCache[path, false] = image; From 9bc27a4ecd16a52d2d05a7baee1d33e5555128fd Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 8 Apr 2025 23:41:15 +1000 Subject: [PATCH 093/125] New Crowdin updates (#3348) --- Flow.Launcher/Languages/ar.xaml | 47 +++++- Flow.Launcher/Languages/cs.xaml | 47 +++++- Flow.Launcher/Languages/da.xaml | 47 +++++- Flow.Launcher/Languages/de.xaml | 69 +++++++-- Flow.Launcher/Languages/es-419.xaml | 47 +++++- Flow.Launcher/Languages/es.xaml | 47 +++++- Flow.Launcher/Languages/fr.xaml | 47 +++++- Flow.Launcher/Languages/he.xaml | 57 +++++-- Flow.Launcher/Languages/it.xaml | 47 +++++- Flow.Launcher/Languages/ja.xaml | 47 +++++- Flow.Launcher/Languages/ko.xaml | 53 ++++++- Flow.Launcher/Languages/nb.xaml | 47 +++++- Flow.Launcher/Languages/nl.xaml | 47 +++++- Flow.Launcher/Languages/pl.xaml | 47 +++++- Flow.Launcher/Languages/pt-br.xaml | 47 +++++- Flow.Launcher/Languages/pt-pt.xaml | 53 ++++++- Flow.Launcher/Languages/ru.xaml | 47 +++++- Flow.Launcher/Languages/sk.xaml | 47 +++++- Flow.Launcher/Languages/sr.xaml | 47 +++++- Flow.Launcher/Languages/tr.xaml | 47 +++++- Flow.Launcher/Languages/uk-UA.xaml | 47 +++++- Flow.Launcher/Languages/vi.xaml | 47 +++++- Flow.Launcher/Languages/zh-cn.xaml | 49 +++++- Flow.Launcher/Languages/zh-tw.xaml | 47 +++++- .../Languages/sk.xaml | 2 +- .../Languages/ko.xaml | 2 +- .../Languages/de.xaml | 4 +- .../Languages/ar.xaml | 2 + .../Languages/cs.xaml | 2 + .../Languages/da.xaml | 2 + .../Languages/de.xaml | 2 + .../Languages/es-419.xaml | 2 + .../Languages/es.xaml | 2 + .../Languages/fr.xaml | 2 + .../Languages/he.xaml | 2 + .../Languages/it.xaml | 2 + .../Languages/ja.xaml | 2 + .../Languages/ko.xaml | 2 + .../Languages/nb.xaml | 2 + .../Languages/nl.xaml | 2 + .../Languages/pl.xaml | 2 + .../Languages/pt-br.xaml | 2 + .../Languages/pt-pt.xaml | 2 + .../Languages/ru.xaml | 2 + .../Languages/sk.xaml | 2 + .../Languages/sr.xaml | 2 + .../Languages/tr.xaml | 2 + .../Languages/uk-UA.xaml | 2 + .../Languages/vi.xaml | 2 + .../Languages/zh-cn.xaml | 2 + .../Languages/zh-tw.xaml | 2 + .../Languages/de.xaml | 4 +- .../Languages/he.xaml | 2 +- .../Languages/de.xaml | 2 +- .../Languages/ar.xaml | 14 +- .../Languages/cs.xaml | 14 +- .../Languages/da.xaml | 14 +- .../Languages/de.xaml | 20 ++- .../Languages/es-419.xaml | 14 +- .../Languages/es.xaml | 14 +- .../Languages/fr.xaml | 14 +- .../Languages/he.xaml | 14 +- .../Languages/it.xaml | 14 +- .../Languages/ja.xaml | 14 +- .../Languages/ko.xaml | 14 +- .../Languages/nb.xaml | 14 +- .../Languages/nl.xaml | 14 +- .../Languages/pl.xaml | 14 +- .../Languages/pt-br.xaml | 14 +- .../Languages/pt-pt.xaml | 18 ++- .../Languages/ru.xaml | 14 +- .../Languages/sk.xaml | 14 +- .../Languages/sr.xaml | 14 +- .../Languages/tr.xaml | 14 +- .../Languages/uk-UA.xaml | 14 +- .../Languages/vi.xaml | 14 +- .../Languages/zh-cn.xaml | 14 +- .../Languages/zh-tw.xaml | 14 +- .../Languages/ar.xaml | 2 +- .../Languages/cs.xaml | 2 +- .../Languages/da.xaml | 2 +- .../Languages/de.xaml | 8 +- .../Languages/es-419.xaml | 2 +- .../Languages/es.xaml | 2 +- .../Languages/fr.xaml | 2 +- .../Languages/he.xaml | 2 +- .../Languages/it.xaml | 2 +- .../Languages/ja.xaml | 2 +- .../Languages/ko.xaml | 2 +- .../Languages/nb.xaml | 2 +- .../Languages/nl.xaml | 2 +- .../Languages/pl.xaml | 2 +- .../Languages/pt-br.xaml | 2 +- .../Languages/pt-pt.xaml | 2 +- .../Languages/ru.xaml | 9 +- .../Languages/sk.xaml | 2 +- .../Languages/sr.xaml | 2 +- .../Languages/tr.xaml | 2 +- .../Languages/uk-UA.xaml | 2 +- .../Languages/vi.xaml | 2 +- .../Languages/zh-cn.xaml | 2 +- .../Languages/zh-tw.xaml | 2 +- .../Properties/Resources.de-DE.resx | 8 +- .../Properties/Resources.he-IL.resx | 2 +- .../Properties/Resources.ko-KR.resx | 2 +- .../Properties/Resources.pt-PT.resx | 140 +++++++++--------- .../Properties/Resources.sk-SK.resx | 2 +- 107 files changed, 1536 insertions(+), 263 deletions(-) diff --git a/Flow.Launcher/Languages/ar.xaml b/Flow.Launcher/Languages/ar.xaml index a57179da6..b5eafaae9 100644 --- a/Flow.Launcher/Languages/ar.xaml +++ b/Flow.Launcher/Languages/ar.xaml @@ -7,6 +7,11 @@ انقر فوق لا إذا كان مثبتاً بالفعل، وسوف يطلب منك تحديد المجلد الذي يحتوي على {1} القابل للتنفيذ الرجاء اختيار الملف التنفيذي لـ {0} + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + تعذر تعيين مسار الملف التنفيذي لـ {0}، يرجى المحاولة من إعدادات Flow (قم بالتمرير إلى الأسفل). فشل في تهيئة الإضافات الإضافات: {0} - فشل في التحميل وسيتم تعطيلها، يرجى الاتصال بمطور الإضافة للحصول على المساعدة @@ -37,7 +42,7 @@ وضع اللعب تعليق استخدام مفاتيح التشغيل السريع. إعادة تعيين الموقع - إعادة تعيين موضع نافذة البحث + Type here to search الإعدادات @@ -70,8 +75,6 @@ تفريغ الاستعلام الأخير Preserve Last Action Keyword Select Last Action Keyword - ارتفاع ثابت للنافذة - ارتفاع النافذة غير قابل للتعديل عن طريق السحب. الحد الأقصى للنتائج المعروضة يمكنك أيضًا تعديل هذا بسرعة باستخدام CTRL+Plus وCTRL+Minus. تجاهل مفاتيح التشغيل السريع في وضع ملء الشاشة @@ -102,6 +105,15 @@ دائمًا معاينة فتح لوحة المعاينة دائمًا عند تنشيط Flow. اضغط على {0} للتبديل بين المعاينة وعدمها. تأثير الظل غير مسموح به بينما يتم تمكين تأثير التمويه في السمة الحالية + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short البحث عن إضافة @@ -118,6 +130,8 @@ كلمة الفعل الحالية كلمة فعل جديدة تغيير كلمات الفعل + Plugin seach delay time + Change Plugin Seach Delay Time الأولوية الحالية أولوية جديدة الأولوية @@ -131,6 +145,9 @@ إلغاء التثبيت Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default متجر الإضافات @@ -193,8 +210,20 @@ مخصص الساعة التاريخ + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + بلا + Acrylic + Mica + Mica Alt هذه السمة تدعم الوضعين (فاتح/داكن). هذه السمة تدعم الخلفية الضبابية الشفافة. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. مفتاح الاختصار @@ -294,6 +323,9 @@ مجلد السجلات مسح السجلات هل أنت متأكد أنك تريد حذف جميع السجلات؟ + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information معالج الترحيب موقع بيانات المستخدم يتم حفظ إعدادات المستخدم والإضافات المثبتة في مجلد بيانات المستخدم. قد يختلف هذا الموقع اعتمادًا على ما إذا كان في وضع النقل أم لا. @@ -335,9 +367,16 @@ لا يمكن العثور على الإضافة المحددة كلمة المفتاح الجديدة لا يمكن أن تكون فارغة تم تعيين كلمة المفتاح الجديدة هذه إلى إضافة أخرى، يرجى اختيار كلمة أخرى + This new Action Keyword is the same as old, please choose a different one نجاح اكتمل بنجاح - أدخل كلمة المفتاح التي ترغب في استخدامها لبدء الإضافة. استخدم * إذا كنت لا ترغب في تحديد أي كلمة، وسيتم تشغيل الإضافة بدون كلمات مفتاحية. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time مفتاح اختصار الاستعلام المخصص diff --git a/Flow.Launcher/Languages/cs.xaml b/Flow.Launcher/Languages/cs.xaml index 92721b70a..806e9f203 100644 --- a/Flow.Launcher/Languages/cs.xaml +++ b/Flow.Launcher/Languages/cs.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Herní režim Potlačit užívání klávesových zkratek. Obnovit pozici - Obnovit pozici vyhledávacího okna + Type here to search Nastavení @@ -70,8 +75,6 @@ Smazat poslední dotaz Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. Počet zobrazených výsledků Toto nastavení můžete také rychle upravit pomocí CTRL + Plus a CTRL + Minus. Ignorovat klávesové zkratky v režimu celé obrazovky @@ -102,6 +105,15 @@ Vždy zobrazit náhled Při aktivaci služby Flow vždy otevřete panel náhledu. Stisknutím klávesy {0} přepnete náhled. Stínový efekt není povolen, pokud je aktivní efekt rozostření + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Vyhledat plugin @@ -118,6 +130,8 @@ Aktuální aktivační příkaz Nový aktivační příkaz Upravit aktivační příkaz + Plugin seach delay time + Change Plugin Seach Delay Time Aktuální priorita Nová priorita Priorita @@ -131,6 +145,9 @@ Odinstalovat Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Obchod s pluginy @@ -193,8 +210,20 @@ Vlastní Hodiny Datum + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Klávesová zkratka @@ -294,6 +323,9 @@ Složka s logy Vymazat logy Opravdu chcete odstranit všechny logy? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Průvodce User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ Nepodařilo se najít zadaný plugin Nový aktivační příkaz nemůže být prázdný Nový aktivační příkaz byl již přiřazen jinému pluginu, vyberte jiný aktivační příkaz + This new Action Keyword is the same as old, please choose a different one Úspěšné Úspěšně dokončeno - Zadejte aktivační příkaz, který je nutný ke spuštění pluginu. Pokud nechcete zadávat aktivační příkaz, použijte * a plugin bude spuštěn bez aktivačního příkazu. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Vlastní klávesová zkratka pro vyhledávání diff --git a/Flow.Launcher/Languages/da.xaml b/Flow.Launcher/Languages/da.xaml index 629173f74..6055a79e1 100644 --- a/Flow.Launcher/Languages/da.xaml +++ b/Flow.Launcher/Languages/da.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Game Mode Suspend the use of Hotkeys. Position Reset - Reset search window position + Type here to search Indstillinger @@ -70,8 +75,6 @@ Empty last Query Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. Maksimum antal resultater vist You can also quickly adjust this by using CTRL+Plus and CTRL+Minus. Ignorer genvejstaster i fuldskærmsmode @@ -102,6 +105,15 @@ Always Preview Always open preview panel when Flow activates. Press {0} to toggle preview. Shadow effect is not allowed while current theme has blur effect enabled + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Search Plugin @@ -118,6 +130,8 @@ Current action keyword New action keyword Change Action Keywords + Plugin seach delay time + Change Plugin Seach Delay Time Current Priority New Priority Priority @@ -131,6 +145,9 @@ Uninstall Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Plugin Store @@ -193,8 +210,20 @@ Custom Clock Date + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Genvejstast @@ -294,6 +323,9 @@ Log Folder Clear Logs Are you sure you want to delete all logs? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ Kan ikke finde det valgte plugin Nyt nøgleord må ikke være tomt Nyt nøgleord er tilknyttet et andet plugin, tilknyt venligst et andet nyt nøgeleord + This new Action Keyword is the same as old, please choose a different one Fortsæt Completed successfully - Brug * hvis du ikke vil angive et nøgleord + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Tilpasset søgegenvejstast diff --git a/Flow.Launcher/Languages/de.xaml b/Flow.Launcher/Languages/de.xaml index 8a7e3498a..4fb441d8c 100644 --- a/Flow.Launcher/Languages/de.xaml +++ b/Flow.Launcher/Languages/de.xaml @@ -7,13 +7,18 @@ Klicken Sie auf „Nein“, wenn es bereits installiert ist, und Sie werden aufgefordert, den Ordner auszuwählen, der die ausführbare Datei {1} enthält Bitte wählen Sie die ausführbare Datei {0} aus + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Der Pfad zur ausführbaren Datei {0} kann nicht festgelegt werden. Bitte versuchen Sie es in den Einstellungen von Flow (scrollen Sie nach unten). Plug-ins können nicht initialisiert werden - Plug-ins: {0} - nicht geladen werden und wird deaktiviert, bitte kontaktiere Sie den Ersteller des Plug-ins für Hilfe + Plug-ins: {0} - nicht geladen werden und wird deaktiviert, bitte kontaktieren Sie den Ersteller des Plug-ins für Hilfe Hotkey "{0}" konnte nicht registriert werden. Der Hotkey ist möglicherweise von einem anderen Programm in Verwendung. Wechseln Sie zu einem anderen Hotkey oder beenden Sie das andere Programm. - Failed to unregister hotkey "{0}". Please try again or see log for details + Registrierung des Hotkeys "{0}" konnte nicht aufgehoben werden. Bitte versuchen Sie es erneut oder lesen Sie das Log für Details Flow Launcher Konnte nicht gestartet werden {0} Flow Launcher Plug-in-Dateiformat ungültig @@ -37,7 +42,7 @@ Spielmodus Aussetzen der Verwendung von Hotkeys. Position zurücksetzen - Position des Suchfensters zurücksetze + Type here to search Einstellungen @@ -45,9 +50,9 @@ Portabler Modus Speichern Sie alle Einstellungen und Benutzerdaten in einem Ordner (nützlich bei Verwendung von Wechsellaufwerken oder Cloud-Diensten). Flow Launcher bei Systemstart starten - Use logon task instead of startup entry for faster startup experience - After uninstallation, you need to manually remove this task (Flow.Launcher Startup) via Task Scheduler - Fehler bei Einstellungsstart bei Start + Log-on-Aufgabe anstelle des Starteintrags für schnelleres Startup-Erfahrung verwenden + Nach der Deinstallation müssen Sie diese Aufgabe (Flow.Launcher Startup) via Task-Scheduler manuell entfernen + Fehler bei Einstellungsstart beim Start Flow Launcher ausblenden, wenn Fokus verloren geht Versionsbenachrichtigungen nicht zeigen Position des Suchfensters @@ -70,8 +75,6 @@ Letzte Abfrage leeren Letztes Aktions-Schlüsselwort beibehalten Letztes Aktions-Schlüsselwort auswählen - Feste Fensterhöhe - Die Fensterhöhe ist durch Ziehen nicht anpassbar. Maximal gezeigte Ergebnisse Sie können dies auch unter Verwendung von STRG+Plus und STRG+Minus schnell anpassen. Hotkeys im Vollbildmodus ignorieren @@ -102,6 +105,15 @@ Immer Vorschau Vorschau-Panel immer öffnen, wenn Flow aktiviert ist. Drücken Sie {0}, um Vorschau umzuschalten. Schatteneffekt ist nicht erlaubt, während das aktuelle Theme den Unschärfe-Effekt aktiviert hat + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Plug-in suchen @@ -118,6 +130,8 @@ Aktuelles Action-Schlüsselwort Neues Aktions-Schlüsselwort Aktions-Schlüsselwörter ändern + Plugin seach delay time + Change Plugin Seach Delay Time Aktuelle Priorität Neue Priorität Priorität @@ -129,8 +143,11 @@ Version Website Deinstallieren - Fail to remove plugin settings - Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Plug-in-Einstellungen können nicht entfernt werden + Plug-ins: {0} - Plug-in-Einstellungsdateien können nicht entfernt werden, bitte entfernen Sie diese manuell + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Plug-in-Store @@ -193,8 +210,20 @@ Benutzerdefiniert Uhr Datum + Backdrop-Typ + Backdrop supported starting from Windows 11 build 22000 and above + Keine + Acrylic + Mica + Mica Alt Dieses Theme unterstützt zwei Modi (hell/dunkel). Dieses Theme unterstützt Unschärfe und transparenten Hintergrund. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Hotkey @@ -294,11 +323,14 @@ Ordner »Logs« Logs löschen Sind Sie sicher, dass Sie alle Logs löschen wollen? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Assistent Speicherort für Benutzerdaten Benutzereinstellungen und installierte Plug-ins werden im Ordner für Benutzerdaten gespeichert. Dieser Speicherort kann variieren, je nachdem, ob sich das Programm im portablen Modus befindet oder nicht. Ordner öffnen - Log Level + Log-Ebene Debug Info @@ -335,9 +367,16 @@ Das angegebene Plug-in kann nicht gefunden werden Neues Aktions-Schlüsselwort darf nicht leer sein Dieses neue Aktions-Schlüsselwort ist bereits einem anderen Plug-in zugewiesen, bitte wählen Sie ein anderes + Dieses neue Aktions-Schlüsselwort ist dasselbe wie das alte, bitte wählen Sie ein anderes Erfolg Erfolgreich abgeschlossen - Geben Sie das Aktions-Schlüsselwort ein, das Sie verwenden möchten, um das Plug-in zu starten. Verwenden Sie *, wenn Sie keines angeben möchten, und das Plug-in wird ohne irgendwelche Aktions-Schlüsselwörter ausgelöst. + Geben Sie die Aktions-Schlüsselwörter ein, die Sie zum Starten des Plug-ins verwenden möchten, und trennen Sie sie durch Leerzeichen voneinander ab. Verwenden Sie *, wenn Sie keine spezifizieren möchten, und das Plug-in wird ohne jegliche Aktions-Schlüsselwörter ausgelöst. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Benutzerdefinierter Abfrage-Hotkey @@ -388,9 +427,9 @@ Wenn Sie bei der Eingabe eines Shortcuts ein '@'-Präfix hinzufügen, stimmt die Bericht erfolgreich gesendet Bericht konnte nicht gesendet werden Flow Launcher hat einen Fehler - Please open new issue in - 1. Upload log file: {0} - 2. Copy below exception message + Bitte öffnen Sie einen neuen Fall in + 1. Logdatei hochladen: {0} + 2. Kopieren Sie die Ausnahmemeldung unterhalb Bitte warten Sie ... diff --git a/Flow.Launcher/Languages/es-419.xaml b/Flow.Launcher/Languages/es-419.xaml index 1ab69727b..23d58eca3 100644 --- a/Flow.Launcher/Languages/es-419.xaml +++ b/Flow.Launcher/Languages/es-419.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Modo de juego Suspender el uso de las teclas de acceso directo. Position Reset - Reset search window position + Type here to search Ajustes @@ -70,8 +75,6 @@ Borrar última consulta Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. Máximo de resultados mostrados You can also quickly adjust this by using CTRL+Plus and CTRL+Minus. Ignorar atajos de teclado en modo pantalla completa @@ -102,6 +105,15 @@ Always Preview Always open preview panel when Flow activates. Press {0} to toggle preview. El efecto de sombra no está permitido mientras el tema actual tenga el efecto de desenfoque habilitado + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Search Plugin @@ -118,6 +130,8 @@ Palabra clave actual Nueva palabra clave Cambiar palabras clave + Plugin seach delay time + Change Plugin Seach Delay Time Prioridad Actual Nueva Prioridad Prioridad @@ -131,6 +145,9 @@ Uninstall Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Tienda de Plugins @@ -193,8 +210,20 @@ Custom Clock Date + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Tecla Rápida @@ -294,6 +323,9 @@ Carpeta de registros Clear Logs Are you sure you want to delete all logs? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Asistente User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ No se puede encontrar el plugin especificado La nueva palabra clave no puede estar vacía Esta palabra clave ya está asignada a otro plugin, por favor elija una diferente + This new Action Keyword is the same as old, please choose a different one Éxito Completado con éxito - Introduzca la palabra clave que desea utilizar para iniciar el plugin. Utilice * si no desea especificar ninguno, y el plugin se activará sin ninguna palabra clave. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Tecla de Acceso Personalizada diff --git a/Flow.Launcher/Languages/es.xaml b/Flow.Launcher/Languages/es.xaml index 4cba4c8a7..8b3c42fa6 100644 --- a/Flow.Launcher/Languages/es.xaml +++ b/Flow.Launcher/Languages/es.xaml @@ -7,6 +7,11 @@ Haga clic en no si ya está instalado, y seleccione la carpeta que contiene el ejecutable {1} Por favor, seleccione el ejecutable {0} + + El ejecutable {0} seleccionado no es válido. + {2}{2} + Pulsar Sí, si desea seleccionar de nuevo el ejecutable {0}. Pulsar No, si desea descargar {1} + No se puede establecer la ruta del ejecutable {0}, por favor inténtelo desde la configuración de Flow (desplácese hacia abajo). Fallo al iniciar los complementos Complemento: {0} - no se pudo cargar y se desactivará, póngase en contacto con el creador del complemento para obtener ayuda @@ -37,7 +42,7 @@ Modo Juego Suspende el uso de atajos de teclado. Restablecer posición - Restablece la posición de la ventana de búsqueda + Escribir aquí para buscar Configuración @@ -70,8 +75,6 @@ Limpiar la última consulta Conservar última palabra clave de acción Seleccionar última palabra clave de acción - Altura de la ventana fija - La altura de la ventana no se puede ajustar arrastrando el ratón. Número máximo de resultados mostrados También puede ajustarse rápidamente usando Ctrl+Más(+) y Ctrl+Menos(-). Ignorar atajos de teclado en modo pantalla completa @@ -102,6 +105,15 @@ Mostrar siempre vista previa Muestra siempre el panel de vista previa al iniciar Flow. Pulsar {0} para mostrar/ocultar la vista previa. El efecto de sombra no está permitido si el tema actual tiene activado el efecto de desenfoque + Retardo de búsqueda + Retrasa un poco la búsqueda al escribir. Esto reduce los saltos en la interfaz y la carga de resultados. + Tiempo de retardo de búsqueda predeterminado + Tiempo de retardo predeterminado del complemento tras el que aparecerán los resultados de la búsqueda cuando se deje de escribir. + Muy largo + Largo + Normal + Corto + Muy corto Buscar complemento @@ -118,6 +130,8 @@ Palabra clave de acción actual Nueva palabra clave de acción Cambia la palabra clave de acción + Tiempo de retardo de la búsqueda del complemento + Cambiar tiempo de retardo de la búsqueda del complemento Prioridad actual Nueva prioridad Prioridad @@ -131,6 +145,9 @@ Desinstalar Fallo al eliminar la configuración del complemento Complementos: {0} - Fallo al eliminar los archivos de configuración del complemento, por favor elimínelos manualmente + Fallo al eliminar la caché del complemento + Complementos: {0} - Fallo al eliminar los archivos de caché del complemento, por favor elimínelos manualmente + Predeterminado Tienda complementos @@ -193,8 +210,20 @@ Personalizada Reloj Fecha + Tipo de telón de fondo + Telón de fondo compatible a partir de Windows 11 build 22000 y superiores + Ninguno + Acrílico + Mica + Mica Alt Este tema soporta dos modos (claro/oscuro). Este tema soporta fondo transparente desenfocado. + Mostrar marcador de posición + Mostrar marcador de posición cuando la consulta esté vacía + Texto del marcador de posición + Cambiar el texto del marcador de posición. La entrada vacía utilizará: {0} + Tamaño fijo de la ventana + El tamaño de la ventana no se puede ajustar mediante arrastre. Atajo de teclado @@ -294,6 +323,9 @@ Carpeta de registros Eliminar registros ¿Está seguro de que desea eliminar todos los registros? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Asistente Ubicación de datos del usuario La configuración del usuario y los complementos instalados se guardan en la carpeta de datos del usuario. Esta ubicación puede variar dependiendo de si está en modo portable o no. @@ -335,9 +367,16 @@ No se puede encontrar el complemento especificado La nueva palabra clave de acción no puede estar vacía Esta nueva palabra clave de acción ya está asignada a otro complemento, por favor elija una diferente + Esta nueva palabra clave de acción es la misma que la anterior, por favor elija una diferente Correcto Finalizado correctamente - Introduzca la palabra clave que desea utilizar para iniciar el complemento. Utilice * si no desea especificar ninguna, y el complemento se activará sin ninguna palabra clave. + Introduzca las palabras clave de acción que desea utilizar para iniciar el complemento y utilice espacios en blanco para separarlas. Utilice * si no desea especificar ninguna, para que el complemento se inicie sin ninguna palabra clave de acción. + + + Ajuste del tiempo de retardo de búsqueda + Seleccionar el tiempo de retardo de búsqueda que se desea utilizar para el complemento. Seleccionar "{0}" si no se desea especificar nada, y el complemento utilizará el tiempo de retardo de búsqueda predeterminado. + Tiempo de retardo de búsqueda actual + Nuevo tiempo de retardo de búsqueda Atajo de teclado de consulta personalizada diff --git a/Flow.Launcher/Languages/fr.xaml b/Flow.Launcher/Languages/fr.xaml index d0d1d010d..e46e0dc9d 100644 --- a/Flow.Launcher/Languages/fr.xaml +++ b/Flow.Launcher/Languages/fr.xaml @@ -7,6 +7,11 @@ Cliquez sur non s'il est déjà installé, et vous serez invité à sélectionner le dossier qui contient l'exécutable {1} Veuillez sélectionner l'exécutable {0} + + L'exécutable {0} que vous avez sélectionné est invalide. + {2}{2} + Cliquez sur oui si vous souhaitez sélectionner l'exécutable {0} à nouveau. Cliquez sur non si vous souhaitez télécharger {1}. + Impossible de définir {0} comme chemin d'accès vers l'exécutable. Veuillez essayer à partir des paramètres de Flow (défiler vers le bas). Échec de l'initialisation des plugins Plugins : {0} - n'ont pas pu être chargés et doivent être désactivés, veuillez contacter le créateur du plugin pour obtenir de l'aide @@ -37,7 +42,7 @@ Mode jeu Suspend l'utilisation des raccourcis claviers. Réinitialiser la position - Rétablir la position de la fenêtre de recherche + Tapez ici pour rechercher Paramètres @@ -70,8 +75,6 @@ Ne pas afficher la dernière recherche Conserver le mot clé de la dernière action Sélectionnez le mot clé de la dernière action - Hauteur de fenêtre fixe - La hauteur de la fenêtre n'est pas réglable par glissement. Résultats maximums à afficher Vous pouvez également ajuster ce paramètre en utilisant CTRL+Plus ou CTRL+Moins. Ignore les raccourcis lorsqu'une application est en plein écran @@ -102,6 +105,15 @@ Toujours prévisualiser Toujours ouvrir le panneau d'aperçu lorsque Flow s'active. Appuyez sur {0} pour activer/désactiver l'aperçu. L'effet d'ombre n'est pas autorisé lorsque le thème actuel à un effet de flou activé + Délai de recherche + Attendre un certain temps pour effectuer une recherche lors de la saisie. Cela permet de réduire les sauts d'interface et la charge des résultats. + Délai de recherche par défaut + Délai par défaut du plugin après lequel les résultats de la recherche s'affichent lorsque la saisie est interrompue. + Très long + Long + Normal + Court + Très court Rechercher des plugins @@ -118,6 +130,8 @@ Mot-clé d'action actuel Nouveau mot-clé d'action Changer les mots-clés d'action + Délai de recherche du plugin + Modifier le délai de recherche du plugin Priorité actuelle Nouvelle priorité Priorité @@ -131,6 +145,9 @@ Désinstaller Échec de la suppression des paramètres du plugin Plugins : {0} - Échec de la suppression des fichiers de configuration des plugins, veuillez les supprimer manuellement + Échec de la suppression du cache du plugin + Plugins : {0} - Échec de la suppression des fichiers cache des plugins, veuillez les supprimer manuellement + Défaut Magasin des Plugins @@ -193,8 +210,20 @@ Personnalisé Heure Date + Type d'arrière-plan + Arrière-plan pris en charge à partir de Windows 11 version 22000 et plus + Aucun + Acrylique + Mica + Mica Alt Ce thème prend en charge deux modes (clair/sombre). Ce thème prend en charge l'arrière-plan flou et transparent. + Afficher l'espace réservé + Afficher un espace réservé lorsque la requête est vide + Texte de l'espace réservé + Modifier le texte de l'espace réservé. Les entrées vides utiliseront : {0} + Taille de la fenêtre fixe + La taille de la fenêtre n'est pas réglable par glissement. Raccourcis @@ -293,6 +322,9 @@ Répertoire des journaux Effacer le journal Êtes-vous sûr de vouloir supprimer tous les journaux ? + Vider les caches + Êtes-vous sûr de vouloir supprimer tous les caches ? + Échec de l'effacement d'une partie des dossiers et des fichiers. Veuillez consulter le fichier journal pour plus d'informations Assistant Emplacement des données utilisateur Les paramètres utilisateur et les plugins installés sont enregistrés dans le dossier des données utilisateur. Cet emplacement peut varier selon que vous soyez en mode portable ou non. @@ -334,9 +366,16 @@ Impossible de trouver le module spécifi Le nouveau mot-clé d'action doit être spécifi Le nouveau mot-clé d'action a été assigné à un autre module, veuillez en choisir un autre + Ce nouveau mot-clé d'action est identique à l'ancien, veuillez en choisir un autre Ajout Terminé avec succès - Saisissez * si vous ne souhaitez pas utiliser de mot-clé spécifique + Saisissez les mots-clés d'action que vous souhaitez utiliser pour lancer le plugin et séparez-les par des espaces. Utilisez * si vous ne voulez en spécifier aucun, et le plugin sera déclenché sans aucun mot-clé d'action. + + + Réglage du délai de recherche + Sélectionnez le délai de recherche que vous souhaitez utiliser pour le plugin. Sélectionnez "{0}" si vous ne voulez pas en spécifier, et le plugin utilisera le délai de recherche par défaut. + Délai de recherche actuel + Nouveau délai de recherche Requêtes personnalisées diff --git a/Flow.Launcher/Languages/he.xaml b/Flow.Launcher/Languages/he.xaml index c912052f1..38e943cda 100644 --- a/Flow.Launcher/Languages/he.xaml +++ b/Flow.Launcher/Languages/he.xaml @@ -7,6 +7,11 @@ אם זה כבר מותקן, לחץ על 'לא' ותתבקש לבחור את התיקיה המכילה את קובץ ההפעלה {1} אנא בחר את קובץ ההפעלה {0} + + קובץ ההפעלה {0} שבחרת אינו חוקי. + {2}{2} + לחץ על כן אם ברצונך, בחר את {0} ההפעלה הקודמת. לחץ על לא אם ברצונך להוריד את {1} + לא ניתן להגדיר נתיב הפעלה {0}, אנא נסה שוב בהגדרות Flow (גלול עד למטה). נכשל בהפעלת תוספים תוספים: {0} - נכשלו בטעינה ויושבתו, אנא צור קשר עם יוצרי התוספים לקבלת עזרה @@ -37,7 +42,7 @@ מצב משחק השהה את השימוש במקשי קיצור. איפוס מיקום - אפס את מיקום חלון החיפוש + הקלד כאן כדי לחפש הגדרות @@ -70,8 +75,6 @@ נקה שאילתא אחרונה שמור מילת מפתח לפעולה האחרונה בחר מילת מפתח לפעולה האחרונה - גובה חלון קבוע - גובה החלון אינו ניתן להתאמה באמצעות גרירה. כמות תוצאות מרבית ניתן גם להתאים במהירות באמצעות CTRL+פלוס ו-CTRL+מינוס. התעלם מקיצורי מקשים במצב מסך מלא @@ -97,11 +100,20 @@ ללא נמוך Regular - Search with Pinyin + חפש באמצעות Pinyin Allows using Pinyin to search. Pinyin is the standard system of romanized spelling for translating Chinese. הצג תמיד תצוגה מקדימה פתח תמיד את לוח התצוגה המקדימה כאשר Flow מופעל. הקש על {0} כדי להחליף את התצוגה המקדימה. לא ניתן להחיל אפקט צל כאשר העיצוב הנוכחי מוגדר לאפקט טשטוש + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short חפש תוסף @@ -118,6 +130,8 @@ מילת מפתח נוכחית לפעולה מילת מפתח חדשה לפעולה שנה מילות מפתח לפעולה + Plugin seach delay time + Change Plugin Seach Delay Time עדיפות נוכחית עדיפות חדשה עדיפות @@ -131,6 +145,9 @@ הסר התקנה נכשל בהסרת הגדרות התוסף תוספים: {0} - נכשל בהסרת קבצי הגדרות התוסף, יש להסירם ידנית + נכשל בהסרת מטמון התוסף + תוספים: {0} - נכשל בהסרת קובצי מטמון התוסף, אנא הסר אותם ידנית + Default חנות תוספים @@ -156,7 +173,7 @@ סייר חפש קבצים, תיקיות ובתוכן הקבצים חיפוש באינטרנט - Search the web with different search engine support + חפש באינטרנט עם תמיכה במנועי חיפוש שונים תוכנה הפעל תוכנות כמנהל או כמשתמש אחר ProcessKiller @@ -193,8 +210,20 @@ מותאם אישית שעון תאריך + סוג רקע + התמיכה ב-Backdrop קיימת החל מ-Windows 11 build 22000 ומעלה + ללא + אקריליק + מיקה + Mica Alt ערכת נושא זאת תומך בשני מצבים (בהיר/כהה). ערכת נושא זו תומכת בטשטוש רקע שקוף. + הצג מציין מיקום + הצג מציין מיקום כאשר השאילתה ריקה + טקסט מציין מיקום + שנה את טקסט מציין המיקום. אם הקלט ריק, ייעשה שימוש ב: {0} + גודל חלון קבוע + לא ניתן להתאים את גודל החלון באמצעות גרירה. מקש קיצור @@ -289,18 +318,21 @@ הערות שחרור טיפים לשימוש - DevTools + כלי פיתוח תיקיית ההגדרות תיקיית יומני רישום נקה יומני רישום האם אתה בטוח שברצונך למחוק את כל היומנים? + נקה נתוני מטמון + האם אתה בטוח שברצונך למחוק את כל הנתונים שבמטמון? + נכשל ניקוי חלק מהתיקיות והקבצים. עיין בלוג לקבלת מידע נוסף אשף מיקום נתוני משתמש הגדרות המשתמש והתוספים המותקנים נשמרים בתיקיית נתוני המשתמש. מיקום זה עשוי להשתנות אם התוכנה במצב נייד. פתח תיקיה Log Level - Debug - Info + ניפוי שגיאות + מידע בחר מנהל קבצים @@ -335,9 +367,16 @@ לא ניתן למצוא את התוסף שצוין מילת הפעולה החדשה לא יכולה להיות ריקה מילת הפעולה החדשה כבר מוקצה לתוסף אחר, אנא בחר אחת שונה + מילת הפעולה החדשה זהה לישנה, נא לבחור מילת פעולה שונה הצליח הושלם בהצלחה - הזן את מילת הפעולה שברצונך להשתמש בה להפעלת התוסף. השתמש ב-* אם אינך רוצה לציין מילה כלשהי, והתוסף יופעל ללא צורך במילת פעולה. + הזן את מילות הפעולה שבהן תרצה להשתמש כדי להפעיל את התוסף, והשתמש ברווחים כדי להפריד ביניהן. השתמש ב-* אם אינך רוצה להגדיר כלל, והתוסף יופעל ללא מילות פעולה. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time מקש קיצור לשאילתה מותאמת אישית diff --git a/Flow.Launcher/Languages/it.xaml b/Flow.Launcher/Languages/it.xaml index e4d4d3e2c..fd34bf366 100644 --- a/Flow.Launcher/Languages/it.xaml +++ b/Flow.Launcher/Languages/it.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Modalità gioco Sospendere l'uso dei tasti di scelta rapida. Ripristina Posizione - Ripristina posizione finestra di ricerca + Type here to search Impostazioni @@ -70,8 +75,6 @@ Cancella ultima ricerca Preserve Last Action Keyword Select Last Action Keyword - Altezza Finestra Fissa - L'altezza della finestra non si può regolare trascinando. Numero massimo di risultati mostrati È anche possibile regolarlo rapidamente utilizzando CTRL+Più e CTRL+Meno. Ignora i tasti di scelta rapida in applicazione a schermo pieno @@ -102,6 +105,15 @@ Mostra Sempre Anteprima Apri sempre il pannello di anteprima quando Flow si attiva. Premi {0} per attivare l'anteprima. L'effetto ombra non è consentito mentre il tema corrente ha un effetto di sfocatura abilitato + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Plugin di ricerca @@ -118,6 +130,8 @@ Parola chiave di azione corrente Nuova parola chiave d'azione Cambia Keywords Azione + Plugin seach delay time + Change Plugin Seach Delay Time Priorità Attuale Nuova Priorità Priorità @@ -131,6 +145,9 @@ Disinstalla Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Negozio dei Plugin @@ -193,8 +210,20 @@ Personalizzato Orologio Data + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Vuoto + Acrylic + Mica + Mica Alt Questo tema supporta due (chiaro/scuro) varianti. Questo tema supporta lo sfondo trasparente blurrato. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Tasti scelta rapida @@ -294,6 +323,9 @@ Cartella dei Log Cancella i log Sei sicuro di voler cancellare tutti i log? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard Posizione Dati Utente Le impostazioni dell'utente e i plugin installati sono salvati nella cartella dati utente. Questa posizione può variare se è in modalità portable o no. @@ -335,9 +367,16 @@ Impossibile trovare il plugin specificato La nuova parola chiave d'azione non può essere vuota La nuova parola chiave d'azione è stata assegnata ad un altro plugin, per favore sceglierne una differente + This new Action Keyword is the same as old, please choose a different one Successo Completato con successo - Usa * se non vuoi specificare una parola chiave d'azione + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Tasti scelta rapida per ricerche personalizzate diff --git a/Flow.Launcher/Languages/ja.xaml b/Flow.Launcher/Languages/ja.xaml index 28c334667..e6f2223cd 100644 --- a/Flow.Launcher/Languages/ja.xaml +++ b/Flow.Launcher/Languages/ja.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ ゲームモード ホットキーの使用を一時停止します。 位置のリセット - 検索ウィンドウの位置をリセットします。 + Type here to search 設定 @@ -70,8 +75,6 @@ 前回のクエリを消去 Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. 結果の最大表示件数 CTRL+PlusとCTRL+Minusを使用すれば、簡単に調整することもできます。 ウィンドウがフルスクリーン時にホットキーを無効にする @@ -102,6 +105,15 @@ 常にプレビューする Flow が有効になったとき、常にプレビューパネルを開きます。 {0} を押してプレビューの表示/非表示を切り替えます。 現在のテーマでぼかしの効果が有効になっている場合、影の効果を有効にすることはできません + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Search Plugin @@ -118,6 +130,8 @@ Current action keyword New action keyword Change Action Keywords + Plugin seach delay time + Change Plugin Seach Delay Time Current Priority New Priority 重要度 @@ -131,6 +145,9 @@ アンインストール Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default プラグインストア @@ -193,8 +210,20 @@ カスタム 時刻 日付 + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. ホットキー @@ -294,6 +323,9 @@ Log Folder Clear Logs Are you sure you want to delete all logs? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ プラグインが見つかりません 新しいアクションキーボードを空にすることはできません 新しいアクションキーボードは他のプラグインに割り当てられています。他のアクションキーボードを指定してください + This new Action Keyword is the same as old, please choose a different one 成功しました Completed successfully - アクションキーボードを指定しない場合、* を使用してください + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml index d9da26bcb..3aee3f5e4 100644 --- a/Flow.Launcher/Languages/ko.xaml +++ b/Flow.Launcher/Languages/ko.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ 게임 모드 단축키 사용을 일시중단합니다. 창 위치 초기화 - 검색창 위치 초기화 + 검색어 입력 설정 @@ -45,8 +50,8 @@ 포터블 모드 모든 설정이 폴더안에 들어갑니다. USB 드라이브나 클라우드로 사용 가능합니다. 시스템 시작 시 Flow Launcher 실행 - Use logon task instead of startup entry for faster startup experience - After uninstallation, you need to manually remove this task (Flow.Launcher Startup) via Task Scheduler + 더 빠른 시작을 위해 시작 프로그램 항목 대신 로그온 Task 사용 + Flow Launcher를 제거한 후에는 작업 스케줄러에서 이 작업(Flow.Launcher Startup)을 수동으로 삭제해야 합니다 Error setting launch on startup 포커스 잃으면 Flow Launcher 숨김 새 버전 알림 끄기 @@ -70,8 +75,6 @@ 직전 쿼리 지우기 Preserve Last Action Keyword Select Last Action Keyword - 창 높이 고정 - 드래그로 창 높이를 조정하지 않습니다. 표시할 결과 수 Ctrl + '+'키와 Ctrl + '-'키로도 빠르게 조정할 수 있습니다 전체화면 모드에서는 단축키 무시 @@ -89,7 +92,7 @@ 자동 업데이트 선택 시작 시 Flow Launcher 숨김 - Flow Launcher search window is hidden in the tray after starting up. + Flowr Launcher가 트레이에 숨겨진 상태로 시작합니다. 트레이 아이콘 숨기기 트레이에서 아이콘을 숨길 경우, 검색창 우클릭으로 설정창을 열 수 있습니다. 쿼리 검색 정밀도 @@ -102,6 +105,15 @@ 항상 미리보기 Flow 사용시 항상 미리보기 패널을 열어둡니다. {0} 키를 눌러 프리뷰창을 켜고 끌 수 있습니다. 반투명 흐림 효과를 사용하는 경우, 그림자 효과를 쓸 수 없습니다. + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short 플러그인 검색 @@ -118,6 +130,8 @@ 현재 액션 키워드 새 액션 키워드 액션 키워드 변경 + Plugin seach delay time + Change Plugin Seach Delay Time 현재 중요도: 새 중요도: 중요도 @@ -131,6 +145,9 @@ 제거 Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default 플러그인 스토어 @@ -193,8 +210,20 @@ 사용자 정의 시계 날짜 + 배경 효과 타입 + Backdrop supported starting from Windows 11 build 22000 and above + 없음 + 아크릴 + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + 안내 텍스트 표시 + 입력 내용이 없을때 입력창 위치를 알 수 있는 텍스트를 표시합니다 + 안내 텍스트 + 안내 텍스트를 변경하세요. 아무것도 입력하지 않으면 다음을 사용합니다: "{0}" + Fixed Window Size + The window size is not adjustable by dragging. 단축키 @@ -294,6 +323,9 @@ 로그 폴더 로그 삭제 정말 모든 로그를 삭제하시겠습니까? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information 마법사 사용자 데이터 위치 사용자 설정과 설치된 플러그인은 사용자 데이터 폴더에 저장됩니다. 이 위치는 휴대용 모드 활성화 여부에 따라 달라질 수 있습니다. @@ -335,9 +367,16 @@ 플러그인을 찾을 수 없습니다. 새 액션 키워드를 입력하세요. 새 액션 키워드가 할당된 플러그인이 이미 있습니다. 다른 액션 키워드를 입력하세요. + This new Action Keyword is the same as old, please choose a different one 성공 성공적으로 완료했습니다. - 플러그인을 시작하는데 필요한 액션 키워드를 입력하세요. 액션 키워드를 지정하지 않으려면 *를 사용하세요. 이 경우 키워드를 입력하지 않아도 동작합니다. + 플러그인을 실행할 때 사용할 액션 키워드를 입력하세요. 여러 개를 입력할 경우 공백으로 구분하세요. 아무 키워드도 지정하지 않으려면 * 를 입력하세요. 이 경우 액션 키워드 없이도 플러그인이 실행됩니다. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time 사용자지정 쿼리 단축키 diff --git a/Flow.Launcher/Languages/nb.xaml b/Flow.Launcher/Languages/nb.xaml index a37a204e1..b78bcb7d7 100644 --- a/Flow.Launcher/Languages/nb.xaml +++ b/Flow.Launcher/Languages/nb.xaml @@ -7,6 +7,11 @@ Klikk nei hvis det allerede er installert, og du vil bli bedt om å velge mappen som inneholder {1} kjørbar fil Velg den kjørbare filen for {0} + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Kan ikke angi {0} kjørbar bane, prøv fra Flows innstillinger (bla ned til bunnen). Mislykkes i å initialisere programtillegg Programtillegg: {0} - mislykkes å lastes inn og vil bli deaktivert, vennligst kontakt utvikleren av programtillegget for hjelp @@ -37,7 +42,7 @@ Spillmodus Stopp bruken av hurtigtaster. Tilbakestilling av posisjon - Tilbakestill posisjonen til søkevinduet + Type here to search Innstillinger @@ -70,8 +75,6 @@ Tøm siste spørring Preserve Last Action Keyword Select Last Action Keyword - Fast vindushøyde - Vindushøyden kan ikke justeres ved å dra. Maksimalt antall resultater vist Du kan også raskt justere dette ved å bruke CTRL+Plus og CTRL+Minus. Ignorer hurtigtaster i fullskjermmodus @@ -102,6 +105,15 @@ Alltid forhåndsvisning Åpne alltid forhåndsvisningspanel når Flow aktiveres. Trykk på {0} for å velge forhåndsvisning. Skyggeeffekt er ikke tillatt mens gjeldende tema har uskarphet-effekt aktivert + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Søk etter programtillegg @@ -118,6 +130,8 @@ Nåværende handlingsnøkkelord Nytt handlingsnøkkelord Endre handlingsnøkkelord + Plugin seach delay time + Change Plugin Seach Delay Time Gjeldende prioritet Ny prioritet Prioritet @@ -131,6 +145,9 @@ Avinstaller Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Programtillegg butikk @@ -193,8 +210,20 @@ Egendefinert Klokke Dato + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Ingen + Acrylic + Mica + Mica Alt Dette temaet støtter to (lys/mørk) moduser. Dette temaet støtter uskarp gjennomsiktig bakgrunn. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Hurtigtast @@ -294,6 +323,9 @@ Loggmappe Tøm logger Er du sikker på at du vil slette alle loggene? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Veiviser Plassering av brukerdata Brukerinnstillinger og installerte programtillegg lagres i brukerens datamappe. Denne plasseringen kan variere avhengig av om den er i portabel modus eller ikke. @@ -335,9 +367,16 @@ Kan ikke finne spesifisert programtillegg Nytt handlingsnøkkelord kan ikke være tom Det nye nøkkelordet for handling er allerede tilordnet et annet programtillegg, velg et annet + This new Action Keyword is the same as old, please choose a different one Vellykket Fullført vellykket - Skriv inn handlingsnøkkelord du vil bruke for å starte programtillegget. Bruk * hvis du ikke ønsker å spesifisere noen, og utvidelsen vil bli utløst uten noen handlingsord. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Hurtigtast for egendefinert spørring diff --git a/Flow.Launcher/Languages/nl.xaml b/Flow.Launcher/Languages/nl.xaml index 64adccd94..ce3406142 100644 --- a/Flow.Launcher/Languages/nl.xaml +++ b/Flow.Launcher/Languages/nl.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Spelmodus Stop het gebruik van Sneltoetsen. Positie resetten - Positie zoekvenster resetten + Type here to search Instellingen @@ -70,8 +75,6 @@ Laatste zoekopdracht verwijderen Preserve Last Action Keyword Select Last Action Keyword - Vaste venster hoogte - De vensterhoogte is niet aanpasbaar door te slepen. Laat maximale resultaten zien Je kunt dit ook snel aanpassen met CTRL+Plus en CTRL+Minus. Negeer sneltoetsen in vol scherm modus @@ -102,6 +105,15 @@ Altijd voorbeeld Open altijd het voorbeeld paneel wanneer Flow activeert. Druk op {0} om voorbeeld te schakelen. Schaduw effect is niet toegestaan omdat het huidige thema een vervagingseffect heeft + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Plug-ins zoeken @@ -118,6 +130,8 @@ Huidige actie sneltoets Nieuw actie sneltoets Wijzig actie-sneltoets + Plugin seach delay time + Change Plugin Seach Delay Time Huidige Prioriteit Nieuwe Prioriteit Prioriteit @@ -131,6 +145,9 @@ Verwijderen Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Plugin Winkel @@ -193,8 +210,20 @@ Aangepast Klok Datum + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt Dit thema ondersteunt twee (licht/donker) modi. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Sneltoets @@ -294,6 +323,9 @@ Log Map Logbestanden wissen Weet u zeker dat u alle logbestanden wilt verwijderen? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard Gegevenslocatie van gebruiker Gebruikersinstellingen en geïnstalleerde plug-ins worden opgeslagen in de gebruikersgegevensmap. Deze locatie kan variëren afhankelijk van of het in draagbare modus is of niet. @@ -335,9 +367,16 @@ Kan plugin niet vinden Nieuwe actie sneltoets moet ingevuld worden Nieuwe actie sneltoets is toegewezen aan een andere plugin, wijs een nieuwe actie sneltoets aan + This new Action Keyword is the same as old, please choose a different one Succesvol Succesvol afgerond - Gebruik * wanneer je geen nieuwe actie sneltoets wilt specificeren + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Custom Query Sneltoets diff --git a/Flow.Launcher/Languages/pl.xaml b/Flow.Launcher/Languages/pl.xaml index 06204395c..12af37c3e 100644 --- a/Flow.Launcher/Languages/pl.xaml +++ b/Flow.Launcher/Languages/pl.xaml @@ -7,6 +7,11 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy poproszony o wybranie folderu zawierającego plik wykonywalny {1} Wybierz plik wykonywalny {0} + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Nie można ustawić ścieżki do pliku wykonywalnego {0}. Spróbuj ponownie w ustawieniach Flow (przewiń na sam dół). Nie udało się zainicjować wtyczek Wtyczki: {0} – nie udało się ich wczytać i zostaną wyłączone. Skontaktuj się z twórcą wtyczki, aby uzyskać pomoc @@ -37,7 +42,7 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Tryb grania Wstrzymaj używanie skrótów. Resetowanie pozycji - Zresetuj pozycję okna wyszukiwania + Type here to search Ustawienia @@ -70,8 +75,6 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Puste ostatnie zapytanie Zachowaj ostatnie słowo kluczowe akcji Wybierz ostatnie słowo kluczowe akcji - Stała wysokość okna - Wysokość okna nie jest regulowana poprzez przeciąganie. Maksymalna liczba wyników Możesz to również szybko dostosować używając CTRL+Plus i CTRL+Minus. Ignoruj skróty klawiszowe w trybie pełnoekranowym @@ -102,6 +105,15 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Zawsze podgląd Zawsze otwieraj panel podglądu, gdy aktywowany jest Flow. Naciśnij {0}, aby przełączyć podgląd. Efekt cienia jest niedozwolony, gdy bieżący motyw ma włączony efekt rozmycia + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Szukaj wtyczek @@ -118,6 +130,8 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Bieżące słowo kluczowe akcji Nowe słowo kluczowe akcji Zmień słowa kluczowe akcji + Plugin seach delay time + Change Plugin Seach Delay Time Obecny Priorytet Nowy Priorytet Priorytet @@ -131,6 +145,9 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Odinstalowywanie Nie udało się usunąć ustawień wtyczki Wtyczki: {0} – nie udało się usunąć plików ustawień wtyczek, usuń je ręcznie + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Sklep z wtyczkami @@ -193,8 +210,20 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Niestandardowa Zegar Data + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Brak + Acrylic + Mica + Mica Alt Ten motyw obsługuje dwa tryby (jasny/ciemny). Ten motyw obsługuje rozmyte przezroczyste tło. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Skrót klawiszowy @@ -294,6 +323,9 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Folder dziennika Wyczyść logi Czy na pewno chcesz usunąć wszystkie logi? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Kreator Lokalizacja danych użytkownika Ustawienia użytkownika i zainstalowane wtyczki są zapisywane w folderze danych użytkownika. Ta lokalizacja może się różnić w zależności od tego, czy aplikacja jest w trybie przenośnym, czy nie. @@ -335,9 +367,16 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Nie można odnaleźć podanej wtyczki Nowy wyzwalacz nie może być pusty Ten wyzwalacz został już przypisany do innej wtyczki, musisz podać inny wyzwalacz. + This new Action Keyword is the same as old, please choose a different one Sukces Zakończono pomyślnie - Użyj * jeżeli nie chcesz podawać wyzwalacza + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Skrót klawiszowy niestandardowych zapyta diff --git a/Flow.Launcher/Languages/pt-br.xaml b/Flow.Launcher/Languages/pt-br.xaml index 62293b1a1..d0040d799 100644 --- a/Flow.Launcher/Languages/pt-br.xaml +++ b/Flow.Launcher/Languages/pt-br.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Modo Gamer Suspender o uso de Teclas de Atalho. Redefinição de Posição - Redefinir posição da janela de busca + Type here to search Configurações @@ -70,8 +75,6 @@ Limpar última consulta Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. Máximo de resultados mostrados Você também pode ajustar isso rapidamente usando CTRL+Mais e CTRL+Menos. Ignorar atalhos em tela cheia @@ -102,6 +105,15 @@ Sempre Pré-visualizar Sempre abrir o painel de pré-visualização quando o Flow é ativado. Pressione {0} para ativar ou desativar a pré-visualização. O efeito de sombra não é permitido enquanto o tema atual tem o efeito de desfoque ativado + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Buscar Plugin @@ -118,6 +130,8 @@ Palavra-chave de ação atual Nova palavra-chave de ação Alterar Palavras-chave de Ação + Plugin seach delay time + Change Plugin Seach Delay Time Prioridade atual Nova Prioridade Prioridade @@ -131,6 +145,9 @@ Desinstalar Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Loja de Plugins @@ -193,8 +210,20 @@ Personalizado Relógio Data + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Atalho @@ -294,6 +323,9 @@ Pasta de Registro Limpar Registros Tem certeza que quer excluir todos os registros? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Assistente User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ Não foi possível encontrar o plugin especificado A nova palavra-chave da ação não pode ser vazia A nova palavra-chave da ação já foi atribuída a outro plugin, por favor tente outra + This new Action Keyword is the same as old, please choose a different one Sucesso Concluído com sucesso - Use * se não quiser especificar uma palavra-chave de ação + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Atalho de Consulta Personalizada diff --git a/Flow.Launcher/Languages/pt-pt.xaml b/Flow.Launcher/Languages/pt-pt.xaml index bad37f688..9dc520cbd 100644 --- a/Flow.Launcher/Languages/pt-pt.xaml +++ b/Flow.Launcher/Languages/pt-pt.xaml @@ -7,6 +7,11 @@ Clique "Não" se já tiver instalado e, de seguida, ser-lhe-á solicitada a pasta que contém o executável {1}. Por favor, selecione o executável {0} + + O executável {0} é inválido. + {2}{2} + Clique Sim se quiser escolher o novo executável {0}. Clique Não se quiser descarregar {1}. + Não foi possível definir o caminho do executável {0}. Experimente definir o caminho nas definições (desloque até ao fundo). Falha ao iniciar os plugins Plugin: {0} - não foi possível iniciar e será desativado. Contacte o criador do plugin para obter ajuda. @@ -37,7 +42,7 @@ Modo de jogo Suspender utilização das teclas de atalho Repor posição - Repor posição da janela de pesquisa + Escreva aqui para pesquisar Definições @@ -70,8 +75,6 @@ Limpar última consulta Manter palavra-chave da última ação Selecionar palavra-chave da última ação - Altura fixa de janela - Não é possível ajustar o tamanho da janela por arrasto. Número máximo de resultados Também pode ajustar rapidamente através do atalho Ctrl+ e Ctrl-. Ignorar teclas de atalho se em ecrã completo @@ -102,6 +105,15 @@ Pré-visualizar sempre Abrir painel de pré-visualização ao ativar Flow Launcher. Prima {0} para comutar a pré-visualização. O efeito sombra não é permitido com este tema porque o efeito desfocar está ativo + Atraso da pesquisa + Tempo a esperar após a digitação. Esta definição melhora o carregamento dos resultados. + Tempo de espera padrão + O valor padrão a esperar, antes de iniciar a pesquisa após terminar a digitação. + Muito longo + Longo + Normal + Curto + Muito curto Pesquisar plugins @@ -118,6 +130,8 @@ Palavra-chave atual Nova palavra-chave Alterar palavras-chave + Tempo de espera do plugin + Alterar tempo de espera do plugin Prioridade atual Nova prioridade Prioridade @@ -131,6 +145,9 @@ Desinstalar Falha ao remover as definições do plugin Plugin: {0} - Falha ao remover o ficheiro de definições do plugin. Experimente remover manualmente. + Falha ao limpar a cache do plugin + Plugin: {0} - Falha ao remover os ficheiros em cache do plugin. Experimente remover manualmente. + Padrão Loja de plugins @@ -193,8 +210,20 @@ Personalizada Relógio Data + Tipo de fundo + Esta opção apenas está disponível em sistemas após Windows 11 Build 22000 + Nenhuma + Acrílico + Mica + Mica alternativo Este tema tem suporte a dois modos (claro/escuro). Este tema tem suporte a fundo transparente desfocado. + Mostrar marcador de posição + Mostrar marcador de posição se a consulta estiver vazia + Texto do marcador + O texto do marcador de posição. Se vazio, será utilizado: {0} + Janela com tamanho fixo + Não pode ajustar o tamanho da janela por arrasto. Tecla de atalho @@ -293,13 +322,16 @@ Pasta de registos Limpar registos Tem a certeza de que deseja remover todos os registos? + Limpar cache + Tem a certeza de que pretende limpar todas as caches? + Não foi possível limpar todas as pastas e ficheiros. Consulte o ficheiro de registo para mais informações. Assistente Localização dos dados do utilizador As definições e os plugins instalados são guardados na pasta de dados do utilizador. A localização pode variar, tendo em conta se a aplicação está instalada ou no modo portátil Abrir pasta - Log Level - Debug - Info + Nível de registo + Depuração + Informação Selecione o gestor de ficheiros @@ -334,9 +366,16 @@ Plugin não encontrado A nova palavra-chave não pode estar vazia Esta palavra-chave já está associada a um plugin. Por favor escolha outra. + A palavra-chave escolhida é igual à anterior. Por favor escolha outra. Sucesso Terminado com sucesso - Introduza a palavra-chave a utilizar para iniciar o plugin. Utilize * se não quiser utilizar esta funcionalidade e o plugin não será ativado com palavras-chave. + Introduza as palavras-chave que pretende utilizar para iniciar o plugin e um espaço vazio caso queira mais do que uma. Utilize * se não quiser especificar uma palavra-chave e o plugin será ativado sem palavras-chave. + + + Definição do tempo de espera + Selecione o tempo de espera que pretende utilizar com este plugin. Selecione "{0}" se não o quiser especificar e, desta forma, o plugin irá utilizar o tempo de espera padrão. + Tempo de espera atual + Novo tempo de espera Tecla de atalho personalizada diff --git a/Flow.Launcher/Languages/ru.xaml b/Flow.Launcher/Languages/ru.xaml index a56a770da..c38855474 100644 --- a/Flow.Launcher/Languages/ru.xaml +++ b/Flow.Launcher/Languages/ru.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Игровой режим Приостановить использование горячих клавиш. Сброс положения - Сброс положения окна поиска + Type here to search Настройки @@ -70,8 +75,6 @@ Очистить последний запрос Preserve Last Action Keyword Select Last Action Keyword - Фиксированная высота окна - The window height is not adjustable by dragging. Максимальное количество результатов Вы также можете быстро настроить это с помощью CTRL+плюс и CTRL+минус. Игнорировать горячие клавиши в полноэкранном режиме @@ -102,6 +105,15 @@ Всегда предпросмотр Всегда открывать панель предварительного просмотра при запуске Flow. Нажмите {0}, чтобы переключить предварительный просмотр. Эффект тени не допускается, если в текущей теме включён эффект размытия + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Поиск плагина @@ -118,6 +130,8 @@ Ключевое слово текущего действия Ключевое слово нового действия Изменить ключевое слово действия + Plugin seach delay time + Change Plugin Seach Delay Time Текущий приоритет Новый приоритет Приоритет @@ -131,6 +145,9 @@ Удалить Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Магазин плагинов @@ -193,8 +210,20 @@ Своя Часы Дата + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Горячая клавиша @@ -294,6 +323,9 @@ Папка журнала Очистить журнал Вы уверены, что хотите удалить все журналы? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Мастер User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ Не удалось найти заданный плагин Новая горячая клавиша не может быть пустой Новая горячая клавиша уже используется другим плагином. Пожалуйста, задайте новую + This new Action Keyword is the same as old, please choose a different one Успешно Выполнено успешно - Введите горячую клавишу, которое вы хотите использовать для запуска плагина. Используйте *, если вы не хотите ничего указывать, и плагин будет запускаться без каких-либо горячих клавиш. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Задаваемые горячие клавиши для запросов diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml index 332528b2b..0f07387c6 100644 --- a/Flow.Launcher/Languages/sk.xaml +++ b/Flow.Launcher/Languages/sk.xaml @@ -7,6 +7,11 @@ Ak už ho máte nainštalovaný, kliknite na nie, a budete vyzvaný na zadanie cesty k priečinku spustiteľného súboru {1} Vyberte spustiteľný súbor {0} + + Vybrali ste nesprávny spustiteľný súbor {0}. + {2}{2} + Ak chcete znovu vybrať spustiteľný súbor {0}, kliknite na Áno. Kliknutím na Nie sa stiahne {1}. + Nie je možné nastaviť cestu ku spustiteľnému súboru {0}, skúste to v nastaveniach Flowu (prejdite nadol). Nepodarilo sa inicializovať pluginy Pluginy: {0} – nepodarilo sa načítať a mal by byť zakázaný, na pomoc kontaktujte autora pluginu @@ -37,7 +42,7 @@ Herný režim Pozastaviť používanie klávesových skratiek. Resetovať pozíciu - Resetovať pozíciu vyhľadávacieho okna + Zadajte text na vyhľadávanie Nastavenia @@ -70,8 +75,6 @@ Vymazať Ponechať posledný akčný príkaz Označiť posledný akčný príkaz - Pevná výška okna - Výška okna sa nedá nastaviť ťahaním. Maximum výsledkov Túto hodnotu môžete rýchlo upraviť aj pomocou klávesových skratiek CTRL + znamienko plus (+) a CTRL + znamienko mínus (-). Ignorovať klávesové skratky v režime na celú obrazovku @@ -102,6 +105,15 @@ Vždy zobraziť náhľad Pri aktivácii Flowu vždy otvoriť panel s náhľadom. Stlačením klávesu {0} prepnete náhľad. Efekt tieňa nie je povolený, kým má aktuálny motív povolený efekt rozostrenia + Oneskorenie vyhľadávania + Pri písaní sa na chvíľu oneskorí vyhľadávanie. Tým sa zníži skákanie rozhrania a načítanie výsledkov. + Predvolené oneskorenie vyhľadávania + Predvolené oneskorenie pluginu, po ktorom sa zobrazia výsledky vyhľadávania po zastavení písania. + Veľmi dlhé + Dlhé + Normálne + Krátke + Veľmi krátke Vyhľadať plugin @@ -118,6 +130,8 @@ Aktuálny aktivačný príkaz Nový aktivačný príkaz Upraviť aktivačný príkaz + Oneskorenie vyhľadávania pomocou pluginu + Zmení oneskorenie vyhľadávania pomocou pluginu Aktuálna priorita Nová priorita Priorita @@ -131,6 +145,9 @@ Odinštalovať Nepodarilo sa odstrániť nastavenia pluginu Pluginy: {0} – Nepodarilo sa odstrániť súbory s nastaveniami pluginu, odstráňte ich manuálne + Nepodarilo sa odstrániť vyrovnávaciu pamäť pluginu + Pluginy: {0} – Nepodarilo sa odstrániť vyrovnávaciu pamäť pluginu, odstráňte ju manuálne + Predvolené Repozitár pluginov @@ -193,8 +210,20 @@ Vlastné Hodiny Dátum + Typ pozadia + Backdrop je podporovaný od Windows 11 zostava 22000 a novších + Žiadna + Acrylic + Mica + Mica Alt Tento motív podporuje 2 režimy (svetlý/tmavý). Tento motív podporuje rozostrenie priehľadného pozadia. + Zobraziť zástupný text + Zobrazí zástupný text v prázdnom vyhľadávacom poli + Zástupný text + Zobrazí zástupný text. V prázdnom poli sa zobrazí: {0} + Pevná veľkosť okna + Veľkosť okna sa nedá nastaviť ťahaním. Klávesové skratky @@ -294,6 +323,9 @@ Priečinok s logmi Vymazať logy Naozaj chcete odstrániť všetky logy? + Vymazať vyrovnávaciu pamäť + Naozaj chcete vymazať všetky vyrovnávacie pamäte? + Nepodarilo sa odstrániť niektoré priečinky a súbory. Pre viac informácií si pozrite súbor logu Sprievodca Cesta k používateľskému priečinku Nastavenia používateľa a nainštalované pluginy sa ukladajú do používateľského priečinka. Toto umiestnenie sa môže líšiť v závislosti od toho, či je v prenosnom režime alebo nie. @@ -335,9 +367,16 @@ Nepodarilo sa nájsť zadaný plugin Nový aktivačný príkaz nemôže byť prázdny Nový aktivačný príkaz už bol priradený inému pluginu, prosím, zvoľte iný aktivačný príkaz + Tento nový aktivačný príkaz je rovnaký ako starý, vyberte iný Úspešné Úspešne dokončené - Zadajte aktivačný príkaz, ktorý je potrebný na spustenie pluginu. Ak nechcete zadať aktivačný príkaz, použite * a plugin bude spustený bez aktivačného príkazu. + Zadajte aktivačné príkazy, ktoré chcete používať na spustenie pluginu a oddeľte ich medzerou. Ak nechcete zadať aktivačný príkaz, použite * a plugin bude spustený bez aktivačného príkazu. + + + Nastavenie oneskoreného vyhľadávania + Vyberte oneskorenie vyhľadávania, ktoré chcete použiť pre plugin. Ak vyberiete "{0}", plugin použije predvolené oneskorenie vyhľadávania. + Aktuálne oneskorenie vyhľadávania + Nové oneskorenie vyhľadávania Klávesová skratka vlastného vyhľadávania diff --git a/Flow.Launcher/Languages/sr.xaml b/Flow.Launcher/Languages/sr.xaml index b244c4660..1d1eb9120 100644 --- a/Flow.Launcher/Languages/sr.xaml +++ b/Flow.Launcher/Languages/sr.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Game Mode Suspend the use of Hotkeys. Position Reset - Reset search window position + Type here to search Podešavanja @@ -70,8 +75,6 @@ Isprazni poslednji Upit Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. Maksimum prikazanih rezultata You can also quickly adjust this by using CTRL+Plus and CTRL+Minus. Ignoriši prečice u fullscreen režimu @@ -102,6 +105,15 @@ Always Preview Always open preview panel when Flow activates. Press {0} to toggle preview. Shadow effect is not allowed while current theme has blur effect enabled + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Search Plugin @@ -118,6 +130,8 @@ Current action keyword New action keyword Change Action Keywords + Plugin seach delay time + Change Plugin Seach Delay Time Current Priority New Priority Priority @@ -131,6 +145,9 @@ Uninstall Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Plugin Store @@ -193,8 +210,20 @@ Custom Clock Date + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Prečica @@ -294,6 +323,9 @@ Log Folder Clear Logs Are you sure you want to delete all logs? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ Navedeni plugin nije moguće pronaći Prečica za novu radnju ne može da bude prazna Prečica za novu radnju je dodeljena drugom plugin-u, molim Vas dodelite drugu prečicu + This new Action Keyword is the same as old, please choose a different one Uspešno Completed successfully - Koristite * ako ne želite da navedete prečicu za radnju + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time prečica za ručno dodat upit diff --git a/Flow.Launcher/Languages/tr.xaml b/Flow.Launcher/Languages/tr.xaml index 5d550ebed..b9b5d351e 100644 --- a/Flow.Launcher/Languages/tr.xaml +++ b/Flow.Launcher/Languages/tr.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Oyun Modu Kısayol tuşlarının kullanımını durdurun. Pencere Konumunu Sıfırla - Arama penceresinin konumunu sıfırla + Type here to search Ayarlar @@ -70,8 +75,6 @@ Sorgu Kutusunu Temizle Preserve Last Action Keyword Select Last Action Keyword - Sabit Pencere Yükseliği - Pencere yüksekliği sürükleme ile ayarlanamaz. Maksimum Sonuç Sayısı Bunu CTRL + ve CTRL - kısayollarıyla da ayarlayabilirsiniz. Tam Ekran Modunda Kısayol Tuşunu Gözardı Et @@ -102,6 +105,15 @@ Önizleme Önizleme panelini her zaman aç. Önizlemeyi bu ayardan bağımsız {0} kısayolu ile açıp kapatabilirsiniz. Mevcut temada bulanıklık efekti etkinken gölgelendirme efektine izin verilmez + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Eklenti Ara @@ -118,6 +130,8 @@ Geçerli anahtar kelime Yeni anahtar kelime Anahtar kelimeyi değiştir + Plugin seach delay time + Change Plugin Seach Delay Time Mevcut öncelik Yeni Öncelik Öncelik @@ -131,6 +145,9 @@ Kaldır Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Eklenti Mağazası @@ -193,8 +210,20 @@ Özel Saat Tarih + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Hiçbiri + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Kısayol Tuşu @@ -294,6 +323,9 @@ Günlük Klasörü Günlükleri Temizle Tüm günlük kayıtlarını silmek istediğinize emin misiniz? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Kurulum Sihirbazı Kullanıcı Verisi Dizini Kullanıcı ayarları ve yüklü eklentiler bu klasörde saklanır. Klasörün konumu taşınabilir moda bağlı olarak değişebilir. @@ -335,9 +367,16 @@ Belirtilen eklenti bulunamadı Yeni anahtar kelime boş olamaz Yeni anahtar kelime başka bir eklentiye atanmış durumda. Lütfen başka bir anahtar kelime seçin. + This new Action Keyword is the same as old, please choose a different one Başarılı Başarıyla tamamlandı - Herhangi bir anahtar kelime belirlemek istemiyorsanız * kullanın + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Özel Sorgu Kısayolları diff --git a/Flow.Launcher/Languages/uk-UA.xaml b/Flow.Launcher/Languages/uk-UA.xaml index 95a746a51..427511c66 100644 --- a/Flow.Launcher/Languages/uk-UA.xaml +++ b/Flow.Launcher/Languages/uk-UA.xaml @@ -7,6 +7,11 @@ Клацніть Ні, якщо воно вже встановлене, і вам буде запропоновано вибрати теку, яка містить виконуваник {1} Будласка оберіть виконуваник {0} + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Не вдається встановити шлях до виконуваника {0}, будласка спробуйте в налаштуваннях Flow (прокрутіть вниз до кінця). Невдача ініціалізації плагінів Плагіни: {0} - не вдалося підвантажити і буде вимкнено, зверніться за допомогою до автора плагіна @@ -37,7 +42,7 @@ Режим гри Призупинити використання гарячих клавіш. Скидання позиції - Скинути положення вікна пошуку + Type here to search Налаштування @@ -70,8 +75,6 @@ Очистити останній запит Preserve Last Action Keyword Select Last Action Keyword - Фіксована висота вікна - Висота вікна не регулюється перетягуванням. Максимальна кількість результатів Ви також можете швидко налаштувати цей параметр за допомогою клавіш CTRL+Плюс чи CTRL+Мінус. Ігнорувати гарячі клавіші в повноекранному режимі @@ -102,6 +105,15 @@ Завжди переглядати Завжди відкривати панель попереднього перегляду при активації Flow. Натисніть {0}, щоб переключити попередній перегляд. Ефект тіні не дозволено, коли поточна тема має ефект розмиття + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Плагін для пошуку @@ -118,6 +130,8 @@ Поточна гаряча клавіша Нова гаряча клавіша Змінити гарячі клавіши + Plugin seach delay time + Change Plugin Seach Delay Time Поточний пріоритет Новий пріоритет Пріоритет @@ -131,6 +145,9 @@ Видалити Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Магазин плагінів @@ -193,8 +210,20 @@ Користувацька Годинник Дата + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Нема + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. Ця тема підтримує розмитий прозорий фон. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Гаряча клавіша @@ -294,6 +323,9 @@ Тека журналу Очистити журнали Ви впевнені, що хочете видалити всі журнали? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Чаклун Розташування даних користувача Налаштування користувача та встановлені плагіни зберігаються у теці даних користувача. Це місце може змінюватися залежно від того, чи перебуває програма в портативному режимі, чи ні. @@ -335,9 +367,16 @@ Не вдалося знайти вказаний плагін Нова гаряча клавіша не може бути порожньою Нова гаряча клавіша вже використовується іншим плагіном. Будь ласка, вкажіть нову + This new Action Keyword is the same as old, please choose a different one Успішно Успішно завершено - Введіть гарячу клавішу, яку ви хочете використовувати для запуску плагіна. Використовуйте * у разі, якщо ви не хочете ставити конкретну гарячу клавішу. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Задані гарячі клавіші для запитів diff --git a/Flow.Launcher/Languages/vi.xaml b/Flow.Launcher/Languages/vi.xaml index 17e421e16..6223efc00 100644 --- a/Flow.Launcher/Languages/vi.xaml +++ b/Flow.Launcher/Languages/vi.xaml @@ -7,6 +7,11 @@ Hãy chọn không nếu nó đã được cài đặt, và bạn sẽ được hỏi chọn thư mục chứa chương trình thực thi {1} Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Chế độ trò chơi Tạm dừng sử dụng phím nóng. Đặt lại vị trí - Đặt lại vị trí của cửa sổ tìm kiếm + Type here to search Cài đặt @@ -70,8 +75,6 @@ Trống truy vấn cuối cùng Preserve Last Action Keyword Select Last Action Keyword - Giữ nguyên chiều cao cửa sổ - Chiều cao cửa sổ không thể thay đổi bằng cách kéo. Số kết quả tối đa Có thể thiết lập nhanh chóng bằng CTRL+Plus và CTRL+Minus. Bỏ qua phím nóng khi cửa sổ ở chế độ toàn màn hình @@ -102,6 +105,15 @@ Luôn xem trước Luôn mở bảng xem trước khi Flow kích hoạt. Nhấn {0} để chuyển đổi chế độ xem trước. Hiệu ứng đổ bóng không được phép nếu chủ đề hiện tại bật hiệu ứng làm mờ + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Plugin tìm kiếm @@ -118,6 +130,8 @@ Từ hành động hiện tại Từ hành động mới Thay đổi từ hành động + Plugin seach delay time + Change Plugin Seach Delay Time Ưu tiên hiện tại Ưu tiên mới Ưu tiên @@ -131,6 +145,9 @@ Gỡ cài đặt Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Tải tiện ích mở rộng @@ -193,8 +210,20 @@ Tùy chỉnh Giờ Ngày + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Không + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Phím tắt @@ -296,6 +325,9 @@ Thư mục nhật ký Xóa tệp nhật ký Bạn có chắc chắn muốn xóa tất cả nhật ký không? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard Vị trí dữ liệu người dùng Thiết đặt người dùng và plugin đã cài đặt sẽ được lưu trong thư mục dữ liệu người dùng. Vị trí này có thể thay đổi tùy thuộc vào việc nó có ở chế độ di động hay không. @@ -337,9 +369,16 @@ Không thể tìm thấy plugin được chỉ định Từ khóa hành động mới không được để trống Từ khóa hành động mới này đã được gán cho một plugin khác, vui lòng chọn một plugin khác + This new Action Keyword is the same as old, please choose a different one Thành công Đã hoàn tất thành công - Sử dụng * nếu bạn muốn xác định từ khóa hành động. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Phím nóng truy vấn tùy chỉnh diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index d9966d757..3d302da5b 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -7,6 +7,11 @@ 如果已安装,请单击“否”,系统将提示您选择包含 {1} 可执行文件的文件夹 请选择 {0} 可执行文件 + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + 无法设置 {0} 可执行路径,请尝试从 Flow 的设置中设置(向下滚动到底部)。 无法初始化插件 插件:{0} - 无法加载并将被禁用,请联系插件创建者寻求帮助 @@ -37,7 +42,7 @@ 游戏模式 暂停使用热键。 重置位置 - 重置搜索窗口位置 + Type here to search 设置 @@ -70,8 +75,6 @@ 清空上次搜索关键字 Preserve Last Action Keyword Select Last Action Keyword - 固定窗口高度 - 窗口高度不能通过拖动来调整。 最大结果显示个数 您也可以通过使用 CTRL+ "+" 和 CTRL+ "-" 来快速调整它。 全屏模式下忽略热键 @@ -102,6 +105,15 @@ 始终打开预览 Flow 启动时总是打开预览面板。按 {0} 以切换预览。 当前主题已启用模糊效果,不允许启用阴影效果 + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short 搜索插件 @@ -118,6 +130,8 @@ 当前触发关键字 新触发关键字 更改触发关键字 + Plugin seach delay time + Change Plugin Seach Delay Time 当前优先级 新优先级 优先级 @@ -131,6 +145,9 @@ 卸载 Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default 插件商店 @@ -193,8 +210,20 @@ 自定义 时钟 日期 + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + + Acrylic + Mica + Mica Alt 该主题支持两种(浅色/深色)模式。 该主题支持模糊透明背景。 + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. 热键 @@ -294,6 +323,9 @@ 日志目录 清除日志 你确定要删除所有的日志吗? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information 向导 用户数据位置 用户设置和已安装的插件保存在用户数据文件夹中。此位置可能因是否处于便携模式而异。 @@ -335,9 +367,16 @@ 找不到指定的插件 新触发关键字不能为空 此触发关键字已经被指派给其他插件了,请换一个关键字 + This new Action Keyword is the same as old, please choose a different one 成功 成功完成 - 如果你不想设置触发关键字,可以使用*代替 + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time 自定义查询热键 @@ -371,7 +410,7 @@ 更新 - 背景 + 后台 版本 diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index 01b667e72..cecad8e0d 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ 遊戲模式 暫停使用快捷鍵。 重設位置 - 重設搜尋視窗位置 + Type here to search 設定 @@ -70,8 +75,6 @@ 清空上次搜尋關鍵字 Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. 最大結果顯示個數 You can also quickly adjust this by using CTRL+Plus and CTRL+Minus. 全螢幕模式下忽略快捷鍵 @@ -102,6 +105,15 @@ 一律預覽 當 Flow 啟動時,一律開啟預覽面板。按下 {0} 可切換預覽。 Shadow effect is not allowed while current theme has blur effect enabled + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Search Plugin @@ -118,6 +130,8 @@ 目前觸發關鍵字 新觸發關鍵字 更改觸發關鍵字 + Plugin seach delay time + Change Plugin Seach Delay Time 目前優先 新增優先 優先 @@ -131,6 +145,9 @@ 解除安裝 Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default 插件商店 @@ -193,8 +210,20 @@ Custom 時鐘 日期 + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. 快捷鍵 @@ -294,6 +323,9 @@ 日誌資料夾 清除日誌 請確認要刪除所有日誌嗎? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information 嚮導 User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ 找不到指定的插件 新觸發關鍵字不能為空白 新觸發關鍵字已經被指派給另一個插件,請設定其他關鍵字。 + This new Action Keyword is the same as old, please choose a different one 成功 成功完成 - 如果不想設定觸發關鍵字,可以使用*代替 + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time 自定義快捷鍵查詢 diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml index 4cdd4c934..d8d3a586f 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml @@ -2,7 +2,7 @@ Kalkulačka - Spracúva matematické operácie.(Skúste 5*3-2 vo flowlauncheri) + Spracúva matematické operácie. (Skúste 5*3-2 vo Flow Launcheri) Nie je číslo (NaN) Nesprávny alebo neúplný výraz (Nezabudli ste na zátvorky?) Kopírovať výsledok do schránky diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ko.xaml index 41a4abfcf..cc78c9a9a 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ko.xaml @@ -4,6 +4,6 @@ Activate {0} plugin action keyword 플러그인 인디케이터 - 플러그인의 액션 키워드 제안을 제공합니다 + 사용중인 플러그인들의 전체 액션 키워드 목록을 보여줍니다 diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/de.xaml index df162af92..47ea31cce 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/de.xaml @@ -13,8 +13,8 @@ Plugin wird installiert {0} herunterladen und installieren Plug-in-Deinstallation - Keep plugin settings - Do you want to keep the settings of the plugin for the next usage? + Plug-in-Einstellungen beibehalten + Möchten Sie die Einstellungen des Plug-ins für die nächste Nutzung beibehalten? Plug-in {0} erfolgreich installiert. Flow wird neu gestartet, bitte warten Sie ... Die Metadaten-Datei plugin.json in der entpackten Zip-Datei kann nicht gefunden werden. Fehler: Ein Plug-in, welches die gleiche oder eine höhere Version mit {0} hat, ist bereits vorhanden. diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ar.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ar.xaml index 4104bd757..04619239d 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ar.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ar.xaml @@ -8,4 +8,6 @@ قتل عمليات {0} قتل جميع الأمثلة + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/cs.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/cs.xaml index 4dc11fcec..d621b63c4 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/cs.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/cs.xaml @@ -8,4 +8,6 @@ ukončit {0} procesů ukončit všechny instance + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/da.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/da.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/da.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/da.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/de.xaml index 8697818dc..766d170a4 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/de.xaml @@ -8,4 +8,6 @@ {0} Prozesse beenden Alle Instanzen beenden + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es-419.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es-419.xaml index 2dd0745c3..9b4a20a69 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es-419.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es-419.xaml @@ -8,4 +8,6 @@ terminar {0} procesos termina todas las instancias + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es.xaml index 27fda1db7..ab788075e 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es.xaml @@ -8,4 +8,6 @@ finalizar {0} procesos finalizar todas las instancias + Colocar procesos con ventanas visibles en la parte superior + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/fr.xaml index ec880406a..7064de1fe 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/fr.xaml @@ -8,4 +8,6 @@ Tuer {0} processus Tuer toutes les instances + Placer les processus dont les fenêtres sont visibles en haut de la page + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/he.xaml index 018435eca..8567b5412 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/he.xaml @@ -8,4 +8,6 @@ סגור {0} תהליכים סגור את כל המופעים + הצב תהליכים עם חלונות גלויים בחלק העליון + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/it.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/it.xaml index 1ea52e741..1333fe573 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/it.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/it.xaml @@ -8,4 +8,6 @@ termina {0} processi termina tutte le istanze + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ko.xaml index a19c958b4..c3d1f6d08 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ko.xaml @@ -8,4 +8,6 @@ {0} 프로세스 종료 모든 인스턴스 종료 + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nb.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nb.xaml index f06121887..1210818bf 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nb.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nb.xaml @@ -8,4 +8,6 @@ terminer {0} processes terminer alle forekomstene + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nl.xaml index c4cc85463..cfcd71c37 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nl.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Zet processen met zichtbare vensters bovenaan + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pl.xaml index a111f8776..650f14657 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pl.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pl.xaml @@ -8,4 +8,6 @@ zamknij {0} procesów zamknij wszystkie instancje + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-br.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-br.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-pt.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-pt.xaml index b5c75f2d9..944a883c9 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-pt.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-pt.xaml @@ -8,4 +8,6 @@ terminar {0} processos terminar todas as instâncias + Colocar processos com janelas visíveis por cima + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ru.xaml index 26963bddb..0e2bef052 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ru.xaml @@ -8,4 +8,6 @@ удалить {0} процессов удалить все экземпляры + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sk.xaml index bfa4792e4..2b06d3bbe 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sk.xaml @@ -8,4 +8,6 @@ ukončiť {0} procesov ukončiť všetky inštancie + Zobraziť procesy s viditeľným oknom navrchu + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sr.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sr.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sr.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sr.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/tr.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/tr.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/uk-UA.xaml index e23f43875..02dab46ba 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/uk-UA.xaml @@ -8,4 +8,6 @@ вбити {0} процесів вбити всі екземпляри + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/vi.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/vi.xaml index 0bf065ee1..89fd67635 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/vi.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/vi.xaml @@ -8,4 +8,6 @@ Buộc tắt các tiến trình {0} Tắt tất cả phên bản + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-cn.xaml index 160ca5f96..15e717c79 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-cn.xaml @@ -8,4 +8,6 @@ 杀死 {0} 进程 杀死所有实例 + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-tw.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-tw.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/de.xaml index 662765760..14e228b2a 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/de.xaml @@ -34,8 +34,8 @@ Blendet Programme mit gängigen Uninstaller-Namen aus, wie unins000.exe In Programmbeschreibung suchen Flow wird in Programmbeschreibung suchen - Hide duplicated apps - Hide duplicated Win32 programs that are already in the UWP list + Duplizierte Apps ausblenden + Duplizierte Win32-Programme ausblenden, die bereits in der UWP-Liste sind Suffixe Maximale Tiefe diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/he.xaml index 0e8b2f1d5..af272fb46 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/he.xaml @@ -84,7 +84,7 @@ סייר מותאם אישית ארגומנטים - You can customize the explorer used for opening the container folder by inputing the Environmental Variable of the explorer you want to use. It will be useful to use CMD to test whether the Environmental Variable is available. + באפשרותך להתאים אישית את הסייר שבו נעשה שימוש לפתיחת תיקיית המכולה על ידי הזנת משתנה הסביבה של הסייר שברצונך להשתמש בו. כדאי לבדוק באמצעות CMD אם משתנה הסביבה זמין. הזן את הארגומנטים שברצונך להוסיף לסייר המותאם אישית שלך. %s עבור ספריית האב, %f עבור הנתיב המלא (זמין רק עבור win32). בדוק באתר הסייר לפרטים נוספים. diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Shell/Languages/de.xaml index 77a3fed47..dcfc82e0a 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.Shell/Languages/de.xaml @@ -6,7 +6,7 @@ Drücken Sie eine beliebige Taste, um dieses Fenster zu schließen ... Eingabeaufforderung nach Befehlsausführung nicht schließen Immer als Administrator ausführen - Use Windows Terminal + Windows-Terminal verwenden Als anderer Benutzer ausführen Shell Ermöglicht das Ausführen von Systembefehlen aus Flow Launcher diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ar.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ar.xaml index 529be9f45..ccc50678e 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ar.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ar.xaml @@ -2,8 +2,9 @@ - أمر + اسم البرنامج وصف + أمر إيقاف التشغيل إعادة التشغيل @@ -27,6 +28,8 @@ تبديل وضع اللعبة Set the Flow Launcher Theme + تعدي + إيقاف تشغيل الكمبيوتر إعادة تشغيل الكمبيوتر @@ -59,6 +62,15 @@ هل أنت متأكد أنك تريد إعادة تشغيل الكمبيوتر مع خيارات التمهيد المتقدمة؟ هل أنت متأكد أنك تريد تسجيل الخروج؟ + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + إعادة تعيين + Confirm + إلغاء + Please enter a non-empty command keyword + أوامر النظام يوفر أوامر متعلقة بالنظام، مثل إيقاف التشغيل، القفل، الإعدادات، وما إلى ذلك. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/cs.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/cs.xaml index 1a42ce51b..de35c9592 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/cs.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/cs.xaml @@ -2,8 +2,9 @@ - Příkaz + Jméno Popis + Příkaz Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Editovat + Vypnout počítač Restartovat počítač @@ -59,6 +62,15 @@ Opravdu chcete restartovat počítač s rozšířenými možnostmi spouštění? Opravdu se chcete odhlásit? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Potvrdit + Zrušit + Please enter a non-empty command keyword + Systémové příkazy Poskytuje příkazy související se systémem, jako je vypnutí, uzamčení počítače atd. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/da.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/da.xaml index 172adfd2f..91230e7e3 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/da.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/da.xaml @@ -2,8 +2,9 @@ - Command + Name Description + Command Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Rediger + Shutdown Computer Restart Computer @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + Annuller + Please enter a non-empty command keyword + System Commands Provides System related commands. e.g. shutdown, lock, settings etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/de.xaml index cdd0e0348..794e949ad 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/de.xaml @@ -2,8 +2,9 @@ - Befehl + Name Beschreibung + Befehl Herunterfahren Neu starten @@ -25,7 +26,9 @@ Flow Launcher-Tipps Flow Launcher UserData-Ordner Spielmodus umschalten - Set the Flow Launcher Theme + Flow Launcher-Theme festlegen + + Bearbeiten Computer herunterfahren @@ -48,7 +51,7 @@ Besuchen Sie die Dokumentation von Flow Launcher für mehr Hilfe und Tipps zur Verwendung Den Ort öffnen, an dem die Einstellungen von Flow Launcher gespeichert sind Spielmodus umschalten - Quickly change the Flow Launcher theme + Das Flow-Launcher-Theme schnell ändern Erfolg @@ -56,9 +59,18 @@ Alle anwendbaren Plug-in-Daten neu geladen Sind Sie sicher, dass Sie den Computer herunterfahren wollen? Sind Sie sicher, dass Sie den Computer neu starten wollen? - Soll der Computer wirklich mit erweiterten Startoptionen neu gestartet werden? + Sind Sie sicher, dass Sie den Computer mit erweiterten Boot-Optionen neu starten wollen? Sind Sie sicher, dass Sie sich ausloggen wollen? + Befehls-Schlüsselwort-Einstellung + Benutzerdefiniertes Befehls-Schlüsselwort + Geben Sie ein Schlüsselwort ein, um nach dem Befehl zu suchen: {0}. Dieses Schlüsselwort wird verwendet, um Ihre Anfrage abzugleichen. + Befehls-Schlüsselwort + Zurücksetzen + Bestätigen + Abbrechen + Bitte geben Sie ein nicht-leeres Befehls-Schlüsselwort ein + Systembefehle Bietet systembezogene Befehle, z. B. Herunterfahren, Sperren, Einstellungen etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/es-419.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/es-419.xaml index 99eec60fa..ac4040dca 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/es-419.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/es-419.xaml @@ -2,8 +2,9 @@ - Command + Name Description + Command Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Editar + Shutdown Computer Restart Computer @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + Cancelar + Please enter a non-empty command keyword + System Commands Provides System related commands. e.g. shutdown, lock, settings etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/es.xaml index 2139738f7..5f3688ab8 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/es.xaml @@ -2,8 +2,9 @@ - Comando + Nombre Descripción + Comando Apagar Reiniciar @@ -27,6 +28,8 @@ Cambiar a Modo Juego Establecer el tema de Flow Launcher + Editar + Apaga el equipo Reinicia el equipo @@ -59,6 +62,15 @@ ¿Está seguro de que desea reiniciar el equipo con opciones de arranque avanzadas? ¿Está seguro de que desea cerrar la sesión? + Configuración de la palabra clave de comando + Palabra clave de comando personalizada + Introducir una palabra clave para buscar el comando: {0}. Esta palabra clave se utiliza para que coincida con la búsqueda. + Palabra clave de comando + Restablecer + Confirmar + Cancelar + Por favor, introducir una palabra clave de comando no vacía + Comandos del sistema Proporciona comandos relacionados con el sistema. Por ejemplo, apagar, bloquear, configurar, etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/fr.xaml index 727a9a6ad..5419bd8e2 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/fr.xaml @@ -2,8 +2,9 @@ - Commande + Nom Description + Commande Arrêter Redémarrer @@ -27,6 +28,8 @@ Basculer le mode de jeu Définir le thème Flow Launcher + Modifier + Éteindre l'ordinateur Redémarrer l'ordinateur @@ -59,6 +62,15 @@ Êtes-vous sûr de vouloir redémarrer l'ordinateur avec les options de démarrage avancées ? Êtes-vous sûr de vouloir vous déconnecter ? + Réglage du mot-clé de commande + Mot-clé de commande personnalisé + Entrez un mot-clé pour rechercher la commande : {0}. Ce mot-clé est utilisé pour répondre à votre requête. + Mot-clé de commande + Réinitialiser + Confirmer + Annuler + Veuillez saisir un mot-clé de commande non vide + Commandes système Fournit des commandes liées au système. Par exemple, arrêt, verrouillage, paramètres, etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/he.xaml index acc3f3b59..86688a130 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/he.xaml @@ -2,8 +2,9 @@ - פקודה + שם תיאור + פקודה כיבוי הפעלה מחדש @@ -27,6 +28,8 @@ מצב משחק Set the Flow Launcher Theme + ערו + כבה את המחשב הפעל מחדש את המחשב @@ -59,6 +62,15 @@ האם אתה בטוח שברצונך להפעיל מחדש את המחשב עם אפשרויות אתחול מתקדמות? האם אתה בטוח שברצונך להתנתק? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + אפס + אישו + ביטול + Please enter a non-empty command keyword + פקודות מערכת מספק פקודות הקשורות למערכת, כגון כיבוי, נעילה, הגדרות ועוד. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/it.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/it.xaml index b464cab28..be31e4e52 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/it.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/it.xaml @@ -2,8 +2,9 @@ - Comando + Nome Descrizione + Comando Spegni Riavvia @@ -27,6 +28,8 @@ Attiva/Disattiva Modalità Di Gioco Set the Flow Launcher Theme + Modifica + Spegni il computer Riavvia il Computer @@ -59,6 +62,15 @@ Sei sicuro di voler riavviare il computer con le Opzioni di Avvio Avanzate? Sei sicuro di volerti disconettere? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Resetta + Conferma + Annulla + Please enter a non-empty command keyword + Comandi di Sistema Fornisce comandi relativi al sistema, ad esempio spegnimento, blocco, impostazioni ecc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml index cff426d4e..bc7dff59f 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml @@ -2,8 +2,9 @@ - コマンド + Name 説明 + コマンド Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + + コンピュータをシャットダウンする コンピュータを再起動する @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + + Please enter a non-empty command keyword + システムコマンド システム関連のコマンドを提供します。例:シャットダウン、ロック、設定など diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ko.xaml index d9b568e14..f2049038f 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ko.xaml @@ -2,8 +2,9 @@ - 명령어 + Name 설명 + 명령어 Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + 편집 + 시스템 종료 시스템 재시작 @@ -59,6 +62,15 @@ 고급 부팅 옵션으로 시스템을 다시 시작하시겠습니까? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + 확인 + 취소 + Please enter a non-empty command keyword + 시스템 명령어 시스템 종료, 컴퓨터 잠금, 설정 등과 같은 시스템 관련 명령어를 제공합니다 diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/nb.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/nb.xaml index a531189fe..072fd623d 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/nb.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/nb.xaml @@ -2,8 +2,9 @@ - Kommando + Navn Beskrivelse + Kommando Slå av Start på nytt @@ -27,6 +28,8 @@ Vis/Skjul spillmodus Set the Flow Launcher Theme + Rediger + Slår av datamaskin Start datamaskinen på nytt @@ -59,6 +62,15 @@ Er du sikker på at du vil starte datamaskinen på nytt med avanserte oppstartsalternativer? Er du sikker på at du vil logge av? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Tilbakestill + Bekreft + Avbryt + Please enter a non-empty command keyword + Systemkommandoer Gir systemrelaterte kommandoer, f.eks. slå av, lås, innstillinger osv. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml index e0e4d46a8..9d1d54076 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml @@ -2,8 +2,9 @@ - Opdracht + Name Beschrijving + Opdracht Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Bewerken + Computer afsluiten Computer opnieuw opstarten @@ -59,6 +62,15 @@ Weet u zeker dat u de computer wilt herstarten met geavanceerde opstartopties? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Herstellen + Confirm + Annuleer + Please enter a non-empty command keyword + Systeemopdrachten Voorziet in systeem gerelateerde opdrachten. bijv.: afsluiten, vergrendelen, instellingen, enz. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pl.xaml index bbb3bec88..c09a447d2 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pl.xaml @@ -2,8 +2,9 @@ - Komenda + Nazwa Opis + Komenda Wyłącz komputer Restart @@ -27,6 +28,8 @@ Przełącz tryb gry Set the Flow Launcher Theme + Edytuj + Wyłącz komputer Uruchom ponownie komputer @@ -59,6 +62,15 @@ Czy na pewno chcesz ponownie uruchomić komputer z Zaawansowanymi opcjami rozruchu? Czy na pewno chcesz się wylogować? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Zresetuj + Potwierdź + Anuluj + Please enter a non-empty command keyword + Komendy systemowe Wykonywanie komend systemowych, np. wyłącz, zablokuj komputer, otwórz ustawienia itp. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-br.xaml index b356f6bc7..a19ab39d6 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-br.xaml @@ -2,8 +2,9 @@ - Comando + Nome Descrição + Comando Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Editar + Desligar o Computador Reiniciar o Computador @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + Cancelar + Please enter a non-empty command keyword + System Commands Provides System related commands. e.g. shutdown, lock, settings etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-pt.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-pt.xaml index aa7217c01..9e0e39066 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-pt.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-pt.xaml @@ -2,8 +2,9 @@ - Comando + Nome Descrição + Comando Desligar Reiniciar @@ -25,7 +26,9 @@ Dicas Flow Launcher Pasta de dados do utilizador Flow Launcher Comutar modo de jogo - Set the Flow Launcher Theme + Definir tema Flow Launcher + + Editar Desligar computador @@ -48,7 +51,7 @@ Aceda à documentação para mais informações e dicas de utilização Abrir localização onde as definições do Flow Launcher estão guardadas Comutar modo de jogo - Quickly change the Flow Launcher theme + Alterar rapidamente o tema da aplicação Sucesso @@ -59,6 +62,15 @@ Tem certeza de que deseja reiniciar o computador com as opções avançadas de arranque? Tem certeza de que deseja terminar a sessão? + Definição de palavra-chave + Palavra-chave personalizada + Indique a palavra-chave para pesquisar o comando: {0}. A aplavra-chave será usada para correspondência com a consulta. + Palavra-chave + Repor + Confirmar + Cancelar + Não pode indicar uma palavra-chave vazia + Comandos do sistema Disponibiliza os comandos relacionados com o sistema tais como: desligar, bloquear, reiniciar... diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml index 4547274f8..796cda69d 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml @@ -2,8 +2,9 @@ - Command + Name Description + Command Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Редактировать + Shutdown Computer Restart Computer @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + Отменить + Please enter a non-empty command keyword + System Commands Provides System related commands. e.g. shutdown, lock, settings etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/sk.xaml index 0f8894288..087ff9f05 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/sk.xaml @@ -2,8 +2,9 @@ - Príkaz + Názov Popis + Príkaz Vypnúť Reštartovať @@ -27,6 +28,8 @@ Prepnúť herný režim Nastaviť motív pre Flow Laucher + Upraviť + Vypnúť počítač Reštartovať počítač @@ -59,6 +62,15 @@ Naozaj chcete počítač reštartovať s pokročilými možnosťami spúšťania? Naozaj sa chcete odhlásiť? + Nastavenia kľúčového slova príkazu + Vlastné kľúčové slovo príkazu + Na vyhľadanie príkazu zadajte kľúčové slovo: {0}. Toto kľúčové slovo sa použije na vyhľadnie príkazu. + Kľúčové slovo príkazu + Resetovať + Potvrdiť + Zrušiť + Prosím, zadajte neprázdne kľúčové slovo príkazu + Systémové príkazy Poskytuje príkazy súvisiace so systémom ako je vypnutie, uzamknutie počítača atď. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/sr.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/sr.xaml index d04a783d0..f5a2f1b30 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/sr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/sr.xaml @@ -2,8 +2,9 @@ - Command + Name Description + Command Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Izmeni + Shutdown Computer Restart Computer @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + Otkaži + Please enter a non-empty command keyword + System Commands Provides System related commands. e.g. shutdown, lock, settings etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/tr.xaml index 93973913f..18f7f63f5 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/tr.xaml @@ -2,8 +2,9 @@ - Komut + Name Açıklama + Komut Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Düzenle + Bilgisayarı Kapat Yeniden Başlat @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Sıfırla + Onayla + İptal + Please enter a non-empty command keyword + Sistem Komutları Sistem ile ilgili komutlara erişim sağlar. ör. shutdown, lock, settings vb. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml index 57c83e1a5..19d69511b 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml @@ -2,8 +2,9 @@ - Команда + Назва Опис + Команда Вимкнути Перезавантажити @@ -27,6 +28,8 @@ Перемкнути режим гри Set the Flow Launcher Theme + Редагувати + Вимкнути комп'ютер Перезавантажити комп'ютер @@ -59,6 +62,15 @@ Ви впевнені, що хочете перезавантажити комп'ютер за допомогою додаткових параметрів завантаження? Ви впевнені, що хочете вийти з системи? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Скинути + Підтвердити + Скасувати + Please enter a non-empty command keyword + Системні команди Надає команди, пов'язані з системою, наприклад, вимкнення, блокування, налаштування тощо. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/vi.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/vi.xaml index 8d0bc43c0..dae12c501 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/vi.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/vi.xaml @@ -2,8 +2,9 @@ - Lệnh + Tên Mô Tả + Lệnh Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Sửa + shutdown máy tính Khởi động lại máy tính @@ -59,6 +62,15 @@ Bạn có chắc chắn muốn khởi động lại máy tính bằng Advanced Boot Options không? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Đặt lại + Xác nhận + Hủy + Please enter a non-empty command keyword + Lệnh hệ thống Cung cấp các lệnh liên quan đến Hệ thống. ví dụ. tắt máy, khóa, cài đặt, v.v. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-cn.xaml index e08f312b1..745129130 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-cn.xaml @@ -2,8 +2,9 @@ - 命令 + 名称 描述 + 命令 关机 重启 @@ -27,6 +28,8 @@ 切换游戏模式 Set the Flow Launcher Theme + 编辑 + 关闭电脑 重启这台电脑 @@ -59,6 +62,15 @@ 您确定要以高级启动选项重启吗? 您确定要注销吗? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + 重置 + 确认 + 取消 + Please enter a non-empty command keyword + 系统命令 提供操作系统相关的命令,如关机、锁定、设置等。 diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml index d43496466..573aefcbd 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml @@ -2,8 +2,9 @@ - 命令 + 名稱 描述 + 命令 Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + 編輯 + 電腦關機 電腦重新啟動 @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + 確認 + 取消 + Please enter a non-empty command keyword + 系統命令 系統相關的命令。例如,關機,鎖定,設定等 diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ar.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ar.xaml index 6e92178db..cefb5d1d1 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ar.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ar.xaml @@ -17,7 +17,7 @@ كلمة مفتاحية للعمل الرابط بحث - استخدام الإكمال التلقائي لاستعلام البحث: + Use Search Query Autocomplete بيانات الإكمال التلقائي من: يرجى اختيار بحث على الويب هل أنت متأكد أنك تريد حذف {0}؟ diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/cs.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/cs.xaml index 849f27f05..ca98581c3 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/cs.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/cs.xaml @@ -17,7 +17,7 @@ Aktivační příkaz URL Hledat - Používejte automatické dokončování vyhledávaných výrazů: + Use Search Query Autocomplete Automatické doplnění údajů z: Vyberte webové vyhledávání Opravdu chcete odstranit {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/da.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/da.xaml index 2a7d4aa32..b1113acb7 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/da.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/da.xaml @@ -17,7 +17,7 @@ Action Keyword URL Search - Use Search Query Autocomplete: + Use Search Query Autocomplete Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml index 0c72b11bf..2a7dca596 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml @@ -17,8 +17,8 @@ Aktions-Schlüsselwort URL Suche - Autovervollständigung von Suchanfragen verwenden: - Daten automatisch vervollständigen aus: + Autovervollständigung von Suchanfragen verwenden + Autovervollständigung der Daten aus: Bitte wählen Sie eine Websuche aus Sind Sie sicher, dass Sie {0} löschen wollen? Wenn Sie Flow eine Suche nach einer bestimmten Website hinzufügen möchten, geben Sie zunächst eine Dummy-Textzeichenfolge in die Suchleiste dieser Website ein und starten Sie die Suche. Kopieren Sie jetzt den Inhalt der Adressleiste des Browsers und fügen Sie ihn in das URL-Feld unten ein. Ersetzen Sie Ihre Testzeichenfolge durch {q}. Zum Beispiel, wenn Sie auf Netflix nach casino suchen, steht in der Adressleiste @@ -30,8 +30,8 @@ https://www.netflix.com/search?q={q} - Copy URL - Copy search URL to clipboard + URL kopieren + Such-URL in Zwischenablage kopieren Titel diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es-419.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es-419.xaml index 517ac0918..3ce22bb78 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es-419.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es-419.xaml @@ -17,7 +17,7 @@ Palabra clave URL Buscar - Autocompletar la búsqueda: + Use Search Query Autocomplete Autocompletar datos de: Por favor, seleccione una búsqueda ¿Seguro que desea eliminar {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml index e6e4a94d2..7f14b59c6 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml @@ -17,7 +17,7 @@ Palabra clave de acción URL Busca en - Usar autocompletado en consultas de búsqueda: + Usar autocompletado en consultas de búsqueda Autocompletar datos desde: Por favor, seleccione una búsqueda web ¿Está seguro de que desea eliminar {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml index c6b1b145c..f04cfb48a 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml @@ -17,7 +17,7 @@ Mot-clé d'action URL Rechercher sur - Utiliser la saisie automatique de la requête de recherche : + Utiliser la fonction d'auto-complétion des requêtes de recherche Saisir automatiquement les données à partir de : Veuillez sélectionner une recherche web Êtes-vous sûr de vouloir supprimer {0} ? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/he.xaml index 630287983..78ee7ca7d 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/he.xaml @@ -17,7 +17,7 @@ מילת מפתח לפעולה כתובת URL חיפו - השתמש בהשלמה אוטומטית לשאילתות חיפוש: + השתמש בהשלמה אוטומטית לשאילתת חיפוש השלמה אוטומטית מתוך: בחר שירות חיפוש אינטרנטי האם אתה בטוח שברצונך למחוק את {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/it.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/it.xaml index 26c1e8459..db2a4dfeb 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/it.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/it.xaml @@ -17,7 +17,7 @@ Parola Chiave URL Cerca - Usa Autocompletamento Ricerca: + Use Search Query Autocomplete Autocompleta i dati da: Seleziona una ricerca web Sei sicuro di voler eliminare {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml index 85ce0e282..9ae628853 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml @@ -17,7 +17,7 @@ キーワード URL 検索 - 検索サジェスチョンを有効にする + Use Search Query Autocomplete Autocomplete Data from: web検索を選択してください Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ko.xaml index 5ab5fffa3..3ac9f6a6c 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ko.xaml @@ -17,7 +17,7 @@ 액션 키워드 URL 검색 - 검색 쿼리 자동완성 사용: + Use Search Query Autocomplete 자동완성 데이터 출처: 웹 검색을 선택하세요 Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nb.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nb.xaml index 4bba382a9..9f793c43f 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nb.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nb.xaml @@ -17,7 +17,7 @@ Nøkkelord for handling Nettadresse Søk - Bruk autofullføring av søkespørring: + Use Search Query Autocomplete Autofullfør data fra: Vennligst velg et websøk Er du sikker på at du ønsker å slette {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nl.xaml index a48d99487..a18710324 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nl.xaml @@ -17,7 +17,7 @@ Action Keyword URL Search - Use Search Query Autocomplete: + Use Search Query Autocomplete Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pl.xaml index 499351343..d693a3f28 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pl.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pl.xaml @@ -17,7 +17,7 @@ Wyzwalacz Adres URL Szukaj - Pokazuj podpowiedzi wyszukiwania + Use Search Query Autocomplete Autouzupełnianie danych z: Musisz wybrać coś z listy Czy jesteś pewien że chcesz usunąć {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml index d4135c795..6f0d7fcc9 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml @@ -17,7 +17,7 @@ Action Keyword URL Search - Use Search Query Autocomplete: + Use Search Query Autocomplete Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-pt.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-pt.xaml index 16969dac7..1a2476a2c 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-pt.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-pt.xaml @@ -17,7 +17,7 @@ Palavra-chave de ação URL Pesquisar - Utilizar conclusão automática da consulta: + Utilizar conclusão automática para as consultas Preencher dados a partir de: Selecione uma pesquisa web Tem a certeza de que deseja eliminar {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml index c59182290..1fd9aca96 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml @@ -1,4 +1,4 @@ - + Search Source Setting @@ -17,7 +17,7 @@ Action Keyword URL Search - Use Search Query Autocomplete: + Use Search Query Autocomplete Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? @@ -28,8 +28,9 @@ Then replace casino with {q}. Thus, the generic formula for a search on Netflix is https://www.netflix.com/search?q={q} - Скопировать URL-адрес - Скопировать URL поиска в буфер обмена + + Copy URL + Copy search URL to clipboard Title diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sk.xaml index 44b765c58..1afcdb360 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sk.xaml @@ -17,7 +17,7 @@ Aktivačný príkaz Adresa URL Hľadať - Použiť automatické dokončovanie výrazov vyhľadávania: + Použiť automatické dokončovanie výrazov vyhľadávania Automatické dokončovanie údajov z: Vyberte webové vyhľadávanie Naozaj chcete odstrániť {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sr.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sr.xaml index 5f1803655..06707b4af 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sr.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sr.xaml @@ -17,7 +17,7 @@ Action Keyword URL Search - Use Search Query Autocomplete: + Use Search Query Autocomplete Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml index 1506b753b..aaad035a0 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml @@ -17,7 +17,7 @@ Anahtar Kelime URL Ara: - Arama önerilerini etkinleştir + Use Search Query Autocomplete Autocomplete Data from: Lütfen bir web araması seçin {0} bağlantısını silmek istediğinize emin misiniz? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml index beb085d28..5536a7e68 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml @@ -17,7 +17,7 @@ Ключове слово дії URL Пошук - Використовувати автозаповнення пошукового запиту: + Use Search Query Autocomplete Автозаповнення даних з: Будь ласка, виберіть пошуковий запит в Інтернеті Ви впевнені, що хочете видалити {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/vi.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/vi.xaml index e3105283f..731275c5e 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/vi.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/vi.xaml @@ -17,7 +17,7 @@ Từ khóa hành động Địa chỉ URL Tìm kiếm - Sử dụng Tự động hoàn thành truy vấn tìm kiếm: + Use Search Query Autocomplete Tự động hoàn thành dữ liệu từ: Vui lòng chọn tìm kiếm trên web Bạn có chắc chắn muốn xóa {0} không? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-cn.xaml index d3df223cc..375a741d0 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-cn.xaml @@ -17,7 +17,7 @@ 触发关键字 打开链接 搜索 - 启用搜索建议 + Use Search Query Autocomplete 自动补全数据: 请选择一项 您确定要删除 {0} 吗? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-tw.xaml index eb58a4ec0..727b2f4a9 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-tw.xaml @@ -17,7 +17,7 @@ 觸發關鍵字 網址 搜尋 - 啟用搜尋建議 + Use Search Query Autocomplete 從以下位置自動填入資料: 請選擇一項 你確認要刪除{0}嗎 diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.de-DE.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.de-DE.resx index dcc74d520..5f8d9a6df 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.de-DE.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.de-DE.resx @@ -275,7 +275,7 @@ Hardware und Sound - Startseite + Homepage Mixed Reality @@ -2161,7 +2161,7 @@ Erweiterte Druckereinrichtung - Change default printer + Standard-Drucker ändern Edit environment variables for your account @@ -2416,7 +2416,7 @@ Erweiterte Sharing-Einstellungen verwalten - Change battery settings + Akku-Einstellungen ändern Diesen Computer umbenennen @@ -2479,7 +2479,7 @@ Find and fix bluescreen problems - Hear a tone when keys are pressed + Einen Ton hören, wenn Tasten gedrückt werden Browsing-Historie löschen diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.he-IL.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.he-IL.resx index 55ac42dd3..faa8c2dcc 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.he-IL.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.he-IL.resx @@ -432,7 +432,7 @@ Area Personalization - Client service for NetWare + שירות לקוח עבור NetWare Area Control Panel (legacy settings) diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ko-KR.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ko-KR.resx index c7c1854b7..ab69a2a31 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ko-KR.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ko-KR.resx @@ -1203,7 +1203,7 @@ Area Gaming - Windows 설정을 검색하는 플러그 인 + Windows 설정을 검색하는 플러그인 Windows Settings diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.pt-PT.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.pt-PT.resx index e7f8e1683..39062bbb8 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.pt-PT.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.pt-PT.resx @@ -1797,13 +1797,13 @@ Mostrar ficheiros e pastas ocultas - Change Windows To Go start-up options + Mudar as configurações de início do Windows Portátil - See which processes start up automatically when you start Windows + Veja quais processos se iniciam automaticamente quando o Windows inicia - Tell if an RSS feed is available on a website + Informar se um feed RSS está disponível em um site Adicionar relógios para diferentes fusos horários @@ -1815,7 +1815,7 @@ Personalizar botões do rato - Set tablet buttons to perform certain tasks + Definir botões do tablet para executar certas tarefas Ver tipos de letra instalados @@ -1869,13 +1869,13 @@ Ver digitalizadores e câmaras - Microsoft IME Register Word (Japanese) + Registro do Word Microsoft IME (japonês) Restaurar ficheiros com o Histórico de ficheiros - Turn On-Screen keyboard on or off + Ativar ou desativar o teclado na tela Bloquear ou permitir cookies de terceiros @@ -1887,7 +1887,7 @@ Criar uma unidade de recuperação - Microsoft New Phonetic Settings + Configurações do Microsoft New Phonetic Gerer relatório de saúde do sistema @@ -1899,16 +1899,16 @@ Cópia de segurança e restauro (Windows 7) - Preview, delete, show or hide fonts + Pré-visualizar, excluir, mostrar ou ocultar fontes - Microsoft Quick Settings + Configurações Rápidas da Microsoft Ver histórico de fiabilidade - Access RemoteApp and desktops + Acessar o RemoteApp e desktops Configurar fontes de dados ODBC @@ -1926,7 +1926,7 @@ Opções SimpleFast do Microsoft Pinyin - Change what closing the lid does + Mudar o que fechar a tampa faz Desativar animações desnecessárias @@ -1947,7 +1947,7 @@ Ver ações recomendadas para manter o sistema a funcionar nas melhores condições - Alterar a frequência de piscar do cursor + Alterar frequência de intermitência do cursor Adicionar ou remover programas @@ -1959,13 +1959,13 @@ Configurar propriedades avançadas do perfil de utilizador - Start or stop using AutoPlay for all media and devices + Inicie ou pare de usar o AutoPlay para todas as mídias e dispositivos Alterar definições de manutenção automática - Specify single- or double-click to open + Especificar se um clique ou dois são necessários para abrir Utilizadores que podem utilizar o ambiente de trabalho remoto @@ -1995,13 +1995,13 @@ Analisar estado do teclado - Control the computer without the mouse or keyboard + Controle o computador sem o mouse ou teclado Alterar ou remover um programa - Change multi-touch gesture settings + Alterar configurações de gestos multi-toque Configurar origens ODBC (64 bits) @@ -2013,13 +2013,13 @@ Alterar página inicial - Group similar windows on the taskbar + Agrupar janelas semelhantes na barra de tarefas - Change Windows SideShow settings + Alterar configurações do Windows SideShow - Use audio description for video + Usar descrição de áudio para vídeos Alterar nome do grupo de trabalho @@ -2028,13 +2028,13 @@ Encontrar e corrigir problemas de impressão - Change when the computer sleeps + Mudar quando o computador dorme Configurar uma rede privada (VPN) - Accommodate learning abilities + Acomodar habilidades de aprendizagem Configurar uma ligação telefónica @@ -2046,7 +2046,7 @@ Como alterar a palavra-passe do Windows - Tornar mais fácil ver o ponteiro do rato + Tornar mais fácil de ver o ponteiro do mouse Configurar o iniciador iSCSI @@ -2067,7 +2067,7 @@ Substituir sons por pistas visuais - Change temporary Internet file settings + Alterar configurações de arquivo de Internet temporárias Estabelecer ligação à Internet @@ -2085,16 +2085,16 @@ Guardar cópias de segurança dos ficheiros no Histórico de Ficheiros - View current accessibility settings + Ver configurações de acessibilidade atuais - Change tablet pen settings + Alterar configurações da caneta Alterar modo de funcionamento do rato - Show how much RAM is on this computer + Mostrar quanta memória RAM este computador tem Editar plano de energia @@ -2115,7 +2115,7 @@ Ampliar partes do ecrão com o Magnificador - Change the file type associated with a file extension + Alterar o tipo de arquivo associado a uma extensão de arquivo Ver registo de eventos @@ -2133,17 +2133,17 @@ Alterar definições de poupança de energia - Optimise for blindness + Otimizar para cegueira - Turn Windows features on or off + Ative ou desative os recursos do Windows - Show which operating system your computer is running + Mostra qual sistema operacional o seu computador está executando Ver serviços locais @@ -2152,7 +2152,7 @@ Gerir pastas de trabalho - Encrypt your offline files + Criptografe seus arquivos offline Treinar o computador para reconhecer a sua voz @@ -2173,43 +2173,43 @@ Alterar definições ddo clique do rato - Change advanced colour management settings for displays, scanners and printers + Alterar configurações avançadas de gerenciamento de cores para telas, scanners e impressoras - Let Windows suggest Ease of Access settings + Permitir que o Windows sugira Facilidade de Acesso - Clear disk space by deleting unnecessary files + Limpar espaço em disco excluindo arquivos desnecessários Ver dispositivos e impressoras - Private Character Editor + Editor de Caracteres Privados - Record steps to reproduce a problem + Registrar as etapas para reproduzir um problema - Adjust the appearance and performance of Windows + Ajustar a aparência e o desempenho do Windows - Settings for Microsoft IME (Japanese) + Configurações para o Microsoft IME (japonês) - Invite someone to connect to your PC and help you, or offer to help someone else + Convide alguém para se conectar ao seu PC e ajudá-lo, ou ofereça para ajudar outra pessoa - Run programs made for previous versions of Windows + Execute programas feitos para versões anteriores do Windows - Choose the order of how your screen rotates + Escolha a ordem de como a tela gira - Change how Windows searches + Alterar como o Windows pesquisa - Set flicks to perform certain tasks + Defina gestos para realizar certas ações Alterar tipo de conta @@ -2221,64 +2221,64 @@ Alterar Configurações de Controlo da Conta do Utilizador - Turn on easy access keys + Ativar teclas de acesso fácil - Identify and repair network problems + Identificar e reparar problemas de rede - Find and fix networking and connection problems + Encontrar e corrigir problemas de rede e conexão - Play CDs or other media automatically + Reproduzir CDs ou outras mídias automaticamente - View basic information about your computer + Ver informações básicas sobre seu computador - Choose how you open links + Escolha como abrir os links - Allow Remote Assistance invitations to be sent from this computer + Permitir que convites de assistência remota sejam enviados a partir deste computador Gestor de tarefas - Turn flicks on or off + Ativar ou desativar gestos Adicionar um idioma - View network status and tasks + Ver status de rede e tarefas - Turn Magnifier on or off + Ativar ou desativar a lupa - See the name of this computer + Ver o nome deste computador Ver ligações de rede - Perform recommended maintenance tasks automatically + Executar tarefas recomendadas de manutenção automaticamente - Manage disk space used by your offline files + Gerir espaço de disco utilizado pelos ficheiros locais - Turn High Contrast on or off + Ativar ou desativar modo de alto contraste - Change the way time is displayed + Alterar modo de exibição da hora - Change how web pages are displayed in tabs + Alterar modo de exibição das páginas web nos separadores - Change the way dates and lists are displayed + Alterar modo de exibição das datas e das listas Gerir dispositivos de áudio @@ -2293,37 +2293,37 @@ Apagar cookies ou ficheiros temporários - Specify which hand you write with + Especificar a mão com a qual escreve - Change touch input settings + Alterar definições do painel de toque - How to change the size of virtual memory + Como alterar tamanho da memória virtual - Hear text read aloud with Narrator + Utilizar Narrador para ouvir os textos - Set up USB game controllers + Configurar controladores de jogos USB - Show which domain your computer is on + Mostrar o domínio ao qual o computador pertence - View all problem reports + Ver todos os relatórios de erro - 16-Bit Application Support + Suporte a aplicações 16-bit - Set up dialling rules + Configurar regras de marcação Ativar ou desativar cookies da sessão - Give administrative rights to a domain user + Conceder direitos de administrador a um domínio Choose when to turn off display diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx index f47b9ada3..5b4dea6a9 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx @@ -118,7 +118,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - O aplikácii + O systéme Area System From 24d43ed84bc29edd373ea1a513f4ef740828cce5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:46:02 +0800 Subject: [PATCH 094/125] Use api functions in Program plugin --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index a50868b69..f03040d68 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Controls; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.Program.Programs; using Flow.Launcher.Plugin.Program.Views; @@ -14,7 +13,6 @@ using Flow.Launcher.Plugin.Program.Views.Models; using Flow.Launcher.Plugin.SharedCommands; using Microsoft.Extensions.Caching.Memory; using Path = System.IO.Path; -using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher.Plugin.Program { @@ -32,6 +30,8 @@ namespace Flow.Launcher.Plugin.Program internal static PluginInitContext Context { get; private set; } + private static readonly string ClassName = nameof(Main); + private static readonly List emptyResults = new(); private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; @@ -109,7 +109,7 @@ namespace Flow.Launcher.Plugin.Program } catch (OperationCanceledException) { - Log.Debug("|Flow.Launcher.Plugin.Program.Main|Query operation cancelled"); + Context.API.LogDebug(ClassName, "Query operation cancelled"); return emptyResults; } finally @@ -188,7 +188,7 @@ namespace Flow.Launcher.Plugin.Program var _win32sCount = 0; var _uwpsCount = 0; - await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () => + await Context.API.StopwatchLogInfoAsync(ClassName, "Preload programs cost", async () => { var pluginCacheDirectory = Context.CurrentPluginMetadata.PluginCacheDirectoryPath; FilesFolders.ValidateDirectory(pluginCacheDirectory); @@ -253,8 +253,8 @@ namespace Flow.Launcher.Plugin.Program _uwpsCount = _uwps.Count; _uwpsLock.Release(); }); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32sCount}>"); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwpsCount}>"); + Context.API.LogInfo(ClassName, $"Number of preload win32 programs <{_win32sCount}>"); + Context.API.LogInfo(ClassName, $"Number of preload uwps <{_uwpsCount}>"); var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0; @@ -295,7 +295,7 @@ namespace Flow.Launcher.Plugin.Program } catch (Exception e) { - Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Win32 programs", e); + Context.API.LogException(ClassName, "Failed to index Win32 programs", e); } finally { @@ -320,7 +320,7 @@ namespace Flow.Launcher.Plugin.Program } catch (Exception e) { - Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Uwp programs", e); + Context.API.LogException(ClassName, "Failed to index Uwp programs", e); } finally { @@ -332,12 +332,12 @@ namespace Flow.Launcher.Plugin.Program { var win32Task = Task.Run(async () => { - await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexWin32ProgramsAsync); + await Context.API.StopwatchLogInfoAsync(ClassName, "Win32Program index cost", IndexWin32ProgramsAsync); }); var uwpTask = Task.Run(async () => { - await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|UWPProgram index cost", IndexUwpProgramsAsync); + await Context.API.StopwatchLogInfoAsync(ClassName, "UWPProgram index cost", IndexUwpProgramsAsync); }); await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false); From 1af9d061f741735b015b880c754bfc5ef9226bb7 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:53:00 +0800 Subject: [PATCH 095/125] Use api functions in other places --- Flow.Launcher.Core/Plugin/PluginManager.cs | 6 ++++-- Flow.Launcher.Core/Plugin/PluginsLoader.cs | 10 +++++++--- Flow.Launcher/App.xaml.cs | 7 ++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 0ee268f5c..4c85fb061 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -23,6 +23,8 @@ namespace Flow.Launcher.Core.Plugin /// public static class PluginManager { + private static readonly string ClassName = nameof(PluginManager); + private static IEnumerable _contextMenuPlugins; public static List AllPlugins { get; private set; } @@ -194,7 +196,7 @@ namespace Flow.Launcher.Core.Plugin { try { - var milliseconds = await Stopwatch.DebugAsync($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", + var milliseconds = await API.StopwatchLogDebugAsync(ClassName, $"Init method time cost for <{pair.Metadata.Name}>", () => pair.Plugin.InitAsync(new PluginInitContext(pair.Metadata, API))); pair.Metadata.InitTime += milliseconds; @@ -266,7 +268,7 @@ namespace Flow.Launcher.Core.Plugin try { - var milliseconds = await Stopwatch.DebugAsync($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", + var milliseconds = await API.StopwatchLogDebugAsync(ClassName, $"Cost for {metadata.Name}", async () => results = await pair.Plugin.QueryAsync(query, token).ConfigureAwait(false)); token.ThrowIfCancellationRequested(); diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs index 495a4c1ab..1010d9f08 100644 --- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs @@ -11,12 +11,17 @@ using Flow.Launcher.Infrastructure.Logger; #pragma warning restore IDE0005 using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; -using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher.Core.Plugin { public static class PluginsLoader { + private static readonly string ClassName = nameof(PluginsLoader); + + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + public static List Plugins(List metadatas, PluginsSettings settings) { var dotnetPlugins = DotNetPlugins(metadatas); @@ -59,8 +64,7 @@ namespace Flow.Launcher.Core.Plugin foreach (var metadata in metadatas) { - var milliseconds = Stopwatch.Debug( - $"|PluginsLoader.DotNetPlugins|Constructor init cost for {metadata.Name}", () => + var milliseconds = API.StopwatchLogDebug(ClassName, $"Constructor init cost for {metadata.Name}", () => { Assembly assembly = null; IAsyncPlugin plugin = null; diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 81938612c..90fefe0a6 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -21,7 +21,6 @@ using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher { @@ -35,6 +34,8 @@ namespace Flow.Launcher #region Private Fields + private static readonly string ClassName = nameof(App); + private static bool _disposed; private MainWindow _mainWindow; private readonly MainViewModel _mainVM; @@ -136,7 +137,7 @@ namespace Flow.Launcher private async void OnStartup(object sender, StartupEventArgs e) { - await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () => + await API.StopwatchLogInfoAsync(ClassName, "Startup cost", async () => { // Because new message box api uses MessageBoxEx window, // if it is created and closed before main window is created, it will cause the application to exit. @@ -313,7 +314,7 @@ namespace Flow.Launcher _disposed = true; } - Stopwatch.Normal("|App.Dispose|Dispose cost", () => + API.StopwatchLogInfo(ClassName, "Dispose cost", () => { Log.Info("|App.Dispose|Begin Flow Launcher dispose ----------------------------------------------------"); From 47743e6362469684e432b790649b419b96d0d543 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 09:31:02 +0800 Subject: [PATCH 096/125] Set max result lower limit to 1 --- .../ViewModels/SettingsViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index d2b85e687..407300924 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -524,7 +524,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels } } - public int MaxResultLowerLimit => 100; + public int MaxResultLowerLimit => 1; public int MaxResultUpperLimit => 100000; public int MaxResult From 49dc657becdac6f23f66c3ee4060165ff5b9838e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:12:32 +0800 Subject: [PATCH 097/125] Fix build issue --- Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index 5dec8b953..3eb74dd74 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Controls; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.BrowserBookmark.Commands; using Flow.Launcher.Plugin.BrowserBookmark.Models; using Flow.Launcher.Plugin.BrowserBookmark.Views; @@ -10,6 +9,7 @@ using System.IO; using System.Threading.Channels; using System.Threading.Tasks; using System.Threading; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Plugin.BrowserBookmark; @@ -35,7 +35,7 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex _context.CurrentPluginMetadata.PluginCacheDirectoryPath, "FaviconCache"); - Helper.ValidateDirectory(_faviconCacheDir); + FilesFolders.ValidateDirectory(_faviconCacheDir); LoadBookmarksIfEnabled(); } From 9c07989edf4f42766922317b639e710ec33d6e35 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:14:07 +0800 Subject: [PATCH 098/125] Improve code quality --- .../ChromiumBookmarkLoader.cs | 4 +- .../ContextMenu.cs | 21 +++----- .../DirectoryInfo/DirectoryInfoSearch.cs | 7 ++- .../Search/WindowsIndex/WindowsIndex.cs | 8 +-- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 13 ++--- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 49 ++++++++++--------- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 7 +-- 7 files changed, 51 insertions(+), 58 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 282876472..27bcbd9a9 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -2,7 +2,6 @@ using System.IO; using System.Text.Json; using System; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.BrowserBookmark.Models; using Microsoft.Data.Sqlite; @@ -116,8 +115,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } else { - Log.Error( - $"ChromiumBookmarkLoader: EnumerateFolderBookmark: type property not found for {subElement.GetString()}"); + Main._context.API.LogError(ClassName, $"type property not found for {subElement.GetString()}"); } } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs index 3f3b7cb58..f6de65e90 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs @@ -2,13 +2,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using System.Threading.Tasks; using System.Windows; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Plugin.Explorer.Search; using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; -using System.Linq; using Flow.Launcher.Plugin.Explorer.Helper; using Flow.Launcher.Plugin.Explorer.ViewModels; @@ -470,22 +469,16 @@ namespace Flow.Launcher.Plugin.Explorer private void LogException(string message, Exception e) { - Log.Exception($"|Flow.Launcher.Plugin.Folder.ContextMenu|{message}", e); + Context.API.LogException(nameof(Main), message, e); } - private bool CanRunAsDifferentUser(string path) + private static bool CanRunAsDifferentUser(string path) { - switch (Path.GetExtension(path)) + return Path.GetExtension(path) switch { - case ".exe": - case ".bat": - case ".msi": - return true; - - default: - return false; - - } + ".exe" or ".bat" or ".msi" => true, + _ => false, + }; } } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs index 9fd495f49..1a0d3bd15 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs @@ -1,10 +1,9 @@ -using Flow.Launcher.Infrastructure.Logger; -using Flow.Launcher.Plugin.SharedCommands; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo { @@ -76,7 +75,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo } catch (Exception e) { - Log.Exception(nameof(DirectoryInfoSearch), "Error occurred while searching path", e); + Main.Context.API.LogException(nameof(DirectoryInfoSearch), "Error occurred while searching path", e); throw; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs index 66230937c..2aeb421e0 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs @@ -1,6 +1,4 @@ -using Flow.Launcher.Infrastructure.Logger; -using Microsoft.Search.Interop; -using System; +using System; using System.Collections.Generic; using System.Data.OleDb; using System.Linq; @@ -9,11 +7,13 @@ using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Threading; using Flow.Launcher.Plugin.Explorer.Exceptions; +using Microsoft.Search.Interop; namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex { internal static class WindowsIndex { + private static readonly string ClassName = nameof(WindowsIndex); // Reserved keywords in oleDB private static Regex _reservedPatternMatcher = new(@"^[`\@\@\#\#\*\^,\&\&\/\\\$\%_;\[\]]+$", RegexOptions.Compiled); @@ -33,7 +33,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex } catch (OleDbException e) { - Log.Exception($"|WindowsIndex.ExecuteWindowsIndexSearchAsync|Failed to execute windows index search query: {indexQueryString}", e); + Main.Context.API.LogException(ClassName, $"Failed to execute windows index search query: {indexQueryString}", e); yield break; } await using var dataReader = dataReaderAttempt; diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index a50868b69..acfa0655e 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Controls; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.Program.Programs; using Flow.Launcher.Plugin.Program.Views; @@ -20,6 +19,8 @@ namespace Flow.Launcher.Plugin.Program { public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, IAsyncReloadable, IDisposable { + private static readonly string ClassName = nameof(Main); + private const string Win32CacheName = "Win32"; private const string UwpCacheName = "UWP"; @@ -109,7 +110,7 @@ namespace Flow.Launcher.Plugin.Program } catch (OperationCanceledException) { - Log.Debug("|Flow.Launcher.Plugin.Program.Main|Query operation cancelled"); + Context.API.LogDebug(ClassName, "Query operation cancelled"); return emptyResults; } finally @@ -253,8 +254,8 @@ namespace Flow.Launcher.Plugin.Program _uwpsCount = _uwps.Count; _uwpsLock.Release(); }); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32sCount}>"); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwpsCount}>"); + Context.API.LogInfo(ClassName, "Number of preload win32 programs <{_win32sCount}>"); + Context.API.LogInfo(ClassName, "Number of preload uwps <{_uwpsCount}>"); var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0; @@ -295,7 +296,7 @@ namespace Flow.Launcher.Plugin.Program } catch (Exception e) { - Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Win32 programs", e); + Context.API.LogException(ClassName, "Failed to index Win32 programs", e); } finally { @@ -320,7 +321,7 @@ namespace Flow.Launcher.Plugin.Program } catch (Exception e) { - Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Uwp programs", e); + Context.API.LogException(ClassName, "Failed to index Uwp programs", e); } finally { diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 53479b81f..97ff61304 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -8,7 +8,6 @@ using System.Threading.Tasks; using WindowsInput; using WindowsInput.Native; using Flow.Launcher.Infrastructure.Hotkey; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.SharedCommands; using Control = System.Windows.Controls.Control; using Keys = System.Windows.Forms.Keys; @@ -17,8 +16,11 @@ namespace Flow.Launcher.Plugin.Shell { public class Main : IPlugin, ISettingProvider, IPluginI18n, IContextMenu { + private static readonly string ClassName = nameof(Main); + + internal PluginInitContext Context { get; private set; } + private const string Image = "Images/shell.png"; - private PluginInitContext context; private bool _winRStroked; private readonly KeyboardSimulator _keyboardSimulator = new KeyboardSimulator(new InputSimulator()); @@ -88,7 +90,7 @@ namespace Flow.Launcher.Plugin.Shell } catch (Exception e) { - Log.Exception($"|Flow.Launcher.Plugin.Shell.Main.Query|Exception when query for <{query}>", e); + Context.API.LogException(ClassName, $"Exception when query for <{query}>", e); } return results; } @@ -102,14 +104,14 @@ namespace Flow.Launcher.Plugin.Shell { if (m.Key == cmd) { - result.SubTitle = string.Format(context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value); + result.SubTitle = string.Format(Context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value); return null; } var ret = new Result { Title = m.Key, - SubTitle = string.Format(context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value), + SubTitle = string.Format(Context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value), IcoPath = Image, Action = c => { @@ -139,7 +141,7 @@ namespace Flow.Launcher.Plugin.Shell { Title = cmd, Score = 5000, - SubTitle = context.API.GetTranslation("flowlauncher_plugin_cmd_execute_through_shell"), + SubTitle = Context.API.GetTranslation("flowlauncher_plugin_cmd_execute_through_shell"), IcoPath = Image, Action = c => { @@ -164,7 +166,7 @@ namespace Flow.Launcher.Plugin.Shell .Select(m => new Result { Title = m.Key, - SubTitle = string.Format(context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value), + SubTitle = string.Format(Context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value), IcoPath = Image, Action = c => { @@ -211,7 +213,7 @@ namespace Flow.Launcher.Plugin.Shell info.FileName = "cmd.exe"; } - info.ArgumentList.Add($"{(_settings.LeaveShellOpen ? "/k" : "/c")} {command} {(_settings.CloseShellAfterPress ? $"&& echo {context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")} && pause > nul /c" : "")}"); + info.ArgumentList.Add($"{(_settings.LeaveShellOpen ? "/k" : "/c")} {command} {(_settings.CloseShellAfterPress ? $"&& echo {Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")} && pause > nul /c" : "")}"); break; } @@ -234,7 +236,7 @@ namespace Flow.Launcher.Plugin.Shell else { info.ArgumentList.Add("-Command"); - info.ArgumentList.Add($"{command}\\; {(_settings.CloseShellAfterPress ? $"Write-Host '{context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); + info.ArgumentList.Add($"{command}\\; {(_settings.CloseShellAfterPress ? $"Write-Host '{Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); } break; } @@ -255,7 +257,7 @@ namespace Flow.Launcher.Plugin.Shell info.ArgumentList.Add("-NoExit"); } info.ArgumentList.Add("-Command"); - info.ArgumentList.Add($"{command}\\; {(_settings.CloseShellAfterPress ? $"Write-Host '{context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); + info.ArgumentList.Add($"{command}\\; {(_settings.CloseShellAfterPress ? $"Write-Host '{Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); break; } @@ -309,13 +311,13 @@ namespace Flow.Launcher.Plugin.Shell { var name = "Plugin: Shell"; var message = $"Command not found: {e.Message}"; - context.API.ShowMsg(name, message); + Context.API.ShowMsg(name, message); } catch (Win32Exception e) { var name = "Plugin: Shell"; var message = $"Error running the command: {e.Message}"; - context.API.ShowMsg(name, message); + Context.API.ShowMsg(name, message); } } @@ -350,14 +352,14 @@ namespace Flow.Launcher.Plugin.Shell public void Init(PluginInitContext context) { - this.context = context; + Context = context; _settings = context.API.LoadSettingJsonStorage(); context.API.RegisterGlobalKeyboardCallback(API_GlobalKeyboardEvent); } bool API_GlobalKeyboardEvent(int keyevent, int vkcode, SpecialKeyState state) { - if (!context.CurrentPluginMetadata.Disabled && _settings.ReplaceWinR) + if (!Context.CurrentPluginMetadata.Disabled && _settings.ReplaceWinR) { if (keyevent == (int)KeyEvent.WM_KEYDOWN && vkcode == (int)Keys.R && state.WinPressed) { @@ -380,10 +382,9 @@ namespace Flow.Launcher.Plugin.Shell // show the main window and set focus to the query box _ = Task.Run(() => { - context.API.ShowMainWindow(); - context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}"); + Context.API.ShowMainWindow(); + Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}"); }); - } public Control CreateSettingPanel() @@ -393,12 +394,12 @@ namespace Flow.Launcher.Plugin.Shell public string GetTranslatedPluginTitle() { - return context.API.GetTranslation("flowlauncher_plugin_cmd_plugin_name"); + return Context.API.GetTranslation("flowlauncher_plugin_cmd_plugin_name"); } public string GetTranslatedPluginDescription() { - return context.API.GetTranslation("flowlauncher_plugin_cmd_plugin_description"); + return Context.API.GetTranslation("flowlauncher_plugin_cmd_plugin_description"); } public List LoadContextMenus(Result selectedResult) @@ -407,8 +408,8 @@ namespace Flow.Launcher.Plugin.Shell { new() { - Title = context.API.GetTranslation("flowlauncher_plugin_cmd_run_as_different_user"), - AsyncAction = async c => + Title = Context.API.GetTranslation("flowlauncher_plugin_cmd_run_as_different_user"), + Action = c => { Execute(ShellCommand.RunAsDifferentUser, PrepareProcessStartInfo(selectedResult.Title)); return true; @@ -418,7 +419,7 @@ namespace Flow.Launcher.Plugin.Shell }, new() { - Title = context.API.GetTranslation("flowlauncher_plugin_cmd_run_as_administrator"), + Title = Context.API.GetTranslation("flowlauncher_plugin_cmd_run_as_administrator"), Action = c => { Execute(Process.Start, PrepareProcessStartInfo(selectedResult.Title, true)); @@ -429,10 +430,10 @@ namespace Flow.Launcher.Plugin.Shell }, new() { - Title = context.API.GetTranslation("flowlauncher_plugin_cmd_copy"), + Title = Context.API.GetTranslation("flowlauncher_plugin_cmd_copy"), Action = c => { - context.API.CopyToClipboard(selectedResult.Title); + Context.API.CopyToClipboard(selectedResult.Title); return true; }, IcoPath = "Images/copy.png", diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 94a9d0348..043eb7a19 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Runtime.InteropServices; using System.Windows; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Windows.Win32; using Windows.Win32.Foundation; @@ -19,6 +18,8 @@ namespace Flow.Launcher.Plugin.Sys { public class Main : IPlugin, ISettingProvider, IPluginI18n { + private static readonly string ClassName = nameof(Main); + private readonly Dictionary KeywordTitleMappings = new() { {"Shutdown", "flowlauncher_plugin_sys_shutdown_computer_cmd"}, @@ -106,7 +107,7 @@ namespace Flow.Launcher.Plugin.Sys { if (!KeywordTitleMappings.TryGetValue(key, out var translationKey)) { - Log.Error("Flow.Launcher.Plugin.Sys.Main", $"Title not found for: {key}"); + _context.API.LogError(ClassName, $"Title not found for: {key}"); return "Title Not Found"; } @@ -117,7 +118,7 @@ namespace Flow.Launcher.Plugin.Sys { if (!KeywordDescriptionMappings.TryGetValue(key, out var translationKey)) { - Log.Error("Flow.Launcher.Plugin.Sys.Main", $"Description not found for: {key}"); + _context.API.LogError(ClassName, $"Description not found for: {key}"); return "Description Not Found"; } From 4e1d4ab7afcddeaa39f0b1aeca0639e401a5e933 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:18:44 +0800 Subject: [PATCH 099/125] Remove unused project reference --- .../Flow.Launcher.Plugin.WebSearch.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj index c2d0a46a0..73726ab37 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj @@ -51,7 +51,6 @@ - From 1aeaaf2fc24d32d67d994f84b2e84b555fb8c367 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:30:50 +0800 Subject: [PATCH 100/125] Add keyevent in Plugin project & Improve Shell plugin code quality --- Flow.Launcher.Infrastructure/NativeMethods.txt | 5 ----- .../Hotkey => Flow.Launcher.Plugin}/KeyEvent.cs | 7 ++++++- Flow.Launcher.Plugin/NativeMethods.txt | 7 ++++++- .../Flow.Launcher.Plugin.Shell.csproj | 1 - Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 7 +++---- 5 files changed, 15 insertions(+), 12 deletions(-) rename {Flow.Launcher.Infrastructure/Hotkey => Flow.Launcher.Plugin}/KeyEvent.cs (61%) diff --git a/Flow.Launcher.Infrastructure/NativeMethods.txt b/Flow.Launcher.Infrastructure/NativeMethods.txt index 363ecb9d0..18b206022 100644 --- a/Flow.Launcher.Infrastructure/NativeMethods.txt +++ b/Flow.Launcher.Infrastructure/NativeMethods.txt @@ -11,11 +11,6 @@ GetModuleHandle GetKeyState VIRTUAL_KEY -WM_KEYDOWN -WM_KEYUP -WM_SYSKEYDOWN -WM_SYSKEYUP - EnumWindows DwmSetWindowAttribute diff --git a/Flow.Launcher.Infrastructure/Hotkey/KeyEvent.cs b/Flow.Launcher.Plugin/KeyEvent.cs similarity index 61% rename from Flow.Launcher.Infrastructure/Hotkey/KeyEvent.cs rename to Flow.Launcher.Plugin/KeyEvent.cs index 95bb25837..321f17cc1 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/KeyEvent.cs +++ b/Flow.Launcher.Plugin/KeyEvent.cs @@ -1,7 +1,12 @@ using Windows.Win32; -namespace Flow.Launcher.Infrastructure.Hotkey +namespace Flow.Launcher.Plugin { + /// + /// Enumeration of key events for + /// + /// and + /// public enum KeyEvent { /// diff --git a/Flow.Launcher.Plugin/NativeMethods.txt b/Flow.Launcher.Plugin/NativeMethods.txt index e3e2b705e..0596691cc 100644 --- a/Flow.Launcher.Plugin/NativeMethods.txt +++ b/Flow.Launcher.Plugin/NativeMethods.txt @@ -1,3 +1,8 @@ EnumThreadWindows GetWindowText -GetWindowTextLength \ No newline at end of file +GetWindowTextLength + +WM_KEYDOWN +WM_KEYUP +WM_SYSKEYDOWN +WM_SYSKEYUP \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj index 8f443214b..c7ea7cdd5 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj +++ b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj @@ -37,7 +37,6 @@ - diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 97ff61304..b149884d7 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Threading.Tasks; using WindowsInput; using WindowsInput.Native; -using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Plugin.SharedCommands; using Control = System.Windows.Controls.Control; using Keys = System.Windows.Forms.Keys; @@ -22,7 +21,7 @@ namespace Flow.Launcher.Plugin.Shell private const string Image = "Images/shell.png"; private bool _winRStroked; - private readonly KeyboardSimulator _keyboardSimulator = new KeyboardSimulator(new InputSimulator()); + private readonly KeyboardSimulator _keyboardSimulator = new(new InputSimulator()); private Settings _settings; @@ -55,7 +54,7 @@ namespace Flow.Launcher.Plugin.Shell { basedir = Path.GetDirectoryName(excmd); var dirName = Path.GetDirectoryName(cmd); - dir = (dirName.EndsWith("/") || dirName.EndsWith(@"\")) ? dirName : cmd.Substring(0, dirName.Length + 1); + dir = (dirName.EndsWith("/") || dirName.EndsWith(@"\")) ? dirName : cmd[..(dirName.Length + 1)]; } if (basedir != null) @@ -321,7 +320,7 @@ namespace Flow.Launcher.Plugin.Shell } } - private bool ExistInPath(string filename) + private static bool ExistInPath(string filename) { if (File.Exists(filename)) { From c035b65517befa0b3df89560f51a6447781b1937 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:31:53 +0800 Subject: [PATCH 101/125] Fix code documents issue --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 273676bfb..ff0f1ba4a 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -372,6 +372,7 @@ namespace Flow.Launcher.Plugin /// public bool SetCurrentTheme(ThemeData theme); + /// /// Save all Flow's plugins caches /// void SavePluginCaches(); @@ -404,6 +405,7 @@ namespace Flow.Launcher.Plugin /// Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new(); + /// /// Load image from path. Support local, remote and data:image url. /// If image path is missing, it will return a missing icon. /// @@ -418,6 +420,7 @@ namespace Flow.Launcher.Plugin /// ValueTask LoadImageAsync(string path, bool loadFullImage = false, bool cacheImage = true); + /// /// Update the plugin manifest /// /// From e07beb22613a7d7c1d4cf7670d52d99546137e89 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:33:22 +0800 Subject: [PATCH 102/125] Add dispose --- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index b149884d7..0d395c053 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -13,7 +13,7 @@ using Keys = System.Windows.Forms.Keys; namespace Flow.Launcher.Plugin.Shell { - public class Main : IPlugin, ISettingProvider, IPluginI18n, IContextMenu + public class Main : IPlugin, ISettingProvider, IPluginI18n, IContextMenu, IDisposable { private static readonly string ClassName = nameof(Main); @@ -442,5 +442,10 @@ namespace Flow.Launcher.Plugin.Shell return results; } + + public void Dispose() + { + Context.API.RemoveGlobalKeyboardCallback(API_GlobalKeyboardEvent); + } } } From 46712f287ffdd188687850875acf884ad54b4a9e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:37:42 +0800 Subject: [PATCH 103/125] Improve api documents --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index ff0f1ba4a..6f17f57f5 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -142,15 +142,47 @@ namespace Flow.Launcher.Plugin List GetAllPlugins(); /// - /// Register a callback for Global Keyboard Event + /// Registers a callback function for global keyboard events. /// - /// + /// + /// The callback function to invoke when a global keyboard event occurs. + /// + /// Parameters: + /// + /// int: The type of (key down, key up, etc.) + /// int: The virtual key code of the pressed/released key + /// : The state of modifier keys (Ctrl, Alt, Shift, etc.) + /// + /// + /// + /// Returns: true to allow normal system processing of the key event, + /// or false to intercept and prevent default handling. + /// + /// + /// + /// This callback will be invoked for all keyboard events system-wide. + /// Use with caution as intercepting system keys may affect normal system operation. + /// public void RegisterGlobalKeyboardCallback(Func callback); - + /// /// Remove a callback for Global Keyboard Event /// - /// + /// + /// The callback function to invoke when a global keyboard event occurs. + /// + /// Parameters: + /// + /// int: The type of (key down, key up, etc.) + /// int: The virtual key code of the pressed/released key + /// : The state of modifier keys (Ctrl, Alt, Shift, etc.) + /// + /// + /// + /// Returns: true to allow normal system processing of the key event, + /// or false to intercept and prevent default handling. + /// + /// public void RemoveGlobalKeyboardCallback(Func callback); /// From f71e7461c6cf83cababdd18d6c4f8f766aa20aa5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:38:52 +0800 Subject: [PATCH 104/125] Remove unused project reference --- Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj index 266c24170..dbc36ad42 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj +++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj @@ -39,7 +39,6 @@ - From 826bc42536432f8b5afe07bee6f34a7db7b7c7f2 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:44:26 +0800 Subject: [PATCH 105/125] Improve code quality --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 2 +- .../Programs/UWPPackage.cs | 19 +++++----- .../Programs/Win32.cs | 37 +++++++++---------- 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index acfa0655e..99fa44257 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -275,7 +275,7 @@ namespace Flow.Launcher.Plugin.Program static void WatchProgramUpdate() { Win32.WatchProgramUpdate(_settings); - _ = UWPPackage.WatchPackageChange(); + _ = UWPPackage.WatchPackageChangeAsync(); } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs index bf100ed7e..cb33250e1 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs @@ -8,7 +8,6 @@ using System.Threading.Tasks; using System.Windows.Media.Imaging; using Windows.ApplicationModel; using Windows.Management.Deployment; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.Program.Logger; using Flow.Launcher.Plugin.SharedModels; using System.Threading.Channels; @@ -290,9 +289,9 @@ namespace Flow.Launcher.Plugin.Program.Programs } } - private static Channel PackageChangeChannel = Channel.CreateBounded(1); + private static readonly Channel PackageChangeChannel = Channel.CreateBounded(1); - public static async Task WatchPackageChange() + public static async Task WatchPackageChangeAsync() { if (Environment.OSVersion.Version.Major >= 10) { @@ -403,13 +402,13 @@ namespace Flow.Launcher.Plugin.Program.Programs if (!Main._settings.EnableDescription || string.IsNullOrWhiteSpace(Description) || Name.Equals(Description)) { title = Name; - matchResult = StringMatcher.FuzzySearch(query, Name); + matchResult = Main.Context.API.FuzzySearch(query, Name); } else { title = $"{Name}: {Description}"; - var nameMatch = StringMatcher.FuzzySearch(query, Name); - var descriptionMatch = StringMatcher.FuzzySearch(query, Description); + var nameMatch = Main.Context.API.FuzzySearch(query, Name); + var descriptionMatch = Main.Context.API.FuzzySearch(query, Description); if (descriptionMatch.Score > nameMatch.Score) { for (int i = 0; i < descriptionMatch.MatchData.Count; i++) @@ -477,7 +476,7 @@ namespace Flow.Launcher.Plugin.Program.Programs { var contextMenus = new List { - new Result + new() { Title = api.GetTranslation("flowlauncher_plugin_program_open_containing_folder"), Action = _ => @@ -496,9 +495,9 @@ namespace Flow.Launcher.Plugin.Program.Programs contextMenus.Add(new Result { Title = api.GetTranslation("flowlauncher_plugin_program_run_as_administrator"), - Action = _ => + Action = c => { - Task.Run(() => Launch(true)).ConfigureAwait(false); + _ = Task.Run(() => Launch(true)).ConfigureAwait(false); return true; }, IcoPath = "Images/cmd.png", @@ -539,7 +538,7 @@ namespace Flow.Launcher.Plugin.Program.Programs { ProgramLogger.LogException($"|UWP|LogoPathFromUri|{Location}" + $"|{UserModelId} 's logo uri is null or empty: {Location}", - new ArgumentException("uri")); + new ArgumentException(null, nameof(uri))); return string.Empty; } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 06be2a628..a87b002d4 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -6,7 +6,6 @@ using System.Security; using System.Text; using System.Threading.Tasks; using Microsoft.Win32; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.Program.Logger; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Plugin.SharedModels; @@ -73,7 +72,7 @@ namespace Flow.Launcher.Plugin.Program.Programs private const string ExeExtension = "exe"; private string _uid = string.Empty; - private static readonly Win32 Default = new Win32() + private static readonly Win32 Default = new() { Name = string.Empty, Description = string.Empty, @@ -92,7 +91,7 @@ namespace Flow.Launcher.Plugin.Program.Programs if (candidates.Count == 0) return null; - var match = candidates.Select(candidate => StringMatcher.FuzzySearch(query, candidate)) + var match = candidates.Select(candidate => Main.Context.API.FuzzySearch(query, candidate)) .MaxBy(match => match.Score); return match?.IsSearchPrecisionScoreMet() ?? false ? match : null; @@ -112,14 +111,14 @@ namespace Flow.Launcher.Plugin.Program.Programs resultName.Equals(Description)) { title = resultName; - matchResult = StringMatcher.FuzzySearch(query, resultName); + matchResult = Main.Context.API.FuzzySearch(query, resultName); } else { // Search in both title = $"{resultName}: {Description}"; - var nameMatch = StringMatcher.FuzzySearch(query, resultName); - var descriptionMatch = StringMatcher.FuzzySearch(query, Description); + var nameMatch = Main.Context.API.FuzzySearch(query, resultName); + var descriptionMatch = Main.Context.API.FuzzySearch(query, Description); if (descriptionMatch.Score > nameMatch.Score) { for (int i = 0; i < descriptionMatch.MatchData.Count; i++) @@ -219,27 +218,27 @@ namespace Flow.Launcher.Plugin.Program.Programs { var contextMenus = new List { - new Result + new() { Title = api.GetTranslation("flowlauncher_plugin_program_run_as_different_user"), - Action = _ => + Action = c => { var info = new ProcessStartInfo { FileName = FullPath, WorkingDirectory = ParentDirectory, UseShellExecute = true }; - Task.Run(() => Main.StartProcess(ShellCommand.RunAsDifferentUser, info)); + _ = Task.Run(() => Main.StartProcess(ShellCommand.RunAsDifferentUser, info)); return true; }, IcoPath = "Images/user.png", Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\xe7ee"), }, - new Result + new() { Title = api.GetTranslation("flowlauncher_plugin_program_run_as_administrator"), - Action = _ => + Action = c => { var info = new ProcessStartInfo { @@ -249,14 +248,14 @@ namespace Flow.Launcher.Plugin.Program.Programs UseShellExecute = true }; - Task.Run(() => Main.StartProcess(Process.Start, info)); + _ = Task.Run(() => Main.StartProcess(Process.Start, info)); return true; }, IcoPath = "Images/cmd.png", Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\xe7ef"), }, - new Result + new() { Title = api.GetTranslation("flowlauncher_plugin_program_open_containing_folder"), Action = _ => @@ -296,7 +295,7 @@ namespace Flow.Launcher.Plugin.Program.Programs return Name; } - private static List Watchers = new List(); + private static readonly List Watchers = new(); private static Win32 Win32Program(string path) { @@ -402,7 +401,7 @@ namespace Flow.Launcher.Plugin.Program.Programs var data = parser.ReadFile(path); var urlSection = data["InternetShortcut"]; var url = urlSection?["URL"]; - if (String.IsNullOrEmpty(url)) + if (string.IsNullOrEmpty(url)) { return program; } @@ -418,12 +417,12 @@ namespace Flow.Launcher.Plugin.Program.Programs } var iconPath = urlSection?["IconFile"]; - if (!String.IsNullOrEmpty(iconPath)) + if (!string.IsNullOrEmpty(iconPath)) { program.IcoPath = iconPath; } } - catch (Exception e) + catch (Exception) { // Many files do not have the required fields, so no logging is done. } @@ -474,7 +473,7 @@ namespace Flow.Launcher.Plugin.Program.Programs var extension = Path.GetExtension(path)?.ToLowerInvariant(); if (!string.IsNullOrEmpty(extension)) { - return extension.Substring(1); // remove dot + return extension[1..]; // remove dot } else { @@ -785,7 +784,7 @@ namespace Flow.Launcher.Plugin.Program.Programs _ = Task.Run(MonitorDirectoryChangeAsync); } - private static Channel indexQueue = Channel.CreateBounded(1); + private static readonly Channel indexQueue = Channel.CreateBounded(1); public static async Task MonitorDirectoryChangeAsync() { From d4c9626cbf5f62fda084db5f6949b636b8da9265 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:54:20 +0800 Subject: [PATCH 106/125] Improve code quality & Remove unused project reference --- ...low.Launcher.Plugin.PluginIndicator.csproj | 2 - .../Main.cs | 41 ++++++++++++++----- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj index 21d964c11..1e662de9e 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj @@ -41,8 +41,6 @@ - - diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs index aea0d77a1..05e8d960f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs @@ -1,20 +1,20 @@ using System.Collections.Generic; using System.Linq; -using Flow.Launcher.Core.Plugin; namespace Flow.Launcher.Plugin.PluginIndicator { public class Main : IPlugin, IPluginI18n { - private PluginInitContext context; + internal PluginInitContext Context { get; private set; } public List Query(Query query) { + var nonGlobalPlugins = GetNonGlobalPlugins(); var results = - from keyword in PluginManager.NonGlobalPlugins.Keys - let plugin = PluginManager.NonGlobalPlugins[keyword].Metadata - let keywordSearchResult = context.API.FuzzySearch(query.Search, keyword) - let searchResult = keywordSearchResult.IsSearchPrecisionScoreMet() ? keywordSearchResult : context.API.FuzzySearch(query.Search, plugin.Name) + from keyword in nonGlobalPlugins.Keys + let plugin = nonGlobalPlugins[keyword].Metadata + let keywordSearchResult = Context.API.FuzzySearch(query.Search, keyword) + let searchResult = keywordSearchResult.IsSearchPrecisionScoreMet() ? keywordSearchResult : Context.API.FuzzySearch(query.Search, plugin.Name) let score = searchResult.Score where (searchResult.IsSearchPrecisionScoreMet() || string.IsNullOrEmpty(query.Search)) // To list all available action keywords @@ -22,32 +22,51 @@ namespace Flow.Launcher.Plugin.PluginIndicator select new Result { Title = keyword, - SubTitle = string.Format(context.API.GetTranslation("flowlauncher_plugin_pluginindicator_result_subtitle"), plugin.Name), + SubTitle = string.Format(Context.API.GetTranslation("flowlauncher_plugin_pluginindicator_result_subtitle"), plugin.Name), Score = score, IcoPath = plugin.IcoPath, AutoCompleteText = $"{keyword}{Plugin.Query.TermSeparator}", Action = c => { - context.API.ChangeQuery($"{keyword}{Plugin.Query.TermSeparator}"); + Context.API.ChangeQuery($"{keyword}{Plugin.Query.TermSeparator}"); return false; } }; return results.ToList(); } + private Dictionary GetNonGlobalPlugins() + { + var nonGlobalPlugins = new Dictionary(); + foreach (var plugin in Context.API.GetAllPlugins()) + { + foreach (var actionKeyword in plugin.Metadata.ActionKeywords) + { + // Skip global keywords + if (actionKeyword == Plugin.Query.GlobalPluginWildcardSign) continue; + + // Skip dulpicated keywords + if (nonGlobalPlugins.ContainsKey(actionKeyword)) continue; + + nonGlobalPlugins.Add(actionKeyword, plugin); + } + } + return nonGlobalPlugins; + } + public void Init(PluginInitContext context) { - this.context = context; + Context = context; } public string GetTranslatedPluginTitle() { - return context.API.GetTranslation("flowlauncher_plugin_pluginindicator_plugin_name"); + return Context.API.GetTranslation("flowlauncher_plugin_pluginindicator_plugin_name"); } public string GetTranslatedPluginDescription() { - return context.API.GetTranslation("flowlauncher_plugin_pluginindicator_plugin_description"); + return Context.API.GetTranslation("flowlauncher_plugin_pluginindicator_plugin_description"); } } } From 17cf74e313cba0f5a0de4b6b3cc5e51bc1f22fc2 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:57:28 +0800 Subject: [PATCH 107/125] Add obsolete warning --- Flow.Launcher.Infrastructure/UI/EnumBindingSource.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher.Infrastructure/UI/EnumBindingSource.cs b/Flow.Launcher.Infrastructure/UI/EnumBindingSource.cs index 350c892cf..f9504e6d9 100644 --- a/Flow.Launcher.Infrastructure/UI/EnumBindingSource.cs +++ b/Flow.Launcher.Infrastructure/UI/EnumBindingSource.cs @@ -3,6 +3,7 @@ using System.Windows.Markup; namespace Flow.Launcher.Infrastructure.UI { + [Obsolete("EnumBindingSourceExtension is obsolete. Use with Flow.Launcher.Localization NuGet package instead.")] public class EnumBindingSourceExtension : MarkupExtension { private Type _enumType; From c41d02127206047641b5e258366dfb1f4d2ee4ab Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:01:29 +0800 Subject: [PATCH 108/125] Add obsolete warning --- Flow.Launcher.Core/Resource/LocalizationConverter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher.Core/Resource/LocalizationConverter.cs b/Flow.Launcher.Core/Resource/LocalizationConverter.cs index 81600e023..fdda33926 100644 --- a/Flow.Launcher.Core/Resource/LocalizationConverter.cs +++ b/Flow.Launcher.Core/Resource/LocalizationConverter.cs @@ -6,6 +6,7 @@ using System.Windows.Data; namespace Flow.Launcher.Core.Resource { + [Obsolete("LocalizationConverter is obsolete. Use with Flow.Launcher.Localization NuGet package instead.")] public class LocalizationConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) From da8a69038a3a9091c67340f5d98bea229f78844b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:05:43 +0800 Subject: [PATCH 109/125] Improve code quality --- .../Resource/LocalizedDescriptionAttribute.cs | 10 ++++++--- .../Resource/TranslationConverter.cs | 14 ++++++++---- .../SettingsPanePluginStoreViewModel.cs | 4 ++-- .../SettingsPanePluginsViewModel.cs | 4 ++-- .../Search/ResultManager.cs | 22 +++++++++---------- 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs b/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs index 52a232334..3e1a19a76 100644 --- a/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs +++ b/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs @@ -1,15 +1,19 @@ using System.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Resource { public class LocalizedDescriptionAttribute : DescriptionAttribute { - private readonly Internationalization _translator; + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + private readonly string _resourceKey; public LocalizedDescriptionAttribute(string resourceKey) { - _translator = InternationalizationManager.Instance; _resourceKey = resourceKey; } @@ -17,7 +21,7 @@ namespace Flow.Launcher.Core.Resource { get { - string description = _translator.GetTranslation(_resourceKey); + string description = API.GetTranslation(_resourceKey); return string.IsNullOrWhiteSpace(description) ? string.Format("[[{0}]]", _resourceKey) : description; } diff --git a/Flow.Launcher.Core/Resource/TranslationConverter.cs b/Flow.Launcher.Core/Resource/TranslationConverter.cs index ebab99e5b..eb0032758 100644 --- a/Flow.Launcher.Core/Resource/TranslationConverter.cs +++ b/Flow.Launcher.Core/Resource/TranslationConverter.cs @@ -1,19 +1,25 @@ using System; using System.Globalization; using System.Windows.Data; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Resource { public class TranslationConverter : IValueConverter { + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var key = value.ToString(); - if (String.IsNullOrEmpty(key)) - return key; - return InternationalizationManager.Instance.GetTranslation(key); + if (string.IsNullOrEmpty(key)) return key; + return API.GetTranslation(key); } - public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException(); + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => + throw new InvalidOperationException(); } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs index 84d8a2ff9..fd2c8e09f 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs @@ -32,7 +32,7 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel public bool SatisfiesFilter(PluginStoreItemViewModel plugin) { return string.IsNullOrEmpty(FilterText) || - StringMatcher.FuzzySearch(FilterText, plugin.Name).IsSearchPrecisionScoreMet() || - StringMatcher.FuzzySearch(FilterText, plugin.Description).IsSearchPrecisionScoreMet(); + App.API.FuzzySearch(FilterText, plugin.Name).IsSearchPrecisionScoreMet() || + App.API.FuzzySearch(FilterText, plugin.Description).IsSearchPrecisionScoreMet(); } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index 4958bb7b7..b89e970e9 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -106,8 +106,8 @@ public partial class SettingsPanePluginsViewModel : BaseModel public List FilteredPluginViewModels => PluginViewModels .Where(v => string.IsNullOrEmpty(FilterText) || - StringMatcher.FuzzySearch(FilterText, v.PluginPair.Metadata.Name).IsSearchPrecisionScoreMet() || - StringMatcher.FuzzySearch(FilterText, v.PluginPair.Metadata.Description).IsSearchPrecisionScoreMet() + App.API.FuzzySearch(FilterText, v.PluginPair.Metadata.Name).IsSearchPrecisionScoreMet() || + App.API.FuzzySearch(FilterText, v.PluginPair.Metadata.Description).IsSearchPrecisionScoreMet() ) .ToList(); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs index 1add84765..5c4accdc0 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs @@ -1,16 +1,14 @@ -using Flow.Launcher.Core.Resource; -using Flow.Launcher.Infrastructure; -using Flow.Launcher.Plugin.SharedCommands; -using System; +using System; using System.IO; using System.Linq; using System.Threading.Tasks; -using Flow.Launcher.Plugin.Explorer.Search.Everything; -using System.Windows.Input; -using Path = System.IO.Path; using System.Windows.Controls; +using System.Windows.Input; +using Flow.Launcher.Plugin.Explorer.Search.Everything; using Flow.Launcher.Plugin.Explorer.Views; +using Flow.Launcher.Plugin.SharedCommands; using Peter; +using Path = System.IO.Path; namespace Flow.Launcher.Plugin.Explorer.Search { @@ -66,7 +64,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search CreateFolderResult(Path.GetFileName(result.FullPath), result.FullPath, result.FullPath, query, result.Score, result.WindowsIndexed), ResultType.File => CreateFileResult(result.FullPath, query, result.Score, result.WindowsIndexed), - _ => throw new ArgumentOutOfRangeException() + _ => throw new ArgumentOutOfRangeException(null) }; } @@ -99,7 +97,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search IcoPath = path, SubTitle = subtitle, AutoCompleteText = GetAutoCompleteText(title, query, path, ResultType.Folder), - TitleHighlightData = StringMatcher.FuzzySearch(query.Search, title).MatchData, + TitleHighlightData = Context.API.FuzzySearch(query.Search, title).MatchData, CopyText = path, Preview = new Result.PreviewInfo { @@ -164,7 +162,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search return false; }, Score = score, - TitleToolTip = InternationalizationManager.Instance.GetTranslation("plugin_explorer_plugin_ToolTipOpenDirectory"), + TitleToolTip = Main.Context.API.GetTranslation("plugin_explorer_plugin_ToolTipOpenDirectory"), SubTitleToolTip = path, ContextData = new SearchResult { Type = ResultType.Folder, FullPath = path, WindowsIndexed = windowsIndexed } }; @@ -286,7 +284,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search FilePath = filePath, }, AutoCompleteText = GetAutoCompleteText(title, query, filePath, ResultType.File), - TitleHighlightData = StringMatcher.FuzzySearch(query.Search, title).MatchData, + TitleHighlightData = Context.API.FuzzySearch(query.Search, title).MatchData, Score = score, CopyText = filePath, PreviewPanel = new Lazy(() => new PreviewPanel(Settings, filePath)), @@ -319,7 +317,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search return true; }, - TitleToolTip = InternationalizationManager.Instance.GetTranslation("plugin_explorer_plugin_ToolTipOpenContainingFolder"), + TitleToolTip = Main.Context.API.GetTranslation("plugin_explorer_plugin_ToolTipOpenContainingFolder"), SubTitleToolTip = filePath, ContextData = new SearchResult { Type = ResultType.File, FullPath = filePath, WindowsIndexed = windowsIndexed } }; From f5de5d70dbede5d276e311489b06fcec01656c42 Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:08:28 +0800 Subject: [PATCH 110/125] Fix log message issue Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 99fa44257..54e59d1be 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -254,9 +254,8 @@ namespace Flow.Launcher.Plugin.Program _uwpsCount = _uwps.Count; _uwpsLock.Release(); }); - Context.API.LogInfo(ClassName, "Number of preload win32 programs <{_win32sCount}>"); - Context.API.LogInfo(ClassName, "Number of preload uwps <{_uwpsCount}>"); - + Context.API.LogInfo(ClassName, $"Number of preload win32 programs <{_win32sCount}>"); + Context.API.LogInfo(ClassName, $"Number of preload uwps <{_uwpsCount}>"); var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0; if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now) From 71b9e4a81121be6d445716786bbf2efe186d85c5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:09:37 +0800 Subject: [PATCH 111/125] Fix log info class name issue --- Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs index f6de65e90..f47907824 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs @@ -393,7 +393,7 @@ namespace Flow.Launcher.Plugin.Explorer { Title = Context.API.GetTranslation("plugin_explorer_excludefromindexsearch"), SubTitle = Context.API.GetTranslation("plugin_explorer_path") + " " + record.FullPath, - Action = _ => + Action = c_ => { if (!Settings.IndexSearchExcludedSubdirectoryPaths.Any(x => string.Equals(x.Path, record.FullPath, StringComparison.OrdinalIgnoreCase))) Settings.IndexSearchExcludedSubdirectoryPaths.Add(new AccessLink @@ -401,7 +401,7 @@ namespace Flow.Launcher.Plugin.Explorer Path = record.FullPath }); - Task.Run(() => + _ = Task.Run(() => { Context.API.ShowMsg(Context.API.GetTranslation("plugin_explorer_excludedfromindexsearch_msg"), Context.API.GetTranslation("plugin_explorer_path") + @@ -469,7 +469,7 @@ namespace Flow.Launcher.Plugin.Explorer private void LogException(string message, Exception e) { - Context.API.LogException(nameof(Main), message, e); + Context.API.LogException(nameof(ContextMenu), message, e); } private static bool CanRunAsDifferentUser(string path) From 048a40d085915e59e7d05d3faf17132ec39aadac Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:11:55 +0800 Subject: [PATCH 112/125] Code quality --- Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index 3eb74dd74..3bee49bf2 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -32,7 +32,7 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex _settings = context.API.LoadSettingJsonStorage(); _faviconCacheDir = Path.Combine( - _context.CurrentPluginMetadata.PluginCacheDirectoryPath, + context.CurrentPluginMetadata.PluginCacheDirectoryPath, "FaviconCache"); FilesFolders.ValidateDirectory(_faviconCacheDir); From 7061ac54485e3bd95177dbe737e8b2c4fc521903 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:12:05 +0800 Subject: [PATCH 113/125] Fix register bookmark file comment --- .../ChromiumBookmarkLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 27bcbd9a9..7631aad91 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -37,7 +37,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader { if (File.Exists(bookmarkPath)) { - //Main.RegisterBookmarkFile(bookmarkPath); + Main.RegisterBookmarkFile(bookmarkPath); } } catch (Exception ex) From f854cd3f7623f12b10eddba2beb69599e9672f5f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 15:22:41 +0800 Subject: [PATCH 114/125] Code quality --- Flow.Launcher.Infrastructure/Image/ImageCache.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageCache.cs b/Flow.Launcher.Infrastructure/Image/ImageCache.cs index ddbab4ef0..b8c12868b 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageCache.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageCache.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; using System.Windows.Media; using BitFaster.Caching.Lfu; @@ -55,7 +53,6 @@ namespace Flow.Launcher.Infrastructure.Image return image != null; } - image = null; return false; } From 82f67884ef4619d2f05a931d02e47b40b95479c3 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 16:15:37 +0800 Subject: [PATCH 115/125] Support svg image file loading --- .../Flow.Launcher.Infrastructure.csproj | 1 + .../Image/ImageLoader.cs | 66 +++++++++++++++++-- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 4 +- .../FirefoxBookmarkLoader.cs | 20 +----- 4 files changed, 66 insertions(+), 25 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index b91da7114..f02b2297f 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -67,6 +67,7 @@ + diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 41a33104b..6fd5c6277 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -9,6 +9,8 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; +using SharpVectors.Converters; +using SharpVectors.Renderers.Wpf; namespace Flow.Launcher.Infrastructure.Image { @@ -25,8 +27,10 @@ namespace Flow.Launcher.Infrastructure.Image public static ImageSource LoadingImage { get; } = new BitmapImage(new Uri(Constant.LoadingImgIcon)); public const int SmallIconSize = 64; public const int FullIconSize = 256; + public const int FullImageSize = 320; private static readonly string[] ImageExtensions = { ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".ico" }; + private static readonly string SvgExtension = ".svg"; public static async Task InitializeAsync() { @@ -245,6 +249,19 @@ namespace Flow.Launcher.Infrastructure.Image image = GetThumbnail(path, ThumbnailOptions.ThumbnailOnly); } } + else if (extension == SvgExtension) + { + try + { + image = LoadFullSvgImage(path, loadFullImage); + type = ImageType.FullImageFile; + } + catch (System.Exception) + { + image = Image; + type = ImageType.Error; + } + } else { type = ImageType.File; @@ -318,7 +335,7 @@ namespace Flow.Launcher.Infrastructure.Image return img; } - private static BitmapImage LoadFullImage(string path) + private static ImageSource LoadFullImage(string path) { BitmapImage image = new BitmapImage(); image.BeginInit(); @@ -327,24 +344,24 @@ namespace Flow.Launcher.Infrastructure.Image image.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; image.EndInit(); - if (image.PixelWidth > 320) + if (image.PixelWidth > FullImageSize) { BitmapImage resizedWidth = new BitmapImage(); resizedWidth.BeginInit(); resizedWidth.CacheOption = BitmapCacheOption.OnLoad; resizedWidth.UriSource = new Uri(path); resizedWidth.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; - resizedWidth.DecodePixelWidth = 320; + resizedWidth.DecodePixelWidth = FullImageSize; resizedWidth.EndInit(); - if (resizedWidth.PixelHeight > 320) + if (resizedWidth.PixelHeight > FullImageSize) { BitmapImage resizedHeight = new BitmapImage(); resizedHeight.BeginInit(); resizedHeight.CacheOption = BitmapCacheOption.OnLoad; resizedHeight.UriSource = new Uri(path); resizedHeight.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; - resizedHeight.DecodePixelHeight = 320; + resizedHeight.DecodePixelHeight = FullImageSize; resizedHeight.EndInit(); return resizedHeight; } @@ -354,5 +371,44 @@ namespace Flow.Launcher.Infrastructure.Image return image; } + + private static ImageSource LoadFullSvgImage(string path, bool loadFullImage = false) + { + // Set up drawing settings + var desiredHeight = loadFullImage ? FullImageSize : SmallIconSize; + var drawingSettings = new WpfDrawingSettings + { + IncludeRuntime = true, + // Set IgnoreRootViewbox to false to respect the SVG's viewBox + IgnoreRootViewbox = false + }; + + // Load and render the SVG + var converter = new FileSvgReader(drawingSettings); + var drawing = converter.Read(path); + + // Calculate scale to achieve desired height + var drawingBounds = drawing.Bounds; + var scale = desiredHeight / drawingBounds.Height; + var scaledWidth = drawingBounds.Width * scale; + var scaledHeight = drawingBounds.Height * scale; + + // Convert the Drawing to a Bitmap + var drawingVisual = new DrawingVisual(); + using DrawingContext drawingContext = drawingVisual.RenderOpen(); + drawingContext.PushTransform(new ScaleTransform(scale, scale)); + drawingContext.DrawDrawing(drawing); + + // Create a RenderTargetBitmap to hold the rendered image + var bitmap = new RenderTargetBitmap( + (int)Math.Ceiling(scaledWidth), + (int)Math.Ceiling(scaledHeight), + 96, // DpiX + 96, // DpiY + PixelFormats.Pbgra32); + bitmap.Render(drawingVisual); + + return bitmap; + } } } diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 6f17f57f5..f37496fd1 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -438,7 +438,9 @@ namespace Flow.Launcher.Plugin Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new(); /// - /// Load image from path. Support local, remote and data:image url. + /// Load image from path. + /// Support local, remote and data:image url. + /// Support png, jpg, jpeg, gif, bmp, tiff, ico, svg image files. /// If image path is missing, it will return a missing icon. /// /// The path of the image. diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index d2f973329..113476703 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -159,16 +159,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader if (!File.Exists(faviconPath)) { - // SVG 파일인지 확인 - if (IsSvgData(imageData)) - { - bookmark.FaviconPath = defaultIconPath; - continue; - } - else - { - SaveBitmapData(imageData, faviconPath); - } + SaveBitmapData(imageData, faviconPath); } bookmark.FaviconPath = faviconPath; @@ -199,15 +190,6 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } } - private static bool IsSvgData(byte[] data) - { - if (data.Length < 5) - return false; - string start = System.Text.Encoding.ASCII.GetString(data, 0, Math.Min(100, data.Length)); - return start.Contains(" Date: Wed, 9 Apr 2025 16:24:09 +0800 Subject: [PATCH 116/125] Change function name --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 6fd5c6277..ba46a7cff 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -253,7 +253,7 @@ namespace Flow.Launcher.Infrastructure.Image { try { - image = LoadFullSvgImage(path, loadFullImage); + image = LoadSvgImage(path, loadFullImage); type = ImageType.FullImageFile; } catch (System.Exception) @@ -372,7 +372,7 @@ namespace Flow.Launcher.Infrastructure.Image return image; } - private static ImageSource LoadFullSvgImage(string path, bool loadFullImage = false) + private static ImageSource LoadSvgImage(string path, bool loadFullImage = false) { // Set up drawing settings var desiredHeight = loadFullImage ? FullImageSize : SmallIconSize; From 5e7573b654d135cb92ca92c576d8f54295763374 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 16:28:53 +0800 Subject: [PATCH 117/125] Add log messages --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index ba46a7cff..e0959ccc2 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -233,10 +233,11 @@ namespace Flow.Launcher.Infrastructure.Image image = LoadFullImage(path); type = ImageType.FullImageFile; } - catch (NotSupportedException) + catch (NotSupportedException ex) { image = Image; type = ImageType.Error; + Log.Exception($"Failed to load image file from path {path}: {ex.Message}", ex); } } else @@ -256,10 +257,11 @@ namespace Flow.Launcher.Infrastructure.Image image = LoadSvgImage(path, loadFullImage); type = ImageType.FullImageFile; } - catch (System.Exception) + catch (System.Exception ex) { image = Image; type = ImageType.Error; + Log.Exception($"Failed to load SVG image from path {path}: {ex.Message}", ex); } } else From cce4e89c221e32291b2c88547a5f8f52e585c84c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 16:30:35 +0800 Subject: [PATCH 118/125] Add safeguards to SVG loading implementation --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index e0959ccc2..0433036b7 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -391,6 +391,10 @@ namespace Flow.Launcher.Infrastructure.Image // Calculate scale to achieve desired height var drawingBounds = drawing.Bounds; + if (drawingBounds.Height <= 0) + { + throw new InvalidOperationException($"Invalid SVG dimensions: Height must be greater than zero in {path}"); + } var scale = desiredHeight / drawingBounds.Height; var scaledWidth = drawingBounds.Width * scale; var scaledHeight = drawingBounds.Height * scale; From 4f246460c353cec83a7b8fbfde31c26eba159219 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 16:46:13 +0800 Subject: [PATCH 119/125] Fix build issue --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 4 ++-- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index be3609956..cd5a4cf71 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -243,7 +243,7 @@ namespace Flow.Launcher.Infrastructure.Image { image = Image; type = ImageType.Error; - Log.Exception($"Failed to load image file from path {path}: {ex.Message}", ex); + API.LogException(ClassName, $"Failed to load image file from path {path}: {ex.Message}", ex); } } else @@ -267,7 +267,7 @@ namespace Flow.Launcher.Infrastructure.Image { image = Image; type = ImageType.Error; - Log.Exception($"Failed to load SVG image from path {path}: {ex.Message}", ex); + API.LogException(ClassName, $"Failed to load SVG image from path {path}: {ex.Message}", ex); } } else diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index dca07d085..16b6bcab2 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -32,8 +32,6 @@ namespace Flow.Launcher.Plugin.Program internal static PluginInitContext Context { get; private set; } - private static readonly string ClassName = nameof(Main); - private static readonly List emptyResults = new(); private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; From ba0205f47100c54b91276bc3e25c45add0981f75 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 17:05:29 +0800 Subject: [PATCH 120/125] Force save favicon icons & Fix svg save issue --- .../ChromiumBookmarkLoader.cs | 8 +++---- .../FirefoxBookmarkLoader.cs | 21 +++++++++++++++---- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 7631aad91..7e29cb350 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -177,11 +177,9 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader if (imageData is not { Length: > 0 }) continue; - var faviconPath = Path.Combine(_faviconCacheDir, $"{domain}_{iconId}.png"); - if (!File.Exists(faviconPath)) - { - SaveBitmapData(imageData, faviconPath); - } + var faviconPath = Path.Combine(_faviconCacheDir, $"chromium_{domain}_{iconId}.png"); + SaveBitmapData(imageData, faviconPath); + bookmark.FaviconPath = faviconPath; } catch (Exception ex) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 113476703..b356d08b8 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -155,12 +155,16 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader if (imageData is not { Length: > 0 }) continue; - var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.png"); - - if (!File.Exists(faviconPath)) + string faviconPath; + if (IsSvgData(imageData)) { - SaveBitmapData(imageData, faviconPath); + faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.svg"); } + else + { + faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.png"); + } + SaveBitmapData(imageData, faviconPath); bookmark.FaviconPath = faviconPath; } @@ -201,6 +205,15 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader Main._context.API.LogException(ClassName, $"Failed to save image: {outputPath}", ex); } } + + private static bool IsSvgData(byte[] data) + { + if (data.Length < 5) + return false; + string start = System.Text.Encoding.ASCII.GetString(data, 0, Math.Min(100, data.Length)); + return start.Contains(" Date: Wed, 9 Apr 2025 17:13:44 +0800 Subject: [PATCH 121/125] Fix svg render issue --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index cd5a4cf71..9e31d2b4e 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -393,7 +393,7 @@ namespace Flow.Launcher.Infrastructure.Image // Load and render the SVG var converter = new FileSvgReader(drawingSettings); - var drawing = converter.Read(path); + var drawing = converter.Read(new Uri(path)); // Calculate scale to achieve desired height var drawingBounds = drawing.Bounds; @@ -407,9 +407,11 @@ namespace Flow.Launcher.Infrastructure.Image // Convert the Drawing to a Bitmap var drawingVisual = new DrawingVisual(); - using DrawingContext drawingContext = drawingVisual.RenderOpen(); - drawingContext.PushTransform(new ScaleTransform(scale, scale)); - drawingContext.DrawDrawing(drawing); + using (DrawingContext drawingContext = drawingVisual.RenderOpen()) + { + drawingContext.PushTransform(new ScaleTransform(scale, scale)); + drawingContext.DrawDrawing(drawing); + } // Create a RenderTargetBitmap to hold the rendered image var bitmap = new RenderTargetBitmap( From 62a5dd784daff12d945c80ac2b1c756fd8571638 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 17:24:40 +0800 Subject: [PATCH 122/125] Delete temporary files --- .../ChromiumBookmarkLoader.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 7e29cb350..156dd2f0e 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -136,6 +136,10 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader Main._context.API.LogException(ClassName, $"Failed to copy favicon DB: {dbPath}", ex); return; } + finally + { + File.Delete(tempDbPath); + } try { From 150ea841912f5dc280a42e6d522f78c86afe60b0 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 17:27:34 +0800 Subject: [PATCH 123/125] Make sure temporary files deleted --- .../FirefoxBookmarkLoader.cs | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index b356d08b8..75f26d322 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -41,6 +41,8 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader if (string.IsNullOrEmpty(placesPath) || !File.Exists(placesPath)) return bookmarks; + var tempDbPath = Path.Combine(_faviconCacheDir, $"tempplaces_{Guid.NewGuid()}.sqlite"); + try { // Try to register file monitoring @@ -54,7 +56,6 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } // Use a copy to avoid lock issues with the original file - var tempDbPath = Path.Combine(_faviconCacheDir, $"tempplaces_{Guid.NewGuid()}.sqlite"); File.Copy(placesPath, tempDbPath, true); // Connect to database and execute query @@ -83,31 +84,32 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader // https://github.com/dotnet/efcore/issues/26580 SqliteConnection.ClearPool(dbConnection); dbConnection.Close(); - - // Delete temporary file - try - { - File.Delete(tempDbPath); - } - catch (Exception ex) - { - Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); - } } catch (Exception ex) { Main._context.API.LogException(ClassName, $"Failed to load Firefox bookmarks: {placesPath}", ex); } + // Delete temporary file + try + { + File.Delete(tempDbPath); + } + catch (Exception ex) + { + Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); + } + return bookmarks; } private void LoadFaviconsFromDb(string faviconDbPath, List bookmarks) { + var tempDbPath = Path.Combine(_faviconCacheDir, $"tempfavicons_{Guid.NewGuid()}.sqlite"); + try { // Use a copy to avoid lock issues with the original file - var tempDbPath = Path.Combine(_faviconCacheDir, $"tempfavicons_{Guid.NewGuid()}.sqlite"); File.Copy(faviconDbPath, tempDbPath, true); var defaultIconPath = Path.Combine( @@ -177,21 +179,21 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader // https://github.com/dotnet/efcore/issues/26580 SqliteConnection.ClearPool(connection); connection.Close(); - - // Delete temporary file - try - { - File.Delete(tempDbPath); - } - catch (Exception ex) - { - Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); - } } catch (Exception ex) { Main._context.API.LogException(ClassName, $"Failed to load Firefox favicon DB: {faviconDbPath}", ex); } + + // Delete temporary file + try + { + File.Delete(tempDbPath); + } + catch (Exception ex) + { + Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); + } } private static void SaveBitmapData(byte[] imageData, string outputPath) From 33800795ed27bddd4e3a5cfb9e3db6b2bba73763 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 17:29:28 +0800 Subject: [PATCH 124/125] Remove useless try catch --- .../ChromiumBookmarkLoader.cs | 121 +++++++++--------- 1 file changed, 57 insertions(+), 64 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 156dd2f0e..4b9499c27 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -122,45 +122,43 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader private void LoadFaviconsFromDb(string dbPath, List bookmarks) { + // Use a copy to avoid lock issues with the original file + var tempDbPath = Path.Combine(_faviconCacheDir, $"tempfavicons_{Guid.NewGuid()}.db"); + try { - // Use a copy to avoid lock issues with the original file - var tempDbPath = Path.Combine(_faviconCacheDir, $"tempfavicons_{Guid.NewGuid()}.db"); + File.Copy(dbPath, tempDbPath, true); + } + catch (Exception ex) + { + Main._context.API.LogException(ClassName, $"Failed to copy favicon DB: {dbPath}", ex); + return; + } + finally + { + File.Delete(tempDbPath); + } - try - { - File.Copy(dbPath, tempDbPath, true); - } - catch (Exception ex) - { - Main._context.API.LogException(ClassName, $"Failed to copy favicon DB: {dbPath}", ex); - return; - } - finally - { - File.Delete(tempDbPath); - } + try + { + using var connection = new SqliteConnection($"Data Source={tempDbPath}"); + connection.Open(); - try + foreach (var bookmark in bookmarks) { - using var connection = new SqliteConnection($"Data Source={tempDbPath}"); - connection.Open(); - - foreach (var bookmark in bookmarks) + try { - try - { - var url = bookmark.Url; - if (string.IsNullOrEmpty(url)) continue; + var url = bookmark.Url; + if (string.IsNullOrEmpty(url)) continue; - // Extract domain from URL - if (!Uri.TryCreate(url, UriKind.Absolute, out Uri uri)) - continue; + // Extract domain from URL + if (!Uri.TryCreate(url, UriKind.Absolute, out Uri uri)) + continue; - var domain = uri.Host; + var domain = uri.Host; - using var cmd = connection.CreateCommand(); - cmd.CommandText = @" + using var cmd = connection.CreateCommand(); + cmd.CommandText = @" SELECT f.id, b.image_data FROM favicons f JOIN favicon_bitmaps b ON f.id = b.icon_id @@ -169,51 +167,46 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader ORDER BY b.width DESC LIMIT 1"; - cmd.Parameters.AddWithValue("@url", $"%{domain}%"); + cmd.Parameters.AddWithValue("@url", $"%{domain}%"); - using var reader = cmd.ExecuteReader(); - if (!reader.Read() || reader.IsDBNull(1)) - continue; + using var reader = cmd.ExecuteReader(); + if (!reader.Read() || reader.IsDBNull(1)) + continue; - var iconId = reader.GetInt64(0).ToString(); - var imageData = (byte[])reader["image_data"]; + var iconId = reader.GetInt64(0).ToString(); + var imageData = (byte[])reader["image_data"]; - if (imageData is not { Length: > 0 }) - continue; + if (imageData is not { Length: > 0 }) + continue; - var faviconPath = Path.Combine(_faviconCacheDir, $"chromium_{domain}_{iconId}.png"); - SaveBitmapData(imageData, faviconPath); + var faviconPath = Path.Combine(_faviconCacheDir, $"chromium_{domain}_{iconId}.png"); + SaveBitmapData(imageData, faviconPath); - bookmark.FaviconPath = faviconPath; - } - catch (Exception ex) - { - Main._context.API.LogException(ClassName, $"Failed to extract bookmark favicon: {bookmark.Url}", ex); - } + bookmark.FaviconPath = faviconPath; + } + catch (Exception ex) + { + Main._context.API.LogException(ClassName, $"Failed to extract bookmark favicon: {bookmark.Url}", ex); } - - // https://github.com/dotnet/efcore/issues/26580 - SqliteConnection.ClearPool(connection); - connection.Close(); - } - catch (Exception ex) - { - Main._context.API.LogException(ClassName, $"Failed to connect to SQLite: {tempDbPath}", ex); } - // Delete temporary file - try - { - File.Delete(tempDbPath); - } - catch (Exception ex) - { - Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); - } + // https://github.com/dotnet/efcore/issues/26580 + SqliteConnection.ClearPool(connection); + connection.Close(); } catch (Exception ex) { - Main._context.API.LogException(ClassName, $"Failed to load favicon DB: {dbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to connect to SQLite: {tempDbPath}", ex); + } + + // Delete temporary file + try + { + File.Delete(tempDbPath); + } + catch (Exception ex) + { + Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); } } From 2d29a42dc950f612e2161bd5f6c49d09444ef8bb Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 17:32:48 +0800 Subject: [PATCH 125/125] Improve code quality --- .../ChromiumBookmarkLoader.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 4b9499c27..66be08903 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -131,13 +131,10 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { + File.Delete(tempDbPath); Main._context.API.LogException(ClassName, $"Failed to copy favicon DB: {dbPath}", ex); return; } - finally - { - File.Delete(tempDbPath); - } try {