Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Story Button #66

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
12 changes: 12 additions & 0 deletions src/Story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export const Story = ({
avatarImageStyle,
avatarWrapperStyle,
avatarFlatListProps,
onAddNewStory,
scrollViewStyle,
renderSwipeUpModal,
renderDeleteButton,
}: StoryProps) => {
const [dataState, setDataState] = useState<IUserStory[]>(data);
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
Expand All @@ -48,6 +52,10 @@ export const Story = ({

// Component Functions
const _handleStoryItemPress = (item: IUserStory, index?: number) => {
if(index === 0 && onAddNewStory){
onAddNewStory();
return;
}
const newData = dataState.slice(index);
if (onStart) {
onStart(item);
Expand Down Expand Up @@ -112,6 +120,7 @@ export const Story = ({
duration={duration * 1000}
key={i}
userId={x.user_id}
isMyStory={x.isMyStory}
profileName={x.user_name}
profileImage={x.user_image}
stories={x.stories}
Expand All @@ -127,6 +136,7 @@ export const Story = ({
onClose(x);
}
}}
renderDeleteButton={renderDeleteButton}
index={i}
onStorySeen={onStorySeen}
unloadedAnimationBarStyle={unloadedAnimationBarStyle}
Expand All @@ -136,6 +146,7 @@ export const Story = ({
storyImageStyle={storyImageStyle}
storyAvatarImageStyle={storyAvatarImageStyle}
storyContainerStyle={storyContainerStyle}
renderSwipeUpModal={renderSwipeUpModal}
/>
);
});
Expand Down Expand Up @@ -175,6 +186,7 @@ export const Story = ({
<View style={style}>
<StoryCircleListView
handleStoryItemPress={_handleStoryItemPress}
style={scrollViewStyle}
data={dataState}
avatarSize={avatarSize}
unPressedBorderColor={unPressedBorderColor}
Expand Down
6 changes: 3 additions & 3 deletions src/StoryCircleListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ const StoryCircleListItem = ({
{
height: avatarWrapperSize,
width: avatarWrapperSize,
borderWidth: item?.user_id.toString() !== 'add_story' && !item?.isMyStory ? 2 : 0,
},
avatarWrapperStyle,
!isPressed
!item?.seen
? {
borderColor: unPressedBorderColor ?? 'red',
}
Expand All @@ -75,7 +76,7 @@ const StoryCircleListItem = ({
avatarImageStyle,
]}
source={{ uri: item.user_image }}
defaultSource={Platform.OS === 'ios' ? DEFAULT_AVATAR : null}
defaultSource={item?.user_id.toString() !== 'add_story' ? DEFAULT_AVATAR : ''}
/>
</TouchableOpacity>
{showText && (
Expand Down Expand Up @@ -108,7 +109,6 @@ const styles = StyleSheet.create({
marginRight: 10,
},
avatarWrapper: {
borderWidth: 2,
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
Expand Down
3 changes: 2 additions & 1 deletion src/StoryCircleListView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ const StoryCircleListView = ({
avatarImageStyle,
avatarWrapperStyle,
avatarFlatListProps,
style,
}: StoryCircleListViewProps) => {
return (
<FlatList
keyExtractor={(_item, index) => index.toString()}
data={data}
horizontal
style={styles.paddingLeft}
style={style}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
ListFooterComponent={<View style={styles.footer} />}
Expand Down
110 changes: 60 additions & 50 deletions src/StoryListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ export const StoryListItem = ({
storyImageStyle,
storyAvatarImageStyle,
storyContainerStyle,
renderSwipeUpModal,
isMyStory,
renderDeleteButton,
...props
}: StoryListItemProps) => {
const [load, setLoad] = useState<boolean>(true);
Expand All @@ -55,6 +58,8 @@ export const StoryListItem = ({
finish: 0,
})),
);
const [showViewModal, setShowViewsModal] = useState<boolean>(false);
const [showDeleteModal, setShowDeleteModal] = useState<boolean>(false);

const [current, setCurrent] = useState(0);

Expand Down Expand Up @@ -82,7 +87,7 @@ export const StoryListItem = ({
}
});
setContent(data);
start();
if(!load) start();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentPage]);

Expand All @@ -95,12 +100,12 @@ export const StoryListItem = ({
current > prevCurrent &&
content[current - 1].story_image == content[current].story_image
) {
start();
if(!load) start();
} else if (
current < prevCurrent &&
content[current + 1].story_image == content[current].story_image
) {
start();
if(!load) start();
}
}
}
Expand All @@ -126,12 +131,27 @@ export const StoryListItem = ({
}

function onSwipeUp(_props?: any) {
if (onClosePress) {
onClosePress();
}
if (content[current].onPress) {
content[current].onPress?.();
}
progress.stopAnimation();
setPressed(true)
setShowViewsModal(true);
}

function onDeleteOpen(_props?: any) {
progress.stopAnimation();
setPressed(true)
setShowDeleteModal(true);
}

function onDeleteClose() {
if(!load) startAnimation();
setPressed(false)
setShowDeleteModal(false);
}

function onViewModalClose() {
if(!load) startAnimation();
setPressed(false)
setShowViewsModal(false);
}

function onSwipeDown(_props?: any) {
Expand All @@ -144,7 +164,6 @@ export const StoryListItem = ({
};

function next() {
// check if the next content is not empty
setLoad(true);
if (current !== content.length - 1) {
let data = [...content];
Expand Down Expand Up @@ -203,22 +222,23 @@ export const StoryListItem = ({
<GestureRecognizer
key={key}
onSwipeUp={onSwipeUp}
onSwipeDown={onSwipeDown}
onSwipeDown={showViewModal? onViewModalClose: onSwipeDown}
config={config}
style={[styles.container, storyContainerStyle]}
>
<SafeAreaView>
<View style={styles.backgroundContainer}>
<Image
onLoadEnd={() => start()}
source={{ uri: content[current].story_image }}
style={[styles.image, storyImageStyle]}
/>
{load && (
<View style={styles.spinnerContainer}>
<ActivityIndicator size="large" color={'white'} />
</View>
)}
<Image
onLoadStart={() => progress.stopAnimation()}
onLoadEnd={() => {if(!showDeleteModal && !showViewModal) start()}}
source={{ uri: content[current].story_image }}
style={[styles.image, storyImageStyle]}
/>
</View>
</SafeAreaView>
<View style={styles.flexCol}>
Expand Down Expand Up @@ -260,24 +280,9 @@ export const StoryListItem = ({
<Text style={styles.avatarText}>{profileName}</Text>
)}
</View>
<View style={styles.closeIconContainer}>
{typeof renderCloseComponent === 'function' ? (
renderCloseComponent({
onPress: onClosePress,
item: content[current],
})
) : (
<TouchableOpacity
onPress={() => {
if (onClosePress) {
onClosePress();
}
}}
>
<Text style={styles.whiteText}>X</Text>
</TouchableOpacity>
)}
</View>
{
renderDeleteButton && isMyStory && renderDeleteButton(content[current]?.story_id, showDeleteModal, onDeleteOpen, onDeleteClose)
}
</View>
<View style={styles.pressContainer}>
<TouchableWithoutFeedback
Expand Down Expand Up @@ -312,21 +317,13 @@ export const StoryListItem = ({
</TouchableWithoutFeedback>
</View>
</View>
{typeof renderSwipeUpComponent === 'function' ? (
renderSwipeUpComponent({
onPress: onSwipeUp,
item: content[current],
})
) : (
<TouchableOpacity
activeOpacity={1}
onPress={onSwipeUp}
style={styles.swipeUpBtn}
>
<Text style={styles.swipeText}></Text>
<Text style={styles.swipeText}>{swipeText}</Text>
</TouchableOpacity>
)}
{
content[current]?.caption !== "" &&
<View style={styles.textContainer}>
<Text style={styles.text}>{content[current]?.caption}</Text>
</View>
}
{showViewModal && isMyStory && renderSwipeUpModal(showViewModal, onViewModalClose, content[current]?.story_id)}
</GestureRecognizer>
);
};
Expand Down Expand Up @@ -366,7 +363,7 @@ const styles = StyleSheet.create({
right: 0,
},
spinnerContainer: {
zIndex: -100,
zIndex: 10,
position: 'absolute',
justifyContent: 'center',
backgroundColor: 'black',
Expand Down Expand Up @@ -425,5 +422,18 @@ const styles = StyleSheet.create({
swipeText: {
color: 'white',
marginTop: 5,
},textContainer: {
width: '100%',
padding: 10,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
borderRadius: 20,
position: 'absolute',
bottom: 0,
paddingBottom: 50,
},
text: {
color: '#fff', // White text
fontSize: 16, // Font size
textAlign:'center'
},
});
9 changes: 9 additions & 0 deletions src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface IUserStory<T = Record<string, any>> {
stories: IUserStoryItem<T>[];
/** INTERNAL USE ONLY */
seen?: boolean;
isMyStory?: boolean;
}

export interface IUserStoryItem<T = Record<string, any>> {
Expand Down Expand Up @@ -115,11 +116,14 @@ export interface StoryListItemProps {
duration: number;
/** Text of the swipe up button */
swipeText?: string;
renderSwipeUpModal?: any,
isMyStory?: boolean,
/**
* Callback which returns a custom React Element to use as the
* swipeUpComponent. IUserStoryItem is passed as an arg.
*/
renderSwipeUpComponent?: RenderCustomButton;
renderDeleteButton?: any;
/**
* Callback which returns a custom React Element to use as the
* closeComponent. IUserStoryItem is passed as an arg.
Expand Down Expand Up @@ -177,6 +181,7 @@ export interface StoryProps {
onClose?: (props?: IUserStory) => any;
/** Called when story item is loaded */
onStart?: (props?: IUserStory) => any;
onAddNewStory?: () => any;
/**
* Function which will get called every time a story is seen. Will be called
* every time the user swipes backwards and forwards to that screen.
Expand All @@ -189,11 +194,14 @@ export interface StoryProps {
* swipeUpComponent. IUserStoryItem is passed as an arg.
*/
renderSwipeUpComponent?: RenderCustomButton;
renderDeleteButton?: any;
/**
* Callback which returns a custom React Element to use as the
* closeComponent. IUserStoryItem is passed as an arg.
*/
renderCloseComponent?: RenderCustomButton;

renderSwipeUpModal?: any;
/**
* Callback which returns a custom React Element to use as the textComponent
* next to the small avatar on the story item page. IUserStoryItem and
Expand Down Expand Up @@ -231,4 +239,5 @@ export interface StoryProps {
storyAvatarImageStyle?: ImageStyle;
/** Custom styles for the main story item container */
storyContainerStyle?: ViewStyle;
scrollViewStyle?: ViewStyle;
}