diff --git a/frontend/src/components/PlayerModal.tsx b/frontend/src/components/PlayerModal.tsx index 7320171..560de63 100644 --- a/frontend/src/components/PlayerModal.tsx +++ b/frontend/src/components/PlayerModal.tsx @@ -50,7 +50,7 @@ function loadYouTubeApi(): Promise { export default function PlayerModal({ video, startAt, - queue, + queue: queueProp, startIndex, onClose, onState, @@ -75,6 +75,14 @@ export default function PlayerModal({ const qc = useQueryClient(); // Browser/mouse Back closes the player instead of leaving the page. useBackToClose(onClose); + // Freeze the launch queue: the player steps through the SAME filtered + sorted list it was + // opened with, for its whole session. The live feed refetches and reorders/drops items under + // us — e.g. auto-marking each video watched near its end removes it from a filtered feed — which + // would otherwise shrink the queue mid-playback and break prev/next + Loop "All" (it could never + // wrap back to the first item once earlier items dropped out). Snapshot once at mount via + // useState's lazy initializer and ignore later prop changes. Items that turn out gone/ + // non-embeddable still surface the existing playback-error overlay when reached. + const [queue] = useState(() => queueProp); // Precise upload date shown inline after the relative time (e.g. "9 yr ago · 12 Jan 2017"). const fullDate = (d: string | null | undefined) => d @@ -93,18 +101,12 @@ export default function PlayerModal({ // `video` in the queue (the feed passes its whole list + the clicked video, no index). startIndex != null ? queue?.[startIndex]?.id ?? video.id : video.id ); - // Resolve the playing item from the LIVE queue so prev/next + the N/M counter track it. But - // the feed query reorders/refetches under us — e.g. auto-marking the current video watched near - // its end invalidates the feed — and the playing item can drop OUT of the loaded queue. When - // that happens we must KEEP PLAYING it, not snap back to queue[0] (which would silently jump to - // an unrelated video mid-playback, ignoring loop/auto-advance). So pin the last resolved video - // in a ref and fall back to it; neighbour stepping just treats it as sitting before queue[0]. - const foundIndex = queue ? queue.findIndex((v) => v.id === playingId) : -1; - const inQueue = foundIndex >= 0; - const activeRef = useRef