refactor: internal refactor for prepare new arch (#3980)
* chore(js): fix typo * refactor(js): refactor type code for codegen * refactor(js): refactor Video component - parse shutterColor value within JS - remove internal fullscreen state * chore(js): add deprecation warning comment * fix(js): fix return type * fix(js): fix import path * refactor(android): apply changed API for new arch * refactor(ios): apply changed API for new arch * fix(ios): fix wrong name * refactor: refactor VideoDecoderProperties - rename and add wrapper * refactor(android): Code fixes for backward compatibility with Kotlin
This commit is contained in:
235
src/Video.tsx
235
src/Video.tsx
@@ -5,57 +5,47 @@ import React, {
|
||||
useRef,
|
||||
forwardRef,
|
||||
useImperativeHandle,
|
||||
type ComponentRef,
|
||||
} from 'react';
|
||||
import {
|
||||
View,
|
||||
StyleSheet,
|
||||
Image,
|
||||
Platform,
|
||||
type StyleProp,
|
||||
type ImageStyle,
|
||||
type NativeSyntheticEvent,
|
||||
} from 'react-native';
|
||||
import type {ElementRef} from 'react';
|
||||
import {View, StyleSheet, Image, Platform, processColor} from 'react-native';
|
||||
import type {StyleProp, ImageStyle, NativeSyntheticEvent} from 'react-native';
|
||||
|
||||
import NativeVideoComponent, {
|
||||
type OnAudioFocusChangedData,
|
||||
type OnAudioTracksData,
|
||||
type OnBandwidthUpdateData,
|
||||
type OnBufferData,
|
||||
type OnControlsVisibilityChange,
|
||||
type OnExternalPlaybackChangeData,
|
||||
type OnGetLicenseData,
|
||||
type OnLoadStartData,
|
||||
type OnPictureInPictureStatusChangedData,
|
||||
type OnPlaybackStateChangedData,
|
||||
type OnProgressData,
|
||||
type OnSeekData,
|
||||
type OnTextTrackDataChangedData,
|
||||
type OnTimedMetadataData,
|
||||
type OnVideoAspectRatioData,
|
||||
type OnVideoErrorData,
|
||||
type OnVideoTracksData,
|
||||
type VideoComponentType,
|
||||
type VideoSrc,
|
||||
import NativeVideoComponent from './specs/VideoNativeComponent';
|
||||
import type {
|
||||
OnAudioFocusChangedData,
|
||||
OnAudioTracksData,
|
||||
OnBandwidthUpdateData,
|
||||
OnBufferData,
|
||||
OnControlsVisibilityChange,
|
||||
OnExternalPlaybackChangeData,
|
||||
OnGetLicenseData,
|
||||
OnLoadStartData,
|
||||
OnPictureInPictureStatusChangedData,
|
||||
OnPlaybackStateChangedData,
|
||||
OnProgressData,
|
||||
OnSeekData,
|
||||
OnTextTrackDataChangedData,
|
||||
OnTimedMetadataData,
|
||||
OnVideoAspectRatioData,
|
||||
OnVideoErrorData,
|
||||
OnVideoTracksData,
|
||||
VideoSrc,
|
||||
} from './specs/VideoNativeComponent';
|
||||
import {
|
||||
generateHeaderForNative,
|
||||
getReactTag,
|
||||
resolveAssetSourceForVideo,
|
||||
} from './utils';
|
||||
import {VideoManager} from './specs/VideoNativeComponent';
|
||||
import {
|
||||
type OnLoadData,
|
||||
type OnTextTracksData,
|
||||
type OnReceiveAdEventData,
|
||||
type ReactVideoProps,
|
||||
ViewType,
|
||||
import NativeVideoManager from './specs/NativeVideoManager';
|
||||
import type {VideoSaveData} from './specs/NativeVideoManager';
|
||||
import {ViewType} from './types';
|
||||
import type {
|
||||
OnLoadData,
|
||||
OnTextTracksData,
|
||||
OnReceiveAdEventData,
|
||||
ReactVideoProps,
|
||||
} from './types';
|
||||
|
||||
export type VideoSaveData = {
|
||||
uri: string;
|
||||
};
|
||||
|
||||
export interface VideoRef {
|
||||
seek: (time: number, tolerance?: number) => void;
|
||||
resume: () => void;
|
||||
@@ -65,10 +55,10 @@ export interface VideoRef {
|
||||
restoreUserInterfaceForPictureInPictureStopCompleted: (
|
||||
restore: boolean,
|
||||
) => void;
|
||||
save: (options: object) => Promise<VideoSaveData>;
|
||||
setVolume: (volume: number) => void;
|
||||
getCurrentPosition: () => Promise<number>;
|
||||
setFullScreen: (fullScreen: boolean) => void;
|
||||
save: (options: object) => Promise<VideoSaveData> | void;
|
||||
getCurrentPosition: () => Promise<number>;
|
||||
}
|
||||
|
||||
const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
@@ -79,7 +69,6 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
resizeMode,
|
||||
posterResizeMode,
|
||||
poster,
|
||||
fullscreen,
|
||||
drm,
|
||||
textTracks,
|
||||
selectedVideoTrack,
|
||||
@@ -88,6 +77,7 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
useTextureView,
|
||||
useSecureView,
|
||||
viewType,
|
||||
shutterColor,
|
||||
onLoadStart,
|
||||
onLoad,
|
||||
onError,
|
||||
@@ -122,9 +112,8 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const nativeRef = useRef<ComponentRef<VideoComponentType>>(null);
|
||||
const nativeRef = useRef<ElementRef<typeof NativeVideoComponent>>(null);
|
||||
const [showPoster, setShowPoster] = useState(!!poster);
|
||||
const [isFullscreen, setIsFullscreen] = useState(fullscreen);
|
||||
const [
|
||||
_restoreUserInterfaceForPIPStopCompletionHandler,
|
||||
setRestoreUserInterfaceForPIPStopCompletionHandler,
|
||||
@@ -274,12 +263,10 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
}
|
||||
|
||||
const callSeekFunction = () => {
|
||||
VideoManager.seek(
|
||||
{
|
||||
time,
|
||||
tolerance: tolerance || 0,
|
||||
},
|
||||
NativeVideoManager.seekCmd(
|
||||
getReactTag(nativeRef),
|
||||
time,
|
||||
tolerance || 0,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -287,31 +274,59 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
ios: callSeekFunction,
|
||||
android: callSeekFunction,
|
||||
default: () => {
|
||||
// TODO: Implement VideoManager.seek for windows
|
||||
// TODO: Implement VideoManager.seekCmd for windows
|
||||
nativeRef.current?.setNativeProps({seek: time});
|
||||
},
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const presentFullscreenPlayer = useCallback(() => {
|
||||
setIsFullscreen(true);
|
||||
}, [setIsFullscreen]);
|
||||
|
||||
const dismissFullscreenPlayer = useCallback(() => {
|
||||
setIsFullscreen(false);
|
||||
}, [setIsFullscreen]);
|
||||
|
||||
const save = useCallback((options: object) => {
|
||||
// VideoManager.save can be null on android & windows
|
||||
return VideoManager.save?.(options, getReactTag(nativeRef));
|
||||
}, []);
|
||||
|
||||
const pause = useCallback(() => {
|
||||
return VideoManager.setPlayerPauseState(true, getReactTag(nativeRef));
|
||||
return NativeVideoManager.setPlayerPauseStateCmd(
|
||||
getReactTag(nativeRef),
|
||||
true,
|
||||
);
|
||||
}, []);
|
||||
|
||||
const resume = useCallback(() => {
|
||||
return VideoManager.setPlayerPauseState(false, getReactTag(nativeRef));
|
||||
return NativeVideoManager.setPlayerPauseStateCmd(
|
||||
getReactTag(nativeRef),
|
||||
false,
|
||||
);
|
||||
}, []);
|
||||
|
||||
const setVolume = useCallback((volume: number) => {
|
||||
return NativeVideoManager.setVolumeCmd(getReactTag(nativeRef), volume);
|
||||
}, []);
|
||||
|
||||
const setFullScreen = useCallback((fullScreen: boolean) => {
|
||||
return NativeVideoManager.setFullScreenCmd(
|
||||
getReactTag(nativeRef),
|
||||
fullScreen,
|
||||
);
|
||||
}, []);
|
||||
|
||||
const presentFullscreenPlayer = useCallback(
|
||||
() => setFullScreen(true),
|
||||
[setFullScreen],
|
||||
);
|
||||
|
||||
const dismissFullscreenPlayer = useCallback(
|
||||
() => setFullScreen(false),
|
||||
[setFullScreen],
|
||||
);
|
||||
|
||||
const save = useCallback((options: object) => {
|
||||
// VideoManager.save can be null on android & windows
|
||||
if (Platform.OS !== 'ios') {
|
||||
return;
|
||||
}
|
||||
// @todo Must implement it in a different way.
|
||||
return NativeVideoManager.save?.(getReactTag(nativeRef), options);
|
||||
}, []);
|
||||
|
||||
const getCurrentPosition = useCallback(() => {
|
||||
// @todo Must implement it in a different way.
|
||||
return NativeVideoManager.getCurrentPosition(getReactTag(nativeRef));
|
||||
}, []);
|
||||
|
||||
const restoreUserInterfaceForPictureInPictureStopCompleted = useCallback(
|
||||
@@ -321,18 +336,6 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
[setRestoreUserInterfaceForPIPStopCompletionHandler],
|
||||
);
|
||||
|
||||
const setVolume = useCallback((volume: number) => {
|
||||
return VideoManager.setVolume(volume, getReactTag(nativeRef));
|
||||
}, []);
|
||||
|
||||
const getCurrentPosition = useCallback(() => {
|
||||
return VideoManager.getCurrentPosition(getReactTag(nativeRef));
|
||||
}, []);
|
||||
|
||||
const setFullScreen = useCallback((fullScreen: boolean) => {
|
||||
return VideoManager.setFullScreen(fullScreen, getReactTag(nativeRef));
|
||||
}, []);
|
||||
|
||||
const onVideoLoadStart = useCallback(
|
||||
(e: NativeSyntheticEvent<OnLoadStartData>) => {
|
||||
hasPoster && setShowPoster(true);
|
||||
@@ -379,6 +382,11 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
[onPlaybackStateChanged],
|
||||
);
|
||||
|
||||
const _shutterColor = useMemo(() => {
|
||||
const color = processColor(shutterColor);
|
||||
return typeof color === 'number' ? color : undefined;
|
||||
}, [shutterColor]);
|
||||
|
||||
// android only
|
||||
const _onTimedMetadata = useCallback(
|
||||
(e: NativeSyntheticEvent<OnTimedMetadataData>) => {
|
||||
@@ -494,56 +502,41 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
[onControlsVisibilityChange],
|
||||
);
|
||||
|
||||
const useExternalGetLicense = drm?.getLicense instanceof Function;
|
||||
const usingExternalGetLicense = drm?.getLicense instanceof Function;
|
||||
|
||||
const onGetLicense = useCallback(
|
||||
(event: NativeSyntheticEvent<OnGetLicenseData>) => {
|
||||
if (useExternalGetLicense) {
|
||||
const data = event.nativeEvent;
|
||||
if (data && data.spcBase64) {
|
||||
const getLicenseOverride = drm.getLicense(
|
||||
async (event: NativeSyntheticEvent<OnGetLicenseData>) => {
|
||||
if (!usingExternalGetLicense) {
|
||||
return;
|
||||
}
|
||||
const data = event.nativeEvent;
|
||||
let result;
|
||||
if (data?.spcBase64) {
|
||||
try {
|
||||
// Handles both scenarios, getLicenseOverride being a promise and not.
|
||||
const license = await drm.getLicense(
|
||||
data.spcBase64,
|
||||
data.contentId,
|
||||
data.licenseUrl,
|
||||
data.loadedLicenseUrl,
|
||||
);
|
||||
const getLicensePromise = Promise.resolve(getLicenseOverride); // Handles both scenarios, getLicenseOverride being a promise and not.
|
||||
getLicensePromise
|
||||
.then((result) => {
|
||||
if (result !== undefined) {
|
||||
nativeRef.current &&
|
||||
VideoManager.setLicenseResult(
|
||||
result,
|
||||
data.loadedLicenseUrl,
|
||||
getReactTag(nativeRef),
|
||||
);
|
||||
} else {
|
||||
nativeRef.current &&
|
||||
VideoManager.setLicenseResultError(
|
||||
'Empty license result',
|
||||
data.loadedLicenseUrl,
|
||||
getReactTag(nativeRef),
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
nativeRef.current &&
|
||||
VideoManager.setLicenseResultError(
|
||||
'fetch error',
|
||||
data.loadedLicenseUrl,
|
||||
getReactTag(nativeRef),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
VideoManager.setLicenseResultError(
|
||||
'No spc received',
|
||||
data.loadedLicenseUrl,
|
||||
getReactTag(nativeRef),
|
||||
);
|
||||
result =
|
||||
typeof license === 'string' ? license : 'Empty license result';
|
||||
} catch {
|
||||
result = 'fetch error';
|
||||
}
|
||||
} else {
|
||||
result = 'No spc received';
|
||||
}
|
||||
if (nativeRef.current) {
|
||||
NativeVideoManager.setLicenseResultErrorCmd(
|
||||
getReactTag(nativeRef),
|
||||
result,
|
||||
data.loadedLicenseUrl,
|
||||
);
|
||||
}
|
||||
},
|
||||
[drm, useExternalGetLicense],
|
||||
[drm, usingExternalGetLicense],
|
||||
);
|
||||
|
||||
useImperativeHandle(
|
||||
@@ -613,7 +606,6 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
src={src}
|
||||
style={StyleSheet.absoluteFill}
|
||||
resizeMode={resizeMode}
|
||||
fullscreen={isFullscreen}
|
||||
restoreUserInterfaceForPIPStopCompletionHandler={
|
||||
_restoreUserInterfaceForPIPStopCompletionHandler
|
||||
}
|
||||
@@ -621,7 +613,8 @@ const Video = forwardRef<VideoRef, ReactVideoProps>(
|
||||
selectedTextTrack={_selectedTextTrack}
|
||||
selectedAudioTrack={_selectedAudioTrack}
|
||||
selectedVideoTrack={_selectedVideoTrack}
|
||||
onGetLicense={useExternalGetLicense ? onGetLicense : undefined}
|
||||
shutterColor={_shutterColor}
|
||||
onGetLicense={usingExternalGetLicense ? onGetLicense : undefined}
|
||||
onVideoLoad={
|
||||
onLoad || hasPoster
|
||||
? (onVideoLoad as (e: NativeSyntheticEvent<object>) => void)
|
||||
|
Reference in New Issue
Block a user