From 00dae69e9b05d65194ee11569e0288b70a33cd42 Mon Sep 17 00:00:00 2001 From: ThaUnknown <6506529+ThaUnknown@users.noreply.github.com> Date: Sun, 15 Jun 2025 23:00:36 +0200 Subject: [PATCH] feat: re-introduce watch progress --- package.json | 2 +- src/lib/components/EpisodesList.svelte | 7 +++++ src/lib/components/ui/player/player.svelte | 23 +++++++++++++++ src/lib/modules/watchProgress.ts | 33 ++++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/lib/modules/watchProgress.ts diff --git a/package.json b/package.json index fe0efb3..3b208c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ui", - "version": "6.3.60", + "version": "6.3.61", "license": "BUSL-1.1", "private": true, "packageManager": "pnpm@9.14.4", diff --git a/src/lib/components/EpisodesList.svelte b/src/lib/components/EpisodesList.svelte index ed66f02..32a9ebe 100644 --- a/src/lib/components/EpisodesList.svelte +++ b/src/lib/components/EpisodesList.svelte @@ -22,6 +22,7 @@ import { episodes as _episodes, dedupeAiring, episodeByAirDate, notes, type Media } from '$lib/modules/anilist' import { authAggregator, list, progress } from '$lib/modules/auth' import { click, dragScroll } from '$lib/modules/navigate' + import { liveAnimeProgress } from '$lib/modules/watchProgress' import { cn, isMobile, since } from '$lib/utils' export let eps: EpisodesResponse | null @@ -74,6 +75,8 @@ export let following = authAggregator.following(media.id) $: followerEntries = $following?.data?.Page?.mediaList?.filter(e => e?.user?.id !== authAggregator.id()) ?? [] + + $: watchProgress = liveAnimeProgress(media.id) @@ -108,6 +111,10 @@ {#if watched || completed}
+ {:else if $watchProgress?.episode === episode} +
+
+
{/if}
{notes(summary ?? '')} diff --git a/src/lib/components/ui/player/player.svelte b/src/lib/components/ui/player/player.svelte index be81334..c42bbec 100644 --- a/src/lib/components/ui/player/player.svelte +++ b/src/lib/components/ui/player/player.svelte @@ -61,6 +61,7 @@ import { settings, SUPPORTS } from '$lib/modules/settings' import { server } from '$lib/modules/torrent' import { w2globby } from '$lib/modules/w2g/lobby' + import { getAnimeProgress, setAnimeProgress } from '$lib/modules/watchProgress' import { toTS, fastPrettyBits } from '$lib/utils' export let mediaInfo: MediaInfo @@ -695,6 +696,27 @@ $: $w2globby?.playerStateChanged({ paused, time: Math.floor(currentTime) }) $: $w2globby?.on('player', updateState) + + function loadAnimeProgress () { + if (!mediaInfo.media.id || !mediaInfo.episode) return + + const animeProgress = getAnimeProgress(mediaInfo.media.id) + if (!animeProgress || animeProgress.episode !== mediaInfo.episode) return + + currentTime = Math.max(animeProgress.currentTime - 5, 0) + } + + function saveAnimeProgress () { + if (!mediaInfo.media.id || !mediaInfo.episode) return + + if (buffering || paused || video.readyState < 4) return + + setAnimeProgress(mediaInfo.media.id, { episode: mediaInfo.episode, currentTime: video.currentTime, safeduration }) + } + const saveProgressLoop = setInterval(saveAnimeProgress, 10000) + onDestroy(() => { + clearInterval(saveProgressLoop) + }) @@ -721,6 +743,7 @@ on:click={() => isMiniplayer ? goto('/app/player') : playPause()} on:dblclick={fullscreen} on:loadeddata={checkAudio} + on:loadedmetadata={loadAnimeProgress} on:timeupdate={checkSkippableChapters} on:timeupdate={checkCompletion} on:loadedmetadata={autoPlay} diff --git a/src/lib/modules/watchProgress.ts b/src/lib/modules/watchProgress.ts new file mode 100644 index 0000000..802a17e --- /dev/null +++ b/src/lib/modules/watchProgress.ts @@ -0,0 +1,33 @@ +import { derived, get } from 'svelte/store' +import { persisted } from 'svelte-persisted-store' + +export interface WatchProgress { + episode: number + currentTime: number + safeduration: number +} + +const animeProgressStore = persisted>('watchProgress', {}) + +export function liveAnimeProgress (mediaId: number) { + return derived(animeProgressStore, (data) => { + if (!mediaId) return + const entry = data[mediaId] + if (!entry) return + return { + progress: Math.ceil(entry.currentTime / entry.safeduration * 100), + episode: entry.episode + } + }) +} + +export function getAnimeProgress (mediaId: number) { + return get(animeProgressStore)[mediaId] +} + +export function setAnimeProgress (mediaId: number, progress: WatchProgress) { + animeProgressStore.update(data => { + data[mediaId] = progress + return data + }) +}