diff --git a/static/player/controls.ts b/static/player/controls.ts index d228f22..f9e6df6 100644 --- a/static/player/controls.ts +++ b/static/player/controls.ts @@ -209,7 +209,7 @@ export const setupControls = (): void => { // mouse move in container shows controls state.container.addEventListener('mousemove', showControls); - // initial sync - updatePlayPauseIcons(false); + // initial sync — check actual video state since inline script may have started playback + updatePlayPauseIcons(!state.video.paused); syncVolumeUI(); }; diff --git a/static/player/main.ts b/static/player/main.ts index 7f00bd1..aac57ed 100644 --- a/static/player/main.ts +++ b/static/player/main.ts @@ -66,9 +66,10 @@ const initPlayer = (): void => { const progressWrap = container.querySelector('[data-progress-wrap]') as HTMLElement | null; // build video src from mode, token, and saved quality preference + // Only set if not already provided by the inline script during HTML parsing const preferredQuality = localStorage.getItem('mal:preferred-quality') || 'best'; const streamToken = state.modeSources[state.currentMode]?.token; - if (streamToken) { + if (!state.video.src && streamToken) { state.video.src = `${state.streamURL}?mode=${encodeURIComponent(state.currentMode)}&token=${encodeURIComponent(streamToken)}${preferredQuality !== 'best' ? `&quality=${encodeURIComponent(preferredQuality)}` : ''}`; } @@ -87,7 +88,7 @@ const initPlayer = (): void => { updateAutoSkipButton(); showControls(); - state.video.addEventListener('loadedmetadata', () => { + const onLoadedMetadata = (): void => { loading && (loading.style.display = 'none'); invalidateBounds(); @@ -104,11 +105,19 @@ const initPlayer = (): void => { state.video.currentTime = state.pendingSeekTime; state.pendingSeekTime = null; } - if (state.shouldAutoPlay) state.video.play().catch(() => {}); + // autoplay if not already playing (inline script may have already called play()) + if (state.shouldAutoPlay || state.video.paused) state.video.play().catch(() => {}); updateTimeline(state.video.currentTime); updateSkipButton(state.video.currentTime); - }); + }; + + state.video.addEventListener('loadedmetadata', onLoadedMetadata); + // inline script runs during HTML parsing before initPlayer; if metadata + // already loaded, fire the handler immediately + if (state.video.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) { + onLoadedMetadata(); + } state.video.addEventListener('waiting', () => { loading && (loading.style.display = 'flex'); diff --git a/templates/components/video_player.gohtml b/templates/components/video_player.gohtml index 68c0b5a..7f792e2 100644 --- a/templates/components/video_player.gohtml +++ b/templates/components/video_player.gohtml @@ -14,7 +14,27 @@ class="group relative aspect-video w-full overflow-hidden bg-black"> - + +