UNPKG

react-native-story-component

Version:
353 lines (349 loc) 12.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _reactNativeSwipeGestures = _interopRequireDefault(require("react-native-swipe-gestures")); var _usePrevious = _interopRequireDefault(require("../helpers/usePrevious")); var _ValidationHelpers = require("../helpers/ValidationHelpers"); var _index = require("../index"); var _StoryImage = _interopRequireDefault(require("./StoryImage")); var _AnimationBar = _interopRequireDefault(require("./AnimationBar")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 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; } /* eslint-disable react-native/no-inline-styles */ const { width, height } = _reactNative.Dimensions.get('window'); const StoryListItem = props => { const [loading, setLoading] = (0, _react.useState)(true); const [pressed, setPressed] = (0, _react.useState)(false); const [currStoryIndex, setCurrStoryIndex] = (0, _react.useState)(0); const [content, setContent] = (0, _react.useState)(props.stories); const [currImageWidth, setCurrImageWidth] = (0, _react.useState)(0); const [currImageHeight, setCurrImageHeight] = (0, _react.useState)(0); const currStory = (0, _react.useMemo)(() => content[currStoryIndex], [content, currStoryIndex]); const currPageIndex = (0, _react.useMemo)(() => props.currentPage, [props.currentPage]); const swipeText = (0, _react.useMemo)(() => { var _content$currStoryInd; return (content === null || content === void 0 ? void 0 : (_content$currStoryInd = content[currStoryIndex]) === null || _content$currStoryInd === void 0 ? void 0 : _content$currStoryInd.swipeText) || props.swipeText || 'Swipe Up'; }, [content, currStoryIndex, props.swipeText]); const progress = (0, _react.useRef)(new _reactNative.Animated.Value(0)).current; const prevPageIndex = (0, _usePrevious.default)(currPageIndex); const prevStoryIndex = (0, _usePrevious.default)(currStoryIndex); const close = (0, _react.useCallback)(state => { let data = [...content]; data.map(x => x.finished = false); setContent(data); progress.setValue(0); if (currPageIndex === props.index) { if (props.onFinish) { props.onFinish(state); } } }, [content, currPageIndex, progress, props]); const next = (0, _react.useCallback)(() => { // check if the next content is not empty setLoading(true); if (currStoryIndex !== content.length - 1) { let data = [...content]; data[currStoryIndex].finished = true; setContent(data); setCurrStoryIndex(currStoryIndex + 1); progress.setValue(0); } else { // the next content is empty close(_index.ActionStates.NEXT); } }, [close, content, currStoryIndex, progress]); const previous = () => { // checking if the previous content is not empty setLoading(true); if (currStoryIndex - 1 >= 0) { let data = [...content]; data[currStoryIndex].finished = false; setContent(data); setCurrStoryIndex(currStoryIndex - 1); progress.setValue(0); } else { // the previous content is empty close(_index.ActionStates.PREVIOUS); } }; const startProgressAnimation = (0, _react.useCallback)(() => { _reactNative.Animated.timing(progress, { toValue: 1, duration: props.duration, useNativeDriver: false }).start(_ref => { let { finished } = _ref; if (finished) next(); }); }, [next, progress, props.duration]); const startStory = (0, _react.useCallback)(() => { _reactNative.Image.getSize(content[currStoryIndex].image, (imageWidth, imageHeight) => { let newHeight = imageHeight; let newWidth = imageWidth; const isImageWidthBiggerThenPhone = imageWidth > width; if (isImageWidthBiggerThenPhone) { newWidth = width; newHeight = imageHeight ? Math.floor(width * (imageHeight / imageWidth)) : width; } const isNewHeightBiggerThenPhone = newHeight > height; if (isNewHeightBiggerThenPhone) { newWidth = height * (imageWidth / imageHeight); newHeight = height; } setCurrImageWidth(newWidth); setCurrImageHeight(newHeight); setLoading(false); progress.setValue(0); startProgressAnimation(); }, errorMsg => { console.log(errorMsg); }); }, [content, currStoryIndex, progress, startProgressAnimation]); // call every page changes (0, _react.useEffect)(() => { const isPrevious = !!prevPageIndex && prevPageIndex > currPageIndex; if (isPrevious) { setCurrStoryIndex(content.length - 1); } else { setCurrStoryIndex(0); } let data = [...content]; data.map((x, i) => { if (isPrevious) { x.finished = true; if (i === content.length - 1) { x.finished = false; } } else { x.finished = false; } }); setContent(data); startStory(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [currPageIndex]); // call every story change requests // ... and decide next or prev (0, _react.useEffect)(() => { if (!(0, _ValidationHelpers.isNullOrWhitespace)(prevStoryIndex)) { const isNextStory = !!prevStoryIndex && currStoryIndex > prevStoryIndex; const isPrevStory = !isNextStory; const nextStory = content[currStoryIndex + 1]; const prevStory = content[currStoryIndex - 1]; if (isNextStory && prevStory.id === currStory.id) { startStory(); } else if (isPrevStory && (nextStory === null || nextStory === void 0 ? void 0 : nextStory.id) === currStory.id) { startStory(); } } // eslint-disable-next-line react-hooks/exhaustive-deps }, [currStoryIndex]); const onSwipeUp = () => { if (props.onClosePress) props.onClosePress(); if (currStory.onPress) currStory.onPress(); }; const onSwipeDown = () => { props === null || props === void 0 ? void 0 : props.onClosePress(); }; const renderSwipeButton = () => { if (props.customSwipeUpButton) { return props.customSwipeUpButton(); } return /*#__PURE__*/_react.default.createElement(_reactNative.Text, { style: styles.swipeText }, swipeText); }; const renderCloseButton = () => { if (props.customCloseButton) { return props.customCloseButton(); } return /*#__PURE__*/_react.default.createElement(_reactNative.Text, { style: styles.closeText }, "X"); }; const renderProfileBanner = () => { if (!props.showProfileBanner) return; if (props.customProfileBanner) return props.customProfileBanner({ image: props.profileImage, name: props.profileName }); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_reactNative.Image, { style: styles.avatarImage, source: props.profileImage }), /*#__PURE__*/_react.default.createElement(_reactNative.Text, { style: styles.avatarText }, props.profileName)); }; const renderStoryImage = () => { if (props.customStoryImage) return props.customStoryImage({ image: currStory.image, onLoadEnd: startStory, imageWidth: currImageWidth, imageHeight: currImageHeight }); return /*#__PURE__*/_react.default.createElement(_StoryImage.default, { source: { uri: currStory.image }, width: currImageWidth, height: currImageHeight, onLoadEnd: startStory }); }; return /*#__PURE__*/_react.default.createElement(_reactNativeSwipeGestures.default, { onSwipeUp: onSwipeUp, onSwipeDown: onSwipeDown, config: { velocityThreshold: 0.3, directionalOffsetThreshold: 80 }, style: styles.container }, /*#__PURE__*/_react.default.createElement(_reactNative.SafeAreaView, { style: styles.backgroundContainer }, renderStoryImage(), loading && /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: styles.spinnerContainer }, /*#__PURE__*/_react.default.createElement(_reactNative.ActivityIndicator, { size: "large", color: "#FFF" }))), /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: styles.content }, /*#__PURE__*/_react.default.createElement(_AnimationBar.default, { currStoryIndex: currStoryIndex, stories: content, progress: progress }), /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: styles.userContainer }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: styles.profileContainer }, renderProfileBanner()), /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, { onPress: () => { if (props.onClosePress) { props.onClosePress(); } } }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: styles.closeIconContainer }, renderCloseButton()))), /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: styles.pressContainer }, /*#__PURE__*/_react.default.createElement(_reactNative.TouchableWithoutFeedback, { onPressIn: () => progress.stopAnimation(), onLongPress: () => setPressed(true), onPressOut: () => { setPressed(false); startProgressAnimation(); }, onPress: () => { if (!pressed && !loading) previous(); } }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: { flex: 0.3 } })), /*#__PURE__*/_react.default.createElement(_reactNative.TouchableWithoutFeedback, { onPressIn: () => progress.stopAnimation(), onLongPress: () => setPressed(true), onPressOut: () => { setPressed(false); startProgressAnimation(); }, onPress: () => { if (!pressed && !loading) next(); } }, /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: { flex: 0.7 } })))), currStory.onPress && /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, { activeOpacity: 1, onPress: onSwipeUp, style: styles.swipeUpBtn }, renderSwipeButton())); }; StoryListItem.defaultProps = { duration: 10000 }; const styles = _reactNative.StyleSheet.create({ container: { flex: 1, backgroundColor: '#000' }, backgroundContainer: { position: 'absolute', top: 0, bottom: 0, left: 0, right: 0, justifyContent: 'center', alignItems: 'center' }, spinnerContainer: { zIndex: -100, position: 'absolute', justifyContent: 'center', backgroundColor: '#000', alignSelf: 'center', width: width, height: height }, content: { flexDirection: 'column', flex: 1 }, userContainer: { height: 50, flexDirection: 'row', justifyContent: 'space-between', paddingHorizontal: 15 }, avatarImage: { height: 30, width: 30, borderRadius: 100 }, avatarText: { fontWeight: 'bold', color: '#FFF', paddingLeft: 10 }, closeIconContainer: { alignItems: 'center', justifyContent: 'center', height: 50, paddingHorizontal: 15 }, pressContainer: { flex: 1, flexDirection: 'row' }, swipeUpBtn: { position: 'absolute', right: 0, left: 0, alignItems: 'center', bottom: _reactNative.Platform.OS === 'ios' ? 20 : 50 }, swipeText: { color: '#FFF', marginTop: 10 }, closeText: { color: '#FFF' }, profileContainer: { flexDirection: 'row', alignItems: 'center' } }); var _default = StoryListItem; exports.default = _default; //# sourceMappingURL=StoryListItem.js.map