Volume size info for sub content providers
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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))
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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!));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user