UNPKG

react-native-insta-story-2

Version:

custom patched version of react-native-insta-story Story component for React Native.

213 lines (200 loc) 5.17 kB
import React, {Fragment, useRef, useState, useEffect} from "react"; import {Dimensions, View, Platform, TextStyle} from "react-native"; import Modal from "react-native-modalbox"; import StoryListItem from "./StoryListItem"; import StoryCircleListView from "./StoryCircleListView"; import {isNullOrWhitespace} from "./helpers/ValidationHelpers"; import type {IUserStory} from "./interfaces/IUserStory"; import AndroidCubeEffect from "./components/AndroidCubeEffect"; import CubeNavigationHorizontal from "./components/CubeNavigationHorizontal"; type Props = { data: IUserStory[], style?: any, unPressedBorderColor?: string, pressedBorderColor?: string, onClose?: function, onStart?: function, duration?: number, swipeText?: string, customSwipeUpComponent?: any, customCloseComponent?: any, avatarSize?: number, showAvatarText?: boolean, avatarTextStyle?: TextStyle, // custom patched avatarWrapperStyle?: TextStyle, customStoryCircleListItem?: any, customStoryComponent?: any, }; export const Story = (props: Props) => { const { data, unPressedBorderColor, pressedBorderColor, style, onStart, onClose, duration, swipeText, customSwipeUpComponent, customCloseComponent, avatarSize, showAvatarText, avatarTextStyle, // custom patched customStoryCircleListItem, avatarWrapperStyle, customStoryComponent, } = props; const [dataState, setDataState] = useState(data); const [isModalOpen, setIsModalOpen] = useState(false); const [currentPage, setCurrentPage] = useState(0); const [selectedData, setSelectedData] = useState([]); const cube = useRef(); // Component Functions const _handleStoryItemPress = (item, index) => { const newData = dataState.slice(index); if (onStart) { onStart(item); } setCurrentPage(0); setSelectedData(newData); setIsModalOpen(true); }; useEffect(() => { handleSeen(); }, [currentPage]); const handleSeen = () => { const seen = selectedData[currentPage]; const seenIndex = dataState.indexOf(seen); if (seenIndex > 0) { if (!dataState[seenIndex]?.seen) { let tempData = dataState; dataState[seenIndex] = { ...dataState[seenIndex], seen: true }; setDataState(tempData); } } }; function onStoryFinish(state) { if (!isNullOrWhitespace(state)) { if (state == "next") { const newPage = currentPage + 1; if (newPage < selectedData.length) { setCurrentPage(newPage); cube?.current?.scrollTo(newPage); } else { setIsModalOpen(false); setCurrentPage(0); if (onClose) { onClose(selectedData[selectedData.length - 1]); } } } else if (state == "previous") { const newPage = currentPage - 1; if (newPage < 0) { setIsModalOpen(false); setCurrentPage(0); } else { setCurrentPage(newPage); cube?.current?.scrollTo(newPage); } } } } const renderStoryList = () => selectedData.map((x, i) => { return ( <StoryListItem duration={duration * 1000} key={i} profileName={x.name} profileImage={x.thumbnail} stories={x.stories} currentPage={currentPage} onFinish={onStoryFinish} swipeText={swipeText} customSwipeUpComponent={customSwipeUpComponent} customCloseComponent={customCloseComponent} onClosePress={() => { setIsModalOpen(false); if (onClose) { onClose(x); } }} index={i} // custom patched customStoryComponent={customStoryComponent} /> ); }); const renderCube = () => { if (Platform.OS == "ios") { return ( <CubeNavigationHorizontal ref={cube} callBackAfterSwipe={(x) => { if (x != currentPage) { setCurrentPage(parseInt(x)); } }} > {renderStoryList()} </CubeNavigationHorizontal> ); } else { return ( <AndroidCubeEffect ref={cube} callBackAfterSwipe={(x) => { if (x != currentPage) { setCurrentPage(parseInt(x)); } }} > {renderStoryList()} </AndroidCubeEffect> ); } }; return ( <Fragment> <View style={style}> <StoryCircleListView handleStoryItemPress={_handleStoryItemPress} data={dataState} avatarSize={avatarSize} unPressedBorderColor={unPressedBorderColor} pressedBorderColor={pressedBorderColor} showText={showAvatarText} textStyle={avatarTextStyle} // custom patched customStoryCircleListItem={customStoryCircleListItem} avatarWrapperStyle={avatarWrapperStyle} /> </View> <Modal style={{ flex: 1, height: Dimensions.get("window").height, width: Dimensions.get("window").width }} isOpen={isModalOpen} onClosed={() => setIsModalOpen(false)} position='center' swipeToClose swipeArea={250} backButtonClose coverScreen={true} > {renderCube()} </Modal> </Fragment> ); }; export default Story; Story.defaultProps = { showAvatarText: true };