diff --git a/src/OwlCore.Storage.csproj b/src/OwlCore.Storage.csproj index 0f592b9..ddf9e7c 100644 --- a/src/OwlCore.Storage.csproj +++ b/src/OwlCore.Storage.csproj @@ -14,7 +14,7 @@ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb Arlo Godfrey - 0.11.0 + 0.11.1 OwlCore The most flexible file system abstraction, ever. Built in partnership with the UWP Community. @@ -23,6 +23,10 @@ LICENSE.txt logo.png +--- 0.11.1 --- +[Fixes] +Fixed an issue where SystemFolderWatcher would not capture any file system events. + --- 0.11.0 --- [New] Added new FileReadExtensions and FileWriteExtensions for reading and writing IFile as text content or byte arrays. @@ -280,4 +284,4 @@ Initial release of OwlCore.Storage. \ - \ No newline at end of file + diff --git a/src/System/IO/SystemFolderWatcher.cs b/src/System/IO/SystemFolderWatcher.cs index e892cdf..1c4b03e 100644 --- a/src/System/IO/SystemFolderWatcher.cs +++ b/src/System/IO/SystemFolderWatcher.cs @@ -12,6 +12,7 @@ namespace OwlCore.Storage.System.IO public class SystemFolderWatcher : IFolderWatcher { private readonly FileSystemWatcher _watcher; + private event NotifyCollectionChangedEventHandler? _collectionChanged; /// /// Creates a new instance of . @@ -43,26 +44,38 @@ private void DetachEvents(FileSystemWatcher watcher) private void OnCreated(object sender, FileSystemEventArgs e) { var newItem = CreateStorableFromPath(e.FullPath); - CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List { newItem })); + _collectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List { newItem })); } private void OnDeleted(object sender, FileSystemEventArgs e) { var oldItem = CreateStorableFromPath(e.FullPath, minimalImplementation: true); - CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new List { oldItem })); + _collectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new List { oldItem })); } private void OnRenamed(object sender, RenamedEventArgs e) { var newItem = CreateStorableFromPath(e.FullPath); - CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List { newItem })); + _collectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List { newItem })); var oldItem = CreateStorableFromPath(e.OldFullPath, minimalImplementation: true); - CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new List { oldItem })); + _collectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new List { oldItem })); } /// - public event NotifyCollectionChangedEventHandler? CollectionChanged; + public event NotifyCollectionChangedEventHandler? CollectionChanged + { + add + { + _collectionChanged += value; + _watcher.EnableRaisingEvents = _collectionChanged is not null; + } + remove + { + _collectionChanged -= value; + _watcher.EnableRaisingEvents = _collectionChanged is not null; + } + } /// public IMutableFolder Folder { get; } @@ -106,7 +119,8 @@ private static IStorable CreateStorableFromPath(string path, bool minimalImpleme return new SystemFile(path); } - throw new ArgumentException($"Could not determine if the path '{path}' is a file or folder."); + // The item is most likely deleted. Return all available information through SimpleStorableItem + return new SimpleStorableItem(id: path, name: Path.GetFileName(path)); } private static bool IsFile(string path) => Path.GetFileName(path) is { } str && str != string.Empty && File.Exists(path); diff --git a/tests/OwlCore.Storage.Tests/SystemIO/IFolderTests.cs b/tests/OwlCore.Storage.Tests/SystemIO/IFolderTests.cs index 37fc3ba..5095032 100644 --- a/tests/OwlCore.Storage.Tests/SystemIO/IFolderTests.cs +++ b/tests/OwlCore.Storage.Tests/SystemIO/IFolderTests.cs @@ -16,7 +16,7 @@ public override Task CreateModifiableFolderAsync() public override Task CreateModifiableFolderWithItems(int fileCount, int folderCount) { var tempFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); - var dir = Directory.CreateDirectory(tempFolder); + _ = Directory.CreateDirectory(tempFolder); for (var i = 0; i < fileCount; i++) { @@ -33,4 +33,51 @@ public override Task CreateModifiableFolderWithItems(int file return Task.FromResult(new SystemFolder(tempFolder)); } + + // Folder Watcher tests + // TODO: Move these to CommonTests. + + [TestMethod] + public async Task FolderWatcherOnFileCreate() + { + var folder = await CreateModifiableFolderAsync(); + + await using var watcher = await folder.GetFolderWatcherAsync(); + var collectionChangedTaskCompletionSource = new TaskCompletionSource(); + watcher.CollectionChanged += (sender, args) => collectionChangedTaskCompletionSource.SetResult(); + + await folder.CreateFileAsync(GetHashCode().ToString(), overwrite: true); + + await collectionChangedTaskCompletionSource.Task; + } + + [TestMethod] + [Timeout(2000)] + public async Task FolderWatcherOnFolderCreate() + { + var folder = await CreateModifiableFolderAsync(); + + await using var watcher = await folder.GetFolderWatcherAsync(); + var collectionChangedTaskCompletionSource = new TaskCompletionSource(); + watcher.CollectionChanged += (sender, args) => collectionChangedTaskCompletionSource.SetResult(); + + await folder.CreateFolderAsync(GetHashCode().ToString(), overwrite: true); + + await collectionChangedTaskCompletionSource.Task; + } + + [TestMethod] + public async Task FolderWatcherOnDelete() + { + var folder = await CreateModifiableFolderWithItems(1, 0); + var existingItem = await folder.GetItemsAsync(StorableType.File).FirstAsync(); + + await using var watcher = await folder.GetFolderWatcherAsync(); + var collectionChangedTaskCompletionSource = new TaskCompletionSource(); + watcher.CollectionChanged += (sender, args) => collectionChangedTaskCompletionSource.SetResult(); + + await folder.DeleteAsync(existingItem); + + await collectionChangedTaskCompletionSource.Task; + } } \ No newline at end of file