From bfee170d0fbeba908d9f228771af7a08351e7a10 Mon Sep 17 00:00:00 2001 From: Sparrkle Date: Wed, 5 Oct 2022 16:20:41 +0900 Subject: [PATCH 01/58] 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 02/58] 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 03/58] 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 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 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 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 04/58] 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 05/58] 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 874a785be40cf57755fd0ebadfb554f6517ac8e8 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 18 Jan 2025 21:06:11 +1100 Subject: [PATCH 06/58] 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 07/58] 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 08/58] 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 5c48acad8922d9367bce917246a5de5d067e98ea Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 28 Feb 2025 11:26:14 +0800 Subject: [PATCH 09/58] Add loading api functions for all plugins --- .../Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs | 10 ++++++++++ Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs index e0a0434a2..8df2ce9ed 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCV2Models/JsonRPCPublicAPI.cs @@ -175,5 +175,15 @@ namespace Flow.Launcher.Core.Plugin.JsonRPCV2Models { _api.BackToQueryResults(); } + + public void StartLoadingBar() + { + _api.StartLoadingBar(); + } + + public void StopLoadingBar() + { + _api.StopLoadingBar(); + } } } diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 07fc378c3..fd96c82c4 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -335,5 +335,15 @@ namespace Flow.Launcher.Plugin /// When user closes the progress box manually by button or esc key, this action will be called. /// A progress box interface. public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action forceClosed = null); + + /// + /// Start the loading bar in main window + /// + public void StartLoadingBar(); + + /// + /// Stop the loading bar in main window + /// + public void StopLoadingBar(); } } From 4e4758677f2b533fb6ed107f948ff7d7a1ab2570 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sat, 1 Mar 2025 19:21:09 +0800 Subject: [PATCH 10/58] Remove unneccessary CreateSettingPanel by introducing need check --- Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs | 7 ++++++- Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs | 9 +++++++-- Flow.Launcher/ViewModel/PluginViewModel.cs | 8 ++++---- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs index ed8f94bcf..7248c6259 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginBase.cs @@ -34,7 +34,7 @@ namespace Flow.Launcher.Core.Plugin /// Represent the plugin that using JsonPRC /// every JsonRPC plugin should has its own plugin instance /// - internal abstract class JsonRPCPluginBase : IAsyncPlugin, IContextMenu, ISettingProvider, ISavable + public abstract class JsonRPCPluginBase : IAsyncPlugin, IContextMenu, ISettingProvider, ISavable { protected PluginInitContext Context; public const string JsonRPC = "JsonRPC"; @@ -157,6 +157,11 @@ namespace Flow.Launcher.Core.Plugin Settings?.Save(); } + public bool NeedCreateSettingPanel() + { + return Settings.NeedCreateSettingPanel(); + } + public Control CreateSettingPanel() { return Settings.CreateSettingPanel(); diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs b/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs index 2a4b22bf3..8412ba7e8 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPluginSettings.cs @@ -109,10 +109,15 @@ namespace Flow.Launcher.Core.Plugin _storage.Save(); } + public bool NeedCreateSettingPanel() + { + // If there are no settings or the settings configuration is empty, return null + return Settings != null && Configuration != null && Configuration.Body.Count != 0; + } + public Control CreateSettingPanel() { - if (Settings == null || Settings.Count == 0) - return null; + // No need to check if NeedCreateSettingPanel is true because CreateSettingPanel will only be called if it's true var settingWindow = new UserControl(); var mainPanel = new Grid { Margin = settingPanelMargin, VerticalAlignment = VerticalAlignment.Center }; diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 46f8e00a2..209a81395 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -90,13 +90,13 @@ namespace Flow.Launcher.ViewModel private Control _bottomPart2; public Control BottomPart2 => IsExpanded ? _bottomPart2 ??= new InstalledPluginDisplayBottomData() : null; - public bool HasSettingControl => PluginPair.Plugin is ISettingProvider settingProvider && settingProvider.CreateSettingPanel() != null; + public bool HasSettingControl => PluginPair.Plugin is ISettingProvider && (PluginPair.Plugin is not JsonRPCPluginBase jsonRPCPluginBase || jsonRPCPluginBase.NeedCreateSettingPanel()); public Control SettingControl => IsExpanded ? _settingControl - ??= PluginPair.Plugin is not ISettingProvider settingProvider - ? null - : settingProvider.CreateSettingPanel() + ??= HasSettingControl + ? ((ISettingProvider)PluginPair.Plugin).CreateSettingPanel() + : null : null; private ImageSource _image = ImageLoader.MissingImage; From 889f4cbfeb4959477c3c3db8bdaf66c527cb902e Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 4 Mar 2025 11:08:09 +0800 Subject: [PATCH 11/58] Fix null reference exception when checking source --- .../Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs index f4c8a66da..4ceadec56 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/PluginsManager.cs @@ -593,7 +593,10 @@ namespace Flow.Launcher.Plugin.PluginsManager var constructedUrlPart = string.Format("{0}/{1}/", acceptedSource, author); return url.StartsWith(acceptedSource) && - Context.API.GetAllPlugins().Any(x => x.Metadata.Website.StartsWith(constructedUrlPart)); + Context.API.GetAllPlugins().Any(x => + !string.IsNullOrEmpty(x.Metadata.Website) && + x.Metadata.Website.StartsWith(constructedUrlPart) + ); } internal async ValueTask> RequestInstallOrUpdateAsync(string search, CancellationToken token, From 92e6e53ab4a01d7eb201b6499dd814fdd92f573a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 5 Mar 2025 13:39:25 +0800 Subject: [PATCH 12/58] Use dependency injection instead of navigation parameter --- Flow.Launcher/MainWindow.xaml.cs | 2 +- Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs | 11 ++++------- Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs | 8 ++------ Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs | 9 +++------ Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs | 9 +++------ Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs | 9 +++------ .../ViewModels/SettingsPaneAboutViewModel.cs | 2 +- Flow.Launcher/WelcomeWindow.xaml.cs | 12 ++++-------- 8 files changed, 21 insertions(+), 41 deletions(-) diff --git a/Flow.Launcher/MainWindow.xaml.cs b/Flow.Launcher/MainWindow.xaml.cs index 3f1bae090..3616e4c59 100644 --- a/Flow.Launcher/MainWindow.xaml.cs +++ b/Flow.Launcher/MainWindow.xaml.cs @@ -445,7 +445,7 @@ namespace Flow.Launcher private void OpenWelcomeWindow() { - var WelcomeWindow = new WelcomeWindow(_settings); + var WelcomeWindow = new WelcomeWindow(); WelcomeWindow.Show(); } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs index 98fb47288..8d4312ba5 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Windows.Navigation; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Core.Resource; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Resources.Pages { @@ -10,10 +10,7 @@ namespace Flow.Launcher.Resources.Pages { protected override void OnNavigatedTo(NavigationEventArgs e) { - if (e.ExtraData is Settings settings) - Settings = settings; - else - throw new ArgumentException("Unexpected Navigation Parameter for Settings"); + Settings = Ioc.Default.GetRequiredService(); InitializeComponent(); } private Internationalization _translater => InternationalizationManager.Instance; @@ -37,4 +34,4 @@ namespace Flow.Launcher.Resources.Pages } } -} \ No newline at end of file +} diff --git a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs index 1ed5747cd..4a4679a4a 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs @@ -1,11 +1,11 @@ using Flow.Launcher.Helper; using Flow.Launcher.Infrastructure.Hotkey; using Flow.Launcher.Infrastructure.UserSettings; -using System; using System.Windows.Navigation; using CommunityToolkit.Mvvm.Input; using Flow.Launcher.ViewModel; using System.Windows.Media; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Resources.Pages { @@ -15,11 +15,7 @@ namespace Flow.Launcher.Resources.Pages protected override void OnNavigatedTo(NavigationEventArgs e) { - if (e.ExtraData is Settings settings) - Settings = settings; - else - throw new ArgumentException("Unexpected Parameter setting."); - + Settings = Ioc.Default.GetRequiredService(); InitializeComponent(); } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs index 9051e7c27..38cb8642a 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs @@ -1,5 +1,5 @@ -using System; -using System.Windows.Navigation; +using System.Windows.Navigation; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; namespace Flow.Launcher.Resources.Pages @@ -8,10 +8,7 @@ namespace Flow.Launcher.Resources.Pages { protected override void OnNavigatedTo(NavigationEventArgs e) { - if (e.ExtraData is Settings settings) - Settings = settings; - else if(Settings is null) - throw new ArgumentException("Unexpected Navigation Parameter for Settings"); + Settings = Ioc.Default.GetRequiredService(); InitializeComponent(); } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs index 11bbcd6ed..fc6568935 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs @@ -1,5 +1,5 @@ -using Flow.Launcher.Infrastructure.UserSettings; -using System; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Infrastructure.UserSettings; using System.Windows.Navigation; namespace Flow.Launcher.Resources.Pages @@ -8,10 +8,7 @@ namespace Flow.Launcher.Resources.Pages { protected override void OnNavigatedTo(NavigationEventArgs e) { - if (e.ExtraData is Settings settings) - Settings = settings; - else - throw new ArgumentException("Unexpected Navigation Parameter for Settings"); + Settings = Ioc.Default.GetRequiredService(); InitializeComponent(); } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs index abb805303..5327eb5c8 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs @@ -1,9 +1,9 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Navigation; using Flow.Launcher.Infrastructure.UserSettings; using Microsoft.Win32; using Flow.Launcher.Infrastructure; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.Resources.Pages { @@ -15,10 +15,7 @@ namespace Flow.Launcher.Resources.Pages protected override void OnNavigatedTo(NavigationEventArgs e) { - if (e.ExtraData is Settings settings) - Settings = settings; - else - throw new ArgumentException("Unexpected Navigation Parameter for Settings"); + Settings = Ioc.Default.GetRequiredService(); InitializeComponent(); } diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs index ade650284..6606b00f0 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneAboutViewModel.cs @@ -54,7 +54,7 @@ public partial class SettingsPaneAboutViewModel : BaseModel [RelayCommand] private void OpenWelcomeWindow() { - var window = new WelcomeWindow(_settings); + var window = new WelcomeWindow(); window.ShowDialog(); } diff --git a/Flow.Launcher/WelcomeWindow.xaml.cs b/Flow.Launcher/WelcomeWindow.xaml.cs index c3723a8c5..1d55b5741 100644 --- a/Flow.Launcher/WelcomeWindow.xaml.cs +++ b/Flow.Launcher/WelcomeWindow.xaml.cs @@ -2,7 +2,6 @@ using System.Windows; using System.Windows.Input; using System.Windows.Controls; -using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Resources.Pages; using ModernWpf.Media.Animation; @@ -10,13 +9,10 @@ namespace Flow.Launcher { public partial class WelcomeWindow : Window { - private readonly Settings settings; - - public WelcomeWindow(Settings settings) + public WelcomeWindow() { InitializeComponent(); BackButton.IsEnabled = false; - this.settings = settings; } private NavigationTransitionInfo _transitionInfo = new SlideNavigationTransitionInfo() @@ -57,7 +53,7 @@ namespace Flow.Launcher pageNum++; UpdateView(); - ContentFrame.Navigate(PageTypeSelector(pageNum), settings, _transitionInfo); + ContentFrame.Navigate(PageTypeSelector(pageNum), null, _transitionInfo); } private void BackwardButton_Click(object sender, RoutedEventArgs e) @@ -66,7 +62,7 @@ namespace Flow.Launcher { pageNum--; UpdateView(); - ContentFrame.Navigate(PageTypeSelector(pageNum), settings, _backTransitionInfo); + ContentFrame.Navigate(PageTypeSelector(pageNum), null, _backTransitionInfo); } else { @@ -109,7 +105,7 @@ namespace Flow.Launcher private void ContentFrame_Loaded(object sender, RoutedEventArgs e) { - ContentFrame.Navigate(PageTypeSelector(1), settings); /* Set First Page */ + ContentFrame.Navigate(PageTypeSelector(1)); /* Set First Page */ } } } From f2248e93b18d92dfc1c4d9d0920f2d9167044702 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 5 Mar 2025 14:42:08 +0800 Subject: [PATCH 13/58] Use dependency injection instead of dependency property --- Flow.Launcher/CustomQueryHotkeySetting.xaml | 1 - Flow.Launcher/HotkeyControl.xaml.cs | 139 +++++++++++++++--- Flow.Launcher/HotkeyControlDialog.xaml.cs | 7 +- .../Resources/Pages/WelcomePage2.xaml | 3 +- .../Views/SettingsPaneHotkey.xaml | 42 ++---- 5 files changed, 137 insertions(+), 55 deletions(-) diff --git a/Flow.Launcher/CustomQueryHotkeySetting.xaml b/Flow.Launcher/CustomQueryHotkeySetting.xaml index 70ebb404b..ccf4de870 100644 --- a/Flow.Launcher/CustomQueryHotkeySetting.xaml +++ b/Flow.Launcher/CustomQueryHotkeySetting.xaml @@ -103,7 +103,6 @@ HorizontalAlignment="Left" VerticalAlignment="Center" HorizontalContentAlignment="Left" - HotkeySettings="{Binding Settings}" DefaultHotkey="" /> (); + public string Hotkey { - get { return (string)GetValue(HotkeyProperty); } - set { SetValue(HotkeyProperty, value); } + get + { + return Type switch + { + HotkeyType.Hotkey => _settings.Hotkey, + HotkeyType.PreviewHotkey => _settings.PreviewHotkey, + HotkeyType.OpenContextMenuHotkey => _settings.OpenContextMenuHotkey, + HotkeyType.SettingWindowHotkey => _settings.SettingWindowHotkey, + HotkeyType.CycleHistoryUpHotkey => _settings.CycleHistoryUpHotkey, + HotkeyType.CycleHistoryDownHotkey => _settings.CycleHistoryDownHotkey, + HotkeyType.SelectPrevPageHotkey => _settings.SelectPrevPageHotkey, + HotkeyType.SelectNextPageHotkey => _settings.SelectNextPageHotkey, + HotkeyType.AutoCompleteHotkey => _settings.AutoCompleteHotkey, + HotkeyType.AutoCompleteHotkey2 => _settings.AutoCompleteHotkey2, + HotkeyType.SelectPrevItemHotkey => _settings.SelectPrevItemHotkey, + HotkeyType.SelectPrevItemHotkey2 => _settings.SelectPrevItemHotkey2, + HotkeyType.SelectNextItemHotkey => _settings.SelectNextItemHotkey, + HotkeyType.SelectNextItemHotkey2 => _settings.SelectNextItemHotkey2, + _ => string.Empty + }; + } + set + { + switch (Type) + { + case HotkeyType.Hotkey: + _settings.Hotkey = value; + break; + case HotkeyType.PreviewHotkey: + _settings.PreviewHotkey = value; + break; + case HotkeyType.OpenContextMenuHotkey: + _settings.OpenContextMenuHotkey = value; + break; + case HotkeyType.SettingWindowHotkey: + _settings.SettingWindowHotkey = value; + break; + case HotkeyType.CycleHistoryUpHotkey: + _settings.CycleHistoryUpHotkey = value; + break; + case HotkeyType.CycleHistoryDownHotkey: + _settings.CycleHistoryDownHotkey = value; + break; + case HotkeyType.SelectPrevPageHotkey: + _settings.SelectPrevPageHotkey = value; + break; + case HotkeyType.SelectNextPageHotkey: + _settings.SelectNextPageHotkey = value; + break; + case HotkeyType.AutoCompleteHotkey: + _settings.AutoCompleteHotkey = value; + break; + case HotkeyType.AutoCompleteHotkey2: + _settings.AutoCompleteHotkey2 = value; + break; + case HotkeyType.SelectPrevItemHotkey: + _settings.SelectPrevItemHotkey = value; + break; + case HotkeyType.SelectNextItemHotkey: + _settings.SelectNextItemHotkey = value; + break; + case HotkeyType.SelectPrevItemHotkey2: + _settings.SelectPrevItemHotkey2 = value; + break; + case HotkeyType.SelectNextItemHotkey2: + _settings.SelectNextItemHotkey2 = value; + break; + default: + return; + } + + // After setting the hotkey, we need to refresh the interface + RefreshHotkeyInterface(Hotkey); + } } public HotkeyControl() @@ -108,7 +198,14 @@ namespace Flow.Launcher InitializeComponent(); HotkeyList.ItemsSource = KeysToDisplay; - SetKeysToDisplay(CurrentHotkey); + + RefreshHotkeyInterface(Hotkey); + } + + public void RefreshHotkeyInterface(string hotkey) + { + SetKeysToDisplay(new HotkeyModel(Hotkey)); + CurrentHotkey = new HotkeyModel(Hotkey); } private static bool CheckHotkeyAvailability(HotkeyModel hotkey, bool validateKeyGesture) => @@ -133,7 +230,7 @@ namespace Flow.Launcher HotKeyMapper.RemoveHotkey(Hotkey); } - var dialog = new HotkeyControlDialog(Hotkey, DefaultHotkey, HotkeySettings, WindowTitle); + var dialog = new HotkeyControlDialog(Hotkey, DefaultHotkey, WindowTitle); await dialog.ShowAsync(); switch (dialog.ResultType) { diff --git a/Flow.Launcher/HotkeyControlDialog.xaml.cs b/Flow.Launcher/HotkeyControlDialog.xaml.cs index a4d21a782..2f8c5eb26 100644 --- a/Flow.Launcher/HotkeyControlDialog.xaml.cs +++ b/Flow.Launcher/HotkeyControlDialog.xaml.cs @@ -4,9 +4,11 @@ using System.Linq; 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; using Flow.Launcher.Plugin; using ModernWpf.Controls; @@ -16,7 +18,7 @@ namespace Flow.Launcher; public partial class HotkeyControlDialog : ContentDialog { - private IHotkeySettings _hotkeySettings; + private static readonly IHotkeySettings _hotkeySettings = Ioc.Default.GetRequiredService(); private Action? _overwriteOtherHotkey; private string DefaultHotkey { get; } public string WindowTitle { get; } @@ -36,7 +38,7 @@ public partial class HotkeyControlDialog : ContentDialog private static bool isOpenFlowHotkey; - public HotkeyControlDialog(string hotkey, string defaultHotkey, IHotkeySettings hotkeySettings, string windowTitle = "") + public HotkeyControlDialog(string hotkey, string defaultHotkey, string windowTitle = "") { WindowTitle = windowTitle switch { @@ -45,7 +47,6 @@ public partial class HotkeyControlDialog : ContentDialog }; DefaultHotkey = defaultHotkey; CurrentHotkey = new HotkeyModel(hotkey); - _hotkeySettings = hotkeySettings; SetKeysToDisplay(CurrentHotkey); InitializeComponent(); diff --git a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml index 6c6fcbb62..04c76d027 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml +++ b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml @@ -114,8 +114,7 @@ Margin="0,8,0,0" ChangeHotkey="{Binding SetTogglingHotkeyCommand}" DefaultHotkey="Alt+Space" - Hotkey="{Binding Settings.Hotkey}" - HotkeySettings="{Binding Settings}" + Type="Hotkey" ValidateKeyGesture="True" WindowTitle="{DynamicResource flowlauncherHotkey}" /> diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml index 22e3960ef..b1d72ede5 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml @@ -34,8 +34,7 @@ @@ -46,8 +45,7 @@ Sub="{DynamicResource previewHotkeyToolTip}"> @@ -105,8 +103,7 @@ Type="Inside"> @@ -221,8 +213,7 @@ @@ -244,8 +234,7 @@ @@ -267,8 +255,7 @@ From c68a764dcfcf1842224bee88ed136de67d08f510 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 5 Mar 2025 14:52:14 +0800 Subject: [PATCH 14/58] Improve code quality --- Flow.Launcher/HotkeyControl.xaml.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Flow.Launcher/HotkeyControl.xaml.cs b/Flow.Launcher/HotkeyControl.xaml.cs index 869774882..273d18e3f 100644 --- a/Flow.Launcher/HotkeyControl.xaml.cs +++ b/Flow.Launcher/HotkeyControl.xaml.cs @@ -111,7 +111,7 @@ namespace Flow.Launcher SelectNextItemHotkey2 } - // We can initialize settings in static field because it has been construct in App constuctor + // We can initialize settings in static field because it has been constructed in App constuctor // and it will not construct settings instances twice private static readonly Settings _settings = Ioc.Default.GetRequiredService(); @@ -202,7 +202,7 @@ namespace Flow.Launcher RefreshHotkeyInterface(Hotkey); } - public void RefreshHotkeyInterface(string hotkey) + private void RefreshHotkeyInterface(string hotkey) { SetKeysToDisplay(new HotkeyModel(Hotkey)); CurrentHotkey = new HotkeyModel(Hotkey); From 31d47a2340173b09ec30b1d1e6ab201796204fc1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 5 Mar 2025 15:18:06 +0800 Subject: [PATCH 15/58] Use dependency injection instead of navigation parameter --- .../SettingPages/Views/SettingsPaneAbout.xaml.cs | 10 ++++++---- .../SettingPages/Views/SettingsPaneGeneral.xaml.cs | 11 +++++++---- .../SettingPages/Views/SettingsPaneHotkey.xaml.cs | 8 ++++---- .../Views/SettingsPanePluginStore.xaml.cs | 8 ++++---- .../SettingPages/Views/SettingsPanePlugins.xaml.cs | 8 ++++---- .../SettingPages/Views/SettingsPaneProxy.xaml.cs | 10 ++++++---- .../SettingPages/Views/SettingsPaneTheme.xaml.cs | 10 ++++------ Flow.Launcher/SettingWindow.xaml.cs | 13 ++----------- 8 files changed, 37 insertions(+), 41 deletions(-) diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml.cs index de6a4df5e..1ecc02aa6 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneAbout.xaml.cs @@ -1,6 +1,8 @@ -using System; -using System.Windows.Navigation; +using System.Windows.Navigation; +using Flow.Launcher.Core; using Flow.Launcher.SettingPages.ViewModels; +using Flow.Launcher.Infrastructure.UserSettings; +using CommunityToolkit.Mvvm.DependencyInjection; namespace Flow.Launcher.SettingPages.Views; @@ -12,8 +14,8 @@ public partial class SettingsPaneAbout { if (!IsInitialized) { - if (e.ExtraData is not SettingWindow.PaneData { Settings: { } settings, Updater: { } updater }) - throw new ArgumentException("Settings are required for SettingsPaneAbout."); + var settings = Ioc.Default.GetRequiredService(); + var updater = Ioc.Default.GetRequiredService(); _viewModel = new SettingsPaneAboutViewModel(settings, updater); DataContext = _viewModel; InitializeComponent(); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs index f95015b2e..dd7fd13a9 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml.cs @@ -1,5 +1,7 @@ -using System; -using System.Windows.Navigation; +using System.Windows.Navigation; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Core; +using Flow.Launcher.Core.Configuration; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.SettingPages.ViewModels; @@ -13,8 +15,9 @@ public partial class SettingsPaneGeneral { if (!IsInitialized) { - if (e.ExtraData is not SettingWindow.PaneData { Settings: { } settings, Updater: {} updater, Portable: {} portable }) - throw new ArgumentException("Settings, Updater and Portable are required for SettingsPaneGeneral."); + var settings = Ioc.Default.GetRequiredService(); + var updater = Ioc.Default.GetRequiredService(); + var portable = Ioc.Default.GetRequiredService(); _viewModel = new SettingsPaneGeneralViewModel(settings, updater, portable); DataContext = _viewModel; InitializeComponent(); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs index 061eabf51..eb100da0c 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneHotkey.xaml.cs @@ -1,6 +1,7 @@ -using System; -using System.Windows.Navigation; +using System.Windows.Navigation; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.SettingPages.ViewModels; +using Flow.Launcher.Infrastructure.UserSettings; namespace Flow.Launcher.SettingPages.Views; @@ -12,8 +13,7 @@ public partial class SettingsPaneHotkey { if (!IsInitialized) { - if (e.ExtraData is not SettingWindow.PaneData { Settings: { } settings }) - throw new ArgumentException("Settings are required for SettingsPaneHotkey."); + var settings = Ioc.Default.GetRequiredService(); _viewModel = new SettingsPaneHotkeyViewModel(settings); DataContext = _viewModel; InitializeComponent(); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs index db4763319..3bd24bc13 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePluginStore.xaml.cs @@ -1,10 +1,11 @@ -using System; -using System.ComponentModel; +using System.ComponentModel; using System.Windows.Data; using System.Windows.Input; using System.Windows.Navigation; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.SettingPages.ViewModels; using Flow.Launcher.ViewModel; +using Flow.Launcher.Infrastructure.UserSettings; namespace Flow.Launcher.SettingPages.Views; @@ -16,8 +17,7 @@ public partial class SettingsPanePluginStore { if (!IsInitialized) { - if (e.ExtraData is not SettingWindow.PaneData { Settings: { } settings }) - throw new ArgumentException($"Settings are required for {nameof(SettingsPanePluginStore)}."); + var settings = Ioc.Default.GetRequiredService(); _viewModel = new SettingsPanePluginStoreViewModel(); DataContext = _viewModel; InitializeComponent(); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs index d48505c3d..f6b435186 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPanePlugins.xaml.cs @@ -1,7 +1,8 @@ -using System; -using System.Windows.Input; +using System.Windows.Input; using System.Windows.Navigation; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.SettingPages.ViewModels; +using Flow.Launcher.Infrastructure.UserSettings; namespace Flow.Launcher.SettingPages.Views; @@ -13,8 +14,7 @@ public partial class SettingsPanePlugins { if (!IsInitialized) { - if (e.ExtraData is not SettingWindow.PaneData { Settings: { } settings }) - throw new ArgumentException("Settings are required for SettingsPaneHotkey."); + var settings = Ioc.Default.GetRequiredService(); _viewModel = new SettingsPanePluginsViewModel(settings); DataContext = _viewModel; InitializeComponent(); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneProxy.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneProxy.xaml.cs index 95c88d627..26350b8bb 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneProxy.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneProxy.xaml.cs @@ -1,6 +1,8 @@ -using System; -using System.Windows.Navigation; +using System.Windows.Navigation; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Core; using Flow.Launcher.SettingPages.ViewModels; +using Flow.Launcher.Infrastructure.UserSettings; namespace Flow.Launcher.SettingPages.Views; @@ -12,8 +14,8 @@ public partial class SettingsPaneProxy { if (!IsInitialized) { - if (e.ExtraData is not SettingWindow.PaneData { Settings: { } settings, Updater: { } updater }) - throw new ArgumentException($"Settings are required for {nameof(SettingsPaneProxy)}."); + var settings = Ioc.Default.GetRequiredService(); + var updater = Ioc.Default.GetRequiredService(); _viewModel = new SettingsPaneProxyViewModel(settings, updater); DataContext = _viewModel; InitializeComponent(); diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs index 7f32728c2..bf7502e19 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneTheme.xaml.cs @@ -1,10 +1,9 @@ -using System; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; +using System.Windows.Controls; using System.Windows.Navigation; +using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.SettingPages.ViewModels; using Page = ModernWpf.Controls.Page; +using Flow.Launcher.Infrastructure.UserSettings; namespace Flow.Launcher.SettingPages.Views; @@ -16,8 +15,7 @@ public partial class SettingsPaneTheme : Page { if (!IsInitialized) { - if (e.ExtraData is not SettingWindow.PaneData { Settings: { } settings }) - throw new ArgumentException($"Settings are required for {nameof(SettingsPaneTheme)}."); + var settings = Ioc.Default.GetRequiredService(); _viewModel = new SettingsPaneThemeViewModel(settings); DataContext = _viewModel; InitializeComponent(); diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs index f87194c30..30b51f992 100644 --- a/Flow.Launcher/SettingWindow.xaml.cs +++ b/Flow.Launcher/SettingWindow.xaml.cs @@ -4,8 +4,6 @@ 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; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; @@ -18,8 +16,6 @@ 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; @@ -30,8 +26,6 @@ public partial class SettingWindow _settings = Ioc.Default.GetRequiredService(); DataContext = viewModel; _viewModel = viewModel; - _updater = Ioc.Default.GetRequiredService(); - _portable = Ioc.Default.GetRequiredService(); _api = Ioc.Default.GetRequiredService(); InitializePosition(); InitializeComponent(); @@ -166,10 +160,9 @@ public partial class SettingWindow private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) { - var paneData = new PaneData(_settings, _updater, _portable); if (args.IsSettingsSelected) { - ContentFrame.Navigate(typeof(SettingsPaneGeneral), paneData); + ContentFrame.Navigate(typeof(SettingsPaneGeneral)); } else { @@ -191,7 +184,7 @@ public partial class SettingWindow nameof(About) => typeof(SettingsPaneAbout), _ => typeof(SettingsPaneGeneral) }; - ContentFrame.Navigate(pageType, paneData); + ContentFrame.Navigate(pageType); } } @@ -211,6 +204,4 @@ public partial class SettingWindow { NavView.SelectedItem ??= NavView.MenuItems[0]; /* Set First Page */ } - - public record PaneData(Settings Settings, Updater Updater, IPortable Portable); } From 719d30ebf0a09e54a46948a786caa6069303ca0e Mon Sep 17 00:00:00 2001 From: Jack Ye <1160210343@qq.com> Date: Thu, 6 Mar 2025 07:41:22 +0800 Subject: [PATCH 16/58] Use official Task Scheduler --- Flow.Launcher/Flow.Launcher.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Flow.Launcher.csproj b/Flow.Launcher/Flow.Launcher.csproj index 33d13614f..8f6e47bbb 100644 --- a/Flow.Launcher/Flow.Launcher.csproj +++ b/Flow.Launcher/Flow.Launcher.csproj @@ -104,7 +104,7 @@ - + From 8ce4bd92e2d39331b40b5a6cc1344b4dd262a3a6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 6 Mar 2025 10:44:15 +0800 Subject: [PATCH 17/58] Fix page number issue when navigating with keyboard --- Flow.Launcher/App.xaml.cs | 1 + .../Resources/Pages/WelcomePage1.xaml.cs | 4 ++ .../Resources/Pages/WelcomePage2.xaml.cs | 3 + .../Resources/Pages/WelcomePage3.xaml.cs | 4 ++ .../Resources/Pages/WelcomePage4.xaml.cs | 4 ++ .../Resources/Pages/WelcomePage5.xaml.cs | 4 ++ Flow.Launcher/ViewModel/WelcomeViewModel.cs | 68 +++++++++++++++++++ Flow.Launcher/WelcomeWindow.xaml | 25 ++++--- Flow.Launcher/WelcomeWindow.xaml.cs | 66 ++++++++---------- 9 files changed, 132 insertions(+), 47 deletions(-) create mode 100644 Flow.Launcher/ViewModel/WelcomeViewModel.cs diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 447eca792..07b721b99 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -64,6 +64,7 @@ namespace Flow.Launcher .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() ).Build(); Ioc.Default.ConfigureServices(host.Services); } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs index 8d4312ba5..880bfd9bc 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage1.xaml.cs @@ -3,6 +3,7 @@ using System.Windows.Navigation; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Core.Resource; using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.ViewModel; namespace Flow.Launcher.Resources.Pages { @@ -11,6 +12,9 @@ namespace Flow.Launcher.Resources.Pages protected override void OnNavigatedTo(NavigationEventArgs e) { Settings = Ioc.Default.GetRequiredService(); + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page number + Ioc.Default.GetRequiredService().PageNum = 1; InitializeComponent(); } private Internationalization _translater => InternationalizationManager.Instance; diff --git a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs index 4a4679a4a..786b4d506 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage2.xaml.cs @@ -16,6 +16,9 @@ namespace Flow.Launcher.Resources.Pages protected override void OnNavigatedTo(NavigationEventArgs e) { Settings = Ioc.Default.GetRequiredService(); + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page number + Ioc.Default.GetRequiredService().PageNum = 2; InitializeComponent(); } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs index 38cb8642a..f59b65c1c 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage3.xaml.cs @@ -1,6 +1,7 @@ using System.Windows.Navigation; using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.ViewModel; namespace Flow.Launcher.Resources.Pages { @@ -9,6 +10,9 @@ namespace Flow.Launcher.Resources.Pages protected override void OnNavigatedTo(NavigationEventArgs e) { Settings = Ioc.Default.GetRequiredService(); + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page number + Ioc.Default.GetRequiredService().PageNum = 3; InitializeComponent(); } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs index fc6568935..4c83f3a83 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage4.xaml.cs @@ -1,5 +1,6 @@ using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Infrastructure.UserSettings; +using Flow.Launcher.ViewModel; using System.Windows.Navigation; namespace Flow.Launcher.Resources.Pages @@ -9,6 +10,9 @@ namespace Flow.Launcher.Resources.Pages protected override void OnNavigatedTo(NavigationEventArgs e) { Settings = Ioc.Default.GetRequiredService(); + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page number + Ioc.Default.GetRequiredService().PageNum = 4; InitializeComponent(); } diff --git a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs index 5327eb5c8..95d7ff1a0 100644 --- a/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs +++ b/Flow.Launcher/Resources/Pages/WelcomePage5.xaml.cs @@ -4,6 +4,7 @@ using Flow.Launcher.Infrastructure.UserSettings; using Microsoft.Win32; using Flow.Launcher.Infrastructure; using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.ViewModel; namespace Flow.Launcher.Resources.Pages { @@ -16,6 +17,9 @@ namespace Flow.Launcher.Resources.Pages protected override void OnNavigatedTo(NavigationEventArgs e) { Settings = Ioc.Default.GetRequiredService(); + // Sometimes the navigation is not triggered by button click, + // so we need to reset the page number + Ioc.Default.GetRequiredService().PageNum = 5; InitializeComponent(); } diff --git a/Flow.Launcher/ViewModel/WelcomeViewModel.cs b/Flow.Launcher/ViewModel/WelcomeViewModel.cs new file mode 100644 index 000000000..5eecabfde --- /dev/null +++ b/Flow.Launcher/ViewModel/WelcomeViewModel.cs @@ -0,0 +1,68 @@ +using Flow.Launcher.Plugin; + +namespace Flow.Launcher.ViewModel +{ + public partial class WelcomeViewModel : BaseModel + { + public const int MaxPageNum = 5; + + public string PageDisplay => $"{PageNum}/5"; + + private int _pageNum = 1; + public int PageNum + { + get => _pageNum; + set + { + if (_pageNum != value) + { + _pageNum = value; + OnPropertyChanged(); + UpdateView(); + } + } + } + + private bool _backEnabled = false; + public bool BackEnabled + { + get => _backEnabled; + set + { + _backEnabled = value; + OnPropertyChanged(); + } + } + + private bool _nextEnabled = true; + public bool NextEnabled + { + get => _nextEnabled; + set + { + _nextEnabled = value; + OnPropertyChanged(); + } + } + + private void UpdateView() + { + OnPropertyChanged(nameof(PageDisplay)); + if (PageNum == 1) + { + BackEnabled = false; + NextEnabled = true; + } + else if (PageNum == MaxPageNum) + { + BackEnabled = true; + NextEnabled = false; + } + else + { + BackEnabled = true; + NextEnabled = true; + } + } + } +} diff --git a/Flow.Launcher/WelcomeWindow.xaml b/Flow.Launcher/WelcomeWindow.xaml index 73f423d0b..e7c483f89 100644 --- a/Flow.Launcher/WelcomeWindow.xaml +++ b/Flow.Launcher/WelcomeWindow.xaml @@ -6,6 +6,7 @@ xmlns:local="clr-namespace:Flow.Launcher" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ui="http://schemas.modernwpf.com/2019" + xmlns:vm="clr-namespace:Flow.Launcher.ViewModel" Name="FlowWelcomeWindow" Title="{DynamicResource Welcome_Page1_Title}" Width="550" @@ -14,8 +15,10 @@ MinHeight="650" MaxWidth="550" MaxHeight="650" + d:DataContext="{d:DesignInstance Type=vm:WelcomeViewModel}" Activated="OnActivated" Background="{DynamicResource Color00B}" + Closed="Window_Closed" Foreground="{DynamicResource PopupTextColor}" MouseDown="window_MouseDown" WindowStartupLocation="CenterScreen" @@ -41,12 +44,12 @@ Grid.Column="0" Width="16" Height="16" - Margin="10,4,4,4" + Margin="10 4 4 4" RenderOptions.BitmapScalingMode="HighQuality" Source="/Images/app.png" /> + BorderThickness="0 1 0 0"> @@ -109,11 +112,11 @@ VerticalAlignment="Center"> @@ -122,25 +125,26 @@ Grid.Column="0" Width="100" Height="40" - Margin="20,5,0,5" + Margin="20 5 0 5" Click="BtnCancel_OnClick" Content="{DynamicResource Skip}" DockPanel.Dock="Right" FontSize="14" /> + + + + + + + + + + + + + + + + + + + +