Use IDeclarativeProperty instead of IObservable
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
using DeclarativeProperty;
|
||||
using FileTime.Core.Timeline;
|
||||
|
||||
namespace FileTime.Core.Command;
|
||||
|
||||
public interface ICommand
|
||||
{
|
||||
IObservable<string> DisplayLabel { get; }
|
||||
IObservable<string> DisplayDetailLabel { get; }
|
||||
IObservable<int> TotalProgress { get; }
|
||||
IObservable<int> CurrentProgress { get; }
|
||||
IDeclarativeProperty<string> DisplayLabel { get; }
|
||||
IDeclarativeProperty<string> DisplayDetailLabel { get; }
|
||||
IDeclarativeProperty<int> TotalProgress { get; }
|
||||
IDeclarativeProperty<int> CurrentProgress { get; }
|
||||
|
||||
Task<CanCommandRun> CanRun(PointInTime currentTime);
|
||||
Task<PointInTime> SimulateCommand(PointInTime currentTime);
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using DeclarativeProperty;
|
||||
using FileTime.Core.Timeline;
|
||||
|
||||
namespace FileTime.Core.Command;
|
||||
|
||||
public abstract class CommandBase : ICommand
|
||||
{
|
||||
private readonly BehaviorSubject<string> _displayLabel;
|
||||
private readonly BehaviorSubject<string> _displayDetailLabel;
|
||||
private readonly BehaviorSubject<int> _totalProgress;
|
||||
private readonly BehaviorSubject<int> _currentProgress;
|
||||
private readonly DeclarativeProperty<string> _displayLabel;
|
||||
private readonly DeclarativeProperty<string> _displayDetailLabel;
|
||||
private readonly DeclarativeProperty<int> _totalProgress;
|
||||
private readonly DeclarativeProperty<int> _currentProgress;
|
||||
|
||||
public IObservable<string> DisplayLabel { get; }
|
||||
public IObservable<string> DisplayDetailLabel { get; }
|
||||
public IObservable<int> TotalProgress { get; }
|
||||
public IObservable<int> CurrentProgress { get; }
|
||||
public IDeclarativeProperty<string> DisplayLabel { get; }
|
||||
public IDeclarativeProperty<string> DisplayDetailLabel { get; }
|
||||
public IDeclarativeProperty<int> TotalProgress { get; }
|
||||
public IDeclarativeProperty<int> CurrentProgress { get; }
|
||||
|
||||
protected CommandBase(string displayLabel = "", string displayDetailLabel = "", int totalProgress = 0, int currentProgress = 0)
|
||||
{
|
||||
@@ -23,32 +24,32 @@ public abstract class CommandBase : ICommand
|
||||
_totalProgress = new(totalProgress);
|
||||
_currentProgress = new(currentProgress);
|
||||
|
||||
DisplayLabel = _displayLabel.AsObservable();
|
||||
DisplayDetailLabel = _displayDetailLabel.AsObservable();
|
||||
TotalProgress = _totalProgress.AsObservable();
|
||||
CurrentProgress = _currentProgress.AsObservable();
|
||||
DisplayLabel = _displayLabel;
|
||||
DisplayDetailLabel = _displayDetailLabel;
|
||||
TotalProgress = _totalProgress;
|
||||
CurrentProgress = _currentProgress;
|
||||
}
|
||||
|
||||
public abstract Task<CanCommandRun> CanRun(PointInTime currentTime);
|
||||
public abstract Task<PointInTime> SimulateCommand(PointInTime currentTime);
|
||||
public abstract void Cancel();
|
||||
|
||||
protected void SetDisplayLabel(string? displayLabel) => _displayLabel.OnNext(displayLabel ?? string.Empty);
|
||||
protected void SetDisplayDetailLabel(string? displayLabel) => _displayDetailLabel.OnNext(displayLabel ?? string.Empty);
|
||||
protected async Task SetDisplayLabelAsync(string? displayLabel) => await _displayLabel.SetValue(displayLabel ?? string.Empty);
|
||||
protected async Task SetDisplayDetailLabel(string? displayLabel) => await _displayDetailLabel.SetValue(displayLabel ?? string.Empty);
|
||||
|
||||
protected void SetTotalProgress(int totalProgress) => _totalProgress.OnNext(totalProgress);
|
||||
protected async Task SetTotalProgress(int totalProgress) => await _totalProgress.SetValue(totalProgress);
|
||||
|
||||
protected void SetCurrentProgress(int currentProgress) => _currentProgress.OnNext(currentProgress);
|
||||
protected async Task SetCurrentProgress(int currentProgress) => await _currentProgress.SetValue(currentProgress);
|
||||
|
||||
protected IDisposable TrackProgress(IEnumerable<OperationProgress> operationProgresses) =>
|
||||
operationProgresses
|
||||
.Select(op => op.Progress.Select(p => (Progress: p, TotalProgress: op.TotalCount)))
|
||||
.CombineLatest()
|
||||
.Select(data =>
|
||||
.Select(op => op.Progress.Map(p => (Progress: p, TotalProgress: op.TotalCount)))
|
||||
.CombineAll(data =>
|
||||
{
|
||||
var total = data.Sum(d => d.TotalProgress);
|
||||
if (total == 0) return 0;
|
||||
return (int) (data.Sum(d => d.Progress) * 100 / total);
|
||||
var dataList = data.ToList();
|
||||
var total = dataList.Sum(d => d.TotalProgress);
|
||||
if (total == 0) return Task.FromResult(0);
|
||||
return Task.FromResult((int)(dataList.Sum(d => d.Progress) * 100 / total));
|
||||
})
|
||||
.Subscribe(SetTotalProgress);
|
||||
.Subscribe(async (p, _) => await SetTotalProgress(p));
|
||||
}
|
||||
@@ -17,7 +17,7 @@ public class CopyCommand : CommandBase, ITransportationCommand
|
||||
private readonly CancellationTokenSource _cancellationTokenSource = new();
|
||||
|
||||
private readonly List<OperationProgress> _operationProgresses = new();
|
||||
private readonly BehaviorSubject<OperationProgress?> _currentOperationProgress = new(null);
|
||||
private readonly DeclarativeProperty<OperationProgress?> _currentOperationProgress = new();
|
||||
|
||||
private long _recentTotalSum;
|
||||
private readonly DeclarativeProperty<long> _recentTotalProcessed = new();
|
||||
@@ -41,22 +41,21 @@ public class CopyCommand : CommandBase, ITransportationCommand
|
||||
ArgumentNullException.ThrowIfNull(sources);
|
||||
ArgumentNullException.ThrowIfNull(mode);
|
||||
ArgumentNullException.ThrowIfNull(targetFullName);
|
||||
|
||||
|
||||
_timelessContentProvider = timelessContentProvider;
|
||||
_commandSchedulerNotifier = commandSchedulerNotifier;
|
||||
_logger = logger;
|
||||
_currentOperationProgress
|
||||
.Select(p =>
|
||||
.Map(p =>
|
||||
{
|
||||
if (p is null) return Observable.Never<int>();
|
||||
return p.Progress.Select(currentProgress =>
|
||||
return p?.Progress.Map(currentProgress =>
|
||||
p.TotalCount == 0
|
||||
? 0
|
||||
: (int) (currentProgress * 100 / p.TotalCount)
|
||||
);
|
||||
})
|
||||
.Switch()
|
||||
.Subscribe(SetCurrentProgress);
|
||||
.Subscribe(async (p, _) => await SetCurrentProgress(p));
|
||||
|
||||
Sources = new List<FullName>(sources).AsReadOnly();
|
||||
TransportMode = mode;
|
||||
@@ -75,7 +74,7 @@ public class CopyCommand : CommandBase, ITransportationCommand
|
||||
|
||||
recentSpeed
|
||||
.Debounce(TimeSpan.FromMilliseconds(500))
|
||||
.Subscribe(SetDisplayDetailLabel);
|
||||
.Subscribe(async (l, _) => await SetDisplayDetailLabel(l));
|
||||
}
|
||||
|
||||
public override Task<CanCommandRun> CanRun(PointInTime currentTime)
|
||||
@@ -145,20 +144,21 @@ public class CopyCommand : CommandBase, ITransportationCommand
|
||||
|
||||
if (Sources.Count == 1)
|
||||
{
|
||||
SetDisplayLabel($"Copy - {Sources[0].GetName()}");
|
||||
await SetDisplayLabelAsync($"Copy - {Sources[0].GetName()}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_operationProgresses
|
||||
.Select(o => o.IsDone)
|
||||
.CombineLatest()
|
||||
.Subscribe(statuses =>
|
||||
.CombineAll(statuses =>
|
||||
{
|
||||
var done = statuses.Count(s => s) + 1;
|
||||
if (done > statuses.Count) done = statuses.Count;
|
||||
var statusList = statuses.ToList();
|
||||
var done = statusList.Count(s => s) + 1;
|
||||
if (done > statusList.Count) done = statusList.Count;
|
||||
|
||||
SetDisplayLabel($"Copy - {done} / {statuses.Count}");
|
||||
});
|
||||
return Task.FromResult($"Copy - {done} / {statusList.Count}");
|
||||
})
|
||||
.Subscribe(async (v, _) => await SetDisplayLabelAsync(v));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ public class CopyCommand : CommandBase, ITransportationCommand
|
||||
var newElementPath = target.GetChild(newElementName, AbsolutePathType.Element);
|
||||
|
||||
var currentProgress = _operationProgresses.Find(o => o.Key == element.FullName!.Path);
|
||||
_currentOperationProgress.OnNext(currentProgress);
|
||||
await _currentOperationProgress.SetValue(currentProgress);
|
||||
|
||||
await copyOperation.CopyAsync(new AbsolutePath(_timelessContentProvider, element), newElementPath, new CopyCommandContext(UpdateProgress, currentProgress, _cancellationTokenSource.Token));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user