mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Support search delay
This commit is contained in:
parent
4bb8bffb78
commit
b1a46817f0
4 changed files with 130 additions and 51 deletions
|
|
@ -275,6 +275,9 @@ namespace Flow.Launcher.Infrastructure.UserSettings
|
||||||
public bool LeaveCmdOpen { get; set; }
|
public bool LeaveCmdOpen { get; set; }
|
||||||
public bool HideWhenDeactivated { get; set; } = true;
|
public bool HideWhenDeactivated { get; set; } = true;
|
||||||
|
|
||||||
|
public bool SearchQueryResultsWithDelay { get; set; } = false;
|
||||||
|
public int SearchInputDelay { get; set; } = 150;
|
||||||
|
|
||||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||||
public SearchWindowScreens SearchWindowScreen { get; set; } = SearchWindowScreens.Cursor;
|
public SearchWindowScreens SearchWindowScreen { get; set; } = SearchWindowScreens.Cursor;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,7 @@
|
||||||
<PackageReference Include="NHotkey.Wpf" Version="3.0.0" />
|
<PackageReference Include="NHotkey.Wpf" Version="3.0.0" />
|
||||||
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
|
<PackageReference Include="PropertyChanged.Fody" Version="3.4.0" />
|
||||||
<PackageReference Include="SemanticVersioning" Version="3.0.0" />
|
<PackageReference Include="SemanticVersioning" Version="3.0.0" />
|
||||||
|
<PackageReference Include="System.Reactive.Linq" Version="6.0.1" />
|
||||||
<PackageReference Include="TaskScheduler" Version="2.12.1" />
|
<PackageReference Include="TaskScheduler" Version="2.12.1" />
|
||||||
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.1" />
|
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media.Animation;
|
using System.Windows.Media.Animation;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Forms;
|
|
||||||
using Flow.Launcher.Core.Plugin;
|
using Flow.Launcher.Core.Plugin;
|
||||||
using Flow.Launcher.Core.Resource;
|
using Flow.Launcher.Core.Resource;
|
||||||
using Flow.Launcher.Helper;
|
using Flow.Launcher.Helper;
|
||||||
|
|
@ -27,6 +26,7 @@ using DataObject = System.Windows.DataObject;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using Windows.Win32;
|
using Windows.Win32;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
|
||||||
namespace Flow.Launcher
|
namespace Flow.Launcher
|
||||||
{
|
{
|
||||||
|
|
@ -68,6 +68,7 @@ namespace Flow.Launcher
|
||||||
var handle = new WindowInteropHelper(this).Handle;
|
var handle = new WindowInteropHelper(this).Handle;
|
||||||
var win = HwndSource.FromHwnd(handle);
|
var win = HwndSource.FromHwnd(handle);
|
||||||
win.AddHook(WndProc);
|
win.AddHook(WndProc);
|
||||||
|
SetupSearchTextBoxReactiveness(_settings.SearchQueryResultsWithDelay);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,63 +205,63 @@ namespace Flow.Launcher
|
||||||
switch (e.PropertyName)
|
switch (e.PropertyName)
|
||||||
{
|
{
|
||||||
case nameof(MainViewModel.MainWindowVisibilityStatus):
|
case nameof(MainViewModel.MainWindowVisibilityStatus):
|
||||||
{
|
|
||||||
Dispatcher.Invoke(() =>
|
|
||||||
{
|
{
|
||||||
if (_viewModel.MainWindowVisibilityStatus)
|
Dispatcher.Invoke(() =>
|
||||||
{
|
{
|
||||||
if (_settings.UseSound)
|
if (_viewModel.MainWindowVisibilityStatus)
|
||||||
{
|
{
|
||||||
SoundPlay();
|
if (_settings.UseSound)
|
||||||
}
|
{
|
||||||
|
SoundPlay();
|
||||||
|
}
|
||||||
|
|
||||||
UpdatePosition();
|
UpdatePosition();
|
||||||
PreviewReset();
|
PreviewReset();
|
||||||
Activate();
|
Activate();
|
||||||
QueryTextBox.Focus();
|
QueryTextBox.Focus();
|
||||||
_settings.ActivateTimes++;
|
_settings.ActivateTimes++;
|
||||||
if (!_viewModel.LastQuerySelected)
|
if (!_viewModel.LastQuerySelected)
|
||||||
|
{
|
||||||
|
QueryTextBox.SelectAll();
|
||||||
|
_viewModel.LastQuerySelected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_viewModel.ProgressBarVisibility == Visibility.Visible &&
|
||||||
|
isProgressBarStoryboardPaused)
|
||||||
|
{
|
||||||
|
_progressBarStoryboard.Begin(ProgressBar, true);
|
||||||
|
isProgressBarStoryboardPaused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_settings.UseAnimation)
|
||||||
|
WindowAnimator();
|
||||||
|
}
|
||||||
|
else if (!isProgressBarStoryboardPaused)
|
||||||
{
|
{
|
||||||
QueryTextBox.SelectAll();
|
_progressBarStoryboard.Stop(ProgressBar);
|
||||||
_viewModel.LastQuerySelected = true;
|
isProgressBarStoryboardPaused = true;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
if (_viewModel.ProgressBarVisibility == Visibility.Visible &&
|
break;
|
||||||
isProgressBarStoryboardPaused)
|
}
|
||||||
|
case nameof(MainViewModel.ProgressBarVisibility):
|
||||||
|
{
|
||||||
|
Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
if (_viewModel.ProgressBarVisibility == Visibility.Hidden && !isProgressBarStoryboardPaused)
|
||||||
|
{
|
||||||
|
_progressBarStoryboard.Stop(ProgressBar);
|
||||||
|
isProgressBarStoryboardPaused = true;
|
||||||
|
}
|
||||||
|
else if (_viewModel.MainWindowVisibilityStatus &&
|
||||||
|
isProgressBarStoryboardPaused)
|
||||||
{
|
{
|
||||||
_progressBarStoryboard.Begin(ProgressBar, true);
|
_progressBarStoryboard.Begin(ProgressBar, true);
|
||||||
isProgressBarStoryboardPaused = false;
|
isProgressBarStoryboardPaused = false;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
if (_settings.UseAnimation)
|
break;
|
||||||
WindowAnimator();
|
}
|
||||||
}
|
|
||||||
else if (!isProgressBarStoryboardPaused)
|
|
||||||
{
|
|
||||||
_progressBarStoryboard.Stop(ProgressBar);
|
|
||||||
isProgressBarStoryboardPaused = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nameof(MainViewModel.ProgressBarVisibility):
|
|
||||||
{
|
|
||||||
Dispatcher.Invoke(() =>
|
|
||||||
{
|
|
||||||
if (_viewModel.ProgressBarVisibility == Visibility.Hidden && !isProgressBarStoryboardPaused)
|
|
||||||
{
|
|
||||||
_progressBarStoryboard.Stop(ProgressBar);
|
|
||||||
isProgressBarStoryboardPaused = true;
|
|
||||||
}
|
|
||||||
else if (_viewModel.MainWindowVisibilityStatus &&
|
|
||||||
isProgressBarStoryboardPaused)
|
|
||||||
{
|
|
||||||
_progressBarStoryboard.Begin(ProgressBar, true);
|
|
||||||
isProgressBarStoryboardPaused = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case nameof(MainViewModel.QueryTextCursorMovedToEnd):
|
case nameof(MainViewModel.QueryTextCursorMovedToEnd):
|
||||||
if (_viewModel.QueryTextCursorMovedToEnd)
|
if (_viewModel.QueryTextCursorMovedToEnd)
|
||||||
{
|
{
|
||||||
|
|
@ -415,10 +416,10 @@ namespace Flow.Launcher
|
||||||
{
|
{
|
||||||
switch (e.Button)
|
switch (e.Button)
|
||||||
{
|
{
|
||||||
case MouseButtons.Left:
|
case System.Windows.Forms.MouseButtons.Left:
|
||||||
_viewModel.ToggleFlowLauncher();
|
_viewModel.ToggleFlowLauncher();
|
||||||
break;
|
break;
|
||||||
case MouseButtons.Right:
|
case System.Windows.Forms.MouseButtons.Right:
|
||||||
|
|
||||||
contextMenu.IsOpen = true;
|
contextMenu.IsOpen = true;
|
||||||
// Get context menu handle and bring it to the foreground
|
// Get context menu handle and bring it to the foreground
|
||||||
|
|
@ -857,5 +858,78 @@ namespace Flow.Launcher
|
||||||
be.UpdateSource();
|
be.UpdateSource();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Search Delay
|
||||||
|
|
||||||
|
// Edited from: https://github.com/microsoft/PowerToys
|
||||||
|
|
||||||
|
private IDisposable _reactiveSubscription;
|
||||||
|
|
||||||
|
private void SetupSearchTextBoxReactiveness(bool showResultsWithDelay)
|
||||||
|
{
|
||||||
|
if (_reactiveSubscription != null)
|
||||||
|
{
|
||||||
|
_reactiveSubscription.Dispose();
|
||||||
|
_reactiveSubscription = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryTextBox.TextChanged -= QueryTextBox_TextChanged;
|
||||||
|
|
||||||
|
if (showResultsWithDelay)
|
||||||
|
{
|
||||||
|
_reactiveSubscription = Observable.FromEventPattern<TextChangedEventHandler, TextChangedEventArgs>(
|
||||||
|
conversion => (sender, eventArg) => conversion(sender, eventArg),
|
||||||
|
add => QueryTextBox.TextChanged += add,
|
||||||
|
remove => QueryTextBox.TextChanged -= remove)
|
||||||
|
.Do(@event => ClearAutoCompleteText((TextBox)@event.Sender))
|
||||||
|
.Throttle(TimeSpan.FromMilliseconds(_settings.SearchInputDelay))
|
||||||
|
.Do(@event => Dispatcher.Invoke(() => PerformSearchQuery((TextBox)@event.Sender)))
|
||||||
|
.Subscribe();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QueryTextBox.TextChanged += QueryTextBox_TextChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void QueryTextBox_TextChanged(object sender, TextChangedEventArgs e)
|
||||||
|
{
|
||||||
|
var textBox = (TextBox)sender;
|
||||||
|
ClearAutoCompleteText(textBox);
|
||||||
|
PerformSearchQuery(textBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearAutoCompleteText(TextBox textBox)
|
||||||
|
{
|
||||||
|
var text = textBox.Text;
|
||||||
|
var autoCompleteText = QueryTextSuggestionBox.Text;
|
||||||
|
|
||||||
|
if (ShouldAutoCompleteTextBeEmpty(text, autoCompleteText))
|
||||||
|
{
|
||||||
|
QueryTextSuggestionBox.Text = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool ShouldAutoCompleteTextBeEmpty(string queryText, string autoCompleteText)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(autoCompleteText))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Using Ordinal this is internal
|
||||||
|
return string.IsNullOrEmpty(queryText) || !autoCompleteText.StartsWith(queryText, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PerformSearchQuery(TextBox textBox)
|
||||||
|
{
|
||||||
|
var text = textBox.Text;
|
||||||
|
_viewModel.QueryText = text;
|
||||||
|
_viewModel.Query();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -569,7 +569,6 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
_queryText = value;
|
_queryText = value;
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
Query();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -631,6 +630,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
// re-query is done in QueryText's setter method
|
// re-query is done in QueryText's setter method
|
||||||
QueryText = queryText;
|
QueryText = queryText;
|
||||||
|
Query();
|
||||||
// set to false so the subsequent set true triggers
|
// set to false so the subsequent set true triggers
|
||||||
// PropertyChanged and MoveQueryTextToEnd is called
|
// PropertyChanged and MoveQueryTextToEnd is called
|
||||||
QueryTextCursorMovedToEnd = false;
|
QueryTextCursorMovedToEnd = false;
|
||||||
|
|
@ -695,6 +695,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QueryText = string.Empty;
|
QueryText = string.Empty;
|
||||||
|
Query();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue