Modern UI, Loading screen CanRunMessages
This commit is contained in:
@@ -22,6 +22,7 @@ namespace FileTime.Core.Command
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
|
||||
public string DisplayLabel { get; } = "Copy";
|
||||
public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly();
|
||||
|
||||
private async Task UpdateProgress()
|
||||
{
|
||||
@@ -73,7 +74,7 @@ namespace FileTime.Core.Command
|
||||
return (IContainer)(await newContainerDiff.AbsolutePath.Resolve())!;
|
||||
};
|
||||
|
||||
await DoCopy(Sources, Target, TransportMode.Value);
|
||||
await TraverseTree(Sources, Target, TransportMode.Value);
|
||||
|
||||
return startPoint.WithDifferences(newDiffs);
|
||||
}
|
||||
@@ -107,7 +108,7 @@ namespace FileTime.Core.Command
|
||||
}
|
||||
};
|
||||
|
||||
await DoCopy(Sources, Target, TransportMode.Value);
|
||||
await TraverseTree(Sources, Target, TransportMode.Value);
|
||||
}
|
||||
|
||||
private async Task CalculateProgress()
|
||||
@@ -136,11 +137,11 @@ namespace FileTime.Core.Command
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
await DoCopy(Sources, Target, TransportMode.Value);
|
||||
await TraverseTree(Sources, Target, TransportMode.Value);
|
||||
_operationStatuses = operationStatuses;
|
||||
}
|
||||
|
||||
private async Task DoCopy(
|
||||
private async Task TraverseTree(
|
||||
IEnumerable<AbsolutePath> sources,
|
||||
IContainer target,
|
||||
TransportMode transportMode)
|
||||
@@ -159,7 +160,7 @@ namespace FileTime.Core.Command
|
||||
var childDirectories = (await container.GetContainers())!.Select(d => new AbsolutePath(d));
|
||||
var childFiles = (await container.GetElements())!.Select(f => new AbsolutePath(f));
|
||||
|
||||
await DoCopy(childDirectories.Concat(childFiles), targetContainer, transportMode);
|
||||
await TraverseTree(childDirectories.Concat(childFiles), targetContainer, transportMode);
|
||||
if (_containerCopyDone != null) await _containerCopyDone.Invoke(new AbsolutePath(container));
|
||||
}
|
||||
else if (item is IElement element)
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace FileTime.Core.Command
|
||||
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
public string DisplayLabel { get; } = "CreateContainer";
|
||||
public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly();
|
||||
|
||||
public CreateContainerCommand(AbsolutePath container, string newContainerName)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace FileTime.Core.Command
|
||||
public int Progress => 100;
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
public string DisplayLabel { get; } = "CreateElement";
|
||||
public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly();
|
||||
|
||||
public CreateElementCommand(AbsolutePath container, string newElementName)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,9 @@ namespace FileTime.Core.Command
|
||||
{
|
||||
public class DeleteCommand : IExecutableCommand
|
||||
{
|
||||
private Func<IContainer, Task>? _deleteContainer;
|
||||
private Func<IElement, Task>? _deleteElement;
|
||||
|
||||
public int Progress => 100;
|
||||
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
@@ -14,46 +17,79 @@ namespace FileTime.Core.Command
|
||||
public IList<AbsolutePath> ItemsToDelete { get; } = new List<AbsolutePath>();
|
||||
public string DisplayLabel { get; } = "DeleteCommand";
|
||||
|
||||
public bool HardDelete { get; set; }
|
||||
public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly();
|
||||
|
||||
public async Task<PointInTime> SimulateCommand(PointInTime startPoint)
|
||||
{
|
||||
var newDifferences = new List<Difference>();
|
||||
|
||||
foreach (var itemToDelete in ItemsToDelete)
|
||||
_deleteContainer = (c) =>
|
||||
{
|
||||
var item = await itemToDelete.Resolve();
|
||||
newDifferences.Add(new Difference(
|
||||
item.ToDifferenceItemType(),
|
||||
DifferenceItemType.Container,
|
||||
DifferenceActionType.Delete,
|
||||
itemToDelete
|
||||
new AbsolutePath(c)
|
||||
));
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
_deleteElement = (e) =>
|
||||
{
|
||||
newDifferences.Add(new Difference(
|
||||
DifferenceItemType.Element,
|
||||
DifferenceActionType.Delete,
|
||||
new AbsolutePath(e)
|
||||
));
|
||||
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
foreach (var item in ItemsToDelete)
|
||||
{
|
||||
await TraverseTree((await item.Resolve())!);
|
||||
}
|
||||
|
||||
return startPoint.WithDifferences(newDifferences);
|
||||
}
|
||||
|
||||
public async Task Execute(TimeRunner timeRunner)
|
||||
{
|
||||
_deleteContainer = async (c) =>
|
||||
{
|
||||
await c.Delete(HardDelete);
|
||||
await timeRunner.RefreshContainer.InvokeAsync(this, new AbsolutePath(c));
|
||||
};
|
||||
_deleteElement = async (e) => await e.Delete(HardDelete);
|
||||
|
||||
foreach (var item in ItemsToDelete)
|
||||
{
|
||||
await DoDelete((await item.Resolve())!, timeRunner);
|
||||
await TraverseTree((await item.Resolve())!);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DoDelete(IItem item, TimeRunner timeRunner)
|
||||
private async Task TraverseTree(IItem item)
|
||||
{
|
||||
if (item is IContainer container)
|
||||
{
|
||||
foreach (var child in (await container.GetItems())!)
|
||||
if (!HardDelete && container.SupportsDirectoryLevelSoftDelete)
|
||||
{
|
||||
await DoDelete(child, timeRunner);
|
||||
await child.Delete();
|
||||
if (_deleteContainer != null) await _deleteContainer.Invoke(container);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var child in (await container.GetItems())!)
|
||||
{
|
||||
await TraverseTree(child);
|
||||
}
|
||||
|
||||
if (_deleteContainer != null) await _deleteContainer.Invoke(container);
|
||||
}
|
||||
|
||||
await item.Delete();
|
||||
await timeRunner.RefreshContainer.InvokeAsync(this, new AbsolutePath(container));
|
||||
}
|
||||
else if (item is IElement element)
|
||||
{
|
||||
await element.Delete();
|
||||
if (_deleteElement != null) await _deleteElement.Invoke(element);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +99,12 @@ namespace FileTime.Core.Command
|
||||
foreach (var itemPath in ItemsToDelete)
|
||||
{
|
||||
var resolvedItem = await itemPath.Resolve();
|
||||
if (!(resolvedItem?.CanDelete ?? true))
|
||||
if (resolvedItem != null
|
||||
&& (
|
||||
resolvedItem.CanDelete == SupportsDelete.False
|
||||
|| (resolvedItem.CanDelete == SupportsDelete.HardDeleteOnly && !HardDelete)
|
||||
)
|
||||
)
|
||||
{
|
||||
result = CanCommandRun.Forceable;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace FileTime.Core.Command
|
||||
public interface ICommand
|
||||
{
|
||||
string DisplayLabel { get; }
|
||||
IReadOnlyList<string> CanRunMessages { get; }
|
||||
Task<CanCommandRun> CanRun(PointInTime startPoint);
|
||||
Task<PointInTime> SimulateCommand(PointInTime startPoint);
|
||||
int Progress { get; }
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace FileTime.Core.Command
|
||||
public int Progress => 100;
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
public string DisplayLabel { get; } = "MoveCommand";
|
||||
public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly();
|
||||
|
||||
public Task<CanCommandRun> CanRun(PointInTime startPoint)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace FileTime.Core.Command
|
||||
public int Progress => 100;
|
||||
public AsyncEventHandler ProgressChanged { get; } = new();
|
||||
public string DisplayLabel { get; } = "RenameCommand";
|
||||
public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly();
|
||||
|
||||
public RenameCommand(AbsolutePath source, string target)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace FileTime.Core.Models
|
||||
Task<bool> CanOpen();
|
||||
|
||||
bool IsLoaded { get; }
|
||||
bool SupportsDirectoryLevelSoftDelete { get; }
|
||||
|
||||
AsyncEventHandler Refreshed { get; }
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ namespace FileTime.Core.Models
|
||||
string Name { get; }
|
||||
string? FullName { get; }
|
||||
bool IsHidden { get; }
|
||||
bool CanDelete { get; }
|
||||
SupportsDelete CanDelete { get; }
|
||||
bool CanRename { get; }
|
||||
IContentProvider Provider { get; }
|
||||
Task Delete();
|
||||
Task Delete(bool hardDelete = false);
|
||||
Task Rename(string newName);
|
||||
IContainer? GetParent();
|
||||
}
|
||||
|
||||
9
src/Core/FileTime.Core/Models/SupportsDelete.cs
Normal file
9
src/Core/FileTime.Core/Models/SupportsDelete.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace FileTime.Core.Models
|
||||
{
|
||||
public enum SupportsDelete
|
||||
{
|
||||
True,
|
||||
HardDeleteOnly,
|
||||
False
|
||||
}
|
||||
}
|
||||
@@ -25,12 +25,14 @@ namespace FileTime.Core.Models
|
||||
|
||||
public bool IsHidden => BaseContainer.IsHidden;
|
||||
public bool IsLoaded => BaseContainer.IsLoaded;
|
||||
public bool CanDelete => BaseContainer.CanDelete;
|
||||
public SupportsDelete CanDelete => BaseContainer.CanDelete;
|
||||
public bool CanRename => BaseContainer.CanRename;
|
||||
|
||||
public IContentProvider Provider => BaseContainer.Provider;
|
||||
public IReadOnlyList<Exception> Exceptions => BaseContainer.Exceptions;
|
||||
|
||||
public bool SupportsDirectoryLevelSoftDelete => BaseContainer.SupportsDirectoryLevelSoftDelete;
|
||||
|
||||
public AsyncEventHandler Refreshed { get; }
|
||||
|
||||
private void RefreshAddBase(Func<object?, AsyncEventArgs, Task> handler)
|
||||
@@ -151,7 +153,7 @@ namespace FileTime.Core.Models
|
||||
return Task.FromResult(Elements);
|
||||
}
|
||||
|
||||
public async Task Delete() => await BaseContainer.Delete();
|
||||
public async Task Delete(bool hardDelete = false) => await BaseContainer.Delete();
|
||||
public async Task<IContainer> Clone()
|
||||
{
|
||||
return new VirtualContainer(
|
||||
|
||||
@@ -24,13 +24,15 @@ namespace FileTime.Core.Providers
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
public IContentProvider Provider => null;
|
||||
#pragma warning restore CS8603 // Possible null reference return.
|
||||
public bool CanDelete => false;
|
||||
public SupportsDelete CanDelete => SupportsDelete.False;
|
||||
public bool CanRename => false;
|
||||
|
||||
public AsyncEventHandler Refreshed { get; } = new();
|
||||
|
||||
public IReadOnlyList<Exception> Exceptions { get; } = new List<Exception>().AsReadOnly();
|
||||
|
||||
public bool SupportsDirectoryLevelSoftDelete => false;
|
||||
|
||||
public TopContainer(IEnumerable<IContentProvider> contentProviders)
|
||||
{
|
||||
_contentProviders = new List<IContentProvider>(contentProviders);
|
||||
@@ -47,7 +49,7 @@ namespace FileTime.Core.Providers
|
||||
|
||||
public Task<IElement> CreateElement(string name) => throw new NotImplementedException();
|
||||
|
||||
public Task Delete() => throw new NotImplementedException();
|
||||
public Task Delete(bool hardDelete = false) => throw new NotImplementedException();
|
||||
|
||||
public Task<IItem?> GetByPath(string path, bool acceptDeepestMatch = false) => throw new NotImplementedException();
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace FileTime.Core.Timeline
|
||||
|
||||
public bool IsHidden => false;
|
||||
|
||||
public bool CanDelete => true;
|
||||
public SupportsDelete CanDelete => SupportsDelete.True;
|
||||
|
||||
public bool CanRename => true;
|
||||
|
||||
@@ -27,6 +27,8 @@ namespace FileTime.Core.Timeline
|
||||
public IContentProvider VirtualProvider { get; }
|
||||
public IReadOnlyList<Exception> Exceptions { get; } = new List<Exception>().AsReadOnly();
|
||||
|
||||
public bool SupportsDirectoryLevelSoftDelete => false;
|
||||
|
||||
public TimeContainer(string name, IContainer parent, IContentProvider contentProvider, IContentProvider virtualContentProvider, PointInTime pointInTime)
|
||||
{
|
||||
_parent = parent;
|
||||
@@ -44,7 +46,7 @@ namespace FileTime.Core.Timeline
|
||||
|
||||
public Task<IElement> CreateElement(string name) => Task.FromResult((IElement)new TimeElement(name, this, Provider, VirtualProvider));
|
||||
|
||||
public Task Delete() => Task.CompletedTask;
|
||||
public Task Delete(bool hardDelete = false) => Task.CompletedTask;
|
||||
|
||||
public async Task<IItem?> GetByPath(string path, bool acceptDeepestMatch = false)
|
||||
{
|
||||
|
||||
@@ -24,14 +24,14 @@ namespace FileTime.Core.Timeline
|
||||
|
||||
public bool IsHidden => false;
|
||||
|
||||
public bool CanDelete => true;
|
||||
public SupportsDelete CanDelete => SupportsDelete.True;
|
||||
|
||||
public bool CanRename => true;
|
||||
|
||||
public IContentProvider Provider { get; }
|
||||
public IContentProvider VirtualProvider { get; }
|
||||
|
||||
public Task Delete() => Task.CompletedTask;
|
||||
public Task Delete(bool hardDelete = false) => Task.CompletedTask;
|
||||
|
||||
public IContainer? GetParent() => _parent;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace FileTime.Core.Timeline
|
||||
|
||||
public bool IsHidden => false;
|
||||
|
||||
public bool CanDelete => false;
|
||||
public SupportsDelete CanDelete => SupportsDelete.False;
|
||||
|
||||
public bool CanRename => false;
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace FileTime.Core.Timeline
|
||||
|
||||
public IReadOnlyList<Exception> Exceptions { get; } = new List<Exception>().AsReadOnly();
|
||||
|
||||
public bool SupportsDirectoryLevelSoftDelete => false;
|
||||
|
||||
public TimeProvider(PointInTime pointInTime)
|
||||
{
|
||||
_pointInTime = pointInTime;
|
||||
@@ -48,7 +50,7 @@ namespace FileTime.Core.Timeline
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task Delete() => throw new NotSupportedException();
|
||||
public Task Delete(bool hardDelete = false) => throw new NotSupportedException();
|
||||
|
||||
public Task<IItem?> GetByPath(string path, bool acceptDeepestMatch = false)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user