diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Services/IClipboardService.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Services/IClipboardService.cs index 6430b05..df4f0e3 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Services/IClipboardService.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Services/IClipboardService.cs @@ -5,11 +5,11 @@ namespace FileTime.App.Core.Services; public interface IClipboardService { - Type? CommandType { get; } + Type? CommandFactoryType { get; } IReadOnlyList Content { get; } void AddContent(FullName absolutePath); void RemoveContent(FullName absolutePath); void Clear(); - void SetCommand() where T : ITransportationCommand; + void SetCommand() where T : ITransportationCommandFactory; } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Services/ClipboardService.cs b/src/AppCommon/FileTime.App.Core/Services/ClipboardService.cs index fa1d861..76af963 100644 --- a/src/AppCommon/FileTime.App.Core/Services/ClipboardService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/ClipboardService.cs @@ -7,7 +7,7 @@ public class ClipboardService : IClipboardService { private List _content; public IReadOnlyList Content { get; private set; } - public Type? CommandType { get; private set; } + public Type? CommandFactoryType { get; private set; } public ClipboardService() { @@ -40,11 +40,11 @@ public class ClipboardService : IClipboardService { _content = new List(); Content = _content.AsReadOnly(); - CommandType = null; + CommandFactoryType = null; } - public void SetCommand() where T : ITransportationCommand + public void SetCommand() where T : ITransportationCommandFactory { - CommandType = typeof(T); + CommandFactoryType = typeof(T); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs index ad96bd8..951727d 100644 --- a/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/UserCommandHandler/ItemManipulationUserCommandHandlerService.cs @@ -84,7 +84,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi private Task Copy() { _clipboardService.Clear(); - _clipboardService.SetCommand(); + _clipboardService.SetCommand(); if ((_markedItems?.Collection?.Count ?? 0) > 0) { @@ -120,23 +120,15 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi private async Task Paste(TransportMode mode) { - if (_clipboardService.CommandType is null) + if (_clipboardService.CommandFactoryType 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; + //TODO: check _currentLocation?.FullName + var commandFactory = (ITransportationCommandFactory) _serviceProvider.GetRequiredService(_clipboardService.CommandFactoryType); + var command = commandFactory.GenerateCommand(_clipboardService.Content, mode, _currentLocation?.FullName); _clipboardService.Clear(); diff --git a/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs b/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs index 9868890..893b6d5 100644 --- a/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs +++ b/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs @@ -49,6 +49,7 @@ public static class DependencyInjection private static IServiceCollection RegisterCommands(this IServiceCollection serviceCollection) { return serviceCollection + .AddCommands() .AddTransient() .AddTransient() .AddTransient() diff --git a/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs b/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs index 28e1e84..f7b8354 100644 --- a/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs +++ b/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs @@ -4,7 +4,7 @@ namespace FileTime.Core.Command; public interface ITransportationCommand : ICommand { - TransportMode? TransportMode { get; set; } - IList Sources { get; } - FullName? Target { get; set; } + TransportMode TransportMode { get; } + IReadOnlyList Sources { get; } + FullName Target { get; } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommandFactory.cs b/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommandFactory.cs new file mode 100644 index 0000000..751087a --- /dev/null +++ b/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommandFactory.cs @@ -0,0 +1,24 @@ +using FileTime.Core.Models; + +namespace FileTime.Core.Command; + +public interface ITransportationCommandFactory +{ + ITransportationCommand GenerateCommand( + IReadOnlyCollection sources, + TransportMode mode, + FullName targetFullName); +} + +public interface ITransportationCommandFactory : ITransportationCommandFactory where T : ITransportationCommand +{ + new T GenerateCommand(IReadOnlyCollection sources, + TransportMode mode, + FullName targetFullName); + + ITransportationCommand ITransportationCommandFactory.GenerateCommand( + IReadOnlyCollection sources, + TransportMode mode, + FullName targetFullName) + => GenerateCommand(sources, mode, targetFullName); +} \ 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 24d1c57..b298db4 100644 --- a/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs +++ b/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs @@ -14,21 +14,32 @@ public class CopyCommand : CommandBase, ITransportationCommand private readonly List _operationProgresses = new(); private readonly BehaviorSubject _currentOperationProgress = new(null); - public IList Sources { get; } = new List(); + public IReadOnlyList Sources { get; } - public FullName? Target { get; set; } + public FullName Target { get; } - public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge; + public TransportMode TransportMode { get; } public IObservable CurrentOperationProgress { get; } public CopyCommand( ITimelessContentProvider timelessContentProvider, - ICommandSchedulerNotifier commandSchedulerNotifier) - : base("Copy") + ICommandSchedulerNotifier commandSchedulerNotifier, + IReadOnlyCollection? sources, + TransportMode? mode, + FullName? targetFullName) + : base("Copy - Calculating...") { _timelessContentProvider = timelessContentProvider; _commandSchedulerNotifier = commandSchedulerNotifier; CurrentOperationProgress = _currentOperationProgress.AsObservable(); + + if (sources is null) throw new ArgumentException(nameof(Sources) + " can not be null"); + if (targetFullName is null) throw new ArgumentException(nameof(Target) + " can not be null"); + if (mode is null) throw new ArgumentException(nameof(TransportMode) + " can not be null"); + + Sources = new List(sources).AsReadOnly(); + TransportMode = mode.Value; + Target = targetFullName; } public override Task CanRun(PointInTime currentTime) @@ -39,10 +50,6 @@ public class CopyCommand : CommandBase, ITransportationCommand public override async Task SimulateCommand(PointInTime currentTime) { - if (Sources == null) throw new ArgumentException(nameof(Sources) + " can not be null"); - if (Target == null) throw new ArgumentException(nameof(Target) + " can not be null"); - if (TransportMode == null) throw new ArgumentException(nameof(TransportMode) + " can not be null"); - var simulateOperation = new SimulateStrategy(_timelessContentProvider); var resolvedTarget = await _timelessContentProvider.GetItemByFullNameAsync(Target, currentTime); @@ -50,7 +57,7 @@ public class CopyCommand : CommandBase, ITransportationCommand currentTime, Sources, new AbsolutePath(_timelessContentProvider, resolvedTarget), - TransportMode.Value, + TransportMode, simulateOperation); return currentTime.WithDifferences(simulateOperation.NewDiffs); @@ -58,10 +65,6 @@ public class CopyCommand : CommandBase, ITransportationCommand public async Task ExecuteAsync(CopyFunc copy) { - if (Sources == null) throw new ArgumentException(nameof(Sources) + " can not be null"); - if (Target == null) throw new ArgumentException(nameof(Target) + " can not be null"); - if (TransportMode == null) throw new ArgumentException(nameof(TransportMode) + " can not be null"); - var currentTime = PointInTime.Present; await CalculateProgressAsync(currentTime); @@ -74,17 +77,13 @@ public class CopyCommand : CommandBase, ITransportationCommand currentTime, Sources, new AbsolutePath(_timelessContentProvider, resolvedTarget), - TransportMode.Value, + TransportMode, copyOperation); //await TimeRunner.RefreshContainer.InvokeAsync(this, Target); } private async Task CalculateProgressAsync(PointInTime currentTime) { - if (Sources == null) throw new ArgumentException(nameof(Sources) + " can not be null"); - if (Target == null) throw new ArgumentException(nameof(Target) + " can not be null"); - if (TransportMode == null) throw new ArgumentException(nameof(TransportMode) + " can not be null"); - var calculateOperation = new CalculateStrategy(); var resolvedTarget = await _timelessContentProvider.GetItemByFullNameAsync(Target, currentTime); @@ -92,7 +91,7 @@ public class CopyCommand : CommandBase, ITransportationCommand currentTime, Sources, new AbsolutePath(_timelessContentProvider, resolvedTarget), - TransportMode.Value, + TransportMode, calculateOperation); _operationProgresses.Clear(); @@ -108,6 +107,24 @@ public class CopyCommand : CommandBase, ITransportationCommand return (int) (data.Sum(d => d.Progress) * 100 / total); }) .Subscribe(SetTotalProgress); + + + if (Sources.Count == 1) + { + SetDisplayLabel($"Copy - {Sources.First().GetName()}"); + } + else + { + _operationProgresses + .Select(o => o.IsDone) + .CombineLatest() + .Subscribe(statuses => + { + var done = statuses.Count(s => s) + 1; + + SetDisplayLabel($"Copy - {done} / {statuses.Count}"); + }); + } } private async Task TraverseTree( diff --git a/src/Core/FileTime.Core.Command/Copy/CopyCommandFactory.cs b/src/Core/FileTime.Core.Command/Copy/CopyCommandFactory.cs new file mode 100644 index 0000000..cd0bda8 --- /dev/null +++ b/src/Core/FileTime.Core.Command/Copy/CopyCommandFactory.cs @@ -0,0 +1,25 @@ +using FileTime.Core.Models; +using FileTime.Core.Timeline; + +namespace FileTime.Core.Command.Copy; + +public class CopyCommandFactory : ITransportationCommandFactory +{ + private readonly ITimelessContentProvider _timelessContentProvider; + private readonly ICommandSchedulerNotifier _commandSchedulerNotifier; + + public CopyCommandFactory( + ITimelessContentProvider timelessContentProvider, + ICommandSchedulerNotifier commandSchedulerNotifier) + + { + _timelessContentProvider = timelessContentProvider; + _commandSchedulerNotifier = commandSchedulerNotifier; + } + + public CopyCommand GenerateCommand( + IReadOnlyCollection sources, + TransportMode mode, + FullName targetFullName) + => new(_timelessContentProvider, _commandSchedulerNotifier, sources, mode, targetFullName); +} \ No newline at end of file diff --git a/src/Core/FileTime.Core.Command/Startup.cs b/src/Core/FileTime.Core.Command/Startup.cs new file mode 100644 index 0000000..96df758 --- /dev/null +++ b/src/Core/FileTime.Core.Command/Startup.cs @@ -0,0 +1,10 @@ +using FileTime.Core.Command.Copy; +using Microsoft.Extensions.DependencyInjection; + +namespace FileTime.Core.Command; + +public static class Startup +{ + public static IServiceCollection AddCommands(this IServiceCollection serviceCollection) + => serviceCollection.AddSingleton(); +} \ No newline at end of file