Skip to content

Commit 0c58a82

Browse files
authored
Code Quality: Use thread-safe collections in ItemViewModel (#12949)
1 parent 794e7e4 commit 0c58a82

File tree

4 files changed

+323
-21
lines changed

4 files changed

+323
-21
lines changed

src/Files.App/Data/Models/ItemViewModel.cs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using Files.App.Helpers.StorageCache;
55
using Files.App.ViewModels.Previews;
66
using Files.Core.Services.SizeProvider;
7-
using FluentFTP;
87
using LibGit2Sharp;
98
using Microsoft.Extensions.Logging;
109
using Microsoft.UI.Xaml.Data;
@@ -44,7 +43,7 @@ public sealed class ItemViewModel : ObservableObject, IDisposable
4443
private Task? gitProcessQueueAction;
4544

4645
// Files and folders list for manipulating
47-
private List<ListedItem> filesAndFolders;
46+
private ConcurrentCollection<ListedItem> filesAndFolders;
4847
private readonly IJumpListService jumpListService = Ioc.Default.GetRequiredService<IJumpListService>();
4948
private readonly IDialogService dialogService = Ioc.Default.GetRequiredService<IDialogService>();
5049
private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetRequiredService<IUserSettingsService>();
@@ -386,7 +385,7 @@ public bool AreDirectoriesSortedAlongsideFiles
386385
public ItemViewModel(FolderSettingsViewModel folderSettingsViewModel)
387386
{
388387
folderSettings = folderSettingsViewModel;
389-
filesAndFolders = new List<ListedItem>();
388+
filesAndFolders = new ConcurrentCollection<ListedItem>();
390389
FilesAndFolders = new BulkConcurrentObservableCollection<ListedItem>();
391390
operationQueue = new ConcurrentQueue<(uint Action, string FileName)>();
392391
gitChangesQueue = new ConcurrentQueue<uint>();
@@ -425,18 +424,10 @@ private async void RecycleBinItemDeleted(object sender, FileSystemEventArgs e)
425424
if (!Constants.UserEnvironmentPaths.RecycleBinPath.Equals(CurrentFolder?.ItemPath, StringComparison.OrdinalIgnoreCase))
426425
return;
427426

428-
// Get the item that immediately follows matching item to be removed
429-
// If the matching item is the last item, try to get the previous item; otherwise, null
430-
// Case must be ignored since $Recycle.Bin != $RECYCLE.BIN
431-
var itemRemovedIndex = filesAndFolders.FindIndex(x => x.ItemPath.Equals(e.FullPath, StringComparison.OrdinalIgnoreCase));
432-
var nextOfMatchingItem = filesAndFolders.ElementAtOrDefault(itemRemovedIndex + 1 < filesAndFolders.Count ? itemRemovedIndex + 1 : itemRemovedIndex - 1);
433427
var removedItem = await RemoveFileOrFolderAsync(e.FullPath);
434428

435429
if (removedItem is not null)
436430
await ApplySingleFileChangeAsync(removedItem);
437-
438-
if (nextOfMatchingItem is not null)
439-
await RequestSelectionAsync(new List<ListedItem>() { nextOfMatchingItem });
440431
}
441432

442433
private async void RecycleBinItemCreated(object sender, FileSystemEventArgs e)
@@ -735,7 +726,7 @@ void OrderEntries()
735726
if (filesAndFolders.Count == 0)
736727
return;
737728

738-
filesAndFolders = SortingHelper.OrderFileList(filesAndFolders, folderSettings.DirectorySortOption, folderSettings.DirectorySortDirection, folderSettings.SortDirectoriesAlongsideFiles).ToList();
729+
filesAndFolders = new ConcurrentCollection<ListedItem>(SortingHelper.OrderFileList(filesAndFolders, folderSettings.DirectorySortOption, folderSettings.DirectorySortDirection, folderSettings.SortDirectoriesAlongsideFiles));
739730
}
740731

741732
if (NativeWinApiHelper.IsHasThreadAccessPropertyPresent && dispatcherQueue.HasThreadAccess)
@@ -2362,14 +2353,14 @@ public async Task SearchAsync(FolderSearch search)
23622353
var results = new List<ListedItem>();
23632354
search.SearchTick += async (s, e) =>
23642355
{
2365-
filesAndFolders = new List<ListedItem>(results);
2356+
filesAndFolders = new ConcurrentCollection<ListedItem>(results);
23662357
await OrderFilesAndFoldersAsync();
23672358
await ApplyFilesAndFoldersChangesAsync();
23682359
};
23692360

23702361
await search.SearchAsync(results, searchCTS.Token);
23712362

2372-
filesAndFolders = new List<ListedItem>(results);
2363+
filesAndFolders = new ConcurrentCollection<ListedItem>(results);
23732364

23742365
await OrderFilesAndFoldersAsync();
23752366
await ApplyFilesAndFoldersChangesAsync();

src/Files.App/Helpers/StorageItemCollection/BulkConcurrentObservableCollection.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -403,8 +403,8 @@ public void ReplaceRange(int index, IEnumerable<T> items)
403403
{
404404
oldItems = collection.Skip(index).Take(count).ToList();
405405
newItems = items.ToList();
406+
collection.RemoveRange(index, count);
406407
collection.InsertRange(index, newItems);
407-
collection.RemoveRange(index + count, count);
408408
}
409409

410410
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newItems, oldItems, index), false);
@@ -467,15 +467,30 @@ int IList.Add(object? value)
467467
return index;
468468
}
469469

470-
bool IList.Contains(object? value) => Contains((T?)value);
470+
bool IList.Contains(object? value)
471+
{
472+
return Contains((T?)value);
473+
}
471474

472-
int IList.IndexOf(object? value) => IndexOf((T?)value);
475+
int IList.IndexOf(object? value)
476+
{
477+
return IndexOf((T?)value);
478+
}
473479

474-
void IList.Insert(int index, object? value) => Insert(index, (T?)value);
480+
void IList.Insert(int index, object? value)
481+
{
482+
Insert(index, (T?)value);
483+
}
475484

476-
void IList.Remove(object? value) => Remove((T?)value);
485+
void IList.Remove(object? value)
486+
{
487+
Remove((T?)value);
488+
}
477489

478-
void ICollection.CopyTo(Array array, int index) => CopyTo((T[])array, index);
490+
void ICollection.CopyTo(Array array, int index)
491+
{
492+
CopyTo((T[])array, index);
493+
}
479494

480495
private static class EventArgsCache
481496
{

0 commit comments

Comments
 (0)