More improvements to player positioning on watch page

This commit is contained in:
WardPearce
2025-11-07 16:06:33 +13:00
parent 35ee2a8047
commit fc0dec833b
5 changed files with 71 additions and 21 deletions
@@ -458,6 +458,20 @@
});
playerElement = document.getElementById('player') as HTMLMediaElement;
// Due to how our player is rendered in layout for stateful pip
// we calaculate player height to then allow children pages
// to wrap around it.
function updateVideoPlayerHeight() {
const container = document.getElementById('shaka-container') as HTMLElement;
if (container) {
const height = container.getBoundingClientRect().height;
document.documentElement.style.setProperty('--video-player-height', `${height}px`);
}
}
window.addEventListener('resize', updateVideoPlayerHeight);
updateVideoPlayerHeight();
// Change instantly to stop video from being loud for a second
restoreVolumePreference();
+4
View File
@@ -2,6 +2,10 @@
display: none;
}
:root {
--video-player-height: 0px;
}
@font-face {
font-family: Inter;
src: url('/static/inter.ttf');
+12 -4
View File
@@ -10,6 +10,7 @@ import { loadEntirePlaylist } from '$lib/playlist';
import {
authStore,
playerProxyVideosStore,
playerState,
returnYTDislikesInstanceStore,
returnYtDislikesStore
} from '$lib/store';
@@ -19,11 +20,18 @@ import { get } from 'svelte/store';
import { _ } from './i18n';
export async function getWatchDetails(videoId: string, url: URL) {
const playerStateRetrieved = get(playerState);
let video;
try {
video = await getVideo(videoId, get(playerProxyVideosStore), { priority: 'high' });
} catch (errorMessage: any) {
error(500, errorMessage);
if (playerStateRetrieved && playerStateRetrieved.data.video.videoId === videoId) {
video = playerStateRetrieved.data.video;
} else {
try {
video = await getVideo(videoId, get(playerProxyVideosStore), { priority: 'high' });
} catch (errorMessage: any) {
error(500, errorMessage);
}
}
if (video.premium) {
+29 -16
View File
@@ -406,22 +406,35 @@
<main id="main-content" class="responsive max root" tabindex="0" role="region">
{#if $playerState}
<div class:pip={playerIsPip}>
{#if playerIsPip}
<nav>
<h6 class="max">{truncate($playerState.data.video.title, 20)}</h6>
<button class="border" onclick={() => playerState.set(undefined)}>
<i>close</i>
</button>
</nav>
<div class="space"></div>
{/if}
{#key $playerState.data.video.videoId}
<Player data={$playerState.data} isSyncing={$playerState.isSyncing} {playerElement} />
{/key}
{#if playerIsPip}
<Author video={$playerState.data.video} hideSubscribe={true} />
{/if}
<div class="grid">
<div
class:pip={playerIsPip}
class:s12={!playerIsPip}
class:m12={!playerIsPip}
class:l9={!playerIsPip}
>
{#if playerIsPip}
<nav>
<h6 class="max">{truncate($playerState.data.video.title, 20)}</h6>
<button class="border" onclick={() => playerState.set(undefined)}>
<i>close</i>
</button>
</nav>
<div class="space"></div>
{/if}
{#key $playerState.data.video.videoId}
<Player data={$playerState.data} isSyncing={$playerState.isSyncing} {playerElement} />
{/key}
{#if playerIsPip}
<nav>
<Author video={$playerState.data.video} hideSubscribe={true} />
<div class="max"></div>
<a class="button border" href={`/watch/${$playerState.data.video.videoId}`}
><i>keyboard_arrow_right</i></a
>
</nav>
{/if}
</div>
</div>
{/if}
@@ -520,7 +520,7 @@
{/if}
</div>
{#if !theatreMode}
<div class="s12 m12 l3">
<div class="s12 m12 l3 recommended">
{#if showTranscript && playerElement}
<Transcript video={data.video} bind:playerElement />
{/if}
@@ -668,6 +668,11 @@
overflow-x: hidden;
}
.recommended {
margin-top: calc(var(--video-player-height) * -1);
position: relative;
}
.video-actions {
display: flex;
align-items: center;
@@ -686,4 +691,10 @@
padding: 0;
}
}
@media only screen and (max-width: 993px) {
.recommended {
margin-top: 0;
}
}
</style>