Volume size info for sub content providers

This commit is contained in:
2023-09-05 23:12:20 +02:00
parent b998dc5b33
commit ba0b55c733
20 changed files with 92 additions and 41 deletions

View File

@@ -84,7 +84,7 @@ public class ContainerSizeSizeScanProvider : ContentProviderBase, IContainerSize
public override Task<bool> CanHandlePathAsync(NativePath path) public override Task<bool> CanHandlePathAsync(NativePath path)
=> Task.FromResult(path.Path.StartsWith(ContentProviderName)); => Task.FromResult(path.Path.StartsWith(ContentProviderName));
public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => null; public override ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path) => ValueTask.FromResult<VolumeSizeInfo?>(null);
public override ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath) public override ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath)
=> ValueTask.FromResult<NativePath?>(nativePath); => ValueTask.FromResult<NativePath?>(nativePath);

View File

@@ -19,12 +19,12 @@ public class ItemPreviewService : IItemPreviewService
.Map(t => t?.CurrentSelectedItem) .Map(t => t?.CurrentSelectedItem)
.Switch() .Switch()
.Debounce(TimeSpan.FromMilliseconds(250)) .Debounce(TimeSpan.FromMilliseconds(250))
.Map(async (item, _) => .Map(async item =>
item == null item == null
? null ? null
: await Map(item) : await Map(item)
) )
.DistinctUntilChanged(); .DistinctUntilChanged()!;
} }
private async Task<IItemPreviewViewModel?> Map(IItemViewModel itemViewModel) private async Task<IItemPreviewViewModel?> Map(IItemViewModel itemViewModel)

View File

@@ -461,7 +461,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi
var deleteCommand = _serviceProvider.GetRequiredService<FileTime.Core.Command.Delete.DeleteCommand>(); var deleteCommand = _serviceProvider.GetRequiredService<FileTime.Core.Command.Delete.DeleteCommand>();
deleteCommand.HardDelete = command.IsHardDelete; deleteCommand.HardDelete = command.IsHardDelete;
deleteCommand.ItemsToDelete.AddRange(itemsToDelete!); deleteCommand.ItemsToDelete.AddRange(itemsToDelete);
await AddCommandAsync(deleteCommand); await AddCommandAsync(deleteCommand);
_selectedTab?.ClearMarkedItems(); _selectedTab?.ClearMarkedItems();

View File

