Show video controls on iOS mobile devices by default (#30737)

* Add controls for Safari iOS video autoplay

* Show controls for all iOS mobile devices

GitOrigin-RevId: a086b127c1e56543a08341474b77de57171ea8c2
This commit is contained in:
Rebeka Dekany
2026-01-14 13:35:19 +01:00
committed by Copybot
parent 6c76d1cd4c
commit 7e19998d15

View File

@@ -7,7 +7,23 @@ function enableControls(videoEl, reason) {
videoEl.setAttribute('controls', '')
}
function isIOS() {
if (typeof navigator === 'undefined') {
return false
}
// Detects iPhone/iPod and iPad in mobile mode
// Note: Modern iPad in desktop mode reports as Mac in UA and is intentionally not detected
// to allow autoplay if the browser permits it
return /iPad|iPhone|iPod/.test(navigator.userAgent)
}
function setup(videoEl) {
// iOS has strict autoplay policies - always show controls first
if (isIOS()) {
enableControls(videoEl, 'iOS devices')
return
}
const reducedMotionReduce = window.matchMedia(
'(prefers-reduced-motion: reduce)'
)
@@ -46,12 +62,23 @@ function setup(videoEl) {
}
}
function attemptPlay() {
if (!videoIsVisible || hasHandledAutoplayFailure) {
return
}
if (videoEl.readyState >= videoEl.HAVE_FUTURE_DATA) {
videoEl.play().catch(handleAutoplayFailure)
}
}
// Retry play when video has enough data
videoEl.addEventListener('canplay', attemptPlay, { once: true })
videoEl.addEventListener('loadeddata', attemptPlay, { once: true })
videoEl.addEventListener('ended', () => {
setTimeout(() => {
videoEl.currentTime = 0
if (videoIsVisible && !hasHandledAutoplayFailure) {
videoEl.play().catch(handleAutoplayFailure)
}
attemptPlay()
}, DELAY_BEFORE_REPLAY)
})
@@ -60,12 +87,7 @@ function setup(videoEl) {
for (const change of changes) {
if (change.isIntersecting) {
videoIsVisible = true
if (
!hasHandledAutoplayFailure &&
videoEl.readyState >= videoEl.HAVE_FUTURE_DATA
) {
videoEl.play().catch(handleAutoplayFailure)
}
attemptPlay()
} else {
videoIsVisible = false
// Pause video when it leaves viewport to save resources