Skip to content

Commit 6a964b0

Browse files
authored
Merge pull request #3350 from Jack251970/search_delay
Input Smooth & Search delay
2 parents d2cfa7f + 39f41e4 commit 6a964b0

21 files changed

+632
-118
lines changed

Flow.Launcher.Core/Plugin/PluginManager.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ internal static async Task UninstallPluginAsync(PluginMetadata plugin, bool remo
622622
API.ShowMsg(API.GetTranslation("failedToRemovePluginCacheTitle"),
623623
string.Format(API.GetTranslation("failedToRemovePluginCacheMessage"), plugin.Name));
624624
}
625-
Settings.Plugins.Remove(plugin.ID);
625+
Settings.RemovePluginSettings(plugin.ID);
626626
AllPlugins.RemoveAll(p => p.Metadata.ID == plugin.ID);
627627
}
628628

Flow.Launcher.Core/Plugin/PluginsLoader.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public static List<PluginPair> Plugins(List<PluginMetadata> metadatas, PluginsSe
5050
return plugins;
5151
}
5252

53-
public static IEnumerable<PluginPair> DotNetPlugins(List<PluginMetadata> source)
53+
private static IEnumerable<PluginPair> DotNetPlugins(List<PluginMetadata> source)
5454
{
5555
var erroredPlugins = new List<string>();
5656

@@ -132,7 +132,7 @@ public static IEnumerable<PluginPair> DotNetPlugins(List<PluginMetadata> source)
132132
return plugins;
133133
}
134134

135-
public static IEnumerable<PluginPair> ExecutablePlugins(IEnumerable<PluginMetadata> source)
135+
private static IEnumerable<PluginPair> ExecutablePlugins(IEnumerable<PluginMetadata> source)
136136
{
137137
return source
138138
.Where(o => o.Language.Equals(AllowedLanguage.Executable, StringComparison.OrdinalIgnoreCase))
@@ -146,7 +146,7 @@ public static IEnumerable<PluginPair> ExecutablePlugins(IEnumerable<PluginMetada
146146
});
147147
}
148148

