Skip to content

Commit

Permalink
Merge pull request #102 from SimformSolutionsPvtLtd/develop
Browse files Browse the repository at this point in the history
Release v3.2.0
  • Loading branch information
mukesh-simform authored Jun 4, 2024
2 parents 63223be + e0b9c26 commit 7bdbf8c
Show file tree
Hide file tree
Showing 17 changed files with 214 additions and 15 deletions.
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ const userStories = [
duration: 5, //default duration
storyId: 1,
isSeen: false,
showOverlay: true, // to show overlay component
link: 'https:google.com', // to handle navigation in overlay component
},
{
id: 1,
Expand Down Expand Up @@ -437,6 +439,38 @@ Pass any custom view in story view. It will be rendered on top of story view as
/>
```
---
### Custom Overlay View
<table>
<tr>
<td><a href="https://github.com/SimformSolutionsPvtLtd/react-native-story-view"><img width="140" alt="SimformSolutions" src="./assets/overlay.png"></a></td>
</tr>
</table>
Pass any custom overlay view in the story view, which will be visible when the story contains showOverlay as true. It will be rendered on top of the image/video. In renderOverlayView, pass a callback function that takes the currently visible item and returns any custom component. In overlayViewPosition, assign one of the following positions: top, middle, or bottom.
```js
<MultiStory
overlayViewPostion={'top'}
renderOverlayView={(item: StoryType) => (
<TouchableOpacity
style={{
padding: 10,
backgroundColor: 'gray',
borderRadius: 10
}}
onPress={() => {
if (item.link) {
Linking.openURL(item.link);
}
}}>
<Text style={{ color: 'white' }}>View More...</Text>
</TouchableOpacity>
)}
/>
```
---
## Story Data
Expand All @@ -456,6 +490,8 @@ Pass any custom view in story view. It will be rendered on top of story view as
isReadMore: boolean
storyId: number,
isSeen?: boolean,
showOverlay?: boolean,
link?: string,
}
]
}]
Expand Down Expand Up @@ -486,6 +522,8 @@ Pass any custom view in story view. It will be rendered on top of story view as
> | onChangePosition | null | (progressIndex, storyIndex) => {} | Callback when progress index changes |
> | transitionMode | TransitionMode.Cube | TransitionMode: {Default, Cube, Scale} | To customize user story transition, (TransitionMode.default : no transition, Transition.scale : zoomIn/zoomOut transition, Transition.Cube: 3D cube transition) cube |
> | onComplete | null | (viewedStories?: Array<boolean[]>) => void | Callback when stories closed or completes. `viewedStories` contains multi array of boolean whether story is seen or not |
> | renderOverlayView | null | (item?: StoryType) => JSX.Element | The callback for the overlay view is triggered only when the story item has showOverlay property set to true |
> | overlayViewPostion | bottom | string | Position of overlay view (top, middle, bottom) |
> | `props` | - | FlatListProps | Pass any `FlatList` props to customize horizontal user list |
---
Expand Down Expand Up @@ -521,6 +559,8 @@ Pass any custom view in story view. It will be rendered on top of story view as
> | onChangePosition | null | (progressIndex, userIndex) => {} | Callback when progress index changes |
> | transitionMode | TransitionMode.Cube | TransitionMode: {Default, Cube, Scale} | To customize user story transition, (TransitionMode.default : no transition, Transition.scale : zoomIn/zoomOut transition, Transition.Cube: 3D cube transition) cube |
> | onComplete | null | () => {} | Callback when stories closed or complete |
> | renderOverlayView | null | (item?: StoryType) => JSX.Element | The callback for the overlay view is triggered only when the story item has showOverlay property set to true |
> | overlayViewPostion | bottom | string | Position of overlay view (top, middle, bottom) |
> | `props` | - | StoryContainerProps | Pass any `StoryContainerProps` props to customize story |
> | pointers | { pageX: 0,<br /> pageY: 0 } | PointerType | Pointers will be used internally for modal opening and closing positions, You can pass profile avatar's position offsets here. |
Expand Down
Binary file added assets/overlay.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions example/src/components/Overlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { Linking, StyleSheet, Text, TouchableOpacity } from 'react-native';
import { Colors } from '../theme';
import { OverlayType } from './types';

const Overlay = ({ item }: OverlayType) => (
<TouchableOpacity
style={styles.overlayView}
onPress={() => {
if (item.link) {
Linking.openURL(item.link);
}
}}>
<Text style={styles.overlayText}>View More...</Text>
</TouchableOpacity>
);

export default Overlay;

const styles = StyleSheet.create({
overlayView: {
padding: 10,
backgroundColor: Colors.darkGrey,
borderRadius: 10
},
overlayText: {
color: Colors.white
}
});
1 change: 1 addition & 0 deletions example/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as Header } from './Header';
export { default as Footer } from './Footer';
export { default as Overlay } from './Overlay';
11 changes: 10 additions & 1 deletion example/src/components/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { RefObject } from 'react';
import type { MultiStoryRef, UserProps, CallbackProps } from '../../../src';
import type {
MultiStoryRef,
UserProps,
CallbackProps,
StoryType
} from '../../../src';

export interface HeaderProps extends Partial<CallbackProps>, UserProps {
multiStoryRef?: RefObject<MultiStoryRef> | null;
}

export interface FooterProps extends Partial<CallbackProps> {}

export interface OverlayType {
item: StoryType;
}
4 changes: 3 additions & 1 deletion example/src/constants/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const stories = [
duration: 3,
isReadMore: true,
storyId: 1,
isSeen: false
isSeen: false,
showOverlay: true,
link: 'https:google.com'
},
{
id: 2,
Expand Down
17 changes: 13 additions & 4 deletions example/src/modules/MultiStory/MultiStoryScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import React, { useRef, useState } from 'react';
import { ImageBackground, View, Text } from 'react-native';
import React, { useEffect, useRef, useState } from 'react';
import {
ImageBackground,
View,
Text,
TouchableOpacity,
Linking
} from 'react-native';
import {
type MultiStoryRef,
Indicator,
MultiStory,
TransitionMode
TransitionMode,
StoryType
} from 'react-native-story-view';
import { stories, Strings } from '../../constants';
import { Header, Footer } from '../../components';
import { Header, Footer, Overlay } from '../../components';
import { Colors } from '../../theme';
import Images from '../../assets';
import styles from './styles';
Expand Down Expand Up @@ -51,6 +58,8 @@ const MultiStoryScreen = () => {
borderColor: Colors.lightGrey
}
}}
overlayViewPostion={'top'}
renderOverlayView={(item: StoryType) => <Overlay item={item} />}
storyContainerProps={{
renderHeaderComponent: ({ userStories }) => (
<Header {...{ userStories, multiStoryRef }} />
Expand Down
13 changes: 11 additions & 2 deletions example/src/modules/Story/StoryScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import React, { useRef, useState } from 'react';
import { Modal, SafeAreaView, View } from 'react-native';
import {
Linking,
Modal,
SafeAreaView,
Text,
TouchableOpacity,
View
} from 'react-native';
import {
StoryAvatar,
StoryContainer,
StoryRef,
StoryType
} from 'react-native-story-view';
import { Footer, Header } from '../../components';
import { Footer, Header, Overlay } from '../../components';
import { stories } from '../../constants';
import styles from './styles';

Expand Down Expand Up @@ -74,6 +81,8 @@ const StoryScreen = () => {
)}
//Callback when status view completes
onComplete={closeStory}
overlayViewPostion={'top'}
renderOverlayView={(item: StoryType) => <Overlay item={item} />}
/>
</SafeAreaView>
</Modal>
Expand Down
3 changes: 2 additions & 1 deletion example/src/theme/Colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ const colors = {
white: '#FFFFFF',
black: '#000000',
grey: '#101010',
lightGrey: '#FFFFFF7F'
lightGrey: '#FFFFFF7F',
darkGrey: '#808080'
};

export default colors;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-story-view",
"version": "3.1.0",
"version": "3.2.0",
"description": "React Native component to provide status/stories feature.",
"main": "lib/index",
"types": "lib/index.d.ts",
Expand Down
2 changes: 2 additions & 0 deletions src/components/MultiStory/MultiStory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ const MultiStory = forwardRef<MultiStoryRef, MultiStoryProps>(
{...props?.storyContainerProps}
stories={stories}
userStoryIndex={pressedIndex}
renderOverlayView={props.renderOverlayView}
overlayViewPostion={props.overlayViewPostion}
/>
)}
</View>
Expand Down
22 changes: 20 additions & 2 deletions src/components/MultiStory/types.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,36 @@
import type { FlatListProps } from 'react-native';
import type { TransitionMode } from '../MultiStoryContainer/types';
import type { StoryAvatarStyleProps } from '../StoryAvatar/types';
import type { StoriesType, StoryContainerProps } from '../StoryView/types';
import type {
StoriesType,
StoryContainerProps,
StoryType,
} from '../StoryView/types';

export interface MultiStoryProps extends Partial<FlatListProps<any>> {
export interface MultiStoryBaseProps extends Partial<FlatListProps<any>> {
stories: StoriesType[];
onComplete?: (viewedStories?: Array<boolean[]>) => void;
onChangePosition?: (progressIndex: number, storyIndex: number) => void;
avatarProps?: StoryAvatarStyleProps;
viewedStories?: Array<boolean[]>;
storyContainerProps?: Omit<StoryContainerProps, 'stories'>;
transitionMode?: TransitionMode;
renderOverlayView?: (item: StoryType) => JSX.Element;
overlayViewPostion?: 'top' | 'bottom' | 'middle';
}

export interface OverlayViewMultiStoryProps extends MultiStoryBaseProps {
renderOverlayView: (item: StoryType) => JSX.Element;
overlayViewPostion: 'top' | 'bottom' | 'middle';
}

export interface MultiStoryMainProps extends MultiStoryBaseProps {
renderOverlayView?: never;
overlayViewPostion?: never;
}

export type MultiStoryProps = MultiStoryMainProps | OverlayViewMultiStoryProps;

export interface MultiStoryRef {
close: () => void;
}
6 changes: 5 additions & 1 deletion src/components/MultiStoryContainer/MultiStoryContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Animated from 'react-native-reanimated';
import { Metrics } from '../../theme';
import { Footer } from '../Footer';
import { Indicator, ProfileHeader, StoryContainer } from '../StoryView';
import type { StoriesType } from '../StoryView/types';
import { OverlayPositions, type StoriesType } from '../StoryView/types';
import { useMultiStoryContainer, useMultiStoryItems } from './hooks';
import styles from './styles';
import type {
Expand Down Expand Up @@ -39,6 +39,8 @@ const MultiStoryListItem = forwardRef<ListItemRef, MultiStoryListItemProps>(
flatListRef,
storyLength,
isInitialStory,
renderOverlayView = () => <></>,
overlayViewPostion = OverlayPositions.Bottom,
...props
}: MultiStoryListItemProps,
ref
Expand Down Expand Up @@ -79,6 +81,8 @@ const MultiStoryListItem = forwardRef<ListItemRef, MultiStoryListItemProps>(
stories={item.stories}
progressIndex={storyInitialIndex < 0 ? 0 : storyInitialIndex}
maxVideoDuration={15}
renderOverlayView={renderOverlayView}
overlayViewPostion={overlayViewPostion}
renderHeaderComponent={() => (
<ProfileHeader
userImage={{ uri: item.profile ?? '' }}
Expand Down
8 changes: 7 additions & 1 deletion src/components/MultiStoryContainer/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import type { ViewToken } from 'react-native';
import type { SharedValue } from 'react-native-reanimated';
import type { GestureHandlerEvent } from 'react-native-reanimated/lib/typescript/reanimated2/hook';
import type { StoriesType, StoryContainerProps } from '../StoryView/types';
import type {
StoriesType,
StoryContainerProps,
StoryType,
} from '../StoryView/types';

export enum TransitionMode {
Default,
Expand Down Expand Up @@ -41,6 +45,8 @@ export interface MultiStoryListItemProps
storyLength: number;
gestureHandler?: (e: GestureHandlerEvent<any>) => void;
isInitialStory?: boolean;
renderOverlayView?: (item: StoryType) => JSX.Element;
overlayViewPostion?: 'top' | 'bottom' | 'middle';
}

export interface ViewConfig {
Expand Down
27 changes: 27 additions & 0 deletions src/components/StoryView/StoryContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ import React, {
forwardRef,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
} from 'react';
import {
KeyboardAvoidingView,
SafeAreaView,
StyleProp,
TouchableOpacity,
View,
ViewStyle,
} from 'react-native';
import Animated from 'react-native-reanimated';
import { Metrics } from '../../theme';
Expand All @@ -19,6 +22,7 @@ import { useStoryContainer } from './hooks';
import styles from './styles';
import {
ClickPosition,
OverlayPositions,
StoryContainerProps,
StoryMode,
StoryRef,
Expand All @@ -37,6 +41,8 @@ const StoryContainer = forwardRef<StoryRef, StoryContainerProps>(
footerViewProps,
progressViewProps,
storyContainerViewProps,
renderOverlayView,
overlayViewPostion = OverlayPositions.Bottom,
...props
}: StoryContainerProps,
ref
Expand Down Expand Up @@ -109,6 +115,20 @@ const StoryContainer = forwardRef<StoryRef, StoryContainerProps>(
: 0
: 0;

const overlayViewStyles = useMemo(() => {
let style: StyleProp<ViewStyle> = [styles.overlayViewStyle];

if (overlayViewPostion === OverlayPositions.Middle) {
style.push(styles.overlayMiddleViewStyle);
} else if (overlayViewPostion === OverlayPositions.Top) {
style.push(styles.overlayTopViewStyle);
} else if (overlayViewPostion === OverlayPositions.Bottom) {
style.push(styles.overlayBottomViewStyle);
}

return style;
}, [overlayViewPostion]);

const storyViewContent = () => {
return (
<View style={styles.rootViewStyle}>
Expand All @@ -131,6 +151,13 @@ const StoryContainer = forwardRef<StoryRef, StoryContainerProps>(
}
onLongPress={onStoryPressHold}
onPressOut={onStoryPressRelease}>
{props.stories?.[progressIndex]?.showOverlay && (
<View style={overlayViewStyles}>
{renderOverlayView &&
renderOverlayView(props.stories?.[progressIndex])}
</View>
)}

<StoryView
viewRef={viewRef}
duration={duration}
Expand Down
Loading

0 comments on commit 7bdbf8c

Please sign in to comment.