From d373d8f2630daea37cbd1cb837cc1750606f334f Mon Sep 17 00:00:00 2001 From: miku-666 <74728189+NessieHax@users.noreply.github.com> Date: Thu, 20 Nov 2025 02:46:43 +0100 Subject: [PATCH] Core - Add FileObserver.cs --- PckStudio.Core/IO/FileObserver.cs | 71 ++++++++++++++++++++++++++++ PckStudio.Core/PckStudio.Core.csproj | 1 + 2 files changed, 72 insertions(+) create mode 100644 PckStudio.Core/IO/FileObserver.cs diff --git a/PckStudio.Core/IO/FileObserver.cs b/PckStudio.Core/IO/FileObserver.cs new file mode 100644 index 00000000..7bd207fe --- /dev/null +++ b/PckStudio.Core/IO/FileObserver.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; + +namespace PckStudio.Core.IO +{ + public sealed class FileObserver : IDisposable + { + + private readonly IDictionary _watchers = new Dictionary(); + + public bool AddFileWatcher(string filepath, Action onChange, T value) + => AddFileWatcher(new FileInfo(filepath), onChange, value); + + public bool AddFileWatcher(FileInfo fileInfo, Action onChange, T value) + { + var watcher = new FileSystemWatcher(fileInfo.DirectoryName); + + watcher.NotifyFilter = NotifyFilters.Size | NotifyFilters.CreationTime | NotifyFilters.FileName; + + watcher.Filter = fileInfo.Name; + watcher.EnableRaisingEvents = true; + + watcher.Error += (e, a) => InternalRemoveFileWatcher(Path.Combine(watcher.Path, watcher.Filter), $"ERROR:({a.GetException().Message})"); + watcher.Deleted += (e, a) => InternalRemoveFileWatcher(Path.Combine(watcher.Path, watcher.Filter), "path deleted"); + watcher.Changed += (e, a) => + { + switch (a.ChangeType) + { + case WatcherChangeTypes.Renamed: + case WatcherChangeTypes.Deleted: + InternalRemoveFileWatcher(Path.Combine(watcher.Path, watcher.Filter), $"File {a.ChangeType}"); + return; + case WatcherChangeTypes.Changed: + onChange(value, new FileInfo(a.FullPath)); + break; + } + }; + if (_watchers.ContainsKey(fileInfo.FullName)) + { + Debug.WriteLine($"File watcher for: {fileInfo.FullName} already listening."); + return false; + } + _watchers.Add(fileInfo.FullName, watcher); + Debug.WriteLine($"Added file watcher for: {fileInfo.FullName}."); + return true; + } + + public bool RemoveFileWatcher(FileInfo fileInfo) => RemoveFileWatcher(fileInfo.FullName); + + public bool RemoveFileWatcher(string filepath) => InternalRemoveFileWatcher(filepath, "User"); + + public void Dispose() + { + foreach (KeyValuePair fsw in _watchers) + { + Debug.WriteLine($"Releasing: {fsw.Key}"); + fsw.Value.Dispose(); + } + _watchers.Clear(); + } + + private bool InternalRemoveFileWatcher(string fullpath, string reason = "None") + { + Debug.WriteLine($"Releasing: {fullpath}. Reason: {reason}."); + _watchers[fullpath]?.Dispose(); + return _watchers.Remove(fullpath); + } + } +} diff --git a/PckStudio.Core/PckStudio.Core.csproj b/PckStudio.Core/PckStudio.Core.csproj index c05415ef..5f7291f3 100644 --- a/PckStudio.Core/PckStudio.Core.csproj +++ b/PckStudio.Core/PckStudio.Core.csproj @@ -128,6 +128,7 @@ +