Modern UI, Loading screen CanRunMessages

This commit is contained in:
2022-02-03 16:49:45 +01:00
parent 1319d0bb98
commit 2ff1aa366e
34 changed files with 913 additions and 563 deletions

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -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;
}

View File

@@ -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; }

View File

@@ -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)
{

View File

@@ -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)
{

View File

@@ -20,6 +20,7 @@ namespace FileTime.Core.Models
Task<bool> CanOpen();
bool IsLoaded { get; }
bool SupportsDirectoryLevelSoftDelete { get; }
AsyncEventHandler Refreshed { get; }
}

View File

@@ -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();
}

View File

@@ -0,0 +1,9 @@
namespace FileTime.Core.Models
{
public enum SupportsDelete
{
True,
HardDeleteOnly,
False
}
}

View File

@@ -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(

View File

@@ -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();

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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)
{