fix: safari specific fixes for video player and watch page
This commit is contained in:
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
/* CSS Variables */
|
/* CSS Variables */
|
||||||
:root {
|
:root {
|
||||||
|
/* iOS Safari toolbar compensation (set dynamically by JS) */
|
||||||
|
--ios-ui-bottom: 0px;
|
||||||
|
|
||||||
|
|
||||||
/* Colors */
|
/* Colors */
|
||||||
--color-bg-primary: #0a0a0f;
|
--color-bg-primary: #0a0a0f;
|
||||||
--color-bg-secondary: #12121a;
|
--color-bg-secondary: #12121a;
|
||||||
@@ -314,6 +318,15 @@ h4 {
|
|||||||
position: relative;
|
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) */
|
/* Floating Channel Toggle Button (Mobile) */
|
||||||
.channel-toggle-btn {
|
.channel-toggle-btn {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -673,6 +686,15 @@ h4 {
|
|||||||
/* Allow flex child to shrink */
|
/* 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 */
|
/* Favorites */
|
||||||
.group-header.favorites-group {
|
.group-header.favorites-group {
|
||||||
background: linear-gradient(to right, rgba(239, 68, 68, 0.1), transparent);
|
background: linear-gradient(to right, rgba(239, 68, 68, 0.1), transparent);
|
||||||
|
|||||||
+1
-2
@@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport"
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
|
|||||||
@@ -11,6 +11,13 @@ function isMobile() {
|
|||||||
class VideoPlayer {
|
class VideoPlayer {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.video = document.getElementById('video-player');
|
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.container = document.querySelector('.video-container');
|
||||||
this.overlay = document.getElementById('player-overlay');
|
this.overlay = document.getElementById('player-overlay');
|
||||||
this.nowPlaying = document.getElementById('now-playing');
|
this.nowPlaying = document.getElementById('now-playing');
|
||||||
@@ -150,6 +157,38 @@ class VideoPlayer {
|
|||||||
this.controlsOverlay = document.getElementById('player-controls-overlay');
|
this.controlsOverlay = document.getElementById('player-controls-overlay');
|
||||||
this.loadingSpinner = document.getElementById('player-loading');
|
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 btnPlay = document.getElementById('btn-play');
|
||||||
const btnMute = document.getElementById('btn-mute');
|
const btnMute = document.getElementById('btn-mute');
|
||||||
const btnFullscreen = document.getElementById('btn-fullscreen');
|
const btnFullscreen = document.getElementById('btn-fullscreen');
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ class WatchPage {
|
|||||||
this.video = document.getElementById('watch-video');
|
this.video = document.getElementById('watch-video');
|
||||||
this.overlay = document.getElementById('watch-overlay');
|
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
|
// Top bar
|
||||||
this.backBtn = document.getElementById('watch-back-btn');
|
this.backBtn = document.getElementById('watch-back-btn');
|
||||||
this.titleEl = document.getElementById('watch-title');
|
this.titleEl = document.getElementById('watch-title');
|
||||||
@@ -90,6 +96,39 @@ class WatchPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
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
|
// Back button
|
||||||
this.backBtn?.addEventListener('click', () => this.goBack());
|
this.backBtn?.addEventListener('click', () => this.goBack());
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user