Add native Picture-in-Picture support and debug ended event
Picture-in-Picture (PiP) improvements: - Add native browser PiP button for videos (P key or 📺 button) - PiP has true OS-level always-on-top when you right-click and select "Keep on top" - PiP works on mobile and desktop with browser's native implementation - Button shows on mobile (PiP is useful on mobile devices) - Active state toggles button text between "📺 PiP" and "📺 Exit PiP" Debug 'ended' event not firing: - Add explicit ended event listener with console logging - Log when media starts playing - Log playback progress every 5 seconds - This will help identify why auto-advance isn't working The native PiP API provides better always-on-top than our window.focus() approach because it's implemented at the OS level by the browser. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
741004b2d2
commit
d244617554
2 changed files with 89 additions and 13 deletions
|
|
@ -381,6 +381,13 @@
|
|||
goToProductPage();
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
e.preventDefault();
|
||||
if (typeof togglePip === 'function') {
|
||||
togglePip();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,10 +72,8 @@
|
|||
}
|
||||
|
||||
/* Hide desktop-only buttons on mobile */
|
||||
#pipBtn,
|
||||
#autoResizeBtn,
|
||||
#alwaysOnTopBtn,
|
||||
#fullscreenBtn {
|
||||
#alwaysOnTopBtn {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
@ -231,8 +229,10 @@
|
|||
|
||||
<!-- Row 2: Features -->
|
||||
<button id="alwaysOnTopBtn" onclick="toggleAlwaysOnTop()" title="Always on Top (T)">📌 On Top</button>
|
||||
{% if media_type == 'video' %}
|
||||
<button id="pipBtn" onclick="togglePip()" title="Picture-in-Picture (P) - Right-click PiP for true always-on-top">📺 PiP</button>
|
||||
{% endif %}
|
||||
<button onclick="goToProductPage()" title="Go to Product Page (G)">🔗 Page</button>
|
||||
<span></span><!-- Empty cell for grid alignment -->
|
||||
|
||||
<!-- Row 3: More options -->
|
||||
<button id="autoResizeBtn" onclick="toggleAutoResize()" title="Auto-Resize Window (R)">↔ Resize</button>
|
||||
|
|
@ -260,6 +260,41 @@
|
|||
window.open(window.playerData.productUrl, '_blank');
|
||||
}
|
||||
|
||||
// Toggle native Picture-in-Picture (true always-on-top via browser)
|
||||
function togglePip() {
|
||||
const media = document.getElementById('media');
|
||||
if (!media || media.tagName !== 'VIDEO') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (document.pictureInPictureElement) {
|
||||
document.exitPictureInPicture().catch(err => {
|
||||
console.error('Failed to exit PiP:', err);
|
||||
});
|
||||
} else {
|
||||
media.requestPictureInPicture().catch(err => {
|
||||
console.error('Failed to enter PiP:', err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Update PiP button state
|
||||
document.addEventListener('enterpictureinpicture', () => {
|
||||
const pipBtn = document.getElementById('pipBtn');
|
||||
if (pipBtn) {
|
||||
pipBtn.classList.add('active');
|
||||
pipBtn.textContent = '📺 Exit PiP';
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('leavepictureinpicture', () => {
|
||||
const pipBtn = document.getElementById('pipBtn');
|
||||
if (pipBtn) {
|
||||
pipBtn.classList.remove('active');
|
||||
pipBtn.textContent = '📺 PiP';
|
||||
}
|
||||
});
|
||||
|
||||
// Mobile: tap to show/hide controls
|
||||
let hideTimeout;
|
||||
const isMobile = window.innerWidth <= 600;
|
||||
|
|
@ -314,17 +349,51 @@
|
|||
if (media && (media.tagName === 'VIDEO' || media.tagName === 'AUDIO')) {
|
||||
// Try to play muted first (allowed by most browsers)
|
||||
media.muted = true;
|
||||
media.play().then(() => {
|
||||
// Once playing, unmute after a short delay
|
||||
setTimeout(() => {
|
||||
media.muted = false;
|
||||
}, 100);
|
||||
}).catch(err => {
|
||||
console.log('Autoplay failed:', err);
|
||||
// User will need to tap play button
|
||||
});
|
||||
const playPromise = media.play();
|
||||
if (playPromise !== undefined) {
|
||||
playPromise.then(() => {
|
||||
// Once playing, unmute after a short delay
|
||||
setTimeout(() => {
|
||||
media.muted = false;
|
||||
}, 100);
|
||||
}).catch(err => {
|
||||
console.log('Autoplay failed:', err);
|
||||
// User will need to tap play button
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Debug: Add ended event listener to verify it works
|
||||
(function() {
|
||||
const media = document.getElementById('media');
|
||||
if (media && (media.tagName === 'VIDEO' || media.tagName === 'AUDIO')) {
|
||||
media.addEventListener('ended', function() {
|
||||
console.log('Media ended event fired!');
|
||||
if (window.playerData && window.playerData.nextProductId) {
|
||||
console.log('Navigating to next:', window.playerData.nextProductId);
|
||||
window.location.href = '/player/' + window.playerData.nextProductId;
|
||||
} else {
|
||||
console.log('No next product available');
|
||||
}
|
||||
});
|
||||
|
||||
// Debug: Log when media is playing
|
||||
media.addEventListener('play', function() {
|
||||
console.log('Media started playing');
|
||||
});
|
||||
|
||||
// Debug: Log time updates to verify playback
|
||||
let lastLogTime = 0;
|
||||
media.addEventListener('timeupdate', function() {
|
||||
const currentTime = Math.floor(media.currentTime);
|
||||
if (currentTime > lastLogTime && currentTime % 5 === 0) {
|
||||
console.log('Playback at:', currentTime + 's / ' + Math.floor(media.duration) + 's');
|
||||
lastLogTime = currentTime;
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue