2023-10-06 10:39:14 -06:00
|
|
|
import React, {
|
|
|
|
useState,
|
|
|
|
useCallback,
|
|
|
|
useMemo,
|
|
|
|
useRef,
|
|
|
|
forwardRef,
|
|
|
|
useImperativeHandle,
|
|
|
|
type ComponentRef,
|
2023-10-07 04:56:35 -06:00
|
|
|
} from 'react';
|
|
|
|
import {View, StyleSheet, Image, Platform} from 'react-native';
|
|
|
|
import NativeVideoComponent, {RCTVideoConstants} from './VideoNativeComponent';
|
|
|
|
import type {
|
|
|
|
NativeVideoResizeMode,
|
|
|
|
OnAudioFocusChangedData,
|
|
|
|
OnAudioTracksData,
|
|
|
|
OnPlaybackStateChangedData,
|
|
|
|
OnTextTracksData,
|
|
|
|
OnTimedMetadataData,
|
|
|
|
OnVideoErrorData,
|
|
|
|
OnVideoTracksData,
|
|
|
|
} from './VideoNativeComponent';
|
|
|
|
|
|
|
|
import type {StyleProp, ImageStyle, NativeSyntheticEvent} from 'react-native';
|
2023-10-06 10:39:14 -06:00
|
|
|
import {
|
|
|
|
type VideoComponentType,
|
|
|
|
type OnLoadData,
|
|
|
|
type OnGetLicenseData,
|
|
|
|
type OnLoadStartData,
|
|
|
|
type OnProgressData,
|
|
|
|
type OnSeekData,
|
|
|
|
type OnPictureInPictureStatusChangedData,
|
|
|
|
type OnBandwidthUpdateData,
|
|
|
|
type OnBufferData,
|
|
|
|
type OnExternalPlaybackChangeData,
|
|
|
|
type OnReceiveAdEventData,
|
|
|
|
VideoManager,
|
2023-10-07 04:56:35 -06:00
|
|
|
} from './VideoNativeComponent';
|
|
|
|
import type {ReactVideoProps} from './types/video';
|
|
|
|
import {getReactTag, resolveAssetSourceForVideo} from './utils';
|
2023-10-06 10:39:14 -06:00
|
|
|
|
|
|
|
export interface VideoRef {
|
|
|
|
seek: (time: number, tolerance?: number) => void;
|
|
|
|
resume: () => void;
|
|
|
|
pause: () => void;
|
|
|
|
presentFullscreenPlayer: () => void;
|
|
|
|
dismissFullscreenPlayer: () => void;
|
2023-10-07 04:56:35 -06:00
|
|
|
restoreUserInterfaceForPictureInPictureStopCompleted: (
|
|
|
|
restore: boolean,
|
|
|
|
) => void;
|
2023-10-06 10:39:14 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
const Video = forwardRef<VideoRef, ReactVideoProps>(
|
|
|
|
(
|
|
|
|
{
|
|
|
|
source,
|
|
|
|
style,
|
|
|
|
resizeMode,
|
|
|
|
posterResizeMode,
|
|
|
|
poster,
|
|
|
|
fullscreen,
|
|
|
|
drm,
|
|
|
|
textTracks,
|
|
|
|
selectedAudioTrack,
|
|
|
|
selectedTextTrack,
|
|
|
|
onLoadStart,
|
|
|
|
onLoad,
|
|
|
|
onError,
|
|
|
|
onProgress,
|
|
|
|
onSeek,
|
|
|
|
onEnd,
|
|
|
|
onBuffer,
|
|
|
|
onBandwidthUpdate,
|
|
|
|
onExternalPlaybackChange,
|
|
|
|
onFullscreenPlayerWillPresent,
|
|
|
|
onFullscreenPlayerDidPresent,
|
|
|
|
onFullscreenPlayerWillDismiss,
|
|
|
|
onFullscreenPlayerDidDismiss,
|
|
|
|
onReadyForDisplay,
|
|
|
|
onPlaybackRateChange,
|
|
|
|
onAudioBecomingNoisy,
|
|
|
|
onPictureInPictureStatusChanged,
|
|
|
|
onRestoreUserInterfaceForPictureInPictureStop,
|
|
|
|
onReceiveAdEvent,
|
|
|
|
onPlaybackStateChanged,
|
|
|
|
onAudioFocusChanged,
|
|
|
|
onIdle,
|
|
|
|
onTimedMetadata,
|
|
|
|
onAudioTracks,
|
|
|
|
onTextTracks,
|
|
|
|
onVideoTracks,
|
|
|
|
...rest
|
|
|
|
},
|
2023-10-07 04:56:35 -06:00
|
|
|
ref,
|
2023-10-06 10:39:14 -06:00
|
|
|
) => {
|
|
|
|
const nativeRef = useRef<ComponentRef<VideoComponentType>>(null);
|
|
|
|
const [showPoster, setShowPoster] = useState(!!poster);
|
|
|
|
const [isFullscreen, setIsFullscreen] = useState(fullscreen);
|
|
|
|
const [
|
|
|
|
_restoreUserInterfaceForPIPStopCompletionHandler,
|
|
|
|
setRestoreUserInterfaceForPIPStopCompletionHandler,
|
|
|
|
] = useState<boolean | undefined>();
|
|
|
|
|
|
|
|
const posterStyle = useMemo<StyleProp<ImageStyle>>(
|
|
|
|
() => ({
|
|
|
|
...StyleSheet.absoluteFillObject,
|
|
|
|
resizeMode:
|
2023-10-07 04:56:35 -06:00
|
|
|
posterResizeMode && posterResizeMode !== 'none'
|
2023-10-06 10:39:14 -06:00
|
|
|
? posterResizeMode
|
2023-10-07 04:56:35 -06:00
|
|
|
: 'contain',
|
2023-10-06 10:39:14 -06:00
|
|
|
}),
|
2023-10-07 04:56:35 -06:00
|
|
|
[posterResizeMode],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
|
|
|
const src = useMemo(() => {
|
2023-10-07 04:56:35 -06:00
|
|
|
if (!source) {
|
|
|
|
return undefined;
|
|
|
|
}
|
2023-10-06 10:39:14 -06:00
|
|
|
|
|
|
|
const resolvedSource = resolveAssetSourceForVideo(source);
|
2023-10-07 04:56:35 -06:00
|
|
|
let uri = resolvedSource.uri || '';
|
|
|
|
if (uri && uri.match(/^\//)) {
|
|
|
|
uri = `file://${uri}`;
|
|
|
|
}
|
|
|
|
if (!uri) {
|
|
|
|
console.warn('Trying to load empty source');
|
|
|
|
}
|
2023-10-06 10:39:14 -06:00
|
|
|
const isNetwork = !!(uri && uri.match(/^https?:/));
|
|
|
|
const isAsset = !!(
|
|
|
|
uri &&
|
|
|
|
uri.match(
|
2023-10-07 04:56:35 -06:00
|
|
|
/^(assets-library|ipod-library|file|content|ms-appx|ms-appdata):/,
|
2023-10-06 10:39:14 -06:00
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
return {
|
|
|
|
uri,
|
|
|
|
isNetwork,
|
|
|
|
isAsset,
|
|
|
|
shouldCache: resolvedSource.shouldCache || false,
|
2023-10-07 04:56:35 -06:00
|
|
|
type: resolvedSource.type || '',
|
2023-10-06 10:39:14 -06:00
|
|
|
mainVer: resolvedSource.mainVer || 0,
|
|
|
|
patchVer: resolvedSource.patchVer || 0,
|
|
|
|
requestHeaders: resolvedSource?.headers || {},
|
|
|
|
startTime: resolvedSource.startTime || 0,
|
2023-10-07 04:56:35 -06:00
|
|
|
endTime: resolvedSource.endTime,
|
2023-10-07 07:14:10 -06:00
|
|
|
title: resolvedSource.title,
|
|
|
|
subtitle: resolvedSource.subtitle,
|
|
|
|
description: resolvedSource.description,
|
|
|
|
customImageUri: resolvedSource.customImageUri,
|
2023-10-06 10:39:14 -06:00
|
|
|
};
|
|
|
|
}, [source]);
|
|
|
|
|
|
|
|
const _resizeMode: NativeVideoResizeMode = useMemo(() => {
|
|
|
|
switch (resizeMode) {
|
2023-10-07 04:56:35 -06:00
|
|
|
case 'contain':
|
2023-10-06 10:39:14 -06:00
|
|
|
return RCTVideoConstants.ScaleAspectFit;
|
2023-10-07 04:56:35 -06:00
|
|
|
case 'cover':
|
2023-10-06 10:39:14 -06:00
|
|
|
return RCTVideoConstants.ScaleAspectFill;
|
2023-10-07 04:56:35 -06:00
|
|
|
case 'stretch':
|
2023-10-06 10:39:14 -06:00
|
|
|
return RCTVideoConstants.ScaleToFill;
|
|
|
|
default:
|
|
|
|
return RCTVideoConstants.ScaleNone;
|
|
|
|
}
|
|
|
|
}, [resizeMode]);
|
|
|
|
|
|
|
|
const _drm = useMemo(() => {
|
2023-10-07 04:56:35 -06:00
|
|
|
if (!drm) {
|
|
|
|
return;
|
|
|
|
}
|
2023-10-06 10:39:14 -06:00
|
|
|
return {
|
|
|
|
drmType: drm.type,
|
|
|
|
licenseServer: drm.licenseServer,
|
|
|
|
headers: drm.headers,
|
|
|
|
contentId: drm.contentId,
|
|
|
|
certificateUrl: drm.certificateUrl,
|
|
|
|
base64Certificate: drm.base64Certificate,
|
|
|
|
useExternalGetLicense: !!drm.getLicense,
|
|
|
|
};
|
|
|
|
}, [drm]);
|
|
|
|
|
|
|
|
const _selectedTextTrack = useMemo(() => {
|
2023-10-07 04:56:35 -06:00
|
|
|
if (!selectedTextTrack) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (typeof selectedTextTrack?.value === 'number') {
|
|
|
|
return {
|
|
|
|
selectedTextType: selectedTextTrack?.type,
|
|
|
|
index: selectedTextTrack?.value,
|
|
|
|
};
|
2023-10-06 10:39:14 -06:00
|
|
|
}
|
|
|
|
return {
|
|
|
|
selectedTextType: selectedTextTrack?.type,
|
|
|
|
value: selectedTextTrack?.value,
|
2023-10-07 04:56:35 -06:00
|
|
|
};
|
2023-10-06 10:39:14 -06:00
|
|
|
}, [selectedTextTrack]);
|
|
|
|
|
|
|
|
const _selectedAudioTrack = useMemo(() => {
|
2023-10-07 04:56:35 -06:00
|
|
|
if (!selectedAudioTrack) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (typeof selectedAudioTrack?.value === 'number') {
|
|
|
|
return {
|
|
|
|
selectedAudioType: selectedAudioTrack?.type,
|
|
|
|
index: selectedAudioTrack?.value,
|
|
|
|
};
|
2023-10-06 10:39:14 -06:00
|
|
|
}
|
|
|
|
return {
|
|
|
|
selectedAudioType: selectedAudioTrack?.type,
|
|
|
|
value: selectedAudioTrack?.value,
|
2023-10-07 04:56:35 -06:00
|
|
|
};
|
2023-10-06 10:39:14 -06:00
|
|
|
}, [selectedAudioTrack]);
|
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
const seek = useCallback(async (time: number, tolerance?: number) => {
|
|
|
|
if (isNaN(time)) {
|
|
|
|
throw new Error('Specified time is not a number');
|
|
|
|
}
|
2023-10-06 10:39:14 -06:00
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
if (!nativeRef.current) {
|
|
|
|
console.warn('Video Component is not mounted');
|
|
|
|
return;
|
|
|
|
}
|
2023-10-06 10:39:14 -06:00
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
Platform.select({
|
|
|
|
ios: () => {
|
|
|
|
nativeRef.current?.setNativeProps({
|
|
|
|
seek: {
|
|
|
|
time,
|
|
|
|
tolerance,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
},
|
|
|
|
default: () => {
|
|
|
|
nativeRef.current?.setNativeProps({
|
|
|
|
seek: time,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
})();
|
|
|
|
}, []);
|
2023-10-06 10:39:14 -06:00
|
|
|
|
|
|
|
const presentFullscreenPlayer = useCallback(() => {
|
|
|
|
setIsFullscreen(true);
|
|
|
|
}, [setIsFullscreen]);
|
|
|
|
|
|
|
|
const dismissFullscreenPlayer = useCallback(() => {
|
|
|
|
setIsFullscreen(false);
|
|
|
|
}, [setIsFullscreen]);
|
|
|
|
|
|
|
|
const save = useCallback(async () => {
|
|
|
|
await VideoManager.save(getReactTag(nativeRef));
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
const pause = useCallback(async () => {
|
|
|
|
await VideoManager.setPlayerPauseState(true, getReactTag(nativeRef));
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
const resume = useCallback(async () => {
|
|
|
|
await VideoManager.setPlayerPauseState(false, getReactTag(nativeRef));
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
const restoreUserInterfaceForPictureInPictureStopCompleted = useCallback(
|
|
|
|
(restored: boolean) => {
|
|
|
|
setRestoreUserInterfaceForPIPStopCompletionHandler(restored);
|
|
|
|
},
|
2023-10-07 04:56:35 -06:00
|
|
|
[setRestoreUserInterfaceForPIPStopCompletionHandler],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
|
|
|
const onVideoLoadStart = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnLoadStartData>) => {
|
|
|
|
onLoadStart?.(e.nativeEvent);
|
|
|
|
},
|
2023-10-07 04:56:35 -06:00
|
|
|
[onLoadStart],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
|
|
|
const onVideoLoad = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnLoadData>) => {
|
2023-10-07 04:56:35 -06:00
|
|
|
if (Platform.OS === 'windows') {
|
|
|
|
setShowPoster(false);
|
|
|
|
}
|
2023-10-06 10:39:14 -06:00
|
|
|
onLoad?.(e.nativeEvent);
|
|
|
|
},
|
2023-10-07 04:56:35 -06:00
|
|
|
[onLoad, setShowPoster],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
|
|
|
const onVideoError = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnVideoErrorData>) => {
|
|
|
|
onError?.(e.nativeEvent);
|
|
|
|
},
|
2023-10-07 04:56:35 -06:00
|
|
|
[onError],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
|
|
|
const onVideoProgress = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnProgressData>) => {
|
|
|
|
onProgress?.(e.nativeEvent);
|
|
|
|
},
|
2023-10-07 04:56:35 -06:00
|
|
|
[onProgress],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
|
|
|
const onVideoSeek = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnSeekData>) => {
|
|
|
|
onSeek?.(e.nativeEvent);
|
|
|
|
},
|
2023-10-07 04:56:35 -06:00
|
|
|
[onSeek],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
|
|
|
// android only
|
2023-10-07 04:56:35 -06:00
|
|
|
const onVideoPlaybackStateChanged = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnPlaybackStateChangedData>) => {
|
|
|
|
onPlaybackStateChanged?.(e.nativeEvent);
|
|
|
|
},
|
|
|
|
[onPlaybackStateChanged],
|
|
|
|
);
|
2023-10-06 10:39:14 -06:00
|
|
|
|
|
|
|
// android only
|
|
|
|
const onVideoIdle = useCallback(() => {
|
2023-10-07 04:56:35 -06:00
|
|
|
onIdle?.();
|
|
|
|
}, [onIdle]);
|
2023-10-06 10:39:14 -06:00
|
|
|
|
|
|
|
const _onTimedMetadata = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnTimedMetadataData>) => {
|
|
|
|
onTimedMetadata?.(e.nativeEvent);
|
|
|
|
},
|
2023-10-07 04:56:35 -06:00
|
|
|
[onTimedMetadata],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
const _onAudioTracks = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnAudioTracksData>) => {
|
|
|
|
onAudioTracks?.(e.nativeEvent);
|
|
|
|
},
|
|
|
|
[onAudioTracks],
|
|
|
|
);
|
2023-10-06 10:39:14 -06:00
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
const _onTextTracks = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnTextTracksData>) => {
|
|
|
|
onTextTracks?.(e.nativeEvent);
|
|
|
|
},
|
|
|
|
[onTextTracks],
|
|
|
|
);
|
2023-10-06 10:39:14 -06:00
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
const _onVideoTracks = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnVideoTracksData>) => {
|
|
|
|
onVideoTracks?.(e.nativeEvent);
|
|
|
|
},
|
|
|
|
[onVideoTracks],
|
|
|
|
);
|
2023-10-06 10:39:14 -06:00
|
|
|
|
|
|
|
const _onPlaybackRateChange = useCallback(
|
2023-10-07 04:56:35 -06:00
|
|
|
(e: NativeSyntheticEvent<Readonly<{playbackRate: number}>>) => {
|
2023-10-06 10:39:14 -06:00
|
|
|
onPlaybackRateChange?.(e.nativeEvent);
|
|
|
|
},
|
2023-10-07 04:56:35 -06:00
|
|
|
[onPlaybackRateChange],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
|
|
|
const _onReadyForDisplay = useCallback(() => {
|
|
|
|
setShowPoster(false);
|
|
|
|
onReadyForDisplay?.();
|
|
|
|
}, [setShowPoster, onReadyForDisplay]);
|
|
|
|
|
|
|
|
const _onPictureInPictureStatusChanged = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnPictureInPictureStatusChangedData>) => {
|
|
|
|
onPictureInPictureStatusChanged?.(e.nativeEvent);
|
|
|
|
},
|
2023-10-07 04:56:35 -06:00
|
|
|
[onPictureInPictureStatusChanged],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
const _onAudioFocusChanged = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnAudioFocusChangedData>) => {
|
|
|
|
onAudioFocusChanged?.(e.nativeEvent);
|
|
|
|
},
|
|
|
|
[onAudioFocusChanged],
|
|
|
|
);
|
2023-10-06 10:39:14 -06:00
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
const onVideoBuffer = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnBufferData>) => {
|
|
|
|
onBuffer?.(e.nativeEvent);
|
|
|
|
},
|
|
|
|
[onBuffer],
|
|
|
|
);
|
2023-10-06 10:39:14 -06:00
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
const onVideoExternalPlaybackChange = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnExternalPlaybackChangeData>) => {
|
|
|
|
onExternalPlaybackChange?.(e.nativeEvent);
|
|
|
|
},
|
|
|
|
[onExternalPlaybackChange],
|
|
|
|
);
|
2023-10-06 10:39:14 -06:00
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
const _onBandwidthUpdate = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnBandwidthUpdateData>) => {
|
|
|
|
onBandwidthUpdate?.(e.nativeEvent);
|
|
|
|
},
|
|
|
|
[onBandwidthUpdate],
|
|
|
|
);
|
2023-10-06 10:39:14 -06:00
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
const _onReceiveAdEvent = useCallback(
|
|
|
|
(e: NativeSyntheticEvent<OnReceiveAdEventData>) => {
|
|
|
|
onReceiveAdEvent?.(e.nativeEvent);
|
|
|
|
},
|
|
|
|
[onReceiveAdEvent],
|
|
|
|
);
|
2023-10-06 10:39:14 -06:00
|
|
|
|
|
|
|
const onGetLicense = useCallback(
|
|
|
|
(event: NativeSyntheticEvent<OnGetLicenseData>) => {
|
|
|
|
if (drm && drm.getLicense instanceof Function) {
|
|
|
|
const data = event.nativeEvent;
|
|
|
|
if (data && data.spcBase64) {
|
2023-10-07 04:56:35 -06:00
|
|
|
const getLicenseOverride = drm.getLicense(
|
|
|
|
data.spcBase64,
|
|
|
|
data.contentId,
|
|
|
|
data.licenseUrl,
|
|
|
|
);
|
2023-10-06 10:39:14 -06:00
|
|
|
const getLicensePromise = Promise.resolve(getLicenseOverride); // Handles both scenarios, getLicenseOverride being a promise and not.
|
2023-10-07 04:56:35 -06:00
|
|
|
getLicensePromise
|
|
|
|
.then((result) => {
|
|
|
|
if (result !== undefined) {
|
|
|
|
nativeRef.current &&
|
|
|
|
VideoManager.setLicenseResult(
|
|
|
|
result,
|
|
|
|
data.licenseUrl,
|
|
|
|
getReactTag(nativeRef),
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
nativeRef.current &&
|
|
|
|
VideoManager.setLicenseResultError(
|
|
|
|
'Empty license result',
|
|
|
|
data.licenseUrl,
|
|
|
|
getReactTag(nativeRef),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
nativeRef.current &&
|
|
|
|
VideoManager.setLicenseResultError(
|
|
|
|
'fetch error',
|
|
|
|
data.licenseUrl,
|
|
|
|
getReactTag(nativeRef),
|
|
|
|
);
|
|
|
|
});
|
2023-10-06 10:39:14 -06:00
|
|
|
} else {
|
2023-10-07 04:56:35 -06:00
|
|
|
VideoManager.setLicenseResultError(
|
|
|
|
'No spc received',
|
|
|
|
data.licenseUrl,
|
|
|
|
getReactTag(nativeRef),
|
|
|
|
);
|
2023-10-06 10:39:14 -06:00
|
|
|
}
|
|
|
|
}
|
2023-10-07 04:56:35 -06:00
|
|
|
},
|
|
|
|
[drm],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
|
|
|
useImperativeHandle(
|
|
|
|
ref,
|
|
|
|
() => ({
|
|
|
|
seek,
|
|
|
|
presentFullscreenPlayer,
|
|
|
|
dismissFullscreenPlayer,
|
|
|
|
save,
|
|
|
|
pause,
|
|
|
|
resume,
|
|
|
|
restoreUserInterfaceForPictureInPictureStopCompleted,
|
|
|
|
}),
|
|
|
|
[
|
|
|
|
seek,
|
|
|
|
presentFullscreenPlayer,
|
|
|
|
dismissFullscreenPlayer,
|
|
|
|
save,
|
|
|
|
pause,
|
|
|
|
resume,
|
|
|
|
restoreUserInterfaceForPictureInPictureStopCompleted,
|
2023-10-07 04:56:35 -06:00
|
|
|
],
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<View style={style}>
|
|
|
|
<NativeVideoComponent
|
|
|
|
ref={nativeRef}
|
|
|
|
{...rest}
|
|
|
|
src={src}
|
|
|
|
drm={_drm}
|
|
|
|
style={StyleSheet.absoluteFill}
|
|
|
|
resizeMode={_resizeMode}
|
|
|
|
fullscreen={isFullscreen}
|
|
|
|
restoreUserInterfaceForPIPStopCompletionHandler={
|
|
|
|
_restoreUserInterfaceForPIPStopCompletionHandler
|
|
|
|
}
|
|
|
|
textTracks={textTracks}
|
|
|
|
selectedTextTrack={_selectedTextTrack}
|
|
|
|
selectedAudioTrack={_selectedAudioTrack}
|
|
|
|
onGetLicense={onGetLicense}
|
|
|
|
onVideoLoad={onVideoLoad}
|
|
|
|
onVideoLoadStart={onVideoLoadStart}
|
|
|
|
onVideoError={onVideoError}
|
|
|
|
onVideoProgress={onVideoProgress}
|
|
|
|
onVideoSeek={onVideoSeek}
|
|
|
|
onVideoEnd={onEnd}
|
|
|
|
onVideoBuffer={onVideoBuffer}
|
|
|
|
onVideoPlaybackStateChanged={onVideoPlaybackStateChanged}
|
|
|
|
onBandwidthUpdate={_onBandwidthUpdate}
|
|
|
|
onTimedMetadata={_onTimedMetadata}
|
|
|
|
onAudioTracks={_onAudioTracks}
|
|
|
|
onTextTracks={_onTextTracks}
|
|
|
|
onVideoTracks={_onVideoTracks}
|
|
|
|
onVideoFullscreenPlayerDidDismiss={onFullscreenPlayerDidDismiss}
|
|
|
|
onVideoFullscreenPlayerDidPresent={onFullscreenPlayerDidPresent}
|
|
|
|
onVideoFullscreenPlayerWillDismiss={onFullscreenPlayerWillDismiss}
|
|
|
|
onVideoFullscreenPlayerWillPresent={onFullscreenPlayerWillPresent}
|
|
|
|
onVideoExternalPlaybackChange={onVideoExternalPlaybackChange}
|
|
|
|
onVideoIdle={onVideoIdle}
|
|
|
|
onAudioFocusChanged={_onAudioFocusChanged}
|
|
|
|
onReadyForDisplay={_onReadyForDisplay}
|
|
|
|
onPlaybackRateChange={_onPlaybackRateChange}
|
|
|
|
onVideoAudioBecomingNoisy={onAudioBecomingNoisy}
|
|
|
|
onPictureInPictureStatusChanged={_onPictureInPictureStatusChanged}
|
|
|
|
onRestoreUserInterfaceForPictureInPictureStop={
|
|
|
|
onRestoreUserInterfaceForPictureInPictureStop
|
|
|
|
}
|
|
|
|
onReceiveAdEvent={_onReceiveAdEvent}
|
|
|
|
/>
|
|
|
|
{showPoster ? (
|
2023-10-07 04:56:35 -06:00
|
|
|
<Image style={posterStyle} source={{uri: poster}} />
|
2023-10-06 10:39:14 -06:00
|
|
|
) : null}
|
|
|
|
</View>
|
|
|
|
);
|
2023-10-07 04:56:35 -06:00
|
|
|
},
|
2023-10-06 10:39:14 -06:00
|
|
|
);
|
|
|
|
|
2023-10-07 04:56:35 -06:00
|
|
|
Video.displayName = 'Video';
|
|
|
|
export default Video;
|