UNPKG

@mpxjs/webpack-plugin

Version:

mpx compile core

254 lines (253 loc) 8.92 kB
/** * ✔ src * ✘ duration * ✔ controls * ✘ danmu-list * ✘ danmu-btn * ✘ enable-danmu * ✔ autoplay * ✔ loop * ✔ muted * ✔ initial-time * ✘ page-gesture * ✘ direction * ✘ show-progress * ✘ show-fullscreen-btn * ✘ show-play-btn * ✘ show-center-play-btn * ✘ enable-progress-gesture * ✔ object-fit * ✔ poster * ✘ show-mute-btn * ✘ title * ✘ play-btn-position * ✘ enable-play-gesture * ✘ auto-pause-if-navigate * ✘ auto-pause-if-open-native * ✘ vslide-gesture * ✘ vslide-gesture-in-fullscreen * ✘ show-bottom-progress(use show-progress) * ✘ ad-unit-id * ✘ poster-for-crawler * ✘ show-casting-button * ✘ picture-in-picture-mode * ✘ picture-in-picture-show-progress * ✘ picture-in-picture-init-position * ✔ enable-auto-rotation (only ios) * ✘ show-screen-lock-button * ✘ show-snapshot-button * ✘ show-background-playback-button * ✘ background-poster * ✘ referrer-policy * ✔ is-drm * ✘ is-live * ✔ provision-url(android) * ✔ certificate-url(ios) * ✔ license-url * ✔ preferred-peak-bit-rate * ✔ bindplay * ✔ bindpause * ✔ bindended * ✘ bindtimeupdate * ✔ bindfullscreenchange * ✔ bindwaiting * ✔ binderror * ✘ bindprogress * ✔ bindloadedmetadata * ✔ bindcontrolstoggle(only android) * ✘ bindenterpictureinpicture * ✘ bindleavepictureinpicture * ✔ bindseekcomplete * ✘ bindcastinguserselect * ✘ bindcastingstatechange * ✘ bindcastinginterrupt */ import { useRef, forwardRef, createElement } from 'react'; import Video, { DRMType } from 'react-native-video'; import { StyleSheet, View } from 'react-native'; import { splitProps, useTransformStyle, useLayout, extendObject } from './utils'; import useInnerProps, { getCustomEvent } from './getInnerListeners'; import useNodesRef from './useNodesRef'; import Portal from './mpx-portal'; const styles = StyleSheet.create({ container: { width: 300, height: 225 }, video: { flex: 1 } }); const MpxVideo = forwardRef((videoProps, ref) => { const { innerProps: props = {} } = splitProps(videoProps); const { src, autoplay = false, loop = false, muted = false, controls = true, poster = '', bindplay, bindpause, bindended, bindtimeupdate, bindfullscreenchange, bindwaiting, binderror, bindloadedmetadata, bindcontrolstoggle, bindseekcomplete, style, 'initial-time': initialTime = 0, 'object-fit': objectFit = 'contain', 'is-drm': isDrm = false, 'provision-url': provisionUrl, 'certificate-url': certificateUrl, 'license-url': licenseUrl, 'preferred-peak-bit-rate': preferredPeakBitRate = 0, 'enable-auto-rotation': enableAutoRotation = false, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight } = props; const videoRef = useRef(null); const viewRef = useRef(null); const videoInfoRef = useRef({}); const propsRef = useRef({}); propsRef.current = props; const { normalStyle, hasSelfPercent, setWidth, setHeight, hasPositionFixed } = useTransformStyle(extendObject({}, styles.container, style), { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight }); const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef: viewRef }); useNodesRef(props, ref, viewRef, { style: normalStyle, node: { play, pause, stop, seek, requestFullScreen, exitFullScreen } }); function handleProgress(data) { const { currentTime } = data; bindtimeupdate && bindtimeupdate(getCustomEvent('timeupdate', {}, { detail: { currentTime, duration: videoInfoRef.current.duration }, layoutRef }, propsRef.current)); } function handleEnd() { bindended(getCustomEvent('end', {}, { layoutRef }, propsRef.current)); } function handleWaiting({ isBuffering }) { if (isBuffering) { bindwaiting(getCustomEvent('waiting', {}, { layoutRef }, propsRef.current)); } } function handleSeekcomplete({ seekTime }) { // 手动拖拽进度条场景,android 可以触发,ios 不可以 bindseekcomplete(getCustomEvent('seekcomplete', {}, { detail: { position: __mpx_mode__ !== 'ios' ? seekTime * 1000 : seekTime }, layoutRef }, propsRef.current)); } function handleEnterFullScreen() { bindfullscreenchange && bindfullscreenchange(getCustomEvent('fullscreenchange', {}, { detail: { fullScreen: 1 }, layoutRef }, propsRef.current)); } function handleExitFullScreen() { bindfullscreenchange && bindfullscreenchange(getCustomEvent('fullscreenchange', {}, { detail: { fullScreen: 0 }, layoutRef }, propsRef.current)); } function handlePlaybackRateChange({ playbackRate }) { if (playbackRate === 0) { bindpause && bindpause(getCustomEvent('pause', {}, { layoutRef }, propsRef.current)); } else { bindplay && bindplay(getCustomEvent('play', {}, { layoutRef }, propsRef.current)); } } function handleAndroidControlsVisibilityChange({ isVisible }) { bindcontrolstoggle(getCustomEvent('progress', {}, { detail: { show: isVisible }, layoutRef }, propsRef.current)); } function handleVideoLoad(data) { const { naturalSize, duration } = data; if (initialTime) { videoRef.current && videoRef.current.seek(initialTime); } videoInfoRef.current = data; bindloadedmetadata && bindloadedmetadata(getCustomEvent('loadedmetadata', {}, { detail: { width: naturalSize.width, height: naturalSize.height, duration }, layoutRef }, propsRef.current)); } function handleError({ error }) { binderror && binderror(getCustomEvent('play', {}, { detail: { errMsg: error.localizedFailureReason }, layoutRef }, propsRef.current)); } function play() { videoRef.current && videoRef.current.resume(); } function pause() { videoRef.current && videoRef.current.pause(); } function seek(position) { videoRef.current && videoRef.current.seek(position); } function stop() { videoRef.current && videoRef.current.pause(); seek(0); } function exitFullScreen() { videoRef.current && videoRef.current.setFullScreen(false); } function requestFullScreen() { videoRef.current && videoRef.current.setFullScreen(true); } const source = { uri: src }; if (isDrm) { source.drm = { type: DRMType.FAIRPLAY, certificateUrl: __mpx_mode__ !== 'ios' ? provisionUrl : certificateUrl, licenseServer: licenseUrl }; } const innerProps = useInnerProps(extendObject({}, props, layoutProps, { style: styles.video, ref: videoRef, source, paused: !autoplay, repeat: loop, muted, controls, maxBitRate: preferredPeakBitRate, fullscreenAutorotate: enableAutoRotation, resizeMode: objectFit === 'fill' ? 'stretch' : objectFit, poster: controls ? poster : '', onProgress: bindtimeupdate && handleProgress, onEnd: bindended && handleEnd, onError: binderror && handleError, onBuffer: bindwaiting && handleWaiting, onSeek: bindseekcomplete && handleSeekcomplete, onPlaybackRateChange: (bindpause || bindplay) && handlePlaybackRateChange, onFullscreenPlayerDidPresent: bindfullscreenchange && handleEnterFullScreen, onFullscreenPlayerWillDismiss: bindfullscreenchange && handleExitFullScreen, onControlsVisibilityChange: bindcontrolstoggle && handleAndroidControlsVisibilityChange, onLoad: handleVideoLoad }), [ 'src', 'autoplay', 'loop', 'bindplay', 'bindpause', 'bindended', 'bindtimeupdate', 'bindfullscreenchange', 'bindwaiting', 'binderror', 'bindloadedmetadata', 'bindcontrolstoggle', 'bindseekcomplete' ], { layoutRef }); let videoComponent = createElement(View, { style: extendObject({}, normalStyle, layoutStyle), ref: viewRef }, createElement(Video, innerProps)); if (hasPositionFixed) { videoComponent = createElement(Portal, null, videoComponent); } return videoComponent; }); export default MpxVideo;