Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2ebbb7e

Browse files
authoredFeb 5, 2023
Feature: Display recent folders in the folders widget (#11155)
1 parent 721b5bd commit 2ebbb7e

File tree

15 files changed

+243
-118
lines changed

15 files changed

+243
-118
lines changed
 

‎src/Files.App/DataModels/NavigationControlItems/LocationItem.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public bool IsExpanded
5656

5757
public bool IsInvalid { get; set; } = false;
5858

59+
public bool IsPinned => App.QuickAccessManager.Model.FavoriteItems.Contains(path);
60+
5961
public SectionType Section { get; set; }
6062

6163
public ContextMenuOptions MenuOptions { get; set; }

‎src/Files.App/DataModels/SidebarPinnedModel.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,7 @@ public int IndexOfItem(INavigationControlItem locationItem)
7575
}
7676
}
7777

78-
/// <summary>
79-
/// Adds the item (from a path) to the navigation sidebar
80-
/// </summary>
81-
/// <param name="path">The path which to save</param>
82-
/// <returns>Task</returns>
83-
public async Task AddItemToSidebarAsync(string path)
78+
public async Task<LocationItem> CreateLocationItemFromPathAsync(string path)
8479
{
8580
var item = await FilesystemTasks.Wrap(() => DrivesManager.GetRootFromPathAsync(path));
8681
var res = await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderFromPathAsync(path, item));
@@ -130,6 +125,18 @@ public async Task AddItemToSidebarAsync(string path)
130125
Debug.WriteLine($"Pinned item was invalid {res.ErrorCode}, item: {path}");
131126
}
132127

128+
return locationItem;
129+
}
130+
131+
/// <summary>
132+
/// Adds the item (from a path) to the navigation sidebar
133+
/// </summary>
134+
/// <param name="path">The path which to save</param>
135+
/// <returns>Task</returns>
136+
public async Task AddItemToSidebarAsync(string path)
137+
{
138+
var locationItem = await CreateLocationItemFromPathAsync(path);
139+
133140
AddLocationItemToSidebar(locationItem);
134141
}
135142

