Iceshrimp.NET/Iceshrimp.Frontend/Components/DriveEntry.razor

311 lines
No EOL
12 KiB
Text

@using Iceshrimp.Frontend.Localization
@using Iceshrimp.Shared.Schemas.Web
@using Microsoft.Extensions.Localization
@using Iceshrimp.Assets.PhosphorIcons
@using Iceshrimp.Frontend.Core.Miscellaneous
@using Iceshrimp.Frontend.Core.Services
@inject ApiService Api;
@inject GlobalComponentSvc Global;
@inject IJSRuntime Js;
@inject IStringLocalizer<Localization> Loc;
@inject NavigationManager Nav;
@if (File != null && Folder == null)
{
<div @ref="FileButton" class="drive-entry" @onclick="SelectFile" @onclick:stopPropagation="true">
<div class="labels">
@if (File.IsAvatar)
{
<Icon Name="Icons.UserCircle" title="@Loc["Avatar"]"/>
}
@if (File.IsBanner)
{
<Icon Name="Icons.Image" title="@Loc["Banner"]"/>
}
@if (File.Description != null)
{
<Icon Name="Icons.ClosedCaptioning" title="@File.Description"/>
}
else
{
<Icon Name="Icons.Warning" title="@Loc["No alt text"]"/>
}
@if (File.Sensitive)
{
<Icon Name="Icons.EyeSlash" title="@Loc["Sensitive"]"/>
}
</div>
@if (File.ContentType.StartsWith("image") || Constants.CommonImageExtensions.Any(e => File.Filename.EndsWith(e)))
{
<img class="thumbnail" src="@File.ThumbnailUrl" alt="@File.Description"/>
}
else if (File.ContentType.StartsWith("audio") || Constants.CommonAudioExtensions.Any(e => File.Filename.EndsWith(e)))
{
<span class="icon">
<Icon Name="Icons.FileAudio" Size="5em"/>
</span>
}
else if (File.ContentType.StartsWith("video") || Constants.CommonVideoExtensions.Any(e => File.Filename.EndsWith(e)))
{
<span class="icon">
<Icon Name="Icons.FileVideo" Size="5em"/>
</span>
}
else
{
<span class="icon">
<Icon Name="Icons.File" Size="5em"/>
</span>
}
<span>@File.Filename</span>
<Menu @ref="FileMenu">
<MenuElement Icon="Icons.ArrowSquareOut" OnSelect="OpenFile">
<Text>@Loc["Open"]</Text>
</MenuElement>
<MenuElement Icon="Icons.Share" OnSelect="CopyFileLink">
<Text>@Loc["Copy link"]</Text>
</MenuElement>
<hr class="rule"/>
<MenuElement Icon="Icons.CursorText" OnSelect="RenameFile">
<Text>@Loc["Rename"]</Text>
</MenuElement>
@if (File.Sensitive)
{
<MenuElement Icon="Icons.Eye" OnSelect="MarkFileNotSensitive">
<Text>@Loc["Mark as not sensitive"]</Text>
</MenuElement>
}
else
{
<MenuElement Icon="Icons.EyeSlash" OnSelect="MarkFileAsSensitive">
<Text>@Loc["Mark as sensitive"]</Text>
</MenuElement>
}
<MenuElement Icon="Icons.ClosedCaptioning" OnSelect="SetFileAltText">
<Text>@Loc["Set alt text"]</Text>
</MenuElement>
<hr class="rule"/>
@if (ParentId != null || FolderList.Count != 0)
{
<MenuElement Icon="Icons.FolderDashed" OnSelect="MoveFile">
<Text>@Loc["Move"]</Text>
</MenuElement>
}
<MenuElement Icon="Icons.Trash" OnSelect="DeleteFile" Danger>
<Text>@Loc["Delete"]</Text>
</MenuElement>
<ClosingBackdrop OnClose="FileMenu.Close"></ClosingBackdrop>
</Menu>
</div>
}
@if (Folder != null && File == null)
{
<div @ref="FolderButton" class="drive-entry" @onclick="SelectFolder" @onclick:stopPropagation="true">
<span class="icon">
<Icon Name="Icons.FolderOpen" Size="5em" Pack="IconStyle.Fill"/>
</span>
<span>@Folder.Name</span>
<Menu @ref="FolderMenu">
<MenuElement Icon="Icons.FolderOpen" OnSelect="OpenFolder">
<Text>@Loc["Open"]</Text>
</MenuElement>
<hr class="rule"/>
<MenuElement Icon="Icons.CursorText" OnSelect="RenameFolder">
<Text>@Loc["Rename"]</Text>
</MenuElement>
@if (ParentId != null || FolderList.Count > 1)
{
<hr class="rule"/>
<MenuElement Icon="Icons.FolderDashed" OnSelect="MoveFolder">
<Text>@Loc["Move"]</Text>
</MenuElement>
}
<ClosingBackdrop OnClose="FolderMenu.Close"></ClosingBackdrop>
</Menu>
</div>
}
@code {
[Parameter] public DriveFileResponse? File { get; set; } = null;
[Parameter] public DriveFolderResponse? Folder { get; set; } = null;
private Menu FileMenu { get; set; } = null!;
private Menu FolderMenu { get; set; } = null!;
private ElementReference FileButton { get; set; }
private ElementReference FolderButton { get; set; }
[Parameter, EditorRequired] public required string? ParentId { get; set; }
[Parameter, EditorRequired] public required List<DriveFolderResponse> FolderList { get; set; }
private void SelectFile() => FileMenu.Toggle(FileButton);
private async Task RenameFile() =>
await Global.PromptDialog?.Prompt(new EventCallback<string?>(this, RenameFileCallback), Loc["Rename file"], Loc["File name"], File!.Filename, buttonText: Loc["Rename"])!;
private async Task RenameFileCallback(string? filename)
{
if (string.IsNullOrWhiteSpace(filename)) return;
try
{
var res = await Api.Drive.UpdateFileAsync(File!.Id, new UpdateDriveFileRequest { Filename = filename });
if (res != null)
{
File.Filename = res.Filename;
StateHasChanged();
}
}
catch (ApiException e)
{
await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
}
}
private async Task MarkFileSensitive(bool sensitive)
{
try
{
var res = await Api.Drive.UpdateFileAsync(File!.Id, new UpdateDriveFileRequest { Sensitive = sensitive });
if (res != null)
{
File.Sensitive = res.Sensitive;
StateHasChanged();
}
}
catch (ApiException e)
{
await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
}
}
private async Task MarkFileNotSensitive() => await MarkFileSensitive(false);
private async Task MarkFileAsSensitive() => await MarkFileSensitive(true);
private async Task SetFileAltText() =>
await Global.PromptDialog?.Prompt(new EventCallback<string?>(this, SetFileAltTextCallback), Loc["Set alt text"], "", File!.Description ?? "", true, true)!;
private async Task SetFileAltTextCallback(string? alt)
{
if (alt == null) return;
try
{
var res = await Api.Drive.UpdateFileAsync(File!.Id, new UpdateDriveFileRequest { Description = string.IsNullOrWhiteSpace(alt) ? null : alt });
if (res != null)
{
File.Description = res.Description;
StateHasChanged();
}
}
catch (ApiException e)
{
await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
}
}
private async Task MoveFile()
{
var folders = FolderList.Select(f => (f.Name ?? "/", (object)(f.Id ?? ""))).OrderBy(f => f.Item1).ToList();
if (ParentId != null) folders.Insert(0, ("/", ""));
await Global.SelectDialog?.Select(new EventCallback<object?>(this, MoveFileCallback), Loc["Move to folder"], folders)!;
}
private async Task MoveFileCallback(object? folderId)
{
if (folderId is not string id) return;
try
{
var res = await Api.Drive.UpdateFileParentAsync(File!.Id, string.IsNullOrWhiteSpace(id) ? null : id);
if (res != null)
{
File = null;
StateHasChanged();
}
}
catch (ApiException e)
{
await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
}
}
private void OpenFile() => Js.InvokeVoidAsync("open", File!.Url, "_blank");
private void CopyFileLink() => Js.InvokeVoidAsync("navigator.clipboard.writeText", File!.Url);
private async Task DeleteFile() =>
await Global.ConfirmDialog?.Confirm(new EventCallback<bool>(this, DeleteFileCallback), Loc["Delete {0}?", File!.Filename], Icons.Trash, Loc["Delete"])!;
private async Task DeleteFileCallback(bool delete)
{
if (!delete) return;
try
{
await Api.Drive.DeleteFileAsync(File!.Id);
File = null;
StateHasChanged();
}
catch (ApiException e)
{
await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
}
}
private void SelectFolder() => FolderMenu.Toggle(FolderButton);
private async Task RenameFolder()
{
if (Folder is not { Id: not null, Name: not null }) return;
await Global.PromptDialog?.Prompt(new EventCallback<string?>(this, RenameFolderCallback), Loc["Rename folder"], Loc["Folder name"], Folder!.Name, buttonText: Loc["Rename"])!;
}
private async Task RenameFolderCallback(string? name)
{
if (Folder is not { Id: not null, Name: not null }) return;
if (string.IsNullOrWhiteSpace(name)) return;
try
{
var res = await Api.Drive.UpdateFolderAsync(Folder.Id, name);
if (res != null)
{
Folder.Name = res.Name;
StateHasChanged();
}
}
catch (ApiException e)
{
await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
}
}
private async Task MoveFolder()
{
var folders = FolderList.Where(f => f.Id != Folder!.Id).Select(f => (f.Name ?? "/", (object)(f.Id ?? ""))).OrderBy(f => f.Item1).ToList();
if (ParentId != null) folders.Insert(0, ("/", ""));
await Global.SelectDialog?.Select(new EventCallback<object?>(this, MoveFolderCallback), Loc["Move to folder"], folders)!;
}
private async Task MoveFolderCallback(object? folderId)
{
if (Folder is not { Id: not null, Name: not null }) return;
if (folderId is not string id) return;
try
{
var res = await Api.Drive.UpdateFolderParentAsync(Folder.Id, string.IsNullOrWhiteSpace(id) ? null : id);
if (res != null)
{
Folder = null;
StateHasChanged();
}
}
catch (ApiException e)
{
await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
}
}
private void OpenFolder() => Nav.NavigateTo($"/drive/{Folder!.Id}");
}