4
4
using Files . Uwp . Filesystem ;
5
5
using Files . Uwp . Helpers ;
6
6
using Files . Backend . Services . Settings ;
7
- using Files . Uwp . UserControls ;
8
7
using Files . Uwp . ViewModels ;
9
8
using CommunityToolkit . Mvvm . DependencyInjection ;
10
9
using Microsoft . Toolkit . Uwp ;
18
17
using Windows . ApplicationModel . Core ;
19
18
using Windows . Storage ;
20
19
using Windows . UI . Xaml . Media . Imaging ;
20
+ using System . Collections . Specialized ;
21
21
22
22
namespace Files . Uwp . DataModels
23
23
{
@@ -27,22 +27,32 @@ public class SidebarPinnedModel
27
27
28
28
private SidebarPinnedController controller ;
29
29
30
- private LocationItem favoriteSection ;
31
-
32
30
[ JsonIgnore ]
33
31
public MainViewModel MainViewModel => App . MainViewModel ;
34
32
35
33
[ JsonProperty ( "items" ) ]
36
34
public List < string > FavoriteItems { get ; set ; } = new List < string > ( ) ;
37
35
36
+ private readonly List < INavigationControlItem > favoriteList = new List < INavigationControlItem > ( ) ;
37
+
38
+ public IReadOnlyList < INavigationControlItem > Favorites
39
+ {
40
+ get
41
+ {
42
+ lock ( favoriteList )
43
+ {
44
+ return favoriteList . ToList ( ) . AsReadOnly ( ) ;
45
+ }
46
+ }
47
+ }
48
+
38
49
public void SetController ( SidebarPinnedController controller )
39
50
{
40
51
this . controller = controller ;
41
52
}
42
53
43
54
public SidebarPinnedModel ( )
44
55
{
45
- favoriteSection = SidebarControl . SideBarItems . FirstOrDefault ( x => x . Text == "SidebarFavorites" . GetLocalized ( ) ) as LocationItem ;
46
56
}
47
57
48
58
/// <summary>
@@ -57,32 +67,6 @@ public void AddDefaultItems()
57
67
FavoriteItems . Add ( udp . Documents ) ;
58
68
}
59
69
60
- private void RemoveFavoritesSideBarSection ( )
61
- {
62
- try
63
- {
64
- var item = ( from n in SidebarControl . SideBarItems where n . Text . Equals ( "SidebarFavorites" . GetLocalized ( ) ) select n ) . FirstOrDefault ( ) ;
65
- if ( ! UserSettingsService . AppearanceSettingsService . ShowFavoritesSection && item != null )
66
- {
67
- SidebarControl . SideBarItems . Remove ( item ) ;
68
- }
69
- }
70
- catch ( Exception )
71
- { }
72
- }
73
-
74
- public async void UpdateFavoritesSectionVisibility ( )
75
- {
76
- if ( UserSettingsService . AppearanceSettingsService . ShowFavoritesSection )
77
- {
78
- await AddAllItemsToSidebar ( ) ;
79
- }
80
- else
81
- {
82
- RemoveFavoritesSideBarSection ( ) ;
83
- }
84
- }
85
-
86
70
/// <summary>
87
71
/// Gets the items from the navigation page
88
72
/// </summary>
@@ -97,20 +81,11 @@ public List<string> GetItems()
97
81
/// <param name="item">Item to remove</param>
98
82
public async void AddItem ( string item )
99
83
{
100
- await SidebarControl . SideBarItemsSemaphore . WaitAsync ( ) ;
101
-
102
- try
103
- {
104
- if ( ! string . IsNullOrEmpty ( item ) && ! FavoriteItems . Contains ( item ) )
105
- {
106
- FavoriteItems . Add ( item ) ;
107
- await AddItemToSidebarAsync ( item ) ;
108
- Save ( ) ;
109
- }
110
- }
111
- finally
84
+ if ( ! string . IsNullOrEmpty ( item ) && ! FavoriteItems . Contains ( item ) )
112
85
{
113
- SidebarControl . SideBarItemsSemaphore . Release ( ) ;
86
+ FavoriteItems . Add ( item ) ;
87
+ await AddItemToSidebarAsync ( item ) ;
88
+ Save ( ) ;
114
89
}
115
90
}
116
91
@@ -134,18 +109,20 @@ public async Task ShowHideRecycleBinItemAsync(bool show)
134
109
} ;
135
110
// Add recycle bin to sidebar, title is read from LocalSettings (provided by the fulltrust process)
136
111
// TODO: the very first time the app is launched localized name not available
137
- if ( ! favoriteSection . ChildItems . Any ( x => x . Path == CommonPaths . RecycleBinPath ) )
112
+ if ( ! favoriteList . Any ( x => x . Path == CommonPaths . RecycleBinPath ) )
138
113
{
139
- await CoreApplication . MainView . DispatcherQueue . EnqueueAsync ( ( ) => favoriteSection . ChildItems . Add ( recycleBinItem ) ) ;
114
+ favoriteList . Add ( recycleBinItem ) ;
115
+ controller . DataChanged ? . Invoke ( SectionType . Favorites , new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Add , recycleBinItem ) ) ;
140
116
}
141
117
}
142
118
else
143
119
{
144
- foreach ( INavigationControlItem item in favoriteSection . ChildItems . ToList ( ) )
120
+ foreach ( INavigationControlItem item in favoriteList . ToList ( ) )
145
121
{
146
122
if ( item is LocationItem && item . Path == CommonPaths . RecycleBinPath )
147
123
{
148
- await CoreApplication . MainView . DispatcherQueue . EnqueueAsync ( ( ) => favoriteSection . ChildItems . Remove ( item ) ) ;
124
+ favoriteList . Remove ( item ) ;
125
+ controller . DataChanged ? . Invoke ( SectionType . Favorites , new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Remove , item ) ) ;
149
126
}
150
127
}
151
128
}
@@ -188,16 +165,12 @@ public bool MoveItem(INavigationControlItem locationItem, int oldIndex, int newI
188
165
{
189
166
FavoriteItems . RemoveAt ( oldIndex - 1 ) ;
190
167
FavoriteItems . Insert ( newIndex - 1 , locationItem . Path ) ;
191
- favoriteSection . ChildItems . RemoveAt ( oldIndex ) ;
192
- favoriteSection . ChildItems . Insert ( newIndex , locationItem ) ;
168
+ favoriteList . RemoveAt ( oldIndex ) ;
169
+ favoriteList . Insert ( newIndex , locationItem ) ;
170
+ controller . DataChanged ? . Invoke ( SectionType . Favorites , new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Move , locationItem , newIndex , oldIndex ) ) ;
193
171
Save ( ) ;
194
172
}
195
- catch ( Exception ex ) when (
196
- ex is ArgumentException // Pinned item was invalid
197
- || ex is FileNotFoundException // Pinned item was deleted
198
- || ex is System . Runtime . InteropServices . COMException // Pinned item's drive was ejected
199
- || ( uint ) ex . HResult == 0x8007000F // The system cannot find the drive specified
200
- || ( uint ) ex . HResult == 0x800700A1 ) // The specified path is invalid (usually an mtp device was disconnected)
173
+ catch ( Exception ex )
201
174
{
202
175
Debug . WriteLine ( $ "An error occurred while moving pinned items in the Favorites sidebar section. { ex . Message } ") ;
203
176
FavoriteItems = sidebarItemsBackup ;
@@ -238,7 +211,7 @@ public void SwapItems(INavigationControlItem firstLocationItem, INavigationContr
238
211
/// <returns>Index of the item</returns>
239
212
public int IndexOfItem ( INavigationControlItem locationItem )
240
213
{
241
- return favoriteSection . ChildItems . IndexOf ( locationItem ) ;
214
+ return favoriteList . FindIndex ( x => x . Path == locationItem . Path ) ;
242
215
}
243
216
244
217
/// <summary>
@@ -266,8 +239,8 @@ public async Task AddItemToSidebarAsync(string path)
266
239
{
267
240
var item = await FilesystemTasks . Wrap ( ( ) => DrivesManager . GetRootFromPathAsync ( path ) ) ;
268
241
var res = await FilesystemTasks . Wrap ( ( ) => StorageFileExtensions . DangerousGetFolderFromPathAsync ( path , item ) ) ;
269
- var lastItem = favoriteSection . ChildItems . LastOrDefault ( x => x . ItemType == NavigationControlItemType . Location && ! x . Path . Equals ( CommonPaths . RecycleBinPath ) ) ;
270
- int insertIndex = lastItem != null ? favoriteSection . ChildItems . IndexOf ( lastItem ) + 1 : 0 ;
242
+ var lastItem = favoriteList . LastOrDefault ( x => x . ItemType == NavigationControlItemType . Location && ! x . Path . Equals ( CommonPaths . RecycleBinPath ) ) ;
243
+ int insertIndex = lastItem != null ? favoriteList . IndexOf ( lastItem ) + 1 : 0 ;
271
244
var locationItem = new LocationItem
272
245
{
273
246
Font = MainViewModel . FontName ,
@@ -314,9 +287,10 @@ public async Task AddItemToSidebarAsync(string path)
314
287
Debug . WriteLine ( $ "Pinned item was invalid { res . ErrorCode } , item: { path } ") ;
315
288
}
316
289
317
- if ( ! favoriteSection . ChildItems . Any ( x => x . Path == locationItem . Path ) )
290
+ if ( ! favoriteList . Any ( x => x . Path == locationItem . Path ) )
318
291
{
319
- await CoreApplication . MainView . DispatcherQueue . EnqueueAsync ( ( ) => favoriteSection . ChildItems . Insert ( insertIndex , locationItem ) ) ;
292
+ favoriteList . Insert ( insertIndex , locationItem ) ;
293
+ controller . DataChanged ? . Invoke ( SectionType . Favorites , new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Add , locationItem , insertIndex ) ) ;
320
294
}
321
295
}
322
296
@@ -326,12 +300,13 @@ public async Task AddItemToSidebarAsync(string path)
326
300
/// <param name="section">The section.</param>
327
301
private void AddLocationItemToSidebar ( LocationItem section )
328
302
{
329
- var lastItem = favoriteSection . ChildItems . LastOrDefault ( x => x . ItemType == NavigationControlItemType . Location && ! x . Path . Equals ( CommonPaths . RecycleBinPath ) ) ;
330
- int insertIndex = lastItem != null ? favoriteSection . ChildItems . IndexOf ( lastItem ) + 1 : 0 ;
303
+ var lastItem = favoriteList . LastOrDefault ( x => x . ItemType == NavigationControlItemType . Location && ! x . Path . Equals ( CommonPaths . RecycleBinPath ) ) ;
304
+ int insertIndex = lastItem != null ? favoriteList . IndexOf ( lastItem ) + 1 : 0 ;
331
305
332
- if ( ! favoriteSection . ChildItems . Any ( x => x . Section == section . Section ) )
306
+ if ( ! favoriteList . Any ( x => x . Section == section . Section ) )
333
307
{
334
- favoriteSection . ChildItems . Insert ( insertIndex , section ) ;
308
+ favoriteList . Insert ( insertIndex , section ) ;
309
+ controller . DataChanged ? . Invoke ( SectionType . Favorites , new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Add , section , insertIndex ) ) ;
335
310
}
336
311
}
337
312
@@ -345,61 +320,28 @@ public async Task AddAllItemsToSidebar()
345
320
return ;
346
321
}
347
322
348
- await SidebarControl . SideBarItemsSemaphore . WaitAsync ( ) ;
349
- try
323
+ var homeSection = new LocationItem ( )
350
324
{
351
- var homeSection = new LocationItem ( )
352
- {
353
- Text = "Home" . GetLocalized ( ) ,
354
- Section = SectionType . Home ,
355
- MenuOptions = new ContextMenuOptions
356
- {
357
- IsLocationItem = true
358
- } ,
359
- Font = MainViewModel . FontName ,
360
- IsDefaultLocation = true ,
361
- Icon = await CoreApplication . MainView . DispatcherQueue . EnqueueAsync ( ( ) => new BitmapImage ( new Uri ( "ms-appx:///Assets/FluentIcons/Home.png" ) ) ) ,
362
- Path = "Home" . GetLocalized ( )
363
- } ;
364
- favoriteSection ??= new LocationItem ( )
365
- {
366
- Text = "SidebarFavorites" . GetLocalized ( ) ,
367
- Section = SectionType . Favorites ,
368
- MenuOptions = new ContextMenuOptions
369
- {
370
- ShowHideSection = true
371
- } ,
372
- SelectsOnInvoked = false ,
373
- Icon = await CoreApplication . MainView . DispatcherQueue . EnqueueAsync ( ( ) => UIHelpers . GetIconResource ( Constants . Shell32 . QuickAccess ) ) ,
374
- Font = MainViewModel . FontName ,
375
- ChildItems = new BulkConcurrentObservableCollection < INavigationControlItem > ( )
376
- } ;
377
-
378
- if ( homeSection != null )
379
- {
380
- AddLocationItemToSidebar ( homeSection ) ;
381
- }
382
-
383
- if ( ! SidebarControl . SideBarItems . Any ( x => x . Text == "SidebarFavorites" . GetLocalized ( ) ) )
384
- {
385
- SidebarControl . SideBarItems . BeginBulkOperation ( ) ;
386
- var index = 0 ; // First section
387
- SidebarControl . SideBarItems . Insert ( index , favoriteSection ) ;
388
- await CoreApplication . MainView . DispatcherQueue . EnqueueAsync ( ( ) => SidebarControl . SideBarItems . EndBulkOperation ( ) ) ;
389
- }
390
-
391
- for ( int i = 0 ; i < FavoriteItems . Count ; i ++ )
325
+ Text = "Home" . GetLocalized ( ) ,
326
+ Section = SectionType . Home ,
327
+ MenuOptions = new ContextMenuOptions
392
328
{
393
- string path = FavoriteItems [ i ] ;
394
- await AddItemToSidebarAsync ( path ) ;
395
- }
329
+ IsLocationItem = true
330
+ } ,
331
+ Font = MainViewModel . FontName ,
332
+ IsDefaultLocation = true ,
333
+ Icon = await CoreApplication . MainView . DispatcherQueue . EnqueueAsync ( ( ) => new BitmapImage ( new Uri ( "ms-appx:///Assets/FluentIcons/Home.png" ) ) ) ,
334
+ Path = "Home" . GetLocalized ( )
335
+ } ;
336
+ AddLocationItemToSidebar ( homeSection ) ;
396
337
397
- await ShowHideRecycleBinItemAsync ( UserSettingsService . AppearanceSettingsService . PinRecycleBinToSidebar ) ;
398
- }
399
- finally
338
+ for ( int i = 0 ; i < FavoriteItems . Count ; i ++ )
400
339
{
401
- SidebarControl . SideBarItemsSemaphore . Release ( ) ;
340
+ string path = FavoriteItems [ i ] ;
341
+ await AddItemToSidebarAsync ( path ) ;
402
342
}
343
+
344
+ await ShowHideRecycleBinItemAsync ( UserSettingsService . AppearanceSettingsService . PinRecycleBinToSidebar ) ;
403
345
}
404
346
405
347
/// <summary>
@@ -409,17 +351,15 @@ public void RemoveStaleSidebarItems()
409
351
{
410
352
// Remove unpinned items from sidebar
411
353
// Reverse iteration to avoid skipping elements while removing
412
- if ( favoriteSection != null )
354
+ for ( int i = favoriteList . Count - 1 ; i >= 0 ; i -- )
413
355
{
414
- for ( int i = favoriteSection . ChildItems . Count - 1 ; i >= 0 ; i -- )
356
+ var childItem = favoriteList [ i ] ;
357
+ if ( childItem is LocationItem item )
415
358
{
416
- var childItem = favoriteSection . ChildItems [ i ] ;
417
- if ( childItem is LocationItem item )
359
+ if ( ! item . IsDefaultLocation && ! FavoriteItems . Contains ( item . Path ) )
418
360
{
419
- if ( ! item . IsDefaultLocation && ! FavoriteItems . Contains ( item . Path ) )
420
- {
421
- favoriteSection . ChildItems . RemoveAt ( i ) ;
422
- }
361
+ favoriteList . RemoveAt ( i ) ;
362
+ controller . DataChanged ? . Invoke ( SectionType . Favorites , new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Remove , item ) ) ;
423
363
}
424
364
}
425
365
}
0 commit comments