Browse ISOs

This commit is contained in:
2023-09-04 15:19:20 +02:00
parent 38979d8572
commit a323edafd3
29 changed files with 555 additions and 60 deletions

View File

@@ -1,10 +1,13 @@
using System.Collections.ObjectModel;
using FileTime.Core.Models;
namespace FileTime.Core.ContentAccess;
public interface IContentProviderRegistry
{
ReadOnlyObservableCollection<IContentProvider> ContentProviders { get; }
ReadOnlyObservableCollection<ISubContentProvider> SubContentProviders { get; }
void AddContentProvider(IContentProvider contentProvider);
void RemoveContentProvider(IContentProvider contentProvider);
Task<ISubContentProvider?> GetSubContentProviderForElement(IElement parentElement);
}

View File

@@ -0,0 +1,17 @@
using FileTime.Core.Enums;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
namespace FileTime.Core.ContentAccess;
public interface ISubContentProvider
{
Task<IItem?> GetItemByFullNameAsync(
IElement parentElement,
FullName itemPath,
PointInTime pointInTime,
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
ItemInitializationSettings itemInitializationSettings = default);
Task<bool> CanHandleAsync(IElement parentElement);
}

View File

@@ -1,8 +1,10 @@
using System.Diagnostics;
using FileTime.Core.Enums;
using FileTime.Core.Timeline;
namespace FileTime.Core.Models;
[DebuggerDisplay("{Path.Path}, {Type}")]
public class AbsolutePath
{
public ITimelessContentProvider TimelessProvider { get; }

View File

@@ -3,4 +3,5 @@ namespace FileTime.Core.Models;
public static class Constants
{
public const char SeparatorChar = '/';
public const string SubContentProviderRootContainer = ":";
}

View File

@@ -1,5 +1,8 @@
using System.Diagnostics;
namespace FileTime.Core.Models;
[DebuggerDisplay("{Path}")]
public record FullName(string Path)
{
public FullName? GetParent()

View File

@@ -1,6 +1,6 @@
namespace FileTime.Core.Models;
public sealed class ItemInitializationSettings
public readonly struct ItemInitializationSettings
{
public bool SkipChildInitialization { get; init; }
public AbsolutePath? Parent { get; init; }

View File

@@ -1,5 +1,8 @@
using System.Diagnostics;
namespace FileTime.Core.Models;
[DebuggerDisplay("{Path}")]
public record NativePath(string Path)
{
public override string ToString() => Path;

View File

@@ -1,4 +1,4 @@
using System.Reactive.Subjects;
using DeclarativeProperty;
using FileTime.Core.Enums;
using FileTime.Core.Models;
@@ -6,7 +6,7 @@ namespace FileTime.Core.Timeline;
public interface ITimelessContentProvider
{
BehaviorSubject<PointInTime> CurrentPointInTime { get; }
IDeclarativeProperty<PointInTime> CurrentPointInTime { get; }
Task<IItem> GetItemByFullNameAsync(FullName fullName,
PointInTime? pointInTime,

View File

@@ -1,4 +1,7 @@
using System.Collections.ObjectModel;
using FileTime.Core.Enums;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
using Microsoft.Extensions.DependencyInjection;
namespace FileTime.Core.ContentAccess;
@@ -8,13 +11,16 @@ public class ContentProviderRegistry : IContentProviderRegistry
private readonly object _lock = new();
private readonly IServiceProvider _serviceProvider;
private readonly ObservableCollection<IContentProvider> _contentProviders = new();
private readonly ObservableCollection<ISubContentProvider> _subContentProviders = new();
private readonly ReadOnlyObservableCollection<IContentProvider> _contentProvidersReadOnly;
private readonly ReadOnlyObservableCollection<ISubContentProvider> _subContentProvidersReadOnly;
private bool _initialized;
public ContentProviderRegistry(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
_contentProvidersReadOnly = new ReadOnlyObservableCollection<IContentProvider>(_contentProviders);
_subContentProvidersReadOnly = new ReadOnlyObservableCollection<ISubContentProvider>(_subContentProviders);
}
public ReadOnlyObservableCollection<IContentProvider> ContentProviders
@@ -26,20 +32,33 @@ public class ContentProviderRegistry : IContentProviderRegistry
}
}
public ReadOnlyObservableCollection<ISubContentProvider> SubContentProviders
{
get
{
InitializeContentProviderListIfNeeded();
return _subContentProvidersReadOnly;
}
}
private void InitializeContentProviderListIfNeeded()
{
if (_initialized) return;
lock (_lock)
{
if (!_initialized)
{
foreach (var contentProvider in _serviceProvider.GetServices<IContentProvider>())
{
_contentProviders.Add(contentProvider);
}
if (_initialized) return;
_initialized = true;
foreach (var contentProvider in _serviceProvider.GetServices<IContentProvider>())
{
_contentProviders.Add(contentProvider);
}
foreach (var subContentProvider in _serviceProvider.GetServices<ISubContentProvider>())
{
_subContentProviders.Add(subContentProvider);
}
_initialized = true;
}
}
@@ -62,4 +81,20 @@ public class ContentProviderRegistry : IContentProviderRegistry
_contentProviders.Remove(contentProvider);
}
}
public async Task<ISubContentProvider?> GetSubContentProviderForElement(IElement parentElement)
{
var subContentProviders = _serviceProvider
.GetServices<ISubContentProvider>()
.ToList();
foreach (var subContentProvider in subContentProviders)
{
if(!await subContentProvider.CanHandleAsync(parentElement)) continue;
return subContentProvider;
}
return null;
}
}

View File

@@ -0,0 +1,46 @@
using FileTime.Core.Enums;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
namespace FileTime.Core.ContentAccess;
public abstract class SubContentProviderBase : ContentProviderBase
{
private readonly IContentProvider _parentContentProvider;
protected SubContentProviderBase(
IContentProvider parentContentProvider,
string name,
ITimelessContentProvider timelessContentProvider) : base(name, timelessContentProvider)
{
_parentContentProvider = parentContentProvider;
}
public override async Task<IItem> GetItemByNativePathAsync(
NativePath nativePath,
PointInTime pointInTime,
bool forceResolve = false,
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
ItemInitializationSettings itemInitializationSettings = default)
=> await _parentContentProvider.GetItemByNativePathAsync(
nativePath,
pointInTime,
forceResolve,
forceResolvePathType,
itemInitializationSettings);
public override async ValueTask<NativePath> GetNativePathAsync(FullName fullName)
=> await _parentContentProvider.GetNativePathAsync(fullName);
public override FullName GetFullName(NativePath nativePath)
=> _parentContentProvider.GetFullName(nativePath);
public override async Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default)
=> await _parentContentProvider.GetContentAsync(element, maxLength, cancellationToken);
public override async Task<bool> CanHandlePathAsync(NativePath path)
=> await _parentContentProvider.CanHandlePathAsync(path);
public override VolumeSizeInfo? GetVolumeSizeInfo(FullName path)
=> _parentContentProvider.GetVolumeSizeInfo(path);
}

View File

@@ -1,4 +1,4 @@
using System.Reactive.Subjects;
using DeclarativeProperty;
using FileTime.Core.ContentAccess;
using FileTime.Core.Enums;
using FileTime.Core.Models;
@@ -10,8 +10,8 @@ public class TimelessContentProvider : ITimelessContentProvider
{
private readonly IContentProviderRegistry _contentProviderRegistry;
private readonly Lazy<IRootContentProvider> _rootContentProvider;
public BehaviorSubject<PointInTime> CurrentPointInTime { get; } = new(PointInTime.Present);
private readonly DeclarativeProperty<PointInTime> _currentPointInTime = new(PointInTime.Present);
public IDeclarativeProperty<PointInTime> CurrentPointInTime => _currentPointInTime;
public TimelessContentProvider(
IContentProviderRegistry contentProviderRegistry,