CreateElement
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
137
src/Core/FileTime.Core.Command/Create/CreateContainerCommand.cs
Normal file
137
src/Core/FileTime.Core.Command/Create/CreateContainerCommand.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
|
||||||
{
|
|
||||||
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.");
|
|
||||||
|
|
||||||
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;
|
protected override async Task CreateItem(IItemCreator itemCreator, IItem resolvedParent)
|
||||||
}
|
|
||||||
|
|
||||||
public Task<PointInTime> SimulateCommand(PointInTime currentTime)
|
|
||||||
{
|
{
|
||||||
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.");
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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!));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)),
|
||||||
|
|||||||
Reference in New Issue
Block a user