7
7
using Files . App . Filesystem ;
8
8
using Files . App . Helpers ;
9
9
using Files . App . Helpers . XamlHelpers ;
10
+ using Files . App . ServicesImplementation ;
10
11
using Files . App . ViewModels . Widgets ;
11
12
using Files . Backend . Services . Settings ;
12
13
using Microsoft . UI . Xaml ;
15
16
using Microsoft . UI . Xaml . Input ;
16
17
using Microsoft . UI . Xaml . Media . Imaging ;
17
18
using System ;
19
+ using System . Collections . Generic ;
18
20
using System . Collections . ObjectModel ;
19
21
using System . ComponentModel ;
22
+ using System . IO ;
20
23
using System . Linq ;
24
+ using System . Net . Sockets ;
21
25
using System . Runtime . CompilerServices ;
22
26
using System . Threading . Tasks ;
23
27
using System . Windows . Input ;
28
+ using Vanara ;
24
29
using Windows . Storage ;
25
30
using Windows . System ;
26
31
using Windows . UI . Core ;
27
32
28
33
namespace Files . App . UserControls . Widgets
29
34
{
30
- public class LibraryCardEventArgs : EventArgs
35
+ public class QuickAccessCardEventArgs : EventArgs
31
36
{
32
- public LibraryLocationItem Library { get ; set ; }
37
+ public LocationItem Item { get ; set ; }
33
38
}
34
39
35
- public class LibraryCardInvokedEventArgs : EventArgs
40
+ public class QuickAccessCardInvokedEventArgs : EventArgs
36
41
{
37
42
public string Path { get ; set ; }
38
43
}
39
44
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
+
40
58
public class FolderCardItem : ObservableObject , IWidgetCardItem < LocationItem >
41
59
{
42
60
private BitmapImage thumbnail ;
@@ -56,18 +74,20 @@ public BitmapImage Thumbnail
56
74
public string Path { get ; set ; }
57
75
public ICommand SelectCommand { get ; set ; }
58
76
public string Text { get ; set ; }
77
+ public bool IsPinned { get ; set ; }
59
78
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 )
61
80
{
62
81
Item = item ;
63
82
}
64
83
65
- public FolderCardItem ( string text )
84
+ public FolderCardItem ( string text , bool isPinned )
66
85
{
67
86
if ( ! string . IsNullOrWhiteSpace ( text ) )
68
87
{
69
88
Text = text ;
70
89
AutomationProperties = Text ;
90
+ IsPinned = isPinned ;
71
91
}
72
92
}
73
93
@@ -84,43 +104,45 @@ public async Task LoadCardThumbnailAsync()
84
104
}
85
105
}
86
106
87
- public sealed partial class FolderWidget : UserControl , IWidgetItemModel , INotifyPropertyChanged
107
+ public sealed partial class QuickAccessWidget : UserControl , IWidgetItemModel , INotifyPropertyChanged
88
108
{
89
109
private IUserSettingsService UserSettingsService { get ; } = Ioc . Default . GetRequiredService < IUserSettingsService > ( ) ;
90
110
111
+ private readonly IQuickAccessService QuickAccessService = Ioc . Default . GetRequiredService < IQuickAccessService > ( ) ;
112
+
91
113
public ObservableCollection < FolderCardItem > ItemsAdded = new ( ) ;
92
114
93
115
private bool showMultiPaneControls ;
94
116
95
- public FolderWidget ( )
117
+ public QuickAccessWidget ( )
96
118
{
97
119
InitializeComponent ( ) ;
98
120
99
- LibraryCardCommand = new AsyncRelayCommand < FolderCardItem > ( OpenLibraryCard ) ;
121
+ QuickAccessCardCommand = new AsyncRelayCommand < FolderCardItem > ( OpenCard ) ;
100
122
101
- Loaded += FolderWidget_Loaded ;
102
- Unloaded += FolderWidget_Unloaded ;
123
+ Loaded += QuickAccessWidget_Loaded ;
124
+ Unloaded += QuickAccessWidget_Unloaded ;
103
125
}
104
126
105
- public delegate void LibraryCardInvokedEventHandler ( object sender , LibraryCardInvokedEventArgs e ) ;
127
+ public delegate void LibraryCardInvokedEventHandler ( object sender , QuickAccessCardInvokedEventArgs e ) ;
106
128
107
- public delegate void LibraryCardNewPaneInvokedEventHandler ( object sender , LibraryCardInvokedEventArgs e ) ;
129
+ public delegate void LibraryCardNewPaneInvokedEventHandler ( object sender , QuickAccessCardInvokedEventArgs e ) ;
108
130
109
- public delegate void LibraryCardPropertiesInvokedEventHandler ( object sender , LibraryCardEventArgs e ) ;
131
+ public delegate void LibraryCardPropertiesInvokedEventHandler ( object sender , QuickAccessCardEventArgs e ) ;
110
132
111
- public event LibraryCardInvokedEventHandler LibraryCardInvoked ;
133
+ public event LibraryCardInvokedEventHandler CardInvoked ;
112
134
113
- public event LibraryCardNewPaneInvokedEventHandler LibraryCardNewPaneInvoked ;
135
+ public event LibraryCardNewPaneInvokedEventHandler CardNewPaneInvoked ;
114
136
115
- public event LibraryCardPropertiesInvokedEventHandler LibraryCardPropertiesInvoked ;
137
+ public event LibraryCardPropertiesInvokedEventHandler CardPropertiesInvoked ;
116
138
117
- public event EventHandler FolderWidgethowMultiPaneControlsInvoked ;
139
+ public event EventHandler QuickAccessWidgetShowMultiPaneControlsInvoked ;
118
140
119
141
public event PropertyChangedEventHandler PropertyChanged ;
120
142
121
- public bool IsWidgetSettingEnabled => UserSettingsService . PreferencesSettingsService . ShowFoldersWidget ;
143
+ public bool IsWidgetSettingEnabled => UserSettingsService . PreferencesSettingsService . ShowQuickAccessWidget ;
122
144
123
- public ICommand LibraryCardCommand { get ; }
145
+ public ICommand QuickAccessCardCommand { get ; }
124
146
125
147
public ICommand ShowCreateNewLibraryDialogCommand { get ; } = new RelayCommand ( LibraryManager . ShowCreateNewLibraryDialog ) ;
126
148
@@ -130,7 +152,7 @@ public bool ShowMultiPaneControls
130
152
{
131
153
get
132
154
{
133
- FolderWidgethowMultiPaneControlsInvoked ? . Invoke ( this , EventArgs . Empty ) ;
155
+ QuickAccessWidgetShowMultiPaneControlsInvoked ? . Invoke ( this , EventArgs . Empty ) ;
134
156
135
157
return showMultiPaneControls ;
136
158
}
@@ -144,64 +166,85 @@ public bool ShowMultiPaneControls
144
166
}
145
167
}
146
168
147
- public string WidgetName => nameof ( FolderWidget ) ;
169
+ public string WidgetName => nameof ( QuickAccessWidget ) ;
148
170
149
- public string AutomationProperties => "FolderWidgetAutomationProperties/Name " . GetLocalizedResource ( ) ;
171
+ public string AutomationProperties => "QuickAccess " . GetLocalizedResource ( ) ;
150
172
151
- public string WidgetHeader => "Folders " . GetLocalizedResource ( ) ;
173
+ public string WidgetHeader => "QuickAccess " . GetLocalizedResource ( ) ;
152
174
153
- private async void FolderWidget_Loaded ( object sender , RoutedEventArgs e )
175
+ private async void ModifyItem ( object ? sender , ModifyQuickAccessEventArgs ? e )
154
176
{
155
- Loaded -= FolderWidget_Loaded ;
177
+ if ( e is null )
178
+ return ;
156
179
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 )
163
181
{
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 )
183
213
{
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 ;
187
223
188
224
var cardLoadTasks = ItemsAdded . Select ( cardItem => cardItem . LoadCardThumbnailAsync ( ) ) ;
189
225
await Task . WhenAll ( cardLoadTasks ) ;
190
226
}
191
227
192
- private void FolderWidget_Unloaded ( object sender , RoutedEventArgs e )
228
+ private void QuickAccessWidget_Unloaded ( object sender , RoutedEventArgs e )
193
229
{
194
- Unloaded -= FolderWidget_Unloaded ;
230
+ Unloaded -= QuickAccessWidget_Unloaded ;
231
+ App . QuickAccessManager . UpdateQuickAccessWidget += ModifyItem ;
195
232
}
196
233
197
234
private void MenuFlyout_Opening ( object sender , object e )
198
235
{
199
236
var newPaneMenuItem = ( sender as MenuFlyout ) . Items . SingleOrDefault ( x => x . Name == "OpenInNewPane" ) ;
200
237
// eg. an empty library doesn't have OpenInNewPane context menu item
201
238
if ( newPaneMenuItem is not null )
202
- {
203
239
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 ;
205
248
}
206
249
207
250
private void NotifyPropertyChanged ( [ CallerMemberName ] string propertyName = "" )
@@ -212,7 +255,7 @@ private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
212
255
private void OpenInNewPane_Click ( object sender , RoutedEventArgs e )
213
256
{
214
257
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 } ) ;
216
259
}
217
260
218
261
private async void OpenInNewTab_Click ( object sender , RoutedEventArgs e )
@@ -236,24 +279,44 @@ private async void OpenInNewWindow_Click(object sender, RoutedEventArgs e)
236
279
await NavigationHelpers . OpenPathInNewWindowAsync ( item . Path ) ;
237
280
}
238
281
239
- private void OpenLibraryProperties_Click ( object sender , RoutedEventArgs e )
282
+ private void OpenProperties_Click ( object sender , RoutedEventArgs e )
240
283
{
241
284
var presenter = DependencyObjectHelpers . FindParent < MenuFlyoutPresenter > ( ( MenuFlyoutItem ) sender ) ;
242
285
var flyoutParent = presenter ? . Parent as Popup ;
243
286
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 )
245
288
return ;
246
289
247
290
EventHandler < object > flyoutClosed = null ! ;
248
291
flyoutClosed = ( s , e ) =>
249
292
{
250
293
flyoutParent . Closed -= flyoutClosed ;
251
- LibraryCardPropertiesInvoked ? . Invoke ( this , new LibraryCardEventArgs { Library = ( propertiesItem . Item as LibraryLocationItem ) ! } ) ;
294
+ CardPropertiesInvoked ? . Invoke ( this , new QuickAccessCardEventArgs { Item = propertiesItem . Item } ) ;
252
295
} ;
253
296
flyoutParent . Closed += flyoutClosed ;
254
297
}
255
298
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 )
257
320
{
258
321
if ( string . IsNullOrEmpty ( item . Path ) )
259
322
{
@@ -271,7 +334,7 @@ private Task OpenLibraryCard(FolderCardItem item)
271
334
return NavigationHelpers . OpenPathInNewTab ( item . Path ) ;
272
335
}
273
336
274
- LibraryCardInvoked ? . Invoke ( this , new LibraryCardInvokedEventArgs { Path = item . Path } ) ;
337
+ CardInvoked ? . Invoke ( this , new QuickAccessCardInvokedEventArgs { Path = item . Path } ) ;
275
338
276
339
return Task . CompletedTask ;
277
340
}
0 commit comments