Skip to content

Commit fa4939d

Browse files
authored
Feature: Improved performance when opening path bar flyouts (#16665)
1 parent 6573831 commit fa4939d

File tree

10 files changed

+66
-38
lines changed

10 files changed

+66
-38
lines changed
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7219ea9bd5832c77f1d6c8e57f97e6504a33f07bdef61122a171061f0dcb3509
1+
cc957911eb0abac03d457a70f1c6ff03eeabd0d05548806ff801998d7218b48d

src/Files.App/Data/EventArguments/ToolbarFlyoutOpenedEventArgs.cs

-14
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) Files Community
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.UI.Xaml.Controls;
5+
6+
namespace Files.App.Data.EventArguments
7+
{
8+
public sealed class ToolbarFlyoutOpeningEventArgs
9+
{
10+
public MenuFlyout OpeningFlyout { get; }
11+
12+
public ToolbarFlyoutOpeningEventArgs(MenuFlyout openingFlyout)
13+
{
14+
OpeningFlyout = openingFlyout;
15+
}
16+
}
17+
}

src/Files.App/UserControls/AddressToolbar.xaml

+2
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@
277277
<Button.ContextFlyout>
278278
<MenuFlyout
279279
x:Name="BackHistoryFlyout"
280+
AreOpenCloseAnimationsEnabled="False"
280281
Opening="BackHistoryFlyout_Opening"
281282
Placement="BottomEdgeAlignedLeft"
282283
ScrollViewer.VerticalScrollBarVisibility="Auto"
@@ -306,6 +307,7 @@
306307
<Button.ContextFlyout>
307308
<MenuFlyout
308309
x:Name="ForwardHistoryFlyout"
310+
AreOpenCloseAnimationsEnabled="False"
309311
Opening="ForwardHistoryFlyout_Opening"
310312
Placement="BottomEdgeAlignedLeft"
311313
ScrollViewer.VerticalScrollBarVisibility="Auto"

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

+20-8
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
// Copyright (c) Files Community
22
// Licensed under the MIT License.
33

4-
using System.Windows.Input;
54
using Microsoft.UI.Input;
65
using Microsoft.UI.Xaml;
76
using Microsoft.UI.Xaml.Controls;
87
using Microsoft.UI.Xaml.Controls.Primitives;
98
using Microsoft.UI.Xaml.Input;
109
using Microsoft.UI.Xaml.Media;
11-
using Windows.System;
1210
using Microsoft.UI.Xaml.Navigation;
11+
using System.Windows.Input;
12+
using Windows.System;
1313
using FocusManager = Microsoft.UI.Xaml.Input.FocusManager;
1414

1515
namespace Files.App.UserControls
@@ -161,37 +161,49 @@ private async void ForwardHistoryFlyout_Opening(object? sender, object e)
161161
await AddHistoryItemsAsync(shellPage.ForwardStack, ForwardHistoryFlyout.Items, false);
162162
}
163163

164-
private async Task AddHistoryItemsAsync(IEnumerable<PageStackEntry> items, IList<MenuFlyoutItemBase> destination, bool isBackMode)
164+
private async Task AddHistoryItemsAsync(IEnumerable<PageStackEntry> items, IList<MenuFlyoutItemBase> flyoutItems, bool isBackMode)
165165
{
166166
// This may not seem performant, however it's the most viable trade-off to make.
167167
// Instead of constantly keeping track of back/forward stack and performing lookups
168168
// (which may degrade performance), we only add items in bulk when it's needed.
169169
// There's also a high chance the user might not use the feature at all in which case
170170
// the former approach would just waste extra performance gain
171171

172-
destination.Clear();
172+
flyoutItems.Clear();
173173
foreach (var item in items.Reverse())
174174
{
175175
if (item.Parameter is not NavigationArguments args || args.NavPathParam is null)
176176
continue;
177177

178-
var imageSource = await NavigationHelpers.GetIconForPathAsync(args.NavPathParam);
179178
var fileName = SystemIO.Path.GetFileName(args.NavPathParam);
180179

181180
// The fileName is empty if the path is (root) drive path
182181
if (string.IsNullOrEmpty(fileName))
183182
fileName = args.NavPathParam;
184183

185-
destination.Add(new MenuFlyoutItem()
184+
var flyoutItem = new MenuFlyoutItem
186185
{
187-
Icon = new ImageIcon() { Source = imageSource },
186+
Icon = new FontIcon { Glyph = "\uE8B7" }, // Use font icon as placeholder
188187
Text = fileName,
189188
Command = historyItemClickedCommand,
190189
CommandParameter = new ToolbarHistoryItemModel(item, isBackMode)
191-
});
190+
};
191+
192+
flyoutItems?.Add(flyoutItem);
193+
194+
// Start loading the thumbnail in the background
195+
_ = LoadFlyoutItemIconAsync(flyoutItem, args.NavPathParam);
192196
}
193197
}
194198

