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
JavaScript
"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