aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-05-21 13:30:34 +0000
committerFuwn <[email protected]>2026-05-21 13:30:34 +0000
commit228fdfad1ebeed95e423898aad2628d88967374f (patch)
treea84730ac16792505975dd3054e229a51a7a5ba5a /src/lib
parentfix(lists): cross-trigger Upcoming and Due refresh on airing/interval (diff)
downloaddue.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.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/List/Anime/CleanAnimeList.svelte46
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;' : ''}