Skip to content

Commit fe52157

Browse files
authored
Code Quality: Improved Omnibar 14 (#17248)
1 parent 3a34707 commit fe52157

File tree

7 files changed

+134
-96
lines changed

7 files changed

+134
-96
lines changed

src/Files.App.Controls/Omnibar/EventArgs.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ public record class OmnibarSuggestionChosenEventArgs(OmnibarMode Mode, object Se
1010
public record class OmnibarTextChangedEventArgs(OmnibarMode Mode, OmnibarTextChangeReason Reason);
1111

1212
public record class OmnibarModeChangedEventArgs(OmnibarMode? OldMode, OmnibarMode NewMode);
13+
14+
public record class OmnibarIsFocusedChangedEventArgs(bool IsFocused);
1315
}

src/Files.App.Controls/Omnibar/Omnibar.Events.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ private void AutoSuggestBox_GotFocus(object sender, RoutedEventArgs e)
4040
GlobalHelper.WriteDebugStringForOmnibar("The TextBox got the focus.");
4141

4242
IsFocused = true;
43+
IsFocusedChanged?.Invoke(this, new(IsFocused));
44+
4345
_textBox.SelectAll();
4446
}
4547

@@ -53,6 +55,7 @@ private void AutoSuggestBox_LostFocus(object sender, RoutedEventArgs e)
5355
GlobalHelper.WriteDebugStringForOmnibar("The TextBox lost the focus.");
5456

5557
IsFocused = false;
58+
IsFocusedChanged?.Invoke(this, new(IsFocused));
5659

5760
// Reset to the default mode when Omnibar loses focus
5861
CurrentSelectedMode = Modes?.FirstOrDefault();

src/Files.App.Controls/Omnibar/Omnibar.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public partial class Omnibar : Control
3838
public event TypedEventHandler<Omnibar, OmnibarSuggestionChosenEventArgs>? SuggestionChosen;
3939
public event TypedEventHandler<Omnibar, OmnibarTextChangedEventArgs>? TextChanged;
4040
public event TypedEventHandler<Omnibar, OmnibarModeChangedEventArgs>? ModeChanged;
41+
public event TypedEventHandler<Omnibar, OmnibarIsFocusedChangedEventArgs> IsFocusedChanged;
4142

4243
// Constructor
4344

src/Files.App.Controls/Omnibar/Omnibar.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
Width="{StaticResource OmnibarModeDefaultClickAreaWidth}"
132132
Height="{StaticResource OmnibarModeDefaultHeight}"
133133
Margin="1"
134+
VerticalAlignment="Stretch"
134135
Background="{TemplateBinding Background}"
135136
BorderBrush="{TemplateBinding BorderBrush}"
136137
BorderThickness="0"

