Skip to content

Commit

Permalink
Auto refresh network folders when content changes (#4999)
Browse files Browse the repository at this point in the history
  • Loading branch information
gave92 authored May 23, 2021
1 parent b22c0aa commit de5dd1b
Showing 1 changed file with 95 additions and 29 deletions.
124 changes: 95 additions & 29 deletions Files/ViewModels/ItemViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.Storage.FileProperties;
using Windows.Storage.Search;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
Expand Down Expand Up @@ -423,8 +424,10 @@ await CoreApplication.MainView.DispatcherQueue.EnqueueAsync(() =>
FilesAndFolders.Remove(item);
if (newIndex != -1)
{
FilesAndFolders.Insert(newIndex, item);
FilesAndFolders.Insert(Math.Min(newIndex, FilesAndFolders.Count), item);
}
IsFolderEmptyTextDisplayed = FilesAndFolders.Count == 0;
DirectoryInfoUpdated?.Invoke(this, EventArgs.Empty);
});
}

Expand Down Expand Up @@ -575,16 +578,16 @@ public async Task GroupOptionsUpdated(CancellationToken token)
{
try
{
try
{
// Conflicts will occur if re-grouping is run while items are still being enumerated, so wait for enumeration to complete first
await enumFolderSemaphore.WaitAsync(token);
}
catch (OperationCanceledException)
{
return;
}
// Conflicts will occur if re-grouping is run while items are still being enumerated, so wait for enumeration to complete first
await enumFolderSemaphore.WaitAsync(token);
}
catch (OperationCanceledException)
{
return;
}

try
{
FilesAndFolders.BeginBulkOperation();
UpdateGroupOptions();
if (FilesAndFolders.IsGrouped)
Expand Down Expand Up @@ -614,9 +617,9 @@ await CoreApplication.MainView.DispatcherQueue.EnqueueAsync(() =>
FilesAndFolders.EndBulkOperation();
});
}
catch (Exception e)
catch (Exception ex)
{
Debug.WriteLine(e);
NLog.LogManager.GetCurrentClassLogger().Warn(ex, ex.Message);
}
finally
{
Expand Down Expand Up @@ -1085,13 +1088,26 @@ private async Task RapidAddItemsToCollection(string path, bool useCache, Library
storageFolder = res.Result;
}
}
if (await EnumerateItemsFromStandardFolderAsync(path, storageFolder, folderSettings.GetLayoutType(path, false), addFilesCTS.Token, cacheResult, cacheOnly: false, library))
var enumerated = await EnumerateItemsFromStandardFolderAsync(path, storageFolder, folderSettings.GetLayoutType(path, false), addFilesCTS.Token, cacheResult, cacheOnly: false, library);
switch (enumerated)
{
// Is folder synced to cloud storage?
var syncStatus = await CheckCloudDriveSyncStatusAsync(currentStorageFolder?.Item);
PageTypeUpdated?.Invoke(this, new PageTypeUpdatedEventArgs() { IsTypeCloudDrive = syncStatus != CloudDriveSyncStatus.NotSynced && syncStatus != CloudDriveSyncStatus.Unknown });
case 0: // Enumerated with FindFirstFileExFromApp
// Is folder synced to cloud storage?
var syncStatus = await CheckCloudDriveSyncStatusAsync(currentStorageFolder?.Item);
PageTypeUpdated?.Invoke(this, new PageTypeUpdatedEventArgs() { IsTypeCloudDrive = syncStatus != CloudDriveSyncStatus.NotSynced && syncStatus != CloudDriveSyncStatus.Unknown });

WatchForDirectoryChanges(path, syncStatus);
WatchForDirectoryChanges(path, syncStatus);
break;

case 1: // Enumerated with StorageFolder
PageTypeUpdated?.Invoke(this, new PageTypeUpdatedEventArgs() { IsTypeCloudDrive = false });
currentStorageFolder ??= await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderWithPathFromPathAsync(path));
WatchForStorageFolderChanges(currentStorageFolder?.Folder);
break;

case -1: // Enumeration failed
default:
break;
}

var parallelLimit = App.AppSettings.PreemptiveCacheParallelLimit;
Expand Down Expand Up @@ -1169,6 +1185,12 @@ public void CloseWatcher()
CloseHandle(hWatchDir);
}
}
if (watchedItemsOperation != null)
{
itemQueryResult.ContentsChanged -= ItemQueryResult_ContentsChanged;
watchedItemsOperation?.Cancel();
watchedItemsOperation = null;
}
}

public async Task EnumerateItemsFromSpecialFolderAsync(string path)
Expand Down Expand Up @@ -1232,7 +1254,7 @@ await Task.Run(async () =>
}
}

public async Task<bool> EnumerateItemsFromStandardFolderAsync(string path, StorageFolderWithPath storageFolderForGivenPath, Type sourcePageType, CancellationToken cancellationToken, List<string> skipItems, bool cacheOnly = false, LibraryItem library = null)
public async Task<int> EnumerateItemsFromStandardFolderAsync(string path, StorageFolderWithPath storageFolderForGivenPath, Type sourcePageType, CancellationToken cancellationToken, List<string> skipItems, bool cacheOnly = false, LibraryItem library = null)
{
// Flag to use FindFirstFileExFromApp or StorageFolder enumeration
bool enumFromStorageFolder =
Expand All @@ -1248,7 +1270,7 @@ public async Task<bool> EnumerateItemsFromStandardFolderAsync(string path, Stora
{
if (storageFolderForGivenPath == null)
{
return false;
return -1;
}
rootFolder = storageFolderForGivenPath.Folder;
enumFromStorageFolder = true;
Expand All @@ -1257,7 +1279,7 @@ public async Task<bool> EnumerateItemsFromStandardFolderAsync(string path, Stora
{
if (cacheOnly)
{
return false;
return -1;
}

if (res == FileSystemStatusCode.Unauthorized)
Expand All @@ -1266,19 +1288,19 @@ public async Task<bool> EnumerateItemsFromStandardFolderAsync(string path, Stora
await DialogDisplayHelper.ShowDialogAsync(
"AccessDeniedDeleteDialog/Title".GetLocalized(),
"SubDirectoryAccessDenied".GetLocalized());
return false;
return -1;
}
else if (res == FileSystemStatusCode.NotFound)
{
await DialogDisplayHelper.ShowDialogAsync(
"FolderNotFoundDialog/Title".GetLocalized(),
"FolderNotFoundDialog/Text".GetLocalized());
return false;
return -1;
}
else
{
await DialogDisplayHelper.ShowDialogAsync("DriveUnpluggedDialog/Title".GetLocalized(), res.ErrorCode.ToString());
return false;
return -1;
}
}

Expand Down Expand Up @@ -1341,7 +1363,7 @@ await DialogDisplayHelper.ShowDialogAsync(
CurrentFolder = currentFolder;
}
await EnumFromStorageFolderAsync(path, currentFolder, rootFolder, storageFolderForGivenPath, sourcePageType, cancellationToken, skipItems, cacheOnly);
return true;
return 1;
}
else
{
Expand Down Expand Up @@ -1409,12 +1431,12 @@ await DialogDisplayHelper.ShowDialogAsync(
{
await DialogDisplayHelper.ShowDialogAsync("DriveUnpluggedDialog/Title".GetLocalized(), "");
}
return false;
return -1;
}
else if (hFile.ToInt64() == -1)
{
await EnumFromStorageFolderAsync(path, currentFolder, rootFolder, storageFolderForGivenPath, sourcePageType, cancellationToken, skipItems, cacheOnly);
return false;
return 1;
}
else
{
Expand Down Expand Up @@ -1459,7 +1481,7 @@ await DialogDisplayHelper.ShowDialogAsync(
await fileListCache.SaveFileListToCache(path, null);
}
}
return true;
return 0;
}
}
}
Expand Down Expand Up @@ -1553,6 +1575,50 @@ private async Task<CloudDriveSyncStatus> CheckCloudDriveSyncStatusAsync(IStorage
return (CloudDriveSyncStatus)syncStatus;
}

private StorageItemQueryResult itemQueryResult;

private IAsyncOperation<IReadOnlyList<IStorageItem>> watchedItemsOperation;

private async void WatchForStorageFolderChanges(StorageFolder rootFolder)
{
if (rootFolder == null)
{
return;
}
await Task.Run(() =>
{
var options = new QueryOptions()
{
FolderDepth = FolderDepth.Shallow,
IndexerOption = IndexerOption.OnlyUseIndexerAndOptimizeForIndexedProperties
};
options.SetPropertyPrefetch(PropertyPrefetchOptions.None, null);
options.SetThumbnailPrefetch(ThumbnailMode.ListView, 0, ThumbnailOptions.ReturnOnlyIfCached);
itemQueryResult = rootFolder.CreateItemQueryWithOptions(options);
itemQueryResult.ContentsChanged += ItemQueryResult_ContentsChanged;
watchedItemsOperation = itemQueryResult.GetItemsAsync(0, 1); // Just get one item to start getting notifications
});
}

private async void ItemQueryResult_ContentsChanged(IStorageQueryResultBase sender, object args)
{
//query options have to be reapplied otherwise old results are returned
var options = new QueryOptions()
{
FolderDepth = FolderDepth.Shallow,
IndexerOption = IndexerOption.OnlyUseIndexerAndOptimizeForIndexedProperties
};
options.SetPropertyPrefetch(PropertyPrefetchOptions.None, null);
options.SetThumbnailPrefetch(ThumbnailMode.ListView, 0, ThumbnailOptions.ReturnOnlyIfCached);

sender.ApplyNewQueryOptions(options);

await CoreApplication.MainView.DispatcherQueue.EnqueueAsync(() =>
{
RefreshItems(null);
});
}

private void WatchForDirectoryChanges(string path, CloudDriveSyncStatus syncStatus)
{
Debug.WriteLine("WatchForDirectoryChanges: {0}", path);
Expand Down Expand Up @@ -1901,7 +1967,7 @@ private async Task UpdateFileOrFolderAsync(string path)

try
{
var matchingItem = filesAndFolders.FirstOrDefault(x => x.ItemPath.Equals(path));
var matchingItem = filesAndFolders.FirstOrDefault(x => x.ItemPath.Equals(path, StringComparison.OrdinalIgnoreCase));

if (matchingItem != null)
{
Expand Down Expand Up @@ -1946,7 +2012,7 @@ public async Task<ListedItem> RemoveFileOrFolderAsync(string path)

try
{
var matchingItem = filesAndFolders.FirstOrDefault(x => x.ItemPath.Equals(path));
var matchingItem = filesAndFolders.FirstOrDefault(x => x.ItemPath.Equals(path, StringComparison.OrdinalIgnoreCase));

if (matchingItem != null)
{
Expand Down

0 comments on commit de5dd1b

Please sign in to comment.