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 // Register default file manager actions in plugin service
var pluginService = context.Application.Services.GetRequiredService<PluginService>(); var pluginService = context.Application.Services.GetRequiredService<PluginService>();
await pluginService.RegisterImplementation<IFileManagerAction>(new RenameAction()); await pluginService.RegisterImplementation<IFileManagerContextAction>(new RenameContextAction());
await pluginService.RegisterImplementation<IFileManagerAction>(new DownloadAction()); await pluginService.RegisterImplementation<IFileManagerContextAction>(new DownloadContextAction());
await pluginService.RegisterImplementation<IFileManagerAction>(new DeleteAction()); await pluginService.RegisterImplementation<IFileManagerContextAction>(new DeleteContextAction());
await pluginService.RegisterImplementation<IFileManagerSelectionAction>(new DeleteSelectionAction()); 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) 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; namespace Moonlight.Features.FileManager.Implementations;
public class DeleteAction : IFileManagerAction public class DeleteContextAction : IFileManagerContextAction
{ {
public string Name => "Delete"; public string Name => "Delete";
public string Icon => "bxs-trash"; public string Icon => "bxs-trash";

View File

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

View File

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

View File

@@ -3,7 +3,7 @@ using Moonlight.Features.FileManager.UI.NewFileManager;
namespace Moonlight.Features.FileManager.Interfaces; namespace Moonlight.Features.FileManager.Interfaces;
public interface IFileManagerAction public interface IFileManagerContextAction
{ {
public string Name { get; } public string Name { get; }
public string Icon { 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"> <a class="btn btn-primary dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
New New
</a> </a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink" style=""> <ul class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<li> @foreach (var action in CreateActions)
<a href="#" class="dropdown-item" @onclick:preventDefault @onclick="CreateFile"> {
<i class="bx bx-sm bx-file text-primary me-2 align-middle"></i> <li>
<span class="align-middle fs-6">File</span> <a href="#" class="dropdown-item" @onclick:preventDefault @onclick="() => InvokeCreateAction(action)">
</a> <i class="bx bx-sm @action.Icon text-@action.Color me-2 align-middle"></i>
</li> <span class="align-middle fs-6">@action.Name</span>
<li> </a>
<a href="#" class="dropdown-item" @onclick:preventDefault @onclick="CreateDirectory"> </li>
<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> </ul>
</div> </div>
} }
@@ -101,7 +98,7 @@ else
OnSelectionChanged="OnSelectionChanged" OnSelectionChanged="OnSelectionChanged"
EnableContextMenu="true"> EnableContextMenu="true">
<ContextMenuTemplate> <ContextMenuTemplate>
@foreach (var action in Actions) @foreach (var action in ContextActions)
{ {
if(!action.Filter.Invoke(context)) if(!action.Filter.Invoke(context))
continue; continue;
@@ -150,8 +147,9 @@ else
private FileView View; private FileView View;
private string Path = "/"; private string Path = "/";
private IFileManagerAction[] Actions; private IFileManagerContextAction[] ContextActions;
private IFileManagerSelectionAction[] SelectionActions; private IFileManagerSelectionAction[] SelectionActions;
private IFileManagerCreateAction[] CreateActions;
// Editor // Editor
private FileEditor Editor; private FileEditor Editor;
@@ -173,8 +171,9 @@ else
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
// Load plugin ui and options // Load plugin ui and options
Actions = await PluginService.GetImplementations<IFileManagerAction>(); ContextActions = await PluginService.GetImplementations<IFileManagerContextAction>();
SelectionActions = await PluginService.GetImplementations<IFileManagerSelectionAction>(); SelectionActions = await PluginService.GetImplementations<IFileManagerSelectionAction>();
CreateActions = await PluginService.GetImplementations<IFileManagerCreateAction>();
OnFolderClicked = async entry => 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 View.HideContextMenu();
await action.Execute(FileAccess, View, entry, ServiceProvider); await contextAction.Execute(FileAccess, View, entry, ServiceProvider);
} }
private async Task InvokeSelectionAction(IFileManagerSelectionAction action) private async Task InvokeSelectionAction(IFileManagerSelectionAction action)
@@ -255,6 +254,11 @@ else
// Refresh resets the selection // Refresh resets the selection
await View.Refresh(); await View.Refresh();
} }
private async Task InvokeCreateAction(IFileManagerCreateAction action)
{
await action.Execute(FileAccess, View, ServiceProvider);
}
private async Task OnSelectionChanged(FileEntry[] _) => await InvokeAsync(StateHasChanged); private async Task OnSelectionChanged(FileEntry[] _) => await InvokeAsync(StateHasChanged);
@@ -302,68 +306,7 @@ else
} }
#endregion #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 #region File Editor
private async Task OpenEditor(FileEntry entry) private async Task OpenEditor(FileEntry entry)