src/Files.App/UserControls/NavigationToolbar.xaml

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@
350350
Grid.Column="1"
351351
x:Load="{x:Bind ViewModel.EnableOmnibar, Mode=OneWay}"
352352
CurrentSelectedModeName="{x:Bind ViewModel.OmnibarCurrentSelectedModeName, Mode=TwoWay}"
353-
IsFocused="{x:Bind ViewModel.IsOmnibarFocused, Mode=TwoWay}"
353+
IsFocusedChanged="Omnibar_IsFocusedChanged"
354354
ModeChanged="Omnibar_ModeChanged"
355355
PreviewKeyDown="Omnibar_PreviewKeyDown"
356356
QuerySubmitted="Omnibar_QuerySubmitted"
@@ -417,9 +417,9 @@
417417
UpdateTextOnSelect="False">
418418
<controls:OmnibarMode.ItemTemplate>
419419
<DataTemplate x:DataType="dataitems:NavigationBarSuggestionItem">
420-
<Grid ColumnSpacing="12">
420+
<Grid Padding="0,0,4,0" ColumnSpacing="12">
421421
<Grid.ColumnDefinitions>
422-
<ColumnDefinition Width="16" />
422+
<ColumnDefinition Width="Auto" />
423423
<ColumnDefinition Width="*" />
424424
<ColumnDefinition Width="Auto" />
425425
</Grid.ColumnDefinitions>
@@ -463,8 +463,44 @@
463463
IconOnInactive="{controls:ThemedIconMarkup Style={StaticResource App.ThemedIcons.Omnibar.Search}, IconType=Outline}"
464464
IsAutoFocusEnabled="True"
465465
IsEnabled="False"
466+
ItemsSource="{x:Bind ViewModel.OmnibarSearchModeSuggestionItems, Mode=OneWay}"
466467
ModeName="{x:Bind Commands.Search.LabelWithHotKey, Mode=OneWay}"
467-
PlaceholderText="{helpers:ResourceString Name=OmnibarSearchModeTextPlaceholder}" />
468+
PlaceholderText="{helpers:ResourceString Name=OmnibarSearchModeTextPlaceholder}"
469+
Text="{x:Bind ViewModel.OmnibarSearchModeText, Mode=TwoWay}"
470+
UpdateTextOnSelect="False">
471+
<controls:OmnibarMode.ItemTemplate>
472+
<DataTemplate x:DataType="datamodels:SuggestionModel">
473+
<Grid ColumnSpacing="8" Tag="{x:Bind ItemPath}">
474+
<Grid.ColumnDefinitions>
475+
<ColumnDefinition Width="Auto" />
476+
<ColumnDefinition Width="*" />
477+
</Grid.ColumnDefinitions>
478+
<Grid
479+
Grid.Column="0"
480+
Width="16"
481+
Height="16"
482+
Tag="ItemImage">
483+
<Border x:Name="IconArea" x:Load="{x:Bind LoadFileIcon, Mode=OneWay}">
484+
<Image
485+
Width="16"
486+
Height="16"
487+
Source="{x:Bind FileImage, Mode=OneWay}"
488+
Stretch="Uniform" />
489+
</Border>
490+
<FontIcon
491+
x:Name="EmptyIconGlyph"
492+
x:Load="{x:Bind NeedsPlaceholderGlyph, Mode=OneWay}"
493+
FontSize="14"
494+
Glyph="{x:Bind IsRecentSearch, Mode=OneTime, Converter={StaticResource SearchSuggestionGlyphConverter}}" />
495+
</Grid>
496+
<TextBlock
497+
Grid.Column="1"
498+
VerticalAlignment="Center"
499+
Text="{x:Bind Name}" />
500+
</Grid>
501+
</DataTemplate>
502+
</controls:OmnibarMode.ItemTemplate>
503+
</controls:OmnibarMode>
468504

469505
</controls:Omnibar>
470506

src/Files.App/UserControls/NavigationToolbar.xaml.cs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -428,11 +428,66 @@ private void BreadcrumbBar_ItemDropDownFlyoutClosed(object sender, BreadcrumbBar
428428
e.Flyout.Items.Clear();
429429
}
430430

431-
private void Omnibar_ModeChanged(object sender, OmnibarModeChangedEventArgs e)
431+
private async void Omnibar_ModeChanged(object sender, OmnibarModeChangedEventArgs e)
432432
{
433-
// Reset the command palette text when switching modes
434-
if (Omnibar.CurrentSelectedMode == OmnibarCommandPaletteMode)
433+
if (e.NewMode == OmnibarPathMode)
434+
{
435+
ViewModel.PathText = string.IsNullOrEmpty(ContentPageContext.ShellPage?.ShellViewModel?.WorkingDirectory)
436+
? Constants.UserEnvironmentPaths.HomePath
437+
: ContentPageContext.ShellPage.ShellViewModel.WorkingDirectory;
438+
439+
await DispatcherQueue.EnqueueOrInvokeAsync(async () =>
440+
{
441+
await ViewModel.PopulateOmnibarSuggestionsForPathMode();
442+
});
443+
}
444+
else if (e.NewMode == OmnibarCommandPaletteMode)
445+
{
435446
ViewModel.OmnibarCommandPaletteModeText = string.Empty;
447+
448+
await DispatcherQueue.EnqueueOrInvokeAsync(() =>
449+
{
450+
ViewModel.PopulateOmnibarSuggestionsForCommandPaletteMode();
451+
});
452+
}
453+
else if (e.NewMode == OmnibarSearchMode)
454+
{
455+
456+
}
457+
}
458+
459+
private async void Omnibar_IsFocusedChanged(Omnibar sender, OmnibarIsFocusedChangedEventArgs args)
460+
{
461+
if (args.IsFocused)
462+
{
463+
if (Omnibar.CurrentSelectedMode == OmnibarPathMode)
464+
{
465+
ViewModel.PathText = string.IsNullOrEmpty(ContentPageContext.ShellPage?.ShellViewModel?.WorkingDirectory)
466+
? Constants.UserEnvironmentPaths.HomePath
467+
: ContentPageContext.ShellPage.ShellViewModel.WorkingDirectory;
468+
469+
await DispatcherQueue.EnqueueOrInvokeAsync(async () =>
470+
{
471+
await ViewModel.PopulateOmnibarSuggestionsForPathMode();
472+
});
473+
}
474+
else if (Omnibar.CurrentSelectedMode == OmnibarCommandPaletteMode)
475+
{
476+
ViewModel.OmnibarCommandPaletteModeText = string.Empty;
477+
478+
if (ViewModel.OmnibarCommandPaletteModeSuggestionItems.Count is 0)
479+
{
480+
await DispatcherQueue.EnqueueOrInvokeAsync(() =>
481+
{
482+
ViewModel.PopulateOmnibarSuggestionsForCommandPaletteMode();
483+
});
484+
}
485+
}
486+
else if (Omnibar.CurrentSelectedMode == OmnibarSearchMode)
487+
{
488+
489+
}
490+
}
436491
}
437492

