From 0951728f0aebcced46896ecd9110da02b020250d Mon Sep 17 00:00:00 2001 From: pancakes Date: Tue, 28 Jan 2025 01:02:12 +1000 Subject: [PATCH] [frontend/components] Add menu and actions to emoji management entries --- .../Components/EmojiManagementEntry.razor | 149 +++++++++++++++++- .../ControllerModels/EmojiControllerModel.cs | 10 +- .../Pages/Moderation/CustomEmojis.razor | 2 +- 3 files changed, 155 insertions(+), 6 deletions(-) diff --git a/Iceshrimp.Frontend/Components/EmojiManagementEntry.razor b/Iceshrimp.Frontend/Components/EmojiManagementEntry.razor index 6c208b99..606bc5bd 100644 --- a/Iceshrimp.Frontend/Components/EmojiManagementEntry.razor +++ b/Iceshrimp.Frontend/Components/EmojiManagementEntry.razor @@ -2,9 +2,13 @@ @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 IJSRuntime Js; @inject IStringLocalizer Loc; -
+
@Emoji.Name @@ -29,9 +33,148 @@ }
+ + @if (Source == "remote") + { + + @Loc["Clone"] + + } + else + { + + @Loc["Rename"] + + @if (Emoji.Sensitive) + { + + @Loc["Mark as not sensitive"] + + } + else + { + + @Loc["Mark as sensitive"] + + } + + @Loc["Set aliases"] + + + @Loc["Set category"] + + + @Loc["Set license"] + + + @Loc["Delete"] + + } + +
@code { - [Parameter, EditorRequired] public required EmojiResponse Emoji { get; set; } - [Parameter, EditorRequired] public required string Source { get; set; } + [Parameter, EditorRequired] public required EmojiResponse Emoji { get; set; } + [Parameter, EditorRequired] public required string Source { get; set; } + [Parameter, EditorRequired] public required EventCallback GetEmojis { get; set; } + private ElementReference EmojiButton { get; set; } + private Menu EmojiMenu { get; set; } = null!; + + private void SelectEmoji() => EmojiMenu.Toggle(EmojiButton); + + private async Task Clone() + { + if (Source == "local" || Emoji.Category == null) return; + + try + { + // Remote emojis endpoint sets EmojiResponse.Category to the emoji's host + var res = await Api.Emoji.CloneEmojiAsync(Emoji.Name, Emoji.Category); + if (res != null) await Js.InvokeVoidAsync("alert", $"Cloned {Emoji.Name}"); + } + catch (ApiException e) + { + await Js.InvokeVoidAsync("alert", e.Response.Message); + } + } + + private async Task Rename() + { + var name = await Js.InvokeAsync("prompt", "Rename emoji", Emoji.Name); + if (string.IsNullOrWhiteSpace(name)) return; + + try + { + var res = await Api.Emoji.UpdateEmojiAsync(Emoji.Id, new UpdateEmojiRequest { Name = name.Trim() }); + if (res != null) + { + Emoji.Name = res.Name; + StateHasChanged(); + } + } + catch (ApiException e) + { + await Js.InvokeVoidAsync("alert", e.Response.Message); + } + } + + private async Task MarkSensitive(bool sensitive) + { + var res = await Api.Emoji.UpdateEmojiAsync(Emoji.Id, new UpdateEmojiRequest { Sensitive = sensitive }); + if (res != null) + { + Emoji.Sensitive = res.Sensitive; + StateHasChanged(); + } + } + + private async Task MarkNotSensitive() => await MarkSensitive(false); + + private async Task MarkAsSensitive() => await MarkSensitive(true); + + private async Task SetAliases() + { + var aliases = await Js.InvokeAsync("prompt", "Set aliases (separated by comma , )", Emoji.License ?? ""); + if (aliases == null) return; + + var res = await Api.Emoji.UpdateEmojiAsync(Emoji.Id, new UpdateEmojiRequest { Aliases = string.IsNullOrWhiteSpace(aliases) ? null : aliases.Replace(" ", "").Split(",").ToList() }); + if (res != null) + { + Emoji.Aliases = res.Aliases; + StateHasChanged(); + } + } + + private async Task SetCategory() + { + var category = await Js.InvokeAsync("prompt", "Set category", Emoji.Category ?? ""); + if (category == null) return; + + var res = await Api.Emoji.UpdateEmojiAsync(Emoji.Id, new UpdateEmojiRequest { Category = category.Trim() }); + if (res != null) + { + Emoji.Category = res.Category; + await GetEmojis.InvokeAsync(); + } + } + + private async Task SetLicense() + { + var license = await Js.InvokeAsync("prompt", "Set license", Emoji.License ?? ""); + if (license == null) return; + + var res = await Api.Emoji.UpdateEmojiAsync(Emoji.Id, new UpdateEmojiRequest { License = string.IsNullOrWhiteSpace(license) ? null : license.Trim() }); + if (res != null) + { + Emoji.License = res.License; + StateHasChanged(); + } + } + + private async Task Delete() + { + var res = await Api.Emoji.DeleteEmojiAsync(Emoji.Id); + if (res) await GetEmojis.InvokeAsync(); + } } \ No newline at end of file diff --git a/Iceshrimp.Frontend/Core/ControllerModels/EmojiControllerModel.cs b/Iceshrimp.Frontend/Core/ControllerModels/EmojiControllerModel.cs index 0916dbd5..d3975c54 100644 --- a/Iceshrimp.Frontend/Core/ControllerModels/EmojiControllerModel.cs +++ b/Iceshrimp.Frontend/Core/ControllerModels/EmojiControllerModel.cs @@ -15,8 +15,14 @@ internal class EmojiControllerModel(ApiClient api) public Task UploadEmojiAsync(IBrowserFile file) => api.CallAsync(HttpMethod.Post, "/emoji", data: file); - public Task UpdateEmojiAsync(string id, EmojiResponse emoji) => - api.CallNullableAsync(HttpMethod.Patch, $"/emoji/{id}", data: emoji); + public Task CloneEmojiAsync(string name, string host) => + api.CallNullableAsync(HttpMethod.Post, $"/emoji/clone/{name}@{host}"); + + public Task UpdateEmojiAsync(string id, UpdateEmojiRequest request) => + api.CallNullableAsync(HttpMethod.Patch, $"/emoji/{id}", data: request); + + public Task DeleteEmojiAsync(string id) => + api.CallNullableAsync(HttpMethod.Delete, $"/emoji/{id}"); public Task GetEmojiAsync(string id) => api.CallNullableAsync(HttpMethod.Get, $"/emoji/{id}"); diff --git a/Iceshrimp.Frontend/Pages/Moderation/CustomEmojis.razor b/Iceshrimp.Frontend/Pages/Moderation/CustomEmojis.razor index 5b8c99dc..ac486533 100644 --- a/Iceshrimp.Frontend/Pages/Moderation/CustomEmojis.razor +++ b/Iceshrimp.Frontend/Pages/Moderation/CustomEmojis.razor @@ -38,7 +38,7 @@
@foreach (var emoji in category.Value) { - + }
}