Skip to content

Code Quality: Use UI thread when populating suggestions #17274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 18 additions & 25 deletions src/Files.App/UserControls/NavigationToolbar.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ private void NavToolbar_Loading(FrameworkElement _, object e)
OngoingTasksViewModel.NewItemAdded += OngoingTasksActions_ProgressBannerPosted;
}

[Obsolete("Superseded by Omnibar.")]
private void VisiblePath_Loaded(object _, RoutedEventArgs e)
{
// AutoSuggestBox won't receive focus unless it's fully loaded
Expand All @@ -73,6 +74,7 @@ private void VisiblePath_Loaded(object _, RoutedEventArgs e)
}
}

[Obsolete("Superseded by Omnibar.")]
private void ManualPathEntryItem_Click(object _, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerDeviceType is PointerDeviceType.Mouse)
Expand All @@ -84,6 +86,7 @@ private void ManualPathEntryItem_Click(object _, PointerRoutedEventArgs e)
ViewModel.IsEditModeEnabled = true;
}

[Obsolete("Superseded by Omnibar.")]
private async void VisiblePath_KeyDown(object _, KeyRoutedEventArgs e)
{
if (e.Key is VirtualKey.Escape)
Expand All @@ -97,6 +100,7 @@ private async void VisiblePath_KeyDown(object _, KeyRoutedEventArgs e)
ClickablePath.Focus(FocusState.Keyboard);
}
}
[Obsolete("Superseded by Omnibar.")]
private void VisiblePath_LostFocus(object _, RoutedEventArgs e)
{
if (App.AppModel.IsMainWindowClosed)
Expand All @@ -119,8 +123,11 @@ private void VisiblePath_LostFocus(object _, RoutedEventArgs e)
VisiblePath.Focus(FocusState.Programmatic);
}

[Obsolete("Superseded by Omnibar.")]
private void SearchRegion_OnGotFocus(object sender, RoutedEventArgs e) => ViewModel.SearchRegion_GotFocus(sender, e);
[Obsolete("Superseded by Omnibar.")]
private void SearchRegion_LostFocus(object sender, RoutedEventArgs e) => ViewModel.SearchRegion_LostFocus(sender, e);
[Obsolete("Superseded by Omnibar.")]
private void SearchRegion_AccessKeyInvoked(UIElement sender, AccessKeyInvokedEventArgs args)
{
// Suppress access key invocation if any dialog is open
Expand All @@ -129,7 +136,7 @@ private void SearchRegion_AccessKeyInvoked(UIElement sender, AccessKeyInvokedEve
else
sender.Focus(FocusState.Keyboard);
}

[Obsolete("Superseded by Omnibar.")]
private void VisiblePath_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
=> ViewModel.VisiblePath_QuerySubmitted(sender, args);

Expand Down Expand Up @@ -247,6 +254,7 @@ void HistoryItemClicked(ToolbarHistoryItemModel? itemModel)
}
}

[Obsolete("Superseded by Omnibar.")]
private void ClickablePath_GettingFocus(UIElement sender, GettingFocusEventArgs args)
{
if (args.InputDevice != FocusInputDeviceKind.Keyboard)
Expand Down Expand Up @@ -342,18 +350,15 @@ private async void Omnibar_TextChanged(Omnibar sender, OmnibarTextChangedEventAr

if (Omnibar.CurrentSelectedMode == OmnibarPathMode)
{
await ViewModel.PopulateOmnibarSuggestionsForPathMode();
await DispatcherQueue.EnqueueOrInvokeAsync(ViewModel.PopulateOmnibarSuggestionsForPathMode);
}
else if (Omnibar.CurrentSelectedMode == OmnibarCommandPaletteMode)
{
await DispatcherQueue.EnqueueOrInvokeAsync(() =>
{
ViewModel.PopulateOmnibarSuggestionsForCommandPaletteMode();
});
await DispatcherQueue.EnqueueOrInvokeAsync(ViewModel.PopulateOmnibarSuggestionsForCommandPaletteMode);
}
else if (Omnibar.CurrentSelectedMode == OmnibarSearchMode)
{
await ViewModel.PopulateOmnibarSuggestionsForSearchMode();
await DispatcherQueue.EnqueueOrInvokeAsync(ViewModel.PopulateOmnibarSuggestionsForSearchMode);
}
}

Expand Down Expand Up @@ -456,19 +461,13 @@ private async void Omnibar_ModeChanged(object sender, OmnibarModeChangedEventArg
? Constants.UserEnvironmentPaths.HomePath
: ContentPageContext.ShellPage.ShellViewModel.WorkingDirectory;

await DispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
await ViewModel.PopulateOmnibarSuggestionsForPathMode();
});
await DispatcherQueue.EnqueueOrInvokeAsync(ViewModel.PopulateOmnibarSuggestionsForPathMode);
}
else if (e.NewMode == OmnibarCommandPaletteMode)
{
ViewModel.OmnibarCommandPaletteModeText = string.Empty;

await DispatcherQueue.EnqueueOrInvokeAsync(() =>
{
ViewModel.PopulateOmnibarSuggestionsForCommandPaletteMode();
});
await DispatcherQueue.EnqueueOrInvokeAsync(ViewModel.PopulateOmnibarSuggestionsForCommandPaletteMode);
}
else if (e.NewMode == OmnibarSearchMode)
{
Expand All @@ -477,7 +476,7 @@ await DispatcherQueue.EnqueueOrInvokeAsync(() =>
else
ViewModel.OmnibarSearchModeText = ViewModel.InstanceViewModel.CurrentSearchQuery;

await ViewModel.PopulateOmnibarSuggestionsForSearchMode();
await DispatcherQueue.EnqueueOrInvokeAsync(ViewModel.PopulateOmnibarSuggestionsForSearchMode);
}
}

