Immediately select search text on opening page (#38842)

closes #38712
closes #38315
related to #38379 (and might sufficiently close that too)

This immediately selects the search text when a page is loaded.
![38712-select-search-text-000](https://github.com/user-attachments/assets/9db8b455-9afb-4b11-9a30-8ddaa23cdb64)
This commit is contained in:
Mike Griese
2025-04-16 14:47:55 -05:00
committed by GitHub
parent e95a570d48
commit 67463abf98
3 changed files with 44 additions and 28 deletions

View File

@@ -52,6 +52,8 @@ public partial class ListViewModel : PageViewModel, IDisposable
public string SearchText { get; private set; } = string.Empty;
public string InitialSearchText { get; private set; } = string.Empty;
public CommandItemViewModel EmptyContent { get; private set; }
private bool _isDynamic;
@@ -128,7 +130,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
try
{
IListItem[] newItems = _model.Unsafe!.GetItems();
var newItems = _model.Unsafe!.GetItems();
// Collect all the items into new viewmodels
Collection<ListItemViewModel> newViewModels = [];
@@ -136,7 +138,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
// TODO we can probably further optimize this by also keeping a
// HashSet of every ExtensionObject we currently have, and only
// building new viewmodels for the ones we haven't already built.
foreach (IListItem? item in newItems)
foreach (var item in newItems)
{
ListItemViewModel viewModel = new(item, new(this));
@@ -147,8 +149,8 @@ public partial class ListViewModel : PageViewModel, IDisposable
}
}
IEnumerable<ListItemViewModel> firstTwenty = newViewModels.Take(20);
foreach (ListItemViewModel? item in firstTwenty)
var firstTwenty = newViewModels.Take(20);
foreach (var item in firstTwenty)
{
item?.SafeInitializeProperties();
}
@@ -233,7 +235,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
iterable = Items.ToArray();
}
foreach (ListItemViewModel item in iterable)
foreach (var item in iterable)
{
ct.ThrowIfCancellationRequested();
@@ -266,8 +268,8 @@ public partial class ListViewModel : PageViewModel, IDisposable
return 1;
}
MatchResult nameMatch = StringMatcher.FuzzySearch(query, listItem.Title);
MatchResult descriptionMatch = StringMatcher.FuzzySearch(query, listItem.Subtitle);
var nameMatch = StringMatcher.FuzzySearch(query, listItem.Title);
var descriptionMatch = StringMatcher.FuzzySearch(query, listItem.Subtitle);
return new[] { nameMatch.Score, (descriptionMatch.Score - 4) / 2, 0 }.Max();
}
@@ -280,7 +282,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
// Similarly stolen from ListHelpers.FilterList
public static IEnumerable<ListItemViewModel> FilterList(IEnumerable<ListItemViewModel> items, string query)
{
IOrderedEnumerable<ScoredListItemViewModel> scores = items
var scores = items
.Where(i => !i.IsInErrorState)
.Select(li => new ScoredListItemViewModel() { ViewModel = li, Score = ScoreListItem(query, li) })
.Where(score => score.Score > 0)
@@ -359,7 +361,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
{
base.InitializeProperties();
IListPage? model = _model.Unsafe;
var model = _model.Unsafe;
if (model == null)
{
return; // throw?
@@ -373,8 +375,9 @@ public partial class ListViewModel : PageViewModel, IDisposable
_modelPlaceholderText = model.PlaceholderText;
UpdateProperty(nameof(PlaceholderText));
SearchText = model.SearchText;
InitialSearchText = SearchText = model.SearchText;
UpdateProperty(nameof(SearchText));
UpdateProperty(nameof(InitialSearchText));
EmptyContent = new(new(model.EmptyContent), PageContext);
EmptyContent.SlowInitializeProperties();
@@ -385,7 +388,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
public void LoadMoreIfNeeded()
{
IListPage? model = this._model.Unsafe;
var model = this._model.Unsafe;
if (model == null)
{
return;
@@ -412,7 +415,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
{
base.FetchProperty(propertyName);
IListPage? model = this._model.Unsafe;
var model = this._model.Unsafe;
if (model == null)
{
return; // throw?
@@ -475,13 +478,13 @@ public partial class ListViewModel : PageViewModel, IDisposable
lock (_listLock)
{
foreach (ListItemViewModel item in Items)
foreach (var item in Items)
{
item.SafeCleanup();
}
Items.Clear();
foreach (ListItemViewModel item in FilteredItems)
foreach (var item in FilteredItems)
{
item.SafeCleanup();
}
@@ -489,7 +492,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
FilteredItems.Clear();
}
IListPage? model = _model.Unsafe;
var model = _model.Unsafe;
if (model != null)
{
model.ItemsChanged -= Model_ItemsChanged;

View File

@@ -250,18 +250,31 @@ public sealed partial class SearchBar : UserControl,
private void Page_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
var property = e.PropertyName;
if (CurrentPageViewModel is ListViewModel list &&
property == nameof(ListViewModel.SearchText))
{
// Only if the text actually changed...
// (sometimes this triggers on a round-trip of the SearchText)
if (FilterBox.Text != list.SearchText)
{
// ... Update our displayed text, and...
FilterBox.Text = list.SearchText;
// ... Move the cursor to the end of the input
FilterBox.Select(FilterBox.Text.Length, 0);
if (CurrentPageViewModel is ListViewModel list)
{
if (property == nameof(ListViewModel.SearchText))
{
// Only if the text actually changed...
// (sometimes this triggers on a round-trip of the SearchText)
if (FilterBox.Text != list.SearchText)
{
// ... Update our displayed text, and...
FilterBox.Text = list.SearchText;
// ... Move the cursor to the end of the input
FilterBox.Select(FilterBox.Text.Length, 0);
}
}
else if (property == nameof(ListViewModel.InitialSearchText))
{
// GH #38712:
// The ListPage will notify us of the `InitialSearchText` when
// we first load the viewmodel. We can use that as an
// opportunity to immediately select the search text. That lets
// the user start typing a new search without manually
// selecting the old one.
SelectSearch();
}
}
}

View File

@@ -88,7 +88,7 @@ namespace Microsoft.CmdPal.Ext.WindowsServices.Properties {
}
/// <summary>
/// Looks up a localized string similar to Open services (Ctrl+O).
/// Looks up a localized string similar to Open services.
/// </summary>
internal static string wox_plugin_service_open_services {
get {
@@ -133,7 +133,7 @@ namespace Microsoft.CmdPal.Ext.WindowsServices.Properties {
}
/// <summary>
/// Looks up a localized string similar to Restart (Ctrl+R).
/// Looks up a localized string similar to Restart.
/// </summary>
internal static string wox_plugin_service_restart {
get {