diff --git a/src/components/player/internals/ProgressSaver.tsx b/src/components/player/internals/ProgressSaver.tsx index 59edefa5..bac294eb 100644 --- a/src/components/player/internals/ProgressSaver.tsx +++ b/src/components/player/internals/ProgressSaver.tsx @@ -5,10 +5,62 @@ import { playerStatus } from "@/stores/player/slices/source"; import { usePlayerStore } from "@/stores/player/store"; import { ProgressItem, useProgressStore } from "@/stores/progress"; +function progressIsNotStarted(duration: number, watched: number): boolean { + // too short watch time + if (watched < 20) return true; + return false; +} + +function progressIsCompleted(duration: number, watched: number): boolean { + const timeFromEnd = duration - watched; + // too close to the end, is completed + if (timeFromEnd < 60 * 2) return true; + return false; +} + +function shouldSaveProgress( + meta: any, + progress: ProgressItem, + existingItems: Record, +): boolean { + const { duration, watched } = progress; + + // Check if progress is acceptable + const isNotStarted = progressIsNotStarted(duration, watched); + const isCompleted = progressIsCompleted(duration, watched); + const isAcceptable = !isNotStarted && !isCompleted; + + // For movies, only save if acceptable + if (meta.type === "movie") { + return isAcceptable; + } + + // For shows, save if acceptable OR if season has other watched episodes + if (isAcceptable) return true; + + // Check if this season has other episodes with progress + const showItem = existingItems[meta.tmdbId]; + if (!showItem || !meta.season) return false; + + const seasonEpisodes = Object.values(showItem.episodes).filter( + (episode: any) => episode.seasonId === meta.season.tmdbId, + ); + + // Check if any other episode in this season has acceptable progress + return seasonEpisodes.some((episode: any) => { + const epProgress = episode.progress; + return ( + !progressIsNotStarted(epProgress.duration, epProgress.watched) && + !progressIsCompleted(epProgress.duration, epProgress.watched) + ); + }); +} + export function ProgressSaver() { const meta = usePlayerStore((s) => s.meta); const progress = usePlayerStore((s) => s.progress); const updateItem = useProgressStore((s) => s.updateItem); + const progressItems = useProgressStore((s) => s.items); const status = usePlayerStore((s) => s.status); const hasPlayedOnce = usePlayerStore((s) => s.mediaPlaying.hasPlayedOnce); @@ -16,6 +68,7 @@ export function ProgressSaver() { const dataRef = useRef({ updateItem, + progressItems, meta, progress, status, @@ -23,11 +76,12 @@ export function ProgressSaver() { }); useEffect(() => { dataRef.current.updateItem = updateItem; + dataRef.current.progressItems = progressItems; dataRef.current.meta = meta; dataRef.current.progress = progress; dataRef.current.status = status; dataRef.current.hasPlayedOnce = hasPlayedOnce; - }, [updateItem, progress, meta, status, hasPlayedOnce]); + }, [updateItem, progressItems, progress, meta, status, hasPlayedOnce]); useInterval(() => { const d = dataRef.current; @@ -47,7 +101,10 @@ export function ProgressSaver() { duration: progress.duration, watched: progress.time, }; - if (isDifferent) + if ( + isDifferent && + shouldSaveProgress(d.meta, lastSavedRef.current, d.progressItems) + ) d.updateItem({ meta: d.meta, progress: lastSavedRef.current,