Expand All @@ -491,23 +490,17 @@ private async void Omnibar_IsFocusedChanged(Omnibar sender, OmnibarIsFocusedChan
? Constants.UserEnvironmentPaths.HomePath
: ContentPageContext.ShellPage.ShellViewModel.WorkingDirectory;

await DispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
await ViewModel.PopulateOmnibarSuggestionsForPathMode();
});
await DispatcherQueue.EnqueueOrInvokeAsync(ViewModel.PopulateOmnibarSuggestionsForPathMode);
}
else if (Omnibar.CurrentSelectedMode == OmnibarCommandPaletteMode)
{
ViewModel.OmnibarCommandPaletteModeText = string.Empty;

await DispatcherQueue.EnqueueOrInvokeAsync(() =>
{
ViewModel.PopulateOmnibarSuggestionsForCommandPaletteMode();
});
await DispatcherQueue.EnqueueOrInvokeAsync(ViewModel.PopulateOmnibarSuggestionsForCommandPaletteMode);
}
else if (Omnibar.CurrentSelectedMode == OmnibarSearchMode)
{
await ViewModel.PopulateOmnibarSuggestionsForSearchMode();
await DispatcherQueue.EnqueueOrInvokeAsync(ViewModel.PopulateOmnibarSuggestionsForSearchMode);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/Files.App/UserControls/SearchBox.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace Files.App.UserControls
{
[Obsolete("Superseded by Omnibar.")]
public sealed partial class SearchBox : UserControl
{
public static readonly DependencyProperty SearchBoxViewModelProperty =
Expand Down
74 changes: 48 additions & 26 deletions src/Files.App/ViewModels/UserControls/NavigationToolbarViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public sealed partial class NavigationToolbarViewModel : ObservableObject, IAddr

public bool IsSingleItemOverride { get; set; }

[Obsolete("Superseded by Omnibar.")]
public bool SearchHasFocus { get; private set; }

public bool EnableOmnibar => GeneralSettingsService.EnableOmnibar;
Expand All @@ -93,6 +94,7 @@ public sealed partial class NavigationToolbarViewModel : ObservableObject, IAddr

private NavigationToolbar? AddressToolbar => (MainWindow.Instance.Content as Frame)?.FindDescendant<NavigationToolbar>();

[Obsolete("Superseded by Omnibar.")]
public SearchBoxViewModel SearchBoxViewModel => (SearchBoxViewModel)SearchBox;

public bool HasAdditionalAction =>
Expand Down Expand Up @@ -186,15 +188,19 @@ public sealed partial class NavigationToolbarViewModel : ObservableObject, IAddr
public bool CanRefresh { get => _CanRefresh; set => SetProperty(ref _CanRefresh, value); }

private string _SearchButtonGlyph = "\uE721";
[Obsolete("Superseded by Omnibar.")]
public string SearchButtonGlyph { get => _SearchButtonGlyph; set => SetProperty(ref _SearchButtonGlyph, value); }

private bool _ManualEntryBoxLoaded;
[Obsolete("Superseded by Omnibar.")]
public bool ManualEntryBoxLoaded { get => _ManualEntryBoxLoaded; set => SetProperty(ref _ManualEntryBoxLoaded, value); }

private bool _ClickablePathLoaded = true;
[Obsolete("Superseded by Omnibar.")]
public bool ClickablePathLoaded { get => _ClickablePathLoaded; set => SetProperty(ref _ClickablePathLoaded, value); }

private string _PathControlDisplayText;
[Obsolete("Superseded by Omnibar.")]
public string PathControlDisplayText { get => _PathControlDisplayText; set => SetProperty(ref _PathControlDisplayText, value); }

private bool _HasItem = false;
Expand All @@ -207,6 +213,7 @@ public sealed partial class NavigationToolbarViewModel : ObservableObject, IAddr
public ISearchBoxViewModel SearchBox { get => _SearchBox; set => SetProperty(ref _SearchBox, value); }

private bool _IsSearchBoxVisible;
[Obsolete("Superseded by Omnibar.")]
public bool IsSearchBoxVisible
{
get => _IsSearchBoxVisible;
Expand Down Expand Up @@ -236,11 +243,7 @@ public string? PathText
public string? OmnibarSearchModeText { get => _OmnibarSearchModeText; set => SetProperty(ref _OmnibarSearchModeText, value); }

private string _OmnibarCurrentSelectedModeName = OmnibarPathModeName;
public string OmnibarCurrentSelectedModeName
{
get => _OmnibarCurrentSelectedModeName;
set => SetProperty(ref _OmnibarCurrentSelectedModeName, value);
}
public string OmnibarCurrentSelectedModeName { get => _OmnibarCurrentSelectedModeName; set => SetProperty(ref _OmnibarCurrentSelectedModeName, value); }

private CurrentInstanceViewModel _InstanceViewModel;
public CurrentInstanceViewModel InstanceViewModel
Expand All @@ -259,7 +262,7 @@ public CurrentInstanceViewModel InstanceViewModel
}
}

[Obsolete("Remove once Omnibar goes out of experimental.")]
[Obsolete("Superseded by Omnibar.")]
public bool IsEditModeEnabled
{
get => ManualEntryBoxLoaded;
Expand Down Expand Up @@ -411,6 +414,7 @@ private void UserSettingsService_OnSettingChangedEvent(object? sender, SettingCh
}
}

[Obsolete("Superseded by Omnibar.")]
public void PathBoxItem_DragLeave(object sender, DragEventArgs e)
{
if (((FrameworkElement)sender).DataContext is not PathBoxItem pathBoxItem ||
Expand All @@ -426,6 +430,7 @@ public void PathBoxItem_DragLeave(object sender, DragEventArgs e)
_dragOverPath = null;
}

[Obsolete("Superseded by Omnibar.")]
public async Task PathBoxItem_Drop(object sender, DragEventArgs e)
{
if (_lockFlag)
Expand Down Expand Up @@ -464,6 +469,7 @@ public async Task PathBoxItem_Drop(object sender, DragEventArgs e)
_lockFlag = false;
}

[Obsolete("Superseded by Omnibar.")]
public async Task PathBoxItem_DragOver(object sender, DragEventArgs e)
{
if (IsSingleItemOverride ||
Expand Down Expand Up @@ -540,6 +546,7 @@ x.Item is ZipStorageFile ||
deferral.Complete();
}

[Obsolete("Superseded by Omnibar.")]
public void PathItemSeparator_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{
var pathSeparatorIcon = sender as FontIcon;
Expand All @@ -553,35 +560,41 @@ public void PathItemSeparator_DataContextChanged(FrameworkElement sender, DataCo
});
}

[Obsolete("Superseded by Omnibar.")]
public void PathboxItemFlyout_Opening(object sender, object e)
{
ToolbarFlyoutOpening?.Invoke(this, new ToolbarFlyoutOpeningEventArgs((MenuFlyout)sender));
}

[Obsolete("Superseded by Omnibar.")]
public void PathBoxItemFlyout_Closed(object sender, object e)
{
((MenuFlyout)sender).Items.Clear();
}

[Obsolete("Superseded by Omnibar.")]
public void CurrentPathSetTextBox_TextChanged(object sender, TextChangedEventArgs args)
{
if (sender is TextBox textBox)
PathBoxQuerySubmitted?.Invoke(this, new ToolbarQuerySubmittedEventArgs() { QueryText = textBox.Text });
}

[Obsolete("Superseded by Omnibar.")]
public void VisiblePath_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)
AddressBarTextEntered?.Invoke(this, new AddressBarTextEnteredEventArgs() { AddressBarTextField = sender });
}

[Obsolete("Superseded by Omnibar.")]
public void VisiblePath_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
{
PathBoxQuerySubmitted?.Invoke(this, new ToolbarQuerySubmittedEventArgs() { QueryText = args.QueryText });

(this as IAddressToolbarViewModel).IsEditModeEnabled = false;
}

[Obsolete("Superseded by Omnibar.")]
public void PathBoxItem_PointerPressed(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerDeviceType != Microsoft.UI.Input.PointerDeviceType.Mouse)
Expand Down Expand Up @@ -710,6 +723,7 @@ await DialogDisplayHelper.ShowDialogAsync(Strings.InvalidItemDialogTitle.GetLoca
PathControlDisplayText = ContentPageContext.ShellPage.ShellViewModel.WorkingDirectory;
}

[Obsolete("Superseded by Omnibar.")]
public void PathBoxItem_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
{
switch (e.Key)
Expand Down Expand Up @@ -794,6 +808,7 @@ public void UpdateAdditionalActions()
OnPropertyChanged(nameof(HasAdditionalAction));
}

[Obsolete("Superseded by Omnibar.")]
private void CloseSearchBox(bool doFocus = false)
{
if (_SearchBox.WasQuerySubmitted)
Expand All @@ -818,11 +833,13 @@ private void CloseSearchBox(bool doFocus = false)
}
}

