Use primary constructors
This commit is contained in:
@@ -3,9 +3,9 @@ using PropertyChanged.SourceGenerator;
|
|||||||
|
|
||||||
namespace FileTime.Core.Interactions;
|
namespace FileTime.Core.Interactions;
|
||||||
|
|
||||||
public partial class OptionsInputElement<T> : InputElementBase, IOptionsInputElement, INotifyPropertyChanged
|
public partial class OptionsInputElement<T>(string label, IEnumerable<OptionElement<T>> options) : InputElementBase(label, InputType.Options), IOptionsInputElement, INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
public IReadOnlyCollection<OptionElement<T>> Options { get; }
|
public IReadOnlyCollection<OptionElement<T>> Options { get; } = Enumerable.ToList<OptionElement<T>>(options);
|
||||||
|
|
||||||
[Notify] private T? _value;
|
[Notify] private T? _value;
|
||||||
|
|
||||||
@@ -26,9 +26,4 @@ public partial class OptionsInputElement<T> : InputElementBase, IOptionsInputEle
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public OptionsInputElement(string label, IEnumerable<OptionElement<T>> options) : base(label, InputType.Options)
|
|
||||||
{
|
|
||||||
Options = options.ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
namespace GeneralInputKey;
|
namespace GeneralInputKey;
|
||||||
|
|
||||||
public class GeneralKeyEventArgs
|
public class GeneralKeyEventArgs(Action<bool>? handledChanged = null)
|
||||||
{
|
{
|
||||||
private readonly Action<bool>? _handledChanged;
|
|
||||||
private bool _handled;
|
private bool _handled;
|
||||||
public required Keys? Key { get; init; }
|
public required Keys? Key { get; init; }
|
||||||
public required char KeyChar { get; init; }
|
public required char KeyChar { get; init; }
|
||||||
@@ -16,13 +15,8 @@ public class GeneralKeyEventArgs
|
|||||||
if (_handled != value)
|
if (_handled != value)
|
||||||
{
|
{
|
||||||
_handled = value;
|
_handled = value;
|
||||||
_handledChanged?.Invoke(value);
|
handledChanged?.Invoke(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeneralKeyEventArgs(Action<bool>? handledChanged = null)
|
|
||||||
{
|
|
||||||
_handledChanged = handledChanged;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -5,9 +5,8 @@ using TerminalUI.TextFormat;
|
|||||||
|
|
||||||
namespace TerminalUI.Examples.Controls;
|
namespace TerminalUI.Examples.Controls;
|
||||||
|
|
||||||
public class ProgressBarExamples
|
public class ProgressBarExamples(IApplicationContext applicationContext)
|
||||||
{
|
{
|
||||||
private readonly IApplicationContext _applicationContext;
|
|
||||||
private static readonly IConsoleDriver _driver;
|
private static readonly IConsoleDriver _driver;
|
||||||
|
|
||||||
static ProgressBarExamples()
|
static ProgressBarExamples()
|
||||||
@@ -16,11 +15,6 @@ public class ProgressBarExamples
|
|||||||
_driver.Init();
|
_driver.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgressBarExamples(IApplicationContext applicationContext)
|
|
||||||
{
|
|
||||||
_applicationContext = applicationContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadingExample()
|
public void LoadingExample()
|
||||||
{
|
{
|
||||||
var progressBar = CreateProgressBar<object>(0);
|
var progressBar = CreateProgressBar<object>(0);
|
||||||
@@ -46,7 +40,7 @@ public class ProgressBarExamples
|
|||||||
{
|
{
|
||||||
Value = percent,
|
Value = percent,
|
||||||
Attached = true,
|
Attached = true,
|
||||||
ApplicationContext = _applicationContext
|
ApplicationContext = applicationContext
|
||||||
};
|
};
|
||||||
|
|
||||||
private void RenderProgressBar<T>(ProgressBar<T> progressBar, Position position)
|
private void RenderProgressBar<T>(ProgressBar<T> progressBar, Position position)
|
||||||
|
|||||||
@@ -6,13 +6,7 @@ namespace TerminalUI.Tests.Models;
|
|||||||
|
|
||||||
public sealed partial class TestViewModel : INotifyPropertyChanged
|
public sealed partial class TestViewModel : INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
[Notify] private List<TestNestedCollectionItem> _items;
|
[Notify] private List<TestNestedCollectionItem> _items = new()
|
||||||
[Notify] private string _text;
|
|
||||||
|
|
||||||
public TestViewModel()
|
|
||||||
{
|
|
||||||
_text = "Initial text";
|
|
||||||
_items = new List<TestNestedCollectionItem>
|
|
||||||
{
|
{
|
||||||
TestNestedCollectionItem.Create(
|
TestNestedCollectionItem.Create(
|
||||||
3,
|
3,
|
||||||
@@ -23,7 +17,7 @@ public sealed partial class TestViewModel : INotifyPropertyChanged
|
|||||||
new()
|
new()
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
[Notify] private string _text = "Initial text";
|
||||||
|
|
||||||
public event PropertyChangedEventHandler? PropertyChanged;
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ using TerminalUI.Styling;
|
|||||||
|
|
||||||
namespace TerminalUI;
|
namespace TerminalUI;
|
||||||
|
|
||||||
public class ApplicationContext : IApplicationContext
|
public class ApplicationContext(IServiceProvider serviceProvider) : IApplicationContext
|
||||||
{
|
{
|
||||||
private readonly Lazy<IConsoleDriver> _consoleDriver;
|
private readonly Lazy<IConsoleDriver> _consoleDriver = new Lazy<IConsoleDriver>(serviceProvider.GetRequiredService<IConsoleDriver>);
|
||||||
private readonly Lazy<IFocusManager> _focusManager;
|
private readonly Lazy<IFocusManager> _focusManager = new Lazy<IFocusManager>(serviceProvider.GetRequiredService<IFocusManager>);
|
||||||
private readonly Lazy<ILoggerFactory?> _loggerFactory;
|
private readonly Lazy<ILoggerFactory?> _loggerFactory = new Lazy<ILoggerFactory?>(serviceProvider.GetService<ILoggerFactory?>);
|
||||||
private readonly Lazy<IRenderEngine> _renderEngine;
|
private readonly Lazy<IRenderEngine> _renderEngine = new Lazy<IRenderEngine>(serviceProvider.GetRequiredService<IRenderEngine>);
|
||||||
|
|
||||||
public IConsoleDriver ConsoleDriver => _consoleDriver.Value;
|
public IConsoleDriver ConsoleDriver => _consoleDriver.Value;
|
||||||
public IFocusManager FocusManager => _focusManager.Value;
|
public IFocusManager FocusManager => _focusManager.Value;
|
||||||
@@ -20,12 +20,4 @@ public class ApplicationContext : IApplicationContext
|
|||||||
public bool IsRunning { get; set; }
|
public bool IsRunning { get; set; }
|
||||||
public char EmptyCharacter { get; init; } = ' ';
|
public char EmptyCharacter { get; init; } = ' ';
|
||||||
public bool SupportUtf8Output { get; set; } = true;
|
public bool SupportUtf8Output { get; set; } = true;
|
||||||
|
|
||||||
public ApplicationContext(IServiceProvider serviceProvider)
|
|
||||||
{
|
|
||||||
_consoleDriver = new Lazy<IConsoleDriver>(serviceProvider.GetRequiredService<IConsoleDriver>);
|
|
||||||
_focusManager = new Lazy<IFocusManager>(serviceProvider.GetRequiredService<IFocusManager>);
|
|
||||||
_loggerFactory = new Lazy<ILoggerFactory?>(serviceProvider.GetService<ILoggerFactory?>);
|
|
||||||
_renderEngine = new Lazy<IRenderEngine>(serviceProvider.GetRequiredService<IRenderEngine>);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -7,31 +7,24 @@ namespace TerminalUI.Controls;
|
|||||||
public record ChildWithDataContextMapper<TSourceDataContext, TTargetDataContext>(IView<TTargetDataContext> Child, Func<TSourceDataContext?, TTargetDataContext?> DataContextMapper);
|
public record ChildWithDataContextMapper<TSourceDataContext, TTargetDataContext>(IView<TTargetDataContext> Child, Func<TSourceDataContext?, TTargetDataContext?> DataContextMapper);
|
||||||
public record ChildWithDataContextBinding<TSourceDataContext, TTargetDataContext>(IView<TTargetDataContext> Child, Expression<Func<TSourceDataContext?, TTargetDataContext?>> DataContextExpression);
|
public record ChildWithDataContextBinding<TSourceDataContext, TTargetDataContext>(IView<TTargetDataContext> Child, Expression<Func<TSourceDataContext?, TTargetDataContext?>> DataContextExpression);
|
||||||
|
|
||||||
public class ChildInitializer<T> : IEnumerable<IView>
|
public class ChildInitializer<T>(IChildContainer<T> childContainer) : IEnumerable<IView>
|
||||||
{
|
{
|
||||||
private readonly IChildContainer<T> _childContainer;
|
public void Add(IView<T> item) => childContainer.AddChild(item);
|
||||||
|
|
||||||
public ChildInitializer(IChildContainer<T> childContainer)
|
|
||||||
{
|
|
||||||
_childContainer = childContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(IView<T> item) => _childContainer.AddChild(item);
|
|
||||||
|
|
||||||
public void Add<TDataContext>(ChildWithDataContextMapper<T, TDataContext> item)
|
public void Add<TDataContext>(ChildWithDataContextMapper<T, TDataContext> item)
|
||||||
=> _childContainer.AddChild(item.Child, item.DataContextMapper);
|
=> childContainer.AddChild(item.Child, item.DataContextMapper);
|
||||||
|
|
||||||
public void Add<TDataContext>(ChildWithDataContextBinding<T, TDataContext> item)
|
public void Add<TDataContext>(ChildWithDataContextBinding<T, TDataContext> item)
|
||||||
{
|
{
|
||||||
item.Child.Bind(
|
item.Child.Bind(
|
||||||
_childContainer,
|
childContainer,
|
||||||
item.DataContextExpression,
|
item.DataContextExpression,
|
||||||
c => c.DataContext
|
c => c.DataContext
|
||||||
);
|
);
|
||||||
_childContainer.AddChild(item.Child);
|
childContainer.AddChild(item.Child);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<IView> GetEnumerator() => _childContainer.Children.GetEnumerator();
|
public IEnumerator<IView> GetEnumerator() => childContainer.Children.GetEnumerator();
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
}
|
}
|
||||||
@@ -2,37 +2,30 @@
|
|||||||
|
|
||||||
namespace TerminalUI;
|
namespace TerminalUI;
|
||||||
|
|
||||||
public class EventLoop : IEventLoop
|
public class EventLoop(IApplicationContext applicationContext,
|
||||||
|
ILogger<EventLoop> logger)
|
||||||
|
: IEventLoop
|
||||||
{
|
{
|
||||||
private readonly IApplicationContext _applicationContext;
|
private readonly ILogger<EventLoop> _logger = logger;
|
||||||
private readonly ILogger<EventLoop> _logger;
|
|
||||||
private readonly List<Action> _initializers = new();
|
private readonly List<Action> _initializers = new();
|
||||||
private readonly List<Action> _permanentQueue = new();
|
private readonly List<Action> _permanentQueue = new();
|
||||||
private readonly List<Action> _finalizers = new();
|
private readonly List<Action> _finalizers = new();
|
||||||
|
|
||||||
public int ThreadId { get; set; } = -1;
|
public int ThreadId { get; set; } = -1;
|
||||||
|
|
||||||
public EventLoop(
|
|
||||||
IApplicationContext applicationContext,
|
|
||||||
ILogger<EventLoop> logger)
|
|
||||||
{
|
|
||||||
_applicationContext = applicationContext;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddToPermanentQueue(Action action) => _permanentQueue.Add(action);
|
public void AddToPermanentQueue(Action action) => _permanentQueue.Add(action);
|
||||||
public void AddInitializer(Action action) => _initializers.Add(action);
|
public void AddInitializer(Action action) => _initializers.Add(action);
|
||||||
public void AddFinalizer(Action action) => _finalizers.Add(action);
|
public void AddFinalizer(Action action) => _finalizers.Add(action);
|
||||||
|
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
_applicationContext.IsRunning = true;
|
applicationContext.IsRunning = true;
|
||||||
ThreadId = Thread.CurrentThread.ManagedThreadId;
|
ThreadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
foreach (var initializer in _initializers)
|
foreach (var initializer in _initializers)
|
||||||
{
|
{
|
||||||
initializer();
|
initializer();
|
||||||
}
|
}
|
||||||
while (_applicationContext.IsRunning)
|
while (applicationContext.IsRunning)
|
||||||
{
|
{
|
||||||
ProcessQueues();
|
ProcessQueues();
|
||||||
Thread.Sleep(10);
|
Thread.Sleep(10);
|
||||||
|
|||||||
@@ -5,9 +5,8 @@ using TerminalUI.Traits;
|
|||||||
|
|
||||||
namespace TerminalUI;
|
namespace TerminalUI;
|
||||||
|
|
||||||
public class FocusManager : IFocusManager
|
public class FocusManager(IRenderEngine renderEngine) : IFocusManager
|
||||||
{
|
{
|
||||||
private readonly IRenderEngine _renderEngine;
|
|
||||||
private IFocusable? _focused;
|
private IFocusable? _focused;
|
||||||
private DateTime _focusLostCandidateTime = DateTime.MinValue;
|
private DateTime _focusLostCandidateTime = DateTime.MinValue;
|
||||||
|
|
||||||
@@ -52,11 +51,6 @@ public class FocusManager : IFocusManager
|
|||||||
private set => _focused = value;
|
private set => _focused = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FocusManager(IRenderEngine renderEngine)
|
|
||||||
{
|
|
||||||
_renderEngine = renderEngine;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetFocus(IFocusable focusable) => Focused = focusable;
|
public void SetFocus(IFocusable focusable) => Focused = focusable;
|
||||||
|
|
||||||
public void UnFocus(IFocusable focusable)
|
public void UnFocus(IFocusable focusable)
|
||||||
@@ -127,8 +121,8 @@ public class FocusManager : IFocusManager
|
|||||||
|
|
||||||
if (element is null) return;
|
if (element is null) return;
|
||||||
|
|
||||||
_renderEngine.RequestRerender(element);
|
renderEngine.RequestRerender(element);
|
||||||
_renderEngine.RequestRerender(view);
|
renderEngine.RequestRerender(view);
|
||||||
Focused = element;
|
Focused = element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
namespace TerminalUI.Models;
|
namespace TerminalUI.Models;
|
||||||
|
|
||||||
public readonly ref struct Option<T>
|
public readonly ref struct Option<T>(T value, bool isSome)
|
||||||
{
|
{
|
||||||
public readonly T Value;
|
public readonly T Value = value;
|
||||||
public readonly bool IsSome;
|
public readonly bool IsSome = isSome;
|
||||||
|
|
||||||
public Option(T value, bool isSome)
|
|
||||||
{
|
|
||||||
Value = value;
|
|
||||||
IsSome = isSome;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,12 @@
|
|||||||
namespace TerminalUI.Models;
|
namespace TerminalUI.Models;
|
||||||
|
|
||||||
public readonly struct SelectiveChar
|
public readonly struct SelectiveChar(char utf8Char, char asciiChar)
|
||||||
{
|
{
|
||||||
public readonly char Utf8Char;
|
public readonly char Utf8Char = utf8Char;
|
||||||
public readonly char AsciiChar;
|
public readonly char AsciiChar = asciiChar;
|
||||||
|
|
||||||
public SelectiveChar(char c)
|
public SelectiveChar(char c) : this(c, c)
|
||||||
{
|
{
|
||||||
Utf8Char = c;
|
|
||||||
AsciiChar = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SelectiveChar(char utf8Char, char asciiChar)
|
|
||||||
{
|
|
||||||
Utf8Char = utf8Char;
|
|
||||||
AsciiChar = asciiChar;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public char GetChar(bool enableUtf8) => enableUtf8 ? Utf8Char : AsciiChar;
|
public char GetChar(bool enableUtf8) => enableUtf8 ? Utf8Char : AsciiChar;
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
namespace TerminalUI.TextFormat;
|
namespace TerminalUI.TextFormat;
|
||||||
|
|
||||||
public readonly struct TextFormatContext
|
public readonly struct TextFormatContext(bool supportsAnsi)
|
||||||
{
|
{
|
||||||
public readonly bool SupportsAnsi;
|
public readonly bool SupportsAnsi = supportsAnsi;
|
||||||
|
|
||||||
public TextFormatContext(bool supportsAnsi)
|
|
||||||
{
|
|
||||||
SupportsAnsi = supportsAnsi;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -6,29 +6,15 @@ using Microsoft.Extensions.Options;
|
|||||||
|
|
||||||
namespace FileTime.Server.Web;
|
namespace FileTime.Server.Web;
|
||||||
|
|
||||||
public class PortWriterService : IHostedService
|
public class PortWriterService(IServer server,
|
||||||
{
|
|
||||||
private readonly IServer _server;
|
|
||||||
private readonly IHostApplicationLifetime _hostApplicationLifetime;
|
|
||||||
private readonly IOptions<PortWriterConfiguration> _configuration;
|
|
||||||
private readonly ILogger<PortWriterService> _logger;
|
|
||||||
|
|
||||||
public PortWriterService(
|
|
||||||
IServer server,
|
|
||||||
IHostApplicationLifetime hostApplicationLifetime,
|
IHostApplicationLifetime hostApplicationLifetime,
|
||||||
IOptions<PortWriterConfiguration> configuration,
|
IOptions<PortWriterConfiguration> configuration,
|
||||||
ILogger<PortWriterService> logger)
|
ILogger<PortWriterService> logger)
|
||||||
{
|
: IHostedService
|
||||||
_server = server;
|
{
|
||||||
_hostApplicationLifetime = hostApplicationLifetime;
|
|
||||||
_configuration = configuration;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_hostApplicationLifetime.ApplicationStarted.Register(WritePort);
|
hostApplicationLifetime.ApplicationStarted.Register(WritePort);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@@ -37,28 +23,28 @@ public class PortWriterService : IHostedService
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var filename = _configuration.Value.Filename;
|
var filename = configuration.Value.Filename;
|
||||||
if (filename is null)
|
if (filename is null)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Could not save port to file as there were no file name given");
|
logger.LogWarning("Could not save port to file as there were no file name given");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var address = GetAddress();
|
var address = GetAddress();
|
||||||
if (address is null)
|
if (address is null)
|
||||||
{
|
{
|
||||||
_logger.LogError("Could not get address");
|
logger.LogError("Could not get address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var couldParsePort = int.TryParse(address.Split(':').LastOrDefault(), out var port);
|
var couldParsePort = int.TryParse(address.Split(':').LastOrDefault(), out var port);
|
||||||
if (!couldParsePort)
|
if (!couldParsePort)
|
||||||
{
|
{
|
||||||
_logger.LogError("Could not parse port from address {Address}", address);
|
logger.LogError("Could not parse port from address {Address}", address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("Writing port to {PortFile}", filename);
|
logger.LogInformation("Writing port to {PortFile}", filename);
|
||||||
using var tempFileStream = File.CreateText(filename);
|
using var tempFileStream = File.CreateText(filename);
|
||||||
tempFileStream.Write(port.ToString());
|
tempFileStream.Write(port.ToString());
|
||||||
|
|
||||||
@@ -67,24 +53,24 @@ public class PortWriterService : IHostedService
|
|||||||
await Task.Delay(5000);
|
await Task.Delay(5000);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Deleting port file {PortFile}", filename);
|
logger.LogInformation("Deleting port file {PortFile}", filename);
|
||||||
File.Delete(filename);
|
File.Delete(filename);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.LogError(e, "Error while deleting port file {PortFile}", filename);
|
logger.LogError(e, "Error while deleting port file {PortFile}", filename);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Could not save port to file");
|
logger.LogError(ex, "Could not save port to file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string? GetAddress()
|
private string? GetAddress()
|
||||||
{
|
{
|
||||||
var features = _server.Features;
|
var features = server.Features;
|
||||||
var addresses = features.Get<IServerAddressesFeature>();
|
var addresses = features.Get<IServerAddressesFeature>();
|
||||||
var address = addresses?.Addresses.FirstOrDefault();
|
var address = addresses?.Addresses.FirstOrDefault();
|
||||||
return address;
|
return address;
|
||||||
|
|||||||
@@ -5,37 +5,26 @@ using SharpCompress.Common;
|
|||||||
|
|
||||||
namespace FileTime.Tools.Compression;
|
namespace FileTime.Tools.Compression;
|
||||||
|
|
||||||
public class CompressOperation<TEntry, TVolume> : ICompressOperation
|
public class CompressOperation<TEntry, TVolume>(IContentAccessorFactory contentAccessorFactory,
|
||||||
|
AbstractWritableArchive<TEntry, TVolume> archive,
|
||||||
|
Action<Stream> saveTo)
|
||||||
|
: ICompressOperation
|
||||||
where TEntry : IArchiveEntry
|
where TEntry : IArchiveEntry
|
||||||
where TVolume : IVolume
|
where TVolume : IVolume
|
||||||
{
|
{
|
||||||
private readonly IContentAccessorFactory _contentAccessorFactory;
|
|
||||||
private readonly AbstractWritableArchive<TEntry, TVolume> _archive;
|
|
||||||
private readonly Action<Stream> _saveTo;
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
public CompressOperation(
|
|
||||||
IContentAccessorFactory contentAccessorFactory,
|
|
||||||
AbstractWritableArchive<TEntry, TVolume> archive,
|
|
||||||
Action<Stream> saveTo
|
|
||||||
)
|
|
||||||
{
|
|
||||||
_contentAccessorFactory = contentAccessorFactory;
|
|
||||||
_archive = archive;
|
|
||||||
_saveTo = saveTo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<IDisposable>> CompressElement(IElement element, string key)
|
public async Task<IEnumerable<IDisposable>> CompressElement(IElement element, string key)
|
||||||
{
|
{
|
||||||
var contentReader = await _contentAccessorFactory.GetContentReaderFactory(element.Provider).CreateContentReaderAsync(element);
|
var contentReader = await contentAccessorFactory.GetContentReaderFactory(element.Provider).CreateContentReaderAsync(element);
|
||||||
var contentReaderStream = contentReader.GetStream();
|
var contentReaderStream = contentReader.GetStream();
|
||||||
_archive.AddEntry(key, contentReaderStream);
|
archive.AddEntry(key, contentReaderStream);
|
||||||
|
|
||||||
return new IDisposable[] {contentReader, contentReaderStream};
|
return new IDisposable[] {contentReader, contentReaderStream};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveTo(Stream stream)
|
public void SaveTo(Stream stream)
|
||||||
=> _saveTo(stream);
|
=> saveTo(stream);
|
||||||
|
|
||||||
~CompressOperation()
|
~CompressOperation()
|
||||||
{
|
{
|
||||||
@@ -54,7 +43,7 @@ public class CompressOperation<TEntry, TVolume> : ICompressOperation
|
|||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
_archive.Dispose();
|
archive.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,31 +6,18 @@ using FileTime.Core.Timeline;
|
|||||||
|
|
||||||
namespace FileTime.Tools.Compression.Compress;
|
namespace FileTime.Tools.Compression.Compress;
|
||||||
|
|
||||||
public class CompressCommandFactory : ITransportationCommandFactory<CompressCommand>
|
public class CompressCommandFactory(IUserCommunicationService userCommunicationService,
|
||||||
{
|
|
||||||
private readonly IUserCommunicationService _userCommunicationService;
|
|
||||||
private readonly ITimelessContentProvider _timelessContentProvider;
|
|
||||||
private readonly IContentAccessorFactory _contentAccessorFactory;
|
|
||||||
private readonly ICommandSchedulerNotifier _commandSchedulerNotifier;
|
|
||||||
|
|
||||||
public CompressCommandFactory(
|
|
||||||
IUserCommunicationService userCommunicationService,
|
|
||||||
ITimelessContentProvider timelessContentProvider,
|
ITimelessContentProvider timelessContentProvider,
|
||||||
IContentAccessorFactory contentAccessorFactory,
|
IContentAccessorFactory contentAccessorFactory,
|
||||||
ICommandSchedulerNotifier commandSchedulerNotifier)
|
ICommandSchedulerNotifier commandSchedulerNotifier)
|
||||||
{
|
: ITransportationCommandFactory<CompressCommand>
|
||||||
_userCommunicationService = userCommunicationService;
|
{
|
||||||
_timelessContentProvider = timelessContentProvider;
|
|
||||||
_contentAccessorFactory = contentAccessorFactory;
|
|
||||||
_commandSchedulerNotifier = commandSchedulerNotifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CompressCommand GenerateCommand(IReadOnlyCollection<FullName> sources, TransportMode mode, FullName targetFullName)
|
public CompressCommand GenerateCommand(IReadOnlyCollection<FullName> sources, TransportMode mode, FullName targetFullName)
|
||||||
=> new(
|
=> new(
|
||||||
_userCommunicationService,
|
userCommunicationService,
|
||||||
_timelessContentProvider,
|
timelessContentProvider,
|
||||||
_contentAccessorFactory,
|
contentAccessorFactory,
|
||||||
_commandSchedulerNotifier,
|
commandSchedulerNotifier,
|
||||||
sources,
|
sources,
|
||||||
mode,
|
mode,
|
||||||
targetFullName
|
targetFullName
|
||||||
|
|||||||
@@ -5,24 +5,14 @@ using SharpCompress.Archives;
|
|||||||
|
|
||||||
namespace FileTime.Tools.Compression.ContentProvider;
|
namespace FileTime.Tools.Compression.ContentProvider;
|
||||||
|
|
||||||
public sealed class CompressedContentProvider : SubContentProviderBase, ICompressedContentProvider
|
public sealed class CompressedContentProvider(ITimelessContentProvider timelessContentProvider,
|
||||||
{
|
|
||||||
private readonly ITimelessContentProvider _timelessContentProvider;
|
|
||||||
|
|
||||||
public CompressedContentProvider(
|
|
||||||
ITimelessContentProvider timelessContentProvider,
|
|
||||||
IContentAccessorFactory contentAccessorFactory,
|
IContentAccessorFactory contentAccessorFactory,
|
||||||
IContentProvider parentContentProvider
|
IContentProvider parentContentProvider)
|
||||||
)
|
: SubContentProviderBase(timelessContentProvider,
|
||||||
: base(
|
|
||||||
timelessContentProvider,
|
|
||||||
contentAccessorFactory,
|
contentAccessorFactory,
|
||||||
parentContentProvider,
|
parentContentProvider,
|
||||||
"compression")
|
"compression"), ICompressedContentProvider
|
||||||
{
|
{
|
||||||
_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)
|
||||||
{
|
{
|
||||||
var parentElementContext = await GetParentElementReaderAsync(element);
|
var parentElementContext = await GetParentElementReaderAsync(element);
|
||||||
@@ -43,7 +33,7 @@ public sealed class CompressedContentProvider : SubContentProviderBase, ICompres
|
|||||||
|
|
||||||
public override async ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path)
|
public override async ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path)
|
||||||
{
|
{
|
||||||
var item = await GetItemByFullNameAsync(path, _timelessContentProvider.CurrentPointInTime.Value!);
|
var item = await GetItemByFullNameAsync(path, timelessContentProvider.CurrentPointInTime.Value!);
|
||||||
var parentElement = await GetParentElementAsync(item);
|
var parentElement = await GetParentElementAsync(item);
|
||||||
return new VolumeSizeInfo(parentElement.Size, 0);
|
return new VolumeSizeInfo(parentElement.Size, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,10 @@ using FileTime.Core.Timeline;
|
|||||||
|
|
||||||
namespace FileTime.Tools.Compression.ContentProvider;
|
namespace FileTime.Tools.Compression.ContentProvider;
|
||||||
|
|
||||||
public sealed class CompressedContentProviderFactory : ICompressedContentProviderFactory
|
public sealed class CompressedContentProviderFactory(ITimelessContentProvider timelessContentProvider,
|
||||||
{
|
|
||||||
private readonly ITimelessContentProvider _timelessContentProvider;
|
|
||||||
private readonly IContentAccessorFactory _contentAccessorFactory;
|
|
||||||
|
|
||||||
public CompressedContentProviderFactory(
|
|
||||||
ITimelessContentProvider timelessContentProvider,
|
|
||||||
IContentAccessorFactory contentAccessorFactory)
|
IContentAccessorFactory contentAccessorFactory)
|
||||||
{
|
: ICompressedContentProviderFactory
|
||||||
_timelessContentProvider = timelessContentProvider;
|
{
|
||||||
_contentAccessorFactory = contentAccessorFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ICompressedContentProvider Create(IContentProvider parentContentProvider)
|
public ICompressedContentProvider Create(IContentProvider parentContentProvider)
|
||||||
=> new CompressedContentProvider(_timelessContentProvider, _contentAccessorFactory, parentContentProvider);
|
=> new CompressedContentProvider(timelessContentProvider, contentAccessorFactory, parentContentProvider);
|
||||||
}
|
}
|
||||||
@@ -3,21 +3,14 @@ using SharpCompress.Archives;
|
|||||||
|
|
||||||
namespace FileTime.Tools.Compression.ContentProvider;
|
namespace FileTime.Tools.Compression.ContentProvider;
|
||||||
|
|
||||||
public sealed class CompressedContentReader : IContentReader
|
public sealed class CompressedContentReader(IArchiveEntry entry, IDisposable[] disposables) : IContentReader
|
||||||
{
|
{
|
||||||
private readonly IDisposable[] _disposables;
|
private readonly Stream _stream = entry.OpenEntryStream();
|
||||||
private readonly Stream _stream;
|
|
||||||
|
|
||||||
public CompressedContentReader(IArchiveEntry entry, IDisposable[] disposables)
|
|
||||||
{
|
|
||||||
_disposables = disposables;
|
|
||||||
_stream = entry.OpenEntryStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_stream.Dispose();
|
_stream.Dispose();
|
||||||
foreach (var disposable in _disposables)
|
foreach (var disposable in disposables)
|
||||||
{
|
{
|
||||||
disposable.Dispose();
|
disposable.Dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,8 @@ using SharpCompress.Archives;
|
|||||||
|
|
||||||
namespace FileTime.Tools.Compression.ContentProvider;
|
namespace FileTime.Tools.Compression.ContentProvider;
|
||||||
|
|
||||||
public sealed class CompressedContentReaderFactory : SubContentReaderBase<CompressedContentProvider>
|
public sealed class CompressedContentReaderFactory(IContentAccessorFactory contentAccessorFactory) : SubContentReaderBase<CompressedContentProvider>(contentAccessorFactory)
|
||||||
{
|
{
|
||||||
|
|
||||||
public CompressedContentReaderFactory(IContentAccessorFactory contentAccessorFactory)
|
|
||||||
: base(contentAccessorFactory)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
public override async Task<IContentReader> CreateContentReaderAsync(IElement element)
|
public override async Task<IContentReader> CreateContentReaderAsync(IElement element)
|
||||||
{
|
{
|
||||||
if (element.Provider is not CompressedContentProvider provider)
|
if (element.Provider is not CompressedContentProvider provider)
|
||||||
|
|||||||
@@ -8,25 +8,13 @@ using IContainer = FileTime.Core.Models.IContainer;
|
|||||||
|
|
||||||
namespace FileTime.Tools.Compression.ContentProvider;
|
namespace FileTime.Tools.Compression.ContentProvider;
|
||||||
|
|
||||||
public sealed class CompressedSubContentProvider : ICompressedSubContentProvider
|
public sealed class CompressedSubContentProvider(IContentAccessorFactory contentAccessorFactory,
|
||||||
|
ICompressedContentProviderFactory compressedContentProviderFactory,
|
||||||
|
ITimelessContentProvider timelessContentProvider)
|
||||||
|
: ICompressedSubContentProvider
|
||||||
{
|
{
|
||||||
private static readonly string[] SupportedExtensions = {".zip", ".gz", ".7z"};
|
private static readonly string[] SupportedExtensions = {".zip", ".gz", ".7z"};
|
||||||
|
|
||||||
private readonly IContentAccessorFactory _contentAccessorFactory;
|
|
||||||
private readonly ICompressedContentProviderFactory _compressedContentProviderFactory;
|
|
||||||
private readonly ITimelessContentProvider _timelessContentProvider;
|
|
||||||
|
|
||||||
public CompressedSubContentProvider(
|
|
||||||
IContentAccessorFactory contentAccessorFactory,
|
|
||||||
ICompressedContentProviderFactory compressedContentProviderFactory,
|
|
||||||
ITimelessContentProvider timelessContentProvider
|
|
||||||
)
|
|
||||||
{
|
|
||||||
_contentAccessorFactory = contentAccessorFactory;
|
|
||||||
_compressedContentProviderFactory = compressedContentProviderFactory;
|
|
||||||
_timelessContentProvider = timelessContentProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<bool> CanHandleAsync(IElement parentElement)
|
public Task<bool> CanHandleAsync(IElement parentElement)
|
||||||
=> Task.FromResult(
|
=> Task.FromResult(
|
||||||
parentElement.NativePath?.Path is { } path
|
parentElement.NativePath?.Path is { } path
|
||||||
@@ -40,7 +28,7 @@ public sealed class CompressedSubContentProvider : ICompressedSubContentProvider
|
|||||||
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
||||||
ItemInitializationSettings itemInitializationSettings = default)
|
ItemInitializationSettings itemInitializationSettings = default)
|
||||||
{
|
{
|
||||||
var parentContentReader = await _contentAccessorFactory.GetContentReaderFactory(parentElement.Provider).CreateContentReaderAsync(parentElement);
|
var parentContentReader = await contentAccessorFactory.GetContentReaderFactory(parentElement.Provider).CreateContentReaderAsync(parentElement);
|
||||||
var parentContentReaderStream = parentContentReader.GetStream();
|
var parentContentReaderStream = parentContentReader.GetStream();
|
||||||
var archive = ArchiveFactory.Open(parentContentReaderStream);
|
var archive = ArchiveFactory.Open(parentContentReaderStream);
|
||||||
var disposables = new IDisposable[] {parentContentReader, parentContentReaderStream, archive};
|
var disposables = new IDisposable[] {parentContentReader, parentContentReaderStream, archive};
|
||||||
@@ -117,7 +105,7 @@ public sealed class CompressedSubContentProvider : ICompressedSubContentProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
var parent = new AbsolutePath(
|
var parent = new AbsolutePath(
|
||||||
_timelessContentProvider,
|
timelessContentProvider,
|
||||||
parentElement.PointInTime,
|
parentElement.PointInTime,
|
||||||
childFullName.GetParent()!,
|
childFullName.GetParent()!,
|
||||||
AbsolutePathType.Container
|
AbsolutePathType.Container
|
||||||
@@ -183,7 +171,7 @@ public sealed class CompressedSubContentProvider : ICompressedSubContentProvider
|
|||||||
SupportsDelete.False,
|
SupportsDelete.False,
|
||||||
false,
|
false,
|
||||||
"",
|
"",
|
||||||
_compressedContentProviderFactory.Create(parentElement.Provider),
|
compressedContentProviderFactory.Create(parentElement.Provider),
|
||||||
false,
|
false,
|
||||||
parentElement.PointInTime,
|
parentElement.PointInTime,
|
||||||
exceptions,
|
exceptions,
|
||||||
@@ -246,7 +234,7 @@ public sealed class CompressedSubContentProvider : ICompressedSubContentProvider
|
|||||||
addedContainers.Add(itemName);
|
addedContainers.Add(itemName);
|
||||||
|
|
||||||
children.Add(new AbsolutePath(
|
children.Add(new AbsolutePath(
|
||||||
_timelessContentProvider,
|
timelessContentProvider,
|
||||||
pointInTime,
|
pointInTime,
|
||||||
container.FullName.GetChild(itemName),
|
container.FullName.GetChild(itemName),
|
||||||
AbsolutePathType.Container)
|
AbsolutePathType.Container)
|
||||||
@@ -256,7 +244,7 @@ public sealed class CompressedSubContentProvider : ICompressedSubContentProvider
|
|||||||
{
|
{
|
||||||
//Element
|
//Element
|
||||||
children.Add(new AbsolutePath(
|
children.Add(new AbsolutePath(
|
||||||
_timelessContentProvider,
|
timelessContentProvider,
|
||||||
pointInTime,
|
pointInTime,
|
||||||
container.FullName.GetChild(itemName),
|
container.FullName.GetChild(itemName),
|
||||||
AbsolutePathType.Element)
|
AbsolutePathType.Element)
|
||||||
@@ -290,7 +278,7 @@ public sealed class CompressedSubContentProvider : ICompressedSubContentProvider
|
|||||||
false,
|
false,
|
||||||
"",
|
"",
|
||||||
size,
|
size,
|
||||||
_compressedContentProviderFactory.Create(parentElement.Provider),
|
compressedContentProviderFactory.Create(parentElement.Provider),
|
||||||
parentElement.PointInTime,
|
parentElement.PointInTime,
|
||||||
exceptions,
|
exceptions,
|
||||||
new ReadOnlyExtensionCollection(new ExtensionCollection())
|
new ReadOnlyExtensionCollection(new ExtensionCollection())
|
||||||
|
|||||||
@@ -5,27 +5,16 @@ using FileTime.Core.Timeline;
|
|||||||
|
|
||||||
namespace FileTime.Tools.Compression.Decompress;
|
namespace FileTime.Tools.Compression.Decompress;
|
||||||
|
|
||||||
public class DecompressCommandFactory : ITransportationCommandFactory<DecompressCommand>
|
public class DecompressCommandFactory(ITimelessContentProvider timelessContentProvider,
|
||||||
{
|
|
||||||
private readonly ITimelessContentProvider _timelessContentProvider;
|
|
||||||
private readonly IContentAccessorFactory _contentAccessorFactory;
|
|
||||||
private readonly ICommandSchedulerNotifier _commandSchedulerNotifier;
|
|
||||||
|
|
||||||
public DecompressCommandFactory(
|
|
||||||
ITimelessContentProvider timelessContentProvider,
|
|
||||||
IContentAccessorFactory contentAccessorFactory,
|
IContentAccessorFactory contentAccessorFactory,
|
||||||
ICommandSchedulerNotifier commandSchedulerNotifier)
|
ICommandSchedulerNotifier commandSchedulerNotifier)
|
||||||
{
|
: ITransportationCommandFactory<DecompressCommand>
|
||||||
_timelessContentProvider = timelessContentProvider;
|
{
|
||||||
_contentAccessorFactory = contentAccessorFactory;
|
|
||||||
_commandSchedulerNotifier = commandSchedulerNotifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DecompressCommand GenerateCommand(IReadOnlyCollection<FullName> sources, TransportMode mode, FullName targetFullName)
|
public DecompressCommand GenerateCommand(IReadOnlyCollection<FullName> sources, TransportMode mode, FullName targetFullName)
|
||||||
=> new(
|
=> new(
|
||||||
_timelessContentProvider,
|
timelessContentProvider,
|
||||||
_contentAccessorFactory,
|
contentAccessorFactory,
|
||||||
_commandSchedulerNotifier,
|
commandSchedulerNotifier,
|
||||||
sources,
|
sources,
|
||||||
mode,
|
mode,
|
||||||
targetFullName);
|
targetFullName);
|
||||||
|
|||||||
@@ -5,24 +5,14 @@ using FileTime.Core.Timeline;
|
|||||||
|
|
||||||
namespace FileTime.Tools.VirtualDiskSources;
|
namespace FileTime.Tools.VirtualDiskSources;
|
||||||
|
|
||||||
public sealed class VirtualDiskContentProvider : SubContentProviderBase, IVirtualDiskContentProvider
|
public sealed class VirtualDiskContentProvider(ITimelessContentProvider timelessContentProvider,
|
||||||
{
|
|
||||||
private readonly ITimelessContentProvider _timelessContentProvider;
|
|
||||||
|
|
||||||
public VirtualDiskContentProvider(
|
|
||||||
ITimelessContentProvider timelessContentProvider,
|
|
||||||
IContentAccessorFactory contentAccessorFactory,
|
IContentAccessorFactory contentAccessorFactory,
|
||||||
IContentProvider parentContentProvider)
|
IContentProvider parentContentProvider)
|
||||||
: base(
|
: SubContentProviderBase(timelessContentProvider,
|
||||||
timelessContentProvider,
|
|
||||||
contentAccessorFactory,
|
contentAccessorFactory,
|
||||||
parentContentProvider,
|
parentContentProvider,
|
||||||
"virtual-disk"
|
"virtual-disk"), IVirtualDiskContentProvider
|
||||||
)
|
{
|
||||||
{
|
|
||||||
_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)
|
||||||
{
|
{
|
||||||
var parentElementContext = await GetParentElementReaderAsync(element);
|
var parentElementContext = await GetParentElementReaderAsync(element);
|
||||||
@@ -44,7 +34,7 @@ public sealed class VirtualDiskContentProvider : SubContentProviderBase, IVirtua
|
|||||||
|
|
||||||
public override async ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path)
|
public override async ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path)
|
||||||
{
|
{
|
||||||
var item = await GetItemByFullNameAsync(path, _timelessContentProvider.CurrentPointInTime.Value!);
|
var item = await GetItemByFullNameAsync(path, timelessContentProvider.CurrentPointInTime.Value!);
|
||||||
var parentElement = await GetParentElementAsync(item);
|
var parentElement = await GetParentElementAsync(item);
|
||||||
return new VolumeSizeInfo(parentElement.Size, 0);
|
return new VolumeSizeInfo(parentElement.Size, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,10 @@ using FileTime.Core.Timeline;
|
|||||||
|
|
||||||
namespace FileTime.Tools.VirtualDiskSources;
|
namespace FileTime.Tools.VirtualDiskSources;
|
||||||
|
|
||||||
public sealed class VirtualDiskContentProviderFactory : IVirtualDiskContentProviderFactory
|
public sealed class VirtualDiskContentProviderFactory(ITimelessContentProvider timelessContentProvider,
|
||||||
{
|
|
||||||
private readonly ITimelessContentProvider _timelessContentProvider;
|
|
||||||
private readonly IContentAccessorFactory _contentAccessorFactory;
|
|
||||||
|
|
||||||
public VirtualDiskContentProviderFactory(
|
|
||||||
ITimelessContentProvider timelessContentProvider,
|
|
||||||
IContentAccessorFactory contentAccessorFactory)
|
IContentAccessorFactory contentAccessorFactory)
|
||||||
{
|
: IVirtualDiskContentProviderFactory
|
||||||
_timelessContentProvider = timelessContentProvider;
|
{
|
||||||
_contentAccessorFactory = contentAccessorFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IVirtualDiskContentProvider Create(IContentProvider parentContentProvider)
|
public IVirtualDiskContentProvider Create(IContentProvider parentContentProvider)
|
||||||
=> new VirtualDiskContentProvider(_timelessContentProvider, _contentAccessorFactory, parentContentProvider);
|
=> new VirtualDiskContentProvider(timelessContentProvider, contentAccessorFactory, parentContentProvider);
|
||||||
}
|
}
|
||||||
@@ -2,23 +2,14 @@
|
|||||||
|
|
||||||
namespace FileTime.Tools.VirtualDiskSources;
|
namespace FileTime.Tools.VirtualDiskSources;
|
||||||
|
|
||||||
public sealed class VirtualDiskContentReader : IContentReader
|
public sealed class VirtualDiskContentReader(Stream stream, ICollection<IDisposable> disposables) : IContentReader
|
||||||
{
|
{
|
||||||
private readonly Stream _stream;
|
public Stream GetStream() => stream;
|
||||||
private readonly ICollection<IDisposable> _disposables;
|
|
||||||
|
|
||||||
public VirtualDiskContentReader(Stream stream, ICollection<IDisposable> disposables)
|
|
||||||
{
|
|
||||||
_stream = stream;
|
|
||||||
_disposables = disposables;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Stream GetStream() => _stream;
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_stream.Dispose();
|
stream.Dispose();
|
||||||
foreach (var disposable in _disposables)
|
foreach (var disposable in disposables)
|
||||||
{
|
{
|
||||||
disposable.Dispose();
|
disposable.Dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,8 @@ using FileTime.Core.Models;
|
|||||||
|
|
||||||
namespace FileTime.Tools.VirtualDiskSources;
|
namespace FileTime.Tools.VirtualDiskSources;
|
||||||
|
|
||||||
public sealed class VirtualDiskContentReaderFactory : SubContentReaderBase<VirtualDiskContentProvider>
|
public sealed class VirtualDiskContentReaderFactory(IContentAccessorFactory contentAccessorFactory) : SubContentReaderBase<VirtualDiskContentProvider>(contentAccessorFactory)
|
||||||
{
|
{
|
||||||
public VirtualDiskContentReaderFactory(IContentAccessorFactory contentAccessorFactory)
|
|
||||||
: base(contentAccessorFactory)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<IContentReader> CreateContentReaderAsync(IElement element)
|
public override async Task<IContentReader> CreateContentReaderAsync(IElement element)
|
||||||
{
|
{
|
||||||
if (element.Provider is not VirtualDiskContentProvider provider)
|
if (element.Provider is not VirtualDiskContentProvider provider)
|
||||||
|
|||||||
@@ -8,23 +8,11 @@ using FileTime.Core.Timeline;
|
|||||||
|
|
||||||
namespace FileTime.Tools.VirtualDiskSources;
|
namespace FileTime.Tools.VirtualDiskSources;
|
||||||
|
|
||||||
public sealed class VirtualDiskSubContentProvider : IVirtualDiskSubContentProvider
|
public sealed class VirtualDiskSubContentProvider(IContentAccessorFactory contentAccessorFactory,
|
||||||
{
|
|
||||||
private readonly IContentAccessorFactory _contentAccessorFactory;
|
|
||||||
private readonly ITimelessContentProvider _timelessContentProvider;
|
|
||||||
private readonly IVirtualDiskContentProviderFactory _virtualDiskContentProviderFactory;
|
|
||||||
|
|
||||||
public VirtualDiskSubContentProvider(
|
|
||||||
IContentAccessorFactory contentAccessorFactory,
|
|
||||||
ITimelessContentProvider timelessContentProvider,
|
ITimelessContentProvider timelessContentProvider,
|
||||||
IVirtualDiskContentProviderFactory virtualDiskContentProviderFactory
|
IVirtualDiskContentProviderFactory virtualDiskContentProviderFactory)
|
||||||
)
|
: IVirtualDiskSubContentProvider
|
||||||
{
|
{
|
||||||
_contentAccessorFactory = contentAccessorFactory;
|
|
||||||
_timelessContentProvider = timelessContentProvider;
|
|
||||||
_virtualDiskContentProviderFactory = virtualDiskContentProviderFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<bool> CanHandleAsync(IElement parentElement)
|
public Task<bool> CanHandleAsync(IElement parentElement)
|
||||||
=> Task.FromResult(parentElement.NativePath?.Path.EndsWith(".iso", StringComparison.OrdinalIgnoreCase) ?? false);
|
=> Task.FromResult(parentElement.NativePath?.Path.EndsWith(".iso", StringComparison.OrdinalIgnoreCase) ?? false);
|
||||||
|
|
||||||
@@ -35,7 +23,7 @@ public sealed class VirtualDiskSubContentProvider : IVirtualDiskSubContentProvid
|
|||||||
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
||||||
ItemInitializationSettings itemInitializationSettings = default)
|
ItemInitializationSettings itemInitializationSettings = default)
|
||||||
{
|
{
|
||||||
var contentReaderFactory = _contentAccessorFactory.GetContentReaderFactory(parentElement.Provider);
|
var contentReaderFactory = contentAccessorFactory.GetContentReaderFactory(parentElement.Provider);
|
||||||
var reader = await contentReaderFactory.CreateContentReaderAsync(parentElement);
|
var reader = await contentReaderFactory.CreateContentReaderAsync(parentElement);
|
||||||
|
|
||||||
await using var readerStream = reader.GetStream();
|
await using var readerStream = reader.GetStream();
|
||||||
@@ -80,7 +68,7 @@ public sealed class VirtualDiskSubContentProvider : IVirtualDiskSubContentProvid
|
|||||||
var childNativePath = new NativePath(childNativePathBase);
|
var childNativePath = new NativePath(childNativePathBase);
|
||||||
|
|
||||||
var parent = new AbsolutePath(
|
var parent = new AbsolutePath(
|
||||||
_timelessContentProvider,
|
timelessContentProvider,
|
||||||
pointInTime,
|
pointInTime,
|
||||||
childFullName.GetParent()!,
|
childFullName.GetParent()!,
|
||||||
AbsolutePathType.Container
|
AbsolutePathType.Container
|
||||||
@@ -152,7 +140,7 @@ public sealed class VirtualDiskSubContentProvider : IVirtualDiskSubContentProvid
|
|||||||
SupportsDelete.False,
|
SupportsDelete.False,
|
||||||
false,
|
false,
|
||||||
FormatAttributes(sourceContainer.Attributes),
|
FormatAttributes(sourceContainer.Attributes),
|
||||||
_virtualDiskContentProviderFactory.Create(parentContentProvider),
|
virtualDiskContentProviderFactory.Create(parentContentProvider),
|
||||||
false,
|
false,
|
||||||
pointInTime,
|
pointInTime,
|
||||||
exceptions,
|
exceptions,
|
||||||
@@ -191,7 +179,7 @@ public sealed class VirtualDiskSubContentProvider : IVirtualDiskSubContentProvid
|
|||||||
foreach (var discDirectoryInfo in sourceContainer.GetDirectories())
|
foreach (var discDirectoryInfo in sourceContainer.GetDirectories())
|
||||||
{
|
{
|
||||||
children.Add(new AbsolutePath(
|
children.Add(new AbsolutePath(
|
||||||
_timelessContentProvider,
|
timelessContentProvider,
|
||||||
pointInTime,
|
pointInTime,
|
||||||
container.FullName.GetChild(discDirectoryInfo.Name),
|
container.FullName.GetChild(discDirectoryInfo.Name),
|
||||||
AbsolutePathType.Container)
|
AbsolutePathType.Container)
|
||||||
@@ -201,7 +189,7 @@ public sealed class VirtualDiskSubContentProvider : IVirtualDiskSubContentProvid
|
|||||||
foreach (var fileInfo in sourceContainer.GetFiles())
|
foreach (var fileInfo in sourceContainer.GetFiles())
|
||||||
{
|
{
|
||||||
children.Add(new AbsolutePath(
|
children.Add(new AbsolutePath(
|
||||||
_timelessContentProvider,
|
timelessContentProvider,
|
||||||
pointInTime,
|
pointInTime,
|
||||||
container.FullName.GetChild(fileInfo.Name),
|
container.FullName.GetChild(fileInfo.Name),
|
||||||
AbsolutePathType.Element)
|
AbsolutePathType.Element)
|
||||||
@@ -230,7 +218,7 @@ public sealed class VirtualDiskSubContentProvider : IVirtualDiskSubContentProvid
|
|||||||
false,
|
false,
|
||||||
FormatAttributes(childElement.Attributes),
|
FormatAttributes(childElement.Attributes),
|
||||||
childElement.Length,
|
childElement.Length,
|
||||||
_virtualDiskContentProviderFactory.Create(parentContentProvider),
|
virtualDiskContentProviderFactory.Create(parentContentProvider),
|
||||||
pointInTime,
|
pointInTime,
|
||||||
new ObservableCollection<Exception>(),
|
new ObservableCollection<Exception>(),
|
||||||
new ReadOnlyExtensionCollection(new ExtensionCollection())
|
new ReadOnlyExtensionCollection(new ExtensionCollection())
|
||||||
|
|||||||
Reference in New Issue
Block a user