From 94e71954ee9eb66e8739a6fdfe27b4db8b299383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Thu, 9 Jun 2022 08:27:51 +0200 Subject: [PATCH] Copy --- ...emManipulationUserCommandHandlerService.cs | 48 ++++++++++++++----- .../NavigationUserCommandHandlerService.cs | 8 ++-- .../ViewModels/AppStateBase.cs | 1 - .../ViewModels/FileViewModel.cs | 2 +- .../ViewModels/TabViewModel.cs | 3 +- .../DependencyInjection.cs | 8 +++- .../Command/IRequireInputCommand.cs | 6 +++ .../Command/ITransportationCommand.cs | 6 ++- .../Command}/TransportMode.cs | 0 ...erface.cs => IUserCommunicationService.cs} | 3 +- .../Timeline/ICommandScheduler.cs | 3 ++ .../Timeline/ICommandSchedulerNotifier.cs | 8 ++++ .../FileTime.Core.Command/Copy/CopyCommand.cs | 16 ++++--- ...eContainerCommand.cs => CreateItemBase.cs} | 0 src/Core/FileTime.Core.Command/Helper.cs | 6 +-- .../CommandScheduler.cs | 16 +++++-- .../LocalCommandSchedulerNotifier.cs | 18 +++++++ .../Services/IDialogService.cs | 3 +- .../Avalonia/FileTime.GuiApp.App/Startup.cs | 2 +- .../LocalContentProvider.cs | 28 ++++++----- .../LocalContentWriterFactory.cs | 2 +- 21 files changed, 135 insertions(+), 52 deletions(-) create mode 100644 src/Core/FileTime.Core.Abstraction/Command/IRequireInputCommand.cs rename src/Core/{FileTime.Core.Command => FileTime.Core.Abstraction/Command}/TransportMode.cs (100%) rename src/Core/FileTime.Core.Abstraction/Interactions/{IInputInterface.cs => IUserCommunicationService.cs} (54%) create mode 100644 src/Core/FileTime.Core.Abstraction/Timeline/ICommandSchedulerNotifier.cs rename src/Core/FileTime.Core.Command/Create/{CreateContainerCommand.cs => CreateItemBase.cs} (100%) create mode 100644 src/Core/FileTime.Core.Timeline/LocalCommandSchedulerNotifier.cs diff --git a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs index 0509008..42f0e6b 100644 --- a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs @@ -10,8 +10,8 @@ using FileTime.Core.Interactions; using FileTime.Core.Models; using FileTime.Core.Timeline; using InitableService; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using CopyCommand = FileTime.Core.Command.Copy.CopyCommand; namespace FileTime.App.Core.Services.UserCommandHandler; @@ -21,7 +21,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi private IItemViewModel? _currentSelectedItem; private readonly IUserCommandHandlerService _userCommandHandlerService; private readonly IClipboardService _clipboardService; - private readonly IInputInterface _inputInterface; + private readonly IUserCommunicationService _userCommunicationService; private readonly ILogger _logger; private readonly ICommandScheduler _commandScheduler; private readonly IServiceProvider _serviceProvider; @@ -32,7 +32,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi IAppState appState, IUserCommandHandlerService userCommandHandlerService, IClipboardService clipboardService, - IInputInterface inputInterface, + IUserCommunicationService userCommunicationService, ILogger logger, ITimelessContentProvider timelessContentProvider, ICommandScheduler commandScheduler, @@ -40,7 +40,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi { _userCommandHandlerService = userCommandHandlerService; _clipboardService = clipboardService; - _inputInterface = inputInterface; + _userCommunicationService = userCommunicationService; _logger = logger; _commandScheduler = commandScheduler; _serviceProvider = serviceProvider; @@ -72,7 +72,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi private Task Copy() { _clipboardService.Clear(); - _clipboardService.SetCommand(); + _clipboardService.SetCommand(); if ((_markedItems?.Collection?.Count ?? 0) > 0) { @@ -120,17 +120,38 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi await Paste(TransportMode.Skip); } - private Task Paste(TransportMode skip) + private async Task Paste(TransportMode mode) { - if (_clipboardService.CommandType is null) return Task.CompletedTask; - return Task.CompletedTask; + if (_clipboardService.CommandType is null) + { + _userCommunicationService.ShowToastMessage("Clipboard is empty."); + return; + } + + var command = (ITransportationCommand) _serviceProvider.GetRequiredService(_clipboardService.CommandType); + command.TransportMode = mode; + + command.Sources.Clear(); + + foreach (var item in _clipboardService.Content) + { + command.Sources.Add(item); + } + + command.Target = _currentLocation?.FullName; + + _clipboardService.Clear(); + + if (command is IRequireInputCommand requireInput) await requireInput.ReadInputs(); + + await AddCommand(command); } private async Task CreateContainer() { var containerNameInput = new TextInputElement("Container name"); - await _inputInterface.ReadInputs(containerNameInput); + await _userCommunicationService.ReadInputs(containerNameInput); //TODO: message on empty result var newContainerName = containerNameInput.Value; @@ -140,14 +161,14 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi var command = _serviceProvider .GetInitableResolver(_currentLocation.FullName, newContainerName) .GetRequiredService(); - await _commandScheduler.AddCommand(command); + await AddCommand(command); } private async Task CreateElement() { var containerNameInput = new TextInputElement("Element name"); - await _inputInterface.ReadInputs(containerNameInput); + await _userCommunicationService.ReadInputs(containerNameInput); //TODO: message on empty result var newContainerName = containerNameInput.Value; @@ -157,6 +178,11 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi var command = _serviceProvider .GetInitableResolver(_currentLocation.FullName, newContainerName) .GetRequiredService(); + await AddCommand(command); + } + + private async Task AddCommand(ICommand command) + { await _commandScheduler.AddCommand(command); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/NavigationUserCommandHandlerService.cs b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/NavigationUserCommandHandlerService.cs index 95b228c..703bab7 100644 --- a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/NavigationUserCommandHandlerService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/NavigationUserCommandHandlerService.cs @@ -19,7 +19,7 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase private readonly ILocalContentProvider _localContentProvider; private readonly IUserCommandHandlerService _userCommandHandlerService; private readonly ITimelessContentProvider _timelessContentProvider; - private readonly IInputInterface _inputInterface; + private readonly IUserCommunicationService _userCommunicationService; private ITabViewModel? _selectedTab; private IContainer? _currentLocation; private IItemViewModel? _currentSelectedItem; @@ -32,14 +32,14 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase ILocalContentProvider localContentProvider, IUserCommandHandlerService userCommandHandlerService, ITimelessContentProvider timelessContentProvider, - IInputInterface inputInterface) : base(appState) + IUserCommunicationService userCommunicationService) : base(appState) { _appState = appState; _serviceProvider = serviceProvider; _localContentProvider = localContentProvider; _userCommandHandlerService = userCommandHandlerService; _timelessContentProvider = timelessContentProvider; - _inputInterface = inputInterface; + _userCommunicationService = userCommunicationService; SaveSelectedTab(t => _selectedTab = t); SaveCurrentSelectedItem(i => _currentSelectedItem = i); @@ -74,7 +74,7 @@ public class NavigationUserCommandHandlerService : UserCommandHandlerServiceBase private async Task GoToPath() { var pathInput = new TextInputElement("Path"); - await _inputInterface.ReadInputs(pathInput); + await _userCommunicationService.ReadInputs(pathInput); //TODO: message on empty result and on null pathInput.Value var resolvedPath = await _timelessContentProvider.GetItemByNativePathAsync(new NativePath(pathInput.Value)); diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/AppStateBase.cs b/src/AppCommon/FileTime.App.Core/ViewModels/AppStateBase.cs index 4873eb9..9e815a6 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/AppStateBase.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/AppStateBase.cs @@ -3,7 +3,6 @@ using System.Reactive.Linq; using System.Reactive.Subjects; using DynamicData; using FileTime.App.Core.Models.Enums; -using FileTime.Core.Timeline; using MvvmGen; using MoreLinq; diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/FileViewModel.cs b/src/AppCommon/FileTime.App.Core/ViewModels/FileViewModel.cs index ffec3c6..172c029 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/FileViewModel.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/FileViewModel.cs @@ -1,7 +1,7 @@ -using FileTime.App.Core.Models; using FileTime.App.Core.Models.Enums; using FileTime.App.Core.Services; using FileTime.Core.Models; +using FileTime.Core.Models.Extensions; using MvvmGen; namespace FileTime.App.Core.ViewModels; diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs b/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs index 6ec7ee6..afcf52d 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs @@ -4,11 +4,10 @@ using FileTime.App.Core.Extensions; using FileTime.App.Core.Models; using FileTime.App.Core.Models.Enums; using FileTime.App.Core.Services; -using FileTime.App.Core.ViewModels.ItemPreview; using FileTime.Core.Models; +using FileTime.Core.Models.Extensions; using FileTime.Core.Services; using InitableService; -using Microsoft.Extensions.DependencyInjection; using MvvmGen; namespace FileTime.App.Core.ViewModels; diff --git a/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs b/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs index 0ba7f6b..11712e8 100644 --- a/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs +++ b/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs @@ -3,6 +3,7 @@ using FileTime.App.Core.Models; using FileTime.App.Core.Services; using FileTime.App.Core.Services.Persistence; using FileTime.Core.Command; +using FileTime.Core.Command.Copy; using FileTime.Core.Command.CreateContainer; using FileTime.Core.Command.CreateElement; using FileTime.Core.CommandHandlers; @@ -25,7 +26,11 @@ public static class DependencyInjection serviceCollection.TryAddSingleton(); serviceCollection.TryAddSingleton(); serviceCollection.TryAddSingleton(); + serviceCollection.TryAddSingleton(); + //TODO: check local/remote context serviceCollection.TryAddSingleton(); + serviceCollection.TryAddSingleton(); + serviceCollection.TryAddSingleton(); serviceCollection.TryAddSingleton(); serviceCollection.TryAddTransient(); @@ -43,6 +48,7 @@ public static class DependencyInjection { return serviceCollection .AddTransient() - .AddTransient(); + .AddTransient() + .AddTransient(); } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Command/IRequireInputCommand.cs b/src/Core/FileTime.Core.Abstraction/Command/IRequireInputCommand.cs new file mode 100644 index 0000000..b5b7787 --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Command/IRequireInputCommand.cs @@ -0,0 +1,6 @@ +namespace FileTime.Core.Command; + +public interface IRequireInputCommand +{ + Task ReadInputs(); +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs b/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs index ac66aee..28e1e84 100644 --- a/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs +++ b/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs @@ -1,6 +1,10 @@ +using FileTime.Core.Models; + namespace FileTime.Core.Command; public interface ITransportationCommand : ICommand { - + TransportMode? TransportMode { get; set; } + IList Sources { get; } + FullName? Target { get; set; } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Command/TransportMode.cs b/src/Core/FileTime.Core.Abstraction/Command/TransportMode.cs similarity index 100% rename from src/Core/FileTime.Core.Command/TransportMode.cs rename to src/Core/FileTime.Core.Abstraction/Command/TransportMode.cs diff --git a/src/Core/FileTime.Core.Abstraction/Interactions/IInputInterface.cs b/src/Core/FileTime.Core.Abstraction/Interactions/IUserCommunicationService.cs similarity index 54% rename from src/Core/FileTime.Core.Abstraction/Interactions/IInputInterface.cs rename to src/Core/FileTime.Core.Abstraction/Interactions/IUserCommunicationService.cs index aa2143c..e59f6f7 100644 --- a/src/Core/FileTime.Core.Abstraction/Interactions/IInputInterface.cs +++ b/src/Core/FileTime.Core.Abstraction/Interactions/IUserCommunicationService.cs @@ -1,6 +1,7 @@ namespace FileTime.Core.Interactions; -public interface IInputInterface +public interface IUserCommunicationService { Task ReadInputs(params IInputElement[] fields); + void ShowToastMessage(string text); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Timeline/ICommandScheduler.cs b/src/Core/FileTime.Core.Abstraction/Timeline/ICommandScheduler.cs index c62703a..e9d6ad6 100644 --- a/src/Core/FileTime.Core.Abstraction/Timeline/ICommandScheduler.cs +++ b/src/Core/FileTime.Core.Abstraction/Timeline/ICommandScheduler.cs @@ -1,8 +1,11 @@ using FileTime.Core.Command; +using FileTime.Core.Models; namespace FileTime.Core.Timeline; public interface ICommandScheduler { Task AddCommand(ICommand command, int? batchId = null, bool toNewBatch = false); + IObservable ContainerToRefresh { get; } + void RefreshContainer(FullName container); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Timeline/ICommandSchedulerNotifier.cs b/src/Core/FileTime.Core.Abstraction/Timeline/ICommandSchedulerNotifier.cs new file mode 100644 index 0000000..92480d3 --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Timeline/ICommandSchedulerNotifier.cs @@ -0,0 +1,8 @@ +using FileTime.Core.Models; + +namespace FileTime.Core.Timeline; + +public interface ICommandSchedulerNotifier +{ + Task RefreshContainer(FullName container); +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs b/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs index babb811..a6d6683 100644 --- a/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs +++ b/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs @@ -8,6 +8,7 @@ namespace FileTime.Core.Command.Copy; public class CopyCommand : ITransportationCommand { private readonly ITimelessContentProvider _timelessContentProvider; + private readonly ICommandSchedulerNotifier _commandSchedulerNotifier; private readonly List _operationProgresses = new(); @@ -18,9 +19,12 @@ public class CopyCommand : ITransportationCommand public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge; public OperationProgress? CurrentOperationProgress { get; private set; } - public CopyCommand(ITimelessContentProvider timelessContentProvider) + public CopyCommand( + ITimelessContentProvider timelessContentProvider, + ICommandSchedulerNotifier commandSchedulerNotifier) { _timelessContentProvider = timelessContentProvider; + _commandSchedulerNotifier = commandSchedulerNotifier; } public Task CanRun(PointInTime currentTime) @@ -58,7 +62,7 @@ public class CopyCommand : ITransportationCommand await CalculateProgressAsync(currentTime); - var copyOperation = new CopyStrategy(copy, new CopyStrategyParam(_operationProgresses)); + var copyOperation = new CopyStrategy(copy, new CopyStrategyParam(_operationProgresses, _commandSchedulerNotifier.RefreshContainer)); var resolvedTarget = await _timelessContentProvider.GetItemByFullNameAsync(Target, currentTime); @@ -92,17 +96,17 @@ public class CopyCommand : ITransportationCommand } private async Task TraverseTree( - PointInTime curretnTime, + PointInTime currentTime, IEnumerable sources, AbsolutePath target, TransportMode transportMode, ICopyStrategy copyOperation) { - var resolvedTarget = ((IContainer)await target.ResolveAsync()) ?? throw new Exception(); + var resolvedTarget = ((IContainer) await target.ResolveAsync()) ?? throw new Exception(); foreach (var source in sources) { - var item = await _timelessContentProvider.GetItemByFullNameAsync(source, curretnTime); + var item = await _timelessContentProvider.GetItemByFullNameAsync(source, currentTime); if (item is IContainer container) { @@ -114,7 +118,7 @@ public class CopyCommand : ITransportationCommand var children = await container.Items.GetItemsAsync(); if (children is null) continue; - await TraverseTree(curretnTime, children.Select(c => c.Path).ToList(), target.GetChild(item.Name, AbsolutePathType.Container), transportMode, copyOperation); + await TraverseTree(currentTime, children.Select(c => c.Path).ToList(), target.GetChild(item.Name, AbsolutePathType.Container), transportMode, copyOperation); await copyOperation.ContainerCopyDoneAsync(new AbsolutePath(_timelessContentProvider, container)); } else if (item is IElement element) diff --git a/src/Core/FileTime.Core.Command/Create/CreateContainerCommand.cs b/src/Core/FileTime.Core.Command/Create/CreateItemBase.cs similarity index 100% rename from src/Core/FileTime.Core.Command/Create/CreateContainerCommand.cs rename to src/Core/FileTime.Core.Command/Create/CreateItemBase.cs diff --git a/src/Core/FileTime.Core.Command/Helper.cs b/src/Core/FileTime.Core.Command/Helper.cs index 99bdb2f..158f127 100644 --- a/src/Core/FileTime.Core.Command/Helper.cs +++ b/src/Core/FileTime.Core.Command/Helper.cs @@ -7,10 +7,10 @@ public static class Helper { public static async Task GetNewNameAsync(IContainer resolvedTarget, string name, TransportMode transportMode) { - var items = await resolvedTarget.Items.GetItemsAsync() ?? throw new NullReferenceException(); + var items = (await resolvedTarget.Items.GetItemsAsync() ?? throw new NullReferenceException()).ToList(); var newName = name; - var targetNameExists = resolvedTarget != null && items.Any(i => i.Path.GetName() == newName); - if (transportMode == TransportMode.Merge && resolvedTarget != null) + var targetNameExists = items.Any(i => i.Path.GetName() == newName); + if (transportMode == TransportMode.Merge) { for (var i = 0; targetNameExists; i++) { diff --git a/src/Core/FileTime.Core.Timeline/CommandScheduler.cs b/src/Core/FileTime.Core.Timeline/CommandScheduler.cs index 1d0e6b7..c21f5ff 100644 --- a/src/Core/FileTime.Core.Timeline/CommandScheduler.cs +++ b/src/Core/FileTime.Core.Timeline/CommandScheduler.cs @@ -1,19 +1,23 @@ +using System.Reactive.Linq; +using System.Reactive.Subjects; using DynamicData; using FileTime.Core.Command; -using Microsoft.Extensions.DependencyInjection; +using FileTime.Core.Models; namespace FileTime.Core.Timeline; public class CommandScheduler : ICommandScheduler { - private readonly IServiceProvider _serviceProvider; private readonly SourceList _commandsToRun = new(); private readonly List _commandExecutors = new(); + private readonly Subject _containerToRefresh = new(); private readonly object _guard = new(); private bool _enableRunning = true; private bool _resourceIsInUse; + public IObservable ContainerToRefresh { get; } + public bool EnableRunning { get @@ -26,10 +30,10 @@ public class CommandScheduler : ICommandScheduler set { RunWithLock(() => _enableRunning = value); } } - public CommandScheduler(IServiceProvider serviceProvider) + public CommandScheduler(ILocalCommandExecutor localExecutor) { - _serviceProvider = serviceProvider; - var localExecutor = serviceProvider.GetRequiredService(); + ContainerToRefresh = _containerToRefresh.AsObservable(); + localExecutor.CommandFinished += LocalExecutorOnCommandFinished; _commandExecutors.Add(localExecutor); } @@ -74,6 +78,8 @@ public class CommandScheduler : ICommandScheduler }); } + public void RefreshContainer(FullName container) => _containerToRefresh.OnNext(container); + private void ExecuteCommands() { if (!_enableRunning) return; diff --git a/src/Core/FileTime.Core.Timeline/LocalCommandSchedulerNotifier.cs b/src/Core/FileTime.Core.Timeline/LocalCommandSchedulerNotifier.cs new file mode 100644 index 0000000..6dd70b4 --- /dev/null +++ b/src/Core/FileTime.Core.Timeline/LocalCommandSchedulerNotifier.cs @@ -0,0 +1,18 @@ +using FileTime.Core.Models; + +namespace FileTime.Core.Timeline; + +public class LocalCommandSchedulerNotifier : ICommandSchedulerNotifier +{ + private readonly ICommandScheduler _commandRunner; + + public LocalCommandSchedulerNotifier(ICommandScheduler commandRunner) + { + _commandRunner = commandRunner; + } + public Task RefreshContainer(FullName container) + { + _commandRunner.RefreshContainer(container); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs index bfae052..1966da5 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDialogService.cs @@ -3,9 +3,8 @@ using FileTime.GuiApp.ViewModels; namespace FileTime.GuiApp.Services; -public interface IDialogService : IInputInterface +public interface IDialogService : IUserCommunicationService { IObservable ReadInput { get; } void ReadInputs(IEnumerable inputs, Action inputHandler, Action? cancelHandler = null); - void ShowToastMessage(string text); } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs index b3811bb..be486ef 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs @@ -42,7 +42,7 @@ public static class Startup serviceCollection.TryAddSingleton(); serviceCollection.TryAddSingleton(); serviceCollection.TryAddSingleton(); - serviceCollection.TryAddSingleton(s => s.GetRequiredService()); + serviceCollection.TryAddSingleton(s => s.GetRequiredService()); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { diff --git a/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs b/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs index bc2051c..74e7359 100644 --- a/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs +++ b/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs @@ -9,6 +9,7 @@ using FileTime.Core.Models.Extensions; using FileTime.Core.Timeline; namespace FileTime.Providers.Local; + public sealed partial class LocalContentProvider : ContentProviderBase, ILocalContentProvider { private readonly ITimelessContentProvider _timelessContentProvider; @@ -58,7 +59,7 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture ) - ); + ); return rootDrive is not null; } @@ -75,11 +76,11 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo { if ((path?.Length ?? 0) == 0) { - return Task.FromResult((IItem)this); + return Task.FromResult((IItem) this); } else if (Directory.Exists(path)) { - return Task.FromResult((IItem)DirectoryToContainer( + return Task.FromResult((IItem) DirectoryToContainer( new DirectoryInfo(path!.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar), pointInTime, !itemInitializationSettings.SkipChildInitialization) @@ -87,7 +88,7 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo } else if (File.Exists(path)) { - return Task.FromResult((IItem)FileToElement(new FileInfo(path), pointInTime)); + return Task.FromResult((IItem) FileToElement(new FileInfo(path), pointInTime)); } var type = forceResolvePathType switch @@ -119,10 +120,10 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo return forceResolvePathType switch { AbsolutePathType.Container => Task.FromResult( - (IItem)CreateEmptyContainer( + (IItem) CreateEmptyContainer( nativePath, pointInTime, - Observable.Return(new List() { innerException }) + Observable.Return(new List() {innerException}) ) ), AbsolutePathType.Element => Task.FromResult(CreateEmptyElement(nativePath)), @@ -234,22 +235,25 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo Task>?> InitChildren() { - SourceCache? result = null; try { - var items = initializeChildren ? (List?)GetItemsByContainer(directoryInfo, pointInTime) : null; + var items = initializeChildren ? (List?) GetItemsByContainer(directoryInfo, pointInTime) : null; if (items != null) { - result = new SourceCache(i => i.Path.Path); + var result = new SourceCache(i => i.Path.Path); + + if (items.Count == 0) return Task.FromResult((IObservable>?) result.Connect().StartWithEmpty()); + result.AddOrUpdate(items); + return Task.FromResult((IObservable>?) result.Connect()); } } catch (Exception e) { - exceptions.OnNext(new List() { e }); + exceptions.OnNext(new List() {e}); } - return Task.FromResult(result?.Connect()); + return Task.FromResult((IObservable>?) null); } } @@ -320,7 +324,7 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo var size = maxLength ?? realFileSize switch { > int.MaxValue => int.MaxValue, - _ => (int)realFileSize + _ => (int) realFileSize }; var buffer = new byte[size]; await reader.ReadAsync(buffer.AsMemory(0, size), cancellationToken); diff --git a/src/Providers/FileTime.Providers.Local/LocalContentWriterFactory.cs b/src/Providers/FileTime.Providers.Local/LocalContentWriterFactory.cs index 71d190b..dfcc715 100644 --- a/src/Providers/FileTime.Providers.Local/LocalContentWriterFactory.cs +++ b/src/Providers/FileTime.Providers.Local/LocalContentWriterFactory.cs @@ -6,5 +6,5 @@ namespace FileTime.Providers.Local; public class LocalContentWriterFactory : IContentWriterFactory { public Task CreateContentWriterAsync(IElement element) - => Task.FromResult((IContentWriter)new LocalContentWriter(File.OpenRead(element.NativePath!.Path))); + => Task.FromResult((IContentWriter)new LocalContentWriter(File.OpenWrite(element.NativePath!.Path))); } \ No newline at end of file