199+
private async Task LoadFlyoutItemIconAsync(MenuFlyoutItem flyoutItem, string path)
200+
{
201+
var imageSource = await NavigationHelpers.GetIconForPathAsync(path);
202+
203+
if (imageSource is not null)
204+
flyoutItem.Icon = new ImageIcon { Source = imageSource };
205+
}
206+
195207
private void HistoryItemClicked(ToolbarHistoryItemModel? itemModel)
196208
{
197209
if (itemModel is null)

src/Files.App/UserControls/PathBreadcrumb.xaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@
9494
<Button.Flyout>
9595
<MenuFlyout
9696
x:Name="ExpandMenuFlyout"
97+
AreOpenCloseAnimationsEnabled="False"
9798
Closed="PathBoxItemFlyout_Closed"
98-
Opened="PathBoxItemFlyout_Opened"
99+
Opening="PathBoxItemFlyout_Opening"
99100
Placement="BottomEdgeAlignedLeft"
100101
ScrollViewer.VerticalScrollBarVisibility="Auto"
101102
ScrollViewer.VerticalScrollMode="Auto">

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ private void PathItemSeparator_DataContextChanged(FrameworkElement sender, DataC
2020
ViewModel.PathItemSeparator_DataContextChanged(sender, args);
2121
}
2222

23-
private void PathBoxItemFlyout_Opened(object sender, object e)
23+
private void PathBoxItemFlyout_Opening(object sender, object e)
2424
{
25-
ViewModel.PathboxItemFlyout_Opened(sender, e);
25+
ViewModel.PathboxItemFlyout_Opening(sender, e);
2626
}
2727

2828
private void PathBoxItemFlyout_Closed(object sender, object e)

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

+17-7
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public sealed class AddressToolbarViewModel : ObservableObject, IAddressToolbarV
3333

3434
public delegate void ToolbarPathItemInvokedEventHandler(object sender, PathNavigationEventArgs e);
3535

36-
public delegate void ToolbarFlyoutOpenedEventHandler(object sender, ToolbarFlyoutOpenedEventArgs e);
36+
public delegate void ToolbarFlyoutOpeningEventHandler(object sender, ToolbarFlyoutOpeningEventArgs e);
3737

3838
public delegate void ToolbarPathItemLoadedEventHandler(object sender, ToolbarPathItemLoadedEventArgs e);
3939

@@ -43,7 +43,7 @@ public sealed class AddressToolbarViewModel : ObservableObject, IAddressToolbarV
4343

4444
public event ToolbarPathItemInvokedEventHandler? ToolbarPathItemInvoked;
4545

46-
public event ToolbarFlyoutOpenedEventHandler? ToolbarFlyoutOpened;
46+
public event ToolbarFlyoutOpeningEventHandler? ToolbarFlyoutOpening;
4747

4848
public event ToolbarPathItemLoadedEventHandler? ToolbarPathItemLoaded;
4949

@@ -456,9 +456,9 @@ public void PathItemSeparator_DataContextChanged(FrameworkElement sender, DataCo
456456
});
457457
}
458458

459-
public void PathboxItemFlyout_Opened(object sender, object e)
459+
public void PathboxItemFlyout_Opening(object sender, object e)
460460
{
461-
ToolbarFlyoutOpened?.Invoke(this, new ToolbarFlyoutOpenedEventArgs() { OpenedFlyout = (MenuFlyout)sender });
461+
ToolbarFlyoutOpening?.Invoke(this, new ToolbarFlyoutOpeningEventArgs((MenuFlyout)sender));
462462
}
463463

