Merge pull request #3421 from onesounds/250331-NewPluginsPage

Plugin Page Control Swap Feature & Restore "Search Delay" Field in General Page
This commit is contained in:
DB P 2025-04-08 22:46:16 +09:00 committed by GitHub
commit d33e751ad1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 483 additions and 711 deletions

View file

@ -120,10 +120,9 @@ namespace Flow.Launcher.Infrastructure.UserSettings
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; }
/// <summary>
/// Used only to save the state of the plugin in settings

View file

@ -321,9 +321,7 @@ namespace Flow.Launcher.Infrastructure.UserSettings
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;

View file

@ -99,10 +99,9 @@ namespace Flow.Launcher.Plugin
public bool HideActionKeywordPanel { get; set; }
/// <summary>
/// Plugin search delay time. Null means use default search delay time.
/// Plugin search delay time in ms. Null means use default search delay time.
/// </summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public SearchDelayTime? SearchDelayTime { get; set; } = null;
public int? SearchDelayTime { get; set; } = null;
/// <summary>
/// Plugin icon path.

View file

@ -1,32 +0,0 @@
namespace Flow.Launcher.Plugin;
/// <summary>
/// Enum for search delay time
/// </summary>
public enum SearchDelayTime
{
/// <summary>
/// Very long search delay time. 250ms.
/// </summary>
VeryLong,
/// <summary>
/// Long search delay time. 200ms.
/// </summary>
Long,
/// <summary>
/// Normal search delay time. 150ms. Default value.
/// </summary>
Normal,
/// <summary>
/// Short search delay time. 100ms.
/// </summary>
Short,
/// <summary>
/// Very short search delay time. 50ms.
/// </summary>
VeryShort
}

View file

@ -108,14 +108,9 @@
<system:String x:Key="AlwaysPreviewToolTip">Always open preview panel when Flow activates. Press {0} to toggle preview.</system:String>
<system:String x:Key="shadowEffectNotAllowed">Shadow effect is not allowed while current theme has blur effect enabled</system:String>
<system:String x:Key="searchDelay">Search Delay</system:String>
<system:String x:Key="searchDelayToolTip">Delay for a while to search when typing. This reduces interface jumpiness and result load.</system:String>
<system:String x:Key="searchDelayToolTip">Adds a short delay while typing to reduce UI flicker and result load. Recommended if your typing speed is average.</system:String>
<system:String x:Key="searchDelayTime">Default Search Delay Time</system:String>
<system:String x:Key="searchDelayTimeToolTip">Plugin default delay time after which search results appear when typing is stopped.</system:String>
<system:String x:Key="SearchDelayTimeVeryLong">Very long</system:String>
<system:String x:Key="SearchDelayTimeLong">Long</system:String>
<system:String x:Key="SearchDelayTimeNormal">Normal</system:String>
<system:String x:Key="SearchDelayTimeShort">Short</system:String>
<system:String x:Key="SearchDelayTimeVeryShort">Very short</system:String>
<system:String x:Key="searchDelayTimeToolTip">Wait time before showing results after typing stops. Higher values wait longer. (ms)</system:String>
<!-- Setting Plugin -->
<system:String x:Key="searchplugin">Search Plugin</system:String>
@ -134,6 +129,10 @@
<system:String x:Key="actionKeywordsTooltip">Change Action Keywords</system:String>
<system:String x:Key="pluginSearchDelayTime">Plugin seach delay time</system:String>
<system:String x:Key="pluginSearchDelayTimeTooltip">Change Plugin Seach Delay Time</system:String>
<system:String x:Key="FilterComboboxLabel">Advanced Settings:</system:String>
<system:String x:Key="DisplayModeOnOff">Enabled</system:String>
<system:String x:Key="DisplayModePriority">Priority</system:String>
<system:String x:Key="DisplayModeSearchDelay">Search Delay</system:String>
<system:String x:Key="currentPriority">Current Priority</system:String>
<system:String x:Key="newPriority">New Priority</system:String>
<system:String x:Key="priority">Priority</system:String>
@ -149,7 +148,6 @@
<system:String x:Key="failedToRemovePluginSettingsMessage">Plugins: {0} - Fail to remove plugin settings files, please remove them manually</system:String>
<system:String x:Key="failedToRemovePluginCacheTitle">Fail to remove plugin cache</system:String>
<system:String x:Key="failedToRemovePluginCacheMessage">Plugins: {0} - Fail to remove plugin cache files, please remove them manually</system:String>
<system:String x:Key="default">Default</system:String>
<!-- Setting Plugin Store -->
<system:String x:Key="pluginStore">Plugin Store</system:String>
@ -376,9 +374,7 @@
<!-- Search Delay Settings Dialog -->
<system:String x:Key="searchDelayTimeTitle">Search Delay Time Setting</system:String>
<system:String x:Key="searchDelayTime_tips">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.</system:String>
<system:String x:Key="currentSearchDelayTime">Current search delay time</system:String>
<system:String x:Key="newSearchDelayTime">New search delay time</system:String>
<system:String x:Key="searchDelayTimeTips">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.</system:String>
<!-- Custom Query Hotkey Dialog -->
<system:String x:Key="customeQueryHotkeyTitle">Custom Query Hotkey</system:String>

