skip resume prompt for ?resume=true and playlist queue
This commit is contained in:
+33
-21
@@ -32,6 +32,7 @@ import PlayerOverlays from '../components/player/PlayerOverlays'
|
||||
import { computeRecapTrigger } from '../lib/recap-trigger'
|
||||
import { usePersonalData } from '../stores/personal-data-store'
|
||||
import { usePlayerRuntimeStore } from '../stores/player-runtime-store'
|
||||
import { useQueueStore } from '../stores/queue-store'
|
||||
import { usePlayerShortcuts } from '../hooks/use-player-shortcuts'
|
||||
import { detachAudioGraph } from '../lib/audio-graph'
|
||||
import type { ShortcutContext } from '../lib/player-shortcuts'
|
||||
@@ -363,15 +364,16 @@ export default function PlayerPage() {
|
||||
})
|
||||
}
|
||||
|
||||
/* Resume prompt: show on first mount when there's a saved position
|
||||
* past the threshold AND the user wants the prompt. The prompt auto-
|
||||
* confirms after a few seconds, which queues the deferred seek via
|
||||
* pendingSeekRef and seeks the underlying HTMLMediaElement directly
|
||||
* (vidstack's MediaPlayerInstance.currentTime has a known bug on
|
||||
* direct-play MP4 sources that restarts the video from 0).
|
||||
* Intentionally scoped to item?.Id only - we only want to evaluate
|
||||
* the resume condition once per item, not re-trigger when item data
|
||||
* refreshes or prefs change mid-playback. */
|
||||
/* Resume behaviour: when the saved position is past the threshold,
|
||||
* queue the seek so onCanPlay can apply it (the underlying
|
||||
* HTMLMediaElement.currentTime is the only path that works for both
|
||||
* direct-play MP4 and HLS without restarting from 0). Decide whether
|
||||
* to also show the prompt:
|
||||
* - ?resume=true : the caller already chose Resume, don't ask again
|
||||
* - playlist queue: auto-advance through a playlist shouldn't ask
|
||||
* before every episode
|
||||
* - otherwise : show the prompt so the user can pick Resume /
|
||||
* Start over (if the show-resume-prompt pref is on) */
|
||||
const resumePromptShownRef = useRef<string | null>(null)
|
||||
const resumeItemId = item?.Id
|
||||
const resumePositionTicks = item?.UserData?.PlaybackPositionTicks
|
||||
@@ -388,25 +390,35 @@ export default function PlayerPage() {
|
||||
usePlayerRuntimeStore.getState().resetForNewItem()
|
||||
}, [id, setPanel])
|
||||
|
||||
/* Resume behaviour: when the saved position is past the threshold,
|
||||
* queue the seek so onCanPlay can apply it (the underlying
|
||||
* HTMLMediaElement.currentTime is the only path that works for both
|
||||
* direct-play MP4 and HLS without restarting from 0). Decide whether
|
||||
* to also show the prompt:
|
||||
* - ?resume=true : the caller already chose Resume, don't ask again
|
||||
* - playlist queue: auto-advance through a playlist shouldn't ask
|
||||
* before every episode
|
||||
* - otherwise : show the prompt so the user can pick Resume /
|
||||
* Start over (if the show-resume-prompt pref is on) */
|
||||
const queueSource = useQueueStore(s => s.source)
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
console.log('[player] resume prompt effect', {
|
||||
resumeItemId,
|
||||
alreadyShown: resumePromptShownRef.current === resumeItemId,
|
||||
pos: Number(resumePositionTicks ?? 0),
|
||||
showResumePromptPref,
|
||||
})
|
||||
}
|
||||
if (!resumeItemId || resumePromptShownRef.current === resumeItemId) return
|
||||
if (!resumeItemId) return
|
||||
const pos = Number(resumePositionTicks ?? 0)
|
||||
const thresholdSec = usePreferencesStore.getState().resumeThresholdSec ?? 5
|
||||
const threshold = thresholdSec * 10_000_000
|
||||
if (showResumePromptPref && pos > threshold) {
|
||||
if (typeof window !== 'undefined') console.log('[player] resume prompt opening')
|
||||
if (pos <= threshold) return
|
||||
const target = pos / 10_000_000
|
||||
if (pendingSeekRef.current == null) {
|
||||
pendingSeekRef.current = target
|
||||
}
|
||||
if (resumePromptShownRef.current === resumeItemId) return
|
||||
const inPlaylist = queueActive && queueSource?.type === 'playlist'
|
||||
const skipPrompt = resume || inPlaylist
|
||||
if (!skipPrompt && showResumePromptPref) {
|
||||
setResumePromptOpen(true)
|
||||
resumePromptShownRef.current = resumeItemId
|
||||
}
|
||||
}, [resumeItemId, resumePositionTicks, showResumePromptPref])
|
||||
}, [resumeItemId, resumePositionTicks, showResumePromptPref, resume, queueActive, queueSource])
|
||||
|
||||
/* Auto-rewatch counter: when an already-played item starts playing
|
||||
* again, record the rewatch. We trip it at most once per item-mount
|
||||
|
||||
Reference in New Issue
Block a user