Implemented modular create actions

This commit is contained in:
Marcel Baumgartner 2024-03-30 22:26:52 +01:00
parent b2929fe211
commit cdc2954d0b
9 changed files with 112 additions and 87 deletions

View file

@ -52,11 +52,14 @@ public class FileManagerFeature : MoonlightFeature
// Register default file manager actions in plugin service
var pluginService = context.Application.Services.GetRequiredService<PluginService>();
await pluginService.RegisterImplementation<IFileManagerAction>(new RenameAction());
await pluginService.RegisterImplementation<IFileManagerAction>(new DownloadAction());
await pluginService.RegisterImplementation<IFileManagerAction>(new DeleteAction());
await pluginService.RegisterImplementation<IFileManagerContextAction>(new RenameContextAction());
await pluginService.RegisterImplementation<IFileManagerContextAction>(new DownloadContextAction());
await pluginService.RegisterImplementation<IFileManagerContextAction>(new DeleteContextAction());
await pluginService.RegisterImplementation<IFileManagerSelectionAction>(new DeleteSelectionAction());
await pluginService.RegisterImplementation<IFileManagerCreateAction>(new CreateFileAction());
await pluginService.RegisterImplementation<IFileManagerCreateAction>(new CreateFolderAction());
}
public override async Task OnSessionInitialized(SessionInitContext context)

View file

@ -0,0 +1,37 @@
using MoonCoreUI.Services;
using Moonlight.Features.FileManager.Interfaces;
using Moonlight.Features.FileManager.Models.Abstractions.FileAccess;
using Moonlight.Features.FileManager.UI.NewFileManager;
namespace Moonlight.Features.FileManager.Implementations;
public class CreateFileAction : IFileManagerCreateAction
{
public string Name => "File";
public string Icon => "bx-file";
public string Color => "primary";
public async Task Execute(BaseFileAccess access, FileView view, IServiceProvider provider)
{
var alertService = provider.GetRequiredService<AlertService>();
var name = await alertService.Text("Enter a name for the new file");
if (string.IsNullOrEmpty(name) || name.Contains(".."))
return;
await access.CreateFile(name);
/*
// We build a virtual entry here so we dont need to fetch one
await OpenEditor(new()
{
Name = name,
Size = 0,
IsFile = true,
IsDirectory = false,
LastModifiedAt = DateTime.UtcNow
});*/
}
}

View file

@ -0,0 +1,29 @@
using MoonCoreUI.Services;
using Moonlight.Features.FileManager.Interfaces;
using Moonlight.Features.FileManager.Models.Abstractions.FileAccess;
using Moonlight.Features.FileManager.UI.NewFileManager;
namespace Moonlight.Features.FileManager.Implementations;
public class CreateFolderAction : IFileManagerCreateAction
{
public string Name => "Folder";
public string Icon => "bx-folder";
public string Color => "primary";
public async Task Execute(BaseFileAccess access, FileView view, IServiceProvider provider)
{
var alertService = provider.GetRequiredService<AlertService>();
var toastService = provider.GetRequiredService<ToastService>();
var name = await alertService.Text("Enter a name for the new directory");
if (string.IsNullOrEmpty(name) || name.Contains(".."))
return;
await access.CreateDirectory(name);
await toastService.Success("Successfully created directory");
await view.Refresh();
}
}

View file