438493
private async void Omnibar_PreviewKeyDown(object sender, KeyRoutedEventArgs e)

src/Files.App/ViewModels/UserControls/NavigationToolbarViewModel.cs

Lines changed: 29 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ public sealed partial class NavigationToolbarViewModel : ObservableObject, IAddr
7878

7979
internal ObservableCollection<NavigationBarSuggestionItem> OmnibarCommandPaletteModeSuggestionItems { get; } = [];
8080

81+
internal ObservableCollection<SuggestionModel> OmnibarSearchModeSuggestionItems { get; } = [];
82+
8183
public bool IsSingleItemOverride { get; set; }
8284

8385
public bool SearchHasFocus { get; private set; }
@@ -231,66 +233,14 @@ public string? PathText
231233
private string? _OmnibarCommandPaletteModeText;
232234
public string? OmnibarCommandPaletteModeText { get => _OmnibarCommandPaletteModeText; set => SetProperty(ref _OmnibarCommandPaletteModeText, value); }
233235

234-
private bool _IsOmnibarFocused;
235-
public bool IsOmnibarFocused
236-
{
237-
get => _IsOmnibarFocused;
238-
set
239-
{
240-
// NOTE: Don't call ObservableObject.SetProperty() here since we don't want to change focus logic outside of the control.
241-
242-
_IsOmnibarFocused = value;
243-
244-
if (value)
245-
{
246-
switch (OmnibarCurrentSelectedModeName)
247-
{
248-
case OmnibarPathModeName:
249-
PathText =
250-
string.IsNullOrEmpty(ContentPageContext.ShellPage?.ShellViewModel?.WorkingDirectory)
251-
? Constants.UserEnvironmentPaths.HomePath
252-
: ContentPageContext.ShellPage.ShellViewModel.WorkingDirectory;
253-
_ = PopulateOmnibarSuggestionsForPathMode();
254-
break;
255-
case OmnibarPaletteModeName:
256-
PopulateOmnibarSuggestionsForCommandPaletteMode();
257-
break;
258-
case OmnibarSearchModeName:
259-
break;
260-
default:
261-
break;
262-
}
263-
}
264-
}
265-
}
236+
private string? _OmnibarSearchModeText;
237+
public string? OmnibarSearchModeText { get => _OmnibarSearchModeText; set => SetProperty(ref _OmnibarSearchModeText, value); }
266238

267239
private string _OmnibarCurrentSelectedModeName = OmnibarPathModeName;
268240
public string OmnibarCurrentSelectedModeName
269241
{
270242
get => _OmnibarCurrentSelectedModeName;
271-
set
272-
{
273-
if (SetProperty(ref _OmnibarCurrentSelectedModeName, value) && IsOmnibarFocused)
274-
{
275-
switch (value)
276-
{
277-
case OmnibarPathModeName:
278-
PathText =
279-
string.IsNullOrEmpty(ContentPageContext.ShellPage?.ShellViewModel?.WorkingDirectory)
280-
? Constants.UserEnvironmentPaths.HomePath
281-
: ContentPageContext.ShellPage.ShellViewModel.WorkingDirectory;
282-
_ = PopulateOmnibarSuggestionsForPathMode();
283-
break;
284-
case OmnibarPaletteModeName:
285-
PopulateOmnibarSuggestionsForCommandPaletteMode();
286-
break;
287-
case OmnibarSearchModeName:
288-
break;
289-
default:
290-
break;
291-
}
292-
}
293-
}
243+
set => SetProperty(ref _OmnibarCurrentSelectedModeName, value);
294244
}
295245