View file

@ -1,121 +0,0 @@
<Window
x:Class="Flow.Launcher.PriorityChangeWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Flow.Launcher"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.modernwpf.com/2019"
Title="{DynamicResource changePriorityWindow}"
Width="350"
Background="{DynamicResource PopuBGColor}"
Foreground="{DynamicResource PopupTextColor}"
Loaded="PriorityChangeWindow_Loaded"
MouseDown="window_MouseDown"
ResizeMode="NoResize"
SizeToContent="Height"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="1"
Click="BtnCancel_OnClick"
Style="{StaticResource TitleBarCloseButtonStyle}">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</Grid>
</StackPanel>
<StackPanel Margin="26,12,26,0">
<StackPanel Margin="0,0,0,12">
<TextBlock
Grid.Column="0"
Margin="0,0,0,0"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource changePriorityWindow}"
TextAlignment="Left" />
</StackPanel>
<StackPanel>
<TextBlock
FontSize="14"
Text="{DynamicResource priority_tips}"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
</StackPanel>
<StackPanel Margin="0,24,0,24" Orientation="Horizontal">
<TextBlock
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource priority}" />
<ui:NumberBox
x:Name="tbAction"
Width="200"
Maximum="100"
Minimum="-100"
Margin="10,0,15,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
CornerRadius="4"
SmallChange="1"
SpinButtonPlacementMode="Inline" />
</StackPanel>
</StackPanel>
</StackPanel>
<Border
Grid.Row="1"
Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0,1,0,0">
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Button
x:Name="btnCancel"
Width="145"
Height="30"
Margin="0,0,5,0"
Click="BtnCancel_OnClick"
Content="{DynamicResource cancel}" />
<Button
x:Name="btnDone"
Width="145"
Height="30"
Margin="5,0,0,0"
Click="btnDone_OnClick"
Style="{StaticResource AccentButtonStyle}">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button>
</StackPanel>
</Border>
</Grid>
</Window>

View file

@ -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
{
/// <summary>
/// Interaction Logic of PriorityChangeWindow.xaml
/// </summary>
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);
}
}
}
}

View file

