Add Explorer Workbench with hierarchical, off-UI Storage analysis.
Storage queries run in the background with cancellation and covering indexes so switching views no longer freezes the UI. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
95
src/Explorer.Domain/Abstractions/Platform.cs
Normal file
95
src/Explorer.Domain/Abstractions/Platform.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
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<VolumeFingerprint> EnumerateOnlineVolumes();
|
||||
VolumeFingerprint? Probe(string path);
|
||||
bool IsPathReachable(string path);
|
||||
}
|
||||
|
||||
public interface IFileSystemEnumerator
|
||||
{
|
||||
IEnumerable<FileSystemItem> EnumerateChildren(string directoryPath);
|
||||
FileSystemItem? GetItem(string path);
|
||||
IReadOnlyList<FileSystemItem> EnumerateChildrenSafe(string directoryPath, out string? error);
|
||||
}
|
||||
|
||||
public interface IUsnJournal
|
||||
{
|
||||
bool TryQuery(string rootPath, out UsnJournalState state, out string? error);
|
||||
IReadOnlyList<UsnRecord> 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<string> paths, out string? error);
|
||||
bool CopyFileWithProgress(string source, string destination, bool overwrite, IProgress<long>? progress, CancellationToken cancellationToken, out string? error);
|
||||
bool MoveFileWithProgress(string source, string destination, bool overwrite, IProgress<long>? progress, CancellationToken cancellationToken, out string? error);
|
||||
}
|
||||
|
||||
public interface IIconService
|
||||
{
|
||||
byte[]? GetIconPng(string path, bool isDirectory, int size);
|
||||
}
|
||||
Reference in New Issue
Block a user