Skip to content

Commit

Permalink
feat: added flashlist as a scrollable
Browse files Browse the repository at this point in the history
  • Loading branch information
gorhom committed Oct 13, 2024
1 parent c941c83 commit 9bf39ed
Show file tree
Hide file tree
Showing 17 changed files with 2,499 additions and 17 deletions.
14 changes: 10 additions & 4 deletions example/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
"resizeMode": "contain",
"backgroundColor": "#000"
},
"assetBundlePatterns": [
"**/*"
],
"assetBundlePatterns": ["**/*"],
"ios": {
"supportsTablet": true,
"bundleIdentifier": "dev.gorhom.bottomsheet"
Expand All @@ -30,6 +28,14 @@
},
"web": {
"favicon": "./assets/favicon.png"
}
},
"plugins": [
[
"expo-asset",
{
"assets": ["./assets"]
}
]
]
}
}
Binary file added example/assets/comment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/assets/like.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/assets/retweet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/assets/share.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
"@react-navigation/native": "^6.1.9",
"@react-navigation/native-stack": "^6.9.17",
"@react-navigation/stack": "^6.3.20",
"@shopify/flash-list": "1.6.4",
"expo": "~51.0.21",
"expo-asset": "~10.0.10",
"expo-blur": "~13.0.2",
"expo-image": "~1.13.0",
"expo-status-bar": "~1.12.1",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
7 changes: 6 additions & 1 deletion example/src/screens/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ShowcaseExampleScreenSectionType } from '@gorhom/showcase-template';
import type { ShowcaseExampleScreenSectionType } from '@gorhom/showcase-template';
import { Platform } from 'react-native';

const screens: ShowcaseExampleScreenSectionType[] = [];
Expand Down Expand Up @@ -163,6 +163,11 @@ if (Platform.OS !== 'web') {
headerTransparent: true,
},
},
{
name: 'FlashList',
slug: 'Integrations/FlashList',
getScreen: () => require('./integrations/flashlist').default,
},
],
collapsed: true,
};
Expand Down
173 changes: 173 additions & 0 deletions example/src/screens/integrations/flashlist/FlashListExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import BottomSheet, { BottomSheetFlashList } from '@gorhom/bottom-sheet';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import {
ActivityIndicator,
type ListRenderItemInfo,
StyleSheet,
Text,
View,
type ViewabilityConfig,
} from 'react-native';
import { Button } from '../../../components/button';
import TweetContent from './TweetContent';
import { tweets as tweetsData } from './data/tweets';
import type Tweet from './models/Tweet';

const keyExtractor = (item: Tweet) => {
return item.id;
};

const snapPoints = ['25%', '50%', '90%'];

const FlashListExample = () => {
//#region state
const [tweets, setTweets] = useState(tweetsData);
//#endregion

//#region refs
const bottomSheetRef = useRef<BottomSheet>(null);
const remainingTweets = useRef([...tweetsData].splice(10, tweetsData.length));
const viewabilityConfig = useRef<ViewabilityConfig>({
waitForInteraction: true,
itemVisiblePercentThreshold: 50,
minimumViewTime: 1000,
}).current;
//#endregion

const handleOnEndReached = useCallback(() => {
setTimeout(() => {
setTweets([...tweets, ...remainingTweets.current.splice(0, 10)]);
}, 1000);
}, [tweets]);
const handleSnapPress = useCallback((index: number) => {
bottomSheetRef.current?.snapToIndex(index);
}, []);
const handleExpandPress = useCallback(() => {
bottomSheetRef.current?.expand();
}, []);
const handleCollapsePress = useCallback(() => {
bottomSheetRef.current?.collapse();
}, []);
const handleClosePress = useCallback(() => {
bottomSheetRef.current?.close();
}, []);

//#region render
const renderItem = useCallback(
({ item }: ListRenderItemInfo<Tweet>) => <TweetContent tweet={item} />,
[]
);
const renderFooter = useMemo(
() => <Footer isLoading={tweets.length !== tweetsData.length} />,
[tweets]
);
return (
<View style={styles.container}>
<Button label="Snap To 90%" onPress={() => handleSnapPress(2)} />
<Button label="Snap To 50%" onPress={() => handleSnapPress(1)} />
<Button label="Snap To 25%" onPress={() => handleSnapPress(0)} />
<Button label="Expand" onPress={handleExpandPress} />
<Button label="Collapse" onPress={handleCollapsePress} />
<Button label="Close" onPress={handleClosePress} />
<BottomSheet
ref={bottomSheetRef}
snapPoints={snapPoints}
enableDynamicSizing={false}
>
<BottomSheetFlashList
keyExtractor={keyExtractor}
renderItem={renderItem}
onEndReached={handleOnEndReached}
ListFooterComponent={renderFooter}
ListEmptyComponent={Empty}
estimatedItemSize={150}
ItemSeparatorComponent={Divider}
data={tweets}
viewabilityConfig={viewabilityConfig}
/>
</BottomSheet>
</View>
);
//#endregion
};

const Divider = () => {
return <View style={styles.divider} />;
};

const Footer = ({ isLoading }: { isLoading: boolean }) => {
return (
<View style={styles.footer}>
{isLoading ? (
<ActivityIndicator />
) : (
<Text style={styles.footerTitle}>No more tweets</Text>
)}
</View>
);
};

const Empty = () => {
const title = 'Welcome to your timeline';
const subTitle =
"It's empty now but it won't be for long. Start following peopled you'll see Tweets show up here";
return (
<View style={styles.emptyComponent} testID="EmptyComponent">
<Text style={styles.emptyComponentTitle}>{title}</Text>
<Text style={styles.emptyComponentSubtitle}>{subTitle}</Text>
</View>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 24,
},

divider: {
width: '100%',
height: StyleSheet.hairlineWidth,
backgroundColor: '#DDD',
},
header: {
height: 40,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#1DA1F2',
},
footer: {
height: 40,
justifyContent: 'center',
alignItems: 'center',
},
headerTitle: {
color: '#FFFFFF',
padding: 8,
borderRadius: 12,
fontSize: 12,
},
footerTitle: {
padding: 8,
borderRadius: 12,
fontSize: 12,
},
emptyComponentTitle: {
color: 'black',
fontSize: 20,
fontWeight: 'bold',
},
emptyComponentSubtitle: {
color: '#808080',
padding: 8,
fontSize: 14,
textAlign: 'center',
},
emptyComponent: {
justifyContent: 'center',
alignItems: 'center',
flex: 1,
},
});

export default FlashListExample;
Loading

0 comments on commit 9bf39ed

Please sign in to comment.