Skip to content

Code Quality: Improved Omnibar 5 #17203

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

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
28 changes: 28 additions & 0 deletions src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Input;
using Windows.Foundation;

namespace Files.App.Controls
Expand All @@ -25,6 +26,8 @@ public partial class BreadcrumbBar : Control

private bool _isEllipsisRendered;

private bool _focusedViaKeyboard = false; // Used to determine if the BreadcrumbBar was focused via keyboard on Tab focus

// Properties

public int IndexAfterEllipsis
Expand Down Expand Up @@ -62,10 +65,18 @@ protected override void OnApplyTemplate()
_ellipsisBreadcrumbBarItem.SetOwner(this);
_itemsRepeater.Layout = _itemsRepeaterLayout;

//GettingFocus += BreadcrumbBar_GettingFocus;
//GettingFocus += BreadcrumbBar_GotFocus;
_itemsRepeater.ElementPrepared += ItemsRepeater_ElementPrepared;
_itemsRepeater.ElementClearing += ItemsRepeater_ElementClearing;
_itemsRepeater.ItemsSourceView.CollectionChanged += ItemsSourceView_CollectionChanged;
}

private void BreadcrumbBar_GettingFocus(UIElement sender, GettingFocusEventArgs args)
{
_focusedViaKeyboard = args.InputDevice is FocusInputDeviceKind.Keyboard;
}

internal protected virtual void RaiseItemClickedEvent(BreadcrumbBarItem item)
{
var index = _itemsRepeater?.GetElementIndex(item) ?? throw new ArgumentNullException($"{_itemsRepeater} is null.");
Expand Down Expand Up @@ -121,11 +132,19 @@ internal bool TryGetElement(int index, out BreadcrumbBarItem? item)

// Event methods

private void BreadcrumbBar_GotFocus(object sender, RoutedEventArgs e)
{
_rootBreadcrumbBarItem?.Focus(FocusState.Keyboard);
}

private void ItemsRepeater_ElementPrepared(ItemsRepeater sender, ItemsRepeaterElementPreparedEventArgs args)
{
if (args.Element is not BreadcrumbBarItem item || _itemsRepeater is null)
return;

item.IsLastItem = false;
item.IsEllipsis = false;

if (args.Index == _itemsRepeater.ItemsSourceView.Count - 1)
{
_lastBreadcrumbBarItem = item;
Expand All @@ -148,5 +167,14 @@ private void ItemsSourceView_CollectionChanged(object? sender, System.Collection
item.IsLastItem = true;
}
}

private void ItemsRepeater_ElementClearing(ItemsRepeater sender, ItemsRepeaterElementClearingEventArgs args)
{
if (args.Element is BreadcrumbBarItem item)
{
item.IsLastItem = false;
item.IsEllipsis = false;
}
}
}
}
3 changes: 2 additions & 1 deletion src/Files.App.Controls/BreadcrumbBar/BreadcrumbBar.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
Grid.Column="0"
Padding="{StaticResource BreadcrumbBarRootItemPadding}"
CornerRadius="{StaticResource BreadcrumbBarRootItemCornerRadius}"
ItemToolTip="{TemplateBinding RootItemToolTip}">
ItemToolTip="{TemplateBinding RootItemToolTip}"
TabIndex="0">
<ContentPresenter Content="{Binding RootItem, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" />
</local:BreadcrumbBarItem>

Expand Down
5 changes: 5 additions & 0 deletions src/Files.App.Controls/Omnibar/Omnibar.Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ private void AutoSuggestBox_LosingFocus(UIElement sender, LosingFocusEventArgs a
args.TryCancel();
return;
}

if (args.InputDevice is FocusInputDeviceKind.Keyboard || args.Direction is FocusNavigationDirection.Next or FocusNavigationDirection.Previous)
{
CurrentSelectedMode?.ContentOnInactive?.Focus(FocusState.Programmatic);
}
}

