diff options
| author | Fuwn <[email protected]> | 2026-05-21 13:30:34 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-05-21 13:30:34 +0000 |
| commit | 228fdfad1ebeed95e423898aad2628d88967374f (patch) | |
| tree | a84730ac16792505975dd3054e229a51a7a5ba5a | |
| parent | fix(lists): cross-trigger Upcoming and Due refresh on airing/interval (diff) | |
| download | due.moe-228fdfad1ebeed95e423898aad2628d88967374f.tar.xz due.moe-228fdfad1ebeed95e423898aad2628d88967374f.zip | |
fix(lists): optimistic increment and snapshot to remove refresh flash
Click + on a Due item now bumps progress locally and drops the row
if the bump catches the user up, with no upfront refresh. The mutation
fires in the background and triggers a single revalidate on response.
Also snapshot the resolved media to previousAnimeList on every render,
so refreshes from any path (countdown, interval, manual, post-increment)
show the prior list during pending instead of a placeholder.
| -rw-r--r-- | src/lib/List/Anime/CleanAnimeList.svelte | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/src/lib/List/Anime/CleanAnimeList.svelte b/src/lib/List/Anime/CleanAnimeList.svelte index 23d87a97..3f397c25 100644 --- a/src/lib/List/Anime/CleanAnimeList.svelte +++ b/src/lib/List/Anime/CleanAnimeList.svelte @@ -9,6 +9,7 @@ import type { AniListAuthorisation } from "$lib/Data/AniList/identity"; import ListTitle from "../ListTitle.svelte"; import { onDestroy, onMount } from "svelte"; import AiringTime from "$lib/Media/Anime/Airing/AiringTime.svelte"; +import { hasDueEpisodes } from "$lib/Media/Anime/Airing/classify"; import { browser } from "$app/environment"; import identity from "$stores/identity"; import "../covers.css"; @@ -109,6 +110,9 @@ $: filteredMedia = ? media : media.filter((m) => m.mediaListEntry?.customLists?.[selectedList]); +$: if (browser && !dummy && media && previousAnimeList !== media) + previousAnimeList = media; + const updateSelectedList = (event: Event) => { const nextSelectedList = (event.currentTarget as HTMLSelectElement).value; @@ -206,28 +210,24 @@ $: if (browser && !dummy) { onDestroy(() => clearAiringRefreshTimeout()); const increment = (anime: Media, progress: number) => { - if (!dummy && pendingUpdate !== anime.id) { + if (dummy || pendingUpdate === anime.id) return; + + pendingUpdate = anime.id; + lastUpdatedMedia = anime.id; + + const target = media.find((m) => m.id === anime.id); + + if (target?.mediaListEntry) target.mediaListEntry.progress = progress + 1; + + media = + !completed && target && !hasDueEpisodes(target) + ? media.filter((m) => m.id !== anime.id) + : media; + + incrementMediaProgress(anime.id, anime.mediaListEntry?.progress, user, () => { + pendingUpdate = null; $revalidateAnime = $revalidateAnime + 1; - lastUpdatedMedia = anime.id; - pendingUpdate = anime.id; - - incrementMediaProgress( - anime.id, - anime.mediaListEntry?.progress, - user, - () => { - const mediaListEntry = media.find( - (m) => m.id === anime.id, - )?.mediaListEntry; - - if (mediaListEntry) mediaListEntry.progress = progress + 1; - - previousAnimeList = media; - animeLists = cleanCache(user, $identity); - pendingUpdate = null; - }, - ); - } + }); }; </script> @@ -279,7 +279,7 @@ const increment = (anime: Media, progress: number) => { > <div slot="title" let:title={anime} let:progress> {#if !upcoming && !notYetReleased} - {pendingUpdate === anime.id ? progress + 1 : progress}{@html totalEpisodes(anime)} + {progress}{@html totalEpisodes(anime)} <button class={`button-square button-action ${pendingUpdate === anime.id ? 'opaque' : ''}`} style={pendingUpdate === anime.id ? 'pointer-events: none;' : ''} @@ -312,7 +312,7 @@ const increment = (anime: Media, progress: number) => { {/if} {#if !upcoming || notYetReleased} <!-- {anime.mediaListEntry?.progress || 0}{@html totalEpisodes(anime)} --> - {pendingUpdate === anime.id ? progress + 1 : progress}{@html totalEpisodes(anime)} + {progress}{@html totalEpisodes(anime)} <button class={`button-square button-action ${pendingUpdate === anime.id ? 'opaque' : ''}`} style={pendingUpdate === anime.id ? 'pointer-events: none;' : ''} |