diff --git a/backend/MangaMagnet.Api/Service/BroadcastProgressService.cs b/backend/MangaMagnet.Api/Service/BroadcastProgressService.cs index 015d21e..3a40f98 100644 --- a/backend/MangaMagnet.Api/Service/BroadcastProgressService.cs +++ b/backend/MangaMagnet.Api/Service/BroadcastProgressService.cs @@ -19,20 +19,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) while (await timer.WaitForNextTickAsync(stoppingToken)) { - var changedTasks = progressService.GetUpdatedTasksAndReset(); - - if (changedTasks.Count == 0) - { - continue; - } - - var writer = new Utf8JsonWriter(buffer); - JsonSerializer.Serialize(writer, changedTasks, jsonOptions.Value.SerializerOptions); - await writer.FlushAsync(stoppingToken); - - await webSocketService.SendToAllAsync(buffer.WrittenMemory, stoppingToken); - - buffer.Reset(); + await TickAsync(buffer, stoppingToken); } } catch (TaskCanceledException) @@ -40,4 +27,22 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) // Ignore } } + + private async Task TickAsync(PooledArrayBufferWriter buffer, CancellationToken stoppingToken) + { + var changedTasks = progressService.GetUpdatedTasksAndReset(); + + if (changedTasks.Count == 0) + { + return; + } + + var writer = new Utf8JsonWriter(buffer); + JsonSerializer.Serialize(writer, changedTasks, jsonOptions.Value.SerializerOptions); + await writer.FlushAsync(stoppingToken); + + await webSocketService.SendToAllAsync(buffer.WrittenMemory, stoppingToken); + + buffer.Reset(); + } } diff --git a/backend/MangaMagnet.Api/Service/WebSocketService.cs b/backend/MangaMagnet.Api/Service/WebSocketService.cs index 22a4524..349df52 100644 --- a/backend/MangaMagnet.Api/Service/WebSocketService.cs +++ b/backend/MangaMagnet.Api/Service/WebSocketService.cs @@ -31,11 +31,20 @@ public void RemoveSocket(Guid id) /// /// Message to send. /// Cancellation token. - public async Task SendToAllAsync(ReadOnlyMemory memory, CancellationToken stoppingToken) + public Task SendToAllAsync(ReadOnlyMemory memory, CancellationToken stoppingToken) { - foreach (var socket in _sockets.Values) + return Task.WhenAll(_sockets.Values.Select(socket => SendToSocketAsync(socket, memory, stoppingToken))); + } + + private static async Task SendToSocketAsync(WebSocket socket, ReadOnlyMemory memory, CancellationToken stoppingToken) + { + try { await socket.SendAsync(memory, WebSocketMessageType.Text, true, stoppingToken); } + catch + { + // ignore + } } } diff --git a/frontend/public/placeholder-cover.webp b/frontend/public/placeholder-cover.webp new file mode 100644 index 0000000..edaf0f1 Binary files /dev/null and b/frontend/public/placeholder-cover.webp differ diff --git a/frontend/src/components/TaskList.tsx b/frontend/src/components/TaskList.tsx new file mode 100644 index 0000000..af18c1f --- /dev/null +++ b/frontend/src/components/TaskList.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import { useTasks } from "@/services/websocket"; + +export const TaskList = () => { + const tasks = useTasks(); + const maxShownTasks = 5; + const shownTasks = tasks.length > maxShownTasks ? tasks.slice(0, maxShownTasks) : tasks; + + return ( + <> + {tasks.length > 0 && ( +
+
+
+ Tasks {tasks.length > maxShownTasks && `(${tasks.length})`} +
+
+
+ {shownTasks.map(i => ( +
+
+
{i.name}
+
{i.progress}%
+
+
+
+ ))} +
+
+ )} + + ) +} \ No newline at end of file diff --git a/frontend/src/components/layout/Layout.tsx b/frontend/src/components/layout/Layout.tsx index 630ee01..b83b081 100644 --- a/frontend/src/components/layout/Layout.tsx +++ b/frontend/src/components/layout/Layout.tsx @@ -1,12 +1,8 @@ import React from "react"; import Link from "next/link"; -import { useTasks } from "@/services/websocket"; +import { TaskList } from "../TaskList"; export const Layout = ({ children }: React.PropsWithChildren) => { - const tasks = useTasks(); - const maxShownTasks = 5; - const shownTasks = tasks.length > maxShownTasks ? tasks.slice(0, maxShownTasks) : tasks; - return (
@@ -28,26 +24,7 @@ export const Layout = ({ children }: React.PropsWithChildren) => {
- {tasks.length > 0 && ( -
-
-
- Tasks {tasks.length > maxShownTasks && `(${tasks.length})`} -
-
-
- {shownTasks.map(i => ( -
-
-
{i.name}
-
{i.progress}%
-
-
-
- ))} -
-
- )} +
{children} diff --git a/frontend/src/components/manga/MangaCard.tsx b/frontend/src/components/manga/MangaCard.tsx index 4335d18..d59c3c1 100644 --- a/frontend/src/components/manga/MangaCard.tsx +++ b/frontend/src/components/manga/MangaCard.tsx @@ -26,7 +26,7 @@ export const MangaCard = ({manga}: { manga: MangaResponse }) => { }}> {manga.metadata.displayTitle} - -