UNPKG

react-native-reanimated-player

Version:

A react-native video player that interacts like Youtube player, built upon Reanimted v2 & react-native-gesture-handle

1,160 lines (1,001 loc) 34.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.width = exports.scale = exports.height = exports.fontScale = exports.default = void 0; var _lottieReactNative = _interopRequireDefault(require("lottie-react-native")); var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _index = require("react-native-awesome-slider/src/index"); var _utils = require("react-native-awesome-slider/src/utils"); var _reactNativeGestureHandler = require("react-native-gesture-handler"); var _reactNativeOrientationLocker = _interopRequireWildcard(require("react-native-orientation-locker")); var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated")); var _reactNativeSafeAreaContext = require("react-native-safe-area-context"); var _reactNativeVideo = _interopRequireDefault(require("react-native-video")); var _components = require("./components"); var _ripple = require("./components/ripple"); var _tapControler = require("./tap-controler"); var _palette = require("./theme/palette"); var _utils2 = require("./utils"); var _videoLoading = require("./video-loading"); var _videoUtils = require("./video-utils"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } const { width, height, scale, fontScale } = _reactNative.Dimensions.get('window'); exports.fontScale = fontScale; exports.scale = scale; exports.height = height; exports.width = width; const VIDEO_DEFAULT_HEIGHT = width * (9 / 16); const hitSlop = { left: 8, bottom: 8, right: 8, top: 8 }; const controlAnimteConfig = { duration: 200 }; const AnimatedLottieView = _reactNativeReanimated.default.createAnimatedComponent(_lottieReactNative.default); const VideoPlayer = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => { let { resizeMode = 'contain', showOnStart = true, source, style, onEnterFullscreen, onExitFullscreen, controlTimeout = 2000, videoDefaultHeight = VIDEO_DEFAULT_HEIGHT, headerBarTitle = '', onTapBack, navigation, autoPlay = false, onToggleAutoPlay, onTapMore, doubleTapInterval = 500, theme = { minimumTrackTintColor: _palette.palette.Main(1), maximumTrackTintColor: _palette.palette.B(0.6), cacheTrackTintColor: _palette.palette.G1(1), bubbleBackgroundColor: _palette.palette.B(0.8), disableMinTrackTintColor: _palette.palette.Main(1) }, paused, onPausedChange, onTapPause, sliderProps, videoHeight, customAnimationStyle, onCustomPanGesture, isFullScreen, disableControl, renderBackIcon, renderMore, renderFullScreen, renderFullScreenBackIcon, onVideoPlayEnd, onAutoPlayText = 'Autoplay is on', offAutoPlayText = 'Autoplay is off', children, onPostProgress, onPostSeek, ...rest } = _ref; /** * hooks */ const insets = (0, _reactNativeSafeAreaContext.useSafeAreaInsets)(); const insetsRef = (0, _react.useRef)(insets); const dimensions = (0, _reactNative.useWindowDimensions)(); const leftDoubleTapBoundary = dimensions.width / 2 - insets.left - insets.right - 80; const rightDoubleTapBoundary = dimensions.width - leftDoubleTapBoundary - insets.left - insets.right; const [isFullScreenState, setIsFullscreen] = (0, _react.useState)(false); const [currentTime, setCurrentTime] = (0, _react.useState)(0); const [duration, setDuration] = (0, _react.useState)(0); const [isLoadEnd, setIsLoadEnd] = (0, _react.useState)(false); const [loading, setIsLoading] = (0, _react.useState)(false); const [showTimeRemaining, setShowTimeRemaining] = (0, _react.useState)(true); const [allowAutoPlayVideo, setAllowAutoPlayVideo] = (0, _react.useState)(autoPlay); (0, _react.useImperativeHandle)(ref, () => ({ setPlay: () => { 'worklet'; checkTapTakesEffect(); play(); }, setPause: () => { 'worklet'; checkTapTakesEffect(); pause(); }, toggleFullSreen: isFullScrren => { isFullScrren ? enterFullScreen() : exitFullScreen(); }, toggleControlViewOpacity: isShow => { 'worklet'; isShow ? showControlAnimation() : hideControlAnimation(); }, setSeekTo: seconds => { seekTo(seconds); } })); /** * refs */ const videoPlayer = (0, _react.useRef)(null); const mounted = (0, _react.useRef)(false); const autoPlayAnimation = (0, _reactNativeReanimated.useSharedValue)(autoPlay ? 1 : 0); const { rippleLeft, rippleRight } = (0, _utils2.useRefs)(); /** * reanimated value */ const controlViewOpacity = (0, _reactNativeReanimated.useSharedValue)(showOnStart ? 1 : 0); const autoPlayTextAnimation = (0, _reactNativeReanimated.useSharedValue)(0); const doubleLeftOpacity = (0, _reactNativeReanimated.useSharedValue)(0); const doubleRightOpacity = (0, _reactNativeReanimated.useSharedValue)(0); const videoScale = (0, _reactNativeReanimated.useSharedValue)(1); const videoTransY = (0, _reactNativeReanimated.useSharedValue)(0); const panIsVertical = (0, _reactNativeReanimated.useSharedValue)(false); const doubleTapIsAlive = (0, _reactNativeReanimated.useSharedValue)(false); const max = (0, _reactNativeReanimated.useSharedValue)(100); const min = (0, _reactNativeReanimated.useSharedValue)(0); const isScrubbing = (0, _reactNativeReanimated.useSharedValue)(false); const isSeeking = (0, _react.useRef)(false); const progress = (0, _reactNativeReanimated.useSharedValue)(0); const defaultVideoStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { transform: [{ scale: videoScale.value }, { translateY: videoTransY.value }], height: videoHeight.value }; }, []); const videoStyle = customAnimationStyle ? customAnimationStyle : defaultVideoStyle; const bottomControlStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { transform: [{ translateY: isFullScreen.value ? -42 : 0 }] }; }); const topControlStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { transform: [{ translateY: isFullScreen.value ? -42 : 0 }], opacity: (0, _reactNativeReanimated.withTiming)((0, _utils2.bin)(!isFullScreen.value)) }; }); const topFullscreenControlStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { opacity: (0, _reactNativeReanimated.withTiming)((0, _utils2.bin)(isFullScreen.value)) }; }); const bottomSliderStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { opacity: (0, _reactNativeReanimated.withTiming)((0, _utils2.bin)(!isFullScreen.value)) }; }); const fullScreenSliderStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { opacity: (0, _reactNativeReanimated.withTiming)((0, _utils2.bin)(isFullScreen.value)) }; }); const controlViewStyles = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { opacity: controlViewOpacity.value }; }); const autoPlayTextStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { opacity: autoPlayTextAnimation.value }; }); const getDoubleLeftStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { opacity: (0, _reactNativeReanimated.withTiming)(doubleLeftOpacity.value) }; }); const getDoubleRightStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { opacity: (0, _reactNativeReanimated.withTiming)(doubleRightOpacity.value) }; }); /** * useAnimatedProps */ const playAnimated = (0, _reactNativeReanimated.useDerivedValue)(() => { return paused ? 0.5 : 0; }, [paused]); const playAnimatedProps = (0, _reactNativeReanimated.useAnimatedProps)(() => { return { progress: (0, _reactNativeReanimated.withTiming)(playAnimated.value) }; }); const fullscreenAnimatedProps = (0, _reactNativeReanimated.useAnimatedProps)(() => { return { progress: (0, _reactNativeReanimated.withTiming)(isFullScreen.value ? 0.5 : 0) }; }); const autoPlayAnimatedProps = (0, _reactNativeReanimated.useAnimatedProps)(() => { return { progress: (0, _reactNativeReanimated.withTiming)(autoPlayAnimation.value, { duration: 600 }) }; }); /** * useEffect */ (0, _react.useEffect)(() => { mounted.current = true; _reactNativeOrientationLocker.default.lockToPortrait(); _reactNative.StatusBar.setBarStyle('light-content'); paused ? pause() : play(); const unBeforeRemove = navigation === null || navigation === void 0 ? void 0 : navigation.addListener('beforeRemove', e => { e === null || e === void 0 ? void 0 : e.preventDefault(); if (isFullScreen.value) { toggleFullScreen(); } else { navigation.dispatch(e.data.action); } }); return () => { mounted.current = false; clearControlTimeout(); pause(); _reactNativeOrientationLocker.default.lockToPortrait(); unBeforeRemove && unBeforeRemove(); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); /** * Set a timeout when the controls are shown * that hides them after a length of time. */ const setControlTimeout = () => { 'worklet'; controlViewOpacity.value = (0, _reactNativeReanimated.withDelay)(controlTimeout, (0, _reactNativeReanimated.withTiming)(0)); }; /** * Clear the hide controls timeout. */ const clearControlTimeout = () => { 'worklet'; (0, _reactNativeReanimated.cancelAnimation)(controlViewOpacity); }; /** * Reset the timer completely */ const resetControlTimeout = () => { 'worklet'; clearControlTimeout(); setControlTimeout(); }; /** * Animation to show controls * fade in. */ const showControlAnimation = () => { 'worklet'; controlViewOpacity.value = (0, _reactNativeReanimated.withTiming)(1, controlAnimteConfig); setControlTimeout(); }; /** * Animation to show controls * fade out. */ const hideControlAnimation = () => { 'worklet'; controlViewOpacity.value = (0, _reactNativeReanimated.withTiming)(0, controlAnimteConfig); }; /** * check on tap icon * @returns bool */ const checkTapTakesEffect = () => { 'worklet'; if (disableControl) { return false; } resetControlTimeout(); if (controlViewOpacity.value === 0) { showControlAnimation(); return false; } return true; }; const seekByStep = function () { let isBack = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; seekTo(currentTime - (isBack ? 10 : -10)); }; /** * Toggle player full screen state on <Video> component */ const enterFullScreen = () => { onEnterFullscreen === null || onEnterFullscreen === void 0 ? void 0 : onEnterFullscreen(); setIsFullscreen(true); _reactNative.StatusBar.setHidden(true, 'fade'); _reactNativeOrientationLocker.default.lockToLandscape(); isFullScreen.value = true; videoHeight.value = width; }; const exitFullScreen = () => { onExitFullscreen === null || onExitFullscreen === void 0 ? void 0 : onExitFullscreen(); setIsFullscreen(false); _reactNative.StatusBar.setHidden(false, 'fade'); _reactNativeOrientationLocker.default.lockToPortrait(); isFullScreen.value = false; videoHeight.value = videoDefaultHeight; }; const toggleFullScreenOnJS = () => { _reactNativeOrientationLocker.default.getOrientation(orientation => { if (isFullScreen.value || orientation !== _reactNativeOrientationLocker.OrientationType.PORTRAIT) { exitFullScreen(); _reactNative.StatusBar.setHidden(false, 'fade'); } else { enterFullScreen(); _reactNative.StatusBar.setHidden(true, 'fade'); } }); }; const toggleFullScreen = () => { 'worklet'; const status = checkTapTakesEffect(); if (!status) { return; } (0, _reactNativeReanimated.runOnJS)(toggleFullScreenOnJS)(); }; /** * on pan event */ const defalutPanGesture = _reactNativeGestureHandler.Gesture.Pan().onStart(_ref2 => { let { velocityY, velocityX } = _ref2; panIsVertical.value = Math.abs(velocityY) > Math.abs(velocityX); }).onUpdate(_ref3 => { let { translationY } = _ref3; controlViewOpacity.value = (0, _reactNativeReanimated.withTiming)(0, { duration: 100 }); if (isFullScreen.value) { if (translationY > 0 && Math.abs(translationY) < 100) { videoScale.value = (0, _utils.clamp)(0.9, 1 - Math.abs(translationY) * 0.008, 1); videoTransY.value = translationY; } } else { if (translationY < 0 && Math.abs(translationY) < 40) { videoScale.value = Math.abs(translationY) * 0.012 + 1; } } }).onEnd((_ref4, success) => { let { translationY } = _ref4; if (!panIsVertical.value && !success) { return; } if (isFullScreen.value) { if (translationY >= 100) { (0, _reactNativeReanimated.runOnJS)(exitFullScreen)(); } } else { if (-translationY >= 40) { (0, _reactNativeReanimated.runOnJS)(enterFullScreen)(); } } videoTransY.value = 0; videoScale.value = (0, _reactNativeReanimated.withTiming)(1); }); const onPanGesture = onCustomPanGesture ? onCustomPanGesture : defalutPanGesture; const singleTapHandler = _reactNativeGestureHandler.Gesture.Tap().onEnd((_event, success) => { if (disableControl) { return; } if (success) { if (controlViewOpacity.value === 0) { controlViewOpacity.value = (0, _reactNativeReanimated.withTiming)(1, controlAnimteConfig); setControlTimeout(); } else { controlViewOpacity.value = (0, _reactNativeReanimated.withTiming)(0, controlAnimteConfig); } } }); const doubleTapHandle = _reactNativeGestureHandler.Gesture.Tap().numberOfTaps(2).maxDuration(doubleTapInterval).onStart(_ref5 => { let { x } = _ref5; doubleTapIsAlive.value = x < leftDoubleTapBoundary && x > rightDoubleTapBoundary; }).onEnd((_ref6, success) => { let { x, y, numberOfPointers } = _ref6; if (success) { if (numberOfPointers !== 1) { return; } if (x < leftDoubleTapBoundary) { var _rippleLeft$current; doubleLeftOpacity.value = 1; (_rippleLeft$current = rippleLeft.current) === null || _rippleLeft$current === void 0 ? void 0 : _rippleLeft$current.onPress({ x, y }); (0, _reactNativeReanimated.runOnJS)(seekByStep)(true); return; } if (x > rightDoubleTapBoundary) { var _rippleRight$current; doubleRightOpacity.value = 1; (_rippleRight$current = rippleRight.current) === null || _rippleRight$current === void 0 ? void 0 : _rippleRight$current.onPress({ x: x - rightDoubleTapBoundary, y }); (0, _reactNativeReanimated.runOnJS)(seekByStep)(false); return; } } }); /** * On toggle play * @returns */ const togglePlayOnJS = () => { if (isLoadEnd) { onReplyVideo(); setIsLoadEnd(false); } onTapPause === null || onTapPause === void 0 ? void 0 : onTapPause(!paused); paused ? play() : pause(); }; const onPauseTapHandler = () => { 'worklet'; const status = checkTapTakesEffect(); if (!status) { return; } (0, _reactNativeReanimated.runOnJS)(togglePlayOnJS)(); }; /** * on tap back * @returns */ const onBackTapHandlerOnJS = () => { _reactNativeOrientationLocker.default.getOrientation(orientation => { if (isFullScreen.value || orientation !== _reactNativeOrientationLocker.OrientationType.PORTRAIT) { setIsFullscreen(false); exitFullScreen(); _reactNative.StatusBar.setHidden(false, 'fade'); } else { onTapBack === null || onTapBack === void 0 ? void 0 : onTapBack(); } }); }; /** * When load starts we display a loading icon * and show the controls. */ const onLoadStart = () => { setIsLoading(true); }; /** * Toggle between showing time remaining or * video duration in the timer control */ const toggleTimerOnJS = () => { setShowTimeRemaining(!showTimeRemaining); }; const toggleTimer = () => { 'worklet'; const status = checkTapTakesEffect(); if (!status) { return; } (0, _reactNativeReanimated.runOnJS)(toggleTimerOnJS)(); }; const onTapSlider = () => { if (disableControl) { return; } if (controlViewOpacity.value === 0) { showControlAnimation(); } }; /** * Calculate the time to show in the timer area * based on if they want to see time remaining * or duration. Formatted to look as 00:00. */ const calculateTime = () => { return showTimeRemaining ? `${(0, _videoUtils.formatTimeToMins)(currentTime)}` : `-${(0, _videoUtils.formatTime)({ time: duration - currentTime, duration: duration })}`; }; /** * Seek to a time in the video. * * @param {float} time time to seek to in ms */ const seekTo = function () { var _videoPlayer$current; let time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; setCurrentTime(time); (_videoPlayer$current = videoPlayer.current) === null || _videoPlayer$current === void 0 ? void 0 : _videoPlayer$current.seek(time); }; const onLoad = data => { setDuration(data === null || data === void 0 ? void 0 : data.duration); max.value = data === null || data === void 0 ? void 0 : data.duration; setIsLoading(false); setControlTimeout(); }; const onEnd = () => { setIsLoadEnd(true); pause(); onVideoPlayEnd === null || onVideoPlayEnd === void 0 ? void 0 : onVideoPlayEnd(); }; /** * For onSeek we clear scrubbing if set. * * @param {object} data The video meta data */ const onSeek = data => { if (isScrubbing.value) { // Seeking may be false here if the user released the seek bar while the player was still processing // the last seek command. In this case, perform the steps that have been postponed. if (!isSeeking.current) { setControlTimeout(); pause(); } isSeeking.current = false; isScrubbing.value = false; setCurrentTime(data.currentTime); } else { isSeeking.current = false; } if (onPostSeek) { onPostSeek(data); } }; /** * For onprogress we fire listeners that * update our seekbar and timer. * * @param {object} data The video meta data */ const onProgress = data => { const { currentTime: cTime } = data; if (!isScrubbing.value) { if (!isSeeking.current) { progress.value = cTime; } setCurrentTime(cTime); } if (onPostProgress) { onPostProgress(data); } }; /** * on replay video */ const onReplyVideo = () => { seekTo(0); setCurrentTime(0); progress.value = 0; }; /** * play the video */ const play = () => { onPausedChange(false); }; /** * pause the video */ const pause = () => { onPausedChange(true); }; /** * on toggle auto play mode * @returns */ const toggleAutoPlayOnJS = () => { setAllowAutoPlayVideo(!allowAutoPlayVideo); onToggleAutoPlay === null || onToggleAutoPlay === void 0 ? void 0 : onToggleAutoPlay(!allowAutoPlayVideo); }; const toggleAutoPlay = () => { 'worklet'; const status = checkTapTakesEffect(); if (!status) { return; } autoPlayAnimation.value = autoPlayAnimation.value === 0 ? 0.5 : 0; autoPlayTextAnimation.value = (0, _reactNativeReanimated.withTiming)(1); autoPlayTextAnimation.value = (0, _reactNativeReanimated.withDelay)(3000, (0, _reactNativeReanimated.withTiming)(0)); (0, _reactNativeReanimated.runOnJS)(toggleAutoPlayOnJS)(); }; const _renderMore = (0, _react.useCallback)(() => /*#__PURE__*/_react.default.createElement(_tapControler.TapControler, { onPress: onMoreTapHandler }, renderMore ? renderMore() : /*#__PURE__*/_react.default.createElement(_reactNative.Image, { source: require('./assets/more_24.png'), style: styles.more })), // eslint-disable-next-line react-hooks/exhaustive-deps [renderMore]); const onBackTapHandler = () => { 'worklet'; const status = checkTapTakesEffect(); if (!status) { return; } (0, _reactNativeReanimated.runOnJS)(onBackTapHandlerOnJS)(); }; const _renderBack = (0, _react.useCallback)(() => /*#__PURE__*/_react.default.createElement(_tapControler.TapControler, { onPress: onBackTapHandler }, renderBackIcon ? renderBackIcon() : /*#__PURE__*/_react.default.createElement(_reactNative.Image, { source: require('./assets/right_16.png'), style: styles.back })), // eslint-disable-next-line react-hooks/exhaustive-deps [renderBackIcon]); const _renderFullScreenBack = (0, _react.useCallback)(() => /*#__PURE__*/_react.default.createElement(_tapControler.TapControler, { onPress: onBackTapHandler }, renderFullScreenBackIcon ? renderFullScreenBackIcon() : /*#__PURE__*/_react.default.createElement(_reactNative.Image, { source: require('./assets/right_16.png'), style: styles.back })), // eslint-disable-next-line react-hooks/exhaustive-deps [renderBackIcon]); const onMoreTapHandler = () => { 'worklet'; const status = checkTapTakesEffect(); if (!status) { return; } if (onTapMore) { (0, _reactNativeReanimated.runOnJS)(onTapMore)(); } }; /** * Render the seekbar and attach its handlers */ const onSlidingComplete = val => { isSeeking.current = true; seekTo(val); }; const onSlidingStart = () => { clearControlTimeout(); }; const taps = _reactNativeGestureHandler.Gesture.Exclusive(doubleTapHandle, singleTapHandler); const gesture = _reactNativeGestureHandler.Gesture.Race(onPanGesture, taps); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_reactNative.StatusBar, { barStyle: 'light-content', translucent: true, backgroundColor: '#000' }), /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.GestureDetector, { gesture: gesture }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [styles.container, videoStyle, style] }, /*#__PURE__*/_react.default.createElement(_reactNativeVideo.default, _extends({}, rest, { ref: videoPlayer, resizeMode: resizeMode, paused: paused, onLoadStart: onLoadStart, style: styles.video, source: source, onLoad: onLoad, onSeek: onSeek, onEnd: onEnd, onProgress: onProgress, fullscreenAutorotate: true })), Boolean(children) && children, /*#__PURE__*/_react.default.createElement(_videoLoading.VideoLoader, { loading: loading }), /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: _reactNative.StyleSheet.absoluteFillObject }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [styles.controlView, controlViewStyles] }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { hitSlop: hitSlop, style: [controlStyle.group, styles.topControls, topControlStyle] }, Boolean(onTapBack) && _renderBack(), /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: controlStyle.line }, Boolean(onToggleAutoPlay) && /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [controlStyle.autoPlayText, autoPlayTextStyle] }, /*#__PURE__*/_react.default.createElement(_components.Text, { tx: allowAutoPlayVideo ? onAutoPlayText : offAutoPlayText, t4: true, color: '#fff' })), Boolean(onToggleAutoPlay) && /*#__PURE__*/_react.default.createElement(_tapControler.TapControler, { onPress: toggleAutoPlay, style: controlStyle.autoPlay }, /*#__PURE__*/_react.default.createElement(AnimatedLottieView, { animatedProps: autoPlayAnimatedProps, source: require('./assets/lottie-auto-play.json') })), Boolean(onTapMore) && _renderMore())), /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [controlStyle.group, styles.topControls, styles.topFullscreenControls, topFullscreenControlStyle], pointerEvents: isFullScreenState ? 'auto' : 'none' }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: controlStyle.line }, Boolean(onTapBack) && _renderFullScreenBack(), /*#__PURE__*/_react.default.createElement(_components.Text, { tx: headerBarTitle, h5: true, numberOfLines: 1, style: styles.headerBarTitle, color: _palette.palette.W(1) })), /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: controlStyle.line }, Boolean(onToggleAutoPlay) && /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [controlStyle.autoPlayText, autoPlayTextStyle] }, /*#__PURE__*/_react.default.createElement(_components.Text, { tx: allowAutoPlayVideo ? onAutoPlayText : offAutoPlayText, t4: true, color: '#fff' })), Boolean(onToggleAutoPlay) && /*#__PURE__*/_react.default.createElement(_tapControler.TapControler, { onPress: toggleAutoPlay, style: controlStyle.autoPlay }, /*#__PURE__*/_react.default.createElement(AnimatedLottieView, { animatedProps: autoPlayAnimatedProps, source: require('./assets/lottie-auto-play.json') })), Boolean(onTapMore) && _renderMore())), /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: controlStyle.pauseView }, /*#__PURE__*/_react.default.createElement(_tapControler.TapControler, { onPress: onPauseTapHandler, style: controlStyle.pause }, /*#__PURE__*/_react.default.createElement(AnimatedLottieView, { animatedProps: playAnimatedProps, source: require('./assets/lottie-play.json') }))), /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [controlStyle.group, controlStyle.bottomControls, bottomControlStyle] }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: [controlStyle.bottomControlGroup, controlStyle.row] }, /*#__PURE__*/_react.default.createElement(_tapControler.TapControler, { onPress: toggleTimer }, /*#__PURE__*/_react.default.createElement(_components.Text, { style: controlStyle.timerText }, /*#__PURE__*/_react.default.createElement(_components.Text, { style: controlStyle.timerText, color: _palette.palette.W(1), tx: calculateTime(), t3: true }), /*#__PURE__*/_react.default.createElement(_components.Text, { style: controlStyle.timerText, color: _palette.palette.W(1), tx: ` / ${(0, _videoUtils.formatTimeToMins)(duration)}`, t3: true }))), /*#__PURE__*/_react.default.createElement(_tapControler.TapControler, { onPress: toggleFullScreen, style: controlStyle.fullToggle }, renderFullScreen ? renderFullScreen() : /*#__PURE__*/_react.default.createElement(AnimatedLottieView, { animatedProps: fullscreenAnimatedProps, source: require('./assets/lottie-fullscreen.json') }))), /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [{ width: height - insetsRef.current.top - insetsRef.current.bottom - 40 }, fullScreenSliderStyle] }, duration > 0 && /*#__PURE__*/_react.default.createElement(_index.Slider, _extends({ theme: theme, progress: progress, onSlidingComplete: onSlidingComplete, onSlidingStart: onSlidingStart, minimumValue: min, maximumValue: max, isScrubbing: isScrubbing, bubble: _videoUtils.secondToTime, disableTapEvent: true, onTap: onTapSlider, thumbScaleValue: controlViewOpacity, thumbWidth: 8, sliderHeight: 2 }, sliderProps))))), /*#__PURE__*/_react.default.createElement(_ripple.Ripple, { ref: rippleLeft, onAnimationEnd: () => { doubleLeftOpacity.value = 0; }, style: [controlStyle.doubleTap, controlStyle.leftDoubleTap], containerStyle: [{ width: leftDoubleTapBoundary }] }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: getDoubleLeftStyle }, /*#__PURE__*/_react.default.createElement(_lottieReactNative.default, { source: require('./assets/lottie-seek-back.json'), autoPlay: true, loop: true, style: controlStyle.backStep }), /*#__PURE__*/_react.default.createElement(_components.Text, { tx: "10s", isCenter: true, color: _palette.palette.W(1), t5: true }))), /*#__PURE__*/_react.default.createElement(_ripple.Ripple, { ref: rippleRight, onAnimationEnd: () => { doubleRightOpacity.value = 0; }, style: [controlStyle.doubleTap, controlStyle.rightDoubleTapContainer], containerStyle: [{ width: leftDoubleTapBoundary }] }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: getDoubleRightStyle }, /*#__PURE__*/_react.default.createElement(_lottieReactNative.default, { source: require('./assets/lottie-seek-back.json'), autoPlay: true, loop: true, style: [controlStyle.backStep, { transform: [{ rotate: '90deg' }] }] }), /*#__PURE__*/_react.default.createElement(_components.Text, { tx: "10s", isCenter: true, color: _palette.palette.W(1), t5: true }))), /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: [styles.slider, bottomSliderStyle] }, duration > 0 && /*#__PURE__*/_react.default.createElement(_index.Slider, _extends({ theme: theme, progress: progress, onSlidingComplete: onSlidingComplete, onSlidingStart: onSlidingStart, minimumValue: min, maximumValue: max, isScrubbing: isScrubbing, bubble: value => { return (0, _videoUtils.secondToTime)(value); }, disableTapEvent: true, onTap: onTapSlider, thumbScaleValue: controlViewOpacity, thumbWidth: 12, sliderHeight: 2 }, sliderProps)))), _utils2.isIos && /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: [styles.stopBackView, { left: -insets.left }], pointerEvents: isFullScreenState ? 'auto' : 'none' })))); }); VideoPlayer.displayName = 'VideoPlayer'; var _default = VideoPlayer; exports.default = _default; const styles = _reactNative.StyleSheet.create({ controlView: { backgroundColor: 'rgba(0,0,0,.6)', justifyContent: 'center', overflow: 'hidden', ..._reactNative.StyleSheet.absoluteFillObject }, headerBarTitle: { marginLeft: 20, maxWidth: height / 2 }, slider: { width: width, zIndex: 1, position: 'absolute', left: 0, right: 0, bottom: 0 }, stopBackView: { height: '100%', position: 'absolute', width: 40 }, topControls: { flexDirection: 'row', justifyContent: 'space-between', position: 'absolute', top: 12, width: '100%' }, topFullscreenControls: { top: 32 }, video: { width: '100%', height: '100%' }, back: { width: 16, height: 16 }, more: { width: 24, height: 24 }, container: { backgroundColor: _palette.palette.B(1), width: '100%', alignItems: 'center', elevation: 10, justifyContent: 'center', zIndex: 10 } }); const controlStyle = _reactNative.StyleSheet.create({ autoPlay: { height: 24, marginRight: 32, width: 24 }, autoPlayText: { marginRight: 10 }, bottomControlGroup: { justifyContent: 'space-between', marginBottom: 10 }, bottomControls: { bottom: 0, position: 'absolute', width: '100%' }, fullToggle: { height: 20, width: 20 }, group: { paddingHorizontal: 20 }, line: { alignItems: 'center', flexDirection: 'row' }, pause: { height: 48, width: 48 }, pauseView: { alignSelf: 'center' }, row: { alignItems: 'center', flexDirection: 'row' }, timerText: { textAlign: 'right' }, doubleTap: { position: 'absolute', height: '100%', justifyContent: 'center', alignContent: 'center', alignItems: 'center' }, leftDoubleTap: { left: 0, borderTopRightRadius: width, borderBottomRightRadius: width }, rightDoubleTapContainer: { borderTopLeftRadius: width, borderBottomLeftRadius: width, right: 0 }, backStep: { width: 40, height: 40 } }); //# sourceMappingURL=index.js.map