diff --git a/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs b/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs index da92a358351..7fb9b895a24 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs @@ -120,10 +120,9 @@ public class Plugin public int Priority { get; set; } [JsonIgnore] - public SearchDelayTime? DefaultSearchDelayTime { get; set; } + public int? DefaultSearchDelayTime { get; set; } - [JsonConverter(typeof(JsonStringEnumConverter))] - public SearchDelayTime? SearchDelayTime { get; set; } + public int? 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 6cb20d12fdd..e304a1b5040 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/Settings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/Settings.cs @@ -321,9 +321,7 @@ public bool HideNotifyIcon public bool HideWhenDeactivated { get; set; } = true; public bool SearchQueryResultsWithDelay { get; set; } - - [JsonConverter(typeof(JsonStringEnumConverter))] - public SearchDelayTime SearchDelayTime { get; set; } = SearchDelayTime.Normal; + public int SearchDelayTime { get; set; } = 150; [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 1496765cea4..da10bc6a504 100644 --- a/Flow.Launcher.Plugin/PluginMetadata.cs +++ b/Flow.Launcher.Plugin/PluginMetadata.cs @@ -99,10 +99,9 @@ internal set public bool HideActionKeywordPanel { get; set; } /// - /// Plugin search delay time. Null means use default search delay time. + /// Plugin search delay time in ms. Null means use default search delay time. /// - [JsonConverter(typeof(JsonStringEnumConverter))] - public SearchDelayTime? SearchDelayTime { get; set; } = null; + public int? SearchDelayTime { get; set; } = null; /// /// Plugin icon path. diff --git a/Flow.Launcher.Plugin/SearchDelayTime.cs b/Flow.Launcher.Plugin/SearchDelayTime.cs deleted file mode 100644 index ae1daabe08a..00000000000 --- a/Flow.Launcher.Plugin/SearchDelayTime.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace Flow.Launcher.Plugin; - -/// -/// Enum for search delay time -/// -public enum SearchDelayTime -{ - /// - /// Very long search delay time. 250ms. - /// - VeryLong, - - /// - /// Long search delay time. 200ms. - /// - Long, - - /// - /// Normal search delay time. 150ms. Default value. - /// - Normal, - - /// - /// Short search delay time. 100ms. - /// - Short, - - /// - /// Very short search delay time. 50ms. - /// - VeryShort -} diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 24ab3cf9477..609859d0dab 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -108,14 +108,9 @@ 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) Search Plugin @@ -134,6 +129,10 @@ Change Action Keywords Plugin seach delay time Change Plugin Seach Delay Time + Advanced Settings: + Enabled + Priority + Search Delay Current Priority New Priority Priority @@ -149,7 +148,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 @@ -376,9 +374,7 @@ 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 + Input the search delay time in ms you like to use for the plugin. Input empty if you don't want to specify any, and the plugin will use default search delay time. Custom Query Hotkey diff --git a/Flow.Launcher/PriorityChangeWindow.xaml b/Flow.Launcher/PriorityChangeWindow.xaml deleted file mode 100644 index 33ed54bb4fa..00000000000 --- 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 fbe2a941d26..00000000000 --- 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 b19c668e0bd..2310362443a 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml @@ -3,6 +3,7 @@ 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" xmlns:ui="http://schemas.modernwpf.com/2019" @@ -11,6 +12,9 @@ d:DesignHeight="300" d:DesignWidth="300" mc:Ignorable="d"> + + + + - - + Orientation="Horizontal" + Visibility="{Binding DataContext.IsSearchDelaySelected, RelativeSource={RelativeSource AncestorType=ListBox}, Converter={StaticResource BooleanToVisibilityConverter}}"> + + + + + OnContent="{DynamicResource enable}" + Visibility="{Binding DataContext.IsOnOffSelected, RelativeSource={RelativeSource AncestorType=ListBox}, Converter={StaticResource BooleanToVisibilityConverter}}" /> @@ -98,8 +116,6 @@ - - - + diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs b/Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml.cs index dfa03a2043f..a27a007823c 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,13 @@ public 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)) + { + sender.Value = 0; + } + } } diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelay.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelay.xaml deleted file mode 100644 index 0fd98bfac42..00000000000 --- a/Flow.Launcher/Resources/Controls/InstalledPluginSearchDelay.xaml +++ /dev/null @@ -1,49 +0,0 @@ - - - - -  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Flow.Launcher/SearchDelayTimeWindow.xaml.cs b/Flow.Launcher/SearchDelayTimeWindow.xaml.cs deleted file mode 100644 index 4a3c9f5a730..00000000000 --- 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 cec8c318c59..35dbab64776 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,7 @@ public class SearchWindowScreenData : DropdownDataGeneric { public class SearchWindowAlignData : DropdownDataGeneric { } public class SearchPrecisionData : DropdownDataGeneric { } public class LastQueryModeData : DropdownDataGeneric { } - public class SearchDelayTimeData : DropdownDataGeneric { } + public bool StartFlowLauncherOnSystemStartup { @@ -144,25 +145,20 @@ public bool PortableMode public List LastQueryModes { get; } = DropdownDataGeneric.GetValues("LastQuery"); - public List SearchDelayTimes { get; } = - DropdownDataGeneric.GetValues("SearchDelayTime"); - - public SearchDelayTimeData SearchDelayTime + public int SearchDelayTimeValue { - get => SearchDelayTimes.FirstOrDefault(x => x.Value == Settings.SearchDelayTime) ?? - SearchDelayTimes.FirstOrDefault(x => x.Value == Plugin.SearchDelayTime.Normal) ?? - SearchDelayTimes.FirstOrDefault(); + 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() { @@ -170,7 +166,6 @@ private void UpdateEnumDropdownLocalizations() DropdownDataGeneric.UpdateLabels(SearchWindowAligns); DropdownDataGeneric.UpdateLabels(SearchPrecisionScores); DropdownDataGeneric.UpdateLabels(LastQueryModes); - DropdownDataGeneric.UpdateLabels(SearchDelayTimes); } public string Language diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs index 3c1aba400a0..4958bb7b748 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPanePluginsViewModel.cs @@ -1,22 +1,90 @@ using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using System.Windows.Controls; +using System.Windows; +using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core.Plugin; using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; +using ModernWpf.Controls; #nullable enable namespace Flow.Launcher.SettingPages.ViewModels; -public class SettingsPanePluginsViewModel : BaseModel +public partial class SettingsPanePluginsViewModel : BaseModel { private readonly Settings _settings; + public class DisplayModeData : DropdownDataGeneric { } + + public List DisplayModes { get; } = + DropdownDataGeneric.GetValues("DisplayMode"); + + private DisplayMode _selectedDisplayMode = DisplayMode.OnOff; + public DisplayMode SelectedDisplayMode + { + get => _selectedDisplayMode; + set + { + if (_selectedDisplayMode != value) + { + _selectedDisplayMode = value; + OnPropertyChanged(); + UpdateDisplayModeFromSelection(); + } + } + } + + private bool _isOnOffSelected = true; + public bool IsOnOffSelected + { + get => _isOnOffSelected; + set + { + if (_isOnOffSelected != value) + { + _isOnOffSelected = value; + OnPropertyChanged(); + } + } + } + + private bool _isPrioritySelected; + public bool IsPrioritySelected + { + get => _isPrioritySelected; + set + { + if (_isPrioritySelected != value) + { + _isPrioritySelected = value; + OnPropertyChanged(); + } + } + } + + private bool _isSearchDelaySelected; + public bool IsSearchDelaySelected + { + get => _isSearchDelaySelected; + set + { + if (_isSearchDelaySelected != value) + { + _isSearchDelaySelected = value; + OnPropertyChanged(); + } + } + } + public SettingsPanePluginsViewModel(Settings settings) { _settings = settings; + UpdateEnumDropdownLocalizations(); } public string FilterText { get; set; } = string.Empty; @@ -42,4 +110,82 @@ public SettingsPanePluginsViewModel(Settings settings) StringMatcher.FuzzySearch(FilterText, v.PluginPair.Metadata.Description).IsSearchPrecisionScoreMet() ) .ToList(); + + [RelayCommand] + private async Task OpenHelperAsync() + { + var helpDialog = new ContentDialog() + { + Content = new StackPanel + { + Children = + { + new TextBlock + { + Text = (string)Application.Current.Resources["priority"], + FontSize = 18, + Margin = new Thickness(0, 0, 0, 10), + TextWrapping = TextWrapping.Wrap + }, + new TextBlock + { + Text = (string)Application.Current.Resources["priority_tips"], + TextWrapping = TextWrapping.Wrap + }, + new TextBlock + { + Text = (string)Application.Current.Resources["searchDelay"], + FontSize = 18, + Margin = new Thickness(0, 24, 0, 10), + TextWrapping = TextWrapping.Wrap + }, + new TextBlock + { + Text = (string)Application.Current.Resources["searchDelayTimeTips"], + TextWrapping = TextWrapping.Wrap + } + } + }, + + PrimaryButtonText = (string)Application.Current.Resources["commonOK"], + CornerRadius = new CornerRadius(8), + Style = (Style)Application.Current.Resources["ContentDialog"] + }; + + await helpDialog.ShowAsync(); + } + + private void UpdateEnumDropdownLocalizations() + { + DropdownDataGeneric.UpdateLabels(DisplayModes); + } + + private void UpdateDisplayModeFromSelection() + { + switch (SelectedDisplayMode) + { + case DisplayMode.Priority: + IsOnOffSelected = false; + IsPrioritySelected = true; + IsSearchDelaySelected = false; + break; + case DisplayMode.SearchDelay: + IsOnOffSelected = false; + IsPrioritySelected = false; + IsSearchDelaySelected = true; + break; + default: + IsOnOffSelected = true; + IsPrioritySelected = false; + IsSearchDelaySelected = false; + break; + } + } +} + +public enum DisplayMode +{ + OnOff, + Priority, + SearchDelay } diff --git a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml index 3f8272ddafe..657e97f30a8 100644 --- a/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml +++ b/Flow.Launcher/SettingPages/Views/SettingsPaneGeneral.xaml @@ -196,6 +196,35 @@ + + + + + + + + + + + - - - @@ -31,58 +28,93 @@ Style="{StaticResource PageTitle}" Text="{DynamicResource plugins}" TextAlignment="Left" /> - - - - - + Orientation="Horizontal"> + + +