Container traits to extensions

This commit is contained in:
2023-08-03 10:48:39 +02:00
parent 86cffa6aa4
commit 558a0a08bb
32 changed files with 258 additions and 158 deletions

View File

@@ -1,4 +1,5 @@
using FileTime.App.Core.Exceptions;
using FileTime.App.Core.Services;
using FileTime.Core.ContentAccess;
using FileTime.Core.Enums;
using FileTime.Core.Models;
@@ -7,14 +8,14 @@ using InitableService;
namespace FileTime.App.ContainerSizeScanner;
public class ContainerScanProvider : ContentProviderBase, IContainerScanSnapshotProvider
public class ContainerSizeSizeScanProvider : ContentProviderBase, IContainerSizeScanProvider
{
private readonly ITimelessContentProvider _timelessContentProvider;
private readonly IServiceProvider _serviceProvider;
private readonly List<ISizeScanTask> _sizeScanTasks = new();
internal const string ContentProviderName = "container-size-scan";
public ContainerScanProvider(
public ContainerSizeSizeScanProvider(
ITimelessContentProvider timelessContentProvider,
IServiceProvider serviceProvider)
: base(ContentProviderName, timelessContentProvider)
@@ -110,4 +111,20 @@ public class ContainerScanProvider : ContentProviderBase, IContainerScanSnapshot
return searchTask;
}
public Task ExitAsync(CancellationToken token = default)
{
foreach (var sizeScanTask in _sizeScanTasks)
{
try
{
sizeScanTask.Stop();
}
catch
{
}
}
return Task.CompletedTask;
}
}

View File

@@ -5,14 +5,15 @@ using DeclarativeProperty;
using FileTime.Core.ContentAccess;
using FileTime.Core.Enums;
using FileTime.Core.Models;
using FileTime.Core.Models.ContainerTraits;
using FileTime.Core.Models.Extensions;
using FileTime.Core.Timeline;
namespace FileTime.App.ContainerSizeScanner;
//TODO: create readonly version
public record SizeScanContainer : ISizeScanContainer, IEscHandlerContainer
//TODO: create readonly version, or not...
public record SizeScanContainer : ISizeScanContainer
{
private readonly ITimelessContentProvider _timelessContentProvider;
private readonly ReadOnlyExtensionCollection _readOnlyExtensions;
private readonly BehaviorSubject<bool> _isLoading = new(false);
private readonly CombineProperty<long, long> _size;
@@ -38,25 +39,35 @@ public record SizeScanContainer : ISizeScanContainer, IEscHandlerContainer
public ObservableCollection<AbsolutePath> Items { get; } = new();
public IObservable<bool> IsLoading { get; }
public bool? IsLoaded { get; private set; }
public Task WaitForLoaded(CancellationToken token = default) => throw new NotImplementedException();
public async Task WaitForLoaded(CancellationToken token = default)
{
while (IsLoaded != true) await Task.Delay(1, token);
}
public bool AllowRecursiveDeletion => false;
public IDeclarativeProperty<long> Size { get; }
public ObservableCollection<ISizeScanContainer> ChildContainers { get; } = new();
public ObservableCollection<ISizeScanElement> ChildElements { get; } = new();
public ObservableCollection<ISizeItem> SizeItems { get; } = new();
public required IContainer RealContainer { get; init; }
internal SizeScanContainer()
internal SizeScanContainer(ITimelessContentProvider timelessContentProvider)
{
_timelessContentProvider = timelessContentProvider;
_readOnlyExtensions = new ReadOnlyExtensionCollection(Extensions);
IsLoading = _isLoading.AsObservable();
CreatedAt = DateTime.Now;
_size = new(childContainerSizes => Task.FromResult(childContainerSizes.Sum()));
Size = _size.Debounce(TimeSpan.FromSeconds(1));
CreatedAt = DateTime.Now;
Extensions.Add(new EscHandlerContainerExtension(HandleEsc));
Extensions.Add(new NonRestorableContainerExtension());
Extensions.Add(new RealContainerProviderExtension(() => new(_timelessContentProvider, RealContainer!)));
Extensions.Add(new StatusProviderContainerExtension(() => Status));
}
public async Task AddSizeSourceAsync(IDeclarativeProperty<long> sizeElement)
@@ -90,4 +101,19 @@ public record SizeScanContainer : ISizeScanContainer, IEscHandlerContainer
SizeScanTask.Stop();
return Task.FromResult(new ContainerEscapeResult(true));
}
public async Task AddSizeChildAsync(ISizeItem newChild)
{
SizeItems.Add(newChild);
if (newChild is ISizeScanContainer newContainer)
{
ChildContainers.Add(newContainer);
}
await AddSizeSourceAsync(newChild.Size);
Items.Add(new AbsolutePath(
_timelessContentProvider,
newChild));
}
}

View File