[Obsolete("Superseded by Omnibar.")]
public void SearchRegion_GotFocus(object sender, RoutedEventArgs e)
{
SearchHasFocus = true;
}

[Obsolete("Superseded by Omnibar.")]
public void SearchRegion_LostFocus(object sender, RoutedEventArgs e)
{
var element = Microsoft.UI.Xaml.Input.FocusManager.GetFocusedElement();
Expand All @@ -833,6 +850,7 @@ public void SearchRegion_LostFocus(object sender, RoutedEventArgs e)
CloseSearchBox();
}

[Obsolete("Superseded by Omnibar.")]
private void SearchRegion_Escaped(object? sender, ISearchBoxViewModel _SearchBox)
=> CloseSearchBox(true);

Expand Down Expand Up @@ -912,7 +930,7 @@ private static string NormalizePathInput(string currentInput, bool isFtp)
return currentInput;
}

[Obsolete("Remove once Omnibar goes out of experimental.")]
[Obsolete("Superseded by Omnibar.")]
public async Task CheckPathInputAsync(string currentInput, string currentSelectedPath, IShellPage shellPage)
{
if (currentInput.StartsWith('>'))
Expand Down Expand Up @@ -1153,7 +1171,7 @@ void AddNoResultsItem()
}
}

public void PopulateOmnibarSuggestionsForCommandPaletteMode()
public async Task PopulateOmnibarSuggestionsForCommandPaletteMode()
{
var newSuggestions = new List<NavigationBarSuggestionItem>();

Expand Down Expand Up @@ -1194,22 +1212,27 @@ public void PopulateOmnibarSuggestionsForCommandPaletteMode()
}
}