@@ -53,7 +53,7 @@ public abstract partial class ItemViewModel : IItemViewModel
var displayName = itemViewModelType switch var displayName = itemViewModelType switch
{ {
ItemViewModelType.Main => _appState.RapidTravelTextDebounced.Map(async (s, _) => ItemViewModelType.Main => _appState.RapidTravelTextDebounced.Map(async s =>
_appState.ViewMode.Value != Models.Enums.ViewMode.RapidTravel _appState.ViewMode.Value != Models.Enums.ViewMode.RapidTravel
&& _appState.SelectedTab.Value?.CurrentLocation.Value?.Provider is IItemNameConverterProvider nameConverterProvider && _appState.SelectedTab.Value?.CurrentLocation.Value?.Provider is IItemNameConverterProvider nameConverterProvider
? (IReadOnlyList<ItemNamePart>) await nameConverterProvider.GetItemNamePartsAsync(item) ? (IReadOnlyList<ItemNamePart>) await nameConverterProvider.GetItemNamePartsAsync(item)

View File

@@ -70,13 +70,13 @@ public partial class TabViewModel : ITabViewModel
CurrentItems = CurrentItems =
tab.CurrentItems tab.CurrentItems
.Map((items, _) => .Map(items =>
Task.FromResult<ObservableCollection<IItemViewModel>?>( Task.FromResult<ObservableCollection<IItemViewModel>?>(
items?.Selecting<IItem, IItemViewModel>( items?.Selecting<IItem, IItemViewModel>(
i => MapItemToViewModel(i, ItemViewModelType.Main) i => MapItemToViewModel(i, ItemViewModelType.Main)
) )
) )
); )!;
using var _ = Defer( using var _ = Defer(
() => CurrentItems.Subscribe(c => UpdateConsumer(c, ref _currentItemsConsumer)) () => CurrentItems.Subscribe(c => UpdateConsumer(c, ref _currentItemsConsumer))
@@ -144,9 +144,9 @@ public partial class TabViewModel : ITabViewModel
SelectedsChildren.Subscribe(c => UpdateConsumer(c, ref _selectedsChildrenConsumer)) SelectedsChildren.Subscribe(c => UpdateConsumer(c, ref _selectedsChildrenConsumer))
); );
ParentsChildren = CurrentLocation.Map(async (item, _) => ParentsChildren = CurrentLocation.Map(async item =>
{ {
if (item is null || item.Parent is null) return (ObservableCollection<IItemViewModel>?) null; if (item?.Parent is null) return (ObservableCollection<IItemViewModel>?) null;
var parent = (IContainer) await item.Parent.ResolveAsync(); var parent = (IContainer) await item.Parent.ResolveAsync();
var items = parent.Items var items = parent.Items
@@ -156,7 +156,7 @@ public partial class TabViewModel : ITabViewModel
.Selecting(i => MapItemToViewModel(i, ItemViewModelType.Parent)); .Selecting(i => MapItemToViewModel(i, ItemViewModelType.Parent));
return items; return items;
}); })!;
using var ___ = Defer(() => using var ___ = Defer(() =>
ParentsChildren.Subscribe(c => UpdateConsumer(c, ref _parentsChildrenConsumer)) ParentsChildren.Subscribe(c => UpdateConsumer(c, ref _parentsChildrenConsumer))
); );

View File

@@ -79,7 +79,7 @@ public class SearchContentProvider : ContentProviderBase, ISearchContentProvider
=> Task.FromResult(null as byte[]); => Task.FromResult(null as byte[]);
public override Task<bool> CanHandlePathAsync(NativePath path) => Task.FromResult(path.Path.StartsWith(ContentProviderName)); public override Task<bool> CanHandlePathAsync(NativePath path) => Task.FromResult(path.Path.StartsWith(ContentProviderName));
public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => null; public override ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path) => ValueTask.FromResult<VolumeSizeInfo?>(null);
public override ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath) => throw new NotImplementedException(); public override ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath) => throw new NotImplementedException();
public async Task<ISearchTask> StartSearchAsync(ISearchMatcher matcher, IContainer searchIn) public async Task<ISearchTask> StartSearchAsync(ISearchMatcher matcher, IContainer searchIn)

View File

@@ -24,8 +24,8 @@ public partial class RootViewModel : IRootViewModel
public IAdminElevationManager AdminElevationManager { get; } public IAdminElevationManager AdminElevationManager { get; }
public IDialogService DialogService { get; } public IDialogService DialogService { get; }
public ITimelineViewModel TimelineViewModel { get; } public ITimelineViewModel TimelineViewModel { get; }
public IDeclarativeProperty<VolumeSizeInfo?> VolumeSizeInfo { get;} public IDeclarativeProperty<VolumeSizeInfo?> VolumeSizeInfo { get; }
public event Action<IInputElement>? FocusReadInputElement; public event Action<IInputElement>? FocusReadInputElement;
public RootViewModel( public RootViewModel(
@@ -71,6 +71,6 @@ public partial class RootViewModel : IRootViewModel
VolumeSizeInfo = appState.SelectedTab VolumeSizeInfo = appState.SelectedTab
.Map(t => t?.CurrentLocation) .Map(t => t?.CurrentLocation)
.Switch() .Switch()
.Map(l => l?.Provider.GetVolumeSizeInfo(l.FullName!)); .Map(async l => l is null ? null : await l.Provider.GetVolumeSizeInfoAsync(l.FullName!));
} }
} }

View File

@@ -28,6 +28,6 @@ public interface IContentProvider : IContainer, IOnContainerEnter
Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default); Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default);
Task<bool> CanHandlePathAsync(NativePath path); Task<bool> CanHandlePathAsync(NativePath path);
Task<bool> CanHandlePathAsync(FullName path); Task<bool> CanHandlePathAsync(FullName path);
VolumeSizeInfo? GetVolumeSizeInfo(FullName path); ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path);
ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath); ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath);
} }

View File

@@ -176,6 +176,15 @@ public class CopyCommand : CommandBase, ITransportationCommand
if (item is IContainer container) if (item is IContainer container)
{ {
try
{
await container.WaitForLoaded(_cancellationTokenSource.Token);
}
catch(OperationCanceledException)
{
return;
}
if (resolvedTarget.Items.All(i => i.Path.GetName() != item.Name)) if (resolvedTarget.Items.All(i => i.Path.GetName() != item.Name))
{ {
await copyOperation.CreateContainerAsync(resolvedTarget, container.Name, container.PointInTime); await copyOperation.CreateContainerAsync(resolvedTarget, container.Name, container.PointInTime);

View File

@@ -9,6 +9,7 @@ public class DeleteCommand : CommandBase, IExecutableCommand
private readonly IContentAccessorFactory _contentAccessorFactory; private readonly IContentAccessorFactory _contentAccessorFactory;
private readonly ITimelessContentProvider _timelessContentProvider; private readonly ITimelessContentProvider _timelessContentProvider;
private readonly ICommandSchedulerNotifier _commandSchedulerNotifier; private readonly ICommandSchedulerNotifier _commandSchedulerNotifier;
private readonly CancellationTokenSource _cancellationTokenSource = new();
public bool HardDelete { get; set; } public bool HardDelete { get; set; }
public List<FullName> ItemsToDelete { get; } = new(); public List<FullName> ItemsToDelete { get; } = new();
@@ -35,10 +36,7 @@ public class DeleteCommand : CommandBase, IExecutableCommand
return Task.FromResult(currentTime); return Task.FromResult(currentTime);
} }
public override void Cancel() public override void Cancel() => _cancellationTokenSource.Cancel();
{
//TODO: Implement
}
public async Task Execute() public async Task Execute()
{ {
@@ -70,6 +68,8 @@ public class DeleteCommand : CommandBase, IExecutableCommand
{ {
foreach (var itemToDeleteName in itemsToDelete) foreach (var itemToDeleteName in itemsToDelete)
{ {
if (_cancellationTokenSource.IsCancellationRequested) return;
var itemToDelete = await _timelessContentProvider.GetItemByFullNameAsync(itemToDeleteName, currentTime); var itemToDelete = await _timelessContentProvider.GetItemByFullNameAsync(itemToDeleteName, currentTime);
IItemDeleter? itemDeleter = null; IItemDeleter? itemDeleter = null;
@@ -93,6 +93,15 @@ public class DeleteCommand : CommandBase, IExecutableCommand
if (itemToDelete is IContainer container) if (itemToDelete is IContainer container)
{ {
try
{
await container.WaitForLoaded(_cancellationTokenSource.Token);
}
catch(OperationCanceledException)
{
return;
}
await TraverseTree( await TraverseTree(
currentTime, currentTime,
container.Items.Select(i => i.Path), container.Items.Select(i => i.Path),

View File

@@ -93,7 +93,7 @@ public abstract class ContentProviderBase : IContentProvider
=> path.Path.TrimEnd(Constants.SeparatorChar) == Name => path.Path.TrimEnd(Constants.SeparatorChar) == Name
|| await CanHandlePathAsync(await GetNativePathAsync(path)); || await CanHandlePathAsync(await GetNativePathAsync(path));
public abstract VolumeSizeInfo? GetVolumeSizeInfo(FullName path); public abstract ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path);
public IItem WithParent(AbsolutePath parent) => this; public IItem WithParent(AbsolutePath parent) => this;
public abstract ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath); public abstract ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath);

View File

@@ -6,12 +6,12 @@ internal static class Helper
{ {
internal static async Task<ParentElementReaderContext> GetParentElementReaderAsync( internal static async Task<ParentElementReaderContext> GetParentElementReaderAsync(
IContentAccessorFactory contentAccessorFactory, IContentAccessorFactory contentAccessorFactory,
IElement element, IItem item,
IContentProvider parentContentProvider) IContentProvider parentContentProvider)
{ {
var elementNativePath = element.NativePath!; var elementNativePath = item.NativePath!;
var supportedPath = (await parentContentProvider.GetSupportedPathPart(elementNativePath))!; var supportedPath = (await parentContentProvider.GetSupportedPathPart(elementNativePath))!;
var parentElement = (IElement) await parentContentProvider.GetItemByNativePathAsync(supportedPath, element.PointInTime); var parentElement = (IElement) await parentContentProvider.GetItemByNativePathAsync(supportedPath, item.PointInTime);
var contentReaderFactory = contentAccessorFactory.GetContentReaderFactory(parentElement.Provider); var contentReaderFactory = contentAccessorFactory.GetContentReaderFactory(parentElement.Provider);
var reader = await contentReaderFactory.CreateContentReaderAsync(parentElement); var reader = await contentReaderFactory.CreateContentReaderAsync(parentElement);
@@ -19,4 +19,15 @@ internal static class Helper
return new ParentElementReaderContext(reader, subPath); return new ParentElementReaderContext(reader, subPath);
} }
internal static async Task<IElement> GetParentElementAsync(
IItem item,
IContentProvider parentContentProvider)
{
var elementNativePath = item.NativePath!;
var supportedPath = (await parentContentProvider.GetSupportedPathPart(elementNativePath))!;
var parentElement = (IElement) await parentContentProvider.GetItemByNativePathAsync(supportedPath, item.PointInTime);
return parentElement;
}
} }

View File

@@ -85,7 +85,7 @@ public class RootContentProvider : IRootContentProvider
public Task<bool> CanHandlePathAsync(NativePath path) => throw new NotImplementedException(); public Task<bool> CanHandlePathAsync(NativePath path) => throw new NotImplementedException();
public Task<bool> CanHandlePathAsync(FullName path) => throw new NotImplementedException(); public Task<bool> CanHandlePathAsync(FullName path) => throw new NotImplementedException();
public VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => null; public ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path) => ValueTask.FromResult<VolumeSizeInfo?>(null);
public ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath) => throw new NotImplementedException(); public ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath) => throw new NotImplementedException();
public IItem WithParent(AbsolutePath parent) => this; public IItem WithParent(AbsolutePath parent) => this;

View File

@@ -46,6 +46,9 @@ public abstract class SubContentProviderBase : ContentProviderBase
public override async ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath) public override async ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath)
=> await ParentContentProvider.GetSupportedPathPart(nativePath); => await ParentContentProvider.GetSupportedPathPart(nativePath);
protected async Task<ParentElementReaderContext> GetParentElementReaderAsync(IElement element) protected async Task<ParentElementReaderContext> GetParentElementReaderAsync(IItem item)
=> await Helper.GetParentElementReaderAsync(_contentAccessorFactory, element, ParentContentProvider); => await Helper.GetParentElementReaderAsync(_contentAccessorFactory, item, ParentContentProvider);
protected async Task<IElement> GetParentElementAsync(IItem item)
=> await Helper.GetParentElementAsync(item, ParentContentProvider);
} }

View File

@@ -13,6 +13,9 @@ public abstract class SubContentReaderBase<TContentProvider> : IContentReaderFac
public abstract Task<IContentReader> CreateContentReaderAsync(IElement element); public abstract Task<IContentReader> CreateContentReaderAsync(IElement element);
protected async Task<ParentElementReaderContext> GetParentElementReaderAsync(IElement element, SubContentProviderBase provider) protected async Task<ParentElementReaderContext> GetParentElementReaderAsync(IItem item, SubContentProviderBase provider)
=> await Helper.GetParentElementReaderAsync(_contentAccessorFactory, element, provider.ParentContentProvider); => await Helper.GetParentElementReaderAsync(_contentAccessorFactory, item, provider.ParentContentProvider);
protected async Task<IElement> GetParentElementAsync(IItem item, SubContentProviderBase provider)
=> await Helper.GetParentElementAsync(item, provider.ParentContentProvider);
} }

