mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-07 11:46:30 +02:00
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. 
This commit is contained in:
@@ -52,6 +52,8 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
|
|
||||||
public string SearchText { get; private set; } = string.Empty;
|
public string SearchText { get; private set; } = string.Empty;
|
||||||
|
|
||||||
|
public string InitialSearchText { get; private set; } = string.Empty;
|
||||||
|
|
||||||
public CommandItemViewModel EmptyContent { get; private set; }
|
public CommandItemViewModel EmptyContent { get; private set; }
|
||||||
|
|
||||||
private bool _isDynamic;
|
private bool _isDynamic;
|
||||||
@@ -128,7 +130,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IListItem[] newItems = _model.Unsafe!.GetItems();
|
var newItems = _model.Unsafe!.GetItems();
|
||||||
|
|
||||||
// Collect all the items into new viewmodels
|
// Collect all the items into new viewmodels
|
||||||
Collection<ListItemViewModel> newViewModels = [];
|
Collection<ListItemViewModel> newViewModels = [];
|
||||||
@@ -136,7 +138,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
// TODO we can probably further optimize this by also keeping a
|
// TODO we can probably further optimize this by also keeping a
|
||||||
// HashSet of every ExtensionObject we currently have, and only
|
// HashSet of every ExtensionObject we currently have, and only
|
||||||
// building new viewmodels for the ones we haven't already built.
|
// 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));
|
ListItemViewModel viewModel = new(item, new(this));
|
||||||
|
|
||||||
@@ -147,8 +149,8 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<ListItemViewModel> firstTwenty = newViewModels.Take(20);
|
var firstTwenty = newViewModels.Take(20);
|
||||||
foreach (ListItemViewModel? item in firstTwenty)
|
foreach (var item in firstTwenty)
|
||||||
{
|
{
|
||||||
item?.SafeInitializeProperties();
|
item?.SafeInitializeProperties();
|
||||||
}
|
}
|
||||||
@@ -233,7 +235,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
iterable = Items.ToArray();
|
iterable = Items.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (ListItemViewModel item in iterable)
|
foreach (var item in iterable)
|
||||||
{
|
{
|
||||||
ct.ThrowIfCancellationRequested();
|
ct.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@@ -266,8 +268,8 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchResult nameMatch = StringMatcher.FuzzySearch(query, listItem.Title);
|
var nameMatch = StringMatcher.FuzzySearch(query, listItem.Title);
|
||||||
MatchResult descriptionMatch = StringMatcher.FuzzySearch(query, listItem.Subtitle);
|
var descriptionMatch = StringMatcher.FuzzySearch(query, listItem.Subtitle);
|
||||||
return new[] { nameMatch.Score, (descriptionMatch.Score - 4) / 2, 0 }.Max();
|
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
|
// Similarly stolen from ListHelpers.FilterList
|
||||||
public static IEnumerable<ListItemViewModel> FilterList(IEnumerable<ListItemViewModel> items, string query)
|
public static IEnumerable<ListItemViewModel> FilterList(IEnumerable<ListItemViewModel> items, string query)
|
||||||
{
|
{
|
||||||
IOrderedEnumerable<ScoredListItemViewModel> scores = items
|
var scores = items
|
||||||
.Where(i => !i.IsInErrorState)
|
.Where(i => !i.IsInErrorState)
|
||||||
.Select(li => new ScoredListItemViewModel() { ViewModel = li, Score = ScoreListItem(query, li) })
|
.Select(li => new ScoredListItemViewModel() { ViewModel = li, Score = ScoreListItem(query, li) })
|
||||||
.Where(score => score.Score > 0)
|
.Where(score => score.Score > 0)
|
||||||
@@ -359,7 +361,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
{
|
{
|
||||||
base.InitializeProperties();
|
base.InitializeProperties();
|
||||||
|
|
||||||
IListPage? model = _model.Unsafe;
|
var model = _model.Unsafe;
|
||||||
if (model == null)
|
if (model == null)
|
||||||
{
|
{
|
||||||
return; // throw?
|
return; // throw?
|
||||||
@@ -373,8 +375,9 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
_modelPlaceholderText = model.PlaceholderText;
|
_modelPlaceholderText = model.PlaceholderText;
|
||||||
UpdateProperty(nameof(PlaceholderText));
|
UpdateProperty(nameof(PlaceholderText));
|
||||||
|
|
||||||
SearchText = model.SearchText;
|
InitialSearchText = SearchText = model.SearchText;
|
||||||
UpdateProperty(nameof(SearchText));
|
UpdateProperty(nameof(SearchText));
|
||||||
|
UpdateProperty(nameof(InitialSearchText));
|
||||||
|
|
||||||
EmptyContent = new(new(model.EmptyContent), PageContext);
|
EmptyContent = new(new(model.EmptyContent), PageContext);
|
||||||
EmptyContent.SlowInitializeProperties();
|
EmptyContent.SlowInitializeProperties();
|
||||||
@@ -385,7 +388,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
|
|
||||||
public void LoadMoreIfNeeded()
|
public void LoadMoreIfNeeded()
|
||||||
{
|
{
|
||||||
IListPage? model = this._model.Unsafe;
|
var model = this._model.Unsafe;
|
||||||
if (model == null)
|
if (model == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -412,7 +415,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
{
|
{
|
||||||
base.FetchProperty(propertyName);
|
base.FetchProperty(propertyName);
|
||||||
|
|
||||||
IListPage? model = this._model.Unsafe;
|
var model = this._model.Unsafe;
|
||||||
if (model == null)
|
if (model == null)
|
||||||
{
|
{
|
||||||
return; // throw?
|
return; // throw?
|
||||||
@@ -475,13 +478,13 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
|
|
||||||
lock (_listLock)
|
lock (_listLock)
|
||||||
{
|
{
|
||||||
foreach (ListItemViewModel item in Items)
|
foreach (var item in Items)
|
||||||
{
|
{
|
||||||
item.SafeCleanup();
|
item.SafeCleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
Items.Clear();
|
Items.Clear();
|
||||||
foreach (ListItemViewModel item in FilteredItems)
|
foreach (var item in FilteredItems)
|
||||||
{
|
{
|
||||||
item.SafeCleanup();
|
item.SafeCleanup();
|
||||||
}
|
}
|
||||||
@@ -489,7 +492,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
|||||||
FilteredItems.Clear();
|
FilteredItems.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
IListPage? model = _model.Unsafe;
|
var model = _model.Unsafe;
|
||||||
if (model != null)
|
if (model != null)
|
||||||
{
|
{
|
||||||
model.ItemsChanged -= Model_ItemsChanged;
|
model.ItemsChanged -= Model_ItemsChanged;
|
||||||
|
|||||||
@@ -250,18 +250,31 @@ public sealed partial class SearchBar : UserControl,
|
|||||||
private void Page_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
private void Page_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
var property = e.PropertyName;
|
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
|
if (CurrentPageViewModel is ListViewModel list)
|
||||||
FilterBox.Select(FilterBox.Text.Length, 0);
|
{
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ namespace Microsoft.CmdPal.Ext.WindowsServices.Properties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Open services (Ctrl+O).
|
/// Looks up a localized string similar to Open services.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string wox_plugin_service_open_services {
|
internal static string wox_plugin_service_open_services {
|
||||||
get {
|
get {
|
||||||
@@ -133,7 +133,7 @@ namespace Microsoft.CmdPal.Ext.WindowsServices.Properties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Restart (Ctrl+R).
|
/// Looks up a localized string similar to Restart.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static string wox_plugin_service_restart {
|
internal static string wox_plugin_service_restart {
|
||||||
get {
|
get {
|
||||||
|
|||||||
Reference in New Issue
Block a user