Skip to content

Commit bb31990

Browse files
authored
Merge branch 'dev' into quickswitch
2 parents e662a1b + 6799b87 commit bb31990

File tree

16 files changed

+451
-75
lines changed

16 files changed

+451
-75
lines changed

Flow.Launcher.Core/Plugin/PluginManager.cs

+44
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public static class PluginManager
2525
private static readonly string ClassName = nameof(PluginManager);
2626

2727
private static IEnumerable<PluginPair> _contextMenuPlugins;
28+
private static IEnumerable<PluginPair> _homePlugins;
2829

2930
public static List<PluginPair> AllPlugins { get; private set; }
3031
public static readonly HashSet<PluginPair> GlobalPlugins = new();
@@ -220,13 +221,16 @@ public static async Task InitializePluginsAsync()
220221
{
221222
API.LogException(ClassName, $"Fail to Init plugin: {pair.Metadata.Name}", e);
222223
pair.Metadata.Disabled = true;
224+
pair.Metadata.HomeDisabled = true;
223225
failedPlugins.Enqueue(pair);
224226
}
225227
}));
226228

227229
await Task.WhenAll(InitTasks);
228230

229231
_contextMenuPlugins = GetPluginsForInterface<IContextMenu>();
232+
_homePlugins = GetPluginsForInterface<IAsyncHomeQuery>();
233+
230234
foreach (var plugin in AllPlugins)
231235
{
232236
// set distinct on each plugin's action keywords helps only firing global(*) and action keywords once where a plugin
@@ -277,6 +281,11 @@ public static ICollection<PluginPair> ValidPluginsForQuery(Query query, bool qui
277281
};
278282
}
279283

