Skip to content

Instantly share code, notes, and snippets.

@vemarav
Created June 19, 2023 03:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vemarav/4c1bfd4484d98acbcd2b3158ca64972e to your computer and use it in GitHub Desktop.
Save vemarav/4c1bfd4484d98acbcd2b3158ca64972e to your computer and use it in GitHub Desktop.
import React, {useState} from 'react';
import {Alert, Clipboard, View, ViewStyle} from 'react-native';
import FastImage, {ResizeMode} from 'react-native-fast-image';
import Video, {VideoProperties} from 'react-native-video';
import {InView} from 'react-native-intersection-observer';
import {useNavigation} from '@react-navigation/native';
export interface VideoBGProps
extends Omit<VideoProperties, 'source' | 'src' | 'resizeMode'> {
imgURL: string;
vidURL: string;
/** @param backgroundColor - default value is '#FFFFFF' */
backgroundColor?: string;
dontUnmountOnPause?: boolean;
/**
* @param style - Do not modify style object
* instead wrap VideoBG inside View to apply other styles
* <View style={{margin: 10, padding: 10}}>
* <VideoBG .../>
* </View>
* */
style: {
height: number;
width: number;
borderRadius?: ViewStyle['borderRadius'];
};
resizeMode?: ResizeMode & ('contain' | 'cover' | 'stretch' | 'none');
}
const VideoBG = React.forwardRef((props: VideoBGProps, ref: any) => {
const {
style,
imgURL,
vidURL,
resizeMode = 'cover',
backgroundColor,
dontUnmountOnPause,
...restProps
} = props;
const videoStyle = {
...style,
position: 'absolute',
} as VideoProperties['style'];
const imageStyle = {...style, backgroundColor};
const navigation = useNavigation();
const [display, setDisplay] = useState<boolean>(false);
const [unmountOnPause, setUnmountOnPause] = useState<boolean>(true);
const [isBlurred, setBlurred] = useState<boolean>(false);
React.useEffect(() => {
if (!dontUnmountOnPause) {
setUnmountOnPause(!restProps.paused ?? false);
} else {
setUnmountOnPause(true);
}
}, [restProps.paused]);
React.useEffect(() => {
return navigation.addListener('blur', () => {
setBlurred(true);
});
}, [navigation]);
React.useEffect(() => {
return navigation.addListener('focus', () => {
setBlurred(false);
});
}, [navigation]);
const imageWidget = imgURL ? (
<FastImage
resizeMode={resizeMode}
style={imageStyle}
source={{uri: imgURL}}
/>
) : (
<View style={imageStyle} />
);
if (isBlurred) {
return imageWidget;
}
return (
<InView onChange={setDisplay}>
{imageWidget}
{vidURL && display && unmountOnPause ? (
// @ts-ignore
<Video
{...restProps}
key={vidURL}
ref={ref}
source={{uri: vidURL}}
style={videoStyle}
resizeMode={resizeMode}
hideShutterView
onError={(...args) => {
if (props.onError) props.onError(...args);
console.error(args, {vidURL});
if (__DEV__) {
Alert.alert(
'Error playing video',
`copied video link to clipboard`,
);
Clipboard.setString(vidURL);
}
}}
// @ts-ignore
shutterColor={'#00FF0050'}
/>
) : null}
</InView>
);
});
export default VideoBG;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment