Skip to content

Commit

Permalink
fix: image preload
Browse files Browse the repository at this point in the history
  • Loading branch information
LukasFridmansky authored and Lipo11 committed Aug 21, 2023
1 parent 0c29f75 commit 41bbdec
Show file tree
Hide file tree
Showing 9 changed files with 24 additions and 165 deletions.
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@ npm install react-native-gesture-handler
npm install @birdwingo/react-native-instagram-stories
```

## Integration with Storage, Preloading and Video
## Integration with Storage and Video

The component offers an option to save and track the progress of seen stories using `saveProgress`. If you use `saveProgress`, please make sure you have `@react-native-async-storage/async-storage` installed.

Additionally, the component preloads images to improve performance when navigating between stories using `preloadImages`. If you use `preloadImages`, please make sure you have `react-native-blob-util` installed.

If you use video in your stories, please make sure you have `react-native-video` installed.

## Usage
Expand Down Expand Up @@ -68,7 +66,6 @@ export default YourComponent;
----------------------------|----------------------------------------------|--------------------------------------------|---------------------
`stories` | [InstagramStoryProps](#instagramstoryprops)[]| **required** | An array of stories.
`saveProgress` | boolean | false | A boolean indicating whether to save and track the progress of seen stories.
`preloadImages` | boolean | false | A boolean indicating whether to preload images.
`avatarBorderColors` | string[] | [DEFAULT_COLORS](#default-gradient-colors) | An array of string colors representing the border colors of story avatars.
`avatarSeenBorderColors` | string[] | [ '#2A2A2C' ] | An array of string colors representing the border colors of seen story avatars.
`avatarSize` | number | 60 | The size of the story avatars.
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
"eslint-config-airbnb-typescript": "^16.1.0",
"husky": "^8.0.3",
"jest": "^29.6.2",
"react-native-blob-util": "^0.19.0",
"react-native-video": "^5.2.1",
"react-test-renderer": "^18.2.0",
"standard-version": "^9.5.0",
Expand Down
65 changes: 10 additions & 55 deletions src/components/Image/index.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
import { Image, View } from 'react-native';
import React, {
FC, memo, useState, useEffect, useRef,
} from 'react';
import React, { FC, memo, useState } from 'react';
import { runOnJS, useAnimatedReaction, useSharedValue } from 'react-native-reanimated';
import { StoryImageProps } from '../../core/dto/componentsDTO';
import Loader from '../Loader';
import { HEIGHT, LOADER_COLORS, WIDTH } from '../../core/constants';
import ImageStyles from './Image.styles';
import { loadImage } from '../../core/helpers/image';
import StoryVideo from './video';

const StoryImage: FC<StoryImageProps> = ( {
stories, active, activeStory, defaultImage, isDefaultVideo, preloadImages, paused,
stories, active, activeStory, defaultImage, isDefaultVideo, paused,
onImageLayout, onLoad,
} ) => {

const [ data, setData ] = useState<{ uri: string, isVideo?: boolean }>( { uri: '' } );
const [ data, setData ] = useState<{ uri: string, isVideo?: boolean }>(
{ uri: defaultImage, isVideo: isDefaultVideo },
);

const loading = useSharedValue( true );
const color = useSharedValue( LOADER_COLORS );

const storyImgUrl = useRef( '' );

const onImageChange = async () => {

if ( !active.value ) {
Expand All @@ -38,58 +35,22 @@ const StoryImage: FC<StoryImageProps> = ( {

}

if ( storyImgUrl.current === story.sourceUrl ) {
if ( data.uri === story.sourceUrl ) {

onLoad();

if ( preloadImages ) {

const nextStory = stories[stories.indexOf( story ) + 1];

if ( nextStory ) {

loadImage( nextStory.sourceUrl );

}

}

return;

}

loading.value = true;

if ( preloadImages ) {

setData( { uri: '', isVideo: false } );

const uri = await loadImage( story.sourceUrl );

setData( { uri, isVideo: story.mediaType === 'video' } );

storyImgUrl.current = story.sourceUrl;

} else {

storyImgUrl.current = story.sourceUrl;
loading.value = true;
setData( { uri: story?.sourceUrl, isVideo: story?.mediaType === 'video' } );

}

};

const setDefaultImage = async () => {
const nextStory = stories[stories.indexOf( story ) + 1];

if ( preloadImages ) {
if ( nextStory ) {

const uri = await loadImage( defaultImage );
setData( { uri, isVideo: isDefaultVideo } );
storyImgUrl.current = defaultImage;

} else {

setData( { uri: defaultImage, isVideo: isDefaultVideo } );
Image.prefetch( nextStory.sourceUrl );

}

Expand All @@ -108,12 +69,6 @@ const StoryImage: FC<StoryImageProps> = ( {

};

useEffect( () => {

setDefaultImage();

}, [] );

return (
<>
<View style={ImageStyles.container}>
Expand Down
18 changes: 11 additions & 7 deletions src/components/InstagramStories/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, {
forwardRef, useImperativeHandle, useState, useEffect, useRef, memo,
} from 'react';
import { useSharedValue } from 'react-native-reanimated';
import { ScrollView } from 'react-native';
import { Image, ScrollView } from 'react-native';
import StoryAvatar from '../Avatar';
import { clearProgressStorage, getProgressStorage, setProgressStorage } from '../../core/helpers/storage';
import { InstagramStoriesProps, InstagramStoriesPublicMethods } from '../../core/dto/instagramStoriesDTO';
Expand All @@ -13,12 +13,10 @@ import {
} from '../../core/constants';
import StoryModal from '../Modal';
import { StoryModalPublicMethods } from '../../core/dto/componentsDTO';
import { preloadStories } from '../../core/helpers/image';

const InstagramStories = forwardRef<InstagramStoriesPublicMethods, InstagramStoriesProps>( ( {
stories,
saveProgress = false,
preloadImages = false,
avatarBorderColors = DEFAULT_COLORS,
avatarSeenBorderColors = SEEN_LOADER_COLORS,
avatarSize = AVATAR_SIZE,
Expand Down Expand Up @@ -69,11 +67,18 @@ const InstagramStories = forwardRef<InstagramStoriesPublicMethods, InstagramStor

seenStories.value = await ( saveProgress ? getProgressStorage() : {} );

if ( preloadImages ) {
const promises = stories.map( ( story ) => {

await preloadStories( data, seenStories.value );
const seenStoryIndex = story.stories.findIndex(
( item ) => item.id === seenStories.value[story.id],
);
const seenStory = story.stories[seenStoryIndex + 1] || story.stories[0];

}
return Image.prefetch( seenStory.sourceUrl );

} );

await Promise.all( promises );

loadedStories.value = true;

Expand Down Expand Up @@ -207,7 +212,6 @@ const InstagramStories = forwardRef<InstagramStoriesPublicMethods, InstagramStor
onLoad={onLoad}
onSeenStoriesChange={onSeenStoriesChange}
backgroundColor={backgroundColor}
preloadImages={preloadImages}
videoDuration={videoAnimationMaxDuration}
{...props}
/>
Expand Down
3 changes: 1 addition & 2 deletions src/components/List/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { HEIGHT } from '../../core/constants';
import StoryContent from '../Content';

const StoryList: FC<StoryListProps> = ( {
id, stories, index, x, activeUser, activeStory, progress, seenStories, preloadImages, paused,
id, stories, index, x, activeUser, activeStory, progress, seenStories, paused,
onLoad, ...props
} ) => {

Expand Down Expand Up @@ -54,7 +54,6 @@ const StoryList: FC<StoryListProps> = ( {
isDefaultVideo={( stories[lastSeenIndex + 1]?.mediaType ?? stories[0].mediaType ) === 'video'}
onImageLayout={onImageLayout}
onLoad={onImageLoad}
preloadImages={preloadImages}
paused={paused}
/>
<Progress
Expand Down
3 changes: 1 addition & 2 deletions src/components/Modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import ModalStyles from './Modal.styles';

const StoryModal = forwardRef<StoryModalPublicMethods, StoryModalProps>( ( {
stories, seenStories, duration, videoDuration, storyAvatarSize, textStyle, containerStyle,
backgroundColor, preloadImages, onLoad, onShow, onHide, onSeenStoriesChange,
backgroundColor, onLoad, onShow, onHide, onSeenStoriesChange,
}, ref ) => {

const [ visible, setVisible ] = useState( false );
Expand Down Expand Up @@ -321,7 +321,6 @@ const StoryModal = forwardRef<StoryModalPublicMethods, StoryModalProps>( ( {
avatarSize={storyAvatarSize}
textStyle={textStyle}
buttonHandled={buttonHandled}
preloadImages={preloadImages}
paused={paused}
key={story.id}
/>
Expand Down
3 changes: 0 additions & 3 deletions src/core/dto/componentsDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export interface StoryModalProps {
textStyle?: TextStyle;
containerStyle?: ViewStyle;
backgroundColor?: string;
preloadImages: boolean;
onLoad: () => void;
onShow?: ( id: string ) => void;
onHide?: ( id: string ) => void;
Expand Down Expand Up @@ -61,7 +60,6 @@ export interface StoryImageProps {
activeStory: SharedValue<string>;
defaultImage: string;
isDefaultVideo: boolean;
preloadImages: boolean;
paused: SharedValue<boolean>;
onImageLayout: ( height: number ) => void;
onLoad: ( duration?: number ) => void;
Expand Down Expand Up @@ -105,7 +103,6 @@ export interface StoryListProps extends InstagramStoryProps, StoryHeaderProps {
activeStory: SharedValue<string>;
progress: SharedValue<number>;
seenStories: SharedValue<ProgressStorageProps>;
preloadImages: boolean;
paused: SharedValue<boolean>;
onLoad: ( duration?: number ) => void;
}
Expand Down
1 change: 0 additions & 1 deletion src/core/dto/instagramStoriesDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export interface InstagramStoryProps {
export interface InstagramStoriesProps {
stories: InstagramStoryProps[];
saveProgress?: boolean;
preloadImages?: boolean;
avatarBorderColors?: string[];
avatarSeenBorderColors?: string[];
avatarSize?: number;
Expand Down
90 changes: 0 additions & 90 deletions src/core/helpers/image.ts

This file was deleted.

0 comments on commit 41bbdec

Please sign in to comment.