@@ -1,5 +1,4 @@
using DeclarativeProperty;
using FileTime.Core.Enums;
using FileTime.Core.Models;
using FileTime.Core.Models.Extensions;
using FileTime.Core.Timeline;
@@ -13,7 +12,7 @@ public class SizeScanTask : ISizeScanTask
private int _processedItems;
private ulong _processedItemsTotal;
private IContainer _scanSizeOf = null!;
private readonly IContainerScanSnapshotProvider _containerScanSnapshotProvider;
private readonly IContainerSizeScanProvider _containerSizeScanProvider;
private readonly ITimelessContentProvider _timelessContentProvider;
private readonly ILogger<SizeScanTask> _logger;
private Thread? _sizeScanThread;
@@ -24,11 +23,11 @@ public class SizeScanTask : ISizeScanTask
public bool IsRunning { get; private set; }
public SizeScanTask(
IContainerScanSnapshotProvider containerScanSnapshotProvider,
IContainerSizeScanProvider containerSizeScanProvider,
ITimelessContentProvider timelessContentProvider,
ILogger<SizeScanTask> logger)
{
_containerScanSnapshotProvider = containerScanSnapshotProvider;
_containerSizeScanProvider = containerSizeScanProvider;
_timelessContentProvider = timelessContentProvider;
_logger = logger;
_containerStatusDebounced = _containerStatus.Debounce(TimeSpan.FromMilliseconds(250));
@@ -38,16 +37,16 @@ public class SizeScanTask : ISizeScanTask
{
_scanSizeOf = scanSizeOf;
var name = $"{_searchId++}_{scanSizeOf.Name}";
var randomId = ContainerScanProvider.ContentProviderName + Constants.SeparatorChar + name;
SizeSizeScanContainer = new SizeScanContainer
var randomId = ContainerSizeSizeScanProvider.ContentProviderName + Constants.SeparatorChar + name;
SizeSizeScanContainer = new SizeScanContainer(_timelessContentProvider)
{
Name = name,
DisplayName = scanSizeOf.DisplayName,
FullName = new FullName(randomId),
NativePath = new NativePath(randomId),
Parent = new AbsolutePath(_timelessContentProvider, _containerScanSnapshotProvider),
Parent = new AbsolutePath(_timelessContentProvider, _containerSizeScanProvider),
RealContainer = scanSizeOf,
Provider = _containerScanSnapshotProvider,
Provider = _containerSizeScanProvider,
Status = _containerStatusDebounced,
SizeScanTask = this
};
@@ -87,8 +86,8 @@ public class SizeScanTask : ISizeScanTask
IContainer realContainer,
ISizeScanContainer sizeScanContainer)
{
if(_cancelled) return;
if (_cancelled) return;
await realContainer.WaitForLoaded();
var resolvedItems = new List<IItem>(realContainer.Items.Count);
foreach (var item in realContainer.Items)
@@ -99,43 +98,36 @@ public class SizeScanTask : ISizeScanTask
foreach (var element in resolvedItems.OfType<IElement>())
{
if(_cancelled) return;
if (_cancelled) return;
var fileExtension = element.GetExtension<FileExtension>();
if (fileExtension?.Size is not { } size) continue;
var size = fileExtension?.Size ?? 0;
var sizeProperty = new DeclarativeProperty<long>(size);
var childName = sizeScanContainer.FullName!.GetChild(element.Name).Path;
await sizeScanContainer.AddSizeSourceAsync(sizeProperty);
sizeScanContainer.Items.Add(new AbsolutePath(
_timelessContentProvider,
PointInTime.Present,
new FullName(childName),
AbsolutePathType.Element));
var childSearchContainer = new SizeScanElement
var childElement = new SizeScanElement
{
Name = element.Name,
DisplayName = element.DisplayName,
FullName = new FullName(childName),
NativePath = new NativePath(childName),
Parent = new AbsolutePath(_timelessContentProvider, sizeScanContainer),
Provider = _containerScanSnapshotProvider,
Provider = _containerSizeScanProvider,
Size = sizeProperty
};
sizeScanContainer.SizeItems.Add(childSearchContainer);
await sizeScanContainer.AddSizeChildAsync(childElement);
_processedItems++;
_processedItemsTotal++;
}
foreach (var childContainer in resolvedItems.OfType<IContainer>())
{
if(_cancelled) return;
if (_cancelled) return;
var childName = sizeScanContainer.FullName!.GetChild(childContainer.Name).Path;
var childSearchContainer = new SizeScanContainer
var childSearchContainer = new SizeScanContainer(_timelessContentProvider)
{
Name = childContainer.Name,
DisplayName = childContainer.DisplayName,
@@ -143,19 +135,12 @@ public class SizeScanTask : ISizeScanTask
NativePath = new NativePath(childName),
Parent = new AbsolutePath(_timelessContentProvider, sizeScanContainer),
RealContainer = childContainer,
Provider = _containerScanSnapshotProvider,
Provider = _containerSizeScanProvider,
Status = _containerStatusDebounced,
SizeScanTask = this
};
sizeScanContainer.ChildContainers.Add(childSearchContainer);
sizeScanContainer.SizeItems.Add(childSearchContainer);
await sizeScanContainer.AddSizeSourceAsync(childSearchContainer.Size);
sizeScanContainer.Items.Add(new AbsolutePath(
_timelessContentProvider,
PointInTime.Present,
new FullName(childName),
AbsolutePathType.Container));
await sizeScanContainer.AddSizeChildAsync(childSearchContainer);
await TraverseTree(childContainer, childSearchContainer);
}

View File

@@ -9,8 +9,9 @@ public static class Startup
{
public static IServiceCollection AddContainerSizeScanner(this IServiceCollection services)
{
services.TryAddSingleton<IContainerScanSnapshotProvider, ContainerScanProvider>();
services.AddSingleton<IContentProvider>(sp => sp.GetRequiredService<IContainerScanSnapshotProvider>());
services.TryAddSingleton<IContainerSizeScanProvider, ContainerSizeSizeScanProvider>();
services.AddSingleton<IContentProvider>(sp => sp.GetRequiredService<IContainerSizeScanProvider>());
services.AddSingleton<IExitHandler>(sp => sp.GetRequiredService<IContainerSizeScanProvider>());
services.AddTransient<ISizeScanTask, SizeScanTask>();
services.AddTransient<IItemPreviewProvider, PreviewProvider>();
return services;