‎src/Files.App/Filesystem/QuickAccessManager.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using CommunityToolkit.Mvvm.DependencyInjection;
22
using Files.App.DataModels;
33
using Files.App.ServicesImplementation;
4+
using Files.App.UserControls.Widgets;
45
using Files.Shared.Extensions;
56
using System;
67
using System.Collections.Generic;
@@ -16,7 +17,11 @@ namespace Files.App.Filesystem
1617
public sealed class QuickAccessManager
1718
{
1819
public FileSystemWatcher? PinnedItemsWatcher;
20+
1921
public event FileSystemEventHandler? PinnedItemsModified;
22+
23+
public EventHandler<ModifyQuickAccessEventArgs>? UpdateQuickAccessWidget;
24+
2025
public IQuickAccessService QuickAccessService { get; } = Ioc.Default.GetRequiredService<IQuickAccessService>();
2126

2227
public SidebarPinnedModel Model;

‎src/Files.App/Helpers/WidgetsHelpers.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ public static class WidgetsHelpers
3737

3838
public static bool TryGetIsWidgetSettingEnabled<TWidget>(IPreferencesSettingsService preferencesSettingsService) where TWidget : IWidgetItemModel
3939
{
40-
if (typeof(TWidget) == typeof(FolderWidget))
40+
if (typeof(TWidget) == typeof(QuickAccessWidget))
4141
{
42-
return preferencesSettingsService.ShowFoldersWidget;
42+
return preferencesSettingsService.ShowQuickAccessWidget;
4343
}
4444
if (typeof(TWidget) == typeof(DrivesWidget))
4545
{

‎src/Files.App/ServicesImplementation/QuickAccessService.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,44 @@
1-
using Files.App.Shell;
1+
using Files.App.DataModels.NavigationControlItems;
2+
using Files.App.Filesystem;
3+
using Files.App.Shell;
4+
using Files.App.UserControls.Widgets;
5+
using Files.Shared;
26
using Files.Shared.Extensions;
37
using System;
48
using System.Collections.Generic;
59
using System.Linq;
10+
using System.Security.Permissions;
611
using System.Threading.Tasks;
712

813
namespace Files.App.ServicesImplementation
914
{
1015
internal class QuickAccessService : IQuickAccessService
1116
{
1217
private readonly static string guid = "::{679f85cb-0220-4080-b29b-5540cc05aab6}";
13-
14-
public async Task<List<string>> GetPinnedFoldersAsync()
18+
19+
public async Task<List<string>> GetPinnedFoldersAsync(bool getRecentItems = false)
1520
{
1621
var sidebarItems = (await Win32Shell.GetShellFolderAsync(guid, "Enumerate", 0, 10000)).Enumerate
1722
.Where(link => link.IsFolder)
1823
.Select(link => link.FilePath).ToList();
1924

20-
if (sidebarItems.Count > 4) // Avoid first opening crash #11139
25+
if (sidebarItems.Count > 4 && !getRecentItems) // Avoid first opening crash #11139
2126
sidebarItems.RemoveRange(sidebarItems.Count - 4, 4); // 4 is the number of recent items shown in explorer sidebar
2227

2328
return sidebarItems;
2429
}
25-
30+
2631
public async Task PinToSidebar(string folderPath)
2732
=> await PinToSidebar(new[] { folderPath });
2833

2934
public async Task PinToSidebar(string[] folderPaths)
3035
{
3136
await ContextMenu.InvokeVerb("pintohome", folderPaths);
3237
await App.QuickAccessManager.Model.LoadAsync();
38+
39+
App.QuickAccessManager.UpdateQuickAccessWidget?.Invoke(this, new ModifyQuickAccessEventArgs(folderPaths, true));
3340
}
34-
41+
3542
public async Task UnpinFromSidebar(string folderPath)
3643
=> await UnpinFromSidebar(new[] { folderPath });
3744

@@ -48,6 +55,8 @@ await SafetyExtensions.IgnoreExceptions(async () => {
4855
});
4956

5057
await App.QuickAccessManager.Model.LoadAsync();
58+
59+
App.QuickAccessManager.UpdateQuickAccessWidget?.Invoke(this, new ModifyQuickAccessEventArgs(folderPaths, false));
5160
}
5261
}
5362
}

‎src/Files.App/ServicesImplementation/Settings/PreferencesSettingsService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public bool AlwaysOpenDualPaneInNewTab
8181
set => Set(value);
8282
}
8383

84-
public bool ShowFoldersWidget
84+
public bool ShowQuickAccessWidget
8585
{
8686
get => Get(true);
8787
set => Set(value);
@@ -194,7 +194,7 @@ protected override void RaiseOnSettingChangedEvent(object sender, SettingChanged
194194
case nameof(AlwaysOpenNewInstance):
195195
case nameof(IsDualPaneEnabled):
196196
case nameof(AlwaysOpenDualPaneInNewTab):
197-
case nameof(ShowFoldersWidget):
197+
case nameof(ShowQuickAccessWidget):
198198
case nameof(ShowRecentFilesWidget):
199199
case nameof(ShowDrivesWidget):
200200
case nameof(ShowBundlesWidget):

‎src/Files.App/Strings/en-US/Resources.resw

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,9 +2289,6 @@
22892289
<data name="DrivesWidgetAutomationProperties.Name" xml:space="preserve">
22902290
<value>Drives Widget</value>
22912291
</data>
2292-
<data name="FolderWidgetAutomationProperties.Name" xml:space="preserve">
2293-
<value>Folders Widget</value>
2294-
</data>
22952292
<data name="RecentFilesWidgetAutomationProperties.Name" xml:space="preserve">
22962293
<value>Recent Files Widget</value>
22972294
</data>
@@ -2900,6 +2897,9 @@
29002897
</data>
29012898
<data name="DisplayEditTagsMenu" xml:space="preserve">
29022899
<value>Display the edit tags flyout</value>
2900+
</data>
2901+
<data name="QuickAccess" xml:space="preserve">
2902+
<value>Quick access</value>
29032903
</data>
29042904
<data name="NetworkAuthenticationDialogMessage" xml:space="preserve">
29052905
<value>Enter your credentials to connect to: {0}</value>

‎src/Files.App/UserControls/Widgets/FolderWidget.xaml renamed to ‎src/Files.App/UserControls/Widgets/QuickAccessWidget.xaml

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<UserControl
2-
x:Class="Files.App.UserControls.Widgets.FolderWidget"
2+
x:Class="Files.App.UserControls.Widgets.QuickAccessWidget"
33
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
55
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@@ -72,10 +72,29 @@
7272
<FontIcon Glyph="&#xE737;" />
7373
</MenuFlyoutItem.Icon>
7474
</MenuFlyoutItem>
75+
<MenuFlyoutItem
76+
x:Name="PinToFavorites"
77+
Click="PinToFavorites_Click"
78+
DataContext="{x:Bind}"
79+
Text="{helpers:ResourceString Name=BaseLayoutItemContextFlyoutPinToFavorites/Text}"
80+
Visibility="Collapsed">
81+
<MenuFlyoutItem.Icon>
82+
<FontIcon Glyph="&#xE840;" />
83+
</MenuFlyoutItem.Icon>
84+
</MenuFlyoutItem>
85+
<MenuFlyoutItem
86+
x:Name="UnpinFromFavorites"
87+
Click="UnpinFromFavorites_Click"
88+
DataContext="{x:Bind}"
89+
Text="{helpers:ResourceString Name=BaseLayoutContextFlyoutUnpinFromFavorites/Text}"
90+
Visibility="Collapsed">
91+
<MenuFlyoutItem.Icon>
92+
<FontIcon Glyph="&#xE77A;" />
93+
</MenuFlyoutItem.Icon>
94+
</MenuFlyoutItem>
7595
<MenuFlyoutItem
7696
x:Name="Properties"
77-
x:Load="{x:Bind IsLibrary}"
78-
Click="OpenLibraryProperties_Click"
97+
Click="OpenProperties_Click"
7998
DataContext="{x:Bind}"
8099
Text="{helpers:ResourceString Name=BaseLayoutContextFlyoutPropertiesFolder/Text}">
81100
<MenuFlyoutItem.Icon>
@@ -85,7 +104,6 @@
85104
</MenuFlyout.Items>
86105
</MenuFlyout>
87106
</Button.ContextFlyout>
88-
89107
<Grid
90108
HorizontalAlignment="Stretch"
91109
VerticalAlignment="Stretch"
@@ -94,6 +112,13 @@
94112
<RowDefinition Height="*" />
95113
<RowDefinition Height="Auto" />
96114
</Grid.RowDefinitions>
115+
<FontIcon
116+
x:Name="PinIcon"
117+
HorizontalAlignment="Right"
118+
VerticalAlignment="Top"
119+
FontSize="12"
120+
Glyph="&#xE840;"
121+
x:Load="{x:Bind IsPinned, Mode=OneWay}" />
97122
<Image
98123
Grid.Row="0"
99124
Width="32"

‎src/Files.App/UserControls/Widgets/FolderWidget.xaml.cs renamed to ‎src/Files.App/UserControls/Widgets/QuickAccessWidget.xaml.cs

Lines changed: 126 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Files.App.Filesystem;
88
using Files.App.Helpers;
99
using Files.App.Helpers.XamlHelpers;
10+
using Files.App.ServicesImplementation;
1011
using Files.App.ViewModels.Widgets;
1112
using Files.Backend.Services.Settings;
1213
using Microsoft.UI.Xaml;
@@ -15,28 +16,45 @@
1516
using Microsoft.UI.Xaml.Input;
1617
using Microsoft.UI.Xaml.Media.Imaging;
1718
using System;
19+
using System.Collections.Generic;
1820
using System.Collections.ObjectModel;
1921
using System.ComponentModel;
22+
using System.IO;
2023
using System.Linq;
24+
using System.Net.Sockets;
2125
using System.Runtime.CompilerServices;
2226
using System.Threading.Tasks;
2327
using System.Windows.Input;
28+
using Vanara;
2429
using Windows.Storage;
2530
using Windows.System;
2631
using Windows.UI.Core;
2732

2833
namespace Files.App.UserControls.Widgets
2934
{
30-
public class LibraryCardEventArgs : EventArgs
35+
public class QuickAccessCardEventArgs : EventArgs
3136
{
32-
public LibraryLocationItem Library { get; set; }
37+
public LocationItem Item { get; set; }
3338
}
3439

35-
public class LibraryCardInvokedEventArgs : EventArgs
40+
public class QuickAccessCardInvokedEventArgs : EventArgs
3641
{
3742
public string Path { get; set; }
3843
}
3944

45+
public class ModifyQuickAccessEventArgs : EventArgs
46+
{
47+
public string[] Paths { get; set; }
48+
public bool Add;
49+
public bool Pin = true;
50+
51+
public ModifyQuickAccessEventArgs(string[] paths, bool add)
52+
{
53+
Paths = paths;
54+
Add = add;
55+
}
56+
}
57+
4058
public class FolderCardItem : ObservableObject, IWidgetCardItem<LocationItem>
4159
{
4260
private BitmapImage thumbnail;
@@ -56,18 +74,20 @@ public BitmapImage Thumbnail
5674
public string Path { get; set; }
5775
public ICommand SelectCommand { get; set; }
5876
public string Text { get; set; }
77+
public bool IsPinned { get; set; }
5978

60-
public FolderCardItem(LocationItem item = null, string text = null) : this(text)
79+
public FolderCardItem(LocationItem item = null, string text = null, bool isPinned = true) : this(text, isPinned)
6180
{
6281
Item = item;
6382
}
6483

65-
public FolderCardItem(string text)
84+
public FolderCardItem(string text, bool isPinned)
6685
{
6786
if (!string.IsNullOrWhiteSpace(text))
6887
{
6988
Text = text;
7089
AutomationProperties = Text;
90+
IsPinned = isPinned;
7191
}
7292
}
7393

@@ -84,43 +104,45 @@ public async Task LoadCardThumbnailAsync()
84104
}
85105
}
86106

87-
public sealed partial class FolderWidget : UserControl, IWidgetItemModel, INotifyPropertyChanged
107+
public sealed partial class QuickAccessWidget : UserControl, IWidgetItemModel, INotifyPropertyChanged
88108
{
89109
private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetRequiredService<IUserSettingsService>();
90110

111+
private readonly IQuickAccessService QuickAccessService = Ioc.Default.GetRequiredService<IQuickAccessService>();
112+
91113
public ObservableCollection<FolderCardItem> ItemsAdded = new();
92114

93115
private bool showMultiPaneControls;
94116

95-
public FolderWidget()
117+
public QuickAccessWidget()
96118
{
97119
InitializeComponent();
98120

99-
LibraryCardCommand = new AsyncRelayCommand<FolderCardItem>(OpenLibraryCard);
121+
QuickAccessCardCommand = new AsyncRelayCommand<FolderCardItem>(OpenCard);
100122

101-
Loaded += FolderWidget_Loaded;
102-
Unloaded += FolderWidget_Unloaded;
123+
Loaded += QuickAccessWidget_Loaded;
124+
Unloaded += QuickAccessWidget_Unloaded;
103125
}
104126

105-
public delegate void LibraryCardInvokedEventHandler(object sender, LibraryCardInvokedEventArgs e);
127+
public delegate void LibraryCardInvokedEventHandler(object sender, QuickAccessCardInvokedEventArgs e);
106128

107-
public delegate void LibraryCardNewPaneInvokedEventHandler(object sender, LibraryCardInvokedEventArgs e);
129+
public delegate void LibraryCardNewPaneInvokedEventHandler(object sender, QuickAccessCardInvokedEventArgs e);
108130

109-
public delegate void LibraryCardPropertiesInvokedEventHandler(object sender, LibraryCardEventArgs e);
131+
public delegate void LibraryCardPropertiesInvokedEventHandler(object sender, QuickAccessCardEventArgs e);
110132

111-
public event LibraryCardInvokedEventHandler LibraryCardInvoked;
133+
public event LibraryCardInvokedEventHandler CardInvoked;
112134

113-
public event LibraryCardNewPaneInvokedEventHandler LibraryCardNewPaneInvoked;
135+
public event LibraryCardNewPaneInvokedEventHandler CardNewPaneInvoked;
114136

115-
public event LibraryCardPropertiesInvokedEventHandler LibraryCardPropertiesInvoked;
137+
public event LibraryCardPropertiesInvokedEventHandler CardPropertiesInvoked;
116138

117-
public event EventHandler FolderWidgethowMultiPaneControlsInvoked;
139+
public event EventHandler QuickAccessWidgetShowMultiPaneControlsInvoked;
118140

119141
public event PropertyChangedEventHandler PropertyChanged;
120142

121-
public bool IsWidgetSettingEnabled => UserSettingsService.PreferencesSettingsService.ShowFoldersWidget;
143+
public bool IsWidgetSettingEnabled => UserSettingsService.PreferencesSettingsService.ShowQuickAccessWidget;
122144

123-
public ICommand LibraryCardCommand { get; }
145+
public ICommand QuickAccessCardCommand { get; }
124146

125147
public ICommand ShowCreateNewLibraryDialogCommand { get; } = new RelayCommand(LibraryManager.ShowCreateNewLibraryDialog);
126148

@@ -130,7 +152,7 @@ public bool ShowMultiPaneControls
130152
{
131153
get
132154
{
133-
FolderWidgethowMultiPaneControlsInvoked?.Invoke(this, EventArgs.Empty);
155+
QuickAccessWidgetShowMultiPaneControlsInvoked?.Invoke(this, EventArgs.Empty);
134156

135157
return showMultiPaneControls;
136158
}
@@ -144,64 +166,85 @@ public bool ShowMultiPaneControls
144166
}
145167
}
146168

147-
public string WidgetName => nameof(FolderWidget);
169+
public string WidgetName => nameof(QuickAccessWidget);
148170

149-
public string AutomationProperties => "FolderWidgetAutomationProperties/Name".GetLocalizedResource();
171+
public string AutomationProperties => "QuickAccess".GetLocalizedResource();
150172

151-
public string WidgetHeader => "Folders".GetLocalizedResource();
173+
public string WidgetHeader => "QuickAccess".GetLocalizedResource();
152174

153-
private async void FolderWidget_Loaded(object sender, RoutedEventArgs e)
175+
private async void ModifyItem(object? sender, ModifyQuickAccessEventArgs? e)
154176
{
155-
Loaded -= FolderWidget_Loaded;
177+
if (e is null)
178+
return;
156179

157-
ItemsAdded.Add(new FolderCardItem("Desktop".GetLocalizedResource())
158-
{
159-
Path = UserDataPaths.GetDefault().Desktop,
160-
SelectCommand = LibraryCardCommand
161-
});
162-
ItemsAdded.Add(new FolderCardItem("Documents".GetLocalizedResource())
180+
if (e.Add)
163181
{
164-
Path = UserDataPaths.GetDefault().Documents,
165-
SelectCommand = LibraryCardCommand
166-
});
167-
ItemsAdded.Add(new FolderCardItem("Downloads".GetLocalizedResource())
168-
{
169-
Path = UserDataPaths.GetDefault().Downloads,
170-
SelectCommand = LibraryCardCommand
171-
});
172-
ItemsAdded.Add(new FolderCardItem("Music".GetLocalizedResource())
173-
{
174-
Path = UserDataPaths.GetDefault().Music,
175-
SelectCommand = LibraryCardCommand
176-
});
177-
ItemsAdded.Add(new FolderCardItem("Pictures".GetLocalizedResource())
178-
{
179-
Path = UserDataPaths.GetDefault().Pictures,
180-
SelectCommand = LibraryCardCommand
181-
});
182-
ItemsAdded.Add(new FolderCardItem("Videos".GetLocalizedResource())
182+
var locationItems = new List<LocationItem>();
183+
foreach (var item in e.Paths)
184+
locationItems.Add(await App.QuickAccessManager.Model.CreateLocationItemFromPathAsync(item));
185+
186+
foreach (var item in locationItems)
187+
ItemsAdded.Insert(e.Pin ? ItemsAdded.Count - 4 : ItemsAdded.Count, new FolderCardItem(Path.GetFileName(item.Text), e.Pin) // Add just after the Recent Folders
188+
{
189+
Path = item.Path,
190+
SelectCommand = QuickAccessCardCommand
191+
});
192+
193+
var cardLoadTasks = ItemsAdded.Select(cardItem => cardItem.LoadCardThumbnailAsync());
194+
await Task.WhenAll(cardLoadTasks);
195+
}
196+
else
197+
foreach (var itemToRemove in ItemsAdded.Where(x => e.Paths.Contains(x.Path)).ToList())
198+
ItemsAdded.Remove(itemToRemove);
199+
}
200+
201+
private async void QuickAccessWidget_Loaded(object sender, RoutedEventArgs e)
202+
{
203+
Loaded -= QuickAccessWidget_Loaded;
204+
205+
var itemsToAdd = await QuickAccessService.GetPinnedFoldersAsync(true);
206+
207+
var locationItems = new List<LocationItem>();
208+
foreach (var item in itemsToAdd)
209+
locationItems.Add(await App.QuickAccessManager.Model.CreateLocationItemFromPathAsync(item));
210+
211+
int idx = 0;
212+
foreach (var item in locationItems)
183213
{
184-
Path = UserDataPaths.GetDefault().Videos,
185-
SelectCommand = LibraryCardCommand
186-
});
214+
ItemsAdded.Add(new FolderCardItem(item, Path.GetFileName(item.Text), idx < locationItems.Count - 4)
215+
{
216+
Path = item.Path,
217+
SelectCommand = QuickAccessCardCommand
218+
});
219+
idx++;
220+
}
221+
222+
App.QuickAccessManager.UpdateQuickAccessWidget += ModifyItem;
187223

188224
var cardLoadTasks = ItemsAdded.Select(cardItem => cardItem.LoadCardThumbnailAsync());
189225
await Task.WhenAll(cardLoadTasks);
190226
}
191227

192-
private void FolderWidget_Unloaded(object sender, RoutedEventArgs e)
228+
private void QuickAccessWidget_Unloaded(object sender, RoutedEventArgs e)
193229
{
194-
Unloaded -= FolderWidget_Unloaded;
230+
Unloaded -= QuickAccessWidget_Unloaded;
231+
App.QuickAccessManager.UpdateQuickAccessWidget += ModifyItem;
195232
}
196233

197234
private void MenuFlyout_Opening(object sender, object e)
198235
{
199236
var newPaneMenuItem = (sender as MenuFlyout).Items.SingleOrDefault(x => x.Name == "OpenInNewPane");
200237
// eg. an empty library doesn't have OpenInNewPane context menu item
201238
if (newPaneMenuItem is not null)
202-
{
203239
newPaneMenuItem.Visibility = ShowMultiPaneControls ? Visibility.Visible : Visibility.Collapsed;
204-
}
240+
241+
var pinToFavoritesItem = (sender as MenuFlyout).Items.SingleOrDefault(x => x.Name == "PinToFavorites");
242+
if (pinToFavoritesItem is not null)
243+
pinToFavoritesItem.Visibility = (pinToFavoritesItem.DataContext as FolderCardItem).IsPinned ? Visibility.Collapsed : Visibility.Visible;
244+
245+
var unpinFromFavoritesItem = (sender as MenuFlyout).Items.SingleOrDefault(x => x.Name == "UnpinFromFavorites");
246+
if (unpinFromFavoritesItem is not null)
247+
unpinFromFavoritesItem.Visibility = (unpinFromFavoritesItem.DataContext as FolderCardItem).IsPinned ? Visibility.Visible : Visibility.Collapsed;
205248
}
206249

207250
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
@@ -212,7 +255,7 @@ private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
212255
private void OpenInNewPane_Click(object sender, RoutedEventArgs e)
213256
{
214257
var item = ((MenuFlyoutItem)sender).DataContext as FolderCardItem;
215-
LibraryCardNewPaneInvoked?.Invoke(this, new LibraryCardInvokedEventArgs { Path = item.Path });
258+
CardNewPaneInvoked?.Invoke(this, new QuickAccessCardInvokedEventArgs { Path = item.Path });
216259
}
217260

218261
private async void OpenInNewTab_Click(object sender, RoutedEventArgs e)
@@ -236,24 +279,44 @@ private async void OpenInNewWindow_Click(object sender, RoutedEventArgs e)
236279
await NavigationHelpers.OpenPathInNewWindowAsync(item.Path);
237280
}
238281