var suggestionItems = Commands
.Where(command => command.IsExecutable
&& command.IsAccessibleGlobally
&& (command.Description.Contains(OmnibarCommandPaletteModeText, StringComparison.OrdinalIgnoreCase)
|| command.Code.ToString().Contains(OmnibarCommandPaletteModeText, StringComparison.OrdinalIgnoreCase)))
.Select(command => new NavigationBarSuggestionItem
{
ThemedIconStyle = command.Glyph.ToThemedIconStyle(),
Glyph = command.Glyph.BaseGlyph,
Text = command.Description,
PrimaryDisplay = command.Description,
HotKeys = command.HotKeys,
SearchText = OmnibarCommandPaletteModeText,
})
.Where(item => item.Text != Commands.OpenCommandPalette.Description.ToString()
&& item.Text != Commands.EditPath.Description.ToString());
IEnumerable<NavigationBarSuggestionItem> suggestionItems = null!;

await Task.Run(() =>
{
suggestionItems = Commands
.Where(command => command.IsExecutable
&& command.IsAccessibleGlobally
&& (command.Description.Contains(OmnibarCommandPaletteModeText, StringComparison.OrdinalIgnoreCase)
|| command.Code.ToString().Contains(OmnibarCommandPaletteModeText, StringComparison.OrdinalIgnoreCase)))
.Select(command => new NavigationBarSuggestionItem
{
ThemedIconStyle = command.Glyph.ToThemedIconStyle(),
Glyph = command.Glyph.BaseGlyph,
Text = command.Description,
PrimaryDisplay = command.Description,
HotKeys = command.HotKeys,
SearchText = OmnibarCommandPaletteModeText,
})
.Where(item => item.Text != Commands.OpenCommandPalette.Description.ToString()
&& item.Text != Commands.EditPath.Description.ToString());
});

newSuggestions.AddRange(suggestionItems);

Expand Down Expand Up @@ -1297,8 +1320,7 @@ public async Task PopulateOmnibarSuggestionsForSearchMode()
OmnibarSearchModeSuggestionItems.Add(item);
}


[Obsolete("Remove once Omnibar goes out of experimental.")]
[Obsolete("Superseded by Omnibar.")]
public async Task SetAddressBarSuggestionsAsync(AutoSuggestBox sender, IShellPage shellpage)
{
if (sender.Text is not null && shellpage.ShellViewModel is not null)
Expand Down
Loading
Loading