UNPKG

4.7 kBTypeScriptView Raw
1import * as React from 'react';
2import { View, createElement } from 'react-native';
3
4import { AVPlaybackNativeSource, AVPlaybackStatus, AVPlaybackStatusToSet } from './AV';
5import ExponentAV from './ExponentAV';
6
7type ExponentVideoProps = {
8 source: AVPlaybackNativeSource | null;
9 resizeMode?: object;
10 status?: AVPlaybackStatusToSet;
11 useNativeControls?: boolean;
12 onStatusUpdate?: (event: { nativeEvent: AVPlaybackStatus }) => void;
13 onReadyForDisplay?: (event: { nativeEvent: object }) => void;
14 onFullscreenUpdate?: (event: { nativeEvent: object }) => void;
15 onLoadStart: () => void;
16 onLoad: (event: { nativeEvent: AVPlaybackStatus }) => void;
17 onError: (event: { nativeEvent: { error: string } }) => void;
18 // Required by react-native
19 scaleX?: number;
20 scaleY?: number;
21 translateX?: number;
22 translateY?: number;
23 rotation?: number;
24} & React.ComponentProps<typeof View>;
25
26export type NaturalSize = {
27 width: number;
28 height: number;
29 orientation: 'portrait' | 'landscape';
30};
31
32export const FULLSCREEN_UPDATE_PLAYER_WILL_PRESENT = 0;
33export const FULLSCREEN_UPDATE_PLAYER_DID_PRESENT = 1;
34export const FULLSCREEN_UPDATE_PLAYER_WILL_DISMISS = 2;
35export const FULLSCREEN_UPDATE_PLAYER_DID_DISMISS = 3;
36
37export const IOS_FULLSCREEN_UPDATE_PLAYER_WILL_PRESENT = FULLSCREEN_UPDATE_PLAYER_WILL_PRESENT;
38export const IOS_FULLSCREEN_UPDATE_PLAYER_DID_PRESENT = FULLSCREEN_UPDATE_PLAYER_DID_PRESENT;
39export const IOS_FULLSCREEN_UPDATE_PLAYER_WILL_DISMISS = FULLSCREEN_UPDATE_PLAYER_WILL_DISMISS;
40export const IOS_FULLSCREEN_UPDATE_PLAYER_DID_DISMISS = FULLSCREEN_UPDATE_PLAYER_DID_DISMISS;
41
42const Video: any = React.forwardRef((props, ref) => createElement('video', { ...props, ref }));
43
44export default class ExponentVideo extends React.Component<ExponentVideoProps> {
45 _video?: HTMLVideoElement;
46
47 componentDidMount() {
48 const isIE11 = !!window['MSStream'];
49 document.addEventListener(
50 isIE11 ? 'MSFullscreenChange' : 'fullscreenchange',
51 this.onFullscreenChange
52 );
53 }
54
55 componentWillUnmount() {
56 const isIE11 = !!window['MSStream'];
57 document.addEventListener(
58 isIE11 ? 'MSFullscreenChange' : 'fullscreenchange',
59 this.onFullscreenChange
60 );
61 }
62
63 onFullscreenChange = event => {
64 if (!this.props.onFullscreenUpdate) return;
65
66 if (event.target === this._video) {
67 if (document.fullscreenElement) {
68 this.props.onFullscreenUpdate({
69 nativeEvent: { fullscreenUpdate: FULLSCREEN_UPDATE_PLAYER_DID_PRESENT },
70 });
71 } else {
72 this.props.onFullscreenUpdate({
73 nativeEvent: { fullscreenUpdate: FULLSCREEN_UPDATE_PLAYER_DID_DISMISS },
74 });
75 }
76 }
77 };
78
79 onStatusUpdate = async () => {
80 if (!this.props.onStatusUpdate) {
81 return;
82 }
83 const nativeEvent = await ExponentAV.getStatusForVideo(this._video);
84 this.props.onStatusUpdate({ nativeEvent });
85 };
86
87 onLoadStart = () => {
88 if (!this.props.onLoadStart) {
89 return;
90 }
91 this.props.onLoadStart();
92 this.onStatusUpdate();
93 };
94
95 onLoadedData = event => {
96 if (!this.props.onLoad) {
97 return;
98 }
99 this.props.onLoad(event);
100 this.onStatusUpdate();
101 };
102
103 onError = event => {
104 if (!this.props.onError) {
105 return;
106 }
107 this.props.onError(event);
108 this.onStatusUpdate();
109 };
110
111 onProgress = () => {
112 this.onStatusUpdate();
113 };
114
115 onSeeking = () => {
116 this.onStatusUpdate();
117 };
118
119 onEnded = () => {
120 this.onStatusUpdate();
121 };
122
123 onLoadedMetadata = () => {
124 this.onStatusUpdate();
125 };
126
127 onCanPlay = event => {
128 if (!this.props.onReadyForDisplay) {
129 return;
130 }
131 this.props.onReadyForDisplay(event);
132 this.onStatusUpdate();
133 };
134
135 onStalled = () => {
136 this.onStatusUpdate();
137 };
138
139 onRef = (ref: HTMLVideoElement) => {
140 this._video = ref;
141 this.onStatusUpdate();
142 };
143
144 render() {
145 const { source, status = {}, resizeMode: objectFit, useNativeControls, style } = this.props;
146
147 const customStyle = {
148 position: undefined,
149 objectFit,
150 overflow: 'hidden',
151 };
152 return (
153 <Video
154 ref={this.onRef}
155 onLoadStart={this.onLoadStart}
156 onLoadedData={this.onLoadedData}
157 onError={this.onError}
158 onTimeUpdate={this.onProgress}
159 onSeeking={this.onSeeking}
160 onEnded={this.onEnded}
161 onLoadedMetadata={this.onLoadedMetadata}
162 onCanPlay={this.onCanPlay}
163 onStalled={this.onStalled}
164 src={(source || { uri: undefined }).uri}
165 muted={status.isMuted}
166 loop={status.isLooping}
167 autoPlay={status.shouldPlay}
168 controls={useNativeControls}
169 style={[style, customStyle]}
170 />
171 );
172 }
173}