239-
private void OpenLibraryProperties_Click(object sender, RoutedEventArgs e)
282+
private void OpenProperties_Click(object sender, RoutedEventArgs e)
240283
{
241284
var presenter = DependencyObjectHelpers.FindParent<MenuFlyoutPresenter>((MenuFlyoutItem)sender);
242285
var flyoutParent = presenter?.Parent as Popup;
243286
var propertiesItem = ((MenuFlyoutItem)sender).DataContext as FolderCardItem;
244-
if (propertiesItem is null || !propertiesItem.IsLibrary || flyoutParent is null)
287+
if (propertiesItem is null || flyoutParent is null)
245288
return;
246289

247290
EventHandler<object> flyoutClosed = null!;
248291
flyoutClosed = (s, e) =>
249292
{
250293
flyoutParent.Closed -= flyoutClosed;
251-
LibraryCardPropertiesInvoked?.Invoke(this, new LibraryCardEventArgs { Library = (propertiesItem.Item as LibraryLocationItem)! });
294+
CardPropertiesInvoked?.Invoke(this, new QuickAccessCardEventArgs { Item = propertiesItem.Item });
252295
};
253296
flyoutParent.Closed += flyoutClosed;
254297
}
255298

256-
private Task OpenLibraryCard(FolderCardItem item)
299+
private async void PinToFavorites_Click(object sender, RoutedEventArgs e)
300+
{
301+
var item = ((MenuFlyoutItem)sender).DataContext as FolderCardItem;
302+
await QuickAccessService.PinToSidebar(item.Path);
303+
ModifyItem(this, new ModifyQuickAccessEventArgs(new[] { item.Path }, false));
304+
var items = await QuickAccessService.GetPinnedFoldersAsync(true);
305+
items.RemoveRange(0, items.Count - 4);
306+
var recentItem = items.Where(x => !ItemsAdded.Select(y => y.Path).Contains(x)).FirstOrDefault();
307+
ModifyItem(this, new ModifyQuickAccessEventArgs(new[] { recentItem }, true)
308+
{
309+
Pin = false
310+
});
311+
}
312+
313+
private void UnpinFromFavorites_Click(object sender, RoutedEventArgs e)
314+
{
315+
var item = ((MenuFlyoutItem)sender).DataContext as FolderCardItem;
316+
_ = QuickAccessService.UnpinFromSidebar(item.Path);
317+
}
318+
319+
private Task OpenCard(FolderCardItem item)
257320
{
258321
if (string.IsNullOrEmpty(item.Path))
259322
{
@@ -271,7 +334,7 @@ private Task OpenLibraryCard(FolderCardItem item)
271334
return NavigationHelpers.OpenPathInNewTab(item.Path);
272335
}
273336

274-
LibraryCardInvoked?.Invoke(this, new LibraryCardInvokedEventArgs { Path = item.Path });
337+
CardInvoked?.Invoke(this, new QuickAccessCardInvokedEventArgs { Path = item.Path });
275338

276339
return Task.CompletedTask;
277340
}

