diff --git a/README.md b/README.md index 122df66..0769243 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,10 @@ > A decent story component for React-Native +| Preview | +| ----------------------------------------------------------------- | +| Preview Image | + # Table of Contents - [Getting started](#getting-started) @@ -25,21 +29,25 @@ npm i react-native-story-component ## Props -| Name | Description | Type | Default Value | -| :--------------------- | :-------------------------------------------------- | :------------------------------------------------------------------------------------------- | :-----------: | -| data | Array of IUserStory. You can check from interfaces. | object | | -| unPressedBorderColor | Unpressed border color of profile circle | color | red | -| pressedBorderColor | Pressed border color of profile circle | color | grey | -| onClose | Todo when close | function | null | -| onStart | Todo when start | function | null | -| duration | Per story duration seconds | number | 10 | -| swipeText | Text of swipe component | string | Swipe Up | -| customSwipeUpComponent | For use custom component for swipe area | () => component | | -| customCloseComponent | For use custom component for close button | () => component | | -| customStoryList | For use custom component for story list | ({data: IUserStory[], onStoryPress: (item: IUserStory, index: number) => void}) => component | | -| avatarSize | Size of avatar circle | number | 60 | -| showAvatarText | For show or hide avatar text. | bool | true | -| textStyle | For avatar text style | TextStyle | | +| Name | Description | Type | Default Value | +| :------------------- | :--------------------------------------- | :----------------------------------------------- | :-----------: | +| data | Array of stories. | IUserStory[] | | +| unPressedBorderColor | Unpressed border color of profile circle | color | red | +| pressedBorderColor | Pressed border color of profile circle | color | grey | +| onClose | Todo when close | (item: IUserStory) => void | null | +| onStart | Todo when start | (item: IUserStory) => void | null | +| duration | Per story duration in seconds | number | 10 | +| swipeText | Text of swipe component | string | Swipe Up | +| customSwipeUpButton | Custom component for swipe area | () => ReactNode | | +| customCloseButton | Custom component for close button | () => ReactNode | | +| customStoryList | Custom component for story list | (props: ICustomStoryList) => React.ReactNode | | +| customStoryView | Custom component for story view | (props: ICustomStoryView) => React.ReactNode | | +| customProfileBanner | Custom component for profile banner | (props: ICustomProfileBanner) => React.ReactNode | | +| avatarSize | Size of avatar circle | number | 60 | +| showAvatarText | Show or hide avatar text | bool | true | +| showProfileBanner | Show or hide profile banner | bool | true | +| textStyle | Avatar text style | TextStyle | | +| storyListStyle | Story list view style | ViewStyle | | ## Usage @@ -88,13 +96,13 @@ const App = () => { }, ]} duration={10} - onStart={(item) => { - console.log(item); + onStart={(openedStory) => { + console.log(openedStory); }} - onClose={(item) => { - console.log('close: ', item); + onClose={(closedStory) => { + console.log(closedStory); }} - customSwipeUpComponent={() => ( + customSwipeUpButton={() => ( Swipe diff --git a/docs/preview.gif b/docs/preview.gif new file mode 100644 index 0000000..33b2951 Binary files /dev/null and b/docs/preview.gif differ diff --git a/example/App.tsx b/example/App.tsx new file mode 100644 index 0000000..1dd0f29 --- /dev/null +++ b/example/App.tsx @@ -0,0 +1,68 @@ +import React from 'react'; +import { StyleSheet, Text, View } from 'react-native'; +import { StatusBar } from 'expo-status-bar'; +import { faker } from '@faker-js/faker'; + +import Story from 'react-native-story-component'; + +const createStories = () => { + const USER_COUNT = 5; + const USER_STORY_COUNT = 3; + + return [...Array(USER_COUNT).keys()].map((i) => ({ + id: `user-${i}`, + avatar: faker.image.avatar(), + name: faker.name.findName(), + // seen: Math.random() < 0.5, + stories: [...Array(USER_STORY_COUNT).keys()].map((y) => ({ + id: `story-${i}-${y}`, + image: faker.image.imageUrl(1080, 1920, undefined, true), + swipeText: faker.lorem.text(), + onPress: () => console.log(`Story ${i}-${y} swiped!`), + })), + })); +}; + +const App = () => { + return ( + <> + + + { + // return ( + // + // Custom View + // + // ); + // }} + customSwipeUpButton={() => ( + + Swipe + + )} + storyListStyle={styles.story} + /> + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#fff', + }, + story: { + marginTop: 70, + }, +}); + +export default App; diff --git a/example/App.js b/example/index.js similarity index 90% rename from example/App.js rename to example/index.js index be6bdb8..9d5d25a 100644 --- a/example/App.js +++ b/example/index.js @@ -1,6 +1,6 @@ import { registerRootComponent } from 'expo'; -import App from './src/App'; +import App from './App'; // registerRootComponent calls AppRegistry.registerComponent('main', () => App); // It also ensures that whether you load the app in the Expo client or in a native build, diff --git a/example/package.json b/example/package.json index e15c58e..6b52aa1 100644 --- a/example/package.json +++ b/example/package.json @@ -3,7 +3,7 @@ "description": "Example app for react-native-story-component", "version": "0.0.1", "private": true, - "main": "App", + "main": "index", "scripts": { "android": "expo start --android", "ios": "expo start --ios", diff --git a/example/src/App.tsx b/example/src/App.tsx deleted file mode 100644 index 61d757a..0000000 --- a/example/src/App.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import React from 'react'; -import { StyleSheet, Text, View } from 'react-native'; -import { StatusBar } from 'expo-status-bar'; -import { faker } from '@faker-js/faker'; - -import Story from 'react-native-story-component'; - -const createData = () => { - const array = []; - - const USER_COUNT = 10; - const USER_STORY_COUNT = 15; - - for (let i = 1; i <= USER_COUNT; i++) { - const storyArray = []; - for (let k = 1; k <= USER_STORY_COUNT; k++) { - storyArray.push({ - id: i, - image: faker.image.imageUrl(1080, 1920, undefined, true), - swipeText: faker.lorem.text(), - onPress: () => console.log(`Story ${i} swiped!`), - }); - } - - array.push({ - // seen: Math.random() < 0.5, - id: i, - avatar: faker.image.avatar(), - name: faker.name.findName(), - stories: storyArray, - }); - } - - return array; -}; - -const App = () => { - return ( - <> - - - ( - - Swipe - - )} - style={styles.story} - /> - - - ); -}; - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#fff', - }, - story: { - marginTop: 70, - }, -}); - -export default App; diff --git a/src/components/AndroidCubeEffect.js b/src/animations/AndroidCubeEffect.js similarity index 100% rename from src/components/AndroidCubeEffect.js rename to src/animations/AndroidCubeEffect.js diff --git a/src/components/CubeNavigationHorizontal.js b/src/animations/CubeNavigationHorizontal.js similarity index 100% rename from src/components/CubeNavigationHorizontal.js rename to src/animations/CubeNavigationHorizontal.js diff --git a/src/Story.tsx b/src/components/Story.tsx similarity index 63% rename from src/Story.tsx rename to src/components/Story.tsx index e276f3e..9ee579b 100644 --- a/src/Story.tsx +++ b/src/components/Story.tsx @@ -4,36 +4,42 @@ import Modal from 'react-native-modalbox'; import StoryListItem from './StoryListItem'; import StoryCircleListView from './StoryCircleListView'; -import AndroidCubeEffect from './components/AndroidCubeEffect'; -import CubeNavigationHorizontal from './components/CubeNavigationHorizontal'; -import { isNullOrWhitespace } from './helpers/ValidationHelpers'; +import AndroidCubeEffect from '../animations/AndroidCubeEffect'; +import CubeNavigationHorizontal from '../animations/CubeNavigationHorizontal'; -import { CloseStates } from './StoryListItem'; +import { isNullOrWhitespace, isUrl } from '../helpers/ValidationHelpers'; + +import { ActionStates } from '../index'; +import type { + IUserStory, + ICustomStoryView, + ICustomStoryList, + ICustomProfileBanner, +} from '../index'; import type { TextStyle, ViewStyle } from 'react-native'; -import type { IUserStory } from './interfaces/IUserStory'; -declare module './components/CubeNavigationHorizontal' {} +declare module '../animations/CubeNavigationHorizontal' {} -declare module './components/AndroidCubeEffect' {} +declare module '../animations/AndroidCubeEffect' {} type Props = { data: IUserStory[]; - style?: ViewStyle; + storyListStyle?: ViewStyle; unPressedBorderColor?: string; pressedBorderColor?: string; onClose?: (item: IUserStory) => void; onStart?: (item: IUserStory) => void; duration?: number; swipeText?: string; - customSwipeUpComponent?: () => React.ReactNode; - customCloseComponent?: () => React.ReactNode; - customStoryList?: (props: { - data: IUserStory[]; - onStoryPress: (item: IUserStory, index: number) => void; - }) => React.ReactNode; + customSwipeUpButton?: () => React.ReactNode; + customCloseButton?: () => React.ReactNode; + customStoryList?: (props: ICustomStoryList) => React.ReactNode; + customStoryView?: (props: ICustomStoryView) => React.ReactNode; + customProfileBanner?: (props: ICustomProfileBanner) => React.ReactNode; avatarSize?: number; showAvatarText?: boolean; + showProfileBanner?: boolean; avatarTextStyle?: TextStyle; }; @@ -42,16 +48,18 @@ const Story = (props: Props) => { data, unPressedBorderColor, pressedBorderColor, - style, + storyListStyle, onStart, onClose, duration, swipeText, - customSwipeUpComponent, - customCloseComponent, + customSwipeUpButton, + customCloseButton, customStoryList, + customProfileBanner, avatarSize, showAvatarText, + showProfileBanner, avatarTextStyle, } = props; @@ -59,7 +67,7 @@ const Story = (props: Props) => { const [isModalOpen, setIsModalOpen] = useState(false); const [currentPage, setCurrentPage] = useState(0); const [selectedData, setSelectedData] = useState([]); - const cube = useRef(); + const cubeRef = useRef(); const _handleStoryItemPress = (item: IUserStory, index: number) => { const newData = dataState.slice(index); @@ -90,14 +98,14 @@ const Story = (props: Props) => { handleSeen(); }, [currentPage, handleSeen]); - const onStoryFinish = (state: CloseStates) => { + const onStoryFinish = (state: ActionStates) => { if (!isNullOrWhitespace(state)) { - if (state === CloseStates.NEXT) { + if (state === ActionStates.NEXT) { const newPage = currentPage + 1; if (newPage < selectedData.length) { setCurrentPage(newPage); //@ts-ignore - cube?.current?.scrollTo(newPage); + cubeRef?.current?.scrollTo(newPage); } else { setIsModalOpen(false); setCurrentPage(0); @@ -105,7 +113,7 @@ const Story = (props: Props) => { onClose(selectedData[selectedData.length - 1]); } } - } else if (state === CloseStates.PREVIOUS) { + } else if (state === ActionStates.PREVIOUS) { const newPage = currentPage - 1; if (newPage < 0) { setIsModalOpen(false); @@ -113,67 +121,49 @@ const Story = (props: Props) => { } else { setCurrentPage(newPage); //@ts-ignore - cube?.current?.scrollTo(newPage); + cubeRef?.current?.scrollTo(newPage); } } } }; - const renderStoryList = () => - selectedData.map((story, i) => { + const onClosePress = (story: IUserStory) => { + setIsModalOpen(false); + if (onClose) onClose(story); + }; + + const renderStoryList = () => { + return selectedData.map((story, i) => { + if (props.customStoryView) + return props.customStoryView({ + index: i, + data: story, + currentPage, + changeStory: onStoryFinish, + close: () => onClosePress(story), + }); + return ( { - setIsModalOpen(false); - if (onClose) { - onClose(story); - } - }} - index={i} + customSwipeUpButton={customSwipeUpButton} + customCloseButton={customCloseButton} + customProfileBanner={customProfileBanner} + showProfileBanner={showProfileBanner} + onClosePress={() => onClosePress(story)} /> ); }); - - const renderCube = () => { - if (Platform.OS === 'ios') { - return ( - { - if (parseInt(`${x}`, 10) !== currentPage) { - setCurrentPage(parseInt(`${x}`, 10)); - } - }} - > - {renderStoryList()} - - ); - } else { - return ( - { - if (parseInt(`${x}`, 10) !== currentPage) { - setCurrentPage(parseInt(`${x}`, 10)); - } - }} - > - {renderStoryList()} - - ); - } }; const renderStoryCircleList = () => { @@ -197,9 +187,41 @@ const Story = (props: Props) => { ); }; + const renderCube = () => { + if (Platform.OS === 'ios') { + return ( + { + if (parseInt(`${x}`, 10) !== currentPage) { + setCurrentPage(parseInt(`${x}`, 10)); + } + }} + > + {renderStoryList()} + + ); + } + + return ( + { + if (parseInt(`${x}`, 10) !== currentPage) { + setCurrentPage(parseInt(`${x}`, 10)); + } + }} + > + {renderStoryList()} + + ); + }; + return ( <> - {renderStoryCircleList()} + {renderStoryCircleList()} { Story.defaultProps = { showAvatarText: true, + showProfileBanner: true, }; const styles = StyleSheet.create({ diff --git a/src/StoryCircleListItem.tsx b/src/components/StoryCircleListItem.tsx similarity index 90% rename from src/StoryCircleListItem.tsx rename to src/components/StoryCircleListItem.tsx index f6c431f..8b1114c 100644 --- a/src/StoryCircleListItem.tsx +++ b/src/components/StoryCircleListItem.tsx @@ -8,10 +8,12 @@ import { StyleSheet, Platform, } from 'react-native'; -import { usePrevious } from './helpers/StateHelpers'; + +import { isUrl } from '../helpers/ValidationHelpers'; +import { usePrevious } from '../helpers/StateHelpers'; import type { TextStyle } from 'react-native'; -import type { IUserStory } from './interfaces/IUserStory'; +import type { IUserStory } from '../index'; interface Props { item: IUserStory; @@ -81,10 +83,10 @@ const StoryCircleListItem = (props: Props) => { width: size, borderRadius: size / 2, }} - source={{ uri: item.avatar }} + source={isUrl(item.avatar) ? { uri: item.avatar } : item.avatar} defaultSource={ Platform.OS === 'ios' - ? require('./assets/images/no_avatar.png') + ? require('../assets/images/no_avatar.png') : null } /> diff --git a/src/StoryCircleListView.tsx b/src/components/StoryCircleListView.tsx similarity index 92% rename from src/StoryCircleListView.tsx rename to src/components/StoryCircleListView.tsx index 6e925fa..47aaca4 100644 --- a/src/StoryCircleListView.tsx +++ b/src/components/StoryCircleListView.tsx @@ -3,7 +3,7 @@ import { View, FlatList, StyleSheet } from 'react-native'; import StoryCircleListItem from './StoryCircleListItem'; import type { TextStyle } from 'react-native'; -import type { IUserStory } from './interfaces/IUserStory'; +import type { IUserStory } from '../index'; interface Props { data: IUserStory[]; @@ -29,7 +29,7 @@ const StoryCircleListView = (props: Props) => { return ( `story-item-${index}`} + keyExtractor={(item) => `story-item-${item.id}`} data={data} horizontal style={styles.container} diff --git a/src/StoryListItem.tsx b/src/components/StoryListItem.tsx similarity index 60% rename from src/StoryListItem.tsx rename to src/components/StoryListItem.tsx index c373af2..c182653 100644 --- a/src/StoryListItem.tsx +++ b/src/components/StoryListItem.tsx @@ -15,121 +15,119 @@ import { } from 'react-native'; import GestureRecognizer from 'react-native-swipe-gestures'; -import { usePrevious } from './helpers/StateHelpers'; -import { isNullOrWhitespace } from './helpers/ValidationHelpers'; +import { usePrevious } from '../helpers/StateHelpers'; +import { isNullOrWhitespace } from '../helpers/ValidationHelpers'; -import type { IUserStoryItem } from './interfaces/IUserStory'; +import { ActionStates } from '../index'; +import type { IUserStoryItem, ICustomProfileBanner } from '../index'; const { width, height } = Dimensions.get('window'); -export enum CloseStates { - PREVIOUS = 'previous', - NEXT = 'next', -} - type Props = { index: number; profileName: string; - profileImage: string; + profileImage: any; // @todo duration?: number; - onFinish?: (state: CloseStates) => void; + onFinish?: (state: ActionStates) => void; onClosePress: () => void; - key: number; swipeText?: string; - customSwipeUpComponent?: () => React.ReactNode; - customCloseComponent?: () => React.ReactNode; + customSwipeUpButton?: () => React.ReactNode; + customCloseButton?: () => React.ReactNode; + customProfileBanner?: (props: ICustomProfileBanner) => React.ReactNode; stories: IUserStoryItem[]; + showProfileBanner?: boolean; currentPage: number; }; const StoryListItem = (props: Props) => { - const stories = props.stories; - - const [load, setLoad] = useState(true); + const [loading, setLoading] = useState(true); const [pressed, setPressed] = useState(false); - const [content, setContent] = useState( - stories.map((story) => { - return { - image: story.image, - onPress: story.onPress, - swipeText: story.swipeText, - finish: 0, - }; - }) + const [currStoryIndex, setCurrentStoryIndex] = useState(0); + const [content, setContent] = useState(props.stories); + + const currStory = useMemo( + () => content[currStoryIndex], + [content, currStoryIndex] ); - const [current, setCurrent] = useState(0); + const currPageIndex = useMemo(() => props.currentPage, [props.currentPage]); + + const swipeText = useMemo( + () => content?.[currStoryIndex]?.swipeText || props.swipeText || 'Swipe Up', + [content, currStoryIndex, props.swipeText] + ); const progress = useRef(new Animated.Value(0)).current; - const prevCurrentPage = usePrevious(props.currentPage); + const prevPageIndex = usePrevious(currPageIndex); + const prevStoryIndex = usePrevious(currStoryIndex); + // call every page changes useEffect(() => { - let isPrevious = !!prevCurrentPage && prevCurrentPage > props.currentPage; + const isPrevious = !!prevPageIndex && prevPageIndex > currPageIndex; + if (isPrevious) { - setCurrent(content.length - 1); + setCurrentStoryIndex(content.length - 1); } else { - setCurrent(0); + setCurrentStoryIndex(0); } let data = [...content]; data.map((x, i) => { if (isPrevious) { - x.finish = 1; + x.finished = true; if (i === content.length - 1) { - x.finish = 0; + x.finished = false; } } else { - x.finish = 0; + x.finished = false; } }); + setContent(data); - start(); + startStory(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [props.currentPage]); - - const prevCurrent = usePrevious(current); + }, [currPageIndex]); + // call every story change requests + // ... and decide next or prev useEffect(() => { - if (!isNullOrWhitespace(prevCurrent)) { - const isCurrent = !!prevCurrent && current > prevCurrent; - if (isCurrent && content[current - 1].image === content[current].image) { - start(); - } else if ( - isCurrent && - content[current + 1].image === content[current].image - ) { - start(); + if (!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?.id === currStory.id) { + startStory(); } } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [current]); + }, [currStoryIndex]); - const start = () => { - setLoad(false); - progress.setValue(0); - startAnimation(); - }; - - const startAnimation = () => { + const startProgressAnimation = () => { Animated.timing(progress, { toValue: 1, duration: props.duration, useNativeDriver: false, }).start(({ finished }) => { - if (finished) { - next(); - } + if (finished) next(); }); }; + const startStory = () => { + setLoading(false); + progress.setValue(0); + startProgressAnimation(); + }; + const onSwipeUp = () => { - if (props.onClosePress) { - props.onClosePress(); - } - if (content[current].onPress) { - content[current].onPress(); - } + if (props.onClosePress) props.onClosePress(); + + if (currStory.onPress) currStory.onPress(); }; const onSwipeDown = () => { @@ -138,72 +136,79 @@ const StoryListItem = (props: Props) => { const next = () => { // check if the next content is not empty - setLoad(true); - if (current !== content.length - 1) { + setLoading(true); + if (currStoryIndex !== content.length - 1) { let data = [...content]; - data[current].finish = 1; + data[currStoryIndex].finished = true; setContent(data); - setCurrent(current + 1); + setCurrentStoryIndex(currStoryIndex + 1); progress.setValue(0); } else { // the next content is empty - close(CloseStates.NEXT); + close(ActionStates.NEXT); } }; const previous = () => { // checking if the previous content is not empty - setLoad(true); - if (current - 1 >= 0) { + setLoading(true); + if (currStoryIndex - 1 >= 0) { let data = [...content]; - data[current].finish = 0; + data[currStoryIndex].finished = false; setContent(data); - setCurrent(current - 1); + setCurrentStoryIndex(currStoryIndex - 1); progress.setValue(0); } else { // the previous content is empty - close(CloseStates.PREVIOUS); + close(ActionStates.PREVIOUS); } }; - const close = (state: CloseStates) => { + const close = (state: ActionStates) => { let data = [...content]; - data.map((x) => (x.finish = 0)); + data.map((x) => (x.finished = false)); setContent(data); progress.setValue(0); - if (props.currentPage === props.index) { + if (currPageIndex === props.index) { if (props.onFinish) { props.onFinish(state); } } }; - const swipeText = useMemo( - () => content?.[current]?.swipeText || props.swipeText || 'Swipe Up', - [content, current, props.swipeText] - ); - const renderSwipeButton = () => { - if (props.customSwipeUpComponent) { - return props.customSwipeUpComponent(); + if (props.customSwipeUpButton) { + return props.customSwipeUpButton(); } - return ( - <> - - {swipeText} - - ); + return {swipeText}; }; const renderCloseButton = () => { - if (props.customCloseComponent) { - return props.customCloseComponent(); + if (props.customCloseButton) { + return props.customCloseButton(); } return X; }; + const renderProfileBanner = () => { + if (!props.showProfileBanner) return; + + if (props.customProfileBanner) + return props.customProfileBanner({ + image: props.profileImage, + name: props.profileName, + }); + + return ( + <> + + {props.profileName} + + ); + }; + return ( { > start()} - source={{ uri: content[current].image }} + onLoadEnd={() => startStory()} + source={{ uri: currStory.image }} style={styles.image} /> - {load && ( + {loading && ( @@ -233,7 +238,12 @@ const StoryListItem = (props: Props) => { { })} - - - {props.profileName} - + {renderProfileBanner()} { if (props.onClosePress) { @@ -266,34 +270,30 @@ const StoryListItem = (props: Props) => { onLongPress={() => setPressed(true)} onPressOut={() => { setPressed(false); - startAnimation(); + startProgressAnimation(); }} onPress={() => { - if (!pressed && !load) { - previous(); - } + if (!pressed && !loading) previous(); }} > - + progress.stopAnimation()} onLongPress={() => setPressed(true)} onPressOut={() => { setPressed(false); - startAnimation(); + startProgressAnimation(); }} onPress={() => { - if (!pressed && !load) { - next(); - } + if (!pressed && !loading) next(); }} > - + - {content[current].onPress && ( + {currStory.onPress && ( { return input.toString().replace(/\s/g, '').length < 1; }; + +export const isUrl = (string: string) => { + try { + return Boolean(new URL(string)); + } catch (e) { + return false; + } +}; diff --git a/src/index.tsx b/src/index.tsx index 708d55e..88bdb37 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,3 +1,45 @@ -import Story from './Story'; +import { Story } from './components'; + +export enum ActionStates { + PREVIOUS, + NEXT, +} + +export interface IUserStory { + id: number | string; + avatar: any; // @todo + name: string; + stories: IUserStoryItem[]; + seen?: Boolean; + extra?: { + [key: string]: any; + }; +} + +export interface IUserStoryItem { + id: number | string; + image: string; + onPress?: () => void; + swipeText?: string; + finished?: boolean; +} + +export interface ICustomStoryView { + index: number; + data: IUserStory; + currentPage: number; + changeStory: (state: ActionStates) => void; + close: () => void; +} + +export interface ICustomStoryList { + data: IUserStory[]; + onStoryPress: (item: IUserStory, index: number) => void; +} + +export interface ICustomProfileBanner { + image: any; + name: string; +} export default Story; diff --git a/src/interfaces/IUserStory.ts b/src/interfaces/IUserStory.ts deleted file mode 100644 index 34cb64e..0000000 --- a/src/interfaces/IUserStory.ts +++ /dev/null @@ -1,14 +0,0 @@ -export interface IUserStory { - id: number; - avatar: string; - name: string; - stories: IUserStoryItem[]; - seen?: Boolean; -} - -export interface IUserStoryItem { - id: number; - image: string; - onPress?: any; - swipeText?: string; -}