* Copyright (c) 2022 - present TinyVue Authors.
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import { on, off } from '../dom'
import { isServer } from '../globalConfig'
interface FullscreenEvents {
fullscreenElement: string
fullscreenEnabled: string
requestFullscreen: string
exitFullscreen: string
fullscreenchange: string
fullscreenerror: string
[key: string]: string
}
interface Screenfull {
request: (element?: any, options?: any) => Promise<void>
exit: () => Promise<void>
toggle: (element?: any, options?: any) => Promise<void>
onchange: (callback: any) => void
onerror: (callback: any) => void
on: (event: string, callback: any) => void
off: (event: string, callback: any) => void
raw: FullscreenEvents | {}
isFullscreen?: boolean
element?: any
isEnabled?: boolean
}
const fullscreenApi = [
'fullscreenElement',
'fullscreenEnabled',
'requestFullscreen',
'exitFullscreen',
'fullscreenchange',
'fullscreenerror'
]
const fullscreenApiMoz = [
'mozFullScreenElement',
'mozFullScreenEnabled',
'mozRequestFullScreen',
'mozCancelFullScreen',
'mozfullscreenchange',
'mozfullscreenerror'
]
const fullscreenApiWebkit = [
'webkitFullscreenElement',
'webkitFullscreenEnabled',
'webkitRequestFullscreen',
'webkitExitFullscreen',
'webkitfullscreenchange',
'webkitfullscreenerror'
]
const fullscreenApiMs = [
'msFullscreenElement',
'msFullscreenEnabled',
'msRequestFullscreen',
'msExitFullscreen',
'MSFullscreenChange',
'MSFullscreenError'
]
const fullscreenApiMap = [fullscreenApi, fullscreenApiWebkit, fullscreenApiMoz, fullscreenApiMs]
const document = typeof window !== 'undefined' && typeof window.document !== 'undefined' ? window.document : {}
let fullscreenEvents: FullscreenEvents | null = null
const getFullScreenEvents = () => {
if (isServer) return
for (let i = 0, len = fullscreenApiMap.length; i < len; i++) {
let eventName = fullscreenApiMap[i]
if (eventName && eventName[1] in document) {
fullscreenEvents = {}
for (i = 0; i < eventName.length; i++) {
fullscreenEvents[fullscreenApiMap[0][i]] = eventName[i]
}
return
}
}
}
getFullScreenEvents()
const eventNameMap: { [key: string]: string | undefined } = {
change: fullscreenEvents && fullscreenEvents.fullscreenchange,
error: fullscreenEvents && fullscreenEvents.fullscreenerror
}
const screenfull: Screenfull = {
request(element, options) {
return new Promise((resolve, reject) => {
const onFullscreenEntered = () => {
this.off('change', onFullscreenEntered)
resolve()
}
this.on('change', onFullscreenEntered)
element = element || (!isServer ? document.documentElement : null)
if (element && fullscreenEvents && element[fullscreenEvents.requestFullscreen]) {
const promiseReturn = element[fullscreenEvents.requestFullscreen](options)
if (promiseReturn instanceof Promise) {
promiseReturn.then(onFullscreenEntered).catch(reject)
}
} else {
reject(new Error('Fullscreen API not supported or element is null.'))
}
})
},
exit() {
return new Promise((resolve, reject) => {
if (!this.isFullscreen) {
resolve()
return
}
const onFullscreenExit = () => {
this.off('change', onFullscreenExit)
resolve()
}
this.on('change', onFullscreenExit)
if (!isServer && fullscreenEvents && document[fullscreenEvents.exitFullscreen]) {
const promiseReturn = document[fullscreenEvents.exitFullscreen]()
if (promiseReturn instanceof Promise) {
promiseReturn.then(onFullscreenExit).catch(reject)
}
} else {
reject(new Error('Fullscreen API not supported.'))
}
})
},
toggle(element, options) {
return this.isFullscreen ? this.exit() : this.request(element, options)
},
onchange(callback) {
this.on('change', callback)
},
onerror(callback) {
this.on('error', callback)
},
on(event, callback) {
const eventName = eventNameMap[event]
if (eventName && !isServer) {
on(document, eventName, callback)
}
},
off(event, callback) {
const eventName = eventNameMap[event]
if (eventName && !isServer) {
off(document, eventName, callback)
}
},
raw: fullscreenEvents || {}
}
if (!isServer) {
Object.defineProperties(screenfull, {
isFullscreen: {
get() {
return !!document[fullscreenEvents && fullscreenEvents.fullscreenElement]
}
},
element: {
enumerable: true,
get() {
return document[fullscreenEvents && fullscreenEvents.fullscreenElement]
}
},
isEnabled: {
enumerable: true,
get() {
return !!document[fullscreenEvents && fullscreenEvents.fullscreenEnabled]
}
}
})
} else {
Object.defineProperties(screenfull, {
isFullscreen: {
get() {
return false
}
},
element: {
enumerable: true,
get() {
return null
}
},
isEnabled: {
enumerable: true,
get() {
return false
}
}
})
}
export default screenfull