284+
public static ICollection<PluginPair> ValidPluginsForHomeQuery()
285+
{
286+
return _homePlugins.ToList();
287+
}
288+
280289
public static async Task<List<Result>> QueryForPluginAsync(PluginPair pair, Query query, CancellationToken token)
281290
{
282291
var results = new List<Result>();
@@ -321,6 +330,36 @@ public static async Task<List<Result>> QueryForPluginAsync(PluginPair pair, Quer
321330
return results;
322331
}
323332

333+
public static async Task<List<Result>> QueryHomeForPluginAsync(PluginPair pair, Query query, CancellationToken token)
334+
{
335+
var results = new List<Result>();
336+
var metadata = pair.Metadata;
337+
338+
try
339+
{
340+
var milliseconds = await API.StopwatchLogDebugAsync(ClassName, $"Cost for {metadata.Name}",
341+
async () => results = await ((IAsyncHomeQuery)pair.Plugin).HomeQueryAsync(token).ConfigureAwait(false));
342+
343+
token.ThrowIfCancellationRequested();
344+
if (results == null)
345+
return null;
346+
UpdatePluginMetadata(results, metadata, query);
347+
348+
token.ThrowIfCancellationRequested();
349+
}
350+
catch (OperationCanceledException)
351+
{
352+
// null will be fine since the results will only be added into queue if the token hasn't been cancelled
353+
return null;
354+
}
355+
catch (Exception e)
356+
{
357+
API.LogException(ClassName, $"Failed to query home for plugin: {metadata.Name}", e);
358+
return null;
359+
}
360+
return results;
361+
}
362+
324363
public static async Task<List<QuickSwitchResult>> QueryQuickSwitchForPluginAsync(PluginPair pair, Query query, CancellationToken token)
325364
{
326365
var results = new List<QuickSwitchResult>();
@@ -411,6 +450,11 @@ public static List<Result> GetContextMenusForPlugin(Result result)
411450
return results;
412451
}
413452

453+
public static bool IsHomePlugin(string id)
454+
{
455+
return _homePlugins.Any(p => p.Metadata.ID == id);
456+
}
457+
414458
public static bool ActionKeywordRegistered(string actionKeyword)
415459
{
416460
// this method is only checking for action keywords (defined as not '*') registration

Flow.Launcher.Core/Plugin/QueryBuilder.cs

+18-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,23 @@ public static class QueryBuilder
88
{
99
public static Query Build(string text, Dictionary<string, PluginPair> nonGlobalPlugins)
1010
{
11+
// home query
12+
if (string.IsNullOrEmpty(text))
13+
{
14+
return new Query()
15+
{
16+
Search = string.Empty,
17+
RawQuery = string.Empty,
18+
SearchTerms = Array.Empty<string>(),
19+
ActionKeyword = string.Empty
20+
};
21+
}
22+
1123
// replace multiple white spaces with one white space
1224
var terms = text.Split(Query.TermSeparator, StringSplitOptions.RemoveEmptyEntries);
1325
if (terms.Length == 0)
14-
{ // nothing was typed
26+
{
27+
// nothing was typed
1528
return null;
1629
}
1730

@@ -21,13 +34,15 @@ public static Query Build(string text, Dictionary<string, PluginPair> nonGlobalP
2134
string[] searchTerms;
2235

2336
if (nonGlobalPlugins.TryGetValue(possibleActionKeyword, out var pluginPair) && !pluginPair.Metadata.Disabled)
24-
{ // use non global plugin for query
37+
{
38+
// use non global plugin for query
2539
actionKeyword = possibleActionKeyword;
2640
search = terms.Length > 1 ? rawQuery[(actionKeyword.Length + 1)..].TrimStart() : string.Empty;
2741
searchTerms = terms[1..];
2842
}
2943
else
30-
{ // non action keyword
44+
{
45+
// non action keyword
3146
actionKeyword = string.Empty;
3247
search = rawQuery.TrimStart();
3348
searchTerms = terms;

Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public void UpdatePluginSettings(List<PluginMetadata> metadatas)
6767
metadata.Disabled = settings.Disabled;
6868
metadata.Priority = settings.Priority;
6969
metadata.SearchDelayTime = settings.SearchDelayTime;
70+
metadata.HomeDisabled = settings.HomeDisabled;
7071
}
7172
else
7273
{
@@ -79,6 +80,7 @@ public void UpdatePluginSettings(List<PluginMetadata> metadatas)
7980
DefaultActionKeywords = metadata.ActionKeywords, // metadata provides default values
8081
ActionKeywords = metadata.ActionKeywords, // use default value
8182
Disabled = metadata.Disabled,
83+
HomeDisabled = metadata.HomeDisabled,
8284
Priority = metadata.Priority,
8385
DefaultSearchDelayTime = metadata.SearchDelayTime, // metadata provides default values
8486
SearchDelayTime = metadata.SearchDelayTime, // use default value
@@ -128,5 +130,6 @@ public class Plugin
128130
/// Used only to save the state of the plugin in settings
129131
/// </summary>
130132
public bool Disabled { get; set; }
133+
public bool HomeDisabled { get; set; }
131134
}
132135
}

Flow.Launcher.Infrastructure/UserSettings/Settings.cs

+18
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,24 @@ public string PlaceholderText
159159
}
160160
}
161161
}
162+
163+
private bool _showHomePage { get; set; } = true;
164+
public bool ShowHomePage
165+
{
166+
get => _showHomePage;
167+
set
168+
{
169+
if (_showHomePage != value)
170+
{
171+
_showHomePage = value;
172+
OnPropertyChanged();
173+
}
174+
}
175+
}
176+
177+
public bool ShowHistoryResultsForHomePage { get; set; } = false;
178+
public int MaxHistoryResultsToShowForHomePage { get; set; } = 5;
179+
162180
public int CustomExplorerIndex { get; set; } = 0;
163181

164182
[JsonIgnore]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Collections.Generic;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace Flow.Launcher.Plugin
6+
{
7+
/// <summary>
8+
/// Asynchronous Query Model for Flow Launcher When Query Text is Empty
9+
/// </summary>
10+
public interface IAsyncHomeQuery : IFeatures
11+
{
12+
/// <summary>
13+
/// Asynchronous Querying When Query Text is Empty
14+
/// </summary>
15+
/// <para>
16+
/// If the Querying method requires high IO transmission
17+
/// or performing CPU intense jobs (performing better with cancellation), please use this IAsyncHomeQuery interface
18+
/// </para>
19+
/// <param name="token">Cancel when querying job is obsolete</param>
20+
/// <returns></returns>
21+
Task<List<Result>> HomeQueryAsync(CancellationToken token);
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Collections.Generic;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace Flow.Launcher.Plugin
6+
{
7+
/// <summary>
8+
/// Synchronous Query Model for Flow Launcher When Query Text is Empty
9+
/// <para>
10+
/// If the Querying method requires high IO transmission
11+
/// or performing CPU intense jobs (performing better with cancellation), please try the IAsyncHomeQuery interface
12+
/// </para>
13+
/// </summary>
14+
public interface IHomeQuery : IAsyncHomeQuery
15+
{
16+
/// <summary>
17+
/// Querying When Query Text is Empty
18+
/// <para>
19+
/// This method will be called within a Task.Run,
20+
/// so please avoid synchronously wait for long.
21+
/// </para>
22+
/// </summary>
23+
/// <returns></returns>
24+
List<Result> HomeQuery();
25+
26+
Task<List<Result>> IAsyncHomeQuery.HomeQueryAsync(CancellationToken token) => Task.Run(HomeQuery);
27+
}
28+
}

Flow.Launcher.Plugin/PluginMetadata.cs

+5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ public class PluginMetadata : BaseModel
5050
/// </summary>
5151
public bool Disabled { get; set; }
5252

53+
/// <summary>
54+
/// Whether plugin is disabled in home query.
55+
/// </summary>
56+
public bool HomeDisabled { get; set; }
57+
5358
/// <summary>
5459
/// Plugin execute file path.
5560
/// </summary>

Flow.Launcher/Languages/en.xaml

+10
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@
126126
<system:String x:Key="KoreanImeOpenLinkButton">Open</system:String>
127127
<system:String x:Key="KoreanImeRegistry">Use Previous Korean IME</system:String>
128128
<system:String x:Key="KoreanImeRegistryTooltip">You can change the Previous Korean IME settings directly from here</system:String>
129+
<system:String x:Key="homePage">Home Page</system:String>
130+
<system:String x:Key="homePageToolTip">Show home page results when query text is empty.</system:String>
131+
<system:String x:Key="historyResultsForHomePage">Show History Results in Home Page</system:String>
132+
<system:String x:Key="historyResultsCountForHomePage">Maximum History Results Shown in Home Page</system:String>
133+
<system:String x:Key="homeToggleBoxToolTip">This can only be edited if plugin supports Home feature and Home Page is enabled.</system:String>
129134

130135
<!-- Setting Plugin -->
131136
<system:String x:Key="searchplugin">Search Plugin</system:String>
@@ -148,6 +153,7 @@
148153
<system:String x:Key="DisplayModeOnOff">Enabled</system:String>
149154
<system:String x:Key="DisplayModePriority">Priority</system:String>
150155
<system:String x:Key="DisplayModeSearchDelay">Search Delay</system:String>
156+
<system:String x:Key="DisplayModeHomeOnOff">Home Page</system:String>
151157
<system:String x:Key="currentPriority">Current Priority</system:String>
152158
<system:String x:Key="newPriority">New Priority</system:String>
153159
<system:String x:Key="priority">Priority</system:String>
@@ -423,6 +429,10 @@
423429
<system:String x:Key="searchDelayTimeTitle">Search Delay Time Setting</system:String>
424430
<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>
425431

432+
<!-- Search Delay Settings Dialog -->
433+
<system:String x:Key="homeTitle">Home Page</system:String>
434+
<system:String x:Key="homeTips">Enable the plugin home page state if you like to show the plugin results when query is empty.</system:String>
435+
426436
<!-- Custom Query Hotkey Dialog -->
427437
<system:String x:Key="customeQueryHotkeyTitle">Custom Query Hotkey</system:String>
428438
<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.cs

+12
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,12 @@ private async void OnLoaded(object sender, RoutedEventArgs e)
283283
case nameof(Settings.SettingWindowFont):
284284
InitializeContextMenu();
285285
break;
286+
case nameof(Settings.ShowHomePage):
287+
if (_viewModel.QueryResultsSelected() && string.IsNullOrEmpty(_viewModel.QueryText))
288+
{
289+
_viewModel.QueryResults();
290+
}
291+
break;
286292
}
287293
};
288294

@@ -298,6 +304,12 @@ private async void OnLoaded(object sender, RoutedEventArgs e)
298304
DependencyPropertyDescriptor
299305
.FromProperty(VisibilityProperty, typeof(StackPanel))
300306
.AddValueChanged(History, (s, e) => UpdateClockPanelVisibility());
307+
308+
// Initialize query state
309+
if (_settings.ShowHomePage && string.IsNullOrEmpty(_viewModel.QueryText))
310+
{
311+
_viewModel.QueryResults();
312+
}
301313
}
302314

303315
private async void OnClosing(object sender, CancelEventArgs e)

Flow.Launcher/Resources/Controls/InstalledPluginDisplay.xaml

+10-1
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,19 @@
100100
ToolTipService.InitialShowDelay="0"
101101
ToolTipService.ShowOnDisabled="True"
102102
Value="{Binding PluginSearchDelayTime, Mode=TwoWay}" />
103-
104103
</StackPanel>
105104

106105
<!-- Put OnOffControl after PriorityControl & SearchDelayControl so that it can display correctly -->
106+
<ui:ToggleSwitch
107+
x:Name="HomeOnOffControl"
108+
Margin="0 0 8 0"
109+
IsEnabled="{Binding HomeEnabled}"
110+
IsOn="{Binding PluginHomeState}"
111+
OffContent="{DynamicResource disable}"
112+
OnContent="{DynamicResource enable}"
113+
ToolTip="{DynamicResource homeToggleBoxToolTip}"
114+
Visibility="{Binding DataContext.IsHomeOnOffSelected, RelativeSource={RelativeSource AncestorType=ListBox}, Converter={StaticResource BooleanToVisibilityConverter}}" />
115+
107116
<ui:ToggleSwitch
108117
x:Name="OnOffControl"
109118
Margin="0 0 8 0"

Flow.Launcher/SettingPages/ViewModels/SettingsPaneGeneralViewModel.cs

+13-2
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,22 @@ public int SearchDelayTimeValue
189189
{
190190
Settings.SearchDelayTime = value;
191191
OnPropertyChanged();
192-
OnPropertyChanged(nameof(SearchDelayTimeDisplay));
193192
}
194193
}
195194
}
196-
public string SearchDelayTimeDisplay => $"{SearchDelayTimeValue}ms";
195+
196+
public int MaxHistoryResultsToShowValue
197+
{
198+
get => Settings.MaxHistoryResultsToShowForHomePage;
199+
set
200+
{
201+
if (Settings.MaxHistoryResultsToShowForHomePage != value)
202+
{
203+
Settings.MaxHistoryResultsToShowForHomePage = value;
204+
OnPropertyChanged();
205+
}
206+
}
207+
}
197208

198209
private void UpdateEnumDropdownLocalizations()
199210
{

0 commit comments

Comments
 (0)