From f5f43d626466bab314cb4e9687740e80958e466d Mon Sep 17 00:00:00 2001 From: Lilian Date: Tue, 9 Jul 2024 00:05:00 +0200 Subject: [PATCH] [frontend] Wire up message service, refactor note rendering --- .../Components/Note/NoteFooter.razor | 10 +-- .../Components/Note/NoteReaction.razor | 3 +- .../Components/TimelineComponent.razor.cs | 78 ++++++++++--------- .../StateServicePatterns/TimelineState.cs | 48 ++++++++++-- 4 files changed, 89 insertions(+), 50 deletions(-) diff --git a/Iceshrimp.Frontend/Components/Note/NoteFooter.razor b/Iceshrimp.Frontend/Components/Note/NoteFooter.razor index 91f1b1d5..7b0facb0 100644 --- a/Iceshrimp.Frontend/Components/Note/NoteFooter.razor +++ b/Iceshrimp.Frontend/Components/Note/NoteFooter.razor @@ -87,13 +87,13 @@ private void ToggleMenu() => Menu.Toggle(); - private void Delete() => Note.Delete(); + private void Delete() => _ = Note.Delete(); private void OpenOriginal() => Js.InvokeVoidAsync("open", Note.NoteResponse.Url, "_blank"); private void Like() - { - Note.Like(); + { + _ = Note.ToggleLike(); } private void Reply() @@ -103,7 +103,7 @@ private void Renote() { - if (RenotePossible) Note.Renote(); + if (RenotePossible) _ = Note.Renote(); } private void Quote() @@ -118,6 +118,6 @@ private void React(EmojiResponse emoji) { - Note.React(emoji.Name, true, emoji.PublicUrl); + Note.React(emoji); } } diff --git a/Iceshrimp.Frontend/Components/Note/NoteReaction.razor b/Iceshrimp.Frontend/Components/Note/NoteReaction.razor index f5834b44..0d2b50c5 100644 --- a/Iceshrimp.Frontend/Components/Note/NoteReaction.razor +++ b/Iceshrimp.Frontend/Components/Note/NoteReaction.razor @@ -21,6 +21,7 @@ private void React() { - Note.React(Reaction.Name, !Reaction.Reacted); + if (Reaction.Reacted) _ = Note.RemoveReact(Reaction.Name); + else _ = Note.AddReact(Reaction.Name, Reaction.Url); } } \ No newline at end of file diff --git a/Iceshrimp.Frontend/Components/TimelineComponent.razor.cs b/Iceshrimp.Frontend/Components/TimelineComponent.razor.cs index 8dc0e28a..32962eaa 100644 --- a/Iceshrimp.Frontend/Components/TimelineComponent.razor.cs +++ b/Iceshrimp.Frontend/Components/TimelineComponent.razor.cs @@ -14,12 +14,7 @@ public partial class TimelineComponent : IAsyncDisposable [Inject] private StreamingService StreamingService { get; set; } = null!; [Inject] private StateService StateService { get; set; } = null!; - private TimelineState State { get; set; } = new() - { - Timeline = [], - MaxId = null, - MinId = null - }; + private TimelineState State { get; set; } = null!; private VirtualScroller VirtualScroller { get; set; } = null!; private bool LockFetch { get; set; } @@ -28,6 +23,7 @@ public partial class TimelineComponent : IAsyncDisposable { StreamingService.NotePublished -= OnNotePublished; await StreamingService.DisposeAsync(); + StateService.Timeline.SetState("home", State); } private async Task Initialize() @@ -42,18 +38,27 @@ public partial class TimelineComponent : IAsyncDisposable // Returning false means the API has no more content. private async Task FetchOlder() { - if (LockFetch) return true; - LockFetch = true; - var pq = new PaginationQuery { Limit = 15, MaxId = State.MinId }; - var res = await ApiService.Timelines.GetHomeTimeline(pq); - switch (res.Count) + try { - case > 0: - State.MinId = res.Last().Id; - State.Timeline.AddRange(res); - break; - case 0: - return false; + if (LockFetch) return true; + LockFetch = true; + Console.WriteLine("Fetching older"); + var pq = new PaginationQuery { Limit = 15, MaxId = State.MinId }; + var res = await ApiService.Timelines.GetHomeTimeline(pq); + switch (res.Count) + { + case > 0: + State.MinId = res.Last().Id; + State.Timeline.AddRange(res); + break; + case 0: + return false; + } + } + catch (HttpRequestException) + { + Console.WriteLine("Network Error"); + return false; } LockFetch = false; @@ -62,16 +67,22 @@ public partial class TimelineComponent : IAsyncDisposable private async Task FetchNewer() { - if (LockFetch) return; - LockFetch = true; - var pq = new PaginationQuery { Limit = 15, MinId = State.MaxId }; - var res = await ApiService.Timelines.GetHomeTimeline(pq); - if (res.Count > 0) + try { - State.MaxId = res.Last().Id; - State.Timeline.InsertRange(0, res); + if (LockFetch) return; + LockFetch = true; + var pq = new PaginationQuery { Limit = 15, MinId = State.MaxId }; + var res = await ApiService.Timelines.GetHomeTimeline(pq); + if (res.Count > 0) + { + State.MaxId = res.Last().Id; + State.Timeline.InsertRange(0, res); + } + } + catch (HttpRequestException) + { + Console.WriteLine("Network Error"); } - LockFetch = false; } @@ -93,21 +104,14 @@ public partial class TimelineComponent : IAsyncDisposable { if (firstRender) { - try - { - var timeline = StateService.Timeline.GetState("home"); - State = timeline; - _init = true; - StateHasChanged(); - } - catch (ArgumentException) + State = StateService.Timeline.GetState("home"); + if (State.Timeline.Count == 0) { + Console.WriteLine("initializing"); await Initialize(); - _init = true; - StateHasChanged(); } + _init = true; + StateHasChanged(); } - - StateService.Timeline.SetState("home", State); } } \ No newline at end of file diff --git a/Iceshrimp.Frontend/Core/Services/StateServicePatterns/TimelineState.cs b/Iceshrimp.Frontend/Core/Services/StateServicePatterns/TimelineState.cs index cc8f2da6..d2ee74cf 100644 --- a/Iceshrimp.Frontend/Core/Services/StateServicePatterns/TimelineState.cs +++ b/Iceshrimp.Frontend/Core/Services/StateServicePatterns/TimelineState.cs @@ -1,10 +1,13 @@ +using System.Diagnostics.CodeAnalysis; using Iceshrimp.Shared.Schemas.Web; +using Microsoft.AspNetCore.Components; namespace Iceshrimp.Frontend.Core.Services.StateServicePatterns; -public class Timeline +internal class Timeline(MessageService messageService) { - private Dictionary States { get; } = new(); + private MessageService MessageService { get; set; } = messageService; + private Dictionary States { get; } = new(); public void SetState(string id, TimelineState state) { @@ -14,13 +17,44 @@ public class Timeline public TimelineState GetState(string id) { States.TryGetValue(id, out var state); - return state ?? throw new ArgumentException($"Requested state '{id}' does not exist."); + if (state != null) return state; + else + { + States[id] = new TimelineState([], null, null, MessageService); + return States[id]; + } } } -public class TimelineState +internal class TimelineState : IDisposable { - public required string? MaxId; - public required string? MinId; - public required List Timeline = []; + private MessageService MessageService { get; set; } + public required string? MaxId; + public required string? MinId; + public required List Timeline; + + [SetsRequiredMembers] + public TimelineState(List timeline, string? maxId, string? minId, MessageService messageService) + { + MaxId = maxId; + MinId = minId; + Timeline = timeline; + MessageService = messageService; + MessageService.AnyNoteChanged += OnNoteChanged; + + } + + private void OnNoteChanged(object? _, NoteResponse note) + { + var i = Timeline.FindIndex(p => p.Id == note.Id); + if (i >= 0) + { + Timeline[i].Liked = note.Liked; + } + } + + public void Dispose() + { + MessageService.AnyNoteChanged -= OnNoteChanged; + } } \ No newline at end of file