View File

@@ -21,6 +21,9 @@ public static class DeclarativePropertyExtensions
public static IDeclarativeProperty<T> DistinctUntilChanged<T>(this IDeclarativeProperty<T> from) public static IDeclarativeProperty<T> DistinctUntilChanged<T>(this IDeclarativeProperty<T> from)
=> new DistinctUntilChangedProperty<T>(from); => new DistinctUntilChangedProperty<T>(from);
public static IDeclarativeProperty<TTo> Map<TFrom, TTo>(this IDeclarativeProperty<TFrom?> from, Func<TFrom?, Task<TTo?>> mapper)
=> Map(from, async (v, _) => await mapper(v));
public static IDeclarativeProperty<TTo> Map<TFrom, TTo>(this IDeclarativeProperty<TFrom?> from, Func<TFrom?, CancellationToken, Task<TTo?>> mapper) public static IDeclarativeProperty<TTo> Map<TFrom, TTo>(this IDeclarativeProperty<TFrom?> from, Func<TFrom?, CancellationToken, Task<TTo?>> mapper)
=> new MapProperty<TFrom?, TTo>(mapper, from); => new MapProperty<TFrom?, TTo>(mapper, from);

View File

@@ -66,14 +66,14 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
return rootDrive is not null; return rootDrive is not null;
} }
public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) public override ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path)
{ {
var rootDriveInfos = _rootDriveInfos.Value; var rootDriveInfos = _rootDriveInfos.Value;
var rootDriveInfo = rootDriveInfos.FirstOrDefault(d => path.Path.StartsWith(d.Path.Path)); var rootDriveInfo = rootDriveInfos.FirstOrDefault(d => path.Path.StartsWith(d.Path.Path));
if (rootDriveInfo is null) return null; if (rootDriveInfo is null) return ValueTask.FromResult<VolumeSizeInfo?>(null);
return new VolumeSizeInfo(rootDriveInfo.Size, rootDriveInfo.Free); return ValueTask.FromResult<VolumeSizeInfo?>(new VolumeSizeInfo(rootDriveInfo.Size, rootDriveInfo.Free));
} }
public override async Task<IItem> GetItemByNativePathAsync(NativePath nativePath, public override async Task<IItem> GetItemByNativePathAsync(NativePath nativePath,

View File

@@ -103,7 +103,7 @@ public sealed class RemoteContentProvider : ContentProviderBase, IRemoteContentP
public override Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default) => throw new NotImplementedException(); public override Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default) => throw new NotImplementedException();
public override Task<bool> CanHandlePathAsync(NativePath path) => throw new NotImplementedException(); public override Task<bool> CanHandlePathAsync(NativePath path) => throw new NotImplementedException();
public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => throw new NotImplementedException(); public override ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path) => throw new NotImplementedException();
public override ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath) => throw new NotImplementedException(); public override ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath) => throw new NotImplementedException();
private string ConvertLocalFullNameToRemote(FullName fullName) private string ConvertLocalFullNameToRemote(FullName fullName)