@ -5,7 +5,7 @@ using Moonlight.Features.FileManager.UI.NewFileManager;
namespace Moonlight.Features.FileManager.Implementations;
public class DeleteAction : IFileManagerAction
public class DeleteContextAction : IFileManagerContextAction
{
public string Name => "Delete";
public string Icon => "bxs-trash";

View file

@ -8,7 +8,7 @@ using Moonlight.Features.FileManager.UI.NewFileManager;
namespace Moonlight.Features.FileManager.Implementations;
public class DownloadAction : IFileManagerAction
public class DownloadContextAction : IFileManagerContextAction
{
public string Name => "Download";
public string Icon => "bxs-cloud-download";

View file

@ -5,7 +5,7 @@ using Moonlight.Features.FileManager.UI.NewFileManager;
namespace Moonlight.Features.FileManager.Implementations;
public class RenameAction : IFileManagerAction
public class RenameContextAction : IFileManagerContextAction
{
public string Name => "Rename";
public string Icon => "bxs-rename";

View file

@ -3,7 +3,7 @@ using Moonlight.Features.FileManager.UI.NewFileManager;
namespace Moonlight.Features.FileManager.Interfaces;
public interface IFileManagerAction
public interface IFileManagerContextAction
{
public string Name { get; }
public string Icon { get; }

View file

@ -0,0 +1,13 @@
using Moonlight.Features.FileManager.Models.Abstractions.FileAccess;
using Moonlight.Features.FileManager.UI.NewFileManager;
namespace Moonlight.Features.FileManager.Interfaces;
public interface IFileManagerCreateAction
{
public string Name { get; }
public string Icon { get; }
public string Color { get; }
public Task Execute(BaseFileAccess access, FileView view, IServiceProvider provider);
}

View file

@ -65,19 +65,16 @@
<a class="btn btn-primary dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
New
</a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink" style="">
<li>
<a href="#" class="dropdown-item" @onclick:preventDefault @onclick="CreateFile">
<i class="bx bx-sm bx-file text-primary me-2 align-middle"></i>
<span class="align-middle fs-6">File</span>
</a>
</li>
<li>
<a href="#" class="dropdown-item" @onclick:preventDefault @onclick="CreateDirectory">
<i class="bx bx-sm bx-folder text-primary me-2 align-middle"></i>
<span class="align-middle fs-6">Folder</span>
</a>
</li>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink">
@foreach (var action in CreateActions)
{
<li>
<a href="#" class="dropdown-item" @onclick:preventDefault @onclick="() => InvokeCreateAction(action)">
<i class="bx bx-sm @action.Icon text-@action.Color me-2 align-middle"></i>
<span class="align-middle fs-6">@action.Name</span>
</a>
</li>
}
</ul>
</div>
}
@ -101,7 +98,7 @@ else
OnSelectionChanged="OnSelectionChanged"
EnableContextMenu="true">
<ContextMenuTemplate>
@foreach (var action in Actions)
@foreach (var action in ContextActions)
{
if(!action.Filter.Invoke(context))
continue;
@ -150,8 +147,9 @@ else
private FileView View;
private string Path = "/";
private IFileManagerAction[] Actions;
private IFileManagerContextAction[] ContextActions;
private IFileManagerSelectionAction[] SelectionActions;
private IFileManagerCreateAction[] CreateActions;
// Editor
private FileEditor Editor;
@ -173,8 +171,9 @@ else
protected override async Task OnInitializedAsync()
{
// Load plugin ui and options
Actions = await PluginService.GetImplementations<IFileManagerAction>();
ContextActions = await PluginService.GetImplementations<IFileManagerContextAction>();
SelectionActions = await PluginService.GetImplementations<IFileManagerSelectionAction>();
CreateActions = await PluginService.GetImplementations<IFileManagerCreateAction>();
OnFolderClicked = async entry =>
{
@ -241,11 +240,11 @@ else
}
}
private async Task InvokeContextAction(IFileManagerAction action, FileEntry entry)
private async Task InvokeContextAction(IFileManagerContextAction contextAction, FileEntry entry)
{
await View.HideContextMenu();
await action.Execute(FileAccess, View, entry, ServiceProvider);
await contextAction.Execute(FileAccess, View, entry, ServiceProvider);
}
private async Task InvokeSelectionAction(IFileManagerSelectionAction action)
@ -255,6 +254,11 @@ else
// Refresh resets the selection
await View.Refresh();
}
private async Task InvokeCreateAction(IFileManagerCreateAction action)
{
await action.Execute(FileAccess, View, ServiceProvider);
}
private async Task OnSelectionChanged(FileEntry[] _) => await InvokeAsync(StateHasChanged);
@ -302,68 +306,7 @@ else
}
#endregion
#region Actions
private async Task DeleteSelection()
{
var itemsToDelete = View.Selection;
await ToastService.CreateProgress("fileManagerDeleteFile", "Deleting items");
var i = 1;
foreach (var entry in itemsToDelete)
{
await ToastService.ModifyProgress("fileManagerDeleteFile", $"[{i}/{FilesToMove.Count}] Deleting items");
await FileAccess.Delete(entry);
i++;
}
await ToastService.RemoveProgress("fileManagerDeleteFile");
await ToastService.Success($"Successfully deleted {FilesToMove.Count} items");
}
#endregion
#region Create Dir / File
private async Task CreateDirectory()
{
var name = await AlertService.Text("Enter a name for the new directory");
if (string.IsNullOrEmpty(name) || name.Contains(".."))
return;
await FileAccess.CreateDirectory(name);
await ToastService.Success("Successfully created directory");
await View.Refresh();
}
private async Task CreateFile()
{
var name = await AlertService.Text("Enter a name for the new file");
if (string.IsNullOrEmpty(name) || name.Contains(".."))
return;
await FileAccess.CreateFile(name);
// We build a virtual entry here so we dont need to fetch one
await OpenEditor(new()
{
Name = name,
Size = 0,
IsFile = true,
IsDirectory = false,
LastModifiedAt = DateTime.UtcNow
});
}
#endregion
#region File Editor
private async Task OpenEditor(FileEntry entry)