@ -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">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</UserControl.Resources>
<Expander
Padding="0"
BorderThickness="0"
@ -44,52 +48,66 @@
Text="{Binding PluginPair.Metadata.Description}"
TextWrapping="WrapWithOverflow" />
</StackPanel>
<StackPanel
Grid.Column="2"
HorizontalAlignment="Right"
Orientation="Horizontal">
<TextBlock
Margin="0 0 8 0"
<StackPanel
x:Name="PriorityControl"
VerticalAlignment="Center"
FontSize="12"
Foreground="{DynamicResource Color08B}"
Text="{DynamicResource priority}" />
<Button
x:Name="PriorityButton"
Margin="0 0 22 0"
VerticalAlignment="Center"
Command="{Binding EditPluginPriorityCommand}"
Content="{Binding Priority}"
Cursor="Hand"
ToolTip="{DynamicResource priorityToolTip}">
<!--#region Priority Button Style-->
<Button.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="2" />
</Style>
</Button.Resources>
<Button.Style>
<Style BasedOn="{StaticResource DefaultButtonStyle}" TargetType="Button">
<Setter Property="Padding" Value="12 8" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FontWeight" Value="DemiBold" />
<Setter Property="Foreground" Value="{DynamicResource Color05B}" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=PriorityButton, UpdateSourceTrigger=PropertyChanged, Path=Content}" Value="0">
<Setter Property="Foreground" Value="{DynamicResource Color08B}" />
<Setter Property="FontWeight" Value="Normal" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<!--#endregion-->
</Button>
Orientation="Horizontal"
Visibility="{Binding DataContext.IsPrioritySelected, RelativeSource={RelativeSource AncestorType=ListBox}, Converter={StaticResource BooleanToVisibilityConverter}}">
<TextBlock
Margin="0 0 8 0"
VerticalAlignment="Center"
FontSize="13"
Foreground="{DynamicResource Color08B}"
Text="{DynamicResource priority}"
ToolTip="{DynamicResource priorityToolTip}" />
<ui:NumberBox
Margin="0 0 8 0"
Maximum="999"
Minimum="-999"
SpinButtonPlacementMode="Inline"
ToolTip="{DynamicResource priorityToolTip}"
ValueChanged="NumberBox_OnValueChanged"
Value="{Binding Priority, Mode=TwoWay}" />
</StackPanel>
<StackPanel
x:Name="SearchDelayControl"
VerticalAlignment="Center"
Orientation="Horizontal"
Visibility="{Binding DataContext.IsSearchDelaySelected, RelativeSource={RelativeSource AncestorType=ListBox}, Converter={StaticResource BooleanToVisibilityConverter}}">
<TextBlock
Margin="0 0 8 0"
VerticalAlignment="Center"
FontSize="13"
Foreground="{DynamicResource Color08B}"
Text="{DynamicResource searchDelay}"
ToolTip="{DynamicResource searchDelayToolTip}" />
<ui:NumberBox
Width="120"
Margin="0 0 8 0"
IsEnabled="{Binding SearchDelayEnabled}"
Maximum="1000"
Minimum="0"
PlaceholderText="{Binding DefaultSearchDelay}"
SmallChange="10"
SpinButtonPlacementMode="Compact"
ToolTip="{DynamicResource searchDelayToolTip}"
Value="{Binding PluginSearchDelayTime, Mode=TwoWay}" />
</StackPanel>
<!-- Put OnOffControl after PriorityControl & SearchDelayControl so that it can display correctly -->
<ui:ToggleSwitch
x:Name="OnOffControl"
Margin="0 0 8 0"
IsOn="{Binding PluginState}"
OffContent="{DynamicResource disable}"
OnContent="{DynamicResource enable}" />
OnContent="{DynamicResource enable}"
Visibility="{Binding DataContext.IsOnOffSelected, RelativeSource={RelativeSource AncestorType=ListBox}, Converter={StaticResource BooleanToVisibilityConverter}}" />
</StackPanel>
</Grid>
</Border>
@ -98,8 +116,6 @@
<StackPanel>
<ContentControl Content="{Binding BottomPart1}" />
<ContentControl Content="{Binding BottomPart2}" />
<Border
Background="{DynamicResource Color00B}"
BorderBrush="{DynamicResource Color03B}"
@ -120,7 +136,7 @@
Content="{Binding SettingControl}" />
</Border>
<ContentControl Content="{Binding BottomPart3}" />
<ContentControl Content="{Binding BottomPart2}" />
</StackPanel>
</Expander>
</UserControl>

View file

@ -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 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))
{
sender.Value = 0;
}
}
}

View file

@ -1,49 +0,0 @@
<UserControl
x:Class="Flow.Launcher.Resources.Controls.InstalledPluginSearchDelay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModel="clr-namespace:Flow.Launcher.ViewModel"
d:DataContext="{d:DesignInstance viewModel:PluginViewModel}"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Border
Width="Auto"
Height="Auto"
Margin="0"
Padding="0"
BorderThickness="0 1 0 0"
CornerRadius="0"
Style="{DynamicResource SettingGroupBox}">
<DockPanel Margin="{StaticResource SettingPanelMargin}">
<TextBlock
Margin="{StaticResource SettingPanelItemRightMargin}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
DockPanel.Dock="Left"
Style="{StaticResource Glyph}">
&#xE916;
</TextBlock>
<TextBlock
Margin="{StaticResource SettingPanelItemRightMargin}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
DockPanel.Dock="Left"
Style="{DynamicResource SettingTitleLabel}"
Text="{DynamicResource pluginSearchDelayTime}" />
<!-- Here Margin="0 -4.5 0 -4.5" is to remove redundant top bottom margin from Margin="{StaticResource SettingPanelMargin}" -->
<Button
Width="100"
Margin="0 -4.5 0 -4.5"
HorizontalAlignment="Right"
Command="{Binding SetSearchDelayTimeCommand}"
Content="{Binding SearchDelayTimeText}"
Cursor="Hand"
DockPanel.Dock="Right"
FontWeight="Bold"
ToolTip="{DynamicResource pluginSearchDelayTimeTooltip}" />
</DockPanel>
</Border>
</UserControl>

View file

@ -1,11 +0,0 @@
using System.Windows.Controls;
namespace Flow.Launcher.Resources.Controls;
public partial class InstalledPluginSearchDelay : UserControl
{
public InstalledPluginSearchDelay()
{
InitializeComponent();
}
}

View file

@ -1503,7 +1503,7 @@
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ui:ControlHelper.PlaceholderForeground" Value="{x:Null}">
<Setter TargetName="PlaceholderTextContentPresenter" Property="Foreground" Value="{DynamicResource TextControlPlaceholderForeground}" />
<Setter TargetName="PlaceholderTextContentPresenter" Property="Foreground" Value="{DynamicResource CustomContextDisabled}" />
</Trigger>
<Trigger Property="ui:TextBoxHelper.HasText" Value="True">
<Setter TargetName="PlaceholderTextContentPresenter" Property="Visibility" Value="Collapsed" />
@ -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">
<Border
x:Name="BorderElementInline"
MinWidth="{TemplateBinding MinWidth}"
MinHeight="{TemplateBinding MinHeight}"
ui:ValidationHelper.IsTemplateValidationAdornerSite="True"
Background="{TemplateBinding Background}"
BorderBrush="{DynamicResource CustomTextBoxInline}"
BorderThickness="{DynamicResource CustomTextBoxInlineThickness}"
CornerRadius="{TemplateBinding ui:ControlHelper.CornerRadius}" />
</Border>
<ScrollViewer
x:Name="PART_ContentHost"
Grid.Row="1"
@ -2767,7 +2777,7 @@
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="ui:ControlHelper.PlaceholderForeground" Value="{x:Null}">
<Setter TargetName="PlaceholderTextContentPresenter" Property="Foreground" Value="{DynamicResource TextControlPlaceholderForeground}" />
<Setter TargetName="PlaceholderTextContentPresenter" Property="Foreground" Value="{DynamicResource NumberBoxPlaceHolder}" />
</Trigger>
<Trigger Property="ui:TextBoxHelper.HasText" Value="True">
<Setter TargetName="PlaceholderTextContentPresenter" Property="Visibility" Value="Collapsed" />
@ -2780,7 +2790,7 @@
<Setter TargetName="PlaceholderTextContentPresenter" Property="Foreground" Value="{DynamicResource TextControlPlaceholderForegroundDisabled}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="BorderElement" Property="BorderBrush" Value="{DynamicResource TextControlBorderBrushPointerOver}" />
<Setter TargetName="BorderElementInline" Property="BorderBrush" Value="{DynamicResource TextControlBorderBrushPointerOver}" />
<Setter Property="Background" Value="{DynamicResource TextControlBackgroundPointerOver}" />
<Setter TargetName="PlaceholderTextContentPresenter" Property="Foreground" Value="{DynamicResource TextControlPlaceholderForegroundPointerOver}" />
<Setter Property="Foreground" Value="{DynamicResource TextControlForegroundPointerOver}" />
@ -2788,8 +2798,10 @@
<Trigger Property="IsSelectionActive" Value="true">
<Setter TargetName="PlaceholderTextContentPresenter" Property="Foreground" Value="{DynamicResource TextControlPlaceholderForegroundFocused}" />
<Setter Property="Background" Value="{DynamicResource TextControlBackgroundFocused}" />
<Setter TargetName="BorderElement" Property="BorderBrush" Value="{DynamicResource TextControlBorderBrushFocused}" />
<Setter TargetName="BorderElement" Property="BorderThickness" Value="{DynamicResource TextControlBorderThemeThicknessFocused}" />
<Setter TargetName="BorderElementInline" Property="BorderBrush" Value="{DynamicResource TextControlBorderBrushFocused}" />
<Setter TargetName="BorderElementInline" Property="BorderThickness" Value="0 0 0 2" />
<Setter TargetName="BorderElement" Property="BorderBrush" Value="{DynamicResource CustomTextBoxOutline}" />
<Setter TargetName="BorderElement" Property="BorderThickness" Value="{DynamicResource 2 2 2 0}" />
<Setter Property="Foreground" Value="{DynamicResource TextControlForegroundFocused}" />
</Trigger>
<MultiTrigger>
@ -3523,8 +3535,8 @@
<!-- Content Dialog -->
<Style x:Key="ContentDialog" TargetType="ui:ContentDialog">
<Setter Property="Foreground" Value="{DynamicResource ContentDialogForeground}" />
<Setter Property="Background" Value="{DynamicResource ContentDialogBackground}" />
<Setter Property="Foreground" Value="{DynamicResource PopupTextColor}" />
<Setter Property="Background" Value="{DynamicResource PopupBGColor}" />
<Setter Property="BorderThickness" Value="{DynamicResource ContentDialogBorderWidth}" />
<Setter Property="BorderBrush" Value="{DynamicResource ContentDialogBorderBrush}" />
<Setter Property="IsTabStop" Value="False" />
@ -3571,11 +3583,11 @@
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Border x:Name="DialogSpace" Padding="{DynamicResource ContentDialogPadding}">
<Border x:Name="DialogSpace" Padding="0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition x:Name="CommandSpaceRow" Height="80" />
</Grid.RowDefinitions>
<ScrollViewer
x:Name="ContentScrollViewer"
@ -3583,7 +3595,7 @@
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
IsTabStop="False"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}">
<Grid>
<Grid Margin="{DynamicResource ContentDialogPadding}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
@ -3626,47 +3638,54 @@
TextWrapping="Wrap" />
</Grid>
</ScrollViewer>
<Grid
x:Name="CommandSpace"
<Border
x:Name="ButtonAreaBorder"
Grid.Row="1"
Margin="{DynamicResource ContentDialogCommandSpaceMargin}"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom"
KeyboardNavigation.DirectionalNavigation="Contained">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button
x:Name="PrimaryButton"
Grid.Column="0"
Margin="0 0 2 0"
Padding="26 0 26 0"
Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0 1 0 0"
CornerRadius="0 0 8 8">
<Grid
x:Name="CommandSpace"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding PrimaryButtonText}"
IsEnabled="{TemplateBinding IsPrimaryButtonEnabled}"
Style="{TemplateBinding PrimaryButtonStyle}" />
<Button
x:Name="SecondaryButton"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="2 0 2 0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding SecondaryButtonText}"
IsEnabled="{TemplateBinding IsSecondaryButtonEnabled}"
Style="{TemplateBinding SecondaryButtonStyle}" />
<Button
x:Name="CloseButton"
Grid.Column="3"
Margin="2 0 0 0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding CloseButtonText}"
Style="{TemplateBinding CloseButtonStyle}" />
</Grid>
VerticalAlignment="Center"
KeyboardNavigation.DirectionalNavigation="Contained">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Button
x:Name="PrimaryButton"
Grid.Column="0"
Margin="0 0 2 0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding PrimaryButtonText}"
IsEnabled="{TemplateBinding IsPrimaryButtonEnabled}"
Style="{TemplateBinding PrimaryButtonStyle}" />
<Button
x:Name="SecondaryButton"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="2 0 2 0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding SecondaryButtonText}"
IsEnabled="{TemplateBinding IsSecondaryButtonEnabled}"
Style="{TemplateBinding SecondaryButtonStyle}" />
<Button
x:Name="CloseButton"
Grid.Column="3"
Margin="2 0 0 0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{TemplateBinding CloseButtonText}"
Style="{TemplateBinding CloseButtonStyle}" />
</Grid>
</Border>
</Grid>
</Border>
</Border>
@ -3774,18 +3793,28 @@
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CommandSpace" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<!--
If the window has no buttons, it's assumed that the buttons are drawn directly within the window itself (as in the case of the HotkeyDialog).
In this case, the command space area is completely hidden.
-->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonAreaBorder" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CommandSpaceRow" Storyboard.TargetProperty="Height">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static GridLength.Auto}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PrimaryVisible">
<Storyboard>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="(Grid.Column)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="1" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="2,0,0,0" />
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="0,0,0,0" />
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
@ -3797,16 +3826,16 @@
</VisualState>
<VisualState x:Name="SecondaryVisible">
<Storyboard>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="(Grid.Column)">
<Int32AnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="(Grid.Column)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="1" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="2,0,0,0" />
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="0,0,0,0" />
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="Visibility">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="Visibility">
@ -3816,19 +3845,19 @@
</VisualState>
<VisualState x:Name="CloseVisible">
<Storyboard>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="(Grid.Column)">
<Int32AnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="(Grid.Column)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="1" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<Int32AnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="(Grid.ColumnSpan)">
<DiscreteInt32KeyFrame KeyTime="0:0:0" Value="2" />
</Int32AnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="2,0,0,0" />
<ThicknessAnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="Margin">
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="0,0,0,0" />
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PrimaryButton" Storyboard.TargetProperty="Visibility">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SecondaryButton" Storyboard.TargetProperty="Visibility">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="CloseButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>

View file

@ -106,6 +106,7 @@
<Color x:Key="NumberBoxColor24">#f5f5f5</Color>
<Color x:Key="NumberBoxColor25">#464646</Color>
<Color x:Key="NumberBoxColor26">#ffffff</Color>
<SolidColorBrush x:Key="NumberBoxPlaceHolder" Color="#565656" />
<Color x:Key="HoverStoreGrid">#272727</Color>
<!-- Resources for HotkeyControl -->
@ -113,7 +114,7 @@
<!-- Resources for Expander -->
<SolidColorBrush x:Key="CustomExpanderHover" Color="#323232" />
<!-- Resource for ContentDialog -->
<SolidColorBrush x:Key="ContentDialogOverlayBG" Color="#4D000000" />
<SolidColorBrush x:Key="ContentDialogOverlayBG" Color="#58000000" />
<!-- Infobar Warning -->
<SolidColorBrush x:Key="InfoBarWarningIcon" Color="#FCE100" />
<SolidColorBrush x:Key="InfoBarWarningBG" Color="#433519" />

View file

@ -97,8 +97,11 @@
<Color x:Key="NumberBoxColor24">#f5f5f5</Color>
<Color x:Key="NumberBoxColor25">#878787</Color>
<Color x:Key="NumberBoxColor26">#1b1b1b</Color>
<SolidColorBrush x:Key="NumberBoxPlaceHolder" Color="#A2A2A2" />
<Color x:Key="HoverStoreGrid">#f6f6f6</Color>
<!-- Resources for HotkeyControl -->
<SolidColorBrush x:Key="CustomHotkeyHover" Color="#f6f6f6" />
<!-- Resources for Expander -->

View file

@ -1,138 +0,0 @@
<Window
x:Class="Flow.Launcher.SearchDelayTimeWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{DynamicResource searchDelayTimeTitle}"
Width="450"
Background="{DynamicResource PopuBGColor}"
Foreground="{DynamicResource PopupTextColor}"
Icon="Images\app.png"
Loaded="SearchDelayTimeWindow_OnLoaded"
ResizeMode="NoResize"
SizeToContent="Height"
WindowStartupLocation="CenterScreen">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<Grid>
<StackPanel Grid.Row="0">
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="4"
Click="BtnCancel_OnClick"
Style="{StaticResource TitleBarCloseButtonStyle}">
<Path
Width="46"
Height="32"
Data="M 18,11 27,20 M 18,20 27,11"
Stroke="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}"
StrokeThickness="1">
<Path.Style>
<Style TargetType="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="False">
<Setter Property="Opacity" Value="0.5" />
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</Grid>
</StackPanel>
<StackPanel Margin="26 12 26 0">
<StackPanel Grid.Row="0" Margin="0 0 0 12">
<TextBlock
Grid.Column="0"
Margin="0 0 0 0"
FontSize="20"
FontWeight="SemiBold"
Text="{DynamicResource searchDelayTimeTitle}"
TextAlignment="Left" />
</StackPanel>
<StackPanel>
<TextBlock
x:Name="tbSearchDelayTimeTips"
FontSize="14"
TextAlignment="Left"
TextWrapping="WrapWithOverflow" />
</StackPanel>
<StackPanel Margin="0 18 0 0" Orientation="Horizontal">
<TextBlock
Grid.Row="0"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource currentSearchDelayTime}" />
<TextBlock
x:Name="tbOldSearchDelayTime"
Grid.Row="0"
Grid.Column="1"
Margin="14 10 10 10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource Color05B}" />
</StackPanel>
<StackPanel Margin="0 0 0 10" Orientation="Horizontal">
<TextBlock
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="14"
Text="{DynamicResource newSearchDelayTime}" />
<ComboBox
x:Name="cbDelay"
MaxWidth="200"
Margin="10 10 15 10"
HorizontalAlignment="Left"
VerticalAlignment="Center"
DisplayMemberPath="Display"
SelectedValuePath="Value" />
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
<Border
Grid.Row="1"
Background="{DynamicResource PopupButtonAreaBGColor}"
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
BorderThickness="0 1 0 0">
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<Button
x:Name="btnCancel"
Width="145"
Height="30"
Margin="10 0 5 0"
Click="BtnCancel_OnClick"
Content="{DynamicResource cancel}" />
<Button
x:Name="btnDone"
Width="145"
Height="30"
Margin="5 0 10 0"
Click="btnDone_OnClick"
Style="{StaticResource AccentButtonStyle}">
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
</Button>
</StackPanel>
</Border>
</Grid>
</Window>

View file

@ -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<SearchDelayTime>.GetValues<SearchDelayTimeData>("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();
}
}

View file

@ -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 partial class SettingsPaneGeneralViewModel : BaseModel
public class SearchWindowAlignData : DropdownDataGeneric<SearchWindowAligns> { }
public class SearchPrecisionData : DropdownDataGeneric<SearchPrecisionScore> { }
public class LastQueryModeData : DropdownDataGeneric<LastQueryMode> { }
public class SearchDelayTimeData : DropdownDataGeneric<SearchDelayTime> { }
public bool StartFlowLauncherOnSystemStartup
{
@ -144,25 +145,20 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
public List<LastQueryModeData> LastQueryModes { get; } =
DropdownDataGeneric<LastQueryMode>.GetValues<LastQueryModeData>("LastQuery");
public List<SearchDelayTimeData> SearchDelayTimes { get; } =
DropdownDataGeneric<SearchDelayTime>.GetValues<SearchDelayTimeData>("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 @@ public partial class SettingsPaneGeneralViewModel : BaseModel
DropdownDataGeneric<SearchWindowAligns>.UpdateLabels(SearchWindowAligns);
DropdownDataGeneric<SearchPrecisionScore>.UpdateLabels(SearchPrecisionScores);
DropdownDataGeneric<LastQueryMode>.UpdateLabels(LastQueryModes);
DropdownDataGeneric<SearchDelayTime>.UpdateLabels(SearchDelayTimes);
}
public string Language

View file

@ -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<DisplayMode> { }
public List<DisplayModeData> DisplayModes { get; } =
DropdownDataGeneric<DisplayMode>.GetValues<DisplayModeData>("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 class SettingsPanePluginsViewModel : BaseModel
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<DisplayMode>.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
}

View file

@ -196,6 +196,35 @@
</cc:Card>
</cc:CardGroup>
<cc:ExCard
Title="{DynamicResource searchDelay}"
Margin="0 14 0 0"
Icon="&#xE961;"
Sub="{DynamicResource searchDelayToolTip}">
<cc:ExCard.SideContent>
<ui:ToggleSwitch
IsOn="{Binding Settings.SearchQueryResultsWithDelay}"
OffContent="{DynamicResource disable}"
OnContent="{DynamicResource enable}" />
</cc:ExCard.SideContent>
<cc:Card
Title="{DynamicResource searchDelayTime}"
Sub="{DynamicResource searchDelayTimeToolTip}"
Type="InsideFit">
<StackPanel Orientation="Horizontal">
<ui:NumberBox
Width="120"
Margin="0 0 0 0"
Minimum="0"
Maximum="1000"
SmallChange="10"
SpinButtonPlacementMode="Compact"
Value="{Binding SearchDelayTimeValue}"
ValidationMode="InvalidInputOverwritten" />
</StackPanel>
</cc:Card>
</cc:ExCard>
<cc:Card
Title="{DynamicResource defaultFileManager}"
Margin="0 14 0 0"

View file

@ -2,22 +2,19 @@
x:Class="Flow.Launcher.SettingPages.Views.SettingsPanePlugins"
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:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:ui="http://schemas.modernwpf.com/2019"
xmlns:viewModels="clr-namespace:Flow.Launcher.SettingPages.ViewModels"
xmlns:cc="clr-namespace:Flow.Launcher.Resources.Controls"
Title="Plugins"
FocusManager.FocusedElement="{Binding ElementName=PluginFilterTextbox}"
KeyDown="SettingsPanePlugins_OnKeyDown"
d:DataContext="{d:DesignInstance viewModels:SettingsPanePluginsViewModel}"
d:DesignHeight="450"
d:DesignWidth="800"
FocusManager.FocusedElement="{Binding ElementName=PluginFilterTextbox}"
KeyDown="SettingsPanePlugins_OnKeyDown"
mc:Ignorable="d">
<ui:Page.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</ui:Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="73" />
@ -31,58 +28,93 @@
Style="{StaticResource PageTitle}"
Text="{DynamicResource plugins}"
TextAlignment="Left" />
<TextBox
Name="PluginFilterTextbox"
Width="150"
Height="34"
Margin="0 5 26 0"
<StackPanel
HorizontalAlignment="Right"
ContextMenu="{StaticResource TextBoxContextMenu}"
VerticalAlignment="Center"
DockPanel.Dock="Right"
FontSize="14"
Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}"
TextAlignment="Left"
ToolTip="{DynamicResource searchpluginToolTip}"
ToolTipService.InitialShowDelay="200"
ToolTipService.Placement="Top">
<TextBox.Style>
<Style BasedOn="{StaticResource DefaultTextBoxStyle}" TargetType="TextBox">
<Style.Resources>
<VisualBrush
x:Key="CueBannerBrush"
AlignmentX="Left"
AlignmentY="Center"
Stretch="None">
<VisualBrush.Visual>
<Label
Padding="10 0 0 0"
Content="{DynamicResource searchplugin}"
Foreground="{DynamicResource CustomContextDisabled}" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="{DynamicResource Color02B}" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
Orientation="Horizontal">
<TextBlock
Margin="0 0 6 0"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource Color15B}"
Text="{DynamicResource FilterComboboxLabel}" />
<ComboBox
x:Name="DisplayModeComboBox"
Width="Auto"
Height="34"
MinWidth="150"
MaxWidth="150"
Margin="0 0 4 0"
HorizontalContentAlignment="Left"
Background="{DynamicResource Color00B}"
DisplayMemberPath="Display"
ItemsSource="{Binding DisplayModes}"
SelectedValue="{Binding SelectedDisplayMode, Mode=TwoWay}"
SelectedValuePath="Value" />
<Button
Width="34"
Height="34"
Margin="0 0 20 0"
Command="{Binding OpenHelperCommand}"
Content="&#xe9ce;"
FontFamily="{DynamicResource SymbolThemeFontFamily}"
FontSize="14" />
<TextBox
Name="PluginFilterTextbox"
Width="150"
Height="34"
Margin="0 0 26 0"
ContextMenu="{StaticResource TextBoxContextMenu}"
FontSize="14"
Text="{Binding FilterText, UpdateSourceTrigger=PropertyChanged}"
TextAlignment="Left"
ToolTip="{DynamicResource searchpluginToolTip}"
ToolTipService.InitialShowDelay="200"
ToolTipService.Placement="Top">
<TextBox.Style>
<Style BasedOn="{StaticResource DefaultTextBoxStyle}" TargetType="TextBox">
<Style.Resources>
<VisualBrush
x:Key="CueBannerBrush"
AlignmentX="Left"
AlignmentY="Center"
Stretch="None">
<VisualBrush.Visual>
<Label
Padding="10 0 0 0"
Content="{DynamicResource searchplugin}"
Foreground="{DynamicResource CustomContextDisabled}" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="{DynamicResource Color02B}" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</StackPanel>
</DockPanel>
<Border Grid.Row="1" Grid.Column="0" Background="{DynamicResource Color01B}">
<Border
Grid.Row="1"
Grid.Column="0"
Background="{DynamicResource Color01B}">
<ListBox
Margin="5 0 7 10"
Background="{DynamicResource Color01B}"
FontSize="14"
ItemsSource="{Binding FilteredPluginViewModels}"
ItemContainerStyle="{StaticResource PluginList}"
ItemsSource="{Binding FilteredPluginViewModels}"
ScrollViewer.CanContentScroll="False"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectedItem="{Binding SelectedPlugin}"

View file

@ -1257,15 +1257,7 @@ namespace Flow.Launcher.ViewModel
{
if (searchDelay)
{
var searchDelayTime = (plugin.Metadata.SearchDelayTime ?? Settings.SearchDelayTime) switch
{
SearchDelayTime.VeryLong => 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);

View file

@ -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<Settings>();
private readonly PluginPair _pluginPair;
public PluginPair PluginPair
{
@ -83,13 +87,33 @@ namespace Flow.Launcher.ViewModel
}
}
public SearchDelayTime? PluginSearchDelayTime
public int Priority
{
get => PluginPair.Metadata.SearchDelayTime;
get => PluginPair.Metadata.Priority;
set
{
PluginPair.Metadata.SearchDelayTime = value;
PluginSettingsObject.SearchDelayTime = value;
PluginPair.Metadata.Priority = value;
PluginSettingsObject.Priority = value;
}
}
public double PluginSearchDelayTime
{
get => PluginPair.Metadata.SearchDelayTime == null ?
double.NaN :
PluginPair.Metadata.SearchDelayTime.Value;
set
{
if (double.IsNaN(value))
{
PluginPair.Metadata.SearchDelayTime = null;
PluginSettingsObject.SearchDelayTime = null;
}
else
{
PluginPair.Metadata.SearchDelayTime = (int)value;
PluginSettingsObject.SearchDelayTime = (int)value;
}
}
}
@ -100,10 +124,7 @@ namespace Flow.Launcher.ViewModel
public Control BottomPart1 => IsExpanded ? _bottomPart1 ??= new InstalledPluginDisplayKeyword() : null;
private Control _bottomPart2;
public Control BottomPart2 => IsExpanded ? _bottomPart2 ??= new InstalledPluginSearchDelay() : null;
private Control _bottomPart3;
public Control BottomPart3 => IsExpanded ? _bottomPart3 ??= new InstalledPluginDisplayBottomData() : null;
public Control BottomPart2 => IsExpanded ? _bottomPart2 ??= new InstalledPluginDisplayBottomData() : null;
public bool HasSettingControl => PluginPair.Plugin is ISettingProvider &&
(PluginPair.Plugin is not JsonRPCPluginBase jsonRPCPluginBase || jsonRPCPluginBase.NeedCreateSettingPanel());
@ -127,11 +148,12 @@ namespace Flow.Launcher.ViewModel
App.API.GetTranslation("plugin_query_time") + " " +
PluginPair.Metadata.AvgQueryTime + "ms";
public string ActionKeywordsText => string.Join(Query.ActionKeywordSeparator, PluginPair.Metadata.ActionKeywords);
public int Priority => PluginPair.Metadata.Priority;
public string SearchDelayTimeText => PluginPair.Metadata.SearchDelayTime == null ?
App.API.GetTranslation("default") :
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()
{
@ -143,20 +165,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()
{
@ -184,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();
}
}
}

View file

@ -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
}