private void AutoSuggestBox_GotFocus(object sender, RoutedEventArgs e)
Expand Down
2 changes: 0 additions & 2 deletions src/Files.App.Controls/Omnibar/Omnibar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ protected void ChangeMode(OmnibarMode? oldMode, OmnibarMode newMode)
// Add the reposition transition to the all modes
mode.Transitions = [new RepositionThemeTransition()];
mode.UpdateLayout();
mode.IsTabStop = true;
}

var index = _modesHostGrid.Children.IndexOf(newMode);
Expand Down Expand Up @@ -154,7 +153,6 @@ protected void ChangeMode(OmnibarMode? oldMode, OmnibarMode newMode)
ChangeTextBoxText(newMode.Text ?? string.Empty);

VisualStateManager.GoToState(newMode, "Focused", true);
newMode.IsTabStop = false;

ModeChanged?.Invoke(this, new(oldMode, newMode!));

Expand Down
4 changes: 2 additions & 2 deletions src/Files.App.Controls/Omnibar/Omnibar.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Stretch" />

<Setter Property="IsTabStop" Value="True" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<!--<Setter Property="IsTabStop" Value="True" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />-->

<Setter Property="Template">
<Setter.Value>
Expand Down
11 changes: 11 additions & 0 deletions src/Files.App.Controls/Omnibar/OmnibarMode.Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ namespace Files.App.Controls
{
public partial class OmnibarMode
{
private void ModeButton_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (_ownerRef is null || _ownerRef.TryGetTarget(out var owner) is false || owner.CurrentSelectedMode == this)
return;

if (e.Key is Windows.System.VirtualKey.Enter)
{
owner.CurrentSelectedMode = this;
}
}

private void ModeButton_PointerEntered(object sender, PointerRoutedEventArgs e)
{
if (_ownerRef is null || _ownerRef.TryGetTarget(out var owner) is false || owner.CurrentSelectedMode == this)
Expand Down
1 change: 1 addition & 0 deletions src/Files.App.Controls/Omnibar/OmnibarMode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ protected override void OnApplyTemplate()
?? throw new MissingFieldException($"Could not find {TemplatePartName_ModeButton} in the given {nameof(OmnibarMode)}'s style.");

Loaded += OmnibarMode_Loaded;
_modeButton.KeyDown += ModeButton_KeyDown;
_modeButton.PointerEntered += ModeButton_PointerEntered;
_modeButton.PointerPressed += ModeButton_PointerPressed;
_modeButton.PointerReleased += ModeButton_PointerReleased;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ public bool IsOmnibarFocused
_ = PopulateOmnibarSuggestionsForPathMode();
break;
case OmnibarPaletteModeName:
PopulateOmnibarSuggestionsForCommandPaletteMode();
if (OmnibarCommandPaletteModeSuggestionItems.Count is 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will cause the command list to display unavailable commands.

PopulateOmnibarSuggestionsForCommandPaletteMode();
break;
case OmnibarSearchModeName:
break;
Expand Down Expand Up @@ -282,7 +283,8 @@ public string OmnibarCurrentSelectedModeName
_ = PopulateOmnibarSuggestionsForPathMode();
break;
case OmnibarPaletteModeName:
PopulateOmnibarSuggestionsForCommandPaletteMode();
if (OmnibarCommandPaletteModeSuggestionItems.Count is 0)
PopulateOmnibarSuggestionsForCommandPaletteMode();
break;
case OmnibarSearchModeName:
break;
Expand Down Expand Up @@ -1100,8 +1102,6 @@ private static async Task<bool> LaunchApplicationFromPath(string currentInput, s

public async Task PopulateOmnibarSuggestionsForPathMode()
{
PathModeSuggestionItems.Clear();

var result = await SafetyExtensions.IgnoreExceptions((Func<Task<bool>>)(async () =>
{
List<OmnibarPathModeSuggestionModel>? newSuggestions = [];
Expand Down
Loading