Files
ArtPlayer/packages/artplayer/src/display/video-fullscreen.ts
T

88 lines
2.4 KiB
TypeScript

import type { FullscreenHost } from './types'
import { getScope, isClosing } from '../lifecycle/instance'
import { listen } from '../lifecycle/resources'
import { abandonVideo, clearAbandonedVideo, isAbandonedVideo, videoIsFullscreen } from './video-fullscreen-state'
export function videoFullscreen(art: FullscreenHost): PropertyDescriptor {
const { $video } = art.template
const scope = getScope(art).child()
let observed = false
let last = videoIsFullscreen($video)
let desired = last
let pending = false
let revision = 0
const active = () => videoIsFullscreen($video, observed)
function changed(hint?: boolean) {
if (isClosing(art) || isAbandonedVideo($video))
return
if (typeof hint === 'boolean')
observed = hint
const value = active()
if (value)
pending = false
if (value === last)
return
last = value
const current = revision
const stale = () => isClosing(art) || active() !== value || (current !== revision && desired !== value)
art.emit('fullscreen', value)
if (stale())
return
if (value)
art.state = 'fullscreen'
if (!stale())
art.emit('resize')
}
scope.add(() => {
revision++
desired = false
if (pending)
abandonVideo($video)
if (active())
$video.webkitExitFullscreen?.()
})
listen(scope, $video, 'webkitbeginfullscreen', () => changed(true))
listen(scope, $video, 'webkitendfullscreen', () => changed(false))
listen(scope, $video, 'webkitpresentationmodechanged', () => changed())
const documentChanged = () => changed()
art.on('document:webkitfullscreenchange', documentChanged)
scope.add(() => {
art.off('document:webkitfullscreenchange', documentChanged)
})
return {
get: () => !isClosing(art) && active(),
set(value: boolean): void {
if (isClosing(art))
return
const current = ++revision
desired = Boolean(value)
if (value) {
clearAbandonedVideo($video)
art.state = 'fullscreen'
if (isClosing(art) || current !== revision)
return
pending = true
try {
$video.webkitEnterFullscreen!()
}
catch (error) {
if (current === revision)
pending = false
throw error
}
}
else {
if (pending) {
pending = false
abandonVideo($video)
}
if (active())
$video.webkitExitFullscreen!()
}
},
}
}