fix: safari specific fixes for video player and watch page

This commit is contained in:
Trevor Mears
2026-01-22 13:35:19 -08:00
parent 89dbb96c92
commit e83b173755
4 changed files with 101 additions and 2 deletions
+22
View File
@@ -4,6 +4,10 @@
/* CSS Variables */
:root {
/* iOS Safari toolbar compensation (set dynamically by JS) */
--ios-ui-bottom: 0px;
/* Colors */
--color-bg-primary: #0a0a0f;
--color-bg-secondary: #12121a;
@@ -314,6 +318,15 @@ h4 {
position: relative;
}
/* Fix scroll sidebar on desktop (Safari / flex bug) */
.main-content,
.page,
.home-layout,
.channel-sidebar,
.channel-list {
min-height: 0;
}
/* Floating Channel Toggle Button (Mobile) */
.channel-toggle-btn {
display: none;
@@ -673,6 +686,15 @@ h4 {
/* Allow flex child to shrink */
}
/* Live TV player controls overlay - iOS Safari safe positioning */
#player-controls-overlay {
position: absolute;
left: 0;
right: 0;
bottom: calc(env(safe-area-inset-bottom, 0px) + var(--ios-ui-bottom, 0px));
box-sizing: border-box;
}
/* Favorites */
.group-header.favorites-group {
background: linear-gradient(to right, rgba(239, 68, 68, 0.1), transparent);
+1 -2
View File
@@ -3,8 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="mobile-web-app-capable" content="yes">
+39
View File
@@ -11,6 +11,13 @@ function isMobile() {
class VideoPlayer {
constructor() {
this.video = document.getElementById('video-player');
// iOS: ensure inline playback (not fullscreen by default)
if (this.video) {
this.video.setAttribute('playsinline', '');
this.video.setAttribute('webkit-playsinline', '');
}
this.container = document.querySelector('.video-container');
this.overlay = document.getElementById('player-overlay');
this.nowPlaying = document.getElementById('now-playing');
@@ -150,6 +157,38 @@ class VideoPlayer {
this.controlsOverlay = document.getElementById('player-controls-overlay');
this.loadingSpinner = document.getElementById('player-loading');
// iOS Safari: detect and compensate for floating bottom toolbar
const updateIosUiBottom = () => {
let uiBottom = 0;
if (window.visualViewport) {
const vv = window.visualViewport;
uiBottom = Math.max(0, window.innerHeight - (vv.height + vv.offsetTop));
}
document.documentElement.style.setProperty('--ios-ui-bottom', uiBottom + 'px');
};
updateIosUiBottom();
if (window.visualViewport) {
window.visualViewport.addEventListener('resize', updateIosUiBottom);
window.visualViewport.addEventListener('scroll', updateIosUiBottom);
} else {
window.addEventListener('resize', updateIosUiBottom);
}
// iOS: use custom --vh unit to avoid 100vh issues with dynamic toolbar
const isIOS = /iP(hone|ad|od)/.test(navigator.userAgent);
if (isIOS && this.container) {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
this.container.style.height = 'calc(var(--vh) * 100)';
}
// Apply safe area + iOS toolbar padding to controls overlay
if (this.controlsOverlay) {
this.controlsOverlay.style.paddingBottom = 'calc(env(safe-area-inset-bottom, 0px) + var(--ios-ui-bottom, 0px) + 12px)';
}
const btnPlay = document.getElementById('btn-play');
const btnMute = document.getElementById('btn-mute');
const btnFullscreen = document.getElementById('btn-fullscreen');
+39
View File
@@ -11,6 +11,12 @@ class WatchPage {
this.video = document.getElementById('watch-video');
this.overlay = document.getElementById('watch-overlay');
// iOS: ensure inline playback (not fullscreen by default)
if (this.video) {
this.video.setAttribute('playsinline', '');
this.video.setAttribute('webkit-playsinline', '');
}
// Top bar
this.backBtn = document.getElementById('watch-back-btn');
this.titleEl = document.getElementById('watch-title');
@@ -90,6 +96,39 @@ class WatchPage {
}
init() {
// iOS Safari: detect and compensate for floating bottom toolbar
const updateIosUiBottom = () => {
let uiBottom = 0;
if (window.visualViewport) {
const vv = window.visualViewport;
uiBottom = Math.max(0, window.innerHeight - (vv.height + vv.offsetTop));
}
document.documentElement.style.setProperty('--ios-ui-bottom', uiBottom + 'px');
};
updateIosUiBottom();
if (window.visualViewport) {
window.visualViewport.addEventListener('resize', updateIosUiBottom);
window.visualViewport.addEventListener('scroll', updateIosUiBottom);
} else {
window.addEventListener('resize', updateIosUiBottom);
}
// iOS: use custom --vh unit to avoid 100vh issues with dynamic toolbar
const isIOS = /iP(hone|ad|od)/.test(navigator.userAgent);
const watchVideoSection = document.querySelector('.watch-video-section');
if (isIOS && watchVideoSection) {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
watchVideoSection.style.height = 'calc(var(--vh) * 100)';
}
// Apply safe area + iOS toolbar padding to overlay
if (this.overlay) {
this.overlay.style.paddingBottom = 'calc(env(safe-area-inset-bottom, 0px) + var(--ios-ui-bottom, 0px) + 12px)';
}
// Back button
this.backBtn?.addEventListener('click', () => this.goBack());