CreateElement

This commit is contained in:
2022-05-24 14:22:33 +02:00
parent 90cb345f96
commit dcff003c28
8 changed files with 201 additions and 105 deletions

View File

@@ -0,0 +1,13 @@
namespace FileTime.App.Core.UserCommand;
public sealed class CreateElement : IIdentifiableUserCommand
{
public const string CommandName = "create_element";
public static CreateElement Instance { get; } = new CreateElement();
private CreateElement()
{
}
public string UserCommandID => CommandName;
}

View File

@@ -5,6 +5,7 @@ using FileTime.App.Core.UserCommand;
using FileTime.App.Core.ViewModels; using FileTime.App.Core.ViewModels;
using FileTime.Core.Command; using FileTime.Core.Command;
using FileTime.Core.Command.CreateContainer; using FileTime.Core.Command.CreateContainer;
using FileTime.Core.Command.CreateElement;
using FileTime.Core.Interactions; using FileTime.Core.Interactions;
using FileTime.Core.Models; using FileTime.Core.Models;
using FileTime.Core.Timeline; using FileTime.Core.Timeline;
@@ -56,6 +57,7 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi
new TypeUserCommandHandler<MarkCommand>(MarkItem), new TypeUserCommandHandler<MarkCommand>(MarkItem),
new TypeUserCommandHandler<PasteCommand>(Paste), new TypeUserCommandHandler<PasteCommand>(Paste),
new TypeUserCommandHandler<CreateContainer>(CreateContainer), new TypeUserCommandHandler<CreateContainer>(CreateContainer),
new TypeUserCommandHandler<CreateElement>(CreateElement),
}); });
} }
@@ -136,8 +138,25 @@ public class ItemManipulationUserCommandHandlerService : UserCommandHandlerServi
if (_currentLocation?.FullName is null || newContainerName is null) return; if (_currentLocation?.FullName is null || newContainerName is null) return;
var command = _serviceProvider var command = _serviceProvider
.GetInitableResolver<FullName, string>(_currentLocation.FullName, newContainerName) .GetInitableResolver(_currentLocation.FullName, newContainerName)
.GetRequiredService<CreateContainerCommand>(); .GetRequiredService<CreateContainerCommand>();
await _commandScheduler.AddCommand(command); await _commandScheduler.AddCommand(command);
} }
private async Task CreateElement()
{
var containerNameInput = new TextInputElement("Element name");
await _inputInterface.ReadInputs(new List<IInputElement>() { containerNameInput });
//TODO: message on empty result
var newContainerName = containerNameInput.Value;
if (_currentLocation?.FullName is null || newContainerName is null) return;
var command = _serviceProvider
.GetInitableResolver(_currentLocation.FullName, newContainerName)
.GetRequiredService<CreateElementCommand>();
await _commandScheduler.AddCommand(command);
}
} }

View File

@@ -14,6 +14,7 @@ public class DefaultIdentifiableCommandHandlerRegister : IStartupHandler
AddUserCommand(CloseTabCommand.Instance); AddUserCommand(CloseTabCommand.Instance);
AddUserCommand(CopyCommand.Instance); AddUserCommand(CopyCommand.Instance);
AddUserCommand(CreateContainer.Instance); AddUserCommand(CreateContainer.Instance);
AddUserCommand(CreateElement.Instance);
AddUserCommand(EnterRapidTravelCommand.Instance); AddUserCommand(EnterRapidTravelCommand.Instance);
AddUserCommand(ExitRapidTravelCommand.Instance); AddUserCommand(ExitRapidTravelCommand.Instance);
AddUserCommand(GoUpCommand.Instance); AddUserCommand(GoUpCommand.Instance);

View File

@@ -1,6 +1,7 @@
using FileTime.App.Core; using FileTime.App.Core;
using FileTime.Core.Command; using FileTime.Core.Command;
using FileTime.Core.Command.CreateContainer; using FileTime.Core.Command.CreateContainer;
using FileTime.Core.Command.CreateElement;
using FileTime.Core.ContentAccess; using FileTime.Core.ContentAccess;
using FileTime.Core.Services; using FileTime.Core.Services;
using FileTime.Core.Timeline; using FileTime.Core.Timeline;
@@ -31,6 +32,8 @@ public static class DependencyInjection
public static IServiceCollection RegisterCommands(this IServiceCollection serviceCollection) public static IServiceCollection RegisterCommands(this IServiceCollection serviceCollection)
{ {
return serviceCollection.AddTransient<CreateContainerCommand>(); return serviceCollection
.AddTransient<CreateContainerCommand>()
.AddTransient<CreateElementCommand>();
} }
} }

View File

@@ -0,0 +1,137 @@
using FileTime.Core.ContentAccess;
using FileTime.Core.Enums;
using FileTime.Core.Extensions;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
using InitableService;
namespace FileTime.Core.Command.Create;
public abstract class CreateItemBase : IExecutableCommand, IInitable<FullName, string>
{
private readonly ITimelessContentProvider _timelessContentProvider;
private readonly IContentAccessorFactory _contentAccessorFactory;
public FullName? Parent { get; private set; }
public string? NewItemName { get; private set; }
protected CreateItemBase(
ITimelessContentProvider timelessContentProvider,
IContentAccessorFactory contentAccessorFactory)
{
_timelessContentProvider = timelessContentProvider;
_contentAccessorFactory = contentAccessorFactory;
}
public async Task<CanCommandRun> CanRun(PointInTime currentTime)
{
if (Parent is null)
{
throw new ArgumentNullException(nameof(Parent),
$"Property {nameof(Parent)} is not initialized. Call the {nameof(Init)} method before using the command.");
}
if (NewItemName is null)
{
throw new ArgumentNullException(nameof(NewItemName),
$"Property {nameof(NewItemName)} is not initialized. Call the {nameof(Init)} method before using the command.");
}
try
{
var parent = await ResolveParentAsync();
if (parent is not IContainer parentContainer) return CanCommandRun.False;
var items = await parentContainer.Items.GetItemsAsync();
if (items is null) return CanCommandRun.Forcable;
var existingItem = items.FirstOrDefault(i => i.Path.GetName() == NewItemName);
return existingItem switch
{
null => CanCommandRun.True,
{ Type: AbsolutePathType.Container } => CanCommandRun.Forcable,
_ => CanCommandRun.False
};
}
catch
{
}
return CanCommandRun.False;
}
public Task<PointInTime> SimulateCommand(PointInTime currentTime)
{
if (Parent is null)
{
throw new ArgumentNullException(nameof(Parent),
$"Property {nameof(Parent)} is not initialized. Call the {nameof(Init)} method before using the command.");
}
if (NewItemName is null)
{
throw new ArgumentNullException(nameof(NewItemName),
$"Property {nameof(NewItemName)} is not initialized. Call the {nameof(Init)} method before using the command.");
}
return Task.FromResult(
currentTime.WithDifferences(newPointInTime =>
new List<Difference>()
{
new(
DifferenceActionType.Create,
new AbsolutePath(_timelessContentProvider,
newPointInTime,
Parent.GetChild(NewItemName),
AbsolutePathType.Container
)
)
}
)
);
}
public async Task Execute()
{
if (Parent is null)
{
throw new ArgumentNullException(nameof(Parent),
$"Property {nameof(Parent)} is not initialized. Call the {nameof(Init)} method before using the command.");
}
if (NewItemName is null)
{
throw new ArgumentNullException(nameof(NewItemName),
$"Property {nameof(NewItemName)} is not initialized. Call the {nameof(Init)} method before using the command.");
}
var resolvedParent = await _timelessContentProvider.GetItemByFullNameAsync(Parent, PointInTime.Present);
var itemCreator = _contentAccessorFactory.GetItemCreator(resolvedParent.Provider);
await CreateItem(itemCreator, resolvedParent);
}
abstract protected Task CreateItem(IItemCreator itemCreator, IItem resolvedParent);
private async Task<IItem> ResolveParentAsync()
{
if (Parent is null)
{
throw new ArgumentNullException(nameof(Parent),
$"Property {nameof(Parent)} is not initialized. Call the {nameof(Init)} method before using the command.");
}
if (NewItemName is null)
{
throw new ArgumentNullException(nameof(NewItemName),
$"Property {nameof(NewItemName)} is not initialized. Call the {nameof(Init)} method before using the command.");
}
return await _timelessContentProvider.GetItemByFullNameAsync(Parent, PointInTime.Present);
}
public void Init(FullName parent, string newContainerName)
{
Parent = parent;
NewItemName = newContainerName;
}
}

View File

