From f40255bc8a65b921c9a1490fad7efde1fabc9a78 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 6 Sep 2025 15:52:57 +0800 Subject: [PATCH 01/73] Use DialogJump to get explorer path --- .../FileExplorerHelper.cs | 75 ++----------------- 1 file changed, 5 insertions(+), 70 deletions(-) diff --git a/Flow.Launcher.Infrastructure/FileExplorerHelper.cs b/Flow.Launcher.Infrastructure/FileExplorerHelper.cs index 1085cc833..6e2d86849 100644 --- a/Flow.Launcher.Infrastructure/FileExplorerHelper.cs +++ b/Flow.Launcher.Infrastructure/FileExplorerHelper.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Windows.Win32; namespace Flow.Launcher.Infrastructure { @@ -13,9 +9,10 @@ namespace Flow.Launcher.Infrastructure /// public static string GetActiveExplorerPath() { - var explorerWindow = GetActiveExplorer(); - string locationUrl = explorerWindow?.LocationURL; - return !string.IsNullOrEmpty(locationUrl) ? GetDirectoryPath(new Uri(locationUrl).LocalPath) : null; + var explorerPath = DialogJump.DialogJump.GetActiveExplorerPath(); + return !string.IsNullOrEmpty(explorerPath) ? + GetDirectoryPath(new Uri(explorerPath).LocalPath) : + null; } /// @@ -23,74 +20,12 @@ namespace Flow.Launcher.Infrastructure /// private static string GetDirectoryPath(string path) { - if (!path.EndsWith("\\")) + if (!path.EndsWith('\\')) { return path + "\\"; } return path; } - - /// - /// Gets the file explorer that is currently in the foreground - /// - private static dynamic GetActiveExplorer() - { - Type type = Type.GetTypeFromProgID("Shell.Application"); - if (type == null) return null; - dynamic shell = Activator.CreateInstance(type); - if (shell == null) - { - return null; - } - - var explorerWindows = new List(); - var openWindows = shell.Windows(); - for (int i = 0; i < openWindows.Count; i++) - { - var window = openWindows.Item(i); - if (window == null) continue; - - // find the desired window and make sure that it is indeed a file explorer - // we don't want the Internet Explorer or the classic control panel - // ToLower() is needed, because Windows can report the path as "C:\\Windows\\Explorer.EXE" - if (Path.GetFileName((string)window.FullName)?.ToLower() == "explorer.exe") - { - explorerWindows.Add(window); - } - } - - if (explorerWindows.Count == 0) return null; - - var zOrders = GetZOrder(explorerWindows); - - return explorerWindows.Zip(zOrders).MinBy(x => x.Second).First; - } - - /// - /// Gets the z-order for one or more windows atomically with respect to each other. In Windows, smaller z-order is higher. If the window is not top level, the z order is returned as -1. - /// - private static IEnumerable GetZOrder(List hWnds) - { - var z = new int[hWnds.Count]; - for (var i = 0; i < hWnds.Count; i++) z[i] = -1; - - var index = 0; - var numRemaining = hWnds.Count; - PInvoke.EnumWindows((wnd, _) => - { - var searchIndex = hWnds.FindIndex(x => new IntPtr(x.HWND) == wnd); - if (searchIndex != -1) - { - z[searchIndex] = index; - numRemaining--; - if (numRemaining == 0) return false; - } - index++; - return true; - }, IntPtr.Zero); - - return z; - } } } From 9321a7df140ce303fbd21f44eb7c09bdfea31225 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 15 Sep 2025 15:40:49 +0800 Subject: [PATCH 02/73] Fix program lock issue --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 62 ++++++++++++------- .../Views/Commands/ProgramSettingDisplay.cs | 52 +++++++++++----- 2 files changed, 79 insertions(+), 35 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 7c30c0c96..0eb1fd403 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -31,7 +31,7 @@ namespace Flow.Launcher.Plugin.Program internal static PluginInitContext Context { get; private set; } - private static readonly List emptyResults = new(); + private static readonly List emptyResults = []; private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; private static MemoryCache cache = new(cacheOptions); @@ -84,7 +84,6 @@ namespace Flow.Launcher.Plugin.Program { await _win32sLock.WaitAsync(token); await _uwpsLock.WaitAsync(token); - try { // Collect all UWP Windows app directories @@ -117,7 +116,7 @@ namespace Flow.Launcher.Plugin.Program } }, token); - resultList = resultList.Any() ? resultList : emptyResults; + resultList = resultList.Count != 0 ? resultList : emptyResults; entry.SetSize(resultList.Count); entry.SetSlidingExpiration(TimeSpan.FromHours(8)); @@ -250,14 +249,26 @@ namespace Flow.Launcher.Plugin.Program } await _win32sLock.WaitAsync(); - _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCacheDirectory, new List()); - _win32sCount = _win32s.Count; - _win32sLock.Release(); + try + { + _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCacheDirectory, new List()); + _win32sCount = _win32s.Count; + } + finally + { + _win32sLock.Release(); + } await _uwpsLock.WaitAsync(); - _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCacheDirectory, new List()); - _uwpsCount = _uwps.Count; - _uwpsLock.Release(); + try + { + _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCacheDirectory, new List()); + _uwpsCount = _uwps.Count; + } + finally + { + _uwpsLock.Release(); + } }); Context.API.LogInfo(ClassName, $"Number of preload win32 programs <{_win32sCount}>"); Context.API.LogInfo(ClassName, $"Number of preload uwps <{_uwpsCount}>"); @@ -408,38 +419,47 @@ namespace Flow.Launcher.Plugin.Program return; await _uwpsLock.WaitAsync(); - if (_uwps.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) + var reindexUwps = true; + try { + reindexUwps = _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)); + } + finally + { _uwpsLock.Release(); + } - // Reindex UWP programs + // Reindex UWP programs + if (reindexUwps) + { _ = Task.Run(IndexUwpProgramsAsync); return; } - else - { - _uwpsLock.Release(); - } await _win32sLock.WaitAsync(); - if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) + var reindexWin32s = true; + try { + reindexWin32s = _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); - return; } - else + finally { _win32sLock.Release(); } + + // Reindex Win32 programs + if (reindexWin32s) + { + _ = Task.Run(IndexWin32ProgramsAsync); + return; + } } public static void StartProcess(Func runProcess, ProcessStartInfo info) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs index b89a2a6ba..2a6a3e987 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs @@ -19,18 +19,30 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands internal static async Task DisplayAllProgramsAsync() { await Main._win32sLock.WaitAsync(); - var win32 = Main._win32s + try + { + 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(); + ProgramSetting.ProgramSettingDisplayList.AddRange(win32); + } + finally + { + Main._win32sLock.Release(); + } await Main._uwpsLock.WaitAsync(); - var uwp = Main._uwps + try + { + var uwp = Main._uwps .Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier)) .Select(x => new ProgramSource(x)); - ProgramSetting.ProgramSettingDisplayList.AddRange(uwp); - Main._uwpsLock.Release(); + ProgramSetting.ProgramSettingDisplayList.AddRange(uwp); + } + finally + { + Main._uwpsLock.Release(); + } } internal static async Task SetProgramSourcesStatusAsync(List selectedProgramSourcesToDisable, bool status) @@ -44,24 +56,36 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands } await Main._win32sLock.WaitAsync(); - foreach (var program in Main._win32s) + try { - if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status)) + foreach (var program in Main._win32s) { - program.Enabled = status; + if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status)) + { + program.Enabled = status; + } } } - Main._win32sLock.Release(); + finally + { + Main._win32sLock.Release(); + } await Main._uwpsLock.WaitAsync(); - foreach (var program in Main._uwps) + try { - if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status)) + foreach (var program in Main._uwps) { - program.Enabled = status; + if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status)) + { + program.Enabled = status; + } } } - Main._uwpsLock.Release(); + finally + { + Main._uwpsLock.Release(); + } } internal static void StoreDisabledInSettings() From ef69e329fc1d28b3e1352f3a04f94bb33da8afc6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 15 Sep 2025 15:50:22 +0800 Subject: [PATCH 03/73] Fix release --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 0eb1fd403..0258a10d2 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -447,7 +447,6 @@ namespace Flow.Launcher.Plugin.Program var program = _win32s.First(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier); program.Enabled = false; _settings.DisabledProgramSources.Add(new ProgramSource(program)); - _win32sLock.Release(); } finally { From e204daa8443aad283feba9dabeed576e16d13c7e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 15 Sep 2025 21:33:21 +0800 Subject: [PATCH 04/73] Catch exception when creating setting panel --- Flow.Launcher/ViewModel/PluginViewModel.cs | 36 +++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index d889bdd52..36c509902 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -131,11 +131,45 @@ namespace Flow.Launcher.ViewModel => IsExpanded ? _settingControl ??= HasSettingControl - ? ((ISettingProvider)PluginPair.Plugin).CreateSettingPanel() + ? TryCreateSettingPanel(PluginPair) : null : null; private ImageSource _image = ImageLoader.MissingImage; + private static readonly Thickness SettingPanelMargin = (Thickness)Application.Current.FindResource("SettingPanelMargin"); + private static readonly Thickness SettingPanelItemTopBottomMargin = (Thickness)Application.Current.FindResource("SettingPanelItemTopBottomMargin"); + private static Control TryCreateSettingPanel(PluginPair pair) + { + try + { + // We can safely cast here as we already check this in HasSettingControl + return ((ISettingProvider)pair.Plugin).CreateSettingPanel(); + } + catch (System.Exception e) + { + var errorMsg = $"Error creating setting panel for plugin {pair.Metadata}\n{e.Message}"; + var grid = new Grid() + { + Margin = SettingPanelMargin + }; + var textBox = new TextBox + { + Text = errorMsg, + IsReadOnly = true, + HorizontalAlignment = HorizontalAlignment.Stretch, + VerticalAlignment = VerticalAlignment.Top, + TextWrapping = TextWrapping.Wrap, + Margin = SettingPanelItemTopBottomMargin + }; + textBox.SetResourceReference(TextBlock.ForegroundProperty, "Color04B"); + grid.Children.Add(textBox); + return new UserControl + { + Content = grid + }; + } + } + public Visibility ActionKeywordsVisibility => PluginPair.Metadata.HideActionKeywordPanel ? Visibility.Collapsed : Visibility.Visible; public string InitializeTime => PluginPair.Metadata.InitTime + "ms"; From 0355993b009b3e29b399a3fdbc02fba481337303 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 15 Sep 2025 21:38:53 +0800 Subject: [PATCH 05/73] Use translation --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/ViewModel/PluginViewModel.cs | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index f7fd0c8e5..e97bd6cf5 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -219,6 +219,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Plugin Store diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 36c509902..4de1ae661 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; @@ -145,9 +146,10 @@ namespace Flow.Launcher.ViewModel // We can safely cast here as we already check this in HasSettingControl return ((ISettingProvider)pair.Plugin).CreateSettingPanel(); } - catch (System.Exception e) + catch (Exception e) { - var errorMsg = $"Error creating setting panel for plugin {pair.Metadata}\n{e.Message}"; + var errorMsg = string.Format(App.API.GetTranslation("errorCreatingSettingPanel"), + pair.Metadata.Name, Environment.NewLine, e.Message); var grid = new Grid() { Margin = SettingPanelMargin From 18c8a04cbcc5fe062730abef62af7c0760682eae Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 15 Sep 2025 21:46:03 +0800 Subject: [PATCH 06/73] Log exception --- Flow.Launcher/ViewModel/PluginViewModel.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 4de1ae661..59bb53a4a 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -15,6 +15,8 @@ namespace Flow.Launcher.ViewModel { public partial class PluginViewModel : BaseModel { + private static readonly string ClassName = nameof(PluginViewModel); + private static readonly Settings Settings = Ioc.Default.GetRequiredService(); private readonly PluginPair _pluginPair; @@ -148,6 +150,10 @@ namespace Flow.Launcher.ViewModel } catch (Exception e) { + // Log exception + App.API.LogException(ClassName, $"Failed to create setting panel for {pair.Metadata.Name}", e); + + // Show error message in UI var errorMsg = string.Format(App.API.GetTranslation("errorCreatingSettingPanel"), pair.Metadata.Name, Environment.NewLine, e.Message); var grid = new Grid() From 23d0b73e20bb0963d5a11a6c910edc04035b52af Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 17 Sep 2025 17:30:03 +0800 Subject: [PATCH 07/73] Fix AllEverythingSortOptions issue --- .../ViewModels/SettingsViewModel.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 7292697ce..ae2235c5c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -577,8 +577,8 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels } } - public int MaxResultLowerLimit => 1; - public int MaxResultUpperLimit => 100000; + public int MaxResultLowerLimit { get; } = 1; + public int MaxResultUpperLimit { get; } = 100000; public int MaxResult { @@ -592,7 +592,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels #region Everything FastSortWarning - public List AllEverythingSortOptions = EverythingSortOptionLocalized.GetValues(); + public List AllEverythingSortOptions { get; } = EverythingSortOptionLocalized.GetValues(); public EverythingSortOption SelectedEverythingSortOption { From 80c283a370fa7a9a2cb74778b97e55b2829069a0 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 17 Sep 2025 19:15:46 +0800 Subject: [PATCH 08/73] Improve code quality --- Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index 93b9a8aaa..c16e1170d 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; @@ -16,7 +17,7 @@ public static class WallpaperPathRetrieval private const int MaxCacheSize = 3; private static readonly Dictionary<(string, DateTime), ImageBrush> WallpaperCache = new(); - private static readonly object CacheLock = new(); + private static readonly Lock CacheLock = new(); public static Brush GetWallpaperBrush() { @@ -56,7 +57,7 @@ public static class WallpaperPathRetrieval if (originalWidth == 0 || originalHeight == 0) { - App.API.LogInfo(ClassName, $"Failed to load bitmap: Width={originalWidth}, Height={originalHeight}"); + App.API.LogError(ClassName, $"Failed to load bitmap: Width={originalWidth}, Height={originalHeight}"); return new SolidColorBrush(Colors.Transparent); } @@ -104,13 +105,13 @@ public static class WallpaperPathRetrieval private static Color GetWallpaperColor() { - RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Colors", false); + using var key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Colors", false); var result = key?.GetValue("Background", null); if (result is string strResult) { try { - var parts = strResult.Trim().Split(new[] { ' ' }, 3).Select(byte.Parse).ToList(); + var parts = strResult.Trim().Split([' '], 3).Select(byte.Parse).ToList(); return Color.FromRgb(parts[0], parts[1], parts[2]); } catch (Exception ex) From 5c16b86edfde80d6b07c08da6a59fddc3ee61880 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 17 Sep 2025 19:16:09 +0800 Subject: [PATCH 09/73] Fix file lock during file stream --- Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index c16e1170d..be35b8f69 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -48,12 +48,15 @@ public static class WallpaperPathRetrieval return cachedWallpaper; } } - - using var fileStream = File.OpenRead(wallpaperPath); - var decoder = BitmapDecoder.Create(fileStream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None); - var frame = decoder.Frames[0]; - var originalWidth = frame.PixelWidth; - var originalHeight = frame.PixelHeight; + + int originalWidth, originalHeight; + using (var fileStream = File.OpenRead(wallpaperPath)) + { + var decoder = BitmapDecoder.Create(fileStream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None); + var frame = decoder.Frames[0]; + originalWidth = frame.PixelWidth; + originalHeight = frame.PixelHeight; + } if (originalWidth == 0 || originalHeight == 0) { From 83f02f5c9144cf49c387a0e408fa92c43e0f7c9f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 17 Sep 2025 19:16:58 +0800 Subject: [PATCH 10/73] Use log error & Improve returned color --- Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index be35b8f69..aa41c9998 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -32,7 +32,7 @@ public static class WallpaperPathRetrieval var wallpaperPath = Win32Helper.GetWallpaperPath(); if (string.IsNullOrEmpty(wallpaperPath) || !File.Exists(wallpaperPath)) { - App.API.LogInfo(ClassName, $"Wallpaper path is invalid: {wallpaperPath}"); + App.API.LogError(ClassName, $"Wallpaper path is invalid: {wallpaperPath}"); var wallpaperColor = GetWallpaperColor(); return new SolidColorBrush(wallpaperColor); } @@ -61,7 +61,8 @@ public static class WallpaperPathRetrieval if (originalWidth == 0 || originalHeight == 0) { App.API.LogError(ClassName, $"Failed to load bitmap: Width={originalWidth}, Height={originalHeight}"); - return new SolidColorBrush(Colors.Transparent); + var wallpaperColor = GetWallpaperColor(); + return new SolidColorBrush(wallpaperColor); } // Calculate the scaling factor to fit the image within 800x600 while preserving aspect ratio From 60ec9b5c497c7a30e58dc29b0d5d602fb50a8adc Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 17 Sep 2025 19:24:32 +0800 Subject: [PATCH 11/73] Use OnLoaded to ensure the wallpaper file is not locked --- Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index aa41c9998..57c1bbe8d 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -75,7 +75,9 @@ public static class WallpaperPathRetrieval // Set DecodePixelWidth and DecodePixelHeight to resize the image while preserving aspect ratio var bitmap = new BitmapImage(); bitmap.BeginInit(); + bitmap.CacheOption = BitmapCacheOption.OnLoad; // Use OnLoaded to ensure the wallpaper file is not locked bitmap.UriSource = new Uri(wallpaperPath); + bitmap.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; bitmap.DecodePixelWidth = decodedPixelWidth; bitmap.DecodePixelHeight = decodedPixelHeight; bitmap.EndInit(); From 354b04bea449091efa5bd61e182d133552367391 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 17 Sep 2025 19:29:36 +0800 Subject: [PATCH 12/73] Add code comments --- Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index 57c1bbe8d..67618d760 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -50,6 +50,7 @@ public static class WallpaperPathRetrieval } int originalWidth, originalHeight; + // Use `using ()` instead of `using var` sentence here to ensure the wallpaper file is not locked using (var fileStream = File.OpenRead(wallpaperPath)) { var decoder = BitmapDecoder.Create(fileStream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None); From e50a2772f82392234eb1389e3fad8b01dfae3e3d Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Wed, 17 Sep 2025 19:33:46 +0800 Subject: [PATCH 13/73] Update code comments Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index 67618d760..fd04b3e88 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -76,7 +76,7 @@ public static class WallpaperPathRetrieval // Set DecodePixelWidth and DecodePixelHeight to resize the image while preserving aspect ratio var bitmap = new BitmapImage(); bitmap.BeginInit(); - bitmap.CacheOption = BitmapCacheOption.OnLoad; // Use OnLoaded to ensure the wallpaper file is not locked + bitmap.CacheOption = BitmapCacheOption.OnLoad; // Use OnLoad to ensure the wallpaper file is not locked bitmap.UriSource = new Uri(wallpaperPath); bitmap.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; bitmap.DecodePixelWidth = decodedPixelWidth; From 1fea8edb747470b076376b76473d52f9c8253f51 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 11:46:09 +0800 Subject: [PATCH 14/73] Add translation for default items & new profile item for explorer & browser window --- .../UserSettings/CustomBrowserViewModel.cs | 17 +++++++++++++---- .../UserSettings/CustomExplorerViewModel.cs | 15 ++++++++++++++- Flow.Launcher/Languages/en.xaml | 3 +++ Flow.Launcher/SelectBrowserWindow.xaml | 2 +- Flow.Launcher/SelectBrowserWindow.xaml.cs | 12 +++++++++++- Flow.Launcher/SelectFileManagerWindow.xaml | 2 +- .../ViewModels/SettingsPaneGeneralViewModel.cs | 4 +++- .../SettingPages/Views/SettingsPaneGeneral.xaml | 4 ++-- .../ViewModel/SelectBrowserViewModel.cs | 12 +----------- 9 files changed, 49 insertions(+), 22 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs index 24584115d..9c795f952 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs @@ -1,11 +1,18 @@ +using System.Text.Json.Serialization; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Plugin; -using System.Text.Json.Serialization; namespace Flow.Launcher.Infrastructure.UserSettings { public class CustomBrowserViewModel : BaseModel { + // 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 string Name { get; set; } + [JsonIgnore] + public string DisplayName => Name == "Default" ? API.GetTranslation("defaultBrowser_default") : Name; public string Path { get; set; } public string PrivateArg { get; set; } public bool EnablePrivate { get; set; } @@ -26,8 +33,10 @@ namespace Flow.Launcher.Infrastructure.UserSettings Editable = Editable }; } + + public void OnDisplayNameChanged() + { + OnPropertyChanged(nameof(DisplayName)); + } } } - - - diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs index c54c30478..5727f0735 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs @@ -1,10 +1,18 @@ -using Flow.Launcher.Plugin; +using System.Text.Json.Serialization; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.ViewModel { public class CustomExplorerViewModel : BaseModel { + // 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 string Name { get; set; } + [JsonIgnore] + public string DisplayName => Name == "Explorer" ? API.GetTranslation("fileManagerExplorer") : Name; public string Path { get; set; } public string FileArgument { get; set; } = "\"%d\""; public string DirectoryArgument { get; set; } = "\"%d\""; @@ -21,5 +29,10 @@ namespace Flow.Launcher.ViewModel Editable = Editable }; } + + public void OnDisplayNameChanged() + { + OnPropertyChanged(nameof(DisplayName)); + } } } diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index f7fd0c8e5..b38fe8aab 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -487,6 +487,7 @@ Arg For File The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Default Web Browser @@ -497,6 +498,8 @@ New Window New Tab Private Mode + Default + New Profile Change Priority diff --git a/Flow.Launcher/SelectBrowserWindow.xaml b/Flow.Launcher/SelectBrowserWindow.xaml index d51d597b7..67c22b07d 100644 --- a/Flow.Launcher/SelectBrowserWindow.xaml +++ b/Flow.Launcher/SelectBrowserWindow.xaml @@ -92,7 +92,7 @@ SelectedIndex="{Binding SelectedCustomBrowserIndex}"> - + diff --git a/Flow.Launcher/SelectBrowserWindow.xaml.cs b/Flow.Launcher/SelectBrowserWindow.xaml.cs index 565b4cbc3..8ef50ca75 100644 --- a/Flow.Launcher/SelectBrowserWindow.xaml.cs +++ b/Flow.Launcher/SelectBrowserWindow.xaml.cs @@ -31,7 +31,7 @@ namespace Flow.Launcher private void btnBrowseFile_Click(object sender, RoutedEventArgs e) { - var selectedFilePath = _viewModel.SelectFile(); + var selectedFilePath = SelectFile(); if (!string.IsNullOrEmpty(selectedFilePath)) { @@ -41,5 +41,15 @@ namespace Flow.Launcher ((Button)sender).Focus(); } } + + private static string SelectFile() + { + var dlg = new Microsoft.Win32.OpenFileDialog(); + var result = dlg.ShowDialog(); + if (result == true) + return dlg.FileName; + + return string.Empty; + } } } diff --git a/Flow.Launcher/SelectFileManagerWindow.xaml b/Flow.Launcher/SelectFileManagerWindow.xaml index b3b219d1c..cd4bec424 100644 --- a/Flow.Launcher/SelectFileManagerWindow.xaml +++ b/Flow.Launcher/SelectFileManagerWindow.xaml @@ -102,7 +102,7 @@ SelectedIndex="{Binding SelectedCustomExplorerIndex}"> - + diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index ec75ddf90..b47b53654 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; @@ -219,6 +219,8 @@ public partial class SettingsPaneGeneralViewModel : BaseModel DropdownDataGeneric.UpdateLabels(DialogJumpFileResultBehaviours); // Since we are using Binding instead of DynamicResource, we need to manually trigger the update OnPropertyChanged(nameof(AlwaysPreviewToolTip)); + Settings.CustomExplorer.OnDisplayNameChanged(); + Settings.CustomBrowser.OnDisplayNameChanged(); } public string Language diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 81e15df69..07cc7b6a7 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -403,7 +403,7 @@ MaxWidth="250" Margin="10 0 0 0" Command="{Binding SelectFileManagerCommand}" - Content="{Binding Settings.CustomExplorer.Name}" /> + Content="{Binding Settings.CustomExplorer.DisplayName}" /> + Content="{Binding Settings.CustomBrowser.DisplayName}" /> diff --git a/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs b/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs index 67bbbd930..bcc6f1489 100644 --- a/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs +++ b/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs @@ -40,22 +40,12 @@ public partial class SelectBrowserViewModel : BaseModel return true; } - internal string SelectFile() - { - var dlg = new Microsoft.Win32.OpenFileDialog(); - var result = dlg.ShowDialog(); - if (result == true) - return dlg.FileName; - - return string.Empty; - } - [RelayCommand] private void Add() { CustomBrowsers.Add(new() { - Name = "New Profile" + Name = App.API.GetTranslation("defaultBrowser_new_profile") }); SelectedCustomBrowserIndex = CustomBrowsers.Count - 1; } From 647c55eaf7e60a525f7e9c4ffa3a1c5809e39d66 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 11:47:18 +0800 Subject: [PATCH 15/73] Add property changed check --- Flow.Launcher/ViewModel/SelectBrowserViewModel.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs b/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs index bcc6f1489..f75a0ef8b 100644 --- a/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs +++ b/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs @@ -17,8 +17,11 @@ public partial class SelectBrowserViewModel : BaseModel get => selectedCustomBrowserIndex; set { - selectedCustomBrowserIndex = value; - OnPropertyChanged(nameof(CustomBrowser)); + if (selectedCustomBrowserIndex != value) + { + selectedCustomBrowserIndex = value; + OnPropertyChanged(nameof(CustomBrowser)); + } } } From dd07baff59756db8b83e0a1ca362c136cd51b2d6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 11:58:38 +0800 Subject: [PATCH 16/73] Add SelectFile helper method & Improve code quality --- Flow.Launcher.Infrastructure/Win32Helper.cs | 16 +++++++++++++++- Flow.Launcher/SelectBrowserWindow.xaml.cs | 13 ++----------- Flow.Launcher/SelectFileManagerWindow.xaml.cs | 5 +++-- .../ViewModel/SelectFileManagerViewModel.cs | 15 --------------- 4 files changed, 20 insertions(+), 29 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 811733925..5d30b740d 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; @@ -904,5 +904,19 @@ namespace Flow.Launcher.Infrastructure } #endregion + + #region File / Folder Dialog + + public static string SelectFile() + { + var dlg = new OpenFileDialog(); + var result = dlg.ShowDialog(); + if (result == true) + return dlg.FileName; + + return string.Empty; + } + + #endregion } } diff --git a/Flow.Launcher/SelectBrowserWindow.xaml.cs b/Flow.Launcher/SelectBrowserWindow.xaml.cs index 8ef50ca75..290712aad 100644 --- a/Flow.Launcher/SelectBrowserWindow.xaml.cs +++ b/Flow.Launcher/SelectBrowserWindow.xaml.cs @@ -1,6 +1,7 @@ using System.Windows; using System.Windows.Controls; using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Infrastructure; using Flow.Launcher.ViewModel; namespace Flow.Launcher @@ -31,7 +32,7 @@ namespace Flow.Launcher private void btnBrowseFile_Click(object sender, RoutedEventArgs e) { - var selectedFilePath = SelectFile(); + var selectedFilePath = Win32Helper.SelectFile(); if (!string.IsNullOrEmpty(selectedFilePath)) { @@ -41,15 +42,5 @@ namespace Flow.Launcher ((Button)sender).Focus(); } } - - private static string SelectFile() - { - var dlg = new Microsoft.Win32.OpenFileDialog(); - var result = dlg.ShowDialog(); - if (result == true) - return dlg.FileName; - - return string.Empty; - } } } diff --git a/Flow.Launcher/SelectFileManagerWindow.xaml.cs b/Flow.Launcher/SelectFileManagerWindow.xaml.cs index d9c672aff..5143f9a56 100644 --- a/Flow.Launcher/SelectFileManagerWindow.xaml.cs +++ b/Flow.Launcher/SelectFileManagerWindow.xaml.cs @@ -2,6 +2,7 @@ using System.Windows.Controls; using System.Windows.Navigation; using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Infrastructure; using Flow.Launcher.ViewModel; namespace Flow.Launcher @@ -32,13 +33,13 @@ namespace Flow.Launcher private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) { - _viewModel.OpenUrl(e.Uri.AbsoluteUri); + App.API.OpenUrl(e.Uri.AbsoluteUri); e.Handled = true; } private void btnBrowseFile_Click(object sender, RoutedEventArgs e) { - var selectedFilePath = _viewModel.SelectFile(); + var selectedFilePath = Win32Helper.SelectFile(); if (!string.IsNullOrEmpty(selectedFilePath)) { diff --git a/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs b/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs index 77f004980..253f74b47 100644 --- a/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs +++ b/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs @@ -98,21 +98,6 @@ public partial class SelectFileManagerViewModel : BaseModel } } - internal void OpenUrl(string absoluteUri) - { - App.API.OpenUrl(absoluteUri); - } - - internal string SelectFile() - { - var dlg = new Microsoft.Win32.OpenFileDialog(); - var result = dlg.ShowDialog(); - if (result == true) - return dlg.FileName; - - return string.Empty; - } - [RelayCommand] private void Add() { From a03f62832ad52362cefc06f23f5130e1d78c82af Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 12:08:49 +0800 Subject: [PATCH 17/73] Ignore index change for -1 --- Flow.Launcher/ViewModel/SelectBrowserViewModel.cs | 2 ++ Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs b/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs index f75a0ef8b..e3a0e4e44 100644 --- a/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs +++ b/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs @@ -17,6 +17,8 @@ public partial class SelectBrowserViewModel : BaseModel get => selectedCustomBrowserIndex; set { + // When one custom browser is selected and removed, the index will become -1, so we need to ignore this change + if (value < 0) return; if (selectedCustomBrowserIndex != value) { selectedCustomBrowserIndex = value; diff --git a/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs b/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs index 253f74b47..b0851b90c 100644 --- a/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs +++ b/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs @@ -21,6 +21,8 @@ public partial class SelectFileManagerViewModel : BaseModel get => selectedCustomExplorerIndex; set { + // When one custom file manager is selected and removed, the index will become -1, so we need to ignore this change + if (value < 0) return; if (selectedCustomExplorerIndex != value) { selectedCustomExplorerIndex = value; From 256ae5c4b0a49b24f37326ef6a25218581d68aec Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 12:15:33 +0800 Subject: [PATCH 18/73] Fill missing translation --- Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs b/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs index b0851b90c..f6a32e3fe 100644 --- a/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs +++ b/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs @@ -105,7 +105,7 @@ public partial class SelectFileManagerViewModel : BaseModel { CustomExplorers.Add(new() { - Name = "New Profile" + Name = App.API.GetTranslation("defaultBrowser_new_profile") }); SelectedCustomExplorerIndex = CustomExplorers.Count - 1; } From 101750115389e169a491f42c3ece4310165eec3d Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 12:36:40 +0800 Subject: [PATCH 19/73] Fix namespace issue --- .../UserSettings/CustomExplorerViewModel.cs | 2 +- Flow.Launcher.Infrastructure/UserSettings/Settings.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs index 5727f0735..2af0bb0e5 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs @@ -2,7 +2,7 @@ using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Plugin; -namespace Flow.Launcher.ViewModel +namespace Flow.Launcher.Infrastructure.UserSettings { public class CustomExplorerViewModel : BaseModel { diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 23f9047fe..f70c4559b 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -9,7 +9,6 @@ using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels; -using Flow.Launcher.ViewModel; namespace Flow.Launcher.Infrastructure.UserSettings { From b05c2c1e1af62d07a8bd27dc2e9ae409a362df0f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 16:25:21 +0800 Subject: [PATCH 20/73] Remove old dictionaries references to fix possible memory leak --- Flow.Launcher.Core/Resource/Internationalization.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index 8261feab3..e8711819c 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -256,6 +256,7 @@ namespace Flow.Launcher.Core.Resource foreach (var r in _oldResources) { dicts.Remove(r); + _oldResources.Remove(r); } } From 6c695f09e71ef88571c40494747cb08f95e14979 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 17:55:06 +0800 Subject: [PATCH 21/73] Use clear function --- Flow.Launcher.Core/Resource/Internationalization.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index e8711819c..6df2a28c6 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -256,8 +256,8 @@ namespace Flow.Launcher.Core.Resource foreach (var r in _oldResources) { dicts.Remove(r); - _oldResources.Remove(r); } + _oldResources.Clear(); } private void LoadLanguage(Language language) From 330e6c09e7d8321ca268147de4a6490331d92bc0 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 18:07:18 +0800 Subject: [PATCH 22/73] Add language change lock --- .../Resource/Internationalization.cs | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index 6df2a28c6..c1fa2ea16 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -30,6 +30,7 @@ namespace Flow.Launcher.Core.Resource private readonly List _languageDirectories = []; private readonly List _oldResources = []; private static string SystemLanguageCode; + private readonly SemaphoreSlim _langChangeLock = new(1, 1); public Internationalization(Settings settings) { @@ -185,20 +186,29 @@ namespace Flow.Launcher.Core.Resource private async Task ChangeLanguageAsync(Language language, bool updateMetadata = true) { - // Remove old language files and load language - RemoveOldLanguageFiles(); - if (language != AvailableLanguages.English) + await _langChangeLock.WaitAsync(); + + try { - LoadLanguage(language); + // Remove old language files and load language + RemoveOldLanguageFiles(); + if (language != AvailableLanguages.English) + { + LoadLanguage(language); + } + + // Change culture info + ChangeCultureInfo(language.LanguageCode); + + if (updateMetadata) + { + // Raise event for plugins after culture is set + await Task.Run(UpdatePluginMetadataTranslations); + } } - - // Change culture info - ChangeCultureInfo(language.LanguageCode); - - if (updateMetadata) + finally { - // Raise event for plugins after culture is set - await Task.Run(UpdatePluginMetadataTranslations); + _langChangeLock.Release(); } } From 86581e6a00f0d7806a3e910fa39283c03c0f498b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 18:17:27 +0800 Subject: [PATCH 23/73] Add disposable for internalization --- Flow.Launcher.Core/Resource/Internationalization.cs | 12 +++++++++++- Flow.Launcher/App.xaml.cs | 5 ++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index c1fa2ea16..2e270a20b 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -14,7 +14,7 @@ using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Resource { - public class Internationalization + public class Internationalization : IDisposable { private static readonly string ClassName = nameof(Internationalization); @@ -379,5 +379,15 @@ namespace Flow.Launcher.Core.Resource } #endregion + + #region IDisposable + + public void Dispose() + { + RemoveOldLanguageFiles(); + _langChangeLock.Dispose(); + } + + #endregion } } diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 0360c761e..8ec11e5ff 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -45,6 +45,7 @@ namespace Flow.Launcher private static Settings _settings; private static MainWindow _mainWindow; private readonly MainViewModel _mainVM; + private readonly Internationalization _internationalization; // To prevent two disposals running at the same time. private static readonly object _disposingLock = new(); @@ -107,6 +108,7 @@ namespace Flow.Launcher API = Ioc.Default.GetRequiredService(); _settings.Initialize(); _mainVM = Ioc.Default.GetRequiredService(); + _internationalization = Ioc.Default.GetRequiredService(); } catch (Exception e) { @@ -193,7 +195,7 @@ namespace Flow.Launcher Win32Helper.EnableWin32DarkMode(_settings.ColorScheme); // Initialize language before portable clean up since it needs translations - await Ioc.Default.GetRequiredService().InitializeLanguageAsync(); + await _internationalization.InitializeLanguageAsync(); Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate(); @@ -421,6 +423,7 @@ namespace Flow.Launcher _mainWindow?.Dispatcher.Invoke(_mainWindow.Dispose); _mainVM?.Dispose(); DialogJump.Dispose(); + _internationalization.Dispose(); } API.LogInfo(ClassName, "End Flow Launcher dispose ----------------------------------------------------"); From 0f6245a072f8ad7c7b7fa93b4915d2505c880f0f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 18:18:02 +0800 Subject: [PATCH 24/73] Handle exceptions inside ChangeLanguageAsync to avoid unobserved task crashes --- Flow.Launcher.Core/Resource/Internationalization.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index 2e270a20b..983f8b234 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -206,6 +206,10 @@ namespace Flow.Launcher.Core.Resource await Task.Run(UpdatePluginMetadataTranslations); } } + catch (Exception e) + { + API.LogException(ClassName, $"Failed to change language to <{language.LanguageCode}>", e); + } finally { _langChangeLock.Release(); From fc2e3fec630f98c532ae4525b8a99eddbf3e1314 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 18:29:45 +0800 Subject: [PATCH 25/73] Improve ImageLoader performance --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 64d323de6..598347fd2 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -22,7 +22,7 @@ namespace Flow.Launcher.Infrastructure.Image private static Lock storageLock { get; } = new(); private static BinaryStorage> _storage; private static readonly ConcurrentDictionary GuidToKey = new(); - private static IImageHashGenerator _hashGenerator; + private static ImageHashGenerator _hashGenerator; private static readonly bool EnableImageHash = true; public static ImageSource Image => ImageCache[Constant.ImageIcon, false]; public static ImageSource MissingImage => ImageCache[Constant.MissingImgIcon, false]; @@ -31,7 +31,7 @@ namespace Flow.Launcher.Infrastructure.Image 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[] ImageExtensions = [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".ico"]; private static readonly string SvgExtension = ".svg"; public static async Task InitializeAsync() @@ -327,7 +327,7 @@ namespace Flow.Launcher.Infrastructure.Image return img; } - private static ImageSource LoadFullImage(string path) + private static BitmapImage LoadFullImage(string path) { BitmapImage image = new BitmapImage(); image.BeginInit(); @@ -364,7 +364,7 @@ namespace Flow.Launcher.Infrastructure.Image return image; } - private static ImageSource LoadSvgImage(string path, bool loadFullImage = false) + private static RenderTargetBitmap LoadSvgImage(string path, bool loadFullImage = false) { // Set up drawing settings var desiredHeight = loadFullImage ? FullImageSize : SmallIconSize; From 9a597f2b4d1e3928c849b28de3d0b1b6cd7d84c8 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 18:32:13 +0800 Subject: [PATCH 26/73] Disable cache feature --- Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index fd04b3e88..fe0ff39ad 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -15,8 +15,9 @@ public static class WallpaperPathRetrieval { private static readonly string ClassName = nameof(WallpaperPathRetrieval); - private const int MaxCacheSize = 3; - private static readonly Dictionary<(string, DateTime), ImageBrush> WallpaperCache = new(); + // Disable cache feature because some wallpaper applications (like Wallpaper Engine) may change wallpaper frequently + private const int MaxCacheSize = 0;//3; + private static readonly Dictionary<(string, DateTime), ImageBrush> WallpaperCache = []; private static readonly Lock CacheLock = new(); public static Brush GetWallpaperBrush() From 35a5e27e2d10f19b1f689e989d4efbf92d28a78f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 19:15:22 +0800 Subject: [PATCH 27/73] Fix DirectoryNotFoundException when deleting cache twice --- .../ViewModels/SettingsPaneAboutViewModel.cs | 59 ++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index 1efc89972..5e24b9dc8 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -231,36 +231,41 @@ public partial class SettingsPaneAboutViewModel : BaseModel } }); - // Firstly, delete plugin cache directories - pluginCacheDirectory.EnumerateDirectories("*", SearchOption.TopDirectoryOnly) - .ToList() - .ForEach(dir => + // Check if plugin cache directory exists before attempting to delete + // Or it will throw DirectoryNotFoundException in `pluginCacheDirectory.EnumerateDirectories` + if (pluginCacheDirectory.Exists) + { + // Firstly, delete plugin cache directories + pluginCacheDirectory.EnumerateDirectories("*", SearchOption.TopDirectoryOnly) + .ToList() + .ForEach(dir => + { + try + { + // Plugin may create directories in its cache directory + dir.Delete(recursive: true); + } + catch (Exception e) + { + App.API.LogException(ClassName, $"Failed to delete cache directory: {dir.Name}", e); + success = false; + } + }); + + // Then, delete plugin directory + var dir = pluginCacheDirectory; + try { - try - { - // Plugin may create directories in its cache directory - dir.Delete(recursive: true); - } - catch (Exception e) - { - App.API.LogException(ClassName, $"Failed to delete cache directory: {dir.Name}", e); - success = false; - } - }); + dir.Delete(recursive: false); + } + catch (Exception e) + { + App.API.LogException(ClassName, $"Failed to delete cache directory: {dir.Name}", e); + success = false; + } - // Then, delete plugin directory - var dir = GetPluginCacheDir(); - try - { - dir.Delete(recursive: false); + OnPropertyChanged(nameof(CacheFolderSize)); } - catch (Exception e) - { - App.API.LogException(ClassName, $"Failed to delete cache directory: {dir.Name}", e); - success = false; - } - - OnPropertyChanged(nameof(CacheFolderSize)); return success; } From ec182ade398544605da0a90bc7afadf65ef575be Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 19:18:11 +0800 Subject: [PATCH 28/73] Fix property changed event --- .../SettingPages/ViewModels/SettingsPaneAboutViewModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index 5e24b9dc8..7a6a1d91b 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -263,10 +263,10 @@ public partial class SettingsPaneAboutViewModel : BaseModel App.API.LogException(ClassName, $"Failed to delete cache directory: {dir.Name}", e); success = false; } - - OnPropertyChanged(nameof(CacheFolderSize)); } + OnPropertyChanged(nameof(CacheFolderSize)); + return success; } From 4bea4101a1c5a7e13f8befa7ef33b0bafe98e1e7 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Thu, 18 Sep 2025 21:40:37 +1000 Subject: [PATCH 29/73] add comment for cache folder size refresh event --- .../SettingPages/ViewModels/SettingsPaneAboutViewModel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index 7a6a1d91b..647b36701 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -265,6 +265,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel } } + // Raise regardless to cover scenario where size needs to be recalculated if the folder is manually removed on disk. OnPropertyChanged(nameof(CacheFolderSize)); return success; From 7a5e55e5f0b5f96a29e67cefab6a6dec63463ba6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 21:06:18 +0800 Subject: [PATCH 30/73] Use Debug instead of Info --- Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs index 2ff51ff73..841099dd1 100644 --- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs +++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs @@ -75,7 +75,7 @@ namespace Flow.Launcher.Core.ExternalPlugins } catch (OperationCanceledException) when (token.IsCancellationRequested) { - API.LogInfo(ClassName, $"Fetching from {ManifestFileUrl} was cancelled by caller."); + API.LogDebug(ClassName, $"Fetching from {ManifestFileUrl} was cancelled by caller."); return null; } catch (TaskCanceledException) From 245c492906aad3cd138b501363e9cdee914c484d Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 21:13:12 +0800 Subject: [PATCH 31/73] Improve code quality --- Flow.Launcher/ViewModel/PluginViewModel.cs | 48 ++++++++++++---------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 59bb53a4a..c42791e8f 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -19,6 +19,9 @@ namespace Flow.Launcher.ViewModel private static readonly Settings Settings = Ioc.Default.GetRequiredService(); + private static readonly Thickness SettingPanelMargin = (Thickness)Application.Current.FindResource("SettingPanelMargin"); + private static readonly Thickness SettingPanelItemTopBottomMargin = (Thickness)Application.Current.FindResource("SettingPanelItemTopBottomMargin"); + private readonly PluginPair _pluginPair; public PluginPair PluginPair { @@ -139,8 +142,6 @@ namespace Flow.Launcher.ViewModel : null; private ImageSource _image = ImageLoader.MissingImage; - private static readonly Thickness SettingPanelMargin = (Thickness)Application.Current.FindResource("SettingPanelMargin"); - private static readonly Thickness SettingPanelItemTopBottomMargin = (Thickness)Application.Current.FindResource("SettingPanelItemTopBottomMargin"); private static Control TryCreateSettingPanel(PluginPair pair) { try @@ -156,25 +157,7 @@ namespace Flow.Launcher.ViewModel // Show error message in UI var errorMsg = string.Format(App.API.GetTranslation("errorCreatingSettingPanel"), pair.Metadata.Name, Environment.NewLine, e.Message); - var grid = new Grid() - { - Margin = SettingPanelMargin - }; - var textBox = new TextBox - { - Text = errorMsg, - IsReadOnly = true, - HorizontalAlignment = HorizontalAlignment.Stretch, - VerticalAlignment = VerticalAlignment.Top, - TextWrapping = TextWrapping.Wrap, - Margin = SettingPanelItemTopBottomMargin - }; - textBox.SetResourceReference(TextBlock.ForegroundProperty, "Color04B"); - grid.Children.Add(textBox); - return new UserControl - { - Content = grid - }; + return CreateErrorSettingPanel(errorMsg); } } @@ -228,5 +211,28 @@ namespace Flow.Launcher.ViewModel var changeKeywordsWindow = new ActionKeywords(this); changeKeywordsWindow.ShowDialog(); } + + private static UserControl CreateErrorSettingPanel(string text) + { + var grid = new Grid() + { + Margin = SettingPanelMargin + }; + var textBox = new TextBox + { + Text = text, + IsReadOnly = true, + HorizontalAlignment = HorizontalAlignment.Stretch, + VerticalAlignment = VerticalAlignment.Top, + TextWrapping = TextWrapping.Wrap, + Margin = SettingPanelItemTopBottomMargin + }; + textBox.SetResourceReference(TextBlock.ForegroundProperty, "Color04B"); + grid.Children.Add(textBox); + return new UserControl + { + Content = grid + }; + } } } From 72dae631fe8c3fd8e9cd7c466c3481be8ae3da7a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 21:19:49 +0800 Subject: [PATCH 32/73] Use TextBox.ForegroundProperty --- Flow.Launcher/ViewModel/PluginViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index c42791e8f..29f2b9b43 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -227,7 +227,7 @@ namespace Flow.Launcher.ViewModel TextWrapping = TextWrapping.Wrap, Margin = SettingPanelItemTopBottomMargin }; - textBox.SetResourceReference(TextBlock.ForegroundProperty, "Color04B"); + textBox.SetResourceReference(TextBox.ForegroundProperty, "Color04B"); grid.Children.Add(textBox); return new UserControl { From bbc12ec04123b7006b902001e860d9c78da4ef0d Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 18 Sep 2025 21:45:24 +0800 Subject: [PATCH 33/73] Revert "Disable cache feature" This reverts commit 9a597f2b4d1e3928c849b28de3d0b1b6cd7d84c8. --- Flow.Launcher/Helper/WallpaperPathRetrieval.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index fe0ff39ad..fd04b3e88 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -15,9 +15,8 @@ public static class WallpaperPathRetrieval { private static readonly string ClassName = nameof(WallpaperPathRetrieval); - // Disable cache feature because some wallpaper applications (like Wallpaper Engine) may change wallpaper frequently - private const int MaxCacheSize = 0;//3; - private static readonly Dictionary<(string, DateTime), ImageBrush> WallpaperCache = []; + private const int MaxCacheSize = 3; + private static readonly Dictionary<(string, DateTime), ImageBrush> WallpaperCache = new(); private static readonly Lock CacheLock = new(); public static Brush GetWallpaperBrush() From 78e5bf2a601e30c41a7aaaf4428bfd7822f36a93 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 21 Sep 2025 11:50:51 +0800 Subject: [PATCH 34/73] Use Flow.Launcher.Localization to improve code quality --- ...low.Launcher.Plugin.BrowserBookmark.csproj | 2 +- .../Flow.Launcher.Plugin.Calculator.csproj | 2 +- .../ContextMenu.cs | 114 ++++++++---------- .../Flow.Launcher.Plugin.Explorer.csproj | 2 +- .../Languages/en.xaml | 1 + Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 4 +- .../Everything/EverythingDownloadHelper.cs | 15 ++- .../Everything/EverythingSearchManager.cs | 14 +-- .../Search/ResultManager.cs | 29 ++--- .../Search/SearchManager.cs | 4 +- .../WindowsIndex/WindowsIndexSearchManager.cs | 4 +- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 9 +- .../ViewModels/SettingsViewModel.cs | 12 +- .../Views/ActionKeywordSetting.xaml.cs | 12 +- .../Views/PreviewPanel.xaml.cs | 59 +++++---- .../Views/QuickAccessLinkSettings.xaml.cs | 4 +- 16 files changed, 134 insertions(+), 153 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 9cb2469d9..e3233f73d 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -104,7 +104,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 b3cee425d..20a0ec4f0 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,7 @@ - + diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs index 3802c701b..90db87966 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs @@ -66,8 +66,8 @@ namespace Flow.Launcher.Plugin.Explorer { contextMenus.Add(new Result { - Title = Context.API.GetTranslation("plugin_explorer_add_to_quickaccess_title"), - SubTitle = Context.API.GetTranslation("plugin_explorer_add_to_quickaccess_subtitle"), + Title = Localize.plugin_explorer_add_to_quickaccess_title(), + SubTitle = Localize.plugin_explorer_add_to_quickaccess_subtitle(), Action = (context) => { Settings.QuickAccessLinks.Add(new AccessLink @@ -77,16 +77,14 @@ namespace Flow.Launcher.Plugin.Explorer Type = record.Type }); - Context.API.ShowMsg(Context.API.GetTranslation("plugin_explorer_addfilefoldersuccess"), - Context.API.GetTranslation("plugin_explorer_addfilefoldersuccess_detail"), - Constants.ExplorerIconImageFullPath); - - + Context.API.ShowMsg(Localize.plugin_explorer_addfilefoldersuccess(), + Localize.plugin_explorer_addfilefoldersuccess_detail(), + Constants.ExplorerIconImageFullPath); return true; }, - SubTitleToolTip = Context.API.GetTranslation("plugin_explorer_contextmenu_titletooltip"), - TitleToolTip = Context.API.GetTranslation("plugin_explorer_contextmenu_titletooltip"), + SubTitleToolTip = Localize.plugin_explorer_contextmenu_titletooltip(), + TitleToolTip = Localize.plugin_explorer_contextmenu_titletooltip(), IcoPath = Constants.QuickAccessImagePath, Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\ue718"), }); @@ -95,22 +93,20 @@ namespace Flow.Launcher.Plugin.Explorer { contextMenus.Add(new Result { - Title = Context.API.GetTranslation("plugin_explorer_remove_from_quickaccess_title"), - SubTitle = Context.API.GetTranslation("plugin_explorer_remove_from_quickaccess_subtitle"), + Title = Localize.plugin_explorer_remove_from_quickaccess_title(), + SubTitle = Localize.plugin_explorer_remove_from_quickaccess_subtitle(), Action = (context) => { Settings.QuickAccessLinks.Remove(Settings.QuickAccessLinks.FirstOrDefault(x => string.Equals(x.Path, record.FullPath, StringComparison.OrdinalIgnoreCase))); - Context.API.ShowMsg(Context.API.GetTranslation("plugin_explorer_removefilefoldersuccess"), - Context.API.GetTranslation("plugin_explorer_removefilefoldersuccess_detail"), - Constants.ExplorerIconImageFullPath); - - + Context.API.ShowMsg(Localize.plugin_explorer_removefilefoldersuccess(), + Localize.plugin_explorer_removefilefoldersuccess_detail(), + Constants.ExplorerIconImageFullPath); return true; }, - SubTitleToolTip = Context.API.GetTranslation("plugin_explorer_contextmenu_remove_titletooltip"), - TitleToolTip = Context.API.GetTranslation("plugin_explorer_contextmenu_remove_titletooltip"), + SubTitleToolTip = Localize.plugin_explorer_contextmenu_remove_titletooltip(), + TitleToolTip = Localize.plugin_explorer_contextmenu_remove_titletooltip(), IcoPath = Constants.RemoveQuickAccessImagePath, Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uecc9") }); @@ -118,8 +114,8 @@ namespace Flow.Launcher.Plugin.Explorer contextMenus.Add(new Result { - Title = Context.API.GetTranslation("plugin_explorer_copypath"), - SubTitle = Context.API.GetTranslation("plugin_explorer_copypath_subtitle"), + Title = Localize.plugin_explorer_copypath(), + SubTitle = Localize.plugin_explorer_copypath_subtitle(), Action = _ => { try @@ -130,7 +126,7 @@ namespace Flow.Launcher.Plugin.Explorer catch (Exception e) { LogException("Fail to set text in clipboard", e); - Context.API.ShowMsgError(Context.API.GetTranslation("plugin_explorer_fail_to_set_text")); + Context.API.ShowMsgError(Localize.plugin_explorer_fail_to_set_text()); return false; } }, @@ -140,8 +136,8 @@ namespace Flow.Launcher.Plugin.Explorer contextMenus.Add(new Result { - Title = Context.API.GetTranslation("plugin_explorer_copyname"), - SubTitle = Context.API.GetTranslation("plugin_explorer_copyname_subtitle"), + Title = Localize.plugin_explorer_copyname(), + SubTitle = Localize.plugin_explorer_copyname_subtitle(), Action = _ => { try @@ -152,7 +148,7 @@ namespace Flow.Launcher.Plugin.Explorer catch (Exception e) { LogException("Fail to set text in clipboard", e); - Context.API.ShowMsgError(Context.API.GetTranslation("plugin_explorer_fail_to_set_text")); + Context.API.ShowMsgError(Localize.plugin_explorer_fail_to_set_text()); return false; } }, @@ -162,8 +158,8 @@ namespace Flow.Launcher.Plugin.Explorer contextMenus.Add(new Result { - Title = Context.API.GetTranslation("plugin_explorer_copyfilefolder"), - SubTitle = isFile ? Context.API.GetTranslation("plugin_explorer_copyfile_subtitle") : Context.API.GetTranslation("plugin_explorer_copyfolder_subtitle"), + Title = Localize.plugin_explorer_copyfilefolder(), + SubTitle = isFile ? Localize.plugin_explorer_copyfile_subtitle(): Localize.plugin_explorer_copyfolder_subtitle(), Action = _ => { try @@ -174,28 +170,26 @@ namespace Flow.Launcher.Plugin.Explorer catch (Exception e) { LogException($"Fail to set file/folder in clipboard", e); - Context.API.ShowMsgError(Context.API.GetTranslation("plugin_explorer_fail_to_set_files")); + Context.API.ShowMsgError(Localize.plugin_explorer_fail_to_set_files()); return false; } - }, IcoPath = icoPath, Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\uf12b") }); - if (record.Type is ResultType.File or ResultType.Folder) contextMenus.Add(new Result { - Title = Context.API.GetTranslation("plugin_explorer_deletefilefolder"), - SubTitle = isFile ? Context.API.GetTranslation("plugin_explorer_deletefile_subtitle") : Context.API.GetTranslation("plugin_explorer_deletefolder_subtitle"), + Title = Localize.plugin_explorer_deletefilefolder(), + SubTitle = isFile ? Localize.plugin_explorer_deletefile_subtitle(): Localize.plugin_explorer_deletefolder_subtitle(), Action = (context) => { try { if (Context.API.ShowMsgBox( - string.Format(Context.API.GetTranslation("plugin_explorer_delete_folder_link"), record.FullPath), - Context.API.GetTranslation("plugin_explorer_deletefilefolder"), + Localize.plugin_explorer_delete_folder_link(record.FullPath), + Localize.plugin_explorer_deletefilefolder(), MessageBoxButton.OKCancel, MessageBoxImage.Warning) == MessageBoxResult.Cancel) @@ -208,15 +202,15 @@ namespace Flow.Launcher.Plugin.Explorer _ = Task.Run(() => { - Context.API.ShowMsg(Context.API.GetTranslation("plugin_explorer_deletefilefoldersuccess"), - string.Format(Context.API.GetTranslation("plugin_explorer_deletefilefoldersuccess_detail"), record.FullPath), + Context.API.ShowMsg(Localize.plugin_explorer_deletefilefoldersuccess(), + Localize.plugin_explorer_deletefilefoldersuccess_detail(record.FullPath), Constants.ExplorerIconImageFullPath); }); } catch (Exception e) { LogException($"Fail to delete {record.FullPath}", e); - Context.API.ShowMsgError(string.Format(Context.API.GetTranslation("plugin_explorer_fail_to_delete"), record.FullPath)); + Context.API.ShowMsgError(Localize.plugin_explorer_fail_to_delete(record.FullPath)); return false; } @@ -230,7 +224,7 @@ namespace Flow.Launcher.Plugin.Explorer { contextMenus.Add(new Result() { - Title = Context.API.GetTranslation("plugin_explorer_show_contextmenu_title"), + Title = Localize.plugin_explorer_show_contextmenu_title(), IcoPath = Constants.ShowContextMenuImagePath, Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\ue700"), Action = _ => @@ -248,8 +242,8 @@ namespace Flow.Launcher.Plugin.Explorer if (record.Type == ResultType.File && CanRunAsDifferentUser(record.FullPath)) contextMenus.Add(new Result { - Title = Context.API.GetTranslation("plugin_explorer_runasdifferentuser"), - SubTitle = Context.API.GetTranslation("plugin_explorer_runasdifferentuser_subtitle"), + Title = Localize.plugin_explorer_runasdifferentuser(), + SubTitle = Localize.plugin_explorer_runasdifferentuser_subtitle(), Action = (context) => { try @@ -259,8 +253,8 @@ namespace Flow.Launcher.Plugin.Explorer catch (FileNotFoundException e) { Context.API.ShowMsgError( - Context.API.GetTranslation("plugin_explorer_plugin_name"), - string.Format(Context.API.GetTranslation("plugin_explorer_file_not_found"), e.Message)); + Localize.plugin_explorer_plugin_name(), + Localize.plugin_explorer_file_not_found(e.Message)); return false; } @@ -317,8 +311,8 @@ namespace Flow.Launcher.Plugin.Explorer { return new Result { - Title = Context.API.GetTranslation("plugin_explorer_opencontainingfolder"), - SubTitle = Context.API.GetTranslation("plugin_explorer_opencontainingfolder_subtitle"), + Title = Localize.plugin_explorer_opencontainingfolder(), + SubTitle = Localize.plugin_explorer_opencontainingfolder_subtitle(), Action = _ => { try @@ -328,7 +322,7 @@ namespace Flow.Launcher.Plugin.Explorer catch (Exception e) { LogException($"Fail to open file at {record.FullPath}", e); - Context.API.ShowMsgError(string.Format(Context.API.GetTranslation("plugin_explorer_fail_to_open"), record.FullPath)); + Context.API.ShowMsgError(Localize.plugin_explorer_fail_to_open(record.FullPath)); return false; } @@ -339,11 +333,9 @@ namespace Flow.Launcher.Plugin.Explorer }; } - - private Result CreateOpenWithEditorResult(SearchResult record, string editorPath) { - var name = $"{Context.API.GetTranslation("plugin_explorer_openwitheditor")} {Path.GetFileNameWithoutExtension(editorPath)}"; + var name = $"{Localize.plugin_explorer_openwitheditor()} {Path.GetFileNameWithoutExtension(editorPath)}"; return new Result { @@ -361,8 +353,7 @@ namespace Flow.Launcher.Plugin.Explorer } catch (Exception e) { - var raw_message = Context.API.GetTranslation("plugin_explorer_openwitheditor_error"); - var message = string.Format(raw_message, record.FullPath, Path.GetFileNameWithoutExtension(editorPath), editorPath); + var message = Localize.plugin_explorer_openwitheditor_error(record.FullPath, Path.GetFileNameWithoutExtension(editorPath), editorPath); LogException(message, e); Context.API.ShowMsgError(message); return false; @@ -377,7 +368,7 @@ namespace Flow.Launcher.Plugin.Explorer { string shellPath = Settings.ShellPath; - var name = $"{Context.API.GetTranslation("plugin_explorer_openwithshell")} {Path.GetFileNameWithoutExtension(shellPath)}"; + var name = $"{Localize.plugin_explorer_openwithshell()} {Path.GetFileNameWithoutExtension(shellPath)}"; return new Result { @@ -394,8 +385,7 @@ namespace Flow.Launcher.Plugin.Explorer } catch (Exception e) { - var raw_message = Context.API.GetTranslation("plugin_explorer_openwithshell_error"); - var message = string.Format(raw_message, record.FullPath, Path.GetFileNameWithoutExtension(shellPath), shellPath); + var message = Localize.plugin_explorer_openwithshell_error(record.FullPath, Path.GetFileNameWithoutExtension(shellPath), shellPath); LogException(message, e); Context.API.ShowMsgError(message); return false; @@ -410,8 +400,8 @@ namespace Flow.Launcher.Plugin.Explorer { return new Result { - Title = Context.API.GetTranslation("plugin_explorer_excludefromindexsearch"), - SubTitle = Context.API.GetTranslation("plugin_explorer_path") + " " + record.FullPath, + Title = Localize.plugin_explorer_excludefromindexsearch(), + SubTitle = Localize.plugin_explorer_path()+ " " + record.FullPath, Action = c_ => { if (!Settings.IndexSearchExcludedSubdirectoryPaths.Any(x => string.Equals(x.Path, record.FullPath, StringComparison.OrdinalIgnoreCase))) @@ -422,8 +412,8 @@ namespace Flow.Launcher.Plugin.Explorer _ = Task.Run(() => { - Context.API.ShowMsg(Context.API.GetTranslation("plugin_explorer_excludedfromindexsearch_msg"), - Context.API.GetTranslation("plugin_explorer_path") + + Context.API.ShowMsg(Localize.plugin_explorer_excludedfromindexsearch_msg(), + Localize.plugin_explorer_path()+ " " + record.FullPath, Constants.ExplorerIconImageFullPath); // so the new path can be persisted to storage and not wait till next ViewModel save. @@ -441,8 +431,8 @@ namespace Flow.Launcher.Plugin.Explorer { return new Result { - Title = Context.API.GetTranslation("plugin_explorer_openindexingoptions"), - SubTitle = Context.API.GetTranslation("plugin_explorer_openindexingoptions_subtitle"), + Title = Localize.plugin_explorer_openindexingoptions(), + SubTitle = Localize.plugin_explorer_openindexingoptions_subtitle(), Action = _ => { try @@ -459,7 +449,7 @@ namespace Flow.Launcher.Plugin.Explorer } catch (Exception e) { - var message = Context.API.GetTranslation("plugin_explorer_openindexingoptions_errormsg"); + var message = Localize.plugin_explorer_openindexingoptions_errormsg(); LogException(message, e); Context.API.ShowMsgError(message); return false; @@ -470,12 +460,12 @@ namespace Flow.Launcher.Plugin.Explorer }; } - private Result CreateOpenWithMenu(SearchResult record) + private static Result CreateOpenWithMenu(SearchResult record) { return new Result { - Title = Context.API.GetTranslation("plugin_explorer_openwith"), - SubTitle = Context.API.GetTranslation("plugin_explorer_openwith_subtitle"), + Title = Localize.plugin_explorer_openwith(), + SubTitle = Localize.plugin_explorer_openwith_subtitle(), Action = _ => { Process.Start("rundll32.exe", $"{Path.Combine(Environment.SystemDirectory, "shell32.dll")},OpenAs_RunDLL {record.FullPath}"); 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 b7c54e578..a837a49b4 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -48,7 +48,7 @@ - + diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index 16ef037cc..c40040df5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -24,6 +24,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Delete diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index d93c6c77b..f5b8b9325 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -90,12 +90,12 @@ namespace Flow.Launcher.Plugin.Explorer public string GetTranslatedPluginTitle() { - return Context.API.GetTranslation("plugin_explorer_plugin_name"); + return Localize.plugin_explorer_plugin_name(); } public string GetTranslatedPluginDescription() { - return Context.API.GetTranslation("plugin_explorer_plugin_description"); + return Localize.plugin_explorer_plugin_description(); } public void OnCultureInfoChanged(CultureInfo newCulture) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingDownloadHelper.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingDownloadHelper.cs index c8bd68279..13d988f1a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingDownloadHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingDownloadHelper.cs @@ -21,9 +21,9 @@ public static class EverythingDownloadHelper if (string.IsNullOrEmpty(installedLocation)) { if (api.ShowMsgBox( - string.Format(api.GetTranslation("flowlauncher_plugin_everything_installing_select"), Environment.NewLine), - api.GetTranslation("flowlauncher_plugin_everything_installing_title"), - MessageBoxButton.YesNo) == MessageBoxResult.Yes) + Localize.flowlauncher_plugin_everything_installing_select(Environment.NewLine), + Localize.flowlauncher_plugin_everything_installing_title(), + MessageBoxButton.YesNo) == MessageBoxResult.Yes) { var dlg = new System.Windows.Forms.OpenFileDialog { @@ -41,13 +41,13 @@ public static class EverythingDownloadHelper return installedLocation; } - api.ShowMsg(api.GetTranslation("flowlauncher_plugin_everything_installing_title"), - api.GetTranslation("flowlauncher_plugin_everything_installing_subtitle"), "", useMainWindowAsOwner: false); + api.ShowMsg(Localize.flowlauncher_plugin_everything_installing_title(), + Localize.flowlauncher_plugin_everything_installing_subtitle(), "", useMainWindowAsOwner: false); await DroplexPackage.Drop(App.Everything1_4_1_1009).ConfigureAwait(false); - api.ShowMsg(api.GetTranslation("flowlauncher_plugin_everything_installing_title"), - api.GetTranslation("flowlauncher_plugin_everything_installationsuccess_subtitle"), "", useMainWindowAsOwner: false); + api.ShowMsg(Localize.flowlauncher_plugin_everything_installing_title(), + Localize.flowlauncher_plugin_everything_installationsuccess_subtitle(), "", useMainWindowAsOwner: false); installedLocation = "C:\\Program Files\\Everything\\Everything.exe"; @@ -83,6 +83,5 @@ public static class EverythingDownloadHelper var scoopInstalledPath = Environment.ExpandEnvironmentVariables(@"%userprofile%\scoop\apps\everything\current\Everything.exe"); return File.Exists(scoopInstalledPath) ? scoopInstalledPath : string.Empty; - } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs index ce71c94ba..eb994a6f9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs @@ -27,8 +27,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything if (!await EverythingApi.IsEverythingRunningAsync(token)) throw new EngineNotAvailableException( Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, - Main.Context.API.GetTranslation("flowlauncher_plugin_everything_click_to_launch_or_install"), - Main.Context.API.GetTranslation("flowlauncher_plugin_everything_is_not_running"), + Localize.flowlauncher_plugin_everything_click_to_launch_or_install(), + Localize.flowlauncher_plugin_everything_is_not_running(), Constants.EverythingErrorImagePath, ClickToInstallEverythingAsync); } @@ -38,7 +38,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, "Please check whether your system is x86 or x64", Constants.GeneralSearchErrorImagePath, - Main.Context.API.GetTranslation("flowlauncher_plugin_everything_sdk_issue")); + Localize.flowlauncher_plugin_everything_sdk_issue()); } } @@ -50,7 +50,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything if (installedPath == null) { - Main.Context.API.ShowMsgError(Main.Context.API.GetTranslation("flowlauncher_plugin_everything_not_found")); + Main.Context.API.ShowMsgError(Localize.flowlauncher_plugin_everything_not_found()); Main.Context.API.LogError(ClassName, "Unable to find Everything.exe"); return false; @@ -65,7 +65,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything // Just let the user know that Everything is not installed properly and ask them to install it manually catch (Exception e) { - Main.Context.API.ShowMsgError(Main.Context.API.GetTranslation("flowlauncher_plugin_everything_install_issue")); + Main.Context.API.ShowMsgError(Localize.flowlauncher_plugin_everything_install_issue()); Main.Context.API.LogException(ClassName, "Failed to install Everything", e); return false; @@ -97,8 +97,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything if (!Settings.EnableEverythingContentSearch) { throw new EngineNotAvailableException(Enum.GetName(Settings.IndexSearchEngineOption.Everything)!, - Main.Context.API.GetTranslation("flowlauncher_plugin_everything_enable_content_search"), - Main.Context.API.GetTranslation("flowlauncher_plugin_everything_enable_content_search_tips"), + Localize.flowlauncher_plugin_everything_enable_content_search(), + Localize.flowlauncher_plugin_everything_enable_content_search_tips(), Constants.EverythingErrorImagePath, _ => { diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs index dfa2c8d43..18eb168b9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -124,7 +124,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search } catch (Exception ex) { - Context.API.ShowMsgBox(ex.Message, Context.API.GetTranslation("plugin_explorer_opendir_error")); + Context.API.ShowMsgBox(ex.Message, Localize.plugin_explorer_opendir_error()); return false; } } @@ -138,7 +138,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search } catch (Exception ex) { - Context.API.ShowMsgBox(ex.Message, Context.API.GetTranslation("plugin_explorer_opendir_error")); + Context.API.ShowMsgBox(ex.Message, Localize.plugin_explorer_opendir_error()); return false; } } @@ -153,7 +153,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search } catch (Exception ex) { - Context.API.ShowMsgBox(ex.Message, Context.API.GetTranslation("plugin_explorer_opendir_error")); + Context.API.ShowMsgBox(ex.Message, Localize.plugin_explorer_opendir_error()); return false; } } @@ -166,7 +166,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search return false; }, Score = score, - TitleToolTip = Main.Context.API.GetTranslation("plugin_explorer_plugin_ToolTipOpenDirectory"), + TitleToolTip = Localize.plugin_explorer_plugin_ToolTipOpenDirectory(), SubTitleToolTip = Settings.DisplayMoreInformationInToolTip ? GetFolderMoreInfoTooltip(path) : path, ContextData = new SearchResult { Type = ResultType.Folder, FullPath = path, WindowsIndexed = windowsIndexed } }; @@ -190,7 +190,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search DriveInfo drv = new DriveInfo(driveLetter); var freespace = ToReadableSize(drv.AvailableFreeSpace, 2); var totalspace = ToReadableSize(drv.TotalSize, 2); - var subtitle = string.Format(Context.API.GetTranslation("plugin_explorer_diskfreespace"), freespace, totalspace); + var subtitle = Localize.plugin_explorer_diskfreespace(freespace, totalspace); double usingSize = (Convert.ToDouble(drv.TotalSize) - Convert.ToDouble(drv.AvailableFreeSpace)) / Convert.ToDouble(drv.TotalSize) * 100; int? progressValue = Convert.ToInt32(usingSize); @@ -262,8 +262,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search return new Result { - Title = Context.API.GetTranslation("plugin_explorer_openresultfolder"), - SubTitle = Context.API.GetTranslation("plugin_explorer_openresultfolder_subtitle"), + Title = Localize.plugin_explorer_openresultfolder(), + SubTitle = Localize.plugin_explorer_openresultfolder_subtitle(), AutoCompleteText = GetPathWithActionKeyword(folderPath, ResultType.Folder, actionKeyword), IcoPath = folderPath, Score = 500, @@ -330,12 +330,12 @@ namespace Flow.Launcher.Plugin.Explorer.Search } catch (Exception ex) { - Context.API.ShowMsgBox(ex.Message, Context.API.GetTranslation("plugin_explorer_openfile_error")); + Context.API.ShowMsgBox(ex.Message, Localize.plugin_explorer_openfile_error()); } return true; }, - TitleToolTip = Main.Context.API.GetTranslation("plugin_explorer_plugin_ToolTipOpenContainingFolder"), + TitleToolTip = Localize.plugin_explorer_plugin_ToolTipOpenContainingFolder(), SubTitleToolTip = Settings.DisplayMoreInformationInToolTip ? GetFileMoreInfoTooltip(filePath) : filePath, ContextData = new SearchResult { Type = ResultType.File, FullPath = filePath, WindowsIndexed = windowsIndexed } }; @@ -374,8 +374,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search var fileSize = PreviewPanel.GetFileSize(filePath); var fileCreatedAt = PreviewPanel.GetFileCreatedAt(filePath, Settings.PreviewPanelDateFormat, Settings.PreviewPanelTimeFormat, Settings.ShowFileAgeInPreviewPanel); var fileModifiedAt = PreviewPanel.GetFileLastModifiedAt(filePath, Settings.PreviewPanelDateFormat, Settings.PreviewPanelTimeFormat, Settings.ShowFileAgeInPreviewPanel); - return string.Format(Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info"), - filePath, fileSize, fileCreatedAt, fileModifiedAt, Environment.NewLine); + return Localize.plugin_explorer_plugin_tooltip_more_info(filePath, fileSize, fileCreatedAt, fileModifiedAt, Environment.NewLine); } catch (Exception e) { @@ -391,8 +390,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search var folderSize = PreviewPanel.GetFolderSize(folderPath); var folderCreatedAt = PreviewPanel.GetFolderCreatedAt(folderPath, Settings.PreviewPanelDateFormat, Settings.PreviewPanelTimeFormat, Settings.ShowFileAgeInPreviewPanel); var folderModifiedAt = PreviewPanel.GetFolderLastModifiedAt(folderPath, Settings.PreviewPanelDateFormat, Settings.PreviewPanelTimeFormat, Settings.ShowFileAgeInPreviewPanel); - return string.Format(Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info"), - folderPath, folderSize, folderCreatedAt, folderModifiedAt, Environment.NewLine); + return Localize.plugin_explorer_plugin_tooltip_more_info(folderPath, folderSize, folderCreatedAt, folderModifiedAt, Environment.NewLine); } catch (Exception e) { @@ -403,8 +401,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search private static string GetVolumeMoreInfoTooltip(string volumePath, string freespace, string totalspace) { - return string.Format(Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_volume"), - volumePath, freespace, totalspace, Environment.NewLine); + return Localize.plugin_explorer_plugin_tooltip_more_info_volume(volumePath, freespace, totalspace, Environment.NewLine); } private static readonly string[] MediaExtensions = diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index f4f87d4d4..f9d8963e6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -161,8 +161,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search { new() { - Title = Context.API.GetTranslation("flowlauncher_plugin_everything_enable_content_search"), - SubTitle = Context.API.GetTranslation("flowlauncher_plugin_everything_enable_content_search_tips"), + Title = Localize.flowlauncher_plugin_everything_enable_content_search(), + SubTitle = Localize.flowlauncher_plugin_everything_enable_content_search_tips(), IcoPath = "Images/index_error.png", Action = c => { diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs index 3d69a1ee6..eeb5c2c4a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs @@ -105,8 +105,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex throw new EngineNotAvailableException( "Windows Index", - Main.Context.API.GetTranslation("plugin_explorer_windowsSearchServiceFix"), - Main.Context.API.GetTranslation("plugin_explorer_windowsSearchServiceNotRunning"), + Localize.plugin_explorer_windowsSearchServiceFix(), + Localize.plugin_explorer_windowsSearchServiceNotRunning(), Constants.WindowsIndexErrorImagePath, c => { diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 672e81d03..8d62531cd 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -14,9 +14,9 @@ namespace Flow.Launcher.Plugin.Explorer { public int MaxResult { get; set; } = 100; - public ObservableCollection QuickAccessLinks { get; set; } = new(); + public ObservableCollection QuickAccessLinks { get; set; } = []; - public ObservableCollection IndexSearchExcludedSubdirectoryPaths { get; set; } = new ObservableCollection(); + public ObservableCollection IndexSearchExcludedSubdirectoryPaths { get; set; } = []; public string EditorPath { get; set; } = ""; @@ -58,7 +58,6 @@ namespace Flow.Launcher.Plugin.Explorer public bool QuickAccessKeywordEnabled { get; set; } - public bool WarnWindowsSearchServiceOff { get; set; } = true; public bool ShowFileSizeInPreviewPanel { get; set; } = true; @@ -69,7 +68,6 @@ namespace Flow.Launcher.Plugin.Explorer public bool ShowFileAgeInPreviewPanel { get; set; } = false; - public string PreviewPanelDateFormat { get; set; } = "yyyy-MM-dd"; public string PreviewPanelTimeFormat { get; set; } = "HH:mm"; @@ -82,8 +80,8 @@ namespace Flow.Launcher.Plugin.Explorer private EverythingSearchManager EverythingManagerInstance => _everythingManagerInstance ??= new EverythingSearchManager(this); private WindowsIndexSearchManager WindowsIndexSearchManager => _windowsIndexSearchManager ??= new WindowsIndexSearchManager(this); - public IndexSearchEngineOption IndexSearchEngine { get; set; } = IndexSearchEngineOption.WindowsIndex; + [JsonIgnore] public IIndexProvider IndexProvider => IndexSearchEngine switch { @@ -139,7 +137,6 @@ namespace Flow.Launcher.Plugin.Explorer #endregion - #region Everything Settings public string EverythingInstalledPath { get; set; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index ae2235c5c..2d46c6307 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -296,7 +296,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels return; } - var actionKeywordWindow = new ActionKeywordSetting(actionKeyword, Context.API); + var actionKeywordWindow = new ActionKeywordSetting(actionKeyword); if (!(actionKeywordWindow.ShowDialog() ?? false)) { @@ -432,8 +432,8 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels case "QuickAccessLink": if (SelectedQuickAccessLink == null) return; if (Context.API.ShowMsgBox( - Context.API.GetTranslation("plugin_explorer_delete_quick_access_link"), - Context.API.GetTranslation("plugin_explorer_delete"), + Localize.plugin_explorer_delete_quick_access_link(), + Localize.plugin_explorer_delete(), MessageBoxButton.OKCancel, MessageBoxImage.Warning) == MessageBoxResult.Cancel) @@ -443,8 +443,8 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels case "IndexSearchExcludedPaths": if (SelectedIndexSearchExcludedPath == null) return; if (Context.API.ShowMsgBox( - Context.API.GetTranslation("plugin_explorer_delete_index_search_excluded_path"), - Context.API.GetTranslation("plugin_explorer_delete"), + Localize.plugin_explorer_delete_index_search_excluded_path(), + Localize.plugin_explorer_delete(), MessageBoxButton.OKCancel, MessageBoxImage.Warning) == MessageBoxResult.Cancel) @@ -457,7 +457,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels private void ShowUnselectedMessage() { - var warning = Context.API.GetTranslation("plugin_explorer_make_selection_warning"); + var warning = Localize.plugin_explorer_make_selection_warning(); Context.API.ShowMsgBox(warning); } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs index 829a2feed..562170062 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml.cs @@ -29,13 +29,11 @@ namespace Flow.Launcher.Plugin.Explorer.Views } private string actionKeyword; - private readonly IPublicAPI _api; private bool _keywordEnabled; - public ActionKeywordSetting(ActionKeywordModel selectedActionKeyword, IPublicAPI api) + public ActionKeywordSetting(ActionKeywordModel selectedActionKeyword) { CurrentActionKeyword = selectedActionKeyword; - _api = api; ActionKeyword = selectedActionKeyword.Keyword; KeywordEnabled = selectedActionKeyword.Enabled; @@ -60,14 +58,14 @@ namespace Flow.Launcher.Plugin.Explorer.Views switch (CurrentActionKeyword.KeywordProperty, KeywordEnabled) { case (Settings.ActionKeyword.FileContentSearchActionKeyword, true): - _api.ShowMsgBox(_api.GetTranslation("plugin_explorer_globalActionKeywordInvalid")); + Main.Context.API.ShowMsgBox(Localize.plugin_explorer_globalActionKeywordInvalid()); return; case (Settings.ActionKeyword.QuickAccessActionKeyword, true): - _api.ShowMsgBox(_api.GetTranslation("plugin_explorer_quickaccess_globalActionKeywordInvalid")); + Main.Context.API.ShowMsgBox(Localize.plugin_explorer_quickaccess_globalActionKeywordInvalid()); return; } - if (!KeywordEnabled || !_api.ActionKeywordAssigned(ActionKeyword)) + if (!KeywordEnabled || !Main.Context.API.ActionKeywordAssigned(ActionKeyword)) { DialogResult = true; Close(); @@ -75,7 +73,7 @@ namespace Flow.Launcher.Plugin.Explorer.Views } // The keyword is not valid, so show message - _api.ShowMsgBox(_api.GetTranslation("newActionKeywordsHasBeenAssigned")); + Main.Context.API.ShowMsgBox(Localize.plugin_explorer_new_action_keyword_assigned()); } private void BtnCancel_OnClick(object sender, RoutedEventArgs e) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs index 4dd0588ee..3c627cc06 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs @@ -25,7 +25,7 @@ public partial class PreviewPanel : UserControl public string FileName { get; } [ObservableProperty] - private string _fileSize = Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + private string _fileSize = Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); [ObservableProperty] private string _createdAt = ""; @@ -111,17 +111,17 @@ public partial class PreviewPanel : UserControl catch (FileNotFoundException) { Main.Context.API.LogError(ClassName, $"File not found: {filePath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (UnauthorizedAccessException) { Main.Context.API.LogError(ClassName, $"Access denied to file: {filePath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (Exception e) { Main.Context.API.LogException(ClassName, $"Failed to get file size for {filePath}", e); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } } @@ -142,17 +142,17 @@ public partial class PreviewPanel : UserControl catch (FileNotFoundException) { Main.Context.API.LogError(ClassName, $"File not found: {filePath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (UnauthorizedAccessException) { Main.Context.API.LogError(ClassName, $"Access denied to file: {filePath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (Exception e) { Main.Context.API.LogException(ClassName, $"Failed to get file created date for {filePath}", e); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } } @@ -173,17 +173,17 @@ public partial class PreviewPanel : UserControl catch (FileNotFoundException) { Main.Context.API.LogError(ClassName, $"File not found: {filePath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (UnauthorizedAccessException) { Main.Context.API.LogError(ClassName, $"Access denied to file: {filePath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (Exception e) { Main.Context.API.LogException(ClassName, $"Failed to get file modified date for {filePath}", e); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } } @@ -205,17 +205,17 @@ public partial class PreviewPanel : UserControl catch (FileNotFoundException) { Main.Context.API.LogError(ClassName, $"Folder not found: {folderPath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (UnauthorizedAccessException) { Main.Context.API.LogError(ClassName, $"Access denied to folder: {folderPath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (OperationCanceledException) { Main.Context.API.LogError(ClassName, $"Operation timed out while calculating folder size for {folderPath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } // For parallel operations, AggregateException may be thrown if any of the tasks fail catch (AggregateException ae) @@ -224,22 +224,22 @@ public partial class PreviewPanel : UserControl { case FileNotFoundException: Main.Context.API.LogError(ClassName, $"Folder not found: {folderPath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); case UnauthorizedAccessException: Main.Context.API.LogError(ClassName, $"Access denied to folder: {folderPath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); case OperationCanceledException: Main.Context.API.LogError(ClassName, $"Operation timed out while calculating folder size for {folderPath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); default: Main.Context.API.LogException(ClassName, $"Failed to get folder size for {folderPath}", ae); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } } catch (Exception e) { Main.Context.API.LogException(ClassName, $"Failed to get folder size for {folderPath}", e); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } } @@ -260,17 +260,17 @@ public partial class PreviewPanel : UserControl catch (FileNotFoundException) { Main.Context.API.LogError(ClassName, $"Folder not found: {folderPath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (UnauthorizedAccessException) { Main.Context.API.LogError(ClassName, $"Access denied to folder: {folderPath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (Exception e) { Main.Context.API.LogException(ClassName, $"Failed to get folder created date for {folderPath}", e); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } } @@ -291,17 +291,17 @@ public partial class PreviewPanel : UserControl catch (FileNotFoundException) { Main.Context.API.LogError(ClassName, $"Folder not found: {folderPath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (UnauthorizedAccessException) { Main.Context.API.LogError(ClassName, $"Access denied to folder: {folderPath}"); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } catch (Exception e) { Main.Context.API.LogException(ClassName, $"Failed to get folder modified date for {folderPath}", e); - return Main.Context.API.GetTranslation("plugin_explorer_plugin_tooltip_more_info_unknown"); + return Localize.plugin_explorer_plugin_tooltip_more_info_unknown(); } } @@ -311,21 +311,20 @@ public partial class PreviewPanel : UserControl var difference = now - fileDateTime; if (difference.TotalDays < 1) - return Main.Context.API.GetTranslation("Today"); + return Localize.Today(); if (difference.TotalDays < 30) - return string.Format(Main.Context.API.GetTranslation("DaysAgo"), (int)difference.TotalDays); + return Localize.DaysAgo((int)difference.TotalDays); var monthsDiff = (now.Year - fileDateTime.Year) * 12 + now.Month - fileDateTime.Month; if (monthsDiff == 1) - return Main.Context.API.GetTranslation("OneMonthAgo"); + return Localize.OneMonthAgo(); if (monthsDiff < 12) - return string.Format(Main.Context.API.GetTranslation("MonthsAgo"), monthsDiff); + return Localize.MonthsAgo(monthsDiff); var yearsDiff = now.Year - fileDateTime.Year; if (now.Month < fileDateTime.Month || (now.Month == fileDateTime.Month && now.Day < fileDateTime.Day)) yearsDiff--; - return yearsDiff == 1 ? Main.Context.API.GetTranslation("OneYearAgo") : - string.Format(Main.Context.API.GetTranslation("YearsAgo"), yearsDiff); + return yearsDiff == 1 ? Localize.OneYearAgo(): Localize.YearsAgo(yearsDiff); } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs index e6294b98b..f8929549b 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs @@ -97,7 +97,7 @@ public partial class QuickAccessLinkSettings // Validate the input before proceeding if (string.IsNullOrEmpty(SelectedName) || string.IsNullOrEmpty(SelectedPath)) { - var warning = Main.Context.API.GetTranslation("plugin_explorer_quick_access_link_no_folder_selected"); + var warning = Localize.plugin_explorer_quick_access_link_no_folder_selected(); Main.Context.API.ShowMsgBox(warning); return; } @@ -107,7 +107,7 @@ public partial class QuickAccessLinkSettings x.Path.Equals(SelectedPath, StringComparison.OrdinalIgnoreCase) && x.Name.Equals(SelectedName, StringComparison.OrdinalIgnoreCase))) { - var warning = Main.Context.API.GetTranslation("plugin_explorer_quick_access_link_path_already_exists"); + var warning = Localize.plugin_explorer_quick_access_link_path_already_exists(); Main.Context.API.ShowMsgBox(warning); return; } From 846cc65d8e01f6b1f4c765c7641d169db2988781 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Sep 2025 04:49:51 +0000 Subject: [PATCH 35/73] Bump Svg.Skia from 3.0.6 to 3.2.1 --- updated-dependencies: - dependency-name: Svg.Skia dependency-version: 3.2.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../Flow.Launcher.Plugin.BrowserBookmark.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e3233f73d..6f058ea24 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -106,7 +106,7 @@ - + From d7e1ad73cc213231bbc31f5a50b1219688577d53 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sun, 21 Sep 2025 21:36:35 +1000 Subject: [PATCH 36/73] New Crowdin updates (#3948) --- Flow.Launcher/Languages/ar.xaml | 8 +- Flow.Launcher/Languages/cs.xaml | 8 +- Flow.Launcher/Languages/da.xaml | 8 +- Flow.Launcher/Languages/de.xaml | 8 +- Flow.Launcher/Languages/es-419.xaml | 8 +- Flow.Launcher/Languages/es.xaml | 16 +- Flow.Launcher/Languages/fr.xaml | 8 +- Flow.Launcher/Languages/he.xaml | 8 +- Flow.Launcher/Languages/it.xaml | 8 +- Flow.Launcher/Languages/ja.xaml | 374 +++++++++--------- Flow.Launcher/Languages/ko.xaml | 8 +- Flow.Launcher/Languages/nb.xaml | 8 +- Flow.Launcher/Languages/nl.xaml | 8 +- Flow.Launcher/Languages/pl.xaml | 8 +- Flow.Launcher/Languages/pt-br.xaml | 8 +- Flow.Launcher/Languages/pt-pt.xaml | 10 +- Flow.Launcher/Languages/ru.xaml | 16 +- Flow.Launcher/Languages/sk.xaml | 62 +-- Flow.Launcher/Languages/sr-Cyrl-RS.xaml | 8 +- Flow.Launcher/Languages/sr.xaml | 8 +- Flow.Launcher/Languages/tr.xaml | 14 +- Flow.Launcher/Languages/uk-UA.xaml | 8 +- Flow.Launcher/Languages/vi.xaml | 8 +- Flow.Launcher/Languages/zh-cn.xaml | 8 +- Flow.Launcher/Languages/zh-tw.xaml | 8 +- .../Languages/ja.xaml | 14 +- .../Languages/ar.xaml | 5 +- .../Languages/cs.xaml | 5 +- .../Languages/da.xaml | 5 +- .../Languages/de.xaml | 5 +- .../Languages/es-419.xaml | 5 +- .../Languages/es.xaml | 5 +- .../Languages/fr.xaml | 5 +- .../Languages/he.xaml | 5 +- .../Languages/it.xaml | 5 +- .../Languages/ja.xaml | 13 +- .../Languages/ko.xaml | 5 +- .../Languages/nb.xaml | 5 +- .../Languages/nl.xaml | 5 +- .../Languages/pl.xaml | 5 +- .../Languages/pt-br.xaml | 5 +- .../Languages/pt-pt.xaml | 5 +- .../Languages/ru.xaml | 5 +- .../Languages/sk.xaml | 5 +- .../Languages/sr-Cyrl-RS.xaml | 3 +- .../Languages/sr.xaml | 5 +- .../Languages/tr.xaml | 5 +- .../Languages/uk-UA.xaml | 5 +- .../Languages/vi.xaml | 5 +- .../Languages/zh-cn.xaml | 5 +- .../Languages/zh-tw.xaml | 5 +- .../Languages/ar.xaml | 1 + .../Languages/cs.xaml | 1 + .../Languages/da.xaml | 1 + .../Languages/de.xaml | 1 + .../Languages/es-419.xaml | 1 + .../Languages/es.xaml | 1 + .../Languages/fr.xaml | 1 + .../Languages/he.xaml | 1 + .../Languages/it.xaml | 1 + .../Languages/ja.xaml | 165 ++++---- .../Languages/ko.xaml | 1 + .../Languages/nb.xaml | 1 + .../Languages/nl.xaml | 1 + .../Languages/pl.xaml | 1 + .../Languages/pt-br.xaml | 1 + .../Languages/pt-pt.xaml | 1 + .../Languages/ru.xaml | 5 +- .../Languages/sk.xaml | 1 + .../Languages/sr-Cyrl-RS.xaml | 1 + .../Languages/sr.xaml | 1 + .../Languages/tr.xaml | 3 +- .../Languages/uk-UA.xaml | 1 + .../Languages/vi.xaml | 1 + .../Languages/zh-cn.xaml | 1 + .../Languages/zh-tw.xaml | 1 + .../Languages/ja.xaml | 6 +- .../Languages/ja.xaml | 110 +++--- .../Languages/ru.xaml | 4 +- .../Languages/sk.xaml | 2 +- .../Languages/ja.xaml | 14 +- .../Languages/ja.xaml | 124 +++--- .../Languages/ja.xaml | 30 +- .../Languages/ja.xaml | 68 ++-- .../Languages/ru.xaml | 4 +- .../Languages/ja.xaml | 10 +- .../Languages/ru.xaml | 4 +- .../Languages/ja.xaml | 45 +-- .../Languages/ru.xaml | 22 +- .../Properties/Resources.ja-JP.resx | 78 ++-- .../Properties/Resources.tr-TR.resx | 88 ++--- 91 files changed, 897 insertions(+), 696 deletions(-) diff --git a/Flow.Launcher/Languages/ar.xaml b/Flow.Launcher/Languages/ar.xaml index 9c252f7a7..b8845c3f5 100644 --- a/Flow.Launcher/Languages/ar.xaml +++ b/Flow.Launcher/Languages/ar.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} متجر الإضافات @@ -467,8 +468,10 @@ فتح المجلد Advanced Log Level - Debug + Silent + خطأ Info + Debug Setting Window Font @@ -490,6 +493,7 @@ حجة للملف The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer متصفح الويب الافتراضي @@ -500,6 +504,8 @@ نافذة جديدة تبويب جديد الوضع الخاص + Default + New Profile تغيير الأولوية diff --git a/Flow.Launcher/Languages/cs.xaml b/Flow.Launcher/Languages/cs.xaml index 57415948f..30a1cdbb9 100644 --- a/Flow.Launcher/Languages/cs.xaml +++ b/Flow.Launcher/Languages/cs.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Obchod s pluginy @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Chyba Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Argumenty pro Soubor The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Výchozí prohlížeč @@ -500,6 +504,8 @@ Nové okno Nová karta Soukromý režim + Default + New Profile Změnit prioritu diff --git a/Flow.Launcher/Languages/da.xaml b/Flow.Launcher/Languages/da.xaml index 363d8de9a..067ea16fc 100644 --- a/Flow.Launcher/Languages/da.xaml +++ b/Flow.Launcher/Languages/da.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Plugin-butik @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg for fil The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Default Web Browser @@ -500,6 +504,8 @@ New Window New Tab Privattilstand + Default + New Profile Skift prioritet diff --git a/Flow.Launcher/Languages/de.xaml b/Flow.Launcher/Languages/de.xaml index fc16826bd..529531b58 100644 --- a/Flow.Launcher/Languages/de.xaml +++ b/Flow.Launcher/Languages/de.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Plug-in-Store @@ -467,8 +468,10 @@ Ordner öffnen Erweitert Log-Ebene - Debug + Silent + Fehler Info + Debug Einstellung der Fensterschriftart @@ -490,6 +493,7 @@ Arg For File Der Dateimanager '{0}' konnte nicht unter '{1}' gefunden werden. Möchten Sie fortfahren? Pfadfehler bei Dateimanager + File Explorer Webbrowser per Default @@ -500,6 +504,8 @@ Neues Fenster Neuer Tab Privater Modus + Default + New Profile Priorität ändern diff --git a/Flow.Launcher/Languages/es-419.xaml b/Flow.Launcher/Languages/es-419.xaml index b3333c7a9..e18cdb3fe 100644 --- a/Flow.Launcher/Languages/es-419.xaml +++ b/Flow.Launcher/Languages/es-419.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Tienda de Plugins @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg para Archivo The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Navegador Web Predeterminado @@ -500,6 +504,8 @@ Nueva Ventana Nueva Pestaña Modo Privado + Default + New Profile Cambiar Prioridad diff --git a/Flow.Launcher/Languages/es.xaml b/Flow.Launcher/Languages/es.xaml index 73cd943a2..faaef8451 100644 --- a/Flow.Launcher/Languages/es.xaml +++ b/Flow.Launcher/Languages/es.xaml @@ -24,8 +24,8 @@ Flow Launcher ha detectado que los datos de usario existen tanto en {0} como en {1}. {2}{2}Por favor, elimine {1} para continuar. No se han producido cambios. - El siguiente complemento ha sufrido un error y no puede cargarse: - Los siguientes complementos han sufrido un error y no pueden cargarse: + El siguiente complemento ha sufrido un fallo y no se puede cargar: + Los siguientes complementos han sufrido un fallo y no se pueden cargar: Por favor, consulte los registros para más información @@ -224,6 +224,7 @@ Fallo al desinstalar {0} No se puede encontrar plugin.json en el archivo zip extraído, o esta ruta {0} no existe Ya existe un complemento con el mismo ID y versión, o la versión es superior a la de este complemento descargado + Error creating setting panel for plugin {0}:{1}{2} Tienda complementos @@ -332,7 +333,7 @@ Cambia 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. - Since Always Preview is on, maximum results shown may not take effect because preview panel requires a certain minimum height + Dado que la vista previa está siempre activada, es posible que no se muestren los resultados máximos, ya que el panel de vista previa requiere una altura mínima determinada Atajo de teclado @@ -395,7 +396,7 @@ Mostrar distintivos en resultados Para los complementos compatibles, se muestran distintivos que ayudan a distinguirlos más fácilmente. Mostrar distintivos en resultados solo para consulta global - Mostrar distintivos solo para los resultados de consultas globales + Muestra distintivos solo para los resultados de consultas globales Salto de diálogo Introducir atajo de teclado para acceder rápidamente a la ventana de diálogo Abrir/Guardar como en la ruta del administrador de archivos actual. Salto de diálogo @@ -467,8 +468,10 @@ Abrir carpeta Avanzado Nivel de registro - Depuración + Silencioso + Error Información + Depuración Configuración de fuente de la ventana @@ -490,6 +493,7 @@ Argumentos del archivo El administrador de archivos '{0}' no pudo ser localizado en '{1}'. ¿Desea continuar? Error de ruta del administrador de archivos + File Explorer Navegador web predeterminado @@ -500,6 +504,8 @@ Nueva ventana Nueva pestaña Modo privado + Default + New Profile Cambiar la prioridad diff --git a/Flow.Launcher/Languages/fr.xaml b/Flow.Launcher/Languages/fr.xaml index ced3aabe0..8aa1b5cd5 100644 --- a/Flow.Launcher/Languages/fr.xaml +++ b/Flow.Launcher/Languages/fr.xaml @@ -224,6 +224,7 @@ Échec de la désinstallation de {0} Impossible de trouver le fichier plugin.json dans le fichier zip extrait, ou ce chemin {0} n'existe pas Un plugin avec le même ID et la même version existe déjà, ou la version est supérieure à ce plugin téléchargé + Erreur lors de la création du panneau de configuration pour le plugin {0}:{1}{2} Magasin des Plugins @@ -466,8 +467,10 @@ Ouvrir le dossier Avancé Niveau de journalisation - Débogage + Silencieux + Erreur Info + Débogage Réglage de la police de la fenêtre @@ -489,6 +492,7 @@ Arguments pour le fichier Le gestionnaire de fichiers '{0}' n'a pas pu être situé à '{1}'. Souhaitez-vous continuer ? Erreur de chemin du gestionnaire de fichiers + Explorateur de fichiers Navigateur web par défaut @@ -499,6 +503,8 @@ Nouvelle fenêtre Nouvel onglet Mode privé + Par défaut + Nouveau profil Changer la priorité diff --git a/Flow.Launcher/Languages/he.xaml b/Flow.Launcher/Languages/he.xaml index 164f13afd..f9f0ba2e3 100644 --- a/Flow.Launcher/Languages/he.xaml +++ b/Flow.Launcher/Languages/he.xaml @@ -223,6 +223,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} חנות תוספים @@ -466,8 +467,10 @@ פתח תיקיה Advanced רמת יומן - ניפוי שגיאות + Silent + שגיאה מידע + ניפוי שגיאות Setting Window Font @@ -489,6 +492,7 @@ ארגומנט לקובץ לא ניתן היה לאתר את מנהל הקבצים '{0}' ב-'{1}'. האם ברצונך להמשיך? שגיאת נתיב למנהל הקבצים + File Explorer דפדפן ברירת מחדל @@ -499,6 +503,8 @@ חלון חדש כרטיסייה חדשה מצב פרטיות + Default + New Profile שנה עדיפות diff --git a/Flow.Launcher/Languages/it.xaml b/Flow.Launcher/Languages/it.xaml index e1d0fadca..60584807c 100644 --- a/Flow.Launcher/Languages/it.xaml +++ b/Flow.Launcher/Languages/it.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Negozio dei Plugin @@ -467,8 +468,10 @@ Apri Cartella Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg Per Cartella The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Browser predefinito @@ -500,6 +504,8 @@ Nuova Finestra Nuova Scheda Modalità Privata + Default + New Profile Cambia Priorità diff --git a/Flow.Launcher/Languages/ja.xaml b/Flow.Launcher/Languages/ja.xaml index 13cd30fd7..de142733f 100644 --- a/Flow.Launcher/Languages/ja.xaml +++ b/Flow.Launcher/Languages/ja.xaml @@ -2,43 +2,43 @@ - Flow detected you have installed {0} plugins, which will require {1} to run. Would you like to download {1}? + Flow はあなたが {0} プラグインをインストールしており、実行するために {1} が必要であることを検知しました。{1} をインストールしますか? {2}{2} - Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable + {1}がすでにインストールされている場合は「いいえ」をクリックし、それが入っているフォルダーを選択してください - Please select the {0} executable + {0} の実行ファイルを選択してください - Your selected {0} executable is invalid. + あなたが選択した {0} の実行ファイルが不正です。 {2}{2} - Click yes if you would like select the {0} executable again. Click no if you would like to download {1} + {0} の実行ファイルをもう一度選択する場合は「はい」を、{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 + {0} の実行可能ファイルのパスを設定できません。Flow の設定から試してください(下までスクロールしてください)。 + プラグインの起動失敗 + プラグイン: {0} の読み込みに失敗したため、無効になりました。プラグインの作成者にお問い合わせください Flow Launcherはポータブルモードの無効化のために再起動する必要があります。再起動の後、ポータブルな形式の設定項目は削除され、あなたのパソコンのフォルダに保存されます Flow Launcherはポータブルモードの有効化のために再起動する必要があります。再起動の後、パソコンに保存された設定項目は削除され、ポータブルな形式で保存されます Flow Launcherはポータブルモードの有効化を検知しました。Flow Launcherを別の場所に移動しますか? Flow Launcherはポータブルモードの無効化を検知しました。関連するショートカットやアンインストーラーが配置されます - Flow Launcher detected your user data exists both in {0} and {1}. {2}{2}Please delete {1} in order to proceed. No changes have occurred. + Flow Launcherはあなたのユーザーデータが{0} と {1} の両方に存在することを検知しました。{2}{2}続行するには、{1}を削除してください。処理は中断されました。 - The following plugin has errored and cannot be loaded: - The following plugins have errored and cannot be loaded: - Please refer to the logs for more information + 以下のプラグインにエラーがあるためロードできません: + 以下のプラグインにエラーがあるためロードできません: + 詳細はログを参照してください - Please try again - Unable to parse Http Proxy + もう一度お試しください + Http プロキシをパースできません - Failed to install TypeScript environment. Please try again later - Failed to install Python environment. Please try again later. + TypeScript環境のインストールに失敗しました。後でもう一度お試しください + Python 環境のインストールに失敗しました。後でもう一度お試しください。 ホットキー "{0}" の登録に失敗しました。このホットキーは別のプログラムで使用されている可能性があります。別のホットキーに変更するか、このホットキーを使用しているプログラムを終了してください。 - Failed to unregister hotkey "{0}". Please try again or see log for details + ホットキー「{0}」の登録解除に失敗しました。もう一度試すか、ログを参照して詳細を確認してください Flow Launcher {0}の起動に失敗しました Flow Launcherプラグインの形式が正しくありません @@ -58,7 +58,7 @@ 全て選択 ファイル フォルダー - Text + テキスト ゲームモード ホットキーの使用を一時停止します。 位置のリセット @@ -73,7 +73,7 @@ スタートアップ時にFlow Launcherを起動する 起動の高速化のためにスタートアップではなくログオンタスクを使用 アンインストール後は、「タスク スケジューラ」からこのタスク(Flow.Launcher Startup)を手動で削除する必要があります。 - Error setting launch on startup + スタートアップ時に起動の設定失敗 フォーカスを失った時にFlow Launcherを隠す 最新版が入手可能であっても、アップグレードメッセージを表示しない 検索ウィンドウの位置 @@ -111,7 +111,7 @@ 常に英語モードで入力を開始する Flowを起動したとき、一時的に入力方法を英語モードに変更します。 自動更新 - Automatically check and update the app when available + 利用可能な場合、Flow Launcherを自動的に確認して更新します 選択 起動時にFlow Launcherを隠す 起動後、Flow Launcher の検索ウィンドウは非表示になり、トレイに格納されます。 @@ -123,10 +123,10 @@ 標準 ピンインによる検索 - Pinyin is the standard system of romanized spelling for translating Chinese. Please note, enabling this can significantly increase memory usage during search. - Use Double Pinyin - Use Double Pinyin instead of Full Pinyin to search. - Double Pinyin Schema + Pinyinは中国語を翻訳するためのローマ字入力の標準的な方法です。有効にすると、検索時のメモリ使用量が大幅に増加する可能性があります。 + 双拼入力を使用 + 検索するときに全拼の代わりに双拼を使用する。 + 双拼の入力方式 Xiao He Zi Ran Ma Wei Ruan @@ -142,10 +142,10 @@ 現在のテーマでぼかしの効果が有効になっている場合、影の効果を有効にすることはできません 検索遅延 入力中に短い遅延を追加することで、UIのちらつきや結果の読み込みを軽減します。平均的なタイピング速度のユーザーにおすすめです。 - Enter the wait time (in ms) until input is considered complete. This can only be edited if Search Delay is enabled. + 入力中の結果表示までの待ち時間をミリ秒単位で入力します。これは、検索遅延が有効な場合にのみ編集できます。 デフォルトの検索遅延時間 入力が停止した後に結果が表示されるまでの待ち時間。値が大きいほど長く待機します。(単位 ms) - Information for Korean IME user + 韓国語IMEユーザーへの情報 The Korean input method used in Windows 11 may cause some issues in Flow Launcher. @@ -160,29 +160,29 @@ - Open Language and Region System Settings + システムの言語と地域設定を開く Opens the Korean IME setting location. Go to Korean > Language Options > Keyboard - Microsoft IME > Compatibility 開く - Use Previous Korean IME + 前の韓国語IMEを使用 You can change the Previous Korean IME settings directly from here Failed to change Korean IME setting - Please check your system registry access or contact support. + システムのレジストリへのアクセスが可能か確認するか、サポートにお問い合わせください。 ホームページ 検索文字列が空の場合、ホームページの結果を表示します。 クエリの履歴をホームページに表示 ホームページに表示される最大の履歴の数 - This can only be edited if plugin supports Home feature and Home Page is enabled. - Show Search Window at Foremost + これは、プラグインがホーム機能をサポートし、ホームページが有効な場合にのみ編集することができます。 + 検索ウィンドウを最前面に表示 他のプログラムの 'Always on Top' (最前面に表示)設定を上書きし、常に最前面のウィンドウで Flow を表示します。 - プラグインストアでプラグインを変更した後に再起動します + プラグインストアでプラグインを変更した後に再起動 プラグインストア経由でプラグインをインストール、アンインストール、または更新した後、Flow Lancherを自動的に再起動します 不明なソースの警告を表示 不明なソースからプラグインをインストールするときに警告を表示する - Auto update plugins - Automatically check plugin updates and notify if there are any updates available + プラグインの自動アップデート + プラグインの更新を自動的にチェックし、利用可能な更新がある場合に通知します - Search Plugin + プラグインの検索 Ctrl+F でプラグインを検索します 検索結果が見つかりませんでした 別の検索を試してみてください。 @@ -191,20 +191,20 @@ プラグインを探す 有効 無効 - Action keyword Setting + アクションキーワードの設定 キーワード - Current action keyword - New action keyword - Change Action Keywords - Plugin search delay time - Change Plugin Search Delay Time + 現在のアクションキーワード + 新しいアクションキーワード + アクションキーワードの変更 + プラグインの検索遅延時間 + プラグインの検索遅延時間を変更 詳細設定: 有効 重要度 検索遅延 ホームページ - Current Priority - New Priority + 現在の優先度 + 新しい優先度 重要度 プラグインの結果の優先度を変更します。 プラグイン・ディレクトリ @@ -214,59 +214,60 @@ バージョン ウェブサイト アンインストール - 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 - {0} modified already - Please restart Flow before making any further changes - Fail to install {0} - Fail to uninstall {0} - Unable to find plugin.json from the extracted zip file, or this path {0} does not exist - A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + プラグイン設定の削除に失敗 + プラグイン: {0} - プラグイン設定ファイルの削除に失敗しました。手動で削除してください + プラグインキャッシュの削除に失敗 + プラグイン: {0} - プラグインキャッシュファイルの削除に失敗しました。手動で削除してください + {0} は既に変更されています + これ以上変更を加える前に Flow Launcher を再起動してください + {0} のインストールに失敗 + {0} のアンインストールに失敗 + 展開されたzipファイルからplugin.jsonが見つからないか、このパス {0} が存在しません + 同じIDとバージョンのプラグインがすでに存在するか、またはこのダウンロードしたプラグインよりもバージョンが大きいです + Error creating setting panel for plugin {0}:{1}{2} プラグインストア 新規リリース 最近の更新 プラグイン - Installed + インストール済み 更新 インストール アンインストール 更新 - Plugin already installed - New Version - This plugin has been updated within the last 7 days + プラグインは既にインストールされています + 新しいバージョン + このプラグインは過去1週間以内に更新されました 新しいアップデートが利用可能です プラグインのインストール失敗 プラグインのアンインストール失敗 - Error updating plugin + プラグインの更新に失敗 プラグインの設定を維持 再びインストールして使用するときのためにプラグインの設定を維持しますか? - Plugin {0} successfully installed. Please restart Flow. - Plugin {0} successfully uninstalled. Please restart Flow. - Plugin {0} successfully updated. Please restart Flow. + プラグイン {0} のインストールに成功しました。Flow を再起動してください。 + プラグイン {0} のアンインストールに成功しました。Flow を再起動してください。 + プラグイン {0} が正常に更新されました。Flow を再起動してください。 プラグインのインストール {0} by {1} {2}{2}このプラグインをインストールしますか? プラグインのアンインストール {0} by {1} {2}{2}このプラグインをアンインストールしますか? - Plugin update - {0} by {1} {2}{2}Would you like to update this plugin? - Downloading plugin - Automatically restart after installing/uninstalling/updating plugins in plugin store - Zip file does not have a valid plugin.json configuration + プラグインの更新 + {0} by {1} {2}{2}このプラグインを更新しますか? + プラグインをダウンロード中 + プラグインストア経由でのプラグインのインストール 、アンインストール、または更新後に自動的に再起動します + Zipファイルに有効なplugin.jsonファイルがありません 不明なソースからのインストール このプラグインは不明なソースから提供されており、潜在的なリスクを含んでいる可能性があります!{0}{0}このプラグインの開発元をよく調べ、安全であることをご自身で確かめてください。{0}{0}それでもあなたはこのプラグインをインストールしますか?{0}{0}(この警告は設定の「一般」セクションで無効にすることができます) - Zip files - Please select zip file + Zip ファイル + zipファイルを選択してください ローカルパスからプラグインをインストール - No update available - All plugins are up to date - Plugin updates available - Update plugins - Check plugin updates - Plugins are successfully updated. Please restart Flow. + 利用可能な更新はありません + すべてのプラグインが最新です + プラグインの更新が利用可能 + プラグインを更新 + プラグインの更新を確認 + プラグインが正常に更新されました。Flow を再起動してください。 テーマ @@ -285,13 +286,13 @@ 検索バーの高さ アイテムの高さ 検索ボックスのフォント - Result Title Font - Result Subtitle Font + 結果のタイトルのフォント + 結果のサブタイトルのフォント リセット - Reset to the recommended font and size settings. - Import Theme Size - If a size value intended by the theme designer is available, it will be retrieved and applied. - Customize + 推奨されるフォントとサイズの設定にリセットします。 + テーマ中のサイズをインポート + テーマのデザイナーによって意図されたサイズ値が利用可能なとき、それを取得して適用します。 + カスタマイズ ウィンドウモード 透過度 テーマ {0} が存在しません、デフォルトのテーマに戻します。 @@ -306,7 +307,7 @@ 検索ウィンドウが開いたとき、小さな音を鳴らします 効果音の音量 効果音の音量を調整します - Windows Media Player is unavailable and is required for Flow's volume adjustment. Please check your installation if you need to adjust volume. + Windows Media Player は Flow を使った音量調整に必要です。ボリュームを調整する必要がある場合は、Windows Media Player がインストールされているかどうか確認してください。 アニメーション UIでアニメーションを使用します アニメーション速度 @@ -324,15 +325,15 @@ アクリル マイカ マイカ(代替) - This theme supports two (light/dark) modes. - This theme supports Blur Transparent Background. + このテーマはライト/ダークの2モードに対応しています。 + このテーマは背景をぼかした透明効果をサポートしています。 プレースホルダーを表示 クエリが空の場合にプレースホルダを表示します 検索欄の案内文 - Change placeholder text. Input empty will use: {0} + プレースホルダのテキストを変更します。空にすると、 {0} が使用されます ウィンドウサイズの固定 ウィンドウのサイズを固定し、ドラッグでの変更を無効にします。 - Since Always Preview is on, maximum results shown may not take effect because preview panel requires a certain minimum height + 「常にプレビューする」が有効になっているため、プレビューパネルの高さの確保のために「結果の最大表示件数」設定は無視される可能性があります ホットキー @@ -372,51 +373,51 @@ カスタムクエリ ホットキー Custom Query Shortcut 組み込みショートカット - Query + クエリー ショートカット 展開 説明 削除 編集 追加 - None + なし 項目を選択してください {0} プラグインのホットキーを本当に削除しますか? 本当にこのショートカットを削除しますか?: {0} を {1} に展開 - Get text from clipboard. + クリップボードからテキストを取得します。 アクティブなエクスプローラーからパスを取得します。 検索ウィンドウの落陰効果 - Shadow effect has a substantial usage of GPU. Not recommended if your computer performance is limited. - Window Width Size - You can also quickly adjust this by using Ctrl+[ and Ctrl+]. + 影の効果は GPU に大きな負荷をかけます。お使いのコンピューターの性能が限定的な場合、無効にすることをおすすめします。 + ウィンドウ幅のサイズ + Ctrl+Plus と Ctrl+Minus を使用すれば、簡単に調整することもできます。 Segoe Fluent アイコンを使用する サポートされているクエリ結果にSegoe Fluentアイコンを使用する - Press Key - Show Result Badges + キーを入力 + 結果のバッジを表示 サポートされているプラグインでは、バッジが表示され、より簡単に区別できます。 - Show Result Badges for Global Query Only - Show badges for global query results only - Dialog Jump - Enter shortcut to quickly navigate the Open/Save As dialog window to the path of the current file manager. - Dialog Jump - When Open/Save As dialog window opens, quickly navigate to the current path of the file manager. - Dialog Jump Automatically - When Open/Save As dialog window is displayed, automatically navigate to the path of the current file manager. (Experimental) - Show Dialog Jump Window - Display Dialog Jump search window when the open/save dialog window is shown to quickly navigate to file/folder locations. - Dialog Jump Window Position - Select position for the Dialog Jump search window - Fixed under the Open/Save As dialog window. Displayed on open and stays until the window is closed - Default search window position. Displayed when triggered by search window hotkey - Dialog Jump Result Navigation Behaviour - Behaviour to navigate Open/Save As dialog window to the selected result path - Left click or Enter key - Right click - Dialog Jump File Navigation Behaviour - Behaviour to navigate Open/Save As dialog window when the result is a file path - Fill full path in file name box - Fill full path in file name box and open - Fill directory in path box + グローバルクエリのみ、結果のバッジを表示 + グローバルクエリの結果にのみバッジを表示する + ダイアログジャンプ + ショートカットを入力して、「名前を付けて開く/保存」ダイアログ・ウィンドウを現在のファイルマネージャのパスにすばやくナビゲートします。 + ダイアログジャンプ + 「名前を付けて開く/保存」ダイアログウィンドウが開いたら、すぐにファイルマネージャの現在のパスに移動します。 + 自動ダイアログジャンプ + 開く/名前を付けて保存ダイアログが表示されると、自動的に現在のファイルマネージャのパスに移動させます。 (実験的) + ダイアログジャンプウィンドウを表示 + 「名前をつけて保存/開く」ダイアログウィンドウが表示されたときにダイアログジャンプのウィンドウを開いて、ファイルやフォルダーを素早く開く。 + ダイアログジャンプのウィンドウの位置 + ダイアログジャンプ検索ウィンドウの位置を選択します + 「名前を付けて開く/保存」ダイアログウィンドウの下に固定。ウィンドウが閉じるまで開いたまま表示されます + デフォルトの検索ウィンドウの位置。検索ウィンドウのホットキーによってトリガーされたときに表示されます + ダイアログジャンプの検索結果の開き方 + 「開く/名前を付けて保存」ダイアログウィンドウの選択した結果パスに移動する動作 + 左クリックまたはEnter キー + 右クリック + ダイアログジャンプのファイルに対する動作 + 結果がファイルパスの場合の、「開く/名前を付けて保存」ダイアログウィンドウに対する動作 + フルパスをファイル名ボックスに入力 + フルパスをファイル名ボックスに入力して開く + パスボックスに含まれるフォルダを入力 HTTP プロキシ @@ -467,44 +468,49 @@ フォルダーを開く 上級者向け機能 ログレベル - デバッグ + Silent + エラー 情報 + デバッグ 設定ウィンドウで使用するフォント - See more release notes on GitHub - Failed to fetch release notes - Please check your network connection or ensure GitHub is accessible - Flow Launcher has been updated to {0} - Click here to view the release notes + GitHub で詳細なリリース ノートを見る + リリースノートの取得に失敗 + ネットワーク接続を確認するか、GitHubにアクセスできることを確認してください + Flow Launcher が {0}に更新されました + ここをクリックしてリリースノートを表示 デフォルトのファイルマネージャー - Learn more - Please specify the file location of the file manager you using and add arguments as required. The "%d" represents the directory path to open for, used by the Arg for Folder field and for commands opening specific directories. The "%f" represents the file path to open for, used by the Arg for File field and for commands opening specific files. - For example, if the file manager uses a command such as "totalcmd.exe /A c:\windows" to open the c:\windows directory, the File Manager Path will be totalcmd.exe, and the Arg For Folder will be /A "%d". Certain file managers like QTTabBar may just require a path to be supplied, in this instance use "%d" as the File Manager Path and leave the rest of the fields blank. - File Manager - Profile Name - File Manager Path - Arg For Folder - Arg For File - The file manager '{0}' could not be located at '{1}'. Would you like to continue? - File Manager Path Error + 詳細を見る + 使用したいファイルマネージャーのファイルの位置を指定し、コマンドライン引数を入力してください。"%d" は開こうとしているフォルダーのパスを表し、「フォルダー用の引数」の欄で特定のフォルダーを開くために使用されます。"%f" は開こうとしているファイルのパスを表し、「ファイル用の引数」の欄で特定のファイルを開くために使用されます。 + 例として、ファイルマネージャーが "totalcmd.exe /A c:\windows" というコマンドを c:\windows というフォルダを開くために使用する場合を考えます。この場合、ファイルマネージャーのパスは totalcmd.exe で、フォルダー用の引数は /A "%d" になります。QTTabBarのように、パスのみを要求するファイルマネージャーの場合、”%d” をファイルマネージャーのパスの欄に指定し、残りを空欄にしてください。 + ファイル マネージャー + プロファイル名 + ファイルマネージャーのパス + フォルダー用の引数 + ファイル用の引数 + ファイルマネージャー '{0}' は、'{1}' に見つかりませんでした。続行しますか? + ファイルマネージャのパスエラー + File Explorer デフォルトのウェブブラウザー - The default setting follows the OS default browser setting. If specified separately, flow uses that browser. - Browser - Browser Name - Browser Path - New Window - New Tab - Private Mode + デフォルトの設定は、OS のデフォルトのブラウザ設定に従います。別々に指定すると、Flow はそのブラウザを使用します。 + ブラウザー + ブラウザー名 + ブラウザーのパス + 新しいウィンドウ + 新しいタブ + プライベートモード + Default + New Profile - Change Priority - Greater the number, the higher the result will be ranked. Try setting it as 5. If you want the results to be lower than any other plugin's, provide a negative number - Please provide an valid integer for Priority! + 優先度の変更 + 数値が大きいほど、結果の上の方に表示されます。試しに5として設定してみてください。 結果を他のプラグインよりも低くしたい場合は、負の数字を入力してください + 優先度には有効な整数を入力してください! 古いアクションキーワード @@ -514,33 +520,33 @@ 指定されたプラグインが見つかりません 新しいアクションキーワードを空にすることはできません 新しいアクションキーワードは他のプラグインに割り当てられています。他のアクションキーワードを入力してください - This new Action Keyword is the same as old, please choose a different one + そのアクションキーワードは以前のものと同じです。他のアクションキーワードを入力してください 成功しました - Completed successfully - Failed to copy - 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 - Input the search delay time in ms you like to use for the plugin. Input empty if you don't want to specify any, and the plugin will use default search delay time. + 検索の遅延時間の設定 + プラグインに使用したい検索の遅延時間をミリ秒で入力します。 何も指定したくない場合は空にしておくと、プラグインはデフォルトの検索の遅延時間を使用します。 ホームページ - Enable the plugin home page state if you like to show the plugin results when query is empty. + クエリが空のときにプラグインの結果を表示したい場合は、プラグインのホームページの設定を有効にします。 カスタムクエリのホットキー - Press a custom hotkey to open Flow Launcher and input the specified query automatically. + カスタムホットキーを押して Flow Launcher を開き、指定したクエリを自動的に入力します。 プレビュー ホットキーは使用できません。新しいホットキーを選択してください - Hotkey is invalid + そのホットキーは無効です 更新 - Binding Hotkey - Current hotkey is unavailable. - This hotkey is reserved for "{0}" and can't be used. Please choose another hotkey. - This hotkey is already in use by "{0}". If you press "Overwrite", it will be removed from "{0}". - Press the keys you want to use for this function. - Hotkey and action keyword are empty + ホットキーの設定 + 現在のホットキーは使用できません。 + このホットキーは "{0}" で予約されており、使用できません。別のホットキーを選択してください。 + このホットキーは "{0}" によってすでに使用されています。「上書き」を押すと、"{0}"から削除されます。 + この機能に使用するキーを押してください。 + ホットキーとアクションキーワードが空です カスタムクエリのショートカット @@ -551,11 +557,11 @@ そのショートカットは既に存在します。新しいショートカットを入力するか、既存のショートカットを編集してください。 ショートカット、展開の少なくとも一方が空です。 - Shortcut is invalid + ショートカットが無効です 保存 - Overwrite + 上書き キャンセル リセット 削除 @@ -580,46 +586,46 @@ クラッシュレポートの送信に失敗しました Flow Launcherにエラーが発生しました Please open new issue in - 1. Upload log file: {0} - 2. Copy below exception message + 1. ログファイルをアップロード: {0} + 2. 例外メッセージ以下をコピー - File Manager Error + ファイルマネージャのエラー - The specified file manager could not be found. Please check the Custom File Manager setting under Settings > General. + 指定されたファイルマネージャーが見つかりませんでした。設定 > 一般でカスタムファイルマネージャの設定を確認してください。 - Error - An error occurred while opening the folder. {0} - An error occurred while opening the URL in the browser. Please check your Default Web Browser configuration in the General section of the settings window + エラー + フォルダを開く際にエラーが発生しました。 {0} + ブラウザでURLを開く際にエラーが発生しました。設定ウィンドウの一般セクションでデフォルトのウェブブラウザ設定を確認してください - Please wait... + しばらくお待ちください… - Checking for new update + 新しい更新を確認中 Flow Launcherは既に最新です - Update found - Updating... + 更新が見つかりました + 更新中… - Flow Launcher was not able to move your user profile data to the new update version. - Please manually move your profile data folder from {0} to {1} + Flow Launcherはユーザープロファイルデータを新しいバージョンに移動できませんでした。 + 手動で {0} から {1}にプロフィールデータフォルダを移動してください - New Update + 新しい更新 Flow Launcher の最新バージョン V{0} が入手可能です Flow Launcherのアップデート中にエラーが発生しました 更新 キャンセル - Update Failed - Check your connection and try updating proxy settings to github-cloud.s3.amazonaws.com. + アップデート失敗 + 接続を確認し、その後プロキシ設定を github-cloud.s3.amazonaws.com に更新してみてください。 このアップデートでは、Flow Launcherの再起動が必要です 次のファイルがアップデートされます 更新ファイル一覧 アップデートの詳細 - Restart Flow Launcher after updating plugins - {0}: Update from v{1} to v{2} - No plugin selected + プラグインを更新した後、Flow Launcher を再起動する + {0}: v{1} から v{2} へ更新 + プラグインが選択されていません スキップ @@ -642,18 +648,18 @@ コンテキストメニューを開く ファイルのあるフォルダを開く 管理者として実行、または、 デフォルトのファイルマネージャでフォルダを開く - Query History + クエリの履歴 コンテキストメニューから検索結果に戻る - Autocomplete + 自動補完 選択したアイテムを開く、または、実行する Flow Launcherの設定ウインドウを開く プラグインデータのリロード - Select first result - Select last result - Run current query again + 最初の結果を選択 + 最後の結果を選択 + 現在のクエリをもう一度実行 結果を開く - Open result #{0} + #{0} を開く 天気 天気についてのGoogle検索 diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml index 6cf1a6274..131aa50cb 100644 --- a/Flow.Launcher/Languages/ko.xaml +++ b/Flow.Launcher/Languages/ko.xaml @@ -215,6 +215,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} 플러그인 스토어 @@ -458,8 +459,10 @@ 폴더 열기 Advanced 로그 레벨 - Debug + Silent + Error Info + Debug 설정창 글꼴 @@ -481,6 +484,7 @@ 파일경로 인수 The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer 기본 웹 브라우저 @@ -491,6 +495,8 @@ 새 창 새 탭 사생활 보호 모드 + Default + New Profile 중요도 변경 diff --git a/Flow.Launcher/Languages/nb.xaml b/Flow.Launcher/Languages/nb.xaml index 57afaa87b..a27f66d11 100644 --- a/Flow.Launcher/Languages/nb.xaml +++ b/Flow.Launcher/Languages/nb.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Programtillegg butikk @@ -467,8 +468,10 @@ Åpne mappe Advanced Log Level - Debug + Silent + Feil Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg for fil The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Standard nettleser @@ -500,6 +504,8 @@ Nytt vindu Ny fane Privat modus + Default + New Profile Endre prioritet diff --git a/Flow.Launcher/Languages/nl.xaml b/Flow.Launcher/Languages/nl.xaml index 5b7ba1d21..416091858 100644 --- a/Flow.Launcher/Languages/nl.xaml +++ b/Flow.Launcher/Languages/nl.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Plugin Winkel @@ -467,8 +468,10 @@ Map openen Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg voor bestand The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Standaard webbrowser @@ -500,6 +504,8 @@ Nieuw Venster Nieuw tabblad Privé modus + Default + New Profile Prioriteit wijzigen diff --git a/Flow.Launcher/Languages/pl.xaml b/Flow.Launcher/Languages/pl.xaml index 92b91d287..1295e66c9 100644 --- a/Flow.Launcher/Languages/pl.xaml +++ b/Flow.Launcher/Languages/pl.xaml @@ -223,6 +223,7 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Sklep z wtyczkami @@ -466,8 +467,10 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Otwórz folder Zaawansowane Poziom logowania - Debug + Silent + Błąd Info + Debug Ustawienia czcionki okna @@ -489,6 +492,7 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Arg dla pliku Menedżer plików „{0}” nie został znaleziony w lokalizacji „{1}”. Czy chcesz kontynuować? Błąd ścieżki do menedżera plików + File Explorer Domyślna przeglądarka @@ -499,6 +503,8 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Nowe okno Nowa zakładka Tryb prywatny + Default + New Profile Zmień priorytet diff --git a/Flow.Launcher/Languages/pt-br.xaml b/Flow.Launcher/Languages/pt-br.xaml index 9b0db5a9e..91193bd0a 100644 --- a/Flow.Launcher/Languages/pt-br.xaml +++ b/Flow.Launcher/Languages/pt-br.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Loja de Plugins @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg para Arquivo The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Navegador da Web Padrão @@ -500,6 +504,8 @@ Nova Janela Nova Aba Modo Privado + Default + New Profile Alterar Prioridade diff --git a/Flow.Launcher/Languages/pt-pt.xaml b/Flow.Launcher/Languages/pt-pt.xaml index 1a68f23f4..080573821 100644 --- a/Flow.Launcher/Languages/pt-pt.xaml +++ b/Flow.Launcher/Languages/pt-pt.xaml @@ -223,6 +223,7 @@ Falha ao desinstalar {0} Não foi possível encontrar plugin.json no ficheiro zip ou, então, o caminho {0} não existe. Já existe um plugin com a mesma ID e versão ou, então, a versão instalada é superior à do plugin descarregado. + Erro ao criar o painel de definição para o plugin {0}:{1}{2} Loja de plugins @@ -331,7 +332,7 @@ 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. - Since Always Preview is on, maximum results shown may not take effect because preview panel requires a certain minimum height + Como a opção "Pré-visualizar sempre" está ativa, os resultados máximos mostrados podem não ter efeito porque o painel de visualização requer uma altura mínima Tecla de atalho @@ -465,8 +466,10 @@ Abrir pasta Avançado Nível de registo - Depuração + Silencioso + Erro Informação + Depuração Tipo de letra da aplicação @@ -488,6 +491,7 @@ Argumento para ficheiro Não foi possível encontrar o gestor de ficheiros '{0}' em '{1}'. Deseja continuar? Erro no caminho do gestor de ficheiros + Gestor de ficheiros Navegador web padrão @@ -498,6 +502,8 @@ Nova janela Novo separador Modo privado + Padrão + Novo perfil Alterar prioridade diff --git a/Flow.Launcher/Languages/ru.xaml b/Flow.Launcher/Languages/ru.xaml index 43d26aff2..c506d0765 100644 --- a/Flow.Launcher/Languages/ru.xaml +++ b/Flow.Launcher/Languages/ru.xaml @@ -167,7 +167,7 @@ You can change the Previous Korean IME settings directly from here Failed to change Korean IME setting Please check your system registry access or contact support. - Home Page + Главная страница Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page @@ -199,10 +199,10 @@ Plugin search delay time Change Plugin Search Delay Time Advanced Settings: - Enabled + Включено Приоритет Search Delay - Home Page + Главная страница Текущий приоритет Новый приоритет Приоритет @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Магазин плагинов @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Ошибка Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Аргумент для файла The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Браузер по умолчанию @@ -500,6 +504,8 @@ Новое окно Новая вкладка Приватный режим + Default + New Profile Изменить приоритет @@ -525,7 +531,7 @@ Input the search delay time in ms you like to use for the plugin. Input empty if you don't want to specify any, and the plugin will use default search delay time. - Home Page + Главная страница Enable the plugin home page state if you like to show the plugin results when query is empty. diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml index 855c0635e..e909a24b1 100644 --- a/Flow.Launcher/Languages/sk.xaml +++ b/Flow.Launcher/Languages/sk.xaml @@ -176,7 +176,7 @@ Nevykonali sa žiadne zmeny. Zobraziť vyhľadávacie okno v popredí Prepíše nastavenie "Vždy na vrchu" ostatných programov a zobrazí navrchu Flow. Reštartovať po úprave pluginu cez Repozitár pluginov - Automaticky reštartovať Flow Launcher po inštalácii/odinštalácii/aktualizáciu pluginu cez Repozitár pluginov + Automaticky reštartovať Flow Launcher po inštalácii/odinštalácii/aktualizácii pluginu cez Repozitár pluginov Zobraziť upozornenie na neznámy zdroj Zobraziť upozornenie pri inštalácii z neznámych zdrojov Automaticky aktualizovať pluginy @@ -225,6 +225,7 @@ Nevykonali sa žiadne zmeny. Nepodarilo sa odinštalovať {0} Súbor plugin.json sa nenašiel v rozbalenom zip súbore, alebo táto cesta {0} neexistuje Plugin s rovnakým ID už existuje, alebo ide o vyššiu verziu ako stiahnutý plugin + Chyba pri vytváraní panelu nastavení pre plugin {0}:{1}{2} Repozitár pluginov @@ -255,7 +256,7 @@ Nevykonali sa žiadne zmeny. Aktualizácia pluginu {0} od {1} {2}{2}Chcete aktualizovať tento plugin? Sťahovanie pluginu - Automaticky reštartovať po inštalácii/odinštalácii/aktualizáciu pluginov cez Repozitár pluginov + Automaticky reštartovať po inštalácii/odinštalácii/aktualizácii pluginov cez Repozitár pluginov V zipe sa nenachádza platná konfigurácia plugin.json Inštalácia z neznámeho zdroja Tento plugin pochádza z neznámeho zdroja a môže predstavovať potenciálne riziká!{0}{0}Uistite sa, že viete, odkiaľ tento plugin pochádza, a že je bezpečný.{0}{0}Stále chcete pokračovať?{0}{0}(Toto upozornenie môžete vypnúť sekcii Všeobecné v nastaveniach) @@ -267,7 +268,7 @@ Nevykonali sa žiadne zmeny. Dostupná aktualizácia pluginu Aktualizovať pluginy Skontrolovať dostupnosť aktualizácií - Pluginy {0} boli úspešne aktualizované. Prosím, reštartuje Flow. + Pluginy boli úspešne aktualizované. Prosím, reštartuje Flow. Motív @@ -396,28 +397,28 @@ Nevykonali sa žiadne zmeny. Zobraziť výsledok v odznaku Ak to plugin podporuje, zobrazí sa jeho ikona v odznaku na jednoduchšie odlíšenie. Zobraziť výsledok v odznaku len pre globálne vyhľadávanie - Show badges for global query results only - Dialog Jump - Enter shortcut to quickly navigate the Open/Save As dialog window to the path of the current file manager. - Dialog Jump - When Open/Save As dialog window opens, quickly navigate to the current path of the file manager. - Dialog Jump Automatically - When Open/Save As dialog window is displayed, automatically navigate to the path of the current file manager. (Experimental) - Show Dialog Jump Window - Display Dialog Jump search window when the open/save dialog window is shown to quickly navigate to file/folder locations. - Dialog Jump Window Position - Select position for the Dialog Jump search window - Fixed under the Open/Save As dialog window. Displayed on open and stays until the window is closed - Default search window position. Displayed when triggered by search window hotkey - Dialog Jump Result Navigation Behaviour - Behaviour to navigate Open/Save As dialog window to the selected result path - Left click or Enter key - Right click - Dialog Jump File Navigation Behaviour - Behaviour to navigate Open/Save As dialog window when the result is a file path - Fill full path in file name box - Fill full path in file name box and open - Fill directory in path box + Zobrazí výsledok v odznaku len pre výsledky globálneho vyhľadávania + Rýchly prechod + Zadajte skratku na rýchly prechod na aktuálnu cestu správcu súborov v dialógovom okne Otvoriť/Uložiť. + Rýchly prechod + Keď sa otvorí dialógové okno Otvoriť/Uložiť, rýchlo prejdete na aktuálnu cestu správcu súborov. + Automatický rýchly prechod + Keď je otvorené dialógové okno Otvoriť/Uložiť, automaticky prejsť na cestu v aktuálnom správcovi súborov (Experimentálne) + Zobraziť okno na rýchly prechod + Zobraziť okno rýchleho prechodu, keď je zobrazené dialógové okno Ovoriť/Uložiť na rýchlu navigáciu do umiestnenia súborov/priečinkov. + Umiestnenie okna "rýchly prechod" + Vyberte umiestnenie vyhľadávacieho okna pre "rýchly prechod" + Fixné pod oknom Otvoriť/Uložiť. Zostane zobrazené po otvorení až do uzavretia okna + Predvolená pozícia vyhľadávacieho okna. Zobrazí sa po zadaní skratky na otvorenie vyhľadávacieho okna + Akcia na prechod k výsledku rýchleho prechodu + Ako prejsť na vybranú cestu v otvorenom dialógovom okne Otvoriť/Uložiť + Kliknutie ľavým tlačidlom myši alebo klávesom Enter + Kliknutie pravým tlačidlom myši + Akcia na prechod k súboru rýchleho prechodu + Akcia, ktorá sa vykoná na navigáciu v dialógovom okne Otvoriť/Uložiť, ak výsledkom je súbor + Vložiť celú cestu k súboru do poľa názvu súboru + Vložiť celú cestu k súboru do poľa názvu súboru a otvoriť + Vložiť priečinok do poľa s cestou HTTP proxy @@ -468,8 +469,10 @@ Nevykonali sa žiadne zmeny. Otvoriť priečinok Rozšírené Úroveň logovania - Debug + Žiadne + Chyba Info + Debug Nastavenie písma okna @@ -482,8 +485,8 @@ Nevykonali sa žiadne zmeny. Vyberte správcu súborov Viac informácií - Zadajte umiestnenie súboru správcu súborov, ktorý používate, a podľa potreby pridajte argumenty. "%d" predstavuje cestu k priečinku, ktorý sa má otvoriť, používa sa v poli Arg pre priečinok a pri príkazoch na otvorenie konkrétnych priečinkov. "%f" predstavuje cestu k súboru, ktorá sa má otvoriť a používa sa v poli Arg pre súbor a pri príkazoch na otvorenie konkrétnych súborov. - Napríklad, ak správca súborov používa príkaz ako "totalcmd.exe /A c:\windows" na otvorenie priečinka c:\windows, cesta správcu súborov bude totalcmd.exe a Arg pre priečinok bude /A "%d". Niektorí správcovia súborov, ako napríklad QTTabBar, môžu vyžadovať len zadanie cesty, v tomto prípade použite "%d" ako cestu správcu súborov a zvyšok súborov nechajte prázdny. + Zadajte umiestnenie súboru správcu súborov, ktorý používate, a podľa potreby pridajte argumenty. "%d" predstavuje cestu k priečinku, ktorý sa má otvoriť, používa sa v poli Arg. pre priečinok a pri príkazoch na otvorenie konkrétnych priečinkov. "%f" predstavuje cestu k súboru, ktorá sa má otvoriť a používa sa v poli Arg. pre súbor a pri príkazoch na otvorenie konkrétnych súborov. + Napríklad, ak správca súborov používa príkaz ako "totalcmd.exe /A c:\windows" na otvorenie priečinka c:\windows, cesta správcu súborov bude totalcmd.exe a Arg. pre priečinok bude /A "%d". Niektorí správcovia súborov, ako napríklad QTTabBar, môžu vyžadovať len zadanie cesty, v tomto prípade použite "%d" ako cestu správcu súborov a zvyšok súborov nechajte prázdny. Správca súborov Názov profilu Cesta k správcovi súborov @@ -491,6 +494,7 @@ Nevykonali sa žiadne zmeny. Arg. pre súbor Správca súborov '{0}' sa nenachádza na '{1}'. Chcete pokračovať? Chyba v ceste k správcovi súborov + Prieskumník Predvolený webový prehliadač @@ -501,6 +505,8 @@ Nevykonali sa žiadne zmeny. Nové okno Nová karta Privátny režim + Predvolené + Nový profil Zmena priority diff --git a/Flow.Launcher/Languages/sr-Cyrl-RS.xaml b/Flow.Launcher/Languages/sr-Cyrl-RS.xaml index 4e6c35d98..189e882ec 100644 --- a/Flow.Launcher/Languages/sr-Cyrl-RS.xaml +++ b/Flow.Launcher/Languages/sr-Cyrl-RS.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Plugin Store @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg For File The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Default Web Browser @@ -500,6 +504,8 @@ New Window New Tab Private Mode + Default + New Profile Change Priority diff --git a/Flow.Launcher/Languages/sr.xaml b/Flow.Launcher/Languages/sr.xaml index e1495efd6..636942ac4 100644 --- a/Flow.Launcher/Languages/sr.xaml +++ b/Flow.Launcher/Languages/sr.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Plugin Store @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg For File The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Default Web Browser @@ -500,6 +504,8 @@ New Window New Tab Private Mode + Default + New Profile Change Priority diff --git a/Flow.Launcher/Languages/tr.xaml b/Flow.Launcher/Languages/tr.xaml index a91b7997d..e91ba5b3f 100644 --- a/Flow.Launcher/Languages/tr.xaml +++ b/Flow.Launcher/Languages/tr.xaml @@ -224,6 +224,7 @@ {0} kaldırılamıyor plugin.json dosyası çıkarılan zip dosyasında bulunamadı veya {0} yolu mevcut değil Bu eklentiyle aynı ID ve sürüme sahip bir eklenti zaten var, ya da mevcut sürüm daha yüksek + Error creating setting panel for plugin {0}:{1}{2} Eklenti Mağazası @@ -405,14 +406,14 @@ Diyalog Atlama Penceresini Göster Dosya/klasör konumlarına hızlı erişim için aç/kaydet penceresi gösterildiğinde Diyalog Atlama arama penceresini görüntüle. Diyalog Atlama Penceresi Konumu - Select position for the Dialog Jump search window + Diyalog Atlama arama penceresi için konum seçin Farklı Aç/Kaydet iletişim penceresinin altında düzeltildi. Açıldığında görüntülenir ve pencere kapatılana kadar kalır Varsayılan arama penceresi konumu. Arama penceresi kısayol tuşu tarafından tetiklendiğinde görüntülenir - Dialog Jump Result Navigation Behaviour + Diyalog Atlama Sonucu Gezinme Davranışı Farklı Aç/Kaydet iletişim penceresini seçilen sonuç yoluna yönlendirmek için davranış Sol tık veya Enter tuşu Sağ tık - Dialog Jump File Navigation Behaviour + Dialog Jump Dosya Gezinme Davranışı Sonuç bir dosya yolu olduğunda Farklı Aç/Kaydet iletişim penceresinde gezinme davranışı Dosya adı kutusuna tam yolu girin Dosya adı kutusuna tam yolu girin ve açın @@ -467,8 +468,10 @@ Klasörü Aç Gelişmiş Günlük Düzeyi - Hata ayıklama + Sessiz + Hata Bilgi + Hata ayıklama Pencere Yazı Tipini Ayarla @@ -490,6 +493,7 @@ Dosya Açarken '{0}' dosya yöneticisi '{1}' konumunda bulunamadı. Devam etmek ister misiniz? Dosya Yöneticisi Yol Hatası + File Explorer İnternet Tarayıcı Seçenekleri @@ -500,6 +504,8 @@ Yeni Pencere Yeni Sekme Gizli Mod için Bağımsız Değişken + Default + New Profile Önceliği Ayarla diff --git a/Flow.Launcher/Languages/uk-UA.xaml b/Flow.Launcher/Languages/uk-UA.xaml index 55d12a14e..42541d046 100644 --- a/Flow.Launcher/Languages/uk-UA.xaml +++ b/Flow.Launcher/Languages/uk-UA.xaml @@ -224,6 +224,7 @@ Не вдалося видалити {0} Не вдалося знайти файл plugin.json у розпакованому zip-файлі або цей шлях {0} не існує. Вже існує плагін з таким самим ідентифікатором та версією, або версія цього плагіну вища за версію завантаженого. + Помилка створення панелі налаштувань для плагіну {0}: {1}{2} Магазин плагінів @@ -467,8 +468,10 @@ Відкрити теку Розширені Рівень журналювання - Налагодження + Без звуку + Помилка Інформація + Налагодження Встановлення шрифту вікна @@ -490,6 +493,7 @@ Аргумент для файлу Не вдалося знайти файловий менеджер «{0}» за адресою «{1}». Чи бажаєте продовжити? Помилка шляху до файлового менеджера + Файловий провідник Типовий веббраузер @@ -500,6 +504,8 @@ Нове вікно Нова вкладка Приватний режим + Типово + Новий профіль Змінити пріоритет diff --git a/Flow.Launcher/Languages/vi.xaml b/Flow.Launcher/Languages/vi.xaml index 29aaffc8a..f56703b7a 100644 --- a/Flow.Launcher/Languages/vi.xaml +++ b/Flow.Launcher/Languages/vi.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Tải tiện ích mở rộng @@ -469,8 +470,10 @@ Mở thư mục Advanced Log Level - Debug + Silent + Lỗi Info + Debug Setting Window Font @@ -492,6 +495,7 @@ Đối số cho tệp The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Trình duyệt web tiêu chuẩn @@ -502,6 +506,8 @@ Cửa sổ mới Thẻ Mới Chế độ riêng tư + Default + New Profile Thay đổi mức độ ưu tiên diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index 0f8934fe4..3b368f170 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -224,6 +224,7 @@ 卸载 {0} 失败 无法从提取的zip文件中找到plugin.json,或者此路径 {0} 不存在 已存在相同ID和版本的插件,或者存在版本大于此下载的插件 + Error creating setting panel for plugin {0}:{1}{2} 插件商店 @@ -467,8 +468,10 @@ 打开文件夹 高级 日志等级 - 调试 + 静默 + 错误 信息 + 调试 设置窗口字体 @@ -490,6 +493,7 @@ 选中文件路径参数 文件管理器 '{0}' 不能在 '{1}'中定位。您想要继续吗? 文件管理器路径错误 + 文件资源管理器 默认浏览器 @@ -500,6 +504,8 @@ 新窗口 新标签 隐身模式 + 默认 + 新配置 更改优先级 diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index 0cec258f1..c80e8b092 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} 插件商店 @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ 檔案參數 The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer 預設瀏覽器 @@ -500,6 +504,8 @@ 新增視窗 新增分頁 無痕模式 + Default + New Profile 更改優先度 diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Languages/ja.xaml index 6700bce19..d60739468 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Languages/ja.xaml @@ -6,15 +6,15 @@ ブラウザのブックマークを検索します - Failed to set url in clipboard + クリップボードにURLをコピーできませんでした - Bookmark Data - Open bookmarks in: - New window - New tab - Set browser from path: - Choose + ブックマークのデータ + ブックマークを開く場所: + 新しいウインドウ + 新しいタブ + 以下のパスからブラウザーを設定: + 選択 URLをコピー ブックマークのURLをクリップボードにコピー 次のブラウザから読み込む: diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ar.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ar.xaml index 759ba99de..324c91972 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ar.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ar.xaml @@ -1,8 +1,8 @@ - + آلة حاسبة - تمكنك من إجراء العمليات الحسابية. (جرب 5*3-2 في Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. ليست رقمًا (NaN) التعبير خاطئ أو غير مكتمل (هل نسيت بعض الأقواس؟) نسخ هذا الرقم إلى الحافظة @@ -13,4 +13,5 @@ نقطة (.) أقصى عدد من المنازل العشرية Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/cs.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/cs.xaml index f5dbe8e20..844c2dc30 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/cs.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/cs.xaml @@ -1,8 +1,8 @@ - + Kalkulačka - Umožňuje provádět matematické výpočty.(Try 5*3-2 v průtokovém spouštěči) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Není číslo (NaN) Nesprávný nebo neúplný výraz (Nezapomněli jste na závorky?) Kopírování výsledku do schránky @@ -13,4 +13,5 @@ Tečka (.) Desetinná místa Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/da.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/da.xaml index 2f2777aa1..405a39e92 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/da.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/da.xaml @@ -1,8 +1,8 @@ - + Calculator - Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Not a number (NaN) Expression wrong or incomplete (Did you forget some parentheses?) Copy this number to the clipboard @@ -13,4 +13,5 @@ Dot (.) Max. decimal places Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/de.xaml index 46f5efe23..4dc634db2 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/de.xaml @@ -1,8 +1,8 @@ - + Rechner - Ermöglicht mathematische Berechnungen. (Versuchen Sie 5*3-2 in Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Nicht eine Zahl (NaN) Ausdruck falsch oder unvollständig (Haben Sie einige Klammern vergessen?) Diese Zahl in die Zwischenablage kopieren @@ -13,4 +13,5 @@ Punkt (.) Max. Dezimalstellen Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es-419.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es-419.xaml index dce29cba5..12b4fdb0a 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es-419.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es-419.xaml @@ -1,8 +1,8 @@ - + Calculadora - Permite hacer cálculos matemáticos. (Pruebe con 5*3-2 en Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. No es un número (NaN) Expresión incorrecta o incompleta (¿Olvidó algún paréntesis?) Copiar este número al portapapeles @@ -13,4 +13,5 @@ Punto (.) Número máximo de decimales Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es.xaml index 7f1775e2e..05a862d78 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es.xaml @@ -1,8 +1,8 @@ - + Calculadora - Realiza cálculos matemáticos (incluyendo valores hexadecimales). Utilizar ',' o '.' como separador de miles o decimal. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. No es un número (NaN) Expresión incorrecta o incompleta (¿Ha olvidado algunos paréntesis?) Copiar este número al portapapeles @@ -13,4 +13,5 @@ Punto (.) Número máximo de decimales Ha fallado la copia, inténtelo más tarde + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/fr.xaml index a6db34811..3219e517a 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/fr.xaml @@ -1,8 +1,8 @@ - + Calculatrice - Effectuer des calculs mathématiques (y compris les valeurs hexadécimales). Utilisez ',' ou '.' comme séparateur de milliers ou décimaux. + Effectuez des calculs mathématiques, y compris les valeurs hexadécimales et les fonctions avancées telles que 'min(1,2,3)', 'sqrt(123)' et 'cos(123)'. Pas un nombre (NaN) Expression incorrecte ou incomplète (avez-vous oublié certaines parenthèses ?) Copier ce chiffre dans le presse-papiers @@ -13,4 +13,5 @@ Point (.) Décimales max. Échec de la copie, réessayer plus tard + Afficher le message d'erreur lorsque le calcul échoue diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/he.xaml index b053c8905..7ee027743 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/he.xaml @@ -1,8 +1,8 @@ - + מחשבו - מאפשר לבצע חישובים מתמטיים. (נסה 5*3-2 ב-Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. לא מספר (NaN) הביטוי שגוי או לא שלם (האם שכחת סוגריים?) העתק מספר זה ללוח @@ -13,4 +13,5 @@ נקודה (.) מספר מקסימלי של מקומות עשרוניים Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/it.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/it.xaml index 5b724e82e..a0e61ff32 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/it.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/it.xaml @@ -1,8 +1,8 @@ - + Calcolatrice - Consente di eseguire calcoli matematici (provare 5*3-2 in Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Non è un numero (NaN) Espressione sbagliata o incompleta (avete dimenticato delle parentesi?) Copiare questo numero negli appunti @@ -13,4 +13,5 @@ Punto (.) Max. cifre decimali Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ja.xaml index bbd06006f..da0b64bdb 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ja.xaml @@ -1,16 +1,17 @@  - Calculator - Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place. - Not a number (NaN) - Expression wrong or incomplete (Did you forget some parentheses?) + 電卓 + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. + 数値で表せません (NaN) + 式が間違っているか不完全です(括弧を忘れていませんか?) この数字をクリップボードにコピーします 小数点の区切り記号 - The decimal separator to be used in the output. + 出力で使用される小数点の区切り文字。 システムのロケールを使用 コンマ(,) ドット (.) 小数点以下の最大桁数 - Copy failed, please try later + コピーに失敗しました。後でやり直してください + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ko.xaml index e4ca16d41..a595f4839 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ko.xaml @@ -1,8 +1,8 @@ - + 계산기 - 수학 계산을 할 수 있습니다. Flow Launcher에서 5*3-2를 입력해보세요. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. 숫자가 아님 (NaN) 표현식이 잘못되었거나 불완전합니다. (괄호를 깜빡하셨나요?) 해당 숫자를 클립보드에 복사 @@ -13,4 +13,5 @@ 마침표 (.) 최대 소수점 아래 자릿 수 Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nb.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nb.xaml index 9ae31e976..9b6b1f808 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nb.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nb.xaml @@ -1,8 +1,8 @@ - + Kalkulator - Lar deg gjøre matematiske beregninger. (Prøv 5*3-2 i Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Ikke et tall (NaN) Uttrykk feil eller ufullstendig (glem noen parenteser?) Kopier dette nummeret til utklippstavlen @@ -13,4 +13,5 @@ Prikk (.) Maks. desimaler Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nl.xaml index 2f2777aa1..405a39e92 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nl.xaml @@ -1,8 +1,8 @@ - + Calculator - Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Not a number (NaN) Expression wrong or incomplete (Did you forget some parentheses?) Copy this number to the clipboard @@ -13,4 +13,5 @@ Dot (.) Max. decimal places Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pl.xaml index e73298dca..03f50ca23 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pl.xaml @@ -1,8 +1,8 @@ - + Kalkulator - Szybkie wykonywanie obliczeń matematycznych. (Spróbuj wpisać 5*3-2 w oknie Flow Launchera) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Nie liczba (NaN) Wyrażenie niepoprawne lub niekompletne (Czy zapomniałeś o nawiasach?) Skopiuj ten numer do schowka @@ -13,4 +13,5 @@ Kropka (.) Maks. liczba miejsc po przecinku Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-br.xaml index 73a60d42f..9afc3b784 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-br.xaml @@ -1,8 +1,8 @@ - + Calculadora - Permite fazer cálculos matemáticos.(Tente 5*3-2 no Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Não é um número (NaN) Expressão errada ou incompleta (Você esqueceu de adicionar parênteses?) Copiar este numero para a área de transferência @@ -13,4 +13,5 @@ Ponto (.) Max. decimal places Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-pt.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-pt.xaml index 7ec52be8c..1201e2555 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-pt.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-pt.xaml @@ -1,8 +1,8 @@ - + Calculadora - Execução de cálculos matemáticos (incluindo valores hexadecimais). Utilize ',' ou '.' como separador de milhares ou de casas decimais. + Execute cálculos matemáticos, incluindo valores hexadecimais e funções avançadas como 'min(1,2,3)', 'sqrt(123)' e 'cos(123)'. Não é número (NN) Expressão errada ou incompleta (esqueceu-se de algum parêntese?) Copiar número para a área de transferência @@ -13,4 +13,5 @@ Ponto (.) Número máximo de casas decimais Falha ao copiar. Por favor tente mais tarde. + Mostrar mensagem de erro se o cálculo falhar diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ru.xaml index 43a7d44c7..7b40770cd 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ru.xaml @@ -1,8 +1,8 @@ - + Калькулятор - Позволяет выполнять математические вычисления. (Попробуйте 5*3-2 в Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Не является числом (NaN) Выражение неправильное или неполное (Вы забыли скобки?) Скопировать этот номер в буфер обмена @@ -13,4 +13,5 @@ Точка (.) Макс. число знаков после запятой Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml index 498b6eb50..f398ab3e2 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml @@ -1,8 +1,8 @@ - + Kalkulačka - Vykonávanie matematických výpočtov (vrátane hexadecimálnych hodnôt). Ako oddeľovač tisícov alebo desatinného miesta použite ',' alebo '.'. + Vykonávajte matematické výpočty vrátane hexadecimálnych hodnôt a pokročilých funkcií, ako napríklad "min(1,2,3)", "sqrt(123)" a "cos(123)". Nie je číslo (NaN) Nesprávny alebo neúplný výraz (Nezabudli ste na zátvorky?) Kopírovať výsledok do schránky @@ -13,4 +13,5 @@ Bodka (.) Desatinné miesta Kopírovanie zlyhalo, skúste to neskôr + Zobraziť chybovú správu, keď výpočet zlyhá diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr-Cyrl-RS.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr-Cyrl-RS.xaml index 98e3aebb5..405a39e92 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr-Cyrl-RS.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr-Cyrl-RS.xaml @@ -2,7 +2,7 @@ Calculator - Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Not a number (NaN) Expression wrong or incomplete (Did you forget some parentheses?) Copy this number to the clipboard @@ -13,4 +13,5 @@ Dot (.) Max. decimal places Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr.xaml index 2f2777aa1..405a39e92 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr.xaml @@ -1,8 +1,8 @@ - + Calculator - Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Not a number (NaN) Expression wrong or incomplete (Did you forget some parentheses?) Copy this number to the clipboard @@ -13,4 +13,5 @@ Dot (.) Max. decimal places Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/tr.xaml index b41fc0656..aec5bec43 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/tr.xaml @@ -1,8 +1,8 @@ - + Hesap Makinesi - Matematiksel hesaplamalar yapmaya yarar. (5*3-2 yazmayı deneyin) + Onaltılık değerler ve 'min(1,2,3)', 'sqrt(123)' ve 'cos(123)' gibi gelişmiş fonksiyonlar dahil olmak üzere matematiksel hesaplamalar gerçekleştirin. Sayı değil (NaN) İfade hatalı ya da eksik. (Parantez koymayı mı unuttunuz?) Bu sayıyı panoya kopyala @@ -13,4 +13,5 @@ Nokta (.) Maks. ondalık basamak Kopyalama başarısız oldu, lütfen daha sonra deneyin + Hesaplama başarısız olduğunda hata mesajı göster diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/uk-UA.xaml index 14042dffd..c2af4bbe3 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/uk-UA.xaml @@ -1,8 +1,8 @@ - + Калькулятор - Виконуйте математичні обчислення (включаючи шістнадцяткові значення). Використовуйте «,» або «.» як роздільник тисяч або десяткових знаків. + Виконуйте математичні розрахунки, включаючи шістнадцяткові значення та розширені функції, такі як «min(1,2,3)», «sqrt(123)» та «cos(123)». Не є числом (NaN) Вираз неправильний або неповний (Ви забули якісь дужки?) Скопіюйте це число в буфер обміну @@ -13,4 +13,5 @@ Крапка (.) Макс. кількість знаків після коми Копіювання не вдалося, спробуйте пізніше + Показувати повідомлення про помилку, якщо обчислення не вдалося diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/vi.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/vi.xaml index 20717d1db..6efbda3e4 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/vi.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/vi.xaml @@ -1,8 +1,8 @@ - + Máy tính - Cho phép thực hiện các phép tính toán học. (Thử 5*3-2 trong Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Không phải là số (NaN) Biểu thức sai hoặc không đầy đủ (Bạn có quên một số dấu ngoặc đơn không?) Sao chép số này vào clipboard @@ -13,4 +13,5 @@ dấu chấm (.) Tối đa. chữ số thập phân Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml index 445ed394f..234c613c6 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml @@ -1,8 +1,8 @@ - + 计算器 - 执行数学计算(包括十六进制值)。使用 , 或 . 作为分隔符或小数点。 + 进行数学计算,包括十六进制值和高级函数,如“最小(1,2,3)”、“sqrt(123)”和“cos123”等。 请输入数字 表达错误或不完整(您是否忘记了一些括号?) 将结果复制到剪贴板 @@ -13,4 +13,5 @@ 点(.) 小数点后最大位数 复制失败,请稍后再试 + 计算错误时显示错误消息 diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml index 7c8acf40b..b56e4660f 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml @@ -1,8 +1,8 @@ - + 計算機 - 為 Flow Launcher 提供數學計算功能。(試著在 Flow Launcher 輸入 5*3-2) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. 不是一個數 (NaN) Expression wrong or incomplete (Did you forget some parentheses?) 複製此數至剪貼簿 @@ -13,4 +13,5 @@ 點 (.) 小數點後最大位數 Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml index b2bf99515..608fe88a1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml @@ -22,6 +22,7 @@ حدث خطأ أثناء البحث: {0} تعذر فتح المجلد تعذر فتح الملف + This new action keyword is already assigned to another plugin, please choose a different one حذف diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml index 0acdb5ca1..2381d501b 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml @@ -22,6 +22,7 @@ Při vyhledávání došlo k chybě: {0} Adresář nelze otevřít Nelze otevřít soubor + This new action keyword is already assigned to another plugin, please choose a different one Smazat diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml index 66816de93..f5f13e5a3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Slet diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml index 8ddb958ad..8e352e614 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml @@ -22,6 +22,7 @@ Fehler aufgetreten während Suche: {0} Ordner konnte nicht geöffnet werden Datei konnte nicht geöffnet werden + This new action keyword is already assigned to another plugin, please choose a different one Löschen diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml index f80a55965..7379571a7 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Eliminar diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml index 474ba9a4c..0a1d73c28 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml @@ -22,6 +22,7 @@ Se ha producido un error durante la búsqueda: {0} No se ha podido abrir la carpeta No se ha podido abrir el archivo + This new action keyword is already assigned to another plugin, please choose a different one Eliminar diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml index 096cd4a0d..d9b767b9c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml @@ -22,6 +22,7 @@ Une erreur s'est produite pendant la recherche : {0} Impossible d'ouvrir le dossier Impossible d'ouvrir le fichier + This new action keyword is already assigned to another plugin, please choose a different one Supprimer diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml index a4e4445ae..a84d7707d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml @@ -22,6 +22,7 @@ אירעה שגיאה במהלך החיפוש: {0} לא ניתן היה לפתוח את התיקייה לא ניתן היה לפתוח את הקובץ + This new action keyword is already assigned to another plugin, please choose a different one מחק diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml index f3fa1e1e6..a88ad2da1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml @@ -22,6 +22,7 @@ Errore durante la ricerca: {0} Impossibile aprire la cartella Impossibile aprire il file + This new action keyword is already assigned to another plugin, please choose a different one Cancella diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml index d0b045175..8a701ebc6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml @@ -2,17 +2,17 @@ - Please make a selection first - Please select a folder path. - Please choose a different name or folder path. - Are you sure you want to delete this quick access link? - Are you sure you want to delete this index search excluded path? - Please select a folder link - Are you sure you want to delete {0}? - Are you sure you want to permanently delete this file? - Are you sure you want to permanently delete this file/folder? - Deletion successful - Successfully deleted {0} + 項目を選択してください + フォルダのパスを選択してください。 + 別の名前またはフォルダのパスを選択してください。 + このクイックアクセスリンクを削除してもよろしいですか? + このインデックス検索の除外パスを削除してもよろしいですか? + フォルダーのリンクを選択してください + {0} を削除してもよろしいですか? + このファイルを完全に削除してもよろしいですか? + このファイルやフォルダーを完全に削除してもよろしいですか? + 削除に成功 + {0} は正常に削除されました Assigning the global action keyword could bring up too many results during search. Please choose a specific action keyword Quick Access can not be set to the global action keyword when enabled. Please choose a specific action keyword The required service for Windows Index Search does not appear to be running @@ -20,8 +20,9 @@ The warning message has been switched off. As an alternative for searching files and folders, would you like to install Everything plugin?{0}{0}Select 'Yes' to install Everything plugin, or 'No' to return Explorer Alternative Error occurred during search: {0} - Could not open folder - Could not open file + フォルダーを開けませんでした + ファイルを開けませんでした + This new action keyword is already assigned to another plugin, please choose a different one 削除 @@ -31,7 +32,7 @@ アクションキーワードのカスタマイズ Customise Quick Access Quick Access Links - Everything Setting + Everything の設定 プレビューパネル サイズ 作成日時 @@ -39,8 +40,8 @@ File Age ファイル情報の表示 日付と時刻の形式 - Sort Option: - Everything Path: + 並べ替え方法: + Everything のパス: Launch Hidden Editor Path Shell Path @@ -64,16 +65,16 @@ Direct Enumeration ファイル エディターのパス フォルダー エディターのパス - Enabled - Disabled + 有効 + 無効 Content Search Engine Directory Recursive Search Engine Index Search Engine Windowsのインデックスオプションを開く Excluded File Types (comma seperated) - For example: exe,jpg,png - Maximum results + 例: exe,jpg,png + 結果の最大表示件数 The maximum number of results requested from active search engine @@ -81,17 +82,17 @@ Windows SearchまたはEverythingを使って、ファイルやフォルダーを検索・管理します - Ctrl + Enter to open the directory + Ctrl + Enter でフォルダーを開く Ctrl + Enter to open the containing folder {0}{4}Size: {1}{4}Date created: {2}{4}Date modified: {3} - Unknown + 不明 {0}{3}Space free: {1}{3}Total size: {2} パスをコピー 現在の項目のパスをコピー - Copy name - Copy name of current item to clipboard + 名前をコピー + 現在の項目の名前をクリップボードにコピーする コピー 現在のファイルをコピー 現在のフォルダーをコピー @@ -99,13 +100,13 @@ 現在のファイルを完全に削除 現在のフォルダーを完全に削除 名前 - Type - Path + 種類 + パス ファイル フォルダー - Delete the selected - Run as different user - Run the selected using a different user account + 選択したものを削除する + 別のユーザーとして実行 + 別のユーザーアカウントを使用して選択したものを実行する フォルダーを開く 現在の項目が含まれている場所を開きます エディターで開く: @@ -119,9 +120,9 @@ Windowsインデックスオプションを開けませんでした クイックアクセスに追加 現在の項目をクイックアクセスに追加 - Successfully Added + 正常に追加されました クイックアクセスに追加しました - Successfully Removed + 削除に成功しました Successfully removed from Quick Access エクスプローラーの検索アクティベーション用アクションキーワードで開けるように、クイックアクセスに追加します クイックアクセスから削除 @@ -130,81 +131,81 @@ Windowsの右クリックメニューを表示 アプリで開く 開くためのプログラムを選択します - Fail to delete {0} + {0} の削除に失敗しました File not found: {0} - Fail to open {0} - Fail to set text in clipboard - Fail to set files/folders in clipboard + {0} の削除に失敗しました + クリップボードにテキストをコピーできませんでした + ファイル/フォルダのコピーに失敗しました - {0} free of {1} - Open in Default File Manager + 空き領域 {1} 中の {0} + デフォルトのファイルマネージャーで開く Use '>' to search in this directory, '*' to search for file extensions or '>*' to combine both searches. - Failed to load Everything SDK - Warning: Everything service is not running - Error while querying Everything - Sort By - Name ↑ - Name ↓ - Path ↑ - Path ↓ - Size ↑ - Size ↓ - Extension ↑ - Extension ↓ - Type Name ↑ - Type Name ↓ - Date Created ↑ - Date Created ↓ - Date Modified ↑ - Date Modified ↓ + Everything SDK の読み込みに失敗しました + 警告: Everythingのサービスが実行されていません + Everything へのクエリ中にエラーが発生しました + 並べ替え順 + 名前 ↑ + 名前 ↓ + パス ↑ + パス ↓ + サイズ ↑ + サイズ ↓ + 拡張子 ↑ + 拡張子 ↓ + 種類名 ↑ + 種類名 ↓ + 作成日時 ↑ + 作成日時 ↓ + 更新日時 ↑ + 更新日時 ↓ Attributes ↑ Attributes ↓ File List FileName ↑ File List FileName ↓ - Run Count ↑ - Run Count ↓ + 実行回数 ↑ + 実行回数 ↓ Date Recently Changed ↑ Date Recently Changed ↓ - Date Accessed ↑ - Date Accessed ↓ - Date Run ↑ - Date Run ↓ + アクセス日時 ↑ + アクセス日時 ↓ + 実行日時 ↑ + 実行日時 ↓ - Warning: This is not a Fast Sort option, searches may be slow + 警告:これは高速な並べ替えオプションではありません。検索が遅くなる場合があります Search Full Path - Enable File/Folder Run Count + ファイル/フォルダの実行カウントを有効にする - Click to launch or install Everything - Everything Installation - Installing Everything service. Please wait... - Successfully installed Everything service - Failed to automatically install Everything service. Please manually install it from https://www.voidtools.com + クリックして Everything を起動またはインストール + Everything のインストール + Everything サービスをインストールしています。お待ちください… + Everything サービスを正常にインストールしました + Everything サービスを自動的にインストールできませんでした。https://www.voidtools.com から手動でインストールしてください Click here to start it Everythingのインストールが見つかりませんでした。手動で場所を指定しますか?{0}{0}「いいえ」をクリックすると、Everythingが自動的にインストールされます。 - Do you want to enable content search for Everything? - It can be very slow without index (which is only supported in Everything v1.5+) + Everything でのコンテンツ検索を有効にしますか? + インデックスなしでは非常に遅くなることがあります(Everything v1.5以降でのみサポートされています) - Unable to find Everything.exe - Failed to install Everything, please install it manually + Everything.exe が見つかりません + Everything のインストールに失敗しました。手動でインストールしてください - Native Context Menu - Display native context menu (experimental) - Below you can specify items you want to include in the context menu, they can be partial (e.g. 'pen wit') or complete ('Open with'). - Below you can specify items you want to exclude from context menu, they can be partial (e.g. 'pen wit') or complete ('Open with'). + Windowsのコンテキストメニュー + Windowsのコンテキストメニューを表示(実験的) + 以下では、コンテキストメニューに表示する項目を指定することができます。部分的 (例: 「開」)、または完全な項目名を指定することができます (「開く」)。 + 以下では、コンテキストメニューから除外する項目を指定することができます。部分的 (例: 「開」)、または完全な項目名を指定することができます (「開く」)。 - Today - {0} days ago - 1 month ago - {0} months ago - 1 year ago - {0} years ago + 今日 + {0} 日前 + 1 か月前 + {0} か月前 + 1 年前 + {0} 年前 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml index 3195ff6e5..e437926c8 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one 삭제 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml index 5efdead0c..b0672d3ad 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml @@ -22,6 +22,7 @@ Feil oppstod under søk: {0} Kunne ikke åpne mappe Kunne ikke åpne fil + This new action keyword is already assigned to another plugin, please choose a different one Slett diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml index cc6d350c9..3de4ce5e5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Verwijder diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml index c981c2832..1a01e8b90 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml @@ -22,6 +22,7 @@ Wystąpił błąd podczas wyszukiwania: {0} Nie można otworzyć folderu Nie można otworzyć pliku + This new action keyword is already assigned to another plugin, please choose a different one Usuń diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml index fe4fa320a..9a3a4ffeb 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Apagar diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml index d0651cc53..2d33768f9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml @@ -22,6 +22,7 @@ Ocorreu um erro ao pesquisar: {0} Não foi possível abrir a pasta Não foi possível abrir o ficheiro + This new action keyword is already assigned to another plugin, please choose a different one Eliminar diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml index 1644745ae..cb28fcfd5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml @@ -22,6 +22,7 @@ При поиске произошла ошибка: {0} Не удалось открыть папку Не удалось открыть файл + This new action keyword is already assigned to another plugin, please choose a different one Удалить @@ -57,14 +58,14 @@ Quick Access: Current Action Keyword Подтвердить - Enabled + Включено When disabled Flow will not execute this search option, and will additionally revert back to '*' to free up the action keyword Everything Windows Index Direct Enumeration Путь к редактору файлов Путь к редактору папки - Enabled + Включено Отключён Content Search Engine diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml index 3ca738b69..1350969b6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml @@ -22,6 +22,7 @@ Počas vyhľadávania došlo k chybe: {0} Nepodarilo sa otvoriť priečinok Nepodarilo sa otvoriť súbor + Nový aktivačný príkaz už bol priradený inému pluginu, prosím, zvoľte iný aktivačný príkaz Odstrániť diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml index 19fe6dc64..e7979f6dd 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Delete diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml index f8effbd7c..ef7e6a5c3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Obriši diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml index aefe8af30..3e491ea22 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml @@ -22,6 +22,7 @@ Arama sırasında hata oluştu: {0} Klasör açılamadı Dosya açılamadı + This new action keyword is already assigned to another plugin, please choose a different one Sil @@ -123,7 +124,7 @@ Hızlı Erişim'e başarıyla eklendi Başarıyla Kaldırıldı Hızlı Erişim'den başarıyla kaldırıldı - Add to Quick Access so it can be opened with Explorer's Search Activation action keyword + Dosya Gezgini'nin Arama Etkinleştirme anahtar sözcüğü ile açılabilmesi için Hızlı Erişim'e ekleyin Hızlı Erişimden Kaldır Hızlı Erişimden Kaldır Geçerli öğeyi Hızlı Erişim'den kaldır diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml index 823c33193..60a08a82f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml @@ -22,6 +22,7 @@ Виникла помилка під час пошуку: {0} Не вдалося відкрити папку Не вдалося відкрити файл + This new action keyword is already assigned to another plugin, please choose a different one Видалити diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml index 7b64af3d8..6416fc447 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml @@ -22,6 +22,7 @@ Đã xảy ra lỗi trong quá trình tìm kiếm: {0} Không thể mở thư mục Không thể mở file + This new action keyword is already assigned to another plugin, please choose a different one Xóa diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml index 8ad979ac8..1cab71d8d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml @@ -22,6 +22,7 @@ 搜索时发生错误:{0} 无法打开文件夹 无法打开文件 + This new action keyword is already assigned to another plugin, please choose a different one 删除 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml index 39f260499..d64cd7698 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one 刪除 diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ja.xaml index 893948d3d..85188e622 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ja.xaml @@ -1,9 +1,9 @@  - Activate {0} plugin action keyword + {0} プラグインのアクションキーワード - Plugin Indicator - Provides plugins action words suggestions + プラグインインジケーター + プラグインのアクションキーワードの一覧を検索します diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ja.xaml index d62f0f61b..f51b692e6 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ja.xaml @@ -2,69 +2,69 @@ - Downloading plugin - Successfully downloaded - Error: Unable to download the plugin - {0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart. - {0} by {1} {2}{2}Would you like to uninstall this plugin? - {0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart. - {0} by {1} {2}{2}Would you like to install this plugin? - Plugin Install - Installing Plugin - Download and install {0} - Plugin Uninstall - Keep plugin settings - Do you want to keep the settings of the plugin for the next usage? + プラグインをダウンロード中 + {0} のダウンロードに成功 + エラー: プラグインをダウンロードできません + {0} by {1} {2}{3}このプラグインをアンインストールしますか?アンインストール後、Flow Launcherは自動的に再起動されます。 + {0} by {1} {2}{2}このプラグインをアンインストールしますか? + {0} by {1} {2}{3}このプラグインをインストールしますか?インストール後、Flow Launcherは自動的に再起動されます。 + {0} by {1} {2}{2}このプラグインをインストールしますか? + プラグインのインストール + プラグインをインストール中 + {0} をダウンロードしてインストール中 + プラグインのアンインストール + プラグインの設定を保持 + 再びインストールして使用するときのためにプラグインの設定を維持しますか? Plugin successfully installed. Restarting Flow, please wait... - Unable to find the plugin.json metadata file from the extracted zip file. - Error: A plugin which has the same or greater version with {0} already exists. - Error installing plugin - Error occurred while trying to install {0} - Error uninstalling plugin - No update available - All plugins are up to date - {0} by {1} {2}{3}Would you like to update this plugin? After the update Flow will automatically restart. - {0} by {1} {2}{2}Would you like to update this plugin? - Plugin Update - This plugin is already installed - Plugin Manifest Download Failed - Please check if you can connect to github.com. This error means you may not be able to install or update plugins. - Update all plugins - Would you like to update all plugins? - Would you like to update {0} plugins?{1}Flow Launcher will restart after updating all plugins. - Would you like to update {0} plugins? - {0} plugins successfully updated. Restarting Flow, please wait... - Plugin {0} successfully updated. Restarting Flow, please wait... - Installing from an unknown source - You are installing this plugin from an unknown source and it may contain potential risks!{0}{0}Please ensure you understand where this plugin is from and that it is safe.{0}{0}Would you like to continue still?{0}{0}(You can switch off this warning via settings) + 展開されたzipファイルからplugin.jsonメタデータファイルが見つかりません。 + エラー: {0} と同じまたはそれ以上のバージョンを持つプラグインが既に存在します。 + プラグインのインストール失敗 + {0} のインストール中にエラーが発生しました + プラグインのアンインストール失敗 + 利用可能な更新はありません + すべてのプラグインが最新です + {0} by {1} {2}{3}このプラグインを更新しますか?更新後、Flow Launcherは自動的に再起動されます。 + {0} by {1} {2}{2}このプラグインを更新しますか? + プラグインの更新 + このプラグインは既にインストールされています + プラグインマニフェストのダウンロードに失敗 + github.com に接続できるかどうかを確認してください。このエラーはプラグインをインストールまたは更新できないことを意味します。 + すべてのプラグインを更新 + すべてのプラグインを更新しますか? + {0} 個のプラグインを更新してもよいですか?{1}すべてのプラグインを更新した後、Flow Launcher が再起動します。 + {0} 個のプラグインを更新してもよいですか? + {0} 個のプラグインが正常に更新されました。Flow を再起動しています。お待ちください… + プラグイン {0} が正常に更新されました。Flow を再起動しています。お待ちください… + 不明なソースからインストール中 + あなたは不明なソースから提供されたプラグインをインストールしようとしており、潜在的なリスクを含んでいる可能性があります!{0}{0}このプラグインの開発元をよく調べ、安全であることをご自身で確かめてください。{0}{0}それでもあなたはこのプラグインをインストールしますか?{0}{0}(この警告は設定で無効にすることができます) - Plugin {0} successfully installed. Please restart Flow. - Plugin {0} successfully uninstalled. Please restart Flow. - Plugin {0} successfully updated. Please restart Flow. - {0} plugins successfully updated. Please restart Flow. - Plugin {0} has already been modified. Please restart Flow before making any further changes. - {0} modified already - Please restart Flow before making any further changes + プラグイン {0} のインストールに成功しました。Flow を再起動してください。 + プラグイン {0} のアンインストールに成功しました。Flow を再起動してください。 + プラグイン {0} が正常に更新されました。Flow を再起動してください。 + {0} 個のプラグインが正常に更新されました。Flow を再起動してください。 + プラグイン {0} は既に変更されています。Flow Launcher を再起動してからもう一度お試しください。 + {0} は既に変更されています + これ以上変更を加える前に Flow Launcher を再起動してください - Invalid zip installer file - Please check if there is a plugin.json in {0} + 無効な zip インストーラーファイル + {0} に plugin.json があるか確認してください - Plugins Manager - Install, uninstall or update Flow Launcher plugins via the search window - Unknown Author + プラグインマネージャー + 検索ウィンドウから Flow Launcher のプラグインをインストール、アンインストール、または更新する + 不明な作者 - Open website - Visit the plugin's website - See source code - See the plugin's source code - Suggest an enhancement or submit an issue - Suggest an enhancement or submit an issue to the plugin developer - Go to Flow's plugins repository - Visit the PluginsManifest repository to see community-made plugin submissions + ウェブサイトを開く + プラグインのウェブサイトを開く + ソースコードを参照 + プラグインのソースコードを見る + 改善を提案するか、問題を報告してください + プラグイン開発者に機能改善を提案するか問題を報告してください + Flow のプラグインリポジトリに移動 + PluginsManifest リポジトリにアクセスして、コミュニティで作られたプラグインを表示する 不明な提供元からインストールするとき警告する - Restart Flow Launcher automatically after installing/uninstalling/updating plugin via Plugins Manager + プラグインマネージャー経由でプラグインをインストール、アンインストール、または更新した後、Flow Lancher を自動的に再起動します diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ru.xaml index 18913c7c6..5ecd203f8 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ru.xaml @@ -56,8 +56,8 @@ Перейти на сайт - Visit the plugin's website - See source code + Перейти на сайт плагина + Посмотреть исходный код See the plugin's source code Suggest an enhancement or submit an issue Suggest an enhancement or submit an issue to the plugin developer diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml index f788c9ce3..22d8aee6e 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml @@ -66,5 +66,5 @@ Upozornenie na inštaláciu z neznámeho zdroja - Automaticky reštartovať Flow Launcher po inštalácii/odinštalácii/aktualizáciu pluginu cez Správcu pluginov + Automaticky reštartovať Flow Launcher po inštalácii/odinštalácii/aktualizácii pluginu cez Správcu pluginov diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml index 0a7176d2c..bda1ec5f5 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml @@ -1,14 +1,14 @@  - Process Killer - Kill running processes from Flow Launcher + プロセスキラー + Flow Launcherから実行中のプロセスを終了します - kill all instances of "{0}" - kill {0} processes - kill all instances + "{0}" のすべてのインスタンスを終了する + {0} プロセスを終了する + すべてのインスタンスを終了する - Show title for processes with visible windows - Put processes with visible windows on the top + ウィンドウが表示されているプロセスのタイトルを表示する + ウィンドウが表示されているプロセスを上に表示する diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/ja.xaml index 0134627c5..38879713d 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/ja.xaml @@ -2,98 +2,98 @@ - Reset Default + デフォルトにリセット 削除 編集 追加 名前 - 有効 - Enabled - 無効 - Status - Enabled - Disabled + 有効化 + 有効 + 無効化 + 状態 + 有効 + 無効 場所 - All Programs - File Type - Reindex - Indexing - Index Sources - Options - UWP Apps - When enabled, Flow will load UWP Applications - Start Menu - When enabled, Flow will load programs from the start menu - Registry - When enabled, Flow will load programs from the registry - PATH - When enabled, Flow will load programs from the PATH environment variable + すべてのプログラム + ファイルの種類 + 再読み込み + インデックス作成中 + インデックスのソース + オプション + UWP アプリ + 有効にすると、Flow は UWP アプリケーションを読み込みます + スタートメニュー + 有効にすると、Flowはスタートメニューからプログラムを読み込みます + レジストリー + 有効にすると、Flowはレジストリーからプログラムを読み込みます + PATH変数 + 有効にすると、Flow は環境変数のPATHに登録されたフォルダーからプログラムを読み込みます アプリのパスを非表示 UWPやlnkなどの実行可能ファイルについて、サブタイトル領域にファイルパスが表示されないようにします。 - Hide uninstallers - Hides programs with common uninstaller names, such as unins000.exe + アンインストーラーを非表示 + unins000.exe のような一般的な名前のアンインストーラのプログラムを非表示にします プログラムの説明で検索 - Flow will search program's description - Hide duplicated apps - Hide duplicated Win32 programs that are already in the UWP list - Suffixes - Max Depth + Flow はプログラムの説明を検索します + 重複したアプリを非表示 + UWPリストに既に存在するアプリと同じ名前の、Win32プログラムを非表示にする + 接尾辞 + 最大の深さ - Directory: - Browse - File Suffixes: - Maximum Search Depth (-1 is unlimited): + フォルダー + 選択 + ファイル名の末尾: + 最大の検索の深さ (-1に設定すると無制限): - Please select a program source - Are your sure to delete {0}? - Please select program sources that are not added by you - Please select program sources that are added by you - Another program source with the same location already exists. + プログラムのソースを選択してください + 選択したプログラムソースを削除してもよろしいですか? + あなたが追加していないプログラムのソースを選択してください + あなたが追加したプログラムのソースを選択してください + 同じ場所を持つ別のプログラムのソースが既に存在します。 - Program Source - Edit directory and status of this program source. + プログラムのソース + このプログラムのソースのフォルダーとステータスを編集します。 更新 - Program Plugin will only index files with selected suffixes and .url files with selected protocols. + プログラムプラグインは、選択されたファイル名の末尾と .url ファイルのみをインデックス化します。 Sucessfully update file suffixes - File suffixes can't be empty - Protocols can't be empty + ファイル名の末尾は空にできません + プロトコルは空にできません Index file suffixes - URL Protocols - Steam Games - Epic Games + ショートカット(URL) + Steam ゲーム + Epic ゲーム Http/Https - Custom URL Protocols - Custom File Suffixes + カスタムURLプロトコルを指定 + カスタムファイル名の末尾を指定 - Insert file suffixes you want to index. Suffixes should be separated by ';'. (ex>bat;py) + インデックスするファイル名の末尾を入力してください。サフィックスは';'で区切る必要があります。(例>bat;py) - Insert protocols of .url files you want to index. Protocols should be separated by ';', and should end with "://". (ex>ftp://;mailto://) + インデックスしたい.urlファイルのプロトコルを入力してください。プロトコルは';'で区切られ、"://"で終了する必要があります。(例>ftp://;mailto://) 別のユーザーとして実行 管理者として実行 - Open containing folder - Hide - Open target folder + 保存先のフォルダーを開く + 非表示にする + ターゲットフォルダーを開く プログラム Flow Launcherでプログラムを検索 - Invalid Path + 不正なパス - Customized Explorer - Args - 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. - Enter the customized args you want to add for your customized explorer. %s for parent directory, %f for full path (which only works for win32). Check the explorer's website for details. + カスタムされたエクスプローラー + 引数 + エクスプローラーで使用したい環境変数を入力することで、コンテナフォルダを開く際に使用するエクスプローラをカスタマイズできます。 環境変数が利用可能かどうかをテストするために、コマンドプロンプトを使用すると便利です。 + カスタマイズされたエクスプローラに追加したいカスタムの引数を入力します。 %s は親ディレクトリ、 %f はフルパス (win32でのみ動作します)です。 詳細についてはエクスプローラのウェブサイトをご覧ください。 - 成功しまし - Error - Successfully disabled this program from displaying in your query - This app is not intended to be run as administrator - Unable to run {0} + 成功しました + エラー + このプログラムは検索結果に表示されなくなりました + このアプリは管理者として実行されることを想定されていません + {0} を実行できません diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Shell/Languages/ja.xaml index 440d33697..475a6b4fb 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Shell/Languages/ja.xaml @@ -1,20 +1,20 @@  - Replace Win+R - Close Command Prompt after pressing any key - Press any key to close this window... - Do not close Command Prompt after command execution - Always run as administrator - Use Windows Terminal - Run as different user - Shell - Allows to execute system commands from Flow Launcher - this command has been executed {0} times - execute command through command shell + Win+Rを置き換え + 任意のキーを押して、実行後のコマンドプロンプトを閉じる + このウィンドウを閉じるには、任意のキーを押してください… + コマンド実行後にコマンドプロンプトを閉じない + 常に管理者として実行 + Windows ターミナルを使用する + 別のユーザーとして実行 + シェル + Flow Launcherからシステムコマンドを実行できます + このコマンドは {0} 回実行されました + コマンドシェル経由でコマンドを実行する 管理者として実行 - Copy the command - Only show number of most used commands: - Command not found: {0} - Error running the command: {0} + コマンドをコピー + コマンド履歴に表示されるコマンドの最大数: + コマンドが見つかりません: {0} + コマンド実行中にエラーが発生しました: {0} diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml index 398c39c9f..00aa91fb9 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml @@ -8,12 +8,12 @@ シャットダウン 再起動 - Restart With Advanced Boot Options - Log Off/Sign Out - Lock - Sleep - Hibernate - Index Option + 詳細ブートオプションで再起動 + ログオフ / サインアウト + ロック + スリープ + 休止状態 + 検索のオプション ごみ箱を空にする ごみ箱を開く 終了 @@ -21,19 +21,19 @@ Flow Launcherを再起動する 設定 プラグインデータのリロード - Check For Update - Open Log Location - Flow Launcher Tips - Flow Launcher UserData Folder - Toggle Game Mode - Set the Flow Launcher Theme + 更新を確認 + ログの場所を開く + Flow Launcher のヒント + Flow Launcher のユーザーデータフォルダー + ゲームモードの切り替え + Flow Launcher のテーマを設定 編集 コンピュータをシャットダウンする コンピュータを再起動する - Restart the computer with Advanced Boot Options for Safe and Debugging modes, as well as other options + セーフモードおよびデバッグモードやその他のオプションを使用するため、コンピュータを再起動して詳細ブートオプションを表示します ログオフ このコンピュータをロックする Flow Launcherを終了する @@ -42,36 +42,36 @@ スリープ ゴミ箱を空にする ごみ箱を開く - Indexing Options - Hibernate computer - Save all Flow Launcher settings - Refreshes plugin data with new content - Open Flow Launcher's log location - Check for new Flow Launcher update - Visit Flow Launcher's documentation for more help and how to use tips - Open the location where Flow Launcher's settings are stored - Toggle Game Mode - Quickly change the Flow Launcher theme + インデックスのオプション + コンピューターを休止状態にする + Flow Launcher の全ての設定を保存 + プラグインのデータを再読み込みし、新しいコンテンツを適用する + Flow Launcher のログがある場所を開く + 新しい Flow Launcher の更新を確認する + Flow Launcher のドキュメントを開いて、ヘルプと使い方のヒントを確認する + Flow Launcher の設定が保存されている場所を開く + ゲームモードの切り替え + Flow Launcher のテーマを素早く変更する - 成功しまし - All Flow Launcher settings saved - Reloaded all applicable plugin data - Are you sure you want to shut the computer down? + 成功 + Flow Launcher のすべての設定が保存されました + 該当するすべてのプラグインデータを再読み込みしました + 本当にコンピューターをシャットダウンしますか? 本当にコンピューターを再起動しますか? 高度な起動オプションでコンピューターを再起動しますか? 本当にログオフしますか? - Error - Failed to empty the recycle bin. This might happen if:{0}- Some items are currently in use{0}- Some items can't be deleted due to permissions{0}Please close any applications that might be using these files and try again. + エラー + ゴミ箱を空にできませんでした。以下の原因が考えられます:{0}ー 現在使用中のアイテムがある{0}- 権限が原因で削除できないアイテムがある{0}ファイルを使用しているアプリケーションを終了してから、再度お試しください。 - Command Keyword Setting - Custom Command Keyword - Enter a keyword to search for command: {0}. This keyword is used to match your query. - Command Keyword + コマンドキーワードの設定 + カスタムのコマンドキーワード + コマンド: {0}を検索するキーワードを入力してください。このキーワードはクエリに一致するために使用されます。 + コマンドキーワード リセット 確認 キャンセル - Please enter a non-empty command keyword + 空でないコマンドキーワードを入力してください システムコマンド システム関連のコマンドを提供します。例:シャットダウン、ロック、設定など diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml index 69746e836..0313a7918 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml @@ -69,11 +69,11 @@ 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.Url/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml index 532ff793d..4275713a1 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml @@ -1,9 +1,9 @@  - Open search in: - New Window - New Tab + 検索を開く: + 新しいウィンドウ + 新しいタブ 次のURLを開く:{0} 次のURLを開くことができません:{0} @@ -11,7 +11,7 @@ URL 入力したURLをFlow Launcherから開くプラグインです。 - Please set your browser path: - Choose + ブラウザのパスを設定してください: + 選択 Application(*.exe)|*.exe|All files|*.* diff --git a/Plugins/Flow.Launcher.Plugin.Url/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/ru.xaml index 5110f65ef..15c1eeadb 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/ru.xaml @@ -2,8 +2,8 @@ Open search in: - New Window - New Tab + Новое окно + Новая вкладка Open url:{0} Can't open url:{0} diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml index 16c5fb3e9..ebc7d6196 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml @@ -1,37 +1,38 @@  - Search Source Setting - Open search in: - New Window - New Tab - Set browser from path: - Choose + 検索ソース設定 + 検索を開く: + 新しいウィンドウ + 新しいタブ + 以下のパスからブラウザーを設定: + 選択 削除 編集 追加 - Enabled - Private Mode - Enabled - Disabled - Confirm + 有効化 + プライベートモード + 有効 + 無効 + 確認 キーワード URL 検索 - Use Search Query Autocomplete - Autocomplete Data from: + 検索クエリのサジェストを有効にする + サジェストデータの情報源: web検索を選択してください - Are you sure you want to delete {0}? - If you want to add a search for a particular website to Flow, first enter a dummy text string in the search bar of that website, and launch the search. Now copy the contents of the browser's address bar, and paste it in the URL field below. Replace your test string with {q}. For example, if you search for casino on Netflix, its address bar reads - https://www.netflix.com/search?q=Casino + {0} を削除してもよろしいですか? + 特定のウェブサイトでの検索をFlowに追加したい場合、まず、 ウェブサイトの検索バーにダミーの文字列を入力して検索を開始します。 次に、ブラウザのアドレスバーの内容をコピーし、下のURLフィールドに貼り付けます。 テスト文字列を {q}に置き換えます。例えば、Netflixでカジノを検索すると、アドレスバーは以下のようになります + https://www.netflix.com/search?q=Casino - Now copy this entire string and paste it in the URL field below. - Then replace casino with {q}. - Thus, the generic formula for a search on Netflix is https://www.netflix.com/search?q={q} + コピーしたURLを下のURL欄に貼り付けてください。 + 次に、casinoという文字列を{q}に置き換えます。 + すると、Netflixで検索を行うためのURLは以下のようになります +https://www.netflix.com/search?q={q} - Copy URL - Copy search URL to clipboard + URL をコピー + 検索URLをクリップボードにコピーする タイトル @@ -44,7 +45,7 @@ キーワードを入力してください URLを入力してください キーワードはすでに存在します。違うキーワードを入力してください - 成功しまし + 成功しました Hint: You do not need to place custom images in this directory, if Flow's version is updated they will be lost. Flow will automatically copy any images outside of this directory across to WebSearch's custom image location. Web検索 diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml index 67435b5b9..6539f9617 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml @@ -3,25 +3,25 @@ Search Source Setting Open search in: - New Window - New Tab + Новое окно + Новая вкладка Установить браузер по пути: Выберите Удалить Редактировать Добавить - Enabled + Включено Приватный режим - Enabled + Включено Отключён - Confirm + Подтвердить Action Keyword URL - Search + Поиск Use Search Query Autocomplete Autocomplete Data from: Please select a web search - Are you sure you want to delete {0}? + Вы уверены, что хотите удалить {0}? If you want to add a search for a particular website to Flow, first enter a dummy text string in the search bar of that website, and launch the search. Now copy the contents of the browser's address bar, and paste it in the URL field below. Replace your test string with {q}. For example, if you search for casino on Netflix, its address bar reads https://www.netflix.com/search?q=Casino @@ -34,13 +34,13 @@ Copy search URL to clipboard - Title + Название Состояние - Select Icon - Icon + Выбрать иконку + Иконка Отменить Invalid web search - Please enter a title + Пожалуйста, укажите название Please enter an action keyword Please enter a URL Action keyword already exists, please enter a different one diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx index 6625a42dd..3a2f991a1 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx @@ -251,10 +251,10 @@ アプリ - クロックとリージョン + 時計とリージョン - Control Panel + コントロールパネル Cortana @@ -456,7 +456,7 @@ Area Personalization - + コマンド The command to direct start a setting @@ -468,7 +468,7 @@ Area Privacy - Control Panel + コントロールパネル Type of the setting is a "(legacy) Control Panel setting" @@ -1117,7 +1117,7 @@ Area Control Panel (legacy settings) - + パスワード password.cpl @@ -1667,7 +1667,7 @@ Area UserAccounts - Windows Insider Program + Windows Insider プログラム Area UpdateAndSecurity @@ -2314,7 +2314,7 @@ View all problem reports - 16-Bit Application Support + 16 ビットアプリケーションのサポート Set up dialling rules @@ -2326,10 +2326,10 @@ Give administrative rights to a domain user - Choose when to turn off display + 表示をオフにするタイミングを選択 - Move the pointer with the keypad using MouseKeys + マウスキーを使用してキーパッドでポインタを移動する Change Windows SideShow-compatible device settings @@ -2338,16 +2338,16 @@ Adjust commonly used mobility settings - Change text-to-speech settings + テキスト読み上げの設定を変更 - Set the time and date + 時刻と日付を設定 - Change location settings + 位置情報の設定を変更 - Change mouse settings + マウスの設定を変更 Manage Storage Spaces @@ -2362,46 +2362,46 @@ Change system sounds - Adjust ClearType text + ClearTypeテキストを調整 - Turn screen saver on or off + スクリーンセーバーのオン/オフを切り替え - Find and fix windows update problems + Windows Update の問題を見つけて修正 - Change Bluetooth settings + Bluetooth 設定の変更 - Connect to a network + ネットワークに接続 - Change the search provider in Internet Explorer + Internet Explorer の検索プロバイダを変更する Join a domain - Add a device + 端末を追加 - Find and fix problems with Windows Search + Windows検索の問題を見つけて解決 - Choose a power plan + 電源プランを選択 Change how the mouse pointer looks when it’s moving - Uninstall a program + プログラムのアンインストール Create and format hard disk partitions - Change date, time or number formats + 日付、時刻、数の書式を変更 Change PC wake-up settings @@ -2416,10 +2416,10 @@ Manage advanced sharing settings - Change battery settings + バッテリー設定の変更 - Rename this computer + このコンピューターの名前を変更 Lock or unlock the taskbar @@ -2431,7 +2431,7 @@ Change the time zone - Start speech recognition + 音声認識を開始 View installed updates @@ -2458,34 +2458,34 @@ Restore data, files or computer from backup (Windows 7) - Set your default programs + 既定のプログラムを設定 Set up a broadband connection - Calibrate the screen for pen or touch input + ペンまたはタッチ入力の画面をキャリブレーション Manage user certificates - Schedule tasks + タスクのスケジュール - Ignore repeated keystrokes using FilterKeys + フィルタキーを使用して繰り返しのキー入力を無視 - Find and fix bluescreen problems + ブルースクリーンの問題を見つけて修正 Hear a tone when keys are pressed - Delete browsing history + 閲覧履歴を削除 - Change what the power buttons do + 電源ボタンの動作を変更 Create standard user account @@ -2494,21 +2494,21 @@ Take speech tutorials - View system resource usage in Task Manager + タスク マネージャーでシステム リソースの使用状況を表示 - Create an account + アカウントを新規作成 - Get more features with a new edition of Windows + Windowsの新しいエディションでより多くの機能を入手 - Control Panel + コントロールパネル TaskLink - Unknown + 不明 \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.tr-TR.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.tr-TR.resx index d920e7550..746499a42 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.tr-TR.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.tr-TR.resx @@ -1773,13 +1773,13 @@ Sorunları bul ve düzelt - Change settings for content received using Tap and send + Dokun ve gönder kullanılarak alınan içerik için ayarları değiştir Medya veya cihazlar için varsayılan ayarları değiştir - Print the speech reference card + Konuşma referans kartını yazdır Ekran rengini kalibre et @@ -1815,13 +1815,13 @@ Fare düğmelerini özelleştir - Set tablet buttons to perform certain tasks + Belirli görevleri gerçekleştirmek için tablet düğmelerini ayarla Yüklü yazı tiplerini görüntüle - Change the way currency is displayed + Para biriminin görüntülenme şeklini değiştirme Grup ilkesini düzenle @@ -1908,7 +1908,7 @@ Güvenilirlik geçmişini görüntüle - Access RemoteApp and desktops + RemoteApp ve masaüstlerine eriş ODBC veri kaynaklarını ayarla @@ -1926,7 +1926,7 @@ Microsoft Pinyin SimpleFast Seçenekleri - Change what closing the lid does + Güç düğmesiyle kapatmanın ne yapacağını değiştirin Gereksiz animasyonları kapat @@ -1935,16 +1935,16 @@ Geri yükleme noktası oluştur - Turn off automatic window arrangement + Otomatik pencere düzenlemesini kapatın Sorun Giderme Geçmişi - Diagnose your computer's memory problems + Bilgisayarınızın bellek sorunlarını teşhis edin - View recommended actions to keep Windows running smoothly + Windows'un sorunsuz çalışmasını sağlamak için önerilen eylemleri görüntüleyin İmleç yanıp sönme hızını değiştir @@ -1956,22 +1956,22 @@ Parola sıfırlama diski oluştur - Configure advanced user profile properties + Gelişmiş kullanıcı profili özelliklerini yapılandır - Start or stop using AutoPlay for all media and devices + Tüm medya ve aygıtlar için Otomatik Kullan'ı etkinleştir veya devre dışı bırak - Change Automatic Maintenance settings + Otomatik Bakım ayarlarını değiştir Açmak için tek veya çift tıkla - Select users who can use remote desktop + Uzak masaüstünü kullanabilecek kullanıcıları seç - Show which programs are installed on your computer + Bilgisayarımda hangi programların yüklü olduğunu göster Bilgisayarınıza uzaktan erişime izin ver @@ -1986,22 +1986,22 @@ Klavyenin çalışma şeklini değiştir - Automatically adjust for daylight saving time + Gün ışığından yararlanma saatine göre otomatik ayarla - Change the order of Windows SideShow gadgets + Windows SideShow araçlarının sırasını değiştir Klavye durumunu kontrol et - Control the computer without the mouse or keyboard + Bilgisayarı fare veya klavye olmadan kontrol et Bir programı değiştir veya kaldır - Change multi-touch gesture settings + Çoklu dokunma hareketi ayarlarını değiştir ODBC veri kaynaklarını ayarla (64-bit) @@ -2016,7 +2016,7 @@ Görev çubuğunda benzer pencereleri gruplama - Change Windows SideShow settings + Windows SideShow ayarlarını değiştir Video için sesli açıklama kullan @@ -2058,13 +2058,13 @@ Çevrim dışı dosyaları yönet - Review your computer's status and resolve issues + Bilgisayarınızın durumunu gözden geçirin ve sorunları çözün Microsoft ChangJie Ayarları - Replace sounds with visual cues + Sesleri görsel ipuçlarıyla değiştirin Geçici İnternet dosyası ayarlarını değiştir @@ -2082,7 +2082,7 @@ Kurtarma anahtarınızı yedekleyin - Save backup copies of your files with File History + Dosya Geçmişi ile dosyalarınızın yedek kopyalarını kaydedin Geçerli erişilebilirlik ayarlarını görüntüle @@ -2103,7 +2103,7 @@ Sistem ses seviyesini ayarla - Defragment and optimise your drives + Sürücülerinizi birleştirin ve optimize edin ODBC veri kaynaklarını ayarla (32-bit) @@ -2112,16 +2112,16 @@ Yazı Tipi Ayarlarını Değiştir - Magnify portions of the screen using Magnifier + Büyüteç kullanarak ekranın bazı bölümlerini büyütme - Change the file type associated with a file extension + Bir dosya uzantısı ile ilişkili dosya türünü değiştir Olay günlüklerini görüntüle - Manage Windows Credentials + Windows Kimlik Bilgilerini Yönet Bir mikrofon ayarla @@ -2173,10 +2173,10 @@ Fare tıklama ayarlarını değiştir - Change advanced colour management settings for displays, scanners and printers + Ekranlar, tarayıcılar ve yazıcılar için gelişmiş renk yönetimi ayarlarını değiştirme - Let Windows suggest Ease of Access settings + Windows'un Erişim Kolaylığı ayarlarını önermesine izin verin Gereksiz dosyaları silerek disk alanını temizle @@ -2188,7 +2188,7 @@ Özel Karakter Düzenleyici - Record steps to reproduce a problem + Bir sorunu yeniden üretmek için adımları kaydedin Windows'un görünümünü ve performansını ayarla @@ -2209,7 +2209,7 @@ Windows'un arama şeklini değiştir - Set flicks to perform certain tasks + Belirli görevleri gerçekleştirmek için fiskeleri ayarla Hesap türünü değiştir @@ -2239,13 +2239,13 @@ Bağlantıları nasıl açacağınızı seçin - Allow Remote Assistance invitations to be sent from this computer + Bu bilgisayara Uzaktan Yardım bağlantılarına izin ver Görev Yöneticisi - Turn flicks on or off + Fiskeleri açın veya kapatın Bir dil ekleyin @@ -2254,7 +2254,7 @@ Ağ durumunu ve görevlerini görüntüle - Turn Magnifier on or off + Büyüteci aç veya kapat Bu bilgisayarın adına bakın @@ -2320,22 +2320,22 @@ Arama kurallarını ayarla - Enable or disable session cookies + Oturum çerezlerini etkinleştir veya devre dışı bırak - Give administrative rights to a domain user + Bir etki alanı kullanıcısına yönetici hakları verme - Choose when to turn off display + Ekranın ne zaman kapatılacağını seçin - Move the pointer with the keypad using MouseKeys + MouseKeys kullanarak imleci tuş takımıyla hareket ettirme - Change Windows SideShow-compatible device settings + Windows SideShow uyumlu cihaz ayarlarını değiştir - Adjust commonly used mobility settings + Sık kullanılan mobilite ayarlarını yapın Metinden sese ayarlarını değiştir @@ -2362,7 +2362,7 @@ Sistem seslerini değiştir - Adjust ClearType text + ClearType metnini ayarla Ekran koruyucuyu aç/kapat @@ -2392,7 +2392,7 @@ Bir güç planı seç - Change how the mouse pointer looks when it’s moving + Fare işaretçisinin hareket ederken nasıl görüneceğini değiştir Bir program kaldır @@ -2443,7 +2443,7 @@ Dosya ve klasörler için arama seçeneklerini değiştir - Adjust settings before giving a presentation + Sunum yapmadan önce ayarları yapın Bir belgeyi veya resmi tara @@ -2464,7 +2464,7 @@ Geniş bant bağlantısı kur - Calibrate the screen for pen or touch input + Kalem veya dokunmatik giriş için ekranı kalibre edin Kullanıcı sertifikalarını yönet @@ -2473,7 +2473,7 @@ Görevleri planla - Ignore repeated keystrokes using FilterKeys + Filtre Tuşları kullanarak tekrarlanan tuş vuruşlarını yok say Mavi ekran sorunlarını bul ve düzelt From 6fca1c919e8a654b1829ae9efa771b0593f6f1f9 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 21 Sep 2025 20:07:18 +0800 Subject: [PATCH 37/73] Fix issue in PortableDataLocationInUse --- Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs | 7 ++++--- .../ViewModels/SettingsPaneGeneralViewModel.cs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs b/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs index 5b948e450..de9cb841e 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/DataLocation.cs @@ -7,8 +7,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings { public const string PortableFolderName = "UserData"; public const string DeletionIndicatorFile = ".dead"; - public static string PortableDataPath = Path.Combine(Constant.ProgramDirectory, PortableFolderName); - public static string RoamingDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FlowLauncher"); + public static readonly string PortableDataPath = Path.Combine(Constant.ProgramDirectory, PortableFolderName); + public static readonly string RoamingDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FlowLauncher"); public static string DataDirectory() { if (PortableDataLocationInUse()) @@ -19,7 +19,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings public static bool PortableDataLocationInUse() { - if (Directory.Exists(PortableDataPath) && !File.Exists(DeletionIndicatorFile)) + if (Directory.Exists(PortableDataPath) && + !File.Exists(Path.Combine(PortableDataPath, DeletionIndicatorFile))) return true; return false; diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index b47b53654..885330b8c 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -123,7 +123,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel } // This is only required to set at startup. When portable mode enabled/disabled a restart is always required - private static bool _portableMode = DataLocation.PortableDataLocationInUse(); + private static readonly bool _portableMode = DataLocation.PortableDataLocationInUse(); public bool PortableMode { From a05e09908cbccf0c6d7714d496dc5e1b3167e8fd Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sun, 21 Sep 2025 22:23:00 +1000 Subject: [PATCH 38/73] Release 2.0.1 (#3998) --- .../ExternalPlugins/CommunityPluginSource.cs | 11 + Flow.Launcher.Core/Flow.Launcher.Core.csproj | 4 +- .../Plugin/JsonRPCPluginSettings.cs | 39 +- .../Resource/Internationalization.cs | 51 ++- Flow.Launcher.Core/packages.lock.json | 40 +- .../Flow.Launcher.Infrastructure.csproj | 10 +- .../Image/ImageLoader.cs | 8 +- .../UserSettings/CustomBrowserViewModel.cs | 17 +- .../UserSettings/CustomExplorerViewModel.cs | 17 +- .../UserSettings/Settings.cs | 1 - Flow.Launcher.Infrastructure/Win32Helper.cs | 16 +- .../packages.lock.json | 38 +- .../Flow.Launcher.Plugin.csproj | 8 +- Flow.Launcher.Plugin/packages.lock.json | 18 +- Flow.Launcher.Test/Flow.Launcher.Test.csproj | 5 +- Flow.Launcher.Test/Plugins/CalculatorTest.cs | 92 ++++ Flow.Launcher/App.xaml.cs | 5 +- Flow.Launcher/Flow.Launcher.csproj | 50 +-- .../Helper/WallpaperPathRetrieval.cs | 32 +- Flow.Launcher/Languages/ar.xaml | 8 +- Flow.Launcher/Languages/cs.xaml | 8 +- Flow.Launcher/Languages/da.xaml | 8 +- Flow.Launcher/Languages/de.xaml | 8 +- Flow.Launcher/Languages/en.xaml | 3 + Flow.Launcher/Languages/es-419.xaml | 8 +- Flow.Launcher/Languages/es.xaml | 16 +- Flow.Launcher/Languages/fr.xaml | 8 +- Flow.Launcher/Languages/he.xaml | 8 +- Flow.Launcher/Languages/it.xaml | 8 +- Flow.Launcher/Languages/ja.xaml | 374 ++++++++-------- Flow.Launcher/Languages/ko.xaml | 8 +- Flow.Launcher/Languages/nb.xaml | 8 +- Flow.Launcher/Languages/nl.xaml | 8 +- Flow.Launcher/Languages/pl.xaml | 8 +- Flow.Launcher/Languages/pt-br.xaml | 8 +- Flow.Launcher/Languages/pt-pt.xaml | 10 +- Flow.Launcher/Languages/ru.xaml | 16 +- Flow.Launcher/Languages/sk.xaml | 62 +-- Flow.Launcher/Languages/sr-Cyrl-RS.xaml | 8 +- Flow.Launcher/Languages/sr.xaml | 8 +- Flow.Launcher/Languages/tr.xaml | 14 +- Flow.Launcher/Languages/uk-UA.xaml | 8 +- Flow.Launcher/Languages/vi.xaml | 8 +- Flow.Launcher/Languages/zh-cn.xaml | 8 +- Flow.Launcher/Languages/zh-tw.xaml | 8 +- Flow.Launcher/SelectBrowserWindow.xaml | 2 +- Flow.Launcher/SelectBrowserWindow.xaml.cs | 3 +- Flow.Launcher/SelectFileManagerWindow.xaml | 2 +- Flow.Launcher/SelectFileManagerWindow.xaml.cs | 5 +- .../ViewModels/SettingsPaneAboutViewModel.cs | 58 +-- .../SettingsPaneGeneralViewModel.cs | 4 +- .../Views/SettingsPaneGeneral.xaml | 4 +- .../ViewModel/SelectBrowserViewModel.cs | 21 +- .../ViewModel/SelectFileManagerViewModel.cs | 19 +- Flow.Launcher/packages.lock.json | 360 +++++++-------- ...low.Launcher.Plugin.BrowserBookmark.csproj | 7 +- .../Helper/FaviconHelper.cs | 13 +- .../Languages/ja.xaml | 14 +- .../Flow.Launcher.Plugin.Calculator.csproj | 3 +- .../Languages/ar.xaml | 5 +- .../Languages/cs.xaml | 5 +- .../Languages/da.xaml | 5 +- .../Languages/de.xaml | 5 +- .../Languages/en.xaml | 3 +- .../Languages/es-419.xaml | 5 +- .../Languages/es.xaml | 5 +- .../Languages/fr.xaml | 5 +- .../Languages/he.xaml | 5 +- .../Languages/it.xaml | 5 +- .../Languages/ja.xaml | 13 +- .../Languages/ko.xaml | 5 +- .../Languages/nb.xaml | 5 +- .../Languages/nl.xaml | 5 +- .../Languages/pl.xaml | 5 +- .../Languages/pt-br.xaml | 5 +- .../Languages/pt-pt.xaml | 5 +- .../Languages/ru.xaml | 5 +- .../Languages/sk.xaml | 5 +- .../Languages/sr-Cyrl-RS.xaml | 3 +- .../Languages/sr.xaml | 5 +- .../Languages/tr.xaml | 5 +- .../Languages/uk-UA.xaml | 5 +- .../Languages/vi.xaml | 5 +- .../Languages/zh-cn.xaml | 5 +- .../Languages/zh-tw.xaml | 5 +- .../Flow.Launcher.Plugin.Calculator/Main.cs | 419 +++++++++++------- .../MainRegexHelper.cs | 21 +- .../Settings.cs | 14 +- .../ViewModels/SettingsViewModel.cs | 36 +- .../Views/CalculatorSettings.xaml | 10 + .../Views/CalculatorSettings.xaml.cs | 26 +- .../plugin.json | 2 +- .../Flow.Launcher.Plugin.Explorer.csproj | 5 +- .../Languages/ar.xaml | 1 + .../Languages/cs.xaml | 1 + .../Languages/da.xaml | 1 + .../Languages/de.xaml | 1 + .../Languages/es-419.xaml | 1 + .../Languages/es.xaml | 1 + .../Languages/fr.xaml | 1 + .../Languages/he.xaml | 1 + .../Languages/it.xaml | 1 + .../Languages/ja.xaml | 165 +++---- .../Languages/ko.xaml | 1 + .../Languages/nb.xaml | 1 + .../Languages/nl.xaml | 1 + .../Languages/pl.xaml | 1 + .../Languages/pt-br.xaml | 1 + .../Languages/pt-pt.xaml | 1 + .../Languages/ru.xaml | 5 +- .../Languages/sk.xaml | 1 + .../Languages/sr-Cyrl-RS.xaml | 1 + .../Languages/sr.xaml | 1 + .../Languages/tr.xaml | 3 +- .../Languages/uk-UA.xaml | 1 + .../Languages/vi.xaml | 1 + .../Languages/zh-cn.xaml | 1 + .../Languages/zh-tw.xaml | 1 + .../ViewModels/SettingsViewModel.cs | 6 +- .../Languages/ja.xaml | 6 +- .../Languages/ja.xaml | 110 ++--- .../Languages/ru.xaml | 4 +- .../Languages/sk.xaml | 2 +- .../Flow.Launcher.Plugin.ProcessKiller.csproj | 2 +- .../Languages/ja.xaml | 14 +- .../Flow.Launcher.Plugin.Program.csproj | 6 +- .../Languages/ja.xaml | 124 +++--- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 63 ++- .../Views/Commands/ProgramSettingDisplay.cs | 52 ++- .../Languages/ja.xaml | 30 +- .../Flow.Launcher.Plugin.Sys.csproj | 2 +- .../Languages/ja.xaml | 68 +-- .../Languages/ru.xaml | 4 +- .../Languages/ja.xaml | 10 +- .../Languages/ru.xaml | 4 +- .../Languages/ja.xaml | 45 +- .../Languages/ru.xaml | 22 +- .../Properties/Resources.ja-JP.resx | 78 ++-- .../Properties/Resources.tr-TR.resx | 88 ++-- appveyor.yml | 2 +- 140 files changed, 1879 insertions(+), 1349 deletions(-) create mode 100644 Flow.Launcher.Test/Plugins/CalculatorTest.cs diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs index 6f3b23e11..841099dd1 100644 --- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs +++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs @@ -73,6 +73,17 @@ namespace Flow.Launcher.Core.ExternalPlugins return null; } } + catch (OperationCanceledException) when (token.IsCancellationRequested) + { + API.LogDebug(ClassName, $"Fetching from {ManifestFileUrl} was cancelled by caller."); + return null; + } + catch (TaskCanceledException) + { + // Likely an HttpClient timeout or external cancellation not requested by our token + API.LogWarn(ClassName, $"Fetching from {ManifestFileUrl} timed out."); + return null; + } catch (Exception e) { if (e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException) diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj index 527950061..1369d7e5d 100644 --- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj +++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj @@ -55,8 +55,8 @@ - - + + diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs index 435d97ab7..9212dada6 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs @@ -27,6 +27,7 @@ namespace Flow.Launcher.Core.Plugin private JsonStorage> _storage = null!; + private static readonly double MainGridColumn0MaxWidthRatio = 0.6; private static readonly Thickness SettingPanelMargin = (Thickness)Application.Current.FindResource("SettingPanelMargin"); private static readonly Thickness SettingPanelItemLeftMargin = (Thickness)Application.Current.FindResource("SettingPanelItemLeftMargin"); private static readonly Thickness SettingPanelItemTopBottomMargin = (Thickness)Application.Current.FindResource("SettingPanelItemTopBottomMargin"); @@ -156,7 +157,7 @@ namespace Flow.Launcher.Core.Plugin { if (!NeedCreateSettingPanel()) return null!; - // Create main grid with two columns (Column 1: Auto, Column 2: *) + // Create main grid with two columns (Column 0: Auto, Column 1: *) var mainPanel = new Grid { Margin = SettingPanelMargin, VerticalAlignment = VerticalAlignment.Center }; mainPanel.ColumnDefinitions.Add(new ColumnDefinition() { @@ -200,7 +201,7 @@ namespace Flow.Launcher.Core.Plugin { Text = attributes.Label, VerticalAlignment = VerticalAlignment.Center, - TextWrapping = TextWrapping.WrapWithOverflow + TextWrapping = TextWrapping.Wrap }; // Create a text block for description @@ -211,7 +212,7 @@ namespace Flow.Launcher.Core.Plugin { Text = attributes.Description, VerticalAlignment = VerticalAlignment.Center, - TextWrapping = TextWrapping.WrapWithOverflow + TextWrapping = TextWrapping.Wrap }; desc.SetResourceReference(TextBlock.StyleProperty, "SettingPanelTextBlockDescriptionStyle"); // for theme change @@ -247,7 +248,8 @@ namespace Flow.Launcher.Core.Plugin VerticalAlignment = VerticalAlignment.Center, Margin = SettingPanelItemLeftTopBottomMargin, Text = Settings[attributes.Name] as string ?? string.Empty, - ToolTip = attributes.Description + ToolTip = attributes.Description, + TextWrapping = TextWrapping.Wrap }; textBox.TextChanged += (_, _) => @@ -269,7 +271,8 @@ namespace Flow.Launcher.Core.Plugin VerticalAlignment = VerticalAlignment.Center, Margin = SettingPanelItemLeftMargin, Text = Settings[attributes.Name] as string ?? string.Empty, - ToolTip = attributes.Description + ToolTip = attributes.Description, + TextWrapping = TextWrapping.Wrap }; textBox.TextChanged += (_, _) => @@ -333,7 +336,7 @@ namespace Flow.Launcher.Core.Plugin HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Center, Margin = SettingPanelItemLeftTopBottomMargin, - TextWrapping = TextWrapping.WrapWithOverflow, + TextWrapping = TextWrapping.Wrap, AcceptsReturn = true, Text = Settings[attributes.Name] as string ?? string.Empty, ToolTip = attributes.Description @@ -488,6 +491,8 @@ namespace Flow.Launcher.Core.Plugin rowCount++; } + mainPanel.SizeChanged += MainPanel_SizeChanged; + // Wrap the main grid in a user control return new UserControl() { @@ -495,6 +500,28 @@ namespace Flow.Launcher.Core.Plugin }; } + private void MainPanel_SizeChanged(object sender, SizeChangedEventArgs e) + { + if (sender is not Grid grid) return; + + var workingWidth = grid.ActualWidth; + + if (workingWidth <= 0) return; + + var constrainedWidth = MainGridColumn0MaxWidthRatio * workingWidth; + + // Set MaxWidth of column 0 and its children + // We must set MaxWidth of its children to make text wrapping work correctly + grid.ColumnDefinitions[0].MaxWidth = constrainedWidth; + foreach (var child in grid.Children) + { + if (child is FrameworkElement element && Grid.GetColumn(element) == 0 && Grid.GetColumnSpan(element) == 1) + { + element.MaxWidth = constrainedWidth; + } + } + } + private static bool NeedSaveInSettings(string type) { return type != "textBlock" && type != "separator" && type != "hyperlink"; diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index 8261feab3..983f8b234 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -14,7 +14,7 @@ using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Resource { - public class Internationalization + public class Internationalization : IDisposable { private static readonly string ClassName = nameof(Internationalization); @@ -30,6 +30,7 @@ namespace Flow.Launcher.Core.Resource private readonly List _languageDirectories = []; private readonly List _oldResources = []; private static string SystemLanguageCode; + private readonly SemaphoreSlim _langChangeLock = new(1, 1); public Internationalization(Settings settings) { @@ -185,20 +186,33 @@ namespace Flow.Launcher.Core.Resource private async Task ChangeLanguageAsync(Language language, bool updateMetadata = true) { - // Remove old language files and load language - RemoveOldLanguageFiles(); - if (language != AvailableLanguages.English) + await _langChangeLock.WaitAsync(); + + try { - LoadLanguage(language); + // Remove old language files and load language + RemoveOldLanguageFiles(); + if (language != AvailableLanguages.English) + { + LoadLanguage(language); + } + + // Change culture info + ChangeCultureInfo(language.LanguageCode); + + if (updateMetadata) + { + // Raise event for plugins after culture is set + await Task.Run(UpdatePluginMetadataTranslations); + } } - - // Change culture info - ChangeCultureInfo(language.LanguageCode); - - if (updateMetadata) + catch (Exception e) { - // Raise event for plugins after culture is set - await Task.Run(UpdatePluginMetadataTranslations); + API.LogException(ClassName, $"Failed to change language to <{language.LanguageCode}>", e); + } + finally + { + _langChangeLock.Release(); } } @@ -257,6 +271,7 @@ namespace Flow.Launcher.Core.Resource { dicts.Remove(r); } + _oldResources.Clear(); } private void LoadLanguage(Language language) @@ -368,5 +383,15 @@ namespace Flow.Launcher.Core.Resource } #endregion + + #region IDisposable + + public void Dispose() + { + RemoveOldLanguageFiles(); + _langChangeLock.Dispose(); + } + + #endregion } } diff --git a/Flow.Launcher.Core/packages.lock.json b/Flow.Launcher.Core/packages.lock.json index 5e9abc24c..b7a00d94d 100644 --- a/Flow.Launcher.Core/packages.lock.json +++ b/Flow.Launcher.Core/packages.lock.json @@ -13,15 +13,15 @@ }, "FSharp.Core": { "type": "Direct", - "requested": "[9.0.300, )", - "resolved": "9.0.300", - "contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ==" + "requested": "[9.0.303, )", + "resolved": "9.0.303", + "contentHash": "6JlV8aD8qQvcmfoe/PMOxCHXc0uX4lR23u0fAyQtnVQxYULLoTZgwgZHSnRcuUHOvS3wULFWcwdnP1iwslH60g==" }, "Meziantou.Framework.Win32.Jobs": { "type": "Direct", - "requested": "[3.4.3, )", - "resolved": "3.4.3", - "contentHash": "REjInKnQ0OrhjjtSMPQtLtdURctCroB4L8Sd2gjTOYDysklvsdnrStx1tHS7uLv+fSyFF3aazZmo5Ka0v1oz/w==" + "requested": "[3.4.4, )", + "resolved": "3.4.4", + "contentHash": "AivBzH5wM1NHBLehclim+o37SmireP7JxCRUoTilsc/h7LH9+YCPjb6Ig6y0khnQhFcO1P8RHYw4oiR15TGHUg==" }, "Microsoft.IO.RecyclableMemoryStream": { "type": "Direct", @@ -90,8 +90,8 @@ }, "JetBrains.Annotations": { "type": "Transitive", - "resolved": "2024.3.0", - "contentHash": "ox5pkeLQXjvJdyAB4b2sBYAlqZGLh3PjSnP1bQNVx72ONuTJ9+34/+Rq91Fc0dG29XG9RgZur9+NcP4riihTug==" + "resolved": "2025.2.2", + "contentHash": "0X56ZRizuHdrnPpgXjWV7f2tQO1FlQg5O1967OGKnI/4ZRNOK642J8L7brM1nYvrxTTU5TP1yRyXLRLaXLPQ8A==" }, "MemoryPack": { "type": "Transitive", @@ -199,21 +199,21 @@ }, "NLog": { "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "qDWiqy8/xdpZKtHna/645KbalwP86N2NFJEzfqhcv+Si4V2iNaEfR/dCneuF/4+Dcwl3f7jHMXj3ndWYftV3Ug==" + "resolved": "6.0.4", + "contentHash": "Xr+lIk1ZlTTFXEqnxQVLxrDqZlt2tm5X+/AhJbaY2emb/dVtGDiU5QuEtj3gHtwV/SWlP/rJ922I/BPuOJXlRw==" }, "NLog.OutputDebugString": { "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "wwJCQLaHVzuRf8TsXB+EEdrzVvE3dnzCSMQMDgwkw3AXp8VSp3JSVF/Q/H0oEqggKgKhPs13hh3a7svyQr4s3A==", + "resolved": "6.0.4", + "contentHash": "TOP2Ap9BbE98B/l/TglnguowOD0rXo8B/20xAgvj9shO/kf6IJ5M4QMhVxq72mrneJ/ANhHY7Jcd+xJbzuI5PA==", "dependencies": { - "NLog": "6.0.1" + "NLog": "6.0.4" } }, "SharpVectors.Wpf": { "type": "Transitive", - "resolved": "1.8.4.2", - "contentHash": "PNxLkMBJnV8A+6yH9OqOlhLJegvWP/dvh0rAJp2l0kcrR+rB4R2tQ9vhUqka+UilH4atN8T6zvjDOizVyfz2Ng==" + "resolved": "1.8.5", + "contentHash": "WURdBDq5AE8RjKV9pFS7lNkJe81gxja9SaMGE4URq9GJUZ6M+5DGUL0Lm3B0iYW2/Meyowaz4ffGsyW+RBSTtg==" }, "Splat": { "type": "Transitive", @@ -254,14 +254,14 @@ "Ben.Demystifier": "[0.4.1, )", "BitFaster.Caching": "[2.5.4, )", "CommunityToolkit.Mvvm": "[8.4.0, )", - "Flow.Launcher.Plugin": "[4.7.0, )", + "Flow.Launcher.Plugin": "[5.0.0, )", "InputSimulator": "[1.0.4, )", "MemoryPack": "[1.21.4, )", "Microsoft.VisualStudio.Threading": "[17.14.15, )", "NHotkey.Wpf": "[3.0.0, )", - "NLog": "[6.0.1, )", - "NLog.OutputDebugString": "[6.0.1, )", - "SharpVectors.Wpf": "[1.8.4.2, )", + "NLog": "[6.0.4, )", + "NLog.OutputDebugString": "[6.0.4, )", + "SharpVectors.Wpf": "[1.8.5, )", "System.Drawing.Common": "[7.0.0, )", "ToolGood.Words.Pinyin": "[3.1.0.3, )" } @@ -269,7 +269,7 @@ "flow.launcher.plugin": { "type": "Project", "dependencies": { - "JetBrains.Annotations": "[2024.3.0, )" + "JetBrains.Annotations": "[2025.2.2, )" } } } diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index c32c36248..5b4eaf893 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -56,24 +56,24 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all - + diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 64d323de6..598347fd2 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -22,7 +22,7 @@ namespace Flow.Launcher.Infrastructure.Image private static Lock storageLock { get; } = new(); private static BinaryStorage> _storage; private static readonly ConcurrentDictionary GuidToKey = new(); - private static IImageHashGenerator _hashGenerator; + private static ImageHashGenerator _hashGenerator; private static readonly bool EnableImageHash = true; public static ImageSource Image => ImageCache[Constant.ImageIcon, false]; public static ImageSource MissingImage => ImageCache[Constant.MissingImgIcon, false]; @@ -31,7 +31,7 @@ namespace Flow.Launcher.Infrastructure.Image 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[] ImageExtensions = [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".ico"]; private static readonly string SvgExtension = ".svg"; public static async Task InitializeAsync() @@ -327,7 +327,7 @@ namespace Flow.Launcher.Infrastructure.Image return img; } - private static ImageSource LoadFullImage(string path) + private static BitmapImage LoadFullImage(string path) { BitmapImage image = new BitmapImage(); image.BeginInit(); @@ -364,7 +364,7 @@ namespace Flow.Launcher.Infrastructure.Image return image; } - private static ImageSource LoadSvgImage(string path, bool loadFullImage = false) + private static RenderTargetBitmap LoadSvgImage(string path, bool loadFullImage = false) { // Set up drawing settings var desiredHeight = loadFullImage ? FullImageSize : SmallIconSize; diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs index 24584115d..9c795f952 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs @@ -1,11 +1,18 @@ +using System.Text.Json.Serialization; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Plugin; -using System.Text.Json.Serialization; namespace Flow.Launcher.Infrastructure.UserSettings { public class CustomBrowserViewModel : BaseModel { + // 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 string Name { get; set; } + [JsonIgnore] + public string DisplayName => Name == "Default" ? API.GetTranslation("defaultBrowser_default") : Name; public string Path { get; set; } public string PrivateArg { get; set; } public bool EnablePrivate { get; set; } @@ -26,8 +33,10 @@ namespace Flow.Launcher.Infrastructure.UserSettings Editable = Editable }; } + + public void OnDisplayNameChanged() + { + OnPropertyChanged(nameof(DisplayName)); + } } } - - - diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs index c54c30478..2af0bb0e5 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs @@ -1,10 +1,18 @@ -using Flow.Launcher.Plugin; +using System.Text.Json.Serialization; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; -namespace Flow.Launcher.ViewModel +namespace Flow.Launcher.Infrastructure.UserSettings { public class CustomExplorerViewModel : BaseModel { + // 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 string Name { get; set; } + [JsonIgnore] + public string DisplayName => Name == "Explorer" ? API.GetTranslation("fileManagerExplorer") : Name; public string Path { get; set; } public string FileArgument { get; set; } = "\"%d\""; public string DirectoryArgument { get; set; } = "\"%d\""; @@ -21,5 +29,10 @@ namespace Flow.Launcher.ViewModel Editable = Editable }; } + + public void OnDisplayNameChanged() + { + OnPropertyChanged(nameof(DisplayName)); + } } } diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 0c3402050..d49cd276a 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -9,7 +9,6 @@ using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels; -using Flow.Launcher.ViewModel; namespace Flow.Launcher.Infrastructure.UserSettings { diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 811733925..5d30b740d 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; @@ -904,5 +904,19 @@ namespace Flow.Launcher.Infrastructure } #endregion + + #region File / Folder Dialog + + public static string SelectFile() + { + var dlg = new OpenFileDialog(); + var result = dlg.ShowDialog(); + if (result == true) + return dlg.FileName; + + return string.Empty; + } + + #endregion } } diff --git a/Flow.Launcher.Infrastructure/packages.lock.json b/Flow.Launcher.Infrastructure/packages.lock.json index abd250f7c..47c94d5f6 100644 --- a/Flow.Launcher.Infrastructure/packages.lock.json +++ b/Flow.Launcher.Infrastructure/packages.lock.json @@ -25,9 +25,9 @@ }, "Fody": { "type": "Direct", - "requested": "[6.9.2, )", - "resolved": "6.9.2", - "contentHash": "YBHobPGogb0vYhGYIxn/ndWqTjNWZveDi5jdjrcshL2vjwU3gQGyDeI7vGgye+2rAM5fGRvlLgNWLW3DpviS/w==" + "requested": "[6.9.3, )", + "resolved": "6.9.3", + "contentHash": "1CUGgFdyECDKgi5HaUBhdv6k+VG9Iy4OCforGfHyar3xQXAJypZkzymgKtWj/4SPd6nSG0Qi7NH71qHrDSZLaA==" }, "InputSimulator": { "type": "Direct", @@ -58,9 +58,9 @@ }, "Microsoft.Windows.CsWin32": { "type": "Direct", - "requested": "[0.3.183, )", - "resolved": "0.3.183", - "contentHash": "Ze3aE2y7xgzKxEWtNb4SH0CExXpCHr3sbmwnvMiWMzJhWDX/G4Rs5wgg2UNs3VN+qVHh/DkDWLCPaVQv/b//Nw==", + "requested": "[0.3.205, )", + "resolved": "0.3.205", + "contentHash": "U5wGAnyKd7/I2YMd43nogm81VMtjiKzZ9dsLMVI4eAB7jtv5IEj0gprj0q/F3iRmAIaGv5omOf8iSYx2+nE6BQ==", "dependencies": { "Microsoft.Windows.SDK.Win32Docs": "0.1.42-alpha", "Microsoft.Windows.SDK.Win32Metadata": "61.0.15-preview", @@ -78,17 +78,17 @@ }, "NLog": { "type": "Direct", - "requested": "[6.0.1, )", - "resolved": "6.0.1", - "contentHash": "qDWiqy8/xdpZKtHna/645KbalwP86N2NFJEzfqhcv+Si4V2iNaEfR/dCneuF/4+Dcwl3f7jHMXj3ndWYftV3Ug==" + "requested": "[6.0.4, )", + "resolved": "6.0.4", + "contentHash": "Xr+lIk1ZlTTFXEqnxQVLxrDqZlt2tm5X+/AhJbaY2emb/dVtGDiU5QuEtj3gHtwV/SWlP/rJ922I/BPuOJXlRw==" }, "NLog.OutputDebugString": { "type": "Direct", - "requested": "[6.0.1, )", - "resolved": "6.0.1", - "contentHash": "wwJCQLaHVzuRf8TsXB+EEdrzVvE3dnzCSMQMDgwkw3AXp8VSp3JSVF/Q/H0oEqggKgKhPs13hh3a7svyQr4s3A==", + "requested": "[6.0.4, )", + "resolved": "6.0.4", + "contentHash": "TOP2Ap9BbE98B/l/TglnguowOD0rXo8B/20xAgvj9shO/kf6IJ5M4QMhVxq72mrneJ/ANhHY7Jcd+xJbzuI5PA==", "dependencies": { - "NLog": "6.0.1" + "NLog": "6.0.4" } }, "PropertyChanged.Fody": { @@ -102,9 +102,9 @@ }, "SharpVectors.Wpf": { "type": "Direct", - "requested": "[1.8.4.2, )", - "resolved": "1.8.4.2", - "contentHash": "PNxLkMBJnV8A+6yH9OqOlhLJegvWP/dvh0rAJp2l0kcrR+rB4R2tQ9vhUqka+UilH4atN8T6zvjDOizVyfz2Ng==" + "requested": "[1.8.5, )", + "resolved": "1.8.5", + "contentHash": "WURdBDq5AE8RjKV9pFS7lNkJe81gxja9SaMGE4URq9GJUZ6M+5DGUL0Lm3B0iYW2/Meyowaz4ffGsyW+RBSTtg==" }, "System.Drawing.Common": { "type": "Direct", @@ -123,8 +123,8 @@ }, "JetBrains.Annotations": { "type": "Transitive", - "resolved": "2024.3.0", - "contentHash": "ox5pkeLQXjvJdyAB4b2sBYAlqZGLh3PjSnP1bQNVx72ONuTJ9+34/+Rq91Fc0dG29XG9RgZur9+NcP4riihTug==" + "resolved": "2025.2.2", + "contentHash": "0X56ZRizuHdrnPpgXjWV7f2tQO1FlQg5O1967OGKnI/4ZRNOK642J8L7brM1nYvrxTTU5TP1yRyXLRLaXLPQ8A==" }, "MemoryPack.Core": { "type": "Transitive", @@ -190,7 +190,7 @@ "flow.launcher.plugin": { "type": "Project", "dependencies": { - "JetBrains.Annotations": "[2024.3.0, )" + "JetBrains.Annotations": "[2025.2.2, )" } } } diff --git a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj index ae2454279..1ae0b1f58 100644 --- a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj +++ b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj @@ -1,4 +1,4 @@ - + net9.0-windows @@ -68,13 +68,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Flow.Launcher.Plugin/packages.lock.json b/Flow.Launcher.Plugin/packages.lock.json index af835c598..70f71f20d 100644 --- a/Flow.Launcher.Plugin/packages.lock.json +++ b/Flow.Launcher.Plugin/packages.lock.json @@ -4,15 +4,15 @@ "net9.0-windows7.0": { "Fody": { "type": "Direct", - "requested": "[6.9.2, )", - "resolved": "6.9.2", - "contentHash": "YBHobPGogb0vYhGYIxn/ndWqTjNWZveDi5jdjrcshL2vjwU3gQGyDeI7vGgye+2rAM5fGRvlLgNWLW3DpviS/w==" + "requested": "[6.9.3, )", + "resolved": "6.9.3", + "contentHash": "1CUGgFdyECDKgi5HaUBhdv6k+VG9Iy4OCforGfHyar3xQXAJypZkzymgKtWj/4SPd6nSG0Qi7NH71qHrDSZLaA==" }, "JetBrains.Annotations": { "type": "Direct", - "requested": "[2024.3.0, )", - "resolved": "2024.3.0", - "contentHash": "ox5pkeLQXjvJdyAB4b2sBYAlqZGLh3PjSnP1bQNVx72ONuTJ9+34/+Rq91Fc0dG29XG9RgZur9+NcP4riihTug==" + "requested": "[2025.2.2, )", + "resolved": "2025.2.2", + "contentHash": "0X56ZRizuHdrnPpgXjWV7f2tQO1FlQg5O1967OGKnI/4ZRNOK642J8L7brM1nYvrxTTU5TP1yRyXLRLaXLPQ8A==" }, "Microsoft.SourceLink.GitHub": { "type": "Direct", @@ -26,9 +26,9 @@ }, "Microsoft.Windows.CsWin32": { "type": "Direct", - "requested": "[0.3.183, )", - "resolved": "0.3.183", - "contentHash": "Ze3aE2y7xgzKxEWtNb4SH0CExXpCHr3sbmwnvMiWMzJhWDX/G4Rs5wgg2UNs3VN+qVHh/DkDWLCPaVQv/b//Nw==", + "requested": "[0.3.205, )", + "resolved": "0.3.205", + "contentHash": "U5wGAnyKd7/I2YMd43nogm81VMtjiKzZ9dsLMVI4eAB7jtv5IEj0gprj0q/F3iRmAIaGv5omOf8iSYx2+nE6BQ==", "dependencies": { "Microsoft.Windows.SDK.Win32Docs": "0.1.42-alpha", "Microsoft.Windows.SDK.Win32Metadata": "61.0.15-preview", diff --git a/Flow.Launcher.Test/Flow.Launcher.Test.csproj b/Flow.Launcher.Test/Flow.Launcher.Test.csproj index 33479c5a0..11ccff05b 100644 --- a/Flow.Launcher.Test/Flow.Launcher.Test.csproj +++ b/Flow.Launcher.Test/Flow.Launcher.Test.csproj @@ -39,6 +39,7 @@ + @@ -49,8 +50,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Flow.Launcher.Test/Plugins/CalculatorTest.cs b/Flow.Launcher.Test/Plugins/CalculatorTest.cs new file mode 100644 index 000000000..b075813db --- /dev/null +++ b/Flow.Launcher.Test/Plugins/CalculatorTest.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Flow.Launcher.Plugin.Calculator; +using Mages.Core; +using NUnit.Framework; +using NUnit.Framework.Legacy; + +namespace Flow.Launcher.Test.Plugins +{ + [TestFixture] + public class CalculatorPluginTest + { + private readonly Main _plugin; + private readonly Settings _settings = new() + { + DecimalSeparator = DecimalSeparator.UseSystemLocale, + MaxDecimalPlaces = 10, + ShowErrorMessage = false // Make sure we return the empty results when error occurs + }; + private readonly Engine _engine = new(new Configuration + { + Scope = new Dictionary + { + { "e", Math.E }, // e is not contained in the default mages engine + } + }); + + public CalculatorPluginTest() + { + _plugin = new Main(); + + var settingField = typeof(Main).GetField("_settings", BindingFlags.NonPublic | BindingFlags.Instance); + if (settingField == null) + Assert.Fail("Could not find field '_settings' on Flow.Launcher.Plugin.Calculator.Main"); + settingField.SetValue(_plugin, _settings); + + var engineField = typeof(Main).GetField("MagesEngine", BindingFlags.NonPublic | BindingFlags.Static); + if (engineField == null) + Assert.Fail("Could not find static field 'MagesEngine' on Flow.Launcher.Plugin.Calculator.Main"); + engineField.SetValue(null, _engine); + } + + // Basic operations + [TestCase(@"1+1", "2")] + [TestCase(@"2-1", "1")] + [TestCase(@"2*2", "4")] + [TestCase(@"4/2", "2")] + [TestCase(@"2^3", "8")] + // Decimal places + [TestCase(@"10/3", "3.3333333333")] + // Parentheses + [TestCase(@"(1+2)*3", "9")] + [TestCase(@"2^(1+2)", "8")] + // Functions + [TestCase(@"pow(2,3)", "8")] + [TestCase(@"min(1,-1,-2)", "-2")] + [TestCase(@"max(1,-1,-2)", "1")] + [TestCase(@"sqrt(16)", "4")] + [TestCase(@"sin(pi)", "0.0000000000")] + [TestCase(@"cos(0)", "1")] + [TestCase(@"tan(0)", "0")] + [TestCase(@"log10(100)", "2")] + [TestCase(@"log(100)", "2")] + [TestCase(@"log2(8)", "3")] + [TestCase(@"ln(e)", "1")] + [TestCase(@"abs(-5)", "5")] + // Constants + [TestCase(@"pi", "3.1415926536")] + // Complex expressions + [TestCase(@"(2+3)*sqrt(16)-log(100)/ln(e)", "18")] + [TestCase(@"sin(pi/2)+cos(0)+tan(0)", "2")] + // Error handling (should return empty result) + [TestCase(@"10/0", "")] + [TestCase(@"sqrt(-1)", "")] + [TestCase(@"log(0)", "")] + [TestCase(@"invalid_expression", "")] + public void CalculatorTest(string expression, string result) + { + ClassicAssert.AreEqual(GetCalculationResult(expression), result); + } + + private string GetCalculationResult(string expression) + { + var results = _plugin.Query(new Plugin.Query() + { + Search = expression + }); + return results.Count > 0 ? results[0].Title : string.Empty; + } + } +} diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 0360c761e..8ec11e5ff 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -45,6 +45,7 @@ namespace Flow.Launcher private static Settings _settings; private static MainWindow _mainWindow; private readonly MainViewModel _mainVM; + private readonly Internationalization _internationalization; // To prevent two disposals running at the same time. private static readonly object _disposingLock = new(); @@ -107,6 +108,7 @@ namespace Flow.Launcher API = Ioc.Default.GetRequiredService(); _settings.Initialize(); _mainVM = Ioc.Default.GetRequiredService(); + _internationalization = Ioc.Default.GetRequiredService(); } catch (Exception e) { @@ -193,7 +195,7 @@ namespace Flow.Launcher Win32Helper.EnableWin32DarkMode(_settings.ColorScheme); // Initialize language before portable clean up since it needs translations - await Ioc.Default.GetRequiredService().InitializeLanguageAsync(); + await _internationalization.InitializeLanguageAsync(); Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate(); @@ -421,6 +423,7 @@ namespace Flow.Launcher _mainWindow?.Dispatcher.Invoke(_mainWindow.Dispose); _mainVM?.Dispose(); DialogJump.Dispose(); + _internationalization.Dispose(); } API.LogInfo(ClassName, "End Flow Launcher dispose ----------------------------------------------------"); diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index fa23d8886..a99d4d8c2 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -40,49 +40,11 @@ - + - + @@ -132,7 +94,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -141,8 +103,8 @@ - - + + @@ -152,7 +114,7 @@ - + diff --git a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs index 93b9a8aaa..fd04b3e88 100644 --- a/Flow.Launcher/Helper/WallpaperPathRetrieval.cs +++ b/Flow.Launcher/Helper/WallpaperPathRetrieval.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; @@ -16,7 +17,7 @@ public static class WallpaperPathRetrieval private const int MaxCacheSize = 3; private static readonly Dictionary<(string, DateTime), ImageBrush> WallpaperCache = new(); - private static readonly object CacheLock = new(); + private static readonly Lock CacheLock = new(); public static Brush GetWallpaperBrush() { @@ -31,7 +32,7 @@ public static class WallpaperPathRetrieval var wallpaperPath = Win32Helper.GetWallpaperPath(); if (string.IsNullOrEmpty(wallpaperPath) || !File.Exists(wallpaperPath)) { - App.API.LogInfo(ClassName, $"Wallpaper path is invalid: {wallpaperPath}"); + App.API.LogError(ClassName, $"Wallpaper path is invalid: {wallpaperPath}"); var wallpaperColor = GetWallpaperColor(); return new SolidColorBrush(wallpaperColor); } @@ -47,17 +48,22 @@ public static class WallpaperPathRetrieval return cachedWallpaper; } } - - using var fileStream = File.OpenRead(wallpaperPath); - var decoder = BitmapDecoder.Create(fileStream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None); - var frame = decoder.Frames[0]; - var originalWidth = frame.PixelWidth; - var originalHeight = frame.PixelHeight; + + int originalWidth, originalHeight; + // Use `using ()` instead of `using var` sentence here to ensure the wallpaper file is not locked + using (var fileStream = File.OpenRead(wallpaperPath)) + { + var decoder = BitmapDecoder.Create(fileStream, BitmapCreateOptions.DelayCreation, BitmapCacheOption.None); + var frame = decoder.Frames[0]; + originalWidth = frame.PixelWidth; + originalHeight = frame.PixelHeight; + } if (originalWidth == 0 || originalHeight == 0) { - App.API.LogInfo(ClassName, $"Failed to load bitmap: Width={originalWidth}, Height={originalHeight}"); - return new SolidColorBrush(Colors.Transparent); + App.API.LogError(ClassName, $"Failed to load bitmap: Width={originalWidth}, Height={originalHeight}"); + var wallpaperColor = GetWallpaperColor(); + return new SolidColorBrush(wallpaperColor); } // Calculate the scaling factor to fit the image within 800x600 while preserving aspect ratio @@ -70,7 +76,9 @@ public static class WallpaperPathRetrieval // Set DecodePixelWidth and DecodePixelHeight to resize the image while preserving aspect ratio var bitmap = new BitmapImage(); bitmap.BeginInit(); + bitmap.CacheOption = BitmapCacheOption.OnLoad; // Use OnLoad to ensure the wallpaper file is not locked bitmap.UriSource = new Uri(wallpaperPath); + bitmap.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; bitmap.DecodePixelWidth = decodedPixelWidth; bitmap.DecodePixelHeight = decodedPixelHeight; bitmap.EndInit(); @@ -104,13 +112,13 @@ public static class WallpaperPathRetrieval private static Color GetWallpaperColor() { - RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Colors", false); + using var key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Colors", false); var result = key?.GetValue("Background", null); if (result is string strResult) { try { - var parts = strResult.Trim().Split(new[] { ' ' }, 3).Select(byte.Parse).ToList(); + var parts = strResult.Trim().Split([' '], 3).Select(byte.Parse).ToList(); return Color.FromRgb(parts[0], parts[1], parts[2]); } catch (Exception ex) diff --git a/Flow.Launcher/Languages/ar.xaml b/Flow.Launcher/Languages/ar.xaml index 9c252f7a7..b8845c3f5 100644 --- a/Flow.Launcher/Languages/ar.xaml +++ b/Flow.Launcher/Languages/ar.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} متجر الإضافات @@ -467,8 +468,10 @@ فتح المجلد Advanced Log Level - Debug + Silent + خطأ Info + Debug Setting Window Font @@ -490,6 +493,7 @@ حجة للملف The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer متصفح الويب الافتراضي @@ -500,6 +504,8 @@ نافذة جديدة تبويب جديد الوضع الخاص + Default + New Profile تغيير الأولوية diff --git a/Flow.Launcher/Languages/cs.xaml b/Flow.Launcher/Languages/cs.xaml index 57415948f..30a1cdbb9 100644 --- a/Flow.Launcher/Languages/cs.xaml +++ b/Flow.Launcher/Languages/cs.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Obchod s pluginy @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Chyba Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Argumenty pro Soubor The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Výchozí prohlížeč @@ -500,6 +504,8 @@ Nové okno Nová karta Soukromý režim + Default + New Profile Změnit prioritu diff --git a/Flow.Launcher/Languages/da.xaml b/Flow.Launcher/Languages/da.xaml index 363d8de9a..067ea16fc 100644 --- a/Flow.Launcher/Languages/da.xaml +++ b/Flow.Launcher/Languages/da.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Plugin-butik @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg for fil The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Default Web Browser @@ -500,6 +504,8 @@ New Window New Tab Privattilstand + Default + New Profile Skift prioritet diff --git a/Flow.Launcher/Languages/de.xaml b/Flow.Launcher/Languages/de.xaml index fc16826bd..529531b58 100644 --- a/Flow.Launcher/Languages/de.xaml +++ b/Flow.Launcher/Languages/de.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Plug-in-Store @@ -467,8 +468,10 @@ Ordner öffnen Erweitert Log-Ebene - Debug + Silent + Fehler Info + Debug Einstellung der Fensterschriftart @@ -490,6 +493,7 @@ Arg For File Der Dateimanager '{0}' konnte nicht unter '{1}' gefunden werden. Möchten Sie fortfahren? Pfadfehler bei Dateimanager + File Explorer Webbrowser per Default @@ -500,6 +504,8 @@ Neues Fenster Neuer Tab Privater Modus + Default + New Profile Priorität ändern diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index d2f78e1f6..fba57a593 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -485,6 +485,7 @@ Arg For File The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Default Web Browser @@ -495,6 +496,8 @@ New Window New Tab Private Mode + Default + New Profile Change Priority diff --git a/Flow.Launcher/Languages/es-419.xaml b/Flow.Launcher/Languages/es-419.xaml index b3333c7a9..e18cdb3fe 100644 --- a/Flow.Launcher/Languages/es-419.xaml +++ b/Flow.Launcher/Languages/es-419.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Tienda de Plugins @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg para Archivo The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Navegador Web Predeterminado @@ -500,6 +504,8 @@ Nueva Ventana Nueva Pestaña Modo Privado + Default + New Profile Cambiar Prioridad diff --git a/Flow.Launcher/Languages/es.xaml b/Flow.Launcher/Languages/es.xaml index 73cd943a2..faaef8451 100644 --- a/Flow.Launcher/Languages/es.xaml +++ b/Flow.Launcher/Languages/es.xaml @@ -24,8 +24,8 @@ Flow Launcher ha detectado que los datos de usario existen tanto en {0} como en {1}. {2}{2}Por favor, elimine {1} para continuar. No se han producido cambios. - El siguiente complemento ha sufrido un error y no puede cargarse: - Los siguientes complementos han sufrido un error y no pueden cargarse: + El siguiente complemento ha sufrido un fallo y no se puede cargar: + Los siguientes complementos han sufrido un fallo y no se pueden cargar: Por favor, consulte los registros para más información @@ -224,6 +224,7 @@ Fallo al desinstalar {0} No se puede encontrar plugin.json en el archivo zip extraído, o esta ruta {0} no existe Ya existe un complemento con el mismo ID y versión, o la versión es superior a la de este complemento descargado + Error creating setting panel for plugin {0}:{1}{2} Tienda complementos @@ -332,7 +333,7 @@ Cambia 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. - Since Always Preview is on, maximum results shown may not take effect because preview panel requires a certain minimum height + Dado que la vista previa está siempre activada, es posible que no se muestren los resultados máximos, ya que el panel de vista previa requiere una altura mínima determinada Atajo de teclado @@ -395,7 +396,7 @@ Mostrar distintivos en resultados Para los complementos compatibles, se muestran distintivos que ayudan a distinguirlos más fácilmente. Mostrar distintivos en resultados solo para consulta global - Mostrar distintivos solo para los resultados de consultas globales + Muestra distintivos solo para los resultados de consultas globales Salto de diálogo Introducir atajo de teclado para acceder rápidamente a la ventana de diálogo Abrir/Guardar como en la ruta del administrador de archivos actual. Salto de diálogo @@ -467,8 +468,10 @@ Abrir carpeta Avanzado Nivel de registro - Depuración + Silencioso + Error Información + Depuración Configuración de fuente de la ventana @@ -490,6 +493,7 @@ Argumentos del archivo El administrador de archivos '{0}' no pudo ser localizado en '{1}'. ¿Desea continuar? Error de ruta del administrador de archivos + File Explorer Navegador web predeterminado @@ -500,6 +504,8 @@ Nueva ventana Nueva pestaña Modo privado + Default + New Profile Cambiar la prioridad diff --git a/Flow.Launcher/Languages/fr.xaml b/Flow.Launcher/Languages/fr.xaml index ced3aabe0..8aa1b5cd5 100644 --- a/Flow.Launcher/Languages/fr.xaml +++ b/Flow.Launcher/Languages/fr.xaml @@ -224,6 +224,7 @@ Échec de la désinstallation de {0} Impossible de trouver le fichier plugin.json dans le fichier zip extrait, ou ce chemin {0} n'existe pas Un plugin avec le même ID et la même version existe déjà, ou la version est supérieure à ce plugin téléchargé + Erreur lors de la création du panneau de configuration pour le plugin {0}:{1}{2} Magasin des Plugins @@ -466,8 +467,10 @@ Ouvrir le dossier Avancé Niveau de journalisation - Débogage + Silencieux + Erreur Info + Débogage Réglage de la police de la fenêtre @@ -489,6 +492,7 @@ Arguments pour le fichier Le gestionnaire de fichiers '{0}' n'a pas pu être situé à '{1}'. Souhaitez-vous continuer ? Erreur de chemin du gestionnaire de fichiers + Explorateur de fichiers Navigateur web par défaut @@ -499,6 +503,8 @@ Nouvelle fenêtre Nouvel onglet Mode privé + Par défaut + Nouveau profil Changer la priorité diff --git a/Flow.Launcher/Languages/he.xaml b/Flow.Launcher/Languages/he.xaml index 164f13afd..f9f0ba2e3 100644 --- a/Flow.Launcher/Languages/he.xaml +++ b/Flow.Launcher/Languages/he.xaml @@ -223,6 +223,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} חנות תוספים @@ -466,8 +467,10 @@ פתח תיקיה Advanced רמת יומן - ניפוי שגיאות + Silent + שגיאה מידע + ניפוי שגיאות Setting Window Font @@ -489,6 +492,7 @@ ארגומנט לקובץ לא ניתן היה לאתר את מנהל הקבצים '{0}' ב-'{1}'. האם ברצונך להמשיך? שגיאת נתיב למנהל הקבצים + File Explorer דפדפן ברירת מחדל @@ -499,6 +503,8 @@ חלון חדש כרטיסייה חדשה מצב פרטיות + Default + New Profile שנה עדיפות diff --git a/Flow.Launcher/Languages/it.xaml b/Flow.Launcher/Languages/it.xaml index e1d0fadca..60584807c 100644 --- a/Flow.Launcher/Languages/it.xaml +++ b/Flow.Launcher/Languages/it.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Negozio dei Plugin @@ -467,8 +468,10 @@ Apri Cartella Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg Per Cartella The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Browser predefinito @@ -500,6 +504,8 @@ Nuova Finestra Nuova Scheda Modalità Privata + Default + New Profile Cambia Priorità diff --git a/Flow.Launcher/Languages/ja.xaml b/Flow.Launcher/Languages/ja.xaml index 13cd30fd7..de142733f 100644 --- a/Flow.Launcher/Languages/ja.xaml +++ b/Flow.Launcher/Languages/ja.xaml @@ -2,43 +2,43 @@ - Flow detected you have installed {0} plugins, which will require {1} to run. Would you like to download {1}? + Flow はあなたが {0} プラグインをインストールしており、実行するために {1} が必要であることを検知しました。{1} をインストールしますか? {2}{2} - Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable + {1}がすでにインストールされている場合は「いいえ」をクリックし、それが入っているフォルダーを選択してください - Please select the {0} executable + {0} の実行ファイルを選択してください - Your selected {0} executable is invalid. + あなたが選択した {0} の実行ファイルが不正です。 {2}{2} - Click yes if you would like select the {0} executable again. Click no if you would like to download {1} + {0} の実行ファイルをもう一度選択する場合は「はい」を、{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 + {0} の実行可能ファイルのパスを設定できません。Flow の設定から試してください(下までスクロールしてください)。 + プラグインの起動失敗 + プラグイン: {0} の読み込みに失敗したため、無効になりました。プラグインの作成者にお問い合わせください Flow Launcherはポータブルモードの無効化のために再起動する必要があります。再起動の後、ポータブルな形式の設定項目は削除され、あなたのパソコンのフォルダに保存されます Flow Launcherはポータブルモードの有効化のために再起動する必要があります。再起動の後、パソコンに保存された設定項目は削除され、ポータブルな形式で保存されます Flow Launcherはポータブルモードの有効化を検知しました。Flow Launcherを別の場所に移動しますか? Flow Launcherはポータブルモードの無効化を検知しました。関連するショートカットやアンインストーラーが配置されます - Flow Launcher detected your user data exists both in {0} and {1}. {2}{2}Please delete {1} in order to proceed. No changes have occurred. + Flow Launcherはあなたのユーザーデータが{0} と {1} の両方に存在することを検知しました。{2}{2}続行するには、{1}を削除してください。処理は中断されました。 - The following plugin has errored and cannot be loaded: - The following plugins have errored and cannot be loaded: - Please refer to the logs for more information + 以下のプラグインにエラーがあるためロードできません: + 以下のプラグインにエラーがあるためロードできません: + 詳細はログを参照してください - Please try again - Unable to parse Http Proxy + もう一度お試しください + Http プロキシをパースできません - Failed to install TypeScript environment. Please try again later - Failed to install Python environment. Please try again later. + TypeScript環境のインストールに失敗しました。後でもう一度お試しください + Python 環境のインストールに失敗しました。後でもう一度お試しください。 ホットキー "{0}" の登録に失敗しました。このホットキーは別のプログラムで使用されている可能性があります。別のホットキーに変更するか、このホットキーを使用しているプログラムを終了してください。 - Failed to unregister hotkey "{0}". Please try again or see log for details + ホットキー「{0}」の登録解除に失敗しました。もう一度試すか、ログを参照して詳細を確認してください Flow Launcher {0}の起動に失敗しました Flow Launcherプラグインの形式が正しくありません @@ -58,7 +58,7 @@ 全て選択 ファイル フォルダー - Text + テキスト ゲームモード ホットキーの使用を一時停止します。 位置のリセット @@ -73,7 +73,7 @@ スタートアップ時にFlow Launcherを起動する 起動の高速化のためにスタートアップではなくログオンタスクを使用 アンインストール後は、「タスク スケジューラ」からこのタスク(Flow.Launcher Startup)を手動で削除する必要があります。 - Error setting launch on startup + スタートアップ時に起動の設定失敗 フォーカスを失った時にFlow Launcherを隠す 最新版が入手可能であっても、アップグレードメッセージを表示しない 検索ウィンドウの位置 @@ -111,7 +111,7 @@ 常に英語モードで入力を開始する Flowを起動したとき、一時的に入力方法を英語モードに変更します。 自動更新 - Automatically check and update the app when available + 利用可能な場合、Flow Launcherを自動的に確認して更新します 選択 起動時にFlow Launcherを隠す 起動後、Flow Launcher の検索ウィンドウは非表示になり、トレイに格納されます。 @@ -123,10 +123,10 @@ 標準 ピンインによる検索 - Pinyin is the standard system of romanized spelling for translating Chinese. Please note, enabling this can significantly increase memory usage during search. - Use Double Pinyin - Use Double Pinyin instead of Full Pinyin to search. - Double Pinyin Schema + Pinyinは中国語を翻訳するためのローマ字入力の標準的な方法です。有効にすると、検索時のメモリ使用量が大幅に増加する可能性があります。 + 双拼入力を使用 + 検索するときに全拼の代わりに双拼を使用する。 + 双拼の入力方式 Xiao He Zi Ran Ma Wei Ruan @@ -142,10 +142,10 @@ 現在のテーマでぼかしの効果が有効になっている場合、影の効果を有効にすることはできません 検索遅延 入力中に短い遅延を追加することで、UIのちらつきや結果の読み込みを軽減します。平均的なタイピング速度のユーザーにおすすめです。 - Enter the wait time (in ms) until input is considered complete. This can only be edited if Search Delay is enabled. + 入力中の結果表示までの待ち時間をミリ秒単位で入力します。これは、検索遅延が有効な場合にのみ編集できます。 デフォルトの検索遅延時間 入力が停止した後に結果が表示されるまでの待ち時間。値が大きいほど長く待機します。(単位 ms) - Information for Korean IME user + 韓国語IMEユーザーへの情報 The Korean input method used in Windows 11 may cause some issues in Flow Launcher. @@ -160,29 +160,29 @@ - Open Language and Region System Settings + システムの言語と地域設定を開く Opens the Korean IME setting location. Go to Korean > Language Options > Keyboard - Microsoft IME > Compatibility 開く - Use Previous Korean IME + 前の韓国語IMEを使用 You can change the Previous Korean IME settings directly from here Failed to change Korean IME setting - Please check your system registry access or contact support. + システムのレジストリへのアクセスが可能か確認するか、サポートにお問い合わせください。 ホームページ 検索文字列が空の場合、ホームページの結果を表示します。 クエリの履歴をホームページに表示 ホームページに表示される最大の履歴の数 - This can only be edited if plugin supports Home feature and Home Page is enabled. - Show Search Window at Foremost + これは、プラグインがホーム機能をサポートし、ホームページが有効な場合にのみ編集することができます。 + 検索ウィンドウを最前面に表示 他のプログラムの 'Always on Top' (最前面に表示)設定を上書きし、常に最前面のウィンドウで Flow を表示します。 - プラグインストアでプラグインを変更した後に再起動します + プラグインストアでプラグインを変更した後に再起動 プラグインストア経由でプラグインをインストール、アンインストール、または更新した後、Flow Lancherを自動的に再起動します 不明なソースの警告を表示 不明なソースからプラグインをインストールするときに警告を表示する - Auto update plugins - Automatically check plugin updates and notify if there are any updates available + プラグインの自動アップデート + プラグインの更新を自動的にチェックし、利用可能な更新がある場合に通知します - Search Plugin + プラグインの検索 Ctrl+F でプラグインを検索します 検索結果が見つかりませんでした 別の検索を試してみてください。 @@ -191,20 +191,20 @@ プラグインを探す 有効 無効 - Action keyword Setting + アクションキーワードの設定 キーワード - Current action keyword - New action keyword - Change Action Keywords - Plugin search delay time - Change Plugin Search Delay Time + 現在のアクションキーワード + 新しいアクションキーワード + アクションキーワードの変更 + プラグインの検索遅延時間 + プラグインの検索遅延時間を変更 詳細設定: 有効 重要度 検索遅延 ホームページ - Current Priority - New Priority + 現在の優先度 + 新しい優先度 重要度 プラグインの結果の優先度を変更します。 プラグイン・ディレクトリ @@ -214,59 +214,60 @@ バージョン ウェブサイト アンインストール - 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 - {0} modified already - Please restart Flow before making any further changes - Fail to install {0} - Fail to uninstall {0} - Unable to find plugin.json from the extracted zip file, or this path {0} does not exist - A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + プラグイン設定の削除に失敗 + プラグイン: {0} - プラグイン設定ファイルの削除に失敗しました。手動で削除してください + プラグインキャッシュの削除に失敗 + プラグイン: {0} - プラグインキャッシュファイルの削除に失敗しました。手動で削除してください + {0} は既に変更されています + これ以上変更を加える前に Flow Launcher を再起動してください + {0} のインストールに失敗 + {0} のアンインストールに失敗 + 展開されたzipファイルからplugin.jsonが見つからないか、このパス {0} が存在しません + 同じIDとバージョンのプラグインがすでに存在するか、またはこのダウンロードしたプラグインよりもバージョンが大きいです + Error creating setting panel for plugin {0}:{1}{2} プラグインストア 新規リリース 最近の更新 プラグイン - Installed + インストール済み 更新 インストール アンインストール 更新 - Plugin already installed - New Version - This plugin has been updated within the last 7 days + プラグインは既にインストールされています + 新しいバージョン + このプラグインは過去1週間以内に更新されました 新しいアップデートが利用可能です プラグインのインストール失敗 プラグインのアンインストール失敗 - Error updating plugin + プラグインの更新に失敗 プラグインの設定を維持 再びインストールして使用するときのためにプラグインの設定を維持しますか? - Plugin {0} successfully installed. Please restart Flow. - Plugin {0} successfully uninstalled. Please restart Flow. - Plugin {0} successfully updated. Please restart Flow. + プラグイン {0} のインストールに成功しました。Flow を再起動してください。 + プラグイン {0} のアンインストールに成功しました。Flow を再起動してください。 + プラグイン {0} が正常に更新されました。Flow を再起動してください。 プラグインのインストール {0} by {1} {2}{2}このプラグインをインストールしますか? プラグインのアンインストール {0} by {1} {2}{2}このプラグインをアンインストールしますか? - Plugin update - {0} by {1} {2}{2}Would you like to update this plugin? - Downloading plugin - Automatically restart after installing/uninstalling/updating plugins in plugin store - Zip file does not have a valid plugin.json configuration + プラグインの更新 + {0} by {1} {2}{2}このプラグインを更新しますか? + プラグインをダウンロード中 + プラグインストア経由でのプラグインのインストール 、アンインストール、または更新後に自動的に再起動します + Zipファイルに有効なplugin.jsonファイルがありません 不明なソースからのインストール このプラグインは不明なソースから提供されており、潜在的なリスクを含んでいる可能性があります!{0}{0}このプラグインの開発元をよく調べ、安全であることをご自身で確かめてください。{0}{0}それでもあなたはこのプラグインをインストールしますか?{0}{0}(この警告は設定の「一般」セクションで無効にすることができます) - Zip files - Please select zip file + Zip ファイル + zipファイルを選択してください ローカルパスからプラグインをインストール - No update available - All plugins are up to date - Plugin updates available - Update plugins - Check plugin updates - Plugins are successfully updated. Please restart Flow. + 利用可能な更新はありません + すべてのプラグインが最新です + プラグインの更新が利用可能 + プラグインを更新 + プラグインの更新を確認 + プラグインが正常に更新されました。Flow を再起動してください。 テーマ @@ -285,13 +286,13 @@ 検索バーの高さ アイテムの高さ 検索ボックスのフォント - Result Title Font - Result Subtitle Font + 結果のタイトルのフォント + 結果のサブタイトルのフォント リセット - Reset to the recommended font and size settings. - Import Theme Size - If a size value intended by the theme designer is available, it will be retrieved and applied. - Customize + 推奨されるフォントとサイズの設定にリセットします。 + テーマ中のサイズをインポート + テーマのデザイナーによって意図されたサイズ値が利用可能なとき、それを取得して適用します。 + カスタマイズ ウィンドウモード 透過度 テーマ {0} が存在しません、デフォルトのテーマに戻します。 @@ -306,7 +307,7 @@ 検索ウィンドウが開いたとき、小さな音を鳴らします 効果音の音量 効果音の音量を調整します - Windows Media Player is unavailable and is required for Flow's volume adjustment. Please check your installation if you need to adjust volume. + Windows Media Player は Flow を使った音量調整に必要です。ボリュームを調整する必要がある場合は、Windows Media Player がインストールされているかどうか確認してください。 アニメーション UIでアニメーションを使用します アニメーション速度 @@ -324,15 +325,15 @@ アクリル マイカ マイカ(代替) - This theme supports two (light/dark) modes. - This theme supports Blur Transparent Background. + このテーマはライト/ダークの2モードに対応しています。 + このテーマは背景をぼかした透明効果をサポートしています。 プレースホルダーを表示 クエリが空の場合にプレースホルダを表示します 検索欄の案内文 - Change placeholder text. Input empty will use: {0} + プレースホルダのテキストを変更します。空にすると、 {0} が使用されます ウィンドウサイズの固定 ウィンドウのサイズを固定し、ドラッグでの変更を無効にします。 - Since Always Preview is on, maximum results shown may not take effect because preview panel requires a certain minimum height + 「常にプレビューする」が有効になっているため、プレビューパネルの高さの確保のために「結果の最大表示件数」設定は無視される可能性があります ホットキー @@ -372,51 +373,51 @@ カスタムクエリ ホットキー Custom Query Shortcut 組み込みショートカット - Query + クエリー ショートカット 展開 説明 削除 編集 追加 - None + なし 項目を選択してください {0} プラグインのホットキーを本当に削除しますか? 本当にこのショートカットを削除しますか?: {0} を {1} に展開 - Get text from clipboard. + クリップボードからテキストを取得します。 アクティブなエクスプローラーからパスを取得します。 検索ウィンドウの落陰効果 - Shadow effect has a substantial usage of GPU. Not recommended if your computer performance is limited. - Window Width Size - You can also quickly adjust this by using Ctrl+[ and Ctrl+]. + 影の効果は GPU に大きな負荷をかけます。お使いのコンピューターの性能が限定的な場合、無効にすることをおすすめします。 + ウィンドウ幅のサイズ + Ctrl+Plus と Ctrl+Minus を使用すれば、簡単に調整することもできます。 Segoe Fluent アイコンを使用する サポートされているクエリ結果にSegoe Fluentアイコンを使用する - Press Key - Show Result Badges + キーを入力 + 結果のバッジを表示 サポートされているプラグインでは、バッジが表示され、より簡単に区別できます。 - Show Result Badges for Global Query Only - Show badges for global query results only - Dialog Jump - Enter shortcut to quickly navigate the Open/Save As dialog window to the path of the current file manager. - Dialog Jump - When Open/Save As dialog window opens, quickly navigate to the current path of the file manager. - Dialog Jump Automatically - When Open/Save As dialog window is displayed, automatically navigate to the path of the current file manager. (Experimental) - Show Dialog Jump Window - Display Dialog Jump search window when the open/save dialog window is shown to quickly navigate to file/folder locations. - Dialog Jump Window Position - Select position for the Dialog Jump search window - Fixed under the Open/Save As dialog window. Displayed on open and stays until the window is closed - Default search window position. Displayed when triggered by search window hotkey - Dialog Jump Result Navigation Behaviour - Behaviour to navigate Open/Save As dialog window to the selected result path - Left click or Enter key - Right click - Dialog Jump File Navigation Behaviour - Behaviour to navigate Open/Save As dialog window when the result is a file path - Fill full path in file name box - Fill full path in file name box and open - Fill directory in path box + グローバルクエリのみ、結果のバッジを表示 + グローバルクエリの結果にのみバッジを表示する + ダイアログジャンプ + ショートカットを入力して、「名前を付けて開く/保存」ダイアログ・ウィンドウを現在のファイルマネージャのパスにすばやくナビゲートします。 + ダイアログジャンプ + 「名前を付けて開く/保存」ダイアログウィンドウが開いたら、すぐにファイルマネージャの現在のパスに移動します。 + 自動ダイアログジャンプ + 開く/名前を付けて保存ダイアログが表示されると、自動的に現在のファイルマネージャのパスに移動させます。 (実験的) + ダイアログジャンプウィンドウを表示 + 「名前をつけて保存/開く」ダイアログウィンドウが表示されたときにダイアログジャンプのウィンドウを開いて、ファイルやフォルダーを素早く開く。 + ダイアログジャンプのウィンドウの位置 + ダイアログジャンプ検索ウィンドウの位置を選択します + 「名前を付けて開く/保存」ダイアログウィンドウの下に固定。ウィンドウが閉じるまで開いたまま表示されます + デフォルトの検索ウィンドウの位置。検索ウィンドウのホットキーによってトリガーされたときに表示されます + ダイアログジャンプの検索結果の開き方 + 「開く/名前を付けて保存」ダイアログウィンドウの選択した結果パスに移動する動作 + 左クリックまたはEnter キー + 右クリック + ダイアログジャンプのファイルに対する動作 + 結果がファイルパスの場合の、「開く/名前を付けて保存」ダイアログウィンドウに対する動作 + フルパスをファイル名ボックスに入力 + フルパスをファイル名ボックスに入力して開く + パスボックスに含まれるフォルダを入力 HTTP プロキシ @@ -467,44 +468,49 @@ フォルダーを開く 上級者向け機能 ログレベル - デバッグ + Silent + エラー 情報 + デバッグ 設定ウィンドウで使用するフォント - See more release notes on GitHub - Failed to fetch release notes - Please check your network connection or ensure GitHub is accessible - Flow Launcher has been updated to {0} - Click here to view the release notes + GitHub で詳細なリリース ノートを見る + リリースノートの取得に失敗 + ネットワーク接続を確認するか、GitHubにアクセスできることを確認してください + Flow Launcher が {0}に更新されました + ここをクリックしてリリースノートを表示 デフォルトのファイルマネージャー - Learn more - Please specify the file location of the file manager you using and add arguments as required. The "%d" represents the directory path to open for, used by the Arg for Folder field and for commands opening specific directories. The "%f" represents the file path to open for, used by the Arg for File field and for commands opening specific files. - For example, if the file manager uses a command such as "totalcmd.exe /A c:\windows" to open the c:\windows directory, the File Manager Path will be totalcmd.exe, and the Arg For Folder will be /A "%d". Certain file managers like QTTabBar may just require a path to be supplied, in this instance use "%d" as the File Manager Path and leave the rest of the fields blank. - File Manager - Profile Name - File Manager Path - Arg For Folder - Arg For File - The file manager '{0}' could not be located at '{1}'. Would you like to continue? - File Manager Path Error + 詳細を見る + 使用したいファイルマネージャーのファイルの位置を指定し、コマンドライン引数を入力してください。"%d" は開こうとしているフォルダーのパスを表し、「フォルダー用の引数」の欄で特定のフォルダーを開くために使用されます。"%f" は開こうとしているファイルのパスを表し、「ファイル用の引数」の欄で特定のファイルを開くために使用されます。 + 例として、ファイルマネージャーが "totalcmd.exe /A c:\windows" というコマンドを c:\windows というフォルダを開くために使用する場合を考えます。この場合、ファイルマネージャーのパスは totalcmd.exe で、フォルダー用の引数は /A "%d" になります。QTTabBarのように、パスのみを要求するファイルマネージャーの場合、”%d” をファイルマネージャーのパスの欄に指定し、残りを空欄にしてください。 + ファイル マネージャー + プロファイル名 + ファイルマネージャーのパス + フォルダー用の引数 + ファイル用の引数 + ファイルマネージャー '{0}' は、'{1}' に見つかりませんでした。続行しますか? + ファイルマネージャのパスエラー + File Explorer デフォルトのウェブブラウザー - The default setting follows the OS default browser setting. If specified separately, flow uses that browser. - Browser - Browser Name - Browser Path - New Window - New Tab - Private Mode + デフォルトの設定は、OS のデフォルトのブラウザ設定に従います。別々に指定すると、Flow はそのブラウザを使用します。 + ブラウザー + ブラウザー名 + ブラウザーのパス + 新しいウィンドウ + 新しいタブ + プライベートモード + Default + New Profile - Change Priority - Greater the number, the higher the result will be ranked. Try setting it as 5. If you want the results to be lower than any other plugin's, provide a negative number - Please provide an valid integer for Priority! + 優先度の変更 + 数値が大きいほど、結果の上の方に表示されます。試しに5として設定してみてください。 結果を他のプラグインよりも低くしたい場合は、負の数字を入力してください + 優先度には有効な整数を入力してください! 古いアクションキーワード @@ -514,33 +520,33 @@ 指定されたプラグインが見つかりません 新しいアクションキーワードを空にすることはできません 新しいアクションキーワードは他のプラグインに割り当てられています。他のアクションキーワードを入力してください - This new Action Keyword is the same as old, please choose a different one + そのアクションキーワードは以前のものと同じです。他のアクションキーワードを入力してください 成功しました - Completed successfully - Failed to copy - 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 - Input the search delay time in ms you like to use for the plugin. Input empty if you don't want to specify any, and the plugin will use default search delay time. + 検索の遅延時間の設定 + プラグインに使用したい検索の遅延時間をミリ秒で入力します。 何も指定したくない場合は空にしておくと、プラグインはデフォルトの検索の遅延時間を使用します。 ホームページ - Enable the plugin home page state if you like to show the plugin results when query is empty. + クエリが空のときにプラグインの結果を表示したい場合は、プラグインのホームページの設定を有効にします。 カスタムクエリのホットキー - Press a custom hotkey to open Flow Launcher and input the specified query automatically. + カスタムホットキーを押して Flow Launcher を開き、指定したクエリを自動的に入力します。 プレビュー ホットキーは使用できません。新しいホットキーを選択してください - Hotkey is invalid + そのホットキーは無効です 更新 - Binding Hotkey - Current hotkey is unavailable. - This hotkey is reserved for "{0}" and can't be used. Please choose another hotkey. - This hotkey is already in use by "{0}". If you press "Overwrite", it will be removed from "{0}". - Press the keys you want to use for this function. - Hotkey and action keyword are empty + ホットキーの設定 + 現在のホットキーは使用できません。 + このホットキーは "{0}" で予約されており、使用できません。別のホットキーを選択してください。 + このホットキーは "{0}" によってすでに使用されています。「上書き」を押すと、"{0}"から削除されます。 + この機能に使用するキーを押してください。 + ホットキーとアクションキーワードが空です カスタムクエリのショートカット @@ -551,11 +557,11 @@ そのショートカットは既に存在します。新しいショートカットを入力するか、既存のショートカットを編集してください。 ショートカット、展開の少なくとも一方が空です。 - Shortcut is invalid + ショートカットが無効です 保存 - Overwrite + 上書き キャンセル リセット 削除 @@ -580,46 +586,46 @@ クラッシュレポートの送信に失敗しました Flow Launcherにエラーが発生しました Please open new issue in - 1. Upload log file: {0} - 2. Copy below exception message + 1. ログファイルをアップロード: {0} + 2. 例外メッセージ以下をコピー - File Manager Error + ファイルマネージャのエラー - The specified file manager could not be found. Please check the Custom File Manager setting under Settings > General. + 指定されたファイルマネージャーが見つかりませんでした。設定 > 一般でカスタムファイルマネージャの設定を確認してください。 - Error - An error occurred while opening the folder. {0} - An error occurred while opening the URL in the browser. Please check your Default Web Browser configuration in the General section of the settings window + エラー + フォルダを開く際にエラーが発生しました。 {0} + ブラウザでURLを開く際にエラーが発生しました。設定ウィンドウの一般セクションでデフォルトのウェブブラウザ設定を確認してください - Please wait... + しばらくお待ちください… - Checking for new update + 新しい更新を確認中 Flow Launcherは既に最新です - Update found - Updating... + 更新が見つかりました + 更新中… - Flow Launcher was not able to move your user profile data to the new update version. - Please manually move your profile data folder from {0} to {1} + Flow Launcherはユーザープロファイルデータを新しいバージョンに移動できませんでした。 + 手動で {0} から {1}にプロフィールデータフォルダを移動してください - New Update + 新しい更新 Flow Launcher の最新バージョン V{0} が入手可能です Flow Launcherのアップデート中にエラーが発生しました 更新 キャンセル - Update Failed - Check your connection and try updating proxy settings to github-cloud.s3.amazonaws.com. + アップデート失敗 + 接続を確認し、その後プロキシ設定を github-cloud.s3.amazonaws.com に更新してみてください。 このアップデートでは、Flow Launcherの再起動が必要です 次のファイルがアップデートされます 更新ファイル一覧 アップデートの詳細 - Restart Flow Launcher after updating plugins - {0}: Update from v{1} to v{2} - No plugin selected + プラグインを更新した後、Flow Launcher を再起動する + {0}: v{1} から v{2} へ更新 + プラグインが選択されていません スキップ @@ -642,18 +648,18 @@ コンテキストメニューを開く ファイルのあるフォルダを開く 管理者として実行、または、 デフォルトのファイルマネージャでフォルダを開く - Query History + クエリの履歴 コンテキストメニューから検索結果に戻る - Autocomplete + 自動補完 選択したアイテムを開く、または、実行する Flow Launcherの設定ウインドウを開く プラグインデータのリロード - Select first result - Select last result - Run current query again + 最初の結果を選択 + 最後の結果を選択 + 現在のクエリをもう一度実行 結果を開く - Open result #{0} + #{0} を開く 天気 天気についてのGoogle検索 diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml index 6cf1a6274..131aa50cb 100644 --- a/Flow.Launcher/Languages/ko.xaml +++ b/Flow.Launcher/Languages/ko.xaml @@ -215,6 +215,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} 플러그인 스토어 @@ -458,8 +459,10 @@ 폴더 열기 Advanced 로그 레벨 - Debug + Silent + Error Info + Debug 설정창 글꼴 @@ -481,6 +484,7 @@ 파일경로 인수 The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer 기본 웹 브라우저 @@ -491,6 +495,8 @@ 새 창 새 탭 사생활 보호 모드 + Default + New Profile 중요도 변경 diff --git a/Flow.Launcher/Languages/nb.xaml b/Flow.Launcher/Languages/nb.xaml index 57afaa87b..a27f66d11 100644 --- a/Flow.Launcher/Languages/nb.xaml +++ b/Flow.Launcher/Languages/nb.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Programtillegg butikk @@ -467,8 +468,10 @@ Åpne mappe Advanced Log Level - Debug + Silent + Feil Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg for fil The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Standard nettleser @@ -500,6 +504,8 @@ Nytt vindu Ny fane Privat modus + Default + New Profile Endre prioritet diff --git a/Flow.Launcher/Languages/nl.xaml b/Flow.Launcher/Languages/nl.xaml index 5b7ba1d21..416091858 100644 --- a/Flow.Launcher/Languages/nl.xaml +++ b/Flow.Launcher/Languages/nl.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Plugin Winkel @@ -467,8 +468,10 @@ Map openen Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg voor bestand The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Standaard webbrowser @@ -500,6 +504,8 @@ Nieuw Venster Nieuw tabblad Privé modus + Default + New Profile Prioriteit wijzigen diff --git a/Flow.Launcher/Languages/pl.xaml b/Flow.Launcher/Languages/pl.xaml index 92b91d287..1295e66c9 100644 --- a/Flow.Launcher/Languages/pl.xaml +++ b/Flow.Launcher/Languages/pl.xaml @@ -223,6 +223,7 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Sklep z wtyczkami @@ -466,8 +467,10 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Otwórz folder Zaawansowane Poziom logowania - Debug + Silent + Błąd Info + Debug Ustawienia czcionki okna @@ -489,6 +492,7 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Arg dla pliku Menedżer plików „{0}” nie został znaleziony w lokalizacji „{1}”. Czy chcesz kontynuować? Błąd ścieżki do menedżera plików + File Explorer Domyślna przeglądarka @@ -499,6 +503,8 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Nowe okno Nowa zakładka Tryb prywatny + Default + New Profile Zmień priorytet diff --git a/Flow.Launcher/Languages/pt-br.xaml b/Flow.Launcher/Languages/pt-br.xaml index 9b0db5a9e..91193bd0a 100644 --- a/Flow.Launcher/Languages/pt-br.xaml +++ b/Flow.Launcher/Languages/pt-br.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Loja de Plugins @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg para Arquivo The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Navegador da Web Padrão @@ -500,6 +504,8 @@ Nova Janela Nova Aba Modo Privado + Default + New Profile Alterar Prioridade diff --git a/Flow.Launcher/Languages/pt-pt.xaml b/Flow.Launcher/Languages/pt-pt.xaml index 1a68f23f4..080573821 100644 --- a/Flow.Launcher/Languages/pt-pt.xaml +++ b/Flow.Launcher/Languages/pt-pt.xaml @@ -223,6 +223,7 @@ Falha ao desinstalar {0} Não foi possível encontrar plugin.json no ficheiro zip ou, então, o caminho {0} não existe. Já existe um plugin com a mesma ID e versão ou, então, a versão instalada é superior à do plugin descarregado. + Erro ao criar o painel de definição para o plugin {0}:{1}{2} Loja de plugins @@ -331,7 +332,7 @@ 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. - Since Always Preview is on, maximum results shown may not take effect because preview panel requires a certain minimum height + Como a opção "Pré-visualizar sempre" está ativa, os resultados máximos mostrados podem não ter efeito porque o painel de visualização requer uma altura mínima Tecla de atalho @@ -465,8 +466,10 @@ Abrir pasta Avançado Nível de registo - Depuração + Silencioso + Erro Informação + Depuração Tipo de letra da aplicação @@ -488,6 +491,7 @@ Argumento para ficheiro Não foi possível encontrar o gestor de ficheiros '{0}' em '{1}'. Deseja continuar? Erro no caminho do gestor de ficheiros + Gestor de ficheiros Navegador web padrão @@ -498,6 +502,8 @@ Nova janela Novo separador Modo privado + Padrão + Novo perfil Alterar prioridade diff --git a/Flow.Launcher/Languages/ru.xaml b/Flow.Launcher/Languages/ru.xaml index 43d26aff2..c506d0765 100644 --- a/Flow.Launcher/Languages/ru.xaml +++ b/Flow.Launcher/Languages/ru.xaml @@ -167,7 +167,7 @@ You can change the Previous Korean IME settings directly from here Failed to change Korean IME setting Please check your system registry access or contact support. - Home Page + Главная страница Show home page results when query text is empty. Show History Results in Home Page Maximum History Results Shown in Home Page @@ -199,10 +199,10 @@ Plugin search delay time Change Plugin Search Delay Time Advanced Settings: - Enabled + Включено Приоритет Search Delay - Home Page + Главная страница Текущий приоритет Новый приоритет Приоритет @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Магазин плагинов @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Ошибка Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Аргумент для файла The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Браузер по умолчанию @@ -500,6 +504,8 @@ Новое окно Новая вкладка Приватный режим + Default + New Profile Изменить приоритет @@ -525,7 +531,7 @@ Input the search delay time in ms you like to use for the plugin. Input empty if you don't want to specify any, and the plugin will use default search delay time. - Home Page + Главная страница Enable the plugin home page state if you like to show the plugin results when query is empty. diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml index 855c0635e..e909a24b1 100644 --- a/Flow.Launcher/Languages/sk.xaml +++ b/Flow.Launcher/Languages/sk.xaml @@ -176,7 +176,7 @@ Nevykonali sa žiadne zmeny. Zobraziť vyhľadávacie okno v popredí Prepíše nastavenie "Vždy na vrchu" ostatných programov a zobrazí navrchu Flow. Reštartovať po úprave pluginu cez Repozitár pluginov - Automaticky reštartovať Flow Launcher po inštalácii/odinštalácii/aktualizáciu pluginu cez Repozitár pluginov + Automaticky reštartovať Flow Launcher po inštalácii/odinštalácii/aktualizácii pluginu cez Repozitár pluginov Zobraziť upozornenie na neznámy zdroj Zobraziť upozornenie pri inštalácii z neznámych zdrojov Automaticky aktualizovať pluginy @@ -225,6 +225,7 @@ Nevykonali sa žiadne zmeny. Nepodarilo sa odinštalovať {0} Súbor plugin.json sa nenašiel v rozbalenom zip súbore, alebo táto cesta {0} neexistuje Plugin s rovnakým ID už existuje, alebo ide o vyššiu verziu ako stiahnutý plugin + Chyba pri vytváraní panelu nastavení pre plugin {0}:{1}{2} Repozitár pluginov @@ -255,7 +256,7 @@ Nevykonali sa žiadne zmeny. Aktualizácia pluginu {0} od {1} {2}{2}Chcete aktualizovať tento plugin? Sťahovanie pluginu - Automaticky reštartovať po inštalácii/odinštalácii/aktualizáciu pluginov cez Repozitár pluginov + Automaticky reštartovať po inštalácii/odinštalácii/aktualizácii pluginov cez Repozitár pluginov V zipe sa nenachádza platná konfigurácia plugin.json Inštalácia z neznámeho zdroja Tento plugin pochádza z neznámeho zdroja a môže predstavovať potenciálne riziká!{0}{0}Uistite sa, že viete, odkiaľ tento plugin pochádza, a že je bezpečný.{0}{0}Stále chcete pokračovať?{0}{0}(Toto upozornenie môžete vypnúť sekcii Všeobecné v nastaveniach) @@ -267,7 +268,7 @@ Nevykonali sa žiadne zmeny. Dostupná aktualizácia pluginu Aktualizovať pluginy Skontrolovať dostupnosť aktualizácií - Pluginy {0} boli úspešne aktualizované. Prosím, reštartuje Flow. + Pluginy boli úspešne aktualizované. Prosím, reštartuje Flow. Motív @@ -396,28 +397,28 @@ Nevykonali sa žiadne zmeny. Zobraziť výsledok v odznaku Ak to plugin podporuje, zobrazí sa jeho ikona v odznaku na jednoduchšie odlíšenie. Zobraziť výsledok v odznaku len pre globálne vyhľadávanie - Show badges for global query results only - Dialog Jump - Enter shortcut to quickly navigate the Open/Save As dialog window to the path of the current file manager. - Dialog Jump - When Open/Save As dialog window opens, quickly navigate to the current path of the file manager. - Dialog Jump Automatically - When Open/Save As dialog window is displayed, automatically navigate to the path of the current file manager. (Experimental) - Show Dialog Jump Window - Display Dialog Jump search window when the open/save dialog window is shown to quickly navigate to file/folder locations. - Dialog Jump Window Position - Select position for the Dialog Jump search window - Fixed under the Open/Save As dialog window. Displayed on open and stays until the window is closed - Default search window position. Displayed when triggered by search window hotkey - Dialog Jump Result Navigation Behaviour - Behaviour to navigate Open/Save As dialog window to the selected result path - Left click or Enter key - Right click - Dialog Jump File Navigation Behaviour - Behaviour to navigate Open/Save As dialog window when the result is a file path - Fill full path in file name box - Fill full path in file name box and open - Fill directory in path box + Zobrazí výsledok v odznaku len pre výsledky globálneho vyhľadávania + Rýchly prechod + Zadajte skratku na rýchly prechod na aktuálnu cestu správcu súborov v dialógovom okne Otvoriť/Uložiť. + Rýchly prechod + Keď sa otvorí dialógové okno Otvoriť/Uložiť, rýchlo prejdete na aktuálnu cestu správcu súborov. + Automatický rýchly prechod + Keď je otvorené dialógové okno Otvoriť/Uložiť, automaticky prejsť na cestu v aktuálnom správcovi súborov (Experimentálne) + Zobraziť okno na rýchly prechod + Zobraziť okno rýchleho prechodu, keď je zobrazené dialógové okno Ovoriť/Uložiť na rýchlu navigáciu do umiestnenia súborov/priečinkov. + Umiestnenie okna "rýchly prechod" + Vyberte umiestnenie vyhľadávacieho okna pre "rýchly prechod" + Fixné pod oknom Otvoriť/Uložiť. Zostane zobrazené po otvorení až do uzavretia okna + Predvolená pozícia vyhľadávacieho okna. Zobrazí sa po zadaní skratky na otvorenie vyhľadávacieho okna + Akcia na prechod k výsledku rýchleho prechodu + Ako prejsť na vybranú cestu v otvorenom dialógovom okne Otvoriť/Uložiť + Kliknutie ľavým tlačidlom myši alebo klávesom Enter + Kliknutie pravým tlačidlom myši + Akcia na prechod k súboru rýchleho prechodu + Akcia, ktorá sa vykoná na navigáciu v dialógovom okne Otvoriť/Uložiť, ak výsledkom je súbor + Vložiť celú cestu k súboru do poľa názvu súboru + Vložiť celú cestu k súboru do poľa názvu súboru a otvoriť + Vložiť priečinok do poľa s cestou HTTP proxy @@ -468,8 +469,10 @@ Nevykonali sa žiadne zmeny. Otvoriť priečinok Rozšírené Úroveň logovania - Debug + Žiadne + Chyba Info + Debug Nastavenie písma okna @@ -482,8 +485,8 @@ Nevykonali sa žiadne zmeny. Vyberte správcu súborov Viac informácií - Zadajte umiestnenie súboru správcu súborov, ktorý používate, a podľa potreby pridajte argumenty. "%d" predstavuje cestu k priečinku, ktorý sa má otvoriť, používa sa v poli Arg pre priečinok a pri príkazoch na otvorenie konkrétnych priečinkov. "%f" predstavuje cestu k súboru, ktorá sa má otvoriť a používa sa v poli Arg pre súbor a pri príkazoch na otvorenie konkrétnych súborov. - Napríklad, ak správca súborov používa príkaz ako "totalcmd.exe /A c:\windows" na otvorenie priečinka c:\windows, cesta správcu súborov bude totalcmd.exe a Arg pre priečinok bude /A "%d". Niektorí správcovia súborov, ako napríklad QTTabBar, môžu vyžadovať len zadanie cesty, v tomto prípade použite "%d" ako cestu správcu súborov a zvyšok súborov nechajte prázdny. + Zadajte umiestnenie súboru správcu súborov, ktorý používate, a podľa potreby pridajte argumenty. "%d" predstavuje cestu k priečinku, ktorý sa má otvoriť, používa sa v poli Arg. pre priečinok a pri príkazoch na otvorenie konkrétnych priečinkov. "%f" predstavuje cestu k súboru, ktorá sa má otvoriť a používa sa v poli Arg. pre súbor a pri príkazoch na otvorenie konkrétnych súborov. + Napríklad, ak správca súborov používa príkaz ako "totalcmd.exe /A c:\windows" na otvorenie priečinka c:\windows, cesta správcu súborov bude totalcmd.exe a Arg. pre priečinok bude /A "%d". Niektorí správcovia súborov, ako napríklad QTTabBar, môžu vyžadovať len zadanie cesty, v tomto prípade použite "%d" ako cestu správcu súborov a zvyšok súborov nechajte prázdny. Správca súborov Názov profilu Cesta k správcovi súborov @@ -491,6 +494,7 @@ Nevykonali sa žiadne zmeny. Arg. pre súbor Správca súborov '{0}' sa nenachádza na '{1}'. Chcete pokračovať? Chyba v ceste k správcovi súborov + Prieskumník Predvolený webový prehliadač @@ -501,6 +505,8 @@ Nevykonali sa žiadne zmeny. Nové okno Nová karta Privátny režim + Predvolené + Nový profil Zmena priority diff --git a/Flow.Launcher/Languages/sr-Cyrl-RS.xaml b/Flow.Launcher/Languages/sr-Cyrl-RS.xaml index 4e6c35d98..189e882ec 100644 --- a/Flow.Launcher/Languages/sr-Cyrl-RS.xaml +++ b/Flow.Launcher/Languages/sr-Cyrl-RS.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Plugin Store @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg For File The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Default Web Browser @@ -500,6 +504,8 @@ New Window New Tab Private Mode + Default + New Profile Change Priority diff --git a/Flow.Launcher/Languages/sr.xaml b/Flow.Launcher/Languages/sr.xaml index e1495efd6..636942ac4 100644 --- a/Flow.Launcher/Languages/sr.xaml +++ b/Flow.Launcher/Languages/sr.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Plugin Store @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ Arg For File The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Default Web Browser @@ -500,6 +504,8 @@ New Window New Tab Private Mode + Default + New Profile Change Priority diff --git a/Flow.Launcher/Languages/tr.xaml b/Flow.Launcher/Languages/tr.xaml index a91b7997d..e91ba5b3f 100644 --- a/Flow.Launcher/Languages/tr.xaml +++ b/Flow.Launcher/Languages/tr.xaml @@ -224,6 +224,7 @@ {0} kaldırılamıyor plugin.json dosyası çıkarılan zip dosyasında bulunamadı veya {0} yolu mevcut değil Bu eklentiyle aynı ID ve sürüme sahip bir eklenti zaten var, ya da mevcut sürüm daha yüksek + Error creating setting panel for plugin {0}:{1}{2} Eklenti Mağazası @@ -405,14 +406,14 @@ Diyalog Atlama Penceresini Göster Dosya/klasör konumlarına hızlı erişim için aç/kaydet penceresi gösterildiğinde Diyalog Atlama arama penceresini görüntüle. Diyalog Atlama Penceresi Konumu - Select position for the Dialog Jump search window + Diyalog Atlama arama penceresi için konum seçin Farklı Aç/Kaydet iletişim penceresinin altında düzeltildi. Açıldığında görüntülenir ve pencere kapatılana kadar kalır Varsayılan arama penceresi konumu. Arama penceresi kısayol tuşu tarafından tetiklendiğinde görüntülenir - Dialog Jump Result Navigation Behaviour + Diyalog Atlama Sonucu Gezinme Davranışı Farklı Aç/Kaydet iletişim penceresini seçilen sonuç yoluna yönlendirmek için davranış Sol tık veya Enter tuşu Sağ tık - Dialog Jump File Navigation Behaviour + Dialog Jump Dosya Gezinme Davranışı Sonuç bir dosya yolu olduğunda Farklı Aç/Kaydet iletişim penceresinde gezinme davranışı Dosya adı kutusuna tam yolu girin Dosya adı kutusuna tam yolu girin ve açın @@ -467,8 +468,10 @@ Klasörü Aç Gelişmiş Günlük Düzeyi - Hata ayıklama + Sessiz + Hata Bilgi + Hata ayıklama Pencere Yazı Tipini Ayarla @@ -490,6 +493,7 @@ Dosya Açarken '{0}' dosya yöneticisi '{1}' konumunda bulunamadı. Devam etmek ister misiniz? Dosya Yöneticisi Yol Hatası + File Explorer İnternet Tarayıcı Seçenekleri @@ -500,6 +504,8 @@ Yeni Pencere Yeni Sekme Gizli Mod için Bağımsız Değişken + Default + New Profile Önceliği Ayarla diff --git a/Flow.Launcher/Languages/uk-UA.xaml b/Flow.Launcher/Languages/uk-UA.xaml index 55d12a14e..42541d046 100644 --- a/Flow.Launcher/Languages/uk-UA.xaml +++ b/Flow.Launcher/Languages/uk-UA.xaml @@ -224,6 +224,7 @@ Не вдалося видалити {0} Не вдалося знайти файл plugin.json у розпакованому zip-файлі або цей шлях {0} не існує. Вже існує плагін з таким самим ідентифікатором та версією, або версія цього плагіну вища за версію завантаженого. + Помилка створення панелі налаштувань для плагіну {0}: {1}{2} Магазин плагінів @@ -467,8 +468,10 @@ Відкрити теку Розширені Рівень журналювання - Налагодження + Без звуку + Помилка Інформація + Налагодження Встановлення шрифту вікна @@ -490,6 +493,7 @@ Аргумент для файлу Не вдалося знайти файловий менеджер «{0}» за адресою «{1}». Чи бажаєте продовжити? Помилка шляху до файлового менеджера + Файловий провідник Типовий веббраузер @@ -500,6 +504,8 @@ Нове вікно Нова вкладка Приватний режим + Типово + Новий профіль Змінити пріоритет diff --git a/Flow.Launcher/Languages/vi.xaml b/Flow.Launcher/Languages/vi.xaml index 29aaffc8a..f56703b7a 100644 --- a/Flow.Launcher/Languages/vi.xaml +++ b/Flow.Launcher/Languages/vi.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} Tải tiện ích mở rộng @@ -469,8 +470,10 @@ Mở thư mục Advanced Log Level - Debug + Silent + Lỗi Info + Debug Setting Window Font @@ -492,6 +495,7 @@ Đối số cho tệp The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer Trình duyệt web tiêu chuẩn @@ -502,6 +506,8 @@ Cửa sổ mới Thẻ Mới Chế độ riêng tư + Default + New Profile Thay đổi mức độ ưu tiên diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index 0f8934fe4..3b368f170 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -224,6 +224,7 @@ 卸载 {0} 失败 无法从提取的zip文件中找到plugin.json,或者此路径 {0} 不存在 已存在相同ID和版本的插件,或者存在版本大于此下载的插件 + Error creating setting panel for plugin {0}:{1}{2} 插件商店 @@ -467,8 +468,10 @@ 打开文件夹 高级 日志等级 - 调试 + 静默 + 错误 信息 + 调试 设置窗口字体 @@ -490,6 +493,7 @@ 选中文件路径参数 文件管理器 '{0}' 不能在 '{1}'中定位。您想要继续吗? 文件管理器路径错误 + 文件资源管理器 默认浏览器 @@ -500,6 +504,8 @@ 新窗口 新标签 隐身模式 + 默认 + 新配置 更改优先级 diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index 0cec258f1..c80e8b092 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -224,6 +224,7 @@ Fail to uninstall {0} Unable to find plugin.json from the extracted zip file, or this path {0} does not exist A plugin with the same ID and version already exists, or the version is greater than this downloaded plugin + Error creating setting panel for plugin {0}:{1}{2} 插件商店 @@ -467,8 +468,10 @@ Open Folder Advanced Log Level - Debug + Silent + Error Info + Debug Setting Window Font @@ -490,6 +493,7 @@ 檔案參數 The file manager '{0}' could not be located at '{1}'. Would you like to continue? File Manager Path Error + File Explorer 預設瀏覽器 @@ -500,6 +504,8 @@ 新增視窗 新增分頁 無痕模式 + Default + New Profile 更改優先度 diff --git a/Flow.Launcher/SelectBrowserWindow.xaml b/Flow.Launcher/SelectBrowserWindow.xaml index d51d597b7..67c22b07d 100644 --- a/Flow.Launcher/SelectBrowserWindow.xaml +++ b/Flow.Launcher/SelectBrowserWindow.xaml @@ -92,7 +92,7 @@ SelectedIndex="{Binding SelectedCustomBrowserIndex}"> - + diff --git a/Flow.Launcher/SelectBrowserWindow.xaml.cs b/Flow.Launcher/SelectBrowserWindow.xaml.cs index 565b4cbc3..290712aad 100644 --- a/Flow.Launcher/SelectBrowserWindow.xaml.cs +++ b/Flow.Launcher/SelectBrowserWindow.xaml.cs @@ -1,6 +1,7 @@ using System.Windows; using System.Windows.Controls; using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Infrastructure; using Flow.Launcher.ViewModel; namespace Flow.Launcher @@ -31,7 +32,7 @@ namespace Flow.Launcher private void btnBrowseFile_Click(object sender, RoutedEventArgs e) { - var selectedFilePath = _viewModel.SelectFile(); + var selectedFilePath = Win32Helper.SelectFile(); if (!string.IsNullOrEmpty(selectedFilePath)) { diff --git a/Flow.Launcher/SelectFileManagerWindow.xaml b/Flow.Launcher/SelectFileManagerWindow.xaml index b3b219d1c..cd4bec424 100644 --- a/Flow.Launcher/SelectFileManagerWindow.xaml +++ b/Flow.Launcher/SelectFileManagerWindow.xaml @@ -102,7 +102,7 @@ SelectedIndex="{Binding SelectedCustomExplorerIndex}"> - + diff --git a/Flow.Launcher/SelectFileManagerWindow.xaml.cs b/Flow.Launcher/SelectFileManagerWindow.xaml.cs index d9c672aff..5143f9a56 100644 --- a/Flow.Launcher/SelectFileManagerWindow.xaml.cs +++ b/Flow.Launcher/SelectFileManagerWindow.xaml.cs @@ -2,6 +2,7 @@ using System.Windows.Controls; using System.Windows.Navigation; using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Infrastructure; using Flow.Launcher.ViewModel; namespace Flow.Launcher @@ -32,13 +33,13 @@ namespace Flow.Launcher private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) { - _viewModel.OpenUrl(e.Uri.AbsoluteUri); + App.API.OpenUrl(e.Uri.AbsoluteUri); e.Handled = true; } private void btnBrowseFile_Click(object sender, RoutedEventArgs e) { - var selectedFilePath = _viewModel.SelectFile(); + var selectedFilePath = Win32Helper.SelectFile(); if (!string.IsNullOrEmpty(selectedFilePath)) { diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index 1efc89972..647b36701 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -231,35 +231,41 @@ public partial class SettingsPaneAboutViewModel : BaseModel } }); - // Firstly, delete plugin cache directories - pluginCacheDirectory.EnumerateDirectories("*", SearchOption.TopDirectoryOnly) - .ToList() - .ForEach(dir => + // Check if plugin cache directory exists before attempting to delete + // Or it will throw DirectoryNotFoundException in `pluginCacheDirectory.EnumerateDirectories` + if (pluginCacheDirectory.Exists) + { + // Firstly, delete plugin cache directories + pluginCacheDirectory.EnumerateDirectories("*", SearchOption.TopDirectoryOnly) + .ToList() + .ForEach(dir => + { + try + { + // Plugin may create directories in its cache directory + dir.Delete(recursive: true); + } + catch (Exception e) + { + App.API.LogException(ClassName, $"Failed to delete cache directory: {dir.Name}", e); + success = false; + } + }); + + // Then, delete plugin directory + var dir = pluginCacheDirectory; + try { - try - { - // Plugin may create directories in its cache directory - dir.Delete(recursive: true); - } - catch (Exception e) - { - App.API.LogException(ClassName, $"Failed to delete cache directory: {dir.Name}", e); - success = false; - } - }); - - // Then, delete plugin directory - var dir = GetPluginCacheDir(); - try - { - dir.Delete(recursive: false); - } - catch (Exception e) - { - App.API.LogException(ClassName, $"Failed to delete cache directory: {dir.Name}", e); - success = false; + dir.Delete(recursive: false); + } + catch (Exception e) + { + App.API.LogException(ClassName, $"Failed to delete cache directory: {dir.Name}", e); + success = false; + } } + // Raise regardless to cover scenario where size needs to be recalculated if the folder is manually removed on disk. OnPropertyChanged(nameof(CacheFolderSize)); return success; diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index ec75ddf90..b47b53654 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; @@ -219,6 +219,8 @@ public partial class SettingsPaneGeneralViewModel : BaseModel DropdownDataGeneric.UpdateLabels(DialogJumpFileResultBehaviours); // Since we are using Binding instead of DynamicResource, we need to manually trigger the update OnPropertyChanged(nameof(AlwaysPreviewToolTip)); + Settings.CustomExplorer.OnDisplayNameChanged(); + Settings.CustomBrowser.OnDisplayNameChanged(); } public string Language diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 81e15df69..07cc7b6a7 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -403,7 +403,7 @@ MaxWidth="250" Margin="10 0 0 0" Command="{Binding SelectFileManagerCommand}" - Content="{Binding Settings.CustomExplorer.Name}" /> + Content="{Binding Settings.CustomExplorer.DisplayName}" /> + Content="{Binding Settings.CustomBrowser.DisplayName}" /> diff --git a/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs b/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs index 67bbbd930..e3a0e4e44 100644 --- a/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs +++ b/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs @@ -17,8 +17,13 @@ public partial class SelectBrowserViewModel : BaseModel get => selectedCustomBrowserIndex; set { - selectedCustomBrowserIndex = value; - OnPropertyChanged(nameof(CustomBrowser)); + // When one custom browser is selected and removed, the index will become -1, so we need to ignore this change + if (value < 0) return; + if (selectedCustomBrowserIndex != value) + { + selectedCustomBrowserIndex = value; + OnPropertyChanged(nameof(CustomBrowser)); + } } } @@ -40,22 +45,12 @@ public partial class SelectBrowserViewModel : BaseModel return true; } - internal string SelectFile() - { - var dlg = new Microsoft.Win32.OpenFileDialog(); - var result = dlg.ShowDialog(); - if (result == true) - return dlg.FileName; - - return string.Empty; - } - [RelayCommand] private void Add() { CustomBrowsers.Add(new() { - Name = "New Profile" + Name = App.API.GetTranslation("defaultBrowser_new_profile") }); SelectedCustomBrowserIndex = CustomBrowsers.Count - 1; } diff --git a/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs b/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs index 77f004980..f6a32e3fe 100644 --- a/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs +++ b/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs @@ -21,6 +21,8 @@ public partial class SelectFileManagerViewModel : BaseModel get => selectedCustomExplorerIndex; set { + // When one custom file manager is selected and removed, the index will become -1, so we need to ignore this change + if (value < 0) return; if (selectedCustomExplorerIndex != value) { selectedCustomExplorerIndex = value; @@ -98,27 +100,12 @@ public partial class SelectFileManagerViewModel : BaseModel } } - internal void OpenUrl(string absoluteUri) - { - App.API.OpenUrl(absoluteUri); - } - - internal string SelectFile() - { - var dlg = new Microsoft.Win32.OpenFileDialog(); - var result = dlg.ShowDialog(); - if (result == true) - return dlg.FileName; - - return string.Empty; - } - [RelayCommand] private void Add() { CustomExplorers.Add(new() { - Name = "New Profile" + Name = App.API.GetTranslation("defaultBrowser_new_profile") }); SelectedCustomExplorerIndex = CustomExplorers.Count - 1; } diff --git a/Flow.Launcher/packages.lock.json b/Flow.Launcher/packages.lock.json index 32b78c334..c90db6b0c 100644 --- a/Flow.Launcher/packages.lock.json +++ b/Flow.Launcher/packages.lock.json @@ -16,9 +16,9 @@ }, "Fody": { "type": "Direct", - "requested": "[6.9.2, )", - "resolved": "6.9.2", - "contentHash": "YBHobPGogb0vYhGYIxn/ndWqTjNWZveDi5jdjrcshL2vjwU3gQGyDeI7vGgye+2rAM5fGRvlLgNWLW3DpviS/w==" + "requested": "[6.9.3, )", + "resolved": "6.9.3", + "contentHash": "1CUGgFdyECDKgi5HaUBhdv6k+VG9Iy4OCforGfHyar3xQXAJypZkzymgKtWj/4SPd6nSG0Qi7NH71qHrDSZLaA==" }, "MdXaml": { "type": "Direct", @@ -71,41 +71,41 @@ }, "Microsoft.Extensions.DependencyInjection": { "type": "Direct", - "requested": "[9.0.7, )", - "resolved": "9.0.7", - "contentHash": "i05AYA91vgq0as84ROVCyltD2gnxaba/f1Qw2rG7mUsS0gv8cPTr1Gm7jPQHq7JTr4MJoQUcanLVs16tIOUJaQ==", + "requested": "[9.0.9, )", + "resolved": "9.0.9", + "contentHash": "zQV2WOSP+3z1EuK91ULxfGgo2Y75bTRnmJHp08+w/YXAyekZutX/qCd88/HOMNh35MDW9mJJJxPpMPS+1Rww8A==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7" + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9" } }, "Microsoft.Extensions.Hosting": { "type": "Direct", - "requested": "[9.0.7, )", - "resolved": "9.0.7", - "contentHash": "Dkv55VfitwJjPUk9mFHxT9MJAd8su7eJNaCHhBU/Y9xFqw3ZNHwrpeptXeaXiaPtfQq+alMmawIz1Impk5pHkQ==", + "requested": "[9.0.9, )", + "resolved": "9.0.9", + "contentHash": "DmRsWH3g8yZGho/pLQ79hxhM2ctE1eDTZ/HbAnrD/uw8m+P2pRRJOoBVxlrhbhMP3/y3oAJoy0yITasfmilbTg==", "dependencies": { - "Microsoft.Extensions.Configuration": "9.0.7", - "Microsoft.Extensions.Configuration.Abstractions": "9.0.7", - "Microsoft.Extensions.Configuration.Binder": "9.0.7", - "Microsoft.Extensions.Configuration.CommandLine": "9.0.7", - "Microsoft.Extensions.Configuration.EnvironmentVariables": "9.0.7", - "Microsoft.Extensions.Configuration.FileExtensions": "9.0.7", - "Microsoft.Extensions.Configuration.Json": "9.0.7", - "Microsoft.Extensions.Configuration.UserSecrets": "9.0.7", - "Microsoft.Extensions.DependencyInjection": "9.0.7", - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7", - "Microsoft.Extensions.Diagnostics": "9.0.7", - "Microsoft.Extensions.FileProviders.Abstractions": "9.0.7", - "Microsoft.Extensions.FileProviders.Physical": "9.0.7", - "Microsoft.Extensions.Hosting.Abstractions": "9.0.7", - "Microsoft.Extensions.Logging": "9.0.7", - "Microsoft.Extensions.Logging.Abstractions": "9.0.7", - "Microsoft.Extensions.Logging.Configuration": "9.0.7", - "Microsoft.Extensions.Logging.Console": "9.0.7", - "Microsoft.Extensions.Logging.Debug": "9.0.7", - "Microsoft.Extensions.Logging.EventLog": "9.0.7", - "Microsoft.Extensions.Logging.EventSource": "9.0.7", - "Microsoft.Extensions.Options": "9.0.7" + "Microsoft.Extensions.Configuration": "9.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9", + "Microsoft.Extensions.Configuration.Binder": "9.0.9", + "Microsoft.Extensions.Configuration.CommandLine": "9.0.9", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "9.0.9", + "Microsoft.Extensions.Configuration.FileExtensions": "9.0.9", + "Microsoft.Extensions.Configuration.Json": "9.0.9", + "Microsoft.Extensions.Configuration.UserSecrets": "9.0.9", + "Microsoft.Extensions.DependencyInjection": "9.0.9", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Diagnostics": "9.0.9", + "Microsoft.Extensions.FileProviders.Abstractions": "9.0.9", + "Microsoft.Extensions.FileProviders.Physical": "9.0.9", + "Microsoft.Extensions.Hosting.Abstractions": "9.0.9", + "Microsoft.Extensions.Logging": "9.0.9", + "Microsoft.Extensions.Logging.Abstractions": "9.0.9", + "Microsoft.Extensions.Logging.Configuration": "9.0.9", + "Microsoft.Extensions.Logging.Console": "9.0.9", + "Microsoft.Extensions.Logging.Debug": "9.0.9", + "Microsoft.Extensions.Logging.EventLog": "9.0.9", + "Microsoft.Extensions.Logging.EventSource": "9.0.9", + "Microsoft.Extensions.Options": "9.0.9" } }, "Microsoft.Toolkit.Uwp.Notifications": { @@ -154,9 +154,9 @@ }, "VirtualizingWrapPanel": { "type": "Direct", - "requested": "[2.3.0, )", - "resolved": "2.3.0", - "contentHash": "Dpmtcpn2HqAWZR0NkN7Qd4YCjf+sdQcemIMKm2suZVbOIB9NsmKZnYaQDIpXWTh87a9+nArVto6Od1cM2ohzCQ==" + "requested": "[2.3.1, )", + "resolved": "2.3.1", + "contentHash": "imph3SJqFFgX8vc7XRBcftfgzIL7Q+uE0Tvk7dbY0KY0tcqUCs0ZmKV3Gt9QX2745v6bSw6ns8UHpXtiptHqdA==" }, "AvalonEdit": { "type": "Transitive", @@ -196,8 +196,8 @@ }, "FSharp.Core": { "type": "Transitive", - "resolved": "9.0.300", - "contentHash": "TVt2J7RCE1KCS2IaONF+p8/KIZ1eHNbW+7qmKF6hGoD4tXl+o07ja1mPtFjMqRa5uHMFaTrGTPn/m945WnDLiQ==" + "resolved": "9.0.303", + "contentHash": "6JlV8aD8qQvcmfoe/PMOxCHXc0uX4lR23u0fAyQtnVQxYULLoTZgwgZHSnRcuUHOvS3wULFWcwdnP1iwslH60g==" }, "HtmlAgilityPack": { "type": "Transitive", @@ -211,8 +211,8 @@ }, "JetBrains.Annotations": { "type": "Transitive", - "resolved": "2024.3.0", - "contentHash": "ox5pkeLQXjvJdyAB4b2sBYAlqZGLh3PjSnP1bQNVx72ONuTJ9+34/+Rq91Fc0dG29XG9RgZur9+NcP4riihTug==" + "resolved": "2025.2.2", + "contentHash": "0X56ZRizuHdrnPpgXjWV7f2tQO1FlQg5O1967OGKnI/4ZRNOK642J8L7brM1nYvrxTTU5TP1yRyXLRLaXLPQ8A==" }, "MemoryPack": { "type": "Transitive", @@ -249,249 +249,249 @@ }, "Meziantou.Framework.Win32.Jobs": { "type": "Transitive", - "resolved": "3.4.3", - "contentHash": "REjInKnQ0OrhjjtSMPQtLtdURctCroB4L8Sd2gjTOYDysklvsdnrStx1tHS7uLv+fSyFF3aazZmo5Ka0v1oz/w==" + "resolved": "3.4.4", + "contentHash": "AivBzH5wM1NHBLehclim+o37SmireP7JxCRUoTilsc/h7LH9+YCPjb6Ig6y0khnQhFcO1P8RHYw4oiR15TGHUg==" }, "Microsoft.Extensions.Configuration": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "oxGR51+w5cXm5B9gU6XwpAB2sTiyPSmZm7hjvv0rzRnmL5o/KZzE103AuQj7sK26OBupjVzU/bZxDWvvU4nhEg==", + "resolved": "9.0.9", + "contentHash": "w87wF/90/VI0ZQBhf4rbMEeyEy0vi2WKjFmACsNAKNaorY+ZlVz7ddyXkbADvaWouMKffNmR0yQOGcrvSSvKGg==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "9.0.7", - "Microsoft.Extensions.Primitives": "9.0.7" + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9", + "Microsoft.Extensions.Primitives": "9.0.9" } }, "Microsoft.Extensions.Configuration.Abstractions": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "lut/kiVvNsQ120VERMUYSFhpXPpKjjql+giy03LesASPBBcC0o6+aoFdzJH9GaYpFTQ3fGVhVjKjvJDoAW5/IQ==", + "resolved": "9.0.9", + "contentHash": "p5RKAY9POvs3axwA/AQRuJeM8AHuE8h4qbP1NxQeGm0ep46aXz1oCLAp/oOYxX1GsjStgdhHrN3XXLLXr0+b3w==", "dependencies": { - "Microsoft.Extensions.Primitives": "9.0.7" + "Microsoft.Extensions.Primitives": "9.0.9" } }, "Microsoft.Extensions.Configuration.Binder": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "ExY+zXHhU4o9KC2alp3ZdLWyVWVRSn5INqax5ABk+HEOHlAHzomhJ7ek9HHliyOMiVGoYWYaMFOGr9q59mSAGA==", + "resolved": "9.0.9", + "contentHash": "6SIp/6Bngk4jm2W36JekZbiIbFPdE/eMUtrJEqIqHGpd1zar3jvgnwxnpWQfzUiGrkyY8q8s6V82zkkEZozghA==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "9.0.7" + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9" } }, "Microsoft.Extensions.Configuration.CommandLine": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "LqwdkMNFeRyuqExewBSaWj8roEgZH8JQ9zEAmHl5ZFcnhCvjAdHICdYVRIiSEq9RWGB731LL8kZJM8tdTKEscA==", + "resolved": "9.0.9", + "contentHash": "9bzGOcHoTi8ijrj0MHh5qUY6n9CuittZUqEOj5iE0ZJoSCfG0BI9nhcpd8MC9bOOgjZW5OeizKO8rgta9lSVyA==", "dependencies": { - "Microsoft.Extensions.Configuration": "9.0.7", - "Microsoft.Extensions.Configuration.Abstractions": "9.0.7" + "Microsoft.Extensions.Configuration": "9.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9" } }, "Microsoft.Extensions.Configuration.EnvironmentVariables": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "R8kgazVpDr4k1K7MeWPLAwsi5VpwrhE3ubXK38D9gpHEvf9XhZhJ8kWHKK00LDg5hJ7pMQLggdZ7XFdQ5182Ug==", + "resolved": "9.0.9", + "contentHash": "AB8suTh4STAMGDkPer5vL0YNp09eplvbkIbOfFJ1z8D1zOiFF8Hipk9FhCLU4Ea6TosWmGrK30ZIUO9KvAeFcg==", "dependencies": { - "Microsoft.Extensions.Configuration": "9.0.7", - "Microsoft.Extensions.Configuration.Abstractions": "9.0.7" + "Microsoft.Extensions.Configuration": "9.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9" } }, "Microsoft.Extensions.Configuration.FileExtensions": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "3LVg32iMfR9ENeegXAo73L+877iOcQauLJsXlKZNVSsLA/HbPgClZdeMGdjLSkaidYw3l02XbXTlOdGYNgu91Q==", + "resolved": "9.0.9", + "contentHash": "fvgubCs++wTowHWuQ5TAyZV0S6ldA59U+tBVqFr4/WLd0oEf6ESbdBN2CFaVdn4sZqnarqMnl2O3++RG/Jrf/w==", "dependencies": { - "Microsoft.Extensions.Configuration": "9.0.7", - "Microsoft.Extensions.Configuration.Abstractions": "9.0.7", - "Microsoft.Extensions.FileProviders.Abstractions": "9.0.7", - "Microsoft.Extensions.FileProviders.Physical": "9.0.7", - "Microsoft.Extensions.Primitives": "9.0.7" + "Microsoft.Extensions.Configuration": "9.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9", + "Microsoft.Extensions.FileProviders.Abstractions": "9.0.9", + "Microsoft.Extensions.FileProviders.Physical": "9.0.9", + "Microsoft.Extensions.Primitives": "9.0.9" } }, "Microsoft.Extensions.Configuration.Json": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "3HQV326liEInT9UKEc+k73f1ECwNhvDS/DJAe5WvtMKDJTJqTH2ujrUC2ZlK/j6pXyPbV9f0Ku8JB20JveGImg==", + "resolved": "9.0.9", + "contentHash": "PiPYo1GTinR2ECM80zYdZUIFmde6jj5DryXUcOJg3yIjh+KQMQr42e+COD03QUsUiqNkJk511wVTnVpTm2AVZA==", "dependencies": { - "Microsoft.Extensions.Configuration": "9.0.7", - "Microsoft.Extensions.Configuration.Abstractions": "9.0.7", - "Microsoft.Extensions.Configuration.FileExtensions": "9.0.7", - "Microsoft.Extensions.FileProviders.Abstractions": "9.0.7" + "Microsoft.Extensions.Configuration": "9.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9", + "Microsoft.Extensions.Configuration.FileExtensions": "9.0.9", + "Microsoft.Extensions.FileProviders.Abstractions": "9.0.9" } }, "Microsoft.Extensions.Configuration.UserSecrets": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "ouDuPgRdeF4TJXKUh+lbm6QwyWwnCy+ijiqfFM2cI5NmW83MwKg1WNp2nCdMVcwQW8wJXteF/L9lA6ZPS3bCIQ==", + "resolved": "9.0.9", + "contentHash": "bFaNxfU8gQJX3K/Dd6XT0YIJ5ZVihdAY6Z02p2nVTUHjUsaWflLIucZOgB/ecSNnN3zbbBEf1oFC7q5NHTZIHw==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "9.0.7", - "Microsoft.Extensions.Configuration.Json": "9.0.7", - "Microsoft.Extensions.FileProviders.Abstractions": "9.0.7", - "Microsoft.Extensions.FileProviders.Physical": "9.0.7" + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9", + "Microsoft.Extensions.Configuration.Json": "9.0.9", + "Microsoft.Extensions.FileProviders.Abstractions": "9.0.9", + "Microsoft.Extensions.FileProviders.Physical": "9.0.9" } }, "Microsoft.Extensions.DependencyInjection.Abstractions": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "iPK1FxbGFr2Xb+4Y+dTYI8Gupu9pOi8I3JPuPsrogUmEhe2hzZ9LpCmolMEBhVDo2ikcSr7G5zYiwaapHSQTew==" + "resolved": "9.0.9", + "contentHash": "/hymojfWbE9AlDOa0mczR44m00Jj+T3+HZO0ZnVTI032fVycI0ZbNOVFP6kqZMcXiLSYXzR2ilcwaRi6dzeGyA==" }, "Microsoft.Extensions.Diagnostics": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "6ykfInm6yw7pPHJACgnrPUXxUWVslFnzad44K/siXk6Ovan6fNMnXxI5X9vphHJuZ4JbMOdPIgsfTmLD+Dyxug==", + "resolved": "9.0.9", + "contentHash": "gtzl9SD6CvFYOb92qEF41Z9rICzYniM342TWbbJwN3eLS6a5fCLFvO1pQGtpMSnP3h1zHXupMEeKSA9musWYCQ==", "dependencies": { - "Microsoft.Extensions.Configuration": "9.0.7", - "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.7", - "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.7" + "Microsoft.Extensions.Configuration": "9.0.9", + "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.9", + "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.9" } }, "Microsoft.Extensions.Diagnostics.Abstractions": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "d39Ov1JpeWCGLCOTinlaDkujhrSAQ0HFxb7Su1BjhCKBfmDcQ6Ia1i3JI6kd3NFgwi1dexTunu82daDNwt7E6w==", + "resolved": "9.0.9", + "contentHash": "YHGmxccrVZ2Ar3eI+/NdbOHkd1/HzrHvmQ5yBsp0Gl7jTyBe6qcXNYjUt9v9JIO+Z14la44+YYEe63JSqs1fYg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7", - "Microsoft.Extensions.Options": "9.0.7" + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Options": "9.0.9" } }, "Microsoft.Extensions.FileProviders.Abstractions": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "y9djCca1cz/oz/J8jTxtoecNiNvaiGBJeWd7XOPxonH+FnfHqcfslJMcSr5JMinmWFyS7eh3C9L6m6oURZ5lSA==", + "resolved": "9.0.9", + "contentHash": "M1ZhL9QkBQ/k6l/Wjgcli5zrV86HzytQ+gQiNtk9vs9Ge1fb17KKZil9T6jd15p2x/BGfXpup7Hg55CC0kkfig==", "dependencies": { - "Microsoft.Extensions.Primitives": "9.0.7" + "Microsoft.Extensions.Primitives": "9.0.9" } }, "Microsoft.Extensions.FileProviders.Physical": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "JYEPYrb+YBpFTCdmSBrk8cg3wAi1V4so7ccq04qbhg3FQHQqgJk28L3heEOKMXcZobOBUjTnGCFJD49Ez9kG5w==", + "resolved": "9.0.9", + "contentHash": "sRrPtEwbK23OCFOQ36Xn6ofiB0/nl54/BOdR7lJ/Vwg3XlyvUdmyXvFUS1EU5ltn+sQtbcPuy1l0hsysO8++SQ==", "dependencies": { - "Microsoft.Extensions.FileProviders.Abstractions": "9.0.7", - "Microsoft.Extensions.FileSystemGlobbing": "9.0.7", - "Microsoft.Extensions.Primitives": "9.0.7" + "Microsoft.Extensions.FileProviders.Abstractions": "9.0.9", + "Microsoft.Extensions.FileSystemGlobbing": "9.0.9", + "Microsoft.Extensions.Primitives": "9.0.9" } }, "Microsoft.Extensions.FileSystemGlobbing": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "5VKpTH2ME0SSs0lrtkpKgjCeHzXR5ka/H+qThPwuWi78wHubApZ/atD7w69FDt0OOM7UMV6LIbkqEQgoby4IXA==" + "resolved": "9.0.9", + "contentHash": "iQAgORaVIlkhcpxFnVEfjqNWfQCwBEEH7x2IanTwGafA6Tb4xiBoDWySTxUo3MV2NUV/PmwS/8OhT/elPnJCnw==" }, "Microsoft.Extensions.Hosting.Abstractions": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "yG2JCXAR+VqI1mKqynLPNJlNlrUJeEISEpX4UznOp2uM4IEFz3pDDauzyMvTjICutEJtOigJ1yWBvxbaIlibBw==", + "resolved": "9.0.9", + "contentHash": "ORA4dICNz7cuwupPkjXpSuoiK6GMg0aygInBIQCCFEimwoHntRKdJqB59faxq2HHJuTPW3NsZm5EjN5P5Zh6nQ==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "9.0.7", - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7", - "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.7", - "Microsoft.Extensions.FileProviders.Abstractions": "9.0.7", - "Microsoft.Extensions.Logging.Abstractions": "9.0.7" + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.9", + "Microsoft.Extensions.FileProviders.Abstractions": "9.0.9", + "Microsoft.Extensions.Logging.Abstractions": "9.0.9" } }, "Microsoft.Extensions.Logging": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "fdIeQpXYV8yxSWG03cCbU2Otdrq4NWuhnQLXokWLv3L9YcK055E7u8WFJvP+uuP4CFeCEoqZQL4yPcjuXhCZrg==", + "resolved": "9.0.9", + "contentHash": "MaCB0Y9hNDs4YLu3HCJbo199WnJT8xSgajG1JYGANz9FkseQ5f3v/llu3HxLI6mjDlu7pa7ps9BLPWjKzsAAzQ==", "dependencies": { - "Microsoft.Extensions.DependencyInjection": "9.0.7", - "Microsoft.Extensions.Logging.Abstractions": "9.0.7", - "Microsoft.Extensions.Options": "9.0.7" + "Microsoft.Extensions.DependencyInjection": "9.0.9", + "Microsoft.Extensions.Logging.Abstractions": "9.0.9", + "Microsoft.Extensions.Options": "9.0.9" } }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "sMM6NEAdUTE/elJ2wqjOi0iBWqZmSyaTByLF9e8XHv6DRJFFnOe0N+s8Uc6C91E4SboQCfLswaBIZ+9ZXA98AA==", + "resolved": "9.0.9", + "contentHash": "FEgpSF+Z9StMvrsSViaybOBwR0f0ZZxDm8xV5cSOFiXN/t+ys+rwAlTd/6yG7Ld1gfppgvLcMasZry3GsI9lGA==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7" + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9" } }, "Microsoft.Extensions.Logging.Configuration": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "AEBty9rvFGvdFRqgIDEhQmiCnIfQWyzVoOZrO244cfu+n9M+wI1QLDpuROVILlplIBtLVmOezAF7d1H3Qog6Xw==", + "resolved": "9.0.9", + "contentHash": "Abuo+S0Sg+Ke6vzSh5Ell+lwJJM+CEIqg1ImtWnnqF6a/ibJkQnmFJi4/ekEw/0uAcdFKJXtGV7w6cFN0nyXeg==", "dependencies": { - "Microsoft.Extensions.Configuration": "9.0.7", - "Microsoft.Extensions.Configuration.Abstractions": "9.0.7", - "Microsoft.Extensions.Configuration.Binder": "9.0.7", - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7", - "Microsoft.Extensions.Logging": "9.0.7", - "Microsoft.Extensions.Logging.Abstractions": "9.0.7", - "Microsoft.Extensions.Options": "9.0.7", - "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.7" + "Microsoft.Extensions.Configuration": "9.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9", + "Microsoft.Extensions.Configuration.Binder": "9.0.9", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Logging": "9.0.9", + "Microsoft.Extensions.Logging.Abstractions": "9.0.9", + "Microsoft.Extensions.Options": "9.0.9", + "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.9" } }, "Microsoft.Extensions.Logging.Console": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "pEHlNa8iCfKsBFA3YVDn/8EicjSU/m8uDfyoR0i4svONDss4Yu9Kznw53E/TyI+TveTo7CwRid4kfd4pLYXBig==", + "resolved": "9.0.9", + "contentHash": "x3+W7IfW9Tg3sV+sU9N1039M4CqklaAecwhz9qNtjOCBdmg7h96JaL+NAvhYgZgweVJTJaxAvuO8I+ZZehE7Pg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7", - "Microsoft.Extensions.Logging": "9.0.7", - "Microsoft.Extensions.Logging.Abstractions": "9.0.7", - "Microsoft.Extensions.Logging.Configuration": "9.0.7", - "Microsoft.Extensions.Options": "9.0.7" + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Logging": "9.0.9", + "Microsoft.Extensions.Logging.Abstractions": "9.0.9", + "Microsoft.Extensions.Logging.Configuration": "9.0.9", + "Microsoft.Extensions.Options": "9.0.9" } }, "Microsoft.Extensions.Logging.Debug": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "MxzZj7XbsYJwfjclVTjJym2/nVIkksu7l7tC/4HYy+YRdDmpE4B+hTzCXu3BNfLNhdLPZsWpyXuYe6UGgWDm3g==", + "resolved": "9.0.9", + "contentHash": "q8IbjIzTjfaGfuf9LAuG3X9BytAWj2hWhLU61rEkit847oaSSbcdx/yybY3yL9RgVG1u9ctk7kbCv18M+7Fi6Q==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7", - "Microsoft.Extensions.Logging": "9.0.7", - "Microsoft.Extensions.Logging.Abstractions": "9.0.7" + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Logging": "9.0.9", + "Microsoft.Extensions.Logging.Abstractions": "9.0.9" } }, "Microsoft.Extensions.Logging.EventLog": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "usrMVsY7c8M8fESt34Y3eEIQIlRlKXfPDlI+vYEb6xT7SUjhua2ey3NpHgQktiTgz8Uo5RiWqGD8ieiyo2WaDA==", + "resolved": "9.0.9", + "contentHash": "1SX5+mv16SBb5NrtLNxIvUt8PHbdvDloZazQdxz1CNM39jG7yeF6olH3sceQ4ONF0oVD5mVUsTag0iVX4xgyog==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7", - "Microsoft.Extensions.Logging": "9.0.7", - "Microsoft.Extensions.Logging.Abstractions": "9.0.7", - "Microsoft.Extensions.Options": "9.0.7", - "System.Diagnostics.EventLog": "9.0.7" + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Logging": "9.0.9", + "Microsoft.Extensions.Logging.Abstractions": "9.0.9", + "Microsoft.Extensions.Options": "9.0.9", + "System.Diagnostics.EventLog": "9.0.9" } }, "Microsoft.Extensions.Logging.EventSource": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "/wwi6ckTEegCExFV6gVToCO7CvysZnmE50fpdkYUsSMh0ue9vRkQ7uOqkHyHol93ASYTEahrp+guMtS/+fZKaA==", + "resolved": "9.0.9", + "contentHash": "rGQi5mImot7tTFxj1tQWknWjOBHX1+gsX1WLmQNl5WHr4Sx1kXUBGDuRUjfx4c8pe/hcYHdalAmgk7RdusW6Jw==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7", - "Microsoft.Extensions.Logging": "9.0.7", - "Microsoft.Extensions.Logging.Abstractions": "9.0.7", - "Microsoft.Extensions.Options": "9.0.7", - "Microsoft.Extensions.Primitives": "9.0.7" + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Logging": "9.0.9", + "Microsoft.Extensions.Logging.Abstractions": "9.0.9", + "Microsoft.Extensions.Options": "9.0.9", + "Microsoft.Extensions.Primitives": "9.0.9" } }, "Microsoft.Extensions.Options": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "trJnF6cRWgR5uMmHpGoHmM1wOVFdIYlELlkO9zX+RfieK0321Y55zrcs4AaEymKup7dxgEN/uJU25CAcMNQRXw==", + "resolved": "9.0.9", + "contentHash": "loxGGHE1FC2AefwPHzrjPq7X92LQm64qnU/whKfo6oWaceewPUVYQJBJs3S3E2qlWwnCpeZ+dGCPTX+5dgVAuQ==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7", - "Microsoft.Extensions.Primitives": "9.0.7" + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Primitives": "9.0.9" } }, "Microsoft.Extensions.Options.ConfigurationExtensions": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "pE/jeAWHEIy/8HsqYA+I1+toTsdvsv+WywAcRoNSvPoFwjOREa8Fqn7D0/i0PbiXsDLFupltTTctliePx8ib4w==", + "resolved": "9.0.9", + "contentHash": "n4DCdnn2qs6V5U06Sx62FySEAZsJiJJgOzrPHDh9hPK7c2W8hEabC76F3Re3tGPjpiKa02RvB6FxZyxo8iICzg==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "9.0.7", - "Microsoft.Extensions.Configuration.Binder": "9.0.7", - "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.7", - "Microsoft.Extensions.Options": "9.0.7", - "Microsoft.Extensions.Primitives": "9.0.7" + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9", + "Microsoft.Extensions.Configuration.Binder": "9.0.9", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Options": "9.0.9", + "Microsoft.Extensions.Primitives": "9.0.9" } }, "Microsoft.Extensions.Primitives": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "ti/zD9BuuO50IqlvhWQs9GHxkCmoph5BHjGiWKdg2t6Or8XoyAfRJiKag+uvd/fpASnNklfsB01WpZ4fhAe0VQ==" + "resolved": "9.0.9", + "contentHash": "z4pyMePOrl733ltTowbN565PxBw1oAr8IHmIXNDiDqd22nFpYltX9KhrNC/qBWAG1/Zx5MHX+cOYhWJQYCO/iw==" }, "Microsoft.IO.RecyclableMemoryStream": { "type": "Transitive", @@ -590,15 +590,15 @@ }, "NLog": { "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "qDWiqy8/xdpZKtHna/645KbalwP86N2NFJEzfqhcv+Si4V2iNaEfR/dCneuF/4+Dcwl3f7jHMXj3ndWYftV3Ug==" + "resolved": "6.0.4", + "contentHash": "Xr+lIk1ZlTTFXEqnxQVLxrDqZlt2tm5X+/AhJbaY2emb/dVtGDiU5QuEtj3gHtwV/SWlP/rJ922I/BPuOJXlRw==" }, "NLog.OutputDebugString": { "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "wwJCQLaHVzuRf8TsXB+EEdrzVvE3dnzCSMQMDgwkw3AXp8VSp3JSVF/Q/H0oEqggKgKhPs13hh3a7svyQr4s3A==", + "resolved": "6.0.4", + "contentHash": "TOP2Ap9BbE98B/l/TglnguowOD0rXo8B/20xAgvj9shO/kf6IJ5M4QMhVxq72mrneJ/ANhHY7Jcd+xJbzuI5PA==", "dependencies": { - "NLog": "6.0.1" + "NLog": "6.0.4" } }, "runtime.osx.10.10-x64.CoreCompat.System.Drawing": { @@ -608,8 +608,8 @@ }, "SharpVectors.Wpf": { "type": "Transitive", - "resolved": "1.8.4.2", - "contentHash": "PNxLkMBJnV8A+6yH9OqOlhLJegvWP/dvh0rAJp2l0kcrR+rB4R2tQ9vhUqka+UilH4atN8T6zvjDOizVyfz2Ng==" + "resolved": "1.8.5", + "contentHash": "WURdBDq5AE8RjKV9pFS7lNkJe81gxja9SaMGE4URq9GJUZ6M+5DGUL0Lm3B0iYW2/Meyowaz4ffGsyW+RBSTtg==" }, "Splat": { "type": "Transitive", @@ -672,8 +672,8 @@ }, "System.Diagnostics.EventLog": { "type": "Transitive", - "resolved": "9.0.7", - "contentHash": "AJ+9fyCtQUImntxAJ9l4PZiCd4iepuk4pm7Qcno7PBIWQnfXlvwKuFsGk2H+QyY69GUVzDP2heELW6ho5BCXUg==" + "resolved": "9.0.9", + "contentHash": "wpsUfnyv8E5K4WQaok6weewvAbQhcLwXFcHBm5U0gdEaBs85N//ssuYvRPFWwz2rO/9/DFP3A1sGMzUFBj8y3w==" }, "System.Drawing.Common": { "type": "Transitive", @@ -838,10 +838,10 @@ "type": "Project", "dependencies": { "Droplex": "[1.7.0, )", - "FSharp.Core": "[9.0.300, )", + "FSharp.Core": "[9.0.303, )", "Flow.Launcher.Infrastructure": "[1.0.0, )", - "Flow.Launcher.Plugin": "[4.7.0, )", - "Meziantou.Framework.Win32.Jobs": "[3.4.3, )", + "Flow.Launcher.Plugin": "[5.0.0, )", + "Meziantou.Framework.Win32.Jobs": "[3.4.4, )", "Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )", "SemanticVersioning": "[3.0.0, )", "StreamJsonRpc": "[2.22.11, )", @@ -854,14 +854,14 @@ "Ben.Demystifier": "[0.4.1, )", "BitFaster.Caching": "[2.5.4, )", "CommunityToolkit.Mvvm": "[8.4.0, )", - "Flow.Launcher.Plugin": "[4.7.0, )", + "Flow.Launcher.Plugin": "[5.0.0, )", "InputSimulator": "[1.0.4, )", "MemoryPack": "[1.21.4, )", "Microsoft.VisualStudio.Threading": "[17.14.15, )", "NHotkey.Wpf": "[3.0.0, )", - "NLog": "[6.0.1, )", - "NLog.OutputDebugString": "[6.0.1, )", - "SharpVectors.Wpf": "[1.8.4.2, )", + "NLog": "[6.0.4, )", + "NLog.OutputDebugString": "[6.0.4, )", + "SharpVectors.Wpf": "[1.8.5, )", "System.Drawing.Common": "[7.0.0, )", "ToolGood.Words.Pinyin": "[3.1.0.3, )" } @@ -869,7 +869,7 @@ "flow.launcher.plugin": { "type": "Project", "dependencies": { - "JetBrains.Annotations": "[2024.3.0, )" + "JetBrains.Annotations": "[2025.2.2, )" } } } 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 901dc2a37..9cb2469d9 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -34,6 +34,7 @@ prompt 4 false + $(NoWarn);FLSG0007 @@ -103,9 +104,9 @@ - - - + + + diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs index 1820a7836..82b089033 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs @@ -106,12 +106,13 @@ public static class FaviconHelper { try { - using (var image = SKImage.FromBitmap(bitmap)) - using (var webp = image.Encode(SKEncodedImageFormat.Webp, 65)) - { - if (webp != null) - return webp.ToArray(); - } + using var image = SKImage.FromBitmap(bitmap); + if (image is null) + return null; + + using var webp = image.Encode(SKEncodedImageFormat.Webp, 65); + if (webp != null) + return webp.ToArray(); } finally { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Languages/ja.xaml index 6700bce19..d60739468 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Languages/ja.xaml @@ -6,15 +6,15 @@ ブラウザのブックマークを検索します - Failed to set url in clipboard + クリップボードにURLをコピーできませんでした - Bookmark Data - Open bookmarks in: - New window - New tab - Set browser from path: - Choose + ブックマークのデータ + ブックマークを開く場所: + 新しいウインドウ + 新しいタブ + 以下のパスからブラウザーを設定: + 選択 URLをコピー ブックマークのURLをクリップボードにコピー 次のブラウザから読み込む: 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 43a2c2f3c..b3cee425d 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj @@ -33,6 +33,7 @@ prompt 4 false + $(NoWarn);FLSG0007 @@ -62,7 +63,7 @@ - + diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ar.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ar.xaml index 759ba99de..324c91972 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ar.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ar.xaml @@ -1,8 +1,8 @@ - + آلة حاسبة - تمكنك من إجراء العمليات الحسابية. (جرب 5*3-2 في Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. ليست رقمًا (NaN) التعبير خاطئ أو غير مكتمل (هل نسيت بعض الأقواس؟) نسخ هذا الرقم إلى الحافظة @@ -13,4 +13,5 @@ نقطة (.) أقصى عدد من المنازل العشرية Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/cs.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/cs.xaml index f5dbe8e20..844c2dc30 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/cs.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/cs.xaml @@ -1,8 +1,8 @@ - + Kalkulačka - Umožňuje provádět matematické výpočty.(Try 5*3-2 v průtokovém spouštěči) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Není číslo (NaN) Nesprávný nebo neúplný výraz (Nezapomněli jste na závorky?) Kopírování výsledku do schránky @@ -13,4 +13,5 @@ Tečka (.) Desetinná místa Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/da.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/da.xaml index 2f2777aa1..405a39e92 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/da.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/da.xaml @@ -1,8 +1,8 @@ - + Calculator - Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Not a number (NaN) Expression wrong or incomplete (Did you forget some parentheses?) Copy this number to the clipboard @@ -13,4 +13,5 @@ Dot (.) Max. decimal places Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/de.xaml index 46f5efe23..4dc634db2 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/de.xaml @@ -1,8 +1,8 @@ - + Rechner - Ermöglicht mathematische Berechnungen. (Versuchen Sie 5*3-2 in Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Nicht eine Zahl (NaN) Ausdruck falsch oder unvollständig (Haben Sie einige Klammern vergessen?) Diese Zahl in die Zwischenablage kopieren @@ -13,4 +13,5 @@ Punkt (.) Max. Dezimalstellen Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml index b71e5d8a0..b12972b1b 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/en.xaml @@ -4,7 +4,7 @@ xmlns:system="clr-namespace:System;assembly=mscorlib"> Calculator - Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Not a number (NaN) Expression wrong or incomplete (Did you forget some parentheses?) Copy this number to the clipboard @@ -15,4 +15,5 @@ Dot (.) Max. decimal places Copy failed, please try later + Show error message when calculation fails \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es-419.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es-419.xaml index dce29cba5..12b4fdb0a 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es-419.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es-419.xaml @@ -1,8 +1,8 @@ - + Calculadora - Permite hacer cálculos matemáticos. (Pruebe con 5*3-2 en Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. No es un número (NaN) Expresión incorrecta o incompleta (¿Olvidó algún paréntesis?) Copiar este número al portapapeles @@ -13,4 +13,5 @@ Punto (.) Número máximo de decimales Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es.xaml index 7f1775e2e..05a862d78 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/es.xaml @@ -1,8 +1,8 @@ - + Calculadora - Realiza cálculos matemáticos (incluyendo valores hexadecimales). Utilizar ',' o '.' como separador de miles o decimal. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. No es un número (NaN) Expresión incorrecta o incompleta (¿Ha olvidado algunos paréntesis?) Copiar este número al portapapeles @@ -13,4 +13,5 @@ Punto (.) Número máximo de decimales Ha fallado la copia, inténtelo más tarde + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/fr.xaml index a6db34811..3219e517a 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/fr.xaml @@ -1,8 +1,8 @@ - + Calculatrice - Effectuer des calculs mathématiques (y compris les valeurs hexadécimales). Utilisez ',' ou '.' comme séparateur de milliers ou décimaux. + Effectuez des calculs mathématiques, y compris les valeurs hexadécimales et les fonctions avancées telles que 'min(1,2,3)', 'sqrt(123)' et 'cos(123)'. Pas un nombre (NaN) Expression incorrecte ou incomplète (avez-vous oublié certaines parenthèses ?) Copier ce chiffre dans le presse-papiers @@ -13,4 +13,5 @@ Point (.) Décimales max. Échec de la copie, réessayer plus tard + Afficher le message d'erreur lorsque le calcul échoue diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/he.xaml index b053c8905..7ee027743 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/he.xaml @@ -1,8 +1,8 @@ - + מחשבו - מאפשר לבצע חישובים מתמטיים. (נסה 5*3-2 ב-Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. לא מספר (NaN) הביטוי שגוי או לא שלם (האם שכחת סוגריים?) העתק מספר זה ללוח @@ -13,4 +13,5 @@ נקודה (.) מספר מקסימלי של מקומות עשרוניים Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/it.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/it.xaml index 5b724e82e..a0e61ff32 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/it.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/it.xaml @@ -1,8 +1,8 @@ - + Calcolatrice - Consente di eseguire calcoli matematici (provare 5*3-2 in Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Non è un numero (NaN) Espressione sbagliata o incompleta (avete dimenticato delle parentesi?) Copiare questo numero negli appunti @@ -13,4 +13,5 @@ Punto (.) Max. cifre decimali Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ja.xaml index bbd06006f..da0b64bdb 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ja.xaml @@ -1,16 +1,17 @@  - Calculator - Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place. - Not a number (NaN) - Expression wrong or incomplete (Did you forget some parentheses?) + 電卓 + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. + 数値で表せません (NaN) + 式が間違っているか不完全です(括弧を忘れていませんか?) この数字をクリップボードにコピーします 小数点の区切り記号 - The decimal separator to be used in the output. + 出力で使用される小数点の区切り文字。 システムのロケールを使用 コンマ(,) ドット (.) 小数点以下の最大桁数 - Copy failed, please try later + コピーに失敗しました。後でやり直してください + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ko.xaml index e4ca16d41..a595f4839 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ko.xaml @@ -1,8 +1,8 @@ - + 계산기 - 수학 계산을 할 수 있습니다. Flow Launcher에서 5*3-2를 입력해보세요. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. 숫자가 아님 (NaN) 표현식이 잘못되었거나 불완전합니다. (괄호를 깜빡하셨나요?) 해당 숫자를 클립보드에 복사 @@ -13,4 +13,5 @@ 마침표 (.) 최대 소수점 아래 자릿 수 Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nb.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nb.xaml index 9ae31e976..9b6b1f808 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nb.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nb.xaml @@ -1,8 +1,8 @@ - + Kalkulator - Lar deg gjøre matematiske beregninger. (Prøv 5*3-2 i Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Ikke et tall (NaN) Uttrykk feil eller ufullstendig (glem noen parenteser?) Kopier dette nummeret til utklippstavlen @@ -13,4 +13,5 @@ Prikk (.) Maks. desimaler Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nl.xaml index 2f2777aa1..405a39e92 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/nl.xaml @@ -1,8 +1,8 @@ - + Calculator - Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Not a number (NaN) Expression wrong or incomplete (Did you forget some parentheses?) Copy this number to the clipboard @@ -13,4 +13,5 @@ Dot (.) Max. decimal places Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pl.xaml index e73298dca..03f50ca23 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pl.xaml @@ -1,8 +1,8 @@ - + Kalkulator - Szybkie wykonywanie obliczeń matematycznych. (Spróbuj wpisać 5*3-2 w oknie Flow Launchera) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Nie liczba (NaN) Wyrażenie niepoprawne lub niekompletne (Czy zapomniałeś o nawiasach?) Skopiuj ten numer do schowka @@ -13,4 +13,5 @@ Kropka (.) Maks. liczba miejsc po przecinku Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-br.xaml index 73a60d42f..9afc3b784 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-br.xaml @@ -1,8 +1,8 @@ - + Calculadora - Permite fazer cálculos matemáticos.(Tente 5*3-2 no Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Não é um número (NaN) Expressão errada ou incompleta (Você esqueceu de adicionar parênteses?) Copiar este numero para a área de transferência @@ -13,4 +13,5 @@ Ponto (.) Max. decimal places Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-pt.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-pt.xaml index 7ec52be8c..1201e2555 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-pt.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/pt-pt.xaml @@ -1,8 +1,8 @@ - + Calculadora - Execução de cálculos matemáticos (incluindo valores hexadecimais). Utilize ',' ou '.' como separador de milhares ou de casas decimais. + Execute cálculos matemáticos, incluindo valores hexadecimais e funções avançadas como 'min(1,2,3)', 'sqrt(123)' e 'cos(123)'. Não é número (NN) Expressão errada ou incompleta (esqueceu-se de algum parêntese?) Copiar número para a área de transferência @@ -13,4 +13,5 @@ Ponto (.) Número máximo de casas decimais Falha ao copiar. Por favor tente mais tarde. + Mostrar mensagem de erro se o cálculo falhar diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ru.xaml index 43a7d44c7..7b40770cd 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/ru.xaml @@ -1,8 +1,8 @@ - + Калькулятор - Позволяет выполнять математические вычисления. (Попробуйте 5*3-2 в Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Не является числом (NaN) Выражение неправильное или неполное (Вы забыли скобки?) Скопировать этот номер в буфер обмена @@ -13,4 +13,5 @@ Точка (.) Макс. число знаков после запятой Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml index 498b6eb50..f398ab3e2 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml @@ -1,8 +1,8 @@ - + Kalkulačka - Vykonávanie matematických výpočtov (vrátane hexadecimálnych hodnôt). Ako oddeľovač tisícov alebo desatinného miesta použite ',' alebo '.'. + Vykonávajte matematické výpočty vrátane hexadecimálnych hodnôt a pokročilých funkcií, ako napríklad "min(1,2,3)", "sqrt(123)" a "cos(123)". Nie je číslo (NaN) Nesprávny alebo neúplný výraz (Nezabudli ste na zátvorky?) Kopírovať výsledok do schránky @@ -13,4 +13,5 @@ Bodka (.) Desatinné miesta Kopírovanie zlyhalo, skúste to neskôr + Zobraziť chybovú správu, keď výpočet zlyhá diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr-Cyrl-RS.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr-Cyrl-RS.xaml index 98e3aebb5..405a39e92 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr-Cyrl-RS.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr-Cyrl-RS.xaml @@ -2,7 +2,7 @@ Calculator - Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Not a number (NaN) Expression wrong or incomplete (Did you forget some parentheses?) Copy this number to the clipboard @@ -13,4 +13,5 @@ Dot (.) Max. decimal places Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr.xaml index 2f2777aa1..405a39e92 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sr.xaml @@ -1,8 +1,8 @@ - + Calculator - Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place. + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Not a number (NaN) Expression wrong or incomplete (Did you forget some parentheses?) Copy this number to the clipboard @@ -13,4 +13,5 @@ Dot (.) Max. decimal places Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/tr.xaml index b41fc0656..aec5bec43 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/tr.xaml @@ -1,8 +1,8 @@ - + Hesap Makinesi - Matematiksel hesaplamalar yapmaya yarar. (5*3-2 yazmayı deneyin) + Onaltılık değerler ve 'min(1,2,3)', 'sqrt(123)' ve 'cos(123)' gibi gelişmiş fonksiyonlar dahil olmak üzere matematiksel hesaplamalar gerçekleştirin. Sayı değil (NaN) İfade hatalı ya da eksik. (Parantez koymayı mı unuttunuz?) Bu sayıyı panoya kopyala @@ -13,4 +13,5 @@ Nokta (.) Maks. ondalık basamak Kopyalama başarısız oldu, lütfen daha sonra deneyin + Hesaplama başarısız olduğunda hata mesajı göster diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/uk-UA.xaml index 14042dffd..c2af4bbe3 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/uk-UA.xaml @@ -1,8 +1,8 @@ - + Калькулятор - Виконуйте математичні обчислення (включаючи шістнадцяткові значення). Використовуйте «,» або «.» як роздільник тисяч або десяткових знаків. + Виконуйте математичні розрахунки, включаючи шістнадцяткові значення та розширені функції, такі як «min(1,2,3)», «sqrt(123)» та «cos(123)». Не є числом (NaN) Вираз неправильний або неповний (Ви забули якісь дужки?) Скопіюйте це число в буфер обміну @@ -13,4 +13,5 @@ Крапка (.) Макс. кількість знаків після коми Копіювання не вдалося, спробуйте пізніше + Показувати повідомлення про помилку, якщо обчислення не вдалося diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/vi.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/vi.xaml index 20717d1db..6efbda3e4 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/vi.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/vi.xaml @@ -1,8 +1,8 @@ - + Máy tính - Cho phép thực hiện các phép tính toán học. (Thử 5*3-2 trong Flow Launcher) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. Không phải là số (NaN) Biểu thức sai hoặc không đầy đủ (Bạn có quên một số dấu ngoặc đơn không?) Sao chép số này vào clipboard @@ -13,4 +13,5 @@ dấu chấm (.) Tối đa. chữ số thập phân Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml index 445ed394f..234c613c6 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-cn.xaml @@ -1,8 +1,8 @@ - + 计算器 - 执行数学计算(包括十六进制值)。使用 , 或 . 作为分隔符或小数点。 + 进行数学计算,包括十六进制值和高级函数,如“最小(1,2,3)”、“sqrt(123)”和“cos123”等。 请输入数字 表达错误或不完整(您是否忘记了一些括号?) 将结果复制到剪贴板 @@ -13,4 +13,5 @@ 点(.) 小数点后最大位数 复制失败,请稍后再试 + 计算错误时显示错误消息 diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml index 7c8acf40b..b56e4660f 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/zh-tw.xaml @@ -1,8 +1,8 @@ - + 計算機 - 為 Flow Launcher 提供數學計算功能。(試著在 Flow Launcher 輸入 5*3-2) + Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'. 不是一個數 (NaN) Expression wrong or incomplete (Did you forget some parentheses?) 複製此數至剪貼簿 @@ -13,4 +13,5 @@ 點 (.) 小數點後最大位數 Copy failed, please try later + Show error message when calculation fails diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs index 6878c54b4..9d5e4700f 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs @@ -13,30 +13,24 @@ namespace Flow.Launcher.Plugin.Calculator { public class Main : IPlugin, IPluginI18n, ISettingProvider { - private static readonly Regex RegValidExpressChar = MainRegexHelper.GetRegValidExpressChar(); - private static readonly Regex RegBrackets = MainRegexHelper.GetRegBrackets(); private static readonly Regex ThousandGroupRegex = MainRegexHelper.GetThousandGroupRegex(); private static readonly Regex NumberRegex = MainRegexHelper.GetNumberRegex(); + private static readonly Regex PowRegex = MainRegexHelper.GetPowRegex(); + private static readonly Regex LogRegex = MainRegexHelper.GetLogRegex(); + private static readonly Regex LnRegex = MainRegexHelper.GetLnRegex(); + private static readonly Regex FunctionRegex = MainRegexHelper.GetFunctionRegex(); private static Engine MagesEngine; private const string Comma = ","; private const string Dot = "."; + private const string IcoPath = "Images/calculator.png"; + private static readonly List EmptyResults = []; internal static PluginInitContext Context { get; set; } = null!; private Settings _settings; private SettingsViewModel _viewModel; - /// - /// Holds the formatting information for a single query. - /// This is used to ensure thread safety by keeping query state local. - /// - private class ParsingContext - { - public string InputDecimalSeparator { get; set; } - public bool InputUsesGroupSeparators { get; set; } - } - public void Init(PluginInitContext context) { Context = context; @@ -54,38 +48,98 @@ namespace Flow.Launcher.Plugin.Calculator public List Query(Query query) { - if (!CanCalculate(query)) + if (string.IsNullOrWhiteSpace(query.Search)) { - return new List(); + return EmptyResults; } - var context = new ParsingContext(); - try { - var expression = NumberRegex.Replace(query.Search, m => NormalizeNumber(m.Value, context)); + var search = query.Search; + bool isFunctionPresent = FunctionRegex.IsMatch(search); + + // Mages is case sensitive, so we need to convert all function names to lower case. + search = FunctionRegex.Replace(search, m => m.Value.ToLowerInvariant()); + + var decimalSep = GetDecimalSeparator(); + var groupSep = GetGroupSeparator(decimalSep); + var expression = NumberRegex.Replace(search, m => NormalizeNumber(m.Value, isFunctionPresent, decimalSep, groupSep)); + + // WORKAROUND START: The 'pow' function in Mages v3.0.0 is broken. + // https://github.com/FlorianRappl/Mages/issues/132 + // We bypass it by rewriting any pow(x,y) expression to the equivalent (x^y) expression + // before the engine sees it. This loop handles nested calls. + { + string previous; + do + { + previous = expression; + expression = PowRegex.Replace(previous, PowMatchEvaluator); + } while (previous != expression); + } + // WORKAROUND END + + // WORKAROUND START: The 'log' & 'ln' function in Mages v3.0.0 are broken. + // https://github.com/FlorianRappl/Mages/issues/137 + // We bypass it by rewriting any log & ln expression to the equivalent (log10 & log) expression + // before the engine sees it. This loop handles nested calls. + { + string previous; + do + { + previous = expression; + expression = LogRegex.Replace(previous, LogMatchEvaluator); + } while (previous != expression); + } + { + string previous; + do + { + previous = expression; + expression = LnRegex.Replace(previous, LnMatchEvaluator); + } while (previous != expression); + } + // WORKAROUND END var result = MagesEngine.Interpret(expression); - if (result?.ToString() == "NaN") + if (result == null || string.IsNullOrEmpty(result.ToString())) + { + if (!_settings.ShowErrorMessage) return EmptyResults; + return + [ + new Result + { + Title = Localize.flowlauncher_plugin_calculator_expression_not_complete(), + IcoPath = IcoPath + } + ]; + } + + if (result.ToString() == "NaN") + { result = Localize.flowlauncher_plugin_calculator_not_a_number(); + } if (result is Function) + { result = Localize.flowlauncher_plugin_calculator_expression_not_complete(); + } - if (!string.IsNullOrEmpty(result?.ToString())) + if (!string.IsNullOrEmpty(result.ToString())) { decimal roundedResult = Math.Round(Convert.ToDecimal(result), _settings.MaxDecimalPlaces, MidpointRounding.AwayFromZero); - string newResult = FormatResult(roundedResult, context); + string newResult = FormatResult(roundedResult); - return new List - { + return + [ new Result { Title = newResult, - IcoPath = "Images/calculator.png", + IcoPath = IcoPath, Score = 300, - SubTitle = Localize.flowlauncher_plugin_calculator_copy_number_to_clipboard(), + // Check context nullability for unit testing + SubTitle = Context == null ? string.Empty : Localize.flowlauncher_plugin_calculator_copy_number_to_clipboard(), CopyText = newResult, Action = c => { @@ -101,118 +155,206 @@ namespace Flow.Launcher.Plugin.Calculator } } } - }; + ]; } } catch (Exception) { - // ignored + // Mages engine can throw various exceptions, for simplicity we catch them all and show a generic message. + if (!_settings.ShowErrorMessage) return EmptyResults; + return + [ + new Result + { + Title = Localize.flowlauncher_plugin_calculator_expression_not_complete(), + IcoPath = IcoPath + } + ]; } - return new List(); + return EmptyResults; } - /// - /// Parses a string representation of a number, detecting its format. It uses structural analysis - /// and falls back to system culture for truly ambiguous cases (e.g., "1,234"). - /// It populates the provided ParsingContext with the detected format for later use. - /// - /// A normalized number string with '.' as the decimal separator for the Mages engine. - private string NormalizeNumber(string numberStr, ParsingContext context) + private static string PowMatchEvaluator(Match m) { - var systemGroupSep = CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator; - int dotCount = numberStr.Count(f => f == '.'); - int commaCount = numberStr.Count(f => f == ','); + // m.Groups[1].Value will be `(...)` with parens + var contentWithParen = m.Groups[1].Value; + // remove outer parens. `(min(2,3), 4)` becomes `min(2,3), 4` + var argsContent = contentWithParen[1..^1]; - // Case 1: Unambiguous mixed separators (e.g., "1.234,56") - if (dotCount > 0 && commaCount > 0) + var bracketCount = 0; + var splitIndex = -1; + + // Find the top-level comma that separates the two arguments of pow. + for (var i = 0; i < argsContent.Length; i++) { - context.InputUsesGroupSeparators = true; - if (numberStr.LastIndexOf('.') > numberStr.LastIndexOf(',')) + switch (argsContent[i]) { - context.InputDecimalSeparator = Dot; - return numberStr.Replace(Comma, string.Empty); + case '(': + case '[': + bracketCount++; + break; + case ')': + case ']': + bracketCount--; + break; + case ',' when bracketCount == 0: + splitIndex = i; + break; + } + + if (splitIndex != -1) + break; + } + + if (splitIndex == -1) + { + // This indicates malformed arguments for pow, e.g., pow(5) or pow(). + // Return original string to let Mages handle the error. + return m.Value; + } + + var arg1 = argsContent[..splitIndex].Trim(); + var arg2 = argsContent[(splitIndex + 1)..].Trim(); + + // Check for empty arguments which can happen with stray commas, e.g., pow(,5) + if (string.IsNullOrEmpty(arg1) || string.IsNullOrEmpty(arg2)) + { + return m.Value; + } + + return $"({arg1}^{arg2})"; + } + + private static string LogMatchEvaluator(Match m) + { + // m.Groups[1].Value will be `(...)` with parens + var contentWithParen = m.Groups[1].Value; + var argsContent = contentWithParen[1..^1]; + + // log is unary — if malformed, return original to let Mages handle it + var arg = argsContent.Trim(); + if (string.IsNullOrEmpty(arg)) return m.Value; + + // log(x) -> log10(x) (natural log) + return $"(log10({arg}))"; + } + + private static string LnMatchEvaluator(Match m) + { + // m.Groups[1].Value will be `(...)` with parens + var contentWithParen = m.Groups[1].Value; + var argsContent = contentWithParen[1..^1]; + + // ln is unary — if malformed, return original to let Mages handle it + var arg = argsContent.Trim(); + if (string.IsNullOrEmpty(arg)) return m.Value; + + // ln(x) -> log(x) (natural log) + return $"(log({arg}))"; + } + private static string NormalizeNumber(string numberStr, bool isFunctionPresent, string decimalSep, string groupSep) + { + if (isFunctionPresent) + { + // STRICT MODE: When functions are present, ',' is ALWAYS an argument separator. + if (numberStr.Contains(',')) + { + return numberStr; + } + + string processedStr = numberStr; + + // Handle group separator, with special care for ambiguous dot. + if (!string.IsNullOrEmpty(groupSep)) + { + if (groupSep == ".") + { + var parts = processedStr.Split('.'); + if (parts.Length > 1) + { + var culture = CultureInfo.CurrentCulture; + if (IsValidGrouping(parts, culture.NumberFormat.NumberGroupSizes)) + { + processedStr = processedStr.Replace(groupSep, ""); + } + // If not grouped, it's likely a decimal number, so we don't strip dots. + } + } + else + { + processedStr = processedStr.Replace(groupSep, ""); + } + } + + // Handle decimal separator. + if (decimalSep != ".") + { + processedStr = processedStr.Replace(decimalSep, "."); + } + + return processedStr; + } + else + { + // LENIENT MODE: No functions are present, so we can be flexible. + string processedStr = numberStr; + if (!string.IsNullOrEmpty(groupSep)) + { + processedStr = processedStr.Replace(groupSep, ""); + } + if (decimalSep != ".") + { + processedStr = processedStr.Replace(decimalSep, "."); + } + return processedStr; + } + } + + private static bool IsValidGrouping(string[] parts, int[] groupSizes) + { + if (parts.Length <= 1) return true; + + if (groupSizes is null || groupSizes.Length == 0 || groupSizes[0] == 0) + return false; // has groups, but culture defines none. + + var firstPart = parts[0]; + if (firstPart.StartsWith('-')) firstPart = firstPart[1..]; + if (firstPart.Length == 0) return false; // e.g. ",123" + + if (firstPart.Length > groupSizes[0]) return false; + + var lastGroupSize = groupSizes.Last(); + var canRepeatLastGroup = lastGroupSize != 0; + + int groupIndex = 0; + for (int i = parts.Length - 1; i > 0; i--) + { + int expectedSize; + if (groupIndex < groupSizes.Length) + { + expectedSize = groupSizes[groupIndex]; + } + else if(canRepeatLastGroup) + { + expectedSize = lastGroupSize; } else { - context.InputDecimalSeparator = Comma; - return numberStr.Replace(Dot, string.Empty).Replace(Comma, Dot); + return false; } + + if (parts[i].Length != expectedSize) return false; + + groupIndex++; } - // Case 2: Only dots - if (dotCount > 0) - { - if (dotCount > 1) - { - context.InputUsesGroupSeparators = true; - return numberStr.Replace(Dot, string.Empty); - } - // A number is ambiguous if it has a single Dot in the thousands position, - // and does not start with a "0." or "." - bool isAmbiguous = numberStr.Length - numberStr.LastIndexOf('.') == 4 - && !numberStr.StartsWith("0.") - && !numberStr.StartsWith("."); - if (isAmbiguous) - { - if (systemGroupSep == Dot) - { - context.InputUsesGroupSeparators = true; - return numberStr.Replace(Dot, string.Empty); - } - else - { - context.InputDecimalSeparator = Dot; - return numberStr; - } - } - else // Unambiguous decimal (e.g., "12.34" or "0.123" or ".123") - { - context.InputDecimalSeparator = Dot; - return numberStr; - } - } - - // Case 3: Only commas - if (commaCount > 0) - { - if (commaCount > 1) - { - context.InputUsesGroupSeparators = true; - return numberStr.Replace(Comma, string.Empty); - } - // A number is ambiguous if it has a single Comma in the thousands position, - // and does not start with a "0," or "," - bool isAmbiguous = numberStr.Length - numberStr.LastIndexOf(',') == 4 - && !numberStr.StartsWith("0,") - && !numberStr.StartsWith(","); - if (isAmbiguous) - { - if (systemGroupSep == Comma) - { - context.InputUsesGroupSeparators = true; - return numberStr.Replace(Comma, string.Empty); - } - else - { - context.InputDecimalSeparator = Comma; - return numberStr.Replace(Comma, Dot); - } - } - else // Unambiguous decimal (e.g., "12,34" or "0,123" or ",123") - { - context.InputDecimalSeparator = Comma; - return numberStr.Replace(Comma, Dot); - } - } - - // Case 4: No separators - return numberStr; + return true; } - private string FormatResult(decimal roundedResult, ParsingContext context) + private string FormatResult(decimal roundedResult) { - string decimalSeparator = context.InputDecimalSeparator ?? GetDecimalSeparator(); + string decimalSeparator = GetDecimalSeparator(); string groupSeparator = GetGroupSeparator(decimalSeparator); string resultStr = roundedResult.ToString(CultureInfo.InvariantCulture); @@ -221,7 +363,7 @@ namespace Flow.Launcher.Plugin.Calculator string integerPart = parts[0]; string fractionalPart = parts.Length > 1 ? parts[1] : string.Empty; - if (context.InputUsesGroupSeparators && integerPart.Length > 3) + if (integerPart.Length > 3) { integerPart = ThousandGroupRegex.Replace(integerPart, groupSeparator); } @@ -236,29 +378,23 @@ namespace Flow.Launcher.Plugin.Calculator private string GetGroupSeparator(string decimalSeparator) { - // This logic is now independent of the system's group separator - // to ensure consistent output for unit testing. - return decimalSeparator == Dot ? Comma : Dot; - } + var culture = CultureInfo.CurrentCulture; + var systemGroupSeparator = culture.NumberFormat.NumberGroupSeparator; - private bool CanCalculate(Query query) - { - if (query.Search.Length < 2) + if (_settings.DecimalSeparator == DecimalSeparator.UseSystemLocale) { - return false; + return systemGroupSeparator; } - if (!RegValidExpressChar.IsMatch(query.Search)) + // When a custom decimal separator is used, + // use the system's group separator unless it conflicts with the custom decimal separator. + if (decimalSeparator == systemGroupSeparator) { - return false; + // Conflict: use the opposite of the decimal separator as a fallback. + return decimalSeparator == Dot ? Comma : Dot; } - if (!IsBracketComplete(query.Search)) - { - return false; - } - - return true; + return systemGroupSeparator; } private string GetDecimalSeparator() @@ -273,25 +409,6 @@ namespace Flow.Launcher.Plugin.Calculator }; } - private static bool IsBracketComplete(string query) - { - var matchs = RegBrackets.Matches(query); - var leftBracketCount = 0; - foreach (Match match in matchs) - { - if (match.Value == "(" || match.Value == "[") - { - leftBracketCount++; - } - else - { - leftBracketCount--; - } - } - - return leftBracketCount == 0; - } - public string GetTranslatedPluginTitle() { return Localize.flowlauncher_plugin_calculator_plugin_name(); diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/MainRegexHelper.cs b/Plugins/Flow.Launcher.Plugin.Calculator/MainRegexHelper.cs index f4e2090e7..a8b582ccc 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/MainRegexHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/MainRegexHelper.cs @@ -4,16 +4,21 @@ namespace Flow.Launcher.Plugin.Calculator; internal static partial class MainRegexHelper { - - [GeneratedRegex(@"[\(\)\[\]]", RegexOptions.Compiled)] - public static partial Regex GetRegBrackets(); - - [GeneratedRegex(@"^(ceil|floor|exp|pi|e|max|min|det|abs|log|ln|sqrt|sin|cos|tan|arcsin|arccos|arctan|eigval|eigvec|eig|sum|polar|plot|round|sort|real|zeta|bin2dec|hex2dec|oct2dec|factorial|sign|isprime|isinfty|==|~=|&&|\|\||(?:\<|\>)=?|[ei]|[0-9]|0x[\da-fA-F]+|[\+\%\-\*\/\^\., ""]|[\(\)\|\!\[\]])+$", RegexOptions.Compiled)] - public static partial Regex GetRegValidExpressChar(); - - [GeneratedRegex(@"[\d\.,]+", RegexOptions.Compiled)] + [GeneratedRegex(@"-?[\d\.,'\u00A0\u202F]+", RegexOptions.Compiled | RegexOptions.CultureInvariant)] public static partial Regex GetNumberRegex(); [GeneratedRegex(@"\B(?=(\d{3})+(?!\d))", RegexOptions.Compiled)] public static partial Regex GetThousandGroupRegex(); + + [GeneratedRegex(@"\bpow(\((?:[^()\[\]]|\((?)|\)(?<-Depth>)|\[(?)|\](?<-Depth>))*(?(Depth)(?!))\))", RegexOptions.Compiled | RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] + public static partial Regex GetPowRegex(); + + [GeneratedRegex(@"\blog(\((?:[^()\[\]]|\((?)|\)(?<-Depth>)|\[(?)|\](?<-Depth>))*(?(Depth)(?!))\))", RegexOptions.Compiled | RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] + public static partial Regex GetLogRegex(); + + [GeneratedRegex(@"\bln(\((?:[^()\[\]]|\((?)|\)(?<-Depth>)|\[(?)|\](?<-Depth>))*(?(Depth)(?!))\))", RegexOptions.Compiled | RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] + public static partial Regex GetLnRegex(); + + [GeneratedRegex(@"\b(sqrt|pow|factorial|abs|sign|ceil|floor|round|exp|log|log2|log10|min|max|lt|eq|gt|sin|cos|tan|arcsin|arccos|arctan|isnan|isint|isprime|isinfty|rand|randi|type|is|as|length|throw|catch|eval|map|clamp|lerp|regex|shuffle)\s*\(", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] + public static partial Regex GetFunctionRegex(); } diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs index 8354863b8..cac0f3080 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs @@ -1,9 +1,11 @@  -namespace Flow.Launcher.Plugin.Calculator +namespace Flow.Launcher.Plugin.Calculator; + +public class Settings { - public class Settings - { - public DecimalSeparator DecimalSeparator { get; set; } = DecimalSeparator.UseSystemLocale; - public int MaxDecimalPlaces { get; set; } = 10; - } + public DecimalSeparator DecimalSeparator { get; set; } = DecimalSeparator.UseSystemLocale; + + public int MaxDecimalPlaces { get; set; } = 10; + + public bool ShowErrorMessage { get; set; } = false; } diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Calculator/ViewModels/SettingsViewModel.cs index 87ae72fb6..79236bdf8 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/ViewModels/SettingsViewModel.cs @@ -1,31 +1,25 @@ using System.Collections.Generic; using System.Linq; -namespace Flow.Launcher.Plugin.Calculator.ViewModels +namespace Flow.Launcher.Plugin.Calculator.ViewModels; + +public class SettingsViewModel(Settings settings) : BaseModel { - public class SettingsViewModel : BaseModel + public Settings Settings { get; } = settings; + + public static IEnumerable MaxDecimalPlacesRange => Enumerable.Range(1, 20); + + public List AllDecimalSeparator { get; } = DecimalSeparatorLocalized.GetValues(); + + public DecimalSeparator SelectedDecimalSeparator { - public SettingsViewModel(Settings settings) + get => Settings.DecimalSeparator; + set { - Settings = settings; - } - - public Settings Settings { get; init; } - - public static IEnumerable MaxDecimalPlacesRange => Enumerable.Range(1, 20); - - public List AllDecimalSeparator { get; } = DecimalSeparatorLocalized.GetValues(); - - public DecimalSeparator SelectedDecimalSeparator - { - get => Settings.DecimalSeparator; - set + if (Settings.DecimalSeparator != value) { - if (Settings.DecimalSeparator != value) - { - Settings.DecimalSeparator = value; - OnPropertyChanged(); - } + Settings.DecimalSeparator = value; + OnPropertyChanged(); } } } diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml index 8d240ef39..9e7549b2d 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml @@ -15,6 +15,7 @@ + @@ -58,5 +59,14 @@ ItemsSource="{Binding MaxDecimalPlacesRange}" SelectedItem="{Binding Settings.MaxDecimalPlaces}" /> + diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml.cs index 7bc307d11..9e75e7bfb 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Views/CalculatorSettings.xaml.cs @@ -1,22 +1,16 @@ using System.Windows.Controls; using Flow.Launcher.Plugin.Calculator.ViewModels; -namespace Flow.Launcher.Plugin.Calculator.Views -{ - /// - /// Interaction logic for CalculatorSettings.xaml - /// - public partial class CalculatorSettings : UserControl - { - private readonly SettingsViewModel _viewModel; - private readonly Settings _settings; +namespace Flow.Launcher.Plugin.Calculator.Views; - public CalculatorSettings(Settings settings) - { - _viewModel = new SettingsViewModel(settings); - _settings = _viewModel.Settings; - DataContext = _viewModel; - InitializeComponent(); - } +public partial class CalculatorSettings : UserControl +{ + private readonly SettingsViewModel _viewModel; + + public CalculatorSettings(Settings settings) + { + _viewModel = new SettingsViewModel(settings); + DataContext = _viewModel; + InitializeComponent(); } } diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json b/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json index c9435e043..93df9ec72 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Calculator/plugin.json @@ -2,7 +2,7 @@ "ID": "CEA0FDFC6D3B4085823D60DC76F28855", "ActionKeyword": "*", "Name": "Calculator", - "Description": "Perform mathematical calculations (including hexadecimal values). Use ',' or '.' as thousand separator or decimal place.", + "Description": "Perform mathematical calculations, including hex values and advanced functions such as 'min(1,2,3)', 'sqrt(123)' and 'cos(123)'.", "Author": "cxfksword, dcog989", "Version": "1.0.0", "Language": "csharp", 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 af33f4da2..b7c54e578 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -19,6 +19,7 @@ ..\..\Output\Release\Plugins\Flow.Launcher.Plugin.Explorer + $(NoWarn);FLSG0007 @@ -47,8 +48,8 @@ - - + + diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml index b2bf99515..608fe88a1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ar.xaml @@ -22,6 +22,7 @@ حدث خطأ أثناء البحث: {0} تعذر فتح المجلد تعذر فتح الملف + This new action keyword is already assigned to another plugin, please choose a different one حذف diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml index 0acdb5ca1..2381d501b 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/cs.xaml @@ -22,6 +22,7 @@ Při vyhledávání došlo k chybě: {0} Adresář nelze otevřít Nelze otevřít soubor + This new action keyword is already assigned to another plugin, please choose a different one Smazat diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml index 66816de93..f5f13e5a3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/da.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Slet diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml index 8ddb958ad..8e352e614 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/de.xaml @@ -22,6 +22,7 @@ Fehler aufgetreten während Suche: {0} Ordner konnte nicht geöffnet werden Datei konnte nicht geöffnet werden + This new action keyword is already assigned to another plugin, please choose a different one Löschen diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml index f80a55965..7379571a7 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es-419.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Eliminar diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml index 474ba9a4c..0a1d73c28 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/es.xaml @@ -22,6 +22,7 @@ Se ha producido un error durante la búsqueda: {0} No se ha podido abrir la carpeta No se ha podido abrir el archivo + This new action keyword is already assigned to another plugin, please choose a different one Eliminar diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml index 096cd4a0d..d9b767b9c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/fr.xaml @@ -22,6 +22,7 @@ Une erreur s'est produite pendant la recherche : {0} Impossible d'ouvrir le dossier Impossible d'ouvrir le fichier + This new action keyword is already assigned to another plugin, please choose a different one Supprimer diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml index a4e4445ae..a84d7707d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/he.xaml @@ -22,6 +22,7 @@ אירעה שגיאה במהלך החיפוש: {0} לא ניתן היה לפתוח את התיקייה לא ניתן היה לפתוח את הקובץ + This new action keyword is already assigned to another plugin, please choose a different one מחק diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml index f3fa1e1e6..a88ad2da1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/it.xaml @@ -22,6 +22,7 @@ Errore durante la ricerca: {0} Impossibile aprire la cartella Impossibile aprire il file + This new action keyword is already assigned to another plugin, please choose a different one Cancella diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml index d0b045175..8a701ebc6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ja.xaml @@ -2,17 +2,17 @@ - Please make a selection first - Please select a folder path. - Please choose a different name or folder path. - Are you sure you want to delete this quick access link? - Are you sure you want to delete this index search excluded path? - Please select a folder link - Are you sure you want to delete {0}? - Are you sure you want to permanently delete this file? - Are you sure you want to permanently delete this file/folder? - Deletion successful - Successfully deleted {0} + 項目を選択してください + フォルダのパスを選択してください。 + 別の名前またはフォルダのパスを選択してください。 + このクイックアクセスリンクを削除してもよろしいですか? + このインデックス検索の除外パスを削除してもよろしいですか? + フォルダーのリンクを選択してください + {0} を削除してもよろしいですか? + このファイルを完全に削除してもよろしいですか? + このファイルやフォルダーを完全に削除してもよろしいですか? + 削除に成功 + {0} は正常に削除されました Assigning the global action keyword could bring up too many results during search. Please choose a specific action keyword Quick Access can not be set to the global action keyword when enabled. Please choose a specific action keyword The required service for Windows Index Search does not appear to be running @@ -20,8 +20,9 @@ The warning message has been switched off. As an alternative for searching files and folders, would you like to install Everything plugin?{0}{0}Select 'Yes' to install Everything plugin, or 'No' to return Explorer Alternative Error occurred during search: {0} - Could not open folder - Could not open file + フォルダーを開けませんでした + ファイルを開けませんでした + This new action keyword is already assigned to another plugin, please choose a different one 削除 @@ -31,7 +32,7 @@ アクションキーワードのカスタマイズ Customise Quick Access Quick Access Links - Everything Setting + Everything の設定 プレビューパネル サイズ 作成日時 @@ -39,8 +40,8 @@ File Age ファイル情報の表示 日付と時刻の形式 - Sort Option: - Everything Path: + 並べ替え方法: + Everything のパス: Launch Hidden Editor Path Shell Path @@ -64,16 +65,16 @@ Direct Enumeration ファイル エディターのパス フォルダー エディターのパス - Enabled - Disabled + 有効 + 無効 Content Search Engine Directory Recursive Search Engine Index Search Engine Windowsのインデックスオプションを開く Excluded File Types (comma seperated) - For example: exe,jpg,png - Maximum results + 例: exe,jpg,png + 結果の最大表示件数 The maximum number of results requested from active search engine @@ -81,17 +82,17 @@ Windows SearchまたはEverythingを使って、ファイルやフォルダーを検索・管理します - Ctrl + Enter to open the directory + Ctrl + Enter でフォルダーを開く Ctrl + Enter to open the containing folder {0}{4}Size: {1}{4}Date created: {2}{4}Date modified: {3} - Unknown + 不明 {0}{3}Space free: {1}{3}Total size: {2} パスをコピー 現在の項目のパスをコピー - Copy name - Copy name of current item to clipboard + 名前をコピー + 現在の項目の名前をクリップボードにコピーする コピー 現在のファイルをコピー 現在のフォルダーをコピー @@ -99,13 +100,13 @@ 現在のファイルを完全に削除 現在のフォルダーを完全に削除 名前 - Type - Path + 種類 + パス ファイル フォルダー - Delete the selected - Run as different user - Run the selected using a different user account + 選択したものを削除する + 別のユーザーとして実行 + 別のユーザーアカウントを使用して選択したものを実行する フォルダーを開く 現在の項目が含まれている場所を開きます エディターで開く: @@ -119,9 +120,9 @@ Windowsインデックスオプションを開けませんでした クイックアクセスに追加 現在の項目をクイックアクセスに追加 - Successfully Added + 正常に追加されました クイックアクセスに追加しました - Successfully Removed + 削除に成功しました Successfully removed from Quick Access エクスプローラーの検索アクティベーション用アクションキーワードで開けるように、クイックアクセスに追加します クイックアクセスから削除 @@ -130,81 +131,81 @@ Windowsの右クリックメニューを表示 アプリで開く 開くためのプログラムを選択します - Fail to delete {0} + {0} の削除に失敗しました File not found: {0} - Fail to open {0} - Fail to set text in clipboard - Fail to set files/folders in clipboard + {0} の削除に失敗しました + クリップボードにテキストをコピーできませんでした + ファイル/フォルダのコピーに失敗しました - {0} free of {1} - Open in Default File Manager + 空き領域 {1} 中の {0} + デフォルトのファイルマネージャーで開く Use '>' to search in this directory, '*' to search for file extensions or '>*' to combine both searches. - Failed to load Everything SDK - Warning: Everything service is not running - Error while querying Everything - Sort By - Name ↑ - Name ↓ - Path ↑ - Path ↓ - Size ↑ - Size ↓ - Extension ↑ - Extension ↓ - Type Name ↑ - Type Name ↓ - Date Created ↑ - Date Created ↓ - Date Modified ↑ - Date Modified ↓ + Everything SDK の読み込みに失敗しました + 警告: Everythingのサービスが実行されていません + Everything へのクエリ中にエラーが発生しました + 並べ替え順 + 名前 ↑ + 名前 ↓ + パス ↑ + パス ↓ + サイズ ↑ + サイズ ↓ + 拡張子 ↑ + 拡張子 ↓ + 種類名 ↑ + 種類名 ↓ + 作成日時 ↑ + 作成日時 ↓ + 更新日時 ↑ + 更新日時 ↓ Attributes ↑ Attributes ↓ File List FileName ↑ File List FileName ↓ - Run Count ↑ - Run Count ↓ + 実行回数 ↑ + 実行回数 ↓ Date Recently Changed ↑ Date Recently Changed ↓ - Date Accessed ↑ - Date Accessed ↓ - Date Run ↑ - Date Run ↓ + アクセス日時 ↑ + アクセス日時 ↓ + 実行日時 ↑ + 実行日時 ↓ - Warning: This is not a Fast Sort option, searches may be slow + 警告:これは高速な並べ替えオプションではありません。検索が遅くなる場合があります Search Full Path - Enable File/Folder Run Count + ファイル/フォルダの実行カウントを有効にする - Click to launch or install Everything - Everything Installation - Installing Everything service. Please wait... - Successfully installed Everything service - Failed to automatically install Everything service. Please manually install it from https://www.voidtools.com + クリックして Everything を起動またはインストール + Everything のインストール + Everything サービスをインストールしています。お待ちください… + Everything サービスを正常にインストールしました + Everything サービスを自動的にインストールできませんでした。https://www.voidtools.com から手動でインストールしてください Click here to start it Everythingのインストールが見つかりませんでした。手動で場所を指定しますか?{0}{0}「いいえ」をクリックすると、Everythingが自動的にインストールされます。 - Do you want to enable content search for Everything? - It can be very slow without index (which is only supported in Everything v1.5+) + Everything でのコンテンツ検索を有効にしますか? + インデックスなしでは非常に遅くなることがあります(Everything v1.5以降でのみサポートされています) - Unable to find Everything.exe - Failed to install Everything, please install it manually + Everything.exe が見つかりません + Everything のインストールに失敗しました。手動でインストールしてください - Native Context Menu - Display native context menu (experimental) - Below you can specify items you want to include in the context menu, they can be partial (e.g. 'pen wit') or complete ('Open with'). - Below you can specify items you want to exclude from context menu, they can be partial (e.g. 'pen wit') or complete ('Open with'). + Windowsのコンテキストメニュー + Windowsのコンテキストメニューを表示(実験的) + 以下では、コンテキストメニューに表示する項目を指定することができます。部分的 (例: 「開」)、または完全な項目名を指定することができます (「開く」)。 + 以下では、コンテキストメニューから除外する項目を指定することができます。部分的 (例: 「開」)、または完全な項目名を指定することができます (「開く」)。 - Today - {0} days ago - 1 month ago - {0} months ago - 1 year ago - {0} years ago + 今日 + {0} 日前 + 1 か月前 + {0} か月前 + 1 年前 + {0} 年前 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml index 3195ff6e5..e437926c8 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ko.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one 삭제 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml index 5efdead0c..b0672d3ad 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nb.xaml @@ -22,6 +22,7 @@ Feil oppstod under søk: {0} Kunne ikke åpne mappe Kunne ikke åpne fil + This new action keyword is already assigned to another plugin, please choose a different one Slett diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml index cc6d350c9..3de4ce5e5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/nl.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Verwijder diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml index c981c2832..1a01e8b90 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pl.xaml @@ -22,6 +22,7 @@ Wystąpił błąd podczas wyszukiwania: {0} Nie można otworzyć folderu Nie można otworzyć pliku + This new action keyword is already assigned to another plugin, please choose a different one Usuń diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml index fe4fa320a..9a3a4ffeb 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-br.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Apagar diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml index d0651cc53..2d33768f9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/pt-pt.xaml @@ -22,6 +22,7 @@ Ocorreu um erro ao pesquisar: {0} Não foi possível abrir a pasta Não foi possível abrir o ficheiro + This new action keyword is already assigned to another plugin, please choose a different one Eliminar diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml index 1644745ae..cb28fcfd5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/ru.xaml @@ -22,6 +22,7 @@ При поиске произошла ошибка: {0} Не удалось открыть папку Не удалось открыть файл + This new action keyword is already assigned to another plugin, please choose a different one Удалить @@ -57,14 +58,14 @@ Quick Access: Current Action Keyword Подтвердить - Enabled + Включено When disabled Flow will not execute this search option, and will additionally revert back to '*' to free up the action keyword Everything Windows Index Direct Enumeration Путь к редактору файлов Путь к редактору папки - Enabled + Включено Отключён Content Search Engine diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml index 3ca738b69..1350969b6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sk.xaml @@ -22,6 +22,7 @@ Počas vyhľadávania došlo k chybe: {0} Nepodarilo sa otvoriť priečinok Nepodarilo sa otvoriť súbor + Nový aktivačný príkaz už bol priradený inému pluginu, prosím, zvoľte iný aktivačný príkaz Odstrániť diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml index 19fe6dc64..e7979f6dd 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr-Cyrl-RS.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Delete diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml index f8effbd7c..ef7e6a5c3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/sr.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one Obriši diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml index aefe8af30..3e491ea22 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/tr.xaml @@ -22,6 +22,7 @@ Arama sırasında hata oluştu: {0} Klasör açılamadı Dosya açılamadı + This new action keyword is already assigned to another plugin, please choose a different one Sil @@ -123,7 +124,7 @@ Hızlı Erişim'e başarıyla eklendi Başarıyla Kaldırıldı Hızlı Erişim'den başarıyla kaldırıldı - Add to Quick Access so it can be opened with Explorer's Search Activation action keyword + Dosya Gezgini'nin Arama Etkinleştirme anahtar sözcüğü ile açılabilmesi için Hızlı Erişim'e ekleyin Hızlı Erişimden Kaldır Hızlı Erişimden Kaldır Geçerli öğeyi Hızlı Erişim'den kaldır diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml index 823c33193..60a08a82f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/uk-UA.xaml @@ -22,6 +22,7 @@ Виникла помилка під час пошуку: {0} Не вдалося відкрити папку Не вдалося відкрити файл + This new action keyword is already assigned to another plugin, please choose a different one Видалити diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml index 7b64af3d8..6416fc447 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/vi.xaml @@ -22,6 +22,7 @@ Đã xảy ra lỗi trong quá trình tìm kiếm: {0} Không thể mở thư mục Không thể mở file + This new action keyword is already assigned to another plugin, please choose a different one Xóa diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml index 8ad979ac8..1cab71d8d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml @@ -22,6 +22,7 @@ 搜索时发生错误:{0} 无法打开文件夹 无法打开文件 + This new action keyword is already assigned to another plugin, please choose a different one 删除 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml index 39f260499..d64cd7698 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-tw.xaml @@ -22,6 +22,7 @@ Error occurred during search: {0} Could not open folder Could not open file + This new action keyword is already assigned to another plugin, please choose a different one 刪除 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 7292697ce..ae2235c5c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -577,8 +577,8 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels } } - public int MaxResultLowerLimit => 1; - public int MaxResultUpperLimit => 100000; + public int MaxResultLowerLimit { get; } = 1; + public int MaxResultUpperLimit { get; } = 100000; public int MaxResult { @@ -592,7 +592,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels #region Everything FastSortWarning - public List AllEverythingSortOptions = EverythingSortOptionLocalized.GetValues(); + public List AllEverythingSortOptions { get; } = EverythingSortOptionLocalized.GetValues(); public EverythingSortOption SelectedEverythingSortOption { diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ja.xaml index 893948d3d..85188e622 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ja.xaml @@ -1,9 +1,9 @@  - Activate {0} plugin action keyword + {0} プラグインのアクションキーワード - Plugin Indicator - Provides plugins action words suggestions + プラグインインジケーター + プラグインのアクションキーワードの一覧を検索します diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ja.xaml index d62f0f61b..f51b692e6 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ja.xaml @@ -2,69 +2,69 @@ - Downloading plugin - Successfully downloaded - Error: Unable to download the plugin - {0} by {1} {2}{3}Would you like to uninstall this plugin? After the uninstallation Flow will automatically restart. - {0} by {1} {2}{2}Would you like to uninstall this plugin? - {0} by {1} {2}{3}Would you like to install this plugin? After the installation Flow will automatically restart. - {0} by {1} {2}{2}Would you like to install this plugin? - Plugin Install - Installing Plugin - Download and install {0} - Plugin Uninstall - Keep plugin settings - Do you want to keep the settings of the plugin for the next usage? + プラグインをダウンロード中 + {0} のダウンロードに成功 + エラー: プラグインをダウンロードできません + {0} by {1} {2}{3}このプラグインをアンインストールしますか?アンインストール後、Flow Launcherは自動的に再起動されます。 + {0} by {1} {2}{2}このプラグインをアンインストールしますか? + {0} by {1} {2}{3}このプラグインをインストールしますか?インストール後、Flow Launcherは自動的に再起動されます。 + {0} by {1} {2}{2}このプラグインをインストールしますか? + プラグインのインストール + プラグインをインストール中 + {0} をダウンロードしてインストール中 + プラグインのアンインストール + プラグインの設定を保持 + 再びインストールして使用するときのためにプラグインの設定を維持しますか? Plugin successfully installed. Restarting Flow, please wait... - Unable to find the plugin.json metadata file from the extracted zip file. - Error: A plugin which has the same or greater version with {0} already exists. - Error installing plugin - Error occurred while trying to install {0} - Error uninstalling plugin - No update available - All plugins are up to date - {0} by {1} {2}{3}Would you like to update this plugin? After the update Flow will automatically restart. - {0} by {1} {2}{2}Would you like to update this plugin? - Plugin Update - This plugin is already installed - Plugin Manifest Download Failed - Please check if you can connect to github.com. This error means you may not be able to install or update plugins. - Update all plugins - Would you like to update all plugins? - Would you like to update {0} plugins?{1}Flow Launcher will restart after updating all plugins. - Would you like to update {0} plugins? - {0} plugins successfully updated. Restarting Flow, please wait... - Plugin {0} successfully updated. Restarting Flow, please wait... - Installing from an unknown source - You are installing this plugin from an unknown source and it may contain potential risks!{0}{0}Please ensure you understand where this plugin is from and that it is safe.{0}{0}Would you like to continue still?{0}{0}(You can switch off this warning via settings) + 展開されたzipファイルからplugin.jsonメタデータファイルが見つかりません。 + エラー: {0} と同じまたはそれ以上のバージョンを持つプラグインが既に存在します。 + プラグインのインストール失敗 + {0} のインストール中にエラーが発生しました + プラグインのアンインストール失敗 + 利用可能な更新はありません + すべてのプラグインが最新です + {0} by {1} {2}{3}このプラグインを更新しますか?更新後、Flow Launcherは自動的に再起動されます。 + {0} by {1} {2}{2}このプラグインを更新しますか? + プラグインの更新 + このプラグインは既にインストールされています + プラグインマニフェストのダウンロードに失敗 + github.com に接続できるかどうかを確認してください。このエラーはプラグインをインストールまたは更新できないことを意味します。 + すべてのプラグインを更新 + すべてのプラグインを更新しますか? + {0} 個のプラグインを更新してもよいですか?{1}すべてのプラグインを更新した後、Flow Launcher が再起動します。 + {0} 個のプラグインを更新してもよいですか? + {0} 個のプラグインが正常に更新されました。Flow を再起動しています。お待ちください… + プラグイン {0} が正常に更新されました。Flow を再起動しています。お待ちください… + 不明なソースからインストール中 + あなたは不明なソースから提供されたプラグインをインストールしようとしており、潜在的なリスクを含んでいる可能性があります!{0}{0}このプラグインの開発元をよく調べ、安全であることをご自身で確かめてください。{0}{0}それでもあなたはこのプラグインをインストールしますか?{0}{0}(この警告は設定で無効にすることができます) - Plugin {0} successfully installed. Please restart Flow. - Plugin {0} successfully uninstalled. Please restart Flow. - Plugin {0} successfully updated. Please restart Flow. - {0} plugins successfully updated. Please restart Flow. - Plugin {0} has already been modified. Please restart Flow before making any further changes. - {0} modified already - Please restart Flow before making any further changes + プラグイン {0} のインストールに成功しました。Flow を再起動してください。 + プラグイン {0} のアンインストールに成功しました。Flow を再起動してください。 + プラグイン {0} が正常に更新されました。Flow を再起動してください。 + {0} 個のプラグインが正常に更新されました。Flow を再起動してください。 + プラグイン {0} は既に変更されています。Flow Launcher を再起動してからもう一度お試しください。 + {0} は既に変更されています + これ以上変更を加える前に Flow Launcher を再起動してください - Invalid zip installer file - Please check if there is a plugin.json in {0} + 無効な zip インストーラーファイル + {0} に plugin.json があるか確認してください - Plugins Manager - Install, uninstall or update Flow Launcher plugins via the search window - Unknown Author + プラグインマネージャー + 検索ウィンドウから Flow Launcher のプラグインをインストール、アンインストール、または更新する + 不明な作者 - Open website - Visit the plugin's website - See source code - See the plugin's source code - Suggest an enhancement or submit an issue - Suggest an enhancement or submit an issue to the plugin developer - Go to Flow's plugins repository - Visit the PluginsManifest repository to see community-made plugin submissions + ウェブサイトを開く + プラグインのウェブサイトを開く + ソースコードを参照 + プラグインのソースコードを見る + 改善を提案するか、問題を報告してください + プラグイン開発者に機能改善を提案するか問題を報告してください + Flow のプラグインリポジトリに移動 + PluginsManifest リポジトリにアクセスして、コミュニティで作られたプラグインを表示する 不明な提供元からインストールするとき警告する - Restart Flow Launcher automatically after installing/uninstalling/updating plugin via Plugins Manager + プラグインマネージャー経由でプラグインをインストール、アンインストール、または更新した後、Flow Lancher を自動的に再起動します diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ru.xaml index 18913c7c6..5ecd203f8 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/ru.xaml @@ -56,8 +56,8 @@ Перейти на сайт - Visit the plugin's website - See source code + Перейти на сайт плагина + Посмотреть исходный код See the plugin's source code Suggest an enhancement or submit an issue Suggest an enhancement or submit an issue to the plugin developer diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml index f788c9ce3..22d8aee6e 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/sk.xaml @@ -66,5 +66,5 @@ Upozornenie na inštaláciu z neznámeho zdroja - Automaticky reštartovať Flow Launcher po inštalácii/odinštalácii/aktualizáciu pluginu cez Správcu pluginov + Automaticky reštartovať Flow Launcher po inštalácii/odinštalácii/aktualizácii pluginu cez Správcu pluginov 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 2da97ebbd..0a7a02a45 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj @@ -52,7 +52,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml index 0a7176d2c..bda1ec5f5 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml @@ -1,14 +1,14 @@  - Process Killer - Kill running processes from Flow Launcher + プロセスキラー + Flow Launcherから実行中のプロセスを終了します - kill all instances of "{0}" - kill {0} processes - kill all instances + "{0}" のすべてのインスタンスを終了する + {0} プロセスを終了する + すべてのインスタンスを終了する - Show title for processes with visible windows - Put processes with visible windows on the top + ウィンドウが表示されているプロセスのタイトルを表示する + ウィンドウが表示されているプロセスを上に表示する 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 da2b19d7c..e9515fab4 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj +++ b/Plugins/Flow.Launcher.Plugin.Program/Flow.Launcher.Plugin.Program.csproj @@ -64,12 +64,12 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/ja.xaml index 0134627c5..38879713d 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/ja.xaml @@ -2,98 +2,98 @@ - Reset Default + デフォルトにリセット 削除 編集 追加 名前 - 有効 - Enabled - 無効 - Status - Enabled - Disabled + 有効化 + 有効 + 無効化 + 状態 + 有効 + 無効 場所 - All Programs - File Type - Reindex - Indexing - Index Sources - Options - UWP Apps - When enabled, Flow will load UWP Applications - Start Menu - When enabled, Flow will load programs from the start menu - Registry - When enabled, Flow will load programs from the registry - PATH - When enabled, Flow will load programs from the PATH environment variable + すべてのプログラム + ファイルの種類 + 再読み込み + インデックス作成中 + インデックスのソース + オプション + UWP アプリ + 有効にすると、Flow は UWP アプリケーションを読み込みます + スタートメニュー + 有効にすると、Flowはスタートメニューからプログラムを読み込みます + レジストリー + 有効にすると、Flowはレジストリーからプログラムを読み込みます + PATH変数 + 有効にすると、Flow は環境変数のPATHに登録されたフォルダーからプログラムを読み込みます アプリのパスを非表示 UWPやlnkなどの実行可能ファイルについて、サブタイトル領域にファイルパスが表示されないようにします。 - Hide uninstallers - Hides programs with common uninstaller names, such as unins000.exe + アンインストーラーを非表示 + unins000.exe のような一般的な名前のアンインストーラのプログラムを非表示にします プログラムの説明で検索 - Flow will search program's description - Hide duplicated apps - Hide duplicated Win32 programs that are already in the UWP list - Suffixes - Max Depth + Flow はプログラムの説明を検索します + 重複したアプリを非表示 + UWPリストに既に存在するアプリと同じ名前の、Win32プログラムを非表示にする + 接尾辞 + 最大の深さ - Directory: - Browse - File Suffixes: - Maximum Search Depth (-1 is unlimited): + フォルダー + 選択 + ファイル名の末尾: + 最大の検索の深さ (-1に設定すると無制限): - Please select a program source - Are your sure to delete {0}? - Please select program sources that are not added by you - Please select program sources that are added by you - Another program source with the same location already exists. + プログラムのソースを選択してください + 選択したプログラムソースを削除してもよろしいですか? + あなたが追加していないプログラムのソースを選択してください + あなたが追加したプログラムのソースを選択してください + 同じ場所を持つ別のプログラムのソースが既に存在します。 - Program Source - Edit directory and status of this program source. + プログラムのソース + このプログラムのソースのフォルダーとステータスを編集します。 更新 - Program Plugin will only index files with selected suffixes and .url files with selected protocols. + プログラムプラグインは、選択されたファイル名の末尾と .url ファイルのみをインデックス化します。 Sucessfully update file suffixes - File suffixes can't be empty - Protocols can't be empty + ファイル名の末尾は空にできません + プロトコルは空にできません Index file suffixes - URL Protocols - Steam Games - Epic Games + ショートカット(URL) + Steam ゲーム + Epic ゲーム Http/Https - Custom URL Protocols - Custom File Suffixes + カスタムURLプロトコルを指定 + カスタムファイル名の末尾を指定 - Insert file suffixes you want to index. Suffixes should be separated by ';'. (ex>bat;py) + インデックスするファイル名の末尾を入力してください。サフィックスは';'で区切る必要があります。(例>bat;py) - Insert protocols of .url files you want to index. Protocols should be separated by ';', and should end with "://". (ex>ftp://;mailto://) + インデックスしたい.urlファイルのプロトコルを入力してください。プロトコルは';'で区切られ、"://"で終了する必要があります。(例>ftp://;mailto://) 別のユーザーとして実行 管理者として実行 - Open containing folder - Hide - Open target folder + 保存先のフォルダーを開く + 非表示にする + ターゲットフォルダーを開く プログラム Flow Launcherでプログラムを検索 - Invalid Path + 不正なパス - Customized Explorer - Args - 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. - Enter the customized args you want to add for your customized explorer. %s for parent directory, %f for full path (which only works for win32). Check the explorer's website for details. + カスタムされたエクスプローラー + 引数 + エクスプローラーで使用したい環境変数を入力することで、コンテナフォルダを開く際に使用するエクスプローラをカスタマイズできます。 環境変数が利用可能かどうかをテストするために、コマンドプロンプトを使用すると便利です。 + カスタマイズされたエクスプローラに追加したいカスタムの引数を入力します。 %s は親ディレクトリ、 %f はフルパス (win32でのみ動作します)です。 詳細についてはエクスプローラのウェブサイトをご覧ください。 - 成功しまし - Error - Successfully disabled this program from displaying in your query - This app is not intended to be run as administrator - Unable to run {0} + 成功しました + エラー + このプログラムは検索結果に表示されなくなりました + このアプリは管理者として実行されることを想定されていません + {0} を実行できません diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 7c30c0c96..0258a10d2 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -31,7 +31,7 @@ namespace Flow.Launcher.Plugin.Program internal static PluginInitContext Context { get; private set; } - private static readonly List emptyResults = new(); + private static readonly List emptyResults = []; private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; private static MemoryCache cache = new(cacheOptions); @@ -84,7 +84,6 @@ namespace Flow.Launcher.Plugin.Program { await _win32sLock.WaitAsync(token); await _uwpsLock.WaitAsync(token); - try { // Collect all UWP Windows app directories @@ -117,7 +116,7 @@ namespace Flow.Launcher.Plugin.Program } }, token); - resultList = resultList.Any() ? resultList : emptyResults; + resultList = resultList.Count != 0 ? resultList : emptyResults; entry.SetSize(resultList.Count); entry.SetSlidingExpiration(TimeSpan.FromHours(8)); @@ -250,14 +249,26 @@ namespace Flow.Launcher.Plugin.Program } await _win32sLock.WaitAsync(); - _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCacheDirectory, new List()); - _win32sCount = _win32s.Count; - _win32sLock.Release(); + try + { + _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCacheDirectory, new List()); + _win32sCount = _win32s.Count; + } + finally + { + _win32sLock.Release(); + } await _uwpsLock.WaitAsync(); - _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCacheDirectory, new List()); - _uwpsCount = _uwps.Count; - _uwpsLock.Release(); + try + { + _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCacheDirectory, new List()); + _uwpsCount = _uwps.Count; + } + finally + { + _uwpsLock.Release(); + } }); Context.API.LogInfo(ClassName, $"Number of preload win32 programs <{_win32sCount}>"); Context.API.LogInfo(ClassName, $"Number of preload uwps <{_uwpsCount}>"); @@ -408,38 +419,46 @@ namespace Flow.Launcher.Plugin.Program return; await _uwpsLock.WaitAsync(); - if (_uwps.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) + var reindexUwps = true; + try { + reindexUwps = _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)); + } + finally + { _uwpsLock.Release(); + } - // Reindex UWP programs + // Reindex UWP programs + if (reindexUwps) + { _ = Task.Run(IndexUwpProgramsAsync); return; } - else - { - _uwpsLock.Release(); - } await _win32sLock.WaitAsync(); - if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) + var reindexWin32s = true; + try { + reindexWin32s = _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); - return; } - else + finally { _win32sLock.Release(); } + + // Reindex Win32 programs + if (reindexWin32s) + { + _ = Task.Run(IndexWin32ProgramsAsync); + return; + } } public static void StartProcess(Func runProcess, ProcessStartInfo info) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs index b89a2a6ba..2a6a3e987 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/Commands/ProgramSettingDisplay.cs @@ -19,18 +19,30 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands internal static async Task DisplayAllProgramsAsync() { await Main._win32sLock.WaitAsync(); - var win32 = Main._win32s + try + { + 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(); + ProgramSetting.ProgramSettingDisplayList.AddRange(win32); + } + finally + { + Main._win32sLock.Release(); + } await Main._uwpsLock.WaitAsync(); - var uwp = Main._uwps + try + { + var uwp = Main._uwps .Where(t1 => !ProgramSetting.ProgramSettingDisplayList.Any(x => x.UniqueIdentifier == t1.UniqueIdentifier)) .Select(x => new ProgramSource(x)); - ProgramSetting.ProgramSettingDisplayList.AddRange(uwp); - Main._uwpsLock.Release(); + ProgramSetting.ProgramSettingDisplayList.AddRange(uwp); + } + finally + { + Main._uwpsLock.Release(); + } } internal static async Task SetProgramSourcesStatusAsync(List selectedProgramSourcesToDisable, bool status) @@ -44,24 +56,36 @@ namespace Flow.Launcher.Plugin.Program.Views.Commands } await Main._win32sLock.WaitAsync(); - foreach (var program in Main._win32s) + try { - if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status)) + foreach (var program in Main._win32s) { - program.Enabled = status; + if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status)) + { + program.Enabled = status; + } } } - Main._win32sLock.Release(); + finally + { + Main._win32sLock.Release(); + } await Main._uwpsLock.WaitAsync(); - foreach (var program in Main._uwps) + try { - if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status)) + foreach (var program in Main._uwps) { - program.Enabled = status; + if (selectedProgramSourcesToDisable.Any(x => x.UniqueIdentifier == program.UniqueIdentifier && program.Enabled != status)) + { + program.Enabled = status; + } } } - Main._uwpsLock.Release(); + finally + { + Main._uwpsLock.Release(); + } } internal static void StoreDisabledInSettings() diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Shell/Languages/ja.xaml index 440d33697..475a6b4fb 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Shell/Languages/ja.xaml @@ -1,20 +1,20 @@  - Replace Win+R - Close Command Prompt after pressing any key - Press any key to close this window... - Do not close Command Prompt after command execution - Always run as administrator - Use Windows Terminal - Run as different user - Shell - Allows to execute system commands from Flow Launcher - this command has been executed {0} times - execute command through command shell + Win+Rを置き換え + 任意のキーを押して、実行後のコマンドプロンプトを閉じる + このウィンドウを閉じるには、任意のキーを押してください… + コマンド実行後にコマンドプロンプトを閉じない + 常に管理者として実行 + Windows ターミナルを使用する + 別のユーザーとして実行 + シェル + Flow Launcherからシステムコマンドを実行できます + このコマンドは {0} 回実行されました + コマンドシェル経由でコマンドを実行する 管理者として実行 - Copy the command - Only show number of most used commands: - Command not found: {0} - Error running the command: {0} + コマンドをコピー + コマンド履歴に表示されるコマンドの最大数: + コマンドが見つかりません: {0} + コマンド実行中にエラーが発生しました: {0} 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 8e54e1894..44fc9a8cf 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj +++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj @@ -58,7 +58,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml index 398c39c9f..00aa91fb9 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml @@ -8,12 +8,12 @@ シャットダウン 再起動 - Restart With Advanced Boot Options - Log Off/Sign Out - Lock - Sleep - Hibernate - Index Option + 詳細ブートオプションで再起動 + ログオフ / サインアウト + ロック + スリープ + 休止状態 + 検索のオプション ごみ箱を空にする ごみ箱を開く 終了 @@ -21,19 +21,19 @@ Flow Launcherを再起動する 設定 プラグインデータのリロード - Check For Update - Open Log Location - Flow Launcher Tips - Flow Launcher UserData Folder - Toggle Game Mode - Set the Flow Launcher Theme + 更新を確認 + ログの場所を開く + Flow Launcher のヒント + Flow Launcher のユーザーデータフォルダー + ゲームモードの切り替え + Flow Launcher のテーマを設定 編集 コンピュータをシャットダウンする コンピュータを再起動する - Restart the computer with Advanced Boot Options for Safe and Debugging modes, as well as other options + セーフモードおよびデバッグモードやその他のオプションを使用するため、コンピュータを再起動して詳細ブートオプションを表示します ログオフ このコンピュータをロックする Flow Launcherを終了する @@ -42,36 +42,36 @@ スリープ ゴミ箱を空にする ごみ箱を開く - Indexing Options - Hibernate computer - Save all Flow Launcher settings - Refreshes plugin data with new content - Open Flow Launcher's log location - Check for new Flow Launcher update - Visit Flow Launcher's documentation for more help and how to use tips - Open the location where Flow Launcher's settings are stored - Toggle Game Mode - Quickly change the Flow Launcher theme + インデックスのオプション + コンピューターを休止状態にする + Flow Launcher の全ての設定を保存 + プラグインのデータを再読み込みし、新しいコンテンツを適用する + Flow Launcher のログがある場所を開く + 新しい Flow Launcher の更新を確認する + Flow Launcher のドキュメントを開いて、ヘルプと使い方のヒントを確認する + Flow Launcher の設定が保存されている場所を開く + ゲームモードの切り替え + Flow Launcher のテーマを素早く変更する - 成功しまし - All Flow Launcher settings saved - Reloaded all applicable plugin data - Are you sure you want to shut the computer down? + 成功 + Flow Launcher のすべての設定が保存されました + 該当するすべてのプラグインデータを再読み込みしました + 本当にコンピューターをシャットダウンしますか? 本当にコンピューターを再起動しますか? 高度な起動オプションでコンピューターを再起動しますか? 本当にログオフしますか? - Error - Failed to empty the recycle bin. This might happen if:{0}- Some items are currently in use{0}- Some items can't be deleted due to permissions{0}Please close any applications that might be using these files and try again. + エラー + ゴミ箱を空にできませんでした。以下の原因が考えられます:{0}ー 現在使用中のアイテムがある{0}- 権限が原因で削除できないアイテムがある{0}ファイルを使用しているアプリケーションを終了してから、再度お試しください。 - Command Keyword Setting - Custom Command Keyword - Enter a keyword to search for command: {0}. This keyword is used to match your query. - Command Keyword + コマンドキーワードの設定 + カスタムのコマンドキーワード + コマンド: {0}を検索するキーワードを入力してください。このキーワードはクエリに一致するために使用されます。 + コマンドキーワード リセット 確認 キャンセル - Please enter a non-empty command keyword + 空でないコマンドキーワードを入力してください システムコマンド システム関連のコマンドを提供します。例:シャットダウン、ロック、設定など diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml index 69746e836..0313a7918 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml @@ -69,11 +69,11 @@ 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.Url/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml index 532ff793d..4275713a1 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/ja.xaml @@ -1,9 +1,9 @@  - Open search in: - New Window - New Tab + 検索を開く: + 新しいウィンドウ + 新しいタブ 次のURLを開く:{0} 次のURLを開くことができません:{0} @@ -11,7 +11,7 @@ URL 入力したURLをFlow Launcherから開くプラグインです。 - Please set your browser path: - Choose + ブラウザのパスを設定してください: + 選択 Application(*.exe)|*.exe|All files|*.* diff --git a/Plugins/Flow.Launcher.Plugin.Url/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Url/Languages/ru.xaml index 5110f65ef..15c1eeadb 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Url/Languages/ru.xaml @@ -2,8 +2,8 @@ Open search in: - New Window - New Tab + Новое окно + Новая вкладка Open url:{0} Can't open url:{0} diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml index 16c5fb3e9..ebc7d6196 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml @@ -1,37 +1,38 @@  - Search Source Setting - Open search in: - New Window - New Tab - Set browser from path: - Choose + 検索ソース設定 + 検索を開く: + 新しいウィンドウ + 新しいタブ + 以下のパスからブラウザーを設定: + 選択 削除 編集 追加 - Enabled - Private Mode - Enabled - Disabled - Confirm + 有効化 + プライベートモード + 有効 + 無効 + 確認 キーワード URL 検索 - Use Search Query Autocomplete - Autocomplete Data from: + 検索クエリのサジェストを有効にする + サジェストデータの情報源: web検索を選択してください - Are you sure you want to delete {0}? - If you want to add a search for a particular website to Flow, first enter a dummy text string in the search bar of that website, and launch the search. Now copy the contents of the browser's address bar, and paste it in the URL field below. Replace your test string with {q}. For example, if you search for casino on Netflix, its address bar reads - https://www.netflix.com/search?q=Casino + {0} を削除してもよろしいですか? + 特定のウェブサイトでの検索をFlowに追加したい場合、まず、 ウェブサイトの検索バーにダミーの文字列を入力して検索を開始します。 次に、ブラウザのアドレスバーの内容をコピーし、下のURLフィールドに貼り付けます。 テスト文字列を {q}に置き換えます。例えば、Netflixでカジノを検索すると、アドレスバーは以下のようになります + https://www.netflix.com/search?q=Casino - Now copy this entire string and paste it in the URL field below. - Then replace casino with {q}. - Thus, the generic formula for a search on Netflix is https://www.netflix.com/search?q={q} + コピーしたURLを下のURL欄に貼り付けてください。 + 次に、casinoという文字列を{q}に置き換えます。 + すると、Netflixで検索を行うためのURLは以下のようになります +https://www.netflix.com/search?q={q} - Copy URL - Copy search URL to clipboard + URL をコピー + 検索URLをクリップボードにコピーする タイトル @@ -44,7 +45,7 @@ キーワードを入力してください URLを入力してください キーワードはすでに存在します。違うキーワードを入力してください - 成功しまし + 成功しました Hint: You do not need to place custom images in this directory, if Flow's version is updated they will be lost. Flow will automatically copy any images outside of this directory across to WebSearch's custom image location. Web検索 diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml index 67435b5b9..6539f9617 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml @@ -3,25 +3,25 @@ Search Source Setting Open search in: - New Window - New Tab + Новое окно + Новая вкладка Установить браузер по пути: Выберите Удалить Редактировать Добавить - Enabled + Включено Приватный режим - Enabled + Включено Отключён - Confirm + Подтвердить Action Keyword URL - Search + Поиск Use Search Query Autocomplete Autocomplete Data from: Please select a web search - Are you sure you want to delete {0}? + Вы уверены, что хотите удалить {0}? If you want to add a search for a particular website to Flow, first enter a dummy text string in the search bar of that website, and launch the search. Now copy the contents of the browser's address bar, and paste it in the URL field below. Replace your test string with {q}. For example, if you search for casino on Netflix, its address bar reads https://www.netflix.com/search?q=Casino @@ -34,13 +34,13 @@ Copy search URL to clipboard - Title + Название Состояние - Select Icon - Icon + Выбрать иконку + Иконка Отменить Invalid web search - Please enter a title + Пожалуйста, укажите название Please enter an action keyword Please enter a URL Action keyword already exists, please enter a different one diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx index 6625a42dd..3a2f991a1 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ja-JP.resx @@ -251,10 +251,10 @@ アプリ - クロックとリージョン + 時計とリージョン - Control Panel + コントロールパネル Cortana @@ -456,7 +456,7 @@ Area Personalization - + コマンド The command to direct start a setting @@ -468,7 +468,7 @@ Area Privacy - Control Panel + コントロールパネル Type of the setting is a "(legacy) Control Panel setting" @@ -1117,7 +1117,7 @@ Area Control Panel (legacy settings) - + パスワード password.cpl @@ -1667,7 +1667,7 @@ Area UserAccounts - Windows Insider Program + Windows Insider プログラム Area UpdateAndSecurity @@ -2314,7 +2314,7 @@ View all problem reports - 16-Bit Application Support + 16 ビットアプリケーションのサポート Set up dialling rules @@ -2326,10 +2326,10 @@ Give administrative rights to a domain user - Choose when to turn off display + 表示をオフにするタイミングを選択 - Move the pointer with the keypad using MouseKeys + マウスキーを使用してキーパッドでポインタを移動する Change Windows SideShow-compatible device settings @@ -2338,16 +2338,16 @@ Adjust commonly used mobility settings - Change text-to-speech settings + テキスト読み上げの設定を変更 - Set the time and date + 時刻と日付を設定 - Change location settings + 位置情報の設定を変更 - Change mouse settings + マウスの設定を変更 Manage Storage Spaces @@ -2362,46 +2362,46 @@ Change system sounds - Adjust ClearType text + ClearTypeテキストを調整 - Turn screen saver on or off + スクリーンセーバーのオン/オフを切り替え - Find and fix windows update problems + Windows Update の問題を見つけて修正 - Change Bluetooth settings + Bluetooth 設定の変更 - Connect to a network + ネットワークに接続 - Change the search provider in Internet Explorer + Internet Explorer の検索プロバイダを変更する Join a domain - Add a device + 端末を追加 - Find and fix problems with Windows Search + Windows検索の問題を見つけて解決 - Choose a power plan + 電源プランを選択 Change how the mouse pointer looks when it’s moving - Uninstall a program + プログラムのアンインストール Create and format hard disk partitions - Change date, time or number formats + 日付、時刻、数の書式を変更 Change PC wake-up settings @@ -2416,10 +2416,10 @@ Manage advanced sharing settings - Change battery settings + バッテリー設定の変更 - Rename this computer + このコンピューターの名前を変更 Lock or unlock the taskbar @@ -2431,7 +2431,7 @@ Change the time zone - Start speech recognition + 音声認識を開始 View installed updates @@ -2458,34 +2458,34 @@ Restore data, files or computer from backup (Windows 7) - Set your default programs + 既定のプログラムを設定 Set up a broadband connection - Calibrate the screen for pen or touch input + ペンまたはタッチ入力の画面をキャリブレーション Manage user certificates - Schedule tasks + タスクのスケジュール - Ignore repeated keystrokes using FilterKeys + フィルタキーを使用して繰り返しのキー入力を無視 - Find and fix bluescreen problems + ブルースクリーンの問題を見つけて修正 Hear a tone when keys are pressed - Delete browsing history + 閲覧履歴を削除 - Change what the power buttons do + 電源ボタンの動作を変更 Create standard user account @@ -2494,21 +2494,21 @@ Take speech tutorials - View system resource usage in Task Manager + タスク マネージャーでシステム リソースの使用状況を表示 - Create an account + アカウントを新規作成 - Get more features with a new edition of Windows + Windowsの新しいエディションでより多くの機能を入手 - Control Panel + コントロールパネル TaskLink - Unknown + 不明 \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.tr-TR.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.tr-TR.resx index d920e7550..746499a42 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.tr-TR.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.tr-TR.resx @@ -1773,13 +1773,13 @@ Sorunları bul ve düzelt - Change settings for content received using Tap and send + Dokun ve gönder kullanılarak alınan içerik için ayarları değiştir Medya veya cihazlar için varsayılan ayarları değiştir - Print the speech reference card + Konuşma referans kartını yazdır Ekran rengini kalibre et @@ -1815,13 +1815,13 @@ Fare düğmelerini özelleştir - Set tablet buttons to perform certain tasks + Belirli görevleri gerçekleştirmek için tablet düğmelerini ayarla Yüklü yazı tiplerini görüntüle - Change the way currency is displayed + Para biriminin görüntülenme şeklini değiştirme Grup ilkesini düzenle @@ -1908,7 +1908,7 @@ Güvenilirlik geçmişini görüntüle - Access RemoteApp and desktops + RemoteApp ve masaüstlerine eriş ODBC veri kaynaklarını ayarla @@ -1926,7 +1926,7 @@ Microsoft Pinyin SimpleFast Seçenekleri - Change what closing the lid does + Güç düğmesiyle kapatmanın ne yapacağını değiştirin Gereksiz animasyonları kapat @@ -1935,16 +1935,16 @@ Geri yükleme noktası oluştur - Turn off automatic window arrangement + Otomatik pencere düzenlemesini kapatın Sorun Giderme Geçmişi - Diagnose your computer's memory problems + Bilgisayarınızın bellek sorunlarını teşhis edin - View recommended actions to keep Windows running smoothly + Windows'un sorunsuz çalışmasını sağlamak için önerilen eylemleri görüntüleyin İmleç yanıp sönme hızını değiştir @@ -1956,22 +1956,22 @@ Parola sıfırlama diski oluştur - Configure advanced user profile properties + Gelişmiş kullanıcı profili özelliklerini yapılandır - Start or stop using AutoPlay for all media and devices + Tüm medya ve aygıtlar için Otomatik Kullan'ı etkinleştir veya devre dışı bırak - Change Automatic Maintenance settings + Otomatik Bakım ayarlarını değiştir Açmak için tek veya çift tıkla - Select users who can use remote desktop + Uzak masaüstünü kullanabilecek kullanıcıları seç - Show which programs are installed on your computer + Bilgisayarımda hangi programların yüklü olduğunu göster Bilgisayarınıza uzaktan erişime izin ver @@ -1986,22 +1986,22 @@ Klavyenin çalışma şeklini değiştir - Automatically adjust for daylight saving time + Gün ışığından yararlanma saatine göre otomatik ayarla - Change the order of Windows SideShow gadgets + Windows SideShow araçlarının sırasını değiştir Klavye durumunu kontrol et - Control the computer without the mouse or keyboard + Bilgisayarı fare veya klavye olmadan kontrol et Bir programı değiştir veya kaldır - Change multi-touch gesture settings + Çoklu dokunma hareketi ayarlarını değiştir ODBC veri kaynaklarını ayarla (64-bit) @@ -2016,7 +2016,7 @@ Görev çubuğunda benzer pencereleri gruplama - Change Windows SideShow settings + Windows SideShow ayarlarını değiştir Video için sesli açıklama kullan @@ -2058,13 +2058,13 @@ Çevrim dışı dosyaları yönet - Review your computer's status and resolve issues + Bilgisayarınızın durumunu gözden geçirin ve sorunları çözün Microsoft ChangJie Ayarları - Replace sounds with visual cues + Sesleri görsel ipuçlarıyla değiştirin Geçici İnternet dosyası ayarlarını değiştir @@ -2082,7 +2082,7 @@ Kurtarma anahtarınızı yedekleyin - Save backup copies of your files with File History + Dosya Geçmişi ile dosyalarınızın yedek kopyalarını kaydedin Geçerli erişilebilirlik ayarlarını görüntüle @@ -2103,7 +2103,7 @@ Sistem ses seviyesini ayarla - Defragment and optimise your drives + Sürücülerinizi birleştirin ve optimize edin ODBC veri kaynaklarını ayarla (32-bit) @@ -2112,16 +2112,16 @@ Yazı Tipi Ayarlarını Değiştir - Magnify portions of the screen using Magnifier + Büyüteç kullanarak ekranın bazı bölümlerini büyütme - Change the file type associated with a file extension + Bir dosya uzantısı ile ilişkili dosya türünü değiştir Olay günlüklerini görüntüle - Manage Windows Credentials + Windows Kimlik Bilgilerini Yönet Bir mikrofon ayarla @@ -2173,10 +2173,10 @@ Fare tıklama ayarlarını değiştir - Change advanced colour management settings for displays, scanners and printers + Ekranlar, tarayıcılar ve yazıcılar için gelişmiş renk yönetimi ayarlarını değiştirme - Let Windows suggest Ease of Access settings + Windows'un Erişim Kolaylığı ayarlarını önermesine izin verin Gereksiz dosyaları silerek disk alanını temizle @@ -2188,7 +2188,7 @@ Özel Karakter Düzenleyici - Record steps to reproduce a problem + Bir sorunu yeniden üretmek için adımları kaydedin Windows'un görünümünü ve performansını ayarla @@ -2209,7 +2209,7 @@ Windows'un arama şeklini değiştir - Set flicks to perform certain tasks + Belirli görevleri gerçekleştirmek için fiskeleri ayarla Hesap türünü değiştir @@ -2239,13 +2239,13 @@ Bağlantıları nasıl açacağınızı seçin - Allow Remote Assistance invitations to be sent from this computer + Bu bilgisayara Uzaktan Yardım bağlantılarına izin ver Görev Yöneticisi - Turn flicks on or off + Fiskeleri açın veya kapatın Bir dil ekleyin @@ -2254,7 +2254,7 @@ Ağ durumunu ve görevlerini görüntüle - Turn Magnifier on or off + Büyüteci aç veya kapat Bu bilgisayarın adına bakın @@ -2320,22 +2320,22 @@ Arama kurallarını ayarla - Enable or disable session cookies + Oturum çerezlerini etkinleştir veya devre dışı bırak - Give administrative rights to a domain user + Bir etki alanı kullanıcısına yönetici hakları verme - Choose when to turn off display + Ekranın ne zaman kapatılacağını seçin - Move the pointer with the keypad using MouseKeys + MouseKeys kullanarak imleci tuş takımıyla hareket ettirme - Change Windows SideShow-compatible device settings + Windows SideShow uyumlu cihaz ayarlarını değiştir - Adjust commonly used mobility settings + Sık kullanılan mobilite ayarlarını yapın Metinden sese ayarlarını değiştir @@ -2362,7 +2362,7 @@ Sistem seslerini değiştir - Adjust ClearType text + ClearType metnini ayarla Ekran koruyucuyu aç/kapat @@ -2392,7 +2392,7 @@ Bir güç planı seç - Change how the mouse pointer looks when it’s moving + Fare işaretçisinin hareket ederken nasıl görüneceğini değiştir Bir program kaldır @@ -2443,7 +2443,7 @@ Dosya ve klasörler için arama seçeneklerini değiştir - Adjust settings before giving a presentation + Sunum yapmadan önce ayarları yapın Bir belgeyi veya resmi tara @@ -2464,7 +2464,7 @@ Geniş bant bağlantısı kur - Calibrate the screen for pen or touch input + Kalem veya dokunmatik giriş için ekranı kalibre edin Kullanıcı sertifikalarını yönet @@ -2473,7 +2473,7 @@ Görevleri planla - Ignore repeated keystrokes using FilterKeys + Filtre Tuşları kullanarak tekrarlanan tuş vuruşlarını yok say Mavi ekran sorunlarını bul ve düzelt diff --git a/appveyor.yml b/appveyor.yml index 911e30423..f95b8dc08 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: '2.0.0.{build}' +version: '2.0.1.{build}' # Do not build on tags because we create a release on merge to master. Otherwise will upload artifacts twice changing the hash, as well as triggering duplicate GitHub release action & NuGet deployments. skip_tags: true From bfd10f690324af0a30b7767817e04da8c4db3b47 Mon Sep 17 00:00:00 2001 From: dcog989 Date: Mon, 22 Sep 2025 13:37:22 +0100 Subject: [PATCH 39/73] Crash when opening non-existent file --- Flow.Launcher/PublicAPIInstance.cs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 6a8ee40f9..731c329e2 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -412,6 +412,14 @@ namespace Flow.Launcher private void OpenUri(Uri uri, bool? inPrivate = null, bool forceBrowser = false) { + if (uri.IsFile) + { + if (!File.Exists(uri.LocalPath) && !Directory.Exists(uri.LocalPath)) + { + ShowMsgError(GetTranslation("errorTitle"), $"File or directory not found: {uri.LocalPath}"); + return; + } + } if (forceBrowser || uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps) { var browserInfo = _settings.CustomBrowser; @@ -441,13 +449,19 @@ namespace Flow.Launcher } else { - Process.Start(new ProcessStartInfo() + try { - FileName = uri.AbsoluteUri, - UseShellExecute = true - })?.Dispose(); - - return; + Process.Start(new ProcessStartInfo() + { + FileName = uri.AbsoluteUri, + UseShellExecute = true + })?.Dispose(); + } + catch (Exception e) + { + LogException(ClassName, $"Failed to open: {uri.AbsoluteUri}", e); + ShowMsgError(GetTranslation("errorTitle"), e.Message); + } } } From 71b8144c3c428f4ffe2ebbbfc3544a0bf5afbc69 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 22 Sep 2025 20:55:36 +0800 Subject: [PATCH 40/73] Add translations & Improve code quality --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/PublicAPIInstance.cs | 12 +++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 626fe1385..561bb277e 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -590,6 +590,7 @@ Error An error occurred while opening the folder. {0} An error occurred while opening the URL in the browser. Please check your Default Web Browser configuration in the General section of the settings window + File or directory not found: {0} Please wait... diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 731c329e2..cbd793dc8 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; @@ -412,14 +412,12 @@ namespace Flow.Launcher private void OpenUri(Uri uri, bool? inPrivate = null, bool forceBrowser = false) { - if (uri.IsFile) + if (uri.IsFile && !File.Exists(uri.LocalPath) && !Directory.Exists(uri.LocalPath)) { - if (!File.Exists(uri.LocalPath) && !Directory.Exists(uri.LocalPath)) - { - ShowMsgError(GetTranslation("errorTitle"), $"File or directory not found: {uri.LocalPath}"); - return; - } + ShowMsgError(GetTranslation("errorTitle"), string.Format(GetTranslation("fileNotFoundError"), uri.LocalPath)); + return; } + if (forceBrowser || uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps) { var browserInfo = _settings.CustomBrowser; From 763fee0c1400ef3cf3b1cfb49cd0e54ec5c0ce7b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 22 Sep 2025 20:58:22 +0800 Subject: [PATCH 41/73] Add new helper method & Improve code quality --- Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs | 10 ++++++++++ Flow.Launcher/PublicAPIInstance.cs | 11 +++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs index 6c506cfc0..3af57f00d 100644 --- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs +++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs @@ -150,6 +150,16 @@ namespace Flow.Launcher.Plugin.SharedCommands return File.Exists(filePath); } + /// + /// Checks if a file or directory exists + /// + /// + /// + public static bool FileOrLocationExists(this string path) + { + return LocationExists(path) || FileExists(path); + } + /// /// Open a directory window (using the OS's default handler, usually explorer) /// diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index cbd793dc8..b4c3aa92b 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -74,7 +74,6 @@ namespace Flow.Launcher _mainVM.ChangeQueryText(query, requery); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "")] public void RestartApp() { _mainVM.Hide(); @@ -179,7 +178,7 @@ namespace Flow.Launcher Clipboard.SetFileDropList(paths); }); - + if (exception == null) { if (showDefaultNotification) @@ -218,7 +217,7 @@ namespace Flow.Launcher { LogException(nameof(PublicAPIInstance), "Failed to copy text to clipboard", exception); ShowMsgError(GetTranslation("failedToCopy")); - } + } } } @@ -327,7 +326,7 @@ namespace Flow.Launcher ((PluginJsonStorage)_pluginJsonStorages[type]).Save(); } - + public void OpenDirectory(string directoryPath, string fileNameOrFilePath = null) { try @@ -412,7 +411,7 @@ namespace Flow.Launcher private void OpenUri(Uri uri, bool? inPrivate = null, bool forceBrowser = false) { - if (uri.IsFile && !File.Exists(uri.LocalPath) && !Directory.Exists(uri.LocalPath)) + if (uri.IsFile && !FilesFolders.FileOrLocationExists(uri.LocalPath)) { ShowMsgError(GetTranslation("errorTitle"), string.Format(GetTranslation("fileNotFoundError"), uri.LocalPath)); return; @@ -493,7 +492,7 @@ namespace Flow.Launcher OpenUri(appUri); } - public void ToggleGameMode() + public void ToggleGameMode() { _mainVM.ToggleGameMode(); } From fbc88bb4cdea088751578e5c749d2a20c499a722 Mon Sep 17 00:00:00 2001 From: Spencer Stream Date: Mon, 22 Sep 2025 19:40:01 -0500 Subject: [PATCH 42/73] Add ini-parser package to Infrastructure project --- Flow.Launcher.Core/packages.lock.json | 8 +++++++- .../Flow.Launcher.Infrastructure.csproj | 1 + Flow.Launcher.Infrastructure/packages.lock.json | 6 ++++++ Flow.Launcher/packages.lock.json | 8 +++++++- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Core/packages.lock.json b/Flow.Launcher.Core/packages.lock.json index b7a00d94d..373cdcd15 100644 --- a/Flow.Launcher.Core/packages.lock.json +++ b/Flow.Launcher.Core/packages.lock.json @@ -83,6 +83,11 @@ "resolved": "1.0.0", "contentHash": "nwbZAYd+DblXAIzlnwDSnl0CiCm8jWLfHSYnoN4wYhtIav6AegB3+T/vKzLbU2IZlPB8Bvl8U3NXpx3eaz+N5w==" }, + "ini-parser": { + "type": "Transitive", + "resolved": "2.5.2", + "contentHash": "hp3gKmC/14+6eKLgv7Jd1Z7OV86lO+tNfOXr/stQbwmRhdQuXVSvrRAuAe7G5+lwhkov0XkqZ8/bn1PYWMx6eg==" + }, "InputSimulator": { "type": "Transitive", "resolved": "1.0.4", @@ -263,7 +268,8 @@ "NLog.OutputDebugString": "[6.0.4, )", "SharpVectors.Wpf": "[1.8.5, )", "System.Drawing.Common": "[7.0.0, )", - "ToolGood.Words.Pinyin": "[3.1.0.3, )" + "ToolGood.Words.Pinyin": "[3.1.0.3, )", + "ini-parser": "[2.5.2, )" } }, "flow.launcher.plugin": { diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index 5b4eaf893..d0c9ebdda 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -60,6 +60,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Flow.Launcher.Infrastructure/packages.lock.json b/Flow.Launcher.Infrastructure/packages.lock.json index 47c94d5f6..a1aea7f88 100644 --- a/Flow.Launcher.Infrastructure/packages.lock.json +++ b/Flow.Launcher.Infrastructure/packages.lock.json @@ -29,6 +29,12 @@ "resolved": "6.9.3", "contentHash": "1CUGgFdyECDKgi5HaUBhdv6k+VG9Iy4OCforGfHyar3xQXAJypZkzymgKtWj/4SPd6nSG0Qi7NH71qHrDSZLaA==" }, + "ini-parser": { + "type": "Direct", + "requested": "[2.5.2, )", + "resolved": "2.5.2", + "contentHash": "hp3gKmC/14+6eKLgv7Jd1Z7OV86lO+tNfOXr/stQbwmRhdQuXVSvrRAuAe7G5+lwhkov0XkqZ8/bn1PYWMx6eg==" + }, "InputSimulator": { "type": "Direct", "requested": "[1.0.4, )", diff --git a/Flow.Launcher/packages.lock.json b/Flow.Launcher/packages.lock.json index c90db6b0c..4af9894ce 100644 --- a/Flow.Launcher/packages.lock.json +++ b/Flow.Launcher/packages.lock.json @@ -204,6 +204,11 @@ "resolved": "1.11.42", "contentHash": "LDc1bEfF14EY2DZzak4xvzWvbpNXK3vi1u0KQbBpLUN4+cx/VrvXhgCAMSJhSU5vz0oMfW9JZIR20vj/PkDHPA==" }, + "ini-parser": { + "type": "Transitive", + "resolved": "2.5.2", + "contentHash": "hp3gKmC/14+6eKLgv7Jd1Z7OV86lO+tNfOXr/stQbwmRhdQuXVSvrRAuAe7G5+lwhkov0XkqZ8/bn1PYWMx6eg==" + }, "InputSimulator": { "type": "Transitive", "resolved": "1.0.4", @@ -863,7 +868,8 @@ "NLog.OutputDebugString": "[6.0.4, )", "SharpVectors.Wpf": "[1.8.5, )", "System.Drawing.Common": "[7.0.0, )", - "ToolGood.Words.Pinyin": "[3.1.0.3, )" + "ToolGood.Words.Pinyin": "[3.1.0.3, )", + "ini-parser": "[2.5.2, )" } }, "flow.launcher.plugin": { From 90c73e5e3df07bd1fcee73d9e423017456d541ab Mon Sep 17 00:00:00 2001 From: Spencer Stream Date: Mon, 22 Sep 2025 19:40:58 -0500 Subject: [PATCH 43/73] Support .url file icons --- .../Image/ThumbnailReader.cs | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs index 4ce0df026..dbe6a694b 100644 --- a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs +++ b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs @@ -1,13 +1,14 @@ using System; -using System.Runtime.InteropServices; using System.IO; +using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop; using System.Windows.Media.Imaging; +using IniParser; using Windows.Win32; using Windows.Win32.Foundation; -using Windows.Win32.UI.Shell; using Windows.Win32.Graphics.Gdi; +using Windows.Win32.UI.Shell; namespace Flow.Launcher.Infrastructure.Image { @@ -35,9 +36,21 @@ namespace Flow.Launcher.Infrastructure.Image private static readonly HRESULT S_PATHNOTFOUND = (HRESULT)0x8004B205; + private const string UrlExtension = ".url"; + public static BitmapSource GetThumbnail(string fileName, int width, int height, ThumbnailOptions options) { - HBITMAP hBitmap = GetHBitmap(Path.GetFullPath(fileName), width, height, options); + HBITMAP hBitmap; + + var extension = Path.GetExtension(fileName)?.ToLowerInvariant(); + if (extension is UrlExtension) + { + hBitmap = GetHBitmapForUrlFile(fileName, width, height, options); + } + else + { + hBitmap = GetHBitmap(Path.GetFullPath(fileName), width, height, options); + } try { @@ -108,5 +121,30 @@ namespace Flow.Launcher.Infrastructure.Image return hBitmap; } + + private static unsafe HBITMAP GetHBitmapForUrlFile(string fileName, int width, int height, ThumbnailOptions options) + { + HBITMAP hBitmap; + + try + { + var parser = new FileIniDataParser(); + var data = parser.ReadFile(fileName); + var urlSection = data["InternetShortcut"]; + + var iconPath = urlSection?["IconFile"]; + if (string.IsNullOrEmpty(iconPath)) + { + throw new FileNotFoundException(); + } + hBitmap = GetHBitmap(Path.GetFullPath(iconPath), width, height, options); + } + catch + { + hBitmap = GetHBitmap(Path.GetFullPath(fileName), width, height, options); + } + + return hBitmap; + } } } From c293a273ca5b7839d715e7a94cd436c4a01ab7c1 Mon Sep 17 00:00:00 2001 From: Spencer Stream Date: Mon, 22 Sep 2025 21:53:54 -0500 Subject: [PATCH 44/73] Fix nitpick on extension string comparison --- Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs index dbe6a694b..68940ff6a 100644 --- a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs +++ b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs @@ -42,8 +42,8 @@ namespace Flow.Launcher.Infrastructure.Image { HBITMAP hBitmap; - var extension = Path.GetExtension(fileName)?.ToLowerInvariant(); - if (extension is UrlExtension) + var extension = Path.GetExtension(fileName); + if (string.Equals(extension, UrlExtension, StringComparison.OrdinalIgnoreCase)) { hBitmap = GetHBitmapForUrlFile(fileName, width, height, options); } From 130033cf4b8f302537c969fba4a4529b2b93f0d2 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Tue, 23 Sep 2025 12:22:46 +0800 Subject: [PATCH 45/73] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs index 68940ff6a..c942488c4 100644 --- a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs +++ b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs @@ -135,7 +135,7 @@ namespace Flow.Launcher.Infrastructure.Image var iconPath = urlSection?["IconFile"]; if (string.IsNullOrEmpty(iconPath)) { - throw new FileNotFoundException(); + throw new FileNotFoundException("Icon file not specified in Internet shortcut (.url) file."); } hBitmap = GetHBitmap(Path.GetFullPath(iconPath), width, height, options); } From 49d5cd36df9bb788e1899cfbe61dbd60fa0b17c1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 23 Sep 2025 12:24:44 +0800 Subject: [PATCH 46/73] Catch exception --- Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs index c942488c4..9f38a64df 100644 --- a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs +++ b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs @@ -141,7 +141,15 @@ namespace Flow.Launcher.Infrastructure.Image } catch { - hBitmap = GetHBitmap(Path.GetFullPath(fileName), width, height, options); + try + { + hBitmap = GetHBitmap(Path.GetFullPath(fileName), width, height, options); + } + catch (System.Exception ex) + { + // Handle other exceptions + throw new InvalidOperationException("Failed to get thumbnail", ex); + } } return hBitmap; From 486522445889ac273122b43f3e515f312f06dde1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 23 Sep 2025 14:09:21 +0800 Subject: [PATCH 47/73] Fix format --- Flow.Launcher/Flow.Launcher.csproj | 42 ++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index a99d4d8c2..c486023d0 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -40,11 +40,49 @@ - + - + From d87650de08357bbbf1cc621718dff34038770998 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 23 Sep 2025 16:21:09 +0800 Subject: [PATCH 48/73] Use Flow.Launcher.Localization to improve code quality --- Flow.Launcher/ActionKeywords.xaml.cs | 4 +-- Flow.Launcher/App.xaml.cs | 2 +- .../CustomQueryHotkeySetting.xaml.cs | 2 +- Flow.Launcher/CustomShortcutSetting.xaml.cs | 4 +-- Flow.Launcher/Flow.Launcher.csproj | 6 ++++ Flow.Launcher/Helper/HotKeyMapper.cs | 12 ++++---- Flow.Launcher/HotkeyControl.xaml.cs | 4 +-- Flow.Launcher/HotkeyControlDialog.xaml.cs | 16 ++++------ Flow.Launcher/Languages/en.xaml | 4 ++- Flow.Launcher/MainWindow.xaml.cs | 30 +++++++++---------- Flow.Launcher/PluginUpdateWindow.xaml.cs | 9 ++---- Flow.Launcher/PublicAPIInstance.cs | 30 +++++++++---------- Flow.Launcher/ReleaseNotesWindow.xaml.cs | 4 +-- Flow.Launcher/ReportWindow.xaml.cs | 6 ++-- .../Resources/Pages/WelcomePage5.xaml.cs | 2 +- .../ViewModels/SettingsPaneAboutViewModel.cs | 21 ++++++------- .../SettingsPaneGeneralViewModel.cs | 15 ++++------ .../ViewModels/SettingsPaneHotkeyViewModel.cs | 24 +++++++-------- .../SettingsPanePluginStoreViewModel.cs | 6 ++-- .../ViewModels/SettingsPaneThemeViewModel.cs | 20 ++++++------- Flow.Launcher/ViewModel/MainViewModel.cs | 28 ++++++++--------- Flow.Launcher/ViewModel/PluginViewModel.cs | 13 ++++---- .../ViewModel/SelectBrowserViewModel.cs | 2 +- .../ViewModel/SelectFileManagerViewModel.cs | 7 ++--- Flow.Launcher/packages.lock.json | 6 ++++ 25 files changed, 134 insertions(+), 143 deletions(-) diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index 8e05686c9..a94b265fc 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -47,7 +47,7 @@ namespace Flow.Launcher if (addedActionKeywords.Any(App.API.ActionKeywordAssigned)) { - App.API.ShowMsgBox(App.API.GetTranslation("newActionKeywordsHasBeenAssigned")); + App.API.ShowMsgBox(Localize.newActionKeywordsHasBeenAssigned()); return; } @@ -63,7 +63,7 @@ namespace Flow.Launcher if (sortedOldActionKeywords.SequenceEqual(sortedNewActionKeywords)) { // User just changes the sequence of action keywords - App.API.ShowMsgBox(App.API.GetTranslation("newActionKeywordsSameAsOld")); + App.API.ShowMsgBox(Localize.newActionKeywordsSameAsOld()); } else { diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 8ec11e5ff..58f8438d2 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -276,7 +276,7 @@ namespace Flow.Launcher // but if it fails (permissions, etc) then don't keep retrying // this also gives the user a visual indication in the Settings widget _settings.StartFlowLauncherOnSystemStartup = false; - API.ShowMsgError(API.GetTranslation("setAutoStartFailed"), e.Message); + API.ShowMsgError(Localize.setAutoStartFailed(), e.Message); } } } diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index 2ee08bf85..3bba2c5b8 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -41,7 +41,7 @@ namespace Flow.Launcher if (string.IsNullOrEmpty(Hotkey) && string.IsNullOrEmpty(ActionKeyword)) { - App.API.ShowMsgBox(App.API.GetTranslation("emptyPluginHotkey")); + App.API.ShowMsgBox(Localize.emptyPluginHotkey()); return; } diff --git a/Flow.Launcher/CustomShortcutSetting.xaml.cs b/Flow.Launcher/CustomShortcutSetting.xaml.cs index f4644a267..317d059a1 100644 --- a/Flow.Launcher/CustomShortcutSetting.xaml.cs +++ b/Flow.Launcher/CustomShortcutSetting.xaml.cs @@ -40,14 +40,14 @@ namespace Flow.Launcher { if (string.IsNullOrEmpty(Key) || string.IsNullOrEmpty(Value)) { - App.API.ShowMsgBox(App.API.GetTranslation("emptyShortcut")); + App.API.ShowMsgBox(Localize.emptyShortcut()); return; } // Check if key is modified or adding a new one if (((update && originalKey != Key) || !update) && _hotkeyVm.DoesShortcutExist(Key)) { - App.API.ShowMsgBox(App.API.GetTranslation("duplicateShortcut")); + App.API.ShowMsgBox(Localize.duplicateShortcut()); return; } diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index c486023d0..aa8e95429 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -37,6 +37,7 @@ prompt 4 false + $(NoWarn);FLSG0007 @@ -132,6 +133,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -161,6 +163,10 @@ + + true + + Always diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index 86a68475e..bb1cddc6c 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -61,8 +61,8 @@ internal static class HotKeyMapper string.Format("|HotkeyMapper.SetWithChefKeys|Error registering hotkey: {0} \nStackTrace:{1}", e.Message, e.StackTrace)); - string errorMsg = string.Format(App.API.GetTranslation("registerHotkeyFailed"), hotkeyStr); - string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle"); + string errorMsg = Localize.registerHotkeyFailed(hotkeyStr); + string errorMsgTitle = Localize.MessageBoxTitle(); App.API.ShowMsgBox(errorMsg, errorMsgTitle); } } @@ -87,8 +87,8 @@ internal static class HotKeyMapper e.Message, e.StackTrace, hotkeyStr)); - string errorMsg = string.Format(App.API.GetTranslation("registerHotkeyFailed"), hotkeyStr); - string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle"); + string errorMsg = Localize.registerHotkeyFailed(hotkeyStr); + string errorMsgTitle = Localize.MessageBoxTitle(); App.API.ShowMsgBox(errorMsg, errorMsgTitle); } } @@ -112,8 +112,8 @@ internal static class HotKeyMapper string.Format("|HotkeyMapper.RemoveHotkey|Error removing hotkey: {0} \nStackTrace:{1}", e.Message, e.StackTrace)); - string errorMsg = string.Format(App.API.GetTranslation("unregisterHotkeyFailed"), hotkeyStr); - string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle"); + string errorMsg = Localize.unregisterHotkeyFailed(hotkeyStr); + string errorMsgTitle = Localize.MessageBoxTitle(); App.API.ShowMsgBox(errorMsg, errorMsgTitle); } } diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs index 89bfde349..b920b53a7 100644 --- a/Flow.Launcher/HotkeyControl.xaml.cs +++ b/Flow.Launcher/HotkeyControl.xaml.cs @@ -1,4 +1,4 @@ -using System.Collections.ObjectModel; +using System.Collections.ObjectModel; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; @@ -234,7 +234,7 @@ namespace Flow.Launcher private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) => hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey); - public string EmptyHotkey => App.API.GetTranslation("none"); + public string EmptyHotkey => Localize.none(); public ObservableCollection KeysToDisplay { get; set; } = new(); diff --git a/Flow.Launcher/HotkeyControlDialog.xaml.cs b/Flow.Launcher/HotkeyControlDialog.xaml.cs index c7af8c5b8..740425f8b 100644 --- a/Flow.Launcher/HotkeyControlDialog.xaml.cs +++ b/Flow.Launcher/HotkeyControlDialog.xaml.cs @@ -33,7 +33,7 @@ public partial class HotkeyControlDialog : ContentDialog public EResultType ResultType { get; private set; } = EResultType.Cancel; public string ResultValue { get; private set; } = string.Empty; - public static string EmptyHotkey => App.API.GetTranslation("none"); + public static string EmptyHotkey => Localize.none(); private static bool isOpenFlowHotkey; @@ -41,7 +41,7 @@ public partial class HotkeyControlDialog : ContentDialog { WindowTitle = windowTitle switch { - "" or null => App.API.GetTranslation("hotkeyRegTitle"), + "" or null => Localize.hotkeyRegTitle(), _ => windowTitle }; DefaultHotkey = defaultHotkey; @@ -146,10 +146,7 @@ public partial class HotkeyControlDialog : ContentDialog Alert.Visibility = Visibility.Visible; if (registeredHotkeyData.RemoveHotkey is not null) { - tbMsg.Text = string.Format( - App.API.GetTranslation("hotkeyUnavailableEditable"), - description - ); + tbMsg.Text = Localize.hotkeyUnavailableEditable(description); SaveBtn.IsEnabled = false; SaveBtn.Visibility = Visibility.Collapsed; OverwriteBtn.IsEnabled = true; @@ -158,10 +155,7 @@ public partial class HotkeyControlDialog : ContentDialog } else { - tbMsg.Text = string.Format( - App.API.GetTranslation("hotkeyUnavailableUneditable"), - description - ); + tbMsg.Text = Localize.hotkeyUnavailableUneditable(description); SaveBtn.IsEnabled = false; SaveBtn.Visibility = Visibility.Visible; OverwriteBtn.IsEnabled = false; @@ -175,7 +169,7 @@ public partial class HotkeyControlDialog : ContentDialog if (!CheckHotkeyAvailability(hotkey.Value, true)) { - tbMsg.Text = App.API.GetTranslation("hotkeyUnavailable"); + tbMsg.Text = Localize.hotkeyUnavailable(); Alert.Visibility = Visibility.Visible; SaveBtn.IsEnabled = false; SaveBtn.Visibility = Visibility.Visible; diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 561bb277e..a51782f40 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -209,6 +209,8 @@ Version Website Uninstall + Search delay time: default + Search delay time: {0}ms Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually Fail to remove plugin cache @@ -588,7 +590,7 @@ The specified file manager could not be found. Please check the Custom File Manager setting under Settings > General. Error - An error occurred while opening the folder. {0} + An error occurred while opening the folder. An error occurred while opening the URL in the browser. Please check your Default Web Browser configuration in the General section of the settings window File or directory not found: {0} diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 7b6a0d79b..21cb124b0 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel; using System.Linq; using System.Media; @@ -145,8 +145,8 @@ namespace Flow.Launcher _settings.ReleaseNotesVersion = Constant.Version; // Show release note popup with button App.API.ShowMsgWithButton( - string.Format(App.API.GetTranslation("appUpdateTitle"), Constant.Version), - App.API.GetTranslation("appUpdateButtonContent"), + Localize.appUpdateTitle(Constant.Version), + Localize.appUpdateButtonContent(), () => { Application.Current.Dispatcher.Invoke(() => @@ -753,12 +753,12 @@ namespace Flow.Launcher private void UpdateNotifyIconText() { var menu = _contextMenu; - ((MenuItem)menu.Items[0]).Header = App.API.GetTranslation("iconTrayOpen") + + ((MenuItem)menu.Items[0]).Header = Localize.iconTrayOpen()+ " (" + _settings.Hotkey + ")"; - ((MenuItem)menu.Items[1]).Header = App.API.GetTranslation("GameMode"); - ((MenuItem)menu.Items[2]).Header = App.API.GetTranslation("PositionReset"); - ((MenuItem)menu.Items[3]).Header = App.API.GetTranslation("iconTraySettings"); - ((MenuItem)menu.Items[4]).Header = App.API.GetTranslation("iconTrayExit"); + ((MenuItem)menu.Items[1]).Header = Localize.GameMode(); + ((MenuItem)menu.Items[2]).Header = Localize.PositionReset(); + ((MenuItem)menu.Items[3]).Header = Localize.iconTraySettings(); + ((MenuItem)menu.Items[4]).Header = Localize.iconTrayExit(); } private void InitializeContextMenu() @@ -768,31 +768,31 @@ namespace Flow.Launcher var openIcon = new FontIcon { Glyph = "\ue71e" }; var open = new MenuItem { - Header = App.API.GetTranslation("iconTrayOpen") + " (" + _settings.Hotkey + ")", + Header = Localize.iconTrayOpen()+ " (" + _settings.Hotkey + ")", Icon = openIcon }; var gamemodeIcon = new FontIcon { Glyph = "\ue7fc" }; var gamemode = new MenuItem { - Header = App.API.GetTranslation("GameMode"), + Header = Localize.GameMode(), Icon = gamemodeIcon }; var positionresetIcon = new FontIcon { Glyph = "\ue73f" }; var positionreset = new MenuItem { - Header = App.API.GetTranslation("PositionReset"), + Header = Localize.PositionReset(), Icon = positionresetIcon }; var settingsIcon = new FontIcon { Glyph = "\ue713" }; var settings = new MenuItem { - Header = App.API.GetTranslation("iconTraySettings"), + Header = Localize.iconTraySettings(), Icon = settingsIcon }; var exitIcon = new FontIcon { Glyph = "\ue7e8" }; var exit = new MenuItem { - Header = App.API.GetTranslation("iconTrayExit"), + Header = Localize.iconTrayExit(), Icon = exitIcon }; @@ -802,8 +802,8 @@ namespace Flow.Launcher settings.Click += (o, e) => App.API.OpenSettingDialog(); exit.Click += (o, e) => Close(); - gamemode.ToolTip = App.API.GetTranslation("GameModeToolTip"); - positionreset.ToolTip = App.API.GetTranslation("PositionResetToolTip"); + gamemode.ToolTip = Localize.GameModeToolTip(); + positionreset.ToolTip = Localize.PositionResetToolTip(); _contextMenu.Items.Add(open); _contextMenu.Items.Add(gamemode); diff --git a/Flow.Launcher/PluginUpdateWindow.xaml.cs b/Flow.Launcher/PluginUpdateWindow.xaml.cs index 20f033425..4b56e5836 100644 --- a/Flow.Launcher/PluginUpdateWindow.xaml.cs +++ b/Flow.Launcher/PluginUpdateWindow.xaml.cs @@ -23,7 +23,7 @@ namespace Flow.Launcher { var checkBox = new CheckBox { - Content = string.Format(App.API.GetTranslation("updatePluginCheckboxContent"), plugin.Name, plugin.CurrentVersion, plugin.NewVersion), + Content = Localize.updatePluginCheckboxContent(plugin.Name, plugin.CurrentVersion, plugin.NewVersion), IsChecked = true, Margin = new Thickness(0, 5, 0, 5), Tag = plugin, @@ -50,10 +50,7 @@ namespace Flow.Launcher { if (sender is not CheckBox cb) return; if (cb.Tag is not PluginUpdateInfo plugin) return; - if (Plugins.Contains(plugin)) - { - Plugins.Remove(plugin); - } + Plugins.Remove(plugin); } private void BtnCancel_OnClick(object sender, RoutedEventArgs e) @@ -66,7 +63,7 @@ namespace Flow.Launcher { if (Plugins.Count == 0) { - App.API.ShowMsgBox(App.API.GetTranslation("updatePluginNoSelected")); + App.API.ShowMsgBox(Localize.updatePluginNoSelected()); return; } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index b4c3aa92b..bd2f80743 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -184,14 +184,14 @@ namespace Flow.Launcher if (showDefaultNotification) { ShowMsg( - $"{GetTranslation("copy")} {(isFile ? GetTranslation("fileTitle") : GetTranslation("folderTitle"))}", - GetTranslation("completedSuccessfully")); + $"{Localize.copy()} {(isFile ? Localize.fileTitle(): Localize.folderTitle())}", + Localize.completedSuccessfully()); } } else { LogException(nameof(PublicAPIInstance), "Failed to copy file/folder to clipboard", exception); - ShowMsgError(GetTranslation("failedToCopy")); + ShowMsgError(Localize.failedToCopy()); } } else @@ -209,14 +209,14 @@ namespace Flow.Launcher if (showDefaultNotification) { ShowMsg( - $"{GetTranslation("copy")} {GetTranslation("textTitle")}", - GetTranslation("completedSuccessfully")); + $"{Localize.copy()} {Localize.textTitle()}", + Localize.completedSuccessfully()); } } else { LogException(nameof(PublicAPIInstance), "Failed to copy text to clipboard", exception); - ShowMsgError(GetTranslation("failedToCopy")); + ShowMsgError(Localize.failedToCopy()); } } } @@ -393,18 +393,18 @@ namespace Flow.Launcher } catch (Win32Exception ex) when (ex.NativeErrorCode == 2) { - LogError(ClassName, "File Manager not found"); + LogException(ClassName, "File Manager not found", ex); ShowMsgError( - GetTranslation("fileManagerNotFoundTitle"), - string.Format(GetTranslation("fileManagerNotFound"), ex.Message) + Localize.fileManagerNotFoundTitle(), + Localize.fileManagerNotFound() ); } catch (Exception ex) { LogException(ClassName, "Failed to open folder", ex); ShowMsgError( - GetTranslation("errorTitle"), - string.Format(GetTranslation("folderOpenError"), ex.Message) + Localize.errorTitle(), + Localize.folderOpenError() ); } } @@ -413,7 +413,7 @@ namespace Flow.Launcher { if (uri.IsFile && !FilesFolders.FileOrLocationExists(uri.LocalPath)) { - ShowMsgError(GetTranslation("errorTitle"), string.Format(GetTranslation("fileNotFoundError"), uri.LocalPath)); + ShowMsgError(Localize.errorTitle(), Localize.fileNotFoundError(uri.LocalPath)); return; } @@ -439,8 +439,8 @@ namespace Flow.Launcher var tabOrWindow = browserInfo.OpenInTab ? "tab" : "window"; LogException(ClassName, $"Failed to open URL in browser {tabOrWindow}: {path}, {inPrivate ?? browserInfo.EnablePrivate}, {browserInfo.PrivateArg}", e); ShowMsgError( - GetTranslation("errorTitle"), - GetTranslation("browserOpenError") + Localize.errorTitle(), + Localize.browserOpenError() ); } } @@ -457,7 +457,7 @@ namespace Flow.Launcher catch (Exception e) { LogException(ClassName, $"Failed to open: {uri.AbsoluteUri}", e); - ShowMsgError(GetTranslation("errorTitle"), e.Message); + ShowMsgError(Localize.errorTitle(), e.Message); } } } diff --git a/Flow.Launcher/ReleaseNotesWindow.xaml.cs b/Flow.Launcher/ReleaseNotesWindow.xaml.cs index ce7a3e084..4e3f30d30 100644 --- a/Flow.Launcher/ReleaseNotesWindow.xaml.cs +++ b/Flow.Launcher/ReleaseNotesWindow.xaml.cs @@ -132,8 +132,8 @@ namespace Flow.Launcher RefreshButton.Visibility = Visibility.Visible; MarkdownViewer.Visibility = Visibility.Collapsed; App.API.ShowMsgError( - App.API.GetTranslation("checkNetworkConnectionTitle"), - App.API.GetTranslation("checkNetworkConnectionSubTitle")); + Localize.checkNetworkConnectionTitle(), + Localize.checkNetworkConnectionSubTitle()); } else { diff --git a/Flow.Launcher/ReportWindow.xaml.cs b/Flow.Launcher/ReportWindow.xaml.cs index ae0767934..bb0ce0073 100644 --- a/Flow.Launcher/ReportWindow.xaml.cs +++ b/Flow.Launcher/ReportWindow.xaml.cs @@ -48,10 +48,10 @@ namespace Flow.Launcher _ => Constant.IssuesUrl }; - var paragraph = Hyperlink(App.API.GetTranslation("reportWindow_please_open_issue"), websiteUrl); - paragraph.Inlines.Add(string.Format(App.API.GetTranslation("reportWindow_upload_log"), log.FullName)); + var paragraph = Hyperlink(Localize.reportWindow_please_open_issue(), websiteUrl); + paragraph.Inlines.Add(Localize.reportWindow_upload_log(log.FullName)); paragraph.Inlines.Add("\n"); - paragraph.Inlines.Add(App.API.GetTranslation("reportWindow_copy_below")); + paragraph.Inlines.Add(Localize.reportWindow_copy_below()); ErrorTextbox.Document.Blocks.Add(paragraph); StringBuilder content = new StringBuilder(); diff --git a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs index 10cd18821..5e3ab6815 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs @@ -59,7 +59,7 @@ namespace Flow.Launcher.Resources.Pages } catch (Exception e) { - App.API.ShowMsgError(App.API.GetTranslation("setAutoStartFailed"), e.Message); + App.API.ShowMsgError(Localize.setAutoStartFailed(), e.Message); } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index 647b36701..f906bf55c 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -25,7 +25,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel get { var size = GetLogFiles().Sum(file => file.Length); - return $"{App.API.GetTranslation("clearlogfolder")} ({BytesToReadableString(size)})"; + return $"{Localize.clearlogfolder()} ({BytesToReadableString(size)})"; } } @@ -34,7 +34,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel get { var size = GetCacheFiles().Sum(file => file.Length); - return $"{App.API.GetTranslation("clearcachefolder")} ({BytesToReadableString(size)})"; + return $"{Localize.clearcachefolder()} ({BytesToReadableString(size)})"; } } @@ -51,10 +51,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel _ => Constant.Version }; - public string ActivatedTimes => string.Format( - App.API.GetTranslation("about_activate_times"), - _settings.ActivateTimes - ); + public string ActivatedTimes => Localize.about_activate_times(_settings.ActivateTimes); public class LogLevelData : DropdownDataGeneric { } @@ -98,8 +95,8 @@ public partial class SettingsPaneAboutViewModel : BaseModel private void AskClearLogFolderConfirmation() { var confirmResult = App.API.ShowMsgBox( - App.API.GetTranslation("clearlogfolderMessage"), - App.API.GetTranslation("clearlogfolder"), + Localize.clearlogfolderMessage(), + Localize.clearlogfolder(), MessageBoxButton.YesNo ); @@ -107,7 +104,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel { if (!ClearLogFolder()) { - App.API.ShowMsgBox(App.API.GetTranslation("clearfolderfailMessage")); + App.API.ShowMsgBox(Localize.clearfolderfailMessage()); } } } @@ -116,8 +113,8 @@ public partial class SettingsPaneAboutViewModel : BaseModel private void AskClearCacheFolderConfirmation() { var confirmResult = App.API.ShowMsgBox( - App.API.GetTranslation("clearcachefolderMessage"), - App.API.GetTranslation("clearcachefolder"), + Localize.clearcachefolderMessage(), + Localize.clearcachefolder(), MessageBoxButton.YesNo ); @@ -125,7 +122,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel { if (!ClearCacheFolder()) { - App.API.ShowMsgBox(App.API.GetTranslation("clearfolderfailMessage")); + App.API.ShowMsgBox(Localize.clearfolderfailMessage()); } } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 885330b8c..6641ac689 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -65,7 +65,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel } catch (Exception e) { - App.API.ShowMsgError(App.API.GetTranslation("setAutoStartFailed"), e.Message); + App.API.ShowMsgError(Localize.setAutoStartFailed(), e.Message); } } } @@ -92,7 +92,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel } catch (Exception e) { - App.API.ShowMsgError(App.API.GetTranslation("setAutoStartFailed"), e.Message); + App.API.ShowMsgError(Localize.setAutoStartFailed(), e.Message); } } } @@ -257,7 +257,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel else { // Since this is rarely seen text, language support is not provided. - App.API.ShowMsgError(App.API.GetTranslation("KoreanImeSettingChangeFailTitle"), App.API.GetTranslation("KoreanImeSettingChangeFailSubTitle")); + App.API.ShowMsgError(Localize.KoreanImeSettingChangeFailTitle(), Localize.KoreanImeSettingChangeFailSubTitle()); } } } @@ -325,10 +325,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public List Languages => _translater.LoadAvailableLanguages(); - public string AlwaysPreviewToolTip => string.Format( - App.API.GetTranslation("AlwaysPreviewToolTip"), - Settings.PreviewHotkey - ); + public string AlwaysPreviewToolTip => Localize.AlwaysPreviewToolTip(Settings.PreviewHotkey); private static string GetFileFromDialog(string title, string filter = "") { @@ -372,7 +369,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel private void SelectPython() { var selectedFile = GetFileFromDialog( - App.API.GetTranslation("selectPythonExecutable"), + Localize.selectPythonExecutable(), "Python|pythonw.exe" ); @@ -384,7 +381,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel private void SelectNode() { var selectedFile = GetFileFromDialog( - App.API.GetTranslation("selectNodeExecutable"), + Localize.selectNodeExecutable(), "node|*.exe" ); diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs index 9e6a31dc7..3e7c3cb83 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs @@ -50,15 +50,13 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomPluginHotkey; if (item is null) { - App.API.ShowMsgBox(App.API.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(Localize.pleaseSelectAnItem()); return; } var result = App.API.ShowMsgBox( - string.Format( - App.API.GetTranslation("deleteCustomHotkeyWarning"), item.Hotkey - ), - App.API.GetTranslation("delete"), + Localize.deleteCustomHotkeyWarning(item.Hotkey), + Localize.delete(), MessageBoxButton.YesNo ); @@ -75,7 +73,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomPluginHotkey; if (item is null) { - App.API.ShowMsgBox(App.API.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(Localize.pleaseSelectAnItem()); return; } @@ -83,7 +81,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel o.ActionKeyword == item.ActionKeyword && o.Hotkey == item.Hotkey); if (settingItem == null) { - App.API.ShowMsgBox(App.API.GetTranslation("invalidPluginHotkey")); + App.API.ShowMsgBox(Localize.invalidPluginHotkey()); return; } @@ -114,15 +112,13 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomShortcut; if (item is null) { - App.API.ShowMsgBox(App.API.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(Localize.pleaseSelectAnItem()); return; } var result = App.API.ShowMsgBox( - string.Format( - App.API.GetTranslation("deleteCustomShortcutWarning"), item.Key, item.Value - ), - App.API.GetTranslation("delete"), + Localize.deleteCustomShortcutWarning(item.Key, item.Value), + Localize.delete(), MessageBoxButton.YesNo ); @@ -138,7 +134,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomShortcut; if (item is null) { - App.API.ShowMsgBox(App.API.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(Localize.pleaseSelectAnItem()); return; } @@ -146,7 +142,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel o.Key == item.Key && o.Value == item.Value); if (settingItem == null) { - App.API.ShowMsgBox(App.API.GetTranslation("invalidShortcut")); + App.API.ShowMsgBox(Localize.invalidShortcut()); return; } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs index f133b7d2b..d67695a75 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -103,8 +103,8 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel private async Task InstallPluginAsync() { var file = GetFileFromDialog( - App.API.GetTranslation("SelectZipFile"), - $"{App.API.GetTranslation("ZipFiles")} (*.zip)|*.zip"); + Localize.SelectZipFile(), + $"{Localize.ZipFiles()} (*.zip)|*.zip"); if (!string.IsNullOrEmpty(file)) await PluginInstaller.InstallPluginAndCheckRestartAsync(file); diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index 98dac499f..70bcbcc18 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -26,7 +26,7 @@ public partial class SettingsPaneThemeViewModel : BaseModel private readonly Theme _theme; private readonly string DefaultFont = Win32Helper.GetSystemDefaultFont(); - public string BackdropSubText => !Win32Helper.IsBackdropSupported() ? App.API.GetTranslation("BackdropTypeDisabledToolTip") : ""; + public string BackdropSubText => !Win32Helper.IsBackdropSupported() ? Localize.BackdropTypeDisabledToolTip(): ""; public static string LinkHowToCreateTheme => @"https://www.flowlauncher.com/theme-builder/"; public static string LinkThemeGallery => "https://github.com/Flow-Launcher/Flow.Launcher/discussions/1438"; @@ -272,7 +272,7 @@ public partial class SettingsPaneThemeViewModel : BaseModel public string PlaceholderTextTip { - get => string.Format(App.API.GetTranslation("PlaceholderTextTip"), App.API.GetTranslation("queryTextBoxPlaceholder")); + get => Localize.PlaceholderTextTip(Localize.queryTextBoxPlaceholder()); } public string PlaceholderText @@ -447,8 +447,8 @@ public partial class SettingsPaneThemeViewModel : BaseModel { new() { - Title = App.API.GetTranslation("SampleTitleExplorer"), - SubTitle = App.API.GetTranslation("SampleSubTitleExplorer"), + Title = Localize.SampleTitleExplorer(), + SubTitle = Localize.SampleSubTitleExplorer(), IcoPath = Path.Combine( Constant.ProgramDirectory, @"Plugins\Flow.Launcher.Plugin.Explorer\Images\explorer.png" @@ -456,8 +456,8 @@ public partial class SettingsPaneThemeViewModel : BaseModel }, new() { - Title = App.API.GetTranslation("SampleTitleWebSearch"), - SubTitle = App.API.GetTranslation("SampleSubTitleWebSearch"), + Title = Localize.SampleTitleWebSearch(), + SubTitle = Localize.SampleSubTitleWebSearch(), IcoPath = Path.Combine( Constant.ProgramDirectory, @"Plugins\Flow.Launcher.Plugin.WebSearch\Images\web_search.png" @@ -465,8 +465,8 @@ public partial class SettingsPaneThemeViewModel : BaseModel }, new() { - Title = App.API.GetTranslation("SampleTitleProgram"), - SubTitle = App.API.GetTranslation("SampleSubTitleProgram"), + Title = Localize.SampleTitleProgram(), + SubTitle = Localize.SampleSubTitleProgram(), IcoPath = Path.Combine( Constant.ProgramDirectory, @"Plugins\Flow.Launcher.Plugin.Program\Images\program.png" @@ -474,8 +474,8 @@ public partial class SettingsPaneThemeViewModel : BaseModel }, new() { - Title = App.API.GetTranslation("SampleTitleProcessKiller"), - SubTitle = App.API.GetTranslation("SampleSubTitleProcessKiller"), + Title = Localize.SampleTitleProcessKiller(), + SubTitle = Localize.SampleSubTitleProcessKiller(), IcoPath = Path.Combine( Constant.ProgramDirectory, @"Plugins\Flow.Launcher.Plugin.ProcessKiller\Images\app.png" diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index d492f28c5..66fa70682 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -342,8 +342,8 @@ namespace Flow.Launcher.ViewModel Hide(); await PluginManager.ReloadDataAsync().ConfigureAwait(false); - App.API.ShowMsg(App.API.GetTranslation("success"), - App.API.GetTranslation("completedSuccessfully")); + App.API.ShowMsg(Localize.success(), + Localize.completedSuccessfully()); } [RelayCommand] @@ -908,7 +908,7 @@ namespace Flow.Launcher.ViewModel private string _placeholderText; public string PlaceholderText { - get => string.IsNullOrEmpty(_placeholderText) ? App.API.GetTranslation("queryTextBoxPlaceholder") : _placeholderText; + get => string.IsNullOrEmpty(_placeholderText) ? Localize.queryTextBoxPlaceholder(): _placeholderText; set { _placeholderText = value; @@ -1312,12 +1312,10 @@ namespace Flow.Launcher.ViewModel var results = new List(); foreach (var h in historyItems) { - var title = App.API.GetTranslation("executeQuery"); - var time = App.API.GetTranslation("lastExecuteTime"); var result = new Result { - Title = string.Format(title, h.Query), - SubTitle = string.Format(time, h.ExecutedDateTime), + Title = Localize.executeQuery(h.Query), + SubTitle = Localize.lastExecuteTime(h.ExecutedDateTime), IcoPath = Constant.HistoryIcon, OriginQuery = new Query { RawQuery = h.Query }, Action = _ => @@ -1714,13 +1712,13 @@ namespace Flow.Launcher.ViewModel { menu = new Result { - Title = App.API.GetTranslation("cancelTopMostInThisQuery"), + Title = Localize.cancelTopMostInThisQuery(), IcoPath = "Images\\down.png", PluginDirectory = Constant.ProgramDirectory, Action = _ => { _topMostRecord.Remove(result); - App.API.ShowMsg(App.API.GetTranslation("success")); + App.API.ShowMsg(Localize.success()); App.API.ReQuery(); return false; }, @@ -1732,13 +1730,13 @@ namespace Flow.Launcher.ViewModel { menu = new Result { - Title = App.API.GetTranslation("setAsTopMostInThisQuery"), + Title = Localize.setAsTopMostInThisQuery(), IcoPath = "Images\\up.png", PluginDirectory = Constant.ProgramDirectory, Action = _ => { _topMostRecord.AddOrUpdate(result); - App.API.ShowMsg(App.API.GetTranslation("success")); + App.API.ShowMsg(Localize.success()); App.API.ReQuery(); return false; }, @@ -1756,10 +1754,10 @@ namespace Flow.Launcher.ViewModel var metadata = PluginManager.GetPluginForId(id).Metadata; var translator = App.API; - var author = translator.GetTranslation("author"); - var website = translator.GetTranslation("website"); - var version = translator.GetTranslation("version"); - var plugin = translator.GetTranslation("plugin"); + var author = Localize.author(); + var website = Localize.website(); + var version = Localize.version(); + var plugin = Localize.plugin(); var title = $"{plugin}: {metadata.Name}"; var icon = metadata.IcoPath; var subtitle = $"{author} {metadata.Author}"; diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 29f2b9b43..87d1839c7 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -155,8 +155,7 @@ namespace Flow.Launcher.ViewModel App.API.LogException(ClassName, $"Failed to create setting panel for {pair.Metadata.Name}", e); // Show error message in UI - var errorMsg = string.Format(App.API.GetTranslation("errorCreatingSettingPanel"), - pair.Metadata.Name, Environment.NewLine, e.Message); + var errorMsg = Localize.errorCreatingSettingPanel(pair.Metadata.Name, Environment.NewLine, e.Message); return CreateErrorSettingPanel(errorMsg); } } @@ -165,16 +164,16 @@ namespace Flow.Launcher.ViewModel Visibility.Collapsed : Visibility.Visible; public string InitializeTime => PluginPair.Metadata.InitTime + "ms"; public string QueryTime => PluginPair.Metadata.AvgQueryTime + "ms"; - public string Version => App.API.GetTranslation("plugin_query_version") + " " + PluginPair.Metadata.Version; + public string Version => Localize.plugin_query_version()+ " " + PluginPair.Metadata.Version; public string InitAndQueryTime => - App.API.GetTranslation("plugin_init_time") + " " + + Localize.plugin_init_time()+ " " + PluginPair.Metadata.InitTime + "ms, " + - App.API.GetTranslation("plugin_query_time") + " " + + Localize.plugin_query_time()+ " " + PluginPair.Metadata.AvgQueryTime + "ms"; public string ActionKeywordsText => string.Join(Query.ActionKeywordSeparator, PluginPair.Metadata.ActionKeywords); public string SearchDelayTimeText => PluginPair.Metadata.SearchDelayTime == null ? - App.API.GetTranslation("default") : - App.API.GetTranslation($"SearchDelayTime{PluginPair.Metadata.SearchDelayTime}"); + Localize.plugin_default_search_delay_time() : + Localize.plugin_search_delay_time(PluginPair.Metadata.SearchDelayTime); public Infrastructure.UserSettings.Plugin PluginSettingsObject{ get; init; } public bool SearchDelayEnabled => Settings.SearchQueryResultsWithDelay; public string DefaultSearchDelay => Settings.SearchDelayTime.ToString(); diff --git a/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs b/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs index e3a0e4e44..04602dcae 100644 --- a/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs +++ b/Flow.Launcher/ViewModel/SelectBrowserViewModel.cs @@ -50,7 +50,7 @@ public partial class SelectBrowserViewModel : BaseModel { CustomBrowsers.Add(new() { - Name = App.API.GetTranslation("defaultBrowser_new_profile") + Name = Localize.defaultBrowser_new_profile() }); SelectedCustomBrowserIndex = CustomBrowsers.Count - 1; } diff --git a/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs b/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs index f6a32e3fe..42c818042 100644 --- a/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs +++ b/Flow.Launcher/ViewModel/SelectFileManagerViewModel.cs @@ -48,9 +48,8 @@ public partial class SelectFileManagerViewModel : BaseModel if (!IsFileManagerValid(CustomExplorer.Path)) { var result = App.API.ShowMsgBox( - string.Format(App.API.GetTranslation("fileManagerPathNotFound"), - CustomExplorer.Name, CustomExplorer.Path), - App.API.GetTranslation("fileManagerPathError"), + Localize.fileManagerPathNotFound(CustomExplorer.Name, CustomExplorer.Path), + Localize.fileManagerPathError(), MessageBoxButton.YesNo, MessageBoxImage.Warning); @@ -105,7 +104,7 @@ public partial class SelectFileManagerViewModel : BaseModel { CustomExplorers.Add(new() { - Name = App.API.GetTranslation("defaultBrowser_new_profile") + Name = Localize.defaultBrowser_new_profile() }); SelectedCustomExplorerIndex = CustomExplorers.Count - 1; } diff --git a/Flow.Launcher/packages.lock.json b/Flow.Launcher/packages.lock.json index c90db6b0c..c3c8f60e3 100644 --- a/Flow.Launcher/packages.lock.json +++ b/Flow.Launcher/packages.lock.json @@ -14,6 +14,12 @@ "resolved": "8.4.0", "contentHash": "tqVU8yc/ADO9oiTRyTnwhFN68hCwvkliMierptWOudIAvWY1mWCh5VFh+guwHJmpMwfg0J0rY+yyd5Oy7ty9Uw==" }, + "Flow.Launcher.Localization": { + "type": "Direct", + "requested": "[0.0.6, )", + "resolved": "0.0.6", + "contentHash": "Wwh5lrnmAf66go456h9sSrkdIW3G/IaKPE3+qWZLRAQ86kIe1JovHRj+ljHZXnFOWu1cbFmHg3l1RuqzPLAHow==" + }, "Fody": { "type": "Direct", "requested": "[6.9.3, )", From 7350c1d4d547504f7b3c10fd8875859a2617cc11 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 23 Sep 2025 17:14:30 +0800 Subject: [PATCH 49/73] Use Flow.Launcher.Localization to improve code quality --- Flow.Launcher.Core/Configuration/Portable.cs | 11 ++- .../Environments/AbstractPluginEnvironment.cs | 18 +--- .../Environments/PythonEnvironment.cs | 2 +- .../Environments/TypeScriptEnvironment.cs | 2 +- .../Environments/TypeScriptV2Environment.cs | 2 +- Flow.Launcher.Core/Flow.Launcher.Core.csproj | 15 +++- .../Plugin/JsonRPCPluginSettings.cs | 2 +- Flow.Launcher.Core/Plugin/PluginInstaller.cs | 90 ++++++++----------- Flow.Launcher.Core/Plugin/PluginManager.cs | 39 ++++---- Flow.Launcher.Core/Plugin/PluginsLoader.cs | 6 +- Flow.Launcher.Core/Resource/Theme.cs | 4 +- Flow.Launcher.Core/Updater.cs | 25 +++--- Flow.Launcher.Core/packages.lock.json | 7 ++ .../Flow.Launcher.Infrastructure.csproj | 13 +++ Flow.Launcher.Infrastructure/Http/Http.cs | 2 +- .../UserSettings/CustomBrowserViewModel.cs | 7 +- .../UserSettings/CustomExplorerViewModel.cs | 7 +- .../packages.lock.json | 6 ++ Flow.Launcher/packages.lock.json | 2 + 19 files changed, 129 insertions(+), 131 deletions(-) diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index 721e14dca..b6ecd8bae 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -45,7 +45,7 @@ namespace Flow.Launcher.Core.Configuration #endif IndicateDeletion(DataLocation.PortableDataPath); - API.ShowMsgBox(API.GetTranslation("restartToDisablePortableMode")); + API.ShowMsgBox(Localize.restartToDisablePortableMode()); UpdateManager.RestartApp(Constant.ApplicationFileName); } @@ -68,7 +68,7 @@ namespace Flow.Launcher.Core.Configuration #endif IndicateDeletion(DataLocation.RoamingDataPath); - API.ShowMsgBox(API.GetTranslation("restartToEnablePortableMode")); + API.ShowMsgBox(Localize.restartToEnablePortableMode()); UpdateManager.RestartApp(Constant.ApplicationFileName); } @@ -152,7 +152,7 @@ namespace Flow.Launcher.Core.Configuration { FilesFolders.RemoveFolderIfExists(roamingDataDir, (s) => API.ShowMsgBox(s)); - if (API.ShowMsgBox(API.GetTranslation("moveToDifferentLocation"), + if (API.ShowMsgBox(Localize.moveToDifferentLocation(), string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) { FilesFolders.OpenPath(Constant.RootDirectory, (s) => API.ShowMsgBox(s)); @@ -166,7 +166,7 @@ namespace Flow.Launcher.Core.Configuration { FilesFolders.RemoveFolderIfExists(portableDataDir, (s) => API.ShowMsgBox(s)); - API.ShowMsgBox(API.GetTranslation("shortcutsUninstallerCreated")); + API.ShowMsgBox(Localize.shortcutsUninstallerCreated()); } } @@ -177,8 +177,7 @@ namespace Flow.Launcher.Core.Configuration if (roamingLocationExists && portableLocationExists) { - API.ShowMsgBox(string.Format(API.GetTranslation("userDataDuplicated"), - DataLocation.PortableDataPath, DataLocation.RoamingDataPath, Environment.NewLine)); + API.ShowMsgBox(Localize.userDataDuplicated(DataLocation.PortableDataPath, DataLocation.RoamingDataPath, Environment.NewLine)); return false; } diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs index 14796a87a..dcec19020 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs @@ -58,15 +58,10 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments return SetPathForPluginPairs(PluginsSettingsFilePath, Language); } - var noRuntimeMessage = string.Format( - API.GetTranslation("runtimePluginInstalledChooseRuntimePrompt"), - Language, - EnvName, - Environment.NewLine - ); + var noRuntimeMessage = Localize.runtimePluginInstalledChooseRuntimePrompt(Language, EnvName, Environment.NewLine); if (API.ShowMsgBox(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) { - var msg = string.Format(API.GetTranslation("runtimePluginChooseRuntimeExecutable"), EnvName); + var msg = Localize.runtimePluginChooseRuntimeExecutable(EnvName); var selectedFile = GetFileFromDialog(msg, FileDialogFilter); @@ -77,12 +72,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments // Nothing selected because user pressed cancel from the file dialog window else { - var forceDownloadMessage = string.Format( - API.GetTranslation("runtimeExecutableInvalidChooseDownload"), - Language, - EnvName, - Environment.NewLine - ); + var forceDownloadMessage = Localize.runtimeExecutableInvalidChooseDownload(Language, EnvName, Environment.NewLine); // Let users select valid path or choose to download while (string.IsNullOrEmpty(selectedFile)) @@ -120,7 +110,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } else { - API.ShowMsgBox(string.Format(API.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language)); + API.ShowMsgBox(Localize.runtimePluginUnableToSetExecutablePath(Language)); API.LogError(ClassName, $"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.", $"{Language}Environment"); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs index 89286dfb0..76c775fb4 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs @@ -51,7 +51,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } catch (System.Exception e) { - API.ShowMsgError(API.GetTranslation("failToInstallPythonEnv")); + API.ShowMsgError(Localize.failToInstallPythonEnv()); API.LogException(ClassName, "Failed to install Python environment", e); } }); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs index 724ae20f4..d8244cbf3 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs @@ -46,7 +46,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } catch (System.Exception e) { - API.ShowMsgError(API.GetTranslation("failToInstallTypeScriptEnv")); + API.ShowMsgError(Localize.failToInstallTypeScriptEnv()); API.LogException(ClassName, "Failed to install TypeScript environment", e); } }); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs index 6a32664a1..e2de53e39 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs @@ -46,7 +46,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } catch (System.Exception e) { - API.ShowMsgError(API.GetTranslation("failToInstallTypeScriptEnv")); + API.ShowMsgError(Localize.failToInstallTypeScriptEnv()); API.LogException(ClassName, "Failed to install TypeScript environment", e); } }); diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj index 1369d7e5d..52eaf0501 100644 --- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj +++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj @@ -1,4 +1,4 @@ - + net9.0-windows @@ -34,6 +34,7 @@ prompt 4 false + $(NoWarn);FLSG0007 @@ -55,6 +56,7 @@ + @@ -62,6 +64,17 @@ + + + true + + + + + + Languages\en.xaml + + diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs index 9212dada6..abefd47bc 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs @@ -285,7 +285,7 @@ namespace Flow.Launcher.Core.Plugin HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center, Margin = SettingPanelItemLeftMargin, - Content = API.GetTranslation("select") + Content = Localize.select() }; Btn.Click += (_, _) => diff --git a/Flow.Launcher.Core/Plugin/PluginInstaller.cs b/Flow.Launcher.Core/Plugin/PluginInstaller.cs index d01b34ab6..5629da231 100644 --- a/Flow.Launcher.Core/Plugin/PluginInstaller.cs +++ b/Flow.Launcher.Core/Plugin/PluginInstaller.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; @@ -35,16 +35,14 @@ public static class PluginInstaller { if (API.PluginModified(newPlugin.ID)) { - API.ShowMsgError(string.Format(API.GetTranslation("pluginModifiedAlreadyTitle"), newPlugin.Name), - API.GetTranslation("pluginModifiedAlreadyMessage")); + API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(newPlugin.Name), + Localize.pluginModifiedAlreadyMessage()); return; } if (API.ShowMsgBox( - string.Format( - API.GetTranslation("InstallPromptSubtitle"), - newPlugin.Name, newPlugin.Author, Environment.NewLine), - API.GetTranslation("InstallPromptTitle"), + Localize.InstallPromptSubtitle(newPlugin.Name, newPlugin.Author, Environment.NewLine), + Localize.InstallPromptTitle(), button: MessageBoxButton.YesNo) != MessageBoxResult.Yes) return; try @@ -61,7 +59,7 @@ public static class PluginInstaller if (!newPlugin.IsFromLocalInstallPath) { await DownloadFileAsync( - $"{API.GetTranslation("DownloadingPlugin")} {newPlugin.Name}", + $"{Localize.DownloadingPlugin()} {newPlugin.Name}", newPlugin.UrlDownload, filePath, cts); } else @@ -93,7 +91,7 @@ public static class PluginInstaller catch (Exception e) { API.LogException(ClassName, "Failed to install plugin", e); - API.ShowMsgError(API.GetTranslation("ErrorInstallingPlugin")); + API.ShowMsgError(Localize.ErrorInstallingPlugin()); return; // do not restart on failure } @@ -104,11 +102,8 @@ public static class PluginInstaller else { API.ShowMsg( - API.GetTranslation("installbtn"), - string.Format( - API.GetTranslation( - "InstallSuccessNoRestart"), - newPlugin.Name)); + Localize.installbtn(), + Localize.InstallSuccessNoRestart(newPlugin.Name)); } } @@ -134,23 +129,22 @@ public static class PluginInstaller catch (Exception e) { API.LogException(ClassName, "Failed to validate zip file", e); - API.ShowMsgError(API.GetTranslation("ZipFileNotHavePluginJson")); + API.ShowMsgError(Localize.ZipFileNotHavePluginJson()); return; } if (API.PluginModified(plugin.ID)) { - API.ShowMsgError(string.Format(API.GetTranslation("pluginModifiedAlreadyTitle"), plugin.Name), - API.GetTranslation("pluginModifiedAlreadyMessage")); + API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(plugin.Name), + Localize.pluginModifiedAlreadyMessage()); return; } if (Settings.ShowUnknownSourceWarning) { if (!InstallSourceKnown(plugin.Website) - && API.ShowMsgBox(string.Format( - API.GetTranslation("InstallFromUnknownSourceSubtitle"), Environment.NewLine), - API.GetTranslation("InstallFromUnknownSourceTitle"), + && API.ShowMsgBox(Localize.InstallFromUnknownSourceSubtitle(Environment.NewLine), + Localize.InstallFromUnknownSourceTitle(), MessageBoxButton.YesNo) == MessageBoxResult.No) return; } @@ -167,21 +161,19 @@ public static class PluginInstaller { if (API.PluginModified(oldPlugin.ID)) { - API.ShowMsgError(string.Format(API.GetTranslation("pluginModifiedAlreadyTitle"), oldPlugin.Name), - API.GetTranslation("pluginModifiedAlreadyMessage")); + API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(oldPlugin.Name), + Localize.pluginModifiedAlreadyMessage()); return; } if (API.ShowMsgBox( - string.Format( - API.GetTranslation("UninstallPromptSubtitle"), - oldPlugin.Name, oldPlugin.Author, Environment.NewLine), - API.GetTranslation("UninstallPromptTitle"), + Localize.UninstallPromptSubtitle(oldPlugin.Name, oldPlugin.Author, Environment.NewLine), + Localize.UninstallPromptTitle(), button: MessageBoxButton.YesNo) != MessageBoxResult.Yes) return; var removePluginSettings = API.ShowMsgBox( - API.GetTranslation("KeepPluginSettingsSubtitle"), - API.GetTranslation("KeepPluginSettingsTitle"), + Localize.KeepPluginSettingsSubtitle(), + Localize.KeepPluginSettingsTitle(), button: MessageBoxButton.YesNo) == MessageBoxResult.No; try @@ -194,7 +186,7 @@ public static class PluginInstaller catch (Exception e) { API.LogException(ClassName, "Failed to uninstall plugin", e); - API.ShowMsgError(API.GetTranslation("ErrorUninstallingPlugin")); + API.ShowMsgError(Localize.ErrorUninstallingPlugin()); return; // don not restart on failure } @@ -205,11 +197,8 @@ public static class PluginInstaller else { API.ShowMsg( - API.GetTranslation("uninstallbtn"), - string.Format( - API.GetTranslation( - "UninstallSuccessNoRestart"), - oldPlugin.Name)); + Localize.uninstallbtn(), + Localize.UninstallSuccessNoRestart(oldPlugin.Name)); } } @@ -222,10 +211,8 @@ public static class PluginInstaller public static async Task UpdatePluginAndCheckRestartAsync(UserPlugin newPlugin, PluginMetadata oldPlugin) { if (API.ShowMsgBox( - string.Format( - API.GetTranslation("UpdatePromptSubtitle"), - oldPlugin.Name, oldPlugin.Author, Environment.NewLine), - API.GetTranslation("UpdatePromptTitle"), + Localize.UpdatePromptSubtitle(oldPlugin.Name, oldPlugin.Author, Environment.NewLine), + Localize.UpdatePromptTitle(), button: MessageBoxButton.YesNo) != MessageBoxResult.Yes) return; try @@ -237,7 +224,7 @@ public static class PluginInstaller if (!newPlugin.IsFromLocalInstallPath) { await DownloadFileAsync( - $"{API.GetTranslation("DownloadingPlugin")} {newPlugin.Name}", + $"{Localize.DownloadingPlugin()} {newPlugin.Name}", newPlugin.UrlDownload, filePath, cts); } else @@ -259,7 +246,7 @@ public static class PluginInstaller catch (Exception e) { API.LogException(ClassName, "Failed to update plugin", e); - API.ShowMsgError(API.GetTranslation("ErrorUpdatingPlugin")); + API.ShowMsgError(Localize.ErrorUpdatingPlugin()); return; // do not restart on failure } @@ -270,11 +257,8 @@ public static class PluginInstaller else { API.ShowMsg( - API.GetTranslation("updatebtn"), - string.Format( - API.GetTranslation( - "UpdateSuccessNoRestart"), - newPlugin.Name)); + Localize.updatebtn(), + Localize.UpdateSuccessNoRestart(newPlugin.Name)); } } @@ -314,11 +298,11 @@ public static class PluginInstaller }).ToList(); // No updates - if (!resultsForUpdate.Any()) + if (resultsForUpdate.Count == 0) { if (!silentUpdate) { - API.ShowMsg(API.GetTranslation("updateNoResultTitle"), API.GetTranslation("updateNoResultSubtitle")); + API.ShowMsg(Localize.updateNoResultTitle(), Localize.updateNoResultSubtitle()); } return; } @@ -331,8 +315,8 @@ public static class PluginInstaller // Show message box with button to update all plugins API.ShowMsgWithButton( - API.GetTranslation("updateAllPluginsTitle"), - API.GetTranslation("updateAllPluginsButtonContent"), + Localize.updateAllPluginsTitle(), + Localize.updateAllPluginsButtonContent(), () => { updateAllPlugins(resultsForUpdate); @@ -357,7 +341,7 @@ public static class PluginInstaller using var cts = new CancellationTokenSource(); await DownloadFileAsync( - $"{API.GetTranslation("DownloadingPlugin")} {plugin.PluginNewUserPlugin.Name}", + $"{Localize.DownloadingPlugin()} {plugin.PluginNewUserPlugin.Name}", plugin.PluginNewUserPlugin.UrlDownload, downloadToFilePath, cts); // check if user cancelled download before installing plugin @@ -376,7 +360,7 @@ public static class PluginInstaller catch (Exception e) { API.LogException(ClassName, "Failed to update plugin", e); - API.ShowMsgError(API.GetTranslation("ErrorUpdatingPlugin")); + API.ShowMsgError(Localize.ErrorUpdatingPlugin()); } })); @@ -389,8 +373,8 @@ public static class PluginInstaller else { API.ShowMsg( - API.GetTranslation("updatebtn"), - API.GetTranslation("PluginsUpdateSuccessNoRestart")); + Localize.updatebtn(), + Localize.PluginsUpdateSuccessNoRestart()); } } diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index a4ab8de08..ba101d4a7 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; @@ -295,15 +295,12 @@ namespace Flow.Launcher.Core.Plugin } } - if (failedPlugins.Any()) + if (!failedPlugins.IsEmpty) { var failed = string.Join(",", failedPlugins.Select(x => x.Metadata.Name)); API.ShowMsg( - API.GetTranslation("failedToInitializePluginsTitle"), - string.Format( - API.GetTranslation("failedToInitializePluginsMessage"), - failed - ), + Localize.failedToInitializePluginsTitle(), + Localize.failedToInitializePluginsMessage(failed), "", false ); @@ -636,8 +633,8 @@ namespace Flow.Launcher.Core.Plugin { if (PluginModified(existingVersion.ID)) { - API.ShowMsgError(string.Format(API.GetTranslation("pluginModifiedAlreadyTitle"), existingVersion.Name), - API.GetTranslation("pluginModifiedAlreadyMessage")); + API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(existingVersion.Name), + Localize.pluginModifiedAlreadyMessage()); return false; } @@ -669,8 +666,8 @@ namespace Flow.Launcher.Core.Plugin { if (checkModified && PluginModified(plugin.ID)) { - API.ShowMsgError(string.Format(API.GetTranslation("pluginModifiedAlreadyTitle"), plugin.Name), - API.GetTranslation("pluginModifiedAlreadyMessage")); + API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(plugin.Name), + Localize.pluginModifiedAlreadyMessage()); return false; } @@ -689,15 +686,15 @@ namespace Flow.Launcher.Core.Plugin if (string.IsNullOrEmpty(metadataJsonFilePath) || string.IsNullOrEmpty(pluginFolderPath)) { - API.ShowMsgError(string.Format(API.GetTranslation("failedToInstallPluginTitle"), plugin.Name), - string.Format(API.GetTranslation("fileNotFoundMessage"), pluginFolderPath)); + API.ShowMsgError(Localize.failedToInstallPluginTitle(plugin.Name), + Localize.fileNotFoundMessage(pluginFolderPath)); return false; } if (SameOrLesserPluginVersionExists(metadataJsonFilePath)) { - API.ShowMsgError(string.Format(API.GetTranslation("failedToInstallPluginTitle"), plugin.Name), - API.GetTranslation("pluginExistAlreadyMessage")); + API.ShowMsgError(Localize.failedToInstallPluginTitle(plugin.Name), + Localize.pluginExistAlreadyMessage()); return false; } @@ -750,8 +747,8 @@ namespace Flow.Launcher.Core.Plugin { if (checkModified && PluginModified(plugin.ID)) { - API.ShowMsgError(string.Format(API.GetTranslation("pluginModifiedAlreadyTitle"), plugin.Name), - API.GetTranslation("pluginModifiedAlreadyMessage")); + API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(plugin.Name), + Localize.pluginModifiedAlreadyMessage()); return false; } @@ -785,8 +782,8 @@ namespace Flow.Launcher.Core.Plugin catch (Exception e) { API.LogException(ClassName, $"Failed to delete plugin settings folder for {plugin.Name}", e); - API.ShowMsgError(API.GetTranslation("failedToRemovePluginSettingsTitle"), - string.Format(API.GetTranslation("failedToRemovePluginSettingsMessage"), plugin.Name)); + API.ShowMsgError(Localize.failedToRemovePluginSettingsTitle(), + Localize.failedToRemovePluginSettingsMessage(plugin.Name)); } } @@ -801,8 +798,8 @@ namespace Flow.Launcher.Core.Plugin catch (Exception e) { API.LogException(ClassName, $"Failed to delete plugin cache folder for {plugin.Name}", e); - API.ShowMsgError(API.GetTranslation("failedToRemovePluginCacheTitle"), - string.Format(API.GetTranslation("failedToRemovePluginCacheMessage"), plugin.Name)); + API.ShowMsgError(Localize.failedToRemovePluginCacheTitle(), + Localize.failedToRemovePluginCacheMessage(plugin.Name)); } Settings.RemovePluginSettings(plugin.ID); AllPlugins.RemoveAll(p => p.Metadata.ID == plugin.ID); diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs index e9e5ee367..92dfef2c6 100644 --- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs @@ -121,12 +121,12 @@ namespace Flow.Launcher.Core.Plugin var errorPluginString = string.Join(Environment.NewLine, erroredPlugins); var errorMessage = erroredPlugins.Count > 1 ? - API.GetTranslation("pluginsHaveErrored") : - API.GetTranslation("pluginHasErrored"); + Localize.pluginsHaveErrored(): + Localize.pluginHasErrored(); API.ShowMsgError($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + $"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" + - API.GetTranslation("referToLogs")); + Localize.referToLogs()); } return plugins; diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index a6e8dc6bf..d1f7da2a2 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -444,7 +444,7 @@ namespace Flow.Launcher.Core.Resource _api.LogError(ClassName, $"Theme <{theme}> path can't be found"); if (theme != Constant.DefaultTheme) { - _api.ShowMsgBox(string.Format(_api.GetTranslation("theme_load_failure_path_not_exists"), theme)); + _api.ShowMsgBox(Localize.theme_load_failure_path_not_exists(theme)); ChangeTheme(Constant.DefaultTheme); } return false; @@ -454,7 +454,7 @@ namespace Flow.Launcher.Core.Resource _api.LogError(ClassName, $"Theme <{theme}> fail to parse"); if (theme != Constant.DefaultTheme) { - _api.ShowMsgBox(string.Format(_api.GetTranslation("theme_load_failure_parse_error"), theme)); + _api.ShowMsgBox(Localize.theme_load_failure_parse_error(theme)); ChangeTheme(Constant.DefaultTheme); } return false; diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 45275696c..1f138e843 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -41,8 +41,8 @@ namespace Flow.Launcher.Core try { if (!silentUpdate) - _api.ShowMsg(_api.GetTranslation("pleaseWait"), - _api.GetTranslation("update_flowlauncher_update_check")); + _api.ShowMsg(Localize.pleaseWait(), + Localize.update_flowlauncher_update_check()); using var updateManager = await GitHubUpdateManagerAsync(GitHubRepository).ConfigureAwait(false); @@ -58,13 +58,13 @@ namespace Flow.Launcher.Core if (newReleaseVersion <= currentVersion) { if (!silentUpdate) - _api.ShowMsgBox(_api.GetTranslation("update_flowlauncher_already_on_latest")); + _api.ShowMsgBox(Localize.update_flowlauncher_already_on_latest()); return; } if (!silentUpdate) - _api.ShowMsg(_api.GetTranslation("update_flowlauncher_update_found"), - _api.GetTranslation("update_flowlauncher_updating")); + _api.ShowMsg(Localize.update_flowlauncher_update_found(), + Localize.update_flowlauncher_updating()); await updateManager.DownloadReleases(newUpdateInfo.ReleasesToApply).ConfigureAwait(false); @@ -77,10 +77,7 @@ namespace Flow.Launcher.Core FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination, (s) => _api.ShowMsgBox(s)); if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination, (s) => _api.ShowMsgBox(s))) - _api.ShowMsgBox(string.Format( - _api.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"), - DataLocation.PortableDataPath, - targetDestination)); + _api.ShowMsgBox(Localize.update_flowlauncher_fail_moving_portable_user_profile_data(DataLocation.PortableDataPath, targetDestination)); } else { @@ -91,7 +88,7 @@ namespace Flow.Launcher.Core _api.LogInfo(ClassName, $"Update success:{newVersionTips}"); - if (_api.ShowMsgBox(newVersionTips, _api.GetTranslation("update_flowlauncher_new_update"), + if (_api.ShowMsgBox(newVersionTips, Localize.update_flowlauncher_new_update(), MessageBoxButton.YesNo) == MessageBoxResult.Yes) { UpdateManager.RestartApp(Constant.ApplicationFileName); @@ -111,8 +108,8 @@ namespace Flow.Launcher.Core } if (!silentUpdate) - _api.ShowMsgError(_api.GetTranslation("update_flowlauncher_fail"), - _api.GetTranslation("update_flowlauncher_check_connection")); + _api.ShowMsgError(Localize.update_flowlauncher_fail(), + Localize.update_flowlauncher_check_connection()); } finally { @@ -150,9 +147,9 @@ namespace Flow.Launcher.Core return manager; } - private string NewVersionTips(string version) + private static string NewVersionTips(string version) { - var tips = string.Format(_api.GetTranslation("newVersionTips"), version); + var tips = Localize.newVersionTips(version); return tips; } diff --git a/Flow.Launcher.Core/packages.lock.json b/Flow.Launcher.Core/packages.lock.json index b7a00d94d..ab2a1f718 100644 --- a/Flow.Launcher.Core/packages.lock.json +++ b/Flow.Launcher.Core/packages.lock.json @@ -11,6 +11,12 @@ "YamlDotNet": "9.1.0" } }, + "Flow.Launcher.Localization": { + "type": "Direct", + "requested": "[0.0.6, )", + "resolved": "0.0.6", + "contentHash": "Wwh5lrnmAf66go456h9sSrkdIW3G/IaKPE3+qWZLRAQ86kIe1JovHRj+ljHZXnFOWu1cbFmHg3l1RuqzPLAHow==" + }, "FSharp.Core": { "type": "Direct", "requested": "[9.0.303, )", @@ -254,6 +260,7 @@ "Ben.Demystifier": "[0.4.1, )", "BitFaster.Caching": "[2.5.4, )", "CommunityToolkit.Mvvm": "[8.4.0, )", + "Flow.Launcher.Localization": "[0.0.6, )", "Flow.Launcher.Plugin": "[5.0.0, )", "InputSimulator": "[1.0.4, )", "MemoryPack": "[1.21.4, )", diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index 5b4eaf893..df2ffba25 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -34,6 +34,7 @@ prompt 4 false + $(NoWarn);FLSG0007 @@ -56,6 +57,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -80,4 +82,15 @@ + + true + + + + + + Languages\en.xaml + + + \ No newline at end of file diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 8afab419b..5a4371598 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -82,7 +82,7 @@ namespace Flow.Launcher.Infrastructure.Http } catch (UriFormatException e) { - API.ShowMsgError(API.GetTranslation("pleaseTryAgain"), API.GetTranslation("parseProxyFailed")); + API.ShowMsgError(Localize.pleaseTryAgain(), Localize.parseProxyFailed()); Log.Exception(ClassName, "Unable to parse Uri", e); } } diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs index 9c795f952..849762867 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs @@ -1,18 +1,13 @@ using System.Text.Json.Serialization; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Plugin; namespace Flow.Launcher.Infrastructure.UserSettings { public class CustomBrowserViewModel : BaseModel { - // 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 string Name { get; set; } [JsonIgnore] - public string DisplayName => Name == "Default" ? API.GetTranslation("defaultBrowser_default") : Name; + public string DisplayName => Name == "Default" ? Localize.defaultBrowser_default(): Name; public string Path { get; set; } public string PrivateArg { get; set; } public bool EnablePrivate { get; set; } diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs index 2af0bb0e5..ffc48b244 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs @@ -1,18 +1,13 @@ using System.Text.Json.Serialization; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Plugin; namespace Flow.Launcher.Infrastructure.UserSettings { public class CustomExplorerViewModel : BaseModel { - // 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 string Name { get; set; } [JsonIgnore] - public string DisplayName => Name == "Explorer" ? API.GetTranslation("fileManagerExplorer") : Name; + public string DisplayName => Name == "Explorer" ? Localize.fileManagerExplorer(): Name; public string Path { get; set; } public string FileArgument { get; set; } = "\"%d\""; public string DirectoryArgument { get; set; } = "\"%d\""; diff --git a/Flow.Launcher.Infrastructure/packages.lock.json b/Flow.Launcher.Infrastructure/packages.lock.json index 47c94d5f6..94adc16f1 100644 --- a/Flow.Launcher.Infrastructure/packages.lock.json +++ b/Flow.Launcher.Infrastructure/packages.lock.json @@ -23,6 +23,12 @@ "resolved": "8.4.0", "contentHash": "tqVU8yc/ADO9oiTRyTnwhFN68hCwvkliMierptWOudIAvWY1mWCh5VFh+guwHJmpMwfg0J0rY+yyd5Oy7ty9Uw==" }, + "Flow.Launcher.Localization": { + "type": "Direct", + "requested": "[0.0.6, )", + "resolved": "0.0.6", + "contentHash": "Wwh5lrnmAf66go456h9sSrkdIW3G/IaKPE3+qWZLRAQ86kIe1JovHRj+ljHZXnFOWu1cbFmHg3l1RuqzPLAHow==" + }, "Fody": { "type": "Direct", "requested": "[6.9.3, )", diff --git a/Flow.Launcher/packages.lock.json b/Flow.Launcher/packages.lock.json index c3c8f60e3..afbbff6b7 100644 --- a/Flow.Launcher/packages.lock.json +++ b/Flow.Launcher/packages.lock.json @@ -846,6 +846,7 @@ "Droplex": "[1.7.0, )", "FSharp.Core": "[9.0.303, )", "Flow.Launcher.Infrastructure": "[1.0.0, )", + "Flow.Launcher.Localization": "[0.0.6, )", "Flow.Launcher.Plugin": "[5.0.0, )", "Meziantou.Framework.Win32.Jobs": "[3.4.4, )", "Microsoft.IO.RecyclableMemoryStream": "[3.0.1, )", @@ -860,6 +861,7 @@ "Ben.Demystifier": "[0.4.1, )", "BitFaster.Caching": "[2.5.4, )", "CommunityToolkit.Mvvm": "[8.4.0, )", + "Flow.Launcher.Localization": "[0.0.6, )", "Flow.Launcher.Plugin": "[5.0.0, )", "InputSimulator": "[1.0.4, )", "MemoryPack": "[1.21.4, )", From 0e366a6269718e032b5438db8b9bd81a3b93836c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 23 Sep 2025 17:40:54 +0800 Subject: [PATCH 50/73] Use PublicApi.Instance instead of private one --- Flow.Launcher.Core/Configuration/Portable.cs | 28 +++--- .../ExternalPlugins/CommunityPluginSource.cs | 23 ++--- .../Environments/AbstractPluginEnvironment.cs | 13 +-- .../ExternalPlugins/PluginsManifest.cs | 11 +-- Flow.Launcher.Core/Plugin/PluginConfig.cs | 17 ++-- Flow.Launcher.Core/Plugin/PluginInstaller.cs | 94 +++++++++---------- Flow.Launcher.Core/Plugin/PluginManager.cs | 69 +++++++------- Flow.Launcher.Core/Plugin/PluginsLoader.cs | 19 ++-- .../Resource/Internationalization.cs | 21 ++--- .../Resource/LocalizedDescriptionAttribute.cs | 8 +- .../DialogJump/DialogJump.cs | 29 +++--- Flow.Launcher.Infrastructure/Http/Http.cs | 8 +- .../UserSettings/CustomShortcutModel.cs | 8 +- 13 files changed, 140 insertions(+), 208 deletions(-) diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index b6ecd8bae..8b305263d 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -3,10 +3,8 @@ using System.IO; using System.Linq; using System.Reflection; using System.Windows; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.UserSettings; -using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; using Microsoft.Win32; using Squirrel; @@ -17,8 +15,6 @@ namespace Flow.Launcher.Core.Configuration { private static readonly string ClassName = nameof(Portable); - private readonly IPublicAPI API = Ioc.Default.GetRequiredService(); - /// /// As at Squirrel.Windows version 1.5.2, UpdateManager needs to be disposed after finish /// @@ -45,13 +41,13 @@ namespace Flow.Launcher.Core.Configuration #endif IndicateDeletion(DataLocation.PortableDataPath); - API.ShowMsgBox(Localize.restartToDisablePortableMode()); + PublicApi.Instance.ShowMsgBox(Localize.restartToDisablePortableMode()); UpdateManager.RestartApp(Constant.ApplicationFileName); } catch (Exception e) { - API.LogException(ClassName, "Error occurred while disabling portable mode", e); + PublicApi.Instance.LogException(ClassName, "Error occurred while disabling portable mode", e); } } @@ -68,13 +64,13 @@ namespace Flow.Launcher.Core.Configuration #endif IndicateDeletion(DataLocation.RoamingDataPath); - API.ShowMsgBox(Localize.restartToEnablePortableMode()); + PublicApi.Instance.ShowMsgBox(Localize.restartToEnablePortableMode()); UpdateManager.RestartApp(Constant.ApplicationFileName); } catch (Exception e) { - API.LogException(ClassName, "Error occurred while enabling portable mode", e); + PublicApi.Instance.LogException(ClassName, "Error occurred while enabling portable mode", e); } } @@ -94,13 +90,13 @@ namespace Flow.Launcher.Core.Configuration public void MoveUserDataFolder(string fromLocation, string toLocation) { - FilesFolders.CopyAll(fromLocation, toLocation, (s) => API.ShowMsgBox(s)); + FilesFolders.CopyAll(fromLocation, toLocation, (s) => PublicApi.Instance.ShowMsgBox(s)); VerifyUserDataAfterMove(fromLocation, toLocation); } public void VerifyUserDataAfterMove(string fromLocation, string toLocation) { - FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation, (s) => API.ShowMsgBox(s)); + FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation, (s) => PublicApi.Instance.ShowMsgBox(s)); } public void CreateShortcuts() @@ -150,12 +146,12 @@ namespace Flow.Launcher.Core.Configuration // delete it and prompt the user to pick the portable data location if (File.Exists(roamingDataDeleteFilePath)) { - FilesFolders.RemoveFolderIfExists(roamingDataDir, (s) => API.ShowMsgBox(s)); + FilesFolders.RemoveFolderIfExists(roamingDataDir, (s) => PublicApi.Instance.ShowMsgBox(s)); - if (API.ShowMsgBox(Localize.moveToDifferentLocation(), + if (PublicApi.Instance.ShowMsgBox(Localize.moveToDifferentLocation(), string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) { - FilesFolders.OpenPath(Constant.RootDirectory, (s) => API.ShowMsgBox(s)); + FilesFolders.OpenPath(Constant.RootDirectory, (s) => PublicApi.Instance.ShowMsgBox(s)); Environment.Exit(0); } @@ -164,9 +160,9 @@ namespace Flow.Launcher.Core.Configuration // delete it and notify the user about it. else if (File.Exists(portableDataDeleteFilePath)) { - FilesFolders.RemoveFolderIfExists(portableDataDir, (s) => API.ShowMsgBox(s)); + FilesFolders.RemoveFolderIfExists(portableDataDir, (s) => PublicApi.Instance.ShowMsgBox(s)); - API.ShowMsgBox(Localize.shortcutsUninstallerCreated()); + PublicApi.Instance.ShowMsgBox(Localize.shortcutsUninstallerCreated()); } } @@ -177,7 +173,7 @@ namespace Flow.Launcher.Core.Configuration if (roamingLocationExists && portableLocationExists) { - API.ShowMsgBox(Localize.userDataDuplicated(DataLocation.PortableDataPath, DataLocation.RoamingDataPath, Environment.NewLine)); + PublicApi.Instance.ShowMsgBox(Localize.userDataDuplicated(DataLocation.PortableDataPath, DataLocation.RoamingDataPath, Environment.NewLine)); return false; } diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs index 841099dd1..7c0290b2a 100644 --- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs +++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs @@ -8,7 +8,6 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Plugin; @@ -18,13 +17,9 @@ namespace Flow.Launcher.Core.ExternalPlugins { private static readonly string ClassName = nameof(CommunityPluginSource); - // 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 string latestEtag = ""; - private List plugins = new(); + private List plugins = []; private static readonly JsonSerializerOptions PluginStoreItemSerializationOption = new() { @@ -41,7 +36,7 @@ namespace Flow.Launcher.Core.ExternalPlugins /// public async Task> FetchAsync(CancellationToken token) { - API.LogInfo(ClassName, $"Loading plugins from {ManifestFileUrl}"); + PublicApi.Instance.LogInfo(ClassName, $"Loading plugins from {ManifestFileUrl}"); var request = new HttpRequestMessage(HttpMethod.Get, ManifestFileUrl); @@ -59,40 +54,40 @@ namespace Flow.Launcher.Core.ExternalPlugins .ConfigureAwait(false); latestEtag = response.Headers.ETag?.Tag; - API.LogInfo(ClassName, $"Loaded {plugins.Count} plugins from {ManifestFileUrl}"); + PublicApi.Instance.LogInfo(ClassName, $"Loaded {plugins.Count} plugins from {ManifestFileUrl}"); return plugins; } else if (response.StatusCode == HttpStatusCode.NotModified) { - API.LogInfo(ClassName, $"Resource {ManifestFileUrl} has not been modified."); + PublicApi.Instance.LogInfo(ClassName, $"Resource {ManifestFileUrl} has not been modified."); return plugins; } else { - API.LogWarn(ClassName, $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}"); + PublicApi.Instance.LogWarn(ClassName, $"Failed to load resource {ManifestFileUrl} with response {response.StatusCode}"); return null; } } catch (OperationCanceledException) when (token.IsCancellationRequested) { - API.LogDebug(ClassName, $"Fetching from {ManifestFileUrl} was cancelled by caller."); + PublicApi.Instance.LogDebug(ClassName, $"Fetching from {ManifestFileUrl} was cancelled by caller."); return null; } catch (TaskCanceledException) { // Likely an HttpClient timeout or external cancellation not requested by our token - API.LogWarn(ClassName, $"Fetching from {ManifestFileUrl} timed out."); + PublicApi.Instance.LogWarn(ClassName, $"Fetching from {ManifestFileUrl} timed out."); return null; } catch (Exception e) { if (e is HttpRequestException or WebException or SocketException || e.InnerException is TimeoutException) { - API.LogException(ClassName, $"Check your connection and proxy settings to {ManifestFileUrl}.", e); + PublicApi.Instance.LogException(ClassName, $"Check your connection and proxy settings to {ManifestFileUrl}.", e); } else { - API.LogException(ClassName, "Error Occurred", e); + PublicApi.Instance.LogException(ClassName, "Error Occurred", e); } return null; } diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs index dcec19020..d08ea88b3 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Windows; using System.Windows.Forms; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; @@ -15,8 +14,6 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments { private static readonly string ClassName = nameof(AbstractPluginEnvironment); - protected readonly IPublicAPI API = Ioc.Default.GetRequiredService(); - internal abstract string Language { get; } internal abstract string EnvName { get; } @@ -59,7 +56,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } var noRuntimeMessage = Localize.runtimePluginInstalledChooseRuntimePrompt(Language, EnvName, Environment.NewLine); - if (API.ShowMsgBox(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) + if (PublicApi.Instance.ShowMsgBox(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) { var msg = Localize.runtimePluginChooseRuntimeExecutable(EnvName); @@ -77,7 +74,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments // Let users select valid path or choose to download while (string.IsNullOrEmpty(selectedFile)) { - if (API.ShowMsgBox(forceDownloadMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) + if (PublicApi.Instance.ShowMsgBox(forceDownloadMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) { // Continue select file selectedFile = GetFileFromDialog(msg, FileDialogFilter); @@ -110,8 +107,8 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } else { - API.ShowMsgBox(Localize.runtimePluginUnableToSetExecutablePath(Language)); - API.LogError(ClassName, + PublicApi.Instance.ShowMsgBox(Localize.runtimePluginUnableToSetExecutablePath(Language)); + PublicApi.Instance.LogError(ClassName, $"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.", $"{Language}Environment"); @@ -125,7 +122,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments { if (expectedPath == currentPath) return; - FilesFolders.RemoveFolderIfExists(installedDirPath, (s) => API.ShowMsgBox(s)); + FilesFolders.RemoveFolderIfExists(installedDirPath, (s) => PublicApi.Instance.ShowMsgBox(s)); InstallEnvironment(); } diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index 1e845498c..eab9a8c43 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Plugin; using Flow.Launcher.Infrastructure; @@ -23,10 +22,6 @@ namespace Flow.Launcher.Core.ExternalPlugins private static DateTime lastFetchedAt = DateTime.MinValue; private static readonly TimeSpan fetchTimeout = TimeSpan.FromMinutes(2); - // 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 UserPlugins { get; private set; } public static async Task UpdateManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default) @@ -61,7 +56,7 @@ namespace Flow.Launcher.Core.ExternalPlugins } catch (Exception e) { - API.LogException(ClassName, "Http request failed", e); + PublicApi.Instance.LogException(ClassName, "Http request failed", e); } finally { @@ -83,12 +78,12 @@ namespace Flow.Launcher.Core.ExternalPlugins } catch (Exception e) { - API.LogException(ClassName, $"Failed to parse the minimum app version {plugin.MinimumAppVersion} for plugin {plugin.Name}. " + PublicApi.Instance.LogException(ClassName, $"Failed to parse the minimum app version {plugin.MinimumAppVersion} for plugin {plugin.Name}. " + "Plugin excluded from manifest", e); return false; } - API.LogInfo(ClassName, $"Plugin {plugin.Name} requires minimum Flow Launcher version {plugin.MinimumAppVersion}, " + PublicApi.Instance.LogInfo(ClassName, $"Plugin {plugin.Name} requires minimum Flow Launcher version {plugin.MinimumAppVersion}, " + $"but current version is {Constant.Version}. Plugin excluded from manifest."); return false; diff --git a/Flow.Launcher.Core/Plugin/PluginConfig.cs b/Flow.Launcher.Core/Plugin/PluginConfig.cs index f7457b4e1..c5f0f79a7 100644 --- a/Flow.Launcher.Core/Plugin/PluginConfig.cs +++ b/Flow.Launcher.Core/Plugin/PluginConfig.cs @@ -5,7 +5,6 @@ using System.IO; using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin; using System.Text.Json; -using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Core.Plugin { @@ -13,10 +12,6 @@ namespace Flow.Launcher.Core.Plugin { private static readonly string ClassName = nameof(PluginConfig); - // 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(); - /// /// Parse plugin metadata in the given directories /// @@ -38,7 +33,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - API.LogException(ClassName, $"Can't delete <{directory}>", e); + PublicApi.Instance.LogException(ClassName, $"Can't delete <{directory}>", e); } } else @@ -55,7 +50,7 @@ namespace Flow.Launcher.Core.Plugin duplicateList .ForEach( - x => API.LogWarn(ClassName, + x => PublicApi.Instance.LogWarn(ClassName, string.Format("Duplicate plugin name: {0}, id: {1}, version: {2} " + "not loaded due to version not the highest of the duplicates", x.Name, x.ID, x.Version), @@ -107,7 +102,7 @@ namespace Flow.Launcher.Core.Plugin string configPath = Path.Combine(pluginDirectory, Constant.PluginMetadataFileName); if (!File.Exists(configPath)) { - API.LogError(ClassName, $"Didn't find config file <{configPath}>"); + PublicApi.Instance.LogError(ClassName, $"Didn't find config file <{configPath}>"); return null; } @@ -123,19 +118,19 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - API.LogException(ClassName, $"Invalid json for config <{configPath}>", e); + PublicApi.Instance.LogException(ClassName, $"Invalid json for config <{configPath}>", e); return null; } if (!AllowedLanguage.IsAllowed(metadata.Language)) { - API.LogError(ClassName, $"Invalid language <{metadata.Language}> for config <{configPath}>"); + PublicApi.Instance.LogError(ClassName, $"Invalid language <{metadata.Language}> for config <{configPath}>"); return null; } if (!File.Exists(metadata.ExecuteFilePath)) { - API.LogError(ClassName, $"Execute file path didn't exist <{metadata.ExecuteFilePath}> for conifg <{configPath}"); + PublicApi.Instance.LogError(ClassName, $"Execute file path didn't exist <{metadata.ExecuteFilePath}> for conifg <{configPath}"); return null; } diff --git a/Flow.Launcher.Core/Plugin/PluginInstaller.cs b/Flow.Launcher.Core/Plugin/PluginInstaller.cs index 5629da231..6027b712e 100644 --- a/Flow.Launcher.Core/Plugin/PluginInstaller.cs +++ b/Flow.Launcher.Core/Plugin/PluginInstaller.cs @@ -22,10 +22,6 @@ public static class PluginInstaller private static readonly Settings Settings = Ioc.Default.GetRequiredService(); - // 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(); - /// /// Installs a plugin and restarts the application if required by settings. Prompts user for confirmation and handles download if needed. /// @@ -33,14 +29,14 @@ public static class PluginInstaller /// A Task representing the asynchronous install operation. public static async Task InstallPluginAndCheckRestartAsync(UserPlugin newPlugin) { - if (API.PluginModified(newPlugin.ID)) + if (PublicApi.Instance.PluginModified(newPlugin.ID)) { - API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(newPlugin.Name), + PublicApi.Instance.ShowMsgError(Localize.pluginModifiedAlreadyTitle(newPlugin.Name), Localize.pluginModifiedAlreadyMessage()); return; } - if (API.ShowMsgBox( + if (PublicApi.Instance.ShowMsgBox( Localize.InstallPromptSubtitle(newPlugin.Name, newPlugin.Author, Environment.NewLine), Localize.InstallPromptTitle(), button: MessageBoxButton.YesNo) != MessageBoxResult.Yes) return; @@ -78,7 +74,7 @@ public static class PluginInstaller throw new FileNotFoundException($"Plugin {newPlugin.ID} zip file not found at {filePath}", filePath); } - if (!API.InstallPlugin(newPlugin, filePath)) + if (!PublicApi.Instance.InstallPlugin(newPlugin, filePath)) { return; } @@ -90,18 +86,18 @@ public static class PluginInstaller } catch (Exception e) { - API.LogException(ClassName, "Failed to install plugin", e); - API.ShowMsgError(Localize.ErrorInstallingPlugin()); + PublicApi.Instance.LogException(ClassName, "Failed to install plugin", e); + PublicApi.Instance.ShowMsgError(Localize.ErrorInstallingPlugin()); return; // do not restart on failure } if (Settings.AutoRestartAfterChanging) { - API.RestartApp(); + PublicApi.Instance.RestartApp(); } else { - API.ShowMsg( + PublicApi.Instance.ShowMsg( Localize.installbtn(), Localize.InstallSuccessNoRestart(newPlugin.Name)); } @@ -128,14 +124,14 @@ public static class PluginInstaller } catch (Exception e) { - API.LogException(ClassName, "Failed to validate zip file", e); - API.ShowMsgError(Localize.ZipFileNotHavePluginJson()); + PublicApi.Instance.LogException(ClassName, "Failed to validate zip file", e); + PublicApi.Instance.ShowMsgError(Localize.ZipFileNotHavePluginJson()); return; } - if (API.PluginModified(plugin.ID)) + if (PublicApi.Instance.PluginModified(plugin.ID)) { - API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(plugin.Name), + PublicApi.Instance.ShowMsgError(Localize.pluginModifiedAlreadyTitle(plugin.Name), Localize.pluginModifiedAlreadyMessage()); return; } @@ -143,7 +139,7 @@ public static class PluginInstaller if (Settings.ShowUnknownSourceWarning) { if (!InstallSourceKnown(plugin.Website) - && API.ShowMsgBox(Localize.InstallFromUnknownSourceSubtitle(Environment.NewLine), + && PublicApi.Instance.ShowMsgBox(Localize.InstallFromUnknownSourceSubtitle(Environment.NewLine), Localize.InstallFromUnknownSourceTitle(), MessageBoxButton.YesNo) == MessageBoxResult.No) return; @@ -159,44 +155,44 @@ public static class PluginInstaller /// A Task representing the asynchronous uninstall operation. public static async Task UninstallPluginAndCheckRestartAsync(PluginMetadata oldPlugin) { - if (API.PluginModified(oldPlugin.ID)) + if (PublicApi.Instance.PluginModified(oldPlugin.ID)) { - API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(oldPlugin.Name), + PublicApi.Instance.ShowMsgError(Localize.pluginModifiedAlreadyTitle(oldPlugin.Name), Localize.pluginModifiedAlreadyMessage()); return; } - if (API.ShowMsgBox( + if (PublicApi.Instance.ShowMsgBox( Localize.UninstallPromptSubtitle(oldPlugin.Name, oldPlugin.Author, Environment.NewLine), Localize.UninstallPromptTitle(), button: MessageBoxButton.YesNo) != MessageBoxResult.Yes) return; - var removePluginSettings = API.ShowMsgBox( + var removePluginSettings = PublicApi.Instance.ShowMsgBox( Localize.KeepPluginSettingsSubtitle(), Localize.KeepPluginSettingsTitle(), button: MessageBoxButton.YesNo) == MessageBoxResult.No; try { - if (!await API.UninstallPluginAsync(oldPlugin, removePluginSettings)) + if (!await PublicApi.Instance.UninstallPluginAsync(oldPlugin, removePluginSettings)) { return; } } catch (Exception e) { - API.LogException(ClassName, "Failed to uninstall plugin", e); - API.ShowMsgError(Localize.ErrorUninstallingPlugin()); + PublicApi.Instance.LogException(ClassName, "Failed to uninstall plugin", e); + PublicApi.Instance.ShowMsgError(Localize.ErrorUninstallingPlugin()); return; // don not restart on failure } if (Settings.AutoRestartAfterChanging) { - API.RestartApp(); + PublicApi.Instance.RestartApp(); } else { - API.ShowMsg( + PublicApi.Instance.ShowMsg( Localize.uninstallbtn(), Localize.UninstallSuccessNoRestart(oldPlugin.Name)); } @@ -210,7 +206,7 @@ public static class PluginInstaller /// A Task representing the asynchronous update operation. public static async Task UpdatePluginAndCheckRestartAsync(UserPlugin newPlugin, PluginMetadata oldPlugin) { - if (API.ShowMsgBox( + if (PublicApi.Instance.ShowMsgBox( Localize.UpdatePromptSubtitle(oldPlugin.Name, oldPlugin.Author, Environment.NewLine), Localize.UpdatePromptTitle(), button: MessageBoxButton.YesNo) != MessageBoxResult.Yes) return; @@ -238,25 +234,25 @@ public static class PluginInstaller return; } - if (!await API.UpdatePluginAsync(oldPlugin, newPlugin, filePath)) + if (!await PublicApi.Instance.UpdatePluginAsync(oldPlugin, newPlugin, filePath)) { return; } } catch (Exception e) { - API.LogException(ClassName, "Failed to update plugin", e); - API.ShowMsgError(Localize.ErrorUpdatingPlugin()); + PublicApi.Instance.LogException(ClassName, "Failed to update plugin", e); + PublicApi.Instance.ShowMsgError(Localize.ErrorUpdatingPlugin()); return; // do not restart on failure } if (Settings.AutoRestartAfterChanging) { - API.RestartApp(); + PublicApi.Instance.RestartApp(); } else { - API.ShowMsg( + PublicApi.Instance.ShowMsg( Localize.updatebtn(), Localize.UpdateSuccessNoRestart(newPlugin.Name)); } @@ -273,17 +269,17 @@ public static class PluginInstaller public static async Task CheckForPluginUpdatesAsync(Action> updateAllPlugins, bool silentUpdate = true, bool usePrimaryUrlOnly = false, CancellationToken token = default) { // Update the plugin manifest - await API.UpdatePluginManifestAsync(usePrimaryUrlOnly, token); + await PublicApi.Instance.UpdatePluginManifestAsync(usePrimaryUrlOnly, token); // Get all plugins that can be updated var resultsForUpdate = ( - from existingPlugin in API.GetAllPlugins() - join pluginUpdateSource in API.GetPluginManifest() + from existingPlugin in PublicApi.Instance.GetAllPlugins() + join pluginUpdateSource in PublicApi.Instance.GetPluginManifest() on existingPlugin.Metadata.ID equals pluginUpdateSource.ID where string.Compare(existingPlugin.Metadata.Version, pluginUpdateSource.Version, StringComparison.InvariantCulture) < 0 // if current version precedes version of the plugin from update source (e.g. PluginsManifest) - && !API.PluginModified(existingPlugin.Metadata.ID) + && !PublicApi.Instance.PluginModified(existingPlugin.Metadata.ID) select new PluginUpdateInfo() { @@ -302,19 +298,19 @@ public static class PluginInstaller { if (!silentUpdate) { - API.ShowMsg(Localize.updateNoResultTitle(), Localize.updateNoResultSubtitle()); + PublicApi.Instance.ShowMsg(Localize.updateNoResultTitle(), Localize.updateNoResultSubtitle()); } return; } // If all plugins are modified, just return - if (resultsForUpdate.All(x => API.PluginModified(x.ID))) + if (resultsForUpdate.All(x => PublicApi.Instance.PluginModified(x.ID))) { return; } // Show message box with button to update all plugins - API.ShowMsgWithButton( + PublicApi.Instance.ShowMsgWithButton( Localize.updateAllPluginsTitle(), Localize.updateAllPluginsButtonContent(), () => @@ -350,7 +346,7 @@ public static class PluginInstaller return; } - if (!await API.UpdatePluginAsync(plugin.PluginExistingMetadata, plugin.PluginNewUserPlugin, downloadToFilePath)) + if (!await PublicApi.Instance.UpdatePluginAsync(plugin.PluginExistingMetadata, plugin.PluginNewUserPlugin, downloadToFilePath)) { return; } @@ -359,8 +355,8 @@ public static class PluginInstaller } catch (Exception e) { - API.LogException(ClassName, "Failed to update plugin", e); - API.ShowMsgError(Localize.ErrorUpdatingPlugin()); + PublicApi.Instance.LogException(ClassName, "Failed to update plugin", e); + PublicApi.Instance.ShowMsgError(Localize.ErrorUpdatingPlugin()); } })); @@ -368,11 +364,11 @@ public static class PluginInstaller if (restart) { - API.RestartApp(); + PublicApi.Instance.RestartApp(); } else { - API.ShowMsg( + PublicApi.Instance.ShowMsg( Localize.updatebtn(), Localize.PluginsUpdateSuccessNoRestart()); } @@ -396,7 +392,7 @@ public static class PluginInstaller if (showProgress) { var exceptionHappened = false; - await API.ShowProgressBoxAsync(progressBoxTitle, + await PublicApi.Instance.ShowProgressBoxAsync(progressBoxTitle, async (reportProgress) => { if (reportProgress == null) @@ -408,18 +404,18 @@ public static class PluginInstaller } else { - await API.HttpDownloadAsync(downloadUrl, filePath, reportProgress, cts.Token).ConfigureAwait(false); + await PublicApi.Instance.HttpDownloadAsync(downloadUrl, filePath, reportProgress, cts.Token).ConfigureAwait(false); } }, cts.Cancel); // if exception happened while downloading and user does not cancel downloading, // we need to redownload the plugin if (exceptionHappened && (!cts.IsCancellationRequested)) - await API.HttpDownloadAsync(downloadUrl, filePath, token: cts.Token).ConfigureAwait(false); + await PublicApi.Instance.HttpDownloadAsync(downloadUrl, filePath, token: cts.Token).ConfigureAwait(false); } else { - await API.HttpDownloadAsync(downloadUrl, filePath, token: cts.Token).ConfigureAwait(false); + await PublicApi.Instance.HttpDownloadAsync(downloadUrl, filePath, token: cts.Token).ConfigureAwait(false); } } @@ -446,7 +442,7 @@ public static class PluginInstaller if (!Uri.TryCreate(url, UriKind.Absolute, out var uri) || uri.Host != acceptedHost) return false; - return API.GetAllPlugins().Any(x => + return PublicApi.Instance.GetAllPlugins().Any(x => !string.IsNullOrEmpty(x.Metadata.Website) && x.Metadata.Website.StartsWith(constructedUrlPart) ); diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index ba101d4a7..3090212ba 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core.ExternalPlugins; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.DialogJump; @@ -29,10 +28,6 @@ namespace Flow.Launcher.Core.Plugin public static readonly HashSet GlobalPlugins = new(); public static readonly Dictionary NonGlobalPlugins = new(); - // 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 PluginsSettings Settings; private static readonly ConcurrentBag ModifiedPlugins = new(); @@ -75,12 +70,12 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - API.LogException(ClassName, $"Failed to save plugin {pluginPair.Metadata.Name}", e); + PublicApi.Instance.LogException(ClassName, $"Failed to save plugin {pluginPair.Metadata.Name}", e); } } - API.SavePluginSettings(); - API.SavePluginCaches(); + PublicApi.Instance.SavePluginSettings(); + PublicApi.Instance.SavePluginCaches(); } public static async ValueTask DisposePluginsAsync() @@ -107,7 +102,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - API.LogException(ClassName, $"Failed to dispose plugin {pluginPair.Metadata.Name}", e); + PublicApi.Instance.LogException(ClassName, $"Failed to dispose plugin {pluginPair.Metadata.Name}", e); } } @@ -218,7 +213,7 @@ namespace Flow.Launcher.Core.Plugin { if (string.IsNullOrEmpty(metadata.AssemblyName)) { - API.LogWarn(ClassName, $"AssemblyName is empty for plugin with metadata: {metadata.Name}"); + PublicApi.Instance.LogWarn(ClassName, $"AssemblyName is empty for plugin with metadata: {metadata.Name}"); continue; // Skip if AssemblyName is not set, which can happen for erroneous plugins } metadata.PluginSettingsDirectoryPath = Path.Combine(DataLocation.PluginSettingsDirectory, metadata.AssemblyName); @@ -228,7 +223,7 @@ namespace Flow.Launcher.Core.Plugin { if (string.IsNullOrEmpty(metadata.Name)) { - API.LogWarn(ClassName, $"Name is empty for plugin with metadata: {metadata.Name}"); + PublicApi.Instance.LogWarn(ClassName, $"Name is empty for plugin with metadata: {metadata.Name}"); continue; // Skip if Name is not set, which can happen for erroneous plugins } metadata.PluginSettingsDirectoryPath = Path.Combine(DataLocation.PluginSettingsDirectory, metadata.Name); @@ -249,28 +244,28 @@ namespace Flow.Launcher.Core.Plugin { try { - var milliseconds = await API.StopwatchLogDebugAsync(ClassName, $"Init method time cost for <{pair.Metadata.Name}>", - () => pair.Plugin.InitAsync(new PluginInitContext(pair.Metadata, API))); + var milliseconds = await PublicApi.Instance.StopwatchLogDebugAsync(ClassName, $"Init method time cost for <{pair.Metadata.Name}>", + () => pair.Plugin.InitAsync(new PluginInitContext(pair.Metadata, PublicApi.Instance))); pair.Metadata.InitTime += milliseconds; - API.LogInfo(ClassName, + PublicApi.Instance.LogInfo(ClassName, $"Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>"); } catch (Exception e) { - API.LogException(ClassName, $"Fail to Init plugin: {pair.Metadata.Name}", e); + PublicApi.Instance.LogException(ClassName, $"Fail to Init plugin: {pair.Metadata.Name}", e); if (pair.Metadata.Disabled && pair.Metadata.HomeDisabled) { // If this plugin is already disabled, do not show error message again // Or else it will be shown every time - API.LogDebug(ClassName, $"Skipped init for <{pair.Metadata.Name}> due to error"); + PublicApi.Instance.LogDebug(ClassName, $"Skipped init for <{pair.Metadata.Name}> due to error"); } else { pair.Metadata.Disabled = true; pair.Metadata.HomeDisabled = true; failedPlugins.Enqueue(pair); - API.LogDebug(ClassName, $"Disable plugin <{pair.Metadata.Name}> because init failed"); + PublicApi.Instance.LogDebug(ClassName, $"Disable plugin <{pair.Metadata.Name}> because init failed"); } } })); @@ -298,7 +293,7 @@ namespace Flow.Launcher.Core.Plugin if (!failedPlugins.IsEmpty) { var failed = string.Join(",", failedPlugins.Select(x => x.Metadata.Name)); - API.ShowMsg( + PublicApi.Instance.ShowMsg( Localize.failedToInitializePluginsTitle(), Localize.failedToInitializePluginsMessage(failed), "", @@ -323,7 +318,7 @@ namespace Flow.Launcher.Core.Plugin if (dialogJump && plugin.Plugin is not IAsyncDialogJump) return Array.Empty(); - if (API.PluginModified(plugin.Metadata.ID)) + if (PublicApi.Instance.PluginModified(plugin.Metadata.ID)) return Array.Empty(); return new List @@ -344,7 +339,7 @@ namespace Flow.Launcher.Core.Plugin try { - var milliseconds = await API.StopwatchLogDebugAsync(ClassName, $"Cost for {metadata.Name}", + var milliseconds = await PublicApi.Instance.StopwatchLogDebugAsync(ClassName, $"Cost for {metadata.Name}", async () => results = await pair.Plugin.QueryAsync(query, token).ConfigureAwait(false)); token.ThrowIfCancellationRequested(); @@ -388,7 +383,7 @@ namespace Flow.Launcher.Core.Plugin try { - var milliseconds = await API.StopwatchLogDebugAsync(ClassName, $"Cost for {metadata.Name}", + var milliseconds = await PublicApi.Instance.StopwatchLogDebugAsync(ClassName, $"Cost for {metadata.Name}", async () => results = await ((IAsyncHomeQuery)pair.Plugin).HomeQueryAsync(token).ConfigureAwait(false)); token.ThrowIfCancellationRequested(); @@ -405,7 +400,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - API.LogException(ClassName, $"Failed to query home for plugin: {metadata.Name}", e); + PublicApi.Instance.LogException(ClassName, $"Failed to query home for plugin: {metadata.Name}", e); return null; } return results; @@ -418,7 +413,7 @@ namespace Flow.Launcher.Core.Plugin try { - var milliseconds = await API.StopwatchLogDebugAsync(ClassName, $"Cost for {metadata.Name}", + var milliseconds = await PublicApi.Instance.StopwatchLogDebugAsync(ClassName, $"Cost for {metadata.Name}", async () => results = await ((IAsyncDialogJump)pair.Plugin).QueryDialogJumpAsync(query, token).ConfigureAwait(false)); token.ThrowIfCancellationRequested(); @@ -435,7 +430,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - API.LogException(ClassName, $"Failed to query Dialog Jump for plugin: {metadata.Name}", e); + PublicApi.Instance.LogException(ClassName, $"Failed to query Dialog Jump for plugin: {metadata.Name}", e); return null; } return results; @@ -502,7 +497,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - API.LogException(ClassName, + PublicApi.Instance.LogException(ClassName, $"Can't load context menus for plugin <{pluginPair.Metadata.Name}>", e); } @@ -633,7 +628,7 @@ namespace Flow.Launcher.Core.Plugin { if (PluginModified(existingVersion.ID)) { - API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(existingVersion.Name), + PublicApi.Instance.ShowMsgError(Localize.pluginModifiedAlreadyTitle(existingVersion.Name), Localize.pluginModifiedAlreadyMessage()); return false; } @@ -666,7 +661,7 @@ namespace Flow.Launcher.Core.Plugin { if (checkModified && PluginModified(plugin.ID)) { - API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(plugin.Name), + PublicApi.Instance.ShowMsgError(Localize.pluginModifiedAlreadyTitle(plugin.Name), Localize.pluginModifiedAlreadyMessage()); return false; } @@ -686,14 +681,14 @@ namespace Flow.Launcher.Core.Plugin if (string.IsNullOrEmpty(metadataJsonFilePath) || string.IsNullOrEmpty(pluginFolderPath)) { - API.ShowMsgError(Localize.failedToInstallPluginTitle(plugin.Name), + PublicApi.Instance.ShowMsgError(Localize.failedToInstallPluginTitle(plugin.Name), Localize.fileNotFoundMessage(pluginFolderPath)); return false; } if (SameOrLesserPluginVersionExists(metadataJsonFilePath)) { - API.ShowMsgError(Localize.failedToInstallPluginTitle(plugin.Name), + PublicApi.Instance.ShowMsgError(Localize.failedToInstallPluginTitle(plugin.Name), Localize.pluginExistAlreadyMessage()); return false; } @@ -723,7 +718,7 @@ namespace Flow.Launcher.Core.Plugin var newPluginPath = Path.Combine(installDirectory, folderName); - FilesFolders.CopyAll(pluginFolderPath, newPluginPath, (s) => API.ShowMsgBox(s)); + FilesFolders.CopyAll(pluginFolderPath, newPluginPath, (s) => PublicApi.Instance.ShowMsgBox(s)); try { @@ -732,7 +727,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - API.LogException(ClassName, $"Failed to delete temp folder {tempFolderPluginPath}", e); + PublicApi.Instance.LogException(ClassName, $"Failed to delete temp folder {tempFolderPluginPath}", e); } if (checkModified) @@ -747,7 +742,7 @@ namespace Flow.Launcher.Core.Plugin { if (checkModified && PluginModified(plugin.ID)) { - API.ShowMsgError(Localize.pluginModifiedAlreadyTitle(plugin.Name), + PublicApi.Instance.ShowMsgError(Localize.pluginModifiedAlreadyTitle(plugin.Name), Localize.pluginModifiedAlreadyMessage()); return false; } @@ -767,7 +762,7 @@ namespace Flow.Launcher.Core.Plugin if (removePluginSettings) { // For dotnet plugins, we need to remove their PluginJsonStorage and PluginBinaryStorage instances - if (AllowedLanguage.IsDotNet(plugin.Language) && API is IRemovable removable) + if (AllowedLanguage.IsDotNet(plugin.Language) && PublicApi.Instance is IRemovable removable) { removable.RemovePluginSettings(plugin.AssemblyName); removable.RemovePluginCaches(plugin.PluginCacheDirectoryPath); @@ -781,8 +776,8 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - API.LogException(ClassName, $"Failed to delete plugin settings folder for {plugin.Name}", e); - API.ShowMsgError(Localize.failedToRemovePluginSettingsTitle(), + PublicApi.Instance.LogException(ClassName, $"Failed to delete plugin settings folder for {plugin.Name}", e); + PublicApi.Instance.ShowMsgError(Localize.failedToRemovePluginSettingsTitle(), Localize.failedToRemovePluginSettingsMessage(plugin.Name)); } } @@ -797,8 +792,8 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - API.LogException(ClassName, $"Failed to delete plugin cache folder for {plugin.Name}", e); - API.ShowMsgError(Localize.failedToRemovePluginCacheTitle(), + PublicApi.Instance.LogException(ClassName, $"Failed to delete plugin cache folder for {plugin.Name}", e); + PublicApi.Instance.ShowMsgError(Localize.failedToRemovePluginCacheTitle(), Localize.failedToRemovePluginCacheMessage(plugin.Name)); } Settings.RemovePluginSettings(plugin.ID); diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs index 92dfef2c6..a8a4fba3a 100644 --- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs @@ -2,9 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; -using System.Threading.Tasks; -using System.Windows; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core.ExternalPlugins.Environments; #pragma warning disable IDE0005 using Flow.Launcher.Infrastructure.Logger; @@ -18,10 +15,6 @@ namespace Flow.Launcher.Core.Plugin { 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); @@ -64,7 +57,7 @@ namespace Flow.Launcher.Core.Plugin foreach (var metadata in metadatas) { - var milliseconds = API.StopwatchLogDebug(ClassName, $"Constructor init cost for {metadata.Name}", () => + var milliseconds = PublicApi.Instance.StopwatchLogDebug(ClassName, $"Constructor init cost for {metadata.Name}", () => { Assembly assembly = null; IAsyncPlugin plugin = null; @@ -89,19 +82,19 @@ namespace Flow.Launcher.Core.Plugin #else catch (Exception e) when (assembly == null) { - Log.Exception(ClassName, $"Couldn't load assembly for the plugin: {metadata.Name}", e); + PublicApi.Instance.LogException(ClassName, $"Couldn't load assembly for the plugin: {metadata.Name}", e); } catch (InvalidOperationException e) { - Log.Exception(ClassName, $"Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e); + PublicApi.Instance.LogException(ClassName, $"Can't find the required IPlugin interface for the plugin: <{metadata.Name}>", e); } catch (ReflectionTypeLoadException e) { - Log.Exception(ClassName, $"The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e); + PublicApi.Instance.LogException(ClassName, $"The GetTypes method was unable to load assembly types for the plugin: <{metadata.Name}>", e); } catch (Exception e) { - Log.Exception(ClassName, $"The following plugin has errored and can not be loaded: <{metadata.Name}>", e); + PublicApi.Instance.LogException(ClassName, $"The following plugin has errored and can not be loaded: <{metadata.Name}>", e); } #endif @@ -124,7 +117,7 @@ namespace Flow.Launcher.Core.Plugin Localize.pluginsHaveErrored(): Localize.pluginHasErrored(); - API.ShowMsgError($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + + PublicApi.Instance.ShowMsgError($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + $"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" + Localize.referToLogs()); } diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index 983f8b234..6f373746e 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.UserSettings; @@ -18,10 +17,6 @@ namespace Flow.Launcher.Core.Resource { private static readonly string ClassName = nameof(Internationalization); - // 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 const string Folder = "Languages"; private const string DefaultLanguageCode = "en"; private const string DefaultFile = "en.xaml"; @@ -104,7 +99,7 @@ namespace Flow.Launcher.Core.Resource var directory = Path.Combine(Constant.ProgramDirectory, Folder); if (!Directory.Exists(directory)) { - API.LogError(ClassName, $"Flow Launcher language directory can't be found <{directory}>"); + PublicApi.Instance.LogError(ClassName, $"Flow Launcher language directory can't be found <{directory}>"); return; } @@ -175,7 +170,7 @@ namespace Flow.Launcher.Core.Resource FirstOrDefault(o => o.LanguageCode.Equals(languageCode, StringComparison.OrdinalIgnoreCase)); if (language == null) { - API.LogError(ClassName, $"Language code can't be found <{languageCode}>"); + PublicApi.Instance.LogError(ClassName, $"Language code can't be found <{languageCode}>"); return AvailableLanguages.English; } else @@ -208,7 +203,7 @@ namespace Flow.Launcher.Core.Resource } catch (Exception e) { - API.LogException(ClassName, $"Failed to change language to <{language.LanguageCode}>", e); + PublicApi.Instance.LogException(ClassName, $"Failed to change language to <{language.LanguageCode}>", e); } finally { @@ -254,7 +249,7 @@ namespace Flow.Launcher.Core.Resource // "Do you want to search with pinyin?" string text = languageToSet == AvailableLanguages.Chinese ? "是否启用拼音搜索?" : "是否啓用拼音搜索?"; - if (API.ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) + if (PublicApi.Instance.ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) return false; return true; @@ -311,7 +306,7 @@ namespace Flow.Launcher.Core.Resource } else { - API.LogError(ClassName, $"Language path can't be found <{path}>"); + PublicApi.Instance.LogError(ClassName, $"Language path can't be found <{path}>"); var english = Path.Combine(folder, DefaultFile); if (File.Exists(english)) { @@ -319,7 +314,7 @@ namespace Flow.Launcher.Core.Resource } else { - API.LogError(ClassName, $"Default English Language path can't be found <{path}>"); + PublicApi.Instance.LogError(ClassName, $"Default English Language path can't be found <{path}>"); return string.Empty; } } @@ -354,7 +349,7 @@ namespace Flow.Launcher.Core.Resource } else { - API.LogError(ClassName, $"No Translation for key {key}"); + PublicApi.Instance.LogError(ClassName, $"No Translation for key {key}"); return $"No Translation for key {key}"; } } @@ -377,7 +372,7 @@ namespace Flow.Launcher.Core.Resource } catch (Exception e) { - API.LogException(ClassName, $"Failed for <{p.Metadata.Name}>", e); + PublicApi.Instance.LogException(ClassName, $"Failed for <{p.Metadata.Name}>", e); } } } diff --git a/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs b/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs index 3e1a19a76..acd9d9eb7 100644 --- a/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs +++ b/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs @@ -1,15 +1,9 @@ using System.ComponentModel; -using CommunityToolkit.Mvvm.DependencyInjection; -using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Resource { public class LocalizedDescriptionAttribute : DescriptionAttribute { - // 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) @@ -21,7 +15,7 @@ namespace Flow.Launcher.Core.Resource { get { - string description = API.GetTranslation(_resourceKey); + string description = PublicApi.Instance.GetTranslation(_resourceKey); return string.IsNullOrWhiteSpace(description) ? string.Format("[[{0}]]", _resourceKey) : description; } diff --git a/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs b/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs index 65652878f..9035a541d 100644 --- a/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs +++ b/Flow.Launcher.Infrastructure/DialogJump/DialogJump.cs @@ -58,21 +58,17 @@ namespace Flow.Launcher.Infrastructure.DialogJump private static readonly Settings _settings = Ioc.Default.GetRequiredService(); - // 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 HWND _mainWindowHandle = HWND.Null; private static readonly Dictionary _dialogJumpExplorers = new(); private static DialogJumpExplorerPair _lastExplorer = null; - private static readonly object _lastExplorerLock = new(); + private static readonly Lock _lastExplorerLock = new(); private static readonly Dictionary _dialogJumpDialogs = new(); private static IDialogJumpDialogWindow _dialogWindow = null; - private static readonly object _dialogWindowLock = new(); + private static readonly Lock _dialogWindowLock = new(); private static HWINEVENTHOOK _foregroundChangeHook = HWINEVENTHOOK.Null; private static HWINEVENTHOOK _locationChangeHook = HWINEVENTHOOK.Null; @@ -89,8 +85,8 @@ namespace Flow.Launcher.Infrastructure.DialogJump private static DispatcherTimer _dragMoveTimer = null; // A list of all file dialog windows that are auto switched already - private static readonly List _autoSwitchedDialogs = new(); - private static readonly object _autoSwitchedDialogsLock = new(); + private static readonly List _autoSwitchedDialogs = []; + private static readonly Lock _autoSwitchedDialogsLock = new(); private static HWINEVENTHOOK _moveSizeHook = HWINEVENTHOOK.Null; private static readonly WINEVENTPROC _moveProc = MoveSizeCallBack; @@ -315,7 +311,7 @@ namespace Flow.Launcher.Infrastructure.DialogJump { foreach (var explorer in _dialogJumpExplorers.Keys) { - if (API.PluginModified(explorer.Metadata.ID) || // Plugin is modified + if (PublicApi.Instance.PluginModified(explorer.Metadata.ID) || // Plugin is modified explorer.Metadata.Disabled) continue; // Plugin is disabled var explorerWindow = explorer.Plugin.CheckExplorerWindow(hWnd); @@ -493,7 +489,7 @@ namespace Flow.Launcher.Infrastructure.DialogJump var dialogWindowChanged = false; foreach (var dialog in _dialogJumpDialogs.Keys) { - if (API.PluginModified(dialog.Metadata.ID) || // Plugin is modified + if (PublicApi.Instance.PluginModified(dialog.Metadata.ID) || // Plugin is modified dialog.Metadata.Disabled) continue; // Plugin is disabled IDialogJumpDialogWindow dialogWindow; @@ -596,7 +592,7 @@ namespace Flow.Launcher.Infrastructure.DialogJump { foreach (var explorer in _dialogJumpExplorers.Keys) { - if (API.PluginModified(explorer.Metadata.ID) || // Plugin is modified + if (PublicApi.Instance.PluginModified(explorer.Metadata.ID) || // Plugin is modified explorer.Metadata.Disabled) continue; // Plugin is disabled var explorerWindow = explorer.Plugin.CheckExplorerWindow(hwnd); @@ -871,7 +867,7 @@ namespace Flow.Launcher.Infrastructure.DialogJump // Then check all dialog windows foreach (var dialog in _dialogJumpDialogs.Keys) { - if (API.PluginModified(dialog.Metadata.ID) || // Plugin is modified + if (PublicApi.Instance.PluginModified(dialog.Metadata.ID) || // Plugin is modified dialog.Metadata.Disabled) continue; // Plugin is disabled var dialogWindow = _dialogJumpDialogs[dialog]; @@ -884,7 +880,7 @@ namespace Flow.Launcher.Infrastructure.DialogJump // Finally search for the dialog window again foreach (var dialog in _dialogJumpDialogs.Keys) { - if (API.PluginModified(dialog.Metadata.ID) || // Plugin is modified + if (PublicApi.Instance.PluginModified(dialog.Metadata.ID) || // Plugin is modified dialog.Metadata.Disabled) continue; // Plugin is disabled IDialogJumpDialogWindow dialogWindow; @@ -1067,11 +1063,8 @@ namespace Flow.Launcher.Infrastructure.DialogJump _navigationLock.Dispose(); // Stop drag move timer - if (_dragMoveTimer != null) - { - _dragMoveTimer.Stop(); - _dragMoveTimer = null; - } + _dragMoveTimer?.Stop(); + _dragMoveTimer = null; } #endregion diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 5a4371598..f8c111f36 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -4,10 +4,8 @@ using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; -using Flow.Launcher.Plugin; using JetBrains.Annotations; namespace Flow.Launcher.Infrastructure.Http @@ -20,10 +18,6 @@ namespace Flow.Launcher.Infrastructure.Http private static readonly HttpClient client = new(); - // 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(); - static Http() { // need to be added so it would work on a win10 machine @@ -82,7 +76,7 @@ namespace Flow.Launcher.Infrastructure.Http } catch (UriFormatException e) { - API.ShowMsgError(Localize.pleaseTryAgain(), Localize.parseProxyFailed()); + PublicApi.Instance.ShowMsgError(Localize.pleaseTryAgain(), Localize.parseProxyFailed()); Log.Exception(ClassName, "Unable to parse Uri", e); } } diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs index 2603d4675..a2e95b668 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs @@ -1,8 +1,6 @@ using System; using System.Text.Json.Serialization; using System.Threading.Tasks; -using CommunityToolkit.Mvvm.DependencyInjection; -using Flow.Launcher.Plugin; namespace Flow.Launcher.Infrastructure.UserSettings { @@ -55,11 +53,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings { public string Description { get; set; } - public string LocalizedDescription => API.GetTranslation(Description); - - // 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 string LocalizedDescription => PublicApi.Instance.GetTranslation(Description); public BaseBuiltinShortcutModel(string key, string description) { From 0a7ed3b52f1fe886992209aaff14012522c77b40 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 23 Sep 2025 17:52:49 +0800 Subject: [PATCH 51/73] Add AbstractPluginEnvironment.API back --- .../Environments/AbstractPluginEnvironment.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs index d08ea88b3..1a324a993 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs @@ -14,6 +14,8 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments { private static readonly string ClassName = nameof(AbstractPluginEnvironment); + protected readonly IPublicAPI API = PublicApi.Instance; + internal abstract string Language { get; } internal abstract string EnvName { get; } @@ -56,7 +58,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } var noRuntimeMessage = Localize.runtimePluginInstalledChooseRuntimePrompt(Language, EnvName, Environment.NewLine); - if (PublicApi.Instance.ShowMsgBox(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) + if (API.ShowMsgBox(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) { var msg = Localize.runtimePluginChooseRuntimeExecutable(EnvName); @@ -74,7 +76,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments // Let users select valid path or choose to download while (string.IsNullOrEmpty(selectedFile)) { - if (PublicApi.Instance.ShowMsgBox(forceDownloadMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) + if (API.ShowMsgBox(forceDownloadMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) { // Continue select file selectedFile = GetFileFromDialog(msg, FileDialogFilter); @@ -107,8 +109,8 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } else { - PublicApi.Instance.ShowMsgBox(Localize.runtimePluginUnableToSetExecutablePath(Language)); - PublicApi.Instance.LogError(ClassName, + API.ShowMsgBox(Localize.runtimePluginUnableToSetExecutablePath(Language)); + API.LogError(ClassName, $"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.", $"{Language}Environment"); @@ -122,7 +124,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments { if (expectedPath == currentPath) return; - FilesFolders.RemoveFolderIfExists(installedDirPath, (s) => PublicApi.Instance.ShowMsgBox(s)); + FilesFolders.RemoveFolderIfExists(installedDirPath, (s) => API.ShowMsgBox(s)); InstallEnvironment(); } @@ -235,7 +237,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments private static string GetUpdatedEnvironmentPath(string filePath) { var index = filePath.IndexOf(DataLocation.PluginEnvironments); - + // get the substring after "Environments" because we can not determine it dynamically var executablePathSubstring = filePath[(index + DataLocation.PluginEnvironments.Length)..]; return $"{DataLocation.PluginEnvironmentsPath}{executablePathSubstring}"; From 54622d675958cae10b1f01443d6e6a0aa0eb265c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 23 Sep 2025 17:53:04 +0800 Subject: [PATCH 52/73] Fix Flow.Launcher.Localization contentHash issue --- Flow.Launcher.Core/packages.lock.json | 2 +- Flow.Launcher.Infrastructure/packages.lock.json | 2 +- Flow.Launcher/packages.lock.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Core/packages.lock.json b/Flow.Launcher.Core/packages.lock.json index ab2a1f718..5561319ff 100644 --- a/Flow.Launcher.Core/packages.lock.json +++ b/Flow.Launcher.Core/packages.lock.json @@ -15,7 +15,7 @@ "type": "Direct", "requested": "[0.0.6, )", "resolved": "0.0.6", - "contentHash": "Wwh5lrnmAf66go456h9sSrkdIW3G/IaKPE3+qWZLRAQ86kIe1JovHRj+ljHZXnFOWu1cbFmHg3l1RuqzPLAHow==" + "contentHash": "WNI/TLGPDr3XdOW8gaALN0Uyz9h+bzqOaNZev2nHEuA3HW9o7XuqaM6C0PqNi96mNgxiypwWpVazBNzaylJ2Aw==" }, "FSharp.Core": { "type": "Direct", diff --git a/Flow.Launcher.Infrastructure/packages.lock.json b/Flow.Launcher.Infrastructure/packages.lock.json index 94adc16f1..b14f891b7 100644 --- a/Flow.Launcher.Infrastructure/packages.lock.json +++ b/Flow.Launcher.Infrastructure/packages.lock.json @@ -27,7 +27,7 @@ "type": "Direct", "requested": "[0.0.6, )", "resolved": "0.0.6", - "contentHash": "Wwh5lrnmAf66go456h9sSrkdIW3G/IaKPE3+qWZLRAQ86kIe1JovHRj+ljHZXnFOWu1cbFmHg3l1RuqzPLAHow==" + "contentHash": "WNI/TLGPDr3XdOW8gaALN0Uyz9h+bzqOaNZev2nHEuA3HW9o7XuqaM6C0PqNi96mNgxiypwWpVazBNzaylJ2Aw==" }, "Fody": { "type": "Direct", diff --git a/Flow.Launcher/packages.lock.json b/Flow.Launcher/packages.lock.json index afbbff6b7..f5ff0e55d 100644 --- a/Flow.Launcher/packages.lock.json +++ b/Flow.Launcher/packages.lock.json @@ -18,7 +18,7 @@ "type": "Direct", "requested": "[0.0.6, )", "resolved": "0.0.6", - "contentHash": "Wwh5lrnmAf66go456h9sSrkdIW3G/IaKPE3+qWZLRAQ86kIe1JovHRj+ljHZXnFOWu1cbFmHg3l1RuqzPLAHow==" + "contentHash": "WNI/TLGPDr3XdOW8gaALN0Uyz9h+bzqOaNZev2nHEuA3HW9o7XuqaM6C0PqNi96mNgxiypwWpVazBNzaylJ2Aw==" }, "Fody": { "type": "Direct", From ac62ebadf0a96cd03fa7d8bb5fd38b7246a8aba3 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 23 Sep 2025 18:07:15 +0800 Subject: [PATCH 53/73] Add space for code quality --- .../UserSettings/CustomBrowserViewModel.cs | 2 +- .../UserSettings/CustomExplorerViewModel.cs | 2 +- Flow.Launcher/MainWindow.xaml.cs | 4 ++-- Flow.Launcher/ViewModel/PluginViewModel.cs | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs index 849762867..009b27666 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomBrowserViewModel.cs @@ -7,7 +7,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings { public string Name { get; set; } [JsonIgnore] - public string DisplayName => Name == "Default" ? Localize.defaultBrowser_default(): Name; + public string DisplayName => Name == "Default" ? Localize.defaultBrowser_default() : Name; public string Path { get; set; } public string PrivateArg { get; set; } public bool EnablePrivate { get; set; } diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs index ffc48b244..ae406f4c5 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomExplorerViewModel.cs @@ -7,7 +7,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings { public string Name { get; set; } [JsonIgnore] - public string DisplayName => Name == "Explorer" ? Localize.fileManagerExplorer(): Name; + public string DisplayName => Name == "Explorer" ? Localize.fileManagerExplorer() : Name; public string Path { get; set; } public string FileArgument { get; set; } = "\"%d\""; public string DirectoryArgument { get; set; } = "\"%d\""; diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 21cb124b0..c4ed73a0d 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -753,7 +753,7 @@ namespace Flow.Launcher private void UpdateNotifyIconText() { var menu = _contextMenu; - ((MenuItem)menu.Items[0]).Header = Localize.iconTrayOpen()+ + ((MenuItem)menu.Items[0]).Header = Localize.iconTrayOpen() + " (" + _settings.Hotkey + ")"; ((MenuItem)menu.Items[1]).Header = Localize.GameMode(); ((MenuItem)menu.Items[2]).Header = Localize.PositionReset(); @@ -768,7 +768,7 @@ namespace Flow.Launcher var openIcon = new FontIcon { Glyph = "\ue71e" }; var open = new MenuItem { - Header = Localize.iconTrayOpen()+ " (" + _settings.Hotkey + ")", + Header = Localize.iconTrayOpen() + " (" + _settings.Hotkey + ")", Icon = openIcon }; var gamemodeIcon = new FontIcon { Glyph = "\ue7fc" }; diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 87d1839c7..bf7720651 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -164,11 +164,11 @@ namespace Flow.Launcher.ViewModel Visibility.Collapsed : Visibility.Visible; public string InitializeTime => PluginPair.Metadata.InitTime + "ms"; public string QueryTime => PluginPair.Metadata.AvgQueryTime + "ms"; - public string Version => Localize.plugin_query_version()+ " " + PluginPair.Metadata.Version; + public string Version => Localize.plugin_query_version() + " " + PluginPair.Metadata.Version; public string InitAndQueryTime => - Localize.plugin_init_time()+ " " + + Localize.plugin_init_time() + " " + PluginPair.Metadata.InitTime + "ms, " + - Localize.plugin_query_time()+ " " + + Localize.plugin_query_time() + " " + PluginPair.Metadata.AvgQueryTime + "ms"; public string ActionKeywordsText => string.Join(Query.ActionKeywordSeparator, PluginPair.Metadata.ActionKeywords); public string SearchDelayTimeText => PluginPair.Metadata.SearchDelayTime == null ? From 3bd6906c800932c944bd037fa20ad8e0474645b0 Mon Sep 17 00:00:00 2001 From: Spencer Stream Date: Tue, 23 Sep 2025 07:19:39 -0500 Subject: [PATCH 54/73] Validate iconPath exists --- Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs index 9f38a64df..011f01ca5 100644 --- a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs +++ b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs @@ -133,8 +133,9 @@ namespace Flow.Launcher.Infrastructure.Image var urlSection = data["InternetShortcut"]; var iconPath = urlSection?["IconFile"]; - if (string.IsNullOrEmpty(iconPath)) + if (!File.Exists(iconPath)) { + // If the IconFile is missing, throw exception to fallback to the default icon throw new FileNotFoundException("Icon file not specified in Internet shortcut (.url) file."); } hBitmap = GetHBitmap(Path.GetFullPath(iconPath), width, height, options); From 9b2d36b78a79ba6493555eda12ef1595c732a5d6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 23 Sep 2025 20:48:41 +0800 Subject: [PATCH 55/73] Revert "Catch exception" This reverts commit 49d5cd36df9bb788e1899cfbe61dbd60fa0b17c1. --- Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs index 9f38a64df..c942488c4 100644 --- a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs +++ b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs @@ -141,15 +141,7 @@ namespace Flow.Launcher.Infrastructure.Image } catch { - try - { - hBitmap = GetHBitmap(Path.GetFullPath(fileName), width, height, options); - } - catch (System.Exception ex) - { - // Handle other exceptions - throw new InvalidOperationException("Failed to get thumbnail", ex); - } + hBitmap = GetHBitmap(Path.GetFullPath(fileName), width, height, options); } return hBitmap; From ba7de5d33d4b8ae6a35f587ebd2ae022267a665a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 23 Sep 2025 21:39:42 +0800 Subject: [PATCH 56/73] Add documents --- .../Image/ThumbnailReader.cs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs index 3b6f66bca..86f757eb8 100644 --- a/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs +++ b/Flow.Launcher.Infrastructure/Image/ThumbnailReader.cs @@ -38,6 +38,17 @@ namespace Flow.Launcher.Infrastructure.Image private const string UrlExtension = ".url"; + /// + /// Obtains a BitmapSource thumbnail for the specified file. + /// + /// + /// If the file is a Windows URL shortcut (".url"), the method attempts to resolve the shortcut's icon and use that for the thumbnail; otherwise it requests a thumbnail for the file path. The native HBITMAP used to create the BitmapSource is always released to avoid native memory leaks. + /// + /// Path to the file (can be a regular file or a ".url" shortcut). + /// Requested thumbnail width in pixels. + /// Requested thumbnail height in pixels. + /// Thumbnail extraction options (flags) controlling fallback and caching behavior. + /// A BitmapSource representing the requested thumbnail. public static BitmapSource GetThumbnail(string fileName, int width, int height, ThumbnailOptions options) { HBITMAP hBitmap; @@ -63,6 +74,21 @@ namespace Flow.Launcher.Infrastructure.Image } } + /// + /// Obtains a native HBITMAP for the specified file at the requested size using the Windows Shell image factory. + /// + /// + /// If is and thumbnail extraction fails + /// due to extraction errors or a missing path, the method falls back to requesting an icon (). + /// The returned HBITMAP is a raw GDI handle; the caller is responsible for releasing it (e.g., via DeleteObject) to avoid native memory leaks. + /// + /// Path to the file to thumbnail. + /// Requested thumbnail width in pixels. + /// Requested thumbnail height in pixels. + /// Thumbnail request flags that control behavior (e.g., ThumbnailOnly, IconOnly). + /// An HBITMAP handle containing the image. Caller must free the handle when finished. + /// If creating the shell item fails (HRESULT returned by SHCreateItemFromParsingName). + /// If the shell item does not expose IShellItemImageFactory or if an unexpected error occurs while obtaining the image. private static unsafe HBITMAP GetHBitmap(string fileName, int width, int height, ThumbnailOptions options) { var retCode = PInvoke.SHCreateItemFromParsingName( @@ -122,6 +148,19 @@ namespace Flow.Launcher.Infrastructure.Image return hBitmap; } + /// + /// Obtains an HBITMAP for a Windows .url shortcut by resolving its IconFile entry and delegating to GetHBitmap. + /// + /// + /// The method parses the .url file as an INI, looks in the "InternetShortcut" section for the "IconFile" entry, + /// and requests a bitmap for that icon path. If no IconFile is present or any error occurs while reading or + /// resolving the icon, it falls back to requesting a thumbnail for the .url file itself. + /// + /// Path to the .url shortcut file. + /// Requested thumbnail width (pixels). + /// Requested thumbnail height (pixels). + /// ThumbnailOptions flags controlling extraction behavior. + /// An HBITMAP containing the requested image; callers are responsible for freeing the native handle. private static unsafe HBITMAP GetHBitmapForUrlFile(string fileName, int width, int height, ThumbnailOptions options) { HBITMAP hBitmap; From a76e2fea7f4febf7aff1c258ba5997ea49ba996a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Sep 2025 22:06:58 +0000 Subject: [PATCH 57/73] Bump SkiaSharp from 3.119.0 to 3.119.1 --- updated-dependencies: - dependency-name: SkiaSharp dependency-version: 3.119.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../Flow.Launcher.Plugin.BrowserBookmark.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 8a9162e62..5116642ca 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -107,7 +107,7 @@ - + From 5b6ea73513ea4927fc5ade8081e9fd86787e2fde Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Sun, 28 Sep 2025 00:18:33 +0800 Subject: [PATCH 58/73] Code cleanup & Use Flow.Launcher.Localization to improve code quality (#4009) * Use Flow.Launcher.Localization to improve code quality * Code cleanup * Improve code quality * Improve code quality * Use internal static Context & Improve code quality * Use Flow.Launcher.Localization to improve code quality * Code cleanup * Use Flow.Launcher.Localization to improve code quality * Improve code quality * Improve code quality * Use Flow.Launcher.Localization to improve code quality * Fix logic issue * Fix the variable name typo * Fix redundant boolean cast and ensure consistent default value handling * Use Flow.Launcher.Localization to improve code quality * Revert namespace styles * Fix indent format * Revert namespace style * Fix indent format * Fix namespace style * Fix indent format * Fix indent format --- .../DecimalSeparator.cs | 6 +- .../Flow.Launcher.Plugin.Calculator/Main.cs | 20 +-- .../Settings.cs | 3 +- ...low.Launcher.Plugin.PluginIndicator.csproj | 5 + .../Main.cs | 34 ++--- .../Flow.Launcher.Plugin.ProcessKiller.csproj | 2 + .../Main.cs | 64 ++++----- .../ProcessHelper.cs | 16 +-- .../ProcessResult.cs | 21 +-- .../ViewModels/SettingsViewModel.cs | 21 +-- .../Views/SettingsControl.xaml | 6 +- .../Views/SettingsControl.xaml.cs | 3 - .../Flow.Launcher.Plugin.Shell.csproj | 2 + Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 52 ++++---- .../Flow.Launcher.Plugin.Shell/Settings.cs | 12 +- .../ShellSetting.xaml.cs | 13 +- .../CommandKeywordSetting.xaml.cs | 10 +- .../Flow.Launcher.Plugin.Sys.csproj | 2 + .../Languages/en.xaml | 5 + Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 122 +++++++++--------- Plugins/Flow.Launcher.Plugin.Sys/Settings.cs | 6 +- .../SettingsViewModel.cs | 9 +- .../SysSettings.xaml.cs | 11 +- .../Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 61 ++++----- .../Flow.Launcher.Plugin.Url.csproj | 5 + Plugins/Flow.Launcher.Plugin.Url/Main.cs | 14 +- 26 files changed, 252 insertions(+), 273 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/DecimalSeparator.cs b/Plugins/Flow.Launcher.Plugin.Calculator/DecimalSeparator.cs index b3f5a8b4b..895515caa 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/DecimalSeparator.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/DecimalSeparator.cs @@ -7,10 +7,10 @@ namespace Flow.Launcher.Plugin.Calculator { [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_calculator_decimal_separator_use_system_locale))] UseSystemLocale, - + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_calculator_decimal_separator_dot))] - Dot, - + Dot, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_calculator_decimal_separator_comma))] Comma } diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs index 9d5e4700f..a20a1ad5d 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Main.cs @@ -5,9 +5,9 @@ using System.Linq; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Windows.Controls; -using Mages.Core; -using Flow.Launcher.Plugin.Calculator.Views; using Flow.Launcher.Plugin.Calculator.ViewModels; +using Flow.Launcher.Plugin.Calculator.Views; +using Mages.Core; namespace Flow.Launcher.Plugin.Calculator { @@ -26,7 +26,7 @@ namespace Flow.Launcher.Plugin.Calculator private const string IcoPath = "Images/calculator.png"; private static readonly List EmptyResults = []; - internal static PluginInitContext Context { get; set; } = null!; + internal static PluginInitContext Context { get; private set; } = null!; private Settings _settings; private SettingsViewModel _viewModel; @@ -57,10 +57,10 @@ namespace Flow.Launcher.Plugin.Calculator { var search = query.Search; bool isFunctionPresent = FunctionRegex.IsMatch(search); - + // Mages is case sensitive, so we need to convert all function names to lower case. search = FunctionRegex.Replace(search, m => m.Value.ToLowerInvariant()); - + var decimalSep = GetDecimalSeparator(); var groupSep = GetGroupSeparator(decimalSep); var expression = NumberRegex.Replace(search, m => NormalizeNumber(m.Value, isFunctionPresent, decimalSep, groupSep)); @@ -292,7 +292,7 @@ namespace Flow.Launcher.Plugin.Calculator { processedStr = processedStr.Replace(decimalSep, "."); } - + return processedStr; } else @@ -310,7 +310,7 @@ namespace Flow.Launcher.Plugin.Calculator return processedStr; } } - + private static bool IsValidGrouping(string[] parts, int[] groupSizes) { if (parts.Length <= 1) return true; @@ -326,7 +326,7 @@ namespace Flow.Launcher.Plugin.Calculator var lastGroupSize = groupSizes.Last(); var canRepeatLastGroup = lastGroupSize != 0; - + int groupIndex = 0; for (int i = parts.Length - 1; i > 0; i--) { @@ -335,7 +335,7 @@ namespace Flow.Launcher.Plugin.Calculator { expectedSize = groupSizes[groupIndex]; } - else if(canRepeatLastGroup) + else if (canRepeatLastGroup) { expectedSize = lastGroupSize; } @@ -345,7 +345,7 @@ namespace Flow.Launcher.Plugin.Calculator } if (parts[i].Length != expectedSize) return false; - + groupIndex++; } diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs b/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs index cac0f3080..1544dc41f 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Settings.cs @@ -1,5 +1,4 @@ - -namespace Flow.Launcher.Plugin.Calculator; +namespace Flow.Launcher.Plugin.Calculator; public class Settings { 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 d8db0abe1..9002a3a4a 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj @@ -32,6 +32,7 @@ prompt 4 false + $(NoWarn);FLSG0007 @@ -54,5 +55,9 @@ PreserveNewest + + + + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs index 48717816b..503d82cc3 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs @@ -5,19 +5,19 @@ namespace Flow.Launcher.Plugin.PluginIndicator { public class Main : IPlugin, IPluginI18n, IHomeQuery { - internal PluginInitContext Context { get; private set; } + internal static PluginInitContext Context { get; private set; } + + public void Init(PluginInitContext context) + { + Context = context; + } public List Query(Query query) { return QueryResults(query); } - public List HomeQuery() - { - return QueryResults(); - } - - private List QueryResults(Query query = null) + private static List QueryResults(Query query = null) { var nonGlobalPlugins = GetNonGlobalPlugins(); var querySearch = query?.Search ?? string.Empty; @@ -34,7 +34,7 @@ namespace Flow.Launcher.Plugin.PluginIndicator select new Result { Title = keyword, - SubTitle = string.Format(Context.API.GetTranslation("flowlauncher_plugin_pluginindicator_result_subtitle"), plugin.Name), + SubTitle = Localize.flowlauncher_plugin_pluginindicator_result_subtitle(plugin.Name), Score = score, IcoPath = plugin.IcoPath, AutoCompleteText = $"{keyword}{Plugin.Query.TermSeparator}", @@ -44,10 +44,10 @@ namespace Flow.Launcher.Plugin.PluginIndicator return false; } }; - return results.ToList(); + return [.. results]; } - private Dictionary GetNonGlobalPlugins() + private static Dictionary GetNonGlobalPlugins() { var nonGlobalPlugins = new Dictionary(); foreach (var plugin in Context.API.GetAllPlugins()) @@ -66,19 +66,19 @@ namespace Flow.Launcher.Plugin.PluginIndicator return nonGlobalPlugins; } - public void Init(PluginInitContext context) - { - Context = context; - } - public string GetTranslatedPluginTitle() { - return Context.API.GetTranslation("flowlauncher_plugin_pluginindicator_plugin_name"); + return Localize.flowlauncher_plugin_pluginindicator_plugin_name(); } public string GetTranslatedPluginDescription() { - return Context.API.GetTranslation("flowlauncher_plugin_pluginindicator_plugin_description"); + return Localize.flowlauncher_plugin_pluginindicator_plugin_description(); + } + + public List HomeQuery() + { + return QueryResults(); } } } 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 0a7a02a45..39586771f 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj @@ -35,6 +35,7 @@ prompt 4 false + $(NoWarn);FLSG0007 @@ -52,6 +53,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index 8f5ba4bd2..44746fa62 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -9,19 +9,19 @@ namespace Flow.Launcher.Plugin.ProcessKiller { public class Main : IPlugin, IPluginI18n, IContextMenu, ISettingProvider { + internal static PluginInitContext Context { get; private set; } + + private Settings _settings; + private readonly ProcessHelper processHelper = new(); - private static PluginInitContext _context; - - internal Settings Settings; - private SettingsViewModel _viewModel; public void Init(PluginInitContext context) { - _context = context; - Settings = context.API.LoadSettingJsonStorage(); - _viewModel = new SettingsViewModel(Settings); + Context = context; + _settings = context.API.LoadSettingJsonStorage(); + _viewModel = new SettingsViewModel(_settings); } public List Query(Query query) @@ -31,12 +31,12 @@ namespace Flow.Launcher.Plugin.ProcessKiller public string GetTranslatedPluginTitle() { - return _context.API.GetTranslation("flowlauncher_plugin_processkiller_plugin_name"); + return Localize.flowlauncher_plugin_processkiller_plugin_name(); } public string GetTranslatedPluginDescription() { - return _context.API.GetTranslation("flowlauncher_plugin_processkiller_plugin_description"); + return Localize.flowlauncher_plugin_processkiller_plugin_description(); } public List LoadContextMenus(Result result) @@ -51,13 +51,13 @@ namespace Flow.Launcher.Plugin.ProcessKiller { menuOptions.Add(new Result { - Title = _context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_instances"), + Title = Localize.flowlauncher_plugin_processkiller_kill_instances(), SubTitle = processPath, Action = _ => { foreach (var p in similarProcesses) { - processHelper.TryKill(_context, p); + ProcessHelper.TryKill(p); } return true; @@ -72,8 +72,8 @@ namespace Flow.Launcher.Plugin.ProcessKiller private List CreateResultsFromQuery(Query query) { // Get all non-system processes - var allPocessList = processHelper.GetMatchingProcesses(); - if (!allPocessList.Any()) + var allProcessList = processHelper.GetMatchingProcesses(); + if (allProcessList.Count == 0) { return null; } @@ -82,12 +82,12 @@ namespace Flow.Launcher.Plugin.ProcessKiller var searchTerm = query.Search; var processlist = new List(); var processWindowTitle = - Settings.ShowWindowTitle || Settings.PutVisibleWindowProcessesTop ? + _settings.ShowWindowTitle || _settings.PutVisibleWindowProcessesTop ? ProcessHelper.GetProcessesWithNonEmptyWindowTitle() : - new Dictionary(); + []; if (string.IsNullOrWhiteSpace(searchTerm)) { - foreach (var p in allPocessList) + foreach (var p in allProcessList) { var progressNameIdTitle = ProcessHelper.GetProcessNameIdTitle(p); @@ -97,8 +97,8 @@ namespace Flow.Launcher.Plugin.ProcessKiller // Use window title for those processes if enabled processlist.Add(new ProcessResult( p, - Settings.PutVisibleWindowProcessesTop ? 200 : 0, - Settings.ShowWindowTitle ? windowTitle : progressNameIdTitle, + _settings.PutVisibleWindowProcessesTop ? 200 : 0, + _settings.ShowWindowTitle ? windowTitle : progressNameIdTitle, null, progressNameIdTitle)); } @@ -115,35 +115,35 @@ namespace Flow.Launcher.Plugin.ProcessKiller } else { - foreach (var p in allPocessList) + foreach (var p in allProcessList) { var progressNameIdTitle = ProcessHelper.GetProcessNameIdTitle(p); if (processWindowTitle.TryGetValue(p.Id, out var windowTitle)) { // Get max score from searching process name, window title and process id - var windowTitleMatch = _context.API.FuzzySearch(searchTerm, windowTitle); - var processNameIdMatch = _context.API.FuzzySearch(searchTerm, progressNameIdTitle); + var windowTitleMatch = Context.API.FuzzySearch(searchTerm, windowTitle); + var processNameIdMatch = Context.API.FuzzySearch(searchTerm, progressNameIdTitle); var score = Math.Max(windowTitleMatch.Score, processNameIdMatch.Score); if (score > 0) { // Add score to prioritize processes with visible windows // Use window title for those processes - if (Settings.PutVisibleWindowProcessesTop) + if (_settings.PutVisibleWindowProcessesTop) { score += 200; } processlist.Add(new ProcessResult( p, score, - Settings.ShowWindowTitle ? windowTitle : progressNameIdTitle, + _settings.ShowWindowTitle ? windowTitle : progressNameIdTitle, score == windowTitleMatch.Score ? windowTitleMatch : null, progressNameIdTitle)); } } else { - var processNameIdMatch = _context.API.FuzzySearch(searchTerm, progressNameIdTitle); + var processNameIdMatch = Context.API.FuzzySearch(searchTerm, progressNameIdTitle); var score = processNameIdMatch.Score; if (score > 0) { @@ -162,7 +162,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller foreach (var pr in processlist) { var p = pr.Process; - var path = processHelper.TryGetProcessFilename(p); + var path = ProcessHelper.TryGetProcessFilename(p); results.Add(new Result() { IcoPath = path, @@ -172,12 +172,12 @@ namespace Flow.Launcher.Plugin.ProcessKiller TitleHighlightData = pr.TitleMatch?.MatchData, Score = pr.Score, ContextData = p.ProcessName, - AutoCompleteText = $"{_context.CurrentPluginMetadata.ActionKeyword}{Plugin.Query.TermSeparator}{p.ProcessName}", + AutoCompleteText = $"{Context.CurrentPluginMetadata.ActionKeyword}{Plugin.Query.TermSeparator}{p.ProcessName}", Action = (c) => { - processHelper.TryKill(_context, p); + ProcessHelper.TryKill(p); // Re-query to refresh process list - _context.API.ReQuery(); + Context.API.ReQuery(); return true; } }); @@ -194,17 +194,17 @@ namespace Flow.Launcher.Plugin.ProcessKiller sortedResults.Insert(1, new Result() { IcoPath = firstResult?.IcoPath, - Title = string.Format(_context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_all"), firstResult?.ContextData), - SubTitle = string.Format(_context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_all_count"), processlist.Count), + Title = Localize.flowlauncher_plugin_processkiller_kill_all(firstResult?.ContextData), + SubTitle = Localize.flowlauncher_plugin_processkiller_kill_all_count(processlist.Count), Score = 200, Action = (c) => { foreach (var p in processlist) { - processHelper.TryKill(_context, p.Process); + ProcessHelper.TryKill(p.Process); } // Re-query to refresh process list - _context.API.ReQuery(); + Context.API.ReQuery(); return true; } }); diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs index cea34f7dc..0e2f78f87 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs @@ -16,8 +16,8 @@ namespace Flow.Launcher.Plugin.ProcessKiller { private static readonly string ClassName = nameof(ProcessHelper); - private readonly HashSet _systemProcessList = new() - { + private readonly HashSet _systemProcessList = + [ "conhost", "svchost", "idle", @@ -31,12 +31,12 @@ namespace Flow.Launcher.Plugin.ProcessKiller "winlogon", "services", "spoolsv", - "explorer" - }; + "explorer" + ]; private const string FlowLauncherProcessName = "Flow.Launcher"; - private bool IsSystemProcessOrFlowLauncher(Process p) => + private bool IsSystemProcessOrFlowLauncher(Process p) => _systemProcessList.Contains(p.ProcessName.ToLower()) || string.Equals(p.ProcessName, FlowLauncherProcessName, StringComparison.OrdinalIgnoreCase); @@ -142,7 +142,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller return Process.GetProcesses().Where(p => !IsSystemProcessOrFlowLauncher(p) && TryGetProcessFilename(p) == processPath); } - public void TryKill(PluginInitContext context, Process p) + public static void TryKill(Process p) { try { @@ -154,11 +154,11 @@ namespace Flow.Launcher.Plugin.ProcessKiller } catch (Exception e) { - context.API.LogException(ClassName, $"Failed to kill process {p.ProcessName}", e); + Main.Context.API.LogException(ClassName, $"Failed to kill process {p.ProcessName}", e); } } - public unsafe string TryGetProcessFilename(Process p) + public static unsafe string TryGetProcessFilename(Process p) { try { diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessResult.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessResult.cs index 146c9c92c..10a1ebe4a 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessResult.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessResult.cs @@ -3,25 +3,16 @@ using Flow.Launcher.Plugin.SharedModels; namespace Flow.Launcher.Plugin.ProcessKiller { - internal class ProcessResult + internal class ProcessResult(Process process, int score, string title, MatchResult match, string tooltip) { - public ProcessResult(Process process, int score, string title, MatchResult match, string tooltip) - { - Process = process; - Score = score; - Title = title; - TitleMatch = match; - Tooltip = tooltip; - } + public Process Process { get; } = process; - public Process Process { get; } + public int Score { get; } = score; - public int Score { get; } + public string Title { get; } = title; - public string Title { get; } + public MatchResult TitleMatch { get; } = match; - public MatchResult TitleMatch { get; } - - public string Tooltip { get; } + public string Tooltip { get; } = tooltip; } } diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ViewModels/SettingsViewModel.cs index 0728d9c0f..02690b9e5 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ViewModels/SettingsViewModel.cs @@ -1,24 +1,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller.ViewModels { - public class SettingsViewModel + public class SettingsViewModel(Settings settings) { - public Settings Settings { get; set; } - - public SettingsViewModel(Settings settings) - { - Settings = settings; - } - - public bool ShowWindowTitle - { - get => Settings.ShowWindowTitle; - set => Settings.ShowWindowTitle = value; - } - - public bool PutVisibleWindowProcessesTop - { - get => Settings.PutVisibleWindowProcessesTop; - set => Settings.PutVisibleWindowProcessesTop = value; - } + public Settings Settings { get; set; } = settings; } } diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Views/SettingsControl.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Views/SettingsControl.xaml index b969be4e8..761570aff 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Views/SettingsControl.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Views/SettingsControl.xaml @@ -4,6 +4,8 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:vm="clr-namespace:Flow.Launcher.Plugin.ProcessKiller.ViewModels" + d:DataContext="{d:DesignInstance Type=vm:SettingsViewModel}" d:DesignHeight="300" d:DesignWidth="500" mc:Ignorable="d"> @@ -18,11 +20,11 @@ Grid.Row="0" Margin="{StaticResource SettingPanelItemRightTopBottomMargin}" Content="{DynamicResource flowlauncher_plugin_processkiller_show_window_title}" - IsChecked="{Binding ShowWindowTitle}" /> + IsChecked="{Binding Settings.ShowWindowTitle}" /> + IsChecked="{Binding Settings.PutVisibleWindowProcessesTop}" /> \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Views/SettingsControl.xaml.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Views/SettingsControl.xaml.cs index a066ab6a9..7e712da61 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Views/SettingsControl.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Views/SettingsControl.xaml.cs @@ -5,9 +5,6 @@ namespace Flow.Launcher.Plugin.ProcessKiller.Views; public partial class SettingsControl : UserControl { - /// - /// Interaction logic for SettingsControl.xaml - /// public SettingsControl(SettingsViewModel viewModel) { InitializeComponent(); 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 5c3475133..e6932709f 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj +++ b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj @@ -34,6 +34,7 @@ prompt 4 false + $(NoWarn);FLSG0007 @@ -58,6 +59,7 @@ + diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index a86b96800..2440facd0 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -1,13 +1,13 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; +using Flow.Launcher.Plugin.SharedCommands; using WindowsInput; using WindowsInput.Native; -using Flow.Launcher.Plugin.SharedCommands; using Control = System.Windows.Controls.Control; using Keys = System.Windows.Forms.Keys; @@ -17,7 +17,7 @@ namespace Flow.Launcher.Plugin.Shell { private static readonly string ClassName = nameof(Main); - internal PluginInitContext Context { get; private set; } + internal static PluginInitContext Context { get; private set; } private const string Image = "Images/shell.png"; private bool _winRStroked; @@ -27,7 +27,7 @@ namespace Flow.Launcher.Plugin.Shell public List Query(Query query) { - List results = new List(); + List results = []; string cmd = query.Search; if (string.IsNullOrEmpty(cmd)) { @@ -45,7 +45,7 @@ namespace Flow.Launcher.Plugin.Shell string basedir = null; string dir = null; string excmd = Environment.ExpandEnvironmentVariables(cmd); - if (Directory.Exists(excmd) && (cmd.EndsWith("/") || cmd.EndsWith(@"\"))) + if (Directory.Exists(excmd) && (cmd.EndsWith('/') || cmd.EndsWith('\\'))) { basedir = excmd; dir = cmd; @@ -54,7 +54,7 @@ namespace Flow.Launcher.Plugin.Shell { basedir = Path.GetDirectoryName(excmd); var dirName = Path.GetDirectoryName(cmd); - dir = (dirName.EndsWith("/") || dirName.EndsWith(@"\")) ? dirName : cmd[..(dirName.Length + 1)]; + dir = (dirName.EndsWith('/') || dirName.EndsWith('\\')) ? dirName : cmd[..(dirName.Length + 1)]; } if (basedir != null) @@ -103,14 +103,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 = Localize.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 = Localize.flowlauncher_plugin_cmd_cmd_has_been_executed_times(m.Value), IcoPath = Image, Action = c => { @@ -129,9 +129,9 @@ namespace Flow.Launcher.Plugin.Shell }).Where(o => o != null); if (_settings.ShowOnlyMostUsedCMDs) - return history.Take(_settings.ShowOnlyMostUsedCMDsNumber).ToList(); + return [.. history.Take(_settings.ShowOnlyMostUsedCMDsNumber)]; - return history.ToList(); + return [.. history]; } private Result GetCurrentCmd(string cmd) @@ -140,7 +140,7 @@ namespace Flow.Launcher.Plugin.Shell { Title = cmd, Score = 5000, - SubTitle = Context.API.GetTranslation("flowlauncher_plugin_cmd_execute_through_shell"), + SubTitle = Localize.flowlauncher_plugin_cmd_execute_through_shell(), IcoPath = Image, Action = c => { @@ -165,7 +165,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 = Localize.flowlauncher_plugin_cmd_cmd_has_been_executed_times(m.Value), IcoPath = Image, Action = c => { @@ -182,9 +182,9 @@ namespace Flow.Launcher.Plugin.Shell }); if (_settings.ShowOnlyMostUsedCMDs) - return history.Take(_settings.ShowOnlyMostUsedCMDsNumber).ToList(); + return [.. history.Take(_settings.ShowOnlyMostUsedCMDsNumber)]; - return history.ToList(); + return [.. history]; } private ProcessStartInfo PrepareProcessStartInfo(string command, bool runAsAdministrator = false) @@ -199,7 +199,7 @@ namespace Flow.Launcher.Plugin.Shell Verb = runAsAdministratorArg, WorkingDirectory = workingDirectory, }; - var notifyStr = Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close"); + var notifyStr = Localize.flowlauncher_plugin_cmd_press_any_key_to_close(); var addedCharacter = _settings.UseWindowsTerminal ? "\\" : ""; switch (_settings.Shell) { @@ -288,10 +288,10 @@ namespace Flow.Launcher.Plugin.Shell case Shell.RunCommand: { - var parts = command.Split(new[] - { + var parts = command.Split( + [ ' ' - }, 2); + ], 2); if (parts.Length == 2) { var filename = parts[0]; @@ -336,12 +336,12 @@ namespace Flow.Launcher.Plugin.Shell catch (FileNotFoundException e) { Context.API.ShowMsgError(GetTranslatedPluginTitle(), - string.Format(Context.API.GetTranslation("flowlauncher_plugin_cmd_command_not_found"), e.Message)); + Localize.flowlauncher_plugin_cmd_command_not_found(e.Message)); } catch (Win32Exception e) { Context.API.ShowMsgError(GetTranslatedPluginTitle(), - string.Format(Context.API.GetTranslation("flowlauncher_plugin_cmd_error_running_command"), e.Message)); + Localize.flowlauncher_plugin_cmd_error_running_command(e.Message)); } catch (Exception e) { @@ -405,7 +405,7 @@ namespace Flow.Launcher.Plugin.Shell return true; } - private void OnWinRPressed() + private static void OnWinRPressed() { Context.API.ShowMainWindow(); // show the main window and set focus to the query box @@ -428,12 +428,12 @@ namespace Flow.Launcher.Plugin.Shell public string GetTranslatedPluginTitle() { - return Context.API.GetTranslation("flowlauncher_plugin_cmd_plugin_name"); + return Localize.flowlauncher_plugin_cmd_plugin_name(); } public string GetTranslatedPluginDescription() { - return Context.API.GetTranslation("flowlauncher_plugin_cmd_plugin_description"); + return Localize.flowlauncher_plugin_cmd_plugin_description(); } public List LoadContextMenus(Result selectedResult) @@ -442,7 +442,7 @@ namespace Flow.Launcher.Plugin.Shell { new() { - Title = Context.API.GetTranslation("flowlauncher_plugin_cmd_run_as_different_user"), + Title = Localize.flowlauncher_plugin_cmd_run_as_different_user(), Action = c => { Execute(ShellCommand.RunAsDifferentUser, PrepareProcessStartInfo(selectedResult.Title)); @@ -453,7 +453,7 @@ namespace Flow.Launcher.Plugin.Shell }, new() { - Title = Context.API.GetTranslation("flowlauncher_plugin_cmd_run_as_administrator"), + Title = Localize.flowlauncher_plugin_cmd_run_as_administrator(), Action = c => { Execute(Process.Start, PrepareProcessStartInfo(selectedResult.Title, true)); @@ -464,7 +464,7 @@ namespace Flow.Launcher.Plugin.Shell }, new() { - Title = Context.API.GetTranslation("flowlauncher_plugin_cmd_copy"), + Title = Localize.flowlauncher_plugin_cmd_copy(), Action = c => { Context.API.CopyToClipboard(selectedResult.Title); diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs b/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs index 9ce2293a2..4616a18ec 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs @@ -5,11 +5,11 @@ namespace Flow.Launcher.Plugin.Shell public class Settings { public Shell Shell { get; set; } = Shell.Cmd; - + public bool ReplaceWinR { get; set; } = false; public bool CloseShellAfterPress { get; set; } = false; - + public bool LeaveShellOpen { get; set; } public bool RunAsAdministrator { get; set; } = true; @@ -20,18 +20,14 @@ namespace Flow.Launcher.Plugin.Shell public int ShowOnlyMostUsedCMDsNumber { get; set; } - public Dictionary CommandHistory { get; set; } = new Dictionary(); + public Dictionary CommandHistory { get; set; } = []; public void AddCmdHistory(string cmdName) { - if (CommandHistory.ContainsKey(cmdName)) + if (!CommandHistory.TryAdd(cmdName, 1)) { CommandHistory[cmdName] += 1; } - else - { - CommandHistory.Add(cmdName, 1); - } } } diff --git a/Plugins/Flow.Launcher.Plugin.Shell/ShellSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Shell/ShellSetting.xaml.cs index d87c6c7bf..0abc823e0 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/ShellSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/ShellSetting.xaml.cs @@ -19,18 +19,18 @@ namespace Flow.Launcher.Plugin.Shell ReplaceWinR.IsChecked = _settings.ReplaceWinR; CloseShellAfterPress.IsChecked = _settings.CloseShellAfterPress; - + LeaveShellOpen.IsChecked = _settings.LeaveShellOpen; - + AlwaysRunAsAdministrator.IsChecked = _settings.RunAsAdministrator; UseWindowsTerminal.IsChecked = _settings.UseWindowsTerminal; - + LeaveShellOpen.IsEnabled = _settings.Shell != Shell.RunCommand; - + ShowOnlyMostUsedCMDs.IsChecked = _settings.ShowOnlyMostUsedCMDs; - - if ((bool)!ShowOnlyMostUsedCMDs.IsChecked) + + if (ShowOnlyMostUsedCMDs.IsChecked != true) ShowOnlyMostUsedCMDsNumber.IsEnabled = false; ShowOnlyMostUsedCMDsNumber.ItemsSource = new List() { 5, 10, 20 }; @@ -137,7 +137,6 @@ namespace Flow.Launcher.Plugin.Shell { _settings.ShowOnlyMostUsedCMDsNumber = (int)ShowOnlyMostUsedCMDsNumber.SelectedItem; }; - } } } diff --git a/Plugins/Flow.Launcher.Plugin.Sys/CommandKeywordSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Sys/CommandKeywordSetting.xaml.cs index 8797bf220..d0669252d 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/CommandKeywordSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/CommandKeywordSetting.xaml.cs @@ -5,15 +5,13 @@ namespace Flow.Launcher.Plugin.Sys public partial class CommandKeywordSettingWindow { private readonly Command _oldSearchSource; - private readonly PluginInitContext _context; - public CommandKeywordSettingWindow(PluginInitContext context, Command old) + public CommandKeywordSettingWindow(Command old) { - _context = context; _oldSearchSource = old; InitializeComponent(); CommandKeyword.Text = old.Keyword; - CommandKeywordTips.Text = string.Format(_context.API.GetTranslation("flowlauncher_plugin_sys_custom_command_keyword_tip"), old.Name); + CommandKeywordTips.Text = Localize.flowlauncher_plugin_sys_custom_command_keyword_tip(old.Name); } private void OnCancelButtonClick(object sender, RoutedEventArgs e) @@ -26,8 +24,8 @@ namespace Flow.Launcher.Plugin.Sys var keyword = CommandKeyword.Text; if (string.IsNullOrEmpty(keyword)) { - var warning = _context.API.GetTranslation("flowlauncher_plugin_sys_input_command_keyword"); - _context.API.ShowMsgBox(warning); + var warning = Localize.flowlauncher_plugin_sys_input_command_keyword(); + Main.Context.API.ShowMsgBox(warning); } else { 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 44fc9a8cf..4cf09baab 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj +++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj @@ -34,6 +34,7 @@ prompt 4 false + $(NoWarn);FLSG0007 @@ -58,6 +59,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml index 56899eef3..9e9a2f93d 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml @@ -78,4 +78,9 @@ System Commands Provides System related commands. e.g. shutdown, lock, settings etc. + + This theme supports two (light/dark) modes and Blur Transparent Background + This theme supports two (light/dark) modes + This theme supports Blur Transparent Background + diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 77278a054..89067d44c 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Globalization; using System.Linq; using System.Runtime.InteropServices; +using System.Threading.Tasks; using System.Windows; using Windows.Win32; using Windows.Win32.Foundation; @@ -42,7 +43,7 @@ namespace Flow.Launcher.Plugin.Sys {"Toggle Game Mode", "flowlauncher_plugin_sys_toggle_game_mode_cmd"}, {"Set Flow Launcher Theme", "flowlauncher_plugin_sys_theme_selector_cmd"} }; - private readonly Dictionary KeywordDescriptionMappings = new(); + private readonly Dictionary KeywordDescriptionMappings = []; // SHTDN_REASON_MAJOR_OTHER indicates a generic shutdown reason that isn't categorized under hardware failure, // software updates, or other predefined reasons. @@ -52,22 +53,21 @@ namespace Flow.Launcher.Plugin.Sys private const string Documentation = "https://flowlauncher.com/docs/#/usage-tips"; - private PluginInitContext _context; + internal static PluginInitContext Context { get; private set; } private Settings _settings; - private ThemeSelector _themeSelector; private SettingsViewModel _viewModel; public Control CreateSettingPanel() { UpdateLocalizedNameDescription(false); - return new SysSettings(_context, _viewModel); + return new SysSettings(_viewModel); } public List Query(Query query) { - if(query.Search.StartsWith(ThemeSelector.Keyword)) + if (query.Search.StartsWith(ThemeSelector.Keyword)) { - return _themeSelector.Query(query); + return ThemeSelector.Query(query); } var commands = Commands(query); @@ -85,9 +85,9 @@ namespace Flow.Launcher.Plugin.Sys } // Match from localized title & localized subtitle & keyword - var titleMatch = _context.API.FuzzySearch(query.Search, c.Title); - var subTitleMatch = _context.API.FuzzySearch(query.Search, c.SubTitle); - var keywordMatch = _context.API.FuzzySearch(query.Search, command.Keyword); + var titleMatch = Context.API.FuzzySearch(query.Search, c.Title); + var subTitleMatch = Context.API.FuzzySearch(query.Search, c.SubTitle); + var keywordMatch = Context.API.FuzzySearch(query.Search, command.Keyword); // Get the largest score from them var score = Math.Max(titleMatch.Score, subTitleMatch.Score); @@ -113,30 +113,29 @@ namespace Flow.Launcher.Plugin.Sys { if (!KeywordTitleMappings.TryGetValue(key, out var translationKey)) { - _context.API.LogError(ClassName, $"Title not found for: {key}"); + Context.API.LogError(ClassName, $"Title not found for: {key}"); return "Title Not Found"; } - return _context.API.GetTranslation(translationKey); + return Context.API.GetTranslation(translationKey); } private string GetDescription(string key) { if (!KeywordDescriptionMappings.TryGetValue(key, out var translationKey)) { - _context.API.LogError(ClassName, $"Description not found for: {key}"); + Context.API.LogError(ClassName, $"Description not found for: {key}"); return "Description Not Found"; } - return _context.API.GetTranslation(translationKey); + return Context.API.GetTranslation(translationKey); } public void Init(PluginInitContext context) { - _context = context; + Context = context; _settings = context.API.LoadSettingJsonStorage(); _viewModel = new SettingsViewModel(_settings); - _themeSelector = new ThemeSelector(context); foreach (string key in KeywordTitleMappings.Keys) { // Remove _cmd in the last of the strings @@ -194,12 +193,12 @@ namespace Flow.Launcher.Plugin.Sys } } - private List Commands(Query query) + private static List Commands(Query query) { var results = new List(); var recycleBinFolder = "shell:RecycleBinFolder"; - results.AddRange(new[] - { + results.AddRange( + [ new Result { Title = "Shutdown", @@ -207,9 +206,9 @@ namespace Flow.Launcher.Plugin.Sys IcoPath = "Images\\shutdown.png", Action = c => { - var result = _context.API.ShowMsgBox( - _context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_shutdown_computer"), - _context.API.GetTranslation("flowlauncher_plugin_sys_shutdown_computer"), + var result = Context.API.ShowMsgBox( + Localize.flowlauncher_plugin_sys_dlgtext_shutdown_computer(), + Localize.flowlauncher_plugin_sys_shutdown_computer(), MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) @@ -228,9 +227,9 @@ namespace Flow.Launcher.Plugin.Sys IcoPath = "Images\\restart.png", Action = c => { - var result = _context.API.ShowMsgBox( - _context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_restart_computer"), - _context.API.GetTranslation("flowlauncher_plugin_sys_restart_computer"), + var result = Context.API.ShowMsgBox( + Localize.flowlauncher_plugin_sys_dlgtext_restart_computer(), + Localize.flowlauncher_plugin_sys_restart_computer(), MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) @@ -249,9 +248,9 @@ namespace Flow.Launcher.Plugin.Sys IcoPath = "Images\\restart_advanced.png", Action = c => { - var result = _context.API.ShowMsgBox( - _context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_restart_computer_advanced"), - _context.API.GetTranslation("flowlauncher_plugin_sys_restart_computer"), + var result = Context.API.ShowMsgBox( + Localize.flowlauncher_plugin_sys_dlgtext_restart_computer_advanced(), + Localize.flowlauncher_plugin_sys_restart_computer(), MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) @@ -270,9 +269,9 @@ namespace Flow.Launcher.Plugin.Sys IcoPath = "Images\\logoff.png", Action = c => { - var result = _context.API.ShowMsgBox( - _context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_logoff_computer"), - _context.API.GetTranslation("flowlauncher_plugin_sys_log_off"), + var result = Context.API.ShowMsgBox( + Localize.flowlauncher_plugin_sys_dlgtext_logoff_computer(), + Localize.flowlauncher_plugin_sys_log_off(), MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) @@ -338,9 +337,9 @@ namespace Flow.Launcher.Plugin.Sys var result = PInvoke.SHEmptyRecycleBin(new(), string.Empty, 0); if (result != HRESULT.S_OK && result != HRESULT.E_UNEXPECTED) { - _context.API.ShowMsgBox( - string.Format(_context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_empty_recycle_bin_failed"), Environment.NewLine), - _context.API.GetTranslation("flowlauncher_plugin_sys_dlgtitle_error"), + Context.API.ShowMsgBox( + Localize.flowlauncher_plugin_sys_dlgtext_empty_recycle_bin_failed(Environment.NewLine), + Localize.flowlauncher_plugin_sys_dlgtitle_error(), MessageBoxButton.OK, MessageBoxImage.Error); } @@ -366,7 +365,7 @@ namespace Flow.Launcher.Plugin.Sys Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\xe89f"), Action = c => { - _context.API.HideMainWindow(); + Context.API.HideMainWindow(); Application.Current.MainWindow.Close(); return true; } @@ -378,9 +377,9 @@ namespace Flow.Launcher.Plugin.Sys IcoPath = "Images\\app.png", Action = c => { - _context.API.SaveAppAllSettings(); - _context.API.ShowMsg(_context.API.GetTranslation("flowlauncher_plugin_sys_dlgtitle_success"), - _context.API.GetTranslation("flowlauncher_plugin_sys_dlgtext_all_settings_saved")); + Context.API.SaveAppAllSettings(); + Context.API.ShowMsg(Localize.flowlauncher_plugin_sys_dlgtitle_success(), + Localize.flowlauncher_plugin_sys_dlgtext_all_settings_saved()); return true; } }, @@ -391,7 +390,7 @@ namespace Flow.Launcher.Plugin.Sys IcoPath = "Images\\app.png", Action = c => { - _context.API.RestartApp(); + Context.API.RestartApp(); return false; } }, @@ -403,8 +402,8 @@ namespace Flow.Launcher.Plugin.Sys Action = c => { // Hide the window first then open setting dialog because main window can be topmost window which will still display on top of the setting dialog for a while - _context.API.HideMainWindow(); - _context.API.OpenSettingDialog(); + Context.API.HideMainWindow(); + Context.API.OpenSettingDialog(); return true; } }, @@ -416,14 +415,13 @@ namespace Flow.Launcher.Plugin.Sys Action = c => { // Hide the window first then show msg after done because sometimes the reload could take a while, so not to make user think it's frozen. - _context.API.HideMainWindow(); + Context.API.HideMainWindow(); - _ = _context.API.ReloadAllPluginData().ContinueWith(_ => - _context.API.ShowMsg( - _context.API.GetTranslation("flowlauncher_plugin_sys_dlgtitle_success"), - _context.API.GetTranslation( - "flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded")), - System.Threading.Tasks.TaskScheduler.Current); + _ = Context.API.ReloadAllPluginData().ContinueWith(_ => + Context.API.ShowMsg( + Localize.flowlauncher_plugin_sys_dlgtitle_success(), + Localize.flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded()), + TaskScheduler.Current); return true; } @@ -435,8 +433,8 @@ namespace Flow.Launcher.Plugin.Sys IcoPath = "Images\\checkupdate.png", Action = c => { - _context.API.HideMainWindow(); - _context.API.CheckForNewUpdate(); + Context.API.HideMainWindow(); + Context.API.CheckForNewUpdate(); return true; } }, @@ -445,11 +443,11 @@ namespace Flow.Launcher.Plugin.Sys Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\xf12b"), Title = "Open Log Location", IcoPath = "Images\\app.png", - CopyText = _context.API.GetLogDirectory(), - AutoCompleteText = _context.API.GetLogDirectory(), + CopyText = Context.API.GetLogDirectory(), + AutoCompleteText = Context.API.GetLogDirectory(), Action = c => { - _context.API.OpenDirectory(_context.API.GetLogDirectory()); + Context.API.OpenDirectory(Context.API.GetLogDirectory()); return true; } }, @@ -462,7 +460,7 @@ namespace Flow.Launcher.Plugin.Sys AutoCompleteText = Documentation, Action = c => { - _context.API.OpenUrl(Documentation); + Context.API.OpenUrl(Documentation); return true; } }, @@ -471,11 +469,11 @@ namespace Flow.Launcher.Plugin.Sys Title = "Flow Launcher UserData Folder", Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\xf12b"), IcoPath = "Images\\app.png", - CopyText = _context.API.GetDataDirectory(), - AutoCompleteText = _context.API.GetDataDirectory(), + CopyText = Context.API.GetDataDirectory(), + AutoCompleteText = Context.API.GetDataDirectory(), Action = c => { - _context.API.OpenDirectory(_context.API.GetDataDirectory()); + Context.API.OpenDirectory(Context.API.GetDataDirectory()); return true; } }, @@ -486,7 +484,7 @@ namespace Flow.Launcher.Plugin.Sys Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\ue7fc"), Action = c => { - _context.API.ToggleGameMode(); + Context.API.ToggleGameMode(); return true; } }, @@ -499,29 +497,29 @@ namespace Flow.Launcher.Plugin.Sys { if (string.IsNullOrEmpty(query.ActionKeyword)) { - _context.API.ChangeQuery($"{ThemeSelector.Keyword}{Plugin.Query.ActionKeywordSeparator}"); + Context.API.ChangeQuery($"{ThemeSelector.Keyword}{Plugin.Query.ActionKeywordSeparator}"); } else { - _context.API.ChangeQuery($"{query.ActionKeyword}{Plugin.Query.ActionKeywordSeparator}{ThemeSelector.Keyword}{Plugin.Query.ActionKeywordSeparator}"); + Context.API.ChangeQuery($"{query.ActionKeyword}{Plugin.Query.ActionKeywordSeparator}{ThemeSelector.Keyword}{Plugin.Query.ActionKeywordSeparator}"); } return false; } } - }); + ]); return results; } public string GetTranslatedPluginTitle() { - return _context.API.GetTranslation("flowlauncher_plugin_sys_plugin_name"); + return Localize.flowlauncher_plugin_sys_plugin_name(); } public string GetTranslatedPluginDescription() { - return _context.API.GetTranslation("flowlauncher_plugin_sys_plugin_description"); + return Localize.flowlauncher_plugin_sys_plugin_description(); } public void OnCultureInfoChanged(CultureInfo _) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Settings.cs b/Plugins/Flow.Launcher.Plugin.Sys/Settings.cs index f39e6d65f..96a545e74 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Settings.cs @@ -13,8 +13,8 @@ public class Settings : BaseModel } } - public ObservableCollection Commands { get; set; } = new ObservableCollection - { + public ObservableCollection Commands { get; set; } = + [ new() { Key = "Shutdown", @@ -120,7 +120,7 @@ public class Settings : BaseModel Key = "Set Flow Launcher Theme", Keyword = "Set Flow Launcher Theme" } - }; + ]; [JsonIgnore] public Command SelectedCommand { get; set; } diff --git a/Plugins/Flow.Launcher.Plugin.Sys/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Sys/SettingsViewModel.cs index 0755dffa9..bda8c6c04 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/SettingsViewModel.cs @@ -1,12 +1,7 @@ namespace Flow.Launcher.Plugin.Sys { - public class SettingsViewModel + public class SettingsViewModel(Settings settings) { - public SettingsViewModel(Settings settings) - { - Settings = settings; - } - - public Settings Settings { get; } + public Settings Settings { get; } = settings; } } diff --git a/Plugins/Flow.Launcher.Plugin.Sys/SysSettings.xaml.cs b/Plugins/Flow.Launcher.Plugin.Sys/SysSettings.xaml.cs index 1a8621eeb..9906db46d 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/SysSettings.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/SysSettings.xaml.cs @@ -1,17 +1,16 @@ using System.Windows; using System.Windows.Controls; +using System.Windows.Input; namespace Flow.Launcher.Plugin.Sys { public partial class SysSettings : UserControl { - private readonly PluginInitContext _context; private readonly Settings _settings; - public SysSettings(PluginInitContext context, SettingsViewModel viewModel) + public SysSettings(SettingsViewModel viewModel) { InitializeComponent(); - _context = context; _settings = viewModel.Settings; DataContext = viewModel; } @@ -37,15 +36,15 @@ namespace Flow.Launcher.Plugin.Sys public void OnEditCommandKeywordClick(object sender, RoutedEventArgs e) { - var commandKeyword = new CommandKeywordSettingWindow(_context, _settings.SelectedCommand); + var commandKeyword = new CommandKeywordSettingWindow(_settings.SelectedCommand); commandKeyword.ShowDialog(); } - private void MouseDoubleClickItem(object sender, System.Windows.Input.MouseButtonEventArgs e) + private void MouseDoubleClickItem(object sender, MouseButtonEventArgs e) { if (((FrameworkElement)e.OriginalSource).DataContext is Command && _settings.SelectedCommand != null) { - var commandKeyword = new CommandKeywordSettingWindow(_context, _settings.SelectedCommand); + var commandKeyword = new CommandKeywordSettingWindow(_settings.SelectedCommand); commandKeyword.ShowDialog(); } } diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index f8aeaeafd..50b1063ef 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -4,40 +4,30 @@ using Flow.Launcher.Plugin.SharedModels; namespace Flow.Launcher.Plugin.Sys { - public class ThemeSelector + public static class ThemeSelector { public const string Keyword = "fltheme"; - private readonly PluginInitContext _context; - - public ThemeSelector(PluginInitContext context) + public static List Query(Query query) { - _context = context; - } - - public List Query(Query query) - { - var themes = _context.API.GetAvailableThemes(); - var selectedTheme = _context.API.GetCurrentTheme(); + var themes = Main.Context.API.GetAvailableThemes(); + var selectedTheme = Main.Context.API.GetCurrentTheme(); var search = query.SecondToEndSearch; if (string.IsNullOrWhiteSpace(search)) { - return themes.Select(x => CreateThemeResult(x, selectedTheme)) - .OrderBy(x => x.Title) - .ToList(); + return [.. themes.Select(x => CreateThemeResult(x, selectedTheme)).OrderBy(x => x.Title)]; } - return themes.Select(theme => (theme, matchResult: _context.API.FuzzySearch(search, theme.Name))) - .Where(x => x.matchResult.IsSearchPrecisionScoreMet()) - .Select(x => CreateThemeResult(x.theme, selectedTheme, x.matchResult.Score, x.matchResult.MatchData)) - .OrderBy(x => x.Title) - .ToList(); + return [.. themes.Select(theme => (theme, matchResult: Main.Context.API.FuzzySearch(search, theme.Name))) + .Where(x => x.matchResult.IsSearchPrecisionScoreMet()) + .Select(x => CreateThemeResult(x.theme, selectedTheme, x.matchResult.Score, x.matchResult.MatchData)) + .OrderBy(x => x.Title)]; } - private Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme) => CreateThemeResult(theme, selectedTheme, 0, null); + private static Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme) => CreateThemeResult(theme, selectedTheme, 0, null); - private Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme, int score, IList highlightData) + private static Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme, int score, IList highlightData) { string title; if (theme == selectedTheme) @@ -53,17 +43,28 @@ namespace Flow.Launcher.Plugin.Sys score = 1000; } - string description = string.Empty; + string description; if (theme.IsDark == true) { - description += _context.API.GetTranslation("TypeIsDarkToolTip"); + if (theme.HasBlur == true) + { + description = Localize.flowlauncher_plugin_sys_type_isdark_hasblur(); + } + else + { + description = Localize.flowlauncher_plugin_sys_type_isdark(); + } } - - if (theme.HasBlur == true) + else { - if (!string.IsNullOrEmpty(description)) - description += " "; - description += _context.API.GetTranslation("TypeHasBlurToolTip"); + if (theme.HasBlur == true) + { + description = Localize.flowlauncher_plugin_sys_type_hasblur(); + } + else + { + description = string.Empty; + } } return new Result @@ -76,9 +77,9 @@ namespace Flow.Launcher.Plugin.Sys Score = score, Action = c => { - if (_context.API.SetCurrentTheme(theme)) + if (Main.Context.API.SetCurrentTheme(theme)) { - _context.API.ReQuery(); + Main.Context.API.ReQuery(); } return false; } 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 fdfe03224..091248cfd 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj +++ b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj @@ -33,6 +33,7 @@ prompt 4 false + $(NoWarn);FLSG0007 @@ -56,4 +57,8 @@ + + + + diff --git a/Plugins/Flow.Launcher.Plugin.Url/Main.cs b/Plugins/Flow.Launcher.Plugin.Url/Main.cs index 9fa52c8da..db7cecbde 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Url/Main.cs @@ -40,7 +40,7 @@ namespace Flow.Launcher.Plugin.Url "(?:/\\S*)?" + "$"; Regex reg = new Regex(urlPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); - private PluginInitContext context; + internal static PluginInitContext Context { get; private set; } private Settings _settings; public List Query(Query query) @@ -53,7 +53,7 @@ namespace Flow.Launcher.Plugin.Url new Result { Title = raw, - SubTitle = string.Format(context.API.GetTranslation("flowlauncher_plugin_url_open_url"),raw), + SubTitle = Localize.flowlauncher_plugin_url_open_url(raw), IcoPath = "Images/url.png", Score = 8, Action = _ => @@ -64,13 +64,13 @@ namespace Flow.Launcher.Plugin.Url } try { - context.API.OpenUrl(raw); + Context.API.OpenUrl(raw); return true; } catch(Exception) { - context.API.ShowMsgError(string.Format(context.API.GetTranslation("flowlauncher_plugin_url_cannot_open_url"), raw)); + Context.API.ShowMsgError(Localize.flowlauncher_plugin_url_cannot_open_url(raw)); return false; } } @@ -99,19 +99,19 @@ namespace Flow.Launcher.Plugin.Url public void Init(PluginInitContext context) { - this.context = context; + Context = context; _settings = context.API.LoadSettingJsonStorage(); } public string GetTranslatedPluginTitle() { - return context.API.GetTranslation("flowlauncher_plugin_url_plugin_name"); + return Localize.flowlauncher_plugin_url_plugin_name(); } public string GetTranslatedPluginDescription() { - return context.API.GetTranslation("flowlauncher_plugin_url_plugin_description"); + return Localize.flowlauncher_plugin_url_plugin_description(); } } } From d363cf8137d5af58448c1e4df5bd3cec0dbf8c90 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 29 Sep 2025 10:42:19 +0800 Subject: [PATCH 59/73] Add property change for settings class & Add localize support for enum --- .../Flow.Launcher.Plugin.Shell/Settings.cs | 123 ++++++++++++++++-- 1 file changed, 114 insertions(+), 9 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs b/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs index 4616a18ec..92db4771e 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs @@ -1,24 +1,121 @@ using System.Collections.Generic; +using Flow.Launcher.Localization.Attributes; namespace Flow.Launcher.Plugin.Shell { - public class Settings + public class Settings : BaseModel { - public Shell Shell { get; set; } = Shell.Cmd; + private Shell _shell = Shell.Cmd; + public Shell Shell + { + get => _shell; + set + { + if (_shell != value) + { + _shell = value; + OnPropertyChanged(); + } + } + } - public bool ReplaceWinR { get; set; } = false; + private bool _replaceWinR = false; + public bool ReplaceWinR + { + get => _replaceWinR; + set + { + if (_replaceWinR != value) + { + _replaceWinR = value; + OnPropertyChanged(); + } + } + } - public bool CloseShellAfterPress { get; set; } = false; + private bool _closeShellAfterPress = false; + public bool CloseShellAfterPress + { + get => _closeShellAfterPress; + set + { + if (_closeShellAfterPress != value) + { + _closeShellAfterPress = value; + OnPropertyChanged(); + } + } + } - public bool LeaveShellOpen { get; set; } + private bool _leaveShellOpen; + public bool LeaveShellOpen + { + get => _leaveShellOpen; + set + { + if (_leaveShellOpen != value) + { + _leaveShellOpen = value; + OnPropertyChanged(); + } + } + } - public bool RunAsAdministrator { get; set; } = true; + private bool _runAsAdministrator = true; + public bool RunAsAdministrator + { + get => _runAsAdministrator; + set + { + if (_runAsAdministrator != value) + { + _runAsAdministrator = value; + OnPropertyChanged(); + } + } + } - public bool UseWindowsTerminal { get; set; } = false; + private bool _useWindowsTerminal = false; + public bool UseWindowsTerminal + { + get => _useWindowsTerminal; + set + { + if (_useWindowsTerminal != value) + { + _useWindowsTerminal = value; + OnPropertyChanged(); + } + } + } - public bool ShowOnlyMostUsedCMDs { get; set; } + private bool _showOnlyMostUsedCMDs; + public bool ShowOnlyMostUsedCMDs + { + get => _showOnlyMostUsedCMDs; + set + { + if (_showOnlyMostUsedCMDs != value) + { + _showOnlyMostUsedCMDs = value; + OnPropertyChanged(); + } + } + } - public int ShowOnlyMostUsedCMDsNumber { get; set; } + private int _showOnlyMostUsedCMDsNumber; + public int ShowOnlyMostUsedCMDsNumber + { + get => _showOnlyMostUsedCMDsNumber; + set + { + if (_showOnlyMostUsedCMDsNumber != value) + { + _showOnlyMostUsedCMDsNumber = value; + OnPropertyChanged(); + } + } + } public Dictionary CommandHistory { get; set; } = []; @@ -31,11 +128,19 @@ namespace Flow.Launcher.Plugin.Shell } } + [EnumLocalize] public enum Shell { + [EnumLocalizeValue("CMD")] Cmd = 0, + + [EnumLocalizeValue("PowerShell")] Powershell = 1, + + [EnumLocalizeValue("RunCommand")] RunCommand = 2, + + [EnumLocalizeValue("Pwsh")] Pwsh = 3, } } From 175571a1309ecfcf4e6d10f8d813e137206641e5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 29 Sep 2025 23:00:32 +0800 Subject: [PATCH 60/73] Refactor ShellSettings with Binding logic --- .../CloseShellAfterPressEnabledConverter.cs | 22 +++ .../LeaveShellOpenEnabledConverter.cs | 25 +++ Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 1 + .../ShellSetting.xaml.cs | 142 ------------------ .../ViewModels/ShellSettingViewModel.cs | 78 ++++++++++ .../{ => Views}/ShellSetting.xaml | 53 +++++-- .../Views/ShellSetting.xaml.cs | 16 ++ 7 files changed, 180 insertions(+), 157 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Shell/Converters/CloseShellAfterPressEnabledConverter.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Shell/Converters/LeaveShellOpenEnabledConverter.cs delete mode 100644 Plugins/Flow.Launcher.Plugin.Shell/ShellSetting.xaml.cs create mode 100644 Plugins/Flow.Launcher.Plugin.Shell/ViewModels/ShellSettingViewModel.cs rename Plugins/Flow.Launcher.Plugin.Shell/{ => Views}/ShellSetting.xaml (55%) create mode 100644 Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml.cs diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Converters/CloseShellAfterPressEnabledConverter.cs b/Plugins/Flow.Launcher.Plugin.Shell/Converters/CloseShellAfterPressEnabledConverter.cs new file mode 100644 index 000000000..a47b58e1e --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Shell/Converters/CloseShellAfterPressEnabledConverter.cs @@ -0,0 +1,22 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Flow.Launcher.Plugin.Shell.Converters; + +public class CloseShellAfterPressEnabledConverter : IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is not bool) + return Binding.DoNothing; + + var leaveShellOpen = (bool)value; + return !leaveShellOpen; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Converters/LeaveShellOpenEnabledConverter.cs b/Plugins/Flow.Launcher.Plugin.Shell/Converters/LeaveShellOpenEnabledConverter.cs new file mode 100644 index 000000000..ca938ae7e --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Shell/Converters/LeaveShellOpenEnabledConverter.cs @@ -0,0 +1,25 @@ +using System; +using System.Globalization; +using System.Windows.Data; + +namespace Flow.Launcher.Plugin.Shell.Converters; + +public class LeaveShellOpenEnabledConverter : IMultiValueConverter +{ + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + if ( + values.Length != 2 || + values[0] is not bool closeShellAfterPress || + values[1] is not Shell shell + ) + return Binding.DoNothing; + + return (!closeShellAfterPress) && shell != Shell.RunCommand; + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 2440facd0..6433179f0 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using Flow.Launcher.Plugin.SharedCommands; +using Flow.Launcher.Plugin.Shell.Views; using WindowsInput; using WindowsInput.Native; using Control = System.Windows.Controls.Control; diff --git a/Plugins/Flow.Launcher.Plugin.Shell/ShellSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Shell/ShellSetting.xaml.cs deleted file mode 100644 index 0abc823e0..000000000 --- a/Plugins/Flow.Launcher.Plugin.Shell/ShellSetting.xaml.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System.Collections.Generic; -using System.Windows; -using System.Windows.Controls; - -namespace Flow.Launcher.Plugin.Shell -{ - public partial class CMDSetting : UserControl - { - private readonly Settings _settings; - - public CMDSetting(Settings settings) - { - InitializeComponent(); - _settings = settings; - } - - private void CMDSetting_OnLoaded(object sender, RoutedEventArgs re) - { - ReplaceWinR.IsChecked = _settings.ReplaceWinR; - - CloseShellAfterPress.IsChecked = _settings.CloseShellAfterPress; - - LeaveShellOpen.IsChecked = _settings.LeaveShellOpen; - - AlwaysRunAsAdministrator.IsChecked = _settings.RunAsAdministrator; - - UseWindowsTerminal.IsChecked = _settings.UseWindowsTerminal; - - LeaveShellOpen.IsEnabled = _settings.Shell != Shell.RunCommand; - - ShowOnlyMostUsedCMDs.IsChecked = _settings.ShowOnlyMostUsedCMDs; - - if (ShowOnlyMostUsedCMDs.IsChecked != true) - ShowOnlyMostUsedCMDsNumber.IsEnabled = false; - - ShowOnlyMostUsedCMDsNumber.ItemsSource = new List() { 5, 10, 20 }; - - if (_settings.ShowOnlyMostUsedCMDsNumber == 0) - { - ShowOnlyMostUsedCMDsNumber.SelectedIndex = 0; - - _settings.ShowOnlyMostUsedCMDsNumber = (int)ShowOnlyMostUsedCMDsNumber.SelectedItem; - } - - CloseShellAfterPress.Checked += (o, e) => - { - _settings.CloseShellAfterPress = true; - LeaveShellOpen.IsChecked = false; - LeaveShellOpen.IsEnabled = false; - }; - - CloseShellAfterPress.Unchecked += (o, e) => - { - _settings.CloseShellAfterPress = false; - LeaveShellOpen.IsEnabled = true; - }; - - LeaveShellOpen.Checked += (o, e) => - { - _settings.LeaveShellOpen = true; - CloseShellAfterPress.IsChecked = false; - CloseShellAfterPress.IsEnabled = false; - }; - - LeaveShellOpen.Unchecked += (o, e) => - { - _settings.LeaveShellOpen = false; - CloseShellAfterPress.IsEnabled = true; - }; - - AlwaysRunAsAdministrator.Checked += (o, e) => - { - _settings.RunAsAdministrator = true; - }; - - AlwaysRunAsAdministrator.Unchecked += (o, e) => - { - _settings.RunAsAdministrator = false; - }; - - UseWindowsTerminal.Checked += (o, e) => - { - _settings.UseWindowsTerminal = true; - }; - - UseWindowsTerminal.Unchecked += (o, e) => - { - _settings.UseWindowsTerminal = false; - }; - - ReplaceWinR.Checked += (o, e) => - { - _settings.ReplaceWinR = true; - }; - - ReplaceWinR.Unchecked += (o, e) => - { - _settings.ReplaceWinR = false; - }; - - ShellComboBox.SelectedIndex = _settings.Shell switch - { - Shell.Cmd => 0, - Shell.Powershell => 1, - Shell.Pwsh => 2, - _ => ShellComboBox.Items.Count - 1 - }; - - ShellComboBox.SelectionChanged += (o, e) => - { - _settings.Shell = ShellComboBox.SelectedIndex switch - { - 0 => Shell.Cmd, - 1 => Shell.Powershell, - 2 => Shell.Pwsh, - _ => Shell.RunCommand - }; - LeaveShellOpen.IsEnabled = _settings.Shell != Shell.RunCommand; - }; - - ShowOnlyMostUsedCMDs.Checked += (o, e) => - { - _settings.ShowOnlyMostUsedCMDs = true; - - ShowOnlyMostUsedCMDsNumber.IsEnabled = true; - }; - - ShowOnlyMostUsedCMDs.Unchecked += (o, e) => - { - _settings.ShowOnlyMostUsedCMDs = false; - - ShowOnlyMostUsedCMDsNumber.IsEnabled = false; - }; - - ShowOnlyMostUsedCMDsNumber.SelectedItem = _settings.ShowOnlyMostUsedCMDsNumber; - ShowOnlyMostUsedCMDsNumber.SelectionChanged += (o, e) => - { - _settings.ShowOnlyMostUsedCMDsNumber = (int)ShowOnlyMostUsedCMDsNumber.SelectedItem; - }; - } - } -} diff --git a/Plugins/Flow.Launcher.Plugin.Shell/ViewModels/ShellSettingViewModel.cs b/Plugins/Flow.Launcher.Plugin.Shell/ViewModels/ShellSettingViewModel.cs new file mode 100644 index 000000000..341fc3868 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Shell/ViewModels/ShellSettingViewModel.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; + +namespace Flow.Launcher.Plugin.Shell.ViewModels; + +public class ShellSettingViewModel : BaseModel +{ + public Settings Settings { get; } + + public List AllShells { get; } = ShellLocalized.GetValues(); + + public Shell SelectedShell + { + get => Settings.Shell; + set + { + if (Settings.Shell != value) + { + Settings.Shell = value; + OnPropertyChanged(); + } + } + } + + public List OnlyMostUsedCMDsNumbers { get; } = [5, 10, 20]; + public int SelectedOnlyMostUsedCMDsNumber + { + get => Settings.ShowOnlyMostUsedCMDsNumber; + set + { + if (Settings.ShowOnlyMostUsedCMDsNumber != value) + { + Settings.ShowOnlyMostUsedCMDsNumber = value; + OnPropertyChanged(); + } + } + } + + public bool CloseShellAfterPress + { + get => Settings.CloseShellAfterPress; + set + { + if (Settings.CloseShellAfterPress != value) + { + Settings.CloseShellAfterPress = value; + OnPropertyChanged(); + // Only allow CloseShellAfterPress to be true when LeaveShellOpen is false + if (value) + { + LeaveShellOpen = false; + } + } + } + } + + public bool LeaveShellOpen + { + get => Settings.LeaveShellOpen; + set + { + if (Settings.LeaveShellOpen != value) + { + Settings.LeaveShellOpen = value; + OnPropertyChanged(); + // Only allow LeaveShellOpen to be true when CloseShellAfterPress is false + if (value) + { + CloseShellAfterPress = false; + } + } + } + } + + public ShellSettingViewModel(Settings settings) + { + Settings = settings; + } +} diff --git a/Plugins/Flow.Launcher.Plugin.Shell/ShellSetting.xaml b/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml similarity index 55% rename from Plugins/Flow.Launcher.Plugin.Shell/ShellSetting.xaml rename to Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml index 32f2ad69c..ce52d6c7a 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/ShellSetting.xaml +++ b/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml @@ -1,13 +1,20 @@  + + + + + @@ -23,50 +30,66 @@ Grid.Row="0" Margin="{StaticResource SettingPanelItemRightTopBottomMargin}" HorizontalAlignment="Left" - Content="{DynamicResource flowlauncher_plugin_cmd_relace_winr}" /> + Content="{DynamicResource flowlauncher_plugin_cmd_relace_winr}" + IsChecked="{Binding Settings.ReplaceWinR, Mode=TwoWay}" /> + Content="{DynamicResource flowlauncher_plugin_cmd_close_cmd_after_press}" + IsChecked="{Binding CloseShellAfterPress, Mode=TwoWay}" + IsEnabled="{Binding LeaveShellOpen, Converter={StaticResource CloseShellAfterPressEnabledConverter}, Mode=OneWay}" /> + Content="{DynamicResource flowlauncher_plugin_cmd_leave_cmd_open}" + IsChecked="{Binding LeaveShellOpen, Mode=TwoWay}"> + + + + + + + + Content="{DynamicResource flowlauncher_plugin_cmd_always_run_as_administrator}" + IsChecked="{Binding Settings.RunAsAdministrator, Mode=TwoWay}" /> + Content="{DynamicResource flowlauncher_plugin_cmd_use_windows_terminal}" + IsChecked="{Binding Settings.UseWindowsTerminal, Mode=TwoWay}" /> - CMD - PowerShell - Pwsh - RunCommand - + HorizontalAlignment="Left" + DisplayMemberPath="Display" + ItemsSource="{Binding AllShells, Mode=OneTime}" + SelectedValue="{Binding SelectedShell, Mode=TwoWay}" + SelectedValuePath="Value" /> + Content="{DynamicResource flowlauncher_plugin_cmd_history}" + IsChecked="{Binding Settings.ShowOnlyMostUsedCMDs, Mode=TwoWay}" /> + HorizontalAlignment="Left" + IsEnabled="{Binding Settings.ShowOnlyMostUsedCMDs, Mode=OneWay}" + ItemsSource="{Binding OnlyMostUsedCMDsNumbers, Mode=OneTime}" + SelectedItem="{Binding SelectedOnlyMostUsedCMDsNumber, Mode=TwoWay}" /> diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml.cs new file mode 100644 index 000000000..1ec9018df --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml.cs @@ -0,0 +1,16 @@ +using System.Windows.Controls; +using Flow.Launcher.Plugin.Shell.ViewModels; + +namespace Flow.Launcher.Plugin.Shell.Views +{ + public partial class CMDSetting : UserControl + { + public CMDSetting(Settings settings) + { + var viewModel = new ShellSettingViewModel(settings); + DataContext = viewModel; + InitializeComponent(); + DataContext = viewModel; + } + } +} From d106c5144b7a5397408d566ca5acf2faf1606ae0 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 29 Sep 2025 23:12:02 +0800 Subject: [PATCH 61/73] Fix IsEnabled logic --- .../CloseShellAfterPressEnabledConverter.cs | 22 ------------------- ...OrCloseShellAfterPressEnabledConverter.cs} | 6 ++--- .../Views/ShellSetting.xaml | 15 ++++++++----- 3 files changed, 13 insertions(+), 30 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.Shell/Converters/CloseShellAfterPressEnabledConverter.cs rename Plugins/Flow.Launcher.Plugin.Shell/Converters/{LeaveShellOpenEnabledConverter.cs => LeaveShellOpenOrCloseShellAfterPressEnabledConverter.cs} (68%) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Converters/CloseShellAfterPressEnabledConverter.cs b/Plugins/Flow.Launcher.Plugin.Shell/Converters/CloseShellAfterPressEnabledConverter.cs deleted file mode 100644 index a47b58e1e..000000000 --- a/Plugins/Flow.Launcher.Plugin.Shell/Converters/CloseShellAfterPressEnabledConverter.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; - -namespace Flow.Launcher.Plugin.Shell.Converters; - -public class CloseShellAfterPressEnabledConverter : IValueConverter -{ - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is not bool) - return Binding.DoNothing; - - var leaveShellOpen = (bool)value; - return !leaveShellOpen; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } -} diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Converters/LeaveShellOpenEnabledConverter.cs b/Plugins/Flow.Launcher.Plugin.Shell/Converters/LeaveShellOpenOrCloseShellAfterPressEnabledConverter.cs similarity index 68% rename from Plugins/Flow.Launcher.Plugin.Shell/Converters/LeaveShellOpenEnabledConverter.cs rename to Plugins/Flow.Launcher.Plugin.Shell/Converters/LeaveShellOpenOrCloseShellAfterPressEnabledConverter.cs index ca938ae7e..5649353e5 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Converters/LeaveShellOpenEnabledConverter.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Converters/LeaveShellOpenOrCloseShellAfterPressEnabledConverter.cs @@ -4,18 +4,18 @@ using System.Windows.Data; namespace Flow.Launcher.Plugin.Shell.Converters; -public class LeaveShellOpenEnabledConverter : IMultiValueConverter +public class LeaveShellOpenOrCloseShellAfterPressEnabledConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { if ( values.Length != 2 || - values[0] is not bool closeShellAfterPress || + values[0] is not bool closeShellAfterPressOrLeaveShellOpen || values[1] is not Shell shell ) return Binding.DoNothing; - return (!closeShellAfterPress) && shell != Shell.RunCommand; + return (!closeShellAfterPressOrLeaveShellOpen) && shell != Shell.RunCommand; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml b/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml index ce52d6c7a..5f66884ea 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml +++ b/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml @@ -11,8 +11,7 @@ d:DesignWidth="300" mc:Ignorable="d"> - - + @@ -38,8 +37,14 @@ Margin="{StaticResource SettingPanelItemRightTopBottomMargin}" HorizontalAlignment="Left" Content="{DynamicResource flowlauncher_plugin_cmd_close_cmd_after_press}" - IsChecked="{Binding CloseShellAfterPress, Mode=TwoWay}" - IsEnabled="{Binding LeaveShellOpen, Converter={StaticResource CloseShellAfterPressEnabledConverter}, Mode=OneWay}" /> + IsChecked="{Binding CloseShellAfterPress, Mode=TwoWay}"> + + + + + + + - + From 89505fce307c1ab7b5ad8dacfe69f97656a7f5e4 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Tue, 30 Sep 2025 09:37:48 +0800 Subject: [PATCH 62/73] Remove unnecessary DataContext Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml.cs index 1ec9018df..c656ea070 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Views/ShellSetting.xaml.cs @@ -10,7 +10,6 @@ namespace Flow.Launcher.Plugin.Shell.Views var viewModel = new ShellSettingViewModel(settings); DataContext = viewModel; InitializeComponent(); - DataContext = viewModel; } } } From aab213a6b975fb3d223a482729f99541e3e5b8f1 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Tue, 30 Sep 2025 09:38:18 +0800 Subject: [PATCH 63/73] Add default value for ShowOnlyMostUsedCMDsNumber Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Plugins/Flow.Launcher.Plugin.Shell/Settings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs b/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs index 92db4771e..79a906534 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Settings.cs @@ -103,7 +103,7 @@ namespace Flow.Launcher.Plugin.Shell } } - private int _showOnlyMostUsedCMDsNumber; + private int _showOnlyMostUsedCMDsNumber = 5; public int ShowOnlyMostUsedCMDsNumber { get => _showOnlyMostUsedCMDsNumber; From 9be546d6c72d152ecba61cbd4f9ee542abfdf0cd Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 30 Sep 2025 09:50:29 +0800 Subject: [PATCH 64/73] Fix ShowOnlyMostUsedCMDsNumber default value --- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 6433179f0..e89ec376c 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -384,9 +384,15 @@ namespace Flow.Launcher.Plugin.Shell Context = context; _settings = context.API.LoadSettingJsonStorage(); context.API.RegisterGlobalKeyboardCallback(API_GlobalKeyboardEvent); + // Since the old Settings class set default value of ShowOnlyMostUsedCMDsNumber to 0 which is a wrong value, + // we need to fix it here to make sure the default value is 5 + if (_settings.ShowOnlyMostUsedCMDsNumber == 0) + { + _settings.ShowOnlyMostUsedCMDsNumber = 5; + } } - bool API_GlobalKeyboardEvent(int keyevent, int vkcode, SpecialKeyState state) + private bool API_GlobalKeyboardEvent(int keyevent, int vkcode, SpecialKeyState state) { if (!Context.CurrentPluginMetadata.Disabled && _settings.ReplaceWinR) { From d56d85b702a35eafb29b72dfcf2e91f6c0d3045e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 30 Sep 2025 19:41:27 +0800 Subject: [PATCH 65/73] Add lock for sound & Rename variable --- Flow.Launcher/MainWindow.xaml.cs | 52 ++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index c4ed73a0d..a9e03bc8c 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using System.Linq; using System.Media; +using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; @@ -61,8 +62,9 @@ namespace Flow.Launcher private bool _isArrowKeyPressed = false; // Window Sound Effects - private MediaPlayer animationSoundWMP; - private SoundPlayer animationSoundWPF; + private MediaPlayer _animationSoundWMP; + private SoundPlayer _animationSoundWPF; + private readonly Lock _soundLock = new(); // Window WndProc private HwndSource _hwndSource; @@ -687,31 +689,37 @@ namespace Flow.Launcher private void InitSoundEffects() { - if (_settings.WMPInstalled) + lock (_soundLock) { - animationSoundWMP?.Close(); - animationSoundWMP = new MediaPlayer(); - animationSoundWMP.Open(new Uri(AppContext.BaseDirectory + "Resources\\open.wav")); - } - else - { - animationSoundWPF?.Dispose(); - animationSoundWPF = new SoundPlayer(AppContext.BaseDirectory + "Resources\\open.wav"); - animationSoundWPF.Load(); + if (_settings.WMPInstalled) + { + _animationSoundWMP?.Close(); + _animationSoundWMP = new MediaPlayer(); + _animationSoundWMP.Open(new Uri(AppContext.BaseDirectory + "Resources\\open.wav")); + } + else + { + _animationSoundWPF?.Dispose(); + _animationSoundWPF = new SoundPlayer(AppContext.BaseDirectory + "Resources\\open.wav"); + _animationSoundWPF.Load(); + } } } private void SoundPlay() { - if (_settings.WMPInstalled) + lock (_soundLock) { - animationSoundWMP.Position = TimeSpan.Zero; - animationSoundWMP.Volume = _settings.SoundVolume / 100.0; - animationSoundWMP.Play(); - } - else - { - animationSoundWPF.Play(); + if (_settings.WMPInstalled) + { + _animationSoundWMP.Position = TimeSpan.Zero; + _animationSoundWMP.Volume = _settings.SoundVolume / 100.0; + _animationSoundWMP.Play(); + } + else + { + _animationSoundWPF.Play(); + } } } @@ -1436,8 +1444,8 @@ namespace Flow.Launcher { _hwndSource?.Dispose(); _notifyIcon?.Dispose(); - animationSoundWMP?.Close(); - animationSoundWPF?.Dispose(); + _animationSoundWMP?.Close(); + _animationSoundWPF?.Dispose(); _viewModel.ActualApplicationThemeChanged -= ViewModel_ActualApplicationThemeChanged; } From 652ec40d82da67d4db7a2da0c7502f7df1d05fae Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 30 Sep 2025 22:28:41 +1000 Subject: [PATCH 66/73] add removal todo comment --- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index e89ec376c..25303e9d5 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -386,6 +386,7 @@ namespace Flow.Launcher.Plugin.Shell context.API.RegisterGlobalKeyboardCallback(API_GlobalKeyboardEvent); // Since the old Settings class set default value of ShowOnlyMostUsedCMDsNumber to 0 which is a wrong value, // we need to fix it here to make sure the default value is 5 + // todo: remove this code block after release v2.2.0 if (_settings.ShowOnlyMostUsedCMDsNumber == 0) { _settings.ShowOnlyMostUsedCMDsNumber = 5; From f239866c6811792f60da0fd243ffd003a1e609c4 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 30 Sep 2025 21:11:03 +0800 Subject: [PATCH 67/73] Use sleep mode listener to fix modern standby sleep mode issue --- .../NativeMethods.txt | 7 +- Flow.Launcher.Infrastructure/Win32Helper.cs | 104 +++++++++++++++++- Flow.Launcher/MainWindow.xaml.cs | 53 +++++++-- 3 files changed, 150 insertions(+), 14 deletions(-) diff --git a/Flow.Launcher.Infrastructure/NativeMethods.txt b/Flow.Launcher.Infrastructure/NativeMethods.txt index eb844dd7c..cd072f635 100644 --- a/Flow.Launcher.Infrastructure/NativeMethods.txt +++ b/Flow.Launcher.Infrastructure/NativeMethods.txt @@ -85,5 +85,10 @@ QueryFullProcessImageName EVENT_OBJECT_HIDE EVENT_SYSTEM_DIALOGEND +DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS WM_POWERBROADCAST -PBT_APMRESUMEAUTOMATIC \ No newline at end of file +PBT_APMRESUMEAUTOMATIC +PBT_APMRESUMESUSPEND +PowerRegisterSuspendResumeNotification +PowerUnregisterSuspendResumeNotification +DeviceNotifyCallbackRoutine \ No newline at end of file diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 5d30b740d..c94008b03 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -19,6 +19,7 @@ using Microsoft.Win32.SafeHandles; using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.Graphics.Dwm; +using Windows.Win32.System.Power; using Windows.Win32.System.Threading; using Windows.Win32.UI.Input.KeyboardAndMouse; using Windows.Win32.UI.Shell.Common; @@ -338,9 +339,6 @@ namespace Flow.Launcher.Infrastructure public const int SC_MAXIMIZE = (int)PInvoke.SC_MAXIMIZE; public const int SC_MINIMIZE = (int)PInvoke.SC_MINIMIZE; - public const int WM_POWERBROADCAST = (int)PInvoke.WM_POWERBROADCAST; - public const int PBT_APMRESUMEAUTOMATIC = (int)PInvoke.PBT_APMRESUMEAUTOMATIC; - #endregion #region Window Handle @@ -918,5 +916,105 @@ namespace Flow.Launcher.Infrastructure } #endregion + + #region Sleep Mode Listener + + private static Action _func; + private static PDEVICE_NOTIFY_CALLBACK_ROUTINE _callback = null; + private static DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS _recipient; + private static SafeHandle _recipientHandle; + private static HPOWERNOTIFY _handle = HPOWERNOTIFY.Null; + + /// + /// Registers a listener for sleep mode events. + /// Inspired from: https://github.com/XKaguya/LenovoLegionToolkit + /// https://blog.csdn.net/mochounv/article/details/114668594 + /// + /// + /// + public static unsafe void RegisterSleepModeListener(Action func) + { + if (_callback != null) + { + // Only register if not already registered + return; + } + + _func = func; + _callback = new PDEVICE_NOTIFY_CALLBACK_ROUTINE(DeviceNotifyCallback); + _recipient = new DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS() + { + Callback = _callback, + Context = null + }; + + _recipientHandle = new StructSafeHandle(_recipient); + _handle = PInvoke.PowerRegisterSuspendResumeNotification( + REGISTER_NOTIFICATION_FLAGS.DEVICE_NOTIFY_CALLBACK, + _recipientHandle, + out var handle) == WIN32_ERROR.ERROR_SUCCESS ? + new HPOWERNOTIFY(new IntPtr(handle)) : + HPOWERNOTIFY.Null; + if (_handle.IsNull) + { + throw new Win32Exception("Error registering for power notifications: " + Marshal.GetLastWin32Error()); + } + } + + /// + /// Unregisters the sleep mode listener. + /// + public static void UnregisterSleepModeListener() + { + if (!_handle.IsNull) + { + PInvoke.PowerUnregisterSuspendResumeNotification(_handle); + _handle = HPOWERNOTIFY.Null; + _func = null; + _callback = null; + _recipientHandle = null; + } + } + + private static unsafe uint DeviceNotifyCallback(void* context, uint type, void* setting) + { + switch (type) + { + case PInvoke.PBT_APMRESUMEAUTOMATIC: + // Operation is resuming automatically from a low-power state.This message is sent every time the system resumes + _func(); + break; + + case PInvoke.PBT_APMRESUMESUSPEND: + // Operation is resuming from a low-power state.This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key + _func(); + break; + } + + return 0; + } + + private sealed class StructSafeHandle : SafeHandle where T : struct + { + private readonly nint _ptr = nint.Zero; + + public StructSafeHandle(T recipient) : base(nint.Zero, true) + { + var pRecipient = Marshal.AllocHGlobal(Marshal.SizeOf()); + Marshal.StructureToPtr(recipient, pRecipient, false); + SetHandle(pRecipient); + _ptr = pRecipient; + } + + public override bool IsInvalid => handle == nint.Zero; + + protected override bool ReleaseHandle() + { + Marshal.FreeHGlobal(_ptr); + return true; + } + } + + #endregion } } diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index a9e03bc8c..01a7dc9bd 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -95,6 +95,7 @@ namespace Flow.Launcher UpdatePosition(); InitSoundEffects(); + RegisterSoundEffectsEvent(); DataObject.AddPastingHandler(QueryTextBox, QueryTextBox_OnPaste); _viewModel.ActualApplicationThemeChanged += ViewModel_ActualApplicationThemeChanged; } @@ -668,16 +669,6 @@ namespace Flow.Launcher handled = true; } break; - case Win32Helper.WM_POWERBROADCAST: // Handle power broadcast messages - // https://learn.microsoft.com/en-us/windows/win32/power/wm-powerbroadcast - if (wParam.ToInt32() == Win32Helper.PBT_APMRESUMEAUTOMATIC) - { - // Fix for sound not playing after sleep / hibernate - // https://stackoverflow.com/questions/64805186/mediaplayer-doesnt-play-after-computer-sleeps - InitSoundEffects(); - } - handled = true; - break; } return IntPtr.Zero; @@ -723,6 +714,47 @@ namespace Flow.Launcher } } + private void RegisterSoundEffectsEvent() + { + // Fix for sound not playing after sleep / hibernate for both modern standby and legacy standby + // https://stackoverflow.com/questions/64805186/mediaplayer-doesnt-play-after-computer-sleeps + try + { + Win32Helper.RegisterSleepModeListener(() => + { + if (Application.Current == null) + { + return; + } + + // We must run InitSoundEffects on UI thread because MediaPlayer is a DispatcherObject + if (!Application.Current.Dispatcher.CheckAccess()) + { + Application.Current.Dispatcher.Invoke(InitSoundEffects); + return; + } + + InitSoundEffects(); + }); + } + catch (Exception e) + { + App.API.LogException(ClassName, "Failed to register sound effect event", e); + } + } + + private static void UnregisterSoundEffectsEvent() + { + try + { + Win32Helper.UnregisterSleepModeListener(); + } + catch (Exception e) + { + App.API.LogException(ClassName, "Failed to unregister sound effect event", e); + } + } + #endregion #region Window Notify Icon @@ -1447,6 +1479,7 @@ namespace Flow.Launcher _animationSoundWMP?.Close(); _animationSoundWPF?.Dispose(); _viewModel.ActualApplicationThemeChanged -= ViewModel_ActualApplicationThemeChanged; + UnregisterSoundEffectsEvent(); } _disposed = true; From c27817eaf0f7c58bf8aba58afb1856a6e7d34a28 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 30 Sep 2025 21:20:00 +0800 Subject: [PATCH 68/73] Fix possible null exception --- Flow.Launcher.Infrastructure/Win32Helper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index c94008b03..8a41e12b4 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -982,12 +982,12 @@ namespace Flow.Launcher.Infrastructure { case PInvoke.PBT_APMRESUMEAUTOMATIC: // Operation is resuming automatically from a low-power state.This message is sent every time the system resumes - _func(); + _func?.Invoke(); break; case PInvoke.PBT_APMRESUMESUSPEND: // Operation is resuming from a low-power state.This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key - _func(); + _func?.Invoke(); break; } From e376da44820f3ac69602cce1f5e66c5c920af1b2 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 2 Oct 2025 19:29:46 +0800 Subject: [PATCH 69/73] Save settings before shutdown/restart to prevent data loss Added a call to `Context.API.SaveAppAllSettings()` before executing system shutdown, restart, or advanced restart operations. This ensures that any unsaved settings are persisted, reducing the risk of data loss during these actions. --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 89067d44c..d0eb339fe 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -211,6 +211,9 @@ namespace Flow.Launcher.Plugin.Sys Localize.flowlauncher_plugin_sys_shutdown_computer(), MessageBoxButton.YesNo, MessageBoxImage.Warning); + // Save settings before shutdown to avoid data loss + Context.API.SaveAppAllSettings(); + if (result == MessageBoxResult.Yes) if (EnableShutdownPrivilege()) PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF, REASON); @@ -232,6 +235,9 @@ namespace Flow.Launcher.Plugin.Sys Localize.flowlauncher_plugin_sys_restart_computer(), MessageBoxButton.YesNo, MessageBoxImage.Warning); + // Save settings before restart to avoid data loss + Context.API.SaveAppAllSettings(); + if (result == MessageBoxResult.Yes) if (EnableShutdownPrivilege()) PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT, REASON); @@ -253,6 +259,9 @@ namespace Flow.Launcher.Plugin.Sys Localize.flowlauncher_plugin_sys_restart_computer(), MessageBoxButton.YesNo, MessageBoxImage.Warning); + // Save settings before restart to avoid data loss + Context.API.SaveAppAllSettings(); + if (result == MessageBoxResult.Yes) if (EnableShutdownPrivilege()) PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS, REASON); From 167570559f82c8c7fa5bf51a5b33a0ca78c7c26d Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 2 Oct 2025 19:42:24 +0800 Subject: [PATCH 70/73] Move settings save to post-confirmation for actions Previously, `Context.API.SaveAppAllSettings()` was called unconditionally before user confirmation for shutdown, restart, and advanced restart actions. This change ensures settings are only saved if the user confirms the action by clicking "Yes" in the confirmation dialog. For all three functionalities: - Moved the settings save call inside the `if (result == MessageBoxResult.Yes)` block. - Retained the existing logic for executing the respective system commands, with checks for `EnableShutdownPrivilege()` to determine whether to use `PInvoke.ExitWindowsEx` or the `shutdown` command. This change prevents unnecessary settings saves when the user cancels the action. --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 30 ++++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index d0eb339fe..b53c0261b 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -210,16 +210,16 @@ namespace Flow.Launcher.Plugin.Sys Localize.flowlauncher_plugin_sys_dlgtext_shutdown_computer(), Localize.flowlauncher_plugin_sys_shutdown_computer(), MessageBoxButton.YesNo, MessageBoxImage.Warning); - - // Save settings before shutdown to avoid data loss - Context.API.SaveAppAllSettings(); - if (result == MessageBoxResult.Yes) + { + // Save settings before shutdown to avoid data loss + Context.API.SaveAppAllSettings(); + if (EnableShutdownPrivilege()) PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_SHUTDOWN | EXIT_WINDOWS_FLAGS.EWX_POWEROFF, REASON); else Process.Start("shutdown", "/s /t 0"); - + } return true; } }, @@ -234,16 +234,16 @@ namespace Flow.Launcher.Plugin.Sys Localize.flowlauncher_plugin_sys_dlgtext_restart_computer(), Localize.flowlauncher_plugin_sys_restart_computer(), MessageBoxButton.YesNo, MessageBoxImage.Warning); - - // Save settings before restart to avoid data loss - Context.API.SaveAppAllSettings(); - if (result == MessageBoxResult.Yes) + { + // Save settings before restart to avoid data loss + Context.API.SaveAppAllSettings(); + if (EnableShutdownPrivilege()) PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT, REASON); else Process.Start("shutdown", "/r /t 0"); - + } return true; } }, @@ -258,16 +258,16 @@ namespace Flow.Launcher.Plugin.Sys Localize.flowlauncher_plugin_sys_dlgtext_restart_computer_advanced(), Localize.flowlauncher_plugin_sys_restart_computer(), MessageBoxButton.YesNo, MessageBoxImage.Warning); - - // Save settings before restart to avoid data loss - Context.API.SaveAppAllSettings(); - if (result == MessageBoxResult.Yes) + { + // Save settings before restart to avoid data loss + Context.API.SaveAppAllSettings(); + if (EnableShutdownPrivilege()) PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_REBOOT | EXIT_WINDOWS_FLAGS.EWX_BOOTOPTIONS, REASON); else Process.Start("shutdown", "/r /o /t 0"); - + } return true; } }, From d08ee30a7a17c23f481302dad350ff7c042eb42e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 2 Oct 2025 19:43:31 +0800 Subject: [PATCH 71/73] Refactor plugin actions to simplify logic Removed logoff operation logic and associated return statement. Eliminated return statement after recycle bin error handling. Removed async plugin data reload and success message logic. Simplified theme selector query handling by removing `return false`. These changes streamline the code and improve maintainability. --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index b53c0261b..cb3acf77f 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -282,10 +282,8 @@ namespace Flow.Launcher.Plugin.Sys Localize.flowlauncher_plugin_sys_dlgtext_logoff_computer(), Localize.flowlauncher_plugin_sys_log_off(), MessageBoxButton.YesNo, MessageBoxImage.Warning); - if (result == MessageBoxResult.Yes) PInvoke.ExitWindowsEx(EXIT_WINDOWS_FLAGS.EWX_LOGOFF, REASON); - return true; } }, @@ -351,7 +349,6 @@ namespace Flow.Launcher.Plugin.Sys Localize.flowlauncher_plugin_sys_dlgtitle_error(), MessageBoxButton.OK, MessageBoxImage.Error); } - return true; } }, @@ -425,13 +422,11 @@ namespace Flow.Launcher.Plugin.Sys { // Hide the window first then show msg after done because sometimes the reload could take a while, so not to make user think it's frozen. Context.API.HideMainWindow(); - _ = Context.API.ReloadAllPluginData().ContinueWith(_ => Context.API.ShowMsg( Localize.flowlauncher_plugin_sys_dlgtitle_success(), Localize.flowlauncher_plugin_sys_dlgtext_all_applicableplugins_reloaded()), TaskScheduler.Current); - return true; } }, @@ -511,7 +506,6 @@ namespace Flow.Launcher.Plugin.Sys else { Context.API.ChangeQuery($"{query.ActionKeyword}{Plugin.Query.ActionKeywordSeparator}{ThemeSelector.Keyword}{Plugin.Query.ActionKeywordSeparator}"); - } return false; } From 5b0a30774e711fececa2088316657cc9338e01c8 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Thu, 2 Oct 2025 19:45:08 +0800 Subject: [PATCH 72/73] Fix code comment typo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index cb3acf77f..57b9749f7 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -260,7 +260,7 @@ namespace Flow.Launcher.Plugin.Sys MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) { - // Save settings before restart to avoid data loss + // Save settings before advanced restart to avoid data loss Context.API.SaveAppAllSettings(); if (EnableShutdownPrivilege()) From 5ae159de5b69950df4f82b413ba91f4860f43f35 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Sun, 5 Oct 2025 18:44:40 +0800 Subject: [PATCH 73/73] Move to iNKORE.UI.WPF.Modern UI Framework (#3593) --- .../Resource/LocalizedDescriptionAttribute.cs | 24 - Flow.Launcher.Core/Resource/Theme.cs | 14 +- Flow.Launcher/App.xaml | 18 +- Flow.Launcher/App.xaml.cs | 4 + .../BoolToIMEConversionModeConverter.cs | 4 +- .../Converters/CornerRadiusFilterConverter.cs | 91 + .../Converters/PlacementRectangleConverter.cs | 32 + .../Converters/SharedSizeGroupConverter.cs | 19 + .../Converters/StringToKeyBindingConverter.cs | 2 +- Flow.Launcher/Flow.Launcher.csproj | 4 +- Flow.Launcher/Helper/BorderHelper.cs | 33 + Flow.Launcher/HotkeyControlDialog.xaml | 2 +- Flow.Launcher/HotkeyControlDialog.xaml.cs | 2 +- Flow.Launcher/MainWindow.xaml | 2 +- Flow.Launcher/MainWindow.xaml.cs | 7 +- Flow.Launcher/PluginUpdateWindow.xaml | 5 +- Flow.Launcher/PublicAPIInstance.cs | 2 +- Flow.Launcher/ReleaseNotesWindow.xaml | 24 +- Flow.Launcher/ReleaseNotesWindow.xaml.cs | 13 +- Flow.Launcher/Resources/Controls/Card.xaml | 139 - Flow.Launcher/Resources/Controls/Card.xaml.cs | 67 - .../Resources/Controls/CardGroup.xaml | 32 - .../Resources/Controls/CardGroup.xaml.cs | 47 - .../Controls/CardGroupCardStyleSelector.cs | 21 - .../Controls/CustomScrollViewerEx.cs | 253 ++ Flow.Launcher/Resources/Controls/ExCard.xaml | 312 -- .../Resources/Controls/ExCard.xaml.cs | 57 - .../Resources/Controls/HyperLink.xaml | 14 - .../Resources/Controls/HyperLink.xaml.cs | 39 - Flow.Launcher/Resources/Controls/InfoBar.xaml | 81 - .../Resources/Controls/InfoBar.xaml.cs | 222 - .../Controls/InstalledPluginDisplay.xaml | 4 +- .../Controls/InstalledPluginDisplay.xaml.cs | 2 +- .../Resources/CustomControlTemplate.xaml | 3811 +++-------------- Flow.Launcher/Resources/Dark.xaml | 1549 +------ Flow.Launcher/Resources/Light.xaml | 1552 +------ .../Resources/Pages/WelcomePage1.xaml | 11 +- .../Resources/Pages/WelcomePage2.xaml | 17 +- .../Resources/Pages/WelcomePage3.xaml | 153 +- .../Resources/Pages/WelcomePage4.xaml | 9 +- .../Resources/Pages/WelcomePage5.xaml | 13 +- .../Resources/SettingWindowStyle.xaml | 435 +- Flow.Launcher/ResultListBox.xaml | 1 + Flow.Launcher/SelectBrowserWindow.xaml | 2 +- Flow.Launcher/SelectFileManagerWindow.xaml | 6 +- Flow.Launcher/SelectFileManagerWindow.xaml.cs | 6 - .../ViewModels/SettingsPaneAboutViewModel.cs | 6 + .../SettingsPanePluginsViewModel.cs | 2 +- .../ViewModels/SettingsPaneThemeViewModel.cs | 13 +- .../SettingPages/Views/SettingsPaneAbout.xaml | 180 +- .../Views/SettingsPaneAbout.xaml.cs | 6 - .../Views/SettingsPaneGeneral.xaml | 725 ++-- .../Views/SettingsPaneHotkey.xaml | 736 ++-- .../Views/SettingsPanePluginStore.xaml | 102 +- .../Views/SettingsPanePlugins.xaml | 55 +- .../SettingPages/Views/SettingsPaneProxy.xaml | 77 +- .../SettingPages/Views/SettingsPaneTheme.xaml | 666 +-- Flow.Launcher/SettingWindow.xaml | 5 +- Flow.Launcher/SettingWindow.xaml.cs | 9 +- Flow.Launcher/Themes/Base.xaml | 23 +- Flow.Launcher/Themes/BlurWhite.xaml | 2 +- Flow.Launcher/Themes/Circle System.xaml | 2 +- Flow.Launcher/Themes/Cyan Dark.xaml | 12 +- Flow.Launcher/Themes/Dracula.xaml | 6 +- Flow.Launcher/Themes/Gray.xaml | 8 +- Flow.Launcher/Themes/Sublime.xaml | 6 +- Flow.Launcher/Themes/Win10System.xaml | 2 +- Flow.Launcher/Themes/Win11Light.xaml | 2 +- Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- Flow.Launcher/WelcomeWindow.xaml | 7 +- Flow.Launcher/WelcomeWindow.xaml.cs | 2 +- Flow.Launcher/packages.lock.json | 20 +- .../Views/ExplorerSettings.xaml | 15 +- .../ProgramSuffixes.xaml | 2 +- .../SettingsControl.xaml | 42 +- .../SettingsControl.xaml.cs | 23 + README.md | 14 +- 77 files changed, 2846 insertions(+), 9083 deletions(-) delete mode 100644 Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs create mode 100644 Flow.Launcher/Converters/CornerRadiusFilterConverter.cs create mode 100644 Flow.Launcher/Converters/PlacementRectangleConverter.cs create mode 100644 Flow.Launcher/Converters/SharedSizeGroupConverter.cs create mode 100644 Flow.Launcher/Helper/BorderHelper.cs delete mode 100644 Flow.Launcher/Resources/Controls/Card.xaml delete mode 100644 Flow.Launcher/Resources/Controls/Card.xaml.cs delete mode 100644 Flow.Launcher/Resources/Controls/CardGroup.xaml delete mode 100644 Flow.Launcher/Resources/Controls/CardGroup.xaml.cs delete mode 100644 Flow.Launcher/Resources/Controls/CardGroupCardStyleSelector.cs create mode 100644 Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs delete mode 100644 Flow.Launcher/Resources/Controls/ExCard.xaml delete mode 100644 Flow.Launcher/Resources/Controls/ExCard.xaml.cs delete mode 100644 Flow.Launcher/Resources/Controls/HyperLink.xaml delete mode 100644 Flow.Launcher/Resources/Controls/HyperLink.xaml.cs delete mode 100644 Flow.Launcher/Resources/Controls/InfoBar.xaml delete mode 100644 Flow.Launcher/Resources/Controls/InfoBar.xaml.cs diff --git a/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs b/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs deleted file mode 100644 index acd9d9eb7..000000000 --- a/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.ComponentModel; - -namespace Flow.Launcher.Core.Resource -{ - public class LocalizedDescriptionAttribute : DescriptionAttribute - { - private readonly string _resourceKey; - - public LocalizedDescriptionAttribute(string resourceKey) - { - _resourceKey = resourceKey; - } - - public override string Description - { - get - { - string description = PublicApi.Instance.GetTranslation(_resourceKey); - return string.IsNullOrWhiteSpace(description) ? - string.Format("[[{0}]]", _resourceKey) : description; - } - } - } -} diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index d1f7da2a2..c3bb6190f 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -449,9 +449,19 @@ namespace Flow.Launcher.Core.Resource } return false; } - catch (XamlParseException) + catch (XamlParseException e) { - _api.LogError(ClassName, $"Theme <{theme}> fail to parse"); + _api.LogException(ClassName, $"Theme <{theme}> fail to parse xaml", e); + if (theme != Constant.DefaultTheme) + { + _api.ShowMsgBox(Localize.theme_load_failure_parse_error(theme)); + ChangeTheme(Constant.DefaultTheme); + } + return false; + } + catch (Exception e) + { + _api.LogException(ClassName, $"Theme <{theme}> fail to load", e); if (theme != Constant.DefaultTheme) { _api.ShowMsgBox(Localize.theme_load_failure_parse_error(theme)); diff --git a/Flow.Launcher/App.xaml b/Flow.Launcher/App.xaml index 565bbe3c7..e922cd558 100644 --- a/Flow.Launcher/App.xaml +++ b/Flow.Launcher/App.xaml @@ -2,7 +2,8 @@ x:Class="Flow.Launcher.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:ui="http://schemas.modernwpf.com/2019" + xmlns:sys="clr-namespace:System;assembly=mscorlib" + xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern" ShutdownMode="OnMainWindowClose" Startup="OnStartup"> @@ -10,17 +11,17 @@ - + - + - + @@ -33,6 +34,15 @@ + + + 2 + 0 + 0 + 40 + 0 + 36 + \ No newline at end of file diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 58f8438d2..1ca3ce2c6 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -22,6 +22,7 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.SettingPages.ViewModels; using Flow.Launcher.ViewModel; +using iNKORE.UI.WPF.Modern.Common; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.VisualStudio.Threading; @@ -56,6 +57,9 @@ namespace Flow.Launcher public App() { + // Do not use bitmap cache since it can cause WPF second window freezing issue + ShadowAssist.UseBitmapCache = false; + // Initialize settings _settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled(); diff --git a/Flow.Launcher/Converters/BoolToIMEConversionModeConverter.cs b/Flow.Launcher/Converters/BoolToIMEConversionModeConverter.cs index 41e879913..82da6d936 100644 --- a/Flow.Launcher/Converters/BoolToIMEConversionModeConverter.cs +++ b/Flow.Launcher/Converters/BoolToIMEConversionModeConverter.cs @@ -5,7 +5,7 @@ using System.Windows.Input; namespace Flow.Launcher.Converters; -internal class BoolToIMEConversionModeConverter : IValueConverter +public class BoolToIMEConversionModeConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { @@ -22,7 +22,7 @@ internal class BoolToIMEConversionModeConverter : IValueConverter } } -internal class BoolToIMEStateConverter : IValueConverter +public class BoolToIMEStateConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { diff --git a/Flow.Launcher/Converters/CornerRadiusFilterConverter.cs b/Flow.Launcher/Converters/CornerRadiusFilterConverter.cs new file mode 100644 index 000000000..fd43cafac --- /dev/null +++ b/Flow.Launcher/Converters/CornerRadiusFilterConverter.cs @@ -0,0 +1,91 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace Flow.Launcher.Converters; + +public class CornerRadiusFilterConverter : DependencyObject, IValueConverter +{ + public CornerRadiusFilterKind Filter { get; set; } + + public double Scale { get; set; } = 1.0; + + public static CornerRadius Convert(CornerRadius radius, CornerRadiusFilterKind filterKind) + { + CornerRadius result = radius; + + switch (filterKind) + { + case CornerRadiusFilterKind.Top: + result.BottomLeft = 0; + result.BottomRight = 0; + break; + case CornerRadiusFilterKind.Right: + result.TopLeft = 0; + result.BottomLeft = 0; + break; + case CornerRadiusFilterKind.Bottom: + result.TopLeft = 0; + result.TopRight = 0; + break; + case CornerRadiusFilterKind.Left: + result.TopRight = 0; + result.BottomRight = 0; + break; + } + + return result; + } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var cornerRadius = (CornerRadius)value; + + var scale = Scale; + if (!double.IsNaN(scale)) + { + cornerRadius.TopLeft *= scale; + cornerRadius.TopRight *= scale; + cornerRadius.BottomRight *= scale; + cornerRadius.BottomLeft *= scale; + } + + var filterType = Filter; + if (filterType == CornerRadiusFilterKind.TopLeftValue || + filterType == CornerRadiusFilterKind.BottomRightValue) + { + return GetDoubleValue(cornerRadius, filterType); + } + + return Convert(cornerRadius, filterType); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + + private static double GetDoubleValue(CornerRadius radius, CornerRadiusFilterKind filterKind) + { + switch (filterKind) + { + case CornerRadiusFilterKind.TopLeftValue: + return radius.TopLeft; + case CornerRadiusFilterKind.BottomRightValue: + return radius.BottomRight; + } + return 0; + } +} + +public enum CornerRadiusFilterKind +{ + None, + Top, + Right, + Bottom, + Left, + TopLeftValue, + BottomRightValue +} diff --git a/Flow.Launcher/Converters/PlacementRectangleConverter.cs b/Flow.Launcher/Converters/PlacementRectangleConverter.cs new file mode 100644 index 000000000..130d04e16 --- /dev/null +++ b/Flow.Launcher/Converters/PlacementRectangleConverter.cs @@ -0,0 +1,32 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace Flow.Launcher.Converters; + +public class PlacementRectangleConverter : IMultiValueConverter +{ + public Thickness Margin { get; set; } + + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + if (values.Length == 2 && + values[0] is double width && + values[1] is double height) + { + var margin = Margin; + var topLeft = new Point(margin.Left, margin.Top); + var bottomRight = new Point(width - margin.Right, height - margin.Bottom); + var rect = new Rect(topLeft, bottomRight); + return rect; + } + + return Rect.Empty; + } + + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} diff --git a/Flow.Launcher/Converters/SharedSizeGroupConverter.cs b/Flow.Launcher/Converters/SharedSizeGroupConverter.cs new file mode 100644 index 000000000..594787027 --- /dev/null +++ b/Flow.Launcher/Converters/SharedSizeGroupConverter.cs @@ -0,0 +1,19 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace Flow.Launcher.Converters; + +public class SharedSizeGroupConverter : IValueConverter +{ + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (Visibility)value != Visibility.Collapsed ? (string)parameter : null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} diff --git a/Flow.Launcher/Converters/StringToKeyBindingConverter.cs b/Flow.Launcher/Converters/StringToKeyBindingConverter.cs index 21bf584e7..b7bca41c5 100644 --- a/Flow.Launcher/Converters/StringToKeyBindingConverter.cs +++ b/Flow.Launcher/Converters/StringToKeyBindingConverter.cs @@ -5,7 +5,7 @@ using System.Windows.Input; namespace Flow.Launcher.Converters; -class StringToKeyBindingConverter : IValueConverter +public class StringToKeyBindingConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index aa8e95429..8c7670426 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -138,6 +138,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -146,9 +147,6 @@ - - - all diff --git a/Flow.Launcher/Helper/BorderHelper.cs b/Flow.Launcher/Helper/BorderHelper.cs new file mode 100644 index 000000000..0f2a78e7d --- /dev/null +++ b/Flow.Launcher/Helper/BorderHelper.cs @@ -0,0 +1,33 @@ +using System.Windows; +using System.Windows.Controls; + +namespace Flow.Launcher.Helper; + +public static class BorderHelper +{ + #region Child + + public static readonly DependencyProperty ChildProperty = + DependencyProperty.RegisterAttached( + "Child", + typeof(UIElement), + typeof(BorderHelper), + new PropertyMetadata(default(UIElement), OnChildChanged)); + + public static UIElement GetChild(Border border) + { + return (UIElement)border.GetValue(ChildProperty); + } + + public static void SetChild(Border border, UIElement value) + { + border.SetValue(ChildProperty, value); + } + + private static void OnChildChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((Border)d).Child = (UIElement)e.NewValue; + } + + #endregion +} diff --git a/Flow.Launcher/HotkeyControlDialog.xaml b/Flow.Launcher/HotkeyControlDialog.xaml index d416f1bdc..9fdfda865 100644 --- a/Flow.Launcher/HotkeyControlDialog.xaml +++ b/Flow.Launcher/HotkeyControlDialog.xaml @@ -2,7 +2,7 @@ x:Class="Flow.Launcher.HotkeyControlDialog" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:ui="http://schemas.modernwpf.com/2019" + xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern" Background="{DynamicResource PopuBGColor}" BorderBrush="{DynamicResource PopupButtonAreaBorderColor}" BorderThickness="0 1 0 0" diff --git a/Flow.Launcher/HotkeyControlDialog.xaml.cs b/Flow.Launcher/HotkeyControlDialog.xaml.cs index 740425f8b..e1fc86f95 100644 --- a/Flow.Launcher/HotkeyControlDialog.xaml.cs +++ b/Flow.Launcher/HotkeyControlDialog.xaml.cs @@ -9,7 +9,7 @@ using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; -using ModernWpf.Controls; +using iNKORE.UI.WPF.Modern.Controls; namespace Flow.Launcher; diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index 132ec8389..dd47f9d4e 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -6,7 +6,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:flowlauncher="clr-namespace:Flow.Launcher" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:ui="http://schemas.modernwpf.com/2019" + xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern" xmlns:vm="clr-namespace:Flow.Launcher.ViewModel" Name="FlowMainWindow" Title="Flow Launcher" diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 01a7dc9bd..b2ba33269 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -25,7 +25,8 @@ using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher.ViewModel; -using ModernWpf.Controls; +using iNKORE.UI.WPF.Modern; +using iNKORE.UI.WPF.Modern.Controls; using DataObject = System.Windows.DataObject; using Key = System.Windows.Input.Key; using MouseButtons = System.Windows.Forms.MouseButtons; @@ -191,11 +192,11 @@ namespace Flow.Launcher // Initialize color scheme if (_settings.ColorScheme == Constant.Light) { - ModernWpf.ThemeManager.Current.ApplicationTheme = ModernWpf.ApplicationTheme.Light; + ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light; } else if (_settings.ColorScheme == Constant.Dark) { - ModernWpf.ThemeManager.Current.ApplicationTheme = ModernWpf.ApplicationTheme.Dark; + ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark; } // Initialize position diff --git a/Flow.Launcher/PluginUpdateWindow.xaml b/Flow.Launcher/PluginUpdateWindow.xaml index 04cd1f7bc..a4bb06431 100644 --- a/Flow.Launcher/PluginUpdateWindow.xaml +++ b/Flow.Launcher/PluginUpdateWindow.xaml @@ -4,6 +4,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:flowlauncher="clr-namespace:Flow.Launcher" + xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern" Title="{DynamicResource updateAllPluginsButtonContent}" Width="530" Background="{DynamicResource PopuBGColor}" @@ -66,13 +67,13 @@ Text="{DynamicResource updateAllPluginsButtonContent}" TextAlignment="Left" /> - - + - + @@ -161,18 +162,23 @@ Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="5" - Margin="18 0 18 0"> - + Margin="6 0 18 0"> + - + Height="500" + Margin="15 0 0 0" + Padding="0 0 15 0" + HorizontalAlignment="Stretch"> @@ -193,11 +199,11 @@ VerticalScrollBarVisibility="Disabled" Visibility="Collapsed" /> - + - + Properties.Settings.Default.GithubRepo + "/releases"; public ReleaseNotesWindow() { InitializeComponent(); - SeeMore.Uri = ReleaseNotes; - ModernWpf.ThemeManager.Current.ActualApplicationThemeChanged += ThemeManager_ActualApplicationThemeChanged; + ThemeManager.Current.ActualApplicationThemeChanged += ThemeManager_ActualApplicationThemeChanged; } #region Window Events - private void ThemeManager_ActualApplicationThemeChanged(ModernWpf.ThemeManager sender, object args) + private void ThemeManager_ActualApplicationThemeChanged(ThemeManager sender, object args) { Application.Current.Dispatcher.Invoke(() => { - if (ModernWpf.ThemeManager.Current.ActualApplicationTheme == ModernWpf.ApplicationTheme.Light) + if (ThemeManager.Current.ActualApplicationTheme == ApplicationTheme.Light) { MarkdownViewer.MarkdownStyle = (Style)Application.Current.Resources["DocumentStyleGithubLikeLight"]; MarkdownViewer.Foreground = Brushes.Black; @@ -58,7 +58,7 @@ namespace Flow.Launcher private void Window_Closed(object sender, EventArgs e) { - ModernWpf.ThemeManager.Current.ActualApplicationThemeChanged -= ThemeManager_ActualApplicationThemeChanged; + ThemeManager.Current.ActualApplicationThemeChanged -= ThemeManager_ActualApplicationThemeChanged; } #endregion @@ -147,7 +147,6 @@ namespace Flow.Launcher private void Grid_SizeChanged(object sender, SizeChangedEventArgs e) { MarkdownScrollViewer.Height = e.NewSize.Height; - MarkdownScrollViewer.Width = e.NewSize.Width; } private void MarkdownViewer_MouseWheel(object sender, MouseWheelEventArgs e) diff --git a/Flow.Launcher/Resources/Controls/Card.xaml b/Flow.Launcher/Resources/Controls/Card.xaml deleted file mode 100644 index e3c5f8194..000000000 --- a/Flow.Launcher/Resources/Controls/Card.xaml +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Flow.Launcher/Resources/Controls/Card.xaml.cs b/Flow.Launcher/Resources/Controls/Card.xaml.cs deleted file mode 100644 index 6a70dded2..000000000 --- a/Flow.Launcher/Resources/Controls/Card.xaml.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Windows; -using UserControl = System.Windows.Controls.UserControl; - -namespace Flow.Launcher.Resources.Controls -{ - public partial class Card : UserControl - { - public enum CardType - { - Default, - Inside, - InsideFit, - First, - Middle, - Last - } - - public Card() - { - InitializeComponent(); - } - - public string Title - { - get { return (string)GetValue(TitleProperty); } - set { SetValue(TitleProperty, value); } - } - public static readonly DependencyProperty TitleProperty = - DependencyProperty.Register(nameof(Title), typeof(string), typeof(Card), new PropertyMetadata(string.Empty)); - - public string Sub - { - get { return (string)GetValue(SubProperty); } - set { SetValue(SubProperty, value); } - } - public static readonly DependencyProperty SubProperty = - DependencyProperty.Register(nameof(Sub), typeof(string), typeof(Card), new PropertyMetadata(string.Empty)); - - public string Icon - { - get { return (string)GetValue(IconProperty); } - set { SetValue(IconProperty, value); } - } - public static readonly DependencyProperty IconProperty = - DependencyProperty.Register(nameof(Icon), typeof(string), typeof(Card), new PropertyMetadata(string.Empty)); - - /// - /// Gets or sets additional content for the UserControl - /// - public object AdditionalContent - { - get { return (object)GetValue(AdditionalContentProperty); } - set { SetValue(AdditionalContentProperty, value); } - } - public static readonly DependencyProperty AdditionalContentProperty = - DependencyProperty.Register(nameof(AdditionalContent), typeof(object), typeof(Card), - new PropertyMetadata(null)); - public CardType Type - { - get { return (CardType)GetValue(TypeProperty); } - set { SetValue(TypeProperty, value); } - } - public static readonly DependencyProperty TypeProperty = - DependencyProperty.Register(nameof(Type), typeof(CardType), typeof(Card), - new PropertyMetadata(CardType.Default)); - } -} diff --git a/Flow.Launcher/Resources/Controls/CardGroup.xaml b/Flow.Launcher/Resources/Controls/CardGroup.xaml deleted file mode 100644 index f48bf4b6c..000000000 --- a/Flow.Launcher/Resources/Controls/CardGroup.xaml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - diff --git a/Flow.Launcher/Resources/Controls/CardGroup.xaml.cs b/Flow.Launcher/Resources/Controls/CardGroup.xaml.cs deleted file mode 100644 index b9588275c..000000000 --- a/Flow.Launcher/Resources/Controls/CardGroup.xaml.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.Windows; -using System.Windows.Controls; - -namespace Flow.Launcher.Resources.Controls; - -public partial class CardGroup : UserControl -{ - public enum CardGroupPosition - { - NotInGroup, - First, - Middle, - Last - } - - public new ObservableCollection Content - { - get { return (ObservableCollection)GetValue(ContentProperty); } - set { SetValue(ContentProperty, value); } - } - - public static new readonly DependencyProperty ContentProperty = - DependencyProperty.Register(nameof(Content), typeof(ObservableCollection), typeof(CardGroup)); - - public static readonly DependencyProperty PositionProperty = DependencyProperty.RegisterAttached( - "Position", typeof(CardGroupPosition), typeof(CardGroup), - new FrameworkPropertyMetadata(CardGroupPosition.NotInGroup, FrameworkPropertyMetadataOptions.AffectsRender) - ); - - public static void SetPosition(UIElement element, CardGroupPosition value) - { - element.SetValue(PositionProperty, value); - } - - public static CardGroupPosition GetPosition(UIElement element) - { - return (CardGroupPosition)element.GetValue(PositionProperty); - } - - public CardGroup() - { - InitializeComponent(); - Content = new ObservableCollection(); - } -} diff --git a/Flow.Launcher/Resources/Controls/CardGroupCardStyleSelector.cs b/Flow.Launcher/Resources/Controls/CardGroupCardStyleSelector.cs deleted file mode 100644 index 605934e80..000000000 --- a/Flow.Launcher/Resources/Controls/CardGroupCardStyleSelector.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Windows; -using System.Windows.Controls; - -namespace Flow.Launcher.Resources.Controls; - -public class CardGroupCardStyleSelector : StyleSelector -{ - public Style FirstStyle { get; set; } - public Style MiddleStyle { get; set; } - public Style LastStyle { get; set; } - - public override Style SelectStyle(object item, DependencyObject container) - { - var itemsControl = ItemsControl.ItemsControlFromItemContainer(container); - var index = itemsControl.ItemContainerGenerator.IndexFromContainer(container); - - if (index == 0) return FirstStyle; - if (index == itemsControl.Items.Count - 1) return LastStyle; - return MiddleStyle; - } -} diff --git a/Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs b/Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs new file mode 100644 index 000000000..78985108c --- /dev/null +++ b/Flow.Launcher/Resources/Controls/CustomScrollViewerEx.cs @@ -0,0 +1,253 @@ +using iNKORE.UI.WPF.Modern.Controls; +using iNKORE.UI.WPF.Modern.Controls.Helpers; +using iNKORE.UI.WPF.Modern.Controls.Primitives; +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +namespace Flow.Launcher.Resources.Controls +{ + // TODO: Use IsScrollAnimationEnabled property in future: https://github.com/iNKORE-NET/UI.WPF.Modern/pull/347 + public class CustomScrollViewerEx : ScrollViewer + { + private double LastVerticalLocation = 0; + private double LastHorizontalLocation = 0; + + public CustomScrollViewerEx() + { + Loaded += OnLoaded; + var valueSource = DependencyPropertyHelper.GetValueSource(this, AutoPanningMode.IsEnabledProperty).BaseValueSource; + if (valueSource == BaseValueSource.Default) + { + AutoPanningMode.SetIsEnabled(this, true); + } + } + + #region Orientation + + public static readonly DependencyProperty OrientationProperty = + DependencyProperty.Register( + nameof(Orientation), + typeof(Orientation), + typeof(CustomScrollViewerEx), + new PropertyMetadata(Orientation.Vertical)); + + public Orientation Orientation + { + get => (Orientation)GetValue(OrientationProperty); + set => SetValue(OrientationProperty, value); + } + + #endregion + + #region AutoHideScrollBars + + public static readonly DependencyProperty AutoHideScrollBarsProperty = + ScrollViewerHelper.AutoHideScrollBarsProperty + .AddOwner( + typeof(CustomScrollViewerEx), + new PropertyMetadata(true, OnAutoHideScrollBarsChanged)); + + public bool AutoHideScrollBars + { + get => (bool)GetValue(AutoHideScrollBarsProperty); + set => SetValue(AutoHideScrollBarsProperty, value); + } + + private static void OnAutoHideScrollBarsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is CustomScrollViewerEx sv) + { + sv.UpdateVisualState(); + } + } + + #endregion + + private void OnLoaded(object sender, RoutedEventArgs e) + { + LastVerticalLocation = VerticalOffset; + LastHorizontalLocation = HorizontalOffset; + UpdateVisualState(false); + } + + /// + protected override void OnInitialized(EventArgs e) + { + base.OnInitialized(e); + + if (Style == null && ReadLocalValue(StyleProperty) == DependencyProperty.UnsetValue) + { + SetResourceReference(StyleProperty, typeof(ScrollViewer)); + } + } + + /// + protected override void OnMouseWheel(MouseWheelEventArgs e) + { + var Direction = GetDirection(); + ScrollViewerBehavior.SetIsAnimating(this, true); + + if (Direction == Orientation.Vertical) + { + if (ScrollableHeight > 0) + { + e.Handled = true; + } + + var WheelChange = e.Delta * (ViewportHeight / 1.5) / ActualHeight; + var newOffset = LastVerticalLocation - WheelChange; + + if (newOffset < 0) + { + newOffset = 0; + } + + if (newOffset > ScrollableHeight) + { + newOffset = ScrollableHeight; + } + + if (newOffset == LastVerticalLocation) + { + return; + } + + ScrollToVerticalOffset(LastVerticalLocation); + + ScrollToValue(newOffset, Direction); + LastVerticalLocation = newOffset; + } + else + { + if (ScrollableWidth > 0) + { + e.Handled = true; + } + + var WheelChange = e.Delta * (ViewportWidth / 1.5) / ActualWidth; + var newOffset = LastHorizontalLocation - WheelChange; + + if (newOffset < 0) + { + newOffset = 0; + } + + if (newOffset > ScrollableWidth) + { + newOffset = ScrollableWidth; + } + + if (newOffset == LastHorizontalLocation) + { + return; + } + + ScrollToHorizontalOffset(LastHorizontalLocation); + + ScrollToValue(newOffset, Direction); + LastHorizontalLocation = newOffset; + } + } + + /// + protected override void OnScrollChanged(ScrollChangedEventArgs e) + { + base.OnScrollChanged(e); + if (!ScrollViewerBehavior.GetIsAnimating(this)) + { + LastVerticalLocation = VerticalOffset; + LastHorizontalLocation = HorizontalOffset; + } + } + + private Orientation GetDirection() + { + var isShiftDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift); + + if (Orientation == Orientation.Horizontal) + { + return isShiftDown ? Orientation.Vertical : Orientation.Horizontal; + } + else + { + return isShiftDown ? Orientation.Horizontal : Orientation.Vertical; + } + } + + /// + /// Causes the to load a new view into the viewport using the specified offsets and zoom factor. + /// + /// A value between 0 and that specifies the distance the content should be scrolled horizontally. + /// A value between 0 and that specifies the distance the content should be scrolled vertically. + /// A value between MinZoomFactor and MaxZoomFactor that specifies the required target ZoomFactor. + /// if the view is changed; otherwise, . + public bool ChangeView(double? horizontalOffset, double? verticalOffset, float? zoomFactor) + { + return ChangeView(horizontalOffset, verticalOffset, zoomFactor, false); + } + + /// + /// Causes the to load a new view into the viewport using the specified offsets and zoom factor, and optionally disables scrolling animation. + /// + /// A value between 0 and that specifies the distance the content should be scrolled horizontally. + /// A value between 0 and that specifies the distance the content should be scrolled vertically. + /// A value between MinZoomFactor and MaxZoomFactor that specifies the required target ZoomFactor. + /// to disable zoom/pan animations while changing the view; otherwise, . The default is false. + /// if the view is changed; otherwise, . + public bool ChangeView(double? horizontalOffset, double? verticalOffset, float? zoomFactor, bool disableAnimation) + { + if (disableAnimation) + { + if (horizontalOffset.HasValue) + { + ScrollToHorizontalOffset(horizontalOffset.Value); + } + + if (verticalOffset.HasValue) + { + ScrollToVerticalOffset(verticalOffset.Value); + } + } + else + { + if (horizontalOffset.HasValue) + { + ScrollToHorizontalOffset(LastHorizontalLocation); + ScrollToValue(Math.Min(ScrollableWidth, horizontalOffset.Value), Orientation.Horizontal); + LastHorizontalLocation = horizontalOffset.Value; + } + + if (verticalOffset.HasValue) + { + ScrollToVerticalOffset(LastVerticalLocation); + ScrollToValue(Math.Min(ScrollableHeight, verticalOffset.Value), Orientation.Vertical); + LastVerticalLocation = verticalOffset.Value; + } + } + + return true; + } + + private void ScrollToValue(double value, Orientation Direction) + { + if (Direction == Orientation.Vertical) + { + ScrollToVerticalOffset(value); + } + else + { + ScrollToHorizontalOffset(value); + } + + ScrollViewerBehavior.SetIsAnimating(this, false); + } + + private void UpdateVisualState(bool useTransitions = true) + { + var stateName = AutoHideScrollBars ? "NoIndicator" : "MouseIndicator"; + VisualStateManager.GoToState(this, stateName, useTransitions); + } + } +} diff --git a/Flow.Launcher/Resources/Controls/ExCard.xaml b/Flow.Launcher/Resources/Controls/ExCard.xaml deleted file mode 100644 index a70c0f4ea..000000000 --- a/Flow.Launcher/Resources/Controls/ExCard.xaml +++ /dev/null @@ -1,312 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Flow.Launcher/Resources/Controls/ExCard.xaml.cs b/Flow.Launcher/Resources/Controls/ExCard.xaml.cs deleted file mode 100644 index f149951f0..000000000 --- a/Flow.Launcher/Resources/Controls/ExCard.xaml.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Windows; -using System.Windows.Controls; - -namespace Flow.Launcher.Resources.Controls -{ - public partial class ExCard : UserControl - { - public ExCard() - { - InitializeComponent(); - } - public string Title - { - get { return (string)GetValue(TitleProperty); } - set { SetValue(TitleProperty, value); } - } - public static readonly DependencyProperty TitleProperty = - DependencyProperty.Register(nameof(Title), typeof(string), typeof(ExCard), new PropertyMetadata(string.Empty)); - - public string Sub - { - get { return (string)GetValue(SubProperty); } - set { SetValue(SubProperty, value); } - } - public static readonly DependencyProperty SubProperty = - DependencyProperty.Register(nameof(Sub), typeof(string), typeof(ExCard), new PropertyMetadata(string.Empty)); - - public string Icon - { - get { return (string)GetValue(IconProperty); } - set { SetValue(IconProperty, value); } - } - public static readonly DependencyProperty IconProperty = - DependencyProperty.Register(nameof(Icon), typeof(string), typeof(ExCard), new PropertyMetadata(string.Empty)); - - /// - /// Gets or sets additional content for the UserControl - /// - public object AdditionalContent - { - get { return (object)GetValue(AdditionalContentProperty); } - set { SetValue(AdditionalContentProperty, value); } - } - public static readonly DependencyProperty AdditionalContentProperty = - DependencyProperty.Register(nameof(AdditionalContent), typeof(object), typeof(ExCard), - new PropertyMetadata(null)); - - public object SideContent - { - get { return (object)GetValue(SideContentProperty); } - set { SetValue(SideContentProperty, value); } - } - public static readonly DependencyProperty SideContentProperty = - DependencyProperty.Register(nameof(SideContent), typeof(object), typeof(ExCard), - new PropertyMetadata(null)); - } -} diff --git a/Flow.Launcher/Resources/Controls/HyperLink.xaml b/Flow.Launcher/Resources/Controls/HyperLink.xaml deleted file mode 100644 index 9ea550afd..000000000 --- a/Flow.Launcher/Resources/Controls/HyperLink.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - diff --git a/Flow.Launcher/Resources/Controls/HyperLink.xaml.cs b/Flow.Launcher/Resources/Controls/HyperLink.xaml.cs deleted file mode 100644 index 855cccdbd..000000000 --- a/Flow.Launcher/Resources/Controls/HyperLink.xaml.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Windows; -using System.Windows.Controls; -using System.Windows.Navigation; - -namespace Flow.Launcher.Resources.Controls; - -public partial class HyperLink : UserControl -{ - public static readonly DependencyProperty UriProperty = DependencyProperty.Register( - nameof(Uri), typeof(string), typeof(HyperLink), new PropertyMetadata(default(string)) - ); - - public string Uri - { - get => (string)GetValue(UriProperty); - set => SetValue(UriProperty, value); - } - - public static readonly DependencyProperty TextProperty = DependencyProperty.Register( - nameof(Text), typeof(string), typeof(HyperLink), new PropertyMetadata(default(string)) - ); - - public string Text - { - get => (string)GetValue(TextProperty); - set => SetValue(TextProperty, value); - } - - public HyperLink() - { - InitializeComponent(); - } - - private void Hyperlink_OnRequestNavigate(object sender, RequestNavigateEventArgs e) - { - App.API.OpenUrl(e.Uri); - e.Handled = true; - } -} diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml b/Flow.Launcher/Resources/Controls/InfoBar.xaml deleted file mode 100644 index 2ddcbdd0c..000000000 --- a/Flow.Launcher/Resources/Controls/InfoBar.xaml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - + + + + + +