react-native-video-basic-controls
Version:
Controls for the React Native <Video> component at react-native-video.
313 lines (285 loc) • 8.87 kB
JavaScript
import React, { useState, useEffect } from 'react';
import { View, Animated, TouchableWithoutFeedback, StatusBar, LogBox } from 'react-native';
import styles from './MediaControls.style';
import { PLAYER_STATES } from './constants/playerStates';
import { Controls } from './Controls';
import { Slider } from './Slider';
import { Toolbar } from './Toolbar';
import Orientation, { useOrientationChange, useLockListener } from 'react-native-orientation-locker';
import SystemSetting from 'react-native-system-setting';
let SystemSettings = require('react-native-system-setting') ? SystemSetting : null;
import VerticalSlider from './VerticalSlider';
const MediaControls = props => {
const {
children,
containerStyle: customContainerStyle = {},
duration,
bufferValue = 0,
fadeOutDelay = 5000,
isLoading = false,
mainColor = 'rgba(12, 83, 175, 0.9)',
bufferColor = '#fff',
onFullScreen,
fullScreenIconP,
fullScreenIconL,
// onReplay=()=>{},
onReplay: onReplayCallback = () => {},
onSkipFor = () => {},
onSkipBack = () => {},
onSeek,
onSeeking,
playerState,
progress,
showOnStart = true,
sliderStyle,
// defaults are applied in Slider.tsx
iconStyle,
toolbarStyle: customToolbarStyle = {},
VSliderOuterStyles,
VSliderInnerStyles,
showVolume = false,
showBrightness = false,
sliderScale = 10,
sliderType = 'Slider'
} = props;
const {
initialOpacity,
initialIsVisible
} = (() => {
if (showOnStart) {
return {
initialOpacity: 1,
initialIsVisible: true
};
}
return {
initialOpacity: 0,
initialIsVisible: false
};
})();
const [isFullscreen, setIsFullscreen] = useState(false);
const [opacity] = useState(new Animated.Value(initialOpacity));
const [isVisible, setIsVisible] = useState(initialIsVisible);
const [isLocked, setLocked] = useState(false);
const [volume, setVolume] = useState(0);
const [brightness, setBrightness] = useState(0);
const [isChild, setIsChild] = useState(false);
useOrientationChange(o => {
if (o === 'PORTRAIT') {
setIsFullscreen(false);
} else {
setIsFullscreen(true);
}
});
useLockListener(o => {
if (o === 'PORTRAIT') {
setIsFullscreen(false);
} else {
setIsFullscreen(true);
}
});
function checkLocked() {
const locked = Orientation.isLocked();
if (locked !== isLocked) {
setLocked(locked);
}
}
useEffect(() => {
LogBox.ignoreAllLogs();
if (children === undefined || children === null) {
setIsChild(false);
} else {
setIsChild(true);
}
if (showBrightness) {
SystemSettings === null || SystemSettings === void 0 ? void 0 : SystemSettings.getBrightness().then(bright => {
setBrightness(bright);
});
}
Orientation.getOrientation(o => {
if (o === 'PORTRAIT') {
setIsFullscreen(false);
} else {
setIsFullscreen(true);
}
});
if (showVolume) {
var _SystemSettings$getVo;
SystemSettings === null || SystemSettings === void 0 ? void 0 : (_SystemSettings$getVo = SystemSettings.getVolume()) === null || _SystemSettings$getVo === void 0 ? void 0 : _SystemSettings$getVo.then(vol => {
setVolume(vol);
});
}
const volumeListener = SystemSettings === null || SystemSettings === void 0 ? void 0 : SystemSettings.addVolumeListener(data => {
setVolume(data.value);
});
checkLocked();
fadeOutControls(fadeOutDelay);
return () => SystemSettings === null || SystemSettings === void 0 ? void 0 : SystemSettings.removeVolumeListener(volumeListener);
}, []);
const onVolumeChange = value => {
SystemSettings === null || SystemSettings === void 0 ? void 0 : SystemSettings.setVolume(value);
volume !== value ? setVolume(value) : null;
};
const onBrightnessChange = value => {
SystemSettings === null || SystemSettings === void 0 ? void 0 : SystemSettings.setAppBrightness(value);
volume !== value ? setBrightness(value) : null;
};
const fadeOutControls = function () {
let delay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
Animated.timing(opacity, {
toValue: 0,
duration: 30,
delay,
useNativeDriver: false
}).start(result => {
/* I noticed that the callback is called twice, when it is invoked and when it completely finished
This prevents some flickering */
if (result.finished) {
setIsVisible(false);
}
});
};
const fadeInControls = () => {
setIsVisible(true);
Animated.timing(opacity, {
toValue: 1,
duration: 300,
delay: 0,
useNativeDriver: false
}).start();
};
const onReplay = () => {
fadeOutControls(fadeOutDelay);
onReplayCallback();
};
const onFullScreenFunction = () => {
if (isFullscreen) {
Orientation.lockToPortrait();
checkLocked();
setIsFullscreen(false);
} else {
Orientation.lockToLandscape();
checkLocked();
setIsFullscreen(true);
}
};
const cancelAnimation = () => opacity.stopAnimation(() => setIsVisible(true));
const onPause = () => {
const {
onPaused
} = props;
const {
PLAYING,
PAUSED,
ENDED
} = PLAYER_STATES;
switch (playerState) {
case PLAYING:
{
cancelAnimation();
break;
}
case PAUSED:
{
fadeOutControls(fadeOutDelay);
break;
}
case ENDED:
break;
}
const newPlayerState = playerState === PLAYING ? PAUSED : PLAYING;
return onPaused(newPlayerState);
};
const toggleControls = () => {
// value is the last value of the animation when stop animation was called.
// As this is an opacity effect, I used the value (0 or 1) as a boolean
opacity.stopAnimation(value => {
setIsVisible(!!value);
return value ? fadeOutControls() : fadeInControls();
});
};
return /*#__PURE__*/React.createElement(TouchableWithoutFeedback, {
accessible: false,
onPress: toggleControls
}, /*#__PURE__*/React.createElement(Animated.View, {
style: [styles.container, customContainerStyle, {
opacity
}]
}, isFullscreen && /*#__PURE__*/React.createElement(StatusBar, {
hidden: true
}), isVisible && /*#__PURE__*/React.createElement(View, {
style: [styles.container, customContainerStyle]
}, /*#__PURE__*/React.createElement(View, {
style: [{ ...styles.controlsRow,
flex: isChild ? 1 : 0.5
}, styles.toolbarRow, customToolbarStyle]
}, children), /*#__PURE__*/React.createElement(Controls, {
isChild: isChild,
brightness: brightness,
volume: volume,
showBrightness: showBrightness,
showVolume: showVolume,
onBrightness: onBrightnessChange,
onVolume: onVolumeChange,
showSlider: isFullscreen && sliderType === 'Swipe',
onPause: onPause,
onReplay: onReplay,
onSkipFor: onSkipFor,
onSkipBack: onSkipBack,
isLoading: isLoading,
playerState: playerState,
customIconStyle: iconStyle
}), /*#__PURE__*/React.createElement(Slider, {
progress: progress,
duration: duration,
bufferValue: bufferValue,
mainColor: mainColor,
bufferColor: bufferColor,
onFullScreen: onFullScreen ? onFullScreen : onFullScreenFunction,
isFullscreen: isFullscreen,
fullScreenIconL: fullScreenIconL,
fullScreenIconP: fullScreenIconP,
playerState: playerState,
onSeek: onSeek,
onSeeking: onSeeking,
onPause: onPause,
customSliderStyle: sliderStyle
}), isFullscreen && sliderType === 'Slider' && /*#__PURE__*/React.createElement(React.Fragment, null, showBrightness && /*#__PURE__*/React.createElement(View, {
style: styles.VSliderLeft
}, /*#__PURE__*/React.createElement(VerticalSlider, {
value: brightness,
disabled: false,
min: 0,
max: 1,
step: 0.01,
onChange: onBrightnessChange,
onComplete: onBrightnessChange,
width: 4,
height: 200,
borderRadius: 50,
SliderMaxStyles: VSliderOuterStyles,
SliderMinStyles: VSliderInnerStyles,
ballColor: mainColor,
sliderScale: sliderScale
})), showVolume && /*#__PURE__*/React.createElement(View, {
style: styles.VSliderRight
}, /*#__PURE__*/React.createElement(VerticalSlider, {
value: volume,
disabled: false,
min: 0,
max: 1,
step: 0.01,
onChange: onVolumeChange,
onComplete: onVolumeChange,
width: 4,
height: 200,
borderRadius: 50,
SliderMaxStyles: VSliderOuterStyles,
SliderMinStyles: VSliderInnerStyles,
ballColor: mainColor,
sliderScale: sliderScale
}))))));
};
MediaControls.Toolbar = Toolbar;
export default MediaControls;
//# sourceMappingURL=MediaControls.js.map