From ba0b55c7332f0e39a04ca4dd5fcd809c9cdf20da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Tue, 5 Sep 2023 23:12:20 +0200 Subject: [PATCH] Volume size info for sub content providers --- .../ContainerSizeSizeScanProvider.cs | 2 +- .../Services/ItemPreviewService.cs | 4 ++-- ...temManipulationUserCommandHandlerService.cs | 2 +- .../ViewModels/ItemViewModel.cs | 2 +- .../ViewModels/TabViewModel.cs | 10 +++++----- .../SearchContentProvider.cs | 2 +- .../FileTime.ConsoleUI.App/RootViewModel.cs | 6 +++--- .../ContentAccess/IContentProvider.cs | 2 +- .../FileTime.Core.Command/Copy/CopyCommand.cs | 9 +++++++++ .../Delete/DeleteCommand.cs | 17 +++++++++++++---- .../ContentProviderBase.cs | 2 +- src/Core/FileTime.Core.ContentAccess/Helper.cs | 17 ++++++++++++++--- .../RootContentProvider.cs | 2 +- .../SubContentProviderBase.cs | 7 +++++-- .../SubContentReaderBase.cs | 7 +++++-- .../DeclarativePropertyExtensions.cs | 3 +++ .../LocalContentProvider.cs | 6 +++--- .../RemoteContentProvider.cs | 2 +- .../CompressedContentProvider.cs | 18 +++++++++++++----- .../VirtualDiskContentProvider.cs | 13 +++++++++---- 20 files changed, 92 insertions(+), 41 deletions(-) diff --git a/src/AppCommon/FileTime.App.ContainerSizeScanner/ContainerSizeSizeScanProvider.cs b/src/AppCommon/FileTime.App.ContainerSizeScanner/ContainerSizeSizeScanProvider.cs index dd7d452..0a46e06 100644 --- a/src/AppCommon/FileTime.App.ContainerSizeScanner/ContainerSizeSizeScanProvider.cs +++ b/src/AppCommon/FileTime.App.ContainerSizeScanner/ContainerSizeSizeScanProvider.cs @@ -84,7 +84,7 @@ public class ContainerSizeSizeScanProvider : ContentProviderBase, IContainerSize public override Task CanHandlePathAsync(NativePath path) => Task.FromResult(path.Path.StartsWith(ContentProviderName)); - public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => null; + public override ValueTask GetVolumeSizeInfoAsync(FullName path) => ValueTask.FromResult(null); public override ValueTask GetSupportedPathPart(NativePath nativePath) => ValueTask.FromResult(nativePath); diff --git a/src/AppCommon/FileTime.App.Core/Services/ItemPreviewService.cs b/src/AppCommon/FileTime.App.Core/Services/ItemPreviewService.cs index a746f8a..de79937 100644 --- a/src/AppCommon/FileTime.App.Core/Services/ItemPreviewService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/ItemPreviewService.cs @@ -19,12 +19,12 @@ public class ItemPreviewService : IItemPreviewService .Map(t => t?.CurrentSelectedItem) .Switch() .Debounce(TimeSpan.FromMilliseconds(250)) - .Map(async (item, _) => + .Map(async item => item == null ? null : await Map(item) ) - .DistinctUntilChanged(); + .DistinctUntilChanged()!; } private async Task Map(IItemViewModel itemViewModel) diff --git a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs index e638fb0..21bd693 100644 --- a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs @@ -461,7 +461,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi var deleteCommand = _serviceProvider.GetRequiredService(); deleteCommand.HardDelete = command.IsHardDelete; - deleteCommand.ItemsToDelete.AddRange(itemsToDelete!); + deleteCommand.ItemsToDelete.AddRange(itemsToDelete); await AddCommandAsync(deleteCommand); _selectedTab?.ClearMarkedItems(); diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/ItemViewModel.cs b/src/AppCommon/FileTime.App.Core/ViewModels/ItemViewModel.cs index 7685139..06a379d 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/ItemViewModel.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/ItemViewModel.cs @@ -53,7 +53,7 @@ public abstract partial class ItemViewModel : IItemViewModel 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.SelectedTab.Value?.CurrentLocation.Value?.Provider is IItemNameConverterProvider nameConverterProvider ? (IReadOnlyList) await nameConverterProvider.GetItemNamePartsAsync(item) diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs b/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs index dd88281..9556e6b 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs @@ -70,13 +70,13 @@ public partial class TabViewModel : ITabViewModel CurrentItems = tab.CurrentItems - .Map((items, _) => + .Map(items => Task.FromResult?>( items?.Selecting( i => MapItemToViewModel(i, ItemViewModelType.Main) ) ) - ); + )!; using var _ = Defer( () => CurrentItems.Subscribe(c => UpdateConsumer(c, ref _currentItemsConsumer)) @@ -144,9 +144,9 @@ public partial class TabViewModel : ITabViewModel 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?) null; + if (item?.Parent is null) return (ObservableCollection?) null; var parent = (IContainer) await item.Parent.ResolveAsync(); var items = parent.Items @@ -156,7 +156,7 @@ public partial class TabViewModel : ITabViewModel .Selecting(i => MapItemToViewModel(i, ItemViewModelType.Parent)); return items; - }); + })!; using var ___ = Defer(() => ParentsChildren.Subscribe(c => UpdateConsumer(c, ref _parentsChildrenConsumer)) ); diff --git a/src/AppCommon/FileTime.App.Search/SearchContentProvider.cs b/src/AppCommon/FileTime.App.Search/SearchContentProvider.cs index cb9e89b..59d923f 100644 --- a/src/AppCommon/FileTime.App.Search/SearchContentProvider.cs +++ b/src/AppCommon/FileTime.App.Search/SearchContentProvider.cs @@ -79,7 +79,7 @@ public class SearchContentProvider : ContentProviderBase, ISearchContentProvider => Task.FromResult(null as byte[]); public override Task CanHandlePathAsync(NativePath path) => Task.FromResult(path.Path.StartsWith(ContentProviderName)); - public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => null; + public override ValueTask GetVolumeSizeInfoAsync(FullName path) => ValueTask.FromResult(null); public override ValueTask GetSupportedPathPart(NativePath nativePath) => throw new NotImplementedException(); public async Task StartSearchAsync(ISearchMatcher matcher, IContainer searchIn) diff --git a/src/ConsoleApp/FileTime.ConsoleUI.App/RootViewModel.cs b/src/ConsoleApp/FileTime.ConsoleUI.App/RootViewModel.cs index 67cc4a9..1598b69 100644 --- a/src/ConsoleApp/FileTime.ConsoleUI.App/RootViewModel.cs +++ b/src/ConsoleApp/FileTime.ConsoleUI.App/RootViewModel.cs @@ -24,8 +24,8 @@ public partial class RootViewModel : IRootViewModel public IAdminElevationManager AdminElevationManager { get; } public IDialogService DialogService { get; } public ITimelineViewModel TimelineViewModel { get; } - public IDeclarativeProperty VolumeSizeInfo { get;} - + public IDeclarativeProperty VolumeSizeInfo { get; } + public event Action? FocusReadInputElement; public RootViewModel( @@ -71,6 +71,6 @@ public partial class RootViewModel : IRootViewModel VolumeSizeInfo = appState.SelectedTab .Map(t => t?.CurrentLocation) .Switch() - .Map(l => l?.Provider.GetVolumeSizeInfo(l.FullName!)); + .Map(async l => l is null ? null : await l.Provider.GetVolumeSizeInfoAsync(l.FullName!)); } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/ContentAccess/IContentProvider.cs b/src/Core/FileTime.Core.Abstraction/ContentAccess/IContentProvider.cs index 49b6623..96262da 100644 --- a/src/Core/FileTime.Core.Abstraction/ContentAccess/IContentProvider.cs +++ b/src/Core/FileTime.Core.Abstraction/ContentAccess/IContentProvider.cs @@ -28,6 +28,6 @@ public interface IContentProvider : IContainer, IOnContainerEnter Task GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default); Task CanHandlePathAsync(NativePath path); Task CanHandlePathAsync(FullName path); - VolumeSizeInfo? GetVolumeSizeInfo(FullName path); + ValueTask GetVolumeSizeInfoAsync(FullName path); ValueTask GetSupportedPathPart(NativePath nativePath); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs b/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs index 589c4e3..d011645 100644 --- a/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs +++ b/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs @@ -176,6 +176,15 @@ public class CopyCommand : CommandBase, ITransportationCommand if (item is IContainer container) { + try + { + await container.WaitForLoaded(_cancellationTokenSource.Token); + } + catch(OperationCanceledException) + { + return; + } + if (resolvedTarget.Items.All(i => i.Path.GetName() != item.Name)) { await copyOperation.CreateContainerAsync(resolvedTarget, container.Name, container.PointInTime); diff --git a/src/Core/FileTime.Core.Command/Delete/DeleteCommand.cs b/src/Core/FileTime.Core.Command/Delete/DeleteCommand.cs index 4c39e83..981fc63 100644 --- a/src/Core/FileTime.Core.Command/Delete/DeleteCommand.cs +++ b/src/Core/FileTime.Core.Command/Delete/DeleteCommand.cs @@ -9,6 +9,7 @@ public class DeleteCommand : CommandBase, IExecutableCommand private readonly IContentAccessorFactory _contentAccessorFactory; private readonly ITimelessContentProvider _timelessContentProvider; private readonly ICommandSchedulerNotifier _commandSchedulerNotifier; + private readonly CancellationTokenSource _cancellationTokenSource = new(); public bool HardDelete { get; set; } public List ItemsToDelete { get; } = new(); @@ -35,10 +36,7 @@ public class DeleteCommand : CommandBase, IExecutableCommand return Task.FromResult(currentTime); } - public override void Cancel() - { - //TODO: Implement - } + public override void Cancel() => _cancellationTokenSource.Cancel(); public async Task Execute() { @@ -70,6 +68,8 @@ public class DeleteCommand : CommandBase, IExecutableCommand { foreach (var itemToDeleteName in itemsToDelete) { + if (_cancellationTokenSource.IsCancellationRequested) return; + var itemToDelete = await _timelessContentProvider.GetItemByFullNameAsync(itemToDeleteName, currentTime); IItemDeleter? itemDeleter = null; @@ -93,6 +93,15 @@ public class DeleteCommand : CommandBase, IExecutableCommand if (itemToDelete is IContainer container) { + try + { + await container.WaitForLoaded(_cancellationTokenSource.Token); + } + catch(OperationCanceledException) + { + return; + } + await TraverseTree( currentTime, container.Items.Select(i => i.Path), diff --git a/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs b/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs index 9f8aefb..fd583e2 100644 --- a/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs +++ b/src/Core/FileTime.Core.ContentAccess/ContentProviderBase.cs @@ -93,7 +93,7 @@ public abstract class ContentProviderBase : IContentProvider => path.Path.TrimEnd(Constants.SeparatorChar) == Name || await CanHandlePathAsync(await GetNativePathAsync(path)); - public abstract VolumeSizeInfo? GetVolumeSizeInfo(FullName path); + public abstract ValueTask GetVolumeSizeInfoAsync(FullName path); public IItem WithParent(AbsolutePath parent) => this; public abstract ValueTask GetSupportedPathPart(NativePath nativePath); diff --git a/src/Core/FileTime.Core.ContentAccess/Helper.cs b/src/Core/FileTime.Core.ContentAccess/Helper.cs index 86de074..a453891 100644 --- a/src/Core/FileTime.Core.ContentAccess/Helper.cs +++ b/src/Core/FileTime.Core.ContentAccess/Helper.cs @@ -6,12 +6,12 @@ internal static class Helper { internal static async Task GetParentElementReaderAsync( IContentAccessorFactory contentAccessorFactory, - IElement element, + IItem item, IContentProvider parentContentProvider) { - var elementNativePath = element.NativePath!; + var elementNativePath = item.NativePath!; 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 reader = await contentReaderFactory.CreateContentReaderAsync(parentElement); @@ -19,4 +19,15 @@ internal static class Helper return new ParentElementReaderContext(reader, subPath); } + + internal static async Task 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; + } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.ContentAccess/RootContentProvider.cs b/src/Core/FileTime.Core.ContentAccess/RootContentProvider.cs index 0a2d211..c06e856 100644 --- a/src/Core/FileTime.Core.ContentAccess/RootContentProvider.cs +++ b/src/Core/FileTime.Core.ContentAccess/RootContentProvider.cs @@ -85,7 +85,7 @@ public class RootContentProvider : IRootContentProvider public Task CanHandlePathAsync(NativePath path) => throw new NotImplementedException(); public Task CanHandlePathAsync(FullName path) => throw new NotImplementedException(); - public VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => null; + public ValueTask GetVolumeSizeInfoAsync(FullName path) => ValueTask.FromResult(null); public ValueTask GetSupportedPathPart(NativePath nativePath) => throw new NotImplementedException(); public IItem WithParent(AbsolutePath parent) => this; diff --git a/src/Core/FileTime.Core.ContentAccess/SubContentProviderBase.cs b/src/Core/FileTime.Core.ContentAccess/SubContentProviderBase.cs index b912a30..85b7d32 100644 --- a/src/Core/FileTime.Core.ContentAccess/SubContentProviderBase.cs +++ b/src/Core/FileTime.Core.ContentAccess/SubContentProviderBase.cs @@ -46,6 +46,9 @@ public abstract class SubContentProviderBase : ContentProviderBase public override async ValueTask GetSupportedPathPart(NativePath nativePath) => await ParentContentProvider.GetSupportedPathPart(nativePath); - protected async Task GetParentElementReaderAsync(IElement element) - => await Helper.GetParentElementReaderAsync(_contentAccessorFactory, element, ParentContentProvider); + protected async Task GetParentElementReaderAsync(IItem item) + => await Helper.GetParentElementReaderAsync(_contentAccessorFactory, item, ParentContentProvider); + + protected async Task GetParentElementAsync(IItem item) + => await Helper.GetParentElementAsync(item, ParentContentProvider); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.ContentAccess/SubContentReaderBase.cs b/src/Core/FileTime.Core.ContentAccess/SubContentReaderBase.cs index e3ffcc5..70ef21f 100644 --- a/src/Core/FileTime.Core.ContentAccess/SubContentReaderBase.cs +++ b/src/Core/FileTime.Core.ContentAccess/SubContentReaderBase.cs @@ -13,6 +13,9 @@ public abstract class SubContentReaderBase : IContentReaderFac public abstract Task CreateContentReaderAsync(IElement element); - protected async Task GetParentElementReaderAsync(IElement element, SubContentProviderBase provider) - => await Helper.GetParentElementReaderAsync(_contentAccessorFactory, element, provider.ParentContentProvider); + protected async Task GetParentElementReaderAsync(IItem item, SubContentProviderBase provider) + => await Helper.GetParentElementReaderAsync(_contentAccessorFactory, item, provider.ParentContentProvider); + + protected async Task GetParentElementAsync(IItem item, SubContentProviderBase provider) + => await Helper.GetParentElementAsync(item, provider.ParentContentProvider); } \ No newline at end of file diff --git a/src/Library/DeclarativeProperty/DeclarativePropertyExtensions.cs b/src/Library/DeclarativeProperty/DeclarativePropertyExtensions.cs index f7b53f9..7c91307 100644 --- a/src/Library/DeclarativeProperty/DeclarativePropertyExtensions.cs +++ b/src/Library/DeclarativeProperty/DeclarativePropertyExtensions.cs @@ -21,6 +21,9 @@ public static class DeclarativePropertyExtensions public static IDeclarativeProperty DistinctUntilChanged(this IDeclarativeProperty from) => new DistinctUntilChangedProperty(from); + public static IDeclarativeProperty Map(this IDeclarativeProperty from, Func> mapper) + => Map(from, async (v, _) => await mapper(v)); + public static IDeclarativeProperty Map(this IDeclarativeProperty from, Func> mapper) => new MapProperty(mapper, from); diff --git a/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs b/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs index 3ff67e1..15a2b9a 100644 --- a/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs +++ b/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs @@ -66,14 +66,14 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo return rootDrive is not null; } - public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) + public override ValueTask GetVolumeSizeInfoAsync(FullName path) { var rootDriveInfos = _rootDriveInfos.Value; var rootDriveInfo = rootDriveInfos.FirstOrDefault(d => path.Path.StartsWith(d.Path.Path)); - if (rootDriveInfo is null) return null; + if (rootDriveInfo is null) return ValueTask.FromResult(null); - return new VolumeSizeInfo(rootDriveInfo.Size, rootDriveInfo.Free); + return ValueTask.FromResult(new VolumeSizeInfo(rootDriveInfo.Size, rootDriveInfo.Free)); } public override async Task GetItemByNativePathAsync(NativePath nativePath, diff --git a/src/Providers/FileTime.Providers.Remote/RemoteContentProvider.cs b/src/Providers/FileTime.Providers.Remote/RemoteContentProvider.cs index 23d39db..f8ca943 100644 --- a/src/Providers/FileTime.Providers.Remote/RemoteContentProvider.cs +++ b/src/Providers/FileTime.Providers.Remote/RemoteContentProvider.cs @@ -103,7 +103,7 @@ public sealed class RemoteContentProvider : ContentProviderBase, IRemoteContentP public override Task GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default) => throw new NotImplementedException(); public override Task CanHandlePathAsync(NativePath path) => throw new NotImplementedException(); - public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => throw new NotImplementedException(); + public override ValueTask GetVolumeSizeInfoAsync(FullName path) => throw new NotImplementedException(); public override ValueTask GetSupportedPathPart(NativePath nativePath) => throw new NotImplementedException(); private string ConvertLocalFullNameToRemote(FullName fullName) diff --git a/src/Tools/FileTime.Tools.Compression/ContentProvider/CompressedContentProvider.cs b/src/Tools/FileTime.Tools.Compression/ContentProvider/CompressedContentProvider.cs index 1ff67a0..6caf3d4 100644 --- a/src/Tools/FileTime.Tools.Compression/ContentProvider/CompressedContentProvider.cs +++ b/src/Tools/FileTime.Tools.Compression/ContentProvider/CompressedContentProvider.cs @@ -7,6 +7,8 @@ namespace FileTime.Tools.Compression.ContentProvider; public sealed class CompressedContentProvider : SubContentProviderBase, ICompressedContentProvider { + private readonly ITimelessContentProvider _timelessContentProvider; + public CompressedContentProvider( ITimelessContentProvider timelessContentProvider, IContentAccessorFactory contentAccessorFactory, @@ -18,6 +20,7 @@ public sealed class CompressedContentProvider : SubContentProviderBase, ICompres parentContentProvider, "compression") { + _timelessContentProvider = timelessContentProvider; } public override async Task 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 reader = parentElementContext.ContentReader; var subPath = parentElementContext.SubNativePath.Path; - + await using var readerStream = reader.AsStream(); using var archive = ArchiveFactory.Open(readerStream); - + 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 readAsync = await contentReader.ReadAsync(data, cancellationToken); return data[..readAsync].ToArray(); } - public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) => throw new NotImplementedException(); + public override async ValueTask GetVolumeSizeInfoAsync(FullName path) + { + var item = await GetItemByFullNameAsync(path, _timelessContentProvider.CurrentPointInTime.Value!); + var parentElement = await GetParentElementAsync(item); + return new VolumeSizeInfo(parentElement.Size, 0); + } } \ No newline at end of file diff --git a/src/Tools/FileTime.Tools.VirtualDiskSources/VirtualDiskContentProvider.cs b/src/Tools/FileTime.Tools.VirtualDiskSources/VirtualDiskContentProvider.cs index 83d6c2a..c2e354f 100644 --- a/src/Tools/FileTime.Tools.VirtualDiskSources/VirtualDiskContentProvider.cs +++ b/src/Tools/FileTime.Tools.VirtualDiskSources/VirtualDiskContentProvider.cs @@ -7,7 +7,7 @@ namespace FileTime.Tools.VirtualDiskSources; public sealed class VirtualDiskContentProvider : SubContentProviderBase, IVirtualDiskContentProvider { - private readonly IContentAccessorFactory _contentAccessorFactory; + private readonly ITimelessContentProvider _timelessContentProvider; public VirtualDiskContentProvider( ITimelessContentProvider timelessContentProvider, @@ -20,7 +20,7 @@ public sealed class VirtualDiskContentProvider : SubContentProviderBase, IVirtua "virtual-disk" ) { - _contentAccessorFactory = contentAccessorFactory; + _timelessContentProvider = timelessContentProvider; } public override async Task GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default) @@ -41,6 +41,11 @@ public sealed class VirtualDiskContentProvider : SubContentProviderBase, IVirtua return data[..readAsync].ToArray(); } - public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path) - => ParentContentProvider.GetVolumeSizeInfo(path); + + public override async ValueTask GetVolumeSizeInfoAsync(FullName path) + { + var item = await GetItemByFullNameAsync(path, _timelessContentProvider.CurrentPointInTime.Value!); + var parentElement = await GetParentElementAsync(item); + return new VolumeSizeInfo(parentElement.Size, 0); + } } \ No newline at end of file