Command status
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using AsyncEvent;
|
||||
using FileTime.Core.Models;
|
||||
using FileTime.Core.Timeline;
|
||||
|
||||
@@ -5,9 +6,10 @@ namespace FileTime.Core.Command
|
||||
{
|
||||
public class CopyCommand : ITransportationCommand
|
||||
{
|
||||
private Action<AbsolutePath, AbsolutePath>? _copyOperation;
|
||||
private Func<AbsolutePath, AbsolutePath, Task>? _copyOperation;
|
||||
private Dictionary<AbsolutePath, OperationProgress> _operationStatuses = new();
|
||||
private Func<IContainer, string, Task<IContainer>>? _createContainer;
|
||||
private TimeRunner? _timeRunner;
|
||||
private Func<AbsolutePath, Task>? _containerCopyDone;
|
||||
|
||||
public IList<AbsolutePath> Sources { get; } = new List<AbsolutePath>();
|
||||
|
||||
@@ -15,6 +17,27 @@ namespace FileTime.Core.Command
|
||||
|
||||
public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge;
|
||||
|
||||
public int Progress { get; private set; }
|
||||
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
|
||||
public string DisplayLabel { get; } = "Copy";
|
||||
|
||||
private async Task UpdateProgress()
|
||||
{
|
||||
var total = 0;
|
||||
var current = 0;
|
||||
|
||||
foreach (var item in _operationStatuses.Values)
|
||||
{
|
||||
current += item.Progress;
|
||||
total += item.TotalCount;
|
||||
}
|
||||
|
||||
Progress = current * 100 / total;
|
||||
await ProgressChanged.InvokeAsync(this, AsyncEventArgs.Empty);
|
||||
}
|
||||
|
||||
public async Task<PointInTime> SimulateCommand(PointInTime startPoint)
|
||||
{
|
||||
if (Sources == null) throw new ArgumentException(nameof(Sources) + " can not be null");
|
||||
@@ -33,6 +56,8 @@ namespace FileTime.Core.Command
|
||||
DifferenceActionType.Create,
|
||||
to
|
||||
));
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
_createContainer = async (IContainer target, string name) =>
|
||||
@@ -59,13 +84,62 @@ namespace FileTime.Core.Command
|
||||
if (Target == null) throw new ArgumentException(nameof(Target) + " can not be null");
|
||||
if (TransportMode == null) throw new ArgumentException(nameof(TransportMode) + " can not be null");
|
||||
|
||||
_copyOperation = copy;
|
||||
await CalculateProgress();
|
||||
|
||||
_copyOperation = async (from, to) =>
|
||||
{
|
||||
copy(from, to);
|
||||
var parentPath = to.GetParentAsAbsolutePath();
|
||||
if (_operationStatuses.ContainsKey(parentPath))
|
||||
{
|
||||
_operationStatuses[parentPath].Progress++;
|
||||
}
|
||||
await UpdateProgress();
|
||||
};
|
||||
|
||||
_createContainer = async (IContainer target, string name) => await target.CreateContainer(name);
|
||||
_timeRunner = timeRunner;
|
||||
_containerCopyDone = async (path) =>
|
||||
{
|
||||
_operationStatuses[path].Progress = _operationStatuses[path].TotalCount;
|
||||
if (timeRunner != null)
|
||||
{
|
||||
await timeRunner.RefreshContainer.InvokeAsync(this, path);
|
||||
}
|
||||
};
|
||||
|
||||
await DoCopy(Sources, Target, TransportMode.Value);
|
||||
}
|
||||
|
||||
private async Task CalculateProgress()
|
||||
{
|
||||
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 operationStatuses = new Dictionary<AbsolutePath, OperationProgress>();
|
||||
|
||||
_copyOperation = (_, to) =>
|
||||
{
|
||||
var parentPath = to.GetParentAsAbsolutePath();
|
||||
OperationProgress operation;
|
||||
if (operationStatuses.ContainsKey(parentPath))
|
||||
{
|
||||
operation = operationStatuses[parentPath];
|
||||
}
|
||||
else
|
||||
{
|
||||
operation = new OperationProgress();
|
||||
operationStatuses.Add(parentPath, operation);
|
||||
}
|
||||
operation.TotalCount++;
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
await DoCopy(Sources, Target, TransportMode.Value);
|
||||
_operationStatuses = operationStatuses;
|
||||
}
|
||||
|
||||
private async Task DoCopy(
|
||||
IEnumerable<AbsolutePath> sources,
|
||||
IContainer target,
|
||||
@@ -86,7 +160,7 @@ namespace FileTime.Core.Command
|
||||
var childFiles = (await container.GetElements())!.Select(f => new AbsolutePath(f));
|
||||
|
||||
await DoCopy(childDirectories.Concat(childFiles), targetContainer, transportMode);
|
||||
_timeRunner?.RefreshContainer.InvokeAsync(this, new AbsolutePath(container));
|
||||
if (_containerCopyDone != null) await _containerCopyDone.Invoke(new AbsolutePath(container));
|
||||
}
|
||||
else if (item is IElement element)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using AsyncEvent;
|
||||
using FileTime.Core.Models;
|
||||
using FileTime.Core.Timeline;
|
||||
|
||||
@@ -8,6 +9,11 @@ namespace FileTime.Core.Command
|
||||
public AbsolutePath Container { get; }
|
||||
public string NewContainerName { get; }
|
||||
|
||||
public int Progress => 100;
|
||||
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
public string DisplayLabel { get; } = "CreateContainer";
|
||||
|
||||
public CreateContainerCommand(AbsolutePath container, string newContainerName)
|
||||
{
|
||||
Container = container;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using AsyncEvent;
|
||||
using FileTime.Core.Models;
|
||||
using FileTime.Core.Timeline;
|
||||
|
||||
@@ -8,6 +9,10 @@ namespace FileTime.Core.Command
|
||||
public AbsolutePath Container { get; }
|
||||
public string NewElementName { get; }
|
||||
|
||||
public int Progress => 100;
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
public string DisplayLabel { get; } = "CreateElement";
|
||||
|
||||
public CreateElementCommand(AbsolutePath container, string newElementName)
|
||||
{
|
||||
Container = container;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using AsyncEvent;
|
||||
using FileTime.Core.Extensions;
|
||||
using FileTime.Core.Models;
|
||||
using FileTime.Core.Timeline;
|
||||
@@ -6,7 +7,12 @@ namespace FileTime.Core.Command
|
||||
{
|
||||
public class DeleteCommand : IExecutableCommand
|
||||
{
|
||||
public int Progress => 100;
|
||||
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
|
||||
public IList<AbsolutePath> ItemsToDelete { get; } = new List<AbsolutePath>();
|
||||
public string DisplayLabel { get; } = "DeleteCommand";
|
||||
|
||||
public async Task<PointInTime> SimulateCommand(PointInTime startPoint)
|
||||
{
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
using AsyncEvent;
|
||||
using FileTime.Core.Timeline;
|
||||
|
||||
namespace FileTime.Core.Command
|
||||
{
|
||||
public interface ICommand
|
||||
{
|
||||
string DisplayLabel { get; }
|
||||
Task<CanCommandRun> CanRun(PointInTime startPoint);
|
||||
Task<PointInTime> SimulateCommand(PointInTime startPoint);
|
||||
int Progress { get; }
|
||||
AsyncEventHandler ProgressChanged { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using AsyncEvent;
|
||||
using FileTime.Core.Models;
|
||||
using FileTime.Core.Timeline;
|
||||
|
||||
@@ -10,6 +11,10 @@ namespace FileTime.Core.Command
|
||||
public IContainer? Target { get; set; }
|
||||
public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge;
|
||||
|
||||
public int Progress => 100;
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
public string DisplayLabel { get; } = "MoveCommand";
|
||||
|
||||
public Task<CanCommandRun> CanRun(PointInTime startPoint)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
8
src/Core/FileTime.Core/Command/OperationProgress.cs
Normal file
8
src/Core/FileTime.Core/Command/OperationProgress.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace FileTime.Core.Command
|
||||
{
|
||||
public class OperationProgress
|
||||
{
|
||||
public int Progress { get; set; }
|
||||
public int TotalCount { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using AsyncEvent;
|
||||
using FileTime.Core.Extensions;
|
||||
using FileTime.Core.Models;
|
||||
using FileTime.Core.Timeline;
|
||||
|
||||
@@ -8,6 +10,10 @@ namespace FileTime.Core.Command
|
||||
public AbsolutePath Source { get; }
|
||||
public string Target { get; }
|
||||
|
||||
public int Progress => 100;
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
public string DisplayLabel { get; } = "RenameCommand";
|
||||
|
||||
public RenameCommand(AbsolutePath source, string target)
|
||||
{
|
||||
Source = source;
|
||||
@@ -24,14 +30,25 @@ namespace FileTime.Core.Command
|
||||
}
|
||||
}
|
||||
|
||||
public Task<PointInTime> SimulateCommand(PointInTime startPoint)
|
||||
public async Task<PointInTime> SimulateCommand(PointInTime startPoint)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var item = await Source.Resolve();
|
||||
if (item == null) throw new FileNotFoundException();
|
||||
var newDifferences = new List<Difference>()
|
||||
{
|
||||
new Difference(item.ToDifferenceItemType(),
|
||||
DifferenceActionType.Delete,
|
||||
Source),
|
||||
new Difference(item.ToDifferenceItemType(),
|
||||
DifferenceActionType.Delete,
|
||||
Source)
|
||||
};
|
||||
return startPoint.WithDifferences(newDifferences);
|
||||
}
|
||||
|
||||
public Task<CanCommandRun> CanRun(PointInTime startPoint)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Task.FromResult(Source.Resolve() != null ? CanCommandRun.True : CanCommandRun.False);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using FileTime.Core.Timeline;
|
||||
|
||||
namespace FileTime.Core.Models
|
||||
{
|
||||
public sealed class AbsolutePath
|
||||
public sealed class AbsolutePath : IEquatable<AbsolutePath>
|
||||
{
|
||||
public IContentProvider ContentProvider { get; }
|
||||
public IContentProvider? VirtualContentProvider { get; }
|
||||
@@ -67,12 +67,6 @@ namespace FileTime.Core.Models
|
||||
return new AbsolutePath(contentProvider, path, virtualContentProvider);
|
||||
}
|
||||
|
||||
public bool IsEqual(AbsolutePath path)
|
||||
{
|
||||
//TODO: sure??
|
||||
return path.ContentProvider == ContentProvider && path.Path == Path;
|
||||
}
|
||||
|
||||
public async Task<IItem?> Resolve()
|
||||
{
|
||||
var result = VirtualContentProvider != null && (await VirtualContentProvider.IsExists(Path))
|
||||
@@ -87,11 +81,36 @@ namespace FileTime.Core.Models
|
||||
public string GetParent()
|
||||
{
|
||||
var pathParts = Path.Split(Constants.SeparatorChar);
|
||||
return string.Join(Constants.SeparatorChar, pathParts);
|
||||
return string.Join(Constants.SeparatorChar, pathParts[..^1]);
|
||||
}
|
||||
|
||||
public AbsolutePath GetParentAsAbsolutePath() => new(ContentProvider, GetParent(), VirtualContentProvider);
|
||||
|
||||
public string GetName() => Path.Split(Constants.SeparatorChar).Last();
|
||||
|
||||
public override bool Equals(object? obj) => this.Equals(obj as AbsolutePath);
|
||||
|
||||
public bool Equals(AbsolutePath? other) =>
|
||||
other is not null && other.ContentProvider == ContentProvider && other.Path == Path;
|
||||
|
||||
public override int GetHashCode() => (ContentProvider.Name, Path).GetHashCode();
|
||||
|
||||
public static bool operator ==(AbsolutePath? lhs, AbsolutePath? rhs)
|
||||
{
|
||||
if (lhs is null)
|
||||
{
|
||||
if (rhs is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only the left side is null.
|
||||
return false;
|
||||
}
|
||||
// Equals handles case of null on right side.
|
||||
return lhs.Equals(rhs);
|
||||
}
|
||||
|
||||
public static bool operator !=(AbsolutePath? lhs, AbsolutePath? rhs) => !(lhs == rhs);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace FileTime.Core.StateManagement
|
||||
{
|
||||
public class ElementCreationStates
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,12 @@ namespace FileTime.Core.Timeline
|
||||
public class ReadOnlyParallelCommands
|
||||
{
|
||||
public IReadOnlyList<ReadOnlyCommandTimeState> Commands { get; }
|
||||
public ushort Id { get; }
|
||||
|
||||
public ReadOnlyParallelCommands(ParallelCommands parallelCommands)
|
||||
{
|
||||
Commands = parallelCommands.Commands.Select(c => new ReadOnlyCommandTimeState(c)).ToList().AsReadOnly();
|
||||
Id = parallelCommands.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ namespace FileTime.Core.Timeline
|
||||
|
||||
private bool _resourceIsInUse;
|
||||
private readonly List<Thread> _commandRunners = new();
|
||||
private bool _enableRunning = true;
|
||||
private bool _enableRunning = false;//true
|
||||
|
||||
public bool EnableRunning
|
||||
{
|
||||
@@ -98,6 +98,8 @@ namespace FileTime.Core.Timeline
|
||||
|
||||
private void RunCommands()
|
||||
{
|
||||
while (_commandsToRun.Count > 0 && _commandsToRun[0].Commands.Count == 0) _commandsToRun.RemoveAt(0);
|
||||
|
||||
if (_commandsToRun.Count > 0)
|
||||
{
|
||||
foreach (var command in _commandsToRun[0].Commands)
|
||||
@@ -139,6 +141,10 @@ namespace FileTime.Core.Timeline
|
||||
if (command != null)
|
||||
{
|
||||
_commandsToRun[0].Remove(command);
|
||||
if (_commandsToRun[0].Commands.Count == 0)
|
||||
{
|
||||
_commandsToRun.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
_commandRunners.Remove(thread);
|
||||
@@ -150,12 +156,8 @@ namespace FileTime.Core.Timeline
|
||||
|
||||
public async Task Refresh()
|
||||
{
|
||||
await RunWithLockAsync(async () =>
|
||||
{
|
||||
await RefreshCommands(PointInTime.CreateEmpty());
|
||||
});
|
||||
await RunWithLockAsync(async () => await RefreshCommands(PointInTime.CreateEmpty()));
|
||||
await UpdateReadOnlyCommands();
|
||||
|
||||
}
|
||||
|
||||
private async Task RefreshCommands(PointInTime? fullStartTime = null)
|
||||
@@ -171,10 +173,10 @@ namespace FileTime.Core.Timeline
|
||||
|
||||
private async Task UpdateReadOnlyCommands()
|
||||
{
|
||||
await RunWithLockAsync(() =>
|
||||
{
|
||||
ParallelCommands = _commandsToRun.ConvertAll(c => new ReadOnlyParallelCommands(c)).AsReadOnly();
|
||||
});
|
||||
var wait = false;
|
||||
await RunWithLockAsync(() => wait = _commandsToRun.Count == 1);
|
||||
if (wait) await Task.Delay(100);
|
||||
await RunWithLockAsync(() => ParallelCommands = _commandsToRun.ConvertAll(c => new ReadOnlyParallelCommands(c)).AsReadOnly());
|
||||
CommandsChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user