diff --git a/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs b/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs index 9d9106f..24d1c57 100644 --- a/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs +++ b/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs @@ -1,3 +1,5 @@ +using System.Reactive.Linq; +using System.Reactive.Subjects; using FileTime.Core.Enums; using FileTime.Core.Models; using FileTime.Core.Timeline; @@ -10,13 +12,14 @@ public class CopyCommand : CommandBase, ITransportationCommand private readonly ICommandSchedulerNotifier _commandSchedulerNotifier; private readonly List _operationProgresses = new(); + private readonly BehaviorSubject _currentOperationProgress = new(null); public IList Sources { get; } = new List(); public FullName? Target { get; set; } public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge; - public OperationProgress? CurrentOperationProgress { get; private set; } + public IObservable CurrentOperationProgress { get; } public CopyCommand( ITimelessContentProvider timelessContentProvider, @@ -25,6 +28,7 @@ public class CopyCommand : CommandBase, ITransportationCommand { _timelessContentProvider = timelessContentProvider; _commandSchedulerNotifier = commandSchedulerNotifier; + CurrentOperationProgress = _currentOperationProgress.AsObservable(); } public override Task CanRun(PointInTime currentTime) @@ -93,6 +97,17 @@ public class CopyCommand : CommandBase, ITransportationCommand _operationProgresses.Clear(); _operationProgresses.AddRange(calculateOperation.OperationStatuses); + + _operationProgresses + .Select(op => op.Progress.Select(p => (Progress: p, TotalProgress: op.TotalCount))) + .CombineLatest() + .Select(data => + { + var total = data.Sum(d => d.TotalProgress); + if (total == 0) return 0; + return (int) (data.Sum(d => d.Progress) * 100 / total); + }) + .Subscribe(SetTotalProgress); } private async Task TraverseTree( @@ -128,16 +143,15 @@ public class CopyCommand : CommandBase, ITransportationCommand var newElementPath = target.GetChild(newElementName, AbsolutePathType.Element); var currentProgress = _operationProgresses.Find(o => o.Key == element.FullName!.Path); - CurrentOperationProgress = currentProgress; + _currentOperationProgress.OnNext(currentProgress); await copyOperation.CopyAsync(new AbsolutePath(_timelessContentProvider, element), newElementPath, new CopyCommandContext(UpdateProgress, currentProgress)); } } } - private Task UpdateProgress() - { - //TODO - return Task.CompletedTask; - } + private Task UpdateProgress() => + //Not used, progress is reactive in this command + //Note: Maybe this should be removed altogether, and every command should use reactive progress + Task.CompletedTask; } \ No newline at end of file diff --git a/src/Core/FileTime.Core.CommandHandlers/StreamCopyCommandHandler.cs b/src/Core/FileTime.Core.CommandHandlers/StreamCopyCommandHandler.cs index 9fb04a5..1ae89d3 100644 --- a/src/Core/FileTime.Core.CommandHandlers/StreamCopyCommandHandler.cs +++ b/src/Core/FileTime.Core.CommandHandlers/StreamCopyCommandHandler.cs @@ -66,7 +66,7 @@ public class StreamCopyCommandHandler : ICommandHandler using var writer = await _contentAccessorFactory.GetContentWriterFactory(target.Provider).CreateContentWriterAsync(target); byte[] dataRead; - var currentProgress = 0L; + long currentProgress = 0; do {