192 lines
No EOL
6 KiB
Text
192 lines
No EOL
6 KiB
Text
@page "/drive"
|
|
@page "/drive/{Id}"
|
|
@attribute [Authorize]
|
|
@using Iceshrimp.Frontend.Localization
|
|
@using Microsoft.AspNetCore.Components.Sections
|
|
@using Microsoft.Extensions.Localization
|
|
@using Iceshrimp.Assets.PhosphorIcons
|
|
@using Iceshrimp.Frontend.Core.Miscellaneous
|
|
@using Iceshrimp.Frontend.Core.Services
|
|
@using Iceshrimp.Shared.Schemas.Web
|
|
@using Microsoft.AspNetCore.Authorization
|
|
@using Iceshrimp.Frontend.Components
|
|
@inject ApiService Api;
|
|
@inject GlobalComponentSvc Global;
|
|
@inject IJSRuntime Js;
|
|
@inject IStringLocalizer<Localization> Loc;
|
|
@inject ILogger<DrivePage> Logger;
|
|
@inject NavigationManager Nav;
|
|
|
|
<HeadTitle Text="@Loc["Drive"]"/>
|
|
|
|
<SectionContent SectionName="top-bar">
|
|
@if (State == State.Loaded && Folder is { Id: not null, Name: not null })
|
|
{
|
|
<span class="btn" @onclick="NavigateToParent">
|
|
<Icon Name="Icons.ArrowLeft"/>
|
|
</span>
|
|
@Folder.Name
|
|
}
|
|
else
|
|
{
|
|
<Icon Name="Icons.Cloud"/>
|
|
@Loc["Drive"]
|
|
}
|
|
@if (State == State.Loaded && Folder is not null)
|
|
{
|
|
<span class="action btn" @onclick="CreateFolder" title="@Loc["Create folder"]">
|
|
<Icon Name="Icons.FolderPlus"/>
|
|
</span>
|
|
<span class="action btn" @onclick="OpenUpload" title="@Loc["Upload file"]">
|
|
<Icon Name="Icons.Upload"/>
|
|
</span>
|
|
@if (Folder is { Id: not null, Files: [], Folders: [] })
|
|
{
|
|
<span class="action btn" @onclick="DeleteFolder" title="@Loc["Delete folder"]">
|
|
<Icon Name="Icons.FolderMinus"/>
|
|
</span>
|
|
}
|
|
}
|
|
</SectionContent>
|
|
|
|
<div class="file-input">
|
|
<InputFile @ref="UploadInput" OnChange="Upload">Upload!</InputFile>
|
|
</div>
|
|
|
|
@if (State == State.Loaded && Folder != null)
|
|
{
|
|
<ol class="drive-files">
|
|
@foreach (var el in Folder.Folders)
|
|
{
|
|
<li>
|
|
<DriveEntry Folder="el" FolderList="@Folder.Folders" ParentId="@Id"/>
|
|
</li>
|
|
}
|
|
@foreach (var el in Folder.Files)
|
|
{
|
|
<li>
|
|
<DriveEntry File="el" FolderList="@Folder.Folders" ParentId="@Id"/>
|
|
</li>
|
|
}
|
|
</ol>
|
|
}
|
|
@if (State == State.Loading)
|
|
{
|
|
<div class="loading"><LoadingSpinner Scale="2"/></div>
|
|
}
|
|
@if (State == State.NotFound)
|
|
{
|
|
<div>This folder does not exist</div>
|
|
}
|
|
@if (State == State.Error)
|
|
{
|
|
<div>An error occured while loading the drive folder. Please inspect logs.</div>
|
|
}
|
|
|
|
@code {
|
|
[Parameter] public string? Id { get; set; }
|
|
private DriveFolderResponse? Folder { get; set; }
|
|
private State State { get; set; }
|
|
private InputFile UploadInput { get; set; } = null!;
|
|
private IJSObjectReference _module = null!;
|
|
|
|
private async Task Load()
|
|
{
|
|
Logger.LogTrace($"Opening drive folder: {Id ?? "root"}");
|
|
State = State.Loading;
|
|
|
|
try
|
|
{
|
|
Folder = await Api.Drive.GetFolderAsync(Id);
|
|
}
|
|
catch (ApiException e)
|
|
{
|
|
Logger.LogWarning($"Failed to load folder '{Id ?? "root"}' due to API Exception: {e.Message}");
|
|
State = State.Error;
|
|
return;
|
|
}
|
|
|
|
if (Folder == null)
|
|
{
|
|
State = State.NotFound;
|
|
return;
|
|
}
|
|
|
|
State = State.Loaded;
|
|
}
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
await Load();
|
|
_module = await Js.InvokeAsync<IJSObjectReference>("import",
|
|
"./Pages/DrivePage.razor.js");
|
|
}
|
|
|
|
protected override async Task OnParametersSetAsync()
|
|
{
|
|
await Load();
|
|
}
|
|
|
|
private void NavigateToParent()
|
|
{
|
|
Nav.NavigateTo(Folder?.ParentId != null ? $"/drive/{Folder.ParentId}" : "/drive");
|
|
}
|
|
|
|
private async Task CreateFolder() =>
|
|
await Global.PromptDialog?.Prompt(new EventCallback<string?>(this, CreateFolderCallback), Loc["Create folder"], Loc["Folder name"], null, buttonText: Loc["Create"])!;
|
|
|
|
private async Task CreateFolderCallback(string? name)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(name)) return;
|
|
|
|
try
|
|
{
|
|
var res = await Api.Drive.CreateFolderAsync(new DriveFolderRequest { Name = name, ParentId = Folder!.Id });
|
|
if (res != null)
|
|
{
|
|
Folder.Folders.Add(res);
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
catch (ApiException e)
|
|
{
|
|
await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
|
|
}
|
|
}
|
|
|
|
// The <InputFile> Component is hidden, and triggered by a sepperate button.
|
|
// That way we get it's functionality, without the styling limitations of the InputFile component
|
|
private async Task OpenUpload()
|
|
{
|
|
await _module.InvokeVoidAsync("openUpload", UploadInput.Element);
|
|
}
|
|
|
|
private async Task Upload(InputFileChangeEventArgs e)
|
|
{
|
|
var res = Folder?.Id != null ? await Api.Drive.UploadFileToFolderAsync(e.File, Folder.Id) : await Api.Drive.UploadFileAsync(e.File);
|
|
Folder!.Files.Insert(0, res);
|
|
StateHasChanged();
|
|
}
|
|
|
|
private async Task DeleteFolder()
|
|
{
|
|
if (Folder is not { Id: not null, Files: [], Folders: [] }) return;
|
|
await Global.ConfirmDialog?.Confirm(new EventCallback<bool>(this, DeleteFolderCallback), Loc["Delete {0}?", Folder.Name ?? ""], Icons.Trash, Loc["Delete"])!;
|
|
}
|
|
|
|
private async Task DeleteFolderCallback(bool delete)
|
|
{
|
|
if (Folder is not { Id: not null, Files: [], Folders: [] }) return;
|
|
if (!delete) return;
|
|
|
|
try
|
|
{
|
|
await Api.Drive.DeleteFolderAsync(Folder.Id);
|
|
NavigateToParent();
|
|
}
|
|
catch (ApiException e)
|
|
{
|
|
await Global.NoticeDialog?.Display(e.Response.Message ?? Loc["An unknown error occurred"], NoticeDialog.NoticeType.Error)!;
|
|
}
|
|
}
|
|
} |