diff --git a/apps/web/src/components/media-session-sync.tsx b/apps/web/src/components/media-session-sync.tsx index 505d317..bfe13cf 100644 --- a/apps/web/src/components/media-session-sync.tsx +++ b/apps/web/src/components/media-session-sync.tsx @@ -136,7 +136,14 @@ export function MediaSessionSync({ if (!setPositionState) return; if (!Number.isFinite(duration) || duration <= 0) return; if (!Number.isFinite(currentTime) || currentTime < 0) return; - setPositionState({ duration, playbackRate, position: Math.min(duration, currentTime) }); + const safePlaybackRate = Number.isFinite(playbackRate) && playbackRate > 0 ? playbackRate : 1; + try { + setPositionState({ + duration, + playbackRate: safePlaybackRate, + position: Math.min(duration, currentTime), + }); + } catch {} }, [duration, currentTime, playbackRate]); return null; diff --git a/apps/web/src/hooks/use-progress.ts b/apps/web/src/hooks/use-progress.ts index 1aef37d..23d05f7 100644 --- a/apps/web/src/hooks/use-progress.ts +++ b/apps/web/src/hooks/use-progress.ts @@ -1,5 +1,6 @@ -import { useMutation, useQuery } from "@tanstack/react-query"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { fetchProgress, updateProgress } from "../lib/api-collections"; +import type { ProgressItem } from "../types/user"; import { useAuth } from "./use-auth"; export function useProgress(videoUrl: string) { @@ -16,8 +17,19 @@ export function useProgress(videoUrl: string) { export function useSaveProgress(videoUrl: string) { const { authReady, isAuthed } = useAuth(); + const qc = useQueryClient(); return useMutation({ mutationFn: (position: number) => authReady && isAuthed ? updateProgress(videoUrl, position) : Promise.resolve(), + onSuccess: (_, position) => { + if (!authReady || !isAuthed) return; + const next: ProgressItem = { + videoUrl, + position: Math.round(position), + updatedAt: Date.now(), + }; + qc.setQueryData(["progress", videoUrl], next); + void qc.invalidateQueries({ queryKey: ["history"] }); + }, }); } diff --git a/apps/web/src/routes/watch.tsx b/apps/web/src/routes/watch.tsx index 9940137..1825569 100644 --- a/apps/web/src/routes/watch.tsx +++ b/apps/web/src/routes/watch.tsx @@ -39,9 +39,15 @@ function WatchPage() { const addToHistoryRef = useRef(add.mutate); addToHistoryRef.current = add.mutate; + const historyAddedForRef = useRef(null); useEffect(() => { if (!stream) return; + if (authReady && isAuthed && progressFetch.isPending) return; + if (historyAddedForRef.current === stream.id) return; + const historyPositionMs = progressFetch.data?.position ?? (stream.startPosition ?? 0) * 1000; + const progress = Math.max(0, Math.round(historyPositionMs / 1000)); + historyAddedForRef.current = stream.id; addToHistoryRef.current({ url: stream.id, title: stream.title, @@ -50,9 +56,9 @@ function WatchPage() { channelUrl: stream.channelUrl ?? "", channelAvatar: stream.rawChannelAvatar, duration: stream.duration, - progress: 0, + progress, }); - }, [stream]); + }, [authReady, isAuthed, progressFetch.data?.position, progressFetch.isPending, stream]); if (isLoading) return ; if (authReady && isAuthed && progressFetch.isPending) return ;