UNPKG

react-native-video-basic-controls

Version:

Controls for the React Native <Video> component at react-native-video.

313 lines (285 loc) 8.87 kB
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