From fcbf97275406c9775149be25a8c68c606871f6e3 Mon Sep 17 00:00:00 2001 From: pc223 <10551242+pc223@users.noreply.github.com> Date: Tue, 13 Jul 2021 03:44:28 +0700 Subject: [PATCH 0001/1798] Testing new search order: System.Search.Rank --- .../Search/WindowsIndex/QueryConstructor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs index 20e85bbb5..808f8e7e3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs @@ -114,7 +114,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex /// public const string QueryWhereRestrictionsForAllFilesAndFoldersSearch = "scope='file:'"; - public const string QueryOrderByFileNameRestriction = " ORDER BY System.FileName"; + public const string QueryOrderByFileNameRestriction = " ORDER BY System.Search.Rank"; /// From 5d3b0ba2c06ceeea0f9f6cae668068bef0e7763a Mon Sep 17 00:00:00 2001 From: pc223 <10551242+pc223@users.noreply.github.com> Date: Tue, 13 Jul 2021 04:12:09 +0700 Subject: [PATCH 0002/1798] Should be DESC --- .../Search/WindowsIndex/QueryConstructor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs index 808f8e7e3..c42a60193 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs @@ -114,7 +114,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex /// public const string QueryWhereRestrictionsForAllFilesAndFoldersSearch = "scope='file:'"; - public const string QueryOrderByFileNameRestriction = " ORDER BY System.Search.Rank"; + public const string QueryOrderByFileNameRestriction = " ORDER BY System.Search.Rank DESC"; /// From bfee170d0fbeba908d9f228771af7a08351e7a10 Mon Sep 17 00:00:00 2001 From: Sparrkle Date: Wed, 5 Oct 2022 16:20:41 +0900 Subject: [PATCH 0003/1798] Changed ProgressBar Storyboard (No Dispatcher) --- Flow.Launcher/MainWindow.xaml | 1 - Flow.Launcher/MainWindow.xaml.cs | 60 +++++++++++--------------------- 2 files changed, 21 insertions(+), 40 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml b/Flow.Launcher/MainWindow.xaml index dc3b3f145..7d8c195f3 100644 --- a/Flow.Launcher/MainWindow.xaml +++ b/Flow.Launcher/MainWindow.xaml @@ -250,7 +250,6 @@ Height="2" HorizontalAlignment="Right" StrokeThickness="1" - Style="{DynamicResource PendingLineStyle}" Visibility="{Binding ProgressBarVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" X1="-150" X2="-50" diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 332e0f502..1dd9fe34d 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -28,9 +28,6 @@ namespace Flow.Launcher public partial class MainWindow { #region Private Fields - - private readonly Storyboard _progressBarStoryboard = new Storyboard(); - private bool isProgressBarStoryboardPaused; private Settings _settings; private NotifyIcon _notifyIcon; private ContextMenu contextMenu; @@ -119,39 +116,9 @@ namespace Flow.Launcher _viewModel.LastQuerySelected = true; } - if (_viewModel.ProgressBarVisibility == Visibility.Visible && isProgressBarStoryboardPaused) - { - _progressBarStoryboard.Begin(ProgressBar, true); - isProgressBarStoryboardPaused = false; - } - if(_settings.UseAnimation) WindowAnimator(); } - else if (!isProgressBarStoryboardPaused) - { - _progressBarStoryboard.Stop(ProgressBar); - isProgressBarStoryboardPaused = true; - } - - break; - } - case nameof(MainViewModel.ProgressBarVisibility): - { - Dispatcher.Invoke(() => - { - if (_viewModel.ProgressBarVisibility == Visibility.Hidden && !isProgressBarStoryboardPaused) - { - _progressBarStoryboard.Stop(ProgressBar); - isProgressBarStoryboardPaused = true; - } - else if (_viewModel.MainWindowVisibilityStatus && - isProgressBarStoryboardPaused) - { - _progressBarStoryboard.Begin(ProgressBar, true); - isProgressBarStoryboardPaused = false; - } - }); break; } case nameof(MainViewModel.QueryTextCursorMovedToEnd): @@ -291,17 +258,32 @@ namespace Flow.Launcher } private void InitProgressbarAnimation() { - var da = new DoubleAnimation(ProgressBar.X2, ActualWidth + 150, - new Duration(new TimeSpan(0, 0, 0, 0, 1600))); + var progressBarStoryBoard = new Storyboard(); + + var da = new DoubleAnimation(ProgressBar.X2, ActualWidth + 150, new Duration(new TimeSpan(0, 0, 0, 0, 1600))); var da1 = new DoubleAnimation(ProgressBar.X1, ActualWidth + 50, new Duration(new TimeSpan(0, 0, 0, 0, 1600))); Storyboard.SetTargetProperty(da, new PropertyPath("(Line.X2)")); Storyboard.SetTargetProperty(da1, new PropertyPath("(Line.X1)")); - _progressBarStoryboard.Children.Add(da); - _progressBarStoryboard.Children.Add(da1); - _progressBarStoryboard.RepeatBehavior = RepeatBehavior.Forever; + progressBarStoryBoard.Children.Add(da); + progressBarStoryBoard.Children.Add(da1); + progressBarStoryBoard.RepeatBehavior = RepeatBehavior.Forever; + + da.Freeze(); + da1.Freeze(); + + var beginStoryboard = new BeginStoryboard(); + beginStoryboard.Storyboard = progressBarStoryBoard; + + var trigger = new Trigger { Property = System.Windows.Shapes.Line.VisibilityProperty, Value = Visibility.Visible }; + trigger.EnterActions.Add(beginStoryboard); + + var progressStyle = new Style(typeof(System.Windows.Shapes.Line)); + progressStyle.BasedOn = FindResource("PendingLineStyle") as Style; + progressStyle.Triggers.Add(trigger); + + ProgressBar.Style = progressStyle; _viewModel.ProgressBarVisibility = Visibility.Hidden; - isProgressBarStoryboardPaused = true; } public void WindowAnimator() { From 6f0c2549cea809b0a1e406951f734daf4fb8cc0d Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Thu, 24 Nov 2022 14:01:32 -0600 Subject: [PATCH 0004/1798] also pause animation when exit visible --- Flow.Launcher/MainWindow.xaml.cs | 151 ++++++++++++++++++------------- 1 file changed, 89 insertions(+), 62 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 245ab4d05..efa43000b 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -36,6 +36,7 @@ namespace Flow.Launcher public partial class MainWindow { #region Private Fields + private Settings _settings; private NotifyIcon _notifyIcon; private ContextMenu contextMenu; @@ -50,7 +51,7 @@ namespace Flow.Launcher DataContext = mainVM; _viewModel = mainVM; _settings = settings; - + InitializeComponent(); InitializePosition(); animationSound.Open(new Uri(AppDomain.CurrentDomain.BaseDirectory + "Resources\\open.wav")); @@ -60,7 +61,7 @@ namespace Flow.Launcher { InitializeComponent(); } - + private void OnCopy(object sender, ExecutedRoutedEventArgs e) { if (QueryTextBox.SelectionLength == 0) @@ -108,29 +109,29 @@ namespace Flow.Launcher switch (e.PropertyName) { case nameof(MainViewModel.MainWindowVisibilityStatus): + { + if (_viewModel.MainWindowVisibilityStatus) { - if (_viewModel.MainWindowVisibilityStatus) + if (_settings.UseSound) { - if (_settings.UseSound) - { - animationSound.Position = TimeSpan.Zero; - animationSound.Play(); - } - UpdatePosition(); - Activate(); - QueryTextBox.Focus(); - _settings.ActivateTimes++; - if (!_viewModel.LastQuerySelected) - { - QueryTextBox.SelectAll(); - _viewModel.LastQuerySelected = true; - } - - if(_settings.UseAnimation) - WindowAnimator(); + animationSound.Position = TimeSpan.Zero; + animationSound.Play(); } - break; + UpdatePosition(); + Activate(); + QueryTextBox.Focus(); + _settings.ActivateTimes++; + if (!_viewModel.LastQuerySelected) + { + QueryTextBox.SelectAll(); + _viewModel.LastQuerySelected = true; + } + + if (_settings.UseAnimation) + WindowAnimator(); } + break; + } case nameof(MainViewModel.QueryTextCursorMovedToEnd): if (_viewModel.QueryTextCursorMovedToEnd) { @@ -211,35 +212,45 @@ namespace Flow.Launcher Visible = !_settings.HideNotifyIcon }; contextMenu = new ContextMenu(); - var openIcon = new FontIcon { Glyph = "\ue71e" }; + var openIcon = new FontIcon + { + Glyph = "\ue71e" + }; var open = new MenuItem { - Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") + " (" + _settings.Hotkey + ")", - Icon = openIcon + Header = InternationalizationManager.Instance.GetTranslation("iconTrayOpen") + " (" + _settings.Hotkey + ")", Icon = openIcon + }; + var gamemodeIcon = new FontIcon + { + Glyph = "\ue7fc" }; - var gamemodeIcon = new FontIcon { Glyph = "\ue7fc" }; var gamemode = new MenuItem { - Header = InternationalizationManager.Instance.GetTranslation("GameMode"), - Icon = gamemodeIcon + Header = InternationalizationManager.Instance.GetTranslation("GameMode"), Icon = gamemodeIcon + }; + var positionresetIcon = new FontIcon + { + Glyph = "\ue73f" }; - var positionresetIcon = new FontIcon { Glyph = "\ue73f" }; var positionreset = new MenuItem { - Header = InternationalizationManager.Instance.GetTranslation("PositionReset"), - Icon = positionresetIcon + Header = InternationalizationManager.Instance.GetTranslation("PositionReset"), Icon = positionresetIcon + }; + var settingsIcon = new FontIcon + { + Glyph = "\ue713" }; - var settingsIcon = new FontIcon { Glyph = "\ue713" }; var settings = new MenuItem { - Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"), - Icon = settingsIcon + Header = InternationalizationManager.Instance.GetTranslation("iconTraySettings"), Icon = settingsIcon + }; + var exitIcon = new FontIcon + { + Glyph = "\ue7e8" }; - var exitIcon = new FontIcon { Glyph = "\ue7e8" }; var exit = new MenuItem { - Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit"), - Icon = exitIcon + Header = InternationalizationManager.Instance.GetTranslation("iconTrayExit"), Icon = exitIcon }; open.Click += (o, e) => _viewModel.ToggleFlowLauncher(); @@ -300,10 +311,10 @@ namespace Flow.Launcher } private async void PositionReset() { - _viewModel.Show(); - await Task.Delay(300); // If don't give a time, Positioning will be weird. - Left = HorizonCenter(); - Top = VerticalCenter(); + _viewModel.Show(); + await Task.Delay(300); // If don't give a time, Positioning will be weird. + Left = HorizonCenter(); + Top = VerticalCenter(); } private void InitProgressbarAnimation() { @@ -320,14 +331,30 @@ namespace Flow.Launcher da.Freeze(); da1.Freeze(); - var beginStoryboard = new BeginStoryboard(); - beginStoryboard.Storyboard = progressBarStoryBoard; + const string progressBarAnimationName = "ProgressBarAnimation"; + var beginStoryboard = new BeginStoryboard + { + Name = progressBarAnimationName, Storyboard = progressBarStoryBoard + }; + + var stopStoryboard = new StopStoryboard() + { + BeginStoryboardName = progressBarAnimationName + }; - var trigger = new Trigger { Property = System.Windows.Shapes.Line.VisibilityProperty, Value = Visibility.Visible }; + var trigger = new Trigger + { + Property = VisibilityProperty, Value = Visibility.Visible + }; trigger.EnterActions.Add(beginStoryboard); + trigger.ExitActions.Add(stopStoryboard); - var progressStyle = new Style(typeof(System.Windows.Shapes.Line)); - progressStyle.BasedOn = FindResource("PendingLineStyle") as Style; + + var progressStyle = new Style(typeof(System.Windows.Shapes.Line)) + { + BasedOn = FindResource("PendingLineStyle") as Style + }; + progressStyle.RegisterName(progressBarAnimationName, beginStoryboard); progressStyle.Triggers.Add(trigger); ProgressBar.Style = progressStyle; @@ -343,7 +370,7 @@ namespace Flow.Launcher UpdatePosition(); Storyboard sb = new Storyboard(); Storyboard iconsb = new Storyboard(); - CircleEase easing = new CircleEase(); // or whatever easing class you want + CircleEase easing = new CircleEase(); // or whatever easing class you want easing.EasingMode = EasingMode.EaseInOut; var da = new DoubleAnimation { @@ -360,14 +387,14 @@ namespace Flow.Launcher Duration = TimeSpan.FromSeconds(0.25), FillBehavior = FillBehavior.Stop }; - var da3 = new DoubleAnimation - { - From = 12, - To = 0, - EasingFunction = easing, - Duration = TimeSpan.FromSeconds(0.36), - FillBehavior = FillBehavior.Stop - }; + var da3 = new DoubleAnimation + { + From = 12, + To = 0, + EasingFunction = easing, + Duration = TimeSpan.FromSeconds(0.36), + FillBehavior = FillBehavior.Stop + }; Storyboard.SetTarget(da, this); Storyboard.SetTargetProperty(da, new PropertyPath(Window.OpacityProperty)); Storyboard.SetTargetProperty(da2, new PropertyPath(Window.TopProperty)); @@ -395,10 +422,10 @@ namespace Flow.Launcher private async void OnContextMenusForSettingsClick(object sender, RoutedEventArgs e) { _viewModel.Hide(); - - if(_settings.UseAnimation) + + if (_settings.UseAnimation) await Task.Delay(100); - + App.API.OpenSettingDialog(); } @@ -416,7 +443,7 @@ namespace Flow.Launcher // and always after Settings window is closed. if (_settings.UseAnimation) await Task.Delay(100); - + if (_settings.HideWhenDeactive) { _viewModel.Hide(); @@ -454,7 +481,7 @@ namespace Flow.Launcher _viewModel.Show(); } } - + public double HorizonCenter() { var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); @@ -536,9 +563,9 @@ namespace Flow.Launcher && QueryTextBox.Text.Length > 0 && QueryTextBox.CaretIndex == QueryTextBox.Text.Length) { - var queryWithoutActionKeyword = + var queryWithoutActionKeyword = QueryBuilder.Build(QueryTextBox.Text.Trim(), PluginManager.NonGlobalPlugins).Search; - + if (FilesFolders.IsLocationPathString(queryWithoutActionKeyword)) { _viewModel.BackspaceCommand.Execute(null); @@ -574,7 +601,7 @@ namespace Flow.Launcher private void QueryTextBox_KeyUp(object sender, KeyEventArgs e) { - if(_viewModel.QueryText != QueryTextBox.Text) + if (_viewModel.QueryText != QueryTextBox.Text) { BindingExpression be = QueryTextBox.GetBindingExpression(System.Windows.Controls.TextBox.TextProperty); be.UpdateSource(); From 1b31e9c9685abd0d1d556d260425fac4b5aff165 Mon Sep 17 00:00:00 2001 From: Odotocodot <48138990+Odotocodot@users.noreply.github.com> Date: Thu, 30 Nov 2023 14:37:05 +0000 Subject: [PATCH 0005/1798] Create Flow Launcher Theme Selector plugin --- ...w.Launcher.Plugin.FlowThemeSelector.csproj | 37 +++++++ .../Main.cs | 91 ++++++++++++++++++ .../icon.png | Bin 0 -> 6625 bytes .../plugin.json | 12 +++ 4 files changed, 140 insertions(+) create mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj create mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs create mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/icon.png create mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj new file mode 100644 index 000000000..ba0ddd6ab --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj @@ -0,0 +1,37 @@ + + + + + Library + net7.0-windows + true + false + + + + ..\..\Output\Debug\Plugins\Flow.Launcher.Plugin.FlowThemeSelector + + + + ..\..\Output\Release\Plugins\Flow.Launcher.Plugin.FlowThemeSelector + + + + + + + + + + + PreserveNewest + + + + + + PreserveNewest + + + + diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs new file mode 100644 index 000000000..6fd6472db --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Flow.Launcher.Core.Resource; + +namespace Flow.Launcher.Plugin.FlowThemeSelector +{ + public class FlowThemeSelector : IPlugin, IReloadable, IDisposable + { + private PluginInitContext context; + private IEnumerable themes; + + public void Init(PluginInitContext context) + { + this.context = context; + context.API.VisibilityChanged += OnVisibilityChanged; + } + + public List Query(Query query) + { + if (query.IsReQuery) + { + LoadThemes(); + } + + if (string.IsNullOrWhiteSpace(query.Search)) + { + return themes.Select(CreateThemeResult) + .OrderBy(x => x.Title) + .ToList(); + } + + return themes.Select(theme => (theme, matchResult: context.API.FuzzySearch(query.Search, theme))) + .Where(x => x.matchResult.IsSearchPrecisionScoreMet()) + .Select(x => CreateThemeResult(x.theme, x.matchResult.Score, x.matchResult.MatchData)) + .OrderBy(x => x.Title) + .ToList(); + } + + private void OnVisibilityChanged(object sender, VisibilityChangedEventArgs args) + { + if (args.IsVisible && !context.CurrentPluginMetadata.Disabled) + { + LoadThemes(); + } + } + + public void LoadThemes() => themes = ThemeManager.Instance.LoadAvailableThemes().Select(Path.GetFileNameWithoutExtension); + + public static Result CreateThemeResult(string theme) => CreateThemeResult(theme, 0, null); + + public static Result CreateThemeResult(string theme, int score, IList highlightData) + { + string title; + if (theme == ThemeManager.Instance.Settings.Theme) + { + title = $"{theme} ★"; + score = 2000; + } + else + { + title = theme; + } + + return new Result + { + Title = title, + TitleHighlightData = highlightData, + Glyph = new GlyphInfo("/Resources/#Segoe Fluent Icons", "\ue790"), + Score = score, + Action = c => + { + ThemeManager.Instance.ChangeTheme(theme); + return true; + } + }; + } + + public void ReloadData() => LoadThemes(); + + public void Dispose() + { + if (context != null && context.API != null) + { + context.API.VisibilityChanged -= OnVisibilityChanged; + } + } + + } +} diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/icon.png b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..704e9474eb29ffa1fcaeff9e24c60ee35155afd5 GIT binary patch literal 6625 zcmV<786M_|P)?L~#_W&dT5+Df~tR%E=9kt)zb>9h)AYqsw`j&HD=X&5T zo_x;9xxe?h&+}kl&}CiLWnI=~UDjn?)@5DRWnK1+nBx`2yKb4XkC_>=6)stFZLT1&5Y;r?b&_2|)x3Z7H-nk27~+~O4{^jFQ6z?V_@jHd8Y)Ztgd zAyMTCRj|KUDX@>PUTc*idEMZjU{-l}$t_2|z%@sHoj|YmPJvGYPzAgAO4!Cpg|=~( zvkidf4E|TmHCH~yHAlgAV>N=;8~pSZ;3sQ`UmpOwI1+?P*v3lIY~n?I4E~qQ?ULNw zEvGJug70wnwavnJY!iGbb?az}+$Kgk!{Avr$18Zzja9eDm8E#l;qdDN&>Z}v7U0L% z!&e5tCPwAa5?Duz_dK&D$u;Z0rtYk|EH_pi9v8l6t`J_Of!JC7CBBv~#whgirZXG4yg=vvTth_=(NKS1&!y!Y3XnCP6rBumjH< zJoN@V@0P3h#XYwU?Sh}J8GvbdsW|e$3ju#E!;$+-;r-_#?5&&M5P+59iC82Yi`iu( zF@zP}Dtw1F!j0o8{&s@M9l^Z(R>RQUyPpxCoY^qE8K; zMjMhMdEK3*h|?85GgF3n>=W3nn1>&JUx0moETpC9JHY_6V; zbKXJ(eqW=4zeG3=^UFuk>>pn|6vNqrF*xr-IK+#!YJI1WDhxjQCx#rqPp|Gi zaxj0Yg!67;V*u9PhQ*4ju<|R?4*x<0EQp5)S9dmhgQ-Dy!HrcHqA&PNqU}?pSSp-> zRpLolEtyQq4Y`s<*Gn`Wi-lt`pFavSN{3@o$%h!l@x+IBJm7w7C>-KN6ns!ztik@-CqO74-zt z2VqdYE1a)Rhkcv~4i}}Gax+c}hhr6R*(U|_=W4kAQUm7CRdCrSq1o^7RVi$@7GdCq z0$6^217=Gv;r)e~=>PQ%ScO&8*L_%qs>2sjHwzMM?==4Ith&_{ewzazZ+(|b0+1}l zh-*HyzRxQsK8ix0Q#JxKONV1BZx|+&e2CE;CH%n!Zg9EHfL;0zu#c;NJqduC+_a4q z!{LW=IDIFC^Ij1cdqr^GBZAX+0yyj{gWZ?KH2dqzPyfX%^qrrMK1(xTbwSVopJsnZ z1uW{}2h#w^tb#hBgUY-tW4N;v_gaEKI=2MJZ)`;2EnC#xcoTJ3-bMk-3CFTFV`NrI z^8v`Hr2%kBW@A$ESWMv#qrk~^GWR12eoWB^7{MNb4+}joINue_+YH!W8wA_feAvfU zz@8`_^<8dM1?+Z|&^k|m*Sq}=9_+Ri!-l|Lmj}yL*Ol4-Nf!FdNkOmKiLg9h-Yk4` zC486#3efLd`NAg(-y=izANSlkUQ6(|T|0r_xo_ZM(erp%@B;q2^)LK&^(8#WeHjn3 zUV$vN8#bk#YPQG2NU4N#f*5WYAsAis0mc-0(o!>uGlVX-9~BOQXMsCB@|a-UV!-}} z6KoRB!7fSwyI7H?)+hQtN(k%CcjzKZN{!Mv^mprx1vK*sd~>hM=(i{vedndYbVeeK zr^Uk}xD1vdLM8l=Ch&s<=uZQ{Pk*8TaAVa)wgi9ce zqxY;Nm`sU>@qz?c1eL+!yg)1b{^$7Ucc%RB_k+s&JsJ3y>gKdqcCw35m;V+X7QUc# zlKr>;g}<)9hzFNn!h@Wb@gU%+zJpEFE!aht!!}w7yBHBIKN`E-7%>fiD6NSRhsqvm$1<9(<~MIWb~RE52Fdu=)E}`<}?8OM)<)^;1fT~N8dB0t2!J$ zGh6nKd#*yFb-~S+coZFE(a>_A9ub{wnS#{~Px%zJ_}-ufs2H3z=rn zY%Ql$!-;IFE{fq0Cxm@;Iqaj#U>C`QT?Fw`*hZAm%x{D*eYCG1BY|~<00RPf=%EvOx4 zRxJuI+2OBiFVc*sPJX`f5*}Q7xiR}wU&Z~z*KjZHb=-@31GgfXwCp@`sFGX_rvwQc zFN)wm7S~t->|>N}7cEfMd{TDQ;m2zps*wJUb%YQDLd#&`ork^)(rKnsl`}7mF1DoP z^qQUklgY6#8Xtw8W5Up9_hp!$<-#nmtX25$pDst=)8(}tx-)jqQFyrLDE@9qYBJNS zpY`(8g4pR~<;Xu9#WRn#yqFSG* z9kSq(n%_`%wDk3@BP%d4jE?~!r7-*H7EI?P(?ym*C*{VNfG1f$HUd4zN1)HQmtc0L z1ZHP>Fb^u%gdf-hKFNL(fKz2KJ;k%@umHHR>QYFB~YE8?BDzv3s35Nut^DEol*N+loV3+^{E|kM6mP9P5Mgx$a z>WKSkuPW<&y%X?c(M@UsKm1MH4S5Te(DZ+qIJ_ejGgJm!e zmgkCLd6ol2C}ox2y_qVOvNjqzb@K3#0dH=sQ;Jk3oqw0fvQ`#J(xhLqD?F4<@it#3}D z6EBCk3Vc)e{Z#PZZw7wv6Q$_&YiYLL1K^gUNNj6^jg%lpvKSlVkK=Ci8%p5h8uf+} zeE6HV8>%cjcZ1%-f6x5~Yr_NJ7%!sVfVRTdHb&C0=xV@kp|5|T0+t~HJ4P zY!k(Es;sf}sNkCt|CO7sSNJYD^8Ri)^1s{K-E_&Q0V7okMv@pCV~(Rbyr(kTX~wI- z2fu|s1K&pFITNf6I}XRV3gw0?sZysIo_536?CZC>(Q1^NP2krD;8z|@j`Pa&8UR<8 z!n<9qWztTd-vS93i6RV(y9wWjjktN9iJG9Es1EFjn}M!46tW3Jqi-sAxfjK7Ops8y z*=G3hEx>PBbekNex7gQjEBtb;@J$1F=oP@N*6%4-jzZS%zCPK}rYcL3bD{`N@d7x- z@!=F#4#(Jf=fg3+g2E@Y-zm9DPXkn~!`Ir^4;H}g6d&{Ulwj-n0_^_mI=)_f32Rs8 zV)D)#unOR*DV`?qezm%=Hz zQmyQC&LAG~ufPVB}v?q?Z7= z=g3F41b;+=2;RG6knyQEIOBJsaO`#@&-)4cc7RJf6SLCAGH;wBQ}Hk@fRrmXajDK+>8~zSseo3Ru{S1 z+= ze6$3HM@o|Q6aYnbbMV*t=Rz=kCxtH+N9)8+~hiqVZ30v2|WDRXL>8)H_*px6e+*wpsB?_|qb=e#!-`nHYps z<43Xew?+)NpM{yH3Gqqb7$#7XAY!>=ztMIWvM z`-3$o9I_e(gI3|&Z9&RKSC0=%42+h94UCWuv56PGMtne|$kQrZ9PtQzEn2@}qjk0n z@1Npg`I2M``pa1fD!)j7-#RlEo2N%Nz+XEl2%k?lgB4?c!^~NMF!mz>D560i@C^?a z!{~6yXq^M#mZ@0WT#F%f?vJ$At9w2Cl3@gXWA@(}{5kRmtwi*cui>Q8VyJ1m)^Bd3 z6(#vX+kIPxi?_6<^)*_{BmgJ57`Hi#)^`GX^NeVE-84Olg5Nkb4C^O{(7I3Ik2?vk zF##C5Iu=HLg)lx+1fwI30qEg-r?<`laLrPD|40DRs!%XyD}~J+u5t=~BZ}4FlkC4U zjDm&7iy19~dnOYwg}GLn|U%n&Hvt>ywu9ZzZtw%g34-;n*-Wi~`>< zg?K0hzjjhER!=;KRpXVJPvCzt{y6&laves#g)kynuYzyrTcps-V@%9!d6fzJUGk6v9Jys&meK~SHS1a2M+D67Nwtb^T%1&$dZXPE3 zK&#?uoZ)Hc>-Rm$MV|l;+`eI9&Ez0jW=OWLnHWeHTLOONxKmg@_5{2}AIFkWN8zwF z1xAPRVd%$hgzs03o`*QmI>T25;D*LVD}(fQDv>aAFN%h)qrj;Ttp~prY)=CJb0z#i zO8B?jmLYP&PGz$#u~KKPZ`FqJKl8B4H(G+|WF68Y8`0*;-Bz!Rx04Tpqec1zioi3VzPuRamqyo(@krs7A&0*w^2p z75;g_Hk}St0=O_eRtyvWBA6UuD>qtXq4gus$(5}vJ5Avq;-H&1+g5J@aLJTcKhoKx zqk_tBf%C-*c!m_>n~kRsF>xny2d$(YHhw$4TK^k7g6_aRny(xaC)rQtciN-%qg&qP zT833b4hR!{K-L7}W+9@XH1nI&`mK$TXzA;l_?N)MzgW4^I#R5m^&8;R0C3RVhjU49 z@KpgQYqqUSTFRt{pD3n>Dh{!HI7FAjA-WXyQN+odX1Q{7upWMbD*HR|P{l&qM(c6m zAJc5Gslzu^!B=KK2R#mQ(ER{=iCzQ1%#`J6?dzwKv2iI40-0nWXS!r?)*)8u%9{T; z@TD!nZ&Pboi`LgR!=r>>+79@|8t~sc$U%<-oVs`RbM*U+7&BAGYVkchq^n7e5fdeF zB-0GU8|F5}4K@FX_Vt5W(E8fotFpi8p-KaMwH}YU+-!hPvfrohJH5hJ2B7w0n_q%N zjuexslp8J5TF`lbN}?zD&Cl>O51-c#_(cuyd-xQ}jepF0NACe(WXO(o+)I$8YVak0 z4~&wWCi>nswDxVs2;sl2BZLkEBE;Vf2p7paYKBJxen1oW{!QRFqj;3?*+lt#rFZx= z0O_(V9r+R@8=~`LBm$cliHEj(u#OVjuBI86I``+;+g{pu0D_=B=N3Z+A!l zm>D%=JMtw+)-e*ceORSoYxiLlA?#&&p+eCy15|2@ZhPS$V56H)p_f5NnOkP1VY9D& z)W=JZqNT;QkyS=*y%)<1!d)#Ms&tUtY^wDe;M3AmnBC#;3}U3!6l;6u=HtEuiIg3y z2w|`G+=pebz`nDzesl12>_zIP$ZU`O5) zdb=+0oO5b*kzQtaqNI;~P+<`yaBU5~wudG3qxI|Ivn&6zujt9XXWBWXda1EMqbhAlw5uDv9*4*^rS9op??V9)+|VH_i-PV z&{^wK_-wrEeP^3NXPHxKt-V8H^?%zYH#J%e2X%qpFQ}rMS+JnEGqpbPclQ_i8g#Zf zBvwtdPpG=zCaoVW`P({LvQwA8XB8xQy?>D4a@*x*^AAgCQ#^)k(E2L)Ay3Ua;T#jI z7dQ1X*TeTxQAIF|Bv=O7~KI{ z|E$5`D>^6AGil~Q{Led6>v!MJ)=4-#^VUB|kfc@dXninRclg~76yELb&0cKqPq%*O z_}nM1^}X4`?)y2+&i?FAh4nwn|F14uzrFCg9Vm?G{!2-Z&i>p_jrBWMF6l6>uLi&S z0d`F{pTfDF{du1{>vx8Ku0yrH5Bu-#KJ1`(4;S?8?9cjCTK_YAm-kPX{jDGPk7#{X zPjB|1&i;%~z4bX=ept_1pVjkV;bWae{3ESj4Cm$Er^=#qg6~^&|Gh&+XL|UsT{`>o zJewAT7y6vw?d*Mm_eWc`eow!mKYRKXNA&PzFEBpZ0mD-NL^J-i+^AOocZ11sZgQ^x z9^d#F_nz@FuFU9YNr{nv@g>6}C8rIK6s>*Fk3G1XPu@S{|37wFmvvc}by=5nS(kNL fmvx!JvuOVh5a5F)ThAaT00000NkvXXu0mjfwnX-y literal 0 HcmV?d00001 diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json new file mode 100644 index 000000000..f275d129c --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json @@ -0,0 +1,12 @@ +{ + "ID": "4DFA743E1086414BAB0AA3071D561D75", + "ActionKeyword": "flowtheme", + "Name": "Flow Launcher Theme Selector", + "Description": "Quickly switch your Flow Launcher theme.", + "Author": "Odotocodot", + "Version": "1.0.0", + "Language": "csharp", + "Website": "https://github.com/Flow-Launcher/Flow.Launcher", + "IcoPath": "icon.png", + "ExecuteFileName": "Flow.Launcher.Plugin.FlowThemeSelector.dll" +} \ No newline at end of file From 3abd05f6b3a687e73fc9e6ab0f09ec2af2f6c06a Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 18 Nov 2023 14:58:16 +0800 Subject: [PATCH 0006/1798] Implement double pinyin --- .../DoublePinAlphabet.cs | 193 ++++++++++++++++++ .../UserSettings/Settings.cs | 2 + 2 files changed, 195 insertions(+) create mode 100644 Flow.Launcher.Infrastructure/DoublePinAlphabet.cs diff --git a/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs b/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs new file mode 100644 index 000000000..607582097 --- /dev/null +++ b/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using Flow.Launcher.Infrastructure.UserSettings; +using ToolGood.Words.Pinyin; + +namespace Flow.Launcher.Infrastructure +{ + public class DoublePinAlphabet : IAlphabet + { + private ConcurrentDictionary _doublePinCache = + new ConcurrentDictionary(); + + private Settings _settings; + + public void Initialize([NotNull] Settings settings) + { + _settings = settings ?? throw new ArgumentNullException(nameof(settings)); + } + + public bool CanBeTranslated(string stringToTranslate) + { + return WordsHelper.HasChinese(stringToTranslate); + } + + public (string translation, TranslationMapping map) Translate(string content) + { + if (_settings.ShouldUseDoublePin) + { + if (!_doublePinCache.ContainsKey(content)) + { + return BuildCacheFromContent(content); + } + else + { + return _doublePinCache[content]; + } + } + return (content, null); + } + + private (string translation, TranslationMapping map) BuildCacheFromContent(string content) + { + if (WordsHelper.HasChinese(content)) + { + var resultList = WordsHelper.GetPinyinList(content).Select(ToDoublePin).ToArray(); + StringBuilder resultBuilder = new StringBuilder(); + TranslationMapping map = new TranslationMapping(); + + bool pre = false; + + for (int i = 0; i < resultList.Length; i++) + { + if (content[i] >= 0x3400 && content[i] <= 0x9FD5) + { + map.AddNewIndex(i, resultBuilder.Length, resultList[i].Length + 1); + resultBuilder.Append(' '); + resultBuilder.Append(resultList[i]); + pre = true; + } + else + { + if (pre) + { + pre = false; + resultBuilder.Append(' '); + } + + resultBuilder.Append(resultList[i]); + } + } + + map.endConstruct(); + + var key = resultBuilder.ToString(); + map.setKey(key); + + return _doublePinCache[content] = (key, map); + } + else + { + return (content, null); + } + } + + private static readonly ReadOnlyDictionary special = new(new Dictionary(){ + {"a", "aa"}, + {"ai", "ai"}, + {"an", "an"}, + {"ang", "ah"}, + {"ao", "ao"}, + {"e", "ee"}, + {"ei", "ei"}, + {"en", "en"}, + {"er", "er"}, + {"o", "oo"}, + {"ou", "ou"} + }); + + + private static readonly ReadOnlyDictionary first = new(new Dictionary(){ + {"ch", "i"}, + {"sh", "u"}, + {"zh", "v"} + }); + + + private static readonly ReadOnlyDictionary second = new(new Dictionary() + { + {"ua", "x"}, + {"ei", "w"}, + {"e", "e"}, + {"ou", "z"}, + {"iu", "q"}, + {"ve", "t"}, + {"ue", "t"}, + {"u", "u"}, + {"i", "i"}, + {"o", "o"}, + {"uo", "o"}, + {"ie", "p"}, + {"a", "a"}, + {"ong", "s"}, + {"iong", "s"}, + {"ai", "d"}, + {"ing", "k"}, + {"uai", "k"}, + {"ang", "h"}, + {"uan", "r"}, + {"an", "j"}, + {"en", "f"}, + {"ia", "x"}, + {"iang", "l"}, + {"uang", "l"}, + {"eng", "g"}, + {"in", "b"}, + {"ao", "c"}, + {"v", "v"}, + {"ui", "v"}, + {"un", "y"}, + {"iao", "n"}, + {"ian", "m"} + }); + + private static string ToDoublePin(string fullPinyin) + { + // Assuming s is valid + StringBuilder doublePin = new StringBuilder(); + + if (fullPinyin.Length <= 3 && (fullPinyin[0] == 'a' || fullPinyin[0] == 'e' || fullPinyin[0] == 'o')) + { + if (special.ContainsKey(fullPinyin)) + { + return special[fullPinyin]; + } + } + + // zh, ch, sh + if (fullPinyin.Length >= 2 && first.ContainsKey(fullPinyin[..2])) + { + doublePin.Append(first[fullPinyin[..2]]); + + if (second.TryGetValue(fullPinyin[2..], out string tmp)) + { + doublePin.Append(tmp); + } + else + { + doublePin.Append(fullPinyin[2..]); + } + } + else + { + doublePin.Append(fullPinyin[0]); + + if (second.TryGetValue(fullPinyin[1..], out string tmp)) + { + doublePin.Append(tmp); + } + else + { + doublePin.Append(fullPinyin[1..]); + } + } + + return doublePin.ToString(); + } + } +} diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 458846665..8d94cdba5 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -185,6 +185,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings /// when false Alphabet static service will always return empty results /// public bool ShouldUsePinyin { get; set; } = false; + + public bool ShouldUseDoublePin { get; set; } = false; public bool AlwaysPreview { get; set; } = false; public bool AlwaysStartEn { get; set; } = false; From fb6635344b8e5ecae06aadd31a3b112471b48ae2 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 18 Nov 2023 14:58:23 +0800 Subject: [PATCH 0007/1798] Test double pinyin --- Flow.Launcher/App.xaml.cs | 2 +- Flow.Launcher/PublicAPIInstance.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 765a1a559..d74ea62fb 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -30,7 +30,7 @@ namespace Flow.Launcher private SettingWindowViewModel _settingsVM; private readonly Updater _updater = new Updater(Flow.Launcher.Properties.Settings.Default.GithubRepo); private readonly Portable _portable = new Portable(); - private readonly PinyinAlphabet _alphabet = new PinyinAlphabet(); + private readonly DoublePinAlphabet _alphabet = new DoublePinAlphabet(); private StringMatcher _stringMatcher; [STAThread] diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index b49bf39d3..952ce0edb 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -32,11 +32,11 @@ namespace Flow.Launcher { private readonly SettingWindowViewModel _settingsVM; private readonly MainViewModel _mainVM; - private readonly PinyinAlphabet _alphabet; + private readonly DoublePinAlphabet _alphabet; #region Constructor - public PublicAPIInstance(SettingWindowViewModel settingsVM, MainViewModel mainVM, PinyinAlphabet alphabet) + public PublicAPIInstance(SettingWindowViewModel settingsVM, MainViewModel mainVM, DoublePinAlphabet alphabet) { _settingsVM = settingsVM; _mainVM = mainVM; From f6ae71a99f838b2237c14c62c6daff5e97e6eec0 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 18 Nov 2023 20:24:13 +0800 Subject: [PATCH 0008/1798] Only convert to double pinyin when meeting Chinese --- Flow.Launcher.Infrastructure/DoublePinAlphabet.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs b/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs index 607582097..e09046410 100644 --- a/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs @@ -47,7 +47,7 @@ namespace Flow.Launcher.Infrastructure { if (WordsHelper.HasChinese(content)) { - var resultList = WordsHelper.GetPinyinList(content).Select(ToDoublePin).ToArray(); + var resultList = WordsHelper.GetPinyinList(content); StringBuilder resultBuilder = new StringBuilder(); TranslationMapping map = new TranslationMapping(); @@ -57,9 +57,10 @@ namespace Flow.Launcher.Infrastructure { if (content[i] >= 0x3400 && content[i] <= 0x9FD5) { - map.AddNewIndex(i, resultBuilder.Length, resultList[i].Length + 1); + string dp = ToDoublePin(resultList[i].ToLower()); + map.AddNewIndex(i, resultBuilder.Length, dp.Length + 1); resultBuilder.Append(' '); - resultBuilder.Append(resultList[i]); + resultBuilder.Append(dp); pre = true; } else From e5285b19921ae2cc49b6f55ebe5772a77f05cd54 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 19 Nov 2023 12:30:17 +0800 Subject: [PATCH 0009/1798] Temp: compatibility with full pinyin option --- Flow.Launcher.Infrastructure/DoublePinAlphabet.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs b/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs index e09046410..e6930ad93 100644 --- a/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs @@ -29,7 +29,7 @@ namespace Flow.Launcher.Infrastructure public (string translation, TranslationMapping map) Translate(string content) { - if (_settings.ShouldUseDoublePin) + if (_settings.ShouldUsePinyin) { if (!_doublePinCache.ContainsKey(content)) { @@ -57,7 +57,7 @@ namespace Flow.Launcher.Infrastructure { if (content[i] >= 0x3400 && content[i] <= 0x9FD5) { - string dp = ToDoublePin(resultList[i].ToLower()); + string dp = _settings.ShouldUseDoublePin ? resultList[i] : ToDoublePin(resultList[i].ToLower()); map.AddNewIndex(i, resultBuilder.Length, dp.Length + 1); resultBuilder.Append(' '); resultBuilder.Append(dp); From 99ff3b2ec5c9a4d8b4f136735a866f52914c246e Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Mon, 20 Nov 2023 22:49:39 +0800 Subject: [PATCH 0010/1798] Fix wrong condition --- Flow.Launcher.Infrastructure/DoublePinAlphabet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs b/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs index e6930ad93..a1eb788d7 100644 --- a/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs @@ -57,7 +57,7 @@ namespace Flow.Launcher.Infrastructure { if (content[i] >= 0x3400 && content[i] <= 0x9FD5) { - string dp = _settings.ShouldUseDoublePin ? resultList[i] : ToDoublePin(resultList[i].ToLower()); + string dp = _settings.ShouldUseDoublePin ? ToDoublePin(resultList[i].ToLower()) : resultList[i]; map.AddNewIndex(i, resultBuilder.Length, dp.Length + 1); resultBuilder.Append(' '); resultBuilder.Append(dp); From 46d49d8fdf373e020481b111cbd23bf8ee09538d Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sat, 25 May 2024 15:02:37 +0800 Subject: [PATCH 0011/1798] Only translate when string is double pinyin --- Flow.Launcher.Infrastructure/DoublePinAlphabet.cs | 4 ++-- Flow.Launcher.Infrastructure/PinyinAlphabet.cs | 4 ++-- Flow.Launcher.Infrastructure/StringMatcher.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs b/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs index a1eb788d7..945f47a56 100644 --- a/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs @@ -22,9 +22,9 @@ namespace Flow.Launcher.Infrastructure _settings = settings ?? throw new ArgumentNullException(nameof(settings)); } - public bool CanBeTranslated(string stringToTranslate) + public bool ShouldTranslate(string stringToTranslate) { - return WordsHelper.HasChinese(stringToTranslate); + return stringToTranslate.Length % 2 == 0 && !WordsHelper.HasChinese(stringToTranslate); } public (string translation, TranslationMapping map) Translate(string content) diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index 7d7235968..961af1d32 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -119,7 +119,7 @@ namespace Flow.Launcher.Infrastructure /// /// String to translate. /// - public bool CanBeTranslated(string stringToTranslate); + public bool ShouldTranslate(string stringToTranslate); } public class PinyinAlphabet : IAlphabet @@ -134,7 +134,7 @@ namespace Flow.Launcher.Infrastructure _settings = settings ?? throw new ArgumentNullException(nameof(settings)); } - public bool CanBeTranslated(string stringToTranslate) + public bool ShouldTranslate(string stringToTranslate) { return WordsHelper.HasChinese(stringToTranslate); } diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs index bd5dbdda9..4929e4cd2 100644 --- a/Flow.Launcher.Infrastructure/StringMatcher.cs +++ b/Flow.Launcher.Infrastructure/StringMatcher.cs @@ -61,7 +61,7 @@ namespace Flow.Launcher.Infrastructure query = query.Trim(); TranslationMapping translationMapping = null; - if (_alphabet is not null && !_alphabet.CanBeTranslated(query)) + if (_alphabet is not null && _alphabet.ShouldTranslate(query)) { // We assume that if a query can be translated (containing characters of a language, like Chinese) // it actually means user doesn't want it to be translated to English letters. From b1cb852673005e955b1d4bd0bb2ed692e44308c9 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 2 Jun 2024 14:18:57 +0800 Subject: [PATCH 0012/1798] Extract classes --- Flow.Launcher.Infrastructure/IAlphabet.cs | 22 ++++ .../PinyinAlphabet.cs | 113 ------------------ .../TranslationMapping.cs | 99 +++++++++++++++ 3 files changed, 121 insertions(+), 113 deletions(-) create mode 100644 Flow.Launcher.Infrastructure/IAlphabet.cs create mode 100644 Flow.Launcher.Infrastructure/TranslationMapping.cs diff --git a/Flow.Launcher.Infrastructure/IAlphabet.cs b/Flow.Launcher.Infrastructure/IAlphabet.cs new file mode 100644 index 000000000..e79ec0c6d --- /dev/null +++ b/Flow.Launcher.Infrastructure/IAlphabet.cs @@ -0,0 +1,22 @@ +namespace Flow.Launcher.Infrastructure +{ + /// + /// Translate a language to English letters using a given rule. + /// + public interface IAlphabet + { + /// + /// Translate a string to English letters, using a given rule. + /// + /// String to translate. + /// + public (string translation, TranslationMapping map) Translate(string stringToTranslate); + + /// + /// Determine if a string can be translated to English letter with this Alphabet. + /// + /// String to translate. + /// + public bool ShouldTranslate(string stringToTranslate); + } +} diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index 961af1d32..d98d823d7 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -9,119 +9,6 @@ using ToolGood.Words.Pinyin; namespace Flow.Launcher.Infrastructure { - public class TranslationMapping - { - private bool constructed; - - private List originalIndexs = new List(); - private List translatedIndexs = new List(); - private int translatedLength = 0; - - public string key { get; private set; } - - public void setKey(string key) - { - this.key = key; - } - - public void AddNewIndex(int originalIndex, int translatedIndex, int length) - { - if (constructed) - throw new InvalidOperationException("Mapping shouldn't be changed after constructed"); - - originalIndexs.Add(originalIndex); - translatedIndexs.Add(translatedIndex); - translatedIndexs.Add(translatedIndex + length); - translatedLength += length - 1; - } - - public int MapToOriginalIndex(int translatedIndex) - { - if (translatedIndex > translatedIndexs.Last()) - return translatedIndex - translatedLength - 1; - - int lowerBound = 0; - int upperBound = originalIndexs.Count - 1; - - int count = 0; - - // Corner case handle - if (translatedIndex < translatedIndexs[0]) - return translatedIndex; - if (translatedIndex > translatedIndexs.Last()) - { - int indexDef = 0; - for (int k = 0; k < originalIndexs.Count; k++) - { - indexDef += translatedIndexs[k * 2 + 1] - translatedIndexs[k * 2]; - } - - return translatedIndex - indexDef - 1; - } - - // Binary Search with Range - for (int i = originalIndexs.Count / 2;; count++) - { - if (translatedIndex < translatedIndexs[i * 2]) - { - // move to lower middle - upperBound = i; - i = (i + lowerBound) / 2; - } - else if (translatedIndex > translatedIndexs[i * 2 + 1] - 1) - { - lowerBound = i; - // move to upper middle - // due to floor of integer division, move one up on corner case - i = (i + upperBound + 1) / 2; - } - else - return originalIndexs[i]; - - if (upperBound - lowerBound <= 1 && - translatedIndex > translatedIndexs[lowerBound * 2 + 1] && - translatedIndex < translatedIndexs[upperBound * 2]) - { - int indexDef = 0; - - for (int j = 0; j < upperBound; j++) - { - indexDef += translatedIndexs[j * 2 + 1] - translatedIndexs[j * 2]; - } - - return translatedIndex - indexDef - 1; - } - } - } - - public void endConstruct() - { - if (constructed) - throw new InvalidOperationException("Mapping has already been constructed"); - constructed = true; - } - } - - /// - /// Translate a language to English letters using a given rule. - /// - public interface IAlphabet - { - /// - /// Translate a string to English letters, using a given rule. - /// - /// String to translate. - /// - public (string translation, TranslationMapping map) Translate(string stringToTranslate); - - /// - /// Determine if a string can be translated to English letter with this Alphabet. - /// - /// String to translate. - /// - public bool ShouldTranslate(string stringToTranslate); - } - public class PinyinAlphabet : IAlphabet { private ConcurrentDictionary _pinyinCache = diff --git a/Flow.Launcher.Infrastructure/TranslationMapping.cs b/Flow.Launcher.Infrastructure/TranslationMapping.cs new file mode 100644 index 000000000..f288c816a --- /dev/null +++ b/Flow.Launcher.Infrastructure/TranslationMapping.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Flow.Launcher.Infrastructure +{ + public class TranslationMapping + { + private bool constructed; + + private List originalIndexs = new List(); + private List translatedIndexs = new List(); + private int translatedLength = 0; + + public string key { get; private set; } + + public void setKey(string key) + { + this.key = key; + } + + public void AddNewIndex(int originalIndex, int translatedIndex, int length) + { + if (constructed) + throw new InvalidOperationException("Mapping shouldn't be changed after constructed"); + + originalIndexs.Add(originalIndex); + translatedIndexs.Add(translatedIndex); + translatedIndexs.Add(translatedIndex + length); + translatedLength += length - 1; + } + + public int MapToOriginalIndex(int translatedIndex) + { + if (translatedIndex > translatedIndexs.Last()) + return translatedIndex - translatedLength - 1; + + int lowerBound = 0; + int upperBound = originalIndexs.Count - 1; + + int count = 0; + + // Corner case handle + if (translatedIndex < translatedIndexs[0]) + return translatedIndex; + if (translatedIndex > translatedIndexs.Last()) + { + int indexDef = 0; + for (int k = 0; k < originalIndexs.Count; k++) + { + indexDef += translatedIndexs[k * 2 + 1] - translatedIndexs[k * 2]; + } + + return translatedIndex - indexDef - 1; + } + + // Binary Search with Range + for (int i = originalIndexs.Count / 2;; count++) + { + if (translatedIndex < translatedIndexs[i * 2]) + { + // move to lower middle + upperBound = i; + i = (i + lowerBound) / 2; + } + else if (translatedIndex > translatedIndexs[i * 2 + 1] - 1) + { + lowerBound = i; + // move to upper middle + // due to floor of integer division, move one up on corner case + i = (i + upperBound + 1) / 2; + } + else + return originalIndexs[i]; + + if (upperBound - lowerBound <= 1 && + translatedIndex > translatedIndexs[lowerBound * 2 + 1] && + translatedIndex < translatedIndexs[upperBound * 2]) + { + int indexDef = 0; + + for (int j = 0; j < upperBound; j++) + { + indexDef += translatedIndexs[j * 2 + 1] - translatedIndexs[j * 2]; + } + + return translatedIndex - indexDef - 1; + } + } + } + + public void endConstruct() + { + if (constructed) + throw new InvalidOperationException("Mapping has already been constructed"); + constructed = true; + } + } +} From 6807afbe6d753eed6984e1b1ab6019e2864767cd Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 2 Jun 2024 14:03:00 +0800 Subject: [PATCH 0013/1798] Remove unused alphabet arg in PublicAPIInstance --- Flow.Launcher/App.xaml.cs | 2 +- Flow.Launcher/PublicAPIInstance.cs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index d74ea62fb..560bb052b 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -74,7 +74,7 @@ namespace Flow.Launcher PluginManager.LoadPlugins(_settings.PluginSettings); _mainVM = new MainViewModel(_settings); - API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet); + API = new PublicAPIInstance(_settingsVM, _mainVM); Http.API = API; Http.Proxy = _settings.Proxy; diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 952ce0edb..e14d692cd 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -32,15 +32,13 @@ namespace Flow.Launcher { private readonly SettingWindowViewModel _settingsVM; private readonly MainViewModel _mainVM; - private readonly DoublePinAlphabet _alphabet; #region Constructor - public PublicAPIInstance(SettingWindowViewModel settingsVM, MainViewModel mainVM, DoublePinAlphabet alphabet) + public PublicAPIInstance(SettingWindowViewModel settingsVM, MainViewModel mainVM) { _settingsVM = settingsVM; _mainVM = mainVM; - _alphabet = alphabet; GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback; WebRequest.RegisterPrefix("data", new DataWebRequestFactory()); } From a2efa11699fed4b3aac21bdff26555ce57b274aa Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 2 Jun 2024 14:19:27 +0800 Subject: [PATCH 0014/1798] Merge DoublePinAlphabet logic --- .../DoublePinAlphabet.cs | 194 ------------------ .../PinyinAlphabet.cs | 127 +++++++++++- .../UserSettings/Settings.cs | 3 +- Flow.Launcher/App.xaml.cs | 2 +- 4 files changed, 121 insertions(+), 205 deletions(-) delete mode 100644 Flow.Launcher.Infrastructure/DoublePinAlphabet.cs diff --git a/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs b/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs deleted file mode 100644 index 945f47a56..000000000 --- a/Flow.Launcher.Infrastructure/DoublePinAlphabet.cs +++ /dev/null @@ -1,194 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text; -using Flow.Launcher.Infrastructure.UserSettings; -using ToolGood.Words.Pinyin; - -namespace Flow.Launcher.Infrastructure -{ - public class DoublePinAlphabet : IAlphabet - { - private ConcurrentDictionary _doublePinCache = - new ConcurrentDictionary(); - - private Settings _settings; - - public void Initialize([NotNull] Settings settings) - { - _settings = settings ?? throw new ArgumentNullException(nameof(settings)); - } - - public bool ShouldTranslate(string stringToTranslate) - { - return stringToTranslate.Length % 2 == 0 && !WordsHelper.HasChinese(stringToTranslate); - } - - public (string translation, TranslationMapping map) Translate(string content) - { - if (_settings.ShouldUsePinyin) - { - if (!_doublePinCache.ContainsKey(content)) - { - return BuildCacheFromContent(content); - } - else - { - return _doublePinCache[content]; - } - } - return (content, null); - } - - private (string translation, TranslationMapping map) BuildCacheFromContent(string content) - { - if (WordsHelper.HasChinese(content)) - { - var resultList = WordsHelper.GetPinyinList(content); - StringBuilder resultBuilder = new StringBuilder(); - TranslationMapping map = new TranslationMapping(); - - bool pre = false; - - for (int i = 0; i < resultList.Length; i++) - { - if (content[i] >= 0x3400 && content[i] <= 0x9FD5) - { - string dp = _settings.ShouldUseDoublePin ? ToDoublePin(resultList[i].ToLower()) : resultList[i]; - map.AddNewIndex(i, resultBuilder.Length, dp.Length + 1); - resultBuilder.Append(' '); - resultBuilder.Append(dp); - pre = true; - } - else - { - if (pre) - { - pre = false; - resultBuilder.Append(' '); - } - - resultBuilder.Append(resultList[i]); - } - } - - map.endConstruct(); - - var key = resultBuilder.ToString(); - map.setKey(key); - - return _doublePinCache[content] = (key, map); - } - else - { - return (content, null); - } - } - - private static readonly ReadOnlyDictionary special = new(new Dictionary(){ - {"a", "aa"}, - {"ai", "ai"}, - {"an", "an"}, - {"ang", "ah"}, - {"ao", "ao"}, - {"e", "ee"}, - {"ei", "ei"}, - {"en", "en"}, - {"er", "er"}, - {"o", "oo"}, - {"ou", "ou"} - }); - - - private static readonly ReadOnlyDictionary first = new(new Dictionary(){ - {"ch", "i"}, - {"sh", "u"}, - {"zh", "v"} - }); - - - private static readonly ReadOnlyDictionary second = new(new Dictionary() - { - {"ua", "x"}, - {"ei", "w"}, - {"e", "e"}, - {"ou", "z"}, - {"iu", "q"}, - {"ve", "t"}, - {"ue", "t"}, - {"u", "u"}, - {"i", "i"}, - {"o", "o"}, - {"uo", "o"}, - {"ie", "p"}, - {"a", "a"}, - {"ong", "s"}, - {"iong", "s"}, - {"ai", "d"}, - {"ing", "k"}, - {"uai", "k"}, - {"ang", "h"}, - {"uan", "r"}, - {"an", "j"}, - {"en", "f"}, - {"ia", "x"}, - {"iang", "l"}, - {"uang", "l"}, - {"eng", "g"}, - {"in", "b"}, - {"ao", "c"}, - {"v", "v"}, - {"ui", "v"}, - {"un", "y"}, - {"iao", "n"}, - {"ian", "m"} - }); - - private static string ToDoublePin(string fullPinyin) - { - // Assuming s is valid - StringBuilder doublePin = new StringBuilder(); - - if (fullPinyin.Length <= 3 && (fullPinyin[0] == 'a' || fullPinyin[0] == 'e' || fullPinyin[0] == 'o')) - { - if (special.ContainsKey(fullPinyin)) - { - return special[fullPinyin]; - } - } - - // zh, ch, sh - if (fullPinyin.Length >= 2 && first.ContainsKey(fullPinyin[..2])) - { - doublePin.Append(first[fullPinyin[..2]]); - - if (second.TryGetValue(fullPinyin[2..], out string tmp)) - { - doublePin.Append(tmp); - } - else - { - doublePin.Append(fullPinyin[2..]); - } - } - else - { - doublePin.Append(fullPinyin[0]); - - if (second.TryGetValue(fullPinyin[1..], out string tmp)) - { - doublePin.Append(tmp); - } - else - { - doublePin.Append(fullPinyin[1..]); - } - } - - return doublePin.ToString(); - } - } -} diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index d98d823d7..37e4f93d2 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -1,18 +1,18 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; using System.Text; using JetBrains.Annotations; using Flow.Launcher.Infrastructure.UserSettings; using ToolGood.Words.Pinyin; +using System.Collections.Generic; +using System.Collections.ObjectModel; namespace Flow.Launcher.Infrastructure { public class PinyinAlphabet : IAlphabet { - private ConcurrentDictionary _pinyinCache = - new ConcurrentDictionary(); + private readonly ConcurrentDictionary _pinyinCache = + new(); private Settings _settings; @@ -23,20 +23,22 @@ namespace Flow.Launcher.Infrastructure public bool ShouldTranslate(string stringToTranslate) { - return WordsHelper.HasChinese(stringToTranslate); + return _settings.UseDoublePinyin ? + (WordsHelper.HasChinese(stringToTranslate) && stringToTranslate.Length % 2 == 0) : + WordsHelper.HasChinese(stringToTranslate); } public (string translation, TranslationMapping map) Translate(string content) { if (_settings.ShouldUsePinyin) { - if (!_pinyinCache.ContainsKey(content)) + if (!_pinyinCache.TryGetValue(content, out var value)) { return BuildCacheFromContent(content); } else { - return _pinyinCache[content]; + return value; } } return (content, null); @@ -57,9 +59,10 @@ namespace Flow.Launcher.Infrastructure { if (content[i] >= 0x3400 && content[i] <= 0x9FD5) { - map.AddNewIndex(i, resultBuilder.Length, resultList[i].Length + 1); + string dp = _settings.UseDoublePinyin ? ToDoublePin(resultList[i].ToLower()) : resultList[i]; + map.AddNewIndex(i, resultBuilder.Length, dp.Length + 1); resultBuilder.Append(' '); - resultBuilder.Append(resultList[i]); + resultBuilder.Append(dp); pre = true; } else @@ -86,5 +89,111 @@ namespace Flow.Launcher.Infrastructure return (content, null); } } + + #region Double Pinyin + + private static readonly ReadOnlyDictionary special = new(new Dictionary(){ + {"a", "aa"}, + {"ai", "ai"}, + {"an", "an"}, + {"ang", "ah"}, + {"ao", "ao"}, + {"e", "ee"}, + {"ei", "ei"}, + {"en", "en"}, + {"er", "er"}, + {"o", "oo"}, + {"ou", "ou"} + }); + + + private static readonly ReadOnlyDictionary first = new(new Dictionary(){ + {"ch", "i"}, + {"sh", "u"}, + {"zh", "v"} + }); + + + private static readonly ReadOnlyDictionary second = new(new Dictionary() + { + {"ua", "x"}, + {"ei", "w"}, + {"e", "e"}, + {"ou", "z"}, + {"iu", "q"}, + {"ve", "t"}, + {"ue", "t"}, + {"u", "u"}, + {"i", "i"}, + {"o", "o"}, + {"uo", "o"}, + {"ie", "p"}, + {"a", "a"}, + {"ong", "s"}, + {"iong", "s"}, + {"ai", "d"}, + {"ing", "k"}, + {"uai", "k"}, + {"ang", "h"}, + {"uan", "r"}, + {"an", "j"}, + {"en", "f"}, + {"ia", "x"}, + {"iang", "l"}, + {"uang", "l"}, + {"eng", "g"}, + {"in", "b"}, + {"ao", "c"}, + {"v", "v"}, + {"ui", "v"}, + {"un", "y"}, + {"iao", "n"}, + {"ian", "m"} + }); + + private static string ToDoublePin(string fullPinyin) + { + // Assuming s is valid + StringBuilder doublePin = new StringBuilder(); + + if (fullPinyin.Length <= 3 && (fullPinyin[0] == 'a' || fullPinyin[0] == 'e' || fullPinyin[0] == 'o')) + { + if (special.TryGetValue(fullPinyin, out var value)) + { + return value; + } + } + + // zh, ch, sh + if (fullPinyin.Length >= 2 && first.ContainsKey(fullPinyin[..2])) + { + doublePin.Append(first[fullPinyin[..2]]); + + if (second.TryGetValue(fullPinyin[2..], out string tmp)) + { + doublePin.Append(tmp); + } + else + { + doublePin.Append(fullPinyin[2..]); + } + } + else + { + doublePin.Append(fullPinyin[0]); + + if (second.TryGetValue(fullPinyin[1..], out string tmp)) + { + doublePin.Append(tmp); + } + else + { + doublePin.Append(fullPinyin[1..]); + } + } + + return doublePin.ToString(); + } + #endregion } } diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 8d94cdba5..e79c3f52d 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -186,7 +186,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings /// public bool ShouldUsePinyin { get; set; } = false; - public bool ShouldUseDoublePin { get; set; } = false; + public bool UseDoublePinyin { get; set; } = false; + public bool AlwaysPreview { get; set; } = false; public bool AlwaysStartEn { get; set; } = false; diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 560bb052b..83870837a 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -30,7 +30,7 @@ namespace Flow.Launcher private SettingWindowViewModel _settingsVM; private readonly Updater _updater = new Updater(Flow.Launcher.Properties.Settings.Default.GithubRepo); private readonly Portable _portable = new Portable(); - private readonly DoublePinAlphabet _alphabet = new DoublePinAlphabet(); + private readonly PinyinAlphabet _alphabet = new PinyinAlphabet(); private StringMatcher _stringMatcher; [STAThread] From 12c4e37a95df44fc968a6459e7a3cbf6de4063e6 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 2 Jun 2024 14:33:49 +0800 Subject: [PATCH 0015/1798] Developing --- Flow.Launcher.Infrastructure/UserSettings/Settings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index e79c3f52d..30e3b77be 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -186,7 +186,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings /// public bool ShouldUsePinyin { get; set; } = false; - public bool UseDoublePinyin { get; set; } = false; + public bool UseDoublePinyin { get; set; } = true; //For developing public bool AlwaysPreview { get; set; } = false; public bool AlwaysStartEn { get; set; } = false; From f673000d67e4ff1180e6d2856bf85f1640433a7c Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 2 Jun 2024 14:37:15 +0800 Subject: [PATCH 0016/1798] Fix ShouldTranslate() --- Flow.Launcher.Infrastructure/PinyinAlphabet.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index 37e4f93d2..b48a61090 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -23,9 +23,9 @@ namespace Flow.Launcher.Infrastructure public bool ShouldTranslate(string stringToTranslate) { - return _settings.UseDoublePinyin ? - (WordsHelper.HasChinese(stringToTranslate) && stringToTranslate.Length % 2 == 0) : - WordsHelper.HasChinese(stringToTranslate); + return _settings.UseDoublePinyin ? + (!WordsHelper.HasChinese(stringToTranslate) && stringToTranslate.Length % 2 == 0) : + !WordsHelper.HasChinese(stringToTranslate); } public (string translation, TranslationMapping map) Translate(string content) From b10a6e19df5afcbd13ca612f6e6952f19a3b9dde Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 2 Jun 2024 15:18:24 +0800 Subject: [PATCH 0017/1798] Capitalize first letter --- .../PinyinAlphabet.cs | 104 +++++++++--------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index b48a61090..cbec7feae 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -46,71 +46,69 @@ namespace Flow.Launcher.Infrastructure private (string translation, TranslationMapping map) BuildCacheFromContent(string content) { - if (WordsHelper.HasChinese(content)) - { - var resultList = WordsHelper.GetPinyinList(content); - - StringBuilder resultBuilder = new StringBuilder(); - TranslationMapping map = new TranslationMapping(); - - bool pre = false; - - for (int i = 0; i < resultList.Length; i++) - { - if (content[i] >= 0x3400 && content[i] <= 0x9FD5) - { - string dp = _settings.UseDoublePinyin ? ToDoublePin(resultList[i].ToLower()) : resultList[i]; - map.AddNewIndex(i, resultBuilder.Length, dp.Length + 1); - resultBuilder.Append(' '); - resultBuilder.Append(dp); - pre = true; - } - else - { - if (pre) - { - pre = false; - resultBuilder.Append(' '); - } - - resultBuilder.Append(resultList[i]); - } - } - - map.endConstruct(); - - var key = resultBuilder.ToString(); - map.setKey(key); - - return _pinyinCache[content] = (key, map); - } - else + if (!WordsHelper.HasChinese(content)) { return (content, null); } + + var resultList = WordsHelper.GetPinyinList(content); + + StringBuilder resultBuilder = new StringBuilder(); + TranslationMapping map = new TranslationMapping(); + + bool pre = false; + + for (int i = 0; i < resultList.Length; i++) + { + if (content[i] >= 0x3400 && content[i] <= 0x9FD5) + { + string dp = _settings.UseDoublePinyin ? ToDoublePin(resultList[i]) : resultList[i]; + map.AddNewIndex(i, resultBuilder.Length, dp.Length + 1); + resultBuilder.Append(' '); + resultBuilder.Append(dp); + pre = true; + } + else + { + if (pre) + { + pre = false; + resultBuilder.Append(' '); + } + + resultBuilder.Append(resultList[i]); + } + } + + map.endConstruct(); + + var key = resultBuilder.ToString(); + map.setKey(key); + + return _pinyinCache[content] = (key, map); } #region Double Pinyin private static readonly ReadOnlyDictionary special = new(new Dictionary(){ - {"a", "aa"}, - {"ai", "ai"}, - {"an", "an"}, - {"ang", "ah"}, - {"ao", "ao"}, - {"e", "ee"}, - {"ei", "ei"}, - {"en", "en"}, - {"er", "er"}, - {"o", "oo"}, - {"ou", "ou"} + {"A", "aa"}, + {"Ai", "ai"}, + {"An", "an"}, + {"Ang", "ah"}, + {"Ao", "ao"}, + {"E", "ee"}, + {"Ei", "ei"}, + {"En", "en"}, + {"Er", "er"}, + {"O", "oo"}, + {"Ou", "ou"} }); private static readonly ReadOnlyDictionary first = new(new Dictionary(){ - {"ch", "i"}, - {"sh", "u"}, - {"zh", "v"} + {"Ch", "i"}, + {"Sh", "u"}, + {"Zh", "v"} }); From b816d1b866aa93b6d8f2da9f5cef334bda64748b Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Sun, 2 Jun 2024 15:21:04 +0800 Subject: [PATCH 0018/1798] Remove unused key in pinyin alphabet --- Flow.Launcher.Infrastructure/PinyinAlphabet.cs | 1 - Flow.Launcher.Infrastructure/TranslationMapping.cs | 7 ------- 2 files changed, 8 deletions(-) diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index cbec7feae..10799c676 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -83,7 +83,6 @@ namespace Flow.Launcher.Infrastructure map.endConstruct(); var key = resultBuilder.ToString(); - map.setKey(key); return _pinyinCache[content] = (key, map); } diff --git a/Flow.Launcher.Infrastructure/TranslationMapping.cs b/Flow.Launcher.Infrastructure/TranslationMapping.cs index f288c816a..c976fc522 100644 --- a/Flow.Launcher.Infrastructure/TranslationMapping.cs +++ b/Flow.Launcher.Infrastructure/TranslationMapping.cs @@ -12,13 +12,6 @@ namespace Flow.Launcher.Infrastructure private List translatedIndexs = new List(); private int translatedLength = 0; - public string key { get; private set; } - - public void setKey(string key) - { - this.key = key; - } - public void AddNewIndex(int originalIndex, int translatedIndex, int length) { if (constructed) From 49a71d7d53a3c66a3feac30f743f625f47059f83 Mon Sep 17 00:00:00 2001 From: Odotocodot <48138990+Odotocodot@users.noreply.github.com> Date: Sat, 15 Jun 2024 12:16:36 +0100 Subject: [PATCH 0019/1798] Move Theme Selector into Sys plugin --- ...w.Launcher.Plugin.FlowThemeSelector.csproj | 37 ------------------ .../plugin.json | 12 ------ .../Flow.Launcher.Plugin.Sys.csproj | 1 + .../Images/theme_selector.png} | Bin .../Languages/en.xaml | 4 +- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 29 +++++++++++++- .../ThemeSelector.cs} | 24 +++++++----- 7 files changed, 45 insertions(+), 62 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj delete mode 100644 Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json rename Plugins/{Flow.Launcher.Plugin.FlowThemeSelector/icon.png => Flow.Launcher.Plugin.Sys/Images/theme_selector.png} (100%) rename Plugins/{Flow.Launcher.Plugin.FlowThemeSelector/Main.cs => Flow.Launcher.Plugin.Sys/ThemeSelector.cs} (72%) diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj deleted file mode 100644 index ba0ddd6ab..000000000 --- a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Flow.Launcher.Plugin.FlowThemeSelector.csproj +++ /dev/null @@ -1,37 +0,0 @@ - - - - - Library - net7.0-windows - true - false - - - - ..\..\Output\Debug\Plugins\Flow.Launcher.Plugin.FlowThemeSelector - - - - ..\..\Output\Release\Plugins\Flow.Launcher.Plugin.FlowThemeSelector - - - - - - - - - - - PreserveNewest - - - - - - PreserveNewest - - - - diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json b/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json deleted file mode 100644 index f275d129c..000000000 --- a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/plugin.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "ID": "4DFA743E1086414BAB0AA3071D561D75", - "ActionKeyword": "flowtheme", - "Name": "Flow Launcher Theme Selector", - "Description": "Quickly switch your Flow Launcher theme.", - "Author": "Odotocodot", - "Version": "1.0.0", - "Language": "csharp", - "Website": "https://github.com/Flow-Launcher/Flow.Launcher", - "IcoPath": "icon.png", - "ExecuteFileName": "Flow.Launcher.Plugin.FlowThemeSelector.dll" -} \ No newline at end of file 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 c7a722189..bba466384 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj +++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj @@ -38,6 +38,7 @@ + diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/icon.png b/Plugins/Flow.Launcher.Plugin.Sys/Images/theme_selector.png similarity index 100% rename from Plugins/Flow.Launcher.Plugin.FlowThemeSelector/icon.png rename to Plugins/Flow.Launcher.Plugin.Sys/Images/theme_selector.png diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml index 91f32a844..2a266f8f6 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml @@ -27,6 +27,7 @@ Flow Launcher Tips Flow Launcher UserData Folder Toggle Game Mode + Set the Flow Launcher Theme Shutdown Computer @@ -49,8 +50,9 @@ 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 - + Success All Flow Launcher settings saved Reloaded all applicable plugin data diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 1ec07915d..0dbb46be9 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -18,9 +18,10 @@ using MessageBox = System.Windows.MessageBox; namespace Flow.Launcher.Plugin.Sys { - public class Main : IPlugin, ISettingProvider, IPluginI18n + public class Main : IPlugin, ISettingProvider, IPluginI18n, IDisposable { private PluginInitContext context; + private ThemeSelector themeSelector; private Dictionary KeywordTitleMappings = new Dictionary(); #region DllImport @@ -58,6 +59,11 @@ namespace Flow.Launcher.Plugin.Sys public List Query(Query query) { + if(query.Search.StartsWith(ThemeSelector.Keyword)) + { + return themeSelector.Query(query); + } + var commands = Commands(); var results = new List(); foreach (var c in commands) @@ -106,6 +112,7 @@ namespace Flow.Launcher.Plugin.Sys public void Init(PluginInitContext context) { this.context = context; + themeSelector = new ThemeSelector(context); KeywordTitleMappings = new Dictionary{ {"Shutdown", "flowlauncher_plugin_sys_shutdown_computer_cmd"}, {"Restart", "flowlauncher_plugin_sys_restart_computer_cmd"}, @@ -126,7 +133,8 @@ namespace Flow.Launcher.Plugin.Sys {"Open Log Location", "flowlauncher_plugin_sys_open_log_location_cmd"}, {"Flow Launcher Tips", "flowlauncher_plugin_sys_open_docs_tips_cmd"}, {"Flow Launcher UserData Folder", "flowlauncher_plugin_sys_open_userdata_location_cmd"}, - {"Toggle Game Mode", "flowlauncher_plugin_sys_toggle_game_mode_cmd"} + {"Toggle Game Mode", "flowlauncher_plugin_sys_toggle_game_mode_cmd"}, + {"Set Flow Launcher Theme", "flowlauncher_plugin_sys_theme_selector_cmd"} }; } @@ -426,6 +434,18 @@ namespace Flow.Launcher.Plugin.Sys context.API.ToggleGameMode(); return true; } + }, + new Result + { + Title = "Set Flow Launcher Theme", + SubTitle = context.API.GetTranslation("flowlauncher_plugin_sys_theme_selector"), + IcoPath = "Images\\theme_selector.png", + Glyph = new GlyphInfo("/Resources/#Segoe Fluent Icons", "\ue790"), + Action = c => + { + context.API.ChangeQuery($"{ThemeSelector.Keyword} "); + return false; + } } }); @@ -441,5 +461,10 @@ namespace Flow.Launcher.Plugin.Sys { return context.API.GetTranslation("flowlauncher_plugin_sys_plugin_description"); } + + public void Dispose() + { + themeSelector.Dispose(); + } } } diff --git a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs similarity index 72% rename from Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs rename to Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index 6fd6472db..24d17486e 100644 --- a/Plugins/Flow.Launcher.Plugin.FlowThemeSelector/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -4,14 +4,16 @@ using System.IO; using System.Linq; using Flow.Launcher.Core.Resource; -namespace Flow.Launcher.Plugin.FlowThemeSelector +namespace Flow.Launcher.Plugin.Sys { - public class FlowThemeSelector : IPlugin, IReloadable, IDisposable + public class ThemeSelector : IReloadable, IDisposable { - private PluginInitContext context; + public const string Keyword = "fltheme"; + + private readonly PluginInitContext context; private IEnumerable themes; - public void Init(PluginInitContext context) + public ThemeSelector(PluginInitContext context) { this.context = context; context.API.VisibilityChanged += OnVisibilityChanged; @@ -24,14 +26,16 @@ namespace Flow.Launcher.Plugin.FlowThemeSelector LoadThemes(); } - if (string.IsNullOrWhiteSpace(query.Search)) + string search = query.Search[(query.Search.IndexOf(Keyword, StringComparison.Ordinal) + Keyword.Length + 1)..]; + + if (string.IsNullOrWhiteSpace(search)) { return themes.Select(CreateThemeResult) .OrderBy(x => x.Title) .ToList(); } - return themes.Select(theme => (theme, matchResult: context.API.FuzzySearch(query.Search, theme))) + return themes.Select(theme => (theme, matchResult: context.API.FuzzySearch(search, theme))) .Where(x => x.matchResult.IsSearchPrecisionScoreMet()) .Select(x => CreateThemeResult(x.theme, x.matchResult.Score, x.matchResult.MatchData)) .OrderBy(x => x.Title) @@ -46,11 +50,12 @@ namespace Flow.Launcher.Plugin.FlowThemeSelector } } - public void LoadThemes() => themes = ThemeManager.Instance.LoadAvailableThemes().Select(Path.GetFileNameWithoutExtension); + private void LoadThemes() + => themes = ThemeManager.Instance.LoadAvailableThemes().Select(Path.GetFileNameWithoutExtension); - public static Result CreateThemeResult(string theme) => CreateThemeResult(theme, 0, null); + private static Result CreateThemeResult(string theme) => CreateThemeResult(theme, 0, null); - public static Result CreateThemeResult(string theme, int score, IList highlightData) + private static Result CreateThemeResult(string theme, int score, IList highlightData) { string title; if (theme == ThemeManager.Instance.Settings.Theme) @@ -86,6 +91,5 @@ namespace Flow.Launcher.Plugin.FlowThemeSelector context.API.VisibilityChanged -= OnVisibilityChanged; } } - } } From 7a0be2c6103939312eeead86c3a1e01a3d618a3f Mon Sep 17 00:00:00 2001 From: Odotocodot <48138990+Odotocodot@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:50:00 +0100 Subject: [PATCH 0020/1798] Remove Reloadable from theme selector --- Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index 24d17486e..758250421 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -6,7 +6,7 @@ using Flow.Launcher.Core.Resource; namespace Flow.Launcher.Plugin.Sys { - public class ThemeSelector : IReloadable, IDisposable + public class ThemeSelector : IDisposable { public const string Keyword = "fltheme"; @@ -82,8 +82,6 @@ namespace Flow.Launcher.Plugin.Sys }; } - public void ReloadData() => LoadThemes(); - public void Dispose() { if (context != null && context.API != null) From dd29b4ad4419aad72c58f0dac10f4f4a2e7e530b Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Sat, 22 Jun 2024 19:31:47 -0500 Subject: [PATCH 0021/1798] velopack prepare --- Flow.Launcher.Core/Flow.Launcher.Core.csproj | 1 + Flow.Launcher.Core/Updater.cs | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Core/Flow.Launcher.Core.csproj b/Flow.Launcher.Core/Flow.Launcher.Core.csproj index fe2cb7e58..a141243b7 100644 --- a/Flow.Launcher.Core/Flow.Launcher.Core.csproj +++ b/Flow.Launcher.Core/Flow.Launcher.Core.csproj @@ -57,6 +57,7 @@ + diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 3f64b273e..df2b2dae7 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -45,8 +45,8 @@ namespace Flow.Launcher.Core // UpdateApp CheckForUpdate will return value only if the app is squirrel installed var newUpdateInfo = await updateManager.CheckForUpdate().NonNull().ConfigureAwait(false); - var newReleaseVersion = Version.Parse(newUpdateInfo.FutureReleaseEntry.Version.ToString()); - var currentVersion = Version.Parse(Constant.Version); + var newReleaseVersion = SemanticVersioning.Version.Parse(newUpdateInfo.FutureReleaseEntry.Version.ToString()); + var currentVersion = SemanticVersioning.Version.Parse(Constant.Version); Log.Info($"|Updater.UpdateApp|Future Release <{newUpdateInfo.FutureReleaseEntry.Formatted()}>"); @@ -127,7 +127,7 @@ namespace Flow.Launcher.Core await using var jsonStream = await Http.GetStreamAsync(api).ConfigureAwait(false); var releases = await System.Text.Json.JsonSerializer.DeserializeAsync>(jsonStream).ConfigureAwait(false); - var latest = releases.Where(r => !r.Prerelease).OrderByDescending(r => r.PublishedAt).First(); + var latest = releases.OrderByDescending(r => r.PublishedAt).First(); var latestUrl = latest.HtmlUrl.Replace("/tag/", "/download/"); var client = new WebClient From 5a80adcbfec1309b537721ab9e98f9d07187c135 Mon Sep 17 00:00:00 2001 From: Kevin Zhang <45326534+taooceros@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:59:43 -0600 Subject: [PATCH 0022/1798] Send a reload request with ctx when reloading --- Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs index 5a6633525..ae4fd639d 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs @@ -133,10 +133,16 @@ namespace Flow.Launcher.Core.Plugin RPC.StartListening(); } - public virtual Task ReloadDataAsync() + public virtual async Task ReloadDataAsync() { SetupJsonRPC(); - return Task.CompletedTask; + try + { + await RPC.InvokeAsync("reload", context); + } + catch (RemoteMethodNotFoundException e) + { + } } public virtual async ValueTask DisposeAsync() From b2532fc88e09977b2c62d4eec3b8ec1ec0dd43d6 Mon Sep 17 00:00:00 2001 From: "pp.stabrawa" Date: Fri, 27 Dec 2024 12:43:43 +0100 Subject: [PATCH 0023/1798] Order search result by window title --- .../Main.cs | 30 ++++++++----- .../ProcessHelper.cs | 44 ++++++++++++++++++- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index be2a2dd66..03b563c9b 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Flow.Launcher.Infrastructure; @@ -60,30 +60,33 @@ namespace Flow.Launcher.Plugin.ProcessKiller return menuOptions; } + private record RunningProcessInfo(string ProcessName, string MainWindowTitle); + private List CreateResultsFromQuery(Query query) { string termToSearch = query.Search; - var processlist = processHelper.GetMatchingProcesses(termToSearch); - - if (!processlist.Any()) + var processList = processHelper.GetMatchingProcesses(termToSearch); + var processWithNonEmptyMainWindowTitleList = processHelper.GetProcessesWithNonEmptyWindowTitle(); + + if (!processList.Any()) { return null; } var results = new List(); - foreach (var pr in processlist) + foreach (var pr in processList) { var p = pr.Process; var path = processHelper.TryGetProcessFilename(p); results.Add(new Result() { IcoPath = path, - Title = p.ProcessName + " - " + p.Id, + Title = processWithNonEmptyMainWindowTitleList.TryGetValue(p.Id, out var mainWindowTitle) ? mainWindowTitle : p.ProcessName + " - " + p.Id, SubTitle = path, TitleHighlightData = StringMatcher.FuzzySearch(termToSearch, p.ProcessName).MatchData, Score = pr.Score, - ContextData = p.ProcessName, + ContextData = new RunningProcessInfo(p.ProcessName, mainWindowTitle), AutoCompleteText = $"{_context.CurrentPluginMetadata.ActionKeyword}{Plugin.Query.TermSeparator}{p.ProcessName}", Action = (c) => { @@ -95,22 +98,25 @@ namespace Flow.Launcher.Plugin.ProcessKiller }); } - var sortedResults = results.OrderBy(x => x.Title).ToList(); + var sortedResults = results + .OrderBy(x => string.IsNullOrEmpty(((RunningProcessInfo)x.ContextData).MainWindowTitle)) + .ThenBy(x => x.Title) + .ToList(); // When there are multiple results AND all of them are instances of the same executable // add a quick option to kill them all at the top of the results. var firstResult = sortedResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.SubTitle)); - if (processlist.Count > 1 && !string.IsNullOrEmpty(termToSearch) && sortedResults.All(r => r.SubTitle == firstResult?.SubTitle)) + if (processList.Count > 1 && !string.IsNullOrEmpty(termToSearch) && sortedResults.All(r => r.SubTitle == firstResult?.SubTitle)) { 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 = string.Format(_context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_all"), ((RunningProcessInfo)firstResult?.ContextData).ProcessName), + SubTitle = string.Format(_context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_all_count"), processList.Count), Score = 200, Action = (c) => { - foreach (var p in processlist) + foreach (var p in processList) { processHelper.TryKill(p.Process); } diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs index 0acc39fbb..5cc94dfdf 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs @@ -1,4 +1,4 @@ -using Flow.Launcher.Infrastructure; +using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using System; using System.Collections.Generic; @@ -11,6 +11,20 @@ namespace Flow.Launcher.Plugin.ProcessKiller { internal class ProcessHelper { + [DllImport("user32.dll")] + private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam); + + private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); + + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); + + [DllImport("user32.dll")] + private static extern bool IsWindowVisible(IntPtr hWnd); + + [DllImport("user32.dll")] + private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + private readonly HashSet _systemProcessList = new HashSet() { "conhost", @@ -60,6 +74,34 @@ namespace Flow.Launcher.Plugin.ProcessKiller return processlist; } + /// + /// Returns a dictionary of process IDs and their window titles for processes that have a visible main window with a non-empty title. + /// + public Dictionary GetProcessesWithNonEmptyWindowTitle() + { + var processDict = new Dictionary(); + EnumWindows((hWnd, lParam) => + { + StringBuilder windowTitle = new StringBuilder(); + GetWindowText(hWnd, windowTitle, windowTitle.Capacity); + + if (!string.IsNullOrWhiteSpace(windowTitle.ToString()) && IsWindowVisible(hWnd)) + { + GetWindowThreadProcessId(hWnd, out var processId); + var process = Process.GetProcessById((int)processId); + + if (!processDict.ContainsKey((int)processId)) + { + processDict.Add((int)processId, windowTitle.ToString()); + } + } + + return true; + }, IntPtr.Zero); + + return processDict; + } + /// /// Returns all non-system processes whose file path matches the given processPath /// From 4b9c23d49bcf823641258ab003225edd9face248 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2024 22:46:08 +0000 Subject: [PATCH 0024/1798] Bump nunit from 3.14.0 to 4.3.2 Bumps [nunit](https://github.com/nunit/nunit) from 3.14.0 to 4.3.2. - [Release notes](https://github.com/nunit/nunit/releases) - [Changelog](https://github.com/nunit/nunit/blob/main/CHANGES.md) - [Commits](https://github.com/nunit/nunit/compare/v3.14.0...4.3.2) --- updated-dependencies: - dependency-name: nunit dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Flow.Launcher.Test/Flow.Launcher.Test.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Test/Flow.Launcher.Test.csproj b/Flow.Launcher.Test/Flow.Launcher.Test.csproj index 8286e142e..0241a374e 100644 --- a/Flow.Launcher.Test/Flow.Launcher.Test.csproj +++ b/Flow.Launcher.Test/Flow.Launcher.Test.csproj @@ -49,7 +49,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 20ffff6d1b8464d6aa20c7e32e12aac1e5abd6a0 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 9 Jan 2025 21:30:11 +0800 Subject: [PATCH 0025/1798] Use api to call api functions --- Flow.Launcher/ActionKeywords.xaml.cs | 2 +- Flow.Launcher/App.xaml.cs | 4 +++- Flow.Launcher/CustomQueryHotkeySetting.xaml.cs | 2 +- Flow.Launcher/CustomShortcutSetting.xaml.cs | 4 ++-- Flow.Launcher/Helper/HotKeyMapper.cs | 2 +- Flow.Launcher/PriorityChangeWindow.xaml.cs | 4 ++-- .../ViewModels/SettingsPaneAboutViewModel.cs | 2 +- .../ViewModels/SettingsPaneHotkeyViewModel.cs | 12 ++++++------ .../ViewModels/SettingsPaneProxyViewModel.cs | 2 +- .../ViewModels/SettingsPaneThemeViewModel.cs | 2 +- 10 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index ba47a4ded..c3966e618 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -44,7 +44,7 @@ namespace Flow.Launcher else { string msg = translater.GetTranslation("newActionKeywordsHasBeenAssigned"); - MessageBoxEx.Show(msg); + App.API.ShowMsgBox(msg); } } } diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 4d1adc6cd..58da35e85 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -15,13 +15,15 @@ using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Image; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher { - public partial class App : IDisposable, ISingleInstanceApp + public partial class App : IDisposable, ISingleInstanceApp, IApp { + public IPublicAPI PublicAPI => API; public static PublicAPIInstance API { get; private set; } private const string Unique = "Flow.Launcher_Unique_Application_Mutex"; private static bool _disposed; diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index 81e7600b8..47460ff7d 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -63,7 +63,7 @@ namespace Flow.Launcher o.ActionKeyword == item.ActionKeyword && o.Hotkey == item.Hotkey); if (updateCustomHotkey == null) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey")); Close(); return; } diff --git a/Flow.Launcher/CustomShortcutSetting.xaml.cs b/Flow.Launcher/CustomShortcutSetting.xaml.cs index dec3506eb..4589b45ec 100644 --- a/Flow.Launcher/CustomShortcutSetting.xaml.cs +++ b/Flow.Launcher/CustomShortcutSetting.xaml.cs @@ -43,13 +43,13 @@ namespace Flow.Launcher { if (String.IsNullOrEmpty(Key) || String.IsNullOrEmpty(Value)) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("emptyShortcut")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("emptyShortcut")); return; } // Check if key is modified or adding a new one if (((update && originalKey != Key) || !update) && _hotkeyVm.DoesShortcutExist(Key)) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("duplicateShortcut")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("duplicateShortcut")); return; } DialogResult = !update || originalKey != Key || originalValue != Value; diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index 8b30b8be1..b40406e42 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -46,7 +46,7 @@ internal static class HotKeyMapper { string errorMsg = string.Format(InternationalizationManager.Instance.GetTranslation("registerHotkeyFailed"), hotkeyStr); string errorMsgTitle = InternationalizationManager.Instance.GetTranslation("MessageBoxTitle"); - MessageBoxEx.Show(errorMsg, errorMsgTitle); + App.API.ShowMsgBox(errorMsg, errorMsgTitle); } } diff --git a/Flow.Launcher/PriorityChangeWindow.xaml.cs b/Flow.Launcher/PriorityChangeWindow.xaml.cs index 2154b058d..fbe2a941d 100644 --- a/Flow.Launcher/PriorityChangeWindow.xaml.cs +++ b/Flow.Launcher/PriorityChangeWindow.xaml.cs @@ -24,7 +24,7 @@ namespace Flow.Launcher this.pluginViewModel = pluginViewModel; if (plugin == null) { - MessageBoxEx.Show(translater.GetTranslation("cannotFindSpecifiedPlugin")); + App.API.ShowMsgBox(translater.GetTranslation("cannotFindSpecifiedPlugin")); Close(); } } @@ -44,7 +44,7 @@ namespace Flow.Launcher else { string msg = translater.GetTranslation("invalidPriority"); - MessageBoxEx.Show(msg); + App.API.ShowMsgBox(msg); } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index 6e81db5e0..05fb16f5c 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -62,7 +62,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel [RelayCommand] private void AskClearLogFolderConfirmation() { - var confirmResult = MessageBoxEx.Show( + var confirmResult = App.API.ShowMsgBox( InternationalizationManager.Instance.GetTranslation("clearlogfolderMessage"), InternationalizationManager.Instance.GetTranslation("clearlogfolder"), MessageBoxButton.YesNo diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs index 6d8af9a3f..fb57f499b 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs @@ -42,11 +42,11 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomPluginHotkey; if (item is null) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); return; } - var result = MessageBoxEx.Show( + var result = App.API.ShowMsgBox( string.Format( InternationalizationManager.Instance.GetTranslation("deleteCustomHotkeyWarning"), item.Hotkey ), @@ -67,7 +67,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomPluginHotkey; if (item is null) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); return; } @@ -88,11 +88,11 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomShortcut; if (item is null) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); return; } - var result = MessageBoxEx.Show( + var result = App.API.ShowMsgBox( string.Format( InternationalizationManager.Instance.GetTranslation("deleteCustomShortcutWarning"), item.Key, item.Value ), @@ -112,7 +112,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomShortcut; if (item is null) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); return; } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs index 1c840fb27..e2f9e516c 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs @@ -22,7 +22,7 @@ public partial class SettingsPaneProxyViewModel : BaseModel private void OnTestProxyClicked() { var message = TestProxy(); - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation(message)); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation(message)); } private string TestProxy() diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index 8d8ccb780..980b2a811 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -49,7 +49,7 @@ public partial class SettingsPaneThemeViewModel : BaseModel { if (ThemeManager.Instance.BlurEnabled && value) { - MessageBoxEx.Show(InternationalizationManager.Instance.GetTranslation("shadowEffectNotAllowed")); + App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("shadowEffectNotAllowed")); return; } From 8b910500c6f3a2fe170cdc8261c6d0add722b744 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 9 Jan 2025 21:43:33 +0800 Subject: [PATCH 0026/1798] Add IApp & AppExtensions for accessing the properties & functions from anywhere in the application --- Flow.Launcher.Core/AppExtensions.cs | 15 +++++++++++++++ Flow.Launcher.Core/IApp.cs | 13 +++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 Flow.Launcher.Core/AppExtensions.cs create mode 100644 Flow.Launcher.Core/IApp.cs diff --git a/Flow.Launcher.Core/AppExtensions.cs b/Flow.Launcher.Core/AppExtensions.cs new file mode 100644 index 000000000..b02612d72 --- /dev/null +++ b/Flow.Launcher.Core/AppExtensions.cs @@ -0,0 +1,15 @@ +using System.Windows; +using Flow.Launcher.Plugin; + +namespace Flow.Launcher.Core; + +/// +/// Extension properties and functions of the current application singleton object. +/// +public static class AppExtensions +{ + /// + /// Gets the public API of the current application singleton object. + /// + public static IPublicAPI API => (Application.Current as IApp)!.PublicAPI; +} diff --git a/Flow.Launcher.Core/IApp.cs b/Flow.Launcher.Core/IApp.cs new file mode 100644 index 000000000..233fd5ed1 --- /dev/null +++ b/Flow.Launcher.Core/IApp.cs @@ -0,0 +1,13 @@ +using Flow.Launcher.Plugin; + +namespace Flow.Launcher.Core +{ + /// + /// Interface for the current application singleton object exposing the properties + /// and functions that can be accessed from anywhere in the application. + /// + public interface IApp + { + public IPublicAPI PublicAPI { get; } + } +} From 88e84378daee2906bdbfa131ba4d012225464df1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 9 Jan 2025 21:44:24 +0800 Subject: [PATCH 0027/1798] Use api in app extensions to call api functions --- Flow.Launcher.Core/Configuration/Portable.cs | 20 +++++++++---------- .../Environments/AbstractPluginEnvironment.cs | 6 +++--- .../Environments/PythonEnvironment.cs | 2 +- .../Environments/TypeScriptEnvironment.cs | 2 +- .../Environments/TypeScriptV2Environment.cs | 2 +- Flow.Launcher.Core/Plugin/PluginManager.cs | 2 +- Flow.Launcher.Core/Plugin/PluginsLoader.cs | 2 +- .../Resource/Internationalization.cs | 2 +- Flow.Launcher.Core/Resource/Theme.cs | 4 ++-- Flow.Launcher.Core/Updater.cs | 10 +++++----- 10 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index d7c73fb46..cb375c586 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -40,7 +40,7 @@ namespace Flow.Launcher.Core.Configuration #endif IndicateDeletion(DataLocation.PortableDataPath); - MessageBoxEx.Show("Flow Launcher needs to restart to finish disabling portable mode, " + + AppExtensions.API.ShowMsgBox("Flow Launcher needs to restart to finish disabling portable mode, " + "after the restart your portable data profile will be deleted and roaming data profile kept"); UpdateManager.RestartApp(Constant.ApplicationFileName); @@ -64,7 +64,7 @@ namespace Flow.Launcher.Core.Configuration #endif IndicateDeletion(DataLocation.RoamingDataPath); - MessageBoxEx.Show("Flow Launcher needs to restart to finish enabling portable mode, " + + AppExtensions.API.ShowMsgBox("Flow Launcher needs to restart to finish enabling portable mode, " + "after the restart your roaming data profile will be deleted and portable data profile kept"); UpdateManager.RestartApp(Constant.ApplicationFileName); @@ -95,13 +95,13 @@ namespace Flow.Launcher.Core.Configuration public void MoveUserDataFolder(string fromLocation, string toLocation) { - FilesFolders.CopyAll(fromLocation, toLocation, MessageBoxEx.Show); + FilesFolders.CopyAll(fromLocation, toLocation, (s) => AppExtensions.API.ShowMsgBox(s)); VerifyUserDataAfterMove(fromLocation, toLocation); } public void VerifyUserDataAfterMove(string fromLocation, string toLocation) { - FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation, MessageBoxEx.Show); + FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation, (s) => AppExtensions.API.ShowMsgBox(s)); } public void CreateShortcuts() @@ -157,13 +157,13 @@ namespace Flow.Launcher.Core.Configuration // delete it and prompt the user to pick the portable data location if (File.Exists(roamingDataDeleteFilePath)) { - FilesFolders.RemoveFolderIfExists(roamingDataDir, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(roamingDataDir, (s) => AppExtensions.API.ShowMsgBox(s)); - if (MessageBoxEx.Show("Flow Launcher has detected you enabled portable mode, " + + if (AppExtensions.API.ShowMsgBox("Flow Launcher has detected you enabled portable mode, " + "would you like to move it to a different location?", string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) { - FilesFolders.OpenPath(Constant.RootDirectory, MessageBoxEx.Show); + FilesFolders.OpenPath(Constant.RootDirectory, (s) => AppExtensions.API.ShowMsgBox(s)); Environment.Exit(0); } @@ -172,9 +172,9 @@ namespace Flow.Launcher.Core.Configuration // delete it and notify the user about it. else if (File.Exists(portableDataDeleteFilePath)) { - FilesFolders.RemoveFolderIfExists(portableDataDir, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(portableDataDir, (s) => AppExtensions.API.ShowMsgBox(s)); - MessageBoxEx.Show("Flow Launcher has detected you disabled portable mode, " + + AppExtensions.API.ShowMsgBox("Flow Launcher has detected you disabled portable mode, " + "the relevant shortcuts and uninstaller entry have been created"); } } @@ -186,7 +186,7 @@ namespace Flow.Launcher.Core.Configuration if (roamingLocationExists && portableLocationExists) { - MessageBoxEx.Show(string.Format("Flow Launcher detected your user data exists both in {0} and " + + AppExtensions.API.ShowMsgBox(string.Format("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.", DataLocation.PortableDataPath, DataLocation.RoamingDataPath, Environment.NewLine)); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs index 6d41e2383..cada05031 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs @@ -57,7 +57,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments EnvName, Environment.NewLine ); - if (MessageBoxEx.Show(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) + if (AppExtensions.API.ShowMsgBox(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) { var msg = string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginChooseRuntimeExecutable"), EnvName); string selectedFile; @@ -82,7 +82,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } else { - MessageBoxEx.Show(string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language)); + AppExtensions.API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language)); Log.Error("PluginsLoader", $"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.", $"{Language}Environment"); @@ -98,7 +98,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments if (expectedPath == currentPath) return; - FilesFolders.RemoveFolderIfExists(installedDirPath, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(installedDirPath, (s) => AppExtensions.API.ShowMsgBox(s)); InstallEnvironment(); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs index 96c29646e..56bc20b4f 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs @@ -28,7 +28,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal override void InstallEnvironment() { - FilesFolders.RemoveFolderIfExists(InstallPath, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(InstallPath, (s) => AppExtensions.API.ShowMsgBox(s)); // Python 3.11.4 is no longer Windows 7 compatible. If user is on Win 7 and // uses Python plugin they need to custom install and use v3.8.9 diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs index 0d6f109e0..1d43b815a 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs @@ -25,7 +25,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal override void InstallEnvironment() { - FilesFolders.RemoveFolderIfExists(InstallPath, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(InstallPath, (s) => AppExtensions.API.ShowMsgBox(s)); DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait(); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs index 582a4407c..49bf4e958 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs @@ -25,7 +25,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal override void InstallEnvironment() { - FilesFolders.RemoveFolderIfExists(InstallPath, MessageBoxEx.Show); + FilesFolders.RemoveFolderIfExists(InstallPath, (s) => AppExtensions.API.ShowMsgBox(s)); DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait(); diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 5c4eaa1da..9e1cf3b9d 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -519,7 +519,7 @@ namespace Flow.Launcher.Core.Plugin var newPluginPath = Path.Combine(installDirectory, folderName); - FilesFolders.CopyAll(pluginFolderPath, newPluginPath, MessageBoxEx.Show); + FilesFolders.CopyAll(pluginFolderPath, newPluginPath, (s) => AppExtensions.API.ShowMsgBox(s)); Directory.Delete(tempFolderPluginPath, true); diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs index 7973c66ba..8cbeb7473 100644 --- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs @@ -119,7 +119,7 @@ namespace Flow.Launcher.Core.Plugin _ = Task.Run(() => { - MessageBoxEx.Show($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + + AppExtensions.API.ShowMsgBox($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + $"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" + $"Please refer to the logs for more information", "", MessageBoxButton.OK, MessageBoxImage.Warning); diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index 1505e84f8..a1cefabe3 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -124,7 +124,7 @@ namespace Flow.Launcher.Core.Resource // "Do you want to search with pinyin?" string text = languageToSet == AvailableLanguages.Chinese ? "是否启用拼音搜索?" : "是否啓用拼音搜索?" ; - if (MessageBoxEx.Show(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) + if (AppExtensions.API.ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) return false; return true; diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index 1d8409306..8622d4caf 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -108,7 +108,7 @@ namespace Flow.Launcher.Core.Resource Log.Error($"|Theme.ChangeTheme|Theme <{theme}> path can't be found"); if (theme != defaultTheme) { - MessageBoxEx.Show(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_path_not_exists"), theme)); + AppExtensions.API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_path_not_exists"), theme)); ChangeTheme(defaultTheme); } return false; @@ -118,7 +118,7 @@ namespace Flow.Launcher.Core.Resource Log.Error($"|Theme.ChangeTheme|Theme <{theme}> fail to parse"); if (theme != defaultTheme) { - MessageBoxEx.Show(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_parse_error"), theme)); + AppExtensions.API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_parse_error"), theme)); ChangeTheme(defaultTheme); } return false; diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index b92d86568..8745d54b7 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -53,7 +53,7 @@ namespace Flow.Launcher.Core if (newReleaseVersion <= currentVersion) { if (!silentUpdate) - MessageBoxEx.Show(api.GetTranslation("update_flowlauncher_already_on_latest")); + AppExtensions.API.ShowMsgBox(api.GetTranslation("update_flowlauncher_already_on_latest")); return; } @@ -68,9 +68,9 @@ namespace Flow.Launcher.Core if (DataLocation.PortableDataLocationInUse()) { var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}"; - FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination, MessageBoxEx.Show); - if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination, MessageBoxEx.Show)) - MessageBoxEx.Show(string.Format(api.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"), + FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination, (s) => AppExtensions.API.ShowMsgBox(s)); + if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination, (s) => AppExtensions.API.ShowMsgBox(s))) + AppExtensions.API.ShowMsgBox(string.Format(api.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"), DataLocation.PortableDataPath, targetDestination)); } @@ -83,7 +83,7 @@ namespace Flow.Launcher.Core Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); - if (MessageBoxEx.Show(newVersionTips, api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) + if (AppExtensions.API.ShowMsgBox(newVersionTips, api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) { UpdateManager.RestartApp(Constant.ApplicationFileName); } From 2716c40c0bd7229fed198d3ba75fd27fb0816084 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 9 Jan 2025 21:50:07 +0800 Subject: [PATCH 0028/1798] Move MessageBoxEx to main project for better development experience --- {Flow.Launcher.Core => Flow.Launcher}/MessageBoxEx.xaml | 4 ++-- {Flow.Launcher.Core => Flow.Launcher}/MessageBoxEx.xaml.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename {Flow.Launcher.Core => Flow.Launcher}/MessageBoxEx.xaml (98%) rename {Flow.Launcher.Core => Flow.Launcher}/MessageBoxEx.xaml.cs (99%) diff --git a/Flow.Launcher.Core/MessageBoxEx.xaml b/Flow.Launcher/MessageBoxEx.xaml similarity index 98% rename from Flow.Launcher.Core/MessageBoxEx.xaml rename to Flow.Launcher/MessageBoxEx.xaml index fff107a68..be12ca16c 100644 --- a/Flow.Launcher.Core/MessageBoxEx.xaml +++ b/Flow.Launcher/MessageBoxEx.xaml @@ -1,9 +1,9 @@  Date: Thu, 9 Jan 2025 12:48:43 -0600 Subject: [PATCH 0029/1798] resolve link before using File.Replace --- .../Storage/JsonStorage.cs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs index 642250627..33bc1ff6c 100644 --- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs @@ -31,11 +31,12 @@ namespace Flow.Launcher.Infrastructure.Storage protected JsonStorage() { } + public JsonStorage(string filePath) { FilePath = filePath; DirectoryPath = Path.GetDirectoryName(filePath) ?? throw new ArgumentException("Invalid file path"); - + Helper.ValidateDirectory(DirectoryPath); } @@ -97,6 +98,7 @@ namespace Flow.Launcher.Infrastructure.Storage return default; } } + private void RestoreBackup() { Log.Info($"|JsonStorage.Load|Failed to load settings.json, {BackupFilePath} restored successfully"); @@ -179,25 +181,21 @@ namespace Flow.Launcher.Infrastructure.Storage public void Save() { string serialized = JsonSerializer.Serialize(Data, - new JsonSerializerOptions - { - WriteIndented = true - }); + new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(TempFilePath, serialized); AtomicWriteSetting(); } + public async Task SaveAsync() { var tempOutput = File.OpenWrite(TempFilePath); await JsonSerializer.SerializeAsync(tempOutput, Data, - new JsonSerializerOptions - { - WriteIndented = true - }); + new JsonSerializerOptions { WriteIndented = true }); AtomicWriteSetting(); } + private void AtomicWriteSetting() { if (!File.Exists(FilePath)) @@ -206,9 +204,9 @@ namespace Flow.Launcher.Infrastructure.Storage } else { - File.Replace(TempFilePath, FilePath, BackupFilePath); + var finalFilePath = new FileInfo(FilePath).LinkTarget ?? FilePath; + File.Replace(TempFilePath, finalFilePath, BackupFilePath); } } - } } From 4b38e0e714abf705e8f337dbcb26f29893105c7e Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Fri, 10 Jan 2025 13:11:35 -0600 Subject: [PATCH 0030/1798] properly dispose the filestream --- Flow.Launcher.Infrastructure/Storage/JsonStorage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs index 33bc1ff6c..507838d94 100644 --- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs @@ -190,7 +190,7 @@ namespace Flow.Launcher.Infrastructure.Storage public async Task SaveAsync() { - var tempOutput = File.OpenWrite(TempFilePath); + await using var tempOutput = File.OpenWrite(TempFilePath); await JsonSerializer.SerializeAsync(tempOutput, Data, new JsonSerializerOptions { WriteIndented = true }); AtomicWriteSetting(); From 2a1d502affe50f43aafd38e7ee3ff5435993cbef Mon Sep 17 00:00:00 2001 From: Hongtao Zhang Date: Fri, 10 Jan 2025 13:18:14 -0600 Subject: [PATCH 0031/1798] fix build error --- Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs index ae4fd639d..f95266c7f 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs @@ -138,7 +138,7 @@ namespace Flow.Launcher.Core.Plugin SetupJsonRPC(); try { - await RPC.InvokeAsync("reload", context); + await RPC.InvokeAsync("reload", Context); } catch (RemoteMethodNotFoundException e) { From 32cac76c827681b436bd8bdc8de03e608181260c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 12 Jan 2025 18:44:52 +0800 Subject: [PATCH 0032/1798] Improve Settings management --- .../UserSettings/Settings.cs | 16 ++++++++++++++-- Flow.Launcher/App.xaml.cs | 8 ++++++-- .../ViewModel/SettingWindowViewModel.cs | 13 +++---------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 0bcc9368d..3e43e3d32 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -1,10 +1,10 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Drawing; using System.Text.Json.Serialization; using System.Windows; using Flow.Launcher.Infrastructure.Hotkey; +using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher.ViewModel; @@ -13,6 +13,18 @@ namespace Flow.Launcher.Infrastructure.UserSettings { public class Settings : BaseModel, IHotkeySettings { + private FlowLauncherJsonStorage _storage; + + public void Initialize(FlowLauncherJsonStorage storage) + { + _storage = storage; + } + + public void Save() + { + _storage.Save(); + } + private string language = "en"; private string _theme = Constant.DefaultTheme; public string Hotkey { get; set; } = $"{KeyConstant.Alt} + {KeyConstant.Space}"; diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 58da35e85..9d7a0671e 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -14,6 +14,7 @@ using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Image; using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; @@ -52,6 +53,10 @@ namespace Flow.Launcher { await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () => { + var storage = new FlowLauncherJsonStorage(); + _settings = storage.Load(); + _settings.Initialize(storage); + _portable.PreStartCleanUpAfterPortabilityUpdate(); Log.Info( @@ -62,8 +67,7 @@ namespace Flow.Launcher var imageLoadertask = ImageLoader.InitializeAsync(); - _settingsVM = new SettingWindowViewModel(_updater, _portable); - _settings = _settingsVM.Settings; + _settingsVM = new SettingWindowViewModel(_settings, _updater, _portable); _settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled(); AbstractPluginEnvironment.PreStartPluginExecutablePathUpdate(_settings); diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index 04dd6312b..95a1eb675 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -1,6 +1,5 @@ using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; -using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; @@ -8,21 +7,17 @@ namespace Flow.Launcher.ViewModel; public class SettingWindowViewModel : BaseModel { - private readonly FlowLauncherJsonStorage _storage; - public Updater Updater { get; } public IPortable Portable { get; } public Settings Settings { get; } - public SettingWindowViewModel(Updater updater, IPortable portable) + public SettingWindowViewModel(Settings settings, Updater updater, IPortable portable) { - _storage = new FlowLauncherJsonStorage(); - + Settings = settings; Updater = updater; Portable = portable; - Settings = _storage.Load(); } public async void UpdateApp() @@ -30,14 +25,12 @@ public class SettingWindowViewModel : BaseModel await Updater.UpdateAppAsync(App.API, false); } - - /// /// Save Flow settings. Plugins settings are not included. /// public void Save() { - _storage.Save(); + Settings.Save(); } public double SettingWindowWidth From 1b76a2bc1a1c3356b3bab5c3be61b3427b1de7fd Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 12 Jan 2025 19:45:36 +0800 Subject: [PATCH 0033/1798] Use dependency injection for all services --- .../Flow.Launcher.Infrastructure.csproj | 1 + .../PinyinAlphabet.cs | 8 ++- Flow.Launcher.Infrastructure/StringMatcher.cs | 5 +- Flow.Launcher/App.xaml.cs | 61 +++++++++++-------- Flow.Launcher/Flow.Launcher.csproj | 5 +- Flow.Launcher/PublicAPIInstance.cs | 12 ++-- Flow.Launcher/ViewModel/MainViewModel.cs | 5 +- .../ViewModel/SettingWindowViewModel.cs | 11 ++-- 8 files changed, 65 insertions(+), 43 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index 1475252ca..84b603161 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -54,6 +54,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index 7d7235968..8eaa757be 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -6,6 +6,7 @@ using System.Text; using JetBrains.Annotations; using Flow.Launcher.Infrastructure.UserSettings; using ToolGood.Words.Pinyin; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Infrastructure { @@ -129,7 +130,12 @@ namespace Flow.Launcher.Infrastructure private Settings _settings; - public void Initialize([NotNull] Settings settings) + public PinyinAlphabet() + { + Initialize(Ioc.Default.GetRequiredService()); + } + + private void Initialize([NotNull] Settings settings) { _settings = settings ?? throw new ArgumentNullException(nameof(settings)); } diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs index bd5dbdda9..7134fc760 100644 --- a/Flow.Launcher.Infrastructure/StringMatcher.cs +++ b/Flow.Launcher.Infrastructure/StringMatcher.cs @@ -1,4 +1,5 @@ -using Flow.Launcher.Plugin.SharedModels; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin.SharedModels; using System; using System.Collections.Generic; using System.Linq; @@ -15,7 +16,7 @@ namespace Flow.Launcher.Infrastructure public StringMatcher(IAlphabet alphabet = null) { - _alphabet = alphabet; + _alphabet = Ioc.Default.GetRequiredService(); } public static StringMatcher Instance { get; internal set; } diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 9d7a0671e..8cd054148 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; using Flow.Launcher.Core.ExternalPlugins.Environments; @@ -18,23 +19,18 @@ using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher { - public partial class App : IDisposable, ISingleInstanceApp, IApp + public partial class App : IDisposable, ISingleInstanceApp { - public IPublicAPI PublicAPI => API; public static PublicAPIInstance API { get; private set; } private const string Unique = "Flow.Launcher_Unique_Application_Mutex"; private static bool _disposed; private Settings _settings; - private MainViewModel _mainVM; - private SettingWindowViewModel _settingsVM; - private readonly Updater _updater = new Updater(Flow.Launcher.Properties.Settings.Default.GithubRepo); - private readonly Portable _portable = new Portable(); - private readonly PinyinAlphabet _alphabet = new PinyinAlphabet(); - private StringMatcher _stringMatcher; [STAThread] public static void Main() @@ -53,37 +49,51 @@ namespace Flow.Launcher { await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () => { + // Initialize settings var storage = new FlowLauncherJsonStorage(); _settings = storage.Load(); _settings.Initialize(storage); + _settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled(); - _portable.PreStartCleanUpAfterPortabilityUpdate(); + // Configure the dependency injection container + var host = Host.CreateDefaultBuilder() + .UseContentRoot(AppContext.BaseDirectory) + .ConfigureServices(services => services + .AddSingleton(_ => _settings) + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + ).Build(); + Ioc.Default.ConfigureServices(host.Services); - Log.Info( - "|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------"); + Ioc.Default.GetRequiredService().Initialize(Launcher.Properties.Settings.Default.GithubRepo); + + Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate(); + + Log.Info("|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------"); Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}"); + RegisterAppDomainExceptions(); RegisterDispatcherUnhandledException(); var imageLoadertask = ImageLoader.InitializeAsync(); - _settingsVM = new SettingWindowViewModel(_settings, _updater, _portable); - _settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled(); - AbstractPluginEnvironment.PreStartPluginExecutablePathUpdate(_settings); - _alphabet.Initialize(_settings); - _stringMatcher = new StringMatcher(_alphabet); - StringMatcher.Instance = _stringMatcher; - _stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision; + var stringMatcher = Ioc.Default.GetRequiredService(); + StringMatcher.Instance = stringMatcher; + stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision; InternationalizationManager.Instance.Settings = _settings; InternationalizationManager.Instance.ChangeLanguage(_settings.Language); PluginManager.LoadPlugins(_settings.PluginSettings); - _mainVM = new MainViewModel(_settings); - API = new PublicAPIInstance(_settingsVM, _mainVM, _alphabet); + API = Ioc.Default.GetRequiredService() as PublicAPIInstance; Http.API = API; Http.Proxy = _settings.Proxy; @@ -91,14 +101,15 @@ namespace Flow.Launcher await PluginManager.InitializePluginsAsync(API); await imageLoadertask; - var window = new MainWindow(_settings, _mainVM); + var mainVM = Ioc.Default.GetRequiredService(); + var window = new MainWindow(_settings, mainVM); Log.Info($"|App.OnStartup|Dependencies Info:{ErrorReporting.DependenciesInfo()}"); Current.MainWindow = window; Current.MainWindow.Title = Constant.FlowLauncher; - HotKeyMapper.Initialize(_mainVM); + HotKeyMapper.Initialize(mainVM); // main windows needs initialized before theme change because of blur settings ThemeManager.Instance.Settings = _settings; @@ -147,11 +158,11 @@ namespace Flow.Launcher { // check update every 5 hours var timer = new PeriodicTimer(TimeSpan.FromHours(5)); - await _updater.UpdateAppAsync(API); + await Ioc.Default.GetRequiredService().UpdateAppAsync(API); while (await timer.WaitForNextTickAsync()) // check updates on startup - await _updater.UpdateAppAsync(API); + await Ioc.Default.GetRequiredService().UpdateAppAsync(API); } }); } @@ -194,7 +205,7 @@ namespace Flow.Launcher public void OnSecondAppStarted() { - _mainVM.Show(); + Ioc.Default.GetRequiredService().Show(); } } } diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 4ec249c2b..cab3915d5 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -1,4 +1,4 @@ - + WinExe @@ -83,12 +83,13 @@ - all runtime; build; native; contentfiles; analyzers; buildtransitive + + all diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index f0295cf24..50765294c 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -25,7 +25,7 @@ using Flow.Launcher.Infrastructure.Storage; using System.Collections.Concurrent; using System.Diagnostics; using System.Collections.Specialized; -using Flow.Launcher.Core; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher { @@ -33,15 +33,15 @@ namespace Flow.Launcher { private readonly SettingWindowViewModel _settingsVM; private readonly MainViewModel _mainVM; - private readonly PinyinAlphabet _alphabet; + private readonly IAlphabet _alphabet; #region Constructor - public PublicAPIInstance(SettingWindowViewModel settingsVM, MainViewModel mainVM, PinyinAlphabet alphabet) + public PublicAPIInstance() { - _settingsVM = settingsVM; - _mainVM = mainVM; - _alphabet = alphabet; + _settingsVM = Ioc.Default.GetRequiredService(); + _mainVM = Ioc.Default.GetRequiredService(); + _alphabet = Ioc.Default.GetRequiredService(); GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback; WebRequest.RegisterPrefix("data", new DataWebRequestFactory()); } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 55bc8d1b3..f5141a8fa 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -25,6 +25,7 @@ using System.Windows.Input; using System.ComponentModel; using Flow.Launcher.Infrastructure.Image; using System.Windows.Media; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.ViewModel { @@ -58,13 +59,13 @@ namespace Flow.Launcher.ViewModel #region Constructor - public MainViewModel(Settings settings) + public MainViewModel() { _queryTextBeforeLeaveResults = ""; _queryText = ""; _lastQuery = new Query(); - Settings = settings; + Settings = Ioc.Default.GetRequiredService(); Settings.PropertyChanged += (_, args) => { switch (args.PropertyName) diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index 95a1eb675..7549db1a3 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -1,4 +1,5 @@ -using Flow.Launcher.Core; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; @@ -13,11 +14,11 @@ public class SettingWindowViewModel : BaseModel public Settings Settings { get; } - public SettingWindowViewModel(Settings settings, Updater updater, IPortable portable) + public SettingWindowViewModel() { - Settings = settings; - Updater = updater; - Portable = portable; + Settings = Ioc.Default.GetRequiredService(); + Updater = Ioc.Default.GetRequiredService(); + Portable = Ioc.Default.GetRequiredService(); } public async void UpdateApp() From a748141b1e8d7342336068ef65cc0890eac63992 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 12 Jan 2025 19:47:49 +0800 Subject: [PATCH 0034/1798] Use IPublicAPI instead --- Flow.Launcher/App.xaml.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 8cd054148..9b86c6cc4 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -27,7 +27,7 @@ namespace Flow.Launcher { public partial class App : IDisposable, ISingleInstanceApp { - public static PublicAPIInstance API { get; private set; } + public static IPublicAPI API { get; private set; } private const string Unique = "Flow.Launcher_Unique_Application_Mutex"; private static bool _disposed; private Settings _settings; @@ -93,7 +93,7 @@ namespace Flow.Launcher PluginManager.LoadPlugins(_settings.PluginSettings); - API = Ioc.Default.GetRequiredService() as PublicAPIInstance; + API = Ioc.Default.GetRequiredService(); Http.API = API; Http.Proxy = _settings.Proxy; From 3cb9d1dce4b606cc80fb3a7fc9e51da08237c1b8 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 12 Jan 2025 20:04:44 +0800 Subject: [PATCH 0035/1798] Remove IApp & AppExtensions and use dependency injection instead --- Flow.Launcher.Core/AppExtensions.cs | 15 ------------ Flow.Launcher.Core/Configuration/Portable.cs | 24 +++++++++++-------- .../Environments/AbstractPluginEnvironment.cs | 11 +++++---- .../Environments/PythonEnvironment.cs | 2 +- .../Environments/TypeScriptEnvironment.cs | 2 +- .../Environments/TypeScriptV2Environment.cs | 2 +- Flow.Launcher.Core/IApp.cs | 13 ---------- Flow.Launcher.Core/Plugin/PluginManager.cs | 2 +- Flow.Launcher.Core/Plugin/PluginsLoader.cs | 3 ++- .../Resource/Internationalization.cs | 3 ++- Flow.Launcher.Core/Resource/Theme.cs | 7 ++++-- Flow.Launcher.Core/Updater.cs | 17 +++++++------ Flow.Launcher/App.xaml.cs | 2 ++ .../ViewModel/SettingWindowViewModel.cs | 10 ++++++-- 14 files changed, 54 insertions(+), 59 deletions(-) delete mode 100644 Flow.Launcher.Core/AppExtensions.cs delete mode 100644 Flow.Launcher.Core/IApp.cs diff --git a/Flow.Launcher.Core/AppExtensions.cs b/Flow.Launcher.Core/AppExtensions.cs deleted file mode 100644 index b02612d72..000000000 --- a/Flow.Launcher.Core/AppExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Windows; -using Flow.Launcher.Plugin; - -namespace Flow.Launcher.Core; - -/// -/// Extension properties and functions of the current application singleton object. -/// -public static class AppExtensions -{ - /// - /// Gets the public API of the current application singleton object. - /// - public static IPublicAPI API => (Application.Current as IApp)!.PublicAPI; -} diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index cb375c586..069154364 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -9,11 +9,15 @@ using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.SharedCommands; using System.Linq; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Configuration { public class Portable : IPortable { + private readonly IPublicAPI API = Ioc.Default.GetRequiredService(); + /// /// As at Squirrel.Windows version 1.5.2, UpdateManager needs to be disposed after finish /// @@ -40,7 +44,7 @@ namespace Flow.Launcher.Core.Configuration #endif IndicateDeletion(DataLocation.PortableDataPath); - AppExtensions.API.ShowMsgBox("Flow Launcher needs to restart to finish disabling portable mode, " + + API.ShowMsgBox("Flow Launcher needs to restart to finish disabling portable mode, " + "after the restart your portable data profile will be deleted and roaming data profile kept"); UpdateManager.RestartApp(Constant.ApplicationFileName); @@ -64,7 +68,7 @@ namespace Flow.Launcher.Core.Configuration #endif IndicateDeletion(DataLocation.RoamingDataPath); - AppExtensions.API.ShowMsgBox("Flow Launcher needs to restart to finish enabling portable mode, " + + API.ShowMsgBox("Flow Launcher needs to restart to finish enabling portable mode, " + "after the restart your roaming data profile will be deleted and portable data profile kept"); UpdateManager.RestartApp(Constant.ApplicationFileName); @@ -95,13 +99,13 @@ namespace Flow.Launcher.Core.Configuration public void MoveUserDataFolder(string fromLocation, string toLocation) { - FilesFolders.CopyAll(fromLocation, toLocation, (s) => AppExtensions.API.ShowMsgBox(s)); + FilesFolders.CopyAll(fromLocation, toLocation, (s) => API.ShowMsgBox(s)); VerifyUserDataAfterMove(fromLocation, toLocation); } public void VerifyUserDataAfterMove(string fromLocation, string toLocation) { - FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation, (s) => AppExtensions.API.ShowMsgBox(s)); + FilesFolders.VerifyBothFolderFilesEqual(fromLocation, toLocation, (s) => API.ShowMsgBox(s)); } public void CreateShortcuts() @@ -157,13 +161,13 @@ 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) => AppExtensions.API.ShowMsgBox(s)); + FilesFolders.RemoveFolderIfExists(roamingDataDir, (s) => API.ShowMsgBox(s)); - if (AppExtensions.API.ShowMsgBox("Flow Launcher has detected you enabled portable mode, " + + if (API.ShowMsgBox("Flow Launcher has detected you enabled portable mode, " + "would you like to move it to a different location?", string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) { - FilesFolders.OpenPath(Constant.RootDirectory, (s) => AppExtensions.API.ShowMsgBox(s)); + FilesFolders.OpenPath(Constant.RootDirectory, (s) => API.ShowMsgBox(s)); Environment.Exit(0); } @@ -172,9 +176,9 @@ namespace Flow.Launcher.Core.Configuration // delete it and notify the user about it. else if (File.Exists(portableDataDeleteFilePath)) { - FilesFolders.RemoveFolderIfExists(portableDataDir, (s) => AppExtensions.API.ShowMsgBox(s)); + FilesFolders.RemoveFolderIfExists(portableDataDir, (s) => API.ShowMsgBox(s)); - AppExtensions.API.ShowMsgBox("Flow Launcher has detected you disabled portable mode, " + + API.ShowMsgBox("Flow Launcher has detected you disabled portable mode, " + "the relevant shortcuts and uninstaller entry have been created"); } } @@ -186,7 +190,7 @@ namespace Flow.Launcher.Core.Configuration if (roamingLocationExists && portableLocationExists) { - AppExtensions.API.ShowMsgBox(string.Format("Flow Launcher detected your user data exists both in {0} and " + + API.ShowMsgBox(string.Format("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.", DataLocation.PortableDataPath, DataLocation.RoamingDataPath, Environment.NewLine)); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs index cada05031..451df6147 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs @@ -8,11 +8,14 @@ using System.Linq; using System.Windows; using System.Windows.Forms; using Flow.Launcher.Core.Resource; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Core.ExternalPlugins.Environments { public abstract class AbstractPluginEnvironment { + protected readonly IPublicAPI API = Ioc.Default.GetRequiredService(); + internal abstract string Language { get; } internal abstract string EnvName { get; } @@ -25,7 +28,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal virtual string FileDialogFilter => string.Empty; - internal abstract string PluginsSettingsFilePath { get; set; } + internal abstract string PluginsSettingsFilePath { get; set; } internal List PluginMetadataList; @@ -57,7 +60,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments EnvName, Environment.NewLine ); - if (AppExtensions.API.ShowMsgBox(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) + if (API.ShowMsgBox(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) { var msg = string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginChooseRuntimeExecutable"), EnvName); string selectedFile; @@ -82,7 +85,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } else { - AppExtensions.API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language)); + API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language)); Log.Error("PluginsLoader", $"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.", $"{Language}Environment"); @@ -98,7 +101,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments if (expectedPath == currentPath) return; - FilesFolders.RemoveFolderIfExists(installedDirPath, (s) => AppExtensions.API.ShowMsgBox(s)); + FilesFolders.RemoveFolderIfExists(installedDirPath, (s) => API.ShowMsgBox(s)); InstallEnvironment(); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs index 56bc20b4f..607c19062 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs @@ -28,7 +28,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal override void InstallEnvironment() { - FilesFolders.RemoveFolderIfExists(InstallPath, (s) => AppExtensions.API.ShowMsgBox(s)); + FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s)); // Python 3.11.4 is no longer Windows 7 compatible. If user is on Win 7 and // uses Python plugin they need to custom install and use v3.8.9 diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs index 1d43b815a..399f7cc03 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs @@ -25,7 +25,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal override void InstallEnvironment() { - FilesFolders.RemoveFolderIfExists(InstallPath, (s) => AppExtensions.API.ShowMsgBox(s)); + FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s)); DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait(); diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs index 49bf4e958..e8cb72e11 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs @@ -25,7 +25,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal override void InstallEnvironment() { - FilesFolders.RemoveFolderIfExists(InstallPath, (s) => AppExtensions.API.ShowMsgBox(s)); + FilesFolders.RemoveFolderIfExists(InstallPath, (s) => API.ShowMsgBox(s)); DroplexPackage.Drop(App.nodejs_16_18_0, InstallPath).Wait(); diff --git a/Flow.Launcher.Core/IApp.cs b/Flow.Launcher.Core/IApp.cs deleted file mode 100644 index 233fd5ed1..000000000 --- a/Flow.Launcher.Core/IApp.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Flow.Launcher.Plugin; - -namespace Flow.Launcher.Core -{ - /// - /// Interface for the current application singleton object exposing the properties - /// and functions that can be accessed from anywhere in the application. - /// - public interface IApp - { - public IPublicAPI PublicAPI { get; } - } -} diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 9e1cf3b9d..a776c10ab 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -519,7 +519,7 @@ namespace Flow.Launcher.Core.Plugin var newPluginPath = Path.Combine(installDirectory, folderName); - FilesFolders.CopyAll(pluginFolderPath, newPluginPath, (s) => AppExtensions.API.ShowMsgBox(s)); + FilesFolders.CopyAll(pluginFolderPath, newPluginPath, (s) => API.ShowMsgBox(s)); Directory.Delete(tempFolderPluginPath, true); diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs index 8cbeb7473..4827cf69d 100644 --- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs @@ -4,6 +4,7 @@ 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; @@ -119,7 +120,7 @@ namespace Flow.Launcher.Core.Plugin _ = Task.Run(() => { - AppExtensions.API.ShowMsgBox($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + + Ioc.Default.GetRequiredService().ShowMsgBox($"{errorMessage}{Environment.NewLine}{Environment.NewLine}" + $"{errorPluginString}{Environment.NewLine}{Environment.NewLine}" + $"Please refer to the logs for more information", "", MessageBoxButton.OK, MessageBoxImage.Warning); diff --git a/Flow.Launcher.Core/Resource/Internationalization.cs b/Flow.Launcher.Core/Resource/Internationalization.cs index a1cefabe3..de066dda1 100644 --- a/Flow.Launcher.Core/Resource/Internationalization.cs +++ b/Flow.Launcher.Core/Resource/Internationalization.cs @@ -11,6 +11,7 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using System.Globalization; using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Core.Resource { @@ -124,7 +125,7 @@ namespace Flow.Launcher.Core.Resource // "Do you want to search with pinyin?" string text = languageToSet == AvailableLanguages.Chinese ? "是否启用拼音搜索?" : "是否啓用拼音搜索?" ; - if (AppExtensions.API.ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) + if (Ioc.Default.GetRequiredService().ShowMsgBox(text, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) return false; return true; diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index 8622d4caf..2749da532 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -11,6 +11,8 @@ using System.Windows.Media.Effects; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Resource { @@ -22,6 +24,7 @@ namespace Flow.Launcher.Core.Resource private const int ShadowExtraMargin = 32; + private readonly IPublicAPI API = Ioc.Default.GetRequiredService(); private readonly List _themeDirectories = new List(); private ResourceDictionary _oldResource; private string _oldTheme; @@ -108,7 +111,7 @@ namespace Flow.Launcher.Core.Resource Log.Error($"|Theme.ChangeTheme|Theme <{theme}> path can't be found"); if (theme != defaultTheme) { - AppExtensions.API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_path_not_exists"), theme)); + API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_path_not_exists"), theme)); ChangeTheme(defaultTheme); } return false; @@ -118,7 +121,7 @@ namespace Flow.Launcher.Core.Resource Log.Error($"|Theme.ChangeTheme|Theme <{theme}> fail to parse"); if (theme != defaultTheme) { - AppExtensions.API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_parse_error"), theme)); + API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("theme_load_failure_parse_error"), theme)); ChangeTheme(defaultTheme); } return false; diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 8745d54b7..373418055 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -17,14 +17,17 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using System.Text.Json.Serialization; using System.Threading; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Core { public class Updater { - public string GitHubRepository { get; } + private readonly IPublicAPI API = Ioc.Default.GetRequiredService(); - public Updater(string gitHubRepository) + public string GitHubRepository { get; set; } + + public void Initialize(string gitHubRepository) { GitHubRepository = gitHubRepository; } @@ -53,7 +56,7 @@ namespace Flow.Launcher.Core if (newReleaseVersion <= currentVersion) { if (!silentUpdate) - AppExtensions.API.ShowMsgBox(api.GetTranslation("update_flowlauncher_already_on_latest")); + API.ShowMsgBox(api.GetTranslation("update_flowlauncher_already_on_latest")); return; } @@ -68,9 +71,9 @@ namespace Flow.Launcher.Core if (DataLocation.PortableDataLocationInUse()) { var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}"; - FilesFolders.CopyAll(DataLocation.PortableDataPath, targetDestination, (s) => AppExtensions.API.ShowMsgBox(s)); - if (!FilesFolders.VerifyBothFolderFilesEqual(DataLocation.PortableDataPath, targetDestination, (s) => AppExtensions.API.ShowMsgBox(s))) - AppExtensions.API.ShowMsgBox(string.Format(api.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"), + 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)); } @@ -83,7 +86,7 @@ namespace Flow.Launcher.Core Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); - if (AppExtensions.API.ShowMsgBox(newVersionTips, api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) + if (API.ShowMsgBox(newVersionTips, api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) { UpdateManager.RestartApp(Constant.ApplicationFileName); } diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 9b86c6cc4..0d6d9855c 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -74,6 +74,8 @@ namespace Flow.Launcher Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate(); + Ioc.Default.GetRequiredService().Initialize(); + Log.Info("|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------"); Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}"); diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index 7549db1a3..bbd47e731 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -8,15 +8,21 @@ namespace Flow.Launcher.ViewModel; public class SettingWindowViewModel : BaseModel { - public Updater Updater { get; } + public Updater Updater { get; private set; } - public IPortable Portable { get; } + public IPortable Portable { get; private set; } public Settings Settings { get; } public SettingWindowViewModel() { Settings = Ioc.Default.GetRequiredService(); + } + + public void Initialize() + { + // We don not initialize Updater and Portable in the constructor because we want to avoid + // recrusive dependency injection Updater = Ioc.Default.GetRequiredService(); Portable = Ioc.Default.GetRequiredService(); } From 2a423f09bb3fe6c3dfb6dd9f03cce4ce410c5936 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 13 Jan 2025 09:36:14 +0800 Subject: [PATCH 0036/1798] Improve code quality --- Flow.Launcher.Infrastructure/StringMatcher.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs index 7134fc760..b3a265e29 100644 --- a/Flow.Launcher.Infrastructure/StringMatcher.cs +++ b/Flow.Launcher.Infrastructure/StringMatcher.cs @@ -8,13 +8,13 @@ namespace Flow.Launcher.Infrastructure { public class StringMatcher { - private readonly MatchOption _defaultMatchOption = new MatchOption(); + private readonly MatchOption _defaultMatchOption = new(); public SearchPrecisionScore UserSettingSearchPrecision { get; set; } private readonly IAlphabet _alphabet; - public StringMatcher(IAlphabet alphabet = null) + public StringMatcher() { _alphabet = Ioc.Default.GetRequiredService(); } @@ -242,16 +242,16 @@ namespace Flow.Launcher.Infrastructure return false; } - private bool IsAcronymChar(string stringToCompare, int compareStringIndex) + private static bool IsAcronymChar(string stringToCompare, int compareStringIndex) => char.IsUpper(stringToCompare[compareStringIndex]) || compareStringIndex == 0 || // 0 index means char is the start of the compare string, which is an acronym char.IsWhiteSpace(stringToCompare[compareStringIndex - 1]); - private bool IsAcronymNumber(string stringToCompare, int compareStringIndex) + private static bool IsAcronymNumber(string stringToCompare, int compareStringIndex) => stringToCompare[compareStringIndex] >= 0 && stringToCompare[compareStringIndex] <= 9; // To get the index of the closest space which preceeds the first matching index - private int CalculateClosestSpaceIndex(List spaceIndices, int firstMatchIndex) + private static int CalculateClosestSpaceIndex(List spaceIndices, int firstMatchIndex) { var closestSpaceIndex = -1; From ff110b3c49ec139da1222e3ffcb210596eb4642e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 13 Jan 2025 10:01:50 +0800 Subject: [PATCH 0037/1798] Fix test project build issue --- Flow.Launcher.Infrastructure/StringMatcher.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs index b3a265e29..5822057a2 100644 --- a/Flow.Launcher.Infrastructure/StringMatcher.cs +++ b/Flow.Launcher.Infrastructure/StringMatcher.cs @@ -14,9 +14,9 @@ namespace Flow.Launcher.Infrastructure private readonly IAlphabet _alphabet; - public StringMatcher() + public StringMatcher(IAlphabet alphabet = null) { - _alphabet = Ioc.Default.GetRequiredService(); + _alphabet = alphabet ?? Ioc.Default.GetRequiredService(); } public static StringMatcher Instance { get; internal set; } From c3f71c213e8b24870292f4489515558850c9c5b7 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 13 Jan 2025 10:18:35 +0800 Subject: [PATCH 0038/1798] Revert "Fix test project build issue" This reverts commit ff110b3c49ec139da1222e3ffcb210596eb4642e. --- Flow.Launcher.Infrastructure/StringMatcher.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs index 5822057a2..b3a265e29 100644 --- a/Flow.Launcher.Infrastructure/StringMatcher.cs +++ b/Flow.Launcher.Infrastructure/StringMatcher.cs @@ -14,9 +14,9 @@ namespace Flow.Launcher.Infrastructure private readonly IAlphabet _alphabet; - public StringMatcher(IAlphabet alphabet = null) + public StringMatcher() { - _alphabet = alphabet ?? Ioc.Default.GetRequiredService(); + _alphabet = Ioc.Default.GetRequiredService(); } public static StringMatcher Instance { get; internal set; } From 3bebb690935e4b99a508f5a9e98593760f45360c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 13 Jan 2025 10:21:14 +0800 Subject: [PATCH 0039/1798] Fix unitest build issue --- Flow.Launcher.Infrastructure/StringMatcher.cs | 6 +++++ Flow.Launcher.Test/FuzzyMatcherTest.cs | 22 ++++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Flow.Launcher.Infrastructure/StringMatcher.cs b/Flow.Launcher.Infrastructure/StringMatcher.cs index b3a265e29..f5f02cbfc 100644 --- a/Flow.Launcher.Infrastructure/StringMatcher.cs +++ b/Flow.Launcher.Infrastructure/StringMatcher.cs @@ -19,6 +19,12 @@ namespace Flow.Launcher.Infrastructure _alphabet = Ioc.Default.GetRequiredService(); } + // This is a workaround to allow unit tests to set the instance + public StringMatcher(IAlphabet alphabet) + { + _alphabet = alphabet; + } + public static StringMatcher Instance { get; internal set; } public static MatchResult FuzzySearch(string query, string stringToCompare) diff --git a/Flow.Launcher.Test/FuzzyMatcherTest.cs b/Flow.Launcher.Test/FuzzyMatcherTest.cs index d7f143218..d97ce227c 100644 --- a/Flow.Launcher.Test/FuzzyMatcherTest.cs +++ b/Flow.Launcher.Test/FuzzyMatcherTest.cs @@ -21,6 +21,8 @@ namespace Flow.Launcher.Test private const string MicrosoftSqlServerManagementStudio = "Microsoft SQL Server Management Studio"; private const string VisualStudioCode = "Visual Studio Code"; + private readonly IAlphabet alphabet = null; + public List GetSearchStrings() => new List { @@ -59,7 +61,7 @@ namespace Flow.Launcher.Test }; var results = new List(); - var matcher = new StringMatcher(); + var matcher = new StringMatcher(alphabet); foreach (var str in sources) { results.Add(new Result @@ -81,7 +83,7 @@ namespace Flow.Launcher.Test public void WhenNotAllCharactersFoundInSearchString_ThenShouldReturnZeroScore(string searchString) { var compareString = "Can have rum only in my glass"; - var matcher = new StringMatcher(); + var matcher = new StringMatcher(alphabet); var scoreResult = matcher.FuzzyMatch(searchString, compareString).RawScore; Assert.True(scoreResult == 0); @@ -97,7 +99,7 @@ namespace Flow.Launcher.Test string searchTerm) { var results = new List(); - var matcher = new StringMatcher(); + var matcher = new StringMatcher(alphabet); foreach (var str in GetSearchStrings()) { results.Add(new Result @@ -147,7 +149,7 @@ namespace Flow.Launcher.Test string queryString, string compareString, int expectedScore) { // When, Given - var matcher = new StringMatcher {UserSettingSearchPrecision = SearchPrecisionScore.Regular}; + var matcher = new StringMatcher(alphabet) {UserSettingSearchPrecision = SearchPrecisionScore.Regular}; var rawScore = matcher.FuzzyMatch(queryString, compareString).RawScore; // Should @@ -181,7 +183,7 @@ namespace Flow.Launcher.Test bool expectedPrecisionResult) { // When - var matcher = new StringMatcher {UserSettingSearchPrecision = expectedPrecisionScore}; + var matcher = new StringMatcher(alphabet) {UserSettingSearchPrecision = expectedPrecisionScore}; // Given var matchResult = matcher.FuzzyMatch(queryString, compareString); @@ -232,7 +234,7 @@ namespace Flow.Launcher.Test bool expectedPrecisionResult) { // When - var matcher = new StringMatcher {UserSettingSearchPrecision = expectedPrecisionScore}; + var matcher = new StringMatcher(alphabet) {UserSettingSearchPrecision = expectedPrecisionScore}; // Given var matchResult = matcher.FuzzyMatch(queryString, compareString); @@ -260,7 +262,7 @@ namespace Flow.Launcher.Test string queryString, string compareString1, string compareString2) { // When - var matcher = new StringMatcher {UserSettingSearchPrecision = SearchPrecisionScore.Regular}; + var matcher = new StringMatcher(alphabet) {UserSettingSearchPrecision = SearchPrecisionScore.Regular}; // Given var compareString1Result = matcher.FuzzyMatch(queryString, compareString1); @@ -293,7 +295,7 @@ namespace Flow.Launcher.Test string queryString, string compareString1, string compareString2) { // When - var matcher = new StringMatcher { UserSettingSearchPrecision = SearchPrecisionScore.Regular }; + var matcher = new StringMatcher(alphabet) { UserSettingSearchPrecision = SearchPrecisionScore.Regular }; // Given var compareString1Result = matcher.FuzzyMatch(queryString, compareString1); @@ -323,7 +325,7 @@ namespace Flow.Launcher.Test string secondName, string secondDescription, string secondExecutableName) { // Act - var matcher = new StringMatcher(); + var matcher = new StringMatcher(alphabet); var firstNameMatch = matcher.FuzzyMatch(queryString, firstName).RawScore; var firstDescriptionMatch = matcher.FuzzyMatch(queryString, firstDescription).RawScore; var firstExecutableNameMatch = matcher.FuzzyMatch(queryString, firstExecutableName).RawScore; @@ -358,7 +360,7 @@ namespace Flow.Launcher.Test public void WhenGivenAnAcronymQuery_ShouldReturnAcronymScore(string queryString, string compareString, int desiredScore) { - var matcher = new StringMatcher(); + var matcher = new StringMatcher(alphabet); var score = matcher.FuzzyMatch(queryString, compareString).Score; Assert.IsTrue(score == desiredScore, $@"Query: ""{queryString}"" From 8d8384965ea5d39c62d7ce2b865114555b393146 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 13 Jan 2025 12:00:45 +0800 Subject: [PATCH 0040/1798] Improve dependency injection in updater & settings view model & settings page --- Flow.Launcher.Core/Updater.cs | 20 ++++++++-------- Flow.Launcher/App.xaml.cs | 7 +++--- .../CustomQueryHotkeySetting.xaml.cs | 5 +--- Flow.Launcher/PublicAPIInstance.cs | 20 +++++++++++----- .../ViewModels/SettingsPaneAboutViewModel.cs | 2 +- .../SettingsPaneGeneralViewModel.cs | 2 +- .../ViewModels/SettingsPaneHotkeyViewModel.cs | 5 ++-- Flow.Launcher/SettingWindow.xaml.cs | 18 ++++++++++----- .../ViewModel/SettingWindowViewModel.cs | 23 ++----------------- 9 files changed, 46 insertions(+), 56 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 373418055..7a25447b4 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -34,14 +34,14 @@ namespace Flow.Launcher.Core private SemaphoreSlim UpdateLock { get; } = new SemaphoreSlim(1); - public async Task UpdateAppAsync(IPublicAPI api, bool silentUpdate = true) + public async Task UpdateAppAsync(bool silentUpdate = true) { await UpdateLock.WaitAsync().ConfigureAwait(false); try { if (!silentUpdate) - api.ShowMsg(api.GetTranslation("pleaseWait"), - api.GetTranslation("update_flowlauncher_update_check")); + API.ShowMsg(API.GetTranslation("pleaseWait"), + API.GetTranslation("update_flowlauncher_update_check")); using var updateManager = await GitHubUpdateManagerAsync(GitHubRepository).ConfigureAwait(false); @@ -56,13 +56,13 @@ namespace Flow.Launcher.Core if (newReleaseVersion <= currentVersion) { if (!silentUpdate) - API.ShowMsgBox(api.GetTranslation("update_flowlauncher_already_on_latest")); + API.ShowMsgBox(API.GetTranslation("update_flowlauncher_already_on_latest")); return; } if (!silentUpdate) - api.ShowMsg(api.GetTranslation("update_flowlauncher_update_found"), - api.GetTranslation("update_flowlauncher_updating")); + API.ShowMsg(API.GetTranslation("update_flowlauncher_update_found"), + API.GetTranslation("update_flowlauncher_updating")); await updateManager.DownloadReleases(newUpdateInfo.ReleasesToApply).ConfigureAwait(false); @@ -73,7 +73,7 @@ namespace Flow.Launcher.Core var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}"; 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"), + API.ShowMsgBox(string.Format(API.GetTranslation("update_flowlauncher_fail_moving_portable_user_profile_data"), DataLocation.PortableDataPath, targetDestination)); } @@ -86,7 +86,7 @@ namespace Flow.Launcher.Core Log.Info($"|Updater.UpdateApp|Update success:{newVersionTips}"); - if (API.ShowMsgBox(newVersionTips, api.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) + if (API.ShowMsgBox(newVersionTips, API.GetTranslation("update_flowlauncher_new_update"), MessageBoxButton.YesNo) == MessageBoxResult.Yes) { UpdateManager.RestartApp(Constant.ApplicationFileName); } @@ -99,8 +99,8 @@ namespace Flow.Launcher.Core Log.Exception($"|Updater.UpdateApp|Error Occurred", e); if (!silentUpdate) - api.ShowMsg(api.GetTranslation("update_flowlauncher_fail"), - api.GetTranslation("update_flowlauncher_check_connection")); + API.ShowMsg(API.GetTranslation("update_flowlauncher_fail"), + API.GetTranslation("update_flowlauncher_check_connection")); } finally { diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 0d6d9855c..9384aae3d 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -74,8 +74,6 @@ namespace Flow.Launcher Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate(); - Ioc.Default.GetRequiredService().Initialize(); - Log.Info("|App.OnStartup|Begin Flow Launcher startup ----------------------------------------------------"); Log.Info($"|App.OnStartup|Runtime info:{ErrorReporting.RuntimeInfo()}"); @@ -96,6 +94,7 @@ namespace Flow.Launcher PluginManager.LoadPlugins(_settings.PluginSettings); API = Ioc.Default.GetRequiredService(); + ((PublicAPIInstance)API).Initialize(); Http.API = API; Http.Proxy = _settings.Proxy; @@ -160,11 +159,11 @@ namespace Flow.Launcher { // check update every 5 hours var timer = new PeriodicTimer(TimeSpan.FromHours(5)); - await Ioc.Default.GetRequiredService().UpdateAppAsync(API); + await Ioc.Default.GetRequiredService().UpdateAppAsync(); while (await timer.WaitForNextTickAsync()) // check updates on startup - await Ioc.Default.GetRequiredService().UpdateAppAsync(API); + await Ioc.Default.GetRequiredService().UpdateAppAsync(); } }); } diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index 47460ff7d..eab2705d0 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -6,20 +6,17 @@ using System.Linq; using System.Windows; using System.Windows.Input; using System.Windows.Controls; -using Flow.Launcher.Core; namespace Flow.Launcher { public partial class CustomQueryHotkeySetting : Window { - private SettingWindow _settingWidow; private bool update; private CustomPluginHotkey updateCustomHotkey; public Settings Settings { get; } - public CustomQueryHotkeySetting(SettingWindow settingWidow, Settings settings) + public CustomQueryHotkeySetting(Settings settings) { - _settingWidow = settingWidow; Settings = settings; InitializeComponent(); } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 50765294c..54e97f6c6 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -26,6 +26,7 @@ using System.Collections.Concurrent; using System.Diagnostics; using System.Collections.Specialized; using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Core; namespace Flow.Launcher { @@ -33,19 +34,26 @@ namespace Flow.Launcher { private readonly SettingWindowViewModel _settingsVM; private readonly MainViewModel _mainVM; - private readonly IAlphabet _alphabet; - #region Constructor + private Updater _updater; + + #region Constructor & Initialization public PublicAPIInstance() { _settingsVM = Ioc.Default.GetRequiredService(); _mainVM = Ioc.Default.GetRequiredService(); - _alphabet = Ioc.Default.GetRequiredService(); GlobalHotkey.hookedKeyboardCallback = KListener_hookedKeyboardCallback; WebRequest.RegisterPrefix("data", new DataWebRequestFactory()); } + public void Initialize() + { + // We need to initialize Updater not in the constructor because we want to avoid + // recrusive dependency injection + _updater = Ioc.Default.GetRequiredService(); + } + #endregion #region Public API @@ -78,14 +86,14 @@ namespace Flow.Launcher public event VisibilityChangedEventHandler VisibilityChanged { add => _mainVM.VisibilityChanged += value; remove => _mainVM.VisibilityChanged -= value; } - public void CheckForNewUpdate() => _settingsVM.UpdateApp(); + public void CheckForNewUpdate() => _ = _updater.UpdateAppAsync(false); public void SaveAppAllSettings() { PluginManager.Save(); _mainVM.Save(); _settingsVM.Save(); - ImageLoader.Save(); + _ = ImageLoader.Save(); } public Task ReloadAllPluginData() => PluginManager.ReloadDataAsync(); @@ -105,7 +113,7 @@ namespace Flow.Launcher { Application.Current.Dispatcher.Invoke(() => { - SettingWindow sw = SingletonWindowOpener.Open(this, _settingsVM); + SettingWindow sw = SingletonWindowOpener.Open(); }); } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index 05fb16f5c..cb434f399 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -96,7 +96,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel } [RelayCommand] - private Task UpdateApp() => _updater.UpdateAppAsync(App.API, false); + private Task UpdateApp() => _updater.UpdateAppAsync(false); private void ClearLogFolder() { diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 3d94355e6..4e498ba23 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -160,7 +160,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel private void UpdateApp() { - _ = _updater.UpdateAppAsync(App.API, false); + _ = _updater.UpdateAppAsync(false); } public bool AutoUpdates diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs index fb57f499b..b13aaefe3 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs @@ -7,7 +7,6 @@ using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; -using Flow.Launcher.Core; namespace Flow.Launcher.SettingPages.ViewModels; @@ -71,7 +70,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel return; } - var window = new CustomQueryHotkeySetting(null, Settings); + var window = new CustomQueryHotkeySetting(Settings); window.UpdateItem(item); window.ShowDialog(); } @@ -79,7 +78,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel [RelayCommand] private void CustomHotkeyAdd() { - new CustomQueryHotkeySetting(null, Settings).ShowDialog(); + new CustomQueryHotkeySetting(Settings).ShowDialog(); } [RelayCommand] diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index cb3f1e4a1..ab639e987 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -3,6 +3,7 @@ using System.Windows; using System.Windows.Forms; using System.Windows.Input; using System.Windows.Interop; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; using Flow.Launcher.Helper; @@ -17,16 +18,21 @@ namespace Flow.Launcher; public partial class SettingWindow { + private readonly Updater _updater; + private readonly IPortable _portable; private readonly IPublicAPI _api; private readonly Settings _settings; private readonly SettingWindowViewModel _viewModel; - public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel) + public SettingWindow() { + var viewModel = Ioc.Default.GetRequiredService(); _settings = viewModel.Settings; DataContext = viewModel; _viewModel = viewModel; - _api = api; + _updater = Ioc.Default.GetRequiredService(); + _portable = Ioc.Default.GetRequiredService(); + _api = Ioc.Default.GetRequiredService(); InitializePosition(); InitializeComponent(); } @@ -125,7 +131,7 @@ public partial class SettingWindow WindowState = _settings.SettingWindowState; } - private bool IsPositionValid(double top, double left) + private static bool IsPositionValid(double top, double left) { foreach (var screen in Screen.AllScreens) { @@ -145,7 +151,7 @@ public partial class SettingWindow var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.X, 0); var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, screen.WorkingArea.Width, 0); - var left = (dip2.X - this.ActualWidth) / 2 + dip1.X; + var left = (dip2.X - ActualWidth) / 2 + dip1.X; return left; } @@ -154,13 +160,13 @@ public partial class SettingWindow var screen = Screen.FromPoint(System.Windows.Forms.Cursor.Position); var dip1 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Y); var dip2 = WindowsInteropHelper.TransformPixelsToDIP(this, 0, screen.WorkingArea.Height); - var top = (dip2.Y - this.ActualHeight) / 2 + dip1.Y - 20; + var top = (dip2.Y - ActualHeight) / 2 + dip1.Y - 20; return top; } private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) { - var paneData = new PaneData(_settings, _viewModel.Updater, _viewModel.Portable); + var paneData = new PaneData(_settings, _updater, _portable); if (args.IsSettingsSelected) { ContentFrame.Navigate(typeof(SettingsPaneGeneral), paneData); diff --git a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs index bbd47e731..37276a1ad 100644 --- a/Flow.Launcher/ViewModel/SettingWindowViewModel.cs +++ b/Flow.Launcher/ViewModel/SettingWindowViewModel.cs @@ -1,37 +1,18 @@ using CommunityToolkit.Mvvm.DependencyInjection; -using Flow.Launcher.Core; -using Flow.Launcher.Core.Configuration; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; namespace Flow.Launcher.ViewModel; -public class SettingWindowViewModel : BaseModel +public partial class SettingWindowViewModel : BaseModel { - public Updater Updater { get; private set; } - - public IPortable Portable { get; private set; } - - public Settings Settings { get; } + public Settings Settings { get; init; } public SettingWindowViewModel() { Settings = Ioc.Default.GetRequiredService(); } - public void Initialize() - { - // We don not initialize Updater and Portable in the constructor because we want to avoid - // recrusive dependency injection - Updater = Ioc.Default.GetRequiredService(); - Portable = Ioc.Default.GetRequiredService(); - } - - public async void UpdateApp() - { - await Updater.UpdateAppAsync(App.API, false); - } - /// /// Save Flow settings. Plugins settings are not included. /// From 874a785be40cf57755fd0ebadfb554f6517ac8e8 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 18 Jan 2025 21:06:11 +1100 Subject: [PATCH 0041/1798] cache keywordIndex --- Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index 758250421..d48583f26 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -26,20 +26,21 @@ namespace Flow.Launcher.Plugin.Sys LoadThemes(); } - string search = query.Search[(query.Search.IndexOf(Keyword, StringComparison.Ordinal) + Keyword.Length + 1)..]; + int keywordIndex = query.Search.IndexOf(Keyword, StringComparison.Ordinal); + string search = query.Search[(keywordIndex + Keyword.Length + 1)..]; if (string.IsNullOrWhiteSpace(search)) { return themes.Select(CreateThemeResult) - .OrderBy(x => x.Title) - .ToList(); + .OrderBy(x => x.Title) + .ToList(); } return themes.Select(theme => (theme, matchResult: context.API.FuzzySearch(search, theme))) - .Where(x => x.matchResult.IsSearchPrecisionScoreMet()) - .Select(x => CreateThemeResult(x.theme, x.matchResult.Score, x.matchResult.MatchData)) - .OrderBy(x => x.Title) - .ToList(); + .Where(x => x.matchResult.IsSearchPrecisionScoreMet()) + .Select(x => CreateThemeResult(x.theme, x.matchResult.Score, x.matchResult.MatchData)) + .OrderBy(x => x.Title) + .ToList(); } private void OnVisibilityChanged(object sender, VisibilityChangedEventArgs args) From 40050545005adcfaa2acec8f046deeaea79d3049 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 18 Jan 2025 21:16:04 +1100 Subject: [PATCH 0042/1798] implement the complete IDisposable pattern --- .../Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index d48583f26..ca19bd33d 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -83,12 +83,31 @@ namespace Flow.Launcher.Plugin.Sys }; } + private bool disposed; + protected virtual void Dispose(bool disposing) + { + if (!disposed) + { + if (disposing) + { + // Dispose managed resources + if (context?.API != null) + { + context.API.VisibilityChanged -= OnVisibilityChanged; + } + } + // Free unmanaged resources + disposed = true; + } + } + ~ThemeSelector() + { + Dispose(false); + } public void Dispose() { - if (context != null && context.API != null) - { - context.API.VisibilityChanged -= OnVisibilityChanged; - } + Dispose(true); + GC.SuppressFinalize(this); } } } From fce3b3ae3d7ebb59747e3a94fb4011acce325141 Mon Sep 17 00:00:00 2001 From: Odotocodot <48138990+Odotocodot@users.noreply.github.com> Date: Sat, 18 Jan 2025 13:18:48 +0000 Subject: [PATCH 0043/1798] Fix crash on theme search --- Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index ca19bd33d..3ea90197d 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -26,8 +26,7 @@ namespace Flow.Launcher.Plugin.Sys LoadThemes(); } - int keywordIndex = query.Search.IndexOf(Keyword, StringComparison.Ordinal); - string search = query.Search[(keywordIndex + Keyword.Length + 1)..]; + string search = query.SecondToEndSearch; if (string.IsNullOrWhiteSpace(search)) { @@ -52,7 +51,7 @@ namespace Flow.Launcher.Plugin.Sys } private void LoadThemes() - => themes = ThemeManager.Instance.LoadAvailableThemes().Select(Path.GetFileNameWithoutExtension); + => themes = ThemeManager.Instance.LoadAvailableThemes().Select(x => x.FileNameWithoutExtension); private static Result CreateThemeResult(string theme) => CreateThemeResult(theme, 0, null); From ed399371976b60436eeb9042c59696859eed3caf Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 21 Jan 2025 16:19:28 +0800 Subject: [PATCH 0044/1798] Initialize App.API earlier & Improve code quality --- Flow.Launcher/App.xaml.cs | 5 ++--- Flow.Launcher/PublicAPIInstance.cs | 13 ++----------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 9384aae3d..a64c9e750 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -70,6 +70,8 @@ namespace Flow.Launcher ).Build(); Ioc.Default.ConfigureServices(host.Services); + API = Ioc.Default.GetRequiredService(); + Ioc.Default.GetRequiredService().Initialize(Launcher.Properties.Settings.Default.GithubRepo); Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate(); @@ -93,9 +95,6 @@ namespace Flow.Launcher PluginManager.LoadPlugins(_settings.PluginSettings); - API = Ioc.Default.GetRequiredService(); - ((PublicAPIInstance)API).Initialize(); - Http.API = API; Http.Proxy = _settings.Proxy; diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 54e97f6c6..0329d6973 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -35,9 +35,7 @@ namespace Flow.Launcher private readonly SettingWindowViewModel _settingsVM; private readonly MainViewModel _mainVM; - private Updater _updater; - - #region Constructor & Initialization + #region Constructor public PublicAPIInstance() { @@ -47,13 +45,6 @@ namespace Flow.Launcher WebRequest.RegisterPrefix("data", new DataWebRequestFactory()); } - public void Initialize() - { - // We need to initialize Updater not in the constructor because we want to avoid - // recrusive dependency injection - _updater = Ioc.Default.GetRequiredService(); - } - #endregion #region Public API @@ -86,7 +77,7 @@ namespace Flow.Launcher public event VisibilityChangedEventHandler VisibilityChanged { add => _mainVM.VisibilityChanged += value; remove => _mainVM.VisibilityChanged -= value; } - public void CheckForNewUpdate() => _ = _updater.UpdateAppAsync(false); + public void CheckForNewUpdate() => _ = Ioc.Default.GetRequiredService().UpdateAppAsync(false); public void SaveAppAllSettings() { From f9983b587712bdc439022f4ac19bda46133d9ab8 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 22 Jan 2025 12:25:56 +0800 Subject: [PATCH 0045/1798] Move dependency injection codes to constructor --- Flow.Launcher/App.xaml.cs | 47 +++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index a64c9e750..d983ab000 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -30,7 +30,31 @@ namespace Flow.Launcher public static IPublicAPI API { get; private set; } private const string Unique = "Flow.Launcher_Unique_Application_Mutex"; private static bool _disposed; - private Settings _settings; + private readonly Settings _settings; + + public App() + { + // Initialize settings + var storage = new FlowLauncherJsonStorage(); + _settings = storage.Load(); + _settings.Initialize(storage); + _settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled(); + + // Configure the dependency injection container + var host = Host.CreateDefaultBuilder() + .UseContentRoot(AppContext.BaseDirectory) + .ConfigureServices(services => services + .AddSingleton(_ => _settings) + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + ).Build(); + Ioc.Default.ConfigureServices(host.Services); + } [STAThread] public static void Main() @@ -49,27 +73,6 @@ namespace Flow.Launcher { await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () => { - // Initialize settings - var storage = new FlowLauncherJsonStorage(); - _settings = storage.Load(); - _settings.Initialize(storage); - _settings.WMPInstalled = WindowsMediaPlayerHelper.IsWindowsMediaPlayerInstalled(); - - // Configure the dependency injection container - var host = Host.CreateDefaultBuilder() - .UseContentRoot(AppContext.BaseDirectory) - .ConfigureServices(services => services - .AddSingleton(_ => _settings) - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - ).Build(); - Ioc.Default.ConfigureServices(host.Services); - API = Ioc.Default.GetRequiredService(); Ioc.Default.GetRequiredService().Initialize(Launcher.Properties.Settings.Default.GithubRepo); From 23a1e5bc5853d2f6a4ba0e83c1c36ac960da40d9 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 27 Jan 2025 09:39:12 +0800 Subject: [PATCH 0046/1798] Initialize public api instance in constructor so that we can use App.API all the time --- Flow.Launcher/App.xaml.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index d983ab000..f800ccd5d 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -54,6 +54,9 @@ namespace Flow.Launcher .AddSingleton() ).Build(); Ioc.Default.ConfigureServices(host.Services); + + // Initialize the public API first + API = Ioc.Default.GetRequiredService(); } [STAThread] @@ -73,8 +76,6 @@ namespace Flow.Launcher { await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () => { - API = Ioc.Default.GetRequiredService(); - Ioc.Default.GetRequiredService().Initialize(Launcher.Properties.Settings.Default.GithubRepo); Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate(); From ed16d340cb1c43464b9046a2672edc5d189c01bc Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 27 Jan 2025 09:40:24 +0800 Subject: [PATCH 0047/1798] Improve code quality --- Flow.Launcher.Core/Plugin/PluginManager.cs | 6 +++--- Flow.Launcher.Infrastructure/Http/Http.cs | 3 ++- Flow.Launcher/App.xaml.cs | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index a776c10ab..0e8a4b776 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -14,6 +14,7 @@ using ISavable = Flow.Launcher.Plugin.ISavable; using Flow.Launcher.Plugin.SharedCommands; using System.Text.Json; using Flow.Launcher.Core.Resource; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Core.Plugin { @@ -28,7 +29,7 @@ namespace Flow.Launcher.Core.Plugin public static readonly HashSet GlobalPlugins = new(); public static readonly Dictionary NonGlobalPlugins = new(); - public static IPublicAPI API { private set; get; } + public static IPublicAPI API { get; private set; } = Ioc.Default.GetRequiredService(); private static PluginsSettings Settings; private static List _metadatas; @@ -158,9 +159,8 @@ namespace Flow.Launcher.Core.Plugin /// Call initialize for all plugins /// /// return the list of failed to init plugins or null for none - public static async Task InitializePluginsAsync(IPublicAPI api) + public static async Task InitializePluginsAsync() { - API = api; var failedPlugins = new ConcurrentQueue(); var InitTasks = AllPlugins.Select(pair => Task.Run(async delegate diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 14b8eef4e..3711a6b0d 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -8,6 +8,7 @@ using Flow.Launcher.Infrastructure.UserSettings; using System; using System.Threading; using Flow.Launcher.Plugin; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Infrastructure.Http { @@ -17,7 +18,7 @@ namespace Flow.Launcher.Infrastructure.Http private static HttpClient client = new HttpClient(); - public static IPublicAPI API { get; set; } + private static IPublicAPI API { get; set; } = Ioc.Default.GetRequiredService(); static Http() { diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index f800ccd5d..5f7f097e0 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -99,10 +99,9 @@ namespace Flow.Launcher PluginManager.LoadPlugins(_settings.PluginSettings); - Http.API = API; Http.Proxy = _settings.Proxy; - await PluginManager.InitializePluginsAsync(API); + await PluginManager.InitializePluginsAsync(); await imageLoadertask; var mainVM = Ioc.Default.GetRequiredService(); From 6a2389f4b8c95d87ee72041a0e78812333fe3fd3 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 27 Jan 2025 10:45:05 +0800 Subject: [PATCH 0048/1798] Fix test project build issue --- Flow.Launcher.Infrastructure/Http/Http.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Http/Http.cs b/Flow.Launcher.Infrastructure/Http/Http.cs index 3711a6b0d..78545a87b 100644 --- a/Flow.Launcher.Infrastructure/Http/Http.cs +++ b/Flow.Launcher.Infrastructure/Http/Http.cs @@ -18,8 +18,6 @@ namespace Flow.Launcher.Infrastructure.Http private static HttpClient client = new HttpClient(); - private static IPublicAPI API { get; set; } = Ioc.Default.GetRequiredService(); - static Http() { // need to be added so it would work on a win10 machine @@ -79,7 +77,7 @@ namespace Flow.Launcher.Infrastructure.Http } catch (UriFormatException e) { - API.ShowMsg("Please try again", "Unable to parse Http Proxy"); + Ioc.Default.GetRequiredService().ShowMsg("Please try again", "Unable to parse Http Proxy"); Log.Exception("Flow.Launcher.Infrastructure.Http", "Unable to parse Uri", e); } } From 3260faba985a595b2df48c0541ebb9bef6aea88e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 31 Jan 2025 22:01:29 +0800 Subject: [PATCH 0049/1798] Add support for changing startup to logon task for faster startup experience --- .../UserSettings/Settings.cs | 1 + Flow.Launcher/App.xaml.cs | 2 +- Flow.Launcher/Flow.Launcher.csproj | 1 + Flow.Launcher/Helper/AutoStartup.cs | 115 +++++++++++++++++- .../SettingsPaneGeneralViewModel.cs | 34 +++++- .../Views/SettingsPaneGeneral.xaml | 7 ++ 6 files changed, 151 insertions(+), 9 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index c412fb32f..81895fdcc 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -238,6 +238,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings public bool EnableUpdateLog { get; set; } public bool StartFlowLauncherOnSystemStartup { get; set; } = false; + public bool UseLogonTaskForStartup { get; set; } = false; public bool HideOnStartup { get; set; } = true; bool _hideNotifyIcon { get; set; } public bool HideNotifyIcon diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 4d1adc6cd..38f846d92 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -119,7 +119,7 @@ namespace Flow.Launcher { try { - Helper.AutoStartup.Enable(); + Helper.AutoStartup.Enable(_settings.UseLogonTaskForStartup); } catch (Exception e) { diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 788beddfb..570785be7 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -100,6 +100,7 @@ + diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher/Helper/AutoStartup.cs index 4bff30caf..116520ecf 100644 --- a/Flow.Launcher/Helper/AutoStartup.cs +++ b/Flow.Launcher/Helper/AutoStartup.cs @@ -1,18 +1,31 @@ using System; +using System.IO; +using System.Linq; +using System.Security.Principal; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Microsoft.Win32; +using Microsoft.Win32.TaskScheduler; namespace Flow.Launcher.Helper; public class AutoStartup { private const string StartupPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; + private const string LogonTaskName = $"{Constant.FlowLauncher} Startup"; + private const string LogonTaskDesc = $"{Constant.FlowLauncher} Auto Startup"; public static bool IsEnabled { get { + // Check if logon task is enabled + if (CheckLogonTask()) + { + return true; + } + + // Check if registry is enabled try { using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); @@ -28,12 +41,45 @@ public class AutoStartup } } - public static void Disable() + private static bool CheckLogonTask() + { + using var taskService = new TaskService(); + var task = taskService.RootFolder.AllTasks.FirstOrDefault(t => t.Name == LogonTaskName); + if (task != null) + { + try + { + // Check if the action is the same as the current executable path + var action = task.Definition.Actions.FirstOrDefault()!.ToString().Trim(); + if (!Constant.ExecutablePath.Equals(action, StringComparison.OrdinalIgnoreCase) && !File.Exists(action)) + { + UnscheduleLogonTask(); + ScheduleLogonTask(); + } + } + catch (Exception) + { + Log.Error("AutoStartup", "Failed to check logon task"); + return false; + } + } + + return true; + } + + public static void Disable(bool logonTask) { try { - using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); - key?.DeleteValue(Constant.FlowLauncher, false); + if (logonTask) + { + UnscheduleLogonTask(); + } + else + { + using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); + key?.DeleteValue(Constant.FlowLauncher, false); + } } catch (Exception e) { @@ -42,12 +88,19 @@ public class AutoStartup } } - internal static void Enable() + internal static void Enable(bool logonTask) { try { - using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); - key?.SetValue(Constant.FlowLauncher, $"\"{Constant.ExecutablePath}\""); + if (logonTask) + { + ScheduleLogonTask(); + } + else + { + using var key = Registry.CurrentUser.OpenSubKey(StartupPath, true); + key?.SetValue(Constant.FlowLauncher, $"\"{Constant.ExecutablePath}\""); + } } catch (Exception e) { @@ -55,4 +108,54 @@ public class AutoStartup throw; } } + + private static bool ScheduleLogonTask() + { + using var td = TaskService.Instance.NewTask(); + td.RegistrationInfo.Description = LogonTaskDesc; + td.Triggers.Add(new LogonTrigger { UserId = WindowsIdentity.GetCurrent().Name, Delay = TimeSpan.FromSeconds(2) }); + td.Actions.Add(Constant.ExecutablePath); + + if (IsCurrentUserIsAdmin()) + { + td.Principal.RunLevel = TaskRunLevel.Highest; + } + + td.Settings.StopIfGoingOnBatteries = false; + td.Settings.DisallowStartIfOnBatteries = false; + td.Settings.ExecutionTimeLimit = TimeSpan.Zero; + + try + { + TaskService.Instance.RootFolder.RegisterTaskDefinition(LogonTaskName, td); + return true; + } + catch (Exception) + { + Log.Error("AutoStartup", "Failed to schedule logon task"); + return false; + } + } + + private static bool UnscheduleLogonTask() + { + using var taskService = new TaskService(); + try + { + taskService.RootFolder.DeleteTask(LogonTaskName); + return true; + } + catch (Exception) + { + Log.Error("AutoStartup", "Failed to unschedule logon task"); + return false; + } + } + + private static bool IsCurrentUserIsAdmin() + { + var identity = WindowsIdentity.GetCurrent(); + var principal = new WindowsPrincipal(identity); + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 3d94355e6..0aca761a0 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -42,9 +42,16 @@ public partial class SettingsPaneGeneralViewModel : BaseModel try { if (value) - AutoStartup.Enable(); + { + // Enable either registry or task scheduler + AutoStartup.Enable(UseLogonTaskForStartup); + } else - AutoStartup.Disable(); + { + // Disable both registry and task scheduler + AutoStartup.Disable(true); + AutoStartup.Disable(false); + } } catch (Exception e) { @@ -54,6 +61,29 @@ public partial class SettingsPaneGeneralViewModel : BaseModel } } + public bool UseLogonTaskForStartup + { + get => Settings.UseLogonTaskForStartup; + set + { + Settings.UseLogonTaskForStartup = value; + + if (StartFlowLauncherOnSystemStartup) + { + try + { + // Disable and enable to update the startup method + AutoStartup.Disable(!UseLogonTaskForStartup); + AutoStartup.Enable(UseLogonTaskForStartup); + } + catch (Exception e) + { + Notification.Show(InternationalizationManager.Instance.GetTranslation("setAutoStartFailed"), + e.Message); + } + } + } + } public List SearchWindowScreens { get; } = DropdownDataGeneric.GetValues("SearchWindowScreen"); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 30e065b16..f57eba654 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -36,6 +36,13 @@ OnContent="{DynamicResource enable}" /> + + + + Date: Fri, 31 Jan 2025 22:06:53 +0800 Subject: [PATCH 0050/1798] Move string to resources --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/Languages/zh-cn.xaml | 8 ++++++-- Flow.Launcher/Languages/zh-tw.xaml | 8 ++++++-- Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 4c465d61f..8e8c9abef 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -46,6 +46,7 @@ Portable Mode Store all settings and user data in one folder (Useful when used with removable drives or cloud services). Start Flow Launcher on system startup + Use logon task instead of startup entry for faster startup experience Error setting launch on startup Hide Flow Launcher when focus is lost Do not show new version notifications diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index 681c715fb..d2d1044af 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -1,5 +1,8 @@ - - + + Flow 检测到您已安装 {0} 个插件,需要 {1} 才能运行。是否要下载 {1}? @@ -44,6 +47,7 @@ 便携模式 将所有设置和用户数据存储在一个文件夹中 (可用于可移除驱动器或云服务)。 开机自启 + 使用登录任务而非启动项以更快自启 设置开机自启时出错 失去焦点时自动隐藏 Flow Launcher 不显示新版本提示 diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index 44be5257b..b5aa53377 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -1,5 +1,8 @@ - - + + Flow detected you have installed {0} plugins, which will require {1} to run. Would you like to download {1}? @@ -44,6 +47,7 @@ 便攜模式 將所有設定和使用者資料存儲在一個資料夾中(當與可移動磁碟或雲服務一起使用時很有用)。 開機時啟動 + 使用登錄任務而非啟動項以更快自啟 Error setting launch on startup 失去焦點時自動隱藏 Flow Launcher 不顯示新版本提示 diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index f57eba654..e52614e74 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -36,7 +36,7 @@ OnContent="{DynamicResource enable}" /> - + Date: Fri, 31 Jan 2025 22:22:00 +0800 Subject: [PATCH 0051/1798] Fix issue when checking logon task --- Flow.Launcher/Helper/AutoStartup.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Helper/AutoStartup.cs b/Flow.Launcher/Helper/AutoStartup.cs index 116520ecf..79466f1fb 100644 --- a/Flow.Launcher/Helper/AutoStartup.cs +++ b/Flow.Launcher/Helper/AutoStartup.cs @@ -56,15 +56,16 @@ public class AutoStartup UnscheduleLogonTask(); ScheduleLogonTask(); } + + return true; } catch (Exception) { Log.Error("AutoStartup", "Failed to check logon task"); - return false; } } - return true; + return false; } public static void Disable(bool logonTask) From e320ca1d492594351d81f05ab3da8838c8672dd6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 1 Feb 2025 13:10:32 +0800 Subject: [PATCH 0052/1798] Add support for deleting plugin settings when uninstalling plugins --- Flow.Launcher.Core/Plugin/PluginManager.cs | 21 +++++++++++++++---- .../Languages/en.xaml | 6 ++++-- .../Languages/zh-cn.xaml | 6 ++++-- .../Languages/zh-tw.xaml | 6 ++++-- .../PluginsManager.cs | 6 +++++- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 5c4eaa1da..55bc0e2bd 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -14,6 +14,7 @@ using ISavable = Flow.Launcher.Plugin.ISavable; using Flow.Launcher.Plugin.SharedCommands; using System.Text.Json; using Flow.Launcher.Core.Resource; +using Flow.Launcher.Infrastructure.Storage; namespace Flow.Launcher.Core.Plugin { @@ -439,7 +440,7 @@ namespace Flow.Launcher.Core.Plugin public static void UpdatePlugin(PluginMetadata existingVersion, UserPlugin newVersion, string zipFilePath) { InstallPlugin(newVersion, zipFilePath, checkModified:false); - UninstallPlugin(existingVersion, removeSettings:false, checkModified:false); + UninstallPlugin(existingVersion, removeSettings:false, removePluginSettings:false, checkModified: false); _modifiedPlugins.Add(existingVersion.ID); } @@ -454,9 +455,9 @@ namespace Flow.Launcher.Core.Plugin /// /// Uninstall a plugin. /// - public static void UninstallPlugin(PluginMetadata plugin, bool removeSettings = true) + public static void UninstallPlugin(PluginMetadata plugin, bool removeSettings = true, bool removePluginSettings = false) { - UninstallPlugin(plugin, removeSettings, true); + UninstallPlugin(plugin, removeSettings, removePluginSettings, true); } #endregion @@ -529,7 +530,7 @@ namespace Flow.Launcher.Core.Plugin } } - internal static void UninstallPlugin(PluginMetadata plugin, bool removeSettings, bool checkModified) + internal static void UninstallPlugin(PluginMetadata plugin, bool removeSettings, bool removePluginSettings, bool checkModified) { if (checkModified && PluginModified(plugin.ID)) { @@ -542,6 +543,18 @@ namespace Flow.Launcher.Core.Plugin AllPlugins.RemoveAll(p => p.Metadata.ID == plugin.ID); } + if (removePluginSettings) + { + var assemblyLoader = new PluginAssemblyLoader(plugin.ExecuteFilePath); + var assembly = assemblyLoader.LoadAssemblyAndDependencies(); + var assemblyName = assembly.GetName().Name; + var directoryPath = Path.Combine(DataLocation.DataDirectory(), JsonStorage.DirectoryName, Constant.Plugins, assemblyName); + if (Directory.Exists(directoryPath)) + { + Directory.Delete(directoryPath, true); + } + } + // Marked for deletion. Will be deleted on next start up using var _ = File.CreateText(Path.Combine(plugin.PluginDirectory, "NeedDelete.txt")); diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml index de6a3a2fb..573ca9051 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/en.xaml @@ -15,6 +15,8 @@ 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? Plugin {0} 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. @@ -37,13 +39,13 @@ 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) - + 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. - + Plugins Manager Management of installing, uninstalling or updating Flow Launcher plugins diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml index 676c20a73..033bfed94 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml @@ -13,6 +13,8 @@ 正在安装插件 下载与安装 {0} 插件卸载 + 保留插件设置 + 你希望保留插件设置以便于下次使用吗? 插件安装成功。正在重新启动 Flow Launcher,请稍候... 安装失败:无法从新插件中找到plugin.json元数据文件 错误:具有相同或更高版本的 {0} 的插件已经存在。 @@ -35,13 +37,13 @@ 插件{0}更新成功。正在重新启动 Flow Launcher,请稍候... 从未知源安装 您正在从未知源安装此插件,它可能包含潜在风险!{0}{0}请确保您了解来源以及安全性。{0}{0}您想要继续吗?{0}{0}(您可以通过设置关闭此警告) - + 成功安装插件{0}。请重新启动 Flow Launcher。 成功卸载插件{0}。请重新启动 Flow Launcher。 成功更新插件{0}。请重新启动 Flow Launcher。 插件 {0} 更新成功。请重新启动 Flow Launcher。 插件 {0} 已被修改。请在进行任何进一步更改之前重新启动Flow。 - + 插件管理 安装,卸载或更新 Flow Launcher 插件 diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml index ae37579dc..c2497b70b 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml @@ -13,6 +13,8 @@ Installing Plugin 下載並安裝 {0} 解除安裝擴充功能 + 保留插件設置 + 你希望保留插件設置以便於下次使用嗎? 外掛安裝成功。正在重啟 Flow,請稍後... 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. @@ -35,13 +37,13 @@ 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) - + 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. - + 擴充功能管理 Management of installing, uninstalling or updating Flow Launcher plugins diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 305d248d3..fe3b9d3f2 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -682,7 +682,11 @@ namespace Flow.Launcher.Plugin.PluginsManager { try { - PluginManager.UninstallPlugin(plugin, removeSettings: true); + var removePluginSettings = Context.API.ShowMsgBox( + Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_subtitle"), + Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_title"), + button: MessageBoxButton.YesNo) == MessageBoxResult.No; + PluginManager.UninstallPlugin(plugin, removeSettings: true, removePluginSettings: removePluginSettings); } catch (ArgumentException e) { From 0e02a6f9cff393b1cfa7bec5bb70e1f60e87127a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Feb 2025 07:51:44 +0800 Subject: [PATCH 0053/1798] Revert changes in non-English language files --- .../Languages/zh-cn.xaml | 9 +++++---- .../Languages/zh-tw.xaml | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml index 033bfed94..e6be9069d 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml @@ -1,5 +1,8 @@ - - + + 正在下载插件... @@ -13,8 +16,6 @@ 正在安装插件 下载与安装 {0} 插件卸载 - 保留插件设置 - 你希望保留插件设置以便于下次使用吗? 插件安装成功。正在重新启动 Flow Launcher,请稍候... 安装失败:无法从新插件中找到plugin.json元数据文件 错误:具有相同或更高版本的 {0} 的插件已经存在。 diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml index c2497b70b..9736728a7 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml @@ -1,5 +1,8 @@ - - + + 正在下載擴充功能 @@ -13,8 +16,6 @@ Installing Plugin 下載並安裝 {0} 解除安裝擴充功能 - 保留插件設置 - 你希望保留插件設置以便於下次使用嗎? 外掛安裝成功。正在重啟 Flow,請稍後... 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. From 71b79da5d433c10de38241682245add9b6858359 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Feb 2025 07:53:40 +0800 Subject: [PATCH 0054/1798] Revert auto format --- .../Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml | 5 +---- .../Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml index e6be9069d..f73516a56 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml @@ -1,8 +1,5 @@  - + 正在下载插件... diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml index 9736728a7..f1b044d25 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml @@ -1,8 +1,5 @@  - + 正在下載擴充功能 From 1ff8c3620a030294a6d30d9ae2e93ac14438457a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Feb 2025 07:56:24 +0800 Subject: [PATCH 0055/1798] Revert changes in non-English language files --- Flow.Launcher/Languages/zh-cn.xaml | 8 ++------ Flow.Launcher/Languages/zh-tw.xaml | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index d2d1044af..681c715fb 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -1,8 +1,5 @@ - - + + Flow 检测到您已安装 {0} 个插件,需要 {1} 才能运行。是否要下载 {1}? @@ -47,7 +44,6 @@ 便携模式 将所有设置和用户数据存储在一个文件夹中 (可用于可移除驱动器或云服务)。 开机自启 - 使用登录任务而非启动项以更快自启 设置开机自启时出错 失去焦点时自动隐藏 Flow Launcher 不显示新版本提示 diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index b5aa53377..44be5257b 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -1,8 +1,5 @@ - - + + Flow detected you have installed {0} plugins, which will require {1} to run. Would you like to download {1}? @@ -47,7 +44,6 @@ 便攜模式 將所有設定和使用者資料存儲在一個資料夾中(當與可移動磁碟或雲服務一起使用時很有用)。 開機時啟動 - 使用登錄任務而非啟動項以更快自啟 Error setting launch on startup 失去焦點時自動隱藏 Flow Launcher 不顯示新版本提示 From 7598a6aff507cfff363d94b9f225fa7f6955039e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Feb 2025 08:08:45 +0800 Subject: [PATCH 0056/1798] Revert auto format --- .../Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml | 2 +- .../Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml index f73516a56..28196e55f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml @@ -1,4 +1,4 @@ - + diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml index f1b044d25..96155f440 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml @@ -1,4 +1,4 @@ - + From 1f1b31994da4ab774e9c0964de342e7129c958d8 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Feb 2025 09:35:21 +0800 Subject: [PATCH 0057/1798] Improve argument name to avoid possible confusion --- Flow.Launcher.Core/Plugin/PluginManager.cs | 10 +++++----- .../PluginsManager.cs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 55bc0e2bd..fc915bcb3 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -440,7 +440,7 @@ namespace Flow.Launcher.Core.Plugin public static void UpdatePlugin(PluginMetadata existingVersion, UserPlugin newVersion, string zipFilePath) { InstallPlugin(newVersion, zipFilePath, checkModified:false); - UninstallPlugin(existingVersion, removeSettings:false, removePluginSettings:false, checkModified: false); + UninstallPlugin(existingVersion, removePluginFromSettings:false, removePluginSettings:false, checkModified: false); _modifiedPlugins.Add(existingVersion.ID); } @@ -455,9 +455,9 @@ namespace Flow.Launcher.Core.Plugin /// /// Uninstall a plugin. /// - public static void UninstallPlugin(PluginMetadata plugin, bool removeSettings = true, bool removePluginSettings = false) + public static void UninstallPlugin(PluginMetadata plugin, bool removePluginFromSettings = true, bool removePluginSettings = false) { - UninstallPlugin(plugin, removeSettings, removePluginSettings, true); + UninstallPlugin(plugin, removePluginFromSettings, removePluginSettings, true); } #endregion @@ -530,14 +530,14 @@ namespace Flow.Launcher.Core.Plugin } } - internal static void UninstallPlugin(PluginMetadata plugin, bool removeSettings, bool removePluginSettings, bool checkModified) + internal static void UninstallPlugin(PluginMetadata plugin, bool removePluginFromSettings, bool removePluginSettings, bool checkModified) { if (checkModified && PluginModified(plugin.ID)) { throw new ArgumentException($"Plugin {plugin.Name} has been modified"); } - if (removeSettings) + if (removePluginFromSettings) { Settings.Plugins.Remove(plugin.ID); AllPlugins.RemoveAll(p => p.Metadata.ID == plugin.ID); diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index fe3b9d3f2..ac4f90d92 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -686,7 +686,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_subtitle"), Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_title"), button: MessageBoxButton.YesNo) == MessageBoxResult.No; - PluginManager.UninstallPlugin(plugin, removeSettings: true, removePluginSettings: removePluginSettings); + PluginManager.UninstallPlugin(plugin, removePluginFromSettings: true, removePluginSettings: removePluginSettings); } catch (ArgumentException e) { From 0e4cf57e9e29c401a4ff82052b128f5ebe7865b6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 8 Feb 2025 11:57:29 +0800 Subject: [PATCH 0058/1798] Revert blank lines --- .../Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml | 4 ++-- .../Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml index 28196e55f..676c20a73 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-cn.xaml @@ -35,13 +35,13 @@ 插件{0}更新成功。正在重新启动 Flow Launcher,请稍候... 从未知源安装 您正在从未知源安装此插件,它可能包含潜在风险!{0}{0}请确保您了解来源以及安全性。{0}{0}您想要继续吗?{0}{0}(您可以通过设置关闭此警告) - + 成功安装插件{0}。请重新启动 Flow Launcher。 成功卸载插件{0}。请重新启动 Flow Launcher。 成功更新插件{0}。请重新启动 Flow Launcher。 插件 {0} 更新成功。请重新启动 Flow Launcher。 插件 {0} 已被修改。请在进行任何进一步更改之前重新启动Flow。 - + 插件管理 安装,卸载或更新 Flow Launcher 插件 diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml index 96155f440..ae37579dc 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/zh-tw.xaml @@ -35,13 +35,13 @@ 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) - + 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. - + 擴充功能管理 Management of installing, uninstalling or updating Flow Launcher plugins From f0e74a2aa545a74591c62fcd3e67c45faeff4a75 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 8 Feb 2025 19:12:53 +0800 Subject: [PATCH 0059/1798] Fix issue that plugin manager will save settings for the uninstalled and settings-removed plugins --- Flow.Launcher.Core/Plugin/PluginManager.cs | 14 ++++++++++---- .../Storage/PluginJsonStorage.cs | 18 ++++++++++++++---- Flow.Launcher/PublicAPIInstance.cs | 17 +++++++++++++++++ 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index fc915bcb3..146718b93 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -14,7 +14,6 @@ using ISavable = Flow.Launcher.Plugin.ISavable; using Flow.Launcher.Plugin.SharedCommands; using System.Text.Json; using Flow.Launcher.Core.Resource; -using Flow.Launcher.Infrastructure.Storage; namespace Flow.Launcher.Core.Plugin { @@ -548,10 +547,17 @@ namespace Flow.Launcher.Core.Plugin var assemblyLoader = new PluginAssemblyLoader(plugin.ExecuteFilePath); var assembly = assemblyLoader.LoadAssemblyAndDependencies(); var assemblyName = assembly.GetName().Name; - var directoryPath = Path.Combine(DataLocation.DataDirectory(), JsonStorage.DirectoryName, Constant.Plugins, assemblyName); - if (Directory.Exists(directoryPath)) + + // if user want to remove the plugin settings, we cannot call save method for the plugin json storage instance of this plugin + // so we need to remove it from the api instance + var method = API.GetType().GetMethod("RemovePluginSettings"); + var pluginJsonStorage = method?.Invoke(API, new object[] { assemblyName }); + + // if there exists a json storage for current plugin, we need to delete the directory path + if (pluginJsonStorage != null) { - Directory.Delete(directoryPath, true); + var deleteMethod = pluginJsonStorage.GetType().GetMethod("DeleteDirectory"); + deleteMethod?.Invoke(pluginJsonStorage, null); } } diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs index abe3f55b5..bc3900da8 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs @@ -3,14 +3,17 @@ using Flow.Launcher.Infrastructure.UserSettings; namespace Flow.Launcher.Infrastructure.Storage { - public class PluginJsonStorage :JsonStorage where T : new() + public class PluginJsonStorage : JsonStorage where T : new() { + // Use assembly name to check which plugin is using this storage + public readonly string AssemblyName; + public PluginJsonStorage() { // C# related, add python related below var dataType = typeof(T); - var assemblyName = dataType.Assembly.GetName().Name; - DirectoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName, Constant.Plugins, assemblyName); + AssemblyName = dataType.Assembly.GetName().Name; + DirectoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName, Constant.Plugins, AssemblyName); Helper.ValidateDirectory(DirectoryPath); FilePath = Path.Combine(DirectoryPath, $"{dataType.Name}{FileSuffix}"); @@ -20,6 +23,13 @@ namespace Flow.Launcher.Infrastructure.Storage { Data = data; } + + public void DeleteDirectory() + { + if (Directory.Exists(DirectoryPath)) + { + Directory.Delete(DirectoryPath, true); + } + } } } - diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index f0295cf24..12c65018c 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -189,6 +189,23 @@ namespace Flow.Launcher private readonly ConcurrentDictionary _pluginJsonStorages = new(); + public object RemovePluginSettings(string assemblyName) + { + foreach (var keyValuePair in _pluginJsonStorages) + { + var key = keyValuePair.Key; + var value = keyValuePair.Value; + var name = value.GetType().GetField("AssemblyName")?.GetValue(value)?.ToString(); + if (name == assemblyName) + { + _pluginJsonStorages.Remove(key, out var pluginJsonStorage); + return pluginJsonStorage; + } + } + + return null; + } + /// /// Save plugin settings. /// From 37837e7002307443e7b50ee7db01c0a5878c468d Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 8 Feb 2025 22:59:36 +0800 Subject: [PATCH 0060/1798] Fix possible exception when deleting local folder --- Flow.Launcher.Core/Plugin/PluginManager.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 146718b93..50150a069 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -521,7 +521,15 @@ namespace Flow.Launcher.Core.Plugin FilesFolders.CopyAll(pluginFolderPath, newPluginPath, MessageBoxEx.Show); - Directory.Delete(tempFolderPluginPath, true); + try + { + if (Directory.Exists(tempFolderPluginPath)) + Directory.Delete(tempFolderPluginPath, true); + } + catch (Exception e) + { + Log.Exception($"|PluginManager.InstallPlugin|Failed to delete temp folder {tempFolderPluginPath}", e); + } if (checkModified) { @@ -557,7 +565,14 @@ namespace Flow.Launcher.Core.Plugin if (pluginJsonStorage != null) { var deleteMethod = pluginJsonStorage.GetType().GetMethod("DeleteDirectory"); - deleteMethod?.Invoke(pluginJsonStorage, null); + try + { + deleteMethod?.Invoke(pluginJsonStorage, null); + } + catch (Exception e) + { + Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin json folder for {assemblyName}", e); + } } } From 54a0f3d16523ecaa32408277dc30800537094e89 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 9 Feb 2025 10:58:09 +0800 Subject: [PATCH 0061/1798] Add support for delete plugin directory for non-dotnet plugins --- .../Plugin/JsonRPCPluginBase.cs | 14 +++- Flow.Launcher.Core/Plugin/PluginManager.cs | 70 ++++++++++++------- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs index f6e5e5879..ed8f94bcf 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs @@ -44,8 +44,10 @@ namespace Flow.Launcher.Core.Plugin private string SettingConfigurationPath => Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "SettingsTemplate.yaml"); - private string SettingPath => Path.Combine(DataLocation.PluginSettingsDirectory, - Context.CurrentPluginMetadata.Name, "Settings.json"); + private string SettingDirectory => Path.Combine(DataLocation.PluginSettingsDirectory, + Context.CurrentPluginMetadata.Name); + + private string SettingPath => Path.Combine(SettingDirectory, "Settings.json"); public abstract List LoadContextMenus(Result selectedResult); @@ -159,5 +161,13 @@ namespace Flow.Launcher.Core.Plugin { return Settings.CreateSettingPanel(); } + + public void DeletePluginSettingsDirectory() + { + if (Directory.Exists(SettingDirectory)) + { + Directory.Delete(SettingDirectory, true); + } + } } } diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 50150a069..2bce2ba79 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -544,38 +544,56 @@ namespace Flow.Launcher.Core.Plugin throw new ArgumentException($"Plugin {plugin.Name} has been modified"); } + if (removePluginSettings) + { + if (AllowedLanguage.IsDotNet(plugin.Language)) // for the plugin in .NET, we can use assembly loader + { + var assemblyLoader = new PluginAssemblyLoader(plugin.ExecuteFilePath); + var assembly = assemblyLoader.LoadAssemblyAndDependencies(); + var assemblyName = assembly.GetName().Name; + + // if user want to remove the plugin settings, we cannot call save method for the plugin json storage instance of this plugin + // so we need to remove it from the api instance + var method = API.GetType().GetMethod("RemovePluginSettings"); + var pluginJsonStorage = method?.Invoke(API, new object[] { assemblyName }); + + // if there exists a json storage for current plugin, we need to delete the directory path + if (pluginJsonStorage != null) + { + var deleteMethod = pluginJsonStorage.GetType().GetMethod("DeleteDirectory"); + try + { + deleteMethod?.Invoke(pluginJsonStorage, null); + } + catch (Exception e) + { + Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin json folder for {plugin.Name}", e); + } + } + } + else // the plugin with json prc interface + { + var pluginPair = AllPlugins.FirstOrDefault(p => p.Metadata.ID == plugin.ID); + if (pluginPair != null && pluginPair.Plugin is JsonRPCPlugin jsonRpcPlugin) + { + try + { + jsonRpcPlugin.DeletePluginSettingsDirectory(); + } + catch (Exception e) + { + Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin json folder for {plugin.Name}", e); + } + } + } + } + if (removePluginFromSettings) { Settings.Plugins.Remove(plugin.ID); AllPlugins.RemoveAll(p => p.Metadata.ID == plugin.ID); } - if (removePluginSettings) - { - var assemblyLoader = new PluginAssemblyLoader(plugin.ExecuteFilePath); - var assembly = assemblyLoader.LoadAssemblyAndDependencies(); - var assemblyName = assembly.GetName().Name; - - // if user want to remove the plugin settings, we cannot call save method for the plugin json storage instance of this plugin - // so we need to remove it from the api instance - var method = API.GetType().GetMethod("RemovePluginSettings"); - var pluginJsonStorage = method?.Invoke(API, new object[] { assemblyName }); - - // if there exists a json storage for current plugin, we need to delete the directory path - if (pluginJsonStorage != null) - { - var deleteMethod = pluginJsonStorage.GetType().GetMethod("DeleteDirectory"); - try - { - deleteMethod?.Invoke(pluginJsonStorage, null); - } - catch (Exception e) - { - Log.Exception($"|PluginManager.UninstallPlugin|Failed to delete plugin json folder for {assemblyName}", e); - } - } - } - // Marked for deletion. Will be deleted on next start up using var _ = File.CreateText(Path.Combine(plugin.PluginDirectory, "NeedDelete.txt")); From 585b7015b6236ea7fdbe156c39d468a3ca579ed5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 10 Feb 2025 18:20:50 +0800 Subject: [PATCH 0062/1798] Add uninstallation tooltip for logon task settings item --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 8e8c9abef..cd9d0b02a 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -47,6 +47,7 @@ Store all settings and user data in one folder (Useful when used with removable drives or cloud services). Start Flow Launcher on system startup Use logon task instead of startup entry for faster startup experience + After uninstallation, you need to manually remove this task (Flow.Launcher Startup) via Task Scheduler Error setting launch on startup Hide Flow Launcher when focus is lost Do not show new version notifications diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index e52614e74..a80e618e8 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -36,7 +36,7 @@ OnContent="{DynamicResource enable}" /> - + Date: Wed, 12 Feb 2025 15:06:15 +0800 Subject: [PATCH 0063/1798] Make sure back to query results from context menu before changing query --- Flow.Launcher/CustomQueryHotkeySetting.xaml.cs | 1 + Flow.Launcher/CustomShortcutSetting.xaml.cs | 1 + Flow.Launcher/ResultListBox.xaml.cs | 3 +++ Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs | 1 + Flow.Launcher/ViewModel/PluginViewModel.cs | 1 + 5 files changed, 7 insertions(+) diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index 81e7600b8..3db49b381 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -76,6 +76,7 @@ namespace Flow.Launcher private void BtnTestActionKeyword_OnClick(object sender, RoutedEventArgs e) { + App.API.BackToQueryResults(); App.API.ChangeQuery(tbAction.Text); Application.Current.MainWindow.Show(); Application.Current.MainWindow.Opacity = 1; diff --git a/Flow.Launcher/CustomShortcutSetting.xaml.cs b/Flow.Launcher/CustomShortcutSetting.xaml.cs index dec3506eb..10452726d 100644 --- a/Flow.Launcher/CustomShortcutSetting.xaml.cs +++ b/Flow.Launcher/CustomShortcutSetting.xaml.cs @@ -64,6 +64,7 @@ namespace Flow.Launcher private void BtnTestShortcut_OnClick(object sender, RoutedEventArgs e) { + App.API.BackToQueryResults(); App.API.ChangeQuery(tbExpand.Text); Application.Current.MainWindow.Show(); Application.Current.MainWindow.Opacity = 1; diff --git a/Flow.Launcher/ResultListBox.xaml.cs b/Flow.Launcher/ResultListBox.xaml.cs index ac51b195c..cc003457f 100644 --- a/Flow.Launcher/ResultListBox.xaml.cs +++ b/Flow.Launcher/ResultListBox.xaml.cs @@ -149,7 +149,10 @@ namespace Flow.Launcher var rawQuery = query; var effect = DragDrop.DoDragDrop((DependencyObject)sender, data, DragDropEffects.Move | DragDropEffects.Copy); if (effect == DragDropEffects.Move) + { + App.API.BackToQueryResults(); App.API.ChangeQuery(rawQuery, true); + } } private void ResultListBox_OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) { diff --git a/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs b/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs index 38b5bec65..97c938e78 100644 --- a/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs @@ -64,6 +64,7 @@ namespace Flow.Launcher.ViewModel private void ShowCommandQuery(string action) { var actionKeyword = PluginManagerData.Metadata.ActionKeywords.Any() ? PluginManagerData.Metadata.ActionKeywords[0] + " " : String.Empty; + App.API.BackToQueryResults(); App.API.ChangeQuery($"{actionKeyword}{action} {_plugin.Name}"); App.API.ShowMainWindow(); } diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 4ce8bd470..e56e8e9e5 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -146,6 +146,7 @@ namespace Flow.Launcher.ViewModel [RelayCommand] private void OpenDeletePluginWindow() { + PluginManager.API.BackToQueryResults(); PluginManager.API.ChangeQuery($"{PluginManagerActionKeyword} uninstall {PluginPair.Metadata.Name}".Trim(), true); PluginManager.API.ShowMainWindow(); } From d73f3a165b9d3faa8b9cf35f0bd714b286bd5af9 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 17 Feb 2025 00:00:18 +0800 Subject: [PATCH 0064/1798] Fix custom hotkey preview issue --- Flow.Launcher/CustomQueryHotkeySetting.xaml.cs | 18 ++++++++++-------- Flow.Launcher/CustomShortcutSetting.xaml.cs | 8 +++++--- Flow.Launcher/PublicAPIInstance.cs | 2 +- .../ViewModels/SettingsPaneHotkeyViewModel.cs | 11 +++++++---- .../Views/SettingsPaneHotkey.xaml.cs | 4 ++-- Flow.Launcher/SettingWindow.xaml.cs | 8 +++++--- Flow.Launcher/ViewModel/MainViewModel.cs | 5 +++-- 7 files changed, 33 insertions(+), 23 deletions(-) diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index 81e7600b8..db1df0cf2 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -7,20 +7,23 @@ using System.Windows; using System.Windows.Input; using System.Windows.Controls; using Flow.Launcher.Core; +using Flow.Launcher.ViewModel; namespace Flow.Launcher { public partial class CustomQueryHotkeySetting : Window { private SettingWindow _settingWidow; + private readonly Settings _settings; + private readonly MainViewModel _mainViewModel; private bool update; private CustomPluginHotkey updateCustomHotkey; - public Settings Settings { get; } - public CustomQueryHotkeySetting(SettingWindow settingWidow, Settings settings) + public CustomQueryHotkeySetting(SettingWindow settingWidow, Settings settings, MainViewModel mainVM) { _settingWidow = settingWidow; - Settings = settings; + _settings = settings; + _mainViewModel = mainVM; InitializeComponent(); } @@ -33,13 +36,13 @@ namespace Flow.Launcher { if (!update) { - Settings.CustomPluginHotkeys ??= new ObservableCollection(); + _settings.CustomPluginHotkeys ??= new ObservableCollection(); var pluginHotkey = new CustomPluginHotkey { Hotkey = HotkeyControl.CurrentHotkey.ToString(), ActionKeyword = tbAction.Text }; - Settings.CustomPluginHotkeys.Add(pluginHotkey); + _settings.CustomPluginHotkeys.Add(pluginHotkey); HotKeyMapper.SetCustomQueryHotkey(pluginHotkey); } @@ -59,7 +62,7 @@ namespace Flow.Launcher public void UpdateItem(CustomPluginHotkey item) { - updateCustomHotkey = Settings.CustomPluginHotkeys.FirstOrDefault(o => + updateCustomHotkey = _settings.CustomPluginHotkeys.FirstOrDefault(o => o.ActionKeyword == item.ActionKeyword && o.Hotkey == item.Hotkey); if (updateCustomHotkey == null) { @@ -77,8 +80,7 @@ namespace Flow.Launcher private void BtnTestActionKeyword_OnClick(object sender, RoutedEventArgs e) { App.API.ChangeQuery(tbAction.Text); - Application.Current.MainWindow.Show(); - Application.Current.MainWindow.Opacity = 1; + _mainViewModel.Show(false); Application.Current.MainWindow.Focus(); } diff --git a/Flow.Launcher/CustomShortcutSetting.xaml.cs b/Flow.Launcher/CustomShortcutSetting.xaml.cs index dec3506eb..cb2cfcb29 100644 --- a/Flow.Launcher/CustomShortcutSetting.xaml.cs +++ b/Flow.Launcher/CustomShortcutSetting.xaml.cs @@ -4,21 +4,24 @@ using System.Windows; using System.Windows.Input; using Flow.Launcher.SettingPages.ViewModels; using Flow.Launcher.Core; +using Flow.Launcher.ViewModel; namespace Flow.Launcher { public partial class CustomShortcutSetting : Window { private readonly SettingsPaneHotkeyViewModel _hotkeyVm; + private readonly MainViewModel _mainViewModel; public string Key { get; set; } = String.Empty; public string Value { get; set; } = String.Empty; private string originalKey { get; } = null; private string originalValue { get; } = null; private bool update { get; } = false; - public CustomShortcutSetting(SettingsPaneHotkeyViewModel vm) + public CustomShortcutSetting(SettingsPaneHotkeyViewModel vm, MainViewModel mainVM) { _hotkeyVm = vm; + _mainViewModel = mainVM; InitializeComponent(); } @@ -65,8 +68,7 @@ namespace Flow.Launcher private void BtnTestShortcut_OnClick(object sender, RoutedEventArgs e) { App.API.ChangeQuery(tbExpand.Text); - Application.Current.MainWindow.Show(); - Application.Current.MainWindow.Opacity = 1; + _mainViewModel.Show(false); Application.Current.MainWindow.Focus(); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index f0295cf24..2d8126033 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -105,7 +105,7 @@ namespace Flow.Launcher { Application.Current.Dispatcher.Invoke(() => { - SettingWindow sw = SingletonWindowOpener.Open(this, _settingsVM); + SettingWindow sw = SingletonWindowOpener.Open(this, _settingsVM, _mainVM); }); } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs index 6d8af9a3f..5aedd3be7 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs @@ -8,12 +8,14 @@ using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Core; +using Flow.Launcher.ViewModel; namespace Flow.Launcher.SettingPages.ViewModels; public partial class SettingsPaneHotkeyViewModel : BaseModel { public Settings Settings { get; } + private MainViewModel MainVM { get; } public CustomPluginHotkey SelectedCustomPluginHotkey { get; set; } public CustomShortcutModel SelectedCustomShortcut { get; set; } @@ -25,9 +27,10 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel $"{KeyConstant.Ctrl}+{KeyConstant.Alt}" }; - public SettingsPaneHotkeyViewModel(Settings settings) + public SettingsPaneHotkeyViewModel(Settings settings, MainViewModel mainVM) { Settings = settings; + MainVM = mainVM; } [RelayCommand] @@ -71,7 +74,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel return; } - var window = new CustomQueryHotkeySetting(null, Settings); + var window = new CustomQueryHotkeySetting(null, Settings, MainVM); window.UpdateItem(item); window.ShowDialog(); } @@ -79,7 +82,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel [RelayCommand] private void CustomHotkeyAdd() { - new CustomQueryHotkeySetting(null, Settings).ShowDialog(); + new CustomQueryHotkeySetting(null, Settings, MainVM).ShowDialog(); } [RelayCommand] @@ -126,7 +129,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel [RelayCommand] private void CustomShortcutAdd() { - var window = new CustomShortcutSetting(this); + var window = new CustomShortcutSetting(this, MainVM); if (window.ShowDialog() is true) { var shortcut = new CustomShortcutModel(window.Key, window.Value); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs index 061eabf51..26939c9f9 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs @@ -12,9 +12,9 @@ public partial class SettingsPaneHotkey { if (!IsInitialized) { - if (e.ExtraData is not SettingWindow.PaneData { Settings: { } settings }) + if (e.ExtraData is not SettingWindow.PaneData { Settings: { } settings, MainViewModel: { } mainVM }) throw new ArgumentException("Settings are required for SettingsPaneHotkey."); - _viewModel = new SettingsPaneHotkeyViewModel(settings); + _viewModel = new SettingsPaneHotkeyViewModel(settings, mainVM); DataContext = _viewModel; InitializeComponent(); } diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index d5b303516..ae481b65b 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -20,12 +20,14 @@ public partial class SettingWindow private readonly IPublicAPI _api; private readonly Settings _settings; private readonly SettingWindowViewModel _viewModel; + private readonly MainViewModel _mainVM; - public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel) + public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel, MainViewModel mainVM) { _settings = viewModel.Settings; DataContext = viewModel; _viewModel = viewModel; + _mainVM = mainVM; _api = api; InitializePosition(); InitializeComponent(); @@ -160,7 +162,7 @@ public partial class SettingWindow private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) { - var paneData = new PaneData(_settings, _viewModel.Updater, _viewModel.Portable); + var paneData = new PaneData(_settings, _viewModel.Updater, _viewModel.Portable, _mainVM); if (args.IsSettingsSelected) { ContentFrame.Navigate(typeof(SettingsPaneGeneral), paneData); @@ -206,5 +208,5 @@ public partial class SettingWindow NavView.SelectedItem ??= NavView.MenuItems[0]; /* Set First Page */ } - public record PaneData(Settings Settings, Updater Updater, IPortable Portable); + public record PaneData(Settings Settings, Updater Updater, IPortable Portable, MainViewModel MainViewModel); } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 55bc8d1b3..7c2abb078 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1359,7 +1359,7 @@ namespace Flow.Launcher.ViewModel } } - public void Show() + public void Show(bool invokeEvent = true) { Application.Current.Dispatcher.Invoke(() => { @@ -1368,7 +1368,8 @@ namespace Flow.Launcher.ViewModel MainWindowOpacity = 1; MainWindowVisibilityStatus = true; - VisibilityChanged?.Invoke(this, new VisibilityChangedEventArgs { IsVisible = true }); + if (invokeEvent) + VisibilityChanged?.Invoke(this, new VisibilityChangedEventArgs { IsVisible = true }); }); } From 0611340d7159d050bc3a8a9dac7d4df852a568f1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 17 Feb 2025 16:10:07 +0800 Subject: [PATCH 0065/1798] Invoke visibility changed event when previewing --- Flow.Launcher/CustomQueryHotkeySetting.xaml.cs | 2 +- Flow.Launcher/CustomShortcutSetting.xaml.cs | 2 +- Flow.Launcher/ViewModel/MainViewModel.cs | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index db1df0cf2..d33794d61 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -80,7 +80,7 @@ namespace Flow.Launcher private void BtnTestActionKeyword_OnClick(object sender, RoutedEventArgs e) { App.API.ChangeQuery(tbAction.Text); - _mainViewModel.Show(false); + _mainViewModel.Show(); Application.Current.MainWindow.Focus(); } diff --git a/Flow.Launcher/CustomShortcutSetting.xaml.cs b/Flow.Launcher/CustomShortcutSetting.xaml.cs index cb2cfcb29..4cc30c8f5 100644 --- a/Flow.Launcher/CustomShortcutSetting.xaml.cs +++ b/Flow.Launcher/CustomShortcutSetting.xaml.cs @@ -68,7 +68,7 @@ namespace Flow.Launcher private void BtnTestShortcut_OnClick(object sender, RoutedEventArgs e) { App.API.ChangeQuery(tbExpand.Text); - _mainViewModel.Show(false); + _mainViewModel.Show(); Application.Current.MainWindow.Focus(); } } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 7c2abb078..55bc8d1b3 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1359,7 +1359,7 @@ namespace Flow.Launcher.ViewModel } } - public void Show(bool invokeEvent = true) + public void Show() { Application.Current.Dispatcher.Invoke(() => { @@ -1368,8 +1368,7 @@ namespace Flow.Launcher.ViewModel MainWindowOpacity = 1; MainWindowVisibilityStatus = true; - if (invokeEvent) - VisibilityChanged?.Invoke(this, new VisibilityChangedEventArgs { IsVisible = true }); + VisibilityChanged?.Invoke(this, new VisibilityChangedEventArgs { IsVisible = true }); }); } From 6b032b33520a272f8d9a239253272aa0fa234f68 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 18 Feb 2025 11:32:47 +0800 Subject: [PATCH 0066/1798] Revert changes and use api function instead --- Flow.Launcher/CustomQueryHotkeySetting.xaml.cs | 7 ++----- Flow.Launcher/CustomShortcutSetting.xaml.cs | 7 ++----- Flow.Launcher/PublicAPIInstance.cs | 2 +- .../ViewModels/SettingsPaneHotkeyViewModel.cs | 11 ++++------- .../SettingPages/Views/SettingsPaneHotkey.xaml.cs | 4 ++-- Flow.Launcher/SettingWindow.xaml.cs | 8 +++----- 6 files changed, 14 insertions(+), 25 deletions(-) diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index d33794d61..1bd6ee95b 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -7,7 +7,6 @@ using System.Windows; using System.Windows.Input; using System.Windows.Controls; using Flow.Launcher.Core; -using Flow.Launcher.ViewModel; namespace Flow.Launcher { @@ -15,15 +14,13 @@ namespace Flow.Launcher { private SettingWindow _settingWidow; private readonly Settings _settings; - private readonly MainViewModel _mainViewModel; private bool update; private CustomPluginHotkey updateCustomHotkey; - public CustomQueryHotkeySetting(SettingWindow settingWidow, Settings settings, MainViewModel mainVM) + public CustomQueryHotkeySetting(SettingWindow settingWidow, Settings settings) { _settingWidow = settingWidow; _settings = settings; - _mainViewModel = mainVM; InitializeComponent(); } @@ -80,7 +77,7 @@ namespace Flow.Launcher private void BtnTestActionKeyword_OnClick(object sender, RoutedEventArgs e) { App.API.ChangeQuery(tbAction.Text); - _mainViewModel.Show(); + App.API.ShowMainWindow(); Application.Current.MainWindow.Focus(); } diff --git a/Flow.Launcher/CustomShortcutSetting.xaml.cs b/Flow.Launcher/CustomShortcutSetting.xaml.cs index 4cc30c8f5..05d4d3d83 100644 --- a/Flow.Launcher/CustomShortcutSetting.xaml.cs +++ b/Flow.Launcher/CustomShortcutSetting.xaml.cs @@ -4,24 +4,21 @@ using System.Windows; using System.Windows.Input; using Flow.Launcher.SettingPages.ViewModels; using Flow.Launcher.Core; -using Flow.Launcher.ViewModel; namespace Flow.Launcher { public partial class CustomShortcutSetting : Window { private readonly SettingsPaneHotkeyViewModel _hotkeyVm; - private readonly MainViewModel _mainViewModel; public string Key { get; set; } = String.Empty; public string Value { get; set; } = String.Empty; private string originalKey { get; } = null; private string originalValue { get; } = null; private bool update { get; } = false; - public CustomShortcutSetting(SettingsPaneHotkeyViewModel vm, MainViewModel mainVM) + public CustomShortcutSetting(SettingsPaneHotkeyViewModel vm) { _hotkeyVm = vm; - _mainViewModel = mainVM; InitializeComponent(); } @@ -68,7 +65,7 @@ namespace Flow.Launcher private void BtnTestShortcut_OnClick(object sender, RoutedEventArgs e) { App.API.ChangeQuery(tbExpand.Text); - _mainViewModel.Show(); + App.API.ShowMainWindow(); Application.Current.MainWindow.Focus(); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 2d8126033..f0295cf24 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -105,7 +105,7 @@ namespace Flow.Launcher { Application.Current.Dispatcher.Invoke(() => { - SettingWindow sw = SingletonWindowOpener.Open(this, _settingsVM, _mainVM); + SettingWindow sw = SingletonWindowOpener.Open(this, _settingsVM); }); } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs index 5aedd3be7..6d8af9a3f 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs @@ -8,14 +8,12 @@ using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Core; -using Flow.Launcher.ViewModel; namespace Flow.Launcher.SettingPages.ViewModels; public partial class SettingsPaneHotkeyViewModel : BaseModel { public Settings Settings { get; } - private MainViewModel MainVM { get; } public CustomPluginHotkey SelectedCustomPluginHotkey { get; set; } public CustomShortcutModel SelectedCustomShortcut { get; set; } @@ -27,10 +25,9 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel $"{KeyConstant.Ctrl}+{KeyConstant.Alt}" }; - public SettingsPaneHotkeyViewModel(Settings settings, MainViewModel mainVM) + public SettingsPaneHotkeyViewModel(Settings settings) { Settings = settings; - MainVM = mainVM; } [RelayCommand] @@ -74,7 +71,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel return; } - var window = new CustomQueryHotkeySetting(null, Settings, MainVM); + var window = new CustomQueryHotkeySetting(null, Settings); window.UpdateItem(item); window.ShowDialog(); } @@ -82,7 +79,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel [RelayCommand] private void CustomHotkeyAdd() { - new CustomQueryHotkeySetting(null, Settings, MainVM).ShowDialog(); + new CustomQueryHotkeySetting(null, Settings).ShowDialog(); } [RelayCommand] @@ -129,7 +126,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel [RelayCommand] private void CustomShortcutAdd() { - var window = new CustomShortcutSetting(this, MainVM); + var window = new CustomShortcutSetting(this); if (window.ShowDialog() is true) { var shortcut = new CustomShortcutModel(window.Key, window.Value); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs index 26939c9f9..061eabf51 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs @@ -12,9 +12,9 @@ public partial class SettingsPaneHotkey { if (!IsInitialized) { - if (e.ExtraData is not SettingWindow.PaneData { Settings: { } settings, MainViewModel: { } mainVM }) + if (e.ExtraData is not SettingWindow.PaneData { Settings: { } settings }) throw new ArgumentException("Settings are required for SettingsPaneHotkey."); - _viewModel = new SettingsPaneHotkeyViewModel(settings, mainVM); + _viewModel = new SettingsPaneHotkeyViewModel(settings); DataContext = _viewModel; InitializeComponent(); } diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index ae481b65b..d5b303516 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -20,14 +20,12 @@ public partial class SettingWindow private readonly IPublicAPI _api; private readonly Settings _settings; private readonly SettingWindowViewModel _viewModel; - private readonly MainViewModel _mainVM; - public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel, MainViewModel mainVM) + public SettingWindow(IPublicAPI api, SettingWindowViewModel viewModel) { _settings = viewModel.Settings; DataContext = viewModel; _viewModel = viewModel; - _mainVM = mainVM; _api = api; InitializePosition(); InitializeComponent(); @@ -162,7 +160,7 @@ public partial class SettingWindow private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) { - var paneData = new PaneData(_settings, _viewModel.Updater, _viewModel.Portable, _mainVM); + var paneData = new PaneData(_settings, _viewModel.Updater, _viewModel.Portable); if (args.IsSettingsSelected) { ContentFrame.Navigate(typeof(SettingsPaneGeneral), paneData); @@ -208,5 +206,5 @@ public partial class SettingWindow NavView.SelectedItem ??= NavView.MenuItems[0]; /* Set First Page */ } - public record PaneData(Settings Settings, Updater Updater, IPortable Portable, MainViewModel MainViewModel); + public record PaneData(Settings Settings, Updater Updater, IPortable Portable); } From 3dade8bbfcf5c556e5b08caab23b38aabc55f9b1 Mon Sep 17 00:00:00 2001 From: Kevin Zhang <45326534+taooceros@users.noreply.github.com> Date: Wed, 19 Feb 2025 00:03:46 -0800 Subject: [PATCH 0067/1798] Don't restart the jsonrpc process when reloading data. --- Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs index f95266c7f..19d7edb31 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs @@ -135,10 +135,9 @@ namespace Flow.Launcher.Core.Plugin public virtual async Task ReloadDataAsync() { - SetupJsonRPC(); try { - await RPC.InvokeAsync("reload", Context); + await RPC.InvokeAsync("reload_data", Context); } catch (RemoteMethodNotFoundException e) { From 2843236214981585fb2316ea25e675cf56bc21f3 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 19 Feb 2025 17:09:09 +0800 Subject: [PATCH 0068/1798] Improve documents & Improve code quality --- Flow.Launcher/CustomQueryHotkeySetting.xaml.cs | 1 + Flow.Launcher/CustomShortcutSetting.xaml.cs | 1 + Flow.Launcher/ResultListBox.xaml.cs | 1 + Flow.Launcher/ViewModel/MainViewModel.cs | 2 ++ Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs | 1 + Flow.Launcher/ViewModel/PluginViewModel.cs | 1 + Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs | 1 - Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 5 +++-- 8 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index 3db49b381..fd829afe2 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -76,6 +76,7 @@ namespace Flow.Launcher private void BtnTestActionKeyword_OnClick(object sender, RoutedEventArgs e) { + // if user happens to open context menu, we need to return back to query results before changing query App.API.BackToQueryResults(); App.API.ChangeQuery(tbAction.Text); Application.Current.MainWindow.Show(); diff --git a/Flow.Launcher/CustomShortcutSetting.xaml.cs b/Flow.Launcher/CustomShortcutSetting.xaml.cs index 10452726d..d05a5c15c 100644 --- a/Flow.Launcher/CustomShortcutSetting.xaml.cs +++ b/Flow.Launcher/CustomShortcutSetting.xaml.cs @@ -64,6 +64,7 @@ namespace Flow.Launcher private void BtnTestShortcut_OnClick(object sender, RoutedEventArgs e) { + // if user happens to open context menu, we need to return back to query results before changing query App.API.BackToQueryResults(); App.API.ChangeQuery(tbExpand.Text); Application.Current.MainWindow.Show(); diff --git a/Flow.Launcher/ResultListBox.xaml.cs b/Flow.Launcher/ResultListBox.xaml.cs index cc003457f..834692536 100644 --- a/Flow.Launcher/ResultListBox.xaml.cs +++ b/Flow.Launcher/ResultListBox.xaml.cs @@ -150,6 +150,7 @@ namespace Flow.Launcher var effect = DragDrop.DoDragDrop((DependencyObject)sender, data, DragDropEffects.Move | DragDropEffects.Copy); if (effect == DragDropEffects.Move) { + // if user happens to open context menu, we need to return back to query results before changing query App.API.BackToQueryResults(); App.API.ChangeQuery(rawQuery, true); } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 5c3251bfc..4af93daf9 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1266,6 +1266,7 @@ namespace Flow.Launcher.ViewModel { _topMostRecord.Remove(result); App.API.ShowMsg(InternationalizationManager.Instance.GetTranslation("success")); + // if user happens to open context menu, we need to return back to query results before changing query App.API.BackToQueryResults(); App.API.ReQuery(); return false; @@ -1284,6 +1285,7 @@ namespace Flow.Launcher.ViewModel { _topMostRecord.AddOrUpdate(result); App.API.ShowMsg(InternationalizationManager.Instance.GetTranslation("success")); + // if user happens to open context menu, we need to return back to query results before changing query App.API.BackToQueryResults(); App.API.ReQuery(); return false; diff --git a/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs b/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs index 97c938e78..7675ecb16 100644 --- a/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs @@ -64,6 +64,7 @@ namespace Flow.Launcher.ViewModel private void ShowCommandQuery(string action) { var actionKeyword = PluginManagerData.Metadata.ActionKeywords.Any() ? PluginManagerData.Metadata.ActionKeywords[0] + " " : String.Empty; + // if user happens to open context menu, we need to return back to query results before changing query App.API.BackToQueryResults(); App.API.ChangeQuery($"{actionKeyword}{action} {_plugin.Name}"); App.API.ShowMainWindow(); diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index e56e8e9e5..c8601c431 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -146,6 +146,7 @@ namespace Flow.Launcher.ViewModel [RelayCommand] private void OpenDeletePluginWindow() { + // if user happens to open context menu, we need to return back to query results before changing query PluginManager.API.BackToQueryResults(); PluginManager.API.ChangeQuery($"{PluginManagerActionKeyword} uninstall {PluginPair.Metadata.Name}".Trim(), true); PluginManager.API.ShowMainWindow(); diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs index 17e9fe2bc..482e821dc 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs @@ -59,7 +59,6 @@ namespace Flow.Launcher.Plugin.PluginsManager var link = pluginManifestInfo.UrlSourceCode.StartsWith("https://github.com") ? Regex.Replace(pluginManifestInfo.UrlSourceCode, @"\/tree\/\w+$", "") + "/issues" : pluginManifestInfo.UrlSourceCode; - Context.API.OpenUrl(link); return true; } diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 7f1f4bd4d..86808cfbc 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; -using System.Windows; using WindowsInput; using WindowsInput.Native; using Flow.Launcher.Infrastructure.Hotkey; @@ -379,9 +378,11 @@ namespace Flow.Launcher.Plugin.Shell private void OnWinRPressed() { // show the main window and set focus to the query box - Task.Run(() => + _ = Task.Run(() => { context.API.ShowMainWindow(); + // if user happens to open context menu, we need to return back to query results before changing query + context.API.BackToQueryResults(); context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}"); }); From 9880c362fd7196b2fc7792f82b533fc80a945eed Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 19 Feb 2025 23:31:26 +0800 Subject: [PATCH 0069/1798] Remove useless settings control & project reference --- .../Flow.Launcher.Plugin.Url.csproj | 1 - Plugins/Flow.Launcher.Plugin.Url/Main.cs | 10 +--------- .../SettingsControl.xaml | 17 ----------------- .../SettingsControl.xaml.cs | 18 ------------------ 4 files changed, 1 insertion(+), 45 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml delete mode 100644 Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml.cs 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 3db0cd0cb..6d338733e 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj +++ b/Plugins/Flow.Launcher.Plugin.Url/Flow.Launcher.Plugin.Url.csproj @@ -42,7 +42,6 @@ - diff --git a/Plugins/Flow.Launcher.Plugin.Url/Main.cs b/Plugins/Flow.Launcher.Plugin.Url/Main.cs index 80425a8ff..03516636d 100644 --- a/Plugins/Flow.Launcher.Plugin.Url/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Url/Main.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; using System.Text.RegularExpressions; -using System.Windows.Controls; namespace Flow.Launcher.Plugin.Url { - public class Main : ISettingProvider,IPlugin, IPluginI18n + public class Main : IPlugin, IPluginI18n { //based on https://gist.github.com/dperini/729294 private const string urlPattern = "^" + @@ -43,7 +42,6 @@ namespace Flow.Launcher.Plugin.Url Regex reg = new Regex(urlPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); private PluginInitContext context; private Settings _settings; - public List Query(Query query) { @@ -82,12 +80,6 @@ namespace Flow.Launcher.Plugin.Url return new List(0); } - - public Control CreateSettingPanel() - { - return new SettingsControl(context.API,_settings); - } - public bool IsURL(string raw) { raw = raw.ToLower(); diff --git a/Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml b/Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml deleted file mode 100644 index 8ff7b5ab5..000000000 --- a/Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - diff --git a/Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml.cs b/Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml.cs deleted file mode 100644 index f68d1bb2d..000000000 --- a/Plugins/Flow.Launcher.Plugin.Url/SettingsControl.xaml.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Windows.Controls; - -namespace Flow.Launcher.Plugin.Url -{ - public partial class SettingsControl : UserControl - { - private Settings _settings; - private IPublicAPI _flowlauncherAPI; - - public SettingsControl(IPublicAPI flowlauncherAPI,Settings settings) - { - InitializeComponent(); - _settings = settings; - _flowlauncherAPI = flowlauncherAPI; - - } - } -} From 6e84326f57c45cc44e6ab6a756244d277c9ef884 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 19 Feb 2025 23:43:17 +0800 Subject: [PATCH 0070/1798] Reassign margins --- .../Resources/Controls/InstalledPluginDisplayKeyword.xaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplayKeyword.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplayKeyword.xaml index ff2f14c4b..a88b1a731 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplayKeyword.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplayKeyword.xaml @@ -18,9 +18,9 @@ CornerRadius="0" Style="{DynamicResource SettingGroupBox}" Visibility="{Binding ActionKeywordsVisibility}"> - +  @@ -34,7 +34,6 @@ + + + diff --git a/Flow.Launcher/ReportWindow.xaml.cs b/Flow.Launcher/ReportWindow.xaml.cs index a535dfb3e..12ffe3ffc 100644 --- a/Flow.Launcher/ReportWindow.xaml.cs +++ b/Flow.Launcher/ReportWindow.xaml.cs @@ -6,10 +6,10 @@ using System.Text; using System.Linq; using System.Windows; using System.Windows.Documents; -using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.SharedCommands; +using Flow.Launcher.Infrastructure.Exception; namespace Flow.Launcher { @@ -43,32 +43,36 @@ namespace Flow.Launcher var log = directory.GetFiles().OrderByDescending(f => f.LastWriteTime).First(); var websiteUrl = exception switch - { - FlowPluginException pluginException =>GetIssuesUrl(pluginException.Metadata.Website), - _ => Constant.IssuesUrl - }; - + { + FlowPluginException pluginException =>GetIssuesUrl(pluginException.Metadata.Website), + _ => Constant.IssuesUrl + }; - var paragraph = Hyperlink("Please open new issue in: ", websiteUrl); - paragraph.Inlines.Add($"1. upload log file: {log.FullName}\n"); - paragraph.Inlines.Add($"2. copy below exception message"); + var paragraph = Hyperlink(App.API.GetTranslation("reportWindow_please_open_issue"), websiteUrl); + paragraph.Inlines.Add(string.Format(App.API.GetTranslation("reportWindow_upload_log"), log.FullName)); + paragraph.Inlines.Add("\n"); + paragraph.Inlines.Add(App.API.GetTranslation("reportWindow_copy_below")); ErrorTextbox.Document.Blocks.Add(paragraph); StringBuilder content = new StringBuilder(); - content.AppendLine(ErrorReporting.RuntimeInfo()); - content.AppendLine(ErrorReporting.DependenciesInfo()); - content.AppendLine($"Date: {DateTime.Now.ToString(CultureInfo.InvariantCulture)}"); - content.AppendLine("Exception:"); + content.AppendLine(RuntimeInfo()); + content.AppendLine(); + content.AppendLine(DependenciesInfo()); + content.AppendLine(); + content.AppendLine(string.Format(App.API.GetTranslation("reportWindow_date"), DateTime.Now.ToString(CultureInfo.InvariantCulture))); + content.AppendLine(App.API.GetTranslation("reportWindow_exception")); content.AppendLine(exception.ToString()); paragraph = new Paragraph(); paragraph.Inlines.Add(content.ToString()); ErrorTextbox.Document.Blocks.Add(paragraph); } - private Paragraph Hyperlink(string textBeforeUrl, string url) + private static Paragraph Hyperlink(string textBeforeUrl, string url) { - var paragraph = new Paragraph(); - paragraph.Margin = new Thickness(0); + var paragraph = new Paragraph + { + Margin = new Thickness(0) + }; var link = new Hyperlink { @@ -79,10 +83,38 @@ namespace Flow.Launcher link.Click += (s, e) => SearchWeb.OpenInBrowserTab(url); paragraph.Inlines.Add(textBeforeUrl); + paragraph.Inlines.Add(" "); paragraph.Inlines.Add(link); paragraph.Inlines.Add("\n"); return paragraph; } + + private void BtnCancel_OnClick(object sender, RoutedEventArgs e) + { + Close(); + } + + private static string RuntimeInfo() + { + var info = + $""" + Flow Launcher {App.API.GetTranslation("reportWindow_version")}: {Constant.Version} + OS {App.API.GetTranslation("reportWindow_version")}: {ExceptionFormatter.GetWindowsFullVersionFromRegistry()} + IntPtr {App.API.GetTranslation("reportWindow_length")}: {IntPtr.Size} + x64: {Environment.Is64BitOperatingSystem} + """; + return info; + } + + private static string DependenciesInfo() + { + var info = + $""" + {App.API.GetTranslation("pythonFilePath")}: {Constant.PythonPath} + {App.API.GetTranslation("nodeFilePath")}: {Constant.NodePath} + """; + return info; + } } } From 2b9716aa379c3878bd5ef42bb355e4af6f9a5577 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 22 Feb 2025 13:16:09 +0800 Subject: [PATCH 0094/1798] Fix message box window topmost issue when disabling hide FL when loss focus --- Flow.Launcher.Core/MessageBoxEx.xaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher.Core/MessageBoxEx.xaml b/Flow.Launcher.Core/MessageBoxEx.xaml index fff107a68..28cc02283 100644 --- a/Flow.Launcher.Core/MessageBoxEx.xaml +++ b/Flow.Launcher.Core/MessageBoxEx.xaml @@ -12,6 +12,7 @@ Foreground="{DynamicResource PopupTextColor}" ResizeMode="NoResize" SizeToContent="Height" + Topmost="True" WindowStartupLocation="CenterScreen" mc:Ignorable="d"> From dd73e4b4b3962f46ada29f5a273fa5a21c17cc65 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 22 Feb 2025 15:51:36 +0800 Subject: [PATCH 0095/1798] Fix topmost score issue --- Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index e030d8eae..9bab4a3a1 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1494,7 +1494,7 @@ namespace Flow.Launcher.ViewModel { if (_topMostRecord.IsTopMost(result)) { - result.Score = 100000; //Result.MaxScore; + result.Score = Result.MaxScore; } else { From b46922885c2480b1b6dac5185c658e9e7c8c8aea Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 22 Feb 2025 15:59:38 +0800 Subject: [PATCH 0096/1798] Add max value check --- Flow.Launcher/ViewModel/MainViewModel.cs | 25 +++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 9bab4a3a1..a9809a49a 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1499,9 +1499,28 @@ namespace Flow.Launcher.ViewModel else { var priorityScore = metaResults.Metadata.Priority * 150; - result.Score += result.AddSelectedCount ? - _userSelectedRecord.GetSelectedCount(result) + priorityScore : - priorityScore; + if (result.AddSelectedCount) + { + if ((long)result.Score + _userSelectedRecord.GetSelectedCount(result) + priorityScore > Result.MaxScore) + { + result.Score = Result.MaxScore; + } + else + { + result.Score += _userSelectedRecord.GetSelectedCount(result) + priorityScore; + } + } + else + { + if ((long)result.Score + priorityScore > Result.MaxScore) + { + result.Score = Result.MaxScore; + } + else + { + result.Score += priorityScore; + } + } } } } From 156668e1098287328c691ed2fcb76dcc62490d10 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 22 Feb 2025 16:12:41 +0800 Subject: [PATCH 0097/1798] Add minimize & background option for progress box ex --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/ProgressBoxEx.xaml | 31 ++++++++++++++++++++++++++++- Flow.Launcher/ProgressBoxEx.xaml.cs | 11 +++++++--- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 4c465d61f..d36fd2e90 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -367,6 +367,7 @@ OK Yes No + Background Version diff --git a/Flow.Launcher/ProgressBoxEx.xaml b/Flow.Launcher/ProgressBoxEx.xaml index 3102cfb72..32b0f64b4 100644 --- a/Flow.Launcher/ProgressBoxEx.xaml +++ b/Flow.Launcher/ProgressBoxEx.xaml @@ -35,9 +35,32 @@ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Flow.Launcher/SearchDelaySpeedWindow.xaml.cs b/Flow.Launcher/SearchDelaySpeedWindow.xaml.cs new file mode 100644 index 000000000..5889a1280 --- /dev/null +++ b/Flow.Launcher/SearchDelaySpeedWindow.xaml.cs @@ -0,0 +1,55 @@ +using System.Linq; +using System.Windows; +using Flow.Launcher.Plugin; +using Flow.Launcher.SettingPages.ViewModels; +using Flow.Launcher.ViewModel; +using static Flow.Launcher.SettingPages.ViewModels.SettingsPaneGeneralViewModel; + +namespace Flow.Launcher; + +public partial class SearchDelaySpeedWindow : Window +{ + private readonly PluginViewModel _pluginViewModel; + + public SearchDelaySpeedWindow(PluginViewModel pluginViewModel) + { + InitializeComponent(); + _pluginViewModel = pluginViewModel; + } + + private void SearchDelaySpeed_OnLoaded(object sender, RoutedEventArgs e) + { + tbOldSearchDelaySpeed.Text = _pluginViewModel.SearchDelaySpeedText; + var searchDelaySpeeds = DropdownDataGeneric.GetValues("SearchDelaySpeed"); + SearchDelaySpeedData selected = null; + // Because default value is SearchDelaySpeeds.Slow, we need to get selected value before adding default value + if (_pluginViewModel.PluginSearchDelay != null) + { + selected = searchDelaySpeeds.FirstOrDefault(x => x.Value == _pluginViewModel.PluginSearchDelay); + } + // Add default value to the beginning of the list + // This value should be null + searchDelaySpeeds.Insert(0, new SearchDelaySpeedData { Display = App.API.GetTranslation(PluginViewModel.DefaultLocalizationKey), LocalizationKey = PluginViewModel.DefaultLocalizationKey }); + selected ??= searchDelaySpeeds.FirstOrDefault(); + tbDelay.ItemsSource = searchDelaySpeeds; + tbDelay.SelectedItem = selected; + tbDelay.Focus(); + } + + private void BtnCancel_OnClick(object sender, RoutedEventArgs e) + { + Close(); + } + + private void btnDone_OnClick(object sender, RoutedEventArgs _) + { + // Update search delay speed + var selected = tbDelay.SelectedItem as SearchDelaySpeedData; + SearchDelaySpeeds? changedValue = selected?.LocalizationKey != PluginViewModel.DefaultLocalizationKey ? selected.Value : null; + _pluginViewModel.PluginSearchDelay = changedValue; + + // Update search delay speed text and close window + _pluginViewModel.OnSearchDelaySpeedChanged(); + Close(); + } +} diff --git a/Flow.Launcher/SettingPages/ViewModels/DropdownDataGeneric.cs b/Flow.Launcher/SettingPages/ViewModels/DropdownDataGeneric.cs index 15a814436..c8c119e94 100644 --- a/Flow.Launcher/SettingPages/ViewModels/DropdownDataGeneric.cs +++ b/Flow.Launcher/SettingPages/ViewModels/DropdownDataGeneric.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using Flow.Launcher.Core.Resource; using Flow.Launcher.Plugin; namespace Flow.Launcher.SettingPages.ViewModels; @@ -9,7 +8,7 @@ public class DropdownDataGeneric : BaseModel where TValue : Enum { public string Display { get; set; } public TValue Value { get; private init; } - private string LocalizationKey { get; init; } + public string LocalizationKey { get; set; } public static List GetValues(string keyPrefix) where TR : DropdownDataGeneric, new() { @@ -19,7 +18,7 @@ public class DropdownDataGeneric : BaseModel where TValue : Enum foreach (var value in enumValues) { var key = keyPrefix + value; - var display = InternationalizationManager.Instance.GetTranslation(key); + var display = App.API.GetTranslation(key); data.Add(new TR { Display = display, Value = value, LocalizationKey = key }); } @@ -30,7 +29,7 @@ public class DropdownDataGeneric : BaseModel where TValue : Enum { foreach (var item in options) { - item.Display = InternationalizationManager.Instance.GetTranslation(item.LocalizationKey); + item.Display = App.API.GetTranslation(item.LocalizationKey); } } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 4a729b578..909011579 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -150,7 +150,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public SearchDelaySpeedData SearchDelaySpeed { get => SearchDelaySpeeds.FirstOrDefault(x => x.Value == Settings.SearchDelaySpeed) ?? - SearchDelaySpeeds.FirstOrDefault(x => x.Value == Flow.Launcher.Plugin.SearchDelaySpeeds.Medium) ?? + SearchDelaySpeeds.FirstOrDefault(x => x.Value == Plugin.SearchDelaySpeeds.Medium) ?? SearchDelaySpeeds.FirstOrDefault(); set { diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index e63336235..7ca776512 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -13,6 +13,8 @@ namespace Flow.Launcher.ViewModel { public partial class PluginViewModel : BaseModel { + public const string DefaultLocalizationKey = "default"; + private readonly PluginPair _pluginPair; public PluginPair PluginPair { @@ -127,7 +129,7 @@ namespace Flow.Launcher.ViewModel PluginPair.Metadata.AvgQueryTime + "ms"; public string ActionKeywordsText => string.Join(Query.ActionKeywordSeparator, PluginPair.Metadata.ActionKeywords); public int Priority => PluginPair.Metadata.Priority; - public string SearchDelaySpeedText => PluginPair.Metadata.SearchDelaySpeed == null ? App.API.GetTranslation("default") : App.API.GetTranslation($"SearchDelaySpeed{PluginPair.Metadata.SearchDelaySpeed}"); + public string SearchDelaySpeedText => PluginPair.Metadata.SearchDelaySpeed == null ? App.API.GetTranslation(DefaultLocalizationKey) : App.API.GetTranslation($"SearchDelaySpeed{PluginPair.Metadata.SearchDelaySpeed}"); public Infrastructure.UserSettings.Plugin PluginSettingsObject{ get; init; } public void OnActionKeywordsChanged() @@ -135,6 +137,11 @@ namespace Flow.Launcher.ViewModel OnPropertyChanged(nameof(ActionKeywordsText)); } + public void OnSearchDelaySpeedChanged() + { + OnPropertyChanged(nameof(SearchDelaySpeedText)); + } + public void ChangePriority(int newPriority) { PluginPair.Metadata.Priority = newPriority; @@ -180,8 +187,8 @@ namespace Flow.Launcher.ViewModel [RelayCommand] private void SetSearchDelaySpeed() { - /*var searchDelaySpeedWindow = new SearchDelaySpeedWindow(this); - searchDelaySpeedWindow.ShowDialog();*/ + var searchDelaySpeedWindow = new SearchDelaySpeedWindow(this); + searchDelaySpeedWindow.ShowDialog(); } } } From e9c1cffd3304867f24d2cd2f2c609998c75755d3 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 31 Mar 2025 12:58:27 +0800 Subject: [PATCH 0608/1798] Code quality --- .../UserSettings/Settings.cs | 24 +++---------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index ab0a364d2..fed4b667b 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -320,28 +320,10 @@ namespace Flow.Launcher.Infrastructure.UserSettings public bool LeaveCmdOpen { get; set; } public bool HideWhenDeactivated { get; set; } = true; - bool _searchQueryResultsWithDelay { get; set; } - public bool SearchQueryResultsWithDelay - { - get => _searchQueryResultsWithDelay; - set - { - _searchQueryResultsWithDelay = value; - OnPropertyChanged(); - } - } - - SearchDelaySpeeds searchDelaySpeed { get; set; } = SearchDelaySpeeds.Medium; + public bool SearchQueryResultsWithDelay { get; set; } + [JsonConverter(typeof(JsonStringEnumConverter))] - public SearchDelaySpeeds SearchDelaySpeed - { - get => searchDelaySpeed; - set - { - searchDelaySpeed = value; - OnPropertyChanged(); - } - } + public SearchDelaySpeeds SearchDelaySpeed { get; set; } = SearchDelaySpeeds.Medium; [JsonConverter(typeof(JsonStringEnumConverter))] public SearchWindowScreens SearchWindowScreen { get; set; } = SearchWindowScreens.Cursor; From dec1e77b0ce7dd31aab99661b7505d3cf8bf2a7c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 31 Mar 2025 13:04:41 +0800 Subject: [PATCH 0609/1798] Improve code comments --- Flow.Launcher/SearchDelaySpeedWindow.xaml.cs | 2 +- Flow.Launcher/ViewModel/MainViewModel.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/SearchDelaySpeedWindow.xaml.cs b/Flow.Launcher/SearchDelaySpeedWindow.xaml.cs index 5889a1280..cfbde8be2 100644 --- a/Flow.Launcher/SearchDelaySpeedWindow.xaml.cs +++ b/Flow.Launcher/SearchDelaySpeedWindow.xaml.cs @@ -28,7 +28,7 @@ public partial class SearchDelaySpeedWindow : Window selected = searchDelaySpeeds.FirstOrDefault(x => x.Value == _pluginViewModel.PluginSearchDelay); } // Add default value to the beginning of the list - // This value should be null + // When _pluginViewModel.PluginSearchDelay equals null, we will select this searchDelaySpeeds.Insert(0, new SearchDelaySpeedData { Display = App.API.GetTranslation(PluginViewModel.DefaultLocalizationKey), LocalizationKey = PluginViewModel.DefaultLocalizationKey }); selected ??= searchDelaySpeeds.FirstOrDefault(); tbDelay.ItemsSource = searchDelaySpeeds; diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 309cd67bb..f43931192 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -298,7 +298,7 @@ namespace Flow.Launcher.ViewModel { if (QueryResultsSelected()) { - // When we are requiring, we should not delay the query + // When we are re-querying, we should not delay the query _ = QueryResultsAsync(false, isReQuery: true); } } @@ -306,7 +306,7 @@ namespace Flow.Launcher.ViewModel public void ReQuery(bool reselect) { BackToQueryResults(); - // When we are requiring, we should not delay the query + // When we are re-querying, we should not delay the query _ = QueryResultsAsync(false, isReQuery: true, reSelect: reselect); } @@ -660,7 +660,7 @@ namespace Flow.Launcher.ViewModel } else if (isReQuery) { - // When we are requiring, we should not delay the query + // When we are re-querying, we should not delay the query await QueryAsync(false, isReQuery: true); } From c4cd51c3126db130864d40ce05898962526a6d70 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 31 Mar 2025 13:26:09 +0800 Subject: [PATCH 0610/1798] Change to search delay time --- .../UserSettings/PluginSettings.cs | 12 +++---- .../UserSettings/Settings.cs | 2 +- Flow.Launcher.Plugin/PluginMetadata.cs | 4 +-- Flow.Launcher.Plugin/SearchDelaySpeeds.cs | 32 ----------------- Flow.Launcher.Plugin/SearchDelayTime.cs | 32 +++++++++++++++++ Flow.Launcher/Languages/en.xaml | 26 +++++++------- .../Controls/InstalledPluginSearchDelay.xaml | 8 ++--- Flow.Launcher/SearchDelaySpeedWindow.xaml | 16 ++++----- Flow.Launcher/SearchDelaySpeedWindow.xaml.cs | 36 +++++++++---------- .../SettingsPaneGeneralViewModel.cs | 20 +++++------ .../Views/SettingsPaneGeneral.xaml | 8 ++--- Flow.Launcher/ViewModel/MainViewModel.cs | 13 ++++--- Flow.Launcher/ViewModel/PluginViewModel.cs | 22 ++++++------ .../plugin.json | 2 +- 14 files changed, 115 insertions(+), 118 deletions(-) delete mode 100644 Flow.Launcher.Plugin/SearchDelaySpeeds.cs create mode 100644 Flow.Launcher.Plugin/SearchDelayTime.cs diff --git a/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs b/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs index d1c047495..da92a3583 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs @@ -51,7 +51,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings settings.Version = metadata.Version; } settings.DefaultActionKeywords = metadata.ActionKeywords; // metadata provides default values - settings.DefaultSearchDelaySpeed = metadata.SearchDelaySpeed; // metadata provides default values + settings.DefaultSearchDelayTime = metadata.SearchDelayTime; // metadata provides default values // update metadata values with settings if (settings.ActionKeywords?.Count > 0) @@ -66,7 +66,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings } metadata.Disabled = settings.Disabled; metadata.Priority = settings.Priority; - metadata.SearchDelaySpeed = settings.SearchDelaySpeed; + metadata.SearchDelayTime = settings.SearchDelayTime; } else { @@ -80,8 +80,8 @@ namespace Flow.Launcher.Infrastructure.UserSettings ActionKeywords = metadata.ActionKeywords, // use default value Disabled = metadata.Disabled, Priority = metadata.Priority, - DefaultSearchDelaySpeed = metadata.SearchDelaySpeed, // metadata provides default values - SearchDelaySpeed = metadata.SearchDelaySpeed, // use default value + DefaultSearchDelayTime = metadata.SearchDelayTime, // metadata provides default values + SearchDelayTime = metadata.SearchDelayTime, // use default value }; } } @@ -120,10 +120,10 @@ namespace Flow.Launcher.Infrastructure.UserSettings public int Priority { get; set; } [JsonIgnore] - public SearchDelaySpeeds? DefaultSearchDelaySpeed { get; set; } + public SearchDelayTime? DefaultSearchDelayTime { get; set; } [JsonConverter(typeof(JsonStringEnumConverter))] - public SearchDelaySpeeds? SearchDelaySpeed { get; set; } + public SearchDelayTime? SearchDelayTime { get; set; } /// /// Used only to save the state of the plugin in settings diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index fed4b667b..fcfbe8ca0 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -323,7 +323,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings public bool SearchQueryResultsWithDelay { get; set; } [JsonConverter(typeof(JsonStringEnumConverter))] - public SearchDelaySpeeds SearchDelaySpeed { get; set; } = SearchDelaySpeeds.Medium; + public SearchDelayTime SearchDelayTime { get; set; } = SearchDelayTime.Medium; [JsonConverter(typeof(JsonStringEnumConverter))] public SearchWindowScreens SearchWindowScreen { get; set; } = SearchWindowScreens.Cursor; diff --git a/Flow.Launcher.Plugin/PluginMetadata.cs b/Flow.Launcher.Plugin/PluginMetadata.cs index 42b623717..1496765ce 100644 --- a/Flow.Launcher.Plugin/PluginMetadata.cs +++ b/Flow.Launcher.Plugin/PluginMetadata.cs @@ -99,10 +99,10 @@ namespace Flow.Launcher.Plugin public bool HideActionKeywordPanel { get; set; } /// - /// Plugin search delay speed. Null means use default search delay. + /// Plugin search delay time. Null means use default search delay time. /// [JsonConverter(typeof(JsonStringEnumConverter))] - public SearchDelaySpeeds? SearchDelaySpeed { get; set; } = null; + public SearchDelayTime? SearchDelayTime { get; set; } = null; /// /// Plugin icon path. diff --git a/Flow.Launcher.Plugin/SearchDelaySpeeds.cs b/Flow.Launcher.Plugin/SearchDelaySpeeds.cs deleted file mode 100644 index 543f8b3f6..000000000 --- a/Flow.Launcher.Plugin/SearchDelaySpeeds.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace Flow.Launcher.Plugin; - -/// -/// Enum for search delay speeds -/// -public enum SearchDelaySpeeds -{ - /// - /// Slow search delay speed. 50ms. - /// - Slow, - - /// - /// Moderately slow search delay speed. 100ms. - /// - ModeratelySlow, - - /// - /// Medium search delay speed. 150ms. Default value. - /// - Medium, - - /// - /// Moderately fast search delay speed. 200ms. - /// - ModeratelyFast, - - /// - /// Fast search delay speed. 250ms. - /// - Fast -} diff --git a/Flow.Launcher.Plugin/SearchDelayTime.cs b/Flow.Launcher.Plugin/SearchDelayTime.cs new file mode 100644 index 000000000..8dae5997e --- /dev/null +++ b/Flow.Launcher.Plugin/SearchDelayTime.cs @@ -0,0 +1,32 @@ +namespace Flow.Launcher.Plugin; + +/// +/// Enum for search delay time +/// +public enum SearchDelayTime +{ + /// + /// Long search delay time. 250ms. + /// + Long, + + /// + /// Moderately long search delay time. 200ms. + /// + ModeratelyLong, + + /// + /// Medium search delay time. 150ms. Default value. + /// + Medium, + + /// + /// Moderately short search delay time. 100ms. + /// + ModeratelyShort, + + /// + /// Short search delay time. 50ms. + /// + Short +} diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index ae930db70..e6a764d48 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -104,13 +104,13 @@ Shadow effect is not allowed while current theme has blur effect enabled Search Delay Delay for a while to search when typing. This reduces interface jumpiness and result load. - Default Search Delay Speed - Plugins default delay time after which search results appear when typing is stopped. Default is medium. - Slow - Moderately slow - Medium - Moderately fast - Fast + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. Default is "Medium". + Long + Moderately long + Medium + Moderately short + Short Search Plugin @@ -127,8 +127,8 @@ Current action keyword New action keyword Change Action Keywords - Plugin seach delay speed - Change Plugin Seach Delay Speed + Plugin seach delay time + Change Plugin Seach Delay Time Current Priority New Priority Priority @@ -366,10 +366,10 @@ 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 Speed Setting - Select the search delay speed you like to use for the plugin. Select Default if you don't want to specify any, and the plugin will use default search delay speed. - Current search delay speed - New search delay speed + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Custom Query Hotkey diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelay.xaml index bd2f9a7c9..0fd98bfac 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelay.xaml @@ -32,18 +32,18 @@ VerticalAlignment="Center" DockPanel.Dock="Left" Style="{DynamicResource SettingTitleLabel}" - Text="{DynamicResource pluginSearchDelaySpeed}" /> + Text="{DynamicResource pluginSearchDelayTime}" /> - + --> + + + + + + + + + + OnContent="{DynamicResource enable}" + Visibility="Collapsed" /> From eeb9ea78fdc39014f806263145ca5eb64b8d4651 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 31 Mar 2025 21:27:59 +0800 Subject: [PATCH 0621/1798] Code quality --- .../Environments/AbstractPluginEnvironment.cs | 50 +++++++++---------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs index 7e9cc9a48..f80e573f9 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs @@ -1,15 +1,14 @@ -using Flow.Launcher.Infrastructure.Logger; -using Flow.Launcher.Infrastructure.UserSettings; -using Flow.Launcher.Plugin; -using Flow.Launcher.Plugin.SharedCommands; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Windows; using System.Windows.Forms; -using Flow.Launcher.Core.Resource; using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Core.ExternalPlugins.Environments { @@ -43,8 +42,11 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal IEnumerable Setup() { + // If no plugin is using the language, return empty list if (!PluginMetadataList.Any(o => o.Language.Equals(Language, StringComparison.OrdinalIgnoreCase))) + { return new List(); + } if (!string.IsNullOrEmpty(PluginsSettingsFilePath) && FilesFolders.FileExists(PluginsSettingsFilePath)) { @@ -56,24 +58,21 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } var noRuntimeMessage = string.Format( - InternationalizationManager.Instance.GetTranslation("runtimePluginInstalledChooseRuntimePrompt"), + API.GetTranslation("runtimePluginInstalledChooseRuntimePrompt"), Language, EnvName, Environment.NewLine ); if (API.ShowMsgBox(noRuntimeMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.No) { - var msg = string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginChooseRuntimeExecutable"), EnvName); - string selectedFile; + var msg = string.Format(API.GetTranslation("runtimePluginChooseRuntimeExecutable"), EnvName); - selectedFile = GetFileFromDialog(msg, FileDialogFilter); + var selectedFile = GetFileFromDialog(msg, FileDialogFilter); - if (!string.IsNullOrEmpty(selectedFile)) - PluginsSettingsFilePath = selectedFile; + if (!string.IsNullOrEmpty(selectedFile)) PluginsSettingsFilePath = selectedFile; // Nothing selected because user pressed cancel from the file dialog window - if (string.IsNullOrEmpty(selectedFile)) - InstallEnvironment(); + if (string.IsNullOrEmpty(selectedFile)) InstallEnvironment(); } else { @@ -86,7 +85,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments } else { - API.ShowMsgBox(string.Format(InternationalizationManager.Instance.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language)); + API.ShowMsgBox(string.Format(API.GetTranslation("runtimePluginUnableToSetExecutablePath"), Language)); Log.Error("PluginsLoader", $"Not able to successfully set {EnvName} path, setting's plugin executable path variable is still an empty string.", $"{Language}Environment"); @@ -99,13 +98,11 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments private void EnsureLatestInstalled(string expectedPath, string currentPath, string installedDirPath) { - if (expectedPath == currentPath) - return; + if (expectedPath == currentPath) return; FilesFolders.RemoveFolderIfExists(installedDirPath, (s) => API.ShowMsgBox(s)); InstallEnvironment(); - } internal abstract PluginPair CreatePluginPair(string filePath, PluginMetadata metadata); @@ -126,7 +123,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments return pluginPairs; } - private string GetFileFromDialog(string title, string filter = "") + private static string GetFileFromDialog(string title, string filter = "") { var dlg = new OpenFileDialog { @@ -140,7 +137,6 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments var result = dlg.ShowDialog(); return result == DialogResult.OK ? dlg.FileName : string.Empty; - } /// @@ -183,31 +179,33 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments else { if (IsUsingPortablePath(settings.PluginSettings.PythonExecutablePath, DataLocation.PythonEnvironmentName)) + { settings.PluginSettings.PythonExecutablePath = GetUpdatedEnvironmentPath(settings.PluginSettings.PythonExecutablePath); + } if (IsUsingPortablePath(settings.PluginSettings.NodeExecutablePath, DataLocation.NodeEnvironmentName)) + { settings.PluginSettings.NodeExecutablePath = GetUpdatedEnvironmentPath(settings.PluginSettings.NodeExecutablePath); + } } } private static bool IsUsingPortablePath(string filePath, string pluginEnvironmentName) { - if (string.IsNullOrEmpty(filePath)) - return false; + if (string.IsNullOrEmpty(filePath)) return false; // DataLocation.PortableDataPath returns the current portable path, this determines if an out // of date path is also a portable path. - var portableAppEnvLocation = $"UserData\\{DataLocation.PluginEnvironments}\\{pluginEnvironmentName}"; + var portableAppEnvLocation = Path.Combine("UserData", DataLocation.PluginEnvironments, pluginEnvironmentName); return filePath.Contains(portableAppEnvLocation); } private static bool IsUsingRoamingPath(string filePath) { - if (string.IsNullOrEmpty(filePath)) - return false; + if (string.IsNullOrEmpty(filePath)) return false; return filePath.StartsWith(DataLocation.RoamingDataPath); } @@ -217,7 +215,7 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments var index = filePath.IndexOf(DataLocation.PluginEnvironments); // get the substring after "Environments" because we can not determine it dynamically - var ExecutablePathSubstring = filePath.Substring(index + DataLocation.PluginEnvironments.Count()); + var ExecutablePathSubstring = filePath[(index + DataLocation.PluginEnvironments.Length)..]; return $"{DataLocation.PluginEnvironmentsPath}{ExecutablePathSubstring}"; } } From 5fa244c806c430d35325ae30aa1dc22c5c6c4d40 Mon Sep 17 00:00:00 2001 From: DB p Date: Mon, 31 Mar 2025 22:44:34 +0900 Subject: [PATCH 0622/1798] Add setting filter --- .../Converters/StringEqualityToVisibilityConverter.cs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs diff --git a/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs b/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs new file mode 100644 index 000000000..4757681bc --- /dev/null +++ b/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs @@ -0,0 +1,6 @@ +namespace Flow.Launcher.Converters; + +public class StringEqualityToVisibilityConverter +{ + +} From 0136c570faf3d8cdf4e7094054a1ed0cd62103c5 Mon Sep 17 00:00:00 2001 From: DB p Date: Mon, 31 Mar 2025 22:44:46 +0900 Subject: [PATCH 0623/1798] Add Setting Filter --- .../StringEqualityToVisibilityConverter.cs | 23 ++++- .../Controls/InstalledPluginDisplay.xaml | 34 +++++-- .../SettingsPanePluginsViewModel.cs | 69 +++++++++++++++ .../Views/SettingsPanePlugins.xaml | 88 ++++++++++--------- Flow.Launcher/ViewModel/PluginViewModel.cs | 14 ++- 5 files changed, 172 insertions(+), 56 deletions(-) diff --git a/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs b/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs index 4757681bc..4e4453636 100644 --- a/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs +++ b/Flow.Launcher/Converters/StringEqualityToVisibilityConverter.cs @@ -1,6 +1,23 @@ -namespace Flow.Launcher.Converters; +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; -public class StringEqualityToVisibilityConverter +namespace Flow.Launcher.Converters { - + public class StringEqualityToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null || parameter == null) + return Visibility.Collapsed; + + return value.ToString() == parameter.ToString() ? Visibility.Visible : Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } } diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 74edd2dea..ca9f673d8 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -7,10 +7,14 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:viewModel="clr-namespace:Flow.Launcher.ViewModel" + xmlns:converters="clr-namespace:Flow.Launcher.Converters" d:DataContext="{d:DesignInstance viewModel:PluginViewModel}" d:DesignHeight="300" d:DesignWidth="300" mc:Ignorable="d"> + + + + Visibility="{Binding DataContext.CurrentDisplayMode, + RelativeSource={RelativeSource AncestorType=ListBox}, + Converter={StaticResource StringEqualityToVisibilityConverter}, + ConverterParameter=Priority}"> + Margin="0 0 8 0" + VerticalAlignment="Center" + FontSize="13" + Foreground="{DynamicResource Color08B}" + Text="{DynamicResource priority}" /> + + Visibility="{Binding DataContext.CurrentDisplayMode, + RelativeSource={RelativeSource AncestorType=ListBox}, + Converter={StaticResource StringEqualityToVisibilityConverter}, + ConverterParameter=SearchDelay}"> + - + Visibility="{Binding DataContext.CurrentDisplayMode, + RelativeSource={RelativeSource AncestorType=ListBox}, + Converter={StaticResource StringEqualityToVisibilityConverter}, + ConverterParameter=OnOff}" /> + diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index 3c1aba400..5cd14ba7e 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -14,6 +14,75 @@ public class SettingsPanePluginsViewModel : BaseModel { private readonly Settings _settings; + private bool _isOnOffSelected = true; + public bool IsOnOffSelected + { + get => _isOnOffSelected; + set + { + if (_isOnOffSelected != value) + { + _isOnOffSelected = value; + OnPropertyChanged(nameof(IsOnOffSelected)); + UpdateDisplayMode(); + } + } + } + + private bool _isPrioritySelected; + public bool IsPrioritySelected + { + get => _isPrioritySelected; + set + { + if (_isPrioritySelected != value) + { + _isPrioritySelected = value; + OnPropertyChanged(nameof(IsPrioritySelected)); + UpdateDisplayMode(); + } + } + } + + private bool _isSearchDelaySelected; + public bool IsSearchDelaySelected + { + get => _isSearchDelaySelected; + set + { + if (_isSearchDelaySelected != value) + { + _isSearchDelaySelected = value; + OnPropertyChanged(nameof(IsSearchDelaySelected)); + UpdateDisplayMode(); + } + } + } + + private string _currentDisplayMode = "OnOff"; + public string CurrentDisplayMode + { + get => _currentDisplayMode; + set + { + if (_currentDisplayMode != value) + { + _currentDisplayMode = value; + OnPropertyChanged(nameof(CurrentDisplayMode)); + } + } + } + + private void UpdateDisplayMode() + { + if (IsOnOffSelected) + CurrentDisplayMode = "OnOff"; + else if (IsPrioritySelected) + CurrentDisplayMode = "Priority"; + else if (IsSearchDelaySelected) + CurrentDisplayMode = "SearchDelay"; + } + public SettingsPanePluginsViewModel(Settings settings) { _settings = settings; diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml b/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml index 37079a46f..7580a5591 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml @@ -6,6 +6,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:ui="http://schemas.modernwpf.com/2019" + xmlns:converters="clr-namespace:Flow.Launcher.Converters" xmlns:viewModels="clr-namespace:Flow.Launcher.SettingPages.ViewModels" xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls" Title="Plugins" @@ -17,6 +18,7 @@ mc:Ignorable="d"> + @@ -31,51 +33,51 @@ Style="{StaticResource PageTitle}" Text="{DynamicResource plugins}" TextAlignment="Left" /> - - - - - + Orientation="Horizontal" + HorizontalAlignment="Right" + VerticalAlignment="Center"> + + + + + + + string.Join(Query.ActionKeywordSeparator, PluginPair.Metadata.ActionKeywords); - public int Priority => PluginPair.Metadata.Priority; + //public int Priority => PluginPair.Metadata.Priority; + private int _priority; + public int Priority + { + get => PluginPair.Metadata.Priority; + set + { + if (PluginPair.Metadata.Priority != value) + { + ChangePriority(value); + } + } + } public string SearchDelayTimeText => PluginPair.Metadata.SearchDelayTime == null ? App.API.GetTranslation("default") : App.API.GetTranslation($"SearchDelayTime{PluginPair.Metadata.SearchDelayTime}"); From cc1e6dd7eeb40218e1c89b6399530d6db9c5a8e7 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 31 Mar 2025 21:53:33 +0800 Subject: [PATCH 0624/1798] Fix theme select initialization issue --- Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index 4467b94fb..31faeba52 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -9,9 +9,13 @@ namespace Flow.Launcher.Plugin.Sys { public const string Keyword = "fltheme"; - private readonly Theme _theme; private readonly PluginInitContext _context; + // Do not initialize it in the constructor, because it will cause null reference in + // var dicts = Application.Current.Resources.MergedDictionaries; line of Theme + private Theme theme = null; + private Theme Theme => theme ??= Ioc.Default.GetRequiredService(); + #region Theme Selection // Theme select codes simplified from SettingsPaneThemeViewModel.cs @@ -19,24 +23,23 @@ namespace Flow.Launcher.Plugin.Sys private Theme.ThemeData _selectedTheme; public Theme.ThemeData SelectedTheme { - get => _selectedTheme ??= Themes.Find(v => v.FileNameWithoutExtension == _theme.GetCurrentTheme()); + get => _selectedTheme ??= Themes.Find(v => v.FileNameWithoutExtension == Theme.GetCurrentTheme()); set { _selectedTheme = value; - _theme.ChangeTheme(value.FileNameWithoutExtension); + Theme.ChangeTheme(value.FileNameWithoutExtension); - _ = _theme.RefreshFrameAsync(); + _ = Theme.RefreshFrameAsync(); } } - private List Themes => _theme.LoadAvailableThemes(); + private List Themes => Theme.LoadAvailableThemes(); #endregion public ThemeSelector(PluginInitContext context) { _context = context; - _theme = Ioc.Default.GetRequiredService(); } public List Query(Query query) From fb50e6d08f6a31e4e43983867bfff3384acad300 Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 1 Apr 2025 05:03:49 +0900 Subject: [PATCH 0625/1798] Add search delay control --- Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index ca9f673d8..009644fd6 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -120,9 +120,7 @@ RelativeSource={RelativeSource AncestorType=ListBox}, Converter={StaticResource StringEqualityToVisibilityConverter}, ConverterParameter=SearchDelay}"> - From d77400d39bbe1dbc7ae476326dfce66e3748f93f Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 1 Apr 2025 05:36:24 +0900 Subject: [PATCH 0626/1798] Add customcontrol for searchdelay --- .../Controls/InstalledPluginDisplay.xaml | 5 +- .../InstalledPluginSearchDelayCombobox.xaml | 39 +++++++++ ...InstalledPluginSearchDelayCombobox.xaml.cs | 84 +++++++++++++++++++ 3 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml create mode 100644 Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml.cs diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 009644fd6..cb1d8dbc4 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -92,7 +92,7 @@ - - diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml new file mode 100644 index 000000000..b379b875f --- /dev/null +++ b/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml @@ -0,0 +1,39 @@ + + + + + + + + \ No newline at end of file diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml.cs b/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml.cs new file mode 100644 index 000000000..649913872 --- /dev/null +++ b/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelayCombobox.xaml.cs @@ -0,0 +1,84 @@ +using System.Collections.Generic; +using System.Windows.Controls; +using Flow.Launcher.Plugin; + +namespace Flow.Launcher.Resources.Controls +{ + public partial class InstalledPluginSearchDelayCombobox + { + public InstalledPluginSearchDelayCombobox() + { + InitializeComponent(); + LoadDelayOptions(); + Loaded += InstalledPluginSearchDelayCombobox_Loaded; + } + + private void InstalledPluginSearchDelayCombobox_Loaded(object sender, System.Windows.RoutedEventArgs e) + { + if (DataContext is ViewModel.PluginViewModel viewModel) + { + // 초기 값 설정 + int currentDelayMs = GetCurrentDelayMs(viewModel); + foreach (DelayOption option in cbDelay.Items) + { + if (option.Value == currentDelayMs) + { + cbDelay.SelectedItem = option; + break; + } + } + } + } + + private int GetCurrentDelayMs(ViewModel.PluginViewModel viewModel) + { + // SearchDelayTime enum 값을 int로 변환 + SearchDelayTime? delayTime = viewModel.PluginPair.Metadata.SearchDelayTime; + if (delayTime.HasValue) + { + return (int)delayTime.Value; + } + return 0; // 기본값 + } + + private void LoadDelayOptions() + { + // 검색 지연 시간 옵션들 (SearchDelayTime enum 값에 맞춰야 함) + var delayOptions = new List + { + new DelayOption { Display = "0 ms", Value = 0 }, + new DelayOption { Display = "50 ms", Value = 50 }, + new DelayOption { Display = "100 ms", Value = 100 }, + new DelayOption { Display = "150 ms", Value = 150 }, + new DelayOption { Display = "200 ms", Value = 200 }, + new DelayOption { Display = "250 ms", Value = 250 }, + new DelayOption { Display = "300 ms", Value = 300 }, + new DelayOption { Display = "350 ms", Value = 350 }, + new DelayOption { Display = "400 ms", Value = 400 }, + new DelayOption { Display = "450 ms", Value = 450 }, + new DelayOption { Display = "500 ms", Value = 500 }, + }; + + cbDelay.ItemsSource = delayOptions; + } + + private void CbDelay_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (DataContext is ViewModel.PluginViewModel viewModel && cbDelay.SelectedItem is DelayOption selectedOption) + { + // int 값을 SearchDelayTime enum으로 변환 + int delayValue = selectedOption.Value; + viewModel.PluginPair.Metadata.SearchDelayTime = (SearchDelayTime)delayValue; + + // 설정 저장 + //How to save? + } + } + } + + public class DelayOption + { + public string Display { get; set; } + public int Value { get; set; } + } +} From bf259dcb13eb0258417f79e1858303717c32a1e9 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 08:47:57 +0800 Subject: [PATCH 0627/1798] Fix application dispose issue --- Flow.Launcher/App.xaml.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 7b1d113fb..9aee56bff 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -138,6 +138,11 @@ namespace Flow.Launcher { await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () => { + // Because new message box api uses MessageBoxEx window, + // if it is created and closed before main window is created, it will cause the application to exit. + // So set to OnExplicitShutdown to prevent the application from shutting down before main window is created + Current.ShutdownMode = ShutdownMode.OnExplicitShutdown; + Log.SetLogLevel(_settings.LogLevel); Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate(); From 6a2b3495a009927c8593de42a3c21020f01c12d7 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 09:26:39 +0800 Subject: [PATCH 0628/1798] Ask reselect environment path until it is valid --- .../Environments/AbstractPluginEnvironment.cs | 40 +++++++++++++++++-- Flow.Launcher/Languages/en.xaml | 5 +++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs index f80e573f9..0bd00d982 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs @@ -69,10 +69,44 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments var selectedFile = GetFileFromDialog(msg, FileDialogFilter); - if (!string.IsNullOrEmpty(selectedFile)) PluginsSettingsFilePath = selectedFile; - + if (!string.IsNullOrEmpty(selectedFile)) + { + PluginsSettingsFilePath = selectedFile; + } // Nothing selected because user pressed cancel from the file dialog window - if (string.IsNullOrEmpty(selectedFile)) InstallEnvironment(); + else + { + var forceDownloadMessage = string.Format( + API.GetTranslation("runtimeExecutableInvalidChooseDownload"), + Language, + EnvName, + Environment.NewLine + ); + + // Let users select valid path or choose to download + while (string.IsNullOrEmpty(selectedFile)) + { + if (API.ShowMsgBox(forceDownloadMessage, string.Empty, MessageBoxButton.YesNo) == MessageBoxResult.Yes) + { + // Continue select file + selectedFile = GetFileFromDialog(msg, FileDialogFilter); + } + else + { + // User selected no, break the loop + break; + } + } + + if (!string.IsNullOrEmpty(selectedFile)) + { + PluginsSettingsFilePath = selectedFile; + } + else + { + InstallEnvironment(); + } + } } else { diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 3c0e5b153..2df430c3b 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -9,6 +9,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help From a9dfd1b377d2129cf74a51171386db84bc486a78 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 09:57:04 +0800 Subject: [PATCH 0629/1798] Code quality --- .../Environments/AbstractPluginEnvironment.cs | 4 ++-- .../Environments/PythonEnvironment.cs | 12 ++++++++---- .../Environments/TypeScriptEnvironment.cs | 14 +++++++++----- .../Environments/TypeScriptV2Environment.cs | 14 +++++++++----- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs index 0bd00d982..bbb6cf638 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/AbstractPluginEnvironment.cs @@ -249,8 +249,8 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments 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}"; + var executablePathSubstring = filePath[(index + DataLocation.PluginEnvironments.Length)..]; + return $"{DataLocation.PluginEnvironmentsPath}{executablePathSubstring}"; } } } diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs index 607c19062..fab5738de 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/PythonEnvironment.cs @@ -1,10 +1,10 @@ -using Droplex; +using System.Collections.Generic; +using System.IO; +using Droplex; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedCommands; -using System.Collections.Generic; -using System.IO; namespace Flow.Launcher.Core.ExternalPlugins.Environments { @@ -22,7 +22,11 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal override string FileDialogFilter => "Python|pythonw.exe"; - internal override string PluginsSettingsFilePath { get => PluginSettings.PythonExecutablePath; set => PluginSettings.PythonExecutablePath = value; } + internal override string PluginsSettingsFilePath + { + get => PluginSettings.PythonExecutablePath; + set => PluginSettings.PythonExecutablePath = value; + } internal PythonEnvironment(List pluginMetadataList, PluginsSettings pluginSettings) : base(pluginMetadataList, pluginSettings) { } diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs index 399f7cc03..8a4f527ba 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptEnvironment.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; -using Droplex; -using Flow.Launcher.Infrastructure.UserSettings; -using Flow.Launcher.Plugin.SharedCommands; -using Flow.Launcher.Plugin; using System.IO; +using Droplex; using Flow.Launcher.Core.Plugin; +using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Core.ExternalPlugins.Environments { @@ -19,7 +19,11 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal override string InstallPath => Path.Combine(EnvPath, "Node-v16.18.0"); internal override string ExecutablePath => Path.Combine(InstallPath, "node-v16.18.0-win-x64\\node.exe"); - internal override string PluginsSettingsFilePath { get => PluginSettings.NodeExecutablePath; set => PluginSettings.NodeExecutablePath = value; } + internal override string PluginsSettingsFilePath + { + get => PluginSettings.NodeExecutablePath; + set => PluginSettings.NodeExecutablePath = value; + } internal TypeScriptEnvironment(List pluginMetadataList, PluginsSettings pluginSettings) : base(pluginMetadataList, pluginSettings) { } diff --git a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs index e8cb72e11..61fd28376 100644 --- a/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs +++ b/Flow.Launcher.Core/ExternalPlugins/Environments/TypeScriptV2Environment.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; -using Droplex; -using Flow.Launcher.Infrastructure.UserSettings; -using Flow.Launcher.Plugin.SharedCommands; -using Flow.Launcher.Plugin; using System.IO; +using Droplex; using Flow.Launcher.Core.Plugin; +using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Core.ExternalPlugins.Environments { @@ -19,7 +19,11 @@ namespace Flow.Launcher.Core.ExternalPlugins.Environments internal override string InstallPath => Path.Combine(EnvPath, "Node-v16.18.0"); internal override string ExecutablePath => Path.Combine(InstallPath, "node-v16.18.0-win-x64\\node.exe"); - internal override string PluginsSettingsFilePath { get => PluginSettings.NodeExecutablePath; set => PluginSettings.NodeExecutablePath = value; } + internal override string PluginsSettingsFilePath + { + get => PluginSettings.NodeExecutablePath; + set => PluginSettings.NodeExecutablePath = value; + } internal TypeScriptV2Environment(List pluginMetadataList, PluginsSettings pluginSettings) : base(pluginMetadataList, pluginSettings) { } From f9c1b6aa3e4dd7052f484e8518e92fffbe234861 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 09:57:55 +0800 Subject: [PATCH 0630/1798] Adjust usings --- Flow.Launcher.Core/Plugin/PluginManager.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 4f869901c..17517832b 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -1,20 +1,19 @@ -using Flow.Launcher.Core.ExternalPlugins; -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; 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.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; -using ISavable = Flow.Launcher.Plugin.ISavable; using Flow.Launcher.Plugin.SharedCommands; -using System.Text.Json; -using Flow.Launcher.Core.Resource; -using CommunityToolkit.Mvvm.DependencyInjection; +using ISavable = Flow.Launcher.Plugin.ISavable; namespace Flow.Launcher.Core.Plugin { From 6f0126d3ba3f4ab8c6928141287391602d77cf1f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 11:47:18 +0800 Subject: [PATCH 0631/1798] Add log error api function for csharp and jsonrpc --- .../Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs | 8 ++++++-- Flow.Launcher.Infrastructure/Logger/Log.cs | 11 ++--------- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 5 +++++ Flow.Launcher/PublicAPIInstance.cs | 3 +++ 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs index 8df2ce9ed..102d0089f 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs @@ -12,7 +12,7 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models { public class JsonRPCPublicAPI { - private IPublicAPI _api; + private readonly IPublicAPI _api; public JsonRPCPublicAPI(IPublicAPI api) { @@ -104,7 +104,6 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models return _api.GetAllPlugins(); } - public MatchResult FuzzySearch(string query, string stringToCompare) { return _api.FuzzySearch(query, stringToCompare); @@ -156,6 +155,11 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models _api.LogWarn(className, message, methodName); } + public void LogError(string className, string message, [CallerMemberName] string methodName = "") + { + _api.LogError(className, message, methodName); + } + public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null) { _api.OpenDirectory(DirectoryPath, FileNameOrFilePath); diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs index 9f5d6725e..9e1173f34 100644 --- a/Flow.Launcher.Infrastructure/Logger/Log.cs +++ b/Flow.Launcher.Infrastructure/Logger/Log.cs @@ -1,12 +1,12 @@ using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; +using System.Runtime.ExceptionServices; +using Flow.Launcher.Infrastructure.UserSettings; using NLog; using NLog.Config; using NLog.Targets; -using Flow.Launcher.Infrastructure.UserSettings; using NLog.Targets.Wrappers; -using System.Runtime.ExceptionServices; namespace Flow.Launcher.Infrastructure.Logger { @@ -135,13 +135,6 @@ namespace Flow.Launcher.Infrastructure.Logger return className; } - private static void ExceptionInternal(string classAndMethod, string message, System.Exception e) - { - var logger = LogManager.GetLogger(classAndMethod); - - logger.Error(e, message); - } - private static void LogInternal(string message, LogLevel level) { if (FormatValid(message)) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index f178ebb90..9258e5147 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -227,6 +227,11 @@ namespace Flow.Launcher.Plugin /// void LogWarn(string className, string message, [CallerMemberName] string methodName = ""); + /// + /// Log error message + /// + void LogError(string className, string message, [CallerMemberName] string methodName = ""); + /// /// Log an Exception. Will throw if in debug mode so developer will be aware, /// otherwise logs the eror message. This is the primary logging method used for Flow diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index e19ad2fdc..31307b668 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -187,6 +187,9 @@ namespace Flow.Launcher public void LogWarn(string className, string message, [CallerMemberName] string methodName = "") => Log.Warn(className, message, methodName); + public void LogError(string className, string message, [CallerMemberName] string methodName = "") => + Log.Error(className, message, methodName); + public void LogException(string className, string message, Exception e, [CallerMemberName] string methodName = "") => Log.Exception(className, message, e, methodName); From 1381248e9e71444b56704548167830010f97ac68 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 11:54:18 +0800 Subject: [PATCH 0632/1798] Adjust code formats --- Flow.Launcher/PublicAPIInstance.cs | 35 ++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 31307b668..2d2713e79 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -11,9 +11,9 @@ using System.Threading; using System.Threading.Tasks; using System.Windows; using CommunityToolkit.Mvvm.DependencyInjection; -using Squirrel; using Flow.Launcher.Core; using Flow.Launcher.Core.Plugin; +using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Http; @@ -27,7 +27,7 @@ using Flow.Launcher.Plugin.SharedModels; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.ViewModel; using JetBrains.Annotations; -using Flow.Launcher.Core.Resource; +using Squirrel; namespace Flow.Launcher { @@ -78,7 +78,11 @@ namespace Flow.Launcher public bool IsMainWindowVisible() => _mainVM.MainWindowVisibilityStatus; - public event VisibilityChangedEventHandler VisibilityChanged { add => _mainVM.VisibilityChanged += value; remove => _mainVM.VisibilityChanged -= value; } + public event VisibilityChangedEventHandler VisibilityChanged + { + add => _mainVM.VisibilityChanged += value; + remove => _mainVM.VisibilityChanged -= value; + } // Must use Ioc.Default.GetRequiredService() to avoid circular dependency public void CheckForNewUpdate() => _ = Ioc.Default.GetRequiredService().UpdateAppAsync(false); @@ -162,13 +166,14 @@ namespace Flow.Launcher public MatchResult FuzzySearch(string query, string stringToCompare) => StringMatcher.FuzzySearch(query, stringToCompare); - public Task HttpGetStringAsync(string url, CancellationToken token = default) => Http.GetAsync(url, token); + public Task HttpGetStringAsync(string url, CancellationToken token = default) => + Http.GetAsync(url, token); public Task HttpGetStreamAsync(string url, CancellationToken token = default) => Http.GetStreamAsync(url, token); public Task HttpDownloadAsync([NotNull] string url, [NotNull] string filePath, Action reportProgress = null, - CancellationToken token = default) => Http.DownloadAsync(url, filePath, reportProgress, token); + CancellationToken token = default) =>Http.DownloadAsync(url, filePath, reportProgress, token); public void AddActionKeyword(string pluginId, string newActionKeyword) => PluginManager.AddActionKeyword(pluginId, newActionKeyword); @@ -190,8 +195,8 @@ namespace Flow.Launcher public void LogError(string className, string message, [CallerMemberName] string methodName = "") => Log.Error(className, message, methodName); - public void LogException(string className, string message, Exception e, - [CallerMemberName] string methodName = "") => Log.Exception(className, message, e, methodName); + public void LogException(string className, string message, Exception e, [CallerMemberName] string methodName = "") => + Log.Exception(className, message, e, methodName); private readonly ConcurrentDictionary _pluginJsonStorages = new(); @@ -204,7 +209,7 @@ namespace Flow.Launcher var name = value.GetType().GetField("AssemblyName")?.GetValue(value)?.ToString(); if (name == assemblyName) { - _pluginJsonStorages.Remove(key, out var pluginJsonStorage); + _pluginJsonStorages.Remove(key, out var _); } } } @@ -333,17 +338,23 @@ namespace Flow.Launcher private readonly List> _globalKeyboardHandlers = new(); - public void RegisterGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Add(callback); - public void RemoveGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Remove(callback); + public void RegisterGlobalKeyboardCallback(Func callback) => + _globalKeyboardHandlers.Add(callback); + + public void RemoveGlobalKeyboardCallback(Func callback) => + _globalKeyboardHandlers.Remove(callback); public void ReQuery(bool reselect = true) => _mainVM.ReQuery(reselect); public void BackToQueryResults() => _mainVM.BackToQueryResults(); - public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, MessageBoxResult defaultResult = MessageBoxResult.OK) => + public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", + MessageBoxButton button = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None, + MessageBoxResult defaultResult = MessageBoxResult.OK) => MessageBoxEx.Show(messageBoxText, caption, button, icon, defaultResult); - public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress); + public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, + Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress); #endregion From 835e4096c8ec781e6bd319946853060f9de2b493 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 11:56:51 +0800 Subject: [PATCH 0633/1798] Fix build issue --- Flow.Launcher.Infrastructure/Logger/Log.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Logger/Log.cs b/Flow.Launcher.Infrastructure/Logger/Log.cs index 9e1173f34..84331ef70 100644 --- a/Flow.Launcher.Infrastructure/Logger/Log.cs +++ b/Flow.Launcher.Infrastructure/Logger/Log.cs @@ -135,6 +135,15 @@ namespace Flow.Launcher.Infrastructure.Logger return className; } +#if !DEBUG + private static void ExceptionInternal(string classAndMethod, string message, System.Exception e) + { + var logger = LogManager.GetLogger(classAndMethod); + + logger.Error(e, message); + } +#endif + private static void LogInternal(string message, LogLevel level) { if (FormatValid(message)) From 24327533c6e165f0cfa02e9a822fcf973c1880df Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 14:16:32 +0800 Subject: [PATCH 0634/1798] Add plugin json storage --- .../Image/ImageLoader.cs | 1 + .../Storage/BinaryStorage.cs | 62 +++++++++++++++---- .../Storage/PluginBinaryStorage.cs | 15 +++++ .../Storage/PluginJsonStorage.cs | 6 -- 4 files changed, 65 insertions(+), 19 deletions(-) create mode 100644 Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 6f7b1cd90..cca4bd2a4 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -37,6 +37,7 @@ namespace Flow.Launcher.Infrastructure.Image _hashGenerator = new ImageHashGenerator(); var usage = await LoadStorageToConcurrentDictionaryAsync(); + _storage.ClearData(); ImageCache.Initialize(usage); diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs index 5b73faae6..69ac6000b 100644 --- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs @@ -4,6 +4,8 @@ using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using MemoryPack; +#nullable enable + namespace Flow.Launcher.Infrastructure.Storage { /// @@ -15,40 +17,53 @@ namespace Flow.Launcher.Infrastructure.Storage /// public class BinaryStorage { + protected T? Data; + public const string FileSuffix = ".cache"; - // Let the derived class to set the file path - public BinaryStorage(string filename, string directoryPath = null) - { - directoryPath ??= DataLocation.CacheDirectory; - Helper.ValidateDirectory(directoryPath); + protected string FilePath { get; init; } = null!; - FilePath = Path.Combine(directoryPath, $"{filename}{FileSuffix}"); + protected string DirectoryPath { get; init; } = null!; + + // Let the derived class to set the file path + protected BinaryStorage() + { } - public string FilePath { get; } + public BinaryStorage(string filename) + { + DirectoryPath = DataLocation.CacheDirectory; + Helper.ValidateDirectory(DirectoryPath); + + FilePath = Path.Combine(DirectoryPath, $"{filename}{FileSuffix}"); + } public async ValueTask TryLoadAsync(T defaultData) { + if (Data != null) + return Data; + if (File.Exists(FilePath)) { if (new FileInfo(FilePath).Length == 0) { Log.Error($"|BinaryStorage.TryLoad|Zero length cache file <{FilePath}>"); - await SaveAsync(defaultData); - return defaultData; + Data = defaultData; + await SaveAsync(); } await using var stream = new FileStream(FilePath, FileMode.Open); var d = await DeserializeAsync(stream, defaultData); - return d; + Data = d; } else { Log.Info("|BinaryStorage.TryLoad|Cache file not exist, load default data"); - await SaveAsync(defaultData); - return defaultData; + Data = defaultData; + await SaveAsync(); } + + return Data; } private static async ValueTask DeserializeAsync(Stream stream, T defaultData) @@ -56,7 +71,7 @@ namespace Flow.Launcher.Infrastructure.Storage try { var t = await MemoryPackSerializer.DeserializeAsync(stream); - return t; + return t ?? defaultData; } catch (System.Exception) { @@ -65,6 +80,27 @@ namespace Flow.Launcher.Infrastructure.Storage } } + public async ValueTask SaveAsync() + { + await using var stream = new FileStream(FilePath, FileMode.Create); + await MemoryPackSerializer.SerializeAsync(stream, Data); + } + + // For SavePluginSettings function + public void Save() + { + var serialized = MemoryPackSerializer.Serialize(Data); + + File.WriteAllBytes(FilePath, serialized); + } + + // ImageCache need to be converted into concurrent dictionary, so it does not need to cache loading results into Data + public void ClearData() + { + Data = default; + } + + // ImageCache storages data in its class, so it needs to pass it to SaveAsync public async ValueTask SaveAsync(T data) { await using var stream = new FileStream(FilePath, FileMode.Create); diff --git a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs new file mode 100644 index 000000000..87f51d5d7 --- /dev/null +++ b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs @@ -0,0 +1,15 @@ +using System.IO; + +namespace Flow.Launcher.Infrastructure.Storage +{ + public class PluginBinaryStorage : BinaryStorage where T : new() + { + public PluginBinaryStorage(string cacheName, string cacheDirectory) + { + DirectoryPath = cacheDirectory; + Helper.ValidateDirectory(DirectoryPath); + + FilePath = Path.Combine(DirectoryPath, $"{cacheName}{FileSuffix}"); + } + } +} diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs index b377c81aa..9c6547c66 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs @@ -10,7 +10,6 @@ namespace Flow.Launcher.Infrastructure.Storage public PluginJsonStorage() { - // C# related, add python related below var dataType = typeof(T); AssemblyName = dataType.Assembly.GetName().Name; DirectoryPath = Path.Combine(DataLocation.PluginSettingsDirectory, AssemblyName); @@ -18,10 +17,5 @@ namespace Flow.Launcher.Infrastructure.Storage FilePath = Path.Combine(DirectoryPath, $"{dataType.Name}{FileSuffix}"); } - - public PluginJsonStorage(T data) : this() - { - Data = data; - } } } From ca221d710026b3e402873a174696a48e28e5d958 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 14:19:59 +0800 Subject: [PATCH 0635/1798] Add binary storage api functions --- .../JsonRPCV2Models/JsonRPCPublicAPI.cs | 5 ++ Flow.Launcher.Core/Plugin/PluginManager.cs | 5 +- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 33 ++++++++++++ Flow.Launcher.Plugin/Interfaces/ISavable.cs | 7 +-- Flow.Launcher/PublicAPIInstance.cs | 53 ++++++++++++++++--- 5 files changed, 91 insertions(+), 12 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs index 8df2ce9ed..cf1c57f3e 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs @@ -185,5 +185,10 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models { _api.StopLoadingBar(); } + + public void SavePluginCaches() + { + _api.SavePluginCaches(); + } } } diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 4f869901c..fa4e43e07 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -66,6 +66,7 @@ namespace Flow.Launcher.Core.Plugin } API.SavePluginSettings(); + API.SavePluginCaches(); } public static async ValueTask DisposePluginsAsync() @@ -587,11 +588,13 @@ namespace Flow.Launcher.Core.Plugin if (removePluginSettings) { - // For dotnet plugins, we need to remove their PluginJsonStorage instance + // For dotnet plugins, we need to remove their PluginJsonStorage and PluginBinaryStorage instances if (AllowedLanguage.IsDotNet(plugin.Language)) { var method = API.GetType().GetMethod("RemovePluginSettings"); method?.Invoke(API, new object[] { plugin.AssemblyName }); + var method1 = API.GetType().GetMethod("RemovePluginCache"); + method1?.Invoke(API, new object[] { plugin.PluginCacheDirectoryPath }); } try diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index f178ebb90..be776b068 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -344,5 +344,38 @@ namespace Flow.Launcher.Plugin /// Stop the loading bar in main window /// public void StopLoadingBar(); + + /// + /// Save all Flow's plugins caches + /// + void SavePluginCaches(); + + /// + /// Load BinaryStorage for current plugin's cache. This is the method used to load cache from binary in Flow. + /// When the file is not exist, it will create a new instance for the specific type. + /// + /// Type for deserialization + /// Cache file name + /// Cache directory from plugin metadata + /// Default data to return + /// + /// + /// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable + /// + Task LoadCacheBinaryStorageAsync(string cacheName, string cacheDirectory, T defaultData) where T : new(); + + /// + /// Save BinaryStorage for current plugin's cache. This is the method used to save cache to binary in Flow.Launcher + /// This method will save the original instance loaded with LoadCacheBinaryStorageAsync. + /// This API call is for manually Save. Flow will automatically save all cache type that has called LoadCacheBinaryStorageAsync or SaveCacheBinaryStorageAsync previously. + /// + /// Type for Serialization + /// Cache file name + /// Cache directory from plugin metadata + /// + /// + /// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable + /// + Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new(); } } diff --git a/Flow.Launcher.Plugin/Interfaces/ISavable.cs b/Flow.Launcher.Plugin/Interfaces/ISavable.cs index 77bd304e4..cabd26962 100644 --- a/Flow.Launcher.Plugin/Interfaces/ISavable.cs +++ b/Flow.Launcher.Plugin/Interfaces/ISavable.cs @@ -1,11 +1,12 @@ -namespace Flow.Launcher.Plugin +namespace Flow.Launcher.Plugin { /// /// Inherit this interface if additional data e.g. cache needs to be saved. /// /// /// For storing plugin settings, prefer - /// or . + /// or . + /// or . /// Once called, your settings will be automatically saved by Flow. /// public interface ISavable : IFeatures @@ -15,4 +16,4 @@ namespace Flow.Launcher.Plugin /// void Save(); } -} \ No newline at end of file +} diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index e19ad2fdc..17d7e103e 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -236,14 +236,6 @@ namespace Flow.Launcher ((PluginJsonStorage)_pluginJsonStorages[type]).Save(); } - public void SaveJsonStorage(T settings) where T : new() - { - var type = typeof(T); - _pluginJsonStorages[type] = new PluginJsonStorage(settings); - - ((PluginJsonStorage)_pluginJsonStorages[type]).Save(); - } - public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null) { using var explorer = new Process(); @@ -342,6 +334,51 @@ namespace Flow.Launcher public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress); + private readonly ConcurrentDictionary<(string, string, Type), object> _pluginBinaryStorages = new(); + + public void RemovePluginCache(string cacheDirectory) + { + foreach (var keyValuePair in _pluginBinaryStorages) + { + var key = keyValuePair.Key; + var currentCacheDirectory = key.Item2; + if (cacheDirectory == currentCacheDirectory) + { + _pluginBinaryStorages.Remove(key, out var _); + } + } + } + + /// + /// Save plugin caches. + /// + public void SavePluginCaches() + { + foreach (var value in _pluginBinaryStorages.Values) + { + var method = value.GetType().GetMethod("Save"); + method?.Invoke(value, null); + } + } + + public async Task LoadCacheBinaryStorageAsync(string cacheName, string cacheDirectory, T defaultData) where T : new() + { + var type = typeof(T); + if (!_pluginBinaryStorages.ContainsKey((cacheName, cacheDirectory, type))) + _pluginBinaryStorages[(cacheName, cacheDirectory, type)] = new PluginBinaryStorage(cacheName, cacheDirectory); + + return await ((PluginBinaryStorage)_pluginBinaryStorages[(cacheName, cacheDirectory, type)]).TryLoadAsync(defaultData); + } + + public async Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new() + { + var type = typeof(T); + if (!_pluginBinaryStorages.ContainsKey((cacheName, cacheDirectory, type))) + _pluginBinaryStorages[(cacheName, cacheDirectory, type)] = new PluginBinaryStorage(cacheName, cacheDirectory); + + await ((PluginBinaryStorage)_pluginBinaryStorages[(cacheName, cacheDirectory, type)]).SaveAsync(); + } + #endregion #region Private Methods From 0496d6c04ac2bed323060f41519c41fe1358dc73 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 14:21:29 +0800 Subject: [PATCH 0636/1798] Use api functions for Program plugin --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 82 +++++++++---------- .../Programs/UWPPackage.cs | 2 +- .../Programs/Win32.cs | 2 +- .../Views/ProgramSetting.xaml.cs | 6 +- 4 files changed, 46 insertions(+), 46 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 3be23214c..5bc518105 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -8,7 +8,6 @@ using System.Threading.Tasks; using System.Windows.Controls; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; -using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.Program.Programs; using Flow.Launcher.Plugin.Program.Views; @@ -19,19 +18,17 @@ using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher.Plugin.Program { - public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, ISavable, IAsyncReloadable, - IDisposable + public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, IAsyncReloadable, IDisposable { - internal static Win32[] _win32s { get; set; } - internal static UWPApp[] _uwps { get; set; } - internal static Settings _settings { get; set; } + private const string Win32CacheName = "Win32"; + private const string UwpCacheName = "UWP"; + internal static List _win32s { get; private set; } + internal static List _uwps { get; private set; } + internal static Settings _settings { get; private set; } internal static PluginInitContext Context { get; private set; } - private static BinaryStorage _win32Storage; - private static BinaryStorage _uwpStorage; - private static readonly List emptyResults = new(); private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; @@ -81,12 +78,6 @@ namespace Flow.Launcher.Plugin.Program { } - public void Save() - { - _win32Storage.SaveAsync(_win32s); - _uwpStorage.SaveAsync(_uwps); - } - public async Task> QueryAsync(Query query, CancellationToken token) { var result = await cache.GetOrCreateAsync(query.Search, async entry => @@ -191,7 +182,9 @@ namespace Flow.Launcher.Plugin.Program await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () => { - Helper.ValidateDirectory(Context.CurrentPluginMetadata.PluginCacheDirectoryPath); + var pluginCachePath = Context.CurrentPluginMetadata.PluginCacheDirectoryPath; + + Helper.ValidateDirectory(pluginCachePath); static void MoveFile(string sourcePath, string destinationPath) { @@ -236,20 +229,18 @@ namespace Flow.Launcher.Plugin.Program } // Move old cache files to the new cache directory - var oldWin32CacheFile = Path.Combine(DataLocation.CacheDirectory, $"Win32.cache"); - var newWin32CacheFile = Path.Combine(Context.CurrentPluginMetadata.PluginCacheDirectoryPath, $"Win32.cache"); + var oldWin32CacheFile = Path.Combine(DataLocation.CacheDirectory, $"{Win32CacheName}.cache"); + var newWin32CacheFile = Path.Combine(pluginCachePath, $"{Win32CacheName}.cache"); MoveFile(oldWin32CacheFile, newWin32CacheFile); - var oldUWPCacheFile = Path.Combine(DataLocation.CacheDirectory, $"UWP.cache"); - var newUWPCacheFile = Path.Combine(Context.CurrentPluginMetadata.PluginCacheDirectoryPath, $"UWP.cache"); + var oldUWPCacheFile = Path.Combine(DataLocation.CacheDirectory, $"{UwpCacheName}.cache"); + var newUWPCacheFile = Path.Combine(pluginCachePath, $"{UwpCacheName}.cache"); MoveFile(oldUWPCacheFile, newUWPCacheFile); - _win32Storage = new BinaryStorage("Win32", Context.CurrentPluginMetadata.PluginCacheDirectoryPath); - _win32s = await _win32Storage.TryLoadAsync(Array.Empty()); - _uwpStorage = new BinaryStorage("UWP", Context.CurrentPluginMetadata.PluginCacheDirectoryPath); - _uwps = await _uwpStorage.TryLoadAsync(Array.Empty()); + _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List()); + _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List()); }); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Length}>"); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Length}>"); + Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32s.Count}>"); + Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwps.Count}>"); bool cacheEmpty = !_win32s.Any() || !_uwps.Any(); @@ -273,36 +264,45 @@ namespace Flow.Launcher.Plugin.Program } } - public static void IndexWin32Programs() + public static async Task IndexWin32ProgramsAsync() { var win32S = Win32.All(_settings); - _win32s = win32S; + _win32s.Clear(); + foreach (var win32 in win32S) + { + _win32s.Add(win32); + } ResetCache(); - _win32Storage.SaveAsync(_win32s); + await Context.API.SaveCacheBinaryStorageAsync>(Win32CacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); _settings.LastIndexTime = DateTime.Now; } - public static void IndexUwpPrograms() + public static async Task IndexUwpProgramsAsync() { - var applications = UWPPackage.All(_settings); - _uwps = applications; + var uwps = UWPPackage.All(_settings); + _uwps.Clear(); + foreach (var uwp in uwps) + { + _uwps.Add(uwp); + } ResetCache(); - _uwpStorage.SaveAsync(_uwps); + await Context.API.SaveCacheBinaryStorageAsync>(UwpCacheName, Context.CurrentPluginMetadata.PluginCacheDirectoryPath); _settings.LastIndexTime = DateTime.Now; } public static async Task IndexProgramsAsync() { - var a = Task.Run(() => + var win32Task = Task.Run(async () => { - Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexWin32Programs); + await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexWin32ProgramsAsync); }); - var b = Task.Run(() => + var uwpTask = Task.Run(async () => { - Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|UWPProgram index cost", IndexUwpPrograms); + await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|UWPProgram index cost", IndexUwpProgramsAsync); }); - await Task.WhenAll(a, b).ConfigureAwait(false); + + await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false); } internal static void ResetCache() @@ -314,7 +314,7 @@ namespace Flow.Launcher.Plugin.Program public Control CreateSettingPanel() { - return new ProgramSetting(Context, _settings, _win32s, _uwps); + return new ProgramSetting(Context, _settings); } public string GetTranslatedPluginTitle() @@ -370,7 +370,7 @@ namespace Flow.Launcher.Plugin.Program _settings.DisabledProgramSources.Add(new ProgramSource(program)); _ = Task.Run(() => { - IndexUwpPrograms(); + _ = IndexUwpProgramsAsync(); }); } else if (_win32s.Any(x => x.UniqueIdentifier == programToDelete.UniqueIdentifier)) @@ -380,7 +380,7 @@ namespace Flow.Launcher.Plugin.Program _settings.DisabledProgramSources.Add(new ProgramSource(program)); _ = Task.Run(() => { - IndexWin32Programs(); + _ = IndexWin32ProgramsAsync(); }); } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs index 654897cc5..bf100ed7e 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs @@ -317,7 +317,7 @@ namespace Flow.Launcher.Plugin.Program.Programs { await Task.Delay(3000).ConfigureAwait(false); PackageChangeChannel.Reader.TryRead(out _); - await Task.Run(Main.IndexUwpPrograms); + await Task.Run(Main.IndexUwpProgramsAsync); } } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index a64a708ef..06be2a628 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -797,7 +797,7 @@ namespace Flow.Launcher.Plugin.Program.Programs { } - await Task.Run(Main.IndexWin32Programs); + await Task.Run(Main.IndexWin32ProgramsAsync); } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs index 91864cb68..5ad7fcea3 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Views/ProgramSetting.xaml.cs @@ -18,8 +18,8 @@ namespace Flow.Launcher.Plugin.Program.Views /// public partial class ProgramSetting : UserControl { - private PluginInitContext context; - private Settings _settings; + private readonly PluginInitContext context; + private readonly Settings _settings; private GridViewColumnHeader _lastHeaderClicked; private ListSortDirection _lastDirection; @@ -109,7 +109,7 @@ namespace Flow.Launcher.Plugin.Program.Views public bool ShowUWPCheckbox => UWPPackage.SupportUWP(); - public ProgramSetting(PluginInitContext context, Settings settings, Win32[] win32s, UWPApp[] uwps) + public ProgramSetting(PluginInitContext context, Settings settings) { this.context = context; _settings = settings; From 68e1fc28efcc31362193aab4e73aa7459bf1b1af Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 14:35:43 +0800 Subject: [PATCH 0637/1798] Use try remove for safety --- Flow.Launcher/PublicAPIInstance.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 17d7e103e..770195550 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -201,7 +201,7 @@ namespace Flow.Launcher var name = value.GetType().GetField("AssemblyName")?.GetValue(value)?.ToString(); if (name == assemblyName) { - _pluginJsonStorages.Remove(key, out var pluginJsonStorage); + _pluginJsonStorages.TryRemove(key, out var pluginJsonStorage); } } } @@ -344,7 +344,7 @@ namespace Flow.Launcher var currentCacheDirectory = key.Item2; if (cacheDirectory == currentCacheDirectory) { - _pluginBinaryStorages.Remove(key, out var _); + _pluginBinaryStorages.TryRemove(key, out var _); } } } From 8e8b5dbbba6d45c9304b556c022fe2ebf277ed5d Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 19:18:32 +0800 Subject: [PATCH 0638/1798] Code quality --- .../ViewModels/SettingsPaneAboutViewModel.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index 20f905411..07e9fba1e 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using System.Windows; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core; -using Flow.Launcher.Core.Resource; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; @@ -24,7 +23,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel get { var size = GetLogFiles().Sum(file => file.Length); - return $"{InternationalizationManager.Instance.GetTranslation("clearlogfolder")} ({BytesToReadableString(size)})"; + return $"{App.API.GetTranslation("clearlogfolder")} ({BytesToReadableString(size)})"; } } @@ -42,7 +41,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel }; public string ActivatedTimes => string.Format( - InternationalizationManager.Instance.GetTranslation("about_activate_times"), + App.API.GetTranslation("about_activate_times"), _settings.ActivateTimes ); @@ -88,8 +87,8 @@ public partial class SettingsPaneAboutViewModel : BaseModel private void AskClearLogFolderConfirmation() { var confirmResult = App.API.ShowMsgBox( - InternationalizationManager.Instance.GetTranslation("clearlogfolderMessage"), - InternationalizationManager.Instance.GetTranslation("clearlogfolder"), + App.API.GetTranslation("clearlogfolderMessage"), + App.API.GetTranslation("clearlogfolder"), MessageBoxButton.YesNo ); @@ -121,7 +120,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel } [RelayCommand] - private Task UpdateApp() => _updater.UpdateAppAsync(false); + private Task UpdateAppAsync() => _updater.UpdateAppAsync(false); private void ClearLogFolder() { From 482fdc939f9fd01dfdd4b75f485e30768c43e63d Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 1 Apr 2025 20:12:27 +0800 Subject: [PATCH 0639/1798] Add clean cache option --- Flow.Launcher/Languages/en.xaml | 2 + .../ViewModels/SettingsPaneAboutViewModel.cs | 49 ++++++++++++++++++- .../SettingPages/Views/SettingsPaneAbout.xaml | 4 ++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 2df430c3b..6963d81c9 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -325,6 +325,8 @@ Log Folder Clear Logs Are you sure you want to delete all logs? + Clear Caches + Are you sure you want to delete all caches? Wizard User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index 07e9fba1e..47cb1b6c3 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -27,6 +27,15 @@ public partial class SettingsPaneAboutViewModel : BaseModel } } + public string CacheFolderSize + { + get + { + var size = GetCacheFiles().Sum(file => file.Length); + return $"{App.API.GetTranslation("clearcachefolder")} ({BytesToReadableString(size)})"; + } + } + public string Website => Constant.Website; public string SponsorPage => Constant.SponsorPage; public string ReleaseNotes => _updater.GitHubRepository + "/releases/latest"; @@ -98,6 +107,21 @@ public partial class SettingsPaneAboutViewModel : BaseModel } } + [RelayCommand] + private void AskClearCacheFolderConfirmation() + { + var confirmResult = App.API.ShowMsgBox( + App.API.GetTranslation("clearcachefolderMessage"), + App.API.GetTranslation("clearcachefolder"), + MessageBoxButton.YesNo + ); + + if (confirmResult == MessageBoxResult.Yes) + { + ClearCacheFolder(); + } + } + [RelayCommand] private void OpenSettingsFolder() { @@ -112,7 +136,6 @@ public partial class SettingsPaneAboutViewModel : BaseModel App.API.OpenDirectory(parentFolderPath); } - [RelayCommand] private void OpenLogsFolder() { @@ -147,6 +170,30 @@ public partial class SettingsPaneAboutViewModel : BaseModel return GetLogDir(version).EnumerateFiles("*", SearchOption.AllDirectories).ToList(); } + private void ClearCacheFolder() + { + var cacheDirectory = GetCacheDir(); + var cacheFiles = GetCacheFiles(); + + cacheFiles.ForEach(f => f.Delete()); + + cacheDirectory.EnumerateDirectories("*", SearchOption.TopDirectoryOnly) + .ToList() + .ForEach(dir => dir.Delete(true)); + + OnPropertyChanged(nameof(CacheFolderSize)); + } + + private static DirectoryInfo GetCacheDir() + { + return new DirectoryInfo(DataLocation.CacheDirectory); + } + + private static List GetCacheFiles() + { + return GetCacheDir().EnumerateFiles("*", SearchOption.AllDirectories).ToList(); + } + private static string BytesToReadableString(long bytes) { const int scale = 1024; diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml index 75c513411..f7deee7cf 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml @@ -90,6 +90,10 @@ Margin="0 12 0 0" Icon=""> + public void StopLoadingBar(); + + /// + /// Load image from path. Support local, remote and data:image url. + /// If image path is missing, it will retun a missing icon. + /// + /// The path of the image. + /// + /// Load full image or not. + /// + /// + /// Cache the image or not. Cached image will be stored in FL cache. + /// If the image is just used one time, it's better to set this to false. + /// + /// + ValueTask LoadImageAsync(string path, bool loadFullImage = false, bool cacheImage = true); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index e19ad2fdc..d12c6ac3e 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -10,6 +10,7 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using System.Windows; +using System.Windows.Media; using CommunityToolkit.Mvvm.DependencyInjection; using Squirrel; using Flow.Launcher.Core; @@ -342,6 +343,9 @@ namespace Flow.Launcher public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress); + public ValueTask LoadImageAsync(string path, bool loadFullImage = false, bool cacheImage = true) => + ImageLoader.LoadAsync(path, loadFullImage, cacheImage); + #endregion #region Private Methods From f76110856fdc1c104d3dc1c5a888073b1ac3f413 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 18:25:06 +0800 Subject: [PATCH 0645/1798] Use api function in main project --- Flow.Launcher/MessageBoxEx.xaml.cs | 2 +- Flow.Launcher/Msg.xaml.cs | 6 +++--- Flow.Launcher/ViewModel/MainViewModel.cs | 2 +- Flow.Launcher/ViewModel/PluginViewModel.cs | 2 +- Flow.Launcher/ViewModel/ResultViewModel.cs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher/MessageBoxEx.xaml.cs b/Flow.Launcher/MessageBoxEx.xaml.cs index e9b434fd9..3d94769d0 100644 --- a/Flow.Launcher/MessageBoxEx.xaml.cs +++ b/Flow.Launcher/MessageBoxEx.xaml.cs @@ -156,7 +156,7 @@ namespace Flow.Launcher private async Task SetImageAsync(string imageName) { var imagePath = Path.Combine(Constant.ProgramDirectory, "Images", imageName); - var imageSource = await ImageLoader.LoadAsync(imagePath); + var imageSource = await App.API.LoadImageAsync(imagePath); Img.Source = imageSource; } diff --git a/Flow.Launcher/Msg.xaml.cs b/Flow.Launcher/Msg.xaml.cs index 94184ff63..ff9accd62 100644 --- a/Flow.Launcher/Msg.xaml.cs +++ b/Flow.Launcher/Msg.xaml.cs @@ -43,7 +43,7 @@ namespace Flow.Launcher private async System.Threading.Tasks.Task LoadImageAsync() { - imgClose.Source = await ImageLoader.LoadAsync(Path.Combine(Infrastructure.Constant.ProgramDirectory, "Images\\close.png")); + imgClose.Source = await App.API.LoadImageAsync(Path.Combine(Constant.ProgramDirectory, "Images\\close.png")); } void imgClose_MouseUp(object sender, MouseButtonEventArgs e) @@ -71,11 +71,11 @@ namespace Flow.Launcher if (!File.Exists(iconPath)) { - imgIco.Source = await ImageLoader.LoadAsync(Path.Combine(Constant.ProgramDirectory, "Images\\app.png")); + imgIco.Source = await App.API.LoadImageAsync(Path.Combine(Constant.ProgramDirectory, "Images\\app.png")); } else { - imgIco.Source = await ImageLoader.LoadAsync(iconPath); + imgIco.Source = await App.API.LoadImageAsync(iconPath); } Show(); diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 17e4b55b7..bfa5bd504 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1168,7 +1168,7 @@ namespace Flow.Launcher.ViewModel else if (plugins.Count == 1) { PluginIconPath = plugins.Single().Metadata.IcoPath; - PluginIconSource = await ImageLoader.LoadAsync(PluginIconPath); + PluginIconSource = await App.API.LoadImageAsync(PluginIconPath); SearchIconVisibility = Visibility.Hidden; } else diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index e91badb38..93a595de4 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -45,7 +45,7 @@ namespace Flow.Launcher.ViewModel private async Task LoadIconAsync() { - Image = await ImageLoader.LoadAsync(PluginPair.Metadata.IcoPath); + Image = await App.API.LoadImageAsync(PluginPair.Metadata.IcoPath); OnPropertyChanged(nameof(Image)); } diff --git a/Flow.Launcher/ViewModel/ResultViewModel.cs b/Flow.Launcher/ViewModel/ResultViewModel.cs index db124e078..9aab71a32 100644 --- a/Flow.Launcher/ViewModel/ResultViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultViewModel.cs @@ -199,7 +199,7 @@ namespace Flow.Launcher.ViewModel } } - return await ImageLoader.LoadAsync(imagePath, loadFullImage).ConfigureAwait(false); + return await App.API.LoadImageAsync(imagePath, loadFullImage).ConfigureAwait(false); } private async Task LoadImageAsync() From 4572068e768921e0834c53f6f4192c71ae762c04 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 18:25:28 +0800 Subject: [PATCH 0646/1798] Use api functions in plugin projects --- .../Views/PreviewPanel.xaml.cs | 3 +-- .../SearchSourceViewModel.cs | 9 ++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs index 878832e4f..aaf1efdc1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/PreviewPanel.xaml.cs @@ -7,7 +7,6 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; -using Flow.Launcher.Infrastructure.Image; using Flow.Launcher.Plugin.Explorer.Search; namespace Flow.Launcher.Plugin.Explorer.Views; @@ -89,7 +88,7 @@ public partial class PreviewPanel : UserControl, INotifyPropertyChanged private async Task LoadImageAsync() { - PreviewImage = await ImageLoader.LoadAsync(FilePath, true).ConfigureAwait(false); + PreviewImage = await Main.Context.API.LoadImageAsync(FilePath, true).ConfigureAwait(false); } public event PropertyChangedEventHandler? PropertyChanged; diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs index 9c5e81cb5..6554edd83 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceViewModel.cs @@ -1,5 +1,4 @@ -using Flow.Launcher.Infrastructure.Image; -using System; +using System; using System.IO; using System.Threading.Tasks; #pragma warning disable IDE0005 @@ -41,8 +40,8 @@ namespace Flow.Launcher.Plugin.WebSearch #if DEBUG throw; #else - Main._context.API.ShowMsgBox(string.Format("Copying the selected image file to {0} has failed, changes will now be reverted", destinationFileNameFullPath)); - UpdateIconAttributes(selectedSearchSource, fullPathToOriginalImage); + Main._context.API.ShowMsgBox(string.Format("Copying the selected image file to {0} has failed, changes will now be reverted", destinationFileNameFullPath)); + UpdateIconAttributes(selectedSearchSource, fullPathToOriginalImage); #endif } } @@ -61,7 +60,7 @@ namespace Flow.Launcher.Plugin.WebSearch internal async ValueTask LoadPreviewIconAsync(string pathToPreviewIconImage) { - return await ImageLoader.LoadAsync(pathToPreviewIconImage); + return await Main._context.API.LoadImageAsync(pathToPreviewIconImage); } } } From 3de8005297fcba6e517ea674e3b2dc1129aea8e8 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 18:26:22 +0800 Subject: [PATCH 0647/1798] Improve WebSearch project code quality --- .../SuggestionSources/Baidu.cs | 8 +++----- .../SuggestionSources/Bing.cs | 16 +++++----------- .../SuggestionSources/DuckDuckGo.cs | 8 +++----- .../SuggestionSources/Google.cs | 8 +++----- 4 files changed, 14 insertions(+), 26 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs index 51f81b718..590666af7 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs @@ -4,8 +4,6 @@ using System.Linq; using System.Text.Json; using System.Text.RegularExpressions; using System.Threading.Tasks; -using Flow.Launcher.Infrastructure.Http; -using Flow.Launcher.Infrastructure.Logger; using System.Net.Http; using System.Threading; @@ -22,11 +20,11 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources try { const string api = "http://suggestion.baidu.com/su?json=1&wd="; - result = await Http.GetAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false); + result = await Main._context.API.HttpGetStringAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false); } catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException}) { - Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e); + Main._context.API.LogException(nameof(Baidu), "Can't get suggestion from baidu", e); return null; } @@ -41,7 +39,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources } catch (JsonException e) { - Log.Exception("|Baidu.Suggestions|can't parse suggestions", e); + Main._context.API.LogException(nameof(Baidu), "Can't parse suggestions", e); return new List(); } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs index 640674243..938f7d387 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs @@ -1,6 +1,4 @@ -using Flow.Launcher.Infrastructure.Http; -using Flow.Launcher.Infrastructure.Logger; -using System; +using System; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; @@ -10,16 +8,15 @@ using System.Threading; namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { - class Bing : SuggestionSource + public class Bing : SuggestionSource { public override async Task> SuggestionsAsync(string query, CancellationToken token) { - try { const string api = "https://api.bing.com/qsonhs.aspx?q="; - await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false); + await using var resultStream = await Main._context.API.HttpGetStreamAsync(api + Uri.EscapeDataString(query), token).ConfigureAwait(false); using var json = (await JsonDocument.ParseAsync(resultStream, cancellationToken: token)); var root = json.RootElement.GetProperty("AS"); @@ -33,18 +30,15 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources .EnumerateArray() .Select(s => s.GetProperty("Txt").GetString())) .ToList(); - - - } catch (Exception e) when (e is HttpRequestException or { InnerException: TimeoutException }) { - Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e); + Main._context.API.LogException(nameof(Bing), "Can't get suggestion from baidu", e); return null; } catch (JsonException e) { - Log.Exception("|Bing.Suggestions|can't parse suggestions", e); + Main._context.API.LogException(nameof(Bing), "Can't parse suggestions", e); return new List(); } } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs index 8fafb44cc..1d248caf3 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/DuckDuckGo.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Flow.Launcher.Infrastructure.Http; -using Flow.Launcher.Infrastructure.Logger; using System.Net.Http; using System.Threading; using System.Text.Json; @@ -25,7 +23,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { const string api = "https://duckduckgo.com/ac/?type=list&q="; - await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), token: token).ConfigureAwait(false); + await using var resultStream = await Main._context.API.HttpGetStreamAsync(api + Uri.EscapeDataString(query), token: token).ConfigureAwait(false); using var json = await JsonDocument.ParseAsync(resultStream, cancellationToken: token); @@ -36,12 +34,12 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources } catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException}) { - Log.Exception("|DuckDuckGo.Suggestions|Can't get suggestion from DuckDuckGo", e); + Main._context.API.LogException(nameof(DuckDuckGo), "Can't get suggestion from DuckDuckGo", e); return null; } catch (JsonException e) { - Log.Exception("|DuckDuckGo.Suggestions|can't parse suggestions", e); + Main._context.API.LogException(nameof(DuckDuckGo), "Can't parse suggestions", e); return new List(); } } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs index 265de4a98..5f2504009 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Flow.Launcher.Infrastructure.Http; -using Flow.Launcher.Infrastructure.Logger; using System.Net.Http; using System.Threading; using System.Text.Json; @@ -18,7 +16,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { const string api = "https://www.google.com/complete/search?output=chrome&q="; - await using var resultStream = await Http.GetStreamAsync(api + Uri.EscapeDataString(query), token: token).ConfigureAwait(false); + await using var resultStream = await Main._context.API.HttpGetStreamAsync(api + Uri.EscapeDataString(query), token: token).ConfigureAwait(false); using var json = await JsonDocument.ParseAsync(resultStream, cancellationToken: token); @@ -29,12 +27,12 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources } catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException}) { - Log.Exception("|Baidu.Suggestions|Can't get suggestion from baidu", e); + Main._context.API.LogException(nameof(Google), "Can't get suggestion from baidu", e); return null; } catch (JsonException e) { - Log.Exception("|Google.Suggestions|can't parse suggestions", e); + Main._context.API.LogException(nameof(Google), "Can't parse suggestions", e); return new List(); } } From f9a01e10025563e069c3caafce85b80e89d60d2f Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Wed, 2 Apr 2025 18:34:04 +0800 Subject: [PATCH 0648/1798] Fix typos Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index fb80ede83..0ee576b2e 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -348,7 +348,7 @@ namespace Flow.Launcher.Plugin /// /// Load image from path. Support local, remote and data:image url. - /// If image path is missing, it will retun a missing icon. + /// If image path is missing, it will return a missing icon. /// /// The path of the image. /// From 15a7e3a5afd8af4a9139935fd376d963963fb66b Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Wed, 2 Apr 2025 18:35:03 +0800 Subject: [PATCH 0649/1798] Fix log typos Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs index 938f7d387..9efc36263 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs @@ -33,7 +33,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources } catch (Exception e) when (e is HttpRequestException or { InnerException: TimeoutException }) { - Main._context.API.LogException(nameof(Bing), "Can't get suggestion from baidu", e); + Main._context.API.LogException(nameof(Bing), "Can't get suggestion from Bing", e); return null; } catch (JsonException e) From a33ecdbb971869605c4e8c03b5a0a00465040bd4 Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Wed, 2 Apr 2025 18:35:27 +0800 Subject: [PATCH 0650/1798] Fix log typos Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs index 5f2504009..ad8fb508f 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs @@ -27,7 +27,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources } catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException}) { - Main._context.API.LogException(nameof(Google), "Can't get suggestion from baidu", e); + Main._context.API.LogException(nameof(Google), "Can't get suggestion from Google", e); return null; } catch (JsonException e) From e6a8fe3523b7c810faebf2b2235e1322884c0696 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 18:36:25 +0800 Subject: [PATCH 0651/1798] Use caption letter --- .../Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs index 590666af7..65be06b53 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs @@ -24,7 +24,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources } catch (Exception e) when (e is HttpRequestException or {InnerException: TimeoutException}) { - Main._context.API.LogException(nameof(Baidu), "Can't get suggestion from baidu", e); + Main._context.API.LogException(nameof(Baidu), "Can't get suggestion from Baidu", e); return null; } From b62c19e28b0fd8063dc3004dc21a7c840162d3b7 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 19:30:15 +0800 Subject: [PATCH 0652/1798] Move format function position --- Flow.Launcher.Core/Updater.cs | 13 ++++++++++++- Flow.Launcher.Infrastructure/Helper.cs | 22 ---------------------- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 9a77ece32..96efcacf6 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -17,6 +17,7 @@ using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using System.Text.Json.Serialization; using System.Threading; +using System.Text.Json; namespace Flow.Launcher.Core { @@ -51,7 +52,7 @@ namespace Flow.Launcher.Core var newReleaseVersion = Version.Parse(newUpdateInfo.FutureReleaseEntry.Version.ToString()); var currentVersion = Version.Parse(Constant.Version); - Log.Info($"|Updater.UpdateApp|Future Release <{newUpdateInfo.FutureReleaseEntry.Formatted()}>"); + Log.Info($"|Updater.UpdateApp|Future Release <{Formatted(newUpdateInfo.FutureReleaseEntry)}>"); if (newReleaseVersion <= currentVersion) { @@ -151,5 +152,15 @@ namespace Flow.Launcher.Core return tips; } + + private static string Formatted(T t) + { + var formatted = JsonSerializer.Serialize(t, new JsonSerializerOptions + { + WriteIndented = true + }); + + return formatted; + } } } diff --git a/Flow.Launcher.Infrastructure/Helper.cs b/Flow.Launcher.Infrastructure/Helper.cs index 864d796c7..c393c4016 100644 --- a/Flow.Launcher.Infrastructure/Helper.cs +++ b/Flow.Launcher.Infrastructure/Helper.cs @@ -2,18 +2,11 @@ using System; using System.IO; -using System.Text.Json; -using System.Text.Json.Serialization; namespace Flow.Launcher.Infrastructure { public static class Helper { - static Helper() - { - jsonFormattedSerializerOptions.Converters.Add(new JsonStringEnumConverter()); - } - /// /// http://www.yinwang.org/blog-cn/2015/11/21/programming-philosophy /// @@ -71,20 +64,5 @@ namespace Flow.Launcher.Infrastructure Directory.CreateDirectory(path); } } - - private static readonly JsonSerializerOptions jsonFormattedSerializerOptions = new JsonSerializerOptions - { - WriteIndented = true - }; - - public static string Formatted(this T t) - { - var formatted = JsonSerializer.Serialize(t, new JsonSerializerOptions - { - WriteIndented = true - }); - - return formatted; - } } } From 44ba60cdfcd58785456c8fcb61a203197005daa5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 20:17:32 +0800 Subject: [PATCH 0653/1798] Move ValidateDirectory functions to FileFolders for plugin usage --- Flow.Launcher.Infrastructure/Helper.cs | 36 --------------- .../Storage/BinaryStorage.cs | 3 +- .../Storage/FlowLauncherJsonStorage.cs | 5 +- .../Storage/JsonStorage.cs | 3 +- .../Storage/PluginJsonStorage.cs | 3 +- .../SharedCommands/FilesFolders.cs | 46 +++++++++++++++++++ Plugins/Flow.Launcher.Plugin.Program/Main.cs | 4 +- .../Flow.Launcher.Plugin.WebSearch/Main.cs | 3 +- 8 files changed, 58 insertions(+), 45 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Helper.cs b/Flow.Launcher.Infrastructure/Helper.cs index c393c4016..b02d84ca7 100644 --- a/Flow.Launcher.Infrastructure/Helper.cs +++ b/Flow.Launcher.Infrastructure/Helper.cs @@ -1,7 +1,6 @@ #nullable enable using System; -using System.IO; namespace Flow.Launcher.Infrastructure { @@ -29,40 +28,5 @@ namespace Flow.Launcher.Infrastructure throw new NullReferenceException(); } } - - public static void ValidateDataDirectory(string bundledDataDirectory, string dataDirectory) - { - if (!Directory.Exists(dataDirectory)) - { - Directory.CreateDirectory(dataDirectory); - } - - foreach (var bundledDataPath in Directory.GetFiles(bundledDataDirectory)) - { - var data = Path.GetFileName(bundledDataPath); - var dataPath = Path.Combine(dataDirectory, data.NonNull()); - if (!File.Exists(dataPath)) - { - File.Copy(bundledDataPath, dataPath); - } - else - { - var time1 = new FileInfo(bundledDataPath).LastWriteTimeUtc; - var time2 = new FileInfo(dataPath).LastWriteTimeUtc; - if (time1 != time2) - { - File.Copy(bundledDataPath, dataPath, true); - } - } - } - } - - public static void ValidateDirectory(string path) - { - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path); - } - } } } diff --git a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs index 5b73faae6..a8d5f5d62 100644 --- a/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/BinaryStorage.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin.SharedCommands; using MemoryPack; namespace Flow.Launcher.Infrastructure.Storage @@ -21,7 +22,7 @@ namespace Flow.Launcher.Infrastructure.Storage public BinaryStorage(string filename, string directoryPath = null) { directoryPath ??= DataLocation.CacheDirectory; - Helper.ValidateDirectory(directoryPath); + FilesFolders.ValidateDirectory(directoryPath); FilePath = Path.Combine(directoryPath, $"{filename}{FileSuffix}"); } diff --git a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs index 865041fb3..3669bb405 100644 --- a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs @@ -1,5 +1,6 @@ using System.IO; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage { @@ -8,10 +9,10 @@ namespace Flow.Launcher.Infrastructure.Storage public FlowLauncherJsonStorage() { var directoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName); - Helper.ValidateDirectory(directoryPath); + FilesFolders.ValidateDirectory(directoryPath); var filename = typeof(T).Name; FilePath = Path.Combine(directoryPath, $"{filename}{FileSuffix}"); } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs index 40106acd8..a3488124b 100644 --- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs @@ -5,6 +5,7 @@ using System.IO; using System.Text.Json; using System.Threading.Tasks; using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage { @@ -37,7 +38,7 @@ namespace Flow.Launcher.Infrastructure.Storage FilePath = filePath; DirectoryPath = Path.GetDirectoryName(filePath) ?? throw new ArgumentException("Invalid file path"); - Helper.ValidateDirectory(DirectoryPath); + FilesFolders.ValidateDirectory(DirectoryPath); } public async Task LoadAsync() diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs index b377c81aa..cc78bb8f6 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs @@ -1,5 +1,6 @@ using System.IO; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage { @@ -14,7 +15,7 @@ namespace Flow.Launcher.Infrastructure.Storage var dataType = typeof(T); AssemblyName = dataType.Assembly.GetName().Name; DirectoryPath = Path.Combine(DataLocation.PluginSettingsDirectory, AssemblyName); - Helper.ValidateDirectory(DirectoryPath); + FilesFolders.ValidateDirectory(DirectoryPath); FilePath = Path.Combine(DirectoryPath, $"{dataType.Name}{FileSuffix}"); } diff --git a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs index 5f003e351..1de5841a5 100644 --- a/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs +++ b/Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs @@ -318,5 +318,51 @@ namespace Flow.Launcher.Plugin.SharedCommands { return path.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar; } + + /// + /// Validates a directory, creating it if it doesn't exist + /// + /// + public static void ValidateDirectory(string path) + { + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + } + + /// + /// Validates a data directory, synchronizing it by ensuring all files from a bundled source directory exist in it. + /// If files are missing or outdated, they are copied from the bundled directory to the data directory. + /// + /// + /// + public static void ValidateDataDirectory(string bundledDataDirectory, string dataDirectory) + { + if (!Directory.Exists(dataDirectory)) + { + Directory.CreateDirectory(dataDirectory); + } + + foreach (var bundledDataPath in Directory.GetFiles(bundledDataDirectory)) + { + var data = Path.GetFileName(bundledDataPath); + if (data == null) continue; + var dataPath = Path.Combine(dataDirectory, data); + if (!File.Exists(dataPath)) + { + File.Copy(bundledDataPath, dataPath); + } + else + { + var time1 = new FileInfo(bundledDataPath).LastWriteTimeUtc; + var time2 = new FileInfo(dataPath).LastWriteTimeUtc; + if (time1 != time2) + { + File.Copy(bundledDataPath, dataPath, true); + } + } + } + } } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 3be23214c..73b4ae9e6 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -6,13 +6,13 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Controls; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.Program.Programs; using Flow.Launcher.Plugin.Program.Views; using Flow.Launcher.Plugin.Program.Views.Models; +using Flow.Launcher.Plugin.SharedCommands; using Microsoft.Extensions.Caching.Memory; using Path = System.IO.Path; using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; @@ -191,7 +191,7 @@ namespace Flow.Launcher.Plugin.Program await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () => { - Helper.ValidateDirectory(Context.CurrentPluginMetadata.PluginCacheDirectoryPath); + FilesFolders.ValidateDirectory(Context.CurrentPluginMetadata.PluginCacheDirectoryPath); static void MoveFile(string sourcePath, string destinationPath) { diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs index 7ad9715bb..76aeb3250 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Controls; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Plugin.WebSearch @@ -180,7 +179,7 @@ namespace Flow.Launcher.Plugin.WebSearch // Default images directory is in the WebSearch's application folder DefaultImagesDirectory = Path.Combine(pluginDirectory, Images); - Helper.ValidateDataDirectory(bundledImagesDirectory, DefaultImagesDirectory); + FilesFolders.ValidateDataDirectory(bundledImagesDirectory, DefaultImagesDirectory); // Custom images directory is in the WebSearch's data location folder CustomImagesDirectory = Path.Combine(_context.CurrentPluginMetadata.PluginSettingsDirectoryPath, "CustomIcons"); From 0430eea2fd14f208be42d560716319bde2a0362f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 22:25:55 +0800 Subject: [PATCH 0654/1798] Use api functions instead of project reference for code quality --- .../Commands/BookmarkLoader.cs | 5 ++-- .../FirefoxBookmarkLoader.cs | 23 ++++++++++--------- ...low.Launcher.Plugin.BrowserBookmark.csproj | 1 - .../Main.cs | 15 ++---------- 4 files changed, 16 insertions(+), 28 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/BookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/BookmarkLoader.cs index 3468015eb..758ce68ae 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/BookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Commands/BookmarkLoader.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.BrowserBookmark.Models; using Flow.Launcher.Plugin.SharedModels; @@ -10,11 +9,11 @@ internal static class BookmarkLoader { internal static MatchResult MatchProgram(Bookmark bookmark, string queryString) { - var match = StringMatcher.FuzzySearch(queryString, bookmark.Name); + var match = Main._context.API.FuzzySearch(queryString, bookmark.Name); if (match.IsSearchPrecisionScoreMet()) return match; - return StringMatcher.FuzzySearch(queryString, bookmark.Url); + return Main._context.API.FuzzySearch(queryString, bookmark.Url); } internal static List LoadAllBookmarks(Settings setting) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 3b37bbaed..0e02b2c9e 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -1,15 +1,16 @@ -using Flow.Launcher.Plugin.BrowserBookmark.Models; -using Microsoft.Data.Sqlite; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; -using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Plugin.BrowserBookmark.Models; +using Microsoft.Data.Sqlite; namespace Flow.Launcher.Plugin.BrowserBookmark; public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader { + private static readonly string ClassName = nameof(FirefoxBookmarkLoaderBase); + private readonly string _faviconCacheDir; protected FirefoxBookmarkLoaderBase() @@ -52,7 +53,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to register Firefox bookmark file monitoring: {placesPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to register Firefox bookmark file monitoring: {placesPath}", ex); } // Use a copy to avoid lock issues with the original file @@ -93,12 +94,12 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to delete temporary favicon DB: {tempDbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); } } catch (Exception ex) { - Log.Exception($"Failed to load Firefox bookmarks: {placesPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to load Firefox bookmarks: {placesPath}", ex); } return bookmarks; @@ -177,7 +178,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to extract Firefox favicon: {bookmark.Url}", ex); + Main._context.API.LogException(ClassName, $"Failed to extract Firefox favicon: {bookmark.Url}", ex); } } @@ -192,12 +193,12 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to delete temporary favicon DB: {tempDbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); } } catch (Exception ex) { - Log.Exception($"Failed to load Firefox favicon DB: {faviconDbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to load Firefox favicon DB: {faviconDbPath}", ex); } } @@ -218,7 +219,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to save image: {outputPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to save image: {outputPath}", ex); } } } diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index b4e42fbcd..d09b9e750 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -81,7 +81,6 @@ - diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index ce7f56c34..5ab868ab9 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Controls; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.BrowserBookmark.Commands; using Flow.Launcher.Plugin.BrowserBookmark.Models; using Flow.Launcher.Plugin.BrowserBookmark.Views; @@ -15,7 +14,7 @@ namespace Flow.Launcher.Plugin.BrowserBookmark; public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContextMenu, IDisposable { - private static PluginInitContext _context; + internal static PluginInitContext _context; private static List _cachedBookmarks = new(); @@ -23,16 +22,6 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex private static bool _initialized = false; - public static PluginInitContext GetContext() - { - return _context; - } - - public static string GetPluginDirectory() - { - return _context?.CurrentPluginMetadata?.PluginDirectory; - } - public void Init(PluginInitContext context) { _context = context; @@ -223,7 +212,7 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex catch (Exception e) { var message = "Failed to set url in clipboard"; - Log.Exception("Main", message, e, "LoadContextMenus"); + _context.API.LogException(nameof(Main), message, e); _context.API.ShowMsg(message); From 168f898baf15950ed79fe2e2a26c96a4bd4e89aa Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 22:27:45 +0800 Subject: [PATCH 0655/1798] Cleanup namespaces --- .../Views/SettingsControl.xaml.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml.cs index 8584a3eb0..3182adfed 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Views/SettingsControl.xaml.cs @@ -3,13 +3,6 @@ using Flow.Launcher.Plugin.BrowserBookmark.Models; using System.Windows.Input; using System.ComponentModel; using System.Threading.Tasks; -using System; -using System.IO; -using System.Windows; -using System.Windows.Input; -using System.ComponentModel; -using System.Threading.Tasks; -using Flow.Launcher.Plugin.BrowserBookmark.Models; namespace Flow.Launcher.Plugin.BrowserBookmark.Views; @@ -23,6 +16,7 @@ public partial class SettingsControl : INotifyPropertyChanged Settings = settings; InitializeComponent(); } + public bool LoadChromeBookmark { get => Settings.LoadChromeBookmark; @@ -62,6 +56,7 @@ public partial class SettingsControl : INotifyPropertyChanged PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(OpenInNewBrowserWindow))); } } + public event PropertyChangedEventHandler PropertyChanged; private void NewCustomBrowser(object sender, RoutedEventArgs e) From b564a39aae1990610a09ccd54531cae9c82e07e4 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 22:31:31 +0800 Subject: [PATCH 0656/1798] Use api functions instead of project reference for code quality --- .../ChromiumBookmarkLoader.cs | 22 ++++++++++--------- ...low.Launcher.Plugin.BrowserBookmark.csproj | 3 ++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index d9c4e91d0..39bbb73ff 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -1,15 +1,17 @@ -using Flow.Launcher.Plugin.BrowserBookmark.Models; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Text.Json; -using Flow.Launcher.Infrastructure.Logger; using System; +using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Plugin.BrowserBookmark.Models; using Microsoft.Data.Sqlite; namespace Flow.Launcher.Plugin.BrowserBookmark; public abstract class ChromiumBookmarkLoader : IBookmarkLoader { + private readonly static string ClassName = nameof(ChromiumBookmarkLoader); + private readonly string _faviconCacheDir; protected ChromiumBookmarkLoader() @@ -44,7 +46,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to register bookmark file monitoring: {bookmarkPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to register bookmark file monitoring: {bookmarkPath}", ex); } var source = name + (Path.GetFileName(profile) == "Default" ? "" : $" ({Path.GetFileName(profile)})"); @@ -136,7 +138,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to copy favicon DB: {dbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to copy favicon DB: {dbPath}", ex); return; } @@ -189,7 +191,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to extract bookmark favicon: {bookmark.Url}", ex); + Main._context.API.LogException(ClassName, $"Failed to extract bookmark favicon: {bookmark.Url}", ex); } } @@ -199,7 +201,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to connect to SQLite: {tempDbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to connect to SQLite: {tempDbPath}", ex); } // Delete temporary file @@ -209,12 +211,12 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to delete temporary favicon DB: {tempDbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to delete temporary favicon DB: {tempDbPath}", ex); } } catch (Exception ex) { - Log.Exception($"Failed to load favicon DB: {dbPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to load favicon DB: {dbPath}", ex); } } @@ -226,7 +228,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } catch (Exception ex) { - Log.Exception($"Failed to save image: {outputPath}", ex); + Main._context.API.LogException(ClassName, $"Failed to save image: {outputPath}", ex); } } } diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index d09b9e750..49ae26564 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -1,4 +1,4 @@ - + Library @@ -81,6 +81,7 @@ + From a845e68c98f4ed3c350bd291dc0a5847bc4f4a8c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 2 Apr 2025 22:39:30 +0800 Subject: [PATCH 0657/1798] Use plugin cache directory --- .../ChromiumBookmarkLoader.cs | 7 ++----- .../FirefoxBookmarkLoader.cs | 5 +---- Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs | 9 +++++++++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 39bbb73ff..282876472 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -10,16 +10,13 @@ namespace Flow.Launcher.Plugin.BrowserBookmark; public abstract class ChromiumBookmarkLoader : IBookmarkLoader { - private readonly static string ClassName = nameof(ChromiumBookmarkLoader); + private static readonly string ClassName = nameof(ChromiumBookmarkLoader); private readonly string _faviconCacheDir; protected ChromiumBookmarkLoader() { - _faviconCacheDir = Path.Combine( - Path.GetDirectoryName(typeof(ChromiumBookmarkLoader).Assembly.Location), - "FaviconCache"); - Directory.CreateDirectory(_faviconCacheDir); + _faviconCacheDir = Main._faviconCacheDir; } public abstract List GetBookmarks(); diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index 0e02b2c9e..d2f973329 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -15,10 +15,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader protected FirefoxBookmarkLoaderBase() { - _faviconCacheDir = Path.Combine( - Path.GetDirectoryName(typeof(FirefoxBookmarkLoaderBase).Assembly.Location), - "FaviconCache"); - Directory.CreateDirectory(_faviconCacheDir); + _faviconCacheDir = Main._faviconCacheDir; } public abstract List GetBookmarks(); diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index 5ab868ab9..5dec8b953 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Controls; +using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.BrowserBookmark.Commands; using Flow.Launcher.Plugin.BrowserBookmark.Models; using Flow.Launcher.Plugin.BrowserBookmark.Views; @@ -14,6 +15,8 @@ namespace Flow.Launcher.Plugin.BrowserBookmark; public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContextMenu, IDisposable { + internal static string _faviconCacheDir; + internal static PluginInitContext _context; private static List _cachedBookmarks = new(); @@ -28,6 +31,12 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex _settings = context.API.LoadSettingJsonStorage(); + _faviconCacheDir = Path.Combine( + _context.CurrentPluginMetadata.PluginCacheDirectoryPath, + "FaviconCache"); + + Helper.ValidateDirectory(_faviconCacheDir); + LoadBookmarksIfEnabled(); } From 5d16216a5519a42c6f201219ddca60ef24289308 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 21:53:09 +0800 Subject: [PATCH 0658/1798] Fix environment exit --- Flow.Launcher.Core/Configuration/Portable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index 069154364..4f8287c16 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -169,7 +169,7 @@ namespace Flow.Launcher.Core.Configuration { FilesFolders.OpenPath(Constant.RootDirectory, (s) => API.ShowMsgBox(s)); - Environment.Exit(0); + Application.Current.Shutdown(); } } // Otherwise, if the portable data folder is marked for deletion, From 96f10d27997f13e24866a415c346ba947e515f98 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 22:13:12 +0800 Subject: [PATCH 0659/1798] Code quality --- Flow.Launcher.Infrastructure/Win32Helper.cs | 11 +++++++++++ Flow.Launcher/Notification.cs | 5 ++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 7a3a0c36e..42461dc18 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -488,5 +488,16 @@ namespace Flow.Launcher.Infrastructure } #endregion + + #region Noticification + + public static bool IsNotificationSupport() + { + // Noticification only supported Windows 10 19041+ + return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && + Environment.OSVersion.Version.Build >= 19041; + } + + #endregion } } diff --git a/Flow.Launcher/Notification.cs b/Flow.Launcher/Notification.cs index cb1cbb729..23125de15 100644 --- a/Flow.Launcher/Notification.cs +++ b/Flow.Launcher/Notification.cs @@ -9,8 +9,8 @@ namespace Flow.Launcher { internal static class Notification { - internal static bool legacy = Environment.OSVersion.Version.Build < 19041; - [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "")] + internal static bool legacy = !Win32Helper.IsNotificationSupport(); + internal static void Uninstall() { if (!legacy) @@ -25,7 +25,6 @@ namespace Flow.Launcher }); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "")] private static void ShowInternal(string title, string subTitle, string iconPath = null) { // Handle notification for win7/8/early win10 From b1721f15077c264a79df2642e12a5fd1c1b369fe Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 22:25:04 +0800 Subject: [PATCH 0660/1798] Code quality --- Flow.Launcher.Core/Updater.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 9a77ece32..5b2144efe 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -4,10 +4,11 @@ using System.Net; using System.Net.Http; using System.Net.Sockets; using System.Linq; +using System.Text.Json.Serialization; +using System.Threading; using System.Threading.Tasks; using System.Windows; -using JetBrains.Annotations; -using Squirrel; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core.Resource; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Infrastructure; @@ -15,8 +16,8 @@ using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; -using System.Text.Json.Serialization; -using System.Threading; +using JetBrains.Annotations; +using Squirrel; namespace Flow.Launcher.Core { @@ -70,7 +71,7 @@ namespace Flow.Launcher.Core if (DataLocation.PortableDataLocationInUse()) { - var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion.ToString()}\\{DataLocation.PortableFolderName}"; + var targetDestination = updateManager.RootAppDirectory + $"\\app-{newReleaseVersion}\\{DataLocation.PortableFolderName}"; 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"), @@ -122,7 +123,7 @@ namespace Flow.Launcher.Core } // https://github.com/Squirrel/Squirrel.Windows/blob/master/src/Squirrel/UpdateManager.Factory.cs - private async Task GitHubUpdateManagerAsync(string repository) + private static async Task GitHubUpdateManagerAsync(string repository) { var uri = new Uri(repository); var api = $"https://api.github.com/repos{uri.AbsolutePath}/releases"; @@ -144,9 +145,9 @@ namespace Flow.Launcher.Core return manager; } - public string NewVersionTips(string version) + private static string NewVersionTips(string version) { - var translator = InternationalizationManager.Instance; + var translator = Ioc.Default.GetRequiredService(); var tips = string.Format(translator.GetTranslation("newVersionTips"), version); return tips; From 0def881b9d74497974124c35327cfa10b6bc35fa Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 22:27:02 +0800 Subject: [PATCH 0661/1798] Code quality --- Flow.Launcher.Core/Configuration/Portable.cs | 40 ++++++++------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index 4f8287c16..8abdae8d8 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -22,7 +22,7 @@ namespace Flow.Launcher.Core.Configuration /// As at Squirrel.Windows version 1.5.2, UpdateManager needs to be disposed after finish /// /// - private UpdateManager NewUpdateManager() + private static UpdateManager NewUpdateManager() { var applicationFolderName = Constant.ApplicationDirectory .Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None) @@ -81,20 +81,16 @@ namespace Flow.Launcher.Core.Configuration public void RemoveShortcuts() { - using (var portabilityUpdater = NewUpdateManager()) - { - portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu); - portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop); - portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup); - } + using var portabilityUpdater = NewUpdateManager(); + portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu); + portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop); + portabilityUpdater.RemoveShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup); } public void RemoveUninstallerEntry() { - using (var portabilityUpdater = NewUpdateManager()) - { - portabilityUpdater.RemoveUninstallerRegistryEntry(); - } + using var portabilityUpdater = NewUpdateManager(); + portabilityUpdater.RemoveUninstallerRegistryEntry(); } public void MoveUserDataFolder(string fromLocation, string toLocation) @@ -110,12 +106,10 @@ namespace Flow.Launcher.Core.Configuration public void CreateShortcuts() { - using (var portabilityUpdater = NewUpdateManager()) - { - portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu, false); - portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop, false); - portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup, false); - } + using var portabilityUpdater = NewUpdateManager(); + portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.StartMenu, false); + portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Desktop, false); + portabilityUpdater.CreateShortcutsForExecutable(Constant.ApplicationFileName, ShortcutLocation.Startup, false); } public void CreateUninstallerEntry() @@ -129,18 +123,14 @@ namespace Flow.Launcher.Core.Configuration subKey2.SetValue("DisplayIcon", Path.Combine(Constant.ApplicationDirectory, "app.ico"), RegistryValueKind.String); } - using (var portabilityUpdater = NewUpdateManager()) - { - _ = portabilityUpdater.CreateUninstallerRegistryEntry(); - } + using var portabilityUpdater = NewUpdateManager(); + _ = portabilityUpdater.CreateUninstallerRegistryEntry(); } - internal void IndicateDeletion(string filePathTodelete) + private static void IndicateDeletion(string filePathTodelete) { var deleteFilePath = Path.Combine(filePathTodelete, DataLocation.DeletionIndicatorFile); - using (var _ = File.CreateText(deleteFilePath)) - { - } + using var _ = File.CreateText(deleteFilePath); } /// From 2f53a79a26fc84cb012d580a37c9c2bab7eb7965 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 22:56:31 +0800 Subject: [PATCH 0662/1798] Revert "Fix environment exit" This reverts commit 5d16216a5519a42c6f201219ddca60ef24289308. --- Flow.Launcher.Core/Configuration/Portable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Configuration/Portable.cs b/Flow.Launcher.Core/Configuration/Portable.cs index 8abdae8d8..2b570d2c0 100644 --- a/Flow.Launcher.Core/Configuration/Portable.cs +++ b/Flow.Launcher.Core/Configuration/Portable.cs @@ -159,7 +159,7 @@ namespace Flow.Launcher.Core.Configuration { FilesFolders.OpenPath(Constant.RootDirectory, (s) => API.ShowMsgBox(s)); - Application.Current.Shutdown(); + Environment.Exit(0); } } // Otherwise, if the portable data folder is marked for deletion, From b725975b9898e249a7382171cf2edb07437871d0 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 3 Apr 2025 23:01:16 +0800 Subject: [PATCH 0663/1798] Fix environment exit stuck issue --- Flow.Launcher/App.xaml.cs | 8 ++++++++ Flow.Launcher/MainWindow.xaml.cs | 13 +++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 9aee56bff..f484d4dba 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -304,6 +304,14 @@ namespace Flow.Launcher return; } + // If we call Environment.Exit(0), the application dispose will be called before _mainWindow.Close() + // Accessing _mainWindow?.Dispatcher will cause the application stuck + // So here we need to check it and just return so that we will not acees _mainWindow?.Dispatcher + if (!_mainWindow.CanClose) + { + return; + } + _disposed = true; } diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 011d46d6b..c62606743 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -32,6 +32,13 @@ namespace Flow.Launcher { public partial class MainWindow : IDisposable { + #region Public Property + + // Window Event: Close Event + public bool CanClose { get; set; } = false; + + #endregion + #region Private Fields // Dependency Injection @@ -45,8 +52,6 @@ namespace Flow.Launcher private readonly ContextMenu _contextMenu = new(); private readonly MainViewModel _viewModel; - // Window Event: Close Event - private bool _canClose = false; // Window Event: Key Event private bool _isArrowKeyPressed = false; @@ -279,7 +284,7 @@ namespace Flow.Launcher private async void OnClosing(object sender, CancelEventArgs e) { - if (!_canClose) + if (!CanClose) { _notifyIcon.Visible = false; App.API.SaveAppAllSettings(); @@ -287,7 +292,7 @@ namespace Flow.Launcher await PluginManager.DisposePluginsAsync(); Notification.Uninstall(); // After plugins are all disposed, we can close the main window - _canClose = true; + CanClose = true; // Use this instead of Close() to avoid InvalidOperationException when calling Close() in OnClosing event Application.Current.Shutdown(); } From 95b38d21af7b8790659d9eb49e2edbbba9a037b1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 09:57:03 +0800 Subject: [PATCH 0664/1798] Wait image cache saved before restarting --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 8 +++++++- Flow.Launcher/PublicAPIInstance.cs | 7 +++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 6f7b1cd90..0ba059b7b 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -61,7 +61,7 @@ namespace Flow.Launcher.Infrastructure.Image }); } - public static async Task Save() + public static async Task SaveAsync() { await storageLock.WaitAsync(); @@ -77,6 +77,12 @@ namespace Flow.Launcher.Infrastructure.Image } } + public static async Task WaitSaveAsync() + { + await storageLock.WaitAsync(); + storageLock.Release(); + } + private static async Task> LoadStorageToConcurrentDictionaryAsync() { await storageLock.WaitAsync(); diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index e19ad2fdc..b86e731b3 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -57,7 +57,7 @@ namespace Flow.Launcher _mainVM.ChangeQueryText(query, requery); } - public void RestartApp() + public async void RestartApp() { _mainVM.Hide(); @@ -66,6 +66,9 @@ namespace Flow.Launcher // which will cause ungraceful exit SaveAppAllSettings(); + // wait for all image caches to be saved + await ImageLoader.WaitSaveAsync(); + // Restart requires Squirrel's Update.exe to be present in the parent folder, // it is only published from the project's release pipeline. When debugging without it, // the project may not restart or just terminates. This is expected. @@ -88,7 +91,7 @@ namespace Flow.Launcher PluginManager.Save(); _mainVM.Save(); _settings.Save(); - _ = ImageLoader.Save(); + _ = ImageLoader.SaveAsync(); } public Task ReloadAllPluginData() => PluginManager.ReloadDataAsync(); From e4577eb23edbe6ce4e13154d2588d9e42e494764 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 10:02:47 +0800 Subject: [PATCH 0665/1798] Improve code comment --- Flow.Launcher/PublicAPIInstance.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index b86e731b3..a9862c74c 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -57,16 +57,18 @@ namespace Flow.Launcher _mainVM.ChangeQueryText(query, requery); } +#pragma warning disable VSTHRD100 // Avoid async void methods + public async void RestartApp() { _mainVM.Hide(); - // we must manually save + // We must manually save // UpdateManager.RestartApp() will call Environment.Exit(0) // which will cause ungraceful exit SaveAppAllSettings(); - // wait for all image caches to be saved + // Wait for all image caches to be saved before restarting await ImageLoader.WaitSaveAsync(); // Restart requires Squirrel's Update.exe to be present in the parent folder, @@ -75,6 +77,8 @@ namespace Flow.Launcher UpdateManager.RestartApp(Constant.ApplicationFileName); } +#pragma warning restore VSTHRD100 // Avoid async void methods + public void ShowMainWindow() => _mainVM.Show(); public void HideMainWindow() => _mainVM.Hide(); From 043fe76a613a5768bcd0e983acb555c58a8d681f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 10:03:19 +0800 Subject: [PATCH 0666/1798] Add settings save lock --- Flow.Launcher/PublicAPIInstance.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index a9862c74c..d88eeb7c9 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -37,6 +37,8 @@ namespace Flow.Launcher private readonly Internationalization _translater; private readonly MainViewModel _mainVM; + private readonly object _saveSettingsLock = new(); + #region Constructor public PublicAPIInstance(Settings settings, Internationalization translater, MainViewModel mainVM) @@ -92,9 +94,12 @@ namespace Flow.Launcher public void SaveAppAllSettings() { - PluginManager.Save(); - _mainVM.Save(); - _settings.Save(); + lock (_saveSettingsLock) + { + _settings.Save(); + PluginManager.Save(); + _mainVM.Save(); + } _ = ImageLoader.SaveAsync(); } From 95a3fd36dea778911d0f4f8b9a434e4813096b6a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 10:34:59 +0800 Subject: [PATCH 0667/1798] Do not crash when caught exception on saving settings --- .../Plugin/JsonRPCPluginSettings.cs | 20 +++++++++-- .../Storage/FlowLauncherJsonStorage.cs | 35 ++++++++++++++++++- .../Storage/PluginJsonStorage.cs | 33 +++++++++++++++++ 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs index 944b2fd10..e0a217251 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs @@ -23,6 +23,8 @@ namespace Flow.Launcher.Core.Plugin protected ConcurrentDictionary Settings { get; set; } = null!; public required IPublicAPI API { get; init; } + private static readonly string ClassName = nameof(JsonRPCPluginSettings); + private JsonStorage> _storage = null!; private static readonly Thickness SettingPanelMargin = (Thickness)Application.Current.FindResource("SettingPanelMargin"); @@ -122,12 +124,26 @@ namespace Flow.Launcher.Core.Plugin public async Task SaveAsync() { - await _storage.SaveAsync(); + try + { + await _storage.SaveAsync(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin settings to path: {SettingPath}", e); + } } public void Save() { - _storage.Save(); + try + { + _storage.Save(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin settings to path: {SettingPath}", e); + } } public bool NeedCreateSettingPanel() diff --git a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs index 865041fb3..a3634a0e2 100644 --- a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs @@ -1,10 +1,19 @@ using System.IO; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Infrastructure.Storage { public class FlowLauncherJsonStorage : JsonStorage where T : new() { + private static readonly string ClassName = "FlowLauncherJsonStorage"; + + // 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 FlowLauncherJsonStorage() { var directoryPath = Path.Combine(DataLocation.DataDirectory(), DirectoryName); @@ -13,5 +22,29 @@ namespace Flow.Launcher.Infrastructure.Storage var filename = typeof(T).Name; FilePath = Path.Combine(directoryPath, $"{filename}{FileSuffix}"); } + + public new void Save() + { + try + { + base.Save(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save FL settings to path: {FilePath}", e); + } + } + + public new async Task SaveAsync() + { + try + { + await base.SaveAsync(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save FL settings to path: {FilePath}", e); + } + } } -} \ No newline at end of file +} diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs index b377c81aa..e02d51bdb 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs @@ -1,5 +1,8 @@ using System.IO; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Infrastructure.Storage { @@ -8,6 +11,12 @@ namespace Flow.Launcher.Infrastructure.Storage // Use assembly name to check which plugin is using this storage public readonly string AssemblyName; + private static readonly string ClassName = "PluginJsonStorage"; + + // 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 PluginJsonStorage() { // C# related, add python related below @@ -23,5 +32,29 @@ namespace Flow.Launcher.Infrastructure.Storage { Data = data; } + + public new void Save() + { + try + { + base.Save(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin settings to path: {FilePath}", e); + } + } + + public new async Task SaveAsync() + { + try + { + await base.SaveAsync(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin settings to path: {FilePath}", e); + } + } } } From f6e3608f72ab28c48bf8563ea3bb58af7b9950bb Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 10:42:48 +0800 Subject: [PATCH 0668/1798] Do not crash when saving cache --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 0ba059b7b..1ee033821 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -71,6 +71,10 @@ namespace Flow.Launcher.Infrastructure.Image .Select(x => x.Key) .ToList()); } + catch (System.Exception e) + { + Log.Exception($"|ImageLoader.SaveAsync|Failed to save image cache to file", e); + } finally { storageLock.Release(); From 2d6667bb53549c5580004fe194b56b90d20cdcd7 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 10:42:55 +0800 Subject: [PATCH 0669/1798] Test save error --- Flow.Launcher.Infrastructure/Storage/JsonStorage.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs index 40106acd8..52bcdcfab 100644 --- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs @@ -180,20 +180,24 @@ namespace Flow.Launcher.Infrastructure.Storage public void Save() { - string serialized = JsonSerializer.Serialize(Data, + throw new NotImplementedException("Save error"); + + /*string serialized = JsonSerializer.Serialize(Data, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(TempFilePath, serialized); - AtomicWriteSetting(); + AtomicWriteSetting();*/ } public async Task SaveAsync() { - await using var tempOutput = File.OpenWrite(TempFilePath); + throw new NotImplementedException("SaveAsync error"); + + /*await using var tempOutput = File.OpenWrite(TempFilePath); await JsonSerializer.SerializeAsync(tempOutput, Data, new JsonSerializerOptions { WriteIndented = true }); - AtomicWriteSetting(); + AtomicWriteSetting();*/ } private void AtomicWriteSetting() From c2f8480c049a4a818831c05558080907f2bac8d0 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:15:13 +0800 Subject: [PATCH 0670/1798] Revert "Test save error" This reverts commit 2d6667bb53549c5580004fe194b56b90d20cdcd7. --- Flow.Launcher.Infrastructure/Storage/JsonStorage.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs index 52bcdcfab..40106acd8 100644 --- a/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/JsonStorage.cs @@ -180,24 +180,20 @@ namespace Flow.Launcher.Infrastructure.Storage public void Save() { - throw new NotImplementedException("Save error"); - - /*string serialized = JsonSerializer.Serialize(Data, + string serialized = JsonSerializer.Serialize(Data, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(TempFilePath, serialized); - AtomicWriteSetting();*/ + AtomicWriteSetting(); } public async Task SaveAsync() { - throw new NotImplementedException("SaveAsync error"); - - /*await using var tempOutput = File.OpenWrite(TempFilePath); + await using var tempOutput = File.OpenWrite(TempFilePath); await JsonSerializer.SerializeAsync(tempOutput, Data, new JsonSerializerOptions { WriteIndented = true }); - AtomicWriteSetting();*/ + AtomicWriteSetting(); } private void AtomicWriteSetting() From 2a2ef234d952be3bc44507f95248b1622b92256d Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:17:30 +0800 Subject: [PATCH 0671/1798] Fix typos Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Infrastructure/Win32Helper.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 42461dc18..f2b99588d 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -489,8 +489,7 @@ namespace Flow.Launcher.Infrastructure #endregion - #region Noticification - + #region Notification public static bool IsNotificationSupport() { // Noticification only supported Windows 10 19041+ From 834780d6e7d57577a59f35c0ad5715f99e7b61cf Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:17:37 +0800 Subject: [PATCH 0672/1798] Fix typos Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Infrastructure/Win32Helper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index f2b99588d..5bec3e5e7 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -492,7 +492,7 @@ namespace Flow.Launcher.Infrastructure #region Notification public static bool IsNotificationSupport() { - // Noticification only supported Windows 10 19041+ + // Notification only supported Windows 10 19041+ return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version.Build >= 19041; } From 8df1e6a0ce9977346327c9e9249ef2359c3a9ad1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:18:57 +0800 Subject: [PATCH 0673/1798] Add blank line --- Flow.Launcher.Infrastructure/Win32Helper.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 5bec3e5e7..d3023a3f0 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -490,6 +490,7 @@ namespace Flow.Launcher.Infrastructure #endregion #region Notification + public static bool IsNotificationSupport() { // Notification only supported Windows 10 19041+ From 3283adce59384003887d5d91dfa767ca6822c92e Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:27:10 +0800 Subject: [PATCH 0674/1798] Fix typos Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- 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 d3023a3f0..c21849403 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -491,9 +491,9 @@ namespace Flow.Launcher.Infrastructure #region Notification - public static bool IsNotificationSupport() + public static bool IsNotificationSupported() { - // Notification only supported Windows 10 19041+ + // Notifications only supported on Windows 10 19041+ return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Environment.OSVersion.Version.Build >= 19041; } From ec7a4e8aaa1463524ae0cacebceb5ec7f89e94b8 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:27:50 +0800 Subject: [PATCH 0675/1798] Fix build issue --- Flow.Launcher/Notification.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Notification.cs b/Flow.Launcher/Notification.cs index 23125de15..30b3a0673 100644 --- a/Flow.Launcher/Notification.cs +++ b/Flow.Launcher/Notification.cs @@ -9,7 +9,7 @@ namespace Flow.Launcher { internal static class Notification { - internal static bool legacy = !Win32Helper.IsNotificationSupport(); + internal static bool legacy = !Win32Helper.IsNotificationSupported(); internal static void Uninstall() { From 28ab71f11a60304db888c465e871c24be5b18ab5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 11:46:07 +0800 Subject: [PATCH 0676/1798] Fix build issue --- Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs | 1 + Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs index 0fbeed9f5..8b4062b6b 100644 --- a/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/FlowLauncherJsonStorage.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage { diff --git a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs index 910672119..e8cbd70fb 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginJsonStorage.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage { From df84e02f55d87404d1f9fe07299d20747072900c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 15:37:03 +0800 Subject: [PATCH 0677/1798] Improve code quality --- ...Flow.Launcher.Plugin.PluginsManager.csproj | 3 +- .../Main.cs | 13 ++++----- .../PluginsManager.cs | 29 +++++++++---------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj index c33c42889..5a2259ff1 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj @@ -18,8 +18,7 @@ - - + diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index 156135f81..b333aba42 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -1,18 +1,17 @@ -using Flow.Launcher.Core.ExternalPlugins; -using Flow.Launcher.Plugin.PluginsManager.ViewModels; -using Flow.Launcher.Plugin.PluginsManager.Views; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Windows.Controls; -using Flow.Launcher.Infrastructure; using System.Threading.Tasks; using System.Threading; +using Flow.Launcher.Core.ExternalPlugins; +using Flow.Launcher.Plugin.PluginsManager.ViewModels; +using Flow.Launcher.Plugin.PluginsManager.Views; namespace Flow.Launcher.Plugin.PluginsManager { public class Main : ISettingProvider, IAsyncPlugin, IContextMenu, IPluginI18n { - internal PluginInitContext Context { get; set; } + internal static PluginInitContext Context { get; set; } internal Settings Settings; @@ -56,7 +55,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Settings.UpdateCommand => await pluginManager.RequestUpdateAsync(query.SecondToEndSearch, token, query.IsReQuery), _ => pluginManager.GetDefaultHotKeys().Where(hotkey => { - hotkey.Score = StringMatcher.FuzzySearch(query.Search, hotkey.Title).Score; + hotkey.Score = Context.API.FuzzySearch(query.Search, hotkey.Title).Score; return hotkey.Score > 0; }).ToList() }; diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 79d6aedd5..9cee8bc8f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -1,8 +1,5 @@ using Flow.Launcher.Core.ExternalPlugins; using Flow.Launcher.Core.Plugin; -using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Http; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.SharedCommands; using System; using System.Collections.Generic; @@ -17,7 +14,9 @@ namespace Flow.Launcher.Plugin.PluginsManager { internal class PluginsManager { - private const string zip = "zip"; + private const string ZipSuffix = "zip"; + + private static readonly string ClassName = nameof(PluginsManager); private PluginInitContext Context { get; set; } @@ -169,7 +168,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.ShowMsgError( string.Format(Context.API.GetTranslation("plugin_pluginsmanager_downloading_plugin"), plugin.Name), Context.API.GetTranslation("plugin_pluginsmanager_download_error")); - Log.Exception("PluginsManager", "An error occurred while downloading plugin", e); + Context.API.LogException(ClassName, "An error occurred while downloading plugin", e); return; } @@ -179,7 +178,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_subtitle"), plugin.Name)); - Log.Exception("PluginsManager", "An error occurred while downloading plugin", e); + Context.API.LogException(ClassName, "An error occurred while downloading plugin", e); return; } @@ -366,7 +365,7 @@ namespace Flow.Launcher.Plugin.PluginsManager } }).ContinueWith(t => { - Log.Exception("PluginsManager", $"Update failed for {x.Name}", + Context.API.LogException(ClassName, $"Update failed for {x.Name}", t.Exception.InnerException); Context.API.ShowMsg( Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), @@ -438,7 +437,7 @@ namespace Flow.Launcher.Plugin.PluginsManager } catch (Exception ex) { - Log.Exception("PluginsManager", $"Update failed for {plugin.Name}", ex.InnerException); + Context.API.LogException(ClassName, $"Update failed for {plugin.Name}", ex.InnerException); Context.API.ShowMsg( Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format( @@ -486,7 +485,7 @@ namespace Flow.Launcher.Plugin.PluginsManager return results .Where(x => { - var matchResult = StringMatcher.FuzzySearch(searchName, x.Title); + var matchResult = Context.API.FuzzySearch(searchName, x.Title); if (matchResult.IsSearchPrecisionScoreMet()) x.Score = matchResult.Score; @@ -498,7 +497,7 @@ namespace Flow.Launcher.Plugin.PluginsManager internal List InstallFromWeb(string url) { var filename = url.Split("/").Last(); - var name = filename.Split(string.Format(".{0}", zip)).First(); + var name = filename.Split(string.Format(".{0}", ZipSuffix)).First(); var plugin = new UserPlugin { @@ -605,7 +604,7 @@ namespace Flow.Launcher.Plugin.PluginsManager await PluginsManifest.UpdateManifestAsync(token, usePrimaryUrlOnly); if (Uri.IsWellFormedUriString(search, UriKind.Absolute) - && search.Split('.').Last() == zip) + && search.Split('.').Last() == ZipSuffix) return InstallFromWeb(search); if (FilesFolders.IsZipFilePath(search, checkFileExists: true)) @@ -656,21 +655,21 @@ namespace Flow.Launcher.Plugin.PluginsManager { Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), Context.API.GetTranslation("plugin_pluginsmanager_install_errormetadatafile")); - Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); + Context.API.LogException(ClassName, e.Message, e); } catch (InvalidOperationException e) { Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_install_error_duplicate"), plugin.Name)); - Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); + Context.API.LogException(ClassName, e.Message, e); } catch (ArgumentException e) { Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_install_error_title"), string.Format(Context.API.GetTranslation("plugin_pluginsmanager_plugin_modified_error"), plugin.Name)); - Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); + Context.API.LogException(ClassName, e.Message, e); } } @@ -744,7 +743,7 @@ namespace Flow.Launcher.Plugin.PluginsManager } catch (ArgumentException e) { - Log.Exception("Flow.Launcher.Plugin.PluginsManager", e.Message, e); + Context.API.LogException(ClassName, e.Message, e); Context.API.ShowMsgError(Context.API.GetTranslation("plugin_pluginsmanager_uninstall_error_title"), Context.API.GetTranslation("plugin_pluginsmanager_plugin_modified_error")); } From e2d9148702aa47a64d02c915fda77f80b165bc54 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 15:52:57 +0800 Subject: [PATCH 0678/1798] Move user plugin to plugin project --- .../ExternalPlugins/CommunityPluginSource.cs | 1 + .../ExternalPlugins/CommunityPluginStore.cs | 1 + .../ExternalPlugins/PluginsManifest.cs | 1 + .../ExternalPlugins/UserPlugin.cs | 23 ------ Flow.Launcher.Plugin/UserPlugin.cs | 80 +++++++++++++++++++ .../ViewModel/PluginStoreItemViewModel.cs | 2 - .../ContextMenu.cs | 3 +- .../Utilities.cs | 3 +- 8 files changed, 85 insertions(+), 29 deletions(-) delete mode 100644 Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs create mode 100644 Flow.Launcher.Plugin/UserPlugin.cs diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs index 68be746f2..e9713564e 100644 --- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs +++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginSource.cs @@ -1,5 +1,6 @@ using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Plugin; using System; using System.Collections.Generic; using System.Net; diff --git a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs index affd7c312..1f23c2f66 100644 --- a/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs +++ b/Flow.Launcher.Core/ExternalPlugins/CommunityPluginStore.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.ExternalPlugins { diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index ac8abcdcc..4f5c4ae40 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -1,4 +1,5 @@ using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Plugin; using System; using System.Collections.Generic; using System.Threading; diff --git a/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs b/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs deleted file mode 100644 index 79d6d7605..000000000 --- a/Flow.Launcher.Core/ExternalPlugins/UserPlugin.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace Flow.Launcher.Core.ExternalPlugins -{ - public record UserPlugin - { - public string ID { get; set; } - public string Name { get; set; } - public string Description { get; set; } - public string Author { get; set; } - public string Version { get; set; } - public string Language { get; set; } - public string Website { get; set; } - public string UrlDownload { get; set; } - public string UrlSourceCode { get; set; } - public string LocalInstallPath { get; set; } - public string IcoPath { get; set; } - public DateTime? LatestReleaseDate { get; set; } - public DateTime? DateAdded { get; set; } - - public bool IsFromLocalInstallPath => !string.IsNullOrEmpty(LocalInstallPath); - } -} diff --git a/Flow.Launcher.Plugin/UserPlugin.cs b/Flow.Launcher.Plugin/UserPlugin.cs new file mode 100644 index 000000000..5c9189ae1 --- /dev/null +++ b/Flow.Launcher.Plugin/UserPlugin.cs @@ -0,0 +1,80 @@ +using System; + +namespace Flow.Launcher.Plugin +{ + /// + /// User Plugin Model for Flow Launcher + /// + public record UserPlugin + { + /// + /// Unique identifier of the plugin + /// + public string ID { get; set; } + + /// + /// Name of the plugin + /// + public string Name { get; set; } + + /// + /// Description of the plugin + /// + public string Description { get; set; } + + /// + /// Author of the plugin + /// + public string Author { get; set; } + + /// + /// Version of the plugin + /// + public string Version { get; set; } + + /// + /// Allow language of the plugin + /// + public string Language { get; set; } + + /// + /// Website of the plugin + /// + public string Website { get; set; } + + /// + /// URL to download the plugin + /// + public string UrlDownload { get; set; } + + /// + /// URL to the source code of the plugin + /// + public string UrlSourceCode { get; set; } + + /// + /// URL to the issue tracker of the plugin + /// + public string LocalInstallPath { get; set; } + + /// + /// Icon path of the plugin + /// + public string IcoPath { get; set; } + + /// + /// The date when the plugin was last updated + /// + public DateTime? LatestReleaseDate { get; set; } + + /// + /// The date when the plugin was added to the local system + /// + public DateTime? DateAdded { get; set; } + + /// + /// The date when the plugin was last updated on the local system + /// + public bool IsFromLocalInstallPath => !string.IsNullOrEmpty(LocalInstallPath); + } +} diff --git a/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs b/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs index 38b5bec65..d1cf74501 100644 --- a/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginStoreItemViewModel.cs @@ -1,10 +1,8 @@ using System; using System.Linq; using CommunityToolkit.Mvvm.Input; -using Flow.Launcher.Core.ExternalPlugins; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Plugin; -using SemanticVersioning; using Version = SemanticVersioning.Version; namespace Flow.Launcher.ViewModel diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs index 482e821dc..265657ef4 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/ContextMenu.cs @@ -1,5 +1,4 @@ -using Flow.Launcher.Core.ExternalPlugins; -using System.Collections.Generic; +using System.Collections.Generic; using System.Text.RegularExpressions; namespace Flow.Launcher.Plugin.PluginsManager diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Utilities.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Utilities.cs index 743f5b25b..4bb78f6ff 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Utilities.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Utilities.cs @@ -1,5 +1,4 @@ -using Flow.Launcher.Core.ExternalPlugins; -using ICSharpCode.SharpZipLib.Zip; +using ICSharpCode.SharpZipLib.Zip; using System.IO; using System.IO.Compression; using System.Linq; From b9c0eb7b7859d5288f1cb53bb60be110ed669210 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 15:56:18 +0800 Subject: [PATCH 0679/1798] Code quality --- .../ExternalPlugins/PluginsManifest.cs | 12 ++++++------ .../PluginsManager.cs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs index 4f5c4ae40..44d3ef0ff 100644 --- a/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs +++ b/Flow.Launcher.Core/ExternalPlugins/PluginsManifest.cs @@ -1,9 +1,9 @@ -using Flow.Launcher.Infrastructure.Logger; -using Flow.Launcher.Plugin; -using System; +using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.ExternalPlugins { @@ -18,11 +18,11 @@ namespace Flow.Launcher.Core.ExternalPlugins private static readonly SemaphoreSlim manifestUpdateLock = new(1); private static DateTime lastFetchedAt = DateTime.MinValue; - private static TimeSpan fetchTimeout = TimeSpan.FromMinutes(2); + private static readonly TimeSpan fetchTimeout = TimeSpan.FromMinutes(2); public static List UserPlugins { get; private set; } - public static async Task UpdateManifestAsync(CancellationToken token = default, bool usePrimaryUrlOnly = false) + public static async Task UpdateManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default) { try { @@ -44,7 +44,7 @@ namespace Flow.Launcher.Core.ExternalPlugins } catch (Exception e) { - Log.Exception($"|PluginsManifest.{nameof(UpdateManifestAsync)}|Http request failed", e); + Ioc.Default.GetRequiredService().LogException(nameof(PluginsManifest), "Http request failed", e); } finally { diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 9cee8bc8f..9d2a8fe73 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -236,7 +236,7 @@ namespace Flow.Launcher.Plugin.PluginsManager internal async ValueTask> RequestUpdateAsync(string search, CancellationToken token, bool usePrimaryUrlOnly = false) { - await PluginsManifest.UpdateManifestAsync(token, usePrimaryUrlOnly); + await PluginsManifest.UpdateManifestAsync(usePrimaryUrlOnly, token); var pluginFromLocalPath = null as UserPlugin; var updateFromLocalPath = false; @@ -601,7 +601,7 @@ namespace Flow.Launcher.Plugin.PluginsManager internal async ValueTask> RequestInstallOrUpdateAsync(string search, CancellationToken token, bool usePrimaryUrlOnly = false) { - await PluginsManifest.UpdateManifestAsync(token, usePrimaryUrlOnly); + await PluginsManifest.UpdateManifestAsync(usePrimaryUrlOnly, token); if (Uri.IsWellFormedUriString(search, UriKind.Absolute) && search.Split('.').Last() == ZipSuffix) From 55d1754ed6941835745baf7a64efac7be05a5cb1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 16:05:33 +0800 Subject: [PATCH 0680/1798] Move PluginManifest public function to api --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 18 ++++++++++++++++++ Flow.Launcher/PublicAPIInstance.cs | 6 ++++++ .../SettingsPanePluginStoreViewModel.cs | 5 ++--- .../Main.cs | 3 +-- .../PluginsManager.cs | 12 +++++------- 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index f178ebb90..513c2da84 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -344,5 +344,23 @@ namespace Flow.Launcher.Plugin /// Stop the loading bar in main window /// public void StopLoadingBar(); + + /// + /// Update the plugin manifest + /// + /// + /// FL has multiple urls to download the plugin manifest. Set this to true to only use the primary url. + /// + /// + /// + /// True if the manifest is updated successfully, false otherwise. + /// + public Task UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default); + + /// + /// Get the plugin manifest + /// + /// + public IReadOnlyList GetUserPlugins(); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index d88eeb7c9..a8ec46982 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -28,6 +28,7 @@ using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.ViewModel; using JetBrains.Annotations; using Flow.Launcher.Core.Resource; +using Flow.Launcher.Core.ExternalPlugins; namespace Flow.Launcher { @@ -354,6 +355,11 @@ namespace Flow.Launcher public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress); + public Task UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default) => + PluginsManifest.UpdateManifestAsync(usePrimaryUrlOnly, token); + + public IReadOnlyList GetUserPlugins() => PluginsManifest.UserPlugins; + #endregion #region Private Methods diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs index 15579a61d..23a316304 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; using CommunityToolkit.Mvvm.Input; -using Flow.Launcher.Core.ExternalPlugins; using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; @@ -14,7 +13,7 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel public string FilterText { get; set; } = string.Empty; public IList ExternalPlugins => - PluginsManifest.UserPlugins?.Select(p => new PluginStoreItemViewModel(p)) + App.API.GetUserPlugins()?.Select(p => new PluginStoreItemViewModel(p)) .OrderByDescending(p => p.Category == PluginStoreItemViewModel.NewRelease) .ThenByDescending(p => p.Category == PluginStoreItemViewModel.RecentlyUpdated) .ThenByDescending(p => p.Category == PluginStoreItemViewModel.None) @@ -24,7 +23,7 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel [RelayCommand] private async Task RefreshExternalPluginsAsync() { - if (await PluginsManifest.UpdateManifestAsync()) + if (await App.API.UpdatePluginManifestAsync()) { OnPropertyChanged(nameof(ExternalPlugins)); } diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs index b333aba42..742d85fc1 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Main.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Windows.Controls; using System.Threading.Tasks; using System.Threading; -using Flow.Launcher.Core.ExternalPlugins; using Flow.Launcher.Plugin.PluginsManager.ViewModels; using Flow.Launcher.Plugin.PluginsManager.Views; @@ -34,7 +33,7 @@ namespace Flow.Launcher.Plugin.PluginsManager contextMenu = new ContextMenu(Context); pluginManager = new PluginsManager(Context, Settings); - await PluginsManifest.UpdateManifestAsync(); + await Context.API.UpdatePluginManifestAsync(); } public List LoadContextMenus(Result selectedResult) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index 9d2a8fe73..c742e457c 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -1,5 +1,4 @@ -using Flow.Launcher.Core.ExternalPlugins; -using Flow.Launcher.Core.Plugin; +using Flow.Launcher.Core.Plugin; using Flow.Launcher.Plugin.SharedCommands; using System; using System.Collections.Generic; @@ -236,7 +235,7 @@ namespace Flow.Launcher.Plugin.PluginsManager internal async ValueTask> RequestUpdateAsync(string search, CancellationToken token, bool usePrimaryUrlOnly = false) { - await PluginsManifest.UpdateManifestAsync(usePrimaryUrlOnly, token); + await Context.API.UpdatePluginManifestAsync(usePrimaryUrlOnly, token); var pluginFromLocalPath = null as UserPlugin; var updateFromLocalPath = false; @@ -249,7 +248,7 @@ namespace Flow.Launcher.Plugin.PluginsManager } var updateSource = !updateFromLocalPath - ? PluginsManifest.UserPlugins + ? Context.API.GetUserPlugins() : new List { pluginFromLocalPath }; var resultsForUpdate = ( @@ -601,7 +600,7 @@ namespace Flow.Launcher.Plugin.PluginsManager internal async ValueTask> RequestInstallOrUpdateAsync(string search, CancellationToken token, bool usePrimaryUrlOnly = false) { - await PluginsManifest.UpdateManifestAsync(usePrimaryUrlOnly, token); + await Context.API.UpdatePluginManifestAsync(usePrimaryUrlOnly, token); if (Uri.IsWellFormedUriString(search, UriKind.Absolute) && search.Split('.').Last() == ZipSuffix) @@ -611,8 +610,7 @@ namespace Flow.Launcher.Plugin.PluginsManager return InstallFromLocalPath(search); var results = - PluginsManifest - .UserPlugins + Context.API.GetUserPlugins() .Where(x => !PluginExists(x.ID) && !PluginManager.PluginModified(x.ID)) .Select(x => new Result From 4744ff780e91ef36c7f835a7cb7a9b3c02a52af5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 16:33:03 +0800 Subject: [PATCH 0681/1798] Move PluginManager public function to api --- Flow.Launcher.Core/Plugin/PluginManager.cs | 43 +++++++---------- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 47 +++++++++++++++++-- Flow.Launcher/PublicAPIInstance.cs | 13 ++++- .../SettingsPanePluginStoreViewModel.cs | 2 +- .../PluginsManager.cs | 31 ++++++------ 5 files changed, 87 insertions(+), 49 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 17517832b..aa6c54a94 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -454,16 +454,11 @@ namespace Flow.Launcher.Core.Plugin #region Public functions - public static bool PluginModified(string uuid) + public static bool PluginModified(string id) { - return _modifiedPlugins.Contains(uuid); + return _modifiedPlugins.Contains(id); } - - /// - /// Update a plugin to new version, from a zip file. By default will remove the zip file if update is via url, - /// unless it's a local path installation - /// public static async Task UpdatePluginAsync(PluginMetadata existingVersion, UserPlugin newVersion, string zipFilePath) { InstallPlugin(newVersion, zipFilePath, checkModified:false); @@ -471,17 +466,11 @@ namespace Flow.Launcher.Core.Plugin _modifiedPlugins.Add(existingVersion.ID); } - /// - /// Install a plugin. By default will remove the zip file if installation is from url, unless it's a local path installation - /// public static void InstallPlugin(UserPlugin plugin, string zipFilePath) { InstallPlugin(plugin, zipFilePath, checkModified: true); } - /// - /// Uninstall a plugin. - /// public static async Task UninstallPluginAsync(PluginMetadata plugin, bool removePluginFromSettings = true, bool removePluginSettings = false) { await UninstallPluginAsync(plugin, removePluginFromSettings, removePluginSettings, true); @@ -525,20 +514,20 @@ namespace Flow.Launcher.Core.Plugin var folderName = string.IsNullOrEmpty(plugin.Version) ? $"{plugin.Name}-{Guid.NewGuid()}" : $"{plugin.Name}-{plugin.Version}"; var defaultPluginIDs = new List - { - "0ECADE17459B49F587BF81DC3A125110", // BrowserBookmark - "CEA0FDFC6D3B4085823D60DC76F28855", // Calculator - "572be03c74c642baae319fc283e561a8", // Explorer - "6A122269676E40EB86EB543B945932B9", // PluginIndicator - "9f8f9b14-2518-4907-b211-35ab6290dee7", // PluginsManager - "b64d0a79-329a-48b0-b53f-d658318a1bf6", // ProcessKiller - "791FC278BA414111B8D1886DFE447410", // Program - "D409510CD0D2481F853690A07E6DC426", // Shell - "CEA08895D2544B019B2E9C5009600DF4", // Sys - "0308FD86DE0A4DEE8D62B9B535370992", // URL - "565B73353DBF4806919830B9202EE3BF", // WebSearch - "5043CETYU6A748679OPA02D27D99677A" // WindowsSettings - }; + { + "0ECADE17459B49F587BF81DC3A125110", // BrowserBookmark + "CEA0FDFC6D3B4085823D60DC76F28855", // Calculator + "572be03c74c642baae319fc283e561a8", // Explorer + "6A122269676E40EB86EB543B945932B9", // PluginIndicator + "9f8f9b14-2518-4907-b211-35ab6290dee7", // PluginsManager + "b64d0a79-329a-48b0-b53f-d658318a1bf6", // ProcessKiller + "791FC278BA414111B8D1886DFE447410", // Program + "D409510CD0D2481F853690A07E6DC426", // Shell + "CEA08895D2544B019B2E9C5009600DF4", // Sys + "0308FD86DE0A4DEE8D62B9B535370992", // URL + "565B73353DBF4806919830B9202EE3BF", // WebSearch + "5043CETYU6A748679OPA02D27D99677A" // WindowsSettings + }; // Treat default plugin differently, it needs to be removable along with each flow release var installDirectory = !defaultPluginIDs.Any(x => x == plugin.ID) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 513c2da84..eeb3f5de3 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -352,15 +352,54 @@ namespace Flow.Launcher.Plugin /// FL has multiple urls to download the plugin manifest. Set this to true to only use the primary url. /// /// - /// - /// True if the manifest is updated successfully, false otherwise. - /// + /// True if the manifest is updated successfully, false otherwise public Task UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default); /// /// Get the plugin manifest /// /// - public IReadOnlyList GetUserPlugins(); + public IReadOnlyList GetPluginManifest(); + + /// + /// Check if the plugin has been modified. + /// If this plugin is updated, installed or uninstalled and users do not restart the app, + /// it will be marked as modified + /// + /// Plugin id + /// + public bool PluginModified(string id); + + /// + /// Update a plugin to new version, from a zip file. By default will remove the zip file if update is via url, + /// unless it's a local path installation + /// + /// The metadata of the old plugin to update + /// The new plugin to update + /// + /// Path to the zip file containing the plugin. It will be unzipped to the temporary directory, removed and installed. + /// + /// + public Task UpdatePluginAsync(PluginMetadata pluginMetadata, UserPlugin plugin, string zipFilePath); + + /// + /// Install a plugin. By default will remove the zip file if installation is from url, + /// unless it's a local path installation + /// + /// The plugin to install + /// + /// Path to the zip file containing the plugin. It will be unzipped to the temporary directory, removed and installed. + /// + public void InstallPlugin(UserPlugin plugin, string zipFilePath); + + /// + /// Uninstall a plugin + /// + /// The metadata of the plugin to uninstall + /// + /// Plugin has their own settings. If this is set to true, the plugin settings will be removed. + /// + /// + public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index a8ec46982..c40e40ebb 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -358,7 +358,18 @@ namespace Flow.Launcher public Task UpdatePluginManifestAsync(bool usePrimaryUrlOnly = false, CancellationToken token = default) => PluginsManifest.UpdateManifestAsync(usePrimaryUrlOnly, token); - public IReadOnlyList GetUserPlugins() => PluginsManifest.UserPlugins; + public IReadOnlyList GetPluginManifest() => PluginsManifest.UserPlugins; + + public bool PluginModified(string id) => PluginManager.PluginModified(id); + + public Task UpdatePluginAsync(PluginMetadata pluginMetadata, UserPlugin plugin, string zipFilePath) => + PluginManager.UpdatePluginAsync(pluginMetadata, plugin, zipFilePath); + + public void InstallPlugin(UserPlugin plugin, string zipFilePath) => + PluginManager.InstallPlugin(plugin, zipFilePath); + + public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false) => + PluginManager.UninstallPluginAsync(pluginMetadata, removePluginSettings); #endregion diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs index 23a316304..84d8a2ff9 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs @@ -13,7 +13,7 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel public string FilterText { get; set; } = string.Empty; public IList ExternalPlugins => - App.API.GetUserPlugins()?.Select(p => new PluginStoreItemViewModel(p)) + App.API.GetPluginManifest()?.Select(p => new PluginStoreItemViewModel(p)) .OrderByDescending(p => p.Category == PluginStoreItemViewModel.NewRelease) .ThenByDescending(p => p.Category == PluginStoreItemViewModel.RecentlyUpdated) .ThenByDescending(p => p.Category == PluginStoreItemViewModel.None) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index c742e457c..a16778ff4 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -1,6 +1,4 @@ -using Flow.Launcher.Core.Plugin; -using Flow.Launcher.Plugin.SharedCommands; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -8,6 +6,7 @@ using System.Net.Http; using System.Threading; using System.Threading.Tasks; using System.Windows; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Plugin.PluginsManager { @@ -49,7 +48,7 @@ namespace Flow.Launcher.Plugin.PluginsManager { return new List() { - new Result() + new() { Title = Settings.InstallCommand, IcoPath = icoPath, @@ -61,7 +60,7 @@ namespace Flow.Launcher.Plugin.PluginsManager return false; } }, - new Result() + new() { Title = Settings.UninstallCommand, IcoPath = icoPath, @@ -73,7 +72,7 @@ namespace Flow.Launcher.Plugin.PluginsManager return false; } }, - new Result() + new() { Title = Settings.UpdateCommand, IcoPath = icoPath, @@ -248,7 +247,7 @@ namespace Flow.Launcher.Plugin.PluginsManager } var updateSource = !updateFromLocalPath - ? Context.API.GetUserPlugins() + ? Context.API.GetPluginManifest() : new List { pluginFromLocalPath }; var resultsForUpdate = ( @@ -258,7 +257,7 @@ namespace Flow.Launcher.Plugin.PluginsManager 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) - && !PluginManager.PluginModified(existingPlugin.Metadata.ID) + && !Context.API.PluginModified(existingPlugin.Metadata.ID) select new { @@ -274,7 +273,7 @@ namespace Flow.Launcher.Plugin.PluginsManager if (!resultsForUpdate.Any()) return new List { - new Result + new() { Title = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_title"), SubTitle = Context.API.GetTranslation("plugin_pluginsmanager_update_noresult_subtitle"), @@ -339,7 +338,7 @@ namespace Flow.Launcher.Plugin.PluginsManager } else { - await PluginManager.UpdatePluginAsync(x.PluginExistingMetadata, x.PluginNewUserPlugin, + await Context.API.UpdatePluginAsync(x.PluginExistingMetadata, x.PluginNewUserPlugin, downloadToFilePath); if (Settings.AutoRestartAfterChanging) @@ -431,7 +430,7 @@ namespace Flow.Launcher.Plugin.PluginsManager if (cts.IsCancellationRequested) return; else - await PluginManager.UpdatePluginAsync(plugin.PluginExistingMetadata, plugin.PluginNewUserPlugin, + await Context.API.UpdatePluginAsync(plugin.PluginExistingMetadata, plugin.PluginNewUserPlugin, downloadToFilePath); } catch (Exception ex) @@ -550,7 +549,7 @@ namespace Flow.Launcher.Plugin.PluginsManager return new List { - new Result + new() { Title = $"{plugin.Name} by {plugin.Author}", SubTitle = plugin.Description, @@ -610,8 +609,8 @@ namespace Flow.Launcher.Plugin.PluginsManager return InstallFromLocalPath(search); var results = - Context.API.GetUserPlugins() - .Where(x => !PluginExists(x.ID) && !PluginManager.PluginModified(x.ID)) + Context.API.GetPluginManifest() + .Where(x => !PluginExists(x.ID) && !Context.API.PluginModified(x.ID)) .Select(x => new Result { @@ -644,7 +643,7 @@ namespace Flow.Launcher.Plugin.PluginsManager try { - PluginManager.InstallPlugin(plugin, downloadedFilePath); + Context.API.InstallPlugin(plugin, downloadedFilePath); if (!plugin.IsFromLocalInstallPath) File.Delete(downloadedFilePath); @@ -737,7 +736,7 @@ namespace Flow.Launcher.Plugin.PluginsManager Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_subtitle"), Context.API.GetTranslation("plugin_pluginsmanager_keep_plugin_settings_title"), button: MessageBoxButton.YesNo) == MessageBoxResult.No; - await PluginManager.UninstallPluginAsync(plugin, removePluginFromSettings: true, removePluginSettings: removePluginSettings); + await Context.API.UninstallPluginAsync(plugin, removePluginSettings); } catch (ArgumentException e) { From 473b139ea4a6b43346aa79c582ff66f0094477ca Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 16:35:28 +0800 Subject: [PATCH 0682/1798] Move FL project reference --- .../Flow.Launcher.Plugin.PluginsManager.csproj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj index 5a2259ff1..8ff41a7ad 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj @@ -18,7 +18,6 @@ - @@ -36,4 +35,8 @@ PreserveNewest + + + + From 56536d018891a7a28e1c5916a1426045b3682360 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 16:45:58 +0800 Subject: [PATCH 0683/1798] Add log for plugin binary storage --- .../Storage/PluginBinaryStorage.cs | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs index 87f51d5d7..d18060e3d 100644 --- a/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs +++ b/Flow.Launcher.Infrastructure/Storage/PluginBinaryStorage.cs @@ -1,15 +1,49 @@ using System.IO; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Infrastructure.Storage { public class PluginBinaryStorage : BinaryStorage where T : new() { + private static readonly string ClassName = "PluginBinaryStorage"; + + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + public PluginBinaryStorage(string cacheName, string cacheDirectory) { DirectoryPath = cacheDirectory; - Helper.ValidateDirectory(DirectoryPath); + FilesFolders.ValidateDirectory(DirectoryPath); FilePath = Path.Combine(DirectoryPath, $"{cacheName}{FileSuffix}"); } + + public new void Save() + { + try + { + base.Save(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin caches to path: {FilePath}", e); + } + } + + public new async Task SaveAsync() + { + try + { + await base.SaveAsync(); + } + catch (System.Exception e) + { + API.LogException(ClassName, $"Failed to save plugin caches to path: {FilePath}", e); + } + } } } From cbd8d2272386ce4e28b688c9cd3b7bc8a16e832e Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Fri, 4 Apr 2025 17:24:21 +0800 Subject: [PATCH 0684/1798] Improve documents Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Flow.Launcher.Plugin/UserPlugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/UserPlugin.cs b/Flow.Launcher.Plugin/UserPlugin.cs index 5c9189ae1..3488b4b93 100644 --- a/Flow.Launcher.Plugin/UserPlugin.cs +++ b/Flow.Launcher.Plugin/UserPlugin.cs @@ -73,7 +73,7 @@ namespace Flow.Launcher.Plugin public DateTime? DateAdded { get; set; } /// - /// The date when the plugin was last updated on the local system + /// Indicates whether the plugin is installed from a local path /// public bool IsFromLocalInstallPath => !string.IsNullOrEmpty(LocalInstallPath); } From 171ebe955f23491ad6a70b3a6c197313f7aa47b0 Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Fri, 4 Apr 2025 17:24:36 +0800 Subject: [PATCH 0685/1798] Improve documents Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Flow.Launcher.Plugin/UserPlugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/UserPlugin.cs b/Flow.Launcher.Plugin/UserPlugin.cs index 3488b4b93..74a16b83d 100644 --- a/Flow.Launcher.Plugin/UserPlugin.cs +++ b/Flow.Launcher.Plugin/UserPlugin.cs @@ -53,7 +53,7 @@ namespace Flow.Launcher.Plugin public string UrlSourceCode { get; set; } /// - /// URL to the issue tracker of the plugin + /// Local path where the plugin is installed /// public string LocalInstallPath { get; set; } From 358b1fd7c875e4e4863227d53ee977872a9bd703 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:10:39 +0800 Subject: [PATCH 0686/1798] Move theme data and functions into api --- Flow.Launcher.Core/Resource/Theme.cs | 31 ++++---- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 19 +++++ Flow.Launcher.Plugin/ThemeData.cs | 71 +++++++++++++++++++ Flow.Launcher/PublicAPIInstance.cs | 13 ++++ 4 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 Flow.Launcher.Plugin/ThemeData.cs diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index e5980b62f..4cf9ce7a7 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -81,11 +81,6 @@ namespace Flow.Launcher.Core.Resource #region Theme Resources - public string GetCurrentTheme() - { - return _settings.Theme; - } - private void MakeSureThemeDirectoriesExist() { foreach (var dir in _themeDirectories.Where(dir => !Directory.Exists(dir))) @@ -127,7 +122,7 @@ namespace Flow.Launcher.Core.Resource try { // Load a ResourceDictionary for the specified theme. - var themeName = GetCurrentTheme(); + var themeName = _settings.Theme; var dict = GetThemeResourceDictionary(themeName); // Apply font settings to the theme resource. @@ -330,7 +325,7 @@ namespace Flow.Launcher.Core.Resource private ResourceDictionary GetCurrentResourceDictionary() { - return GetResourceDictionary(GetCurrentTheme()); + return GetResourceDictionary(_settings.Theme); } private ThemeData GetThemeDataFromPath(string path) @@ -383,9 +378,15 @@ namespace Flow.Launcher.Core.Resource #endregion - #region Load & Change + #region Get & Change Theme - public List LoadAvailableThemes() + public ThemeData GetCurrentTheme() + { + var themes = GetAvailableThemes(); + return themes.FirstOrDefault(t => t.FileNameWithoutExtension == _settings.Theme) ?? themes.FirstOrDefault(); + } + + public List GetAvailableThemes() { List themes = new List(); foreach (var themeDirectory in _themeDirectories) @@ -403,7 +404,7 @@ namespace Flow.Launcher.Core.Resource public bool ChangeTheme(string theme = null) { if (string.IsNullOrEmpty(theme)) - theme = GetCurrentTheme(); + theme = _settings.Theme; string path = GetThemePath(theme); try @@ -591,7 +592,7 @@ namespace Flow.Launcher.Core.Resource { AutoDropShadow(useDropShadowEffect); } - SetBlurForWindow(GetCurrentTheme(), backdropType); + SetBlurForWindow(_settings.Theme, backdropType); if (!BlurEnabled) { @@ -610,7 +611,7 @@ namespace Flow.Launcher.Core.Resource // Get the actual backdrop type and drop shadow effect settings var (backdropType, _) = GetActualValue(); - SetBlurForWindow(GetCurrentTheme(), backdropType); + SetBlurForWindow(_settings.Theme, backdropType); }, DispatcherPriority.Render); } @@ -898,11 +899,5 @@ namespace Flow.Launcher.Core.Resource } #endregion - - #region Classes - - public record ThemeData(string FileNameWithoutExtension, string Name, bool? IsDark = null, bool? HasBlur = null); - - #endregion } } diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index f178ebb90..bfcc2f9e0 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -344,5 +344,24 @@ namespace Flow.Launcher.Plugin /// Stop the loading bar in main window /// public void StopLoadingBar(); + + /// + /// Get all available themes + /// + /// + public List GetAvailableThemes(); + + /// + /// Get the current theme + /// + /// + public ThemeData GetCurrentTheme(); + + /// + /// Set the current theme + /// + /// + /// + public void SetCurrentTheme(ThemeData theme); } } diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs new file mode 100644 index 000000000..d4a69ef09 --- /dev/null +++ b/Flow.Launcher.Plugin/ThemeData.cs @@ -0,0 +1,71 @@ +namespace Flow.Launcher.Plugin; + +/// +/// Theme data model +/// +public class ThemeData +{ + /// + /// Theme file name without extension + /// + public string FileNameWithoutExtension { get; private init; } + + /// + /// Theme name + /// + public string Name { get; private init; } + + /// + /// Theme file path + /// + public bool? IsDark { get; private init; } + + /// + /// Theme file path + /// + public bool? HasBlur { get; private init; } + + /// + /// Theme data constructor + /// + public ThemeData(string fileNameWithoutExtension, string name, bool? isDark = null, bool? hasBlur = null) + { + FileNameWithoutExtension = fileNameWithoutExtension; + Name = name; + IsDark = isDark; + HasBlur = hasBlur; + } + + /// + public static bool operator ==(ThemeData left, ThemeData right) + { + return left.Equals(right); + } + + /// + public static bool operator !=(ThemeData left, ThemeData right) + { + return !(left == right); + } + + /// + public override bool Equals(object obj) + { + if (obj is not ThemeData other) + return false; + return FileNameWithoutExtension == other.FileNameWithoutExtension && + Name == other.Name; + } + + /// + public override int GetHashCode() + { + return Name?.GetHashCode() ?? 0; + } + + /// + public override string ToString() + { + return Name; + } +} diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index d88eeb7c9..96ccb55c4 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -37,6 +37,9 @@ namespace Flow.Launcher private readonly Internationalization _translater; private readonly MainViewModel _mainVM; + private Theme _theme; + private Theme Theme => _theme ??= Ioc.Default.GetRequiredService(); + private readonly object _saveSettingsLock = new(); #region Constructor @@ -354,6 +357,16 @@ namespace Flow.Launcher public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action cancelProgress = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, cancelProgress); + public List GetAvailableThemes() => Theme.GetAvailableThemes(); + + public ThemeData GetCurrentTheme() => Theme.GetCurrentTheme(); + + public void SetCurrentTheme(ThemeData theme) + { + Theme.ChangeTheme(theme.FileNameWithoutExtension); + _ = _theme.RefreshFrameAsync(); + } + #endregion #region Private Methods From 9b9704e938f1e74584c8bc7688bc333387700c6b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:11:01 +0800 Subject: [PATCH 0687/1798] Improve settings panel theme page & theme selector --- .../ViewModels/SettingsPaneThemeViewModel.cs | 14 +++--- .../Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 47 +++++-------------- 2 files changed, 17 insertions(+), 44 deletions(-) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index 6e2488fe1..58cf3a314 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -28,25 +28,23 @@ public partial class SettingsPaneThemeViewModel : BaseModel public static string LinkHowToCreateTheme => @"https://www.flowlauncher.com/theme-builder/"; public static string LinkThemeGallery => "https://github.com/Flow-Launcher/Flow.Launcher/discussions/1438"; - private List _themes; - public List Themes => _themes ??= _theme.LoadAvailableThemes(); + private List _themes; + public List Themes => _themes ??= App.API.GetAvailableThemes(); - private Theme.ThemeData _selectedTheme; - public Theme.ThemeData SelectedTheme + private ThemeData _selectedTheme; + public ThemeData SelectedTheme { - get => _selectedTheme ??= Themes.Find(v => v.FileNameWithoutExtension == _theme.GetCurrentTheme()); + get => _selectedTheme ??= Themes.Find(v => v == App.API.GetCurrentTheme()); set { _selectedTheme = value; - _theme.ChangeTheme(value.FileNameWithoutExtension); + App.API.SetCurrentTheme(value); // Update UI state OnPropertyChanged(nameof(BackdropType)); OnPropertyChanged(nameof(IsBackdropEnabled)); OnPropertyChanged(nameof(IsDropShadowEnabled)); OnPropertyChanged(nameof(DropShadowEffect)); - - _ = _theme.RefreshFrameAsync(); } } diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index 31faeba52..84bfa218e 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Linq; -using CommunityToolkit.Mvvm.DependencyInjection; -using Flow.Launcher.Core.Resource; namespace Flow.Launcher.Plugin.Sys { @@ -11,32 +9,6 @@ namespace Flow.Launcher.Plugin.Sys private readonly PluginInitContext _context; - // Do not initialize it in the constructor, because it will cause null reference in - // var dicts = Application.Current.Resources.MergedDictionaries; line of Theme - private Theme theme = null; - private Theme Theme => theme ??= Ioc.Default.GetRequiredService(); - - #region Theme Selection - - // Theme select codes simplified from SettingsPaneThemeViewModel.cs - - private Theme.ThemeData _selectedTheme; - public Theme.ThemeData SelectedTheme - { - get => _selectedTheme ??= Themes.Find(v => v.FileNameWithoutExtension == Theme.GetCurrentTheme()); - set - { - _selectedTheme = value; - Theme.ChangeTheme(value.FileNameWithoutExtension); - - _ = Theme.RefreshFrameAsync(); - } - } - - private List Themes => Theme.LoadAvailableThemes(); - - #endregion - public ThemeSelector(PluginInitContext context) { _context = context; @@ -44,28 +16,31 @@ namespace Flow.Launcher.Plugin.Sys public List Query(Query query) { + var themes = _context.API.GetAvailableThemes(); + var selectedTheme = _context.API.GetCurrentTheme(); + var search = query.SecondToEndSearch; if (string.IsNullOrWhiteSpace(search)) { - return Themes.Select(CreateThemeResult) + return themes.Select(x => CreateThemeResult(x, selectedTheme)) .OrderBy(x => x.Title) .ToList(); } - return Themes.Select(theme => (theme, matchResult: _context.API.FuzzySearch(search, theme.Name))) + return themes.Select(theme => (theme, matchResult: _context.API.FuzzySearch(search, theme.Name))) .Where(x => x.matchResult.IsSearchPrecisionScoreMet()) - .Select(x => CreateThemeResult(x.theme, x.matchResult.Score, x.matchResult.MatchData)) + .Select(x => CreateThemeResult(x.theme, selectedTheme, x.matchResult.Score, x.matchResult.MatchData)) .OrderBy(x => x.Title) .ToList(); } - private Result CreateThemeResult(Theme.ThemeData theme) => CreateThemeResult(theme, 0, null); + private Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme) => CreateThemeResult(theme, selectedTheme, 0, null); - private Result CreateThemeResult(Theme.ThemeData theme, int score, IList highlightData) + private Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme, int score, IList highlightData) { - string themeName = theme.Name; + var themeName = theme.FileNameWithoutExtension; string title; - if (theme == SelectedTheme) + if (theme == selectedTheme) { title = $"{theme.Name} ★"; // Set current theme to the top @@ -101,7 +76,7 @@ namespace Flow.Launcher.Plugin.Sys Score = score, Action = c => { - SelectedTheme = theme; + _context.API.SetCurrentTheme(theme); _context.API.ReQuery(); return false; } From 1611ad37f37fde5ac054529cfa3a136e28fa3168 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:15:47 +0800 Subject: [PATCH 0688/1798] Fix ThemeData hashcode issue --- Flow.Launcher.Plugin/ThemeData.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs index d4a69ef09..6cbd0fe74 100644 --- a/Flow.Launcher.Plugin/ThemeData.cs +++ b/Flow.Launcher.Plugin/ThemeData.cs @@ -1,4 +1,6 @@ -namespace Flow.Launcher.Plugin; +using System; + +namespace Flow.Launcher.Plugin; /// /// Theme data model @@ -60,7 +62,7 @@ public class ThemeData /// public override int GetHashCode() { - return Name?.GetHashCode() ?? 0; + return HashCode.Combine(FileNameWithoutExtension, Name); } /// From 514fa0037a0f0ad6b78ad6ae17d943764cf696c7 Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:23:07 +0800 Subject: [PATCH 0689/1798] Improve documents Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Flow.Launcher.Plugin/ThemeData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs index 6cbd0fe74..90a45182c 100644 --- a/Flow.Launcher.Plugin/ThemeData.cs +++ b/Flow.Launcher.Plugin/ThemeData.cs @@ -23,7 +23,7 @@ public class ThemeData public bool? IsDark { get; private init; } /// - /// Theme file path + /// Indicates whether the theme supports blur effects /// public bool? HasBlur { get; private init; } From 28d92c789f181acb2060f7ff0b1c9f226bdb4905 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:23:36 +0800 Subject: [PATCH 0690/1798] Improve documents --- Flow.Launcher.Plugin/ThemeData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/ThemeData.cs b/Flow.Launcher.Plugin/ThemeData.cs index 90a45182c..1888be65e 100644 --- a/Flow.Launcher.Plugin/ThemeData.cs +++ b/Flow.Launcher.Plugin/ThemeData.cs @@ -18,7 +18,7 @@ public class ThemeData public string Name { get; private init; } /// - /// Theme file path + /// Indicates whether the theme supports dark mode /// public bool? IsDark { get; private init; } From 2e885ea5ccec4a42de61e1d1fe6ced1e319656ce Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 4 Apr 2025 20:45:24 +0800 Subject: [PATCH 0691/1798] Remove useless variable --- Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs index 84bfa218e..4b99efe3b 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -38,7 +38,6 @@ namespace Flow.Launcher.Plugin.Sys private Result CreateThemeResult(ThemeData theme, ThemeData selectedTheme, int score, IList highlightData) { - var themeName = theme.FileNameWithoutExtension; string title; if (theme == selectedTheme) { From a65e89b86fbe3e1134c1a098f9af85ed4ea8bf71 Mon Sep 17 00:00:00 2001 From: DB p Date: Sat, 5 Apr 2025 01:06:06 +0900 Subject: [PATCH 0692/1798] Adjust advanced control UI --- .../SettingsPanePluginsViewModel.cs | 22 +++++ .../Views/SettingsPaneGeneral.xaml | 21 ++++ .../Views/SettingsPanePlugins.xaml | 97 +++++++++++++------ .../Views/SettingsPanePlugins.xaml.cs | 9 ++ 4 files changed, 117 insertions(+), 32 deletions(-) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index 5cd14ba7e..69d31a98d 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -14,6 +14,28 @@ public class SettingsPanePluginsViewModel : BaseModel { private readonly Settings _settings; + public void UpdateDisplayModeFromSelection() + { + switch (CurrentDisplayMode) + { + case "OnOff": + IsOnOffSelected = true; + IsPrioritySelected = false; + IsSearchDelaySelected = false; + break; + case "Priority": + IsOnOffSelected = false; + IsPrioritySelected = true; + IsSearchDelaySelected = false; + break; + case "SearchDelay": + IsOnOffSelected = false; + IsPrioritySelected = false; + IsSearchDelaySelected = true; + break; + } + } + private bool _isOnOffSelected = true; public bool IsOnOffSelected { diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 3f8272dda..e36c647a2 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -196,6 +196,27 @@ + + + + + + + + + @@ -34,34 +34,35 @@ Text="{DynamicResource plugins}" TextAlignment="Left" /> - + + - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Flow.Launcher/SearchDelayTimeWindow.xaml.cs b/Flow.Launcher/SearchDelayTimeWindow.xaml.cs deleted file mode 100644 index 4a3c9f5a7..000000000 --- a/Flow.Launcher/SearchDelayTimeWindow.xaml.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Linq; -using System.Windows; -using Flow.Launcher.Plugin; -using Flow.Launcher.SettingPages.ViewModels; -using Flow.Launcher.ViewModel; -using static Flow.Launcher.SettingPages.ViewModels.SettingsPaneGeneralViewModel; - -namespace Flow.Launcher; - -public partial class SearchDelayTimeWindow : Window -{ - private readonly PluginViewModel _pluginViewModel; - - public SearchDelayTimeWindow(PluginViewModel pluginViewModel) - { - InitializeComponent(); - _pluginViewModel = pluginViewModel; - } - - private void SearchDelayTimeWindow_OnLoaded(object sender, RoutedEventArgs e) - { - tbSearchDelayTimeTips.Text = string.Format(App.API.GetTranslation("searchDelayTime_tips"), - App.API.GetTranslation("default")); - tbOldSearchDelayTime.Text = _pluginViewModel.SearchDelayTimeText; - var searchDelayTimes = DropdownDataGeneric.GetValues("SearchDelayTime"); - SearchDelayTimeData selected = null; - // Because default value is SearchDelayTime.VeryShort, we need to get selected value before adding default value - if (_pluginViewModel.PluginSearchDelayTime != null) - { - selected = searchDelayTimes.FirstOrDefault(x => x.Value == _pluginViewModel.PluginSearchDelayTime); - } - // Add default value to the beginning of the list - // When _pluginViewModel.PluginSearchDelayTime equals null, we will select this - searchDelayTimes.Insert(0, new SearchDelayTimeData { Display = App.API.GetTranslation("default"), LocalizationKey = "default" }); - selected ??= searchDelayTimes.FirstOrDefault(); - cbDelay.ItemsSource = searchDelayTimes; - cbDelay.SelectedItem = selected; - cbDelay.Focus(); - } - - private void BtnCancel_OnClick(object sender, RoutedEventArgs e) - { - Close(); - } - - private void btnDone_OnClick(object sender, RoutedEventArgs _) - { - // Update search delay time - var selected = cbDelay.SelectedItem as SearchDelayTimeData; - SearchDelayTime? changedValue = selected?.LocalizationKey != "default" ? selected.Value : null; - _pluginViewModel.PluginSearchDelayTime = changedValue; - - // Update search delay time text and close window - _pluginViewModel.OnSearchDelayTimeChanged(); - Close(); - } -} diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index cec8c318c..74e2d8340 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Forms; +using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; @@ -31,7 +32,25 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public class SearchWindowAlignData : DropdownDataGeneric { } public class SearchPrecisionData : DropdownDataGeneric { } public class LastQueryModeData : DropdownDataGeneric { } - public class SearchDelayTimeData : DropdownDataGeneric { } + public class SearchDelayTimeData + { + public string Display { get; set; } + public int Value { get; set; } + + public static List GetValues() + { + var settings = Ioc.Default.GetRequiredService(); + var data = new List(); + + foreach (var value in settings.SearchDelayTimeRange) + { + var display = $"{value}ms"; + data.Add(new SearchDelayTimeData { Display = display, Value = value }); + } + + return data; + } + } public bool StartFlowLauncherOnSystemStartup { @@ -144,19 +163,15 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public List LastQueryModes { get; } = DropdownDataGeneric.GetValues("LastQuery"); - public List SearchDelayTimes { get; } = - DropdownDataGeneric.GetValues("SearchDelayTime"); + public List SearchDelayTimes { get; } = SearchDelayTimeData.GetValues(); public SearchDelayTimeData SearchDelayTime { - get => SearchDelayTimes.FirstOrDefault(x => x.Value == Settings.SearchDelayTime) ?? - SearchDelayTimes.FirstOrDefault(x => x.Value == Plugin.SearchDelayTime.Normal) ?? - SearchDelayTimes.FirstOrDefault(); + get => SearchDelayTimes.FirstOrDefault(x => x.Value == Settings.SearchDelayTime); set { - if (value == null) - return; - + if (value == null) return; + if (Settings.SearchDelayTime != value.Value) { Settings.SearchDelayTime = value.Value; @@ -170,7 +185,6 @@ public partial class SettingsPaneGeneralViewModel : BaseModel DropdownDataGeneric.UpdateLabels(SearchWindowAligns); DropdownDataGeneric.UpdateLabels(SearchPrecisionScores); DropdownDataGeneric.UpdateLabels(LastQueryModes); - DropdownDataGeneric.UpdateLabels(SearchDelayTimes); } public string Language diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index e36c647a2..10e2b549a 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -196,18 +196,21 @@ - + - - + Sub="{DynamicResource searchDelayTimeToolTip}" + Type="InsideFit"> - + 250, - SearchDelayTime.Long => 200, - SearchDelayTime.Normal => 150, - SearchDelayTime.Short => 100, - SearchDelayTime.VeryShort => 50, - _ => 150 - }; + var searchDelayTime = plugin.Metadata.SearchDelayTime ?? Settings.SearchDelayTime; await Task.Delay(searchDelayTime, token); diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 2016d9c98..bf61b1902 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -95,7 +95,7 @@ namespace Flow.Launcher.ViewModel } } - public SearchDelayTime? PluginSearchDelayTime + public int? PluginSearchDelayTime { get => PluginPair.Metadata.SearchDelayTime; set @@ -192,12 +192,5 @@ namespace Flow.Launcher.ViewModel var changeKeywordsWindow = new ActionKeywords(this); changeKeywordsWindow.ShowDialog(); } - - [RelayCommand] - private void SetSearchDelayTime() - { - var searchDelayTimeWindow = new SearchDelayTimeWindow(this); - searchDelayTimeWindow.ShowDialog(); - } } } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json index 64681f803..c8b6310a7 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json @@ -32,5 +32,5 @@ "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.WebSearch.dll", "IcoPath": "Images\\web_search.png", - "SearchDelayTime": "VeryLong" + "SearchDelayTime": 450 } From dfb6b0a3a300386fe668148d0429de9db7ea9b3a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 7 Apr 2025 14:26:35 +0800 Subject: [PATCH 0716/1798] Fix string resource issue --- .../SettingPages/ViewModels/SettingsPanePluginsViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index af1653c93..46e398eb5 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -141,7 +141,7 @@ public partial class SettingsPanePluginsViewModel : BaseModel }, new TextBlock { - Text = (string)Application.Current.Resources["searchDelayTime_tips"], + Text = (string)Application.Current.Resources["searchDelayTimeTips"], TextWrapping = TextWrapping.Wrap } } From 24bbfcc4139596ac6d3929da44e353508f426974 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 7 Apr 2025 14:27:33 +0800 Subject: [PATCH 0717/1798] Support numerical box for priority --- Flow.Launcher/PriorityChangeWindow.xaml | 121 ------------------ Flow.Launcher/PriorityChangeWindow.xaml.cs | 67 ---------- .../Controls/InstalledPluginDisplay.xaml | 3 +- Flow.Launcher/ViewModel/PluginViewModel.cs | 20 +-- 4 files changed, 4 insertions(+), 207 deletions(-) delete mode 100644 Flow.Launcher/PriorityChangeWindow.xaml delete mode 100644 Flow.Launcher/PriorityChangeWindow.xaml.cs diff --git a/Flow.Launcher/PriorityChangeWindow.xaml b/Flow.Launcher/PriorityChangeWindow.xaml deleted file mode 100644 index 33ed54bb4..000000000 --- a/Flow.Launcher/PriorityChangeWindow.xaml +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Flow.Launcher/PriorityChangeWindow.xaml.cs b/Flow.Launcher/PriorityChangeWindow.xaml.cs deleted file mode 100644 index fbe2a941d..000000000 --- a/Flow.Launcher/PriorityChangeWindow.xaml.cs +++ /dev/null @@ -1,67 +0,0 @@ -using Flow.Launcher.Core.Plugin; -using Flow.Launcher.Core.Resource; -using Flow.Launcher.Plugin; -using Flow.Launcher.ViewModel; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using Flow.Launcher.Core; - -namespace Flow.Launcher -{ - /// - /// Interaction Logic of PriorityChangeWindow.xaml - /// - public partial class PriorityChangeWindow : Window - { - private readonly PluginPair plugin; - private readonly Internationalization translater = InternationalizationManager.Instance; - private readonly PluginViewModel pluginViewModel; - public PriorityChangeWindow(string pluginId, PluginViewModel pluginViewModel) - { - InitializeComponent(); - plugin = PluginManager.GetPluginForId(pluginId); - this.pluginViewModel = pluginViewModel; - if (plugin == null) - { - App.API.ShowMsgBox(translater.GetTranslation("cannotFindSpecifiedPlugin")); - Close(); - } - } - - private void BtnCancel_OnClick(object sender, RoutedEventArgs e) - { - Close(); - } - - private void btnDone_OnClick(object sender, RoutedEventArgs e) - { - if (int.TryParse(tbAction.Text.Trim(), out var newPriority)) - { - pluginViewModel.ChangePriority(newPriority); - Close(); - } - else - { - string msg = translater.GetTranslation("invalidPriority"); - App.API.ShowMsgBox(msg); - } - - } - - private void PriorityChangeWindow_Loaded(object sender, RoutedEventArgs e) - { - tbAction.Text = pluginViewModel.Priority.ToString(); - tbAction.Focus(); - } - private void window_MouseDown(object sender, MouseButtonEventArgs e) /* for close hotkey popup */ - { - TextBox textBox = Keyboard.FocusedElement as TextBox; - if (textBox != null) - { - TraversalRequest tRequest = new TraversalRequest(FocusNavigationDirection.Next); - textBox.MoveFocus(tRequest); - } - } - } -} diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 5ba011fed..778f00160 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -70,7 +70,8 @@ Maximum="999" Minimum="-999" SpinButtonPlacementMode="Inline" - ToolTip="{DynamicResource priorityToolTip}" /> + ToolTip="{DynamicResource priorityToolTip}" + Value="{Binding Priority, Mode=TwoWay}" /> PluginPair.Metadata.Priority; set { - if (PluginPair.Metadata.Priority != value) - { - ChangePriority(value); - } + PluginPair.Metadata.Priority = value; + PluginSettingsObject.Priority = value; } } @@ -151,20 +149,6 @@ namespace Flow.Launcher.ViewModel OnPropertyChanged(nameof(SearchDelayTimeText)); } - public void ChangePriority(int newPriority) - { - PluginPair.Metadata.Priority = newPriority; - PluginSettingsObject.Priority = newPriority; - OnPropertyChanged(nameof(Priority)); - } - - [RelayCommand] - private void EditPluginPriority() - { - var priorityChangeWindow = new PriorityChangeWindow(PluginPair. Metadata.ID, this); - priorityChangeWindow.ShowDialog(); - } - [RelayCommand] private void OpenPluginDirectory() { From 67268284e0e4ae612a5395973a58b6674b203c4f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 7 Apr 2025 14:40:27 +0800 Subject: [PATCH 0718/1798] Support numerical box for search delay --- .../Controls/InstalledPluginDisplay.xaml | 3 ++- Flow.Launcher/ViewModel/PluginViewModel.cs | 18 ++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 778f00160..f57c0e2d9 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -91,7 +91,8 @@ Maximum="1000" Minimum="0" SpinButtonPlacementMode="Inline" - ToolTip="{DynamicResource searchDelayToolTip}" /> + ToolTip="{DynamicResource searchDelayToolTip}" + Value="{Binding PluginSearchDelayTime, Mode=TwoWay}" /> diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 22a69592b..2dff72ac5 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -93,13 +93,23 @@ namespace Flow.Launcher.ViewModel } } - public int? PluginSearchDelayTime + public double PluginSearchDelayTime { - get => PluginPair.Metadata.SearchDelayTime; + get => PluginPair.Metadata.SearchDelayTime == null ? + double.NaN : + PluginPair.Metadata.SearchDelayTime.Value; set { - PluginPair.Metadata.SearchDelayTime = value; - PluginSettingsObject.SearchDelayTime = value; + if (double.IsNaN(value)) + { + PluginPair.Metadata.SearchDelayTime = null; + PluginSettingsObject.SearchDelayTime = null; + } + else + { + PluginPair.Metadata.SearchDelayTime = (int)value; + PluginSettingsObject.SearchDelayTime = (int)value; + } } } From 5c09598f213f3eb4af993364d55e95f48b4a8f8a Mon Sep 17 00:00:00 2001 From: DB p Date: Mon, 7 Apr 2025 15:47:40 +0900 Subject: [PATCH 0719/1798] Add Infobar strings for korean --- Flow.Launcher/Languages/en.xaml | 10 ++++++++++ .../SettingPages/Views/SettingsPaneGeneral.xaml | 10 +++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 24ab3cf94..3de278eca 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -116,6 +116,16 @@ Normal Short Very short + Information for Korean IME user + + You're using the Korean language! The Korean input method used in Windows 11 may cause some issues in Flow Launcher. + If you experience any problems, you may need to enable compatibility mode for the Korean IME. + Open Setting in Windows 11 and go to: + Time & Language > Language & Region > Korean > Language Options > Keyboard - Microsoft IME > Compatibility, + and enable "Use previous version of Microsoft IME". + You can open the relevant menu using the option below, or change the setting directly without manually opening the settings page. + + Very short Search Plugin diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 91f648586..431293a50 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -56,12 +56,12 @@ Message="This is a success message." Type="Error" /> + IsIconVisible="True" + Length="Long" + Message="{DynamicResource KoreanImeGuide}" + Type="Warning" /> Date: Mon, 7 Apr 2025 14:54:09 +0800 Subject: [PATCH 0720/1798] Force priority to 0 when inputing empty --- .../Resources/Controls/InstalledPluginDisplay.xaml | 1 + .../Controls/InstalledPluginDisplay.xaml.cs | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index f57c0e2d9..ece66034c 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -71,6 +71,7 @@ Minimum="-999" SpinButtonPlacementMode="Inline" ToolTip="{DynamicResource priorityToolTip}" + ValueChanged="NumberBox_OnValueChanged" Value="{Binding Priority, Mode=TwoWay}" /> diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs index dfa03a204..ab9496266 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs @@ -1,4 +1,6 @@ -namespace Flow.Launcher.Resources.Controls; +using ModernWpf.Controls; + +namespace Flow.Launcher.Resources.Controls; public partial class InstalledPluginDisplay { @@ -6,4 +8,12 @@ public partial class InstalledPluginDisplay { InitializeComponent(); } + + private void NumberBox_OnValueChanged(NumberBox sender, NumberBoxValueChangedEventArgs args) + { + if (double.IsNaN(args.NewValue)) + { + sender.Value = 0; + } + } } From e955e47e5fafcf54b6aa651dcc04db7ed9355523 Mon Sep 17 00:00:00 2001 From: DB p Date: Mon, 7 Apr 2025 22:47:39 +0900 Subject: [PATCH 0721/1798] - Change combobox to numberbox - Adjust Numberbox Style - Add small change value(10) - Adjust strings --- .../UserSettings/Settings.cs | 4 --- Flow.Launcher/Languages/en.xaml | 10 ++---- .../Controls/InstalledPluginDisplay.xaml | 7 ++-- .../Resources/CustomControlTemplate.xaml | 28 ++++++++++----- .../SettingsPaneGeneralViewModel.cs | 35 +++++-------------- .../SettingsPanePluginsViewModel.cs | 4 +-- .../Views/SettingsPaneGeneral.xaml | 17 +++++---- 7 files changed, 49 insertions(+), 56 deletions(-) diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index d89340e19..e304a1b50 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -321,10 +321,6 @@ namespace Flow.Launcher.Infrastructure.UserSettings public bool HideWhenDeactivated { get; set; } = true; public bool SearchQueryResultsWithDelay { get; set; } - - [JsonIgnore] - public IEnumerable SearchDelayTimeRange = new List { 50, 100, 150, 200, 250, 300, 350, 400, 450, 500 }; - public int SearchDelayTime { get; set; } = 150; [JsonConverter(typeof(JsonStringEnumConverter))] diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 5d9b16e0b..f01d0575a 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -108,14 +108,10 @@ Always open preview panel when Flow activates. Press {0} to toggle preview. Shadow effect is not allowed while current theme has blur effect enabled Search Delay - Delay for a while to search when typing. This reduces interface jumpiness and result load. + Adds a short delay while typing to reduce UI flicker and result load. Recommended if your typing speed is average. Default Search Delay Time - Plugin default delay time after which search results appear when typing is stopped. - Very long - Long - Normal - Short - Very short + Wait time before showing results after typing stops. Higher values wait longer. (ms) + Default Search Plugin diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index ece66034c..9a4e3b7b0 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -88,12 +88,15 @@ Text="{DynamicResource searchDelay}" ToolTip="{DynamicResource searchDelayToolTip}" /> + Value="{Binding PluginSearchDelayTime, Mode=TwoWay}"> + diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index b51e5fec0..157910b4a 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -1503,7 +1503,7 @@ - + @@ -2689,10 +2689,20 @@ MinWidth="{TemplateBinding MinWidth}" MinHeight="{TemplateBinding MinHeight}" ui:ValidationHelper.IsTemplateValidationAdornerSite="True" - Background="{TemplateBinding Background}" - BorderBrush="{TemplateBinding BorderBrush}" - BorderThickness="{TemplateBinding BorderThickness}" - CornerRadius="{TemplateBinding ui:ControlHelper.CornerRadius}" /> + Background="{DynamicResource CustomTextBoxBG}" + BorderBrush="{DynamicResource CustomTextBoxOutline}" + BorderThickness="{DynamicResource CustomTextBoxOutlineThickness}" + CornerRadius="4"> + + - + @@ -2788,8 +2798,10 @@ - - + + + + diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 74e2d8340..35dbab647 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -32,25 +32,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public class SearchWindowAlignData : DropdownDataGeneric { } public class SearchPrecisionData : DropdownDataGeneric { } public class LastQueryModeData : DropdownDataGeneric { } - public class SearchDelayTimeData - { - public string Display { get; set; } - public int Value { get; set; } - - public static List GetValues() - { - var settings = Ioc.Default.GetRequiredService(); - var data = new List(); - - foreach (var value in settings.SearchDelayTimeRange) - { - var display = $"{value}ms"; - data.Add(new SearchDelayTimeData { Display = display, Value = value }); - } - - return data; - } - } + public bool StartFlowLauncherOnSystemStartup { @@ -163,21 +145,20 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public List LastQueryModes { get; } = DropdownDataGeneric.GetValues("LastQuery"); - public List SearchDelayTimes { get; } = SearchDelayTimeData.GetValues(); - - public SearchDelayTimeData SearchDelayTime + public int SearchDelayTimeValue { - get => SearchDelayTimes.FirstOrDefault(x => x.Value == Settings.SearchDelayTime); + get => Settings.SearchDelayTime; set { - if (value == null) return; - - if (Settings.SearchDelayTime != value.Value) + if (Settings.SearchDelayTime != value) { - Settings.SearchDelayTime = value.Value; + Settings.SearchDelayTime = value; + OnPropertyChanged(); + OnPropertyChanged(nameof(SearchDelayTimeDisplay)); } } } + public string SearchDelayTimeDisplay => $"{SearchDelayTimeValue}ms"; private void UpdateEnumDropdownLocalizations() { diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index 46e398eb5..4958bb7b7 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -122,7 +122,7 @@ public partial class SettingsPanePluginsViewModel : BaseModel { new TextBlock { - Text = (string)Application.Current.Resources["changePriorityWindow"], + Text = (string)Application.Current.Resources["priority"], FontSize = 18, Margin = new Thickness(0, 0, 0, 10), TextWrapping = TextWrapping.Wrap @@ -134,7 +134,7 @@ public partial class SettingsPanePluginsViewModel : BaseModel }, new TextBlock { - Text = (string)Application.Current.Resources["searchDelayTimeTitle"], + Text = (string)Application.Current.Resources["searchDelay"], FontSize = 18, Margin = new Thickness(0, 24, 0, 10), TextWrapping = TextWrapping.Wrap diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 10e2b549a..657e97f30 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -211,12 +211,17 @@ Title="{DynamicResource searchDelayTime}" Sub="{DynamicResource searchDelayTimeToolTip}" Type="InsideFit"> - + + + From cbf50317d3cb87bd62dbb42ee39adcd6719bbeee Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 8 Apr 2025 00:02:59 +0900 Subject: [PATCH 0722/1798] Fix content dialog style --- .../Resources/CustomControlTemplate.xaml | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index 157910b4a..d78829471 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -3587,7 +3587,7 @@ - + - + + + + + + + + From 736837ebe8c3ce2babe80d5f1b5a95905aae3ca2 Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 8 Apr 2025 15:23:23 +0900 Subject: [PATCH 0723/1798] Add function for switch and button --- Flow.Launcher/Languages/en.xaml | 6 +- .../SettingsPaneGeneralViewModel.cs | 122 ++++++++++++++---- .../Views/SettingsPaneGeneral.xaml | 62 ++++----- 3 files changed, 133 insertions(+), 57 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 3de278eca..c4c87dbc4 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -125,7 +125,11 @@ and enable "Use previous version of Microsoft IME". You can open the relevant menu using the option below, or change the setting directly without manually opening the settings page. - Very short + Open Language and Region System Settings + Opens the Korean IME setting locationKorean > Language Options > Keyboard - Microsoft IME > Compatibility + Open + Use Legacy Korean IME + You can change the IME settings directly from here without opening a separate settings window Search Plugin diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index a1b38a53c..dcd17cf24 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -13,6 +13,8 @@ using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.SharedModels; using Microsoft.Win32; using OpenFileDialog = System.Windows.Forms.OpenFileDialog; +using System.Windows.Input; + namespace Flow.Launcher.SettingPages.ViewModels; @@ -21,7 +23,8 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public Settings Settings { get; } private readonly Updater _updater; private readonly IPortable _portable; - + public ICommand OpenImeSettingsCommand { get; } + public SettingsPaneGeneralViewModel(Settings settings, Updater updater, IPortable portable) { Settings = settings; @@ -29,6 +32,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel _portable = portable; UpdateEnumDropdownLocalizations(); IsLegacyKoreanIMEEnabled(); + OpenImeSettingsCommand = new RelayCommand(OpenImeSettings); } public class SearchWindowScreenData : DropdownDataGeneric { } @@ -190,8 +194,89 @@ public partial class SettingsPaneGeneralViewModel : BaseModel UpdateEnumDropdownLocalizations(); } } + + public bool LegacyKoreanIMEEnabled + { + get => IsLegacyKoreanIMEEnabled(); + set + { + SetLegacyKoreanIMEEnabled(value); + OnPropertyChanged(nameof(LegacyKoreanIMEEnabled)); + OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero)); + } + } + + public bool KoreanIMERegistryKeyExists => IsKoreanIMEExist(); + + public bool KoreanIMERegistryValueIsZero + { + get + { + object value = GetLegacyKoreanIMERegistryValue(); + if (value is int intValue) + { + return intValue == 0; + } + else if (value != null && int.TryParse(value.ToString(), out int parsedValue)) + { + return parsedValue == 0; + } + + return false; + } + } + + bool IsKoreanIMEExist() + { + return GetLegacyKoreanIMERegistryValue() != null; + } bool IsLegacyKoreanIMEEnabled() + { + object value = GetLegacyKoreanIMERegistryValue(); + + if (value is int intValue) + { + return intValue == 1; + } + else if (value != null && int.TryParse(value.ToString(), out int parsedValue)) + { + return parsedValue == 1; + } + + return false; + } + + bool SetLegacyKoreanIMEEnabled(bool enable) + { + const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}"; + const string valueName = "NoTsf3Override5"; + + try + { + using (RegistryKey key = Registry.CurrentUser.CreateSubKey(subKeyPath)) + { + if (key != null) + { + int value = enable ? 1 : 0; + key.SetValue(valueName, value, RegistryValueKind.DWord); + return true; + } + else + { + Debug.WriteLine($"[IME DEBUG] 레지스트리 키 생성 또는 열기 실패: {subKeyPath}"); + } + } + } + catch (Exception ex) + { + Debug.WriteLine($"[IME DEBUG] 레지스트리 설정 중 예외 발생: {ex.Message}"); + } + + return false; + } + + private object GetLegacyKoreanIMERegistryValue() { const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}"; const string valueName = "NoTsf3Override5"; @@ -202,25 +287,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel { if (key != null) { - object value = key.GetValue(valueName); - if (value != null) - { - Debug.WriteLine($"[IME DEBUG] '{valueName}' 값: {value} (타입: {value.GetType()})"); - - if (value is int intValue) - return intValue == 1; - - if (int.TryParse(value.ToString(), out int parsed)) - return parsed == 1; - } - else - { - Debug.WriteLine($"[IME DEBUG] '{valueName}' 값이 존재하지 않습니다."); - } - } - else - { - Debug.WriteLine($"[IME DEBUG] 레지스트리 키를 찾을 수 없습니다: {subKeyPath}"); + return key.GetValue(valueName); } } } @@ -229,10 +296,21 @@ public partial class SettingsPaneGeneralViewModel : BaseModel Debug.WriteLine($"[IME DEBUG] 예외 발생: {ex.Message}"); } - return false; // 기본적으로 새 IME 사용 중으로 간주 + return null; + } + + private void OpenImeSettings() + { + try + { + Process.Start(new ProcessStartInfo("ms-settings:regionlanguage") { UseShellExecute = true }); + } + catch (Exception e) + { + Debug.WriteLine($"Error opening IME settings: {e.Message}"); + } } - public bool ShouldUsePinyin { get => Settings.ShouldUsePinyin; diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 431293a50..1d4dfd8ae 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -8,12 +8,16 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:settingsViewModels="clr-namespace:Flow.Launcher.SettingPages.ViewModels" xmlns:ui="http://schemas.modernwpf.com/2019" + xmlns:converters="clr-namespace:Flow.Launcher.Converters" xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure" Title="General" d:DataContext="{d:DesignInstance settingsViewModels:SettingsPaneGeneralViewModel}" d:DesignHeight="450" d:DesignWidth="800" mc:Ignorable="d"> + + + - - - - - + + + + + + + + /// - /// It utilize MemoryPack, which means the object must be MemoryPackSerializable + /// It utilizes MemoryPack, which means the object must be MemoryPackSerializable /// public class BinaryStorage : ISavable { diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 85c48f8a4..a3020b607 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -380,7 +380,7 @@ namespace Flow.Launcher.Plugin /// Cache directory from plugin metadata /// /// - /// BinaryStorage utilize MemoryPack, which means the object must be MemoryPackSerializable + /// BinaryStorage utilizes MemoryPack, which means the object must be MemoryPackSerializable /// Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new(); From d7ca36e60a39892295fe2c42c9e2f81e56b59a66 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 19:44:30 +0800 Subject: [PATCH 0742/1798] Change variable name --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 107673f89..745b042e6 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -190,8 +190,8 @@ namespace Flow.Launcher.Plugin.Program var _uwpsCount = 0; await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () => { - var pluginCachePath = Context.CurrentPluginMetadata.PluginCacheDirectoryPath; - FilesFolders.ValidateDirectory(pluginCachePath); + var pluginCacheDirectory = Context.CurrentPluginMetadata.PluginCacheDirectoryPath; + FilesFolders.ValidateDirectory(pluginCacheDirectory); static void MoveFile(string sourcePath, string destinationPath) { @@ -237,19 +237,19 @@ namespace Flow.Launcher.Plugin.Program // Move old cache files to the new cache directory var oldWin32CacheFile = Path.Combine(DataLocation.CacheDirectory, $"{Win32CacheName}.cache"); - var newWin32CacheFile = Path.Combine(pluginCachePath, $"{Win32CacheName}.cache"); + var newWin32CacheFile = Path.Combine(pluginCacheDirectory, $"{Win32CacheName}.cache"); MoveFile(oldWin32CacheFile, newWin32CacheFile); var oldUWPCacheFile = Path.Combine(DataLocation.CacheDirectory, $"{UwpCacheName}.cache"); - var newUWPCacheFile = Path.Combine(pluginCachePath, $"{UwpCacheName}.cache"); + var newUWPCacheFile = Path.Combine(pluginCacheDirectory, $"{UwpCacheName}.cache"); MoveFile(oldUWPCacheFile, newUWPCacheFile); await _win32sLock.WaitAsync(); - _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCachePath, new List()); + _win32s = await context.API.LoadCacheBinaryStorageAsync(Win32CacheName, pluginCacheDirectory, new List()); _win32sCount = _win32s.Count; _win32sLock.Release(); await _uwpsLock.WaitAsync(); - _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCachePath, new List()); + _uwps = await context.API.LoadCacheBinaryStorageAsync(UwpCacheName, pluginCacheDirectory, new List()); _uwpsCount = _uwps.Count; _uwpsLock.Release(); }); From 482e37316a1fee76b924e3b151a4507a42ad2cb7 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 19:46:40 +0800 Subject: [PATCH 0743/1798] Remove useless releases --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 745b042e6..a50868b69 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -258,9 +258,6 @@ namespace Flow.Launcher.Plugin.Program var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0; - _win32sLock.Release(); - _uwpsLock.Release(); - if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now) { _ = Task.Run(async () => From d30f292e3129aeab196b21380a3076f860a976e3 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 20:19:04 +0800 Subject: [PATCH 0744/1798] Remove unused string --- Flow.Launcher/Languages/en.xaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index f01d0575a..7e5a554a9 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -149,7 +149,6 @@ Plugins: {0} - Fail to remove plugin settings files, please remove them manually Fail to remove plugin cache Plugins: {0} - Fail to remove plugin cache files, please remove them manually - Default Plugin Store From 970bb3ac1268f8e3e443f48aef77d80324b2da15 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 20:30:40 +0800 Subject: [PATCH 0745/1798] Add code comments --- Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs index ab9496266..a27a00782 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs @@ -9,6 +9,7 @@ public partial class InstalledPluginDisplay InitializeComponent(); } + // This is used for PriorityControl to force its value to be 0 when the user clears the value private void NumberBox_OnValueChanged(NumberBox sender, NumberBoxValueChangedEventArgs args) { if (double.IsNaN(args.NewValue)) From 61fa4602d529c345616aaea87dd65af14589f77c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:02:42 +0800 Subject: [PATCH 0746/1798] Disable search delay number box when search delay is disabled --- .../Resources/Controls/InstalledPluginDisplay.xaml | 9 +++++---- Flow.Launcher/ViewModel/PluginViewModel.cs | 5 +++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 9a4e3b7b0..63d1af6b1 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -90,13 +90,14 @@ - + Value="{Binding PluginSearchDelayTime, Mode=TwoWay}" /> diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 2dff72ac5..5f19459c9 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -3,9 +3,11 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; +using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure.Image; +using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.Resources.Controls; @@ -13,6 +15,8 @@ namespace Flow.Launcher.ViewModel { public partial class PluginViewModel : BaseModel { + private static readonly Settings Settings = Ioc.Default.GetRequiredService(); + private readonly PluginPair _pluginPair; public PluginPair PluginPair { @@ -148,6 +152,7 @@ namespace Flow.Launcher.ViewModel App.API.GetTranslation("default") : App.API.GetTranslation($"SearchDelayTime{PluginPair.Metadata.SearchDelayTime}"); public Infrastructure.UserSettings.Plugin PluginSettingsObject{ get; init; } + public bool SearchDelayEnabled => Settings.SearchQueryResultsWithDelay; public void OnActionKeywordsChanged() { From ade4fbf7f2a905ef41cdf98e82dcd484d1400367 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:02:56 +0800 Subject: [PATCH 0747/1798] Adjust number box width --- Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 63d1af6b1..4a89d811f 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -88,7 +88,7 @@ Text="{DynamicResource searchDelay}" ToolTip="{DynamicResource searchDelayToolTip}" /> Date: Tue, 8 Apr 2025 21:04:04 +0800 Subject: [PATCH 0748/1798] Change default search delay time to value --- Flow.Launcher/Languages/en.xaml | 1 - Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml | 2 +- Flow.Launcher/ViewModel/PluginViewModel.cs | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 7e5a554a9..609859d0d 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -111,7 +111,6 @@ Adds a short delay while typing to reduce UI flicker and result load. Recommended if your typing speed is average. Default Search Delay Time Wait time before showing results after typing stops. Higher values wait longer. (ms) - Default Search Plugin diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml index 4a89d811f..231036244 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -93,7 +93,7 @@ IsEnabled="{Binding SearchDelayEnabled}" Maximum="1000" Minimum="0" - PlaceholderText="{DynamicResource searchDelayPlaceHolder}" + PlaceholderText="{Binding DefaultSearchDelay}" SmallChange="10" SpinButtonPlacementMode="Compact" ToolTip="{DynamicResource searchDelayToolTip}" diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 5f19459c9..da0ed70fa 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -153,6 +153,7 @@ namespace Flow.Launcher.ViewModel App.API.GetTranslation($"SearchDelayTime{PluginPair.Metadata.SearchDelayTime}"); public Infrastructure.UserSettings.Plugin PluginSettingsObject{ get; init; } public bool SearchDelayEnabled => Settings.SearchQueryResultsWithDelay; + public string DefaultSearchDelay => Settings.SearchDelayTime.ToString(); public void OnActionKeywordsChanged() { From 2589fac0bcb1cd28b0e3074c7bacd3e6baaad27e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:23:02 +0800 Subject: [PATCH 0749/1798] Remove useless function --- Flow.Launcher.Infrastructure/Stopwatch.cs | 34 ----------------------- 1 file changed, 34 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Stopwatch.cs b/Flow.Launcher.Infrastructure/Stopwatch.cs index dd6edaff9..784d323fe 100644 --- a/Flow.Launcher.Infrastructure/Stopwatch.cs +++ b/Flow.Launcher.Infrastructure/Stopwatch.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Threading.Tasks; using Flow.Launcher.Infrastructure.Logger; @@ -7,8 +6,6 @@ namespace Flow.Launcher.Infrastructure { public static class Stopwatch { - private static readonly Dictionary Count = new Dictionary(); - private static readonly object Locker = new object(); /// /// This stopwatch will appear only in Debug mode /// @@ -62,36 +59,5 @@ namespace Flow.Launcher.Infrastructure Log.Info(info); return milliseconds; } - - - - public static void StartCount(string name, Action action) - { - var stopWatch = new System.Diagnostics.Stopwatch(); - stopWatch.Start(); - action(); - stopWatch.Stop(); - var milliseconds = stopWatch.ElapsedMilliseconds; - lock (Locker) - { - if (Count.ContainsKey(name)) - { - Count[name] += milliseconds; - } - else - { - Count[name] = 0; - } - } - } - - public static void EndCount() - { - foreach (var key in Count.Keys) - { - string info = $"{key} already cost {Count[key]}ms"; - Log.Debug(info); - } - } } } From d09899e15c32be3d1755b6222cdae4919735d2fd Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 8 Apr 2025 22:31:33 +0900 Subject: [PATCH 0750/1798] Adjust Placeholder color --- .../Resources/CustomControlTemplate.xaml | 25 +++++++++++-------- Flow.Launcher/Resources/Dark.xaml | 1 + Flow.Launcher/Resources/Light.xaml | 3 +++ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index d78829471..ffa5eea41 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -2777,7 +2777,7 @@ - + @@ -3587,7 +3587,7 @@ - + - + - + diff --git a/Flow.Launcher/Resources/Dark.xaml b/Flow.Launcher/Resources/Dark.xaml index e8629a981..498e96bff 100644 --- a/Flow.Launcher/Resources/Dark.xaml +++ b/Flow.Launcher/Resources/Dark.xaml @@ -106,6 +106,7 @@ #f5f5f5 #464646 #ffffff + #272727 diff --git a/Flow.Launcher/Resources/Light.xaml b/Flow.Launcher/Resources/Light.xaml index aa6da9fb2..0f1e98a6b 100644 --- a/Flow.Launcher/Resources/Light.xaml +++ b/Flow.Launcher/Resources/Light.xaml @@ -97,8 +97,11 @@ #f5f5f5 #878787 #1b1b1b + #f6f6f6 + + From e753bb79b1985de78f21d68dfd02f0b1160f919d Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:32:18 +0800 Subject: [PATCH 0751/1798] Add public methods --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 26 +++++++++++++++++++ Flow.Launcher/PublicAPIInstance.cs | 13 ++++++++++ 2 files changed, 39 insertions(+) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 273676bfb..6d9e5f755 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -473,5 +473,31 @@ namespace Flow.Launcher.Plugin /// /// public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false); + + /// + /// Log debug message of the time taken to execute a method + /// Message will only be logged in Debug mode + /// + /// The time taken to execute the method in milliseconds + public long StopWatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = ""); + + /// + /// Log debug message of the time taken to execute a method asynchronously + /// Message will only be logged in Debug mode + /// + /// The time taken to execute the method in milliseconds + public Task StopWatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); + + /// + /// Log info message of the time taken to execute a method + /// + /// The time taken to execute the method in milliseconds + public long StopWatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = ""); + + /// + /// Log info message of the time taken to execute a method asynchronously + /// + /// The time taken to execute the method in milliseconds + public Task StopWatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index b67ef6ab6..b7aaef143 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -31,6 +31,7 @@ using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.ViewModel; using JetBrains.Annotations; using Squirrel; +using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher { @@ -431,6 +432,18 @@ namespace Flow.Launcher public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false) => PluginManager.UninstallPluginAsync(pluginMetadata, removePluginSettings); + public long StopWatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = "") => + Stopwatch.Debug($"|{className}.{methodName}|{message}", action); + + public Task StopWatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => + Stopwatch.DebugAsync($"|{className}.{methodName}|{message}", action); + + public long StopWatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = "") => + Stopwatch.Normal($"|{className}.{methodName}|{message}", action); + + public Task StopWatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => + Stopwatch.NormalAsync($"|{className}.{methodName}|{message}", action); + #endregion #region Private Methods From f99859ad1eb4fc5f94077327d60f689b8507b16a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:38:17 +0800 Subject: [PATCH 0752/1798] Change api function names --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 8 ++++---- Flow.Launcher/PublicAPIInstance.cs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 6d9e5f755..55f09dc3b 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -479,25 +479,25 @@ namespace Flow.Launcher.Plugin /// Message will only be logged in Debug mode /// /// The time taken to execute the method in milliseconds - public long StopWatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = ""); + public long StopwatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = ""); /// /// Log debug message of the time taken to execute a method asynchronously /// Message will only be logged in Debug mode /// /// The time taken to execute the method in milliseconds - public Task StopWatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); + public Task StopwatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); /// /// Log info message of the time taken to execute a method /// /// The time taken to execute the method in milliseconds - public long StopWatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = ""); + public long StopwatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = ""); /// /// Log info message of the time taken to execute a method asynchronously /// /// The time taken to execute the method in milliseconds - public Task StopWatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); + public Task StopwatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = ""); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index b7aaef143..95ef6c9f3 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -432,16 +432,16 @@ namespace Flow.Launcher public Task UninstallPluginAsync(PluginMetadata pluginMetadata, bool removePluginSettings = false) => PluginManager.UninstallPluginAsync(pluginMetadata, removePluginSettings); - public long StopWatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = "") => + public long StopwatchLogDebug(string className, string message, Action action, [CallerMemberName] string methodName = "") => Stopwatch.Debug($"|{className}.{methodName}|{message}", action); - public Task StopWatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => + public Task StopwatchLogDebugAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => Stopwatch.DebugAsync($"|{className}.{methodName}|{message}", action); - public long StopWatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = "") => + public long StopwatchLogInfo(string className, string message, Action action, [CallerMemberName] string methodName = "") => Stopwatch.Normal($"|{className}.{methodName}|{message}", action); - public Task StopWatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => + public Task StopwatchLogInfoAsync(string className, string message, Func action, [CallerMemberName] string methodName = "") => Stopwatch.NormalAsync($"|{className}.{methodName}|{message}", action); #endregion From 19aa42314b7d335768abe33733e9394429acdc56 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:38:33 +0800 Subject: [PATCH 0753/1798] Use api functions in ImageLoader --- .../Image/ImageLoader.cs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 41a33104b..1483c5865 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -7,13 +7,20 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Media; using System.Windows.Media.Imaging; -using Flow.Launcher.Infrastructure.Logger; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.Storage; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Infrastructure.Image { public static class ImageLoader { + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + + private static readonly string ClassName = nameof(ImageLoader); + private static readonly ImageCache ImageCache = new(); private static SemaphoreSlim storageLock { get; } = new SemaphoreSlim(1, 1); private static BinaryStorage> _storage; @@ -47,15 +54,14 @@ namespace Flow.Launcher.Infrastructure.Image _ = Task.Run(async () => { - await Stopwatch.NormalAsync("|ImageLoader.Initialize|Preload images cost", async () => + await API.StopwatchLogInfoAsync(ClassName, "Preload images cost", async () => { foreach (var (path, isFullImage) in usage) { await LoadAsync(path, isFullImage); } }); - Log.Info( - $"|ImageLoader.Initialize|Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}"); + API.LogInfo(ClassName, $"Number of preload images is <{ImageCache.CacheSize()}>, Images Number: {ImageCache.CacheSize()}, Unique Items {ImageCache.UniqueImagesInCache()}"); }); } @@ -71,7 +77,7 @@ namespace Flow.Launcher.Infrastructure.Image } catch (System.Exception e) { - Log.Exception($"|ImageLoader.SaveAsync|Failed to save image cache to file", e); + API.LogException(ClassName, "Failed to save image cache to file", e); } finally { @@ -166,8 +172,8 @@ namespace Flow.Launcher.Infrastructure.Image } catch (System.Exception e2) { - Log.Exception($"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e); - Log.Exception($"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2); + API.LogException(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on first try", e); + API.LogException(ClassName, $"|ImageLoader.Load|Failed to get thumbnail for {path} on second try", e2); ImageSource image = ImageCache[Constant.MissingImgIcon, false]; ImageCache[path, false] = image; From 9bc27a4ecd16a52d2d05a7baee1d33e5555128fd Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 8 Apr 2025 23:41:15 +1000 Subject: [PATCH 0754/1798] New Crowdin updates (#3348) --- Flow.Launcher/Languages/ar.xaml | 47 +++++- Flow.Launcher/Languages/cs.xaml | 47 +++++- Flow.Launcher/Languages/da.xaml | 47 +++++- Flow.Launcher/Languages/de.xaml | 69 +++++++-- Flow.Launcher/Languages/es-419.xaml | 47 +++++- Flow.Launcher/Languages/es.xaml | 47 +++++- Flow.Launcher/Languages/fr.xaml | 47 +++++- Flow.Launcher/Languages/he.xaml | 57 +++++-- Flow.Launcher/Languages/it.xaml | 47 +++++- Flow.Launcher/Languages/ja.xaml | 47 +++++- Flow.Launcher/Languages/ko.xaml | 53 ++++++- Flow.Launcher/Languages/nb.xaml | 47 +++++- Flow.Launcher/Languages/nl.xaml | 47 +++++- Flow.Launcher/Languages/pl.xaml | 47 +++++- Flow.Launcher/Languages/pt-br.xaml | 47 +++++- Flow.Launcher/Languages/pt-pt.xaml | 53 ++++++- Flow.Launcher/Languages/ru.xaml | 47 +++++- Flow.Launcher/Languages/sk.xaml | 47 +++++- Flow.Launcher/Languages/sr.xaml | 47 +++++- Flow.Launcher/Languages/tr.xaml | 47 +++++- Flow.Launcher/Languages/uk-UA.xaml | 47 +++++- Flow.Launcher/Languages/vi.xaml | 47 +++++- Flow.Launcher/Languages/zh-cn.xaml | 49 +++++- Flow.Launcher/Languages/zh-tw.xaml | 47 +++++- .../Languages/sk.xaml | 2 +- .../Languages/ko.xaml | 2 +- .../Languages/de.xaml | 4 +- .../Languages/ar.xaml | 2 + .../Languages/cs.xaml | 2 + .../Languages/da.xaml | 2 + .../Languages/de.xaml | 2 + .../Languages/es-419.xaml | 2 + .../Languages/es.xaml | 2 + .../Languages/fr.xaml | 2 + .../Languages/he.xaml | 2 + .../Languages/it.xaml | 2 + .../Languages/ja.xaml | 2 + .../Languages/ko.xaml | 2 + .../Languages/nb.xaml | 2 + .../Languages/nl.xaml | 2 + .../Languages/pl.xaml | 2 + .../Languages/pt-br.xaml | 2 + .../Languages/pt-pt.xaml | 2 + .../Languages/ru.xaml | 2 + .../Languages/sk.xaml | 2 + .../Languages/sr.xaml | 2 + .../Languages/tr.xaml | 2 + .../Languages/uk-UA.xaml | 2 + .../Languages/vi.xaml | 2 + .../Languages/zh-cn.xaml | 2 + .../Languages/zh-tw.xaml | 2 + .../Languages/de.xaml | 4 +- .../Languages/he.xaml | 2 +- .../Languages/de.xaml | 2 +- .../Languages/ar.xaml | 14 +- .../Languages/cs.xaml | 14 +- .../Languages/da.xaml | 14 +- .../Languages/de.xaml | 20 ++- .../Languages/es-419.xaml | 14 +- .../Languages/es.xaml | 14 +- .../Languages/fr.xaml | 14 +- .../Languages/he.xaml | 14 +- .../Languages/it.xaml | 14 +- .../Languages/ja.xaml | 14 +- .../Languages/ko.xaml | 14 +- .../Languages/nb.xaml | 14 +- .../Languages/nl.xaml | 14 +- .../Languages/pl.xaml | 14 +- .../Languages/pt-br.xaml | 14 +- .../Languages/pt-pt.xaml | 18 ++- .../Languages/ru.xaml | 14 +- .../Languages/sk.xaml | 14 +- .../Languages/sr.xaml | 14 +- .../Languages/tr.xaml | 14 +- .../Languages/uk-UA.xaml | 14 +- .../Languages/vi.xaml | 14 +- .../Languages/zh-cn.xaml | 14 +- .../Languages/zh-tw.xaml | 14 +- .../Languages/ar.xaml | 2 +- .../Languages/cs.xaml | 2 +- .../Languages/da.xaml | 2 +- .../Languages/de.xaml | 8 +- .../Languages/es-419.xaml | 2 +- .../Languages/es.xaml | 2 +- .../Languages/fr.xaml | 2 +- .../Languages/he.xaml | 2 +- .../Languages/it.xaml | 2 +- .../Languages/ja.xaml | 2 +- .../Languages/ko.xaml | 2 +- .../Languages/nb.xaml | 2 +- .../Languages/nl.xaml | 2 +- .../Languages/pl.xaml | 2 +- .../Languages/pt-br.xaml | 2 +- .../Languages/pt-pt.xaml | 2 +- .../Languages/ru.xaml | 9 +- .../Languages/sk.xaml | 2 +- .../Languages/sr.xaml | 2 +- .../Languages/tr.xaml | 2 +- .../Languages/uk-UA.xaml | 2 +- .../Languages/vi.xaml | 2 +- .../Languages/zh-cn.xaml | 2 +- .../Languages/zh-tw.xaml | 2 +- .../Properties/Resources.de-DE.resx | 8 +- .../Properties/Resources.he-IL.resx | 2 +- .../Properties/Resources.ko-KR.resx | 2 +- .../Properties/Resources.pt-PT.resx | 140 +++++++++--------- .../Properties/Resources.sk-SK.resx | 2 +- 107 files changed, 1536 insertions(+), 263 deletions(-) diff --git a/Flow.Launcher/Languages/ar.xaml b/Flow.Launcher/Languages/ar.xaml index a57179da6..b5eafaae9 100644 --- a/Flow.Launcher/Languages/ar.xaml +++ b/Flow.Launcher/Languages/ar.xaml @@ -7,6 +7,11 @@ انقر فوق لا إذا كان مثبتاً بالفعل، وسوف يطلب منك تحديد المجلد الذي يحتوي على {1} القابل للتنفيذ الرجاء اختيار الملف التنفيذي لـ {0} + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + تعذر تعيين مسار الملف التنفيذي لـ {0}، يرجى المحاولة من إعدادات Flow (قم بالتمرير إلى الأسفل). فشل في تهيئة الإضافات الإضافات: {0} - فشل في التحميل وسيتم تعطيلها، يرجى الاتصال بمطور الإضافة للحصول على المساعدة @@ -37,7 +42,7 @@ وضع اللعب تعليق استخدام مفاتيح التشغيل السريع. إعادة تعيين الموقع - إعادة تعيين موضع نافذة البحث + Type here to search الإعدادات @@ -70,8 +75,6 @@ تفريغ الاستعلام الأخير Preserve Last Action Keyword Select Last Action Keyword - ارتفاع ثابت للنافذة - ارتفاع النافذة غير قابل للتعديل عن طريق السحب. الحد الأقصى للنتائج المعروضة يمكنك أيضًا تعديل هذا بسرعة باستخدام CTRL+Plus وCTRL+Minus. تجاهل مفاتيح التشغيل السريع في وضع ملء الشاشة @@ -102,6 +105,15 @@ دائمًا معاينة فتح لوحة المعاينة دائمًا عند تنشيط Flow. اضغط على {0} للتبديل بين المعاينة وعدمها. تأثير الظل غير مسموح به بينما يتم تمكين تأثير التمويه في السمة الحالية + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short البحث عن إضافة @@ -118,6 +130,8 @@ كلمة الفعل الحالية كلمة فعل جديدة تغيير كلمات الفعل + Plugin seach delay time + Change Plugin Seach Delay Time الأولوية الحالية أولوية جديدة الأولوية @@ -131,6 +145,9 @@ إلغاء التثبيت Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default متجر الإضافات @@ -193,8 +210,20 @@ مخصص الساعة التاريخ + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + بلا + Acrylic + Mica + Mica Alt هذه السمة تدعم الوضعين (فاتح/داكن). هذه السمة تدعم الخلفية الضبابية الشفافة. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. مفتاح الاختصار @@ -294,6 +323,9 @@ مجلد السجلات مسح السجلات هل أنت متأكد أنك تريد حذف جميع السجلات؟ + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information معالج الترحيب موقع بيانات المستخدم يتم حفظ إعدادات المستخدم والإضافات المثبتة في مجلد بيانات المستخدم. قد يختلف هذا الموقع اعتمادًا على ما إذا كان في وضع النقل أم لا. @@ -335,9 +367,16 @@ لا يمكن العثور على الإضافة المحددة كلمة المفتاح الجديدة لا يمكن أن تكون فارغة تم تعيين كلمة المفتاح الجديدة هذه إلى إضافة أخرى، يرجى اختيار كلمة أخرى + This new Action Keyword is the same as old, please choose a different one نجاح اكتمل بنجاح - أدخل كلمة المفتاح التي ترغب في استخدامها لبدء الإضافة. استخدم * إذا كنت لا ترغب في تحديد أي كلمة، وسيتم تشغيل الإضافة بدون كلمات مفتاحية. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time مفتاح اختصار الاستعلام المخصص diff --git a/Flow.Launcher/Languages/cs.xaml b/Flow.Launcher/Languages/cs.xaml index 92721b70a..806e9f203 100644 --- a/Flow.Launcher/Languages/cs.xaml +++ b/Flow.Launcher/Languages/cs.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Herní režim Potlačit užívání klávesových zkratek. Obnovit pozici - Obnovit pozici vyhledávacího okna + Type here to search Nastavení @@ -70,8 +75,6 @@ Smazat poslední dotaz Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. Počet zobrazených výsledků Toto nastavení můžete také rychle upravit pomocí CTRL + Plus a CTRL + Minus. Ignorovat klávesové zkratky v režimu celé obrazovky @@ -102,6 +105,15 @@ Vždy zobrazit náhled Při aktivaci služby Flow vždy otevřete panel náhledu. Stisknutím klávesy {0} přepnete náhled. Stínový efekt není povolen, pokud je aktivní efekt rozostření + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Vyhledat plugin @@ -118,6 +130,8 @@ Aktuální aktivační příkaz Nový aktivační příkaz Upravit aktivační příkaz + Plugin seach delay time + Change Plugin Seach Delay Time Aktuální priorita Nová priorita Priorita @@ -131,6 +145,9 @@ Odinstalovat Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Obchod s pluginy @@ -193,8 +210,20 @@ Vlastní Hodiny Datum + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Klávesová zkratka @@ -294,6 +323,9 @@ Složka s logy Vymazat logy Opravdu chcete odstranit všechny logy? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Průvodce User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ Nepodařilo se najít zadaný plugin Nový aktivační příkaz nemůže být prázdný Nový aktivační příkaz byl již přiřazen jinému pluginu, vyberte jiný aktivační příkaz + This new Action Keyword is the same as old, please choose a different one Úspěšné Úspěšně dokončeno - Zadejte aktivační příkaz, který je nutný ke spuštění pluginu. Pokud nechcete zadávat aktivační příkaz, použijte * a plugin bude spuštěn bez aktivačního příkazu. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Vlastní klávesová zkratka pro vyhledávání diff --git a/Flow.Launcher/Languages/da.xaml b/Flow.Launcher/Languages/da.xaml index 629173f74..6055a79e1 100644 --- a/Flow.Launcher/Languages/da.xaml +++ b/Flow.Launcher/Languages/da.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Game Mode Suspend the use of Hotkeys. Position Reset - Reset search window position + Type here to search Indstillinger @@ -70,8 +75,6 @@ Empty last Query Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. Maksimum antal resultater vist You can also quickly adjust this by using CTRL+Plus and CTRL+Minus. Ignorer genvejstaster i fuldskærmsmode @@ -102,6 +105,15 @@ Always Preview Always open preview panel when Flow activates. Press {0} to toggle preview. Shadow effect is not allowed while current theme has blur effect enabled + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Search Plugin @@ -118,6 +130,8 @@ Current action keyword New action keyword Change Action Keywords + Plugin seach delay time + Change Plugin Seach Delay Time Current Priority New Priority Priority @@ -131,6 +145,9 @@ Uninstall Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Plugin Store @@ -193,8 +210,20 @@ Custom Clock Date + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Genvejstast @@ -294,6 +323,9 @@ Log Folder Clear Logs Are you sure you want to delete all logs? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ Kan ikke finde det valgte plugin Nyt nøgleord må ikke være tomt Nyt nøgleord er tilknyttet et andet plugin, tilknyt venligst et andet nyt nøgeleord + This new Action Keyword is the same as old, please choose a different one Fortsæt Completed successfully - Brug * hvis du ikke vil angive et nøgleord + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Tilpasset søgegenvejstast diff --git a/Flow.Launcher/Languages/de.xaml b/Flow.Launcher/Languages/de.xaml index 8a7e3498a..4fb441d8c 100644 --- a/Flow.Launcher/Languages/de.xaml +++ b/Flow.Launcher/Languages/de.xaml @@ -7,13 +7,18 @@ Klicken Sie auf „Nein“, wenn es bereits installiert ist, und Sie werden aufgefordert, den Ordner auszuwählen, der die ausführbare Datei {1} enthält Bitte wählen Sie die ausführbare Datei {0} aus + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Der Pfad zur ausführbaren Datei {0} kann nicht festgelegt werden. Bitte versuchen Sie es in den Einstellungen von Flow (scrollen Sie nach unten). Plug-ins können nicht initialisiert werden - Plug-ins: {0} - nicht geladen werden und wird deaktiviert, bitte kontaktiere Sie den Ersteller des Plug-ins für Hilfe + Plug-ins: {0} - nicht geladen werden und wird deaktiviert, bitte kontaktieren Sie den Ersteller des Plug-ins für Hilfe Hotkey "{0}" konnte nicht registriert werden. Der Hotkey ist möglicherweise von einem anderen Programm in Verwendung. Wechseln Sie zu einem anderen Hotkey oder beenden Sie das andere Programm. - Failed to unregister hotkey "{0}". Please try again or see log for details + Registrierung des Hotkeys "{0}" konnte nicht aufgehoben werden. Bitte versuchen Sie es erneut oder lesen Sie das Log für Details Flow Launcher Konnte nicht gestartet werden {0} Flow Launcher Plug-in-Dateiformat ungültig @@ -37,7 +42,7 @@ Spielmodus Aussetzen der Verwendung von Hotkeys. Position zurücksetzen - Position des Suchfensters zurücksetze + Type here to search Einstellungen @@ -45,9 +50,9 @@ Portabler Modus Speichern Sie alle Einstellungen und Benutzerdaten in einem Ordner (nützlich bei Verwendung von Wechsellaufwerken oder Cloud-Diensten). Flow Launcher bei Systemstart starten - Use logon task instead of startup entry for faster startup experience - After uninstallation, you need to manually remove this task (Flow.Launcher Startup) via Task Scheduler - Fehler bei Einstellungsstart bei Start + Log-on-Aufgabe anstelle des Starteintrags für schnelleres Startup-Erfahrung verwenden + Nach der Deinstallation müssen Sie diese Aufgabe (Flow.Launcher Startup) via Task-Scheduler manuell entfernen + Fehler bei Einstellungsstart beim Start Flow Launcher ausblenden, wenn Fokus verloren geht Versionsbenachrichtigungen nicht zeigen Position des Suchfensters @@ -70,8 +75,6 @@ Letzte Abfrage leeren Letztes Aktions-Schlüsselwort beibehalten Letztes Aktions-Schlüsselwort auswählen - Feste Fensterhöhe - Die Fensterhöhe ist durch Ziehen nicht anpassbar. Maximal gezeigte Ergebnisse Sie können dies auch unter Verwendung von STRG+Plus und STRG+Minus schnell anpassen. Hotkeys im Vollbildmodus ignorieren @@ -102,6 +105,15 @@ Immer Vorschau Vorschau-Panel immer öffnen, wenn Flow aktiviert ist. Drücken Sie {0}, um Vorschau umzuschalten. Schatteneffekt ist nicht erlaubt, während das aktuelle Theme den Unschärfe-Effekt aktiviert hat + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Plug-in suchen @@ -118,6 +130,8 @@ Aktuelles Action-Schlüsselwort Neues Aktions-Schlüsselwort Aktions-Schlüsselwörter ändern + Plugin seach delay time + Change Plugin Seach Delay Time Aktuelle Priorität Neue Priorität Priorität @@ -129,8 +143,11 @@ Version Website Deinstallieren - Fail to remove plugin settings - Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Plug-in-Einstellungen können nicht entfernt werden + Plug-ins: {0} - Plug-in-Einstellungsdateien können nicht entfernt werden, bitte entfernen Sie diese manuell + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Plug-in-Store @@ -193,8 +210,20 @@ Benutzerdefiniert Uhr Datum + Backdrop-Typ + Backdrop supported starting from Windows 11 build 22000 and above + Keine + Acrylic + Mica + Mica Alt Dieses Theme unterstützt zwei Modi (hell/dunkel). Dieses Theme unterstützt Unschärfe und transparenten Hintergrund. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Hotkey @@ -294,11 +323,14 @@ Ordner »Logs« Logs löschen Sind Sie sicher, dass Sie alle Logs löschen wollen? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Assistent Speicherort für Benutzerdaten Benutzereinstellungen und installierte Plug-ins werden im Ordner für Benutzerdaten gespeichert. Dieser Speicherort kann variieren, je nachdem, ob sich das Programm im portablen Modus befindet oder nicht. Ordner öffnen - Log Level + Log-Ebene Debug Info @@ -335,9 +367,16 @@ Das angegebene Plug-in kann nicht gefunden werden Neues Aktions-Schlüsselwort darf nicht leer sein Dieses neue Aktions-Schlüsselwort ist bereits einem anderen Plug-in zugewiesen, bitte wählen Sie ein anderes + Dieses neue Aktions-Schlüsselwort ist dasselbe wie das alte, bitte wählen Sie ein anderes Erfolg Erfolgreich abgeschlossen - Geben Sie das Aktions-Schlüsselwort ein, das Sie verwenden möchten, um das Plug-in zu starten. Verwenden Sie *, wenn Sie keines angeben möchten, und das Plug-in wird ohne irgendwelche Aktions-Schlüsselwörter ausgelöst. + Geben Sie die Aktions-Schlüsselwörter ein, die Sie zum Starten des Plug-ins verwenden möchten, und trennen Sie sie durch Leerzeichen voneinander ab. Verwenden Sie *, wenn Sie keine spezifizieren möchten, und das Plug-in wird ohne jegliche Aktions-Schlüsselwörter ausgelöst. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Benutzerdefinierter Abfrage-Hotkey @@ -388,9 +427,9 @@ Wenn Sie bei der Eingabe eines Shortcuts ein '@'-Präfix hinzufügen, stimmt die Bericht erfolgreich gesendet Bericht konnte nicht gesendet werden Flow Launcher hat einen Fehler - Please open new issue in - 1. Upload log file: {0} - 2. Copy below exception message + Bitte öffnen Sie einen neuen Fall in + 1. Logdatei hochladen: {0} + 2. Kopieren Sie die Ausnahmemeldung unterhalb Bitte warten Sie ... diff --git a/Flow.Launcher/Languages/es-419.xaml b/Flow.Launcher/Languages/es-419.xaml index 1ab69727b..23d58eca3 100644 --- a/Flow.Launcher/Languages/es-419.xaml +++ b/Flow.Launcher/Languages/es-419.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Modo de juego Suspender el uso de las teclas de acceso directo. Position Reset - Reset search window position + Type here to search Ajustes @@ -70,8 +75,6 @@ Borrar última consulta Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. Máximo de resultados mostrados You can also quickly adjust this by using CTRL+Plus and CTRL+Minus. Ignorar atajos de teclado en modo pantalla completa @@ -102,6 +105,15 @@ Always Preview Always open preview panel when Flow activates. Press {0} to toggle preview. El efecto de sombra no está permitido mientras el tema actual tenga el efecto de desenfoque habilitado + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Search Plugin @@ -118,6 +130,8 @@ Palabra clave actual Nueva palabra clave Cambiar palabras clave + Plugin seach delay time + Change Plugin Seach Delay Time Prioridad Actual Nueva Prioridad Prioridad @@ -131,6 +145,9 @@ Uninstall Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Tienda de Plugins @@ -193,8 +210,20 @@ Custom Clock Date + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Tecla Rápida @@ -294,6 +323,9 @@ Carpeta de registros Clear Logs Are you sure you want to delete all logs? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Asistente User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ No se puede encontrar el plugin especificado La nueva palabra clave no puede estar vacía Esta palabra clave ya está asignada a otro plugin, por favor elija una diferente + This new Action Keyword is the same as old, please choose a different one Éxito Completado con éxito - Introduzca la palabra clave que desea utilizar para iniciar el plugin. Utilice * si no desea especificar ninguno, y el plugin se activará sin ninguna palabra clave. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Tecla de Acceso Personalizada diff --git a/Flow.Launcher/Languages/es.xaml b/Flow.Launcher/Languages/es.xaml index 4cba4c8a7..8b3c42fa6 100644 --- a/Flow.Launcher/Languages/es.xaml +++ b/Flow.Launcher/Languages/es.xaml @@ -7,6 +7,11 @@ Haga clic en no si ya está instalado, y seleccione la carpeta que contiene el ejecutable {1} Por favor, seleccione el ejecutable {0} + + El ejecutable {0} seleccionado no es válido. + {2}{2} + Pulsar Sí, si desea seleccionar de nuevo el ejecutable {0}. Pulsar No, si desea descargar {1} + No se puede establecer la ruta del ejecutable {0}, por favor inténtelo desde la configuración de Flow (desplácese hacia abajo). Fallo al iniciar los complementos Complemento: {0} - no se pudo cargar y se desactivará, póngase en contacto con el creador del complemento para obtener ayuda @@ -37,7 +42,7 @@ Modo Juego Suspende el uso de atajos de teclado. Restablecer posición - Restablece la posición de la ventana de búsqueda + Escribir aquí para buscar Configuración @@ -70,8 +75,6 @@ Limpiar la última consulta Conservar última palabra clave de acción Seleccionar última palabra clave de acción - Altura de la ventana fija - La altura de la ventana no se puede ajustar arrastrando el ratón. Número máximo de resultados mostrados También puede ajustarse rápidamente usando Ctrl+Más(+) y Ctrl+Menos(-). Ignorar atajos de teclado en modo pantalla completa @@ -102,6 +105,15 @@ Mostrar siempre vista previa Muestra siempre el panel de vista previa al iniciar Flow. Pulsar {0} para mostrar/ocultar la vista previa. El efecto de sombra no está permitido si el tema actual tiene activado el efecto de desenfoque + Retardo de búsqueda + Retrasa un poco la búsqueda al escribir. Esto reduce los saltos en la interfaz y la carga de resultados. + Tiempo de retardo de búsqueda predeterminado + Tiempo de retardo predeterminado del complemento tras el que aparecerán los resultados de la búsqueda cuando se deje de escribir. + Muy largo + Largo + Normal + Corto + Muy corto Buscar complemento @@ -118,6 +130,8 @@ Palabra clave de acción actual Nueva palabra clave de acción Cambia la palabra clave de acción + Tiempo de retardo de la búsqueda del complemento + Cambiar tiempo de retardo de la búsqueda del complemento Prioridad actual Nueva prioridad Prioridad @@ -131,6 +145,9 @@ Desinstalar Fallo al eliminar la configuración del complemento Complementos: {0} - Fallo al eliminar los archivos de configuración del complemento, por favor elimínelos manualmente + Fallo al eliminar la caché del complemento + Complementos: {0} - Fallo al eliminar los archivos de caché del complemento, por favor elimínelos manualmente + Predeterminado Tienda complementos @@ -193,8 +210,20 @@ Personalizada Reloj Fecha + Tipo de telón de fondo + Telón de fondo compatible a partir de Windows 11 build 22000 y superiores + Ninguno + Acrílico + Mica + Mica Alt Este tema soporta dos modos (claro/oscuro). Este tema soporta fondo transparente desenfocado. + Mostrar marcador de posición + Mostrar marcador de posición cuando la consulta esté vacía + Texto del marcador de posición + Cambiar el texto del marcador de posición. La entrada vacía utilizará: {0} + Tamaño fijo de la ventana + El tamaño de la ventana no se puede ajustar mediante arrastre. Atajo de teclado @@ -294,6 +323,9 @@ Carpeta de registros Eliminar registros ¿Está seguro de que desea eliminar todos los registros? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Asistente Ubicación de datos del usuario La configuración del usuario y los complementos instalados se guardan en la carpeta de datos del usuario. Esta ubicación puede variar dependiendo de si está en modo portable o no. @@ -335,9 +367,16 @@ No se puede encontrar el complemento especificado La nueva palabra clave de acción no puede estar vacía Esta nueva palabra clave de acción ya está asignada a otro complemento, por favor elija una diferente + Esta nueva palabra clave de acción es la misma que la anterior, por favor elija una diferente Correcto Finalizado correctamente - Introduzca la palabra clave que desea utilizar para iniciar el complemento. Utilice * si no desea especificar ninguna, y el complemento se activará sin ninguna palabra clave. + Introduzca las palabras clave de acción que desea utilizar para iniciar el complemento y utilice espacios en blanco para separarlas. Utilice * si no desea especificar ninguna, para que el complemento se inicie sin ninguna palabra clave de acción. + + + Ajuste del tiempo de retardo de búsqueda + Seleccionar el tiempo de retardo de búsqueda que se desea utilizar para el complemento. Seleccionar "{0}" si no se desea especificar nada, y el complemento utilizará el tiempo de retardo de búsqueda predeterminado. + Tiempo de retardo de búsqueda actual + Nuevo tiempo de retardo de búsqueda Atajo de teclado de consulta personalizada diff --git a/Flow.Launcher/Languages/fr.xaml b/Flow.Launcher/Languages/fr.xaml index d0d1d010d..e46e0dc9d 100644 --- a/Flow.Launcher/Languages/fr.xaml +++ b/Flow.Launcher/Languages/fr.xaml @@ -7,6 +7,11 @@ Cliquez sur non s'il est déjà installé, et vous serez invité à sélectionner le dossier qui contient l'exécutable {1} Veuillez sélectionner l'exécutable {0} + + L'exécutable {0} que vous avez sélectionné est invalide. + {2}{2} + Cliquez sur oui si vous souhaitez sélectionner l'exécutable {0} à nouveau. Cliquez sur non si vous souhaitez télécharger {1}. + Impossible de définir {0} comme chemin d'accès vers l'exécutable. Veuillez essayer à partir des paramètres de Flow (défiler vers le bas). Échec de l'initialisation des plugins Plugins : {0} - n'ont pas pu être chargés et doivent être désactivés, veuillez contacter le créateur du plugin pour obtenir de l'aide @@ -37,7 +42,7 @@ Mode jeu Suspend l'utilisation des raccourcis claviers. Réinitialiser la position - Rétablir la position de la fenêtre de recherche + Tapez ici pour rechercher Paramètres @@ -70,8 +75,6 @@ Ne pas afficher la dernière recherche Conserver le mot clé de la dernière action Sélectionnez le mot clé de la dernière action - Hauteur de fenêtre fixe - La hauteur de la fenêtre n'est pas réglable par glissement. Résultats maximums à afficher Vous pouvez également ajuster ce paramètre en utilisant CTRL+Plus ou CTRL+Moins. Ignore les raccourcis lorsqu'une application est en plein écran @@ -102,6 +105,15 @@ Toujours prévisualiser Toujours ouvrir le panneau d'aperçu lorsque Flow s'active. Appuyez sur {0} pour activer/désactiver l'aperçu. L'effet d'ombre n'est pas autorisé lorsque le thème actuel à un effet de flou activé + Délai de recherche + Attendre un certain temps pour effectuer une recherche lors de la saisie. Cela permet de réduire les sauts d'interface et la charge des résultats. + Délai de recherche par défaut + Délai par défaut du plugin après lequel les résultats de la recherche s'affichent lorsque la saisie est interrompue. + Très long + Long + Normal + Court + Très court Rechercher des plugins @@ -118,6 +130,8 @@ Mot-clé d'action actuel Nouveau mot-clé d'action Changer les mots-clés d'action + Délai de recherche du plugin + Modifier le délai de recherche du plugin Priorité actuelle Nouvelle priorité Priorité @@ -131,6 +145,9 @@ Désinstaller Échec de la suppression des paramètres du plugin Plugins : {0} - Échec de la suppression des fichiers de configuration des plugins, veuillez les supprimer manuellement + Échec de la suppression du cache du plugin + Plugins : {0} - Échec de la suppression des fichiers cache des plugins, veuillez les supprimer manuellement + Défaut Magasin des Plugins @@ -193,8 +210,20 @@ Personnalisé Heure Date + Type d'arrière-plan + Arrière-plan pris en charge à partir de Windows 11 version 22000 et plus + Aucun + Acrylique + Mica + Mica Alt Ce thème prend en charge deux modes (clair/sombre). Ce thème prend en charge l'arrière-plan flou et transparent. + Afficher l'espace réservé + Afficher un espace réservé lorsque la requête est vide + Texte de l'espace réservé + Modifier le texte de l'espace réservé. Les entrées vides utiliseront : {0} + Taille de la fenêtre fixe + La taille de la fenêtre n'est pas réglable par glissement. Raccourcis @@ -293,6 +322,9 @@ Répertoire des journaux Effacer le journal Êtes-vous sûr de vouloir supprimer tous les journaux ? + Vider les caches + Êtes-vous sûr de vouloir supprimer tous les caches ? + Échec de l'effacement d'une partie des dossiers et des fichiers. Veuillez consulter le fichier journal pour plus d'informations Assistant Emplacement des données utilisateur Les paramètres utilisateur et les plugins installés sont enregistrés dans le dossier des données utilisateur. Cet emplacement peut varier selon que vous soyez en mode portable ou non. @@ -334,9 +366,16 @@ Impossible de trouver le module spécifi Le nouveau mot-clé d'action doit être spécifi Le nouveau mot-clé d'action a été assigné à un autre module, veuillez en choisir un autre + Ce nouveau mot-clé d'action est identique à l'ancien, veuillez en choisir un autre Ajout Terminé avec succès - Saisissez * si vous ne souhaitez pas utiliser de mot-clé spécifique + Saisissez les mots-clés d'action que vous souhaitez utiliser pour lancer le plugin et séparez-les par des espaces. Utilisez * si vous ne voulez en spécifier aucun, et le plugin sera déclenché sans aucun mot-clé d'action. + + + Réglage du délai de recherche + Sélectionnez le délai de recherche que vous souhaitez utiliser pour le plugin. Sélectionnez "{0}" si vous ne voulez pas en spécifier, et le plugin utilisera le délai de recherche par défaut. + Délai de recherche actuel + Nouveau délai de recherche Requêtes personnalisées diff --git a/Flow.Launcher/Languages/he.xaml b/Flow.Launcher/Languages/he.xaml index c912052f1..38e943cda 100644 --- a/Flow.Launcher/Languages/he.xaml +++ b/Flow.Launcher/Languages/he.xaml @@ -7,6 +7,11 @@ אם זה כבר מותקן, לחץ על 'לא' ותתבקש לבחור את התיקיה המכילה את קובץ ההפעלה {1} אנא בחר את קובץ ההפעלה {0} + + קובץ ההפעלה {0} שבחרת אינו חוקי. + {2}{2} + לחץ על כן אם ברצונך, בחר את {0} ההפעלה הקודמת. לחץ על לא אם ברצונך להוריד את {1} + לא ניתן להגדיר נתיב הפעלה {0}, אנא נסה שוב בהגדרות Flow (גלול עד למטה). נכשל בהפעלת תוספים תוספים: {0} - נכשלו בטעינה ויושבתו, אנא צור קשר עם יוצרי התוספים לקבלת עזרה @@ -37,7 +42,7 @@ מצב משחק השהה את השימוש במקשי קיצור. איפוס מיקום - אפס את מיקום חלון החיפוש + הקלד כאן כדי לחפש הגדרות @@ -70,8 +75,6 @@ נקה שאילתא אחרונה שמור מילת מפתח לפעולה האחרונה בחר מילת מפתח לפעולה האחרונה - גובה חלון קבוע - גובה החלון אינו ניתן להתאמה באמצעות גרירה. כמות תוצאות מרבית ניתן גם להתאים במהירות באמצעות CTRL+פלוס ו-CTRL+מינוס. התעלם מקיצורי מקשים במצב מסך מלא @@ -97,11 +100,20 @@ ללא נמוך Regular - Search with Pinyin + חפש באמצעות Pinyin Allows using Pinyin to search. Pinyin is the standard system of romanized spelling for translating Chinese. הצג תמיד תצוגה מקדימה פתח תמיד את לוח התצוגה המקדימה כאשר Flow מופעל. הקש על {0} כדי להחליף את התצוגה המקדימה. לא ניתן להחיל אפקט צל כאשר העיצוב הנוכחי מוגדר לאפקט טשטוש + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short חפש תוסף @@ -118,6 +130,8 @@ מילת מפתח נוכחית לפעולה מילת מפתח חדשה לפעולה שנה מילות מפתח לפעולה + Plugin seach delay time + Change Plugin Seach Delay Time עדיפות נוכחית עדיפות חדשה עדיפות @@ -131,6 +145,9 @@ הסר התקנה נכשל בהסרת הגדרות התוסף תוספים: {0} - נכשל בהסרת קבצי הגדרות התוסף, יש להסירם ידנית + נכשל בהסרת מטמון התוסף + תוספים: {0} - נכשל בהסרת קובצי מטמון התוסף, אנא הסר אותם ידנית + Default חנות תוספים @@ -156,7 +173,7 @@ סייר חפש קבצים, תיקיות ובתוכן הקבצים חיפוש באינטרנט - Search the web with different search engine support + חפש באינטרנט עם תמיכה במנועי חיפוש שונים תוכנה הפעל תוכנות כמנהל או כמשתמש אחר ProcessKiller @@ -193,8 +210,20 @@ מותאם אישית שעון תאריך + סוג רקע + התמיכה ב-Backdrop קיימת החל מ-Windows 11 build 22000 ומעלה + ללא + אקריליק + מיקה + Mica Alt ערכת נושא זאת תומך בשני מצבים (בהיר/כהה). ערכת נושא זו תומכת בטשטוש רקע שקוף. + הצג מציין מיקום + הצג מציין מיקום כאשר השאילתה ריקה + טקסט מציין מיקום + שנה את טקסט מציין המיקום. אם הקלט ריק, ייעשה שימוש ב: {0} + גודל חלון קבוע + לא ניתן להתאים את גודל החלון באמצעות גרירה. מקש קיצור @@ -289,18 +318,21 @@ הערות שחרור טיפים לשימוש - DevTools + כלי פיתוח תיקיית ההגדרות תיקיית יומני רישום נקה יומני רישום האם אתה בטוח שברצונך למחוק את כל היומנים? + נקה נתוני מטמון + האם אתה בטוח שברצונך למחוק את כל הנתונים שבמטמון? + נכשל ניקוי חלק מהתיקיות והקבצים. עיין בלוג לקבלת מידע נוסף אשף מיקום נתוני משתמש הגדרות המשתמש והתוספים המותקנים נשמרים בתיקיית נתוני המשתמש. מיקום זה עשוי להשתנות אם התוכנה במצב נייד. פתח תיקיה Log Level - Debug - Info + ניפוי שגיאות + מידע בחר מנהל קבצים @@ -335,9 +367,16 @@ לא ניתן למצוא את התוסף שצוין מילת הפעולה החדשה לא יכולה להיות ריקה מילת הפעולה החדשה כבר מוקצה לתוסף אחר, אנא בחר אחת שונה + מילת הפעולה החדשה זהה לישנה, נא לבחור מילת פעולה שונה הצליח הושלם בהצלחה - הזן את מילת הפעולה שברצונך להשתמש בה להפעלת התוסף. השתמש ב-* אם אינך רוצה לציין מילה כלשהי, והתוסף יופעל ללא צורך במילת פעולה. + הזן את מילות הפעולה שבהן תרצה להשתמש כדי להפעיל את התוסף, והשתמש ברווחים כדי להפריד ביניהן. השתמש ב-* אם אינך רוצה להגדיר כלל, והתוסף יופעל ללא מילות פעולה. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time מקש קיצור לשאילתה מותאמת אישית diff --git a/Flow.Launcher/Languages/it.xaml b/Flow.Launcher/Languages/it.xaml index e4d4d3e2c..fd34bf366 100644 --- a/Flow.Launcher/Languages/it.xaml +++ b/Flow.Launcher/Languages/it.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Modalità gioco Sospendere l'uso dei tasti di scelta rapida. Ripristina Posizione - Ripristina posizione finestra di ricerca + Type here to search Impostazioni @@ -70,8 +75,6 @@ Cancella ultima ricerca Preserve Last Action Keyword Select Last Action Keyword - Altezza Finestra Fissa - L'altezza della finestra non si può regolare trascinando. Numero massimo di risultati mostrati È anche possibile regolarlo rapidamente utilizzando CTRL+Più e CTRL+Meno. Ignora i tasti di scelta rapida in applicazione a schermo pieno @@ -102,6 +105,15 @@ Mostra Sempre Anteprima Apri sempre il pannello di anteprima quando Flow si attiva. Premi {0} per attivare l'anteprima. L'effetto ombra non è consentito mentre il tema corrente ha un effetto di sfocatura abilitato + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Plugin di ricerca @@ -118,6 +130,8 @@ Parola chiave di azione corrente Nuova parola chiave d'azione Cambia Keywords Azione + Plugin seach delay time + Change Plugin Seach Delay Time Priorità Attuale Nuova Priorità Priorità @@ -131,6 +145,9 @@ Disinstalla Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Negozio dei Plugin @@ -193,8 +210,20 @@ Personalizzato Orologio Data + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Vuoto + Acrylic + Mica + Mica Alt Questo tema supporta due (chiaro/scuro) varianti. Questo tema supporta lo sfondo trasparente blurrato. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Tasti scelta rapida @@ -294,6 +323,9 @@ Cartella dei Log Cancella i log Sei sicuro di voler cancellare tutti i log? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard Posizione Dati Utente Le impostazioni dell'utente e i plugin installati sono salvati nella cartella dati utente. Questa posizione può variare se è in modalità portable o no. @@ -335,9 +367,16 @@ Impossibile trovare il plugin specificato La nuova parola chiave d'azione non può essere vuota La nuova parola chiave d'azione è stata assegnata ad un altro plugin, per favore sceglierne una differente + This new Action Keyword is the same as old, please choose a different one Successo Completato con successo - Usa * se non vuoi specificare una parola chiave d'azione + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Tasti scelta rapida per ricerche personalizzate diff --git a/Flow.Launcher/Languages/ja.xaml b/Flow.Launcher/Languages/ja.xaml index 28c334667..e6f2223cd 100644 --- a/Flow.Launcher/Languages/ja.xaml +++ b/Flow.Launcher/Languages/ja.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ ゲームモード ホットキーの使用を一時停止します。 位置のリセット - 検索ウィンドウの位置をリセットします。 + Type here to search 設定 @@ -70,8 +75,6 @@ 前回のクエリを消去 Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. 結果の最大表示件数 CTRL+PlusとCTRL+Minusを使用すれば、簡単に調整することもできます。 ウィンドウがフルスクリーン時にホットキーを無効にする @@ -102,6 +105,15 @@ 常にプレビューする Flow が有効になったとき、常にプレビューパネルを開きます。 {0} を押してプレビューの表示/非表示を切り替えます。 現在のテーマでぼかしの効果が有効になっている場合、影の効果を有効にすることはできません + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Search Plugin @@ -118,6 +130,8 @@ Current action keyword New action keyword Change Action Keywords + Plugin seach delay time + Change Plugin Seach Delay Time Current Priority New Priority 重要度 @@ -131,6 +145,9 @@ アンインストール Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default プラグインストア @@ -193,8 +210,20 @@ カスタム 時刻 日付 + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. ホットキー @@ -294,6 +323,9 @@ Log Folder Clear Logs Are you sure you want to delete all logs? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ プラグインが見つかりません 新しいアクションキーボードを空にすることはできません 新しいアクションキーボードは他のプラグインに割り当てられています。他のアクションキーボードを指定してください + This new Action Keyword is the same as old, please choose a different one 成功しました Completed successfully - アクションキーボードを指定しない場合、* を使用してください + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time diff --git a/Flow.Launcher/Languages/ko.xaml b/Flow.Launcher/Languages/ko.xaml index d9da26bcb..3aee3f5e4 100644 --- a/Flow.Launcher/Languages/ko.xaml +++ b/Flow.Launcher/Languages/ko.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ 게임 모드 단축키 사용을 일시중단합니다. 창 위치 초기화 - 검색창 위치 초기화 + 검색어 입력 설정 @@ -45,8 +50,8 @@ 포터블 모드 모든 설정이 폴더안에 들어갑니다. USB 드라이브나 클라우드로 사용 가능합니다. 시스템 시작 시 Flow Launcher 실행 - Use logon task instead of startup entry for faster startup experience - After uninstallation, you need to manually remove this task (Flow.Launcher Startup) via Task Scheduler + 더 빠른 시작을 위해 시작 프로그램 항목 대신 로그온 Task 사용 + Flow Launcher를 제거한 후에는 작업 스케줄러에서 이 작업(Flow.Launcher Startup)을 수동으로 삭제해야 합니다 Error setting launch on startup 포커스 잃으면 Flow Launcher 숨김 새 버전 알림 끄기 @@ -70,8 +75,6 @@ 직전 쿼리 지우기 Preserve Last Action Keyword Select Last Action Keyword - 창 높이 고정 - 드래그로 창 높이를 조정하지 않습니다. 표시할 결과 수 Ctrl + '+'키와 Ctrl + '-'키로도 빠르게 조정할 수 있습니다 전체화면 모드에서는 단축키 무시 @@ -89,7 +92,7 @@ 자동 업데이트 선택 시작 시 Flow Launcher 숨김 - Flow Launcher search window is hidden in the tray after starting up. + Flowr Launcher가 트레이에 숨겨진 상태로 시작합니다. 트레이 아이콘 숨기기 트레이에서 아이콘을 숨길 경우, 검색창 우클릭으로 설정창을 열 수 있습니다. 쿼리 검색 정밀도 @@ -102,6 +105,15 @@ 항상 미리보기 Flow 사용시 항상 미리보기 패널을 열어둡니다. {0} 키를 눌러 프리뷰창을 켜고 끌 수 있습니다. 반투명 흐림 효과를 사용하는 경우, 그림자 효과를 쓸 수 없습니다. + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short 플러그인 검색 @@ -118,6 +130,8 @@ 현재 액션 키워드 새 액션 키워드 액션 키워드 변경 + Plugin seach delay time + Change Plugin Seach Delay Time 현재 중요도: 새 중요도: 중요도 @@ -131,6 +145,9 @@ 제거 Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default 플러그인 스토어 @@ -193,8 +210,20 @@ 사용자 정의 시계 날짜 + 배경 효과 타입 + Backdrop supported starting from Windows 11 build 22000 and above + 없음 + 아크릴 + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + 안내 텍스트 표시 + 입력 내용이 없을때 입력창 위치를 알 수 있는 텍스트를 표시합니다 + 안내 텍스트 + 안내 텍스트를 변경하세요. 아무것도 입력하지 않으면 다음을 사용합니다: "{0}" + Fixed Window Size + The window size is not adjustable by dragging. 단축키 @@ -294,6 +323,9 @@ 로그 폴더 로그 삭제 정말 모든 로그를 삭제하시겠습니까? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information 마법사 사용자 데이터 위치 사용자 설정과 설치된 플러그인은 사용자 데이터 폴더에 저장됩니다. 이 위치는 휴대용 모드 활성화 여부에 따라 달라질 수 있습니다. @@ -335,9 +367,16 @@ 플러그인을 찾을 수 없습니다. 새 액션 키워드를 입력하세요. 새 액션 키워드가 할당된 플러그인이 이미 있습니다. 다른 액션 키워드를 입력하세요. + This new Action Keyword is the same as old, please choose a different one 성공 성공적으로 완료했습니다. - 플러그인을 시작하는데 필요한 액션 키워드를 입력하세요. 액션 키워드를 지정하지 않으려면 *를 사용하세요. 이 경우 키워드를 입력하지 않아도 동작합니다. + 플러그인을 실행할 때 사용할 액션 키워드를 입력하세요. 여러 개를 입력할 경우 공백으로 구분하세요. 아무 키워드도 지정하지 않으려면 * 를 입력하세요. 이 경우 액션 키워드 없이도 플러그인이 실행됩니다. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time 사용자지정 쿼리 단축키 diff --git a/Flow.Launcher/Languages/nb.xaml b/Flow.Launcher/Languages/nb.xaml index a37a204e1..b78bcb7d7 100644 --- a/Flow.Launcher/Languages/nb.xaml +++ b/Flow.Launcher/Languages/nb.xaml @@ -7,6 +7,11 @@ Klikk nei hvis det allerede er installert, og du vil bli bedt om å velge mappen som inneholder {1} kjørbar fil Velg den kjørbare filen for {0} + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Kan ikke angi {0} kjørbar bane, prøv fra Flows innstillinger (bla ned til bunnen). Mislykkes i å initialisere programtillegg Programtillegg: {0} - mislykkes å lastes inn og vil bli deaktivert, vennligst kontakt utvikleren av programtillegget for hjelp @@ -37,7 +42,7 @@ Spillmodus Stopp bruken av hurtigtaster. Tilbakestilling av posisjon - Tilbakestill posisjonen til søkevinduet + Type here to search Innstillinger @@ -70,8 +75,6 @@ Tøm siste spørring Preserve Last Action Keyword Select Last Action Keyword - Fast vindushøyde - Vindushøyden kan ikke justeres ved å dra. Maksimalt antall resultater vist Du kan også raskt justere dette ved å bruke CTRL+Plus og CTRL+Minus. Ignorer hurtigtaster i fullskjermmodus @@ -102,6 +105,15 @@ Alltid forhåndsvisning Åpne alltid forhåndsvisningspanel når Flow aktiveres. Trykk på {0} for å velge forhåndsvisning. Skyggeeffekt er ikke tillatt mens gjeldende tema har uskarphet-effekt aktivert + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Søk etter programtillegg @@ -118,6 +130,8 @@ Nåværende handlingsnøkkelord Nytt handlingsnøkkelord Endre handlingsnøkkelord + Plugin seach delay time + Change Plugin Seach Delay Time Gjeldende prioritet Ny prioritet Prioritet @@ -131,6 +145,9 @@ Avinstaller Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Programtillegg butikk @@ -193,8 +210,20 @@ Egendefinert Klokke Dato + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Ingen + Acrylic + Mica + Mica Alt Dette temaet støtter to (lys/mørk) moduser. Dette temaet støtter uskarp gjennomsiktig bakgrunn. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Hurtigtast @@ -294,6 +323,9 @@ Loggmappe Tøm logger Er du sikker på at du vil slette alle loggene? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Veiviser Plassering av brukerdata Brukerinnstillinger og installerte programtillegg lagres i brukerens datamappe. Denne plasseringen kan variere avhengig av om den er i portabel modus eller ikke. @@ -335,9 +367,16 @@ Kan ikke finne spesifisert programtillegg Nytt handlingsnøkkelord kan ikke være tom Det nye nøkkelordet for handling er allerede tilordnet et annet programtillegg, velg et annet + This new Action Keyword is the same as old, please choose a different one Vellykket Fullført vellykket - Skriv inn handlingsnøkkelord du vil bruke for å starte programtillegget. Bruk * hvis du ikke ønsker å spesifisere noen, og utvidelsen vil bli utløst uten noen handlingsord. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Hurtigtast for egendefinert spørring diff --git a/Flow.Launcher/Languages/nl.xaml b/Flow.Launcher/Languages/nl.xaml index 64adccd94..ce3406142 100644 --- a/Flow.Launcher/Languages/nl.xaml +++ b/Flow.Launcher/Languages/nl.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Spelmodus Stop het gebruik van Sneltoetsen. Positie resetten - Positie zoekvenster resetten + Type here to search Instellingen @@ -70,8 +75,6 @@ Laatste zoekopdracht verwijderen Preserve Last Action Keyword Select Last Action Keyword - Vaste venster hoogte - De vensterhoogte is niet aanpasbaar door te slepen. Laat maximale resultaten zien Je kunt dit ook snel aanpassen met CTRL+Plus en CTRL+Minus. Negeer sneltoetsen in vol scherm modus @@ -102,6 +105,15 @@ Altijd voorbeeld Open altijd het voorbeeld paneel wanneer Flow activeert. Druk op {0} om voorbeeld te schakelen. Schaduw effect is niet toegestaan omdat het huidige thema een vervagingseffect heeft + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Plug-ins zoeken @@ -118,6 +130,8 @@ Huidige actie sneltoets Nieuw actie sneltoets Wijzig actie-sneltoets + Plugin seach delay time + Change Plugin Seach Delay Time Huidige Prioriteit Nieuwe Prioriteit Prioriteit @@ -131,6 +145,9 @@ Verwijderen Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Plugin Winkel @@ -193,8 +210,20 @@ Aangepast Klok Datum + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt Dit thema ondersteunt twee (licht/donker) modi. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Sneltoets @@ -294,6 +323,9 @@ Log Map Logbestanden wissen Weet u zeker dat u alle logbestanden wilt verwijderen? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard Gegevenslocatie van gebruiker Gebruikersinstellingen en geïnstalleerde plug-ins worden opgeslagen in de gebruikersgegevensmap. Deze locatie kan variëren afhankelijk van of het in draagbare modus is of niet. @@ -335,9 +367,16 @@ Kan plugin niet vinden Nieuwe actie sneltoets moet ingevuld worden Nieuwe actie sneltoets is toegewezen aan een andere plugin, wijs een nieuwe actie sneltoets aan + This new Action Keyword is the same as old, please choose a different one Succesvol Succesvol afgerond - Gebruik * wanneer je geen nieuwe actie sneltoets wilt specificeren + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Custom Query Sneltoets diff --git a/Flow.Launcher/Languages/pl.xaml b/Flow.Launcher/Languages/pl.xaml index 06204395c..12af37c3e 100644 --- a/Flow.Launcher/Languages/pl.xaml +++ b/Flow.Launcher/Languages/pl.xaml @@ -7,6 +7,11 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy poproszony o wybranie folderu zawierającego plik wykonywalny {1} Wybierz plik wykonywalny {0} + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Nie można ustawić ścieżki do pliku wykonywalnego {0}. Spróbuj ponownie w ustawieniach Flow (przewiń na sam dół). Nie udało się zainicjować wtyczek Wtyczki: {0} – nie udało się ich wczytać i zostaną wyłączone. Skontaktuj się z twórcą wtyczki, aby uzyskać pomoc @@ -37,7 +42,7 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Tryb grania Wstrzymaj używanie skrótów. Resetowanie pozycji - Zresetuj pozycję okna wyszukiwania + Type here to search Ustawienia @@ -70,8 +75,6 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Puste ostatnie zapytanie Zachowaj ostatnie słowo kluczowe akcji Wybierz ostatnie słowo kluczowe akcji - Stała wysokość okna - Wysokość okna nie jest regulowana poprzez przeciąganie. Maksymalna liczba wyników Możesz to również szybko dostosować używając CTRL+Plus i CTRL+Minus. Ignoruj skróty klawiszowe w trybie pełnoekranowym @@ -102,6 +105,15 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Zawsze podgląd Zawsze otwieraj panel podglądu, gdy aktywowany jest Flow. Naciśnij {0}, aby przełączyć podgląd. Efekt cienia jest niedozwolony, gdy bieżący motyw ma włączony efekt rozmycia + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Szukaj wtyczek @@ -118,6 +130,8 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Bieżące słowo kluczowe akcji Nowe słowo kluczowe akcji Zmień słowa kluczowe akcji + Plugin seach delay time + Change Plugin Seach Delay Time Obecny Priorytet Nowy Priorytet Priorytet @@ -131,6 +145,9 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Odinstalowywanie Nie udało się usunąć ustawień wtyczki Wtyczki: {0} – nie udało się usunąć plików ustawień wtyczek, usuń je ręcznie + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Sklep z wtyczkami @@ -193,8 +210,20 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Niestandardowa Zegar Data + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Brak + Acrylic + Mica + Mica Alt Ten motyw obsługuje dwa tryby (jasny/ciemny). Ten motyw obsługuje rozmyte przezroczyste tło. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Skrót klawiszowy @@ -294,6 +323,9 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Folder dziennika Wyczyść logi Czy na pewno chcesz usunąć wszystkie logi? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Kreator Lokalizacja danych użytkownika Ustawienia użytkownika i zainstalowane wtyczki są zapisywane w folderze danych użytkownika. Ta lokalizacja może się różnić w zależności od tego, czy aplikacja jest w trybie przenośnym, czy nie. @@ -335,9 +367,16 @@ Kliknij "nie", jeśli jest już zainstalowany. Zostaniesz wtedy popros Nie można odnaleźć podanej wtyczki Nowy wyzwalacz nie może być pusty Ten wyzwalacz został już przypisany do innej wtyczki, musisz podać inny wyzwalacz. + This new Action Keyword is the same as old, please choose a different one Sukces Zakończono pomyślnie - Użyj * jeżeli nie chcesz podawać wyzwalacza + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Skrót klawiszowy niestandardowych zapyta diff --git a/Flow.Launcher/Languages/pt-br.xaml b/Flow.Launcher/Languages/pt-br.xaml index 62293b1a1..d0040d799 100644 --- a/Flow.Launcher/Languages/pt-br.xaml +++ b/Flow.Launcher/Languages/pt-br.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Modo Gamer Suspender o uso de Teclas de Atalho. Redefinição de Posição - Redefinir posição da janela de busca + Type here to search Configurações @@ -70,8 +75,6 @@ Limpar última consulta Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. Máximo de resultados mostrados Você também pode ajustar isso rapidamente usando CTRL+Mais e CTRL+Menos. Ignorar atalhos em tela cheia @@ -102,6 +105,15 @@ Sempre Pré-visualizar Sempre abrir o painel de pré-visualização quando o Flow é ativado. Pressione {0} para ativar ou desativar a pré-visualização. O efeito de sombra não é permitido enquanto o tema atual tem o efeito de desfoque ativado + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Buscar Plugin @@ -118,6 +130,8 @@ Palavra-chave de ação atual Nova palavra-chave de ação Alterar Palavras-chave de Ação + Plugin seach delay time + Change Plugin Seach Delay Time Prioridade atual Nova Prioridade Prioridade @@ -131,6 +145,9 @@ Desinstalar Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Loja de Plugins @@ -193,8 +210,20 @@ Personalizado Relógio Data + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Atalho @@ -294,6 +323,9 @@ Pasta de Registro Limpar Registros Tem certeza que quer excluir todos os registros? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Assistente User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ Não foi possível encontrar o plugin especificado A nova palavra-chave da ação não pode ser vazia A nova palavra-chave da ação já foi atribuída a outro plugin, por favor tente outra + This new Action Keyword is the same as old, please choose a different one Sucesso Concluído com sucesso - Use * se não quiser especificar uma palavra-chave de ação + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Atalho de Consulta Personalizada diff --git a/Flow.Launcher/Languages/pt-pt.xaml b/Flow.Launcher/Languages/pt-pt.xaml index bad37f688..9dc520cbd 100644 --- a/Flow.Launcher/Languages/pt-pt.xaml +++ b/Flow.Launcher/Languages/pt-pt.xaml @@ -7,6 +7,11 @@ Clique "Não" se já tiver instalado e, de seguida, ser-lhe-á solicitada a pasta que contém o executável {1}. Por favor, selecione o executável {0} + + O executável {0} é inválido. + {2}{2} + Clique Sim se quiser escolher o novo executável {0}. Clique Não se quiser descarregar {1}. + Não foi possível definir o caminho do executável {0}. Experimente definir o caminho nas definições (desloque até ao fundo). Falha ao iniciar os plugins Plugin: {0} - não foi possível iniciar e será desativado. Contacte o criador do plugin para obter ajuda. @@ -37,7 +42,7 @@ Modo de jogo Suspender utilização das teclas de atalho Repor posição - Repor posição da janela de pesquisa + Escreva aqui para pesquisar Definições @@ -70,8 +75,6 @@ Limpar última consulta Manter palavra-chave da última ação Selecionar palavra-chave da última ação - Altura fixa de janela - Não é possível ajustar o tamanho da janela por arrasto. Número máximo de resultados Também pode ajustar rapidamente através do atalho Ctrl+ e Ctrl-. Ignorar teclas de atalho se em ecrã completo @@ -102,6 +105,15 @@ Pré-visualizar sempre Abrir painel de pré-visualização ao ativar Flow Launcher. Prima {0} para comutar a pré-visualização. O efeito sombra não é permitido com este tema porque o efeito desfocar está ativo + Atraso da pesquisa + Tempo a esperar após a digitação. Esta definição melhora o carregamento dos resultados. + Tempo de espera padrão + O valor padrão a esperar, antes de iniciar a pesquisa após terminar a digitação. + Muito longo + Longo + Normal + Curto + Muito curto Pesquisar plugins @@ -118,6 +130,8 @@ Palavra-chave atual Nova palavra-chave Alterar palavras-chave + Tempo de espera do plugin + Alterar tempo de espera do plugin Prioridade atual Nova prioridade Prioridade @@ -131,6 +145,9 @@ Desinstalar Falha ao remover as definições do plugin Plugin: {0} - Falha ao remover o ficheiro de definições do plugin. Experimente remover manualmente. + Falha ao limpar a cache do plugin + Plugin: {0} - Falha ao remover os ficheiros em cache do plugin. Experimente remover manualmente. + Padrão Loja de plugins @@ -193,8 +210,20 @@ Personalizada Relógio Data + Tipo de fundo + Esta opção apenas está disponível em sistemas após Windows 11 Build 22000 + Nenhuma + Acrílico + Mica + Mica alternativo Este tema tem suporte a dois modos (claro/escuro). Este tema tem suporte a fundo transparente desfocado. + Mostrar marcador de posição + Mostrar marcador de posição se a consulta estiver vazia + Texto do marcador + O texto do marcador de posição. Se vazio, será utilizado: {0} + Janela com tamanho fixo + Não pode ajustar o tamanho da janela por arrasto. Tecla de atalho @@ -293,13 +322,16 @@ Pasta de registos Limpar registos Tem a certeza de que deseja remover todos os registos? + Limpar cache + Tem a certeza de que pretende limpar todas as caches? + Não foi possível limpar todas as pastas e ficheiros. Consulte o ficheiro de registo para mais informações. Assistente Localização dos dados do utilizador As definições e os plugins instalados são guardados na pasta de dados do utilizador. A localização pode variar, tendo em conta se a aplicação está instalada ou no modo portátil Abrir pasta - Log Level - Debug - Info + Nível de registo + Depuração + Informação Selecione o gestor de ficheiros @@ -334,9 +366,16 @@ Plugin não encontrado A nova palavra-chave não pode estar vazia Esta palavra-chave já está associada a um plugin. Por favor escolha outra. + A palavra-chave escolhida é igual à anterior. Por favor escolha outra. Sucesso Terminado com sucesso - Introduza a palavra-chave a utilizar para iniciar o plugin. Utilize * se não quiser utilizar esta funcionalidade e o plugin não será ativado com palavras-chave. + Introduza as palavras-chave que pretende utilizar para iniciar o plugin e um espaço vazio caso queira mais do que uma. Utilize * se não quiser especificar uma palavra-chave e o plugin será ativado sem palavras-chave. + + + Definição do tempo de espera + Selecione o tempo de espera que pretende utilizar com este plugin. Selecione "{0}" se não o quiser especificar e, desta forma, o plugin irá utilizar o tempo de espera padrão. + Tempo de espera atual + Novo tempo de espera Tecla de atalho personalizada diff --git a/Flow.Launcher/Languages/ru.xaml b/Flow.Launcher/Languages/ru.xaml index a56a770da..c38855474 100644 --- a/Flow.Launcher/Languages/ru.xaml +++ b/Flow.Launcher/Languages/ru.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Игровой режим Приостановить использование горячих клавиш. Сброс положения - Сброс положения окна поиска + Type here to search Настройки @@ -70,8 +75,6 @@ Очистить последний запрос Preserve Last Action Keyword Select Last Action Keyword - Фиксированная высота окна - The window height is not adjustable by dragging. Максимальное количество результатов Вы также можете быстро настроить это с помощью CTRL+плюс и CTRL+минус. Игнорировать горячие клавиши в полноэкранном режиме @@ -102,6 +105,15 @@ Всегда предпросмотр Всегда открывать панель предварительного просмотра при запуске Flow. Нажмите {0}, чтобы переключить предварительный просмотр. Эффект тени не допускается, если в текущей теме включён эффект размытия + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Поиск плагина @@ -118,6 +130,8 @@ Ключевое слово текущего действия Ключевое слово нового действия Изменить ключевое слово действия + Plugin seach delay time + Change Plugin Seach Delay Time Текущий приоритет Новый приоритет Приоритет @@ -131,6 +145,9 @@ Удалить Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Магазин плагинов @@ -193,8 +210,20 @@ Своя Часы Дата + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Горячая клавиша @@ -294,6 +323,9 @@ Папка журнала Очистить журнал Вы уверены, что хотите удалить все журналы? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Мастер User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ Не удалось найти заданный плагин Новая горячая клавиша не может быть пустой Новая горячая клавиша уже используется другим плагином. Пожалуйста, задайте новую + This new Action Keyword is the same as old, please choose a different one Успешно Выполнено успешно - Введите горячую клавишу, которое вы хотите использовать для запуска плагина. Используйте *, если вы не хотите ничего указывать, и плагин будет запускаться без каких-либо горячих клавиш. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Задаваемые горячие клавиши для запросов diff --git a/Flow.Launcher/Languages/sk.xaml b/Flow.Launcher/Languages/sk.xaml index 332528b2b..0f07387c6 100644 --- a/Flow.Launcher/Languages/sk.xaml +++ b/Flow.Launcher/Languages/sk.xaml @@ -7,6 +7,11 @@ Ak už ho máte nainštalovaný, kliknite na nie, a budete vyzvaný na zadanie cesty k priečinku spustiteľného súboru {1} Vyberte spustiteľný súbor {0} + + Vybrali ste nesprávny spustiteľný súbor {0}. + {2}{2} + Ak chcete znovu vybrať spustiteľný súbor {0}, kliknite na Áno. Kliknutím na Nie sa stiahne {1}. + Nie je možné nastaviť cestu ku spustiteľnému súboru {0}, skúste to v nastaveniach Flowu (prejdite nadol). Nepodarilo sa inicializovať pluginy Pluginy: {0} – nepodarilo sa načítať a mal by byť zakázaný, na pomoc kontaktujte autora pluginu @@ -37,7 +42,7 @@ Herný režim Pozastaviť používanie klávesových skratiek. Resetovať pozíciu - Resetovať pozíciu vyhľadávacieho okna + Zadajte text na vyhľadávanie Nastavenia @@ -70,8 +75,6 @@ Vymazať Ponechať posledný akčný príkaz Označiť posledný akčný príkaz - Pevná výška okna - Výška okna sa nedá nastaviť ťahaním. Maximum výsledkov Túto hodnotu môžete rýchlo upraviť aj pomocou klávesových skratiek CTRL + znamienko plus (+) a CTRL + znamienko mínus (-). Ignorovať klávesové skratky v režime na celú obrazovku @@ -102,6 +105,15 @@ Vždy zobraziť náhľad Pri aktivácii Flowu vždy otvoriť panel s náhľadom. Stlačením klávesu {0} prepnete náhľad. Efekt tieňa nie je povolený, kým má aktuálny motív povolený efekt rozostrenia + Oneskorenie vyhľadávania + Pri písaní sa na chvíľu oneskorí vyhľadávanie. Tým sa zníži skákanie rozhrania a načítanie výsledkov. + Predvolené oneskorenie vyhľadávania + Predvolené oneskorenie pluginu, po ktorom sa zobrazia výsledky vyhľadávania po zastavení písania. + Veľmi dlhé + Dlhé + Normálne + Krátke + Veľmi krátke Vyhľadať plugin @@ -118,6 +130,8 @@ Aktuálny aktivačný príkaz Nový aktivačný príkaz Upraviť aktivačný príkaz + Oneskorenie vyhľadávania pomocou pluginu + Zmení oneskorenie vyhľadávania pomocou pluginu Aktuálna priorita Nová priorita Priorita @@ -131,6 +145,9 @@ Odinštalovať Nepodarilo sa odstrániť nastavenia pluginu Pluginy: {0} – Nepodarilo sa odstrániť súbory s nastaveniami pluginu, odstráňte ich manuálne + Nepodarilo sa odstrániť vyrovnávaciu pamäť pluginu + Pluginy: {0} – Nepodarilo sa odstrániť vyrovnávaciu pamäť pluginu, odstráňte ju manuálne + Predvolené Repozitár pluginov @@ -193,8 +210,20 @@ Vlastné Hodiny Dátum + Typ pozadia + Backdrop je podporovaný od Windows 11 zostava 22000 a novších + Žiadna + Acrylic + Mica + Mica Alt Tento motív podporuje 2 režimy (svetlý/tmavý). Tento motív podporuje rozostrenie priehľadného pozadia. + Zobraziť zástupný text + Zobrazí zástupný text v prázdnom vyhľadávacom poli + Zástupný text + Zobrazí zástupný text. V prázdnom poli sa zobrazí: {0} + Pevná veľkosť okna + Veľkosť okna sa nedá nastaviť ťahaním. Klávesové skratky @@ -294,6 +323,9 @@ Priečinok s logmi Vymazať logy Naozaj chcete odstrániť všetky logy? + Vymazať vyrovnávaciu pamäť + Naozaj chcete vymazať všetky vyrovnávacie pamäte? + Nepodarilo sa odstrániť niektoré priečinky a súbory. Pre viac informácií si pozrite súbor logu Sprievodca Cesta k používateľskému priečinku Nastavenia používateľa a nainštalované pluginy sa ukladajú do používateľského priečinka. Toto umiestnenie sa môže líšiť v závislosti od toho, či je v prenosnom režime alebo nie. @@ -335,9 +367,16 @@ Nepodarilo sa nájsť zadaný plugin Nový aktivačný príkaz nemôže byť prázdny Nový aktivačný príkaz už bol priradený inému pluginu, prosím, zvoľte iný aktivačný príkaz + Tento nový aktivačný príkaz je rovnaký ako starý, vyberte iný Úspešné Úspešne dokončené - Zadajte aktivačný príkaz, ktorý je potrebný na spustenie pluginu. Ak nechcete zadať aktivačný príkaz, použite * a plugin bude spustený bez aktivačného príkazu. + Zadajte aktivačné príkazy, ktoré chcete používať na spustenie pluginu a oddeľte ich medzerou. Ak nechcete zadať aktivačný príkaz, použite * a plugin bude spustený bez aktivačného príkazu. + + + Nastavenie oneskoreného vyhľadávania + Vyberte oneskorenie vyhľadávania, ktoré chcete použiť pre plugin. Ak vyberiete "{0}", plugin použije predvolené oneskorenie vyhľadávania. + Aktuálne oneskorenie vyhľadávania + Nové oneskorenie vyhľadávania Klávesová skratka vlastného vyhľadávania diff --git a/Flow.Launcher/Languages/sr.xaml b/Flow.Launcher/Languages/sr.xaml index b244c4660..1d1eb9120 100644 --- a/Flow.Launcher/Languages/sr.xaml +++ b/Flow.Launcher/Languages/sr.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Game Mode Suspend the use of Hotkeys. Position Reset - Reset search window position + Type here to search Podešavanja @@ -70,8 +75,6 @@ Isprazni poslednji Upit Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. Maksimum prikazanih rezultata You can also quickly adjust this by using CTRL+Plus and CTRL+Minus. Ignoriši prečice u fullscreen režimu @@ -102,6 +105,15 @@ Always Preview Always open preview panel when Flow activates. Press {0} to toggle preview. Shadow effect is not allowed while current theme has blur effect enabled + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Search Plugin @@ -118,6 +130,8 @@ Current action keyword New action keyword Change Action Keywords + Plugin seach delay time + Change Plugin Seach Delay Time Current Priority New Priority Priority @@ -131,6 +145,9 @@ Uninstall Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Plugin Store @@ -193,8 +210,20 @@ Custom Clock Date + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Prečica @@ -294,6 +323,9 @@ Log Folder Clear Logs Are you sure you want to delete all logs? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ Navedeni plugin nije moguće pronaći Prečica za novu radnju ne može da bude prazna Prečica za novu radnju je dodeljena drugom plugin-u, molim Vas dodelite drugu prečicu + This new Action Keyword is the same as old, please choose a different one Uspešno Completed successfully - Koristite * ako ne želite da navedete prečicu za radnju + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time prečica za ručno dodat upit diff --git a/Flow.Launcher/Languages/tr.xaml b/Flow.Launcher/Languages/tr.xaml index 5d550ebed..b9b5d351e 100644 --- a/Flow.Launcher/Languages/tr.xaml +++ b/Flow.Launcher/Languages/tr.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Oyun Modu Kısayol tuşlarının kullanımını durdurun. Pencere Konumunu Sıfırla - Arama penceresinin konumunu sıfırla + Type here to search Ayarlar @@ -70,8 +75,6 @@ Sorgu Kutusunu Temizle Preserve Last Action Keyword Select Last Action Keyword - Sabit Pencere Yükseliği - Pencere yüksekliği sürükleme ile ayarlanamaz. Maksimum Sonuç Sayısı Bunu CTRL + ve CTRL - kısayollarıyla da ayarlayabilirsiniz. Tam Ekran Modunda Kısayol Tuşunu Gözardı Et @@ -102,6 +105,15 @@ Önizleme Önizleme panelini her zaman aç. Önizlemeyi bu ayardan bağımsız {0} kısayolu ile açıp kapatabilirsiniz. Mevcut temada bulanıklık efekti etkinken gölgelendirme efektine izin verilmez + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Eklenti Ara @@ -118,6 +130,8 @@ Geçerli anahtar kelime Yeni anahtar kelime Anahtar kelimeyi değiştir + Plugin seach delay time + Change Plugin Seach Delay Time Mevcut öncelik Yeni Öncelik Öncelik @@ -131,6 +145,9 @@ Kaldır Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Eklenti Mağazası @@ -193,8 +210,20 @@ Özel Saat Tarih + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Hiçbiri + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Kısayol Tuşu @@ -294,6 +323,9 @@ Günlük Klasörü Günlükleri Temizle Tüm günlük kayıtlarını silmek istediğinize emin misiniz? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Kurulum Sihirbazı Kullanıcı Verisi Dizini Kullanıcı ayarları ve yüklü eklentiler bu klasörde saklanır. Klasörün konumu taşınabilir moda bağlı olarak değişebilir. @@ -335,9 +367,16 @@ Belirtilen eklenti bulunamadı Yeni anahtar kelime boş olamaz Yeni anahtar kelime başka bir eklentiye atanmış durumda. Lütfen başka bir anahtar kelime seçin. + This new Action Keyword is the same as old, please choose a different one Başarılı Başarıyla tamamlandı - Herhangi bir anahtar kelime belirlemek istemiyorsanız * kullanın + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Özel Sorgu Kısayolları diff --git a/Flow.Launcher/Languages/uk-UA.xaml b/Flow.Launcher/Languages/uk-UA.xaml index 95a746a51..427511c66 100644 --- a/Flow.Launcher/Languages/uk-UA.xaml +++ b/Flow.Launcher/Languages/uk-UA.xaml @@ -7,6 +7,11 @@ Клацніть Ні, якщо воно вже встановлене, і вам буде запропоновано вибрати теку, яка містить виконуваник {1} Будласка оберіть виконуваник {0} + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Не вдається встановити шлях до виконуваника {0}, будласка спробуйте в налаштуваннях Flow (прокрутіть вниз до кінця). Невдача ініціалізації плагінів Плагіни: {0} - не вдалося підвантажити і буде вимкнено, зверніться за допомогою до автора плагіна @@ -37,7 +42,7 @@ Режим гри Призупинити використання гарячих клавіш. Скидання позиції - Скинути положення вікна пошуку + Type here to search Налаштування @@ -70,8 +75,6 @@ Очистити останній запит Preserve Last Action Keyword Select Last Action Keyword - Фіксована висота вікна - Висота вікна не регулюється перетягуванням. Максимальна кількість результатів Ви також можете швидко налаштувати цей параметр за допомогою клавіш CTRL+Плюс чи CTRL+Мінус. Ігнорувати гарячі клавіші в повноекранному режимі @@ -102,6 +105,15 @@ Завжди переглядати Завжди відкривати панель попереднього перегляду при активації Flow. Натисніть {0}, щоб переключити попередній перегляд. Ефект тіні не дозволено, коли поточна тема має ефект розмиття + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Плагін для пошуку @@ -118,6 +130,8 @@ Поточна гаряча клавіша Нова гаряча клавіша Змінити гарячі клавіши + Plugin seach delay time + Change Plugin Seach Delay Time Поточний пріоритет Новий пріоритет Пріоритет @@ -131,6 +145,9 @@ Видалити Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Магазин плагінів @@ -193,8 +210,20 @@ Користувацька Годинник Дата + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Нема + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. Ця тема підтримує розмитий прозорий фон. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Гаряча клавіша @@ -294,6 +323,9 @@ Тека журналу Очистити журнали Ви впевнені, що хочете видалити всі журнали? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Чаклун Розташування даних користувача Налаштування користувача та встановлені плагіни зберігаються у теці даних користувача. Це місце може змінюватися залежно від того, чи перебуває програма в портативному режимі, чи ні. @@ -335,9 +367,16 @@ Не вдалося знайти вказаний плагін Нова гаряча клавіша не може бути порожньою Нова гаряча клавіша вже використовується іншим плагіном. Будь ласка, вкажіть нову + This new Action Keyword is the same as old, please choose a different one Успішно Успішно завершено - Введіть гарячу клавішу, яку ви хочете використовувати для запуску плагіна. Використовуйте * у разі, якщо ви не хочете ставити конкретну гарячу клавішу. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Задані гарячі клавіші для запитів diff --git a/Flow.Launcher/Languages/vi.xaml b/Flow.Launcher/Languages/vi.xaml index 17e421e16..6223efc00 100644 --- a/Flow.Launcher/Languages/vi.xaml +++ b/Flow.Launcher/Languages/vi.xaml @@ -7,6 +7,11 @@ Hãy chọn không nếu nó đã được cài đặt, và bạn sẽ được hỏi chọn thư mục chứa chương trình thực thi {1} Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ Chế độ trò chơi Tạm dừng sử dụng phím nóng. Đặt lại vị trí - Đặt lại vị trí của cửa sổ tìm kiếm + Type here to search Cài đặt @@ -70,8 +75,6 @@ Trống truy vấn cuối cùng Preserve Last Action Keyword Select Last Action Keyword - Giữ nguyên chiều cao cửa sổ - Chiều cao cửa sổ không thể thay đổi bằng cách kéo. Số kết quả tối đa Có thể thiết lập nhanh chóng bằng CTRL+Plus và CTRL+Minus. Bỏ qua phím nóng khi cửa sổ ở chế độ toàn màn hình @@ -102,6 +105,15 @@ Luôn xem trước Luôn mở bảng xem trước khi Flow kích hoạt. Nhấn {0} để chuyển đổi chế độ xem trước. Hiệu ứng đổ bóng không được phép nếu chủ đề hiện tại bật hiệu ứng làm mờ + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Plugin tìm kiếm @@ -118,6 +130,8 @@ Từ hành động hiện tại Từ hành động mới Thay đổi từ hành động + Plugin seach delay time + Change Plugin Seach Delay Time Ưu tiên hiện tại Ưu tiên mới Ưu tiên @@ -131,6 +145,9 @@ Gỡ cài đặt Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default Tải tiện ích mở rộng @@ -193,8 +210,20 @@ Tùy chỉnh Giờ Ngày + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + Không + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. Phím tắt @@ -296,6 +325,9 @@ Thư mục nhật ký Xóa tệp nhật ký Bạn có chắc chắn muốn xóa tất cả nhật ký không? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information Wizard Vị trí dữ liệu người dùng Thiết đặt người dùng và plugin đã cài đặt sẽ được lưu trong thư mục dữ liệu người dùng. Vị trí này có thể thay đổi tùy thuộc vào việc nó có ở chế độ di động hay không. @@ -337,9 +369,16 @@ Không thể tìm thấy plugin được chỉ định Từ khóa hành động mới không được để trống Từ khóa hành động mới này đã được gán cho một plugin khác, vui lòng chọn một plugin khác + This new Action Keyword is the same as old, please choose a different one Thành công Đã hoàn tất thành công - Sử dụng * nếu bạn muốn xác định từ khóa hành động. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time Phím nóng truy vấn tùy chỉnh diff --git a/Flow.Launcher/Languages/zh-cn.xaml b/Flow.Launcher/Languages/zh-cn.xaml index d9966d757..3d302da5b 100644 --- a/Flow.Launcher/Languages/zh-cn.xaml +++ b/Flow.Launcher/Languages/zh-cn.xaml @@ -7,6 +7,11 @@ 如果已安装,请单击“否”,系统将提示您选择包含 {1} 可执行文件的文件夹 请选择 {0} 可执行文件 + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + 无法设置 {0} 可执行路径,请尝试从 Flow 的设置中设置(向下滚动到底部)。 无法初始化插件 插件:{0} - 无法加载并将被禁用,请联系插件创建者寻求帮助 @@ -37,7 +42,7 @@ 游戏模式 暂停使用热键。 重置位置 - 重置搜索窗口位置 + Type here to search 设置 @@ -70,8 +75,6 @@ 清空上次搜索关键字 Preserve Last Action Keyword Select Last Action Keyword - 固定窗口高度 - 窗口高度不能通过拖动来调整。 最大结果显示个数 您也可以通过使用 CTRL+ "+" 和 CTRL+ "-" 来快速调整它。 全屏模式下忽略热键 @@ -102,6 +105,15 @@ 始终打开预览 Flow 启动时总是打开预览面板。按 {0} 以切换预览。 当前主题已启用模糊效果,不允许启用阴影效果 + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short 搜索插件 @@ -118,6 +130,8 @@ 当前触发关键字 新触发关键字 更改触发关键字 + Plugin seach delay time + Change Plugin Seach Delay Time 当前优先级 新优先级 优先级 @@ -131,6 +145,9 @@ 卸载 Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default 插件商店 @@ -193,8 +210,20 @@ 自定义 时钟 日期 + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + + Acrylic + Mica + Mica Alt 该主题支持两种(浅色/深色)模式。 该主题支持模糊透明背景。 + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. 热键 @@ -294,6 +323,9 @@ 日志目录 清除日志 你确定要删除所有的日志吗? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information 向导 用户数据位置 用户设置和已安装的插件保存在用户数据文件夹中。此位置可能因是否处于便携模式而异。 @@ -335,9 +367,16 @@ 找不到指定的插件 新触发关键字不能为空 此触发关键字已经被指派给其他插件了,请换一个关键字 + This new Action Keyword is the same as old, please choose a different one 成功 成功完成 - 如果你不想设置触发关键字,可以使用*代替 + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time 自定义查询热键 @@ -371,7 +410,7 @@ 更新 - 背景 + 后台 版本 diff --git a/Flow.Launcher/Languages/zh-tw.xaml b/Flow.Launcher/Languages/zh-tw.xaml index 01b667e72..cecad8e0d 100644 --- a/Flow.Launcher/Languages/zh-tw.xaml +++ b/Flow.Launcher/Languages/zh-tw.xaml @@ -7,6 +7,11 @@ Click no if it's already installed, and you will be prompted to select the folder that contains the {1} executable Please select the {0} executable + + Your selected {0} executable is invalid. + {2}{2} + Click yes if you would like select the {0} executable agian. Click no if you would like to download {1} + Unable to set {0} executable path, please try from Flow's settings (scroll down to the bottom). Fail to Init Plugins Plugins: {0} - fail to load and would be disabled, please contact plugin creator for help @@ -37,7 +42,7 @@ 遊戲模式 暫停使用快捷鍵。 重設位置 - 重設搜尋視窗位置 + Type here to search 設定 @@ -70,8 +75,6 @@ 清空上次搜尋關鍵字 Preserve Last Action Keyword Select Last Action Keyword - Fixed Window Height - The window height is not adjustable by dragging. 最大結果顯示個數 You can also quickly adjust this by using CTRL+Plus and CTRL+Minus. 全螢幕模式下忽略快捷鍵 @@ -102,6 +105,15 @@ 一律預覽 當 Flow 啟動時,一律開啟預覽面板。按下 {0} 可切換預覽。 Shadow effect is not allowed while current theme has blur effect enabled + Search Delay + Delay for a while to search when typing. This reduces interface jumpiness and result load. + Default Search Delay Time + Plugin default delay time after which search results appear when typing is stopped. + Very long + Long + Normal + Short + Very short Search Plugin @@ -118,6 +130,8 @@ 目前觸發關鍵字 新觸發關鍵字 更改觸發關鍵字 + Plugin seach delay time + Change Plugin Seach Delay Time 目前優先 新增優先 優先 @@ -131,6 +145,9 @@ 解除安裝 Fail to remove plugin settings Plugins: {0} - Fail to remove plugin settings files, please remove them manually + Fail to remove plugin cache + Plugins: {0} - Fail to remove plugin cache files, please remove them manually + Default 插件商店 @@ -193,8 +210,20 @@ Custom 時鐘 日期 + Backdrop Type + Backdrop supported starting from Windows 11 build 22000 and above + None + Acrylic + Mica + Mica Alt This theme supports two(light/dark) modes. This theme supports Blur Transparent Background. + Show placeholder + Display placeholder when query is empty + Placeholder text + Change placeholder text. Input empty will use: {0} + Fixed Window Size + The window size is not adjustable by dragging. 快捷鍵 @@ -294,6 +323,9 @@ 日誌資料夾 清除日誌 請確認要刪除所有日誌嗎? + Clear Caches + Are you sure you want to delete all caches? + Failed to clear part of folders and files. Please see log file for more information 嚮導 User Data Location User settings and installed plugins are saved in the user data folder. This location may vary depending on whether it's in portable mode or not. @@ -335,9 +367,16 @@ 找不到指定的插件 新觸發關鍵字不能為空白 新觸發關鍵字已經被指派給另一個插件,請設定其他關鍵字。 + This new Action Keyword is the same as old, please choose a different one 成功 成功完成 - 如果不想設定觸發關鍵字,可以使用*代替 + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + + + Search Delay Time Setting + Select the search delay time you like to use for the plugin. Select "{0}" if you don't want to specify any, and the plugin will use default search delay time. + Current search delay time + New search delay time 自定義快捷鍵查詢 diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml index 4cdd4c934..d8d3a586f 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Languages/sk.xaml @@ -2,7 +2,7 @@ Kalkulačka - Spracúva matematické operácie.(Skúste 5*3-2 vo flowlauncheri) + Spracúva matematické operácie. (Skúste 5*3-2 vo Flow Launcheri) Nie je číslo (NaN) Nesprávny alebo neúplný výraz (Nezabudli ste na zátvorky?) Kopírovať výsledok do schránky diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ko.xaml index 41a4abfcf..cc78c9a9a 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Languages/ko.xaml @@ -4,6 +4,6 @@ Activate {0} plugin action keyword 플러그인 인디케이터 - 플러그인의 액션 키워드 제안을 제공합니다 + 사용중인 플러그인들의 전체 액션 키워드 목록을 보여줍니다 diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/de.xaml index df162af92..47ea31cce 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Languages/de.xaml @@ -13,8 +13,8 @@ Plugin wird installiert {0} herunterladen und installieren Plug-in-Deinstallation - Keep plugin settings - Do you want to keep the settings of the plugin for the next usage? + Plug-in-Einstellungen beibehalten + Möchten Sie die Einstellungen des Plug-ins für die nächste Nutzung beibehalten? Plug-in {0} erfolgreich installiert. Flow wird neu gestartet, bitte warten Sie ... Die Metadaten-Datei plugin.json in der entpackten Zip-Datei kann nicht gefunden werden. Fehler: Ein Plug-in, welches die gleiche oder eine höhere Version mit {0} hat, ist bereits vorhanden. diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ar.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ar.xaml index 4104bd757..04619239d 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ar.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ar.xaml @@ -8,4 +8,6 @@ قتل عمليات {0} قتل جميع الأمثلة + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/cs.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/cs.xaml index 4dc11fcec..d621b63c4 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/cs.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/cs.xaml @@ -8,4 +8,6 @@ ukončit {0} procesů ukončit všechny instance + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/da.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/da.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/da.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/da.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/de.xaml index 8697818dc..766d170a4 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/de.xaml @@ -8,4 +8,6 @@ {0} Prozesse beenden Alle Instanzen beenden + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es-419.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es-419.xaml index 2dd0745c3..9b4a20a69 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es-419.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es-419.xaml @@ -8,4 +8,6 @@ terminar {0} procesos termina todas las instancias + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es.xaml index 27fda1db7..ab788075e 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/es.xaml @@ -8,4 +8,6 @@ finalizar {0} procesos finalizar todas las instancias + Colocar procesos con ventanas visibles en la parte superior + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/fr.xaml index ec880406a..7064de1fe 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/fr.xaml @@ -8,4 +8,6 @@ Tuer {0} processus Tuer toutes les instances + Placer les processus dont les fenêtres sont visibles en haut de la page + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/he.xaml index 018435eca..8567b5412 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/he.xaml @@ -8,4 +8,6 @@ סגור {0} תהליכים סגור את כל המופעים + הצב תהליכים עם חלונות גלויים בחלק העליון + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/it.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/it.xaml index 1ea52e741..1333fe573 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/it.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/it.xaml @@ -8,4 +8,6 @@ termina {0} processi termina tutte le istanze + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ja.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ko.xaml index a19c958b4..c3d1f6d08 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ko.xaml @@ -8,4 +8,6 @@ {0} 프로세스 종료 모든 인스턴스 종료 + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nb.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nb.xaml index f06121887..1210818bf 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nb.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nb.xaml @@ -8,4 +8,6 @@ terminer {0} processes terminer alle forekomstene + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nl.xaml index c4cc85463..cfcd71c37 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/nl.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Zet processen met zichtbare vensters bovenaan + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pl.xaml index a111f8776..650f14657 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pl.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pl.xaml @@ -8,4 +8,6 @@ zamknij {0} procesów zamknij wszystkie instancje + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-br.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-br.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-pt.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-pt.xaml index b5c75f2d9..944a883c9 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-pt.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/pt-pt.xaml @@ -8,4 +8,6 @@ terminar {0} processos terminar todas as instâncias + Colocar processos com janelas visíveis por cima + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ru.xaml index 26963bddb..0e2bef052 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/ru.xaml @@ -8,4 +8,6 @@ удалить {0} процессов удалить все экземпляры + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sk.xaml index bfa4792e4..2b06d3bbe 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sk.xaml @@ -8,4 +8,6 @@ ukončiť {0} procesov ukončiť všetky inštancie + Zobraziť procesy s viditeľným oknom navrchu + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sr.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sr.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sr.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/sr.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/tr.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/tr.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/uk-UA.xaml index e23f43875..02dab46ba 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/uk-UA.xaml @@ -8,4 +8,6 @@ вбити {0} процесів вбити всі екземпляри + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/vi.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/vi.xaml index 0bf065ee1..89fd67635 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/vi.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/vi.xaml @@ -8,4 +8,6 @@ Buộc tắt các tiến trình {0} Tắt tất cả phên bản + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-cn.xaml index 160ca5f96..15e717c79 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-cn.xaml @@ -8,4 +8,6 @@ 杀死 {0} 进程 杀死所有实例 + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-tw.xaml index c4cc85463..8563f49a0 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/zh-tw.xaml @@ -8,4 +8,6 @@ kill {0} processes kill all instances + Put processes with visible windows on the top + diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/de.xaml index 662765760..14e228b2a 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/de.xaml @@ -34,8 +34,8 @@ Blendet Programme mit gängigen Uninstaller-Namen aus, wie unins000.exe In Programmbeschreibung suchen Flow wird in Programmbeschreibung suchen - Hide duplicated apps - Hide duplicated Win32 programs that are already in the UWP list + Duplizierte Apps ausblenden + Duplizierte Win32-Programme ausblenden, die bereits in der UWP-Liste sind Suffixe Maximale Tiefe diff --git a/Plugins/Flow.Launcher.Plugin.Program/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.Program/Languages/he.xaml index 0e8b2f1d5..af272fb46 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.Program/Languages/he.xaml @@ -84,7 +84,7 @@ סייר מותאם אישית ארגומנטים - You can customize the explorer used for opening the container folder by inputing the Environmental Variable of the explorer you want to use. It will be useful to use CMD to test whether the Environmental Variable is available. + באפשרותך להתאים אישית את הסייר שבו נעשה שימוש לפתיחת תיקיית המכולה על ידי הזנת משתנה הסביבה של הסייר שברצונך להשתמש בו. כדאי לבדוק באמצעות CMD אם משתנה הסביבה זמין. הזן את הארגומנטים שברצונך להוסיף לסייר המותאם אישית שלך. %s עבור ספריית האב, %f עבור הנתיב המלא (זמין רק עבור win32). בדוק באתר הסייר לפרטים נוספים. diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Shell/Languages/de.xaml index 77a3fed47..dcfc82e0a 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.Shell/Languages/de.xaml @@ -6,7 +6,7 @@ Drücken Sie eine beliebige Taste, um dieses Fenster zu schließen ... Eingabeaufforderung nach Befehlsausführung nicht schließen Immer als Administrator ausführen - Use Windows Terminal + Windows-Terminal verwenden Als anderer Benutzer ausführen Shell Ermöglicht das Ausführen von Systembefehlen aus Flow Launcher diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ar.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ar.xaml index 529be9f45..ccc50678e 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ar.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ar.xaml @@ -2,8 +2,9 @@ - أمر + اسم البرنامج وصف + أمر إيقاف التشغيل إعادة التشغيل @@ -27,6 +28,8 @@ تبديل وضع اللعبة Set the Flow Launcher Theme + تعدي + إيقاف تشغيل الكمبيوتر إعادة تشغيل الكمبيوتر @@ -59,6 +62,15 @@ هل أنت متأكد أنك تريد إعادة تشغيل الكمبيوتر مع خيارات التمهيد المتقدمة؟ هل أنت متأكد أنك تريد تسجيل الخروج؟ + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + إعادة تعيين + Confirm + إلغاء + Please enter a non-empty command keyword + أوامر النظام يوفر أوامر متعلقة بالنظام، مثل إيقاف التشغيل، القفل، الإعدادات، وما إلى ذلك. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/cs.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/cs.xaml index 1a42ce51b..de35c9592 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/cs.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/cs.xaml @@ -2,8 +2,9 @@ - Příkaz + Jméno Popis + Příkaz Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Editovat + Vypnout počítač Restartovat počítač @@ -59,6 +62,15 @@ Opravdu chcete restartovat počítač s rozšířenými možnostmi spouštění? Opravdu se chcete odhlásit? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Potvrdit + Zrušit + Please enter a non-empty command keyword + Systémové příkazy Poskytuje příkazy související se systémem, jako je vypnutí, uzamčení počítače atd. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/da.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/da.xaml index 172adfd2f..91230e7e3 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/da.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/da.xaml @@ -2,8 +2,9 @@ - Command + Name Description + Command Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Rediger + Shutdown Computer Restart Computer @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + Annuller + Please enter a non-empty command keyword + System Commands Provides System related commands. e.g. shutdown, lock, settings etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/de.xaml index cdd0e0348..794e949ad 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/de.xaml @@ -2,8 +2,9 @@ - Befehl + Name Beschreibung + Befehl Herunterfahren Neu starten @@ -25,7 +26,9 @@ Flow Launcher-Tipps Flow Launcher UserData-Ordner Spielmodus umschalten - Set the Flow Launcher Theme + Flow Launcher-Theme festlegen + + Bearbeiten Computer herunterfahren @@ -48,7 +51,7 @@ Besuchen Sie die Dokumentation von Flow Launcher für mehr Hilfe und Tipps zur Verwendung Den Ort öffnen, an dem die Einstellungen von Flow Launcher gespeichert sind Spielmodus umschalten - Quickly change the Flow Launcher theme + Das Flow-Launcher-Theme schnell ändern Erfolg @@ -56,9 +59,18 @@ Alle anwendbaren Plug-in-Daten neu geladen Sind Sie sicher, dass Sie den Computer herunterfahren wollen? Sind Sie sicher, dass Sie den Computer neu starten wollen? - Soll der Computer wirklich mit erweiterten Startoptionen neu gestartet werden? + Sind Sie sicher, dass Sie den Computer mit erweiterten Boot-Optionen neu starten wollen? Sind Sie sicher, dass Sie sich ausloggen wollen? + Befehls-Schlüsselwort-Einstellung + Benutzerdefiniertes Befehls-Schlüsselwort + Geben Sie ein Schlüsselwort ein, um nach dem Befehl zu suchen: {0}. Dieses Schlüsselwort wird verwendet, um Ihre Anfrage abzugleichen. + Befehls-Schlüsselwort + Zurücksetzen + Bestätigen + Abbrechen + Bitte geben Sie ein nicht-leeres Befehls-Schlüsselwort ein + Systembefehle Bietet systembezogene Befehle, z. B. Herunterfahren, Sperren, Einstellungen etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/es-419.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/es-419.xaml index 99eec60fa..ac4040dca 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/es-419.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/es-419.xaml @@ -2,8 +2,9 @@ - Command + Name Description + Command Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Editar + Shutdown Computer Restart Computer @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + Cancelar + Please enter a non-empty command keyword + System Commands Provides System related commands. e.g. shutdown, lock, settings etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/es.xaml index 2139738f7..5f3688ab8 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/es.xaml @@ -2,8 +2,9 @@ - Comando + Nombre Descripción + Comando Apagar Reiniciar @@ -27,6 +28,8 @@ Cambiar a Modo Juego Establecer el tema de Flow Launcher + Editar + Apaga el equipo Reinicia el equipo @@ -59,6 +62,15 @@ ¿Está seguro de que desea reiniciar el equipo con opciones de arranque avanzadas? ¿Está seguro de que desea cerrar la sesión? + Configuración de la palabra clave de comando + Palabra clave de comando personalizada + Introducir una palabra clave para buscar el comando: {0}. Esta palabra clave se utiliza para que coincida con la búsqueda. + Palabra clave de comando + Restablecer + Confirmar + Cancelar + Por favor, introducir una palabra clave de comando no vacía + Comandos del sistema Proporciona comandos relacionados con el sistema. Por ejemplo, apagar, bloquear, configurar, etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/fr.xaml index 727a9a6ad..5419bd8e2 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/fr.xaml @@ -2,8 +2,9 @@ - Commande + Nom Description + Commande Arrêter Redémarrer @@ -27,6 +28,8 @@ Basculer le mode de jeu Définir le thème Flow Launcher + Modifier + Éteindre l'ordinateur Redémarrer l'ordinateur @@ -59,6 +62,15 @@ Êtes-vous sûr de vouloir redémarrer l'ordinateur avec les options de démarrage avancées ? Êtes-vous sûr de vouloir vous déconnecter ? + Réglage du mot-clé de commande + Mot-clé de commande personnalisé + Entrez un mot-clé pour rechercher la commande : {0}. Ce mot-clé est utilisé pour répondre à votre requête. + Mot-clé de commande + Réinitialiser + Confirmer + Annuler + Veuillez saisir un mot-clé de commande non vide + Commandes système Fournit des commandes liées au système. Par exemple, arrêt, verrouillage, paramètres, etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/he.xaml index acc3f3b59..86688a130 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/he.xaml @@ -2,8 +2,9 @@ - פקודה + שם תיאור + פקודה כיבוי הפעלה מחדש @@ -27,6 +28,8 @@ מצב משחק Set the Flow Launcher Theme + ערו + כבה את המחשב הפעל מחדש את המחשב @@ -59,6 +62,15 @@ האם אתה בטוח שברצונך להפעיל מחדש את המחשב עם אפשרויות אתחול מתקדמות? האם אתה בטוח שברצונך להתנתק? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + אפס + אישו + ביטול + Please enter a non-empty command keyword + פקודות מערכת מספק פקודות הקשורות למערכת, כגון כיבוי, נעילה, הגדרות ועוד. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/it.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/it.xaml index b464cab28..be31e4e52 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/it.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/it.xaml @@ -2,8 +2,9 @@ - Comando + Nome Descrizione + Comando Spegni Riavvia @@ -27,6 +28,8 @@ Attiva/Disattiva Modalità Di Gioco Set the Flow Launcher Theme + Modifica + Spegni il computer Riavvia il Computer @@ -59,6 +62,15 @@ Sei sicuro di voler riavviare il computer con le Opzioni di Avvio Avanzate? Sei sicuro di volerti disconettere? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Resetta + Conferma + Annulla + Please enter a non-empty command keyword + Comandi di Sistema Fornisce comandi relativi al sistema, ad esempio spegnimento, blocco, impostazioni ecc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml index cff426d4e..bc7dff59f 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ja.xaml @@ -2,8 +2,9 @@ - コマンド + Name 説明 + コマンド Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + + コンピュータをシャットダウンする コンピュータを再起動する @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + + Please enter a non-empty command keyword + システムコマンド システム関連のコマンドを提供します。例:シャットダウン、ロック、設定など diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ko.xaml index d9b568e14..f2049038f 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ko.xaml @@ -2,8 +2,9 @@ - 명령어 + Name 설명 + 명령어 Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + 편집 + 시스템 종료 시스템 재시작 @@ -59,6 +62,15 @@ 고급 부팅 옵션으로 시스템을 다시 시작하시겠습니까? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + 확인 + 취소 + Please enter a non-empty command keyword + 시스템 명령어 시스템 종료, 컴퓨터 잠금, 설정 등과 같은 시스템 관련 명령어를 제공합니다 diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/nb.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/nb.xaml index a531189fe..072fd623d 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/nb.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/nb.xaml @@ -2,8 +2,9 @@ - Kommando + Navn Beskrivelse + Kommando Slå av Start på nytt @@ -27,6 +28,8 @@ Vis/Skjul spillmodus Set the Flow Launcher Theme + Rediger + Slår av datamaskin Start datamaskinen på nytt @@ -59,6 +62,15 @@ Er du sikker på at du vil starte datamaskinen på nytt med avanserte oppstartsalternativer? Er du sikker på at du vil logge av? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Tilbakestill + Bekreft + Avbryt + Please enter a non-empty command keyword + Systemkommandoer Gir systemrelaterte kommandoer, f.eks. slå av, lås, innstillinger osv. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml index e0e4d46a8..9d1d54076 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/nl.xaml @@ -2,8 +2,9 @@ - Opdracht + Name Beschrijving + Opdracht Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Bewerken + Computer afsluiten Computer opnieuw opstarten @@ -59,6 +62,15 @@ Weet u zeker dat u de computer wilt herstarten met geavanceerde opstartopties? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Herstellen + Confirm + Annuleer + Please enter a non-empty command keyword + Systeemopdrachten Voorziet in systeem gerelateerde opdrachten. bijv.: afsluiten, vergrendelen, instellingen, enz. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pl.xaml index bbb3bec88..c09a447d2 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pl.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pl.xaml @@ -2,8 +2,9 @@ - Komenda + Nazwa Opis + Komenda Wyłącz komputer Restart @@ -27,6 +28,8 @@ Przełącz tryb gry Set the Flow Launcher Theme + Edytuj + Wyłącz komputer Uruchom ponownie komputer @@ -59,6 +62,15 @@ Czy na pewno chcesz ponownie uruchomić komputer z Zaawansowanymi opcjami rozruchu? Czy na pewno chcesz się wylogować? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Zresetuj + Potwierdź + Anuluj + Please enter a non-empty command keyword + Komendy systemowe Wykonywanie komend systemowych, np. wyłącz, zablokuj komputer, otwórz ustawienia itp. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-br.xaml index b356f6bc7..a19ab39d6 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-br.xaml @@ -2,8 +2,9 @@ - Comando + Nome Descrição + Comando Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Editar + Desligar o Computador Reiniciar o Computador @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + Cancelar + Please enter a non-empty command keyword + System Commands Provides System related commands. e.g. shutdown, lock, settings etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-pt.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-pt.xaml index aa7217c01..9e0e39066 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-pt.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/pt-pt.xaml @@ -2,8 +2,9 @@ - Comando + Nome Descrição + Comando Desligar Reiniciar @@ -25,7 +26,9 @@ Dicas Flow Launcher Pasta de dados do utilizador Flow Launcher Comutar modo de jogo - Set the Flow Launcher Theme + Definir tema Flow Launcher + + Editar Desligar computador @@ -48,7 +51,7 @@ Aceda à documentação para mais informações e dicas de utilização Abrir localização onde as definições do Flow Launcher estão guardadas Comutar modo de jogo - Quickly change the Flow Launcher theme + Alterar rapidamente o tema da aplicação Sucesso @@ -59,6 +62,15 @@ Tem certeza de que deseja reiniciar o computador com as opções avançadas de arranque? Tem certeza de que deseja terminar a sessão? + Definição de palavra-chave + Palavra-chave personalizada + Indique a palavra-chave para pesquisar o comando: {0}. A aplavra-chave será usada para correspondência com a consulta. + Palavra-chave + Repor + Confirmar + Cancelar + Não pode indicar uma palavra-chave vazia + Comandos do sistema Disponibiliza os comandos relacionados com o sistema tais como: desligar, bloquear, reiniciar... diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml index 4547274f8..796cda69d 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/ru.xaml @@ -2,8 +2,9 @@ - Command + Name Description + Command Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Редактировать + Shutdown Computer Restart Computer @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + Отменить + Please enter a non-empty command keyword + System Commands Provides System related commands. e.g. shutdown, lock, settings etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/sk.xaml index 0f8894288..087ff9f05 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/sk.xaml @@ -2,8 +2,9 @@ - Príkaz + Názov Popis + Príkaz Vypnúť Reštartovať @@ -27,6 +28,8 @@ Prepnúť herný režim Nastaviť motív pre Flow Laucher + Upraviť + Vypnúť počítač Reštartovať počítač @@ -59,6 +62,15 @@ Naozaj chcete počítač reštartovať s pokročilými možnosťami spúšťania? Naozaj sa chcete odhlásiť? + Nastavenia kľúčového slova príkazu + Vlastné kľúčové slovo príkazu + Na vyhľadanie príkazu zadajte kľúčové slovo: {0}. Toto kľúčové slovo sa použije na vyhľadnie príkazu. + Kľúčové slovo príkazu + Resetovať + Potvrdiť + Zrušiť + Prosím, zadajte neprázdne kľúčové slovo príkazu + Systémové príkazy Poskytuje príkazy súvisiace so systémom ako je vypnutie, uzamknutie počítača atď. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/sr.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/sr.xaml index d04a783d0..f5a2f1b30 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/sr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/sr.xaml @@ -2,8 +2,9 @@ - Command + Name Description + Command Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Izmeni + Shutdown Computer Restart Computer @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + Confirm + Otkaži + Please enter a non-empty command keyword + System Commands Provides System related commands. e.g. shutdown, lock, settings etc. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/tr.xaml index 93973913f..18f7f63f5 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/tr.xaml @@ -2,8 +2,9 @@ - Komut + Name Açıklama + Komut Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Düzenle + Bilgisayarı Kapat Yeniden Başlat @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Sıfırla + Onayla + İptal + Please enter a non-empty command keyword + Sistem Komutları Sistem ile ilgili komutlara erişim sağlar. ör. shutdown, lock, settings vb. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml index 57c83e1a5..19d69511b 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/uk-UA.xaml @@ -2,8 +2,9 @@ - Команда + Назва Опис + Команда Вимкнути Перезавантажити @@ -27,6 +28,8 @@ Перемкнути режим гри Set the Flow Launcher Theme + Редагувати + Вимкнути комп'ютер Перезавантажити комп'ютер @@ -59,6 +62,15 @@ Ви впевнені, що хочете перезавантажити комп'ютер за допомогою додаткових параметрів завантаження? Ви впевнені, що хочете вийти з системи? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Скинути + Підтвердити + Скасувати + Please enter a non-empty command keyword + Системні команди Надає команди, пов'язані з системою, наприклад, вимкнення, блокування, налаштування тощо. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/vi.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/vi.xaml index 8d0bc43c0..dae12c501 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/vi.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/vi.xaml @@ -2,8 +2,9 @@ - Lệnh + Tên Mô Tả + Lệnh Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + Sửa + shutdown máy tính Khởi động lại máy tính @@ -59,6 +62,15 @@ Bạn có chắc chắn muốn khởi động lại máy tính bằng Advanced Boot Options không? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Đặt lại + Xác nhận + Hủy + Please enter a non-empty command keyword + Lệnh hệ thống Cung cấp các lệnh liên quan đến Hệ thống. ví dụ. tắt máy, khóa, cài đặt, v.v. diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-cn.xaml index e08f312b1..745129130 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-cn.xaml @@ -2,8 +2,9 @@ - 命令 + 名称 描述 + 命令 关机 重启 @@ -27,6 +28,8 @@ 切换游戏模式 Set the Flow Launcher Theme + 编辑 + 关闭电脑 重启这台电脑 @@ -59,6 +62,15 @@ 您确定要以高级启动选项重启吗? 您确定要注销吗? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + 重置 + 确认 + 取消 + Please enter a non-empty command keyword + 系统命令 提供操作系统相关的命令,如关机、锁定、设置等。 diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml index d43496466..573aefcbd 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/zh-tw.xaml @@ -2,8 +2,9 @@ - 命令 + 名稱 描述 + 命令 Shutdown Restart @@ -27,6 +28,8 @@ Toggle Game Mode Set the Flow Launcher Theme + 編輯 + 電腦關機 電腦重新啟動 @@ -59,6 +62,15 @@ Are you sure you want to restart the computer with Advanced Boot Options? Are you sure you want to log off? + Command Keyword Setting + Custom Command Keyword + Enter a keyword to search for command: {0}. This keyword is used to match your query. + Command Keyword + Reset + 確認 + 取消 + Please enter a non-empty command keyword + 系統命令 系統相關的命令。例如,關機,鎖定,設定等 diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ar.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ar.xaml index 6e92178db..cefb5d1d1 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ar.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ar.xaml @@ -17,7 +17,7 @@ كلمة مفتاحية للعمل الرابط بحث - استخدام الإكمال التلقائي لاستعلام البحث: + Use Search Query Autocomplete بيانات الإكمال التلقائي من: يرجى اختيار بحث على الويب هل أنت متأكد أنك تريد حذف {0}؟ diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/cs.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/cs.xaml index 849f27f05..ca98581c3 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/cs.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/cs.xaml @@ -17,7 +17,7 @@ Aktivační příkaz URL Hledat - Používejte automatické dokončování vyhledávaných výrazů: + Use Search Query Autocomplete Automatické doplnění údajů z: Vyberte webové vyhledávání Opravdu chcete odstranit {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/da.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/da.xaml index 2a7d4aa32..b1113acb7 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/da.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/da.xaml @@ -17,7 +17,7 @@ Action Keyword URL Search - Use Search Query Autocomplete: + Use Search Query Autocomplete Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml index 0c72b11bf..2a7dca596 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/de.xaml @@ -17,8 +17,8 @@ Aktions-Schlüsselwort URL Suche - Autovervollständigung von Suchanfragen verwenden: - Daten automatisch vervollständigen aus: + Autovervollständigung von Suchanfragen verwenden + Autovervollständigung der Daten aus: Bitte wählen Sie eine Websuche aus Sind Sie sicher, dass Sie {0} löschen wollen? Wenn Sie Flow eine Suche nach einer bestimmten Website hinzufügen möchten, geben Sie zunächst eine Dummy-Textzeichenfolge in die Suchleiste dieser Website ein und starten Sie die Suche. Kopieren Sie jetzt den Inhalt der Adressleiste des Browsers und fügen Sie ihn in das URL-Feld unten ein. Ersetzen Sie Ihre Testzeichenfolge durch {q}. Zum Beispiel, wenn Sie auf Netflix nach casino suchen, steht in der Adressleiste @@ -30,8 +30,8 @@ https://www.netflix.com/search?q={q} - Copy URL - Copy search URL to clipboard + URL kopieren + Such-URL in Zwischenablage kopieren Titel diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es-419.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es-419.xaml index 517ac0918..3ce22bb78 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es-419.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es-419.xaml @@ -17,7 +17,7 @@ Palabra clave URL Buscar - Autocompletar la búsqueda: + Use Search Query Autocomplete Autocompletar datos de: Por favor, seleccione una búsqueda ¿Seguro que desea eliminar {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml index e6e4a94d2..7f14b59c6 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/es.xaml @@ -17,7 +17,7 @@ Palabra clave de acción URL Busca en - Usar autocompletado en consultas de búsqueda: + Usar autocompletado en consultas de búsqueda Autocompletar datos desde: Por favor, seleccione una búsqueda web ¿Está seguro de que desea eliminar {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml index c6b1b145c..f04cfb48a 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/fr.xaml @@ -17,7 +17,7 @@ Mot-clé d'action URL Rechercher sur - Utiliser la saisie automatique de la requête de recherche : + Utiliser la fonction d'auto-complétion des requêtes de recherche Saisir automatiquement les données à partir de : Veuillez sélectionner une recherche web Êtes-vous sûr de vouloir supprimer {0} ? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/he.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/he.xaml index 630287983..78ee7ca7d 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/he.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/he.xaml @@ -17,7 +17,7 @@ מילת מפתח לפעולה כתובת URL חיפו - השתמש בהשלמה אוטומטית לשאילתות חיפוש: + השתמש בהשלמה אוטומטית לשאילתת חיפוש השלמה אוטומטית מתוך: בחר שירות חיפוש אינטרנטי האם אתה בטוח שברצונך למחוק את {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/it.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/it.xaml index 26c1e8459..db2a4dfeb 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/it.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/it.xaml @@ -17,7 +17,7 @@ Parola Chiave URL Cerca - Usa Autocompletamento Ricerca: + Use Search Query Autocomplete Autocompleta i dati da: Seleziona una ricerca web Sei sicuro di voler eliminare {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml index 85ce0e282..9ae628853 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ja.xaml @@ -17,7 +17,7 @@ キーワード URL 検索 - 検索サジェスチョンを有効にする + Use Search Query Autocomplete Autocomplete Data from: web検索を選択してください Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ko.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ko.xaml index 5ab5fffa3..3ac9f6a6c 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ko.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ko.xaml @@ -17,7 +17,7 @@ 액션 키워드 URL 검색 - 검색 쿼리 자동완성 사용: + Use Search Query Autocomplete 자동완성 데이터 출처: 웹 검색을 선택하세요 Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nb.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nb.xaml index 4bba382a9..9f793c43f 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nb.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nb.xaml @@ -17,7 +17,7 @@ Nøkkelord for handling Nettadresse Søk - Bruk autofullføring av søkespørring: + Use Search Query Autocomplete Autofullfør data fra: Vennligst velg et websøk Er du sikker på at du ønsker å slette {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nl.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nl.xaml index a48d99487..a18710324 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nl.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/nl.xaml @@ -17,7 +17,7 @@ Action Keyword URL Search - Use Search Query Autocomplete: + Use Search Query Autocomplete Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pl.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pl.xaml index 499351343..d693a3f28 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pl.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pl.xaml @@ -17,7 +17,7 @@ Wyzwalacz Adres URL Szukaj - Pokazuj podpowiedzi wyszukiwania + Use Search Query Autocomplete Autouzupełnianie danych z: Musisz wybrać coś z listy Czy jesteś pewien że chcesz usunąć {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml index d4135c795..6f0d7fcc9 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-br.xaml @@ -17,7 +17,7 @@ Action Keyword URL Search - Use Search Query Autocomplete: + Use Search Query Autocomplete Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-pt.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-pt.xaml index 16969dac7..1a2476a2c 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-pt.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/pt-pt.xaml @@ -17,7 +17,7 @@ Palavra-chave de ação URL Pesquisar - Utilizar conclusão automática da consulta: + Utilizar conclusão automática para as consultas Preencher dados a partir de: Selecione uma pesquisa web Tem a certeza de que deseja eliminar {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml index c59182290..1fd9aca96 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/ru.xaml @@ -1,4 +1,4 @@ - + Search Source Setting @@ -17,7 +17,7 @@ Action Keyword URL Search - Use Search Query Autocomplete: + Use Search Query Autocomplete Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? @@ -28,8 +28,9 @@ Then replace casino with {q}. Thus, the generic formula for a search on Netflix is https://www.netflix.com/search?q={q} - Скопировать URL-адрес - Скопировать URL поиска в буфер обмена + + Copy URL + Copy search URL to clipboard Title diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sk.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sk.xaml index 44b765c58..1afcdb360 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sk.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sk.xaml @@ -17,7 +17,7 @@ Aktivačný príkaz Adresa URL Hľadať - Použiť automatické dokončovanie výrazov vyhľadávania: + Použiť automatické dokončovanie výrazov vyhľadávania Automatické dokončovanie údajov z: Vyberte webové vyhľadávanie Naozaj chcete odstrániť {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sr.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sr.xaml index 5f1803655..06707b4af 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sr.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/sr.xaml @@ -17,7 +17,7 @@ Action Keyword URL Search - Use Search Query Autocomplete: + Use Search Query Autocomplete Autocomplete Data from: Please select a web search Are you sure you want to delete {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml index 1506b753b..aaad035a0 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/tr.xaml @@ -17,7 +17,7 @@ Anahtar Kelime URL Ara: - Arama önerilerini etkinleştir + Use Search Query Autocomplete Autocomplete Data from: Lütfen bir web araması seçin {0} bağlantısını silmek istediğinize emin misiniz? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml index beb085d28..5536a7e68 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/uk-UA.xaml @@ -17,7 +17,7 @@ Ключове слово дії URL Пошук - Використовувати автозаповнення пошукового запиту: + Use Search Query Autocomplete Автозаповнення даних з: Будь ласка, виберіть пошуковий запит в Інтернеті Ви впевнені, що хочете видалити {0}? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/vi.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/vi.xaml index e3105283f..731275c5e 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/vi.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/vi.xaml @@ -17,7 +17,7 @@ Từ khóa hành động Địa chỉ URL Tìm kiếm - Sử dụng Tự động hoàn thành truy vấn tìm kiếm: + Use Search Query Autocomplete Tự động hoàn thành dữ liệu từ: Vui lòng chọn tìm kiếm trên web Bạn có chắc chắn muốn xóa {0} không? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-cn.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-cn.xaml index d3df223cc..375a741d0 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-cn.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-cn.xaml @@ -17,7 +17,7 @@ 触发关键字 打开链接 搜索 - 启用搜索建议 + Use Search Query Autocomplete 自动补全数据: 请选择一项 您确定要删除 {0} 吗? diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-tw.xaml b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-tw.xaml index eb58a4ec0..727b2f4a9 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-tw.xaml +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Languages/zh-tw.xaml @@ -17,7 +17,7 @@ 觸發關鍵字 網址 搜尋 - 啟用搜尋建議 + Use Search Query Autocomplete 從以下位置自動填入資料: 請選擇一項 你確認要刪除{0}嗎 diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.de-DE.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.de-DE.resx index dcc74d520..5f8d9a6df 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.de-DE.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.de-DE.resx @@ -275,7 +275,7 @@ Hardware und Sound - Startseite + Homepage Mixed Reality @@ -2161,7 +2161,7 @@ Erweiterte Druckereinrichtung - Change default printer + Standard-Drucker ändern Edit environment variables for your account @@ -2416,7 +2416,7 @@ Erweiterte Sharing-Einstellungen verwalten - Change battery settings + Akku-Einstellungen ändern Diesen Computer umbenennen @@ -2479,7 +2479,7 @@ Find and fix bluescreen problems - Hear a tone when keys are pressed + Einen Ton hören, wenn Tasten gedrückt werden Browsing-Historie löschen diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.he-IL.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.he-IL.resx index 55ac42dd3..faa8c2dcc 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.he-IL.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.he-IL.resx @@ -432,7 +432,7 @@ Area Personalization - Client service for NetWare + שירות לקוח עבור NetWare Area Control Panel (legacy settings) diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ko-KR.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ko-KR.resx index c7c1854b7..ab69a2a31 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ko-KR.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.ko-KR.resx @@ -1203,7 +1203,7 @@ Area Gaming - Windows 설정을 검색하는 플러그 인 + Windows 설정을 검색하는 플러그인 Windows Settings diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.pt-PT.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.pt-PT.resx index e7f8e1683..39062bbb8 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.pt-PT.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.pt-PT.resx @@ -1797,13 +1797,13 @@ Mostrar ficheiros e pastas ocultas - Change Windows To Go start-up options + Mudar as configurações de início do Windows Portátil - See which processes start up automatically when you start Windows + Veja quais processos se iniciam automaticamente quando o Windows inicia - Tell if an RSS feed is available on a website + Informar se um feed RSS está disponível em um site Adicionar relógios para diferentes fusos horários @@ -1815,7 +1815,7 @@ Personalizar botões do rato - Set tablet buttons to perform certain tasks + Definir botões do tablet para executar certas tarefas Ver tipos de letra instalados @@ -1869,13 +1869,13 @@ Ver digitalizadores e câmaras - Microsoft IME Register Word (Japanese) + Registro do Word Microsoft IME (japonês) Restaurar ficheiros com o Histórico de ficheiros - Turn On-Screen keyboard on or off + Ativar ou desativar o teclado na tela Bloquear ou permitir cookies de terceiros @@ -1887,7 +1887,7 @@ Criar uma unidade de recuperação - Microsoft New Phonetic Settings + Configurações do Microsoft New Phonetic Gerer relatório de saúde do sistema @@ -1899,16 +1899,16 @@ Cópia de segurança e restauro (Windows 7) - Preview, delete, show or hide fonts + Pré-visualizar, excluir, mostrar ou ocultar fontes - Microsoft Quick Settings + Configurações Rápidas da Microsoft Ver histórico de fiabilidade - Access RemoteApp and desktops + Acessar o RemoteApp e desktops Configurar fontes de dados ODBC @@ -1926,7 +1926,7 @@ Opções SimpleFast do Microsoft Pinyin - Change what closing the lid does + Mudar o que fechar a tampa faz Desativar animações desnecessárias @@ -1947,7 +1947,7 @@ Ver ações recomendadas para manter o sistema a funcionar nas melhores condições - Alterar a frequência de piscar do cursor + Alterar frequência de intermitência do cursor Adicionar ou remover programas @@ -1959,13 +1959,13 @@ Configurar propriedades avançadas do perfil de utilizador - Start or stop using AutoPlay for all media and devices + Inicie ou pare de usar o AutoPlay para todas as mídias e dispositivos Alterar definições de manutenção automática - Specify single- or double-click to open + Especificar se um clique ou dois são necessários para abrir Utilizadores que podem utilizar o ambiente de trabalho remoto @@ -1995,13 +1995,13 @@ Analisar estado do teclado - Control the computer without the mouse or keyboard + Controle o computador sem o mouse ou teclado Alterar ou remover um programa - Change multi-touch gesture settings + Alterar configurações de gestos multi-toque Configurar origens ODBC (64 bits) @@ -2013,13 +2013,13 @@ Alterar página inicial - Group similar windows on the taskbar + Agrupar janelas semelhantes na barra de tarefas - Change Windows SideShow settings + Alterar configurações do Windows SideShow - Use audio description for video + Usar descrição de áudio para vídeos Alterar nome do grupo de trabalho @@ -2028,13 +2028,13 @@ Encontrar e corrigir problemas de impressão - Change when the computer sleeps + Mudar quando o computador dorme Configurar uma rede privada (VPN) - Accommodate learning abilities + Acomodar habilidades de aprendizagem Configurar uma ligação telefónica @@ -2046,7 +2046,7 @@ Como alterar a palavra-passe do Windows - Tornar mais fácil ver o ponteiro do rato + Tornar mais fácil de ver o ponteiro do mouse Configurar o iniciador iSCSI @@ -2067,7 +2067,7 @@ Substituir sons por pistas visuais - Change temporary Internet file settings + Alterar configurações de arquivo de Internet temporárias Estabelecer ligação à Internet @@ -2085,16 +2085,16 @@ Guardar cópias de segurança dos ficheiros no Histórico de Ficheiros - View current accessibility settings + Ver configurações de acessibilidade atuais - Change tablet pen settings + Alterar configurações da caneta Alterar modo de funcionamento do rato - Show how much RAM is on this computer + Mostrar quanta memória RAM este computador tem Editar plano de energia @@ -2115,7 +2115,7 @@ Ampliar partes do ecrão com o Magnificador - Change the file type associated with a file extension + Alterar o tipo de arquivo associado a uma extensão de arquivo Ver registo de eventos @@ -2133,17 +2133,17 @@ Alterar definições de poupança de energia - Optimise for blindness + Otimizar para cegueira - Turn Windows features on or off + Ative ou desative os recursos do Windows - Show which operating system your computer is running + Mostra qual sistema operacional o seu computador está executando Ver serviços locais @@ -2152,7 +2152,7 @@ Gerir pastas de trabalho - Encrypt your offline files + Criptografe seus arquivos offline Treinar o computador para reconhecer a sua voz @@ -2173,43 +2173,43 @@ Alterar definições ddo clique do rato - Change advanced colour management settings for displays, scanners and printers + Alterar configurações avançadas de gerenciamento de cores para telas, scanners e impressoras - Let Windows suggest Ease of Access settings + Permitir que o Windows sugira Facilidade de Acesso - Clear disk space by deleting unnecessary files + Limpar espaço em disco excluindo arquivos desnecessários Ver dispositivos e impressoras - Private Character Editor + Editor de Caracteres Privados - Record steps to reproduce a problem + Registrar as etapas para reproduzir um problema - Adjust the appearance and performance of Windows + Ajustar a aparência e o desempenho do Windows - Settings for Microsoft IME (Japanese) + Configurações para o Microsoft IME (japonês) - Invite someone to connect to your PC and help you, or offer to help someone else + Convide alguém para se conectar ao seu PC e ajudá-lo, ou ofereça para ajudar outra pessoa - Run programs made for previous versions of Windows + Execute programas feitos para versões anteriores do Windows - Choose the order of how your screen rotates + Escolha a ordem de como a tela gira - Change how Windows searches + Alterar como o Windows pesquisa - Set flicks to perform certain tasks + Defina gestos para realizar certas ações Alterar tipo de conta @@ -2221,64 +2221,64 @@ Alterar Configurações de Controlo da Conta do Utilizador - Turn on easy access keys + Ativar teclas de acesso fácil - Identify and repair network problems + Identificar e reparar problemas de rede - Find and fix networking and connection problems + Encontrar e corrigir problemas de rede e conexão - Play CDs or other media automatically + Reproduzir CDs ou outras mídias automaticamente - View basic information about your computer + Ver informações básicas sobre seu computador - Choose how you open links + Escolha como abrir os links - Allow Remote Assistance invitations to be sent from this computer + Permitir que convites de assistência remota sejam enviados a partir deste computador Gestor de tarefas - Turn flicks on or off + Ativar ou desativar gestos Adicionar um idioma - View network status and tasks + Ver status de rede e tarefas - Turn Magnifier on or off + Ativar ou desativar a lupa - See the name of this computer + Ver o nome deste computador Ver ligações de rede - Perform recommended maintenance tasks automatically + Executar tarefas recomendadas de manutenção automaticamente - Manage disk space used by your offline files + Gerir espaço de disco utilizado pelos ficheiros locais - Turn High Contrast on or off + Ativar ou desativar modo de alto contraste - Change the way time is displayed + Alterar modo de exibição da hora - Change how web pages are displayed in tabs + Alterar modo de exibição das páginas web nos separadores - Change the way dates and lists are displayed + Alterar modo de exibição das datas e das listas Gerir dispositivos de áudio @@ -2293,37 +2293,37 @@ Apagar cookies ou ficheiros temporários - Specify which hand you write with + Especificar a mão com a qual escreve - Change touch input settings + Alterar definições do painel de toque - How to change the size of virtual memory + Como alterar tamanho da memória virtual - Hear text read aloud with Narrator + Utilizar Narrador para ouvir os textos - Set up USB game controllers + Configurar controladores de jogos USB - Show which domain your computer is on + Mostrar o domínio ao qual o computador pertence - View all problem reports + Ver todos os relatórios de erro - 16-Bit Application Support + Suporte a aplicações 16-bit - Set up dialling rules + Configurar regras de marcação Ativar ou desativar cookies da sessão - Give administrative rights to a domain user + Conceder direitos de administrador a um domínio Choose when to turn off display diff --git a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx index f47b9ada3..5b4dea6a9 100644 --- a/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx +++ b/Plugins/Flow.Launcher.Plugin.WindowsSettings/Properties/Resources.sk-SK.resx @@ -118,7 +118,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - O aplikácii + O systéme Area System From 24d43ed84bc29edd373ea1a513f4ef740828cce5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:46:02 +0800 Subject: [PATCH 0755/1798] Use api functions in Program plugin --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index a50868b69..f03040d68 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Controls; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.Program.Programs; using Flow.Launcher.Plugin.Program.Views; @@ -14,7 +13,6 @@ using Flow.Launcher.Plugin.Program.Views.Models; using Flow.Launcher.Plugin.SharedCommands; using Microsoft.Extensions.Caching.Memory; using Path = System.IO.Path; -using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher.Plugin.Program { @@ -32,6 +30,8 @@ namespace Flow.Launcher.Plugin.Program internal static PluginInitContext Context { get; private set; } + private static readonly string ClassName = nameof(Main); + private static readonly List emptyResults = new(); private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; @@ -109,7 +109,7 @@ namespace Flow.Launcher.Plugin.Program } catch (OperationCanceledException) { - Log.Debug("|Flow.Launcher.Plugin.Program.Main|Query operation cancelled"); + Context.API.LogDebug(ClassName, "Query operation cancelled"); return emptyResults; } finally @@ -188,7 +188,7 @@ namespace Flow.Launcher.Plugin.Program var _win32sCount = 0; var _uwpsCount = 0; - await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Preload programs cost", async () => + await Context.API.StopwatchLogInfoAsync(ClassName, "Preload programs cost", async () => { var pluginCacheDirectory = Context.CurrentPluginMetadata.PluginCacheDirectoryPath; FilesFolders.ValidateDirectory(pluginCacheDirectory); @@ -253,8 +253,8 @@ namespace Flow.Launcher.Plugin.Program _uwpsCount = _uwps.Count; _uwpsLock.Release(); }); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32sCount}>"); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwpsCount}>"); + Context.API.LogInfo(ClassName, $"Number of preload win32 programs <{_win32sCount}>"); + Context.API.LogInfo(ClassName, $"Number of preload uwps <{_uwpsCount}>"); var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0; @@ -295,7 +295,7 @@ namespace Flow.Launcher.Plugin.Program } catch (Exception e) { - Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Win32 programs", e); + Context.API.LogException(ClassName, "Failed to index Win32 programs", e); } finally { @@ -320,7 +320,7 @@ namespace Flow.Launcher.Plugin.Program } catch (Exception e) { - Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Uwp programs", e); + Context.API.LogException(ClassName, "Failed to index Uwp programs", e); } finally { @@ -332,12 +332,12 @@ namespace Flow.Launcher.Plugin.Program { var win32Task = Task.Run(async () => { - await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexWin32ProgramsAsync); + await Context.API.StopwatchLogInfoAsync(ClassName, "Win32Program index cost", IndexWin32ProgramsAsync); }); var uwpTask = Task.Run(async () => { - await Stopwatch.NormalAsync("|Flow.Launcher.Plugin.Program.Main|UWPProgram index cost", IndexUwpProgramsAsync); + await Context.API.StopwatchLogInfoAsync(ClassName, "UWPProgram index cost", IndexUwpProgramsAsync); }); await Task.WhenAll(win32Task, uwpTask).ConfigureAwait(false); From 1af9d061f741735b015b880c754bfc5ef9226bb7 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 8 Apr 2025 21:53:00 +0800 Subject: [PATCH 0756/1798] Use api functions in other places --- Flow.Launcher.Core/Plugin/PluginManager.cs | 6 ++++-- Flow.Launcher.Core/Plugin/PluginsLoader.cs | 10 +++++++--- Flow.Launcher/App.xaml.cs | 7 ++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 0ee268f5c..4c85fb061 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -23,6 +23,8 @@ namespace Flow.Launcher.Core.Plugin /// public static class PluginManager { + private static readonly string ClassName = nameof(PluginManager); + private static IEnumerable _contextMenuPlugins; public static List AllPlugins { get; private set; } @@ -194,7 +196,7 @@ namespace Flow.Launcher.Core.Plugin { try { - var milliseconds = await Stopwatch.DebugAsync($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", + var milliseconds = await API.StopwatchLogDebugAsync(ClassName, $"Init method time cost for <{pair.Metadata.Name}>", () => pair.Plugin.InitAsync(new PluginInitContext(pair.Metadata, API))); pair.Metadata.InitTime += milliseconds; @@ -266,7 +268,7 @@ namespace Flow.Launcher.Core.Plugin try { - var milliseconds = await Stopwatch.DebugAsync($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", + var milliseconds = await API.StopwatchLogDebugAsync(ClassName, $"Cost for {metadata.Name}", async () => results = await pair.Plugin.QueryAsync(query, token).ConfigureAwait(false)); token.ThrowIfCancellationRequested(); diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs index 495a4c1ab..1010d9f08 100644 --- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs @@ -11,12 +11,17 @@ using Flow.Launcher.Infrastructure.Logger; #pragma warning restore IDE0005 using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; -using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher.Core.Plugin { public static class PluginsLoader { + private static readonly string ClassName = nameof(PluginsLoader); + + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + public static List Plugins(List metadatas, PluginsSettings settings) { var dotnetPlugins = DotNetPlugins(metadatas); @@ -59,8 +64,7 @@ namespace Flow.Launcher.Core.Plugin foreach (var metadata in metadatas) { - var milliseconds = Stopwatch.Debug( - $"|PluginsLoader.DotNetPlugins|Constructor init cost for {metadata.Name}", () => + var milliseconds = API.StopwatchLogDebug(ClassName, $"Constructor init cost for {metadata.Name}", () => { Assembly assembly = null; IAsyncPlugin plugin = null; diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 81938612c..90fefe0a6 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -21,7 +21,6 @@ using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch; namespace Flow.Launcher { @@ -35,6 +34,8 @@ namespace Flow.Launcher #region Private Fields + private static readonly string ClassName = nameof(App); + private static bool _disposed; private MainWindow _mainWindow; private readonly MainViewModel _mainVM; @@ -136,7 +137,7 @@ namespace Flow.Launcher private async void OnStartup(object sender, StartupEventArgs e) { - await Stopwatch.NormalAsync("|App.OnStartup|Startup cost", async () => + await API.StopwatchLogInfoAsync(ClassName, "Startup cost", async () => { // Because new message box api uses MessageBoxEx window, // if it is created and closed before main window is created, it will cause the application to exit. @@ -313,7 +314,7 @@ namespace Flow.Launcher _disposed = true; } - Stopwatch.Normal("|App.Dispose|Dispose cost", () => + API.StopwatchLogInfo(ClassName, "Dispose cost", () => { Log.Info("|App.Dispose|Begin Flow Launcher dispose ----------------------------------------------------"); From 47743e6362469684e432b790649b419b96d0d543 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 09:31:02 +0800 Subject: [PATCH 0757/1798] Set max result lower limit to 1 --- .../ViewModels/SettingsViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index d2b85e687..407300924 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -524,7 +524,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels } } - public int MaxResultLowerLimit => 100; + public int MaxResultLowerLimit => 1; public int MaxResultUpperLimit => 100000; public int MaxResult From 49dc657becdac6f23f66c3ee4060165ff5b9838e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:12:32 +0800 Subject: [PATCH 0758/1798] Fix build issue --- Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index 5dec8b953..3eb74dd74 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Controls; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.BrowserBookmark.Commands; using Flow.Launcher.Plugin.BrowserBookmark.Models; using Flow.Launcher.Plugin.BrowserBookmark.Views; @@ -10,6 +9,7 @@ using System.IO; using System.Threading.Channels; using System.Threading.Tasks; using System.Threading; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Plugin.BrowserBookmark; @@ -35,7 +35,7 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex _context.CurrentPluginMetadata.PluginCacheDirectoryPath, "FaviconCache"); - Helper.ValidateDirectory(_faviconCacheDir); + FilesFolders.ValidateDirectory(_faviconCacheDir); LoadBookmarksIfEnabled(); } From 9c07989edf4f42766922317b639e710ec33d6e35 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:14:07 +0800 Subject: [PATCH 0759/1798] Improve code quality --- .../ChromiumBookmarkLoader.cs | 4 +- .../ContextMenu.cs | 21 +++----- .../DirectoryInfo/DirectoryInfoSearch.cs | 7 ++- .../Search/WindowsIndex/WindowsIndex.cs | 8 +-- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 13 ++--- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 49 ++++++++++--------- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 7 +-- 7 files changed, 51 insertions(+), 58 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 282876472..27bcbd9a9 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -2,7 +2,6 @@ using System.IO; using System.Text.Json; using System; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.BrowserBookmark.Models; using Microsoft.Data.Sqlite; @@ -116,8 +115,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader } else { - Log.Error( - $"ChromiumBookmarkLoader: EnumerateFolderBookmark: type property not found for {subElement.GetString()}"); + Main._context.API.LogError(ClassName, $"type property not found for {subElement.GetString()}"); } } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs index 3f3b7cb58..f6de65e90 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs @@ -2,13 +2,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using System.Threading.Tasks; using System.Windows; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Plugin.Explorer.Search; using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; -using System.Linq; using Flow.Launcher.Plugin.Explorer.Helper; using Flow.Launcher.Plugin.Explorer.ViewModels; @@ -470,22 +469,16 @@ namespace Flow.Launcher.Plugin.Explorer private void LogException(string message, Exception e) { - Log.Exception($"|Flow.Launcher.Plugin.Folder.ContextMenu|{message}", e); + Context.API.LogException(nameof(Main), message, e); } - private bool CanRunAsDifferentUser(string path) + private static bool CanRunAsDifferentUser(string path) { - switch (Path.GetExtension(path)) + return Path.GetExtension(path) switch { - case ".exe": - case ".bat": - case ".msi": - return true; - - default: - return false; - - } + ".exe" or ".bat" or ".msi" => true, + _ => false, + }; } } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs index 9fd495f49..1a0d3bd15 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/DirectoryInfo/DirectoryInfoSearch.cs @@ -1,10 +1,9 @@ -using Flow.Launcher.Infrastructure.Logger; -using Flow.Launcher.Plugin.SharedCommands; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; +using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo { @@ -76,7 +75,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo } catch (Exception e) { - Log.Exception(nameof(DirectoryInfoSearch), "Error occurred while searching path", e); + Main.Context.API.LogException(nameof(DirectoryInfoSearch), "Error occurred while searching path", e); throw; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs index 66230937c..2aeb421e0 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs @@ -1,6 +1,4 @@ -using Flow.Launcher.Infrastructure.Logger; -using Microsoft.Search.Interop; -using System; +using System; using System.Collections.Generic; using System.Data.OleDb; using System.Linq; @@ -9,11 +7,13 @@ using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Threading; using Flow.Launcher.Plugin.Explorer.Exceptions; +using Microsoft.Search.Interop; namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex { internal static class WindowsIndex { + private static readonly string ClassName = nameof(WindowsIndex); // Reserved keywords in oleDB private static Regex _reservedPatternMatcher = new(@"^[`\@\@\#\#\*\^,\&\&\/\\\$\%_;\[\]]+$", RegexOptions.Compiled); @@ -33,7 +33,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex } catch (OleDbException e) { - Log.Exception($"|WindowsIndex.ExecuteWindowsIndexSearchAsync|Failed to execute windows index search query: {indexQueryString}", e); + Main.Context.API.LogException(ClassName, $"Failed to execute windows index search query: {indexQueryString}", e); yield break; } await using var dataReader = dataReaderAttempt; diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index a50868b69..acfa0655e 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Controls; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin.Program.Programs; using Flow.Launcher.Plugin.Program.Views; @@ -20,6 +19,8 @@ namespace Flow.Launcher.Plugin.Program { public class Main : ISettingProvider, IAsyncPlugin, IPluginI18n, IContextMenu, IAsyncReloadable, IDisposable { + private static readonly string ClassName = nameof(Main); + private const string Win32CacheName = "Win32"; private const string UwpCacheName = "UWP"; @@ -109,7 +110,7 @@ namespace Flow.Launcher.Plugin.Program } catch (OperationCanceledException) { - Log.Debug("|Flow.Launcher.Plugin.Program.Main|Query operation cancelled"); + Context.API.LogDebug(ClassName, "Query operation cancelled"); return emptyResults; } finally @@ -253,8 +254,8 @@ namespace Flow.Launcher.Plugin.Program _uwpsCount = _uwps.Count; _uwpsLock.Release(); }); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload win32 programs <{_win32sCount}>"); - Log.Info($"|Flow.Launcher.Plugin.Program.Main|Number of preload uwps <{_uwpsCount}>"); + Context.API.LogInfo(ClassName, "Number of preload win32 programs <{_win32sCount}>"); + Context.API.LogInfo(ClassName, "Number of preload uwps <{_uwpsCount}>"); var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0; @@ -295,7 +296,7 @@ namespace Flow.Launcher.Plugin.Program } catch (Exception e) { - Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Win32 programs", e); + Context.API.LogException(ClassName, "Failed to index Win32 programs", e); } finally { @@ -320,7 +321,7 @@ namespace Flow.Launcher.Plugin.Program } catch (Exception e) { - Log.Exception("|Flow.Launcher.Plugin.Program.Main|Failed to index Uwp programs", e); + Context.API.LogException(ClassName, "Failed to index Uwp programs", e); } finally { diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 53479b81f..97ff61304 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -8,7 +8,6 @@ using System.Threading.Tasks; using WindowsInput; using WindowsInput.Native; using Flow.Launcher.Infrastructure.Hotkey; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin.SharedCommands; using Control = System.Windows.Controls.Control; using Keys = System.Windows.Forms.Keys; @@ -17,8 +16,11 @@ namespace Flow.Launcher.Plugin.Shell { public class Main : IPlugin, ISettingProvider, IPluginI18n, IContextMenu { + private static readonly string ClassName = nameof(Main); + + internal PluginInitContext Context { get; private set; } + private const string Image = "Images/shell.png"; - private PluginInitContext context; private bool _winRStroked; private readonly KeyboardSimulator _keyboardSimulator = new KeyboardSimulator(new InputSimulator()); @@ -88,7 +90,7 @@ namespace Flow.Launcher.Plugin.Shell } catch (Exception e) { - Log.Exception($"|Flow.Launcher.Plugin.Shell.Main.Query|Exception when query for <{query}>", e); + Context.API.LogException(ClassName, $"Exception when query for <{query}>", e); } return results; } @@ -102,14 +104,14 @@ namespace Flow.Launcher.Plugin.Shell { if (m.Key == cmd) { - result.SubTitle = string.Format(context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value); + result.SubTitle = string.Format(Context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value); return null; } var ret = new Result { Title = m.Key, - SubTitle = string.Format(context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value), + SubTitle = string.Format(Context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value), IcoPath = Image, Action = c => { @@ -139,7 +141,7 @@ namespace Flow.Launcher.Plugin.Shell { Title = cmd, Score = 5000, - SubTitle = context.API.GetTranslation("flowlauncher_plugin_cmd_execute_through_shell"), + SubTitle = Context.API.GetTranslation("flowlauncher_plugin_cmd_execute_through_shell"), IcoPath = Image, Action = c => { @@ -164,7 +166,7 @@ namespace Flow.Launcher.Plugin.Shell .Select(m => new Result { Title = m.Key, - SubTitle = string.Format(context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value), + SubTitle = string.Format(Context.API.GetTranslation("flowlauncher_plugin_cmd_cmd_has_been_executed_times"), m.Value), IcoPath = Image, Action = c => { @@ -211,7 +213,7 @@ namespace Flow.Launcher.Plugin.Shell info.FileName = "cmd.exe"; } - info.ArgumentList.Add($"{(_settings.LeaveShellOpen ? "/k" : "/c")} {command} {(_settings.CloseShellAfterPress ? $"&& echo {context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")} && pause > nul /c" : "")}"); + info.ArgumentList.Add($"{(_settings.LeaveShellOpen ? "/k" : "/c")} {command} {(_settings.CloseShellAfterPress ? $"&& echo {Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")} && pause > nul /c" : "")}"); break; } @@ -234,7 +236,7 @@ namespace Flow.Launcher.Plugin.Shell else { info.ArgumentList.Add("-Command"); - info.ArgumentList.Add($"{command}\\; {(_settings.CloseShellAfterPress ? $"Write-Host '{context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); + info.ArgumentList.Add($"{command}\\; {(_settings.CloseShellAfterPress ? $"Write-Host '{Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); } break; } @@ -255,7 +257,7 @@ namespace Flow.Launcher.Plugin.Shell info.ArgumentList.Add("-NoExit"); } info.ArgumentList.Add("-Command"); - info.ArgumentList.Add($"{command}\\; {(_settings.CloseShellAfterPress ? $"Write-Host '{context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); + info.ArgumentList.Add($"{command}\\; {(_settings.CloseShellAfterPress ? $"Write-Host '{Context.API.GetTranslation("flowlauncher_plugin_cmd_press_any_key_to_close")}'\\; [System.Console]::ReadKey()\\; exit" : "")}"); break; } @@ -309,13 +311,13 @@ namespace Flow.Launcher.Plugin.Shell { var name = "Plugin: Shell"; var message = $"Command not found: {e.Message}"; - context.API.ShowMsg(name, message); + Context.API.ShowMsg(name, message); } catch (Win32Exception e) { var name = "Plugin: Shell"; var message = $"Error running the command: {e.Message}"; - context.API.ShowMsg(name, message); + Context.API.ShowMsg(name, message); } } @@ -350,14 +352,14 @@ namespace Flow.Launcher.Plugin.Shell public void Init(PluginInitContext context) { - this.context = context; + Context = context; _settings = context.API.LoadSettingJsonStorage(); context.API.RegisterGlobalKeyboardCallback(API_GlobalKeyboardEvent); } bool API_GlobalKeyboardEvent(int keyevent, int vkcode, SpecialKeyState state) { - if (!context.CurrentPluginMetadata.Disabled && _settings.ReplaceWinR) + if (!Context.CurrentPluginMetadata.Disabled && _settings.ReplaceWinR) { if (keyevent == (int)KeyEvent.WM_KEYDOWN && vkcode == (int)Keys.R && state.WinPressed) { @@ -380,10 +382,9 @@ namespace Flow.Launcher.Plugin.Shell // show the main window and set focus to the query box _ = Task.Run(() => { - context.API.ShowMainWindow(); - context.API.ChangeQuery($"{context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}"); + Context.API.ShowMainWindow(); + Context.API.ChangeQuery($"{Context.CurrentPluginMetadata.ActionKeywords[0]}{Plugin.Query.TermSeparator}"); }); - } public Control CreateSettingPanel() @@ -393,12 +394,12 @@ namespace Flow.Launcher.Plugin.Shell public string GetTranslatedPluginTitle() { - return context.API.GetTranslation("flowlauncher_plugin_cmd_plugin_name"); + return Context.API.GetTranslation("flowlauncher_plugin_cmd_plugin_name"); } public string GetTranslatedPluginDescription() { - return context.API.GetTranslation("flowlauncher_plugin_cmd_plugin_description"); + return Context.API.GetTranslation("flowlauncher_plugin_cmd_plugin_description"); } public List LoadContextMenus(Result selectedResult) @@ -407,8 +408,8 @@ namespace Flow.Launcher.Plugin.Shell { new() { - Title = context.API.GetTranslation("flowlauncher_plugin_cmd_run_as_different_user"), - AsyncAction = async c => + Title = Context.API.GetTranslation("flowlauncher_plugin_cmd_run_as_different_user"), + Action = c => { Execute(ShellCommand.RunAsDifferentUser, PrepareProcessStartInfo(selectedResult.Title)); return true; @@ -418,7 +419,7 @@ namespace Flow.Launcher.Plugin.Shell }, new() { - Title = context.API.GetTranslation("flowlauncher_plugin_cmd_run_as_administrator"), + Title = Context.API.GetTranslation("flowlauncher_plugin_cmd_run_as_administrator"), Action = c => { Execute(Process.Start, PrepareProcessStartInfo(selectedResult.Title, true)); @@ -429,10 +430,10 @@ namespace Flow.Launcher.Plugin.Shell }, new() { - Title = context.API.GetTranslation("flowlauncher_plugin_cmd_copy"), + Title = Context.API.GetTranslation("flowlauncher_plugin_cmd_copy"), Action = c => { - context.API.CopyToClipboard(selectedResult.Title); + Context.API.CopyToClipboard(selectedResult.Title); return true; }, IcoPath = "Images/copy.png", diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 94a9d0348..043eb7a19 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Runtime.InteropServices; using System.Windows; using Flow.Launcher.Infrastructure; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; using Windows.Win32; using Windows.Win32.Foundation; @@ -19,6 +18,8 @@ namespace Flow.Launcher.Plugin.Sys { public class Main : IPlugin, ISettingProvider, IPluginI18n { + private static readonly string ClassName = nameof(Main); + private readonly Dictionary KeywordTitleMappings = new() { {"Shutdown", "flowlauncher_plugin_sys_shutdown_computer_cmd"}, @@ -106,7 +107,7 @@ namespace Flow.Launcher.Plugin.Sys { if (!KeywordTitleMappings.TryGetValue(key, out var translationKey)) { - Log.Error("Flow.Launcher.Plugin.Sys.Main", $"Title not found for: {key}"); + _context.API.LogError(ClassName, $"Title not found for: {key}"); return "Title Not Found"; } @@ -117,7 +118,7 @@ namespace Flow.Launcher.Plugin.Sys { if (!KeywordDescriptionMappings.TryGetValue(key, out var translationKey)) { - Log.Error("Flow.Launcher.Plugin.Sys.Main", $"Description not found for: {key}"); + _context.API.LogError(ClassName, $"Description not found for: {key}"); return "Description Not Found"; } From 4e1d4ab7afcddeaa39f0b1aeca0639e401a5e933 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:18:44 +0800 Subject: [PATCH 0760/1798] Remove unused project reference --- .../Flow.Launcher.Plugin.WebSearch.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj index c2d0a46a0..73726ab37 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj @@ -51,7 +51,6 @@ - From 1aeaaf2fc24d32d67d994f84b2e84b555fb8c367 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:30:50 +0800 Subject: [PATCH 0761/1798] Add keyevent in Plugin project & Improve Shell plugin code quality --- Flow.Launcher.Infrastructure/NativeMethods.txt | 5 ----- .../Hotkey => Flow.Launcher.Plugin}/KeyEvent.cs | 7 ++++++- Flow.Launcher.Plugin/NativeMethods.txt | 7 ++++++- .../Flow.Launcher.Plugin.Shell.csproj | 1 - Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 7 +++---- 5 files changed, 15 insertions(+), 12 deletions(-) rename {Flow.Launcher.Infrastructure/Hotkey => Flow.Launcher.Plugin}/KeyEvent.cs (61%) diff --git a/Flow.Launcher.Infrastructure/NativeMethods.txt b/Flow.Launcher.Infrastructure/NativeMethods.txt index 363ecb9d0..18b206022 100644 --- a/Flow.Launcher.Infrastructure/NativeMethods.txt +++ b/Flow.Launcher.Infrastructure/NativeMethods.txt @@ -11,11 +11,6 @@ GetModuleHandle GetKeyState VIRTUAL_KEY -WM_KEYDOWN -WM_KEYUP -WM_SYSKEYDOWN -WM_SYSKEYUP - EnumWindows DwmSetWindowAttribute diff --git a/Flow.Launcher.Infrastructure/Hotkey/KeyEvent.cs b/Flow.Launcher.Plugin/KeyEvent.cs similarity index 61% rename from Flow.Launcher.Infrastructure/Hotkey/KeyEvent.cs rename to Flow.Launcher.Plugin/KeyEvent.cs index 95bb25837..321f17cc1 100644 --- a/Flow.Launcher.Infrastructure/Hotkey/KeyEvent.cs +++ b/Flow.Launcher.Plugin/KeyEvent.cs @@ -1,7 +1,12 @@ using Windows.Win32; -namespace Flow.Launcher.Infrastructure.Hotkey +namespace Flow.Launcher.Plugin { + /// + /// Enumeration of key events for + /// + /// and + /// public enum KeyEvent { /// diff --git a/Flow.Launcher.Plugin/NativeMethods.txt b/Flow.Launcher.Plugin/NativeMethods.txt index e3e2b705e..0596691cc 100644 --- a/Flow.Launcher.Plugin/NativeMethods.txt +++ b/Flow.Launcher.Plugin/NativeMethods.txt @@ -1,3 +1,8 @@ EnumThreadWindows GetWindowText -GetWindowTextLength \ No newline at end of file +GetWindowTextLength + +WM_KEYDOWN +WM_KEYUP +WM_SYSKEYDOWN +WM_SYSKEYUP \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj index 8f443214b..c7ea7cdd5 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj +++ b/Plugins/Flow.Launcher.Plugin.Shell/Flow.Launcher.Plugin.Shell.csproj @@ -37,7 +37,6 @@ - diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index 97ff61304..b149884d7 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Threading.Tasks; using WindowsInput; using WindowsInput.Native; -using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Plugin.SharedCommands; using Control = System.Windows.Controls.Control; using Keys = System.Windows.Forms.Keys; @@ -22,7 +21,7 @@ namespace Flow.Launcher.Plugin.Shell private const string Image = "Images/shell.png"; private bool _winRStroked; - private readonly KeyboardSimulator _keyboardSimulator = new KeyboardSimulator(new InputSimulator()); + private readonly KeyboardSimulator _keyboardSimulator = new(new InputSimulator()); private Settings _settings; @@ -55,7 +54,7 @@ namespace Flow.Launcher.Plugin.Shell { basedir = Path.GetDirectoryName(excmd); var dirName = Path.GetDirectoryName(cmd); - dir = (dirName.EndsWith("/") || dirName.EndsWith(@"\")) ? dirName : cmd.Substring(0, dirName.Length + 1); + dir = (dirName.EndsWith("/") || dirName.EndsWith(@"\")) ? dirName : cmd[..(dirName.Length + 1)]; } if (basedir != null) @@ -321,7 +320,7 @@ namespace Flow.Launcher.Plugin.Shell } } - private bool ExistInPath(string filename) + private static bool ExistInPath(string filename) { if (File.Exists(filename)) { From c035b65517befa0b3df89560f51a6447781b1937 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:31:53 +0800 Subject: [PATCH 0762/1798] Fix code documents issue --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 273676bfb..ff0f1ba4a 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -372,6 +372,7 @@ namespace Flow.Launcher.Plugin /// public bool SetCurrentTheme(ThemeData theme); + /// /// Save all Flow's plugins caches /// void SavePluginCaches(); @@ -404,6 +405,7 @@ namespace Flow.Launcher.Plugin /// Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new(); + /// /// Load image from path. Support local, remote and data:image url. /// If image path is missing, it will return a missing icon. /// @@ -418,6 +420,7 @@ namespace Flow.Launcher.Plugin /// ValueTask LoadImageAsync(string path, bool loadFullImage = false, bool cacheImage = true); + /// /// Update the plugin manifest /// /// From e07beb22613a7d7c1d4cf7670d52d99546137e89 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:33:22 +0800 Subject: [PATCH 0763/1798] Add dispose --- Plugins/Flow.Launcher.Plugin.Shell/Main.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs index b149884d7..0d395c053 100644 --- a/Plugins/Flow.Launcher.Plugin.Shell/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Shell/Main.cs @@ -13,7 +13,7 @@ using Keys = System.Windows.Forms.Keys; namespace Flow.Launcher.Plugin.Shell { - public class Main : IPlugin, ISettingProvider, IPluginI18n, IContextMenu + public class Main : IPlugin, ISettingProvider, IPluginI18n, IContextMenu, IDisposable { private static readonly string ClassName = nameof(Main); @@ -442,5 +442,10 @@ namespace Flow.Launcher.Plugin.Shell return results; } + + public void Dispose() + { + Context.API.RemoveGlobalKeyboardCallback(API_GlobalKeyboardEvent); + } } } From 46712f287ffdd188687850875acf884ad54b4a9e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:37:42 +0800 Subject: [PATCH 0764/1798] Improve api documents --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index ff0f1ba4a..6f17f57f5 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -142,15 +142,47 @@ namespace Flow.Launcher.Plugin List GetAllPlugins(); /// - /// Register a callback for Global Keyboard Event + /// Registers a callback function for global keyboard events. /// - /// + /// + /// The callback function to invoke when a global keyboard event occurs. + /// + /// Parameters: + /// + /// int: The type of (key down, key up, etc.) + /// int: The virtual key code of the pressed/released key + /// : The state of modifier keys (Ctrl, Alt, Shift, etc.) + /// + /// + /// + /// Returns: true to allow normal system processing of the key event, + /// or false to intercept and prevent default handling. + /// + /// + /// + /// This callback will be invoked for all keyboard events system-wide. + /// Use with caution as intercepting system keys may affect normal system operation. + /// public void RegisterGlobalKeyboardCallback(Func callback); - + /// /// Remove a callback for Global Keyboard Event /// - /// + /// + /// The callback function to invoke when a global keyboard event occurs. + /// + /// Parameters: + /// + /// int: The type of (key down, key up, etc.) + /// int: The virtual key code of the pressed/released key + /// : The state of modifier keys (Ctrl, Alt, Shift, etc.) + /// + /// + /// + /// Returns: true to allow normal system processing of the key event, + /// or false to intercept and prevent default handling. + /// + /// public void RemoveGlobalKeyboardCallback(Func callback); /// From f71e7461c6cf83cababdd18d6c4f8f766aa20aa5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:38:52 +0800 Subject: [PATCH 0765/1798] Remove unused project reference --- Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj index 266c24170..dbc36ad42 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj +++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj @@ -39,7 +39,6 @@ - From 826bc42536432f8b5afe07bee6f34a7db7b7c7f2 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:44:26 +0800 Subject: [PATCH 0766/1798] Improve code quality --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 2 +- .../Programs/UWPPackage.cs | 19 +++++----- .../Programs/Win32.cs | 37 +++++++++---------- 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index acfa0655e..99fa44257 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -275,7 +275,7 @@ namespace Flow.Launcher.Plugin.Program static void WatchProgramUpdate() { Win32.WatchProgramUpdate(_settings); - _ = UWPPackage.WatchPackageChange(); + _ = UWPPackage.WatchPackageChangeAsync(); } } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs index bf100ed7e..cb33250e1 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/UWPPackage.cs @@ -8,7 +8,6 @@ using System.Threading.Tasks; using System.Windows.Media.Imaging; using Windows.ApplicationModel; using Windows.Management.Deployment; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.Program.Logger; using Flow.Launcher.Plugin.SharedModels; using System.Threading.Channels; @@ -290,9 +289,9 @@ namespace Flow.Launcher.Plugin.Program.Programs } } - private static Channel PackageChangeChannel = Channel.CreateBounded(1); + private static readonly Channel PackageChangeChannel = Channel.CreateBounded(1); - public static async Task WatchPackageChange() + public static async Task WatchPackageChangeAsync() { if (Environment.OSVersion.Version.Major >= 10) { @@ -403,13 +402,13 @@ namespace Flow.Launcher.Plugin.Program.Programs if (!Main._settings.EnableDescription || string.IsNullOrWhiteSpace(Description) || Name.Equals(Description)) { title = Name; - matchResult = StringMatcher.FuzzySearch(query, Name); + matchResult = Main.Context.API.FuzzySearch(query, Name); } else { title = $"{Name}: {Description}"; - var nameMatch = StringMatcher.FuzzySearch(query, Name); - var descriptionMatch = StringMatcher.FuzzySearch(query, Description); + var nameMatch = Main.Context.API.FuzzySearch(query, Name); + var descriptionMatch = Main.Context.API.FuzzySearch(query, Description); if (descriptionMatch.Score > nameMatch.Score) { for (int i = 0; i < descriptionMatch.MatchData.Count; i++) @@ -477,7 +476,7 @@ namespace Flow.Launcher.Plugin.Program.Programs { var contextMenus = new List { - new Result + new() { Title = api.GetTranslation("flowlauncher_plugin_program_open_containing_folder"), Action = _ => @@ -496,9 +495,9 @@ namespace Flow.Launcher.Plugin.Program.Programs contextMenus.Add(new Result { Title = api.GetTranslation("flowlauncher_plugin_program_run_as_administrator"), - Action = _ => + Action = c => { - Task.Run(() => Launch(true)).ConfigureAwait(false); + _ = Task.Run(() => Launch(true)).ConfigureAwait(false); return true; }, IcoPath = "Images/cmd.png", @@ -539,7 +538,7 @@ namespace Flow.Launcher.Plugin.Program.Programs { ProgramLogger.LogException($"|UWP|LogoPathFromUri|{Location}" + $"|{UserModelId} 's logo uri is null or empty: {Location}", - new ArgumentException("uri")); + new ArgumentException(null, nameof(uri))); return string.Empty; } diff --git a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs index 06be2a628..a87b002d4 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Programs/Win32.cs @@ -6,7 +6,6 @@ using System.Security; using System.Text; using System.Threading.Tasks; using Microsoft.Win32; -using Flow.Launcher.Infrastructure; using Flow.Launcher.Plugin.Program.Logger; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Plugin.SharedModels; @@ -73,7 +72,7 @@ namespace Flow.Launcher.Plugin.Program.Programs private const string ExeExtension = "exe"; private string _uid = string.Empty; - private static readonly Win32 Default = new Win32() + private static readonly Win32 Default = new() { Name = string.Empty, Description = string.Empty, @@ -92,7 +91,7 @@ namespace Flow.Launcher.Plugin.Program.Programs if (candidates.Count == 0) return null; - var match = candidates.Select(candidate => StringMatcher.FuzzySearch(query, candidate)) + var match = candidates.Select(candidate => Main.Context.API.FuzzySearch(query, candidate)) .MaxBy(match => match.Score); return match?.IsSearchPrecisionScoreMet() ?? false ? match : null; @@ -112,14 +111,14 @@ namespace Flow.Launcher.Plugin.Program.Programs resultName.Equals(Description)) { title = resultName; - matchResult = StringMatcher.FuzzySearch(query, resultName); + matchResult = Main.Context.API.FuzzySearch(query, resultName); } else { // Search in both title = $"{resultName}: {Description}"; - var nameMatch = StringMatcher.FuzzySearch(query, resultName); - var descriptionMatch = StringMatcher.FuzzySearch(query, Description); + var nameMatch = Main.Context.API.FuzzySearch(query, resultName); + var descriptionMatch = Main.Context.API.FuzzySearch(query, Description); if (descriptionMatch.Score > nameMatch.Score) { for (int i = 0; i < descriptionMatch.MatchData.Count; i++) @@ -219,27 +218,27 @@ namespace Flow.Launcher.Plugin.Program.Programs { var contextMenus = new List { - new Result + new() { Title = api.GetTranslation("flowlauncher_plugin_program_run_as_different_user"), - Action = _ => + Action = c => { var info = new ProcessStartInfo { FileName = FullPath, WorkingDirectory = ParentDirectory, UseShellExecute = true }; - Task.Run(() => Main.StartProcess(ShellCommand.RunAsDifferentUser, info)); + _ = Task.Run(() => Main.StartProcess(ShellCommand.RunAsDifferentUser, info)); return true; }, IcoPath = "Images/user.png", Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\xe7ee"), }, - new Result + new() { Title = api.GetTranslation("flowlauncher_plugin_program_run_as_administrator"), - Action = _ => + Action = c => { var info = new ProcessStartInfo { @@ -249,14 +248,14 @@ namespace Flow.Launcher.Plugin.Program.Programs UseShellExecute = true }; - Task.Run(() => Main.StartProcess(Process.Start, info)); + _ = Task.Run(() => Main.StartProcess(Process.Start, info)); return true; }, IcoPath = "Images/cmd.png", Glyph = new GlyphInfo(FontFamily: "/Resources/#Segoe Fluent Icons", Glyph: "\xe7ef"), }, - new Result + new() { Title = api.GetTranslation("flowlauncher_plugin_program_open_containing_folder"), Action = _ => @@ -296,7 +295,7 @@ namespace Flow.Launcher.Plugin.Program.Programs return Name; } - private static List Watchers = new List(); + private static readonly List Watchers = new(); private static Win32 Win32Program(string path) { @@ -402,7 +401,7 @@ namespace Flow.Launcher.Plugin.Program.Programs var data = parser.ReadFile(path); var urlSection = data["InternetShortcut"]; var url = urlSection?["URL"]; - if (String.IsNullOrEmpty(url)) + if (string.IsNullOrEmpty(url)) { return program; } @@ -418,12 +417,12 @@ namespace Flow.Launcher.Plugin.Program.Programs } var iconPath = urlSection?["IconFile"]; - if (!String.IsNullOrEmpty(iconPath)) + if (!string.IsNullOrEmpty(iconPath)) { program.IcoPath = iconPath; } } - catch (Exception e) + catch (Exception) { // Many files do not have the required fields, so no logging is done. } @@ -474,7 +473,7 @@ namespace Flow.Launcher.Plugin.Program.Programs var extension = Path.GetExtension(path)?.ToLowerInvariant(); if (!string.IsNullOrEmpty(extension)) { - return extension.Substring(1); // remove dot + return extension[1..]; // remove dot } else { @@ -785,7 +784,7 @@ namespace Flow.Launcher.Plugin.Program.Programs _ = Task.Run(MonitorDirectoryChangeAsync); } - private static Channel indexQueue = Channel.CreateBounded(1); + private static readonly Channel indexQueue = Channel.CreateBounded(1); public static async Task MonitorDirectoryChangeAsync() { From d4c9626cbf5f62fda084db5f6949b636b8da9265 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:54:20 +0800 Subject: [PATCH 0767/1798] Improve code quality & Remove unused project reference --- ...low.Launcher.Plugin.PluginIndicator.csproj | 2 - .../Main.cs | 41 ++++++++++++++----- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj index 21d964c11..1e662de9e 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Flow.Launcher.Plugin.PluginIndicator.csproj @@ -41,8 +41,6 @@ - - diff --git a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs index aea0d77a1..05e8d960f 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginIndicator/Main.cs @@ -1,20 +1,20 @@ using System.Collections.Generic; using System.Linq; -using Flow.Launcher.Core.Plugin; namespace Flow.Launcher.Plugin.PluginIndicator { public class Main : IPlugin, IPluginI18n { - private PluginInitContext context; + internal PluginInitContext Context { get; private set; } public List Query(Query query) { + var nonGlobalPlugins = GetNonGlobalPlugins(); var results = - from keyword in PluginManager.NonGlobalPlugins.Keys - let plugin = PluginManager.NonGlobalPlugins[keyword].Metadata - let keywordSearchResult = context.API.FuzzySearch(query.Search, keyword) - let searchResult = keywordSearchResult.IsSearchPrecisionScoreMet() ? keywordSearchResult : context.API.FuzzySearch(query.Search, plugin.Name) + from keyword in nonGlobalPlugins.Keys + let plugin = nonGlobalPlugins[keyword].Metadata + let keywordSearchResult = Context.API.FuzzySearch(query.Search, keyword) + let searchResult = keywordSearchResult.IsSearchPrecisionScoreMet() ? keywordSearchResult : Context.API.FuzzySearch(query.Search, plugin.Name) let score = searchResult.Score where (searchResult.IsSearchPrecisionScoreMet() || string.IsNullOrEmpty(query.Search)) // To list all available action keywords @@ -22,32 +22,51 @@ namespace Flow.Launcher.Plugin.PluginIndicator select new Result { Title = keyword, - SubTitle = string.Format(context.API.GetTranslation("flowlauncher_plugin_pluginindicator_result_subtitle"), plugin.Name), + SubTitle = string.Format(Context.API.GetTranslation("flowlauncher_plugin_pluginindicator_result_subtitle"), plugin.Name), Score = score, IcoPath = plugin.IcoPath, AutoCompleteText = $"{keyword}{Plugin.Query.TermSeparator}", Action = c => { - context.API.ChangeQuery($"{keyword}{Plugin.Query.TermSeparator}"); + Context.API.ChangeQuery($"{keyword}{Plugin.Query.TermSeparator}"); return false; } }; return results.ToList(); } + private Dictionary GetNonGlobalPlugins() + { + var nonGlobalPlugins = new Dictionary(); + foreach (var plugin in Context.API.GetAllPlugins()) + { + foreach (var actionKeyword in plugin.Metadata.ActionKeywords) + { + // Skip global keywords + if (actionKeyword == Plugin.Query.GlobalPluginWildcardSign) continue; + + // Skip dulpicated keywords + if (nonGlobalPlugins.ContainsKey(actionKeyword)) continue; + + nonGlobalPlugins.Add(actionKeyword, plugin); + } + } + return nonGlobalPlugins; + } + public void Init(PluginInitContext context) { - this.context = context; + Context = context; } public string GetTranslatedPluginTitle() { - return context.API.GetTranslation("flowlauncher_plugin_pluginindicator_plugin_name"); + return Context.API.GetTranslation("flowlauncher_plugin_pluginindicator_plugin_name"); } public string GetTranslatedPluginDescription() { - return context.API.GetTranslation("flowlauncher_plugin_pluginindicator_plugin_description"); + return Context.API.GetTranslation("flowlauncher_plugin_pluginindicator_plugin_description"); } } } From 17cf74e313cba0f5a0de4b6b3cc5e51bc1f22fc2 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 12:57:28 +0800 Subject: [PATCH 0768/1798] Add obsolete warning --- Flow.Launcher.Infrastructure/UI/EnumBindingSource.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher.Infrastructure/UI/EnumBindingSource.cs b/Flow.Launcher.Infrastructure/UI/EnumBindingSource.cs index 350c892cf..f9504e6d9 100644 --- a/Flow.Launcher.Infrastructure/UI/EnumBindingSource.cs +++ b/Flow.Launcher.Infrastructure/UI/EnumBindingSource.cs @@ -3,6 +3,7 @@ using System.Windows.Markup; namespace Flow.Launcher.Infrastructure.UI { + [Obsolete("EnumBindingSourceExtension is obsolete. Use with Flow.Launcher.Localization NuGet package instead.")] public class EnumBindingSourceExtension : MarkupExtension { private Type _enumType; From c41d02127206047641b5e258366dfb1f4d2ee4ab Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:01:29 +0800 Subject: [PATCH 0769/1798] Add obsolete warning --- Flow.Launcher.Core/Resource/LocalizationConverter.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher.Core/Resource/LocalizationConverter.cs b/Flow.Launcher.Core/Resource/LocalizationConverter.cs index 81600e023..fdda33926 100644 --- a/Flow.Launcher.Core/Resource/LocalizationConverter.cs +++ b/Flow.Launcher.Core/Resource/LocalizationConverter.cs @@ -6,6 +6,7 @@ using System.Windows.Data; namespace Flow.Launcher.Core.Resource { + [Obsolete("LocalizationConverter is obsolete. Use with Flow.Launcher.Localization NuGet package instead.")] public class LocalizationConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) From da8a69038a3a9091c67340f5d98bea229f78844b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:05:43 +0800 Subject: [PATCH 0770/1798] Improve code quality --- .../Resource/LocalizedDescriptionAttribute.cs | 10 ++++++--- .../Resource/TranslationConverter.cs | 14 ++++++++---- .../SettingsPanePluginStoreViewModel.cs | 4 ++-- .../SettingsPanePluginsViewModel.cs | 4 ++-- .../Search/ResultManager.cs | 22 +++++++++---------- 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs b/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs index 52a232334..3e1a19a76 100644 --- a/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs +++ b/Flow.Launcher.Core/Resource/LocalizedDescriptionAttribute.cs @@ -1,15 +1,19 @@ using System.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Resource { public class LocalizedDescriptionAttribute : DescriptionAttribute { - private readonly Internationalization _translator; + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + private readonly string _resourceKey; public LocalizedDescriptionAttribute(string resourceKey) { - _translator = InternationalizationManager.Instance; _resourceKey = resourceKey; } @@ -17,7 +21,7 @@ namespace Flow.Launcher.Core.Resource { get { - string description = _translator.GetTranslation(_resourceKey); + string description = API.GetTranslation(_resourceKey); return string.IsNullOrWhiteSpace(description) ? string.Format("[[{0}]]", _resourceKey) : description; } diff --git a/Flow.Launcher.Core/Resource/TranslationConverter.cs b/Flow.Launcher.Core/Resource/TranslationConverter.cs index ebab99e5b..eb0032758 100644 --- a/Flow.Launcher.Core/Resource/TranslationConverter.cs +++ b/Flow.Launcher.Core/Resource/TranslationConverter.cs @@ -1,19 +1,25 @@ using System; using System.Globalization; using System.Windows.Data; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Resource { public class TranslationConverter : IValueConverter { + // We should not initialize API in static constructor because it will create another API instance + private static IPublicAPI api = null; + private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var key = value.ToString(); - if (String.IsNullOrEmpty(key)) - return key; - return InternationalizationManager.Instance.GetTranslation(key); + if (string.IsNullOrEmpty(key)) return key; + return API.GetTranslation(key); } - public object ConvertBack(object value, System.Type targetType, object parameter, CultureInfo culture) => throw new System.InvalidOperationException(); + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => + throw new InvalidOperationException(); } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs index 84d8a2ff9..fd2c8e09f 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs @@ -32,7 +32,7 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel public bool SatisfiesFilter(PluginStoreItemViewModel plugin) { return string.IsNullOrEmpty(FilterText) || - StringMatcher.FuzzySearch(FilterText, plugin.Name).IsSearchPrecisionScoreMet() || - StringMatcher.FuzzySearch(FilterText, plugin.Description).IsSearchPrecisionScoreMet(); + App.API.FuzzySearch(FilterText, plugin.Name).IsSearchPrecisionScoreMet() || + App.API.FuzzySearch(FilterText, plugin.Description).IsSearchPrecisionScoreMet(); } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index 4958bb7b7..b89e970e9 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -106,8 +106,8 @@ public partial class SettingsPanePluginsViewModel : BaseModel public List FilteredPluginViewModels => PluginViewModels .Where(v => string.IsNullOrEmpty(FilterText) || - StringMatcher.FuzzySearch(FilterText, v.PluginPair.Metadata.Name).IsSearchPrecisionScoreMet() || - StringMatcher.FuzzySearch(FilterText, v.PluginPair.Metadata.Description).IsSearchPrecisionScoreMet() + App.API.FuzzySearch(FilterText, v.PluginPair.Metadata.Name).IsSearchPrecisionScoreMet() || + App.API.FuzzySearch(FilterText, v.PluginPair.Metadata.Description).IsSearchPrecisionScoreMet() ) .ToList(); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs index 1add84765..5c4accdc0 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ResultManager.cs @@ -1,16 +1,14 @@ -using Flow.Launcher.Core.Resource; -using Flow.Launcher.Infrastructure; -using Flow.Launcher.Plugin.SharedCommands; -using System; +using System; using System.IO; using System.Linq; using System.Threading.Tasks; -using Flow.Launcher.Plugin.Explorer.Search.Everything; -using System.Windows.Input; -using Path = System.IO.Path; using System.Windows.Controls; +using System.Windows.Input; +using Flow.Launcher.Plugin.Explorer.Search.Everything; using Flow.Launcher.Plugin.Explorer.Views; +using Flow.Launcher.Plugin.SharedCommands; using Peter; +using Path = System.IO.Path; namespace Flow.Launcher.Plugin.Explorer.Search { @@ -66,7 +64,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search CreateFolderResult(Path.GetFileName(result.FullPath), result.FullPath, result.FullPath, query, result.Score, result.WindowsIndexed), ResultType.File => CreateFileResult(result.FullPath, query, result.Score, result.WindowsIndexed), - _ => throw new ArgumentOutOfRangeException() + _ => throw new ArgumentOutOfRangeException(null) }; } @@ -99,7 +97,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search IcoPath = path, SubTitle = subtitle, AutoCompleteText = GetAutoCompleteText(title, query, path, ResultType.Folder), - TitleHighlightData = StringMatcher.FuzzySearch(query.Search, title).MatchData, + TitleHighlightData = Context.API.FuzzySearch(query.Search, title).MatchData, CopyText = path, Preview = new Result.PreviewInfo { @@ -164,7 +162,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search return false; }, Score = score, - TitleToolTip = InternationalizationManager.Instance.GetTranslation("plugin_explorer_plugin_ToolTipOpenDirectory"), + TitleToolTip = Main.Context.API.GetTranslation("plugin_explorer_plugin_ToolTipOpenDirectory"), SubTitleToolTip = path, ContextData = new SearchResult { Type = ResultType.Folder, FullPath = path, WindowsIndexed = windowsIndexed } }; @@ -286,7 +284,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search FilePath = filePath, }, AutoCompleteText = GetAutoCompleteText(title, query, filePath, ResultType.File), - TitleHighlightData = StringMatcher.FuzzySearch(query.Search, title).MatchData, + TitleHighlightData = Context.API.FuzzySearch(query.Search, title).MatchData, Score = score, CopyText = filePath, PreviewPanel = new Lazy(() => new PreviewPanel(Settings, filePath)), @@ -319,7 +317,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search return true; }, - TitleToolTip = InternationalizationManager.Instance.GetTranslation("plugin_explorer_plugin_ToolTipOpenContainingFolder"), + TitleToolTip = Main.Context.API.GetTranslation("plugin_explorer_plugin_ToolTipOpenContainingFolder"), SubTitleToolTip = filePath, ContextData = new SearchResult { Type = ResultType.File, FullPath = filePath, WindowsIndexed = windowsIndexed } }; From f5de5d70dbede5d276e311489b06fcec01656c42 Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:08:28 +0800 Subject: [PATCH 0771/1798] Fix log message issue Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index 99fa44257..54e59d1be 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -254,9 +254,8 @@ namespace Flow.Launcher.Plugin.Program _uwpsCount = _uwps.Count; _uwpsLock.Release(); }); - Context.API.LogInfo(ClassName, "Number of preload win32 programs <{_win32sCount}>"); - Context.API.LogInfo(ClassName, "Number of preload uwps <{_uwpsCount}>"); - + Context.API.LogInfo(ClassName, $"Number of preload win32 programs <{_win32sCount}>"); + Context.API.LogInfo(ClassName, $"Number of preload uwps <{_uwpsCount}>"); var cacheEmpty = _win32sCount == 0 || _uwpsCount == 0; if (cacheEmpty || _settings.LastIndexTime.AddHours(30) < DateTime.Now) From 71b9e4a81121be6d445716786bbf2efe186d85c5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:09:37 +0800 Subject: [PATCH 0772/1798] Fix log info class name issue --- Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs index f6de65e90..f47907824 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ContextMenu.cs @@ -393,7 +393,7 @@ namespace Flow.Launcher.Plugin.Explorer { Title = Context.API.GetTranslation("plugin_explorer_excludefromindexsearch"), SubTitle = Context.API.GetTranslation("plugin_explorer_path") + " " + record.FullPath, - Action = _ => + Action = c_ => { if (!Settings.IndexSearchExcludedSubdirectoryPaths.Any(x => string.Equals(x.Path, record.FullPath, StringComparison.OrdinalIgnoreCase))) Settings.IndexSearchExcludedSubdirectoryPaths.Add(new AccessLink @@ -401,7 +401,7 @@ namespace Flow.Launcher.Plugin.Explorer Path = record.FullPath }); - Task.Run(() => + _ = Task.Run(() => { Context.API.ShowMsg(Context.API.GetTranslation("plugin_explorer_excludedfromindexsearch_msg"), Context.API.GetTranslation("plugin_explorer_path") + @@ -469,7 +469,7 @@ namespace Flow.Launcher.Plugin.Explorer private void LogException(string message, Exception e) { - Context.API.LogException(nameof(Main), message, e); + Context.API.LogException(nameof(ContextMenu), message, e); } private static bool CanRunAsDifferentUser(string path) From 048a40d085915e59e7d05d3faf17132ec39aadac Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:11:55 +0800 Subject: [PATCH 0773/1798] Code quality --- Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs index 3eb74dd74..3bee49bf2 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Main.cs @@ -32,7 +32,7 @@ public class Main : ISettingProvider, IPlugin, IReloadable, IPluginI18n, IContex _settings = context.API.LoadSettingJsonStorage(); _faviconCacheDir = Path.Combine( - _context.CurrentPluginMetadata.PluginCacheDirectoryPath, + context.CurrentPluginMetadata.PluginCacheDirectoryPath, "FaviconCache"); FilesFolders.ValidateDirectory(_faviconCacheDir); From 7061ac54485e3bd95177dbe737e8b2c4fc521903 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 13:12:05 +0800 Subject: [PATCH 0774/1798] Fix register bookmark file comment --- .../ChromiumBookmarkLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs index 27bcbd9a9..7631aad91 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/ChromiumBookmarkLoader.cs @@ -37,7 +37,7 @@ public abstract class ChromiumBookmarkLoader : IBookmarkLoader { if (File.Exists(bookmarkPath)) { - //Main.RegisterBookmarkFile(bookmarkPath); + Main.RegisterBookmarkFile(bookmarkPath); } } catch (Exception ex) From f854cd3f7623f12b10eddba2beb69599e9672f5f Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 15:22:41 +0800 Subject: [PATCH 0775/1798] Code quality --- Flow.Launcher.Infrastructure/Image/ImageCache.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageCache.cs b/Flow.Launcher.Infrastructure/Image/ImageCache.cs index ddbab4ef0..b8c12868b 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageCache.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageCache.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Threading; using System.Threading.Tasks; using System.Windows.Media; using BitFaster.Caching.Lfu; @@ -55,7 +53,6 @@ namespace Flow.Launcher.Infrastructure.Image return image != null; } - image = null; return false; } From 82f67884ef4619d2f05a931d02e47b40b95479c3 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 16:15:37 +0800 Subject: [PATCH 0776/1798] Support svg image file loading --- .../Flow.Launcher.Infrastructure.csproj | 1 + .../Image/ImageLoader.cs | 66 +++++++++++++++++-- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 4 +- .../FirefoxBookmarkLoader.cs | 20 +----- 4 files changed, 66 insertions(+), 25 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj index b91da7114..f02b2297f 100644 --- a/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj +++ b/Flow.Launcher.Infrastructure/Flow.Launcher.Infrastructure.csproj @@ -67,6 +67,7 @@ + diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 41a33104b..6fd5c6277 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -9,6 +9,8 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; +using SharpVectors.Converters; +using SharpVectors.Renderers.Wpf; namespace Flow.Launcher.Infrastructure.Image { @@ -25,8 +27,10 @@ namespace Flow.Launcher.Infrastructure.Image public static ImageSource LoadingImage { get; } = new BitmapImage(new Uri(Constant.LoadingImgIcon)); public const int SmallIconSize = 64; public const int FullIconSize = 256; + public const int FullImageSize = 320; private static readonly string[] ImageExtensions = { ".png", ".jpg", ".jpeg", ".gif", ".bmp", ".tiff", ".ico" }; + private static readonly string SvgExtension = ".svg"; public static async Task InitializeAsync() { @@ -245,6 +249,19 @@ namespace Flow.Launcher.Infrastructure.Image image = GetThumbnail(path, ThumbnailOptions.ThumbnailOnly); } } + else if (extension == SvgExtension) + { + try + { + image = LoadFullSvgImage(path, loadFullImage); + type = ImageType.FullImageFile; + } + catch (System.Exception) + { + image = Image; + type = ImageType.Error; + } + } else { type = ImageType.File; @@ -318,7 +335,7 @@ namespace Flow.Launcher.Infrastructure.Image return img; } - private static BitmapImage LoadFullImage(string path) + private static ImageSource LoadFullImage(string path) { BitmapImage image = new BitmapImage(); image.BeginInit(); @@ -327,24 +344,24 @@ namespace Flow.Launcher.Infrastructure.Image image.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; image.EndInit(); - if (image.PixelWidth > 320) + if (image.PixelWidth > FullImageSize) { BitmapImage resizedWidth = new BitmapImage(); resizedWidth.BeginInit(); resizedWidth.CacheOption = BitmapCacheOption.OnLoad; resizedWidth.UriSource = new Uri(path); resizedWidth.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; - resizedWidth.DecodePixelWidth = 320; + resizedWidth.DecodePixelWidth = FullImageSize; resizedWidth.EndInit(); - if (resizedWidth.PixelHeight > 320) + if (resizedWidth.PixelHeight > FullImageSize) { BitmapImage resizedHeight = new BitmapImage(); resizedHeight.BeginInit(); resizedHeight.CacheOption = BitmapCacheOption.OnLoad; resizedHeight.UriSource = new Uri(path); resizedHeight.CreateOptions = BitmapCreateOptions.IgnoreColorProfile; - resizedHeight.DecodePixelHeight = 320; + resizedHeight.DecodePixelHeight = FullImageSize; resizedHeight.EndInit(); return resizedHeight; } @@ -354,5 +371,44 @@ namespace Flow.Launcher.Infrastructure.Image return image; } + + private static ImageSource LoadFullSvgImage(string path, bool loadFullImage = false) + { + // Set up drawing settings + var desiredHeight = loadFullImage ? FullImageSize : SmallIconSize; + var drawingSettings = new WpfDrawingSettings + { + IncludeRuntime = true, + // Set IgnoreRootViewbox to false to respect the SVG's viewBox + IgnoreRootViewbox = false + }; + + // Load and render the SVG + var converter = new FileSvgReader(drawingSettings); + var drawing = converter.Read(path); + + // Calculate scale to achieve desired height + var drawingBounds = drawing.Bounds; + var scale = desiredHeight / drawingBounds.Height; + var scaledWidth = drawingBounds.Width * scale; + var scaledHeight = drawingBounds.Height * scale; + + // Convert the Drawing to a Bitmap + var drawingVisual = new DrawingVisual(); + using DrawingContext drawingContext = drawingVisual.RenderOpen(); + drawingContext.PushTransform(new ScaleTransform(scale, scale)); + drawingContext.DrawDrawing(drawing); + + // Create a RenderTargetBitmap to hold the rendered image + var bitmap = new RenderTargetBitmap( + (int)Math.Ceiling(scaledWidth), + (int)Math.Ceiling(scaledHeight), + 96, // DpiX + 96, // DpiY + PixelFormats.Pbgra32); + bitmap.Render(drawingVisual); + + return bitmap; + } } } diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 6f17f57f5..f37496fd1 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -438,7 +438,9 @@ namespace Flow.Launcher.Plugin Task SaveCacheBinaryStorageAsync(string cacheName, string cacheDirectory) where T : new(); /// - /// Load image from path. Support local, remote and data:image url. + /// Load image from path. + /// Support local, remote and data:image url. + /// Support png, jpg, jpeg, gif, bmp, tiff, ico, svg image files. /// If image path is missing, it will return a missing icon. /// /// The path of the image. diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index d2f973329..113476703 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -159,16 +159,7 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader if (!File.Exists(faviconPath)) { - // SVG 파일인지 확인 - if (IsSvgData(imageData)) - { - bookmark.FaviconPath = defaultIconPath; - continue; - } - else - { - SaveBitmapData(imageData, faviconPath); - } + SaveBitmapData(imageData, faviconPath); } bookmark.FaviconPath = faviconPath; @@ -199,15 +190,6 @@ public abstract class FirefoxBookmarkLoaderBase : IBookmarkLoader } } - private static bool IsSvgData(byte[] data) - { - if (data.Length < 5) - return false; - string start = System.Text.Encoding.ASCII.GetString(data, 0, Math.Min(100, data.Length)); - return start.Contains(" Date: Wed, 9 Apr 2025 16:24:09 +0800 Subject: [PATCH 0777/1798] Change function name --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index 6fd5c6277..ba46a7cff 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -253,7 +253,7 @@ namespace Flow.Launcher.Infrastructure.Image { try { - image = LoadFullSvgImage(path, loadFullImage); + image = LoadSvgImage(path, loadFullImage); type = ImageType.FullImageFile; } catch (System.Exception) @@ -372,7 +372,7 @@ namespace Flow.Launcher.Infrastructure.Image return image; } - private static ImageSource LoadFullSvgImage(string path, bool loadFullImage = false) + private static ImageSource LoadSvgImage(string path, bool loadFullImage = false) { // Set up drawing settings var desiredHeight = loadFullImage ? FullImageSize : SmallIconSize; From 5e7573b654d135cb92ca92c576d8f54295763374 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 16:28:53 +0800 Subject: [PATCH 0778/1798] Add log messages --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index ba46a7cff..e0959ccc2 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -233,10 +233,11 @@ namespace Flow.Launcher.Infrastructure.Image image = LoadFullImage(path); type = ImageType.FullImageFile; } - catch (NotSupportedException) + catch (NotSupportedException ex) { image = Image; type = ImageType.Error; + Log.Exception($"Failed to load image file from path {path}: {ex.Message}", ex); } } else @@ -256,10 +257,11 @@ namespace Flow.Launcher.Infrastructure.Image image = LoadSvgImage(path, loadFullImage); type = ImageType.FullImageFile; } - catch (System.Exception) + catch (System.Exception ex) { image = Image; type = ImageType.Error; + Log.Exception($"Failed to load SVG image from path {path}: {ex.Message}", ex); } } else From cce4e89c221e32291b2c88547a5f8f52e585c84c Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 16:30:35 +0800 Subject: [PATCH 0779/1798] Add safeguards to SVG loading implementation --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index e0959ccc2..0433036b7 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -391,6 +391,10 @@ namespace Flow.Launcher.Infrastructure.Image // Calculate scale to achieve desired height var drawingBounds = drawing.Bounds; + if (drawingBounds.Height <= 0) + { + throw new InvalidOperationException($"Invalid SVG dimensions: Height must be greater than zero in {path}"); + } var scale = desiredHeight / drawingBounds.Height; var scaledWidth = drawingBounds.Width * scale; var scaledHeight = drawingBounds.Height * scale; From 4f246460c353cec83a7b8fbfde31c26eba159219 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 16:46:13 +0800 Subject: [PATCH 0780/1798] Fix build issue --- Flow.Launcher.Infrastructure/Image/ImageLoader.cs | 4 ++-- Plugins/Flow.Launcher.Plugin.Program/Main.cs | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs index be3609956..cd5a4cf71 100644 --- a/Flow.Launcher.Infrastructure/Image/ImageLoader.cs +++ b/Flow.Launcher.Infrastructure/Image/ImageLoader.cs @@ -243,7 +243,7 @@ namespace Flow.Launcher.Infrastructure.Image { image = Image; type = ImageType.Error; - Log.Exception($"Failed to load image file from path {path}: {ex.Message}", ex); + API.LogException(ClassName, $"Failed to load image file from path {path}: {ex.Message}", ex); } } else @@ -267,7 +267,7 @@ namespace Flow.Launcher.Infrastructure.Image { image = Image; type = ImageType.Error; - Log.Exception($"Failed to load SVG image from path {path}: {ex.Message}", ex); + API.LogException(ClassName, $"Failed to load SVG image from path {path}: {ex.Message}", ex); } } else diff --git a/Plugins/Flow.Launcher.Plugin.Program/Main.cs b/Plugins/Flow.Launcher.Plugin.Program/Main.cs index dca07d085..16b6bcab2 100644 --- a/Plugins/Flow.Launcher.Plugin.Program/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Program/Main.cs @@ -32,8 +32,6 @@ namespace Flow.Launcher.Plugin.Program internal static PluginInitContext Context { get; private set; } - private static readonly string ClassName = nameof(Main); - private static readonly List emptyResults = new(); private static readonly MemoryCacheOptions cacheOptions = new() { SizeLimit = 1560 }; From 5c55d29e1f8788a7f5cc62231fda7b9774e66342 Mon Sep 17 00:00:00 2001 From: DB p Date: Wed, 9 Apr 2025 17:54:37 +0900 Subject: [PATCH 0781/1798] =?UTF-8?q?Handle=20it=20so=20that=20it=20doesn?= =?UTF-8?q?=E2=80=99t=20show=20if=20the=20registry=20is=20missing.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/SettingsPaneGeneral.xaml | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 1d4dfd8ae..d225b01a4 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -3,12 +3,12 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls" + xmlns:converters="clr-namespace:Flow.Launcher.Converters" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:ext="clr-namespace:Flow.Launcher.Resources.MarkupExtensions" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:settingsViewModels="clr-namespace:Flow.Launcher.SettingPages.ViewModels" xmlns:ui="http://schemas.modernwpf.com/2019" - xmlns:converters="clr-namespace:Flow.Launcher.Converters" xmlns:userSettings="clr-namespace:Flow.Launcher.Infrastructure.UserSettings;assembly=Flow.Launcher.Infrastructure" Title="General" d:DataContext="{d:DesignInstance settingsViewModels:SettingsPaneGeneralViewModel}" @@ -32,7 +32,7 @@ Style="{StaticResource PageTitle}" Text="{DynamicResource general}" TextAlignment="left" /> - + - - + + + + + Icon="" + Sub="{DynamicResource KoreanImeRegistryTooltip}"> - internal abstract class JsonRPCPlugin : JsonRPCPluginBase { - public const string JsonRPC = "JsonRPC"; + public new const string JsonRPC = "JsonRPC"; protected abstract Task RequestAsync(JsonRPCRequestModel rpcRequest, CancellationToken token = default); protected abstract string Request(JsonRPCRequestModel rpcRequest, CancellationToken token = default); @@ -29,9 +28,6 @@ namespace Flow.Launcher.Core.Plugin private int RequestId { get; set; } - private string SettingConfigurationPath => Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "SettingsTemplate.yaml"); - private string SettingPath => Path.Combine(Context.CurrentPluginMetadata.PluginSettingsDirectoryPath, "Settings.json"); - public override List LoadContextMenus(Result selectedResult) { var request = new JsonRPCRequestModel(RequestId++, @@ -57,13 +53,6 @@ namespace Flow.Launcher.Core.Plugin } }; - private static readonly JsonSerializerOptions settingSerializeOption = new() - { - WriteIndented = true - }; - - private readonly Dictionary _settingControls = new(); - private async Task> DeserializedResultAsync(Stream output) { await using (output) @@ -122,7 +111,6 @@ namespace Flow.Launcher.Core.Plugin return !result.JsonRPCAction.DontHideAfterAction; } - /// /// Execute external program and return the output /// diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs index 779dcf887..b134e2d50 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs @@ -1,11 +1,11 @@ -using Flow.Launcher.Core.Resource; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Flow.Launcher.Core.Resource; using Flow.Launcher.Plugin; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs index abe563c14..d240ac9be 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs @@ -10,7 +10,6 @@ using Microsoft.VisualStudio.Threading; using StreamJsonRpc; using IAsyncDisposable = System.IAsyncDisposable; - namespace Flow.Launcher.Core.Plugin { internal abstract class JsonRPCPluginV2 : JsonRPCPluginBase, IAsyncDisposable, IAsyncReloadable, IResultUpdated @@ -23,7 +22,6 @@ namespace Flow.Launcher.Core.Plugin private JsonRpc RPC { get; set; } - protected override async Task ExecuteResultAsync(JsonRPCResult result) { var res = await RPC.InvokeAsync(result.JsonRPCAction.Method, @@ -55,7 +53,6 @@ namespace Flow.Launcher.Core.Plugin return results; } - public override async Task InitAsync(PluginInitContext context) { await base.InitAsync(context); @@ -88,7 +85,6 @@ namespace Flow.Launcher.Core.Plugin protected abstract MessageHandlerType MessageHandler { get; } - private void SetupJsonRPC() { var formatter = new SystemTextJsonFormatter { JsonSerializerOptions = RequestSerializeOption }; @@ -118,9 +114,16 @@ namespace Flow.Launcher.Core.Plugin { await RPC.InvokeAsync("reload_data", Context); } - catch (RemoteMethodNotFoundException e) + catch (RemoteMethodNotFoundException) { } + catch (ConnectionLostException) + { + } + catch (Exception e) + { + Context.API.LogException(nameof(JsonRPCPluginV2), "Failed to call reload_data", e); + } } public virtual async ValueTask DisposeAsync() @@ -129,9 +132,16 @@ namespace Flow.Launcher.Core.Plugin { await RPC.InvokeAsync("close"); } - catch (RemoteMethodNotFoundException e) + catch (RemoteMethodNotFoundException) { } + catch (ConnectionLostException) + { + } + catch (Exception e) + { + Context.API.LogException(nameof(JsonRPCPluginV2), "Failed to call close", e); + } finally { RPC?.Dispose(); From 8730a5fce8079a955a98533307c8c91383ce1f95 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 18:10:44 +0800 Subject: [PATCH 0789/1798] Improve log message --- Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs index d240ac9be..eda016d94 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs @@ -122,7 +122,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - Context.API.LogException(nameof(JsonRPCPluginV2), "Failed to call reload_data", e); + Context.API.LogException(nameof(JsonRPCPluginV2), $"Failed to call reload_data for plugin {Context.CurrentPluginMetadata.Name}", e); } } @@ -140,7 +140,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - Context.API.LogException(nameof(JsonRPCPluginV2), "Failed to call close", e); + Context.API.LogException(nameof(JsonRPCPluginV2), $"Failed to call close for plugin {Context.CurrentPluginMetadata.Name}", e); } finally { From 4095eb4b86cccca1d9be969c0cac59e52b48dd64 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 19:26:52 +0800 Subject: [PATCH 0790/1798] Improve code quality --- Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs | 17 +++++++++-------- Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs | 7 ++----- Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs | 6 ++++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs index 9f64e418c..b19bb6c79 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs @@ -7,7 +7,6 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Flow.Launcher.Core.Resource; -using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Plugin; using Microsoft.IO; @@ -21,6 +20,8 @@ namespace Flow.Launcher.Core.Plugin { public new const string JsonRPC = "JsonRPC"; + private static readonly string ClassName = nameof(JsonRPCPlugin); + protected abstract Task RequestAsync(JsonRPCRequestModel rpcRequest, CancellationToken token = default); protected abstract string Request(JsonRPCRequestModel rpcRequest, CancellationToken token = default); @@ -148,11 +149,11 @@ namespace Flow.Launcher.Core.Plugin var error = standardError.ReadToEnd(); if (!string.IsNullOrEmpty(error)) { - Log.Error($"|JsonRPCPlugin.Execute|{error}"); + Context.API.LogError(ClassName, error); return string.Empty; } - Log.Error("|JsonRPCPlugin.Execute|Empty standard output and standard error."); + Context.API.LogError(ClassName, "Empty standard output and standard error."); return string.Empty; } @@ -160,8 +161,8 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - Log.Exception( - $"|JsonRPCPlugin.Execute|Exception for filename <{startInfo.FileName}> with argument <{startInfo.Arguments}>", + Context.API.LogException(ClassName, + $"Exception for filename <{startInfo.FileName}> with argument <{startInfo.Arguments}>", e); return string.Empty; } @@ -172,7 +173,7 @@ namespace Flow.Launcher.Core.Plugin using var process = Process.Start(startInfo); if (process == null) { - Log.Error("|JsonRPCPlugin.ExecuteAsync|Can't start new process"); + Context.API.LogError(ClassName, "Can't start new process"); return Stream.Null; } @@ -192,7 +193,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - Log.Exception("|JsonRPCPlugin.ExecuteAsync|Exception when kill process", e); + Context.API.LogException(ClassName, "Exception when kill process", e); } }); @@ -213,7 +214,7 @@ namespace Flow.Launcher.Core.Plugin { case (0, 0): const string errorMessage = "Empty JSON-RPC Response."; - Log.Warn($"|{nameof(JsonRPCPlugin)}.{nameof(ExecuteAsync)}|{errorMessage}"); + Context.API.LogWarn(ClassName, errorMessage); break; case (_, not 0): throw new InvalidDataException(Encoding.UTF8.GetString(errorBuffer.ToArray())); // The process has exited with an error message diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs index b134e2d50..df0438409 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs @@ -19,10 +19,9 @@ namespace Flow.Launcher.Core.Plugin /// public abstract class JsonRPCPluginBase : IAsyncPlugin, IContextMenu, ISettingProvider, ISavable { - protected PluginInitContext Context; public const string JsonRPC = "JsonRPC"; - private int RequestId { get; set; } + protected PluginInitContext Context; private string SettingConfigurationPath => Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "SettingsTemplate.yaml"); @@ -107,7 +106,6 @@ namespace Flow.Launcher.Core.Plugin public abstract Task> QueryAsync(Query query, CancellationToken token); - private async Task InitSettingAsync() { JsonRpcConfigurationModel configuration = null; @@ -119,7 +117,6 @@ namespace Flow.Launcher.Core.Plugin await File.ReadAllTextAsync(SettingConfigurationPath)); } - Settings ??= new JsonRPCPluginSettings { Configuration = configuration, SettingPath = SettingPath, API = Context.API @@ -130,7 +127,7 @@ namespace Flow.Launcher.Core.Plugin public virtual async Task InitAsync(PluginInitContext context) { - this.Context = context; + Context = context; await InitSettingAsync(); } diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs index eda016d94..6dccfa59b 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs @@ -16,6 +16,8 @@ namespace Flow.Launcher.Core.Plugin { public const string JsonRpc = "JsonRPC"; + private static readonly string ClassName = nameof(JsonRPCPluginV2); + protected abstract IDuplexPipe ClientPipe { get; set; } protected StreamReader ErrorStream { get; set; } @@ -122,7 +124,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - Context.API.LogException(nameof(JsonRPCPluginV2), $"Failed to call reload_data for plugin {Context.CurrentPluginMetadata.Name}", e); + Context.API.LogException(ClassName, $"Failed to call reload_data for plugin {Context.CurrentPluginMetadata.Name}", e); } } @@ -140,7 +142,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - Context.API.LogException(nameof(JsonRPCPluginV2), $"Failed to call close for plugin {Context.CurrentPluginMetadata.Name}", e); + Context.API.LogException(ClassName, $"Failed to call close for plugin {Context.CurrentPluginMetadata.Name}", e); } finally { From 5a2db37d39fcd1c614e06e7d54a938bc37a9d3b3 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 19:43:22 +0800 Subject: [PATCH 0791/1798] Add code comments --- Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs index 6dccfa59b..148fd969e 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs @@ -118,9 +118,11 @@ namespace Flow.Launcher.Core.Plugin } catch (RemoteMethodNotFoundException) { + // Ignored } catch (ConnectionLostException) { + // Ignored } catch (Exception e) { @@ -136,9 +138,11 @@ namespace Flow.Launcher.Core.Plugin } catch (RemoteMethodNotFoundException) { + // Ignored } catch (ConnectionLostException) { + // Ignored } catch (Exception e) { From 1f458d3b564a37944a7a10183fc9be5696cf2e95 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 20:06:17 +0800 Subject: [PATCH 0792/1798] Fix typos & Code quality --- .../TranslationMapping.cs | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/Flow.Launcher.Infrastructure/TranslationMapping.cs b/Flow.Launcher.Infrastructure/TranslationMapping.cs index c976fc522..b33a094db 100644 --- a/Flow.Launcher.Infrastructure/TranslationMapping.cs +++ b/Flow.Launcher.Infrastructure/TranslationMapping.cs @@ -8,8 +8,9 @@ namespace Flow.Launcher.Infrastructure { private bool constructed; - private List originalIndexs = new List(); - private List translatedIndexs = new List(); + private readonly List originalIndexes = new(); + private readonly List translatedIndexes = new(); + private int translatedLength = 0; public void AddNewIndex(int originalIndex, int translatedIndex, int length) @@ -17,46 +18,47 @@ namespace Flow.Launcher.Infrastructure if (constructed) throw new InvalidOperationException("Mapping shouldn't be changed after constructed"); - originalIndexs.Add(originalIndex); - translatedIndexs.Add(translatedIndex); - translatedIndexs.Add(translatedIndex + length); + originalIndexes.Add(originalIndex); + translatedIndexes.Add(translatedIndex); + translatedIndexes.Add(translatedIndex + length); translatedLength += length - 1; } public int MapToOriginalIndex(int translatedIndex) { - if (translatedIndex > translatedIndexs.Last()) + if (translatedIndex > translatedIndexes.Last()) return translatedIndex - translatedLength - 1; int lowerBound = 0; - int upperBound = originalIndexs.Count - 1; + int upperBound = originalIndexes.Count - 1; int count = 0; // Corner case handle - if (translatedIndex < translatedIndexs[0]) + if (translatedIndex < translatedIndexes[0]) return translatedIndex; - if (translatedIndex > translatedIndexs.Last()) + + if (translatedIndex > translatedIndexes.Last()) { int indexDef = 0; - for (int k = 0; k < originalIndexs.Count; k++) + for (int k = 0; k < originalIndexes.Count; k++) { - indexDef += translatedIndexs[k * 2 + 1] - translatedIndexs[k * 2]; + indexDef += translatedIndexes[k * 2 + 1] - translatedIndexes[k * 2]; } return translatedIndex - indexDef - 1; } // Binary Search with Range - for (int i = originalIndexs.Count / 2;; count++) + for (int i = originalIndexes.Count / 2;; count++) { - if (translatedIndex < translatedIndexs[i * 2]) + if (translatedIndex < translatedIndexes[i * 2]) { // move to lower middle upperBound = i; i = (i + lowerBound) / 2; } - else if (translatedIndex > translatedIndexs[i * 2 + 1] - 1) + else if (translatedIndex > translatedIndexes[i * 2 + 1] - 1) { lowerBound = i; // move to upper middle @@ -64,17 +66,19 @@ namespace Flow.Launcher.Infrastructure i = (i + upperBound + 1) / 2; } else - return originalIndexs[i]; + { + return originalIndexes[i]; + } if (upperBound - lowerBound <= 1 && - translatedIndex > translatedIndexs[lowerBound * 2 + 1] && - translatedIndex < translatedIndexs[upperBound * 2]) + translatedIndex > translatedIndexes[lowerBound * 2 + 1] && + translatedIndex < translatedIndexes[upperBound * 2]) { int indexDef = 0; for (int j = 0; j < upperBound; j++) { - indexDef += translatedIndexs[j * 2 + 1] - translatedIndexs[j * 2]; + indexDef += translatedIndexes[j * 2 + 1] - translatedIndexes[j * 2]; } return translatedIndex - indexDef - 1; From 4400734963a6eabc5e13fdc031ed57619755e784 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 21:12:09 +0800 Subject: [PATCH 0793/1798] Remove InternationalizationManager.Instance --- .../Resource/InternationalizationManager.cs | 12 --------- Flow.Launcher/ActionKeywords.xaml.cs | 27 ++++++++----------- Flow.Launcher/Converters/TextConverter.cs | 3 +-- .../CustomQueryHotkeySetting.xaml.cs | 8 +++--- Flow.Launcher/CustomShortcutSetting.xaml.cs | 10 +++---- Flow.Launcher/Helper/HotKeyMapper.cs | 13 +++++---- Flow.Launcher/HotkeyControl.xaml.cs | 13 +++------ Flow.Launcher/HotkeyControlDialog.xaml.cs | 13 +++++---- .../Resources/Pages/WelcomePage1.xaml.cs | 9 ++++--- .../SettingsPaneGeneralViewModel.cs | 27 +++++++++---------- .../ViewModels/SettingsPaneHotkeyViewModel.cs | 17 ++++++------ .../ViewModels/SettingsPaneProxyViewModel.cs | 3 +-- .../Views/SettingsPaneGeneral.xaml.cs | 4 ++- 13 files changed, 65 insertions(+), 94 deletions(-) delete mode 100644 Flow.Launcher.Core/Resource/InternationalizationManager.cs diff --git a/Flow.Launcher.Core/Resource/InternationalizationManager.cs b/Flow.Launcher.Core/Resource/InternationalizationManager.cs deleted file mode 100644 index 5d718466c..000000000 --- a/Flow.Launcher.Core/Resource/InternationalizationManager.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using CommunityToolkit.Mvvm.DependencyInjection; - -namespace Flow.Launcher.Core.Resource -{ - [Obsolete("InternationalizationManager.Instance is obsolete. Use Ioc.Default.GetRequiredService() instead.")] - public static class InternationalizationManager - { - public static Internationalization Instance - => Ioc.Default.GetRequiredService(); - } -} diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index d403d4847..ad24f2a76 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -1,8 +1,6 @@ using System.Windows; -using Flow.Launcher.Core.Resource; using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; -using Flow.Launcher.Core; using System.Linq; using System.Collections.Generic; @@ -10,20 +8,19 @@ namespace Flow.Launcher { public partial class ActionKeywords { - private readonly PluginPair plugin; - private readonly Internationalization translater = InternationalizationManager.Instance; - private readonly PluginViewModel pluginViewModel; + private readonly PluginPair _plugin; + private readonly PluginViewModel _pluginViewModel; public ActionKeywords(PluginViewModel pluginViewModel) { InitializeComponent(); - plugin = pluginViewModel.PluginPair; - this.pluginViewModel = pluginViewModel; + _plugin = pluginViewModel.PluginPair; + _pluginViewModel = pluginViewModel; } private void ActionKeyword_OnLoaded(object sender, RoutedEventArgs e) { - tbOldActionKeyword.Text = string.Join(Query.ActionKeywordSeparator, plugin.Metadata.ActionKeywords.ToArray()); + tbOldActionKeyword.Text = string.Join(Query.ActionKeywordSeparator, _plugin.Metadata.ActionKeywords.ToArray()); tbAction.Focus(); } @@ -34,7 +31,7 @@ namespace Flow.Launcher private void btnDone_OnClick(object sender, RoutedEventArgs _) { - var oldActionKeywords = plugin.Metadata.ActionKeywords; + var oldActionKeywords = _plugin.Metadata.ActionKeywords; var newActionKeywords = tbAction.Text.Split(Query.ActionKeywordSeparator).ToList(); newActionKeywords.RemoveAll(string.IsNullOrEmpty); @@ -48,7 +45,7 @@ namespace Flow.Launcher { if (oldActionKeywords.Count != newActionKeywords.Count) { - ReplaceActionKeyword(plugin.Metadata.ID, removedActionKeywords, addedActionKeywords); + ReplaceActionKeyword(_plugin.Metadata.ID, removedActionKeywords, addedActionKeywords); return; } @@ -58,18 +55,16 @@ namespace Flow.Launcher if (sortedOldActionKeywords.SequenceEqual(sortedNewActionKeywords)) { // User just changes the sequence of action keywords - var msg = translater.GetTranslation("newActionKeywordsSameAsOld"); - MessageBoxEx.Show(msg); + App.API.ShowMsgBox(App.API.GetTranslation("newActionKeywordsSameAsOld")); } else { - ReplaceActionKeyword(plugin.Metadata.ID, removedActionKeywords, addedActionKeywords); + ReplaceActionKeyword(_plugin.Metadata.ID, removedActionKeywords, addedActionKeywords); } } else { - string msg = translater.GetTranslation("newActionKeywordsHasBeenAssigned"); - App.API.ShowMsgBox(msg); + App.API.ShowMsgBox(App.API.GetTranslation("newActionKeywordsHasBeenAssigned")); } } @@ -85,7 +80,7 @@ namespace Flow.Launcher } // Update action keywords text and close window - pluginViewModel.OnActionKeywordsChanged(); + _pluginViewModel.OnActionKeywordsChanged(); Close(); } } diff --git a/Flow.Launcher/Converters/TextConverter.cs b/Flow.Launcher/Converters/TextConverter.cs index 5f0e1ea82..2c4dad4a9 100644 --- a/Flow.Launcher/Converters/TextConverter.cs +++ b/Flow.Launcher/Converters/TextConverter.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using System.Windows.Data; -using Flow.Launcher.Core.Resource; using Flow.Launcher.ViewModel; namespace Flow.Launcher.Converters; @@ -23,7 +22,7 @@ public class TextConverter : IValueConverter if (translationKey is null) return id; - return InternationalizationManager.Instance.GetTranslation(translationKey); + return App.API.GetTranslation(translationKey); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new InvalidOperationException(); diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs index 53fa173a5..8b193fa1d 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml.cs @@ -1,5 +1,4 @@ -using Flow.Launcher.Core.Resource; -using Flow.Launcher.Helper; +using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure.UserSettings; using System.Collections.ObjectModel; using System.Linq; @@ -53,14 +52,13 @@ namespace Flow.Launcher Close(); } - public void UpdateItem(CustomPluginHotkey item) { updateCustomHotkey = _settings.CustomPluginHotkeys.FirstOrDefault(o => o.ActionKeyword == item.ActionKeyword && o.Hotkey == item.Hotkey); if (updateCustomHotkey == null) { - App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("invalidPluginHotkey")); + App.API.ShowMsgBox(App.API.GetTranslation("invalidPluginHotkey")); Close(); return; } @@ -68,7 +66,7 @@ namespace Flow.Launcher tbAction.Text = updateCustomHotkey.ActionKeyword; HotkeyControl.SetHotkey(updateCustomHotkey.Hotkey, false); update = true; - lblAdd.Text = InternationalizationManager.Instance.GetTranslation("update"); + lblAdd.Text = App.API.GetTranslation("update"); } private void BtnTestActionKeyword_OnClick(object sender, RoutedEventArgs e) diff --git a/Flow.Launcher/CustomShortcutSetting.xaml.cs b/Flow.Launcher/CustomShortcutSetting.xaml.cs index 416f8e049..ecbdea606 100644 --- a/Flow.Launcher/CustomShortcutSetting.xaml.cs +++ b/Flow.Launcher/CustomShortcutSetting.xaml.cs @@ -1,9 +1,7 @@ -using Flow.Launcher.Core.Resource; -using System; +using System; using System.Windows; using System.Windows.Input; using Flow.Launcher.SettingPages.ViewModels; -using Flow.Launcher.Core; namespace Flow.Launcher { @@ -41,15 +39,15 @@ namespace Flow.Launcher private void BtnAdd_OnClick(object sender, RoutedEventArgs e) { - if (String.IsNullOrEmpty(Key) || String.IsNullOrEmpty(Value)) + if (string.IsNullOrEmpty(Key) || string.IsNullOrEmpty(Value)) { - App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("emptyShortcut")); + App.API.ShowMsgBox(App.API.GetTranslation("emptyShortcut")); return; } // Check if key is modified or adding a new one if (((update && originalKey != Key) || !update) && _hotkeyVm.DoesShortcutExist(Key)) { - App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("duplicateShortcut")); + App.API.ShowMsgBox(App.API.GetTranslation("duplicateShortcut")); return; } DialogResult = !update || originalKey != Key || originalValue != Value; diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index 7b2fdfcf4..de5f5295b 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -3,7 +3,6 @@ using Flow.Launcher.Infrastructure.UserSettings; using System; using NHotkey; using NHotkey.Wpf; -using Flow.Launcher.Core.Resource; using Flow.Launcher.ViewModel; using ChefKeys; using Flow.Launcher.Infrastructure.Logger; @@ -56,8 +55,8 @@ internal static class HotKeyMapper string.Format("|HotkeyMapper.SetWithChefKeys|Error registering hotkey: {0} \nStackTrace:{1}", e.Message, e.StackTrace)); - string errorMsg = string.Format(InternationalizationManager.Instance.GetTranslation("registerHotkeyFailed"), hotkeyStr); - string errorMsgTitle = InternationalizationManager.Instance.GetTranslation("MessageBoxTitle"); + string errorMsg = string.Format(App.API.GetTranslation("registerHotkeyFailed"), hotkeyStr); + string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle"); MessageBoxEx.Show(errorMsg, errorMsgTitle); } } @@ -82,8 +81,8 @@ internal static class HotKeyMapper e.Message, e.StackTrace, hotkeyStr)); - string errorMsg = string.Format(InternationalizationManager.Instance.GetTranslation("registerHotkeyFailed"), hotkeyStr); - string errorMsgTitle = InternationalizationManager.Instance.GetTranslation("MessageBoxTitle"); + string errorMsg = string.Format(App.API.GetTranslation("registerHotkeyFailed"), hotkeyStr); + string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle"); App.API.ShowMsgBox(errorMsg, errorMsgTitle); } } @@ -107,8 +106,8 @@ internal static class HotKeyMapper string.Format("|HotkeyMapper.RemoveHotkey|Error removing hotkey: {0} \nStackTrace:{1}", e.Message, e.StackTrace)); - string errorMsg = string.Format(InternationalizationManager.Instance.GetTranslation("unregisterHotkeyFailed"), hotkeyStr); - string errorMsgTitle = InternationalizationManager.Instance.GetTranslation("MessageBoxTitle"); + string errorMsg = string.Format(App.API.GetTranslation("unregisterHotkeyFailed"), hotkeyStr); + string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle"); MessageBoxEx.Show(errorMsg, errorMsgTitle); } } diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs index 678280bba..8762a934b 100644 --- a/Flow.Launcher/HotkeyControl.xaml.cs +++ b/Flow.Launcher/HotkeyControl.xaml.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using CommunityToolkit.Mvvm.DependencyInjection; -using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.UserSettings; @@ -65,7 +64,6 @@ namespace Flow.Launcher hotkeyControl.RefreshHotkeyInterface(hotkeyControl.Hotkey); } - public static readonly DependencyProperty ChangeHotkeyProperty = DependencyProperty.Register( nameof(ChangeHotkey), typeof(ICommand), @@ -79,7 +77,6 @@ namespace Flow.Launcher set { SetValue(ChangeHotkeyProperty, value); } } - public static readonly DependencyProperty TypeProperty = DependencyProperty.Register( nameof(Type), typeof(HotkeyType), @@ -227,19 +224,18 @@ namespace Flow.Launcher private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) => hotkey.Validate(validateKeyGesture) && HotKeyMapper.CheckAvailability(hotkey); - public string EmptyHotkey => InternationalizationManager.Instance.GetTranslation("none"); + public string EmptyHotkey => App.API.GetTranslation("none"); public ObservableCollection KeysToDisplay { get; set; } = new(); public HotkeyModel CurrentHotkey { get; private set; } = new(false, false, false, false, Key.None); - public void GetNewHotkey(object sender, RoutedEventArgs e) { - OpenHotkeyDialog(); + _ = OpenHotkeyDialogAsync(); } - private async Task OpenHotkeyDialog() + private async Task OpenHotkeyDialogAsync() { if (!string.IsNullOrEmpty(Hotkey)) { @@ -262,12 +258,11 @@ namespace Flow.Launcher } } - private void SetHotkey(HotkeyModel keyModel, bool triggerValidate = true) { if (triggerValidate) { - bool hotkeyAvailable = false; + bool hotkeyAvailable; // TODO: This is a temporary way to enforce changing only the open flow hotkey to Win, and will be removed by PR #3157 if (keyModel.ToString() == "LWin" || keyModel.ToString() == "RWin") { diff --git a/Flow.Launcher/HotkeyControlDialog.xaml.cs b/Flow.Launcher/HotkeyControlDialog.xaml.cs index 2f8c5eb26..c7af8c5b8 100644 --- a/Flow.Launcher/HotkeyControlDialog.xaml.cs +++ b/Flow.Launcher/HotkeyControlDialog.xaml.cs @@ -5,7 +5,6 @@ using System.Windows; using System.Windows.Input; using ChefKeys; using CommunityToolkit.Mvvm.DependencyInjection; -using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.UserSettings; @@ -34,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 => InternationalizationManager.Instance.GetTranslation("none"); + public static string EmptyHotkey => App.API.GetTranslation("none"); private static bool isOpenFlowHotkey; @@ -42,7 +41,7 @@ public partial class HotkeyControlDialog : ContentDialog { WindowTitle = windowTitle switch { - "" or null => InternationalizationManager.Instance.GetTranslation("hotkeyRegTitle"), + "" or null => App.API.GetTranslation("hotkeyRegTitle"), _ => windowTitle }; DefaultHotkey = defaultHotkey; @@ -141,14 +140,14 @@ public partial class HotkeyControlDialog : ContentDialog if (_hotkeySettings.RegisteredHotkeys.FirstOrDefault(v => v.Hotkey == hotkey) is { } registeredHotkeyData) { var description = string.Format( - InternationalizationManager.Instance.GetTranslation(registeredHotkeyData.DescriptionResourceKey), + App.API.GetTranslation(registeredHotkeyData.DescriptionResourceKey), registeredHotkeyData.DescriptionFormatVariables ); Alert.Visibility = Visibility.Visible; if (registeredHotkeyData.RemoveHotkey is not null) { tbMsg.Text = string.Format( - InternationalizationManager.Instance.GetTranslation("hotkeyUnavailableEditable"), + App.API.GetTranslation("hotkeyUnavailableEditable"), description ); SaveBtn.IsEnabled = false; @@ -160,7 +159,7 @@ public partial class HotkeyControlDialog : ContentDialog else { tbMsg.Text = string.Format( - InternationalizationManager.Instance.GetTranslation("hotkeyUnavailableUneditable"), + App.API.GetTranslation("hotkeyUnavailableUneditable"), description ); SaveBtn.IsEnabled = false; @@ -176,7 +175,7 @@ public partial class HotkeyControlDialog : ContentDialog if (!CheckHotkeyAvailability(hotkey.Value, true)) { - tbMsg.Text = InternationalizationManager.Instance.GetTranslation("hotkeyUnavailable"); + tbMsg.Text = App.API.GetTranslation("hotkeyUnavailable"); Alert.Visibility = Visibility.Visible; SaveBtn.IsEnabled = false; SaveBtn.Visibility = Visibility.Visible; diff --git a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs index 880bfd9bc..64f52edff 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs @@ -17,7 +17,9 @@ namespace Flow.Launcher.Resources.Pages Ioc.Default.GetRequiredService().PageNum = 1; InitializeComponent(); } - private Internationalization _translater => InternationalizationManager.Instance; + + private readonly Internationalization _translater = Ioc.Default.GetRequiredService(); + public List Languages => _translater.LoadAvailableLanguages(); public Settings Settings { get; set; } @@ -30,12 +32,11 @@ namespace Flow.Launcher.Resources.Pages } set { - InternationalizationManager.Instance.ChangeLanguage(value); + _translater.ChangeLanguage(value); - if (InternationalizationManager.Instance.PromptShouldUsePinyin(value)) + if (_translater.PromptShouldUsePinyin(value)) Settings.ShouldUsePinyin = true; } } - } } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 35dbab647..57eb796d3 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Windows.Forms; -using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; @@ -19,12 +17,14 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public Settings Settings { get; } private readonly Updater _updater; private readonly IPortable _portable; + private readonly Internationalization _translater; - public SettingsPaneGeneralViewModel(Settings settings, Updater updater, IPortable portable) + public SettingsPaneGeneralViewModel(Settings settings, Updater updater, IPortable portable, Internationalization translater) { Settings = settings; _updater = updater; _portable = portable; + _translater = translater; UpdateEnumDropdownLocalizations(); } @@ -32,7 +32,6 @@ public partial class SettingsPaneGeneralViewModel : BaseModel public class SearchWindowAlignData : DropdownDataGeneric { } public class SearchPrecisionData : DropdownDataGeneric { } public class LastQueryModeData : DropdownDataGeneric { } - public bool StartFlowLauncherOnSystemStartup { @@ -61,7 +60,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel } catch (Exception e) { - Notification.Show(InternationalizationManager.Instance.GetTranslation("setAutoStartFailed"), + Notification.Show(App.API.GetTranslation("setAutoStartFailed"), e.Message); } } @@ -89,7 +88,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel } catch (Exception e) { - Notification.Show(InternationalizationManager.Instance.GetTranslation("setAutoStartFailed"), + Notification.Show(App.API.GetTranslation("setAutoStartFailed"), e.Message); } } @@ -121,7 +120,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 bool _portableMode = DataLocation.PortableDataLocationInUse(); + private static bool _portableMode = DataLocation.PortableDataLocationInUse(); public bool PortableMode { @@ -173,9 +172,9 @@ public partial class SettingsPaneGeneralViewModel : BaseModel get => Settings.Language; set { - InternationalizationManager.Instance.ChangeLanguage(value); + _translater.ChangeLanguage(value); - if (InternationalizationManager.Instance.PromptShouldUsePinyin(value)) + if (_translater.PromptShouldUsePinyin(value)) ShouldUsePinyin = true; UpdateEnumDropdownLocalizations(); @@ -188,14 +187,14 @@ public partial class SettingsPaneGeneralViewModel : BaseModel set => Settings.ShouldUsePinyin = value; } - public List Languages => InternationalizationManager.Instance.LoadAvailableLanguages(); + public List Languages => _translater.LoadAvailableLanguages(); public string AlwaysPreviewToolTip => string.Format( - InternationalizationManager.Instance.GetTranslation("AlwaysPreviewToolTip"), + App.API.GetTranslation("AlwaysPreviewToolTip"), Settings.PreviewHotkey ); - private string GetFileFromDialog(string title, string filter = "") + private static string GetFileFromDialog(string title, string filter = "") { var dlg = new OpenFileDialog { @@ -237,7 +236,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel private void SelectPython() { var selectedFile = GetFileFromDialog( - InternationalizationManager.Instance.GetTranslation("selectPythonExecutable"), + App.API.GetTranslation("selectPythonExecutable"), "Python|pythonw.exe" ); @@ -249,7 +248,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel private void SelectNode() { var selectedFile = GetFileFromDialog( - InternationalizationManager.Instance.GetTranslation("selectNodeExecutable"), + App.API.GetTranslation("selectNodeExecutable"), "node|*.exe" ); diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs index b13aaefe3..7a7c19dd3 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneHotkeyViewModel.cs @@ -1,7 +1,6 @@ using System.Linq; using System.Windows; using CommunityToolkit.Mvvm.Input; -using Flow.Launcher.Core.Resource; using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Hotkey; @@ -41,15 +40,15 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomPluginHotkey; if (item is null) { - App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(App.API.GetTranslation("pleaseSelectAnItem")); return; } var result = App.API.ShowMsgBox( string.Format( - InternationalizationManager.Instance.GetTranslation("deleteCustomHotkeyWarning"), item.Hotkey + App.API.GetTranslation("deleteCustomHotkeyWarning"), item.Hotkey ), - InternationalizationManager.Instance.GetTranslation("delete"), + App.API.GetTranslation("delete"), MessageBoxButton.YesNo ); @@ -66,7 +65,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomPluginHotkey; if (item is null) { - App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(App.API.GetTranslation("pleaseSelectAnItem")); return; } @@ -87,15 +86,15 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomShortcut; if (item is null) { - App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(App.API.GetTranslation("pleaseSelectAnItem")); return; } var result = App.API.ShowMsgBox( string.Format( - InternationalizationManager.Instance.GetTranslation("deleteCustomShortcutWarning"), item.Key, item.Value + App.API.GetTranslation("deleteCustomShortcutWarning"), item.Key, item.Value ), - InternationalizationManager.Instance.GetTranslation("delete"), + App.API.GetTranslation("delete"), MessageBoxButton.YesNo ); @@ -111,7 +110,7 @@ public partial class SettingsPaneHotkeyViewModel : BaseModel var item = SelectedCustomShortcut; if (item is null) { - App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation("pleaseSelectAnItem")); + App.API.ShowMsgBox(App.API.GetTranslation("pleaseSelectAnItem")); return; } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs index e2f9e516c..38a6ef31e 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneProxyViewModel.cs @@ -1,7 +1,6 @@ using System.Net; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core; -using Flow.Launcher.Core.Resource; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; @@ -22,7 +21,7 @@ public partial class SettingsPaneProxyViewModel : BaseModel private void OnTestProxyClicked() { var message = TestProxy(); - App.API.ShowMsgBox(InternationalizationManager.Instance.GetTranslation(message)); + App.API.ShowMsgBox(App.API.GetTranslation(message)); } private string TestProxy() diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs index dd7fd13a9..569d489d2 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs @@ -2,6 +2,7 @@ using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; +using Flow.Launcher.Core.Resource; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.SettingPages.ViewModels; @@ -18,7 +19,8 @@ public partial class SettingsPaneGeneral var settings = Ioc.Default.GetRequiredService(); var updater = Ioc.Default.GetRequiredService(); var portable = Ioc.Default.GetRequiredService(); - _viewModel = new SettingsPaneGeneralViewModel(settings, updater, portable); + var translater = Ioc.Default.GetRequiredService(); + _viewModel = new SettingsPaneGeneralViewModel(settings, updater, portable, translater); DataContext = _viewModel; InitializeComponent(); } From 0a8963b74ee05da73afbcd05d9e817925c79477b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 21:16:33 +0800 Subject: [PATCH 0794/1798] Remove Notification.Show & _mainViewModel.Show(); --- Flow.Launcher/App.xaml.cs | 2 +- Flow.Launcher/Helper/HotKeyMapper.cs | 2 +- .../SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs | 6 ++---- Flow.Launcher/ViewModel/MainViewModel.cs | 3 +-- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 90fefe0a6..89faa105e 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -343,7 +343,7 @@ namespace Flow.Launcher public void OnSecondAppStarted() { - Ioc.Default.GetRequiredService().Show(); + API.ShowMainWindow(); } #endregion diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index de5f5295b..b7b39ff31 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -136,7 +136,7 @@ internal static class HotKeyMapper if (_mainViewModel.ShouldIgnoreHotkeys()) return; - _mainViewModel.Show(); + App.API.ShowMainWindow(); _mainViewModel.ChangeQueryText(hotkey.ActionKeyword, true); }); } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 57eb796d3..069a7cb24 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -60,8 +60,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel } catch (Exception e) { - Notification.Show(App.API.GetTranslation("setAutoStartFailed"), - e.Message); + App.API.ShowMsg(App.API.GetTranslation("setAutoStartFailed"), e.Message); } } } @@ -88,8 +87,7 @@ public partial class SettingsPaneGeneralViewModel : BaseModel } catch (Exception e) { - Notification.Show(App.API.GetTranslation("setAutoStartFailed"), - e.Message); + App.API.ShowMsg(App.API.GetTranslation("setAutoStartFailed"), e.Message); } } } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 66481cad6..4a6c1d639 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -16,7 +16,6 @@ using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Hotkey; -using Flow.Launcher.Infrastructure.Image; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Infrastructure.UserSettings; @@ -275,7 +274,7 @@ namespace Flow.Launcher.ViewModel Hide(); await PluginManager.ReloadDataAsync().ConfigureAwait(false); - Notification.Show(App.API.GetTranslation("success"), + App.API.ShowMsg(App.API.GetTranslation("success"), App.API.GetTranslation("completedSuccessfully")); } From 1bd7f1471ac73e60d2aeb62fbe6b099b381942b9 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 21:19:09 +0800 Subject: [PATCH 0795/1798] Improve GetTranslation usage --- Flow.Launcher.Core/Updater.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Core/Updater.cs b/Flow.Launcher.Core/Updater.cs index 20b884b3d..83d4fd9e0 100644 --- a/Flow.Launcher.Core/Updater.cs +++ b/Flow.Launcher.Core/Updater.cs @@ -9,8 +9,6 @@ using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using System.Windows; -using CommunityToolkit.Mvvm.DependencyInjection; -using Flow.Launcher.Core.Resource; using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Http; @@ -131,7 +129,7 @@ namespace Flow.Launcher.Core await using var jsonStream = await Http.GetStreamAsync(api).ConfigureAwait(false); - var releases = await System.Text.Json.JsonSerializer.DeserializeAsync>(jsonStream).ConfigureAwait(false); + var releases = await JsonSerializer.DeserializeAsync>(jsonStream).ConfigureAwait(false); var latest = releases.Where(r => !r.Prerelease).OrderByDescending(r => r.PublishedAt).First(); var latestUrl = latest.HtmlUrl.Replace("/tag/", "/download/"); @@ -146,10 +144,9 @@ namespace Flow.Launcher.Core return manager; } - private static string NewVersionTips(string version) + private string NewVersionTips(string version) { - var translator = Ioc.Default.GetRequiredService(); - var tips = string.Format(translator.GetTranslation("newVersionTips"), version); + var tips = string.Format(_api.GetTranslation("newVersionTips"), version); return tips; } From 509705413729ac658cd5ae70df06349a710a0615 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 21:20:32 +0800 Subject: [PATCH 0796/1798] Improve log code quality --- Flow.Launcher.Core/Plugin/PluginManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 4c85fb061..29d91dc8d 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -205,7 +205,7 @@ namespace Flow.Launcher.Core.Plugin } catch (Exception e) { - Log.Exception(nameof(PluginManager), $"Fail to Init plugin: {pair.Metadata.Name}", e); + Log.Exception(ClassName, $"Fail to Init plugin: {pair.Metadata.Name}", e); pair.Metadata.Disabled = true; failedPlugins.Enqueue(pair); } From 9f11c8739aee2ac3362b025f69e858b9e2c20240 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 21:26:27 +0800 Subject: [PATCH 0797/1798] Remove _mainViewModel.ChangeQueryText --- Flow.Launcher/Helper/HotKeyMapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index b7b39ff31..5e3b30281 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -137,7 +137,7 @@ internal static class HotKeyMapper return; App.API.ShowMainWindow(); - _mainViewModel.ChangeQueryText(hotkey.ActionKeyword, true); + App.API.ChangeQuery(hotkey.ActionKeyword, true); }); } From f47699829c4200754491b60082330f6f721b5e29 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 9 Apr 2025 21:27:03 +0800 Subject: [PATCH 0798/1798] Remove MessageBoxEx.Show --- Flow.Launcher/Helper/HotKeyMapper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/Helper/HotKeyMapper.cs b/Flow.Launcher/Helper/HotKeyMapper.cs index 5e3b30281..0771a6074 100644 --- a/Flow.Launcher/Helper/HotKeyMapper.cs +++ b/Flow.Launcher/Helper/HotKeyMapper.cs @@ -57,7 +57,7 @@ internal static class HotKeyMapper e.StackTrace)); string errorMsg = string.Format(App.API.GetTranslation("registerHotkeyFailed"), hotkeyStr); string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle"); - MessageBoxEx.Show(errorMsg, errorMsgTitle); + App.API.ShowMsgBox(errorMsg, errorMsgTitle); } } @@ -108,7 +108,7 @@ internal static class HotKeyMapper e.StackTrace)); string errorMsg = string.Format(App.API.GetTranslation("unregisterHotkeyFailed"), hotkeyStr); string errorMsgTitle = App.API.GetTranslation("MessageBoxTitle"); - MessageBoxEx.Show(errorMsg, errorMsgTitle); + App.API.ShowMsgBox(errorMsg, errorMsgTitle); } } From 7fdc2161c43acb1196ea29ea1614934268f7f118 Mon Sep 17 00:00:00 2001 From: DB p Date: Wed, 9 Apr 2025 23:36:51 +0900 Subject: [PATCH 0799/1798] Fix small things for merging dev --- Flow.Launcher/Languages/en.xaml | 1 - Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index dc0799f90..1b0400d7b 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -130,7 +130,6 @@ Open Use Legacy Korean IME You can change the IME settings directly from here without opening a separate settings window - Wait time before showing results after typing stops. Higher values wait longer. (ms) Search Plugin diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index ca8d2fd6c..6b0f9d440 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -220,12 +220,12 @@ + ValidationMode="InvalidInputOverwritten" + Value="{Binding SearchDelayTimeValue}" /> @@ -325,7 +325,7 @@ IsIconVisible="True" Length="Long" Message="{DynamicResource KoreanImeGuide}" - Type="Info" + Type="Warning" Visibility="{Binding LegacyKoreanIMEEnabled, Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=Inverted, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" /> From 77ffafc582e34898e17167ac80830c6c8181ccb4 Mon Sep 17 00:00:00 2001 From: DB p Date: Wed, 9 Apr 2025 23:43:36 +0900 Subject: [PATCH 0800/1798] Fix string --- Flow.Launcher/Languages/en.xaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 1b0400d7b..9315f05c9 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -148,6 +148,10 @@ Change Action Keywords Plugin seach delay time Change Plugin Seach Delay Time + Advanced Settings: + Enabled + Priority + Search Delay Current Priority New Priority Priority From 3c49d8e7304a352a49b9f96541eab9e8141d7fe9 Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 10 Apr 2025 00:38:35 +0900 Subject: [PATCH 0801/1798] Fix Binding error --- Flow.Launcher/Resources/Controls/InfoBar.xaml | 36 ++++++++++--------- .../Resources/Controls/InfoBar.xaml.cs | 4 +-- .../SettingsPaneGeneralViewModel.cs | 16 ++++++--- .../Views/SettingsPaneGeneral.xaml | 1 + 4 files changed, 32 insertions(+), 25 deletions(-) diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml b/Flow.Launcher/Resources/Controls/InfoBar.xaml index 1713b3459..f82a32a8b 100644 --- a/Flow.Launcher/Resources/Controls/InfoBar.xaml +++ b/Flow.Launcher/Resources/Controls/InfoBar.xaml @@ -2,6 +2,7 @@ x:Class="Flow.Launcher.Resources.Controls.InfoBar" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls" xmlns:converters="clr-namespace:Flow.Launcher.Converters" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" @@ -26,21 +27,22 @@ - - - + + + + Text="{Binding RelativeSource={RelativeSource AncestorType=cc:InfoBar}, Path=Title}" /> diff --git a/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs index f50bc349e..8b82dc3b6 100644 --- a/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs +++ b/Flow.Launcher/Resources/Controls/InfoBar.xaml.cs @@ -19,9 +19,7 @@ namespace Flow.Launcher.Resources.Controls UpdateMessageVisibility(); UpdateOrientation(); UpdateIconAlignmentAndMargin(); - - // DataContext 설정 (예시) - this.DataContext = this; // InfoBar 자체를 DataContext로 사용 + //this.DataContext = this; } public static readonly DependencyProperty TypeProperty = diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index 9590f7283..b98d76000 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -188,15 +188,21 @@ public partial class SettingsPaneGeneralViewModel : BaseModel UpdateEnumDropdownLocalizations(); } } - - public bool LegacyKoreanIMEEnabled + public bool LegacyKoreanIMEEnabled { get => IsLegacyKoreanIMEEnabled(); set { - SetLegacyKoreanIMEEnabled(value); - OnPropertyChanged(nameof(LegacyKoreanIMEEnabled)); - OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero)); + Debug.WriteLine($"[DEBUG] LegacyKoreanIMEEnabled 변경: {value}"); + if (SetLegacyKoreanIMEEnabled(value)) + { + OnPropertyChanged(nameof(LegacyKoreanIMEEnabled)); + OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero)); + } + else + { + Debug.WriteLine("[DEBUG] LegacyKoreanIMEEnabled 설정 실패"); + } } } diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 6b0f9d440..16db1c676 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -322,6 +322,7 @@ Title="{DynamicResource KoreanImeTitle}" Margin="0 12 0 0" Closable="False" + DataContext="{Binding RelativeSource={RelativeSource AncestorType=Border}, Path=DataContext}" IsIconVisible="True" Length="Long" Message="{DynamicResource KoreanImeGuide}" From d9a353b4522b1471e18d684fe270256626094323 Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 10 Apr 2025 00:52:34 +0900 Subject: [PATCH 0802/1798] - Fix String and adjust messages - Adjust Margin - Cleanup comment --- Flow.Launcher/Languages/en.xaml | 11 +- .../SettingsPaneGeneralViewModel.cs | 175 +++++++++--------- .../Views/SettingsPaneGeneral.xaml | 6 +- 3 files changed, 96 insertions(+), 96 deletions(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 9315f05c9..bf430b6f5 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -118,18 +118,17 @@ Very short Information for Korean IME user - You're using the Korean language! The Korean input method used in Windows 11 may cause some issues in Flow Launcher. - If you experience any problems, you may need to enable compatibility mode for the Korean IME. + The Korean input method used in Windows 11 may cause some issues in Flow Launcher. + If you experience any problems, you may need to enable "Use previous version of Korean IME". Open Setting in Windows 11 and go to: Time & Language > Language & Region > Korean > Language Options > Keyboard - Microsoft IME > Compatibility, and enable "Use previous version of Microsoft IME". - You can open the relevant menu using the option below, or change the setting directly without manually opening the settings page. Open Language and Region System Settings - Opens the Korean IME setting locationKorean > Language Options > Keyboard - Microsoft IME > Compatibility + Opens the Korean IME setting location. Go to Korean > Language Options > Keyboard - Microsoft IME > Compatibility Open - Use Legacy Korean IME - You can change the IME settings directly from here without opening a separate settings window + Use Previous Korean IME + You can change the Previous Korean IME settings directly from here Search Plugin diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs index b98d76000..701de4361 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs @@ -189,128 +189,129 @@ public partial class SettingsPaneGeneralViewModel : BaseModel } } public bool LegacyKoreanIMEEnabled +{ + get => IsLegacyKoreanIMEEnabled(); + set { - get => IsLegacyKoreanIMEEnabled(); - set + Debug.WriteLine($"[DEBUG] LegacyKoreanIMEEnabled changed: {value}"); + if (SetLegacyKoreanIMEEnabled(value)) { - Debug.WriteLine($"[DEBUG] LegacyKoreanIMEEnabled 변경: {value}"); - if (SetLegacyKoreanIMEEnabled(value)) - { - OnPropertyChanged(nameof(LegacyKoreanIMEEnabled)); - OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero)); - } - else - { - Debug.WriteLine("[DEBUG] LegacyKoreanIMEEnabled 설정 실패"); - } + OnPropertyChanged(nameof(LegacyKoreanIMEEnabled)); + OnPropertyChanged(nameof(KoreanIMERegistryValueIsZero)); + } + else + { + Debug.WriteLine("[DEBUG] Failed to set LegacyKoreanIMEEnabled"); } } +} - public bool KoreanIMERegistryKeyExists => IsKoreanIMEExist(); +public bool KoreanIMERegistryKeyExists => IsKoreanIMEExist(); - public bool KoreanIMERegistryValueIsZero - { - get - { - object value = GetLegacyKoreanIMERegistryValue(); - if (value is int intValue) - { - return intValue == 0; - } - else if (value != null && int.TryParse(value.ToString(), out int parsedValue)) - { - return parsedValue == 0; - } - - return false; - } - } - - bool IsKoreanIMEExist() - { - return GetLegacyKoreanIMERegistryValue() != null; - } - - bool IsLegacyKoreanIMEEnabled() +public bool KoreanIMERegistryValueIsZero +{ + get { object value = GetLegacyKoreanIMERegistryValue(); - if (value is int intValue) { - return intValue == 1; + return intValue == 0; } else if (value != null && int.TryParse(value.ToString(), out int parsedValue)) { - return parsedValue == 1; + return parsedValue == 0; } return false; } +} - bool SetLegacyKoreanIMEEnabled(bool enable) +bool IsKoreanIMEExist() +{ + return GetLegacyKoreanIMERegistryValue() != null; +} + +bool IsLegacyKoreanIMEEnabled() +{ + object value = GetLegacyKoreanIMERegistryValue(); + + if (value is int intValue) { - const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}"; - const string valueName = "NoTsf3Override5"; + return intValue == 1; + } + else if (value != null && int.TryParse(value.ToString(), out int parsedValue)) + { + return parsedValue == 1; + } - try + return false; +} + +bool SetLegacyKoreanIMEEnabled(bool enable) +{ + const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}"; + const string valueName = "NoTsf3Override5"; + + try + { + using (RegistryKey key = Registry.CurrentUser.CreateSubKey(subKeyPath)) { - using (RegistryKey key = Registry.CurrentUser.CreateSubKey(subKeyPath)) + if (key != null) { - if (key != null) - { - int value = enable ? 1 : 0; - key.SetValue(valueName, value, RegistryValueKind.DWord); - return true; - } - else - { - Debug.WriteLine($"[IME DEBUG] 레지스트리 키 생성 또는 열기 실패: {subKeyPath}"); - } + int value = enable ? 1 : 0; + key.SetValue(valueName, value, RegistryValueKind.DWord); + return true; + } + else + { + Debug.WriteLine($"[IME DEBUG] Failed to create or open registry key: {subKeyPath}"); } } - catch (Exception ex) - { - Debug.WriteLine($"[IME DEBUG] 레지스트리 설정 중 예외 발생: {ex.Message}"); - } - - return false; + } + catch (Exception ex) + { + Debug.WriteLine($"[IME DEBUG] Exception occurred while setting registry: {ex.Message}"); } - private object GetLegacyKoreanIMERegistryValue() - { - const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}"; - const string valueName = "NoTsf3Override5"; + return false; +} - try +private object GetLegacyKoreanIMERegistryValue() +{ + const string subKeyPath = @"Software\Microsoft\input\tsf\tsf3override\{A028AE76-01B1-46C2-99C4-ACD9858AE02F}"; + const string valueName = "NoTsf3Override5"; + + try + { + using (RegistryKey key = Registry.CurrentUser.OpenSubKey(subKeyPath)) { - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(subKeyPath)) + if (key != null) { - if (key != null) - { - return key.GetValue(valueName); - } + return key.GetValue(valueName); } } - catch (Exception ex) - { - Debug.WriteLine($"[IME DEBUG] 예외 발생: {ex.Message}"); - } - - return null; } - - private void OpenImeSettings() + catch (Exception ex) { - try - { - Process.Start(new ProcessStartInfo("ms-settings:regionlanguage") { UseShellExecute = true }); - } - catch (Exception e) - { - Debug.WriteLine($"Error opening IME settings: {e.Message}"); - } + Debug.WriteLine($"[IME DEBUG] Exception occurred: {ex.Message}"); } + return null; +} + +private void OpenImeSettings() +{ + try + { + Process.Start(new ProcessStartInfo("ms-settings:regionlanguage") { UseShellExecute = true }); + } + catch (Exception e) + { + Debug.WriteLine($"Error opening IME settings: {e.Message}"); + } +} + + public bool ShouldUsePinyin { get => Settings.ShouldUsePinyin; diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 16db1c676..5304824fe 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -320,7 +320,7 @@ - + + Sub="{DynamicResource KoreanImeOpenLinkToolTip}"> - + - + + IsEnabled="{Binding NextEnabled, Mode=OneWay}"> + + From 25f39f6934921cc52a4f59243f7adef430b2ed0e Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 24 Apr 2025 11:08:02 +0900 Subject: [PATCH 0946/1798] Add dynamic font support for the setting window --- Flow.Launcher/App.xaml.cs | 2 ++ Flow.Launcher/SettingWindow.xaml | 1 + 2 files changed, 3 insertions(+) diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 87698a545..606536dad 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; +using System.Windows.Media; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core; using Flow.Launcher.Core.Configuration; @@ -175,6 +176,7 @@ namespace Flow.Launcher await imageLoadertask; _mainWindow = new MainWindow(); + Current.Resources["SettingWindowFont"] = new FontFamily(_settings.SettingWindowFont); API.LogInfo(ClassName, "Dependencies Info:{ErrorReporting.DependenciesInfo()}"); diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml index ab27b235a..a34777d30 100644 --- a/Flow.Launcher/SettingWindow.xaml +++ b/Flow.Launcher/SettingWindow.xaml @@ -13,6 +13,7 @@ MinHeight="600" d:DataContext="{d:DesignInstance vm:SettingWindowViewModel}" Closed="OnClosed" + FontFamily="{Binding Settings.SettingWindowFont, Mode=TwoWay}" Icon="Images\app.ico" Left="{Binding SettingWindowLeft, Mode=TwoWay}" Loaded="OnLoaded" From 8432fa3b40ceb87916676fc5021e7e72dac54078 Mon Sep 17 00:00:00 2001 From: DB p Date: Thu, 24 Apr 2025 11:25:21 +0900 Subject: [PATCH 0947/1798] Add SettingWindowFont definition to CustomControlTemplate --- Flow.Launcher/Resources/CustomControlTemplate.xaml | 1 + Flow.Launcher/Resources/SettingWindowStyle.xaml | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Flow.Launcher/Resources/CustomControlTemplate.xaml b/Flow.Launcher/Resources/CustomControlTemplate.xaml index be68fc1b1..4e94da526 100644 --- a/Flow.Launcher/Resources/CustomControlTemplate.xaml +++ b/Flow.Launcher/Resources/CustomControlTemplate.xaml @@ -5,6 +5,7 @@ xmlns:ui="http://schemas.modernwpf.com/2019"> + Segoe UI diff --git a/Flow.Launcher/Resources/SettingWindowStyle.xaml b/Flow.Launcher/Resources/SettingWindowStyle.xaml index c59baeaea..60655fa7c 100644 --- a/Flow.Launcher/Resources/SettingWindowStyle.xaml +++ b/Flow.Launcher/Resources/SettingWindowStyle.xaml @@ -7,8 +7,6 @@ - Segoe UI - F1 M512,512z M0,0z M448,256C448,150,362,64,256,64L256,448C362,448,448,362,448,256z M0,256A256,256,0,1,1,512,256A256,256,0,1,1,0,256z + + {DynamicResource SettingWindowFont} + @@ -1360,7 +1363,6 @@ - @@ -1584,6 +1586,7 @@ diff --git a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml index 32fdb62fc..b6a99d9e9 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml +++ b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml @@ -127,7 +127,7 @@ Style="{DynamicResource StyleImageFadeIn}" /> - - + + @@ -89,29 +89,29 @@ - + @@ -81,26 +81,26 @@ Canvas.Left="0" Width="450" Height="280" - Margin="0,0,0,0" + Margin="0 0 0 0" Source="../../images/page_img01.png" Style="{DynamicResource StyleImageFadeIn}" /> - + diff --git a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml index 3df4b506e..7495231ae 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml +++ b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml @@ -79,18 +79,18 @@ - + - + - + + Padding="5 18 0 0"> + Margin="5 24 0 0"> @@ -97,8 +97,8 @@ - - + + - + @@ -86,23 +86,23 @@ Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" - Margin="5,0,0,20"> + Margin="5 0 0 20"> @@ -180,18 +180,18 @@ Grid.Row="1" Background="{DynamicResource PopupButtonAreaBGColor}" BorderBrush="{DynamicResource PopupButtonAreaBorderColor}" - BorderThickness="0,1,0,0"> + BorderThickness="0 1 0 0"> - - + + - + - + + BorderThickness="0 1 0 0"> - - + + - + @@ -104,16 +104,16 @@ HorizontalAlignment="Stretch" Click="BrowseButton_Click" Content="{DynamicResource flowlauncher_plugin_program_browse}" - Visibility="{Binding IsCustomSource, Converter={StaticResource BooleanToVisibilityConverter}}" - DockPanel.Dock="Right" /> + DockPanel.Dock="Right" + Visibility="{Binding IsCustomSource, Converter={StaticResource BooleanToVisibilityConverter}}" /> + VerticalAlignment="Center" + IsReadOnly="{Binding IsNotCustomSource}" + Text="{Binding Location, Mode=TwoWay}" /> + Margin="10 0" + VerticalAlignment="Center" + IsChecked="{Binding Enabled, Mode=TwoWay}" /> + BorderThickness="0 1 0 0"> - + - + @@ -151,82 +151,82 @@ TextWrapping="Wrap" /> - + - + appref-ms exe lnk + BorderThickness="1 0 0 0"> @@ -237,27 +237,27 @@ Grid.Row="1" Background="{DynamicResource PopupButtonAreaBGColor}" BorderBrush="{DynamicResource PopupButtonAreaBorderColor}" - BorderThickness="0,1,0,0"> + BorderThickness="0 1 0 0"> From 9b666d31363796bef10e8f031fe99b7d7e13ee73 Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 29 Apr 2025 20:06:46 +0900 Subject: [PATCH 0980/1798] Add Flyout UI for Filter --- .../Views/SettingsPanePluginStore.xaml | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml index 66c1cb1bf..fde022da7 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml @@ -65,34 +65,33 @@ Command="{Binding RefreshExternalPluginsCommand}" Content="{DynamicResource refresh}" FontSize="13" /> - - - - + Date: Tue, 29 Apr 2025 19:31:37 +0800 Subject: [PATCH 0981/1798] Adjust margin & Improve ui --- .../SettingPages/Views/SettingsPanePluginStore.xaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml index fde022da7..df9cc3556 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml @@ -58,14 +58,14 @@ Orientation="Horizontal"> + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs new file mode 100644 index 000000000..9d2c54e2d --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Windows; +using System.Windows.Forms; +using Flow.Launcher.Plugin.Explorer.Search; +using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; + +namespace Flow.Launcher.Plugin.Explorer.Views; + +public partial class QuickAccessLinkSettings : INotifyPropertyChanged +{ + + private string _selectedPath; + public string SelectedPath + { + get => _selectedPath; + set + { + if (_selectedPath != value) + { + _selectedPath = value; + OnPropertyChanged(); + SelectedName = GetPathName(); + } + } + } + + + private string _selectedName; + public string SelectedName + { + get => _selectedName; + set + { + if (_selectedName != value) + { + _selectedName = value; + OnPropertyChanged(); + } + } + } + + + public QuickAccessLinkSettings() + { + InitializeComponent(); + } + + + + private void BtnCancel_OnClick(object sender, RoutedEventArgs e) + { + DialogResult = false; + Close(); + } + + private void OnDoneButtonClick(object sender, RoutedEventArgs e) + { + var container = Settings.QuickAccessLinks; + + + // Lembrar de colocar uma logica pra evitar path e name vazios + var newAccessLink = new AccessLink + { + Name = SelectedName, + Path = SelectedPath + }; + container.Add(newAccessLink); + DialogResult = false; + Close(); + } + + private void SelectPath_OnClick(object commandParameter, RoutedEventArgs e) + { + var folderBrowserDialog = new FolderBrowserDialog(); + + if (folderBrowserDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) + return; + + SelectedPath = folderBrowserDialog.SelectedPath; + } + + private string GetPathName() + { + if (string.IsNullOrEmpty(SelectedPath)) return ""; + var path = SelectedPath.EndsWith(Constants.DirectorySeparator) ? SelectedPath[0..^1] : SelectedPath; + + if (path.EndsWith(':')) + return path[0..^1] + " Drive"; + + return path.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None) + .Last(); + } + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + protected bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) + { + if (EqualityComparer.Default.Equals(field, value)) return false; + field = value; + OnPropertyChanged(propertyName); + return true; + } +} + From 3777e2b6d86bfa2f689c942ee9bbf186dc50138d Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sun, 25 May 2025 02:36:55 -0300 Subject: [PATCH 1162/1798] Changing QuickAccessLinks property to static This change is necessary for quick access settings window --- Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 4f83fc72e..2380a1ec9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -15,7 +15,7 @@ namespace Flow.Launcher.Plugin.Explorer { public int MaxResult { get; set; } = 100; - public ObservableCollection QuickAccessLinks { get; set; } = new(); + public static ObservableCollection QuickAccessLinks { get; set; } = new(); public ObservableCollection IndexSearchExcludedSubdirectoryPaths { get; set; } = new ObservableCollection(); From 61aca7409668890b1a55a14457ec02f0414d1209 Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sun, 25 May 2025 02:41:17 -0300 Subject: [PATCH 1163/1798] Separating add commands between QuickAccessLink and IndexSearchExcludedPaths --- .../ViewModels/SettingsViewModel.cs | 27 ++++++++++--------- .../Views/ExplorerSettings.xaml | 4 +-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index fb33dacab..508e20893 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -365,27 +365,28 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels } [RelayCommand] - private void AddLink(object commandParameter) + private void AddQuickAccessLink(object commandParameter) { - var container = commandParameter switch - { - "QuickAccessLink" => Settings.QuickAccessLinks, - "IndexSearchExcludedPaths" => Settings.IndexSearchExcludedSubdirectoryPaths, - _ => throw new ArgumentOutOfRangeException(nameof(commandParameter)) - }; - - ArgumentNullException.ThrowIfNull(container); - + var quickAccessLinkSettings = new QuickAccessLinkSettings(); + quickAccessLinkSettings.ShowDialog(); + } + + + [RelayCommand] + private void AddIndexSearchExcludePaths(object commandParameter) + { + var container = Settings.IndexSearchExcludedSubdirectoryPaths; + var folderBrowserDialog = new FolderBrowserDialog(); - + if (folderBrowserDialog.ShowDialog() != DialogResult.OK) return; - + var newAccessLink = new AccessLink { Path = folderBrowserDialog.SelectedPath }; - + container.Add(newAccessLink); } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index 3ef61573d..07f05b1c1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -762,7 +762,7 @@ From bc2648c216b4ee485c584bd81e1abb3ada9ba3cb Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sun, 25 May 2025 16:05:26 -0300 Subject: [PATCH 1171/1798] Code quality --- .../ViewModels/SettingsViewModel.cs | 4 ++-- .../Views/QuickAccessLinkSettings.xaml.cs | 23 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 447e72736..6237deabb 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -383,14 +383,14 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels return; } - var quickAccessLinkSettings = new QuickAccessLinkSettings(Settings,SelectedQuickAccessLink); + var quickAccessLinkSettings = new QuickAccessLinkSettings(Settings.QuickAccessLinks,SelectedQuickAccessLink); quickAccessLinkSettings.ShowDialog(); } [RelayCommand] private void AddQuickAccessLink(object commandParameter) { - var quickAccessLinkSettings = new QuickAccessLinkSettings(Settings); + var quickAccessLinkSettings = new QuickAccessLinkSettings(Settings.QuickAccessLinks); quickAccessLinkSettings.ShowDialog(); } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs index 5eda62558..28cd68bad 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; @@ -53,20 +54,21 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged private bool IsEdit { get; set; } [CanBeNull] private AccessLink SelectedAccessLink { get; set; } - private Settings Settings { get; } - public QuickAccessLinkSettings(Settings settings) + public ObservableCollection QuickAccessLinks { get; set; } + + public QuickAccessLinkSettings(ObservableCollection quickAccessLinks) { - Settings = settings; + QuickAccessLinks = quickAccessLinks; InitializeComponent(); } - public QuickAccessLinkSettings(Settings settings,AccessLink selectedAccessLink) + public QuickAccessLinkSettings(ObservableCollection quickAccessLinks,AccessLink selectedAccessLink) { IsEdit = true; _selectedName = selectedAccessLink.Name; _selectedPath = selectedAccessLink.Path; SelectedAccessLink = selectedAccessLink; - Settings = settings; + QuickAccessLinks = quickAccessLinks; InitializeComponent(); } @@ -88,7 +90,7 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged return; } - if (Settings.QuickAccessLinks.Any(x => x.Path == SelectedPath && x.Name == SelectedName)) + if (QuickAccessLinks.Any(x => x.Path == SelectedPath && x.Name == SelectedName)) { var warning = Main.Context.API.GetTranslation("plugin_explorer_quick_access_link_select_different_folder"); Main.Context.API.ShowMsgBox(warning); @@ -99,9 +101,8 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged EditAccessLink(); return; } - var container = Settings.QuickAccessLinks; var newAccessLink = new AccessLink { Name = SelectedName, Path = SelectedPath }; - container.Add(newAccessLink); + QuickAccessLinks.Add(newAccessLink); DialogResult = false; Close(); } @@ -120,12 +121,12 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged { if (SelectedAccessLink == null)throw new ArgumentException("Access Link object is null"); - var obj = Settings.QuickAccessLinks.FirstOrDefault(x => x.GetHashCode() == SelectedAccessLink.GetHashCode()); - int index = Settings.QuickAccessLinks.IndexOf(obj); + var obj = QuickAccessLinks.FirstOrDefault(x => x.GetHashCode() == SelectedAccessLink.GetHashCode()); + int index = QuickAccessLinks.IndexOf(obj); if (index >= 0) { SelectedAccessLink = new AccessLink { Name = SelectedName, Path = SelectedPath }; - Settings.QuickAccessLinks[index] = SelectedAccessLink; + QuickAccessLinks[index] = SelectedAccessLink; } DialogResult = false; IsEdit = false; From cd62e7b5dc4695a83339d2a02c9682603d775479 Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sun, 25 May 2025 16:11:03 -0300 Subject: [PATCH 1172/1798] uP --- .../Helper/{FolderPathHelper.cs => PathHelper.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename Plugins/Flow.Launcher.Plugin.Explorer/Helper/{FolderPathHelper.cs => PathHelper.cs} (94%) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Helper/FolderPathHelper.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Helper/PathHelper.cs similarity index 94% rename from Plugins/Flow.Launcher.Plugin.Explorer/Helper/FolderPathHelper.cs rename to Plugins/Flow.Launcher.Plugin.Explorer/Helper/PathHelper.cs index 74e23be3a..36b098d1e 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Helper/FolderPathHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Helper/PathHelper.cs @@ -5,7 +5,7 @@ using Flow.Launcher.Plugin.Explorer.Search; namespace Flow.Launcher.Plugin.Explorer.Helper; -public static class FolderPathHelper +public static class PathHelper { public static string GetPathName(this string selectedPath) { From 29831d61bb2b496b88ecd8588c0518e506d7ea3e Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sun, 25 May 2025 16:48:20 -0300 Subject: [PATCH 1173/1798] AI Review Refactor suggestion --- .../Languages/en.xaml | 2 +- .../ViewModels/SettingsViewModel.cs | 10 ++++---- .../Views/QuickAccessLinkSettings.xaml.cs | 23 ++++++++++--------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index ef55a4088..cc6b58e42 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -6,7 +6,7 @@ Please make a selection first Please select a folder path. - Please choose a different name or folder path. + Please choose a different name or folder path. Please select a folder link Are you sure you want to delete {0}? Are you sure you want to permanently delete this file? diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 6237deabb..d6effb4e2 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Windows; using System.Windows.Forms; using CommunityToolkit.Mvvm.Input; +using Flow.Launcher.Plugin.Explorer.Helper; using Flow.Launcher.Plugin.Explorer.Search; using Flow.Launcher.Plugin.Explorer.Search.Everything; using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions; @@ -352,7 +353,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels collection.Remove(SelectedIndexSearchExcludedPath); collection.Add(new AccessLink { - Path = path, Type = selectedType, + Path = path, Type = selectedType, Name = path.GetPathName() }); } @@ -368,10 +369,12 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels var newAccessLink = new AccessLink { + Name = folderBrowserDialog.SelectedPath.GetPathName(), Path = folderBrowserDialog.SelectedPath }; container.Add(newAccessLink); + Save(); } [RelayCommand] @@ -382,16 +385,15 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels ShowUnselectedMessage(); return; } - var quickAccessLinkSettings = new QuickAccessLinkSettings(Settings.QuickAccessLinks,SelectedQuickAccessLink); - quickAccessLinkSettings.ShowDialog(); + if (quickAccessLinkSettings.ShowDialog() == true) Save(); } [RelayCommand] private void AddQuickAccessLink(object commandParameter) { var quickAccessLinkSettings = new QuickAccessLinkSettings(Settings.QuickAccessLinks); - quickAccessLinkSettings.ShowDialog(); + if (quickAccessLinkSettings.ShowDialog() == true) Save(); } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs index 28cd68bad..388fc2c91 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/QuickAccessLinkSettings.xaml.cs @@ -52,9 +52,9 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged } private bool IsEdit { get; set; } - [CanBeNull] private AccessLink SelectedAccessLink { get; set; } + [CanBeNull] private AccessLink SelectedAccessLink { get; } - public ObservableCollection QuickAccessLinks { get; set; } + public ObservableCollection QuickAccessLinks { get; } public QuickAccessLinkSettings(ObservableCollection quickAccessLinks) { @@ -89,10 +89,12 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged Main.Context.API.ShowMsgBox(warning); return; } - - if (QuickAccessLinks.Any(x => x.Path == SelectedPath && x.Name == SelectedName)) + + if (QuickAccessLinks.Any(x => + x.Path.Equals(SelectedPath, StringComparison.OrdinalIgnoreCase) && + x.Name.Equals(SelectedName, StringComparison.OrdinalIgnoreCase))) { - var warning = Main.Context.API.GetTranslation("plugin_explorer_quick_access_link_select_different_folder"); + var warning = Main.Context.API.GetTranslation("plugin_explorer_quick_access_link_path_already_exists"); Main.Context.API.ShowMsgBox(warning); return; } @@ -103,7 +105,7 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged } var newAccessLink = new AccessLink { Name = SelectedName, Path = SelectedPath }; QuickAccessLinks.Add(newAccessLink); - DialogResult = false; + DialogResult = true; Close(); } @@ -121,14 +123,13 @@ public partial class QuickAccessLinkSettings : INotifyPropertyChanged { if (SelectedAccessLink == null)throw new ArgumentException("Access Link object is null"); - var obj = QuickAccessLinks.FirstOrDefault(x => x.GetHashCode() == SelectedAccessLink.GetHashCode()); - int index = QuickAccessLinks.IndexOf(obj); + var index = QuickAccessLinks.IndexOf(SelectedAccessLink); if (index >= 0) { - SelectedAccessLink = new AccessLink { Name = SelectedName, Path = SelectedPath }; - QuickAccessLinks[index] = SelectedAccessLink; + var updatedLink = new AccessLink { Name = SelectedName, Path = SelectedPath }; + QuickAccessLinks[index] = updatedLink; } - DialogResult = false; + DialogResult = true; IsEdit = false; Close(); } From 47878f3829a9cb10f87d5429d07fad097efec3dd Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 27 May 2025 14:08:32 +0900 Subject: [PATCH 1174/1798] Fix file explorer invocation to ensure correct file selection behavior --- Flow.Launcher/PublicAPIInstance.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 66e11f881..93567288c 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -338,7 +338,10 @@ namespace Flow.Launcher // Windows File Manager explorer.StartInfo = new ProcessStartInfo { - FileName = targetPath, + FileName = "explorer.exe", + Arguments = FileNameOrFilePath is null + ? DirectoryPath // only open the directory + : $"/select,\"{targetPath}\"", // open the directory and select the file UseShellExecute = true }; } From 41c5b36fba5aa1a627c153db7fa9f7ffc525dd4b Mon Sep 17 00:00:00 2001 From: DB p Date: Tue, 27 May 2025 15:20:41 +0900 Subject: [PATCH 1175/1798] Enhance OpenDirectory method to support folder opening and file selection using SHOpenFolderAndSelectItems --- Flow.Launcher/PublicAPIInstance.cs | 99 +++++++++++++++++++++++------- 1 file changed, 76 insertions(+), 23 deletions(-) diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 93567288c..58dbd3ff0 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Net; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -320,47 +321,98 @@ namespace Flow.Launcher ((PluginJsonStorage)_pluginJsonStorages[type]).Save(); } - public void OpenDirectory(string DirectoryPath, string FileNameOrFilePath = null) + [DllImport("shell32.dll", CharSet = CharSet.Unicode)] + private static extern int SHParseDisplayName( + [MarshalAs(UnmanagedType.LPWStr)] string name, + IntPtr bindingContext, + out IntPtr pidl, + uint sfgaoIn, + out uint psfgaoOut + ); + + [DllImport("shell32.dll")] + private static extern int SHOpenFolderAndSelectItems( + IntPtr pidlFolder, + uint cidl, + [MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, + uint dwFlags + ); + + [DllImport("ole32.dll")] + private static extern void CoTaskMemFree(IntPtr pv); + + private void OpenFolderAndSelectItem(string filePath) + { + IntPtr pidlFolder = IntPtr.Zero; + IntPtr pidlFile = IntPtr.Zero; + uint attr; + + string folderPath = Path.GetDirectoryName(filePath); + + try + { + SHParseDisplayName(folderPath, IntPtr.Zero, out pidlFolder, 0, out attr); + SHParseDisplayName(filePath, IntPtr.Zero, out pidlFile, 0, out attr); + + if (pidlFolder != IntPtr.Zero && pidlFile != IntPtr.Zero) + { + SHOpenFolderAndSelectItems(pidlFolder, 1, new[] { pidlFile }, 0); + } + } + finally + { + if (pidlFile != IntPtr.Zero) + CoTaskMemFree(pidlFile); + if (pidlFolder != IntPtr.Zero) + CoTaskMemFree(pidlFolder); + } + } + + public void OpenDirectory(string directoryPath, string fileNameOrFilePath = null) { try { - using var explorer = new Process(); + string targetPath = fileNameOrFilePath is null + ? directoryPath + : Path.IsPathRooted(fileNameOrFilePath) + ? fileNameOrFilePath + : Path.Combine(directoryPath, fileNameOrFilePath); + var explorerInfo = _settings.CustomExplorer; var explorerPath = explorerInfo.Path.Trim().ToLowerInvariant(); - var targetPath = FileNameOrFilePath is null - ? DirectoryPath - : Path.IsPathRooted(FileNameOrFilePath) - ? FileNameOrFilePath - : Path.Combine(DirectoryPath, FileNameOrFilePath); if (Path.GetFileNameWithoutExtension(explorerPath) == "explorer") { - // Windows File Manager - explorer.StartInfo = new ProcessStartInfo + if (fileNameOrFilePath is null) { - FileName = "explorer.exe", - Arguments = FileNameOrFilePath is null - ? DirectoryPath // only open the directory - : $"/select,\"{targetPath}\"", // open the directory and select the file - UseShellExecute = true - }; + // 폴더만 열기 + Process.Start(new ProcessStartInfo + { + FileName = directoryPath, + UseShellExecute = true + })?.Dispose(); + } + else + { + // SHOpenFolderAndSelectItems 방식 + OpenFolderAndSelectItem(targetPath); + } } else { - // Custom File Manager - explorer.StartInfo = new ProcessStartInfo + // 커스텀 파일 관리자 + var shellProcess = new ProcessStartInfo { - FileName = explorerInfo.Path.Replace("%d", DirectoryPath), + FileName = explorerInfo.Path.Replace("%d", directoryPath), UseShellExecute = true, - Arguments = FileNameOrFilePath is null - ? explorerInfo.DirectoryArgument.Replace("%d", DirectoryPath) + Arguments = fileNameOrFilePath is null + ? explorerInfo.DirectoryArgument.Replace("%d", directoryPath) : explorerInfo.FileArgument - .Replace("%d", DirectoryPath) + .Replace("%d", directoryPath) .Replace("%f", targetPath) }; + Process.Start(shellProcess)?.Dispose(); } - - explorer.Start(); } catch (Win32Exception ex) when (ex.NativeErrorCode == 2) { @@ -384,6 +436,7 @@ namespace Flow.Launcher } } + private void OpenUri(Uri uri, bool? inPrivate = null) { if (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps) From 086aeab6c05f4b2ab13e6d0a8239db7d83c588b1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 27 May 2025 14:36:09 +0800 Subject: [PATCH 1176/1798] Use PInvoke to improve code quality --- .../NativeMethods.txt | 4 + Flow.Launcher.Infrastructure/Win32Helper.cs | 31 ++++++++ Flow.Launcher/PublicAPIInstance.cs | 76 ++++--------------- 3 files changed, 50 insertions(+), 61 deletions(-) diff --git a/Flow.Launcher.Infrastructure/NativeMethods.txt b/Flow.Launcher.Infrastructure/NativeMethods.txt index 0e50420b0..2591506c8 100644 --- a/Flow.Launcher.Infrastructure/NativeMethods.txt +++ b/Flow.Launcher.Infrastructure/NativeMethods.txt @@ -57,3 +57,7 @@ LOCALE_TRANSIENT_KEYBOARD1 LOCALE_TRANSIENT_KEYBOARD2 LOCALE_TRANSIENT_KEYBOARD3 LOCALE_TRANSIENT_KEYBOARD4 + +SHParseDisplayName +SHOpenFolderAndSelectItems +CoTaskMemFree diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 783ade14e..4952eec98 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; +using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Threading; @@ -17,6 +18,7 @@ using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.Graphics.Dwm; using Windows.Win32.UI.Input.KeyboardAndMouse; +using Windows.Win32.UI.Shell.Common; using Windows.Win32.UI.WindowsAndMessaging; using Point = System.Windows.Point; using SystemFonts = System.Windows.SystemFonts; @@ -753,5 +755,34 @@ namespace Flow.Launcher.Infrastructure } #endregion + + #region Explorer + + public static unsafe void OpenFolderAndSelectFile(string filePath) + { + ITEMIDLIST* pidlFolder = null; + ITEMIDLIST* pidlFile = null; + + var folderPath = Path.GetDirectoryName(filePath); + + try + { + var hrFolder = PInvoke.SHParseDisplayName(folderPath, null, out pidlFolder, 0, null); + if (hrFolder.Failed) throw new COMException("Failed to parse folder path", hrFolder); + + var hrFile = PInvoke.SHParseDisplayName(filePath, null, out pidlFile, 0, null); + if (hrFile.Failed) throw new COMException("Failed to parse file path", hrFile); + + var hrSelect = PInvoke.SHOpenFolderAndSelectItems(pidlFolder, 1, &pidlFile, 0); + if (hrSelect.Failed) throw new COMException("Failed to open folder and select item", hrSelect); + } + finally + { + if (pidlFile != null) PInvoke.CoTaskMemFree(pidlFile); + if (pidlFolder != null) PInvoke.CoTaskMemFree(pidlFolder); + } + } + + #endregion } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 58dbd3ff0..c06c56039 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -8,11 +8,9 @@ using System.IO; using System.Linq; using System.Net; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Windows; -using System.Windows.Input; using System.Windows.Media; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Core; @@ -320,88 +318,44 @@ namespace Flow.Launcher ((PluginJsonStorage)_pluginJsonStorages[type]).Save(); } - - [DllImport("shell32.dll", CharSet = CharSet.Unicode)] - private static extern int SHParseDisplayName( - [MarshalAs(UnmanagedType.LPWStr)] string name, - IntPtr bindingContext, - out IntPtr pidl, - uint sfgaoIn, - out uint psfgaoOut - ); - - [DllImport("shell32.dll")] - private static extern int SHOpenFolderAndSelectItems( - IntPtr pidlFolder, - uint cidl, - [MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, - uint dwFlags - ); - - [DllImport("ole32.dll")] - private static extern void CoTaskMemFree(IntPtr pv); - - private void OpenFolderAndSelectItem(string filePath) - { - IntPtr pidlFolder = IntPtr.Zero; - IntPtr pidlFile = IntPtr.Zero; - uint attr; - - string folderPath = Path.GetDirectoryName(filePath); - - try - { - SHParseDisplayName(folderPath, IntPtr.Zero, out pidlFolder, 0, out attr); - SHParseDisplayName(filePath, IntPtr.Zero, out pidlFile, 0, out attr); - - if (pidlFolder != IntPtr.Zero && pidlFile != IntPtr.Zero) - { - SHOpenFolderAndSelectItems(pidlFolder, 1, new[] { pidlFile }, 0); - } - } - finally - { - if (pidlFile != IntPtr.Zero) - CoTaskMemFree(pidlFile); - if (pidlFolder != IntPtr.Zero) - CoTaskMemFree(pidlFolder); - } - } public void OpenDirectory(string directoryPath, string fileNameOrFilePath = null) { try { - string targetPath = fileNameOrFilePath is null + var explorerInfo = _settings.CustomExplorer; + var explorerPath = explorerInfo.Path.Trim().ToLowerInvariant(); + var targetPath = fileNameOrFilePath is null ? directoryPath : Path.IsPathRooted(fileNameOrFilePath) ? fileNameOrFilePath : Path.Combine(directoryPath, fileNameOrFilePath); - var explorerInfo = _settings.CustomExplorer; - var explorerPath = explorerInfo.Path.Trim().ToLowerInvariant(); - if (Path.GetFileNameWithoutExtension(explorerPath) == "explorer") { + // Windows File Manager if (fileNameOrFilePath is null) { - // 폴더만 열기 - Process.Start(new ProcessStartInfo + // Only Open the directory + using var explorer = new Process(); + explorer.StartInfo = new ProcessStartInfo { FileName = directoryPath, UseShellExecute = true - })?.Dispose(); + }; + explorer.Start(); } else { - // SHOpenFolderAndSelectItems 방식 - OpenFolderAndSelectItem(targetPath); + // Open the directory and select the file + Win32Helper.OpenFolderAndSelectFile(targetPath); } } else { - // 커스텀 파일 관리자 - var shellProcess = new ProcessStartInfo + // Custom File Manager + using var explorer = new Process(); + explorer.StartInfo = new ProcessStartInfo { FileName = explorerInfo.Path.Replace("%d", directoryPath), UseShellExecute = true, @@ -411,7 +365,7 @@ namespace Flow.Launcher .Replace("%d", directoryPath) .Replace("%f", targetPath) }; - Process.Start(shellProcess)?.Dispose(); + explorer.Start(); } } catch (Win32Exception ex) when (ex.NativeErrorCode == 2) From eb69ce919e65b7b35fe48722f7a7ba8e9aa49096 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 27 May 2025 14:36:24 +0800 Subject: [PATCH 1177/1798] Add url comments --- Flow.Launcher.Infrastructure/Win32Helper.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 4952eec98..96d8e925b 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -758,6 +758,8 @@ namespace Flow.Launcher.Infrastructure #region Explorer + // https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shopenfolderandselectitems + public static unsafe void OpenFolderAndSelectFile(string filePath) { ITEMIDLIST* pidlFolder = null; From 489699ca89a86047509a1dc8a8dd180d986d22b1 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 27 May 2025 10:46:07 +0000 Subject: [PATCH 1178/1798] add update PR script --- .github/update_release_pr.py | 103 +++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 .github/update_release_pr.py diff --git a/.github/update_release_pr.py b/.github/update_release_pr.py new file mode 100644 index 000000000..a9d11651b --- /dev/null +++ b/.github/update_release_pr.py @@ -0,0 +1,103 @@ +import os +import requests + +def get_github_prs(token, owner, repo, milestone, label, state): + """ + Fetches pull requests from a GitHub repository that match a given milestone and label. + + Args: + token (str): GitHub token. + owner (str): The owner of the repository. + repo (str): The name of the repository. + milestone (str): The milestone title. + label (str): The label name. + state (str): State of PR, e.g. open + + Returns: + list: A list of dictionaries, where each dictionary represents a pull request. + Returns an empty list if no PRs are found or an error occurs. + """ + headers = { + "Authorization": f"token {token}", + "Accept": "application/vnd.github.v3+json", + } + + milestone_id = None + milestone_url = f"https://api.github.com/repos/{owner}/{repo}/milestones" + params = {"state": state} + + try: + response = requests.get(milestone_url, headers=headers, params=params) + response.raise_for_status() + milestones = response.json() + for ms in milestones: + if ms["title"] == milestone: + milestone_id = ms["number"] + break + + if not milestone_id: + print(f"Milestone '{milestone}' not found in repository '{owner}/{repo}'.") + return [] + + except requests.exceptions.RequestException as e: + print(f"Error fetching milestones: {e}") + return [] + + prs_url = f"https://api.github.com/repos/{owner}/{repo}/pulls" + params = { + "state": state, + "milestone": milestone_id, + "labels": label, + } + + all_prs = [] + page = 1 + while True: + try: + params["page"] = page + response = requests.get(prs_url, headers=headers, params=params) + response.raise_for_status() # Raise an exception for HTTP errors + prs = response.json() + + if not prs: + break # No more PRs to fetch + + all_prs.extend(prs) + page += 1 + + except requests.exceptions.RequestException as e: + print(f"Error fetching pull requests: {e}") + break + + return all_prs + +if __name__ == "__main__": + github_token = os.environ.get("GITHUB_TOKEN") + + if not github_token: + print("Error: GITHUB_TOKEN environment variable not set.") + exit(1) + + repository_owner = "flow-launcher" + repository_name = "flow.launcher" + target_milestone = "1.20.0" + target_label = "enhancement" + state = "closed" + + print(f"Fetching PRs for {repository_owner}/{repository_name} with milestone '{target_milestone}' and label '{target_label}'...") + + pull_requests = get_github_prs( + github_token, + repository_owner, + repository_name, + target_milestone, + target_label, + state + ) + + if pull_requests: + print(f"\nFound {len(pull_requests)} pull requests:") + for pr in pull_requests: + print(f"- {pr['state']} #{pr['number']}: {pr['title']} (URL: {pr['html_url']})") + else: + print("No matching pull requests found.") From f79a2d24674d7f6f208a6c09c8a60ba98618ea84 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 27 May 2025 11:36:38 +0000 Subject: [PATCH 1179/1798] change to issues endpoint --- .github/update_release_pr.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/update_release_pr.py b/.github/update_release_pr.py index a9d11651b..b51620d73 100644 --- a/.github/update_release_pr.py +++ b/.github/update_release_pr.py @@ -24,7 +24,7 @@ def get_github_prs(token, owner, repo, milestone, label, state): milestone_id = None milestone_url = f"https://api.github.com/repos/{owner}/{repo}/milestones" - params = {"state": state} + params = {"state": open} try: response = requests.get(milestone_url, headers=headers, params=params) @@ -37,17 +37,19 @@ def get_github_prs(token, owner, repo, milestone, label, state): if not milestone_id: print(f"Milestone '{milestone}' not found in repository '{owner}/{repo}'.") - return [] + exit(1) except requests.exceptions.RequestException as e: print(f"Error fetching milestones: {e}") - return [] + exit(1) - prs_url = f"https://api.github.com/repos/{owner}/{repo}/pulls" + # This endpoint allows filtering by milestone and label. A PR in GH's perspective is a type of issue. + prs_url = f"https://api.github.com/repos/{owner}/{repo}/issues" params = { "state": state, "milestone": milestone_id, "labels": label, + "per_page": 100, } all_prs = [] @@ -61,18 +63,19 @@ def get_github_prs(token, owner, repo, milestone, label, state): if not prs: break # No more PRs to fetch - - all_prs.extend(prs) + + # Check for pr key since we are using issues endpoint instead. + all_prs.extend([item for item in prs if "pull_request" in item]) page += 1 except requests.exceptions.RequestException as e: print(f"Error fetching pull requests: {e}") - break + exit(1) return all_prs if __name__ == "__main__": - github_token = os.environ.get("GITHUB_TOKEN") + github_token = os.environ.get("GITHUB_TOKEN") if not github_token: print("Error: GITHUB_TOKEN environment variable not set.") From 55b69c601a12899f054cedab4956a2cb0dcf95e5 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Wed, 28 May 2025 11:20:39 +0000 Subject: [PATCH 1180/1798] get milestone dynamically --- .github/update_release_pr.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/update_release_pr.py b/.github/update_release_pr.py index b51620d73..c00683439 100644 --- a/.github/update_release_pr.py +++ b/.github/update_release_pr.py @@ -1,7 +1,7 @@ import os import requests -def get_github_prs(token, owner, repo, milestone, label, state): +def get_github_prs(token, owner, repo, label, state): """ Fetches pull requests from a GitHub repository that match a given milestone and label. @@ -9,7 +9,6 @@ def get_github_prs(token, owner, repo, milestone, label, state): token (str): GitHub token. owner (str): The owner of the repository. repo (str): The name of the repository. - milestone (str): The milestone title. label (str): The label name. state (str): State of PR, e.g. open @@ -30,13 +29,19 @@ def get_github_prs(token, owner, repo, milestone, label, state): response = requests.get(milestone_url, headers=headers, params=params) response.raise_for_status() milestones = response.json() + + if len(milestones) > 2: + print("More than two milestones found, unable to determine the milestone required.") + + # milestones.pop() for ms in milestones: - if ms["title"] == milestone: + if ms["title"] != "Future": milestone_id = ms["number"] + print(f"Gathering PRs with milestone {ms['title']}..." ) break if not milestone_id: - print(f"Milestone '{milestone}' not found in repository '{owner}/{repo}'.") + print(f"No suitable milestone found in repository '{owner}/{repo}'.") exit(1) except requests.exceptions.RequestException as e: @@ -83,17 +88,15 @@ if __name__ == "__main__": repository_owner = "flow-launcher" repository_name = "flow.launcher" - target_milestone = "1.20.0" target_label = "enhancement" state = "closed" - print(f"Fetching PRs for {repository_owner}/{repository_name} with milestone '{target_milestone}' and label '{target_label}'...") + print(f"Fetching PRs for {repository_owner}/{repository_name} with label '{target_label}'...") pull_requests = get_github_prs( github_token, repository_owner, repository_name, - target_milestone, target_label, state ) From 0b616d8721d432fe940c2683c2edfb9695641bf3 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Wed, 28 May 2025 12:03:13 +0000 Subject: [PATCH 1181/1798] add pr update --- .github/update_release_pr.py | 84 +++++++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 7 deletions(-) diff --git a/.github/update_release_pr.py b/.github/update_release_pr.py index c00683439..b03b0c425 100644 --- a/.github/update_release_pr.py +++ b/.github/update_release_pr.py @@ -79,6 +79,53 @@ def get_github_prs(token, owner, repo, label, state): return all_prs +def update_pull_request_description(token, owner, repo, pr_number, new_description): + """ + Updates the description (body) of a GitHub Pull Request. + + Args: + token (str): Token. + owner (str): The owner of the repository. + repo (str): The name of the repository. + pr_number (int): The number of the pull request to update. + new_description (str): The new content for the PR's description. + + Returns: + dict or None: The updated PR object (as a dictionary) if successful, + None otherwise. + """ + headers = { + "Authorization": f"token {token}", + "Accept": "application/vnd.github.v3+json", + "Content-Type": "application/json" + } + + url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}" + + payload = { + "body": new_description + } + + print(f"Attempting to update PR #{pr_number} in {owner}/{repo}...") + print(f"URL: {url}") + # print(f"Payload: {payload}") # Uncomment for detailed payload debug + + try: + response = requests.patch(url, headers=headers, json=payload) + response.raise_for_status() + + updated_pr_data = response.json() + print(f"Successfully updated PR #{pr_number}.") + return updated_pr_data + + except requests.exceptions.RequestException as e: + print(f"Error updating pull request #{pr_number}: {e}") + if response is not None: + print(f"Response status code: {response.status_code}") + print(f"Response text: {response.text}") + return None + + if __name__ == "__main__": github_token = os.environ.get("GITHUB_TOKEN") @@ -92,7 +139,7 @@ if __name__ == "__main__": state = "closed" print(f"Fetching PRs for {repository_owner}/{repository_name} with label '{target_label}'...") - + pull_requests = get_github_prs( github_token, repository_owner, @@ -101,9 +148,32 @@ if __name__ == "__main__": state ) - if pull_requests: - print(f"\nFound {len(pull_requests)} pull requests:") - for pr in pull_requests: - print(f"- {pr['state']} #{pr['number']}: {pr['title']} (URL: {pr['html_url']})") - else: - print("No matching pull requests found.") + if not pull_requests: + print("No matching pull requests found") + exit(1) + + print(f"\nFound {len(pull_requests)} pull requests:") + + description_content = "" + for pr in pull_requests: + description_content+= f"- {pr['title']} #{pr['number']}\n" + + returned_pr = pull_requests = get_github_prs( + github_token, + repository_owner, + repository_name, + "release", + "open" + ) + + if len(returned_pr) != 1: + print(f"Unable to find the exact release PR. Returned result: {returned_pr}") + exit(1) + + release_pr = returned_pr[0] + + print(f"Found release PR: {release_pr['title']}") + + update_pull_request_description(github_token, repository_owner, repository_name, release_pr["number"], description_content) + + print(description_content) \ No newline at end of file From 4a50eec281e6013301efd5b56eb5c601d3921565 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 30 May 2025 10:59:22 +0800 Subject: [PATCH 1182/1798] Remove TranslationConverter & project reference in Explorer plugin --- .../Resource/TranslationConverter.cs | 25 ------------------- .../UserSettings/CustomShortcutModel.cs | 8 ++++++ .../Resources/SettingWindowStyle.xaml | 1 - .../Views/SettingsPaneHotkey.xaml | 2 +- .../Flow.Launcher.Plugin.Explorer.csproj | 3 +-- .../ViewModels/ActionKeywordModel.cs | 2 ++ .../Views/ExplorerSettings.xaml | 6 ++--- 7 files changed, 14 insertions(+), 33 deletions(-) delete mode 100644 Flow.Launcher.Core/Resource/TranslationConverter.cs diff --git a/Flow.Launcher.Core/Resource/TranslationConverter.cs b/Flow.Launcher.Core/Resource/TranslationConverter.cs deleted file mode 100644 index eb0032758..000000000 --- a/Flow.Launcher.Core/Resource/TranslationConverter.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Globalization; -using System.Windows.Data; -using CommunityToolkit.Mvvm.DependencyInjection; -using Flow.Launcher.Plugin; - -namespace Flow.Launcher.Core.Resource -{ - public class TranslationConverter : IValueConverter - { - // We should not initialize API in static constructor because it will create another API instance - private static IPublicAPI api = null; - private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - var key = value.ToString(); - if (string.IsNullOrEmpty(key)) return key; - return API.GetTranslation(key); - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => - throw new InvalidOperationException(); - } -} diff --git a/Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs b/Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs index 2d15b54c5..2603d4675 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/CustomShortcutModel.cs @@ -1,6 +1,8 @@ using System; using System.Text.Json.Serialization; using System.Threading.Tasks; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Plugin; namespace Flow.Launcher.Infrastructure.UserSettings { @@ -53,6 +55,12 @@ 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 BaseBuiltinShortcutModel(string key, string description) { Key = key; diff --git a/Flow.Launcher/Resources/SettingWindowStyle.xaml b/Flow.Launcher/Resources/SettingWindowStyle.xaml index fc9246aa3..3ebd22c74 100644 --- a/Flow.Launcher/Resources/SettingWindowStyle.xaml +++ b/Flow.Launcher/Resources/SettingWindowStyle.xaml @@ -6,7 +6,6 @@ - F1 M512,512z M0,0z M448,256C448,150,362,64,256,64L256,448C362,448,448,362,448,256z M0,256A256,256,0,1,1,512,256A256,256,0,1,1,0,256z diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml index b1d72ede5..861e9d294 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml @@ -424,7 +424,7 @@ - + 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 98164f489..93691814a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -46,6 +46,7 @@ + @@ -53,8 +54,6 @@ - - diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/ActionKeywordModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/ActionKeywordModel.cs index d4cd1348e..745032d2c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/ActionKeywordModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/ActionKeywordModel.cs @@ -24,6 +24,8 @@ namespace Flow.Launcher.Plugin.Explorer.Views public string Description { get; private init; } + public string LocalizedDescription => Main.Context.API.GetTranslation(Description); + internal Settings.ActionKeyword KeywordProperty { get; } private void OnPropertyChanged([CallerMemberName] string propertyName = "") diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index 4302e721a..c034ac0e1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -3,7 +3,6 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:converters="clr-namespace:Flow.Launcher.Plugin.Explorer.Views.Converters" - xmlns:core="clr-namespace:Flow.Launcher.Core.Resource;assembly=Flow.Launcher.Core" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:qa="clr-namespace:Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks" @@ -109,7 +108,7 @@ + Text="{Binding LocalizedDescription, Mode=OneTime}"> + - @@ -163,653 +79,685 @@ + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - + + + + + + + + + + + + + + + + + + - + + + + + + + + + \ No newline at end of file diff --git a/Flow.Launcher/ReleaseNotesWindow.xaml.cs b/Flow.Launcher/ReleaseNotesWindow.xaml.cs new file mode 100644 index 000000000..18c67ac5b --- /dev/null +++ b/Flow.Launcher/ReleaseNotesWindow.xaml.cs @@ -0,0 +1,149 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Input; +using Flow.Launcher.Infrastructure.Http; + +namespace Flow.Launcher +{ + public partial class ReleaseNotesWindow : Window + { + public ReleaseNotesWindow() + { + InitializeComponent(); + } + + #region Window Events + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "")] + private async void Window_Loaded(object sender, RoutedEventArgs e) + { + RefreshMaximizeRestoreButton(); + MarkdownViewer.Markdown = await GetReleaseNotesMarkdownAsync(); + } + + private void OnCloseExecuted(object sender, ExecutedRoutedEventArgs e) + { + Close(); + } + + #endregion + + #region Window Custom TitleBar + + private void OnMinimizeButtonClick(object sender, RoutedEventArgs e) + { + WindowState = WindowState.Minimized; + } + + private void OnMaximizeRestoreButtonClick(object sender, RoutedEventArgs e) + { + WindowState = WindowState switch + { + WindowState.Maximized => WindowState.Normal, + _ => WindowState.Maximized + }; + } + + private void OnCloseButtonClick(object sender, RoutedEventArgs e) + { + Close(); + } + + private void RefreshMaximizeRestoreButton() + { + if (WindowState == WindowState.Maximized) + { + MaximizeButton.Visibility = Visibility.Hidden; + RestoreButton.Visibility = Visibility.Visible; + } + else + { + MaximizeButton.Visibility = Visibility.Visible; + RestoreButton.Visibility = Visibility.Hidden; + } + } + + private void Window_StateChanged(object sender, EventArgs e) + { + RefreshMaximizeRestoreButton(); + } + + #endregion + + #region Release Notes + + private static async Task GetReleaseNotesMarkdownAsync() + { + var releaseNotesJSON = await Http.GetStringAsync("https://api.github.com/repos/Flow-Launcher/Flow.Launcher/releases"); + var releases = JsonSerializer.Deserialize>(releaseNotesJSON); + + // Get the latest releases + var latestReleases = releases.OrderByDescending(release => release.PublishedDate).Take(3); + + // Build the release notes in Markdown format + var releaseNotesHtmlBuilder = new StringBuilder(string.Empty); + foreach (var release in latestReleases) + { + releaseNotesHtmlBuilder.AppendLine("# " + release.Name); + + // Add unit for images: Replace with + var notes = ImageUnitRegex().Replace(release.ReleaseNotes, m => + { + var prefix = m.Groups[1].Value; + var widthValue = m.Groups[2].Value; + var quote = m.Groups[3].Value; + var suffix = m.Groups[4].Value; + // Only replace if width is number like 500 without units like 500px + if (IsNumber(widthValue)) + return $"{prefix}{widthValue}px{quote}{suffix}"; + return m.Value; + }); + + releaseNotesHtmlBuilder.AppendLine(notes); + releaseNotesHtmlBuilder.AppendLine(" "); + } + + return releaseNotesHtmlBuilder.ToString(); + } + + private static bool IsNumber(string input) + { + if (string.IsNullOrEmpty(input)) + return false; + + foreach (char c in input) + { + if (!char.IsDigit(c)) + return false; + } + return true; + } + + private sealed class GitHubReleaseInfo + { + [JsonPropertyName("published_at")] + public DateTimeOffset PublishedDate { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("tag_name")] + public string TagName { get; set; } + + [JsonPropertyName("body")] + public string ReleaseNotes { get; set; } + } + + [GeneratedRegex("(]*width\\s*=\\s*[\"']?)(\\d+)([\"']?)([^>]*>)", RegexOptions.IgnoreCase, "en-GB")] + private static partial Regex ImageUnitRegex(); + + #endregion + } +} From 7117ba05ee4ef544f4bc0c7c648fa3e5f8c25971 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 6 Jun 2025 23:08:41 +0800 Subject: [PATCH 1297/1798] Test release notes window --- Flow.Launcher/MainWindow.xaml.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index a77d6471c..b266d3dc0 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -132,6 +132,9 @@ namespace Flow.Launcher welcomeWindow.Show(); } + var releaseNotesWindow = new ReleaseNotesWindow(); + releaseNotesWindow.Show(); + // Initialize place holder SetupPlaceholderText(); _viewModel.PlaceholderText = _settings.PlaceholderText; From c241d21a4a9259a3ce1eb50f21b0624c6780cba0 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 6 Jun 2025 23:51:26 +0800 Subject: [PATCH 1298/1798] Fix height --- Flow.Launcher/ReleaseNotesWindow.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/ReleaseNotesWindow.xaml b/Flow.Launcher/ReleaseNotesWindow.xaml index 132de63c8..e61986aea 100644 --- a/Flow.Launcher/ReleaseNotesWindow.xaml +++ b/Flow.Launcher/ReleaseNotesWindow.xaml @@ -157,7 +157,7 @@ Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="5" - MaxHeight="510" + Height="510" Margin="15 0 20 0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" From af0e1180a5cbc18cba3090f10595e58ab12e7ac6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 6 Jun 2025 23:52:34 +0800 Subject: [PATCH 1299/1798] Use loaded event & Add style --- Flow.Launcher/ReleaseNotesWindow.xaml | 3 ++- Flow.Launcher/ReleaseNotesWindow.xaml.cs | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/ReleaseNotesWindow.xaml b/Flow.Launcher/ReleaseNotesWindow.xaml index e61986aea..7b2e5f7e7 100644 --- a/Flow.Launcher/ReleaseNotesWindow.xaml +++ b/Flow.Launcher/ReleaseNotesWindow.xaml @@ -161,7 +161,8 @@ Margin="15 0 20 0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" - ClickAction="SafetyDisplayWithRelativePath" /> + ClickAction="SafetyDisplayWithRelativePath" + Loaded="MarkdownViewer_Loaded" /> diff --git a/Flow.Launcher/ReleaseNotesWindow.xaml.cs b/Flow.Launcher/ReleaseNotesWindow.xaml.cs index 18c67ac5b..4f0c1a9ce 100644 --- a/Flow.Launcher/ReleaseNotesWindow.xaml.cs +++ b/Flow.Launcher/ReleaseNotesWindow.xaml.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using Flow.Launcher.Infrastructure.Http; +using MdXaml; namespace Flow.Launcher { @@ -21,11 +22,9 @@ namespace Flow.Launcher #region Window Events - [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "")] - private async void Window_Loaded(object sender, RoutedEventArgs e) + private void Window_Loaded(object sender, RoutedEventArgs e) { RefreshMaximizeRestoreButton(); - MarkdownViewer.Markdown = await GetReleaseNotesMarkdownAsync(); } private void OnCloseExecuted(object sender, ExecutedRoutedEventArgs e) @@ -82,6 +81,11 @@ namespace Flow.Launcher private static async Task GetReleaseNotesMarkdownAsync() { var releaseNotesJSON = await Http.GetStringAsync("https://api.github.com/repos/Flow-Launcher/Flow.Launcher/releases"); + + if (string.IsNullOrEmpty(releaseNotesJSON)) + { + return string.Empty; + } var releases = JsonSerializer.Deserialize>(releaseNotesJSON); // Get the latest releases @@ -145,5 +149,12 @@ namespace Flow.Launcher private static partial Regex ImageUnitRegex(); #endregion + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "VSTHRD100:Avoid async void methods", Justification = "")] + private async void MarkdownViewer_Loaded(object sender, RoutedEventArgs e) + { + MarkdownViewer.MarkdownStyle = MarkdownStyle.GithubLike; + MarkdownViewer.Markdown = await GetReleaseNotesMarkdownAsync(); + } } } From 02496214ea2cabbd0037bc83f3e9e03125311222 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 7 Jun 2025 00:07:44 +0800 Subject: [PATCH 1300/1798] Add progress ring --- Flow.Launcher/ReleaseNotesWindow.xaml | 23 ++++++++++++++++ Flow.Launcher/ReleaseNotesWindow.xaml.cs | 34 +++++++++++++++++++++--- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher/ReleaseNotesWindow.xaml b/Flow.Launcher/ReleaseNotesWindow.xaml index 7b2e5f7e7..f70fa6f5c 100644 --- a/Flow.Launcher/ReleaseNotesWindow.xaml +++ b/Flow.Launcher/ReleaseNotesWindow.xaml @@ -163,6 +163,29 @@ VerticalAlignment="Stretch" ClickAction="SafetyDisplayWithRelativePath" Loaded="MarkdownViewer_Loaded" /> + + + + + - - - - - - - - - + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -118,14 +117,14 @@ x:Name="btnCancel" Width="145" Height="30" - Margin="10 0 5 0" + Margin="10 0 10 0" Click="BtnCancel_OnClick" Content="{DynamicResource cancel}" /> + Date: Mon, 14 Jul 2025 16:24:46 +0800 Subject: [PATCH 1531/1798] Rename function name --- Flow.Launcher.Core/Plugin/PluginInstaller.cs | 2 +- Flow.Launcher/App.xaml.cs | 4 ++-- .../ViewModels/SettingsPanePluginStoreViewModel.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginInstaller.cs b/Flow.Launcher.Core/Plugin/PluginInstaller.cs index 692fe3ce1..4c551f993 100644 --- a/Flow.Launcher.Core/Plugin/PluginInstaller.cs +++ b/Flow.Launcher.Core/Plugin/PluginInstaller.cs @@ -284,7 +284,7 @@ public static class PluginInstaller /// If true, only use the primary URL for updates. /// Cancellation token to cancel the update operation. /// - public static async Task UpdatePluginAsync(bool silentUpdate = true, bool usePrimaryUrlOnly = false, CancellationToken token = default) + public static async Task CheckForPluginUpdatesAsync(bool silentUpdate = true, bool usePrimaryUrlOnly = false, CancellationToken token = default) { // Update the plugin manifest await API.UpdatePluginManifestAsync(usePrimaryUrlOnly, token); diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 6b04f11d9..7e3915b2b 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -298,11 +298,11 @@ namespace Flow.Launcher { // check plugin updates every 5 hour var timer = new PeriodicTimer(TimeSpan.FromHours(5)); - await PluginInstaller.UpdatePluginAsync(); + await PluginInstaller.CheckForPluginUpdatesAsync(); while (await timer.WaitForNextTickAsync()) // check updates on startup - await PluginInstaller.UpdatePluginAsync(); + await PluginInstaller.CheckForPluginUpdatesAsync(); } }); } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs index bfec08c52..96cd44072 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginStoreViewModel.cs @@ -112,7 +112,7 @@ public partial class SettingsPanePluginStoreViewModel : BaseModel [RelayCommand] private async Task CheckPluginUpdatesAsync() { - await PluginInstaller.UpdatePluginAsync(silentUpdate: false); + await PluginInstaller.CheckForPluginUpdatesAsync(silentUpdate: false); } private static string GetFileFromDialog(string title, string filter = "") From 69d5e33150c83ceaf455aec48a1b83004efc83ad Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 14 Jul 2025 16:31:09 +0800 Subject: [PATCH 1532/1798] Show message box with button instead --- Flow.Launcher.Core/Plugin/PluginInstaller.cs | 22 ++++++++++++-------- Flow.Launcher/Languages/en.xaml | 4 ++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginInstaller.cs b/Flow.Launcher.Core/Plugin/PluginInstaller.cs index 4c551f993..84f0f1fd9 100644 --- a/Flow.Launcher.Core/Plugin/PluginInstaller.cs +++ b/Flow.Launcher.Core/Plugin/PluginInstaller.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; @@ -327,17 +328,20 @@ public static class PluginInstaller return; } - if (API.ShowMsgBox( - string.Format(API.GetTranslation("updateAllPluginsSubtitle"), - Environment.NewLine, string.Join(", ", resultsForUpdate.Select(x => x.PluginExistingMetadata.Name))), + // Show message box with button to update all plugins + API.ShowMsgWithButton( API.GetTranslation("updateAllPluginsTitle"), - MessageBoxButton.YesNo) == MessageBoxResult.No) - { - return; - } + API.GetTranslation("updateAllPluginsButtonContent"), + () => + { + UpdateAllPlugins(resultsForUpdate); + }, + string.Join(", ", resultsForUpdate.Select(x => x.PluginExistingMetadata.Name))); + } - // Update all plugins - await Task.WhenAll(resultsForUpdate.Select(async plugin => + private static void UpdateAllPlugins(IEnumerable resultsForUpdate) + { + _ = Task.WhenAll(resultsForUpdate.Select(async plugin => { var downloadToFilePath = Path.Combine(Path.GetTempPath(), $"{plugin.Name}-{plugin.NewVersion}.zip"); diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index ee500324e..53f26c5f4 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -235,8 +235,8 @@ Install plugin from local path No update available All plugins are up to date - Update all plugins - Would you like to update these plugins?{0}{0}{1} + Plugin updates available + Update all plugins Check plugin updates From 44fbc6eed5763b089c78cc8f9a2eab3e8cb33185 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 14 Jul 2025 16:35:48 +0800 Subject: [PATCH 1533/1798] Add auto update subtitle --- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 53f26c5f4..3905df7c6 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -93,6 +93,7 @@ Always Start Typing in English Mode Temporarily change your input method to English mode when activating Flow. Auto Update + Automatically check app updates and notify if there are any updates available Select Hide Flow Launcher on startup Flow Launcher search window is hidden in the tray after starting up. diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 78b6d8db0..cfb292633 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -182,7 +182,8 @@ + Icon="" + Sub="{DynamicResource autoUpdatesTooltip}"> Date: Mon, 14 Jul 2025 16:49:04 +0800 Subject: [PATCH 1534/1798] Change double pinyin panel design --- .../Views/SettingsPaneGeneral.xaml | 47 ++++++++----------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index df0243ce8..38fc8df54 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -371,44 +371,37 @@ OnContent="{DynamicResource enable}" /> - - - - - + + + + + + - - + + - + Date: Mon, 14 Jul 2025 16:56:12 +0800 Subject: [PATCH 1535/1798] Replace dynamic type with a strongly-typed model --- Flow.Launcher.Core/Plugin/PluginInstaller.cs | 24 +++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginInstaller.cs b/Flow.Launcher.Core/Plugin/PluginInstaller.cs index 84f0f1fd9..c00c83d9e 100644 --- a/Flow.Launcher.Core/Plugin/PluginInstaller.cs +++ b/Flow.Launcher.Core/Plugin/PluginInstaller.cs @@ -300,14 +300,14 @@ public static class PluginInstaller 0 // if current version precedes version of the plugin from update source (e.g. PluginsManifest) && !API.PluginModified(existingPlugin.Metadata.ID) select - new + new PluginUpdateInfo() { - existingPlugin.Metadata.ID, - pluginUpdateSource.Name, - pluginUpdateSource.Author, + ID = existingPlugin.Metadata.ID, + Name = existingPlugin.Metadata.Name, + Author = existingPlugin.Metadata.Author, CurrentVersion = existingPlugin.Metadata.Version, NewVersion = pluginUpdateSource.Version, - existingPlugin.Metadata.IcoPath, + IcoPath = existingPlugin.Metadata.IcoPath, PluginExistingMetadata = existingPlugin.Metadata, PluginNewUserPlugin = pluginUpdateSource }).ToList(); @@ -339,7 +339,7 @@ public static class PluginInstaller string.Join(", ", resultsForUpdate.Select(x => x.PluginExistingMetadata.Name))); } - private static void UpdateAllPlugins(IEnumerable resultsForUpdate) + private static void UpdateAllPlugins(IEnumerable resultsForUpdate) { _ = Task.WhenAll(resultsForUpdate.Select(async plugin => { @@ -445,4 +445,16 @@ public static class PluginInstaller x.Metadata.Website.StartsWith(constructedUrlPart) ); } + + private record PluginUpdateInfo + { + public string ID { get; init; } + public string Name { get; init; } + public string Author { get; init; } + public string CurrentVersion { get; init; } + public string NewVersion { get; init; } + public string IcoPath { get; init; } + public PluginMetadata PluginExistingMetadata { get; init; } + public UserPlugin PluginNewUserPlugin { get; init; } + } } From 6317d0eec6f42b788324fdcf9e6a2c2fdea388f4 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 14 Jul 2025 19:29:12 +0800 Subject: [PATCH 1536/1798] Reload on all settings change --- Flow.Launcher.Infrastructure/PinyinAlphabet.cs | 13 ++++++++++--- .../UserSettings/Settings.cs | 14 +++++++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index cc4eccdc5..0f6d00014 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -25,10 +25,17 @@ namespace Flow.Launcher.Infrastructure _settings.PropertyChanged += (sender, e) => { - if (e.PropertyName == nameof(Settings.UseDoublePinyin) || - e.PropertyName == nameof(Settings.DoublePinyinSchema)) + switch (e.PropertyName) { - Reload(); + case nameof(Settings.ShouldUsePinyin): + Reload(); + break; + case nameof(Settings.UseDoublePinyin): + Reload(); + break; + case nameof(Settings.DoublePinyinSchema): + Reload(); + break; } }; } diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 6b10d693d..726a0023b 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -328,7 +328,19 @@ namespace Flow.Launcher.Infrastructure.UserSettings /// /// when false Alphabet static service will always return empty results /// - public bool ShouldUsePinyin { get; set; } = false; + private bool _useAlphabet = true; + public bool ShouldUsePinyin + { + get => _useAlphabet; + set + { + if (_useAlphabet != value) + { + _useAlphabet = value; + OnPropertyChanged(); + } + } + } private bool _useDoublePinyin = false; public bool UseDoublePinyin From 8c56c0bddf4a4b7b361b26a3a6b32038144c2f35 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 14 Jul 2025 19:30:16 +0800 Subject: [PATCH 1537/1798] Fix logic --- Flow.Launcher.Infrastructure/PinyinAlphabet.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index 0f6d00014..1c0cc6872 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -27,14 +27,18 @@ namespace Flow.Launcher.Infrastructure { switch (e.PropertyName) { - case nameof(Settings.ShouldUsePinyin): - Reload(); + case nameof (Settings.ShouldUsePinyin): + if (_settings.ShouldUsePinyin) + { + Reload(); + } break; case nameof(Settings.UseDoublePinyin): - Reload(); - break; case nameof(Settings.DoublePinyinSchema): - Reload(); + if (_settings.UseDoublePinyin) + { + Reload(); + } break; } }; From fd4efe009cf2839b5eb01c95aaceb025a84edda2 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:07:25 +0800 Subject: [PATCH 1538/1798] Hide double pin card when use pinyin is false --- Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 38fc8df54..a879007c3 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -386,6 +386,8 @@ Date: Mon, 14 Jul 2025 21:21:47 +0800 Subject: [PATCH 1539/1798] Update spell check --- .github/actions/spelling/expect.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 0fea6d9ab..d8c99bce9 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -104,3 +104,12 @@ metadatas WMP VSTHRD CJK +XiaoHe +ZiRanMa +WeiRuan +ZhiNengABC +ZiGuangPinYin +PinYinJiaJia +XingKongJianDao +DaNiu +XiaoLang From 970aa5eefe89d3a3009753ed76a8bec64cd1d827 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:24:11 +0800 Subject: [PATCH 1540/1798] Fix typo --- .../UserSettings/Settings.cs | 2 +- .../ChineseDetectionPerformanceTest.cs | 265 ++++++++++++++++++ 2 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 Flow.Launcher.Test/ChineseDetectionPerformanceTest.cs diff --git a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs index 726a0023b..271f618da 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -514,7 +514,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings { var list = FixedHotkeys(); - // Customizeable hotkeys + // Customizable hotkeys if (!string.IsNullOrEmpty(Hotkey)) list.Add(new(Hotkey, "flowlauncherHotkey", () => Hotkey = "")); if (!string.IsNullOrEmpty(PreviewHotkey)) diff --git a/Flow.Launcher.Test/ChineseDetectionPerformanceTest.cs b/Flow.Launcher.Test/ChineseDetectionPerformanceTest.cs new file mode 100644 index 000000000..1747f2b4a --- /dev/null +++ b/Flow.Launcher.Test/ChineseDetectionPerformanceTest.cs @@ -0,0 +1,265 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using NUnit.Framework.Legacy; +using Flow.Launcher.Infrastructure; +using ToolGood.Words.Pinyin; + +namespace Flow.Launcher.Test +{ + /// + /// Performance test comparing ContainsChinese() vs WordsHelper.HasChinese() + /// + /// This test verifies: + /// 1. Both methods produce identical results (correctness) + /// 2. Performance characteristics of both implementations + /// 3. Memory allocation patterns + /// + /// The ContainsChinese() method uses optimized Unicode range checking with ReadOnlySpan + /// while WordsHelper.HasChinese() uses the ToolGood.Words library implementation. + /// + [TestFixture] + public class ChineseDetectionPerformanceTest + { + private readonly List _testStrings = new() + { + // Pure English - should return false + "Hello World", + "Visual Studio Code", + "Microsoft Office 2023", + "Adobe Photoshop Creative Suite", + "Google Chrome Browser Application", + + // Pure Chinese - should return true + "你好世界", + "微软办公软件", + "谷歌浏览器", + "北京大学计算机科学与技术学院", + "中华人民共和国国家发展和改革委员会", + + // Mixed content - should return true + "Hello 世界", + "Visual Studio 代码编辑器", + "QQ音乐 Music Player", + "Windows 10 操作系统", + "GitHub 代码仓库管理平台", + + // Edge cases + "", + " ", + "123456", + "!@#$%^&*()", + "café résumé naïve", // Accented characters (not Chinese) + + // Long strings for performance testing + "This is a very long English string that contains no Chinese characters but is designed to test performance with longer text content that might appear in file names or application descriptions", + "这是一个非常长的中文字符串,包含了很多汉字,用来测试在处理较长中文文本时的性能表现,比如可能出现在文件名或应用程序描述中的文本内容", + "This is a mixed 混合内容的字符串 that contains both English and Chinese characters 中英文混合 to test performance with 复杂的文本内容 in real-world scenarios 真实场景中的应用" + }; + + [Test] + public void ContainsChinese_CorrectnessTest() + { + // Verify ContainsChinese works correctly for known cases + ClassicAssert.IsFalse(ContainsChinese("Hello World"), "Pure English should return false"); + ClassicAssert.IsTrue(ContainsChinese("你好世界"), "Pure Chinese should return true"); + ClassicAssert.IsTrue(ContainsChinese("Hello 世界"), "Mixed content should return true"); + ClassicAssert.IsFalse(ContainsChinese(""), "Empty string should return false"); + ClassicAssert.IsFalse(ContainsChinese("123456"), "Numbers should return false"); + ClassicAssert.IsFalse(ContainsChinese("café résumé"), "Accented characters should return false"); + } + + [Test] + public void WordsHelper_CorrectnessTest() + { + // Verify WordsHelper.HasChinese works correctly for known cases + ClassicAssert.IsFalse(WordsHelper.HasChinese("Hello World"), "Pure English should return false"); + ClassicAssert.IsTrue(WordsHelper.HasChinese("你好世界"), "Pure Chinese should return true"); + ClassicAssert.IsTrue(WordsHelper.HasChinese("Hello 世界"), "Mixed content should return true"); + ClassicAssert.IsFalse(WordsHelper.HasChinese(""), "Empty string should return false"); + ClassicAssert.IsFalse(WordsHelper.HasChinese("123456"), "Numbers should return false"); + ClassicAssert.IsFalse(WordsHelper.HasChinese("café résumé"), "Accented characters should return false"); + } + + [Test] + public void BothMethods_ShouldProduceSameResults() + { + // Critical test: verify both methods produce identical results for all test cases + foreach (var testString in _testStrings) + { + var wordsHelperResult = WordsHelper.HasChinese(testString); + var containsChineseResult = ContainsChinese(testString); + + ClassicAssert.AreEqual(wordsHelperResult, containsChineseResult, + $"Results differ for string: '{testString}'. WordsHelper: {wordsHelperResult}, ContainsChinese: {containsChineseResult}"); + } + + Console.WriteLine($"✓ Both methods produce identical results for all {_testStrings.Count} test cases"); + } + + [Test] + public void PerformanceComparison_BasicBenchmark() + { + const int iterations = 1000000; + + Console.WriteLine("=== CHINESE CHARACTER DETECTION PERFORMANCE TEST ==="); + Console.WriteLine($"Test iterations: {iterations:N0}"); + Console.WriteLine($"Test strings: {_testStrings.Count}"); + Console.WriteLine($"Total operations: {iterations * _testStrings.Count:N0}"); + Console.WriteLine(); + + // Warmup to ensure JIT compilation + Console.WriteLine("Warming up..."); + for (int i = 0; i < 1000; i++) + { + foreach (var testString in _testStrings) + { + _ = ContainsChinese(testString); + _ = WordsHelper.HasChinese(testString); + } + } + + // Benchmark ContainsChinese method + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + + var sw1 = System.Diagnostics.Stopwatch.StartNew(); + for (int i = 0; i < iterations; i++) + { + foreach (var testString in _testStrings) + { + _ = ContainsChinese(testString); + } + } + sw1.Stop(); + + // Benchmark WordsHelper.HasChinese method + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + + var sw2 = System.Diagnostics.Stopwatch.StartNew(); + for (int i = 0; i < iterations; i++) + { + foreach (var testString in _testStrings) + { + _ = WordsHelper.HasChinese(testString); + } + } + sw2.Stop(); + + // Calculate and display results + var containsChineseMs = sw1.Elapsed.TotalMilliseconds; + var wordsHelperMs = sw2.Elapsed.TotalMilliseconds; + var speedRatio = wordsHelperMs / containsChineseMs; + var timeDifference = wordsHelperMs - containsChineseMs; + + Console.WriteLine("RESULTS:"); + Console.WriteLine($"ContainsChinese(): {containsChineseMs:F3} ms"); + Console.WriteLine($"WordsHelper.HasChinese(): {wordsHelperMs:F3} ms"); + Console.WriteLine($"Time difference: {timeDifference:F3} ms"); + Console.WriteLine($"Speed improvement: {speedRatio:F2}x"); + Console.WriteLine($"Performance gain: {((speedRatio - 1) * 100):F1}%"); + Console.WriteLine(); + + if (speedRatio > 1.0) + { + Console.WriteLine($"✓ ContainsChinese() is {speedRatio:F2}x faster than WordsHelper.HasChinese()"); + } + else + { + Console.WriteLine($"⚠ WordsHelper.HasChinese() is {(1/speedRatio):F2}x faster than ContainsChinese()"); + } + + // Test always passes - this is a measurement test + ClassicAssert.IsTrue(true); + } + + [Test] + public void PerformanceComparison_ByStringType() + { + Console.WriteLine("=== PERFORMANCE BY STRING TYPE ==="); + + var categories = new Dictionary> + { + ["Pure English"] = _testStrings.Where(s => !ContainsChinese(s) && s.All(c => c <= 127)).ToList(), + ["Pure Chinese"] = _testStrings.Where(s => ContainsChinese(s) && s.All(c => IsChineseCharacter(c) || char.IsWhiteSpace(c))).ToList(), + ["Mixed Content"] = _testStrings.Where(s => ContainsChinese(s) && s.Any(c => c <= 127 && char.IsLetter(c))).ToList(), + ["Edge Cases"] = _testStrings.Where(s => string.IsNullOrWhiteSpace(s) || s.All(c => !char.IsLetter(c))).ToList() + }; + + foreach (var category in categories) + { + if (category.Value.Count == 0) continue; + + Console.WriteLine($"\n{category.Key} ({category.Value.Count} strings):"); + + var sample = category.Value.First(); + var displayText = sample.Length > 40 ? sample.Substring(0, 40) + "..." : sample; + Console.WriteLine($" Sample: '{displayText}'"); + + const int categoryIterations = 5000; + + // Test each method + var sw1 = System.Diagnostics.Stopwatch.StartNew(); + for (int i = 0; i < categoryIterations; i++) + { + foreach (var str in category.Value) + { + _ = ContainsChinese(str); + } + } + sw1.Stop(); + + var sw2 = System.Diagnostics.Stopwatch.StartNew(); + for (int i = 0; i < categoryIterations; i++) + { + foreach (var str in category.Value) + { + _ = WordsHelper.HasChinese(str); + } + } + sw2.Stop(); + + var ratio = (double)sw2.ElapsedTicks / sw1.ElapsedTicks; + Console.WriteLine($" Performance: ContainsChinese is {ratio:F2}x faster"); + } + + ClassicAssert.IsTrue(true); + } + + /// + /// Optimized Chinese character detection using comprehensive CJK Unicode ranges + /// This method uses ReadOnlySpan for better performance and covers all CJK character ranges + /// + private static bool ContainsChinese(ReadOnlySpan text) + { + foreach (var c in text) + { + if (IsChineseCharacter(c)) + return true; + } + return false; + } + + /// + /// Check if a character is a Chinese character using comprehensive Unicode ranges + /// Covers CJK Unified Ideographs and all extension blocks + /// + private static bool IsChineseCharacter(char c) + { + return (c >= 0x4E00 && c <= 0x9FFF) || // CJK Unified Ideographs (most common Chinese characters) + (c >= 0x3400 && c <= 0x4DBF) || // CJK Extension A + (c >= 0x20000 && c <= 0x2A6DF) || // CJK Extension B + (c >= 0x2A700 && c <= 0x2B73F) || // CJK Extension C + (c >= 0x2B740 && c <= 0x2B81F) || // CJK Extension D + (c >= 0x2B820 && c <= 0x2CEAF) || // CJK Extension E + (c >= 0x2CEB0 && c <= 0x2EBEF) || // CJK Extension F + (c >= 0xF900 && c <= 0xFAFF) || // CJK Compatibility Ideographs + (c >= 0x2F800 && c <= 0x2FA1F); // CJK Compatibility Supplement + } + } +} From f3bca632326a215836daa84cc3ef056fc1ad9157 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:46:54 +0800 Subject: [PATCH 1541/1798] Update wording --- Flow.Launcher/Languages/en.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 2fca06605..acd38baac 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -106,7 +106,7 @@ Search with Pinyin Allows using Pinyin to search. Pinyin is the standard system of romanized spelling for translating Chinese. Use Double Pinyin - Allows using Double Pinyin to search. Double Pinyin is a variation of Pinyin that uses two characters. + Use Double Pinyin instead of Full Pinyin to search. Double Pinyin Schema Xiao He Zi Ran Ma From dae16b9b8de42752162c21d07741425d86c62d4e Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:53:49 +0800 Subject: [PATCH 1542/1798] Try to fix false spell check alarms by using stable version --- .github/workflows/spelling.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index 47bd66107..eb3bec416 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -72,7 +72,7 @@ jobs: steps: - name: check-spelling id: spelling - uses: check-spelling/check-spelling@prerelease + uses: check-spelling/check-spelling@0.0.25 with: suppress_push_for_open_pull_request: 1 checkout: true From c15ff61f92e6d1a5a755ca9c559a327728be3b5c Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Mon, 14 Jul 2025 22:19:34 +0800 Subject: [PATCH 1543/1798] Use stable version --- .github/workflows/spelling.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index eb3bec416..ebea86d62 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -128,7 +128,7 @@ jobs: if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request') steps: - name: comment - uses: check-spelling/check-spelling@prerelease + uses: check-spelling/check-spelling@0.0.25 with: checkout: true spell_check_this: check-spelling/spell-check-this@main From e08b73154880ae1b1065195a2b39c253937da587 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Tue, 15 Jul 2025 00:10:44 +0800 Subject: [PATCH 1544/1798] Disable line_forbidden.patterns --- .../actions/spelling/line_forbidden.patterns | 124 +++++++++--------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/.github/actions/spelling/line_forbidden.patterns b/.github/actions/spelling/line_forbidden.patterns index 7341d9b73..119d89321 100644 --- a/.github/actions/spelling/line_forbidden.patterns +++ b/.github/actions/spelling/line_forbidden.patterns @@ -1,62 +1,62 @@ -# reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere -# \bm_data\b - -# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test, -# you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want -# to use this: -#\bfit\( - -# s.b. GitHub -#\bGithub\b - -# s.b. GitLab -\bGitlab\b - -# s.b. JavaScript -\bJavascript\b - -# s.b. Microsoft -\bMicroSoft\b - -# s.b. another -\ban[- ]other\b - -# s.b. greater than -\bgreater then\b - -# s.b. into -\sin to\s - -# s.b. opt-in -\sopt in\s - -# s.b. less than -\bless then\b - -# s.b. otherwise -\bother[- ]wise\b - -# s.b. nonexistent -\bnon existing\b -\b[Nn]o[nt][- ]existent\b - -# s.b. preexisting -[Pp]re[- ]existing - -# s.b. preempt -[Pp]re[- ]empt\b - -# s.b. preemptively -[Pp]re[- ]emptively - -# s.b. reentrancy -[Rr]e[- ]entrancy - -# s.b. reentrant -[Rr]e[- ]entrant - -# s.b. workaround(s) -\bwork[- ]arounds?\b - -# Reject duplicate words -\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s +## reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere +## \bm_data\b +# +## If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test, +## you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want +## to use this: +##\bfit\( +# +## s.b. GitHub +##\bGithub\b +# +## s.b. GitLab +#\bGitlab\b +# +## s.b. JavaScript +#\bJavascript\b +# +## s.b. Microsoft +#\bMicroSoft\b +# +## s.b. another +#\ban[- ]other\b +# +## s.b. greater than +#\bgreater then\b +# +## s.b. into +#\sin to\s +# +## s.b. opt-in +#\sopt in\s +# +## s.b. less than +#\bless then\b +# +## s.b. otherwise +#\bother[- ]wise\b +# +## s.b. nonexistent +#\bnon existing\b +#\b[Nn]o[nt][- ]existent\b +# +## s.b. preexisting +#[Pp]re[- ]existing +# +## s.b. preempt +#[Pp]re[- ]empt\b +# +## s.b. preemptively +#[Pp]re[- ]emptively +# +## s.b. reentrancy +#[Rr]e[- ]entrancy +# +## s.b. reentrant +#[Rr]e[- ]entrant +# +## s.b. workaround(s) +#\bwork[- ]arounds?\b +# +## Reject duplicate words +#\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s From ab0e6640734df9ab78e403f7576d83c897c9748c Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Tue, 15 Jul 2025 19:16:59 +0800 Subject: [PATCH 1545/1798] Use a stable version --- .github/workflows/spelling.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml index 47bd66107..f738263fa 100644 --- a/.github/workflows/spelling.yml +++ b/.github/workflows/spelling.yml @@ -72,7 +72,7 @@ jobs: steps: - name: check-spelling id: spelling - uses: check-spelling/check-spelling@prerelease + uses: check-spelling/check-spelling@0.0.24 with: suppress_push_for_open_pull_request: 1 checkout: true @@ -128,7 +128,7 @@ jobs: if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request') steps: - name: comment - uses: check-spelling/check-spelling@prerelease + uses: check-spelling/check-spelling@0.0.24 with: checkout: true spell_check_this: check-spelling/spell-check-this@main From af50c7bdc3181665915656b3f52a46f52f860729 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Tue, 15 Jul 2025 19:57:42 +0800 Subject: [PATCH 1546/1798] Add double pinyin schemas to patterns They are not well formed English words so can be rejected by built-in checks. Use regex as a workaround. --- .github/actions/spelling/allow.txt | 2 -- .github/actions/spelling/expect.txt | 9 --------- .github/actions/spelling/patterns.txt | 9 +++++++++ 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/actions/spelling/allow.txt b/.github/actions/spelling/allow.txt index a36a6af3e..1d7f12d4a 100644 --- a/.github/actions/spelling/allow.txt +++ b/.github/actions/spelling/allow.txt @@ -4,5 +4,3 @@ ssh ubuntu runcount Firefox -Português -Português (Brasil) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index d8c99bce9..0fea6d9ab 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -104,12 +104,3 @@ metadatas WMP VSTHRD CJK -XiaoHe -ZiRanMa -WeiRuan -ZhiNengABC -ZiGuangPinYin -PinYinJiaJia -XingKongJianDao -DaNiu -XiaoLang diff --git a/.github/actions/spelling/patterns.txt b/.github/actions/spelling/patterns.txt index f308ec599..f7c54aa73 100644 --- a/.github/actions/spelling/patterns.txt +++ b/.github/actions/spelling/patterns.txt @@ -134,3 +134,12 @@ \bčeština\b \bPortuguês\b \bIoc\b +\bXiaoHe\b +\bZiRanMa\b +\bWeiRuan\b +\bZhiNengABC\b +\bZiGuangPinYin\b +\bPinYinJiaJia\b +\bXingKongJianDao\b +\bDaNiu\b +\bXiaoLang\b From a858aa8f5554b7e87d01c4c3d563516625ffdbc2 Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Tue, 15 Jul 2025 19:58:12 +0800 Subject: [PATCH 1547/1798] Update auto update desc Co-authored-by: Jeremy Wu --- Flow.Launcher/Languages/en.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 3905df7c6..725d8d3e1 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -93,7 +93,7 @@ Always Start Typing in English Mode Temporarily change your input method to English mode when activating Flow. Auto Update - Automatically check app updates and notify if there are any updates available + Automatically check and update the app when available Select Hide Flow Launcher on startup Flow Launcher search window is hidden in the tray after starting up. From 34238051cf2cca8be2cabec27d599548f27d2645 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Tue, 15 Jul 2025 20:03:17 +0800 Subject: [PATCH 1548/1798] Update spelling patterns to support optional spaces in Pinyin matching --- .github/actions/spelling/patterns.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/actions/spelling/patterns.txt b/.github/actions/spelling/patterns.txt index f7c54aa73..eb8534c49 100644 --- a/.github/actions/spelling/patterns.txt +++ b/.github/actions/spelling/patterns.txt @@ -134,12 +134,12 @@ \bčeština\b \bPortuguês\b \bIoc\b -\bXiaoHe\b -\bZiRanMa\b -\bWeiRuan\b -\bZhiNengABC\b -\bZiGuangPinYin\b -\bPinYinJiaJia\b -\bXingKongJianDao\b -\bDaNiu\b -\bXiaoLang\b +\bXiao\s*He\b +\bZi\s*Ran\s*Ma\b +\bWei\s*Ruan\b +\bZhi\s*Neng\s*ABC\b +\bZi\s*Guang\s*Pin\s*Yin\b +\bPin\s*Yin\s*Jia\s*Jia\b +\bXing\s*Kong\s*Jian\s*Dao\b +\bDa\s*Niu\b +\bXiao\s*Lang\b From 07415913ed5d0741fa021370bf459a89aad1c6f8 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Tue, 15 Jul 2025 20:05:03 +0800 Subject: [PATCH 1549/1798] Add word --- .github/actions/spelling/allow.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/spelling/allow.txt b/.github/actions/spelling/allow.txt index 1d7f12d4a..5bcf16c97 100644 --- a/.github/actions/spelling/allow.txt +++ b/.github/actions/spelling/allow.txt @@ -4,3 +4,4 @@ ssh ubuntu runcount Firefox +workaround \ No newline at end of file From e3e8eff5c989b2a6ef28aefd185b2dbe98952f2f Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Tue, 15 Jul 2025 20:06:33 +0800 Subject: [PATCH 1550/1798] Fix EOF newline --- .github/actions/spelling/allow.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/spelling/allow.txt b/.github/actions/spelling/allow.txt index 5bcf16c97..670a7a799 100644 --- a/.github/actions/spelling/allow.txt +++ b/.github/actions/spelling/allow.txt @@ -4,4 +4,4 @@ ssh ubuntu runcount Firefox -workaround \ No newline at end of file +workaround From 37d6cea2d32822c9b26ede0ee6f2b1a1e4cf5f63 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Tue, 15 Jul 2025 22:10:07 +1000 Subject: [PATCH 1551/1798] fix typo --- Flow.Launcher.Core/Plugin/PluginInstaller.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Plugin/PluginInstaller.cs b/Flow.Launcher.Core/Plugin/PluginInstaller.cs index c00c83d9e..a79f4b47c 100644 --- a/Flow.Launcher.Core/Plugin/PluginInstaller.cs +++ b/Flow.Launcher.Core/Plugin/PluginInstaller.cs @@ -281,7 +281,7 @@ public static class PluginInstaller /// /// Updates the plugin to the latest version available from its source. /// - /// If true, do not show any messages when there is no udpate available. + /// If true, do not show any messages when there is no update available. /// If true, only use the primary URL for updates. /// Cancellation token to cancel the update operation. /// From a34b8f2630a93c439dfea4107a9f27eeb5b3c464 Mon Sep 17 00:00:00 2001 From: WayneFerdon Date: Tue, 15 Jul 2025 21:22:19 +0800 Subject: [PATCH 1552/1798] [Plugin.Sys Enhancement] Support returning all usable commands while query is empty; ChangeQuery by ThemeSelector Action with ActionKeyword at the front as well --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 39bf49654..09581709f 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -70,13 +70,19 @@ namespace Flow.Launcher.Plugin.Sys return _themeSelector.Query(query); } - var commands = Commands(); + var commands = Commands(query); var results = new List(); + var isEmptyQuery = string.IsNullOrEmpty(query.Search) || string.IsNullOrWhiteSpace(query.Search); foreach (var c in commands) { var command = _settings.Commands.First(x => x.Key == c.Title); c.Title = command.Name; c.SubTitle = command.Description; + if (isEmptyQuery) + { + results.Add(c); + continue; + } // Match from localized title & localized subtitle & keyword var titleMatch = _context.API.FuzzySearch(query.Search, c.Title); @@ -188,7 +194,7 @@ namespace Flow.Launcher.Plugin.Sys } } - private List Commands() + private List Commands(Query query) { var results = new List(); var recycleBinFolder = "shell:RecycleBinFolder"; @@ -491,7 +497,7 @@ namespace Flow.Launcher.Plugin.Sys Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\ue790"), Action = c => { - _context.API.ChangeQuery($"{ThemeSelector.Keyword} "); + _context.API.ChangeQuery($"{query.ActionKeyword}{ (string.IsNullOrEmpty(query.ActionKeyword) ? string.Empty : Plugin.Query.ActionKeywordSeparator)}{ThemeSelector.Keyword}{Plugin.Query.ActionKeywordSeparator}"); return false; } } From aece80390560dec310327817f6c26618a8bacabc Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 15 Jul 2025 21:50:41 +0800 Subject: [PATCH 1553/1798] Simplify logic --- 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 09581709f..fc0770375 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -72,7 +72,7 @@ namespace Flow.Launcher.Plugin.Sys var commands = Commands(query); var results = new List(); - var isEmptyQuery = string.IsNullOrEmpty(query.Search) || string.IsNullOrWhiteSpace(query.Search); + var isEmptyQuery = string.IsNullOrWhiteSpace(query.Search); foreach (var c in commands) { var command = _settings.Commands.First(x => x.Key == c.Title); From 539a8523636678b8b10daa60181b04a13bc3cc25 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 15 Jul 2025 21:59:40 +0800 Subject: [PATCH 1554/1798] Improve logic --- Plugins/Flow.Launcher.Plugin.Sys/Main.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index fc0770375..d2dcf6e5a 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -497,7 +497,15 @@ namespace Flow.Launcher.Plugin.Sys Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\ue790"), Action = c => { - _context.API.ChangeQuery($"{query.ActionKeyword}{ (string.IsNullOrEmpty(query.ActionKeyword) ? string.Empty : Plugin.Query.ActionKeywordSeparator)}{ThemeSelector.Keyword}{Plugin.Query.ActionKeywordSeparator}"); + if (string.IsNullOrEmpty(query.ActionKeyword)) + { + _context.API.ChangeQuery($"{ThemeSelector.Keyword}{Plugin.Query.ActionKeywordSeparator}"); + } + else + { + _context.API.ChangeQuery($"{query.ActionKeyword}{Plugin.Query.ActionKeywordSeparator}{ThemeSelector.Keyword}{Plugin.Query.ActionKeywordSeparator}"); + + } return false; } } From 3bf1887362513444a45bd48e5b6c19f37056807b Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Tue, 15 Jul 2025 23:56:03 +0800 Subject: [PATCH 1555/1798] Intoduce dependency --- .../Flow.Launcher.Plugin.Explorer.csproj | 1 + 1 file changed, 1 insertion(+) 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 93691814a..6b1fcdd0d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -47,6 +47,7 @@ + From e116668ef9223ec24d3e4f8e1b26325ea9f9d4e7 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Tue, 15 Jul 2025 23:57:21 +0800 Subject: [PATCH 1556/1798] Rename file --- .../Search/Everything/{SortOption.cs => EverythingSortOption.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/{SortOption.cs => EverythingSortOption.cs} (100%) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/SortOption.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSortOption.cs similarity index 100% rename from Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/SortOption.cs rename to Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSortOption.cs From 363c0fb2a0984d7616c6fe7b496f1bef5ed7935e Mon Sep 17 00:00:00 2001 From: Kevin Zhang <45326534+taooceros@users.noreply.github.com> Date: Tue, 15 Jul 2025 18:11:16 -0500 Subject: [PATCH 1557/1798] Update dotnet.yml --- .github/workflows/dotnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 7498262de..812a56257 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -16,7 +16,7 @@ jobs: runs-on: windows-latest env: - FlowVersion: 1.19.5 + FlowVersion: 1.20.2 NUGET_CERT_REVOCATION_MODE: offline BUILD_NUMBER: ${{ github.run_number }} steps: From 5ed017b026ca3638a728b46027992aab7c691e07 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Wed, 16 Jul 2025 10:02:58 +0800 Subject: [PATCH 1558/1798] Revert line_forbidden.patterns --- .../actions/spelling/line_forbidden.patterns | 124 +++++++++--------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/.github/actions/spelling/line_forbidden.patterns b/.github/actions/spelling/line_forbidden.patterns index 119d89321..7341d9b73 100644 --- a/.github/actions/spelling/line_forbidden.patterns +++ b/.github/actions/spelling/line_forbidden.patterns @@ -1,62 +1,62 @@ -## reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere -## \bm_data\b -# -## If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test, -## you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want -## to use this: -##\bfit\( -# -## s.b. GitHub -##\bGithub\b -# -## s.b. GitLab -#\bGitlab\b -# -## s.b. JavaScript -#\bJavascript\b -# -## s.b. Microsoft -#\bMicroSoft\b -# -## s.b. another -#\ban[- ]other\b -# -## s.b. greater than -#\bgreater then\b -# -## s.b. into -#\sin to\s -# -## s.b. opt-in -#\sopt in\s -# -## s.b. less than -#\bless then\b -# -## s.b. otherwise -#\bother[- ]wise\b -# -## s.b. nonexistent -#\bnon existing\b -#\b[Nn]o[nt][- ]existent\b -# -## s.b. preexisting -#[Pp]re[- ]existing -# -## s.b. preempt -#[Pp]re[- ]empt\b -# -## s.b. preemptively -#[Pp]re[- ]emptively -# -## s.b. reentrancy -#[Rr]e[- ]entrancy -# -## s.b. reentrant -#[Rr]e[- ]entrant -# -## s.b. workaround(s) -#\bwork[- ]arounds?\b -# -## Reject duplicate words -#\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s +# reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere +# \bm_data\b + +# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test, +# you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want +# to use this: +#\bfit\( + +# s.b. GitHub +#\bGithub\b + +# s.b. GitLab +\bGitlab\b + +# s.b. JavaScript +\bJavascript\b + +# s.b. Microsoft +\bMicroSoft\b + +# s.b. another +\ban[- ]other\b + +# s.b. greater than +\bgreater then\b + +# s.b. into +\sin to\s + +# s.b. opt-in +\sopt in\s + +# s.b. less than +\bless then\b + +# s.b. otherwise +\bother[- ]wise\b + +# s.b. nonexistent +\bnon existing\b +\b[Nn]o[nt][- ]existent\b + +# s.b. preexisting +[Pp]re[- ]existing + +# s.b. preempt +[Pp]re[- ]empt\b + +# s.b. preemptively +[Pp]re[- ]emptively + +# s.b. reentrancy +[Rr]e[- ]entrancy + +# s.b. reentrant +[Rr]e[- ]entrant + +# s.b. workaround(s) +\bwork[- ]arounds?\b + +# Reject duplicate words +\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s From 30f7ae0d6726557bdd6d5878e240fe8817847bb6 Mon Sep 17 00:00:00 2001 From: VictoriousRaptor <10308169+VictoriousRaptor@users.noreply.github.com> Date: Wed, 16 Jul 2025 21:28:17 +0800 Subject: [PATCH 1559/1798] Use Localization for Explorer plugin --- .../Helper/SortOptionTranslationHelper.cs | 25 ----------- .../Languages/en.xaml | 41 ++++++++++++------- Plugins/Flow.Launcher.Plugin.Explorer/Main.cs | 2 - .../Search/Everything/EverythingAPI.cs | 7 ++-- .../Everything/EverythingApiDllImport.cs | 9 ++-- .../Everything/EverythingSearchOption.cs | 6 +-- .../Search/Everything/EverythingSortOption.cs | 32 ++++++++++++++- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 8 +--- .../ViewModels/SettingsViewModel.cs | 21 ++++++++-- .../Converters/EverythingEnumNameConverter.cs | 20 --------- .../Views/ExplorerSettings.xaml | 21 +++------- .../Views/ExplorerSettings.xaml.cs | 9 +--- 12 files changed, 93 insertions(+), 108 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Helper/SortOptionTranslationHelper.cs delete mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Views/Converters/EverythingEnumNameConverter.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Helper/SortOptionTranslationHelper.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Helper/SortOptionTranslationHelper.cs deleted file mode 100644 index 72f58f5b6..000000000 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Helper/SortOptionTranslationHelper.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Flow.Launcher.Plugin.Everything.Everything; -using JetBrains.Annotations; -using System; - -namespace Flow.Launcher.Plugin.Explorer.Helper; - -public static class SortOptionTranslationHelper -{ - [CanBeNull] - public static IPublicAPI API { get; internal set; } - - public static string GetTranslatedName(this SortOption sortOption) - { - const string prefix = "flowlauncher_plugin_everything_sort_by_"; - - ArgumentNullException.ThrowIfNull(API); - - var enumName = Enum.GetName(sortOption); - var splited = enumName!.Split('_'); - var name = string.Join('_', splited[..^1]); - var direction = splited[^1]; - - return $"{API.GetTranslation(prefix + name.ToLower())} {API.GetTranslation(prefix + direction.ToLower())}"; - } -} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index 2e0f6a67d..6a28a5be8 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -143,20 +143,33 @@ Warning: Everything service is not running Error while querying Everything Sort By - Name - Path - Size - Extension - Type Name - Date Created - Date Modified - Attributes - File List FileName - Run Count - Date Recently Changed - Date Accessed - Date Run - + Name ↑ + Name ↓ + Path ↑ + Path ↓ + Size ↑ + Size ↓ + Extension ↑ + Extension ↓ + Type Name ↑ + Type Name ↓ + Date Created ↑ + Date Created ↓ + Date Modified ↑ + Date Modified ↓ + 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 diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs index f1aea98b4..54292d550 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Main.cs @@ -42,8 +42,6 @@ namespace Flow.Launcher.Plugin.Explorer contextMenu = new ContextMenu(Context, Settings, viewModel); searchManager = new SearchManager(Settings, Context); ResultManager.Init(Context, Settings); - - SortOptionTranslationHelper.API = context.API; EverythingApiDllImport.Load(Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK", Environment.Is64BitProcess ? "x64" : "x86")); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs index 6159c9355..fd62566d5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs @@ -1,5 +1,4 @@ -using Flow.Launcher.Plugin.Everything.Everything; -using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions; +using Flow.Launcher.Plugin.Explorer.Search.Everything.Exceptions; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -36,7 +35,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything /// /// Checks whether the sort option is Fast Sort. /// - public static bool IsFastSortOption(SortOption sortOption) + public static bool IsFastSortOption(EverythingSortOption sortOption) { var fastSortOptionEnabled = EverythingApiDllImport.Everything_IsFastSort(sortOption); @@ -112,7 +111,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything EverythingApiDllImport.Everything_SetSort(option.SortOption); EverythingApiDllImport.Everything_SetMatchPath(option.IsFullPathSearch); - if (option.SortOption == SortOption.RUN_COUNT_DESCENDING) + if (option.SortOption == EverythingSortOption.RUN_COUNT_DESCENDING) { EverythingApiDllImport.Everything_SetRequestFlags(EVERYTHING_REQUEST_FULL_PATH_AND_FILE_NAME | EVERYTHING_REQUEST_RUN_COUNT); } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs index 5b80819fa..c952a980c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingApiDllImport.cs @@ -1,5 +1,4 @@ -using Flow.Launcher.Plugin.Everything.Everything; -using System; +using System; using System.IO; using System.Runtime.InteropServices; using System.Text; @@ -114,11 +113,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything // Everything 1.4 [DllImport(DLL)] - public static extern void Everything_SetSort(SortOption dwSortType); + public static extern void Everything_SetSort(EverythingSortOption dwSortType); [DllImport(DLL)] - public static extern bool Everything_IsFastSort(SortOption dwSortType); + public static extern bool Everything_IsFastSort(EverythingSortOption dwSortType); [DllImport(DLL)] - public static extern SortOption Everything_GetSort(); + public static extern EverythingSortOption Everything_GetSort(); [DllImport(DLL)] public static extern uint Everything_GetResultListSort(); [DllImport(DLL)] diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs index 92b8e9623..d8b670a08 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchOption.cs @@ -1,10 +1,8 @@ -using Flow.Launcher.Plugin.Everything.Everything; - -namespace Flow.Launcher.Plugin.Explorer.Search.Everything +namespace Flow.Launcher.Plugin.Explorer.Search.Everything { public record struct EverythingSearchOption( string Keyword, - SortOption SortOption, + EverythingSortOption SortOption, bool IsContentSearch = false, string ContentSearchKeyword = default, string ParentPath = default, diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSortOption.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSortOption.cs index 3c2fc3660..6a3d7cb67 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSortOption.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSortOption.cs @@ -1,31 +1,59 @@ -namespace Flow.Launcher.Plugin.Everything.Everything +using Flow.Launcher.Localization.Attributes; + +namespace Flow.Launcher.Plugin.Explorer.Search.Everything { - public enum SortOption : uint + [EnumLocalize] + public enum EverythingSortOption : uint { + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_name_ascending))] NAME_ASCENDING = 1u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_name_descending))] NAME_DESCENDING = 2u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_path_ascending))] PATH_ASCENDING = 3u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_path_descending))] PATH_DESCENDING = 4u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_size_ascending))] SIZE_ASCENDING = 5u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_size_descending))] SIZE_DESCENDING = 6u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_extension_ascending))] EXTENSION_ASCENDING = 7u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_extension_descending))] EXTENSION_DESCENDING = 8u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_type_name_ascending))] TYPE_NAME_ASCENDING = 9u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_type_name_descending))] TYPE_NAME_DESCENDING = 10u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_date_created_ascending))] DATE_CREATED_ASCENDING = 11u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_date_created_descending))] DATE_CREATED_DESCENDING = 12u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_date_modified_ascending))] DATE_MODIFIED_ASCENDING = 13u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_date_modified_descending))] DATE_MODIFIED_DESCENDING = 14u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_attributes_ascending))] ATTRIBUTES_ASCENDING = 15u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_attributes_descending))] ATTRIBUTES_DESCENDING = 16u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_file_list_filename_ascending))] FILE_LIST_FILENAME_ASCENDING = 17u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_file_list_filename_descending))] FILE_LIST_FILENAME_DESCENDING = 18u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_run_count_descending))] RUN_COUNT_DESCENDING = 20u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_date_recently_changed_ascending))] DATE_RECENTLY_CHANGED_ASCENDING = 21u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_date_recently_changed_descending))] DATE_RECENTLY_CHANGED_DESCENDING = 22u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_date_accessed_ascending))] DATE_ACCESSED_ASCENDING = 23u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_date_accessed_descending))] DATE_ACCESSED_DESCENDING = 24u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_date_run_ascending))] DATE_RUN_ASCENDING = 25u, + [EnumLocalizeKey(nameof(Localize.flowlauncher_plugin_everything_sort_by_date_run_descending))] DATE_RUN_DESCENDING = 26u } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 77540f3a8..672e81d03 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -1,5 +1,4 @@ -using Flow.Launcher.Plugin.Everything.Everything; -using Flow.Launcher.Plugin.Explorer.Search; +using Flow.Launcher.Plugin.Explorer.Search; using Flow.Launcher.Plugin.Explorer.Search.Everything; using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex; @@ -145,10 +144,7 @@ namespace Flow.Launcher.Plugin.Explorer public string EverythingInstalledPath { get; set; } - [JsonIgnore] - public SortOption[] SortOptions { get; set; } = Enum.GetValues(); - - public SortOption SortOption { get; set; } = SortOption.NAME_ASCENDING; + public EverythingSortOption SortOption { get; set; } = EverythingSortOption.NAME_ASCENDING; public bool EnableEverythingContentSearch { get; set; } = false; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 5aa6a13be..efffb19e0 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -35,6 +35,7 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels InitializeEngineSelection(); InitializeActionKeywordModels(); + EverythingSortOptionLocalized.UpdateLabels(AllEverythingSortOptions); } public void Save() @@ -578,6 +579,20 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels #region Everything FastSortWarning + public List AllEverythingSortOptions { get; } = EverythingSortOptionLocalized.GetValues(); + + public EverythingSortOption SelectedEverythingSortOption + { + get => Settings.SortOption; + set + { + Settings.SortOption = value; + OnPropertyChanged(nameof(SelectedEverythingSortOption)); + OnPropertyChanged(nameof(FastSortWarningVisibility)); + OnPropertyChanged(nameof(SortOptionWarningMessage)); + } + } + public Visibility FastSortWarningVisibility { get @@ -607,15 +622,15 @@ namespace Flow.Launcher.Plugin.Explorer.ViewModels // this method is used to determine if Everything service is running because as at Everything v1.4.1 // the sdk does not provide a dedicated interface to determine if it is running. return EverythingApi.IsFastSortOption(Settings.SortOption) ? string.Empty - : Context.API.GetTranslation("flowlauncher_plugin_everything_nonfastsort_warning"); + : Localize.flowlauncher_plugin_everything_nonfastsort_warning(); } catch (IPCErrorException) { - return Context.API.GetTranslation("flowlauncher_plugin_everything_is_not_running"); + return Localize.flowlauncher_plugin_everything_is_not_running(); } catch (DllNotFoundException) { - return Context.API.GetTranslation("flowlauncher_plugin_everything_sdk_issue"); + return Localize.flowlauncher_plugin_everything_sdk_issue(); } } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/Converters/EverythingEnumNameConverter.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Views/Converters/EverythingEnumNameConverter.cs deleted file mode 100644 index e24b21dcd..000000000 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/Converters/EverythingEnumNameConverter.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Flow.Launcher.Plugin.Everything.Everything; -using Flow.Launcher.Plugin.Explorer.Helper; -using System; -using System.Globalization; -using System.Windows.Data; - -namespace Flow.Launcher.Plugin.Explorer.Views.Converters; - -public class EnumNameConverter : IValueConverter -{ - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - return value is SortOption option ? option.GetTranslatedName() : value; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } -} \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index 59373b4de..08abc3ba6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -2,7 +2,6 @@ x:Class="Flow.Launcher.Plugin.Explorer.Views.ExplorerSettings" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:converters="clr-namespace:Flow.Launcher.Plugin.Explorer.Views.Converters" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:qa="clr-namespace:Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks" @@ -74,8 +73,6 @@ - - + + + + + + + + + + + + + + + + + +