View File

@@ -7,6 +7,8 @@ namespace FileTime.Tools.Compression.ContentProvider;
public sealed class CompressedContentProvider : SubContentProviderBase, ICompressedContentProvider public sealed class CompressedContentProvider : SubContentProviderBase, ICompressedContentProvider
{ {
private readonly ITimelessContentProvider _timelessContentProvider;
public CompressedContentProvider( public CompressedContentProvider(
ITimelessContentProvider timelessContentProvider, ITimelessContentProvider timelessContentProvider,
IContentAccessorFactory contentAccessorFactory, IContentAccessorFactory contentAccessorFactory,
@@ -18,6 +20,7 @@ public sealed class CompressedContentProvider : SubContentProviderBase, ICompres
parentContentProvider, parentContentProvider,
"compression") "compression")
{ {
_timelessContentProvider = timelessContentProvider;
} }
public override async Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default) public override async Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default)
@@ -25,18 +28,23 @@ public sealed class CompressedContentProvider : SubContentProviderBase, ICompres
var parentElementContext = await GetParentElementReaderAsync(element); var parentElementContext = await GetParentElementReaderAsync(element);
var reader = parentElementContext.ContentReader; var reader = parentElementContext.ContentReader;
var subPath = parentElementContext.SubNativePath.Path; var subPath = parentElementContext.SubNativePath.Path;
await using var readerStream = reader.AsStream(); await using var readerStream = reader.AsStream();
using var archive = ArchiveFactory.Open(readerStream); using var archive = ArchiveFactory.Open(readerStream);
var entry = archive.Entries.First(e => e.Key == subPath); var entry = archive.Entries.First(e => e.Key == subPath);
await using var contentReader= entry.OpenEntryStream(); await using var contentReader = entry.OpenEntryStream();
var data = new byte[1024 * 1024]; var data = new byte[1024 * 1024];
var readAsync = await contentReader.ReadAsync(data, cancellationToken); var readAsync = await contentReader.ReadAsync(data, cancellationToken);
return data[..readAsync].ToArray(); return data[..readAsync].ToArray();
} }
public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => throw new NotImplementedException(); public override async ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path)
{
var item = await GetItemByFullNameAsync(path, _timelessContentProvider.CurrentPointInTime.Value!);
var parentElement = await GetParentElementAsync(item);
return new VolumeSizeInfo(parentElement.Size, 0);
}
} }

View File

@@ -7,7 +7,7 @@ namespace FileTime.Tools.VirtualDiskSources;
public sealed class VirtualDiskContentProvider : SubContentProviderBase, IVirtualDiskContentProvider public sealed class VirtualDiskContentProvider : SubContentProviderBase, IVirtualDiskContentProvider
{ {
private readonly IContentAccessorFactory _contentAccessorFactory; private readonly ITimelessContentProvider _timelessContentProvider;
public VirtualDiskContentProvider( public VirtualDiskContentProvider(
ITimelessContentProvider timelessContentProvider, ITimelessContentProvider timelessContentProvider,
@@ -20,7 +20,7 @@ public sealed class VirtualDiskContentProvider : SubContentProviderBase, IVirtua
"virtual-disk" "virtual-disk"
) )
{ {
_contentAccessorFactory = contentAccessorFactory; _timelessContentProvider = timelessContentProvider;
} }
public override async Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default) public override async Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default)
@@ -41,6 +41,11 @@ public sealed class VirtualDiskContentProvider : SubContentProviderBase, IVirtua
return data[..readAsync].ToArray(); return data[..readAsync].ToArray();
} }
public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path)
=> ParentContentProvider.GetVolumeSizeInfo(path); public override async ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path)
{
var item = await GetItemByFullNameAsync(path, _timelessContentProvider.CurrentPointInTime.Value!);
var parentElement = await GetParentElementAsync(item);
return new VolumeSizeInfo(parentElement.Size, 0);
}
} }