‎src/Files.App/ViewModels/SettingsViewModels/PreferencesViewModel.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,13 +460,13 @@ public bool SearchUnindexedItems
460460
}
461461
}
462462

463-
public bool ShowFoldersWidget
463+
public bool ShowQuickAccessWidget
464464
{
465-
get => UserSettingsService.PreferencesSettingsService.ShowFoldersWidget;
465+
get => UserSettingsService.PreferencesSettingsService.ShowQuickAccessWidget;
466466
set
467467
{
468-
if (value != UserSettingsService.PreferencesSettingsService.ShowFoldersWidget)
469-
UserSettingsService.PreferencesSettingsService.ShowFoldersWidget = value;
468+
if (value != UserSettingsService.PreferencesSettingsService.ShowQuickAccessWidget)
469+
UserSettingsService.PreferencesSettingsService.ShowQuickAccessWidget = value;
470470
}
471471
}
472472

‎src/Files.App/ViewModels/ToolbarViewModel.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,11 +436,16 @@ public async Task CheckForReleaseNotesAsync()
436436
IsReleaseNotesVisible = true;
437437
}
438438

439+
public void RefreshWidgets()
440+
{
441+
RefreshWidgetsRequested?.Invoke(this, EventArgs.Empty);
442+
}
443+
439444
private void UserSettingsService_OnSettingChangedEvent(object? sender, SettingChangedEventArgs e)
440445
{
441446
switch (e.SettingName)
442447
{
443-
case nameof(UserSettingsService.PreferencesSettingsService.ShowFoldersWidget): // ToDo: Move this to the widget page, it doesn't belong here.
448+
case nameof(UserSettingsService.PreferencesSettingsService.ShowQuickAccessWidget): // ToDo: Move this to the widget page, it doesn't belong here.
444449
case nameof(UserSettingsService.PreferencesSettingsService.ShowDrivesWidget):
445450
case nameof(UserSettingsService.PreferencesSettingsService.ShowBundlesWidget):
446451
case nameof(UserSettingsService.PreferencesSettingsService.ShowFileTagsWidget):

‎src/Files.App/Views/SettingsPages/Preferences.xaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,10 @@
225225
</local:SettingsBlockControl.Icon>
226226
<local:SettingsBlockControl.ExpandableContent>
227227
<StackPanel>
228-
<local:SettingsBlockControl Title="{helpers:ResourceString Name=Folders}" HorizontalAlignment="Stretch">
228+
<local:SettingsBlockControl Title="{helpers:ResourceString Name=QuickAccess}" HorizontalAlignment="Stretch">
229229
<ToggleSwitch
230-
AutomationProperties.Name="{helpers:ResourceString Name=Folders}"
231-
IsOn="{x:Bind ViewModel.ShowFoldersWidget, Mode=TwoWay}"
230+
AutomationProperties.Name="{helpers:ResourceString Name=QuickAccess}"
231+
IsOn="{x:Bind ViewModel.ShowQuickAccessWidget, Mode=TwoWay}"
232232
Style="{StaticResource RightAlignedToggleSwitchStyle}" />
233233
</local:SettingsBlockControl>
234234

‎src/Files.App/Views/WidgetsPage.xaml.cs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using CommunityToolkit.Mvvm.DependencyInjection;
2+
using Files.App.DataModels.NavigationControlItems;
23
using Files.App.Dialogs;
34
using Files.App.Extensions;
45
using Files.App.Filesystem;
@@ -14,6 +15,7 @@
1415
using System.Linq;
1516
using System.Runtime.InteropServices;
1617
using System.Threading.Tasks;
18+
using Windows.Storage;
1719

1820
namespace Files.App.Views
1921
{
@@ -24,7 +26,7 @@ public sealed partial class WidgetsPage : Page, IDisposable
2426
private IShellPage AppInstance = null;
2527
public FolderSettingsViewModel FolderSettings => AppInstance?.InstanceViewModel.FolderSettings;
2628

27-
private FolderWidget folderWidget;
29+
private QuickAccessWidget quickAccessWidget;
2830
private DrivesWidget drivesWidget;
2931
private BundlesWidget bundlesWidget;
3032
private FileTagsWidget fileTagsWidget;
@@ -58,26 +60,26 @@ private void ViewModel_WidgetListRefreshRequestedInvoked(object? sender, EventAr
5860
ReloadWidgets();
5961
}
6062

61-
private void ReloadWidgets()
63+
public void ReloadWidgets()
6264
{
63-
folderWidget = WidgetsHelpers.TryGetWidget<FolderWidget>(UserSettingsService.PreferencesSettingsService, Widgets.ViewModel, out bool shouldReloadFolderWidget, folderWidget);
65+
quickAccessWidget = WidgetsHelpers.TryGetWidget<QuickAccessWidget>(UserSettingsService.PreferencesSettingsService, Widgets.ViewModel, out bool shouldReloadQuickAccessWidget, quickAccessWidget);
6466
drivesWidget = WidgetsHelpers.TryGetWidget<DrivesWidget>(UserSettingsService.PreferencesSettingsService, Widgets.ViewModel, out bool shouldReloadDrivesWidget, drivesWidget);
6567
bundlesWidget = WidgetsHelpers.TryGetWidget<BundlesWidget>(UserSettingsService.PreferencesSettingsService, Widgets.ViewModel, out bool shouldReloadBundles, bundlesWidget);
6668
fileTagsWidget = WidgetsHelpers.TryGetWidget<FileTagsWidget>(UserSettingsService.PreferencesSettingsService, Widgets.ViewModel, out bool shouldReloadFileTags, fileTagsWidget);
6769
recentFilesWidget = WidgetsHelpers.TryGetWidget<RecentFilesWidget>(UserSettingsService.PreferencesSettingsService, Widgets.ViewModel, out bool shouldReloadRecentFiles, recentFilesWidget);
6870

69-
if (shouldReloadFolderWidget && folderWidget is not null)
71+
if (shouldReloadQuickAccessWidget && quickAccessWidget is not null)
7072
{
71-
Widgets.ViewModel.InsertWidget(new(folderWidget, (value) => UserSettingsService.PreferencesSettingsService.FoldersWidgetExpanded = value, () => UserSettingsService.PreferencesSettingsService.FoldersWidgetExpanded), 0);
72-
73-
folderWidget.LibraryCardInvoked -= FolderWidget_LibraryCardInvoked;
74-
folderWidget.LibraryCardNewPaneInvoked -= FolderWidget_LibraryCardNewPaneInvoked;
75-
folderWidget.LibraryCardPropertiesInvoked -= FolderWidget_LibraryCardPropertiesInvoked;
76-
folderWidget.FolderWidgethowMultiPaneControlsInvoked -= FolderWidget_FolderWidgethowMultiPaneControlsInvoked;
77-
folderWidget.LibraryCardInvoked += FolderWidget_LibraryCardInvoked;
78-
folderWidget.LibraryCardNewPaneInvoked += FolderWidget_LibraryCardNewPaneInvoked;
79-
folderWidget.LibraryCardPropertiesInvoked += FolderWidget_LibraryCardPropertiesInvoked;
80-
folderWidget.FolderWidgethowMultiPaneControlsInvoked += FolderWidget_FolderWidgethowMultiPaneControlsInvoked;
73+
Widgets.ViewModel.InsertWidget(new(quickAccessWidget, (value) => UserSettingsService.PreferencesSettingsService.FoldersWidgetExpanded = value, () => UserSettingsService.PreferencesSettingsService.FoldersWidgetExpanded), 0);
74+
75+
quickAccessWidget.CardInvoked -= QuickAccessWidget_CardInvoked;
76+
quickAccessWidget.CardNewPaneInvoked -= QuickAccessWidget_CardNewPaneInvoked;
77+
quickAccessWidget.CardPropertiesInvoked -= QuickAccessWidget_CardPropertiesInvoked;
78+
quickAccessWidget.QuickAccessWidgetShowMultiPaneControlsInvoked -= QuickAccessWidget_QuickAccessWidgetShowMultiPaneControlsInvoked;
79+
quickAccessWidget.CardInvoked += QuickAccessWidget_CardInvoked;
80+
quickAccessWidget.CardNewPaneInvoked += QuickAccessWidget_CardNewPaneInvoked;
81+
quickAccessWidget.CardPropertiesInvoked += QuickAccessWidget_CardPropertiesInvoked;
82+
quickAccessWidget.QuickAccessWidgetShowMultiPaneControlsInvoked += QuickAccessWidget_QuickAccessWidgetShowMultiPaneControlsInvoked;
8183
}
8284
if (shouldReloadDrivesWidget && drivesWidget is not null)
8385
{
@@ -118,11 +120,11 @@ private void ViewModel_YourHomeLoadedInvoked(object? sender, Microsoft.UI.Xaml.R
118120
ReloadWidgets();
119121
}
120122

121-
private void FolderWidget_FolderWidgethowMultiPaneControlsInvoked(object sender, EventArgs e)
123+
private void QuickAccessWidget_QuickAccessWidgetShowMultiPaneControlsInvoked(object sender, EventArgs e)
122124
{
123-
FolderWidget FolderWidget = (FolderWidget)sender;
125+
QuickAccessWidget QuickAccessWidget = (QuickAccessWidget)sender;
124126

125-
FolderWidget.ShowMultiPaneControls = AppInstance.PaneHolder?.IsMultiPaneEnabled ?? false;
127+
QuickAccessWidget.ShowMultiPaneControls = AppInstance.PaneHolder?.IsMultiPaneEnabled ?? false;
126128
}
127129

128130
// WINUI3
@@ -175,7 +177,7 @@ private void RecentFilesWidget_RecentFilesOpenLocationInvoked(object sender, Use
175177
});
176178
}
177179

178-
private void FolderWidget_LibraryCardInvoked(object sender, LibraryCardInvokedEventArgs e)
180+
private void QuickAccessWidget_CardInvoked(object sender, QuickAccessCardInvokedEventArgs e)
179181
{
180182
AppInstance.NavigateWithArguments(FolderSettings.GetLayoutType(e.Path), new NavigationArguments()
181183
{
@@ -184,14 +186,21 @@ private void FolderWidget_LibraryCardInvoked(object sender, LibraryCardInvokedEv
184186
AppInstance.InstanceViewModel.IsPageTypeNotHome = true; // show controls that were hidden on the home page
185187
}
186188

187-
private void FolderWidget_LibraryCardNewPaneInvoked(object sender, LibraryCardInvokedEventArgs e)
189+
private void QuickAccessWidget_CardNewPaneInvoked(object sender, QuickAccessCardInvokedEventArgs e)
188190
{
189191
AppInstance.PaneHolder?.OpenPathInNewPane(e.Path);
190192
}
191193

192-
private async void FolderWidget_LibraryCardPropertiesInvoked(object sender, LibraryCardEventArgs e)
194+
private async void QuickAccessWidget_CardPropertiesInvoked(object sender, QuickAccessCardEventArgs e)
193195
{
194-
await FilePropertiesHelpers.OpenPropertiesWindowAsync(new LibraryItem(e.Library), AppInstance);
196+
ListedItem listedItem = new(null!)
197+
{
198+
ItemPath = e.Item.Path,
199+
ItemNameRaw = e.Item.Text,
200+
PrimaryItemAttribute = StorageItemTypes.Folder,
201+
ItemType = "Folder".GetLocalizedResource(),
202+
};
203+
await FilePropertiesHelpers.OpenPropertiesWindowAsync(listedItem, AppInstance);
195204
}
196205

197206
private void DrivesWidget_DrivesWidgetNewPaneInvoked(object sender, DrivesWidget.DrivesWidgetInvokedEventArgs e)

‎src/Files.Backend/Services/IQuickAccessService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public interface IQuickAccessService
99
/// Gets the list of quick access items
1010
/// </summary>
1111
/// <returns></returns>
12-
Task<List<string>> GetPinnedFoldersAsync();
12+
Task<List<string>> GetPinnedFoldersAsync(bool getRecentItems = false);
1313

1414
/// <summary>
1515
/// Pins a folder to the quick access list

‎src/Files.Backend/Services/Settings/IPreferencesSettingsService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ public interface IPreferencesSettingsService : IBaseSettingsService, INotifyProp
6262
bool AlwaysOpenDualPaneInNewTab { get; set; }
6363

6464
/// <summary>
65-
/// Gets or sets a value indicating whether or not to display the folders widget.
65+
/// Gets or sets a value indicating whether or not to display the quick access widget.
6666
/// </summary>
67-
bool ShowFoldersWidget { get; set; }
67+
bool ShowQuickAccessWidget { get; set; }
6868

6969
/// <summary>
7070
/// Gets or sets a value indicating whether or not to display the recent files widget.

0 commit comments

Comments
 (0)
Please sign in to comment.