From 4887d0c5175b768c44dc758832598f49747bc3b2 Mon Sep 17 00:00:00 2001 From: ghassan Date: Sat, 16 May 2026 23:14:28 +0300 Subject: [PATCH] Lock screen to landscape on fullscreen, unlock on exit On mobile, entering fullscreen now also locks the screen orientation to landscape via the Screen Orientation API. Exiting fullscreen unlocks it, allowing the device to return to portrait. Applied to both the video player and audio player. Gracefully ignored on browsers that don't support screen.orientation.lock (e.g. iOS Safari). Also includes the playlist auto-scroll fix (committed separately). Co-Authored-By: Claude Sonnet 4.6 --- resources/views/components/video-player.blade.php | 4 ++++ .../views/videos/partials/audio-player.blade.php | 4 ++++ resources/views/videos/types/generic.blade.php | 9 ++++----- resources/views/videos/types/match.blade.php | 9 ++++----- resources/views/videos/types/music.blade.php | 12 +++++++----- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/resources/views/components/video-player.blade.php b/resources/views/components/video-player.blade.php index 863e9b7..58ca747 100644 --- a/resources/views/components/video-player.blade.php +++ b/resources/views/components/video-player.blade.php @@ -1118,6 +1118,10 @@ document.addEventListener('fullscreenchange', () => { const exit = fsBtn.querySelector('.ytp-svg-fs-exit'); enter.style.display = isFullscreen ? 'none' : ''; exit.style.display = isFullscreen ? '' : 'none'; + if (screen.orientation && screen.orientation.lock) { + if (isFullscreen) screen.orientation.lock('landscape').catch(function(){}); + else screen.orientation.unlock(); + } }); // ── Theater mode ────────────────────────────────────── diff --git a/resources/views/videos/partials/audio-player.blade.php b/resources/views/videos/partials/audio-player.blade.php index 48b2e90..0832216 100644 --- a/resources/views/videos/partials/audio-player.blade.php +++ b/resources/views/videos/partials/audio-player.blade.php @@ -513,6 +513,10 @@ document.addEventListener('fullscreenchange', () => { wrap.classList.toggle('ytp-fullscreen', fs); fsBtn.querySelector('.ytp-svg-fs-enter').style.display = fs ? 'none' : ''; fsBtn.querySelector('.ytp-svg-fs-exit').style.display = fs ? '' : 'none'; + if (screen.orientation && screen.orientation.lock) { + if (fs) screen.orientation.lock('landscape').catch(function(){}); + else screen.orientation.unlock(); + } }); // ── Keyboard shortcuts ──────────────────────────────────────── diff --git a/resources/views/videos/types/generic.blade.php b/resources/views/videos/types/generic.blade.php index 3bb792b..4394426 100644 --- a/resources/views/videos/types/generic.blade.php +++ b/resources/views/videos/types/generic.blade.php @@ -546,7 +546,7 @@ PL_CURRENT=d.id; plRender(); - plHighlight(d.id); + plHighlight(d.id, true); if(pushHist!==false) history.pushState({plVideoId:d.id,url:url},'',url); plSwapContent(url); @@ -584,12 +584,11 @@ } catch(e){ console.warn('plSwapContent',e); } } - function plHighlight(activeId){ + function plHighlight(activeId, scroll){ document.querySelectorAll('.sidebar-video-card[data-pl-id]').forEach(function(c){ c.classList.toggle('current-video',parseInt(c.dataset.plId)===activeId); }); - var a=document.querySelector('.sidebar-video-card.current-video'); - if(a) a.scrollIntoView({behavior:'smooth',block:'nearest'}); + if(scroll){ var a=document.querySelector('.sidebar-video-card.current-video'); if(a) a.scrollIntoView({behavior:'smooth',block:'nearest'}); } } function plRender(){ @@ -628,7 +627,7 @@ var v=document.getElementById('videoPlayer'); if(v&&plLoop==='one') v.loop=true; plRender(); - plHighlight(PL_CURRENT); + plHighlight(PL_CURRENT, false); } if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',plInit); else plInit(); })(); diff --git a/resources/views/videos/types/match.blade.php b/resources/views/videos/types/match.blade.php index 8679876..9d54a61 100644 --- a/resources/views/videos/types/match.blade.php +++ b/resources/views/videos/types/match.blade.php @@ -2619,7 +2619,7 @@ PL_CURRENT=d.id; plRender(); - plHighlight(d.id); + plHighlight(d.id, true); if(pushHist!==false) history.pushState({plVideoId:d.id,url:url},'',url); plSwapContent(url); @@ -2657,12 +2657,11 @@ } catch(e){ console.warn('plSwapContent',e); } } - function plHighlight(activeId){ + function plHighlight(activeId, scroll){ document.querySelectorAll('.sidebar-video-card[data-pl-id]').forEach(function(c){ c.classList.toggle('current-video',parseInt(c.dataset.plId)===activeId); }); - var a=document.querySelector('.sidebar-video-card.current-video'); - if(a) a.scrollIntoView({behavior:'smooth',block:'nearest'}); + if(scroll){ var a=document.querySelector('.sidebar-video-card.current-video'); if(a) a.scrollIntoView({behavior:'smooth',block:'nearest'}); } } function plRender(){ @@ -2700,7 +2699,7 @@ var v=document.getElementById('videoPlayer'); if(v&&plLoop==='one') v.loop=true; plRender(); - plHighlight(PL_CURRENT); + plHighlight(PL_CURRENT, false); } if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',plInit); else plInit(); })(); diff --git a/resources/views/videos/types/music.blade.php b/resources/views/videos/types/music.blade.php index ee06206..9e40d8c 100644 --- a/resources/views/videos/types/music.blade.php +++ b/resources/views/videos/types/music.blade.php @@ -566,7 +566,7 @@ PL_CURRENT = d.id; if(audio&&plLoop==='one') audio.loop=true; else if(audio) audio.loop=false; plRender(); - plHighlight(d.id); + plHighlight(d.id, true); // history if(pushHist!==false) history.pushState({plVideoId:d.id,url:url},'',url); @@ -615,12 +615,14 @@ } // ── sidebar highlight ──────────────────────────────────── - function plHighlight(activeId) { + function plHighlight(activeId, scroll) { document.querySelectorAll('.sidebar-video-card[data-pl-id]').forEach(function(c){ c.classList.toggle('current-video', parseInt(c.dataset.plId)===activeId); }); - var active=document.querySelector('.sidebar-video-card.current-video'); - if(active) active.scrollIntoView({behavior:'smooth',block:'nearest'}); + if(scroll) { + var active=document.querySelector('.sidebar-video-card.current-video'); + if(active) active.scrollIntoView({behavior:'smooth',block:'nearest'}); + } } // ── render control button states ───────────────────────── @@ -658,7 +660,7 @@ var a=document.getElementById('audioEl'); if(a&&plLoop==='one') a.loop=true; plRender(); - plHighlight(PL_CURRENT); + plHighlight(PL_CURRENT, false); } if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',plInit); else plInit(); })();