296246
private CurrentInstanceViewModel _InstanceViewModel;
@@ -1100,8 +1050,6 @@ private static async Task<bool> LaunchApplicationFromPath(string currentInput, s
11001050

11011051
public async Task PopulateOmnibarSuggestionsForPathMode()
11021052
{
1103-
PathModeSuggestionItems.Clear();
1104-
11051053
var result = await SafetyExtensions.IgnoreExceptions((Func<Task<bool>>)(async () =>
11061054
{
11071055
List<OmnibarPathModeSuggestionModel>? newSuggestions = [];
@@ -1200,49 +1148,41 @@ void AddNoResultsItem()
12001148

12011149
public void PopulateOmnibarSuggestionsForCommandPaletteMode()
12021150
{
1203-
OmnibarCommandPaletteModeText ??= string.Empty;
1204-
OmnibarCommandPaletteModeSuggestionItems.Clear();
1205-
12061151
if (ContentPageContext.SelectedItems.Count == 1 && ContentPageContext.SelectedItem is not null && !ContentPageContext.SelectedItem.IsFolder)
12071152
{
1208-
var dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
1209-
1210-
dispatcherQueue.TryEnqueue(() =>
1153+
try
12111154
{
1212-
try
1155+
var selectedItemPath = ContentPageContext.SelectedItem.ItemPath;
1156+
var fileActionEntity = ActionManager.Instance.EntityFactory.CreateFileEntity(selectedItemPath);
1157+
var actions = ActionManager.Instance.ActionRuntime.ActionCatalog.GetActionsForInputs(new[] { fileActionEntity });
1158+
1159+
foreach (var action in actions.Where(a => a.Definition.Description.Contains(OmnibarCommandPaletteModeText, StringComparison.OrdinalIgnoreCase)))
12131160
{
1214-
var selectedItemPath = ContentPageContext.SelectedItem.ItemPath;
1215-
var fileActionEntity = ActionManager.Instance.EntityFactory.CreateFileEntity(selectedItemPath);
1216-
var actions = ActionManager.Instance.ActionRuntime.ActionCatalog.GetActionsForInputs(new[] { fileActionEntity });
1161+
var newItem = new NavigationBarSuggestionItem
1162+
{
1163+
PrimaryDisplay = action.Definition.Description,
1164+
SearchText = OmnibarCommandPaletteModeText,
1165+
ActionInstance = action
1166+
};
12171167

1218-
foreach (var action in actions.Where(a => a.Definition.Description.Contains(OmnibarCommandPaletteModeText, StringComparison.OrdinalIgnoreCase)))
1168+
if (Uri.TryCreate(action.Definition.IconFullPath, UriKind.RelativeOrAbsolute, out Uri? validUri))
12191169
{
1220-
var newItem = new NavigationBarSuggestionItem
1170+
try
12211171
{
1222-
PrimaryDisplay = action.Definition.Description,
1223-
SearchText = OmnibarCommandPaletteModeText,
1224-
ActionInstance = action
1225-
};
1226-
1227-
if (Uri.TryCreate(action.Definition.IconFullPath, UriKind.RelativeOrAbsolute, out Uri? validUri))
1172+
newItem.ActionIconSource = new BitmapImage(validUri);
1173+
}
1174+
catch (Exception)
12281175
{
1229-
try
1230-
{
1231-
newItem.ActionIconSource = new BitmapImage(validUri);
1232-
}
1233-
catch (Exception)
1234-
{
1235-
}
12361176
}
1237-
1238-
OmnibarCommandPaletteModeSuggestionItems.Add(newItem);
12391177
}
1178+
1179+
OmnibarCommandPaletteModeSuggestionItems.Add(newItem);
12401180
}
1241-
catch (Exception ex)
1242-
{
1243-
App.Logger.LogWarning(ex, ex.Message);
1244-
}
1245-
});
1181+
}
1182+
catch (Exception ex)
1183+
{
1184+
App.Logger.LogWarning(ex, ex.Message);
1185+
}
12461186
}
12471187

12481188
var suggestionItems = Commands

0 commit comments

Comments
 (0)