Skip to content

Commit c26f472

Browse files
authored
Code Quality: Improved Omnibar 4 (#17189)
1 parent 1fd43bc commit c26f472

File tree

11 files changed

+95
-46
lines changed

11 files changed

+95
-46
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ public record class OmnibarQuerySubmittedEventArgs(OmnibarMode Mode, object? Ite
88
public record class OmnibarSuggestionChosenEventArgs(OmnibarMode Mode, object SelectedItem);
99

1010
public record class OmnibarTextChangedEventArgs(OmnibarMode Mode, OmnibarTextChangeReason Reason);
11+
12+
public record class OmnibarModeChangedEventArgs(OmnibarMode? OldMode, OmnibarMode NewMode);
1113
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
namespace Files.App.Controls
55
{
66
/// <summary>
7-
/// An interface that provides a way to get the text member path of <see cref="OmnibarMode.SuggestionItemsSource"/>.
7+
/// An interface that provides a way to get the text member path of <see cref="OmnibarMode.ItemsSource"/>.
88
/// </summary>
99
/// <remarks>
1010
/// An alternative to this interface is to use an <see cref="Microsoft.UI.Xaml.Data.IBindableCustomPropertyImplementation"/> powered by CsWinRT.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ partial void OnCurrentSelectedModePropertyChanged(DependencyPropertyChangedEvent
2828
return;
2929

3030
ChangeMode(e.OldValue as OmnibarMode, newMode);
31-
CurrentSelectedModeName = newMode.ModeName;
31+
CurrentSelectedModeName = newMode.Name;
3232
}
3333

3434
partial void OnCurrentSelectedModeNameChanged(string? newValue)

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public partial class Omnibar : Control
4141
public event TypedEventHandler<Omnibar, OmnibarQuerySubmittedEventArgs>? QuerySubmitted;
4242
public event TypedEventHandler<Omnibar, OmnibarSuggestionChosenEventArgs>? SuggestionChosen;
4343
public event TypedEventHandler<Omnibar, OmnibarTextChangedEventArgs>? TextChanged;
44+
public event TypedEventHandler<Omnibar, OmnibarModeChangedEventArgs>? ModeChanged;
4445

4546
// Constructor
4647

@@ -155,9 +156,11 @@ protected void ChangeMode(OmnibarMode? oldMode, OmnibarMode newMode)
155156
VisualStateManager.GoToState(newMode, "Focused", true);
156157
newMode.IsTabStop = false;
157158

159+
ModeChanged?.Invoke(this, new(oldMode, newMode!));
160+
158161
_textBox.PlaceholderText = newMode.PlaceholderText ?? string.Empty;
159-
_textBoxSuggestionsListView.ItemTemplate = newMode.SuggestionItemTemplate;
160-
_textBoxSuggestionsListView.ItemsSource = newMode.SuggestionItemsSource;
162+
_textBoxSuggestionsListView.ItemTemplate = newMode.ItemTemplate;
163+
_textBoxSuggestionsListView.ItemsSource = newMode.ItemsSource;
161164

162165
if (newMode.IsAutoFocusEnabled)
163166
{
@@ -179,10 +182,10 @@ protected void ChangeMode(OmnibarMode? oldMode, OmnibarMode newMode)
179182
{
180183
VisualStateManager.GoToState(_textBox, "InputAreaVisible", true);
181184
}
182-
183-
TryToggleIsSuggestionsPopupOpen(true);
184185
}
185186

187+
TryToggleIsSuggestionsPopupOpen(true);
188+
186189
// Remove the reposition transition from the all modes
187190
foreach (var mode in Modes)
188191
{
@@ -196,12 +199,17 @@ internal protected void FocusTextBox()
196199
_textBox.Focus(FocusState.Keyboard);
197200
}
198201

199-
public bool TryToggleIsSuggestionsPopupOpen(bool wantToOpen)
202+
internal protected bool TryToggleIsSuggestionsPopupOpen(bool wantToOpen)
200203
{
201-
if (wantToOpen && (!IsFocused || CurrentSelectedMode?.SuggestionItemsSource is null || (CurrentSelectedMode?.SuggestionItemsSource is IList collection && collection.Count is 0)) ||
202-
_textBoxSuggestionsPopup is null)
204+
if (_textBoxSuggestionsPopup is null)
203205
return false;
204206

207+
if (wantToOpen && (!IsFocused || CurrentSelectedMode?.ItemsSource is null || (CurrentSelectedMode?.ItemsSource is IList collection && collection.Count is 0)))
208+
{
209+
_textBoxSuggestionsPopup.IsOpen = false;
210+
return false;
211+
}
212+
205213
_textBoxSuggestionsPopup.IsOpen = wantToOpen;
206214

207215
return false;

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

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,11 +145,21 @@
145145
<BrushTransition Duration="0:0:0.083" />
146146
</Border.BackgroundTransition>
147147

148-
<ContentPresenter
149-
x:Name="PART_ModeButtonIconPresenter"
150-
HorizontalAlignment="Center"
151-
VerticalAlignment="Center"
152-
Content="{Binding IconOnInactive, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" />
148+
<Grid>
149+
<ContentPresenter
150+
x:Name="PART_ModeButtonInactiveIconPresenter"
151+
HorizontalAlignment="Center"
152+
VerticalAlignment="Center"
153+
Content="{Binding IconOnInactive, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
154+
Visibility="Visible" />
155+
156+
<ContentPresenter
157+
x:Name="PART_ModeButtonActiveIconPresenter"
158+
HorizontalAlignment="Center"
159+
VerticalAlignment="Center"
160+
Content="{Binding IconOnActive, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
161+
Visibility="Collapsed" />
162+
</Grid>
153163
</Border>
154164

155165
<ContentPresenter
@@ -172,7 +182,8 @@
172182
<VisualState x:Name="PointerPressed">
173183
<VisualState.Setters>
174184
<Setter Target="PART_ModeButton.Background" Value="{ThemeResource SubtleFillColorTertiaryBrush}" />
175-
<Setter Target="PART_ModeButtonIconPresenter.Content" Value="{Binding IconOnActive, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" />
185+
<Setter Target="PART_ModeButtonInactiveIconPresenter.Visibility" Value="Collapsed" />
186+
<Setter Target="PART_ModeButtonActiveIconPresenter.Visibility" Value="Visible" />
176187
</VisualState.Setters>
177188
</VisualState>
178189
</VisualStateGroup>
@@ -181,13 +192,16 @@
181192
<VisualState x:Name="Unfocused" />
182193
<VisualState x:Name="CurrentUnfocused">
183194
<VisualState.Setters>
184-
<Setter Target="PART_ModeButtonIconPresenter.Visibility" Value="Collapsed" />
195+
<Setter Target="PART_ModeButtonInactiveIconPresenter.Visibility" Value="Collapsed" />
196+
<Setter Target="PART_ModeButtonActiveIconPresenter.Visibility" Value="Collapsed" />
197+
<Setter Target="PART_ModeButton.Visibility" Value="Collapsed" />
185198
<Setter Target="PART_InactiveContent.Visibility" Value="Visible" />
186199
</VisualState.Setters>
187200
</VisualState>
188201
<VisualState x:Name="Focused">
189202
<VisualState.Setters>
190-
<Setter Target="PART_ModeButtonIconPresenter.Content" Value="{Binding IconOnActive, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}" />
203+
<Setter Target="PART_ModeButtonInactiveIconPresenter.Visibility" Value="Collapsed" />
204+
<Setter Target="PART_ModeButtonActiveIconPresenter.Visibility" Value="Visible" />
191205
</VisualState.Setters>
192206
</VisualState>
193207
</VisualStateGroup>

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,9 @@ public partial class OmnibarMode
2828
[GeneratedDependencyProperty]
2929
public partial FrameworkElement? IconOnInactive { get; set; }
3030

31-
[GeneratedDependencyProperty]
32-
public partial object? SuggestionItemsSource { get; set; }
33-
34-
[GeneratedDependencyProperty]
35-
public partial DataTemplate? SuggestionItemTemplate { get; set; }
36-
3731
[GeneratedDependencyProperty]
3832
/// <remark>
39-
/// Implement <see cref="IOmnibarTextMemberPathProvider"/> in <see cref="SuggestionItemsSource"/> to get the text member path from the suggestion item correctly.
33+
/// Implement <see cref="IOmnibarTextMemberPathProvider"/> in <see cref="ItemsSource"/> to get the text member path from the suggestion item correctly.
4034
/// </remark>
4135
public partial string? TextMemberPath { get; set; }
4236

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
namespace Files.App.Controls
77
{
88
[DebuggerDisplay("{" + nameof(ToString) + "(),nq}")]
9-
public partial class OmnibarMode : Control
9+
public partial class OmnibarMode : ItemsControl
1010
{
1111
// Constants
1212

@@ -66,6 +66,14 @@ protected override void OnKeyUp(KeyRoutedEventArgs args)
6666
}
6767
}
6868

69+
protected override void OnItemsChanged(object e)
70+
{
71+
base.OnItemsChanged(e);
72+
73+
if (_ownerRef is not null && _ownerRef.TryGetTarget(out var owner))
74+
owner.TryToggleIsSuggestionsPopupOpen(true);
75+
}
76+
6977
private void OmnibarMode_Loaded(object sender, RoutedEventArgs e)
7078
{
7179
// Set this mode as the current mode if it is the default mode

src/Files.App/UserControls/NavigationToolbar.xaml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,6 @@
349349
x:Name="Omnibar"
350350
Grid.Column="1"
351351
x:Load="{x:Bind ViewModel.EnableOmnibar, Mode=OneWay}"
352-
CurrentSelectedMode="{x:Bind ViewModel.OmnibarCurrentSelectedMode, Mode=TwoWay}"
353352
CurrentSelectedModeName="{x:Bind ViewModel.OmnibarCurrentSelectedModeName, Mode=TwoWay}"
354353
IsFocused="{x:Bind ViewModel.IsOmnibarFocused, Mode=TwoWay}"
355354
LostFocus="Omnibar_LostFocus"
@@ -362,9 +361,9 @@
362361
IconOnActive="{controls:ThemedIconMarkup Style={StaticResource App.ThemedIcons.Omnibar.Path}, IsFilled=True}"
363362
IconOnInactive="{controls:ThemedIconMarkup Style={StaticResource App.ThemedIcons.Omnibar.Path}, IconType=Outline}"
364363
IsDefault="True"
364+
ItemsSource="{x:Bind ViewModel.PathModeSuggestionItems, Mode=OneWay}"
365365
ModeName="{x:Bind Commands.EditPath.LabelWithHotKey, Mode=OneWay}"
366366
PlaceholderText="{helpers:ResourceString Name=OmnibarPathModeTextPlaceholder}"
367-
SuggestionItemsSource="{x:Bind ViewModel.PathModeSuggestionItems, Mode=OneWay}"
368367
Text="{x:Bind ViewModel.PathText, Mode=TwoWay}"
369368
TextMemberPath="Path">
370369
<controls:OmnibarMode.ContentOnInactive>
@@ -393,25 +392,25 @@
393392
</controls:BreadcrumbBar.ItemTemplate>
394393
</controls:BreadcrumbBar>
395394
</controls:OmnibarMode.ContentOnInactive>
396-
<controls:OmnibarMode.SuggestionItemTemplate>
395+
<controls:OmnibarMode.ItemTemplate>
397396
<DataTemplate x:DataType="datamodels:OmnibarPathModeSuggestionModel">
398397
<TextBlock Text="{x:Bind DisplayName, Mode=OneWay}" />
399398
</DataTemplate>
400-
</controls:OmnibarMode.SuggestionItemTemplate>
399+
</controls:OmnibarMode.ItemTemplate>
401400
</controls:OmnibarMode>
402401

403402
<controls:OmnibarMode
404403
x:Name="OmnibarCommandPaletteMode"
405404
IconOnActive="{controls:ThemedIconMarkup Style={StaticResource App.ThemedIcons.Omnibar.Commands}, IsFilled=True}"
406405
IconOnInactive="{controls:ThemedIconMarkup Style={StaticResource App.ThemedIcons.Omnibar.Commands}, IconType=Outline}"
407406
IsAutoFocusEnabled="True"
407+
ItemsSource="{x:Bind ViewModel.OmnibarCommandPaletteModeSuggestionItems, Mode=OneWay}"
408408
ModeName="{x:Bind Commands.OpenCommandPalette.LabelWithHotKey, Mode=OneWay}"
409409
PlaceholderText="{helpers:ResourceString Name=OmnibarCommandPaletteModeTextPlaceholder}"
410-
SuggestionItemsSource="{x:Bind ViewModel.OmnibarCommandPaletteModeSuggestionItems, Mode=OneWay}"
411410
Text="{x:Bind ViewModel.OmnibarCommandPaletteModeText, Mode=TwoWay}"
412411
TextMemberPath="Text"
413412
UpdateTextOnSelect="False">
414-
<controls:OmnibarMode.SuggestionItemTemplate>
413+
<controls:OmnibarMode.ItemTemplate>
415414
<DataTemplate x:DataType="dataitems:NavigationBarSuggestionItem">
416415
<Grid ColumnSpacing="12">
417416
<Grid.ColumnDefinitions>
@@ -450,7 +449,7 @@
450449
HotKeys="{x:Bind HotKeys}" />
451450
</Grid>
452451
</DataTemplate>
453-
</controls:OmnibarMode.SuggestionItemTemplate>
452+
</controls:OmnibarMode.ItemTemplate>
454453
</controls:OmnibarMode>
455454

456455
<controls:OmnibarMode

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public sealed partial class NavigationToolbar : UserControl
2323
private readonly MainPageViewModel MainPageViewModel = Ioc.Default.GetRequiredService<MainPageViewModel>();
2424
private readonly ICommandManager Commands = Ioc.Default.GetRequiredService<ICommandManager>();
2525
private readonly StatusCenterViewModel OngoingTasksViewModel = Ioc.Default.GetRequiredService<StatusCenterViewModel>();
26+
private readonly IContentPageContext ContentPageContext = Ioc.Default.GetRequiredService<IContentPageContext>();
2627

2728
// Properties
2829

@@ -413,9 +414,9 @@ private void BreadcrumbBar_ItemDropDownFlyoutClosed(object sender, BreadcrumbBar
413414

414415
private void Omnibar_LostFocus(object sender, RoutedEventArgs e)
415416
{
416-
if (ViewModel.OmnibarCurrentSelectedMode == OmnibarCommandPaletteMode)
417+
if (Omnibar.CurrentSelectedMode == OmnibarCommandPaletteMode)
417418
{
418-
ViewModel.OmnibarCurrentSelectedMode = OmnibarPathMode;
419+
Omnibar.CurrentSelectedMode = OmnibarPathMode;
419420
ViewModel.OmnibarCommandPaletteModeText = string.Empty;
420421
}
421422
}

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

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using CommunityToolkit.WinUI;
55
using Files.App.Controls;
66
using Files.Shared.Helpers;
7+
using Microsoft.Extensions.Logging;
78
using Microsoft.UI.Dispatching;
89
using Microsoft.UI.Xaml;
910
using Microsoft.UI.Xaml.Controls;
@@ -242,7 +243,7 @@ public bool IsOmnibarFocused
242243

243244
if (value)
244245
{
245-
switch (OmnibarCurrentSelectedMode.Name)
246+
switch (OmnibarCurrentSelectedModeName)
246247
{
247248
case OmnibarPathModeName:
248249
PathText =
@@ -263,11 +264,34 @@ public bool IsOmnibarFocused
263264
}
264265
}
265266

266-
private OmnibarMode _OmnibarCurrentSelectedMode;
267-
public OmnibarMode OmnibarCurrentSelectedMode { get => _OmnibarCurrentSelectedMode; set => SetProperty(ref _OmnibarCurrentSelectedMode, value); }
268-
269-
private string _OmnibarCurrentSelectedModeName;
270-
public string OmnibarCurrentSelectedModeName { get => _OmnibarCurrentSelectedModeName; set => SetProperty(ref _OmnibarCurrentSelectedModeName, value); }
267+
private string _OmnibarCurrentSelectedModeName = OmnibarPathModeName;
268+
public string OmnibarCurrentSelectedModeName
269+
{
270+
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+
}
294+
}
271295

272296
private CurrentInstanceViewModel _InstanceViewModel;
273297
public CurrentInstanceViewModel InstanceViewModel
@@ -738,7 +762,6 @@ await DialogDisplayHelper.ShowDialogAsync(Strings.InvalidItemDialogTitle.GetLoca
738762
}
739763

740764
PathControlDisplayText = ContentPageContext.ShellPage.ShellViewModel.WorkingDirectory;
741-
IsOmnibarFocused = false;
742765
}
743766

744767
public void PathBoxItem_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
@@ -1077,6 +1100,8 @@ private static async Task<bool> LaunchApplicationFromPath(string currentInput, s
10771100

10781101
public async Task PopulateOmnibarSuggestionsForPathMode()
10791102
{
1103+
PathModeSuggestionItems.Clear();
1104+
10801105
var result = await SafetyExtensions.IgnoreExceptions((Func<Task<bool>>)(async () =>
10811106
{
10821107
List<OmnibarPathModeSuggestionModel>? newSuggestions = [];
@@ -1117,9 +1142,7 @@ public async Task PopulateOmnibarSuggestionsForPathMode()
11171142

11181143
// If there are no suggestions, show "No suggestions"
11191144
if (newSuggestions.Count is 0)
1120-
{
1121-
AddNoResultsItem();
1122-
}
1145+
return false;
11231146

11241147
// Check whether at least one item is in common between the old and the new suggestions
11251148
// since the suggestions popup becoming empty causes flickering

0 commit comments

Comments
 (0)