From 962a89c3a664586fd28f67b96bf7a2ae06798ec1 Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Wed, 21 Jan 2026 10:47:57 -0500 Subject: [PATCH] Add mobile support and responsive player controls - Mobile devices open player in new tab (better than PiP) - Add playsInline attribute for iOS autoplay support - Responsive controls: hide PiP/auto-resize/always-on-top on mobile - Implement togglePip function for desktop PiP button - Optimize button sizes and spacing for touch screens - Detect mobile via user agent and fallback gracefully --- make_post_sell/static/js/player.js | 20 ++++++++++++ make_post_sell/templates/content.j2 | 12 ++++++- make_post_sell/templates/player.j2 | 49 +++++++++++++++++++++++++++-- make_post_sell/templates/product.j2 | 12 ++++++- 4 files changed, 89 insertions(+), 4 deletions(-) diff --git a/make_post_sell/static/js/player.js b/make_post_sell/static/js/player.js index 63554cf..c05c43f 100644 --- a/make_post_sell/static/js/player.js +++ b/make_post_sell/static/js/player.js @@ -41,6 +41,26 @@ } }; + /** + * Toggle Picture-in-Picture mode + */ + window.togglePip = async function() { + if (!document.pictureInPictureEnabled || !media || media.tagName !== 'VIDEO') { + alert('Picture-in-Picture is not supported for this media'); + return; + } + + try { + if (document.pictureInPictureElement) { + await document.exitPictureInPicture(); + } else { + await media.requestPictureInPicture(); + } + } catch (err) { + console.error('Error toggling PiP:', err); + } + }; + /** * Toggle fullscreen mode */ diff --git a/make_post_sell/templates/content.j2 b/make_post_sell/templates/content.j2 index ac93d0a..224dbc8 100644 --- a/make_post_sell/templates/content.j2 +++ b/make_post_sell/templates/content.j2 @@ -128,7 +128,16 @@ async function loadMedia(mediaElement, productId) { } async function openMediaPlayer(productId) { - // Fetch player data to get media URL and navigation info + // Mobile detection + const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); + + // On mobile, open in new tab (works better than PiP) + if (isMobile) { + window.open(`/player/${productId}`, '_blank'); + return; + } + + // Desktop: Fetch player data to get media URL and navigation info try { const response = await fetch(`/player/${productId}`); const html = await response.text(); @@ -154,6 +163,7 @@ async function openMediaPlayer(productId) { media.style.zIndex = '9999'; media.controls = true; media.autoplay = true; + media.playsInline = true; // Important for iOS document.body.appendChild(media); // Extract playerData from script diff --git a/make_post_sell/templates/player.j2 b/make_post_sell/templates/player.j2 index 2cfafa6..359e41f 100644 --- a/make_post_sell/templates/player.j2 +++ b/make_post_sell/templates/player.j2 @@ -40,6 +40,46 @@ display: block; } + /* Mobile optimizations */ + @media (max-width: 600px) { + .controls-grid { + padding: 1rem; + gap: 0.5rem; + font-size: 0.9rem; + grid-template-columns: 1fr 1fr 1fr; + } + + .controls-grid button { + padding: 0.6rem 0.8rem; + font-size: 0.9rem; + min-width: 80px; + } + + .controls-grid button.nav-btn, + .controls-grid button.play-btn { + font-size: 1.3rem; + padding: 0.8rem; + } + + .product-title { + font-size: 1rem; + padding: 0.4rem 0.8rem; + } + + /* Hide desktop-only buttons on mobile */ + #pipBtn, + #autoResizeBtn, + #alwaysOnTopBtn { + display: none; + } + + /* Adjust grid for mobile - only show essential buttons */ + .controls-grid { + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: auto auto; + } + } + /* Player controls overlay - centered grid */ .player-controls { grid-area: media; @@ -137,11 +177,11 @@
{% if media_type == 'video' %} -
diff --git a/make_post_sell/templates/product.j2 b/make_post_sell/templates/product.j2 index 2f9a81a..fbcdf61 100644 --- a/make_post_sell/templates/product.j2 +++ b/make_post_sell/templates/product.j2 @@ -206,7 +206,16 @@ async function loadMedia(mediaElement, productId) { } async function openMediaPlayer(productId) { - // Fetch player data to get media URL and navigation info + // Mobile detection + const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); + + // On mobile, open in new tab (works better than PiP) + if (isMobile) { + window.open(`/player/${productId}`, '_blank'); + return; + } + + // Desktop: Fetch player data to get media URL and navigation info try { const response = await fetch(`/player/${productId}`); const html = await response.text(); @@ -232,6 +241,7 @@ async function openMediaPlayer(productId) { media.style.zIndex = '9999'; media.controls = true; media.autoplay = true; + media.playsInline = true; // Important for iOS document.body.appendChild(media); // Extract playerData from script