Changeset View
Changeset View
Standalone View
Standalone View
native/chat/settings/thread-settings-media-gallery.react.js
Show All 23 Lines | |||||
const galleryItemGap = 8; | const galleryItemGap = 8; | ||||
const numColumns = 3; | const numColumns = 3; | ||||
type ThreadSettingsMediaGalleryProps = { | type ThreadSettingsMediaGalleryProps = { | ||||
+threadID: string, | +threadID: string, | ||||
+limit: number, | +limit: number, | ||||
+verticalBounds: ?VerticalBounds, | +verticalBounds: ?VerticalBounds, | ||||
+offset?: number, | |||||
+activeTab?: string, | |||||
}; | }; | ||||
function ThreadSettingsMediaGallery( | function ThreadSettingsMediaGallery( | ||||
props: ThreadSettingsMediaGalleryProps, | props: ThreadSettingsMediaGalleryProps, | ||||
): React.Node { | ): React.Node { | ||||
const styles = useStyles(unboundStyles); | const styles = useStyles(unboundStyles); | ||||
const { width } = useWindowDimensions(); | const { width } = useWindowDimensions(); | ||||
// Explanation of galleryItemWidth: | // Explanation of galleryItemWidth: | ||||
// The FlatList has a horizontal padding of 16px on each side, | // The FlatList has a horizontal padding of 16px on each side, | ||||
// and so the width of the actual FlatList is `width - 32px`. | // and so the width of the actual FlatList is `width - 32px`. | ||||
// With three columns, there will be two gaps in between the items, | // With three columns, there will be two gaps in between the items, | ||||
// so the width of each item (with the gaps) will be | // so the width of each item (with the gaps) will be | ||||
// (width - 32px - (numColumns-1) * galleryItemGap) / numColumns. | // (width - 32px - (numColumns-1) * galleryItemGap) / numColumns. | ||||
// E.g. 16px, media, galleryItemGap, media, galleryItemGap, media, 16px | // E.g. 16px, media, galleryItemGap, media, galleryItemGap, media, 16px | ||||
const galleryItemWidth = | const galleryItemWidth = | ||||
(width - 32 - (numColumns - 1) * galleryItemGap) / numColumns; | (width - 32 - (numColumns - 1) * galleryItemGap) / numColumns; | ||||
const { threadID, limit, verticalBounds, offset, activeTab } = props; | |||||
const { threadID, limit, verticalBounds } = props; | |||||
const [mediaInfos, setMediaInfos] = React.useState([]); | const [mediaInfos, setMediaInfos] = React.useState([]); | ||||
const callFetchThreadMedia = useServerCall(fetchThreadMedia); | const callFetchThreadMedia = useServerCall(fetchThreadMedia); | ||||
React.useEffect(() => { | React.useEffect(() => { | ||||
const fetchData = async () => { | const fetchData = async () => { | ||||
const result = await callFetchThreadMedia({ | const result = await callFetchThreadMedia({ | ||||
threadID, | threadID, | ||||
limit, | limit, | ||||
Show All 19 Lines | return { | ||||
}, | }, | ||||
media: { | media: { | ||||
width: galleryItemWidth, | width: galleryItemWidth, | ||||
...styles.media, | ...styles.media, | ||||
}, | }, | ||||
}; | }; | ||||
}, [galleryItemWidth, styles.media, styles.mediaContainer]); | }, [galleryItemWidth, styles.media, styles.mediaContainer]); | ||||
const filteredMediaInfos = React.useMemo(() => { | |||||
if (activeTab === 'ALL') { | |||||
return mediaInfos; | |||||
} else if (activeTab === 'IMAGES') { | |||||
return mediaInfos.filter(mediaInfo => mediaInfo.type === 'photo'); | |||||
} else if (activeTab === 'VIDEOS') { | |||||
return mediaInfos.filter(mediaInfo => mediaInfo.type === 'video'); | |||||
} | |||||
return mediaInfos; | |||||
}, [activeTab, mediaInfos]); | |||||
const renderItem = React.useCallback( | const renderItem = React.useCallback( | ||||
({ item, index }) => ( | ({ item, index }) => ( | ||||
<MediaGalleryItem | <MediaGalleryItem | ||||
item={item} | item={item} | ||||
index={index} | index={index} | ||||
memoizedStyles={memoizedStyles} | memoizedStyles={memoizedStyles} | ||||
threadID={threadID} | threadID={threadID} | ||||
verticalBounds={verticalBounds} | verticalBounds={verticalBounds} | ||||
/> | /> | ||||
), | ), | ||||
[threadID, verticalBounds, memoizedStyles], | [threadID, verticalBounds, memoizedStyles], | ||||
); | ); | ||||
const onEndReached = React.useCallback(async () => { | |||||
// As the FlatList fetches more media, we set the offset to be the length | |||||
// of mediaInfos. This will ensure that the next set of media is retrieved | |||||
// from the starting point. | |||||
const result = await callFetchThreadMedia({ | |||||
threadID, | |||||
limit, | |||||
offset: mediaInfos.length, | |||||
}); | |||||
setMediaInfos([...mediaInfos, ...result.media]); | |||||
}, [callFetchThreadMedia, mediaInfos, threadID, limit]); | |||||
return ( | return ( | ||||
<View style={styles.flatListContainer}> | <View style={styles.flatListContainer}> | ||||
<FlatList | <FlatList | ||||
data={mediaInfos} | data={filteredMediaInfos} | ||||
numColumns={numColumns} | numColumns={numColumns} | ||||
renderItem={renderItem} | renderItem={renderItem} | ||||
onEndReached={offset !== undefined ? onEndReached : null} | |||||
onEndReachedThreshold={1} | |||||
/> | /> | ||||
</View> | </View> | ||||
); | ); | ||||
} | } | ||||
type MediaGalleryItemProps = { | type MediaGalleryItemProps = { | ||||
+item: Media, | +item: Media, | ||||
+index: number, | +index: number, | ||||
▲ Show 20 Lines • Show All 82 Lines • Show Last 20 Lines |