@@ -1,115 +1,19 @@
using FileTime.Core.Command.Create;
using FileTime.Core.ContentAccess; using FileTime.Core.ContentAccess;
using FileTime.Core.Enums;
using FileTime.Core.Extensions;
using FileTime.Core.Models; using FileTime.Core.Models;
using FileTime.Core.Timeline; using FileTime.Core.Timeline;
using InitableService;
namespace FileTime.Core.Command.CreateContainer; namespace FileTime.Core.Command.CreateContainer;
public class CreateContainerCommand : IExecutableCommand, IInitable<FullName, string> public class CreateContainerCommand : CreateItemBase
{ {
private readonly ITimelessContentProvider _timelessContentProvider; public CreateContainerCommand(ITimelessContentProvider timelessContentProvider, IContentAccessorFactory contentAccessorFactory)
private readonly IContentAccessorFactory _contentAccessorFactory; : base(timelessContentProvider, contentAccessorFactory)
public FullName? Parent { get; private set; }
public string? NewContainerName { get; private set; }
public CreateContainerCommand(
ITimelessContentProvider timelessContentProvider,
IContentAccessorFactory contentAccessorFactory)
{ {
_timelessContentProvider = timelessContentProvider;
_contentAccessorFactory = contentAccessorFactory;
} }
public async Task<CanCommandRun> CanRun(PointInTime currentTime) protected override async Task CreateItem(IItemCreator itemCreator, IItem resolvedParent)
{ {
if (Parent is null) await itemCreator.CreateContainerAsync(resolvedParent.Provider, Parent!.GetChild(NewItemName!));
throw new ArgumentNullException(nameof(Parent),
$"Property {nameof(Parent)} is not initialized. Call the {nameof(Init)} method before using the command.");
if (NewContainerName is null)
throw new ArgumentNullException(nameof(NewContainerName),
$"Property {nameof(NewContainerName)} is not initialized. Call the {nameof(Init)} method before using the command.");
try
{
var parent = await ResolveParentAsync();
if (parent is not IContainer parentContainer) return CanCommandRun.False;
var items = await parentContainer.Items.GetItemsAsync();
if (items is null) return CanCommandRun.Forcable;
var existingItem = items.FirstOrDefault(i => i.Path.GetName() == NewContainerName);
return existingItem switch
{
null => CanCommandRun.True,
{ Type: AbsolutePathType.Container } => CanCommandRun.Forcable,
_ => CanCommandRun.False
};
}
catch
{
}
return CanCommandRun.False;
}
public Task<PointInTime> SimulateCommand(PointInTime currentTime)
{
if (Parent is null)
throw new ArgumentNullException(nameof(Parent),
$"Property {nameof(Parent)} is not initialized. Call the {nameof(Init)} method before using the command.");
if (NewContainerName is null)
throw new ArgumentNullException(nameof(NewContainerName),
$"Property {nameof(NewContainerName)} is not initialized. Call the {nameof(Init)} method before using the command.");
return Task.FromResult(
currentTime.WithDifferences(newPointInTime =>
new List<Difference>()
{
new(
DifferenceActionType.Create,
new AbsolutePath(_timelessContentProvider,
newPointInTime,
Parent.GetChild(NewContainerName),
AbsolutePathType.Container
)
)
}
)
);
}
public async Task Execute()
{
if (Parent is null)
throw new ArgumentNullException(nameof(Parent),
$"Property {nameof(Parent)} is not initialized. Call the {nameof(Init)} method before using the command.");
if (NewContainerName is null)
throw new ArgumentNullException(nameof(NewContainerName),
$"Property {nameof(NewContainerName)} is not initialized. Call the {nameof(Init)} method before using the command.");
var resolvedParent = await _timelessContentProvider.GetItemByFullNameAsync(Parent, PointInTime.Present);
var itemCreator = _contentAccessorFactory.GetItemCreator(resolvedParent.Provider);
await itemCreator.CreateContainerAsync(resolvedParent.Provider, Parent.GetChild(NewContainerName));
}
private async Task<IItem> ResolveParentAsync()
{
if (Parent is null)
throw new ArgumentNullException(nameof(Parent),
$"Property {nameof(Parent)} is not initialized. Call the {nameof(Init)} method before using the command.");
if (NewContainerName is null)
throw new ArgumentNullException(nameof(NewContainerName),
$"Property {nameof(NewContainerName)} is not initialized. Call the {nameof(Init)} method before using the command.");
return await _timelessContentProvider.GetItemByFullNameAsync(Parent, PointInTime.Present);
}
public void Init(FullName parent, string newContainerName)
{
Parent = parent;
NewContainerName = newContainerName;
} }
} }

View File

@@ -0,0 +1,19 @@
using FileTime.Core.Command.Create;
using FileTime.Core.ContentAccess;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
namespace FileTime.Core.Command.CreateElement;
public class CreateElementCommand : CreateItemBase
{
public CreateElementCommand(ITimelessContentProvider timelessContentProvider, IContentAccessorFactory contentAccessorFactory)
: base(timelessContentProvider, contentAccessorFactory)
{
}
protected override async Task CreateItem(IItemCreator itemCreator, IItem resolvedParent)
{
await itemCreator.CreateElementAsync(resolvedParent.Provider, Parent!.GetChild(NewItemName!));
}
}

View File

@@ -49,7 +49,7 @@ public static class MainConfiguration
//new CommandBindingConfiguration(ConfigCommand.CopyPath, new[] { Key.C, Key.P }), //new CommandBindingConfiguration(ConfigCommand.CopyPath, new[] { Key.C, Key.P }),
new CommandBindingConfiguration(CreateContainer.CommandName, Key.F7), new CommandBindingConfiguration(CreateContainer.CommandName, Key.F7),
new CommandBindingConfiguration(CreateContainer.CommandName, new[] { Key.C, Key.C }), new CommandBindingConfiguration(CreateContainer.CommandName, new[] { Key.C, Key.C }),
//new CommandBindingConfiguration(ConfigCommand.CreateElement, new[] { Key.C, Key.E }), new CommandBindingConfiguration(CreateElement.CommandName, new[] { Key.C, Key.E }),
//new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Key.D, Key.D }), //new CommandBindingConfiguration(ConfigCommand.Cut, new[] { Key.D, Key.D }),
//new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Key.F4)), //new CommandBindingConfiguration(ConfigCommand.Edit, new KeyConfig(Key.F4)),
new CommandBindingConfiguration(EnterRapidTravelCommand.CommandName, new KeyConfig(Key.OemComma, shift: true)), new CommandBindingConfiguration(EnterRapidTravelCommand.CommandName, new KeyConfig(Key.OemComma, shift: true)),