@zezosoft/zezo-ott-react-native-video-player
Version:
React Native OTT Video Player for Android & iOS. Supports playlists, seasons, auto-next playback, subtitles, theming, analytics, fullscreen mode, and custom controls. 🚀 Powered by ZezoSoft.
154 lines (151 loc) • 4.57 kB
JavaScript
"use strict";
import React, { useEffect } from 'react';
import { TouchableOpacity, View, StyleSheet, Text } from 'react-native';
import Animated, { useSharedValue, useAnimatedStyle, withTiming } from 'react-native-reanimated';
import { scale } from 'react-native-size-matters';
import { useVideoPlayerStore } from "../store/videoPlayerStore.js";
import { videoRef } from "../utils/videoRef.js";
import Display from "../utils/Display.js";
import { handleNext } from "../utils/index.js";
import { useVideoPlayerConfig } from "../context/index.js";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
const SkipAndNextControls = ({
onPressEpisode,
reportProgress
}) => {
const {
activeTrack,
currentTime,
isSkipIntroVisible,
isNextEpisodeVisible,
setIsNextEpisodeVisible,
setIsSkipIntroVisible,
settingsModal,
controlsVisible
} = useVideoPlayerStore();
const {
colors
} = useVideoPlayerConfig();
if (activeTrack?.type !== 'series') return null;
const showSkipIntro = isSkipIntroVisible && !settingsModal.isVisible && activeTrack.skipIntro && activeTrack.skipIntro.start < currentTime && currentTime < activeTrack.skipIntro.end;
const showNextEpisode = isNextEpisodeVisible && !settingsModal.isVisible && activeTrack.nextEpisodeAt && activeTrack.nextEpisodeAt < currentTime;
return /*#__PURE__*/_jsxs(_Fragment, {
children: [showSkipIntro && /*#__PURE__*/_jsx(ActionButton, {
label: "Skip intro",
onPress: () => {
if (activeTrack.skipIntro?.end) {
videoRef?.current?.seek(activeTrack.skipIntro.end);
}
},
onCancel: () => setIsSkipIntroVisible(false),
position: "left",
colors: {
text: colors.black,
onBackground: colors.onBackground
},
controlsVisible: controlsVisible
}), showNextEpisode && /*#__PURE__*/_jsx(ActionButton, {
label: "Next episode",
onPress: () => {
reportProgress('EPISODE_CHANGE');
handleNext({
onPressEpisode,
autoNext: true
});
},
onCancel: () => setIsNextEpisodeVisible(false),
position: "right",
colors: {
text: colors.black,
onBackground: colors.onBackground
},
controlsVisible: controlsVisible
})]
});
};
export default SkipAndNextControls;
const ActionButton = ({
label,
onPress,
onCancel,
position,
colors,
controlsVisible
}) => {
const opacity = useSharedValue(0);
const translateY = useSharedValue(10);
const bottom = useSharedValue(controlsVisible ? Display.setHeight(12) : Display.setHeight(10));
// Animate show
useEffect(() => {
opacity.value = withTiming(1, {
duration: 100
});
translateY.value = withTiming(0, {
duration: 100
});
}, [opacity, translateY]);
// Animate bottom when controls toggle
useEffect(() => {
bottom.value = withTiming(controlsVisible ? Display.setHeight(12) : Display.setHeight(10), {
duration: 100
});
}, [bottom, controlsVisible]);
const animatedStyle = useAnimatedStyle(() => ({
opacity: opacity.value,
transform: [{
translateY: translateY.value
}],
bottom: bottom.value
}));
return /*#__PURE__*/_jsx(Animated.View, {
style: [styles.overlayButton, animatedStyle, position === 'left' ? {
left: scale(58)
} : {
right: scale(58)
}],
children: /*#__PURE__*/_jsxs(View, {
style: styles.buttonRow,
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
style: [styles.actionButton, {
backgroundColor: colors.onBackground
}],
onPress: onPress,
children: /*#__PURE__*/_jsx(Text, {
style: makeTextStyle(colors.text),
children: label
})
}), /*#__PURE__*/_jsx(TouchableOpacity, {
style: [styles.actionButton, {
backgroundColor: colors.onBackground
}],
onPress: onCancel,
children: /*#__PURE__*/_jsx(Text, {
style: makeTextStyle(colors.text),
children: "Cancel"
})
})]
})
});
};
const styles = StyleSheet.create({
overlayButton: {
position: 'absolute',
// fixed, not animated
zIndex: 10
},
buttonRow: {
flexDirection: 'row',
gap: scale(10)
},
actionButton: {
paddingHorizontal: scale(20),
paddingVertical: scale(8),
borderRadius: scale(8),
alignSelf: 'flex-start'
}
});
const makeTextStyle = color => ({
color,
fontWeight: '600'
});
//# sourceMappingURL=SkipAndNextControls.js.map