namespace Explorer.Domain.Abstractions; public interface IClock { DateTimeOffset UtcNow { get; } } public sealed class SystemClock : IClock { public DateTimeOffset UtcNow => DateTimeOffset.UtcNow; } public interface IAppEnvironment { string DataDirectory { get; } string DatabasePath { get; } string LogDirectory { get; } } public interface IVolumeService { IReadOnlyList EnumerateOnlineVolumes(); VolumeFingerprint? Probe(string path); VolumeSpace GetSpace(string path); bool IsPathReachable(string path); } public interface IFileSystemEnumerator { IEnumerable EnumerateChildren(string directoryPath); FileSystemItem? GetItem(string path); IReadOnlyList EnumerateChildrenSafe(string directoryPath, out string? error); IEnumerable EnumerateChildrenStreaming( string directoryPath, FileEnumerationSink sink, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(sink); cancellationToken.ThrowIfCancellationRequested(); var items = EnumerateChildrenSafe(directoryPath, out var error); sink.Error = error; return items; } } public interface IUsnJournal { bool TryQuery(string rootPath, out UsnJournalState state, out string? error); IReadOnlyList Read(string rootPath, UsnJournalState from, int maxRecords, out UsnJournalState next, out UsnReadStatus status); } public sealed class UsnJournalState { public long JournalId { get; init; } public long NextUsn { get; init; } } public enum UsnReadStatus { Ok, Unavailable, JournalReset, AccessDenied, Error } public sealed class UsnRecord { public long FileReferenceNumber { get; init; } public long ParentFileReferenceNumber { get; init; } public long Usn { get; init; } public required string FileName { get; init; } public int Reason { get; init; } public int FileAttributes { get; init; } public bool IsDirectory => (FileAttributes & AttributeFlags.Directory) != 0; public bool IsCreate => (Reason & UsnReasons.FileCreate) != 0; public bool IsDelete => (Reason & UsnReasons.FileDelete) != 0; public bool IsRenameOld => (Reason & UsnReasons.RenameOldName) != 0; public bool IsRenameNew => (Reason & UsnReasons.RenameNewName) != 0; public bool IsDataChange => (Reason & (UsnReasons.DataOverwrite | UsnReasons.DataExtend | UsnReasons.DataTruncation | UsnReasons.BasicInfoChange)) != 0; } public static class UsnReasons { public const int DataOverwrite = 0x00000001; public const int DataExtend = 0x00000002; public const int DataTruncation = 0x00000004; public const int FileCreate = 0x00000100; public const int FileDelete = 0x00000200; public const int RenameOldName = 0x00001000; public const int RenameNewName = 0x00002000; public const int BasicInfoChange = 0x00008000; public const int Close = unchecked((int)0x80000000); } public interface IShellFileOperations { void Open(string path); bool DeleteToRecycleBin(IReadOnlyList paths, out string? error); bool Delete(IReadOnlyList paths, bool recycle, out string? error); bool CreateShortcut(string targetPath, string shortcutPath, out string? error); bool CopyFileWithProgress(string source, string destination, bool overwrite, IProgress? progress, CancellationToken cancellationToken, out string? error, Func? pauseRequested = null); bool MoveFileWithProgress(string source, string destination, bool overwrite, IProgress? progress, CancellationToken cancellationToken, out string? error, Func? pauseRequested = null); bool EmptyRecycleBin(out string? error); } public interface IIconService { byte[]? GetIconPng(string path, bool isDirectory, int size); }