464464
public void PathBoxItemFlyout_Closed(object sender, object e)
@@ -651,11 +651,9 @@ public async Task SetPathBoxDropDownFlyoutAsync(MenuFlyout flyout, PathBoxItem p
651651

652652
foreach (var childFolder in childFolders)
653653
{
654-
var imageSource = await NavigationHelpers.GetIconForPathAsync(childFolder.Path);
655-
656654
var flyoutItem = new MenuFlyoutItem
657655
{
658-
Icon = new ImageIcon() { Source = imageSource },
656+
Icon = new FontIcon { Glyph = "\uE8B7" }, // Use font icon as placeholder
659657
Text = childFolder.Item.Name,
660658
FontSize = 12,
661659
};
@@ -670,9 +668,21 @@ public async Task SetPathBoxDropDownFlyoutAsync(MenuFlyout flyout, PathBoxItem p
670668
}
671669

672670
flyout.Items?.Add(flyoutItem);
671+
672+
// Start loading the thumbnail in the background
673+
_ = LoadFlyoutItemIconAsync(flyoutItem, childFolder.Path);
673674
}
674675
}
675676

677+
private async Task LoadFlyoutItemIconAsync(MenuFlyoutItem flyoutItem, string path)
678+
{
679+
var imageSource = await NavigationHelpers.GetIconForPathAsync(path);
680+
681+
if (imageSource is not null)
682+
flyoutItem.Icon = new ImageIcon { Source = imageSource };
683+
}
684+
685+
676686
private static string NormalizePathInput(string currentInput, bool isFtp)
677687
{
678688
if (currentInput.Contains('/') && !isFtp)

src/Files.App/Views/Shells/BaseShellPage.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public BaseShellPage(CurrentInstanceViewModel instanceViewModel)
180180
FlowDirection = FlowDirection.RightToLeft;
181181

182182
ToolbarViewModel.ToolbarPathItemInvoked += ShellPage_NavigationRequested;
183-
ToolbarViewModel.ToolbarFlyoutOpened += ShellPage_ToolbarFlyoutOpened;
183+
ToolbarViewModel.ToolbarFlyoutOpening += ShellPage_ToolbarFlyoutOpening;
184184
ToolbarViewModel.ToolbarPathItemLoaded += ShellPage_ToolbarPathItemLoaded;
185185
ToolbarViewModel.AddressBarTextEntered += ShellPage_AddressBarTextEntered;
186186
ToolbarViewModel.PathBoxItemDropped += ShellPage_PathBoxItemDropped;
@@ -431,12 +431,12 @@ protected async void ShellPage_ToolbarPathItemLoaded(object sender, ToolbarPathI
431431
await ToolbarViewModel.SetPathBoxDropDownFlyoutAsync(e.OpenedFlyout, e.Item, this);
432432
}
433433

434-
protected async void ShellPage_ToolbarFlyoutOpened(object sender, ToolbarFlyoutOpenedEventArgs e)
434+
protected async void ShellPage_ToolbarFlyoutOpening(object sender, ToolbarFlyoutOpeningEventArgs e)
435435
{
436-
var pathBoxItem = ((Button)e.OpenedFlyout.Target).DataContext as PathBoxItem;
436+
var pathBoxItem = ((Button)e.OpeningFlyout.Target).DataContext as PathBoxItem;
437437

438438
if (pathBoxItem is not null)
439-
await ToolbarViewModel.SetPathBoxDropDownFlyoutAsync(e.OpenedFlyout, pathBoxItem, this);
439+
await ToolbarViewModel.SetPathBoxDropDownFlyoutAsync(e.OpeningFlyout, pathBoxItem, this);
440440
}
441441

442442
protected async void NavigationToolbar_QuerySubmitted(object sender, ToolbarQuerySubmittedEventArgs e)
@@ -828,7 +828,7 @@ public virtual void Dispose()
828828
drivesViewModel.PropertyChanged -= DrivesManager_PropertyChanged;
829829

830830
ToolbarViewModel.ToolbarPathItemInvoked -= ShellPage_NavigationRequested;
831-
ToolbarViewModel.ToolbarFlyoutOpened -= ShellPage_ToolbarFlyoutOpened;
831+
ToolbarViewModel.ToolbarFlyoutOpening -= ShellPage_ToolbarFlyoutOpening;
832832
ToolbarViewModel.ToolbarPathItemLoaded -= ShellPage_ToolbarPathItemLoaded;
833833
ToolbarViewModel.AddressBarTextEntered -= ShellPage_AddressBarTextEntered;
834834
ToolbarViewModel.PathBoxItemDropped -= ShellPage_PathBoxItemDropped;

0 commit comments

Comments
 (0)