fix(ios): auto-PiP on app background via visibilitychange

autoPictureInPicture only works with native <video src> playback — not
with MSE (HLS.js). Add a 'visibilitychange' listener that calls
requestPictureInPicture() when the document becomes hidden while a
video is playing. iOS 16+/iPadOS 16+ exempts this event from the
user-gesture requirement, and requestPictureInPicture() works fine with
MSE (same API the player's own PiP button uses).

Falls back to webkitSetPresentationMode('picture-in-picture') if the
Promise is rejected (iOS < 16) or if the standard API is absent.

https://claude.ai/code/session_01X52sah6aUu3ou26uJWHgzr
This commit is contained in:
Claude 2026-06-11 18:52:15 +00:00
parent 37ee5a85c7
commit 57883ec041
No known key found for this signature in database

View file

@ -198,6 +198,37 @@ export function buildMediaSession(): string {
}, true);
installHandlers();
// --- Auto-PiP quand l'app passe en arrière-plan ---
// autoPictureInPicture ne fonctionne pas avec MSE (HLS.js) sur WKWebView.
// iOS 16+/iPadOS 16+ exempte requestPictureInPicture() de la user-gesture
// requirement lorsqu'il est appelé depuis l'event 'visibilitychange' au moment
// où le document devient caché (app mise en arrière-plan / bouton Home).
// requestPictureInPicture() fonctionne bien avec MSE — c'est d'ailleurs l'API
// que le lecteur Movix utilise pour son bouton PiP manuel.
document.addEventListener('visibilitychange', function() {
if (!document.hidden) return;
if (!activeVideo || activeVideo.paused) return;
if (document.pictureInPictureElement) return; // déjà en PiP
// API standard (iOS 16+, iPadOS 16+, Chrome Android)
if (typeof document.pictureInPictureEnabled !== 'undefined' &&
document.pictureInPictureEnabled &&
typeof activeVideo.requestPictureInPicture === 'function') {
activeVideo.requestPictureInPicture().catch(function() {
// Fallback WebKit si la promesse est rejetée (iOS < 16)
if (typeof activeVideo.webkitSetPresentationMode === 'function') {
try { activeVideo.webkitSetPresentationMode('picture-in-picture'); } catch (e2) {}
}
});
return;
}
// Fallback direct pour iOS/iPadOS < 16
if (typeof activeVideo.webkitSetPresentationMode === 'function') {
try { activeVideo.webkitSetPresentationMode('picture-in-picture'); } catch (e) {}
}
});
})();
true;
`;