mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-27 01:21:20 -08:00
refactor(core): CORE-06 type media surfaces and playback hosts
This commit is contained in:
1 parent
97d320bd74
commit
ee859e4804
27 files changed
+2152
-79
No files matched your search
@@ -0,0 +1,33 @@
|
||||
import type { ResolvedOption } from '../option/types'
|
||||
import type { PlaybackMethods } from './types'
|
||||
|
||||
export interface MediaHost<Media> {
|
||||
template: { $video: Media }
|
||||
}
|
||||
|
||||
interface NoticeHost {
|
||||
i18n: { get: (key: string) => string }
|
||||
notice: { get show(): unknown, set show(value: string | Error) }
|
||||
emit: (name: 'play' | 'pause') => unknown
|
||||
}
|
||||
|
||||
export type PauseHost<Media extends Pick<PlaybackMethods, 'pause'>> = MediaHost<Media> & NoticeHost
|
||||
|
||||
interface PauseTarget {
|
||||
pause: () => unknown
|
||||
}
|
||||
|
||||
export type PlayHost<Media extends Pick<PlaybackMethods, 'play'>> = MediaHost<Media> & NoticeHost & Partial<PauseTarget> & {
|
||||
option: Pick<ResolvedOption, 'mutex'>
|
||||
constructor: { instances: PauseTarget[] }
|
||||
}
|
||||
|
||||
export interface LayoutHost {
|
||||
template: { $player: Pick<Element, 'getBoundingClientRect'> }
|
||||
}
|
||||
|
||||
export type RectState = Readonly<Pick<DOMRect, 'bottom' | 'height' | 'left' | 'right' | 'top' | 'width'>> & {
|
||||
readonly rect: DOMRect
|
||||
readonly x: number
|
||||
readonly y: number
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
export type MediaState = Pick<HTMLMediaElement, 'currentTime' | 'duration' | 'paused' | 'ended' | 'readyState'> & {
|
||||
readonly playing?: boolean
|
||||
}
|
||||
|
||||
export interface PlaybackMethods<PlayResult = unknown, PauseResult = unknown> {
|
||||
play: () => PlayResult
|
||||
pause: () => PauseResult
|
||||
}
|
||||
|
||||
export interface OptionalMediaCapabilities {
|
||||
readonly textTracks?: ArrayLike<TextTrack>
|
||||
readonly error?: unknown
|
||||
requestPictureInPicture?: () => Promise<PictureInPictureWindow>
|
||||
requestVideoFrameCallback?: (callback: VideoFrameRequestCallback) => number
|
||||
cancelVideoFrameCallback?: (handle: number) => void
|
||||
webkitEnterFullscreen?: () => void
|
||||
webkitExitFullscreen?: () => void
|
||||
readonly webkitSupportsFullscreen?: boolean
|
||||
webkitShowPlaybackTargetPicker?: () => void
|
||||
webkitSupportsPresentationMode?: (mode: string) => boolean
|
||||
webkitSetPresentationMode?: (mode: string) => void
|
||||
readonly webkitPresentationMode?: string
|
||||
readonly webkitDisplayingFullscreen?: boolean
|
||||
}
|
||||
|
||||
export type NativeMedia = Omit<HTMLVideoElement, keyof OptionalMediaCapabilities> & OptionalMediaCapabilities
|
||||
|
||||
export type CanvasMedia = HTMLCanvasElement & MediaState & PlaybackMethods & OptionalMediaCapabilities & {
|
||||
src: string | null
|
||||
readonly currentSrc: string | null
|
||||
readonly videoWidth: number
|
||||
readonly videoHeight: number
|
||||
readonly buffered: TimeRanges
|
||||
volume: number
|
||||
muted: boolean
|
||||
playbackRate: number
|
||||
load: () => unknown
|
||||
}
|
||||
|
||||
export type MediaSurface = NativeMedia | CanvasMedia
|
||||
@@ -1,12 +0,0 @@
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function durationMix(art) {
|
||||
def(art, 'duration', {
|
||||
get: () => {
|
||||
const { duration } = art.template.$video
|
||||
if (duration === Infinity)
|
||||
return 0
|
||||
return duration || 0
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import type { MediaHost } from '../media/hosts'
|
||||
import type { MediaState } from '../media/types'
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function durationMix(art: MediaHost<Pick<MediaState, 'duration'>>): asserts art is MediaHost<Pick<MediaState, 'duration'>> & { readonly duration: number } {
|
||||
def(art, 'duration', {
|
||||
get: () => {
|
||||
const { duration } = art.template.$video
|
||||
if (duration === Infinity)
|
||||
return 0
|
||||
return duration || 0
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function pauseMix(art) {
|
||||
const {
|
||||
template: { $video },
|
||||
i18n,
|
||||
notice,
|
||||
} = art
|
||||
|
||||
def(art, 'pause', {
|
||||
value() {
|
||||
const result = $video.pause()
|
||||
notice.show = i18n.get('Pause')
|
||||
art.emit('pause')
|
||||
return result
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { PauseHost } from '../media/hosts'
|
||||
import type { PlaybackMethods } from '../media/types'
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function pauseMix<Media extends Pick<PlaybackMethods, 'pause'>>(art: PauseHost<Media>): asserts art is PauseHost<Media> & { pause: () => ReturnType<Media['pause']> } {
|
||||
const {
|
||||
template: { $video },
|
||||
i18n,
|
||||
notice,
|
||||
} = art
|
||||
|
||||
def(art, 'pause', {
|
||||
value() {
|
||||
const result = $video.pause()
|
||||
notice.show = i18n.get('Pause')
|
||||
art.emit('pause')
|
||||
return result
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { PlayHost } from '../media/hosts'
|
||||
import type { PlaybackMethods } from '../media/types'
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function playMix(art) {
|
||||
export default function playMix<Media extends Pick<PlaybackMethods, 'play'>>(art: PlayHost<Media>): asserts art is PlayHost<Media> & { play: () => Promise<Awaited<ReturnType<Media['play']>>> } {
|
||||
const {
|
||||
i18n,
|
||||
notice,
|
||||
@@ -17,7 +19,7 @@ export default function playMix(art) {
|
||||
|
||||
if (option.mutex) {
|
||||
for (let index = 0; index < instances.length; index++) {
|
||||
const instance = instances[index]
|
||||
const instance = instances[index]!
|
||||
if (instance !== art) {
|
||||
instance.pause()
|
||||
}
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
import type { MediaHost } from '../media/hosts'
|
||||
import type { MediaState } from '../media/types'
|
||||
import { def } from '../utils'
|
||||
|
||||
export default function playingMix(art) {
|
||||
export default function playingMix(art: MediaHost<Omit<MediaState, 'duration'>>): asserts art is MediaHost<Omit<MediaState, 'duration'>> & { readonly playing: boolean } {
|
||||
const { $video } = art.template
|
||||
def(art, 'playing', {
|
||||
get: () => {
|
||||
@@ -1,31 +0,0 @@
|
||||
import { def, getRect } from '../utils'
|
||||
|
||||
export default function rectMix(art) {
|
||||
def(art, 'rect', {
|
||||
get: () => {
|
||||
return getRect(art.template.$player)
|
||||
},
|
||||
})
|
||||
|
||||
const keys = ['bottom', 'height', 'left', 'right', 'top', 'width']
|
||||
for (let index = 0; index < keys.length; index++) {
|
||||
const key = keys[index]
|
||||
def(art, key, {
|
||||
get: () => {
|
||||
return art.rect[key]
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
def(art, 'x', {
|
||||
get: () => {
|
||||
return art.left + window.pageXOffset
|
||||
},
|
||||
})
|
||||
|
||||
def(art, 'y', {
|
||||
get: () => {
|
||||
return art.top + window.pageYOffset
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { LayoutHost, RectState } from '../media/hosts'
|
||||
import { def, getRect } from '../utils'
|
||||
|
||||
export default function rectMix(art: LayoutHost): asserts art is LayoutHost & RectState {
|
||||
// These properties are installed below; no native media element is asserted.
|
||||
const host = art as LayoutHost & RectState
|
||||
def(art, 'rect', {
|
||||
get: () => {
|
||||
return getRect(art.template.$player)
|
||||
},
|
||||
})
|
||||
|
||||
const keys = ['bottom', 'height', 'left', 'right', 'top', 'width'] as const
|
||||
for (let index = 0; index < keys.length; index++) {
|
||||
const key = keys[index]!
|
||||
def(art, key, {
|
||||
get: () => {
|
||||
return host.rect[key]
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
def(art, 'x', {
|
||||
get: () => {
|
||||
return host.left + window.pageXOffset
|
||||
},
|
||||
})
|
||||
|
||||
def(art, 'y', {
|
||||
get: () => {
|
||||
return host.top + window.pageYOffset
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user