149-
public static IEnumerable<PluginPair> ExecutableV2Plugins(IEnumerable<PluginMetadata> source)
149+
private static IEnumerable<PluginPair> ExecutableV2Plugins(IEnumerable<PluginMetadata> source)
150150
{
151151
return source
152152
.Where(o => o.Language.Equals(AllowedLanguage.ExecutableV2, StringComparison.OrdinalIgnoreCase))

Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs

+59-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
using System.Collections.Generic;
2+
using System.Text.Json.Serialization;
23
using Flow.Launcher.Plugin;
34

45
namespace Flow.Launcher.Infrastructure.UserSettings
56
{
67
public class PluginsSettings : BaseModel
78
{
89
private string pythonExecutablePath = string.Empty;
9-
public string PythonExecutablePath {
10-
get { return pythonExecutablePath; }
10+
public string PythonExecutablePath
11+
{
12+
get => pythonExecutablePath;
1113
set
1214
{
1315
pythonExecutablePath = value;
@@ -18,25 +20,40 @@ public string PythonExecutablePath {
1820
private string nodeExecutablePath = string.Empty;
1921
public string NodeExecutablePath
2022
{
21-
get { return nodeExecutablePath; }
23+
get => nodeExecutablePath;
2224
set
2325
{
2426
nodeExecutablePath = value;
2527
Constant.NodePath = value;
2628
}
2729
}
2830

29-
public Dictionary<string, Plugin> Plugins { get; set; } = new Dictionary<string, Plugin>();
31+
/// <summary>
32+
/// Only used for serialization
33+
/// </summary>
34+
public Dictionary<string, Plugin> Plugins { get; set; } = new();
3035

36+
/// <summary>
37+
/// Update plugin settings with metadata.
38+
/// FL will get default values from metadata first and then load settings to metadata
39+
/// </summary>
40+
/// <param name="metadatas">Parsed plugin metadatas</param>
3141
public void UpdatePluginSettings(List<PluginMetadata> metadatas)
3242
{
3343
foreach (var metadata in metadatas)
3444
{
3545
if (Plugins.TryGetValue(metadata.ID, out var settings))
3646
{
47+
// If settings exist, update settings & metadata value
48+
// update settings values with metadata
3749
if (string.IsNullOrEmpty(settings.Version))
50+
{
3851
settings.Version = metadata.Version;
52+
}
53+
settings.DefaultActionKeywords = metadata.ActionKeywords; // metadata provides default values
54+
settings.DefaultSearchDelayTime = metadata.SearchDelayTime; // metadata provides default values
3955

56+
// update metadata values with settings
4057
if (settings.ActionKeywords?.Count > 0)
4158
{
4259
metadata.ActionKeywords = settings.ActionKeywords;
@@ -49,30 +66,65 @@ public void UpdatePluginSettings(List<PluginMetadata> metadatas)
4966
}
5067
metadata.Disabled = settings.Disabled;
5168
metadata.Priority = settings.Priority;
69+
metadata.SearchDelayTime = settings.SearchDelayTime;
5270
}
5371
else
5472
{
73+
// If settings does not exist, create a new one
5574
Plugins[metadata.ID] = new Plugin
5675
{
5776
ID = metadata.ID,
5877
Name = metadata.Name,
5978
Version = metadata.Version,
60-
ActionKeywords = metadata.ActionKeywords,
79+
DefaultActionKeywords = metadata.ActionKeywords, // metadata provides default values
80+
ActionKeywords = metadata.ActionKeywords, // use default value
6181
Disabled = metadata.Disabled,
62-
Priority = metadata.Priority
82+
Priority = metadata.Priority,
83+
DefaultSearchDelayTime = metadata.SearchDelayTime, // metadata provides default values
84+
SearchDelayTime = metadata.SearchDelayTime, // use default value
6385
};
6486
}
6587
}
6688
}
89+
90+
public Plugin GetPluginSettings(string id)
91+
{
92+
if (Plugins.TryGetValue(id, out var plugin))
93+
{
94+
return plugin;
95+
}
96+
return null;
97+
}
98+
99+
public Plugin RemovePluginSettings(string id)
100+
{
101+
Plugins.Remove(id, out var plugin);
102+
return plugin;
103+
}
67104
}
105+
68106
public class Plugin
69107
{
70108
public string ID { get; set; }
109+
71110
public string Name { get; set; }
111+
72112
public string Version { get; set; }
73-
public List<string> ActionKeywords { get; set; } // a reference of the action keywords from plugin manager
113+
114+
[JsonIgnore]
115+
public List<string> DefaultActionKeywords { get; set; }
116+
117+
// a reference of the action keywords from plugin manager
118+
public List<string> ActionKeywords { get; set; }
119+
74120
public int Priority { get; set; }
75121

122+
[JsonIgnore]
123+
public SearchDelayTime? DefaultSearchDelayTime { get; set; }
124+
125+
[JsonConverter(typeof(JsonStringEnumConverter))]
126+
public SearchDelayTime? SearchDelayTime { get; set; }
127+
76128
/// <summary>
77129
/// Used only to save the state of the plugin in settings
78130
/// </summary>

Flow.Launcher.Infrastructure/UserSettings/Settings.cs

+7-3
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public string Theme
112112
public double SettingWindowHeight { get; set; } = 700;
113113
public double? SettingWindowTop { get; set; } = null;
114114
public double? SettingWindowLeft { get; set; } = null;
115-
public System.Windows.WindowState SettingWindowState { get; set; } = WindowState.Normal;
115+
public WindowState SettingWindowState { get; set; } = WindowState.Normal;
116116

117117
bool _showPlaceholder { get; set; } = false;
118118
public bool ShowPlaceholder
@@ -310,7 +310,7 @@ public bool KeepMaxResults
310310
bool _hideNotifyIcon { get; set; }
311311
public bool HideNotifyIcon
312312
{
313-
get { return _hideNotifyIcon; }
313+
get => _hideNotifyIcon;
314314
set
315315
{
316316
_hideNotifyIcon = value;
@@ -320,6 +320,11 @@ public bool HideNotifyIcon
320320
public bool LeaveCmdOpen { get; set; }
321321
public bool HideWhenDeactivated { get; set; } = true;
322322

323+
public bool SearchQueryResultsWithDelay { get; set; }
324+
325+
[JsonConverter(typeof(JsonStringEnumConverter))]
326+
public SearchDelayTime SearchDelayTime { get; set; } = SearchDelayTime.Normal;
327+
323328
[JsonConverter(typeof(JsonStringEnumConverter))]
324329
public SearchWindowScreens SearchWindowScreen { get; set; } = SearchWindowScreens.Cursor;
325330

@@ -342,7 +347,6 @@ public bool HideNotifyIcon
342347
[JsonIgnore]
343348
public bool WMPInstalled { get; set; } = true;
344349

345-
346350
// This needs to be loaded last by staying at the bottom
347351
public PluginsSettings PluginSettings { get; set; } = new PluginsSettings();
348352

Flow.Launcher.Plugin/PluginMetadata.cs

+7-1
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,18 @@ internal set
9292
/// All action keywords of plugin.
9393
/// </summary>
9494
public List<string> ActionKeywords { get; set; }
95-
95+
9696
/// <summary>
9797
/// Hide plugin keyword setting panel.
9898
/// </summary>
9999
public bool HideActionKeywordPanel { get; set; }
100100

101+
/// <summary>
102+
/// Plugin search delay time. Null means use default search delay time.
103+
/// </summary>
104+
[JsonConverter(typeof(JsonStringEnumConverter))]
105+
public SearchDelayTime? SearchDelayTime { get; set; } = null;
106+
101107
/// <summary>
102108
/// Plugin icon path.
103109
/// </summary>
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace Flow.Launcher.Plugin;
2+
3+
/// <summary>
4+
/// Enum for search delay time
5+
/// </summary>
6+
public enum SearchDelayTime
7+
{
8+
/// <summary>
9+
/// Very long search delay time. 250ms.
10+
/// </summary>
11+
VeryLong,
12+
13+
/// <summary>
14+
/// Long search delay time. 200ms.
15+
/// </summary>
16+
Long,
17+
18+
/// <summary>
19+
/// Normal search delay time. 150ms. Default value.
20+
/// </summary>
21+
Normal,
22+
23+
/// <summary>
24+
/// Short search delay time. 100ms.
25+
/// </summary>
26+
Short,
27+
28+
/// <summary>
29+
/// Very short search delay time. 50ms.
30+
/// </summary>
31+
VeryShort
32+
}

Flow.Launcher/Languages/en.xaml

+18
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,15 @@
102102
<system:String x:Key="AlwaysPreview">Always Preview</system:String>
103103
<system:String x:Key="AlwaysPreviewToolTip">Always open preview panel when Flow activates. Press {0} to toggle preview.</system:String>
104104
<system:String x:Key="shadowEffectNotAllowed">Shadow effect is not allowed while current theme has blur effect enabled</system:String>
105+
<system:String x:Key="searchDelay">Search Delay</system:String>
106+
<system:String x:Key="searchDelayToolTip">Delay for a while to search when typing. This reduces interface jumpiness and result load.</system:String>
107+
<system:String x:Key="searchDelayTime">Default Search Delay Time</system:String>
108+
<system:String x:Key="searchDelayTimeToolTip">Plugin default delay time after which search results appear when typing is stopped.</system:String>
109+
<system:String x:Key="SearchDelayTimeVeryLong">Very long</system:String>
110+
<system:String x:Key="SearchDelayTimeLong">Long</system:String>
111+
<system:String x:Key="SearchDelayTimeNormal">Normal</system:String>
112+
<system:String x:Key="SearchDelayTimeShort">Short</system:String>
113+
<system:String x:Key="SearchDelayTimeVeryShort">Very short</system:String>
105114

106115
<!-- Setting Plugin -->
107116
<system:String x:Key="searchplugin">Search Plugin</system:String>
@@ -118,6 +127,8 @@
118127
<system:String x:Key="currentActionKeywords">Current action keyword</system:String>
119128
<system:String x:Key="newActionKeyword">New action keyword</system:String>
120129
<system:String x:Key="actionKeywordsTooltip">Change Action Keywords</system:String>
130+
<system:String x:Key="pluginSearchDelayTime">Plugin seach delay time</system:String>
131+
<system:String x:Key="pluginSearchDelayTimeTooltip">Change Plugin Seach Delay Time</system:String>
121132
<system:String x:Key="currentPriority">Current Priority</system:String>
122133
<system:String x:Key="newPriority">New Priority</system:String>
123134
<system:String x:Key="priority">Priority</system:String>
@@ -133,6 +144,7 @@
133144
<system:String x:Key="failedToRemovePluginSettingsMessage">Plugins: {0} - Fail to remove plugin settings files, please remove them manually</system:String>
134145
<system:String x:Key="failedToRemovePluginCacheTitle">Fail to remove plugin cache</system:String>
135146
<system:String x:Key="failedToRemovePluginCacheMessage">Plugins: {0} - Fail to remove plugin cache files, please remove them manually</system:String>
147+
<system:String x:Key="default">Default</system:String>
136148

137149
<!-- Setting Plugin Store -->
138150
<system:String x:Key="pluginStore">Plugin Store</system:String>
@@ -353,6 +365,12 @@
353365
<system:String x:Key="completedSuccessfully">Completed successfully</system:String>
354366
<system:String x:Key="actionkeyword_tips">Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords.</system:String>
355367

368+
<!-- Search Delay Settings Dialog -->
369+
<system:String x:Key="searchDelayTimeTitle">Search Delay Time Setting</system:String>
370+
<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>
371+
<system:String x:Key="currentSearchDelayTime">Current search delay time</system:String>
372+
<system:String x:Key="newSearchDelayTime">New search delay time</system:String>
373+
356374
<!-- Custom Query Hotkey Dialog -->
357375
<system:String x:Key="customeQueryHotkeyTitle">Custom Query Hotkey</system:String>
358376
<system:String x:Key="customeQueryHotkeyTips">Press a custom hotkey to open Flow Launcher and input the specified query automatically.</system:String>

Flow.Launcher/MainWindow.xaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,8 @@
251251
PreviewDragOver="QueryTextBox_OnPreviewDragOver"
252252
PreviewKeyUp="QueryTextBox_KeyUp"
253253
Style="{DynamicResource QueryBoxStyle}"
254-
Text="{Binding QueryText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
254+
Text="{Binding QueryText, Mode=OneWay}"
255+
TextChanged="QueryTextBox_TextChanged1"
255256
Visibility="Visible"
256257
WindowChrome.IsHitTestVisibleInChrome="True">
257258
<TextBox.CommandBindings>

Flow.Launcher/MainWindow.xaml.cs

+17-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
using Flow.Launcher.Plugin.SharedCommands;
2323
using Flow.Launcher.ViewModel;
2424
using ModernWpf.Controls;
25+
using DataObject = System.Windows.DataObject;
26+
using Key = System.Windows.Input.Key;
2527
using MouseButtons = System.Windows.Forms.MouseButtons;
2628
using NotifyIcon = System.Windows.Forms.NotifyIcon;
2729
using Screen = System.Windows.Forms.Screen;
@@ -165,6 +167,8 @@ private async void OnLoaded(object sender, RoutedEventArgs _)
165167
// Set the initial state of the QueryTextBoxCursorMovedToEnd property
166168
// Without this part, when shown for the first time, switching the context menu does not move the cursor to the end.
167169
_viewModel.QueryTextCursorMovedToEnd = false;
170+
171+
// View model property changed event
168172
_viewModel.PropertyChanged += (o, e) =>
169173
{
170174
switch (e.PropertyName)
@@ -227,6 +231,7 @@ private async void OnLoaded(object sender, RoutedEventArgs _)
227231
}
228232
};
229233

234+
// Settings property changed event
230235
_settings.PropertyChanged += (o, e) =>
231236
{
232237
switch (e.PropertyName)
@@ -1050,7 +1055,7 @@ private void QueryTextBox_OnPreviewDragOver(object sender, DragEventArgs e)
10501055
{
10511056
e.Handled = true;
10521057
}
1053-
1058+
10541059
#endregion
10551060

10561061
#region Placeholder
@@ -1101,6 +1106,17 @@ private void SetupResizeMode()
11011106
}
11021107
}
11031108

1109+
#endregion
1110+
1111+
#region Search Delay
1112+
1113+
private void QueryTextBox_TextChanged1(object sender, TextChangedEventArgs e)
1114+
{
1115+
var textBox = (TextBox)sender;
1116+
_viewModel.QueryText = textBox.Text;
1117+
_viewModel.Query(_settings.SearchQueryResultsWithDelay);
1118+
}
1119+
11041120
#endregion
11051121

11061122
#region IDisposable

0 commit comments

Comments
 (0)