[frontend] Add emoji picker and add it to Note
This commit is contained in:
parent
c9b282a90e
commit
da124c5c98
5 changed files with 124 additions and 20 deletions
38
Iceshrimp.Frontend/Components/EmojiPicker.razor
Normal file
38
Iceshrimp.Frontend/Components/EmojiPicker.razor
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
@using Iceshrimp.Frontend.Core.Services
|
||||||
|
@using Iceshrimp.Shared.Schemas
|
||||||
|
@inject ApiService Api
|
||||||
|
|
||||||
|
@if (_display){
|
||||||
|
<div class="emoji-picker">
|
||||||
|
@foreach (var el in EmojiList)
|
||||||
|
{
|
||||||
|
<div class="emoji">
|
||||||
|
<img @onclick="() => Select(el)" src="@el.PublicUrl" alt="@el.Name"/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] [EditorRequired] public required EventCallback<EmojiResponse> OnEmojiSelect { get; set; }
|
||||||
|
private List<EmojiResponse> EmojiList { get; set; } = [];
|
||||||
|
private bool _display = false;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
EmojiList = await Api.Emoji.GetAllEmoji();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Select(EmojiResponse emoji)
|
||||||
|
{
|
||||||
|
await OnEmojiSelect.InvokeAsync(emoji);
|
||||||
|
_display = false;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Toggle()
|
||||||
|
{
|
||||||
|
_display = !_display;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
Iceshrimp.Frontend/Components/EmojiPicker.razor.css
Normal file
23
Iceshrimp.Frontend/Components/EmojiPicker.razor.css
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
.emoji-picker {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(2.5rem, 1fr));
|
||||||
|
grid-template-rows: repeat(auto-fill, minmax(2.5rem, 1fr));
|
||||||
|
position: absolute;
|
||||||
|
background-color: var(--foreground-color);
|
||||||
|
border: var(--highlight-color) solid 0.1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
min-width: 15rem;
|
||||||
|
min-height: 10rem;
|
||||||
|
top: 3rem;
|
||||||
|
left: -210%;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji {
|
||||||
|
> img {
|
||||||
|
object-fit: cover;
|
||||||
|
height: 2rem;
|
||||||
|
width: 2rem;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
@using Iceshrimp.Shared.Schemas
|
@using Iceshrimp.Shared.Schemas
|
||||||
@inject ApiService ApiService;
|
@inject ApiService ApiService;
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject ComposeService ComposeService
|
@inject ComposeService ComposeService
|
||||||
<CascadingValue Value="this">
|
<CascadingValue Value="this">
|
||||||
<div class="note-header">
|
<div class="note-header">
|
||||||
<NoteUserInfo
|
<NoteUserInfo
|
||||||
|
@ -11,12 +11,12 @@
|
||||||
DisplayName="@Note.User.DisplayName"
|
DisplayName="@Note.User.DisplayName"
|
||||||
Username="@Note.User.Username"
|
Username="@Note.User.Username"
|
||||||
Host="@Note.User.Host"
|
Host="@Note.User.Host"
|
||||||
Indented="Indented"
|
Indented="Indented"/>
|
||||||
/>
|
|
||||||
<NoteMetadata
|
<NoteMetadata
|
||||||
Visibility="@Note.Visibility"
|
Visibility="@Note.Visibility"
|
||||||
InstanceName="@Note.User.InstanceName"
|
InstanceName="@Note.User.InstanceName"
|
||||||
CreatedAt="DateTime.Parse(Note.CreatedAt)"></NoteMetadata>
|
CreatedAt="DateTime.Parse(Note.CreatedAt)">
|
||||||
|
</NoteMetadata>
|
||||||
</div>
|
</div>
|
||||||
<NoteBody NoteBase="Note" OverLength="@CheckLen()" Indented="Indented"/>
|
<NoteBody NoteBase="Note" OverLength="@CheckLen()" Indented="Indented"/>
|
||||||
@if (Quote != null)
|
@if (Quote != null)
|
||||||
|
@ -33,15 +33,16 @@
|
||||||
Likes="Note.Likes"
|
Likes="Note.Likes"
|
||||||
IsLiked="Note.Liked"
|
IsLiked="Note.Liked"
|
||||||
Renotes="Note.Renotes"
|
Renotes="Note.Renotes"
|
||||||
RenotePossible="@(Note.Visibility == NoteVisibility.Public || Note.Visibility == NoteVisibility.Home)"
|
RenotePossible="@(Note.Visibility == NoteVisibility.Public || Note.Visibility == NoteVisibility.Home)"/>
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter][EditorRequired] public required NoteBase Note { get; set; }
|
[Parameter] [EditorRequired] public required NoteBase Note { get; set; }
|
||||||
[Parameter] public bool Indented { get; set; }
|
[Parameter] public bool Indented { get; set; }
|
||||||
[Parameter] public NoteBase? Quote { get; set; }
|
[Parameter] public NoteBase? Quote { get; set; }
|
||||||
[Parameter] public bool AsQuote { get; set; }
|
[Parameter] public bool AsQuote { get; set; }
|
||||||
|
|
||||||
private bool CheckLen()
|
private bool CheckLen()
|
||||||
{
|
{
|
||||||
return Note.Text?.Length > 500;
|
return Note.Text?.Length > 500;
|
||||||
|
@ -52,14 +53,36 @@
|
||||||
NavigationManager.NavigateTo($"/notes/{Quote!.Id}");
|
NavigationManager.NavigateTo($"/notes/{Quote!.Id}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void React(string name, bool target)
|
//FIXME: This needs to be rewritten.
|
||||||
|
public void React(string name, bool target, string? url = null)
|
||||||
{
|
{
|
||||||
var index = Note.Reactions.FindIndex(x => x.Name == name);
|
var index = Note.Reactions.FindIndex(x => x.Name == name);
|
||||||
switch (target)
|
switch (target)
|
||||||
{
|
{
|
||||||
case true:
|
case true:
|
||||||
ApiService.Notes.ReactToNote(Note.Id, name);
|
ApiService.Notes.ReactToNote(Note.Id, name);
|
||||||
Note.Reactions[index].Count++;
|
if (index == -1 && url != null)
|
||||||
|
{
|
||||||
|
Note.Reactions.Add(new NoteReactionSchema
|
||||||
|
{
|
||||||
|
NoteId = Note.Id,
|
||||||
|
Name = name,
|
||||||
|
Count = 1,
|
||||||
|
Reacted = true,
|
||||||
|
Url = url
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Note.Reactions[index].Reacted != true)
|
||||||
|
{
|
||||||
|
Note.Reactions[index].Count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
break;
|
break;
|
||||||
case false:
|
case false:
|
||||||
|
@ -72,6 +95,7 @@
|
||||||
{
|
{
|
||||||
Note.Reactions[index].Count--;
|
Note.Reactions[index].Count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -111,4 +135,5 @@
|
||||||
{
|
{
|
||||||
ComposeService.ComposeDialog?.OpenDialog(null, Note);
|
ComposeService.ComposeDialog?.OpenDialog(null, Note);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
@using Iceshrimp.Assets.PhosphorIcons
|
@using Iceshrimp.Assets.PhosphorIcons
|
||||||
|
@using Iceshrimp.Frontend.Core.Services
|
||||||
@using Iceshrimp.Shared.Schemas
|
@using Iceshrimp.Shared.Schemas
|
||||||
<div class="note-footer">
|
<div class="note-footer">
|
||||||
@if (Reactions.Count > 0)
|
@if (Reactions.Count > 0)
|
||||||
|
@ -41,8 +42,9 @@
|
||||||
<span class="like-count">@Likes</span>
|
<span class="like-count">@Likes</span>
|
||||||
}
|
}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn" @onclick:stopPropagation="true">
|
<button class="btn positioned" @onclick="ToggleEmojiPicker" @onclick:stopPropagation="true">
|
||||||
<Icon Name="Icons.Smiley" Size="1.3em"/>
|
<Icon Name="Icons.Smiley" Size="1.3em"/>
|
||||||
|
<EmojiPicker @ref="EmojiPicker" OnEmojiSelect="React" />
|
||||||
</button>
|
</button>
|
||||||
<button class="btn" @onclick="Quote" @onclick:stopPropagation="true">
|
<button class="btn" @onclick="Quote" @onclick:stopPropagation="true">
|
||||||
<Icon Name="Icons.Quotes" Size="1.3em"/>
|
<Icon Name="Icons.Quotes" Size="1.3em"/>
|
||||||
|
@ -58,6 +60,7 @@
|
||||||
[Parameter] [EditorRequired] public required bool IsLiked { get; set; }
|
[Parameter] [EditorRequired] public required bool IsLiked { get; set; }
|
||||||
[Parameter] [EditorRequired] public required int Renotes { get; set; }
|
[Parameter] [EditorRequired] public required int Renotes { get; set; }
|
||||||
[Parameter] public bool RenotePossible { get; set; }
|
[Parameter] public bool RenotePossible { get; set; }
|
||||||
|
private EmojiPicker EmojiPicker { get; set; }
|
||||||
|
|
||||||
[CascadingParameter] NoteComponent NoteComponent { get; set; } = null!;
|
[CascadingParameter] NoteComponent NoteComponent { get; set; } = null!;
|
||||||
|
|
||||||
|
@ -81,4 +84,14 @@
|
||||||
NoteComponent.DoQuote();
|
NoteComponent.DoQuote();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ToggleEmojiPicker()
|
||||||
|
{
|
||||||
|
EmojiPicker.Toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void React(EmojiResponse emoji)
|
||||||
|
{
|
||||||
|
NoteComponent.React(emoji.Name, true, url: emoji.PublicUrl);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -17,3 +17,8 @@
|
||||||
.renote-count {
|
.renote-count {
|
||||||
margin-left: 0.3em;
|
margin-left: 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.positioned {
|
||||||
|
position: relative;
|
||||||
|
top: 0;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue