[frontend/components] Add move folder/file button

This commit is contained in:
pancakes 2024-12-23 01:12:48 +10:00 committed by Laura Hausmann
parent d6329b7783
commit 637e17be14
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
4 changed files with 63 additions and 5 deletions

View file

@ -76,6 +76,9 @@
<MenuElement Icon="Icons.ClosedCaptioning" OnSelect="SetFileAltText"> <MenuElement Icon="Icons.ClosedCaptioning" OnSelect="SetFileAltText">
<Text>@Loc["Set alt text"]</Text> <Text>@Loc["Set alt text"]</Text>
</MenuElement> </MenuElement>
<MenuElement Icon="Icons.FolderDashed" OnSelect="MoveFile">
<Text>@Loc["Move"]</Text>
</MenuElement>
<MenuElement Icon="Icons.Trash" OnSelect="DeleteFile"> <MenuElement Icon="Icons.Trash" OnSelect="DeleteFile">
<Text>@Loc["Delete"]</Text> <Text>@Loc["Delete"]</Text>
</MenuElement> </MenuElement>
@ -95,6 +98,9 @@
<MenuElement Icon="Icons.CursorText" OnSelect="RenameFolder"> <MenuElement Icon="Icons.CursorText" OnSelect="RenameFolder">
<Text>@Loc["Rename"]</Text> <Text>@Loc["Rename"]</Text>
</MenuElement> </MenuElement>
<MenuElement Icon="Icons.FolderDashed" OnSelect="MoveFolder">
<Text>@Loc["Move"]</Text>
</MenuElement>
<ClosingBackdrop OnClose="FolderMenu.Close"></ClosingBackdrop> <ClosingBackdrop OnClose="FolderMenu.Close"></ClosingBackdrop>
</Menu> </Menu>
</div> </div>
@ -108,6 +114,8 @@
private ElementReference FileButton { get; set; } private ElementReference FileButton { get; set; }
private ElementReference FolderButton { get; set; } private ElementReference FolderButton { get; set; }
[Parameter, EditorRequired] public required List<DriveFolderResponse> FolderList { get; set; }
private void SelectFile() => FileMenu.Toggle(FileButton); private void SelectFile() => FileMenu.Toggle(FileButton);
private async Task RenameFile() private async Task RenameFile()
@ -157,6 +165,27 @@
} }
} }
private async Task MoveFile()
{
// TODO: Move this to a proper prompt dialog once we have that
var folderId = await Js.InvokeAsync<string?>("prompt", "Move to folder by ID: " + string.Join(", ", FolderList.Select(p => $"{p.Name} ({p.Id})")) + " or blank for root");
if (folderId == null) return;
try
{
var res = await Api.Drive.UpdateFileParentAsync(File!.Id, string.IsNullOrWhiteSpace(folderId) ? null : folderId.Trim());
if (res != null)
{
File = null;
StateHasChanged();
}
}
catch (ApiException e)
{
await Js.InvokeVoidAsync("alert", e.Response.Message);
}
}
private void OpenFile() => Js.InvokeVoidAsync("open", File!.Url, "_blank"); private void OpenFile() => Js.InvokeVoidAsync("open", File!.Url, "_blank");
private void CopyFileLink() => Js.InvokeVoidAsync("navigator.clipboard.writeText", File!.Url); private void CopyFileLink() => Js.InvokeVoidAsync("navigator.clipboard.writeText", File!.Url);
@ -192,5 +221,28 @@
} }
} }
private async Task MoveFolder()
{
if (Folder is not { Id: not null, Name: not null }) return;
// TODO: Move this to a proper prompt dialog once we have that
var folderId = await Js.InvokeAsync<string?>("prompt", "Move to folder by ID: " + string.Join(", ", FolderList.FindAll(p => p.Id != Folder.Id).Select(p => $"{p.Name} ({p.Id})")) + " or blank for root");
if (folderId == null) return;
try
{
var res = await Api.Drive.UpdateFolderParentAsync(Folder.Id, string.IsNullOrWhiteSpace(folderId) ? null : folderId.Trim());
if (res != null)
{
Folder = null;
StateHasChanged();
}
}
catch (ApiException e)
{
await Js.InvokeVoidAsync("alert", e.Response.Message);
}
}
private void OpenFolder() => Nav.NavigateTo($"/drive/{Folder!.Id}"); private void OpenFolder() => Nav.NavigateTo($"/drive/{Folder!.Id}");
} }

View file

@ -22,6 +22,9 @@ internal class DriveControllerModel(ApiClient api)
public Task DeleteFileAsync(string id) => public Task DeleteFileAsync(string id) =>
api.CallNullableAsync(HttpMethod.Delete, $"/drive/{id}"); api.CallNullableAsync(HttpMethod.Delete, $"/drive/{id}");
public Task<DriveFileResponse?> UpdateFileParentAsync(string id, string? folderId) =>
api.CallNullableAsync<DriveFileResponse>(HttpMethod.Post, $"/drive/{id}/move", data: new DriveMoveRequest { FolderId = folderId });
public Task<DriveFolderResponse?> CreateFolderAsync(DriveFolderRequest request) => public Task<DriveFolderResponse?> CreateFolderAsync(DriveFolderRequest request) =>
api.CallNullableAsync<DriveFolderResponse>(HttpMethod.Post, $"/drive/folder", data: request); api.CallNullableAsync<DriveFolderResponse>(HttpMethod.Post, $"/drive/folder", data: request);
@ -33,4 +36,7 @@ internal class DriveControllerModel(ApiClient api)
public Task DeleteFolderAsync(string id) => public Task DeleteFolderAsync(string id) =>
api.CallNullableAsync(HttpMethod.Delete, $"/drive/folder/{id}"); api.CallNullableAsync(HttpMethod.Delete, $"/drive/folder/{id}");
public Task<DriveFolderResponse?> UpdateFolderParentAsync(string id, string? folderId) =>
api.CallNullableAsync<DriveFolderResponse>(HttpMethod.Post, $"/drive/folder/{id}/move", data: new DriveMoveRequest { FolderId = folderId });
} }

View file

@ -56,13 +56,13 @@
@foreach (var el in Folder.Folders) @foreach (var el in Folder.Folders)
{ {
<li> <li>
<DriveEntry Folder="el" /> <DriveEntry Folder="el" FolderList="@Folder.Folders"/>
</li> </li>
} }
@foreach (var el in Folder.Files) @foreach (var el in Folder.Files)
{ {
<li> <li>
<DriveEntry File="el"/> <DriveEntry File="el" FolderList="@Folder.Folders"/>
</li> </li>
} }
</ol> </ol>

View file

@ -1,6 +1,6 @@
namespace Iceshrimp.Shared.Schemas.Web; namespace Iceshrimp.Shared.Schemas.Web;
public class DriveMoveRequest(string? folderId) public class DriveMoveRequest
{ {
public required string? FolderId { get; set; } = folderId; public required string? FolderId { get; set; }
} }