diff --git a/Flow.Launcher.sln b/Flow.Launcher.sln
index ec4a29ee78d..f59d3d26fb7 100644
--- a/Flow.Launcher.sln
+++ b/Flow.Launcher.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.29806.167
+# Visual Studio Version 17
+VisualStudioVersion = 17.3.32901.215
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Test", "Flow.Launcher.Test\Flow.Launcher.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}"
ProjectSection(ProjectDependencies) = postProject
diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml
index 1ca2f0f7eaf..2019c1b6629 100644
--- a/Flow.Launcher/Languages/en.xaml
+++ b/Flow.Launcher/Languages/en.xaml
@@ -60,6 +60,10 @@
Shadow effect is not allowed while current theme has blur effect enabled
+ Search Plugin
+ Ctrl+F to search plugins
+ No results found
+ Please try a different search.
Plugin
Find more plugins
On
diff --git a/Flow.Launcher/SettingWindow.xaml b/Flow.Launcher/SettingWindow.xaml
index 9026f8f7c82..0a63b3a6cfb 100644
--- a/Flow.Launcher/SettingWindow.xaml
+++ b/Flow.Launcher/SettingWindow.xaml
@@ -323,8 +323,6 @@
-
-
@@ -388,6 +386,55 @@
+
+
+
+
+
+
+
+ SnapsToDevicePixels="True"
+ Style="{DynamicResource PluginListStyle}">
@@ -945,7 +1045,7 @@
Padding="0"
Background="Transparent"
FlowDirection="RightToLeft"
- IsExpanded="{Binding Mode=TwoWay, Path=IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}"
+ IsExpanded="{Binding Mode=TwoWay, Path=IsExpanded}"
Style="{StaticResource ExpanderStyle1}">
+ Content="{Binding SettingControl}" />
@@ -1248,7 +1347,7 @@
-
+
@@ -1285,19 +1384,66 @@
Text="{DynamicResource pluginStore}"
TextAlignment="left" />
-
+ Margin="5,24,0,0">
+
+
+
+
+
-
+
+ SelectionMode="Single"
+ Style="{DynamicResource StoreListStyle}">
@@ -1354,15 +1501,56 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ VerticalAlignment="Top">
@@ -1445,12 +1638,13 @@
-
+ VerticalAlignment="Top">
+
-
+
-
+
-
@@ -2171,7 +2366,7 @@
diff --git a/Flow.Launcher/SettingWindow.xaml.cs b/Flow.Launcher/SettingWindow.xaml.cs
index 1a4f4da587b..51017b96bd7 100644
--- a/Flow.Launcher/SettingWindow.xaml.cs
+++ b/Flow.Launcher/SettingWindow.xaml.cs
@@ -17,6 +17,7 @@
using System.Linq;
using System.Windows;
using System.Windows.Controls;
+using System.Windows.Data;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
@@ -25,6 +26,7 @@
using Button = System.Windows.Controls.Button;
using Control = System.Windows.Controls.Control;
using ListViewItem = System.Windows.Controls.ListViewItem;
+using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using MessageBox = System.Windows.MessageBox;
using TextBox = System.Windows.Controls.TextBox;
using ThemeManager = ModernWpf.ThemeManager;
@@ -57,6 +59,13 @@ private void OnLoaded(object sender, RoutedEventArgs e)
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
HwndTarget hwndTarget = hwndSource.CompositionTarget;
hwndTarget.RenderMode = RenderMode.SoftwareOnly;
+
+ pluginListView = (CollectionView)CollectionViewSource.GetDefaultView(Plugins.ItemsSource);
+ pluginListView.Filter = PluginListFilter;
+
+ pluginStoreView = (CollectionView)CollectionViewSource.GetDefaultView(StoreListBox.ItemsSource);
+ pluginStoreView.Filter = PluginStoreFilter;
+
InitializePosition();
}
@@ -163,7 +172,7 @@ private void OnnEditCustomHotkeyClick(object sender, RoutedEventArgs e)
}
}
- private void OnAddCustomeHotkeyClick(object sender, RoutedEventArgs e)
+ private void OnAddCustomHotkeyClick(object sender, RoutedEventArgs e)
{
new CustomQueryHotkeySetting(this, settings).ShowDialog();
}
@@ -361,13 +370,77 @@ private void Window_StateChanged(object sender, EventArgs e)
RefreshMaximizeRestoreButton();
}
- private void SelectedPluginChanged(object sender, SelectionChangedEventArgs e)
+ private CollectionView pluginListView;
+ private CollectionView pluginStoreView;
+
+ private bool PluginListFilter(object item)
+ {
+ if (string.IsNullOrEmpty(pluginFilterTxb.Text))
+ return true;
+ if (item is PluginViewModel model)
+ {
+ return StringMatcher.FuzzySearch(pluginFilterTxb.Text, model.PluginPair.Metadata.Name).IsSearchPrecisionScoreMet();
+ }
+ return false;
+ }
+
+ private bool PluginStoreFilter(object item)
+ {
+ if (string.IsNullOrEmpty(pluginStoreFilterTxb.Text))
+ return true;
+ if (item is UserPlugin model)
+ {
+ return StringMatcher.FuzzySearch(pluginStoreFilterTxb.Text, model.Name).IsSearchPrecisionScoreMet()
+ || StringMatcher.FuzzySearch(pluginStoreFilterTxb.Text, model.Description).IsSearchPrecisionScoreMet();
+ }
+ return false;
+ }
+
+ private string lastPluginListSearch = "";
+ private string lastPluginStoreSearch = "";
+
+ private void RefreshPluginListEventHandler(object sender, RoutedEventArgs e)
+ {
+ if (pluginFilterTxb.Text != lastPluginListSearch)
+ {
+ lastPluginListSearch = pluginFilterTxb.Text;
+ pluginListView.Refresh();
+ }
+ }
+
+ private void RefreshPluginStoreEventHandler(object sender, RoutedEventArgs e)
{
- Plugins.ScrollIntoView(Plugins.SelectedItem);
+ if (pluginStoreFilterTxb.Text != lastPluginStoreSearch)
+ {
+ lastPluginStoreSearch = pluginStoreFilterTxb.Text;
+ pluginStoreView.Refresh();
+ }
}
- private void ItemSizeChanged(object sender, SizeChangedEventArgs e)
+
+ private void PluginFilterTxb_OnKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Key == Key.Enter)
+ RefreshPluginListEventHandler(sender, e);
+ }
+
+ private void PluginStoreFilterTxb_OnKeyDown(object sender, KeyEventArgs e)
{
- Plugins.ScrollIntoView(Plugins.SelectedItem);
+ if (e.Key == Key.Enter)
+ RefreshPluginStoreEventHandler(sender, e);
+ }
+
+ private void OnPluginSettingKeydown(object sender, KeyEventArgs e)
+ {
+ if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control && e.Key == Key.F)
+ pluginFilterTxb.Focus();
+ }
+
+ private void PluginStore_OnKeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Key == Key.F && (Keyboard.Modifiers & ModifierKeys.Control) != 0)
+ {
+ pluginStoreFilterTxb.Focus();
+ }
}
public void InitializePosition()
diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs
index 738bd0ec40a..2294681b4dc 100644
--- a/Flow.Launcher/ViewModel/PluginViewModel.cs
+++ b/Flow.Launcher/ViewModel/PluginViewModel.cs
@@ -1,4 +1,4 @@
-using System.Windows;
+using System.Windows;
using System.Windows.Media;
using Flow.Launcher.Plugin;
using Flow.Launcher.Infrastructure.Image;
@@ -30,9 +30,26 @@ public bool PluginState
get => !PluginPair.Metadata.Disabled;
set => PluginPair.Metadata.Disabled = !value;
}
+ public bool IsExpanded
+ {
+ get => _isExpanded;
+ set
+ {
+ _isExpanded = value;
+ OnPropertyChanged();
+ OnPropertyChanged(nameof(SettingControl));
+ }
+ }
private Control _settingControl;
- public Control SettingControl => _settingControl ??= PluginPair.Plugin is not ISettingProvider settingProvider ? new Control() : settingProvider.CreateSettingPanel();
+ private bool _isExpanded;
+ public Control SettingControl
+ => IsExpanded
+ ? _settingControl
+ ??= PluginPair.Plugin is not ISettingProvider settingProvider
+ ? new Control()
+ : settingProvider.CreateSettingPanel()
+ : null;
public Visibility ActionKeywordsVisibility => PluginPair.Metadata.ActionKeywords.Count == 1 ? Visibility.Visible : Visibility.Collapsed;
public string InitilizaTime => PluginPair.Metadata.InitTime + "ms";