diff options
Diffstat (limited to 'src/screens/ProfileList/FeedSection.tsx')
-rw-r--r-- | src/screens/ProfileList/FeedSection.tsx | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/screens/ProfileList/FeedSection.tsx b/src/screens/ProfileList/FeedSection.tsx new file mode 100644 index 000000000..96b1452e2 --- /dev/null +++ b/src/screens/ProfileList/FeedSection.tsx @@ -0,0 +1,111 @@ +import {useCallback, useEffect, useImperativeHandle, useState} from 'react' +import {View} from 'react-native' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {useIsFocused} from '@react-navigation/native' +import {useQueryClient} from '@tanstack/react-query' + +import {isNative} from '#/platform/detection' +import {listenSoftReset} from '#/state/events' +import {type FeedDescriptor} from '#/state/queries/post-feed' +import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed' +import {PostFeed} from '#/view/com/posts/PostFeed' +import {EmptyState} from '#/view/com/util/EmptyState' +import {type ListRef} from '#/view/com/util/List' +import {LoadLatestBtn} from '#/view/com/util/load-latest/LoadLatestBtn' +import {atoms as a} from '#/alf' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import {PersonPlus_Stroke2_Corner0_Rounded as PersonPlusIcon} from '#/components/icons/Person' + +interface SectionRef { + scrollToTop: () => void +} + +interface FeedSectionProps { + ref?: React.Ref<SectionRef> + feed: FeedDescriptor + headerHeight: number + scrollElRef: ListRef + isFocused: boolean + isOwner: boolean + onPressAddUser: () => void +} + +export function FeedSection({ + ref, + feed, + scrollElRef, + headerHeight, + isFocused, + isOwner, + onPressAddUser, +}: FeedSectionProps) { + const queryClient = useQueryClient() + const [hasNew, setHasNew] = useState(false) + const [isScrolledDown, setIsScrolledDown] = useState(false) + const isScreenFocused = useIsFocused() + const {_} = useLingui() + + const onScrollToTop = useCallback(() => { + scrollElRef.current?.scrollToOffset({ + animated: isNative, + offset: -headerHeight, + }) + queryClient.resetQueries({queryKey: FEED_RQKEY(feed)}) + setHasNew(false) + }, [scrollElRef, headerHeight, queryClient, feed, setHasNew]) + useImperativeHandle(ref, () => ({ + scrollToTop: onScrollToTop, + })) + + useEffect(() => { + if (!isScreenFocused) { + return + } + return listenSoftReset(onScrollToTop) + }, [onScrollToTop, isScreenFocused]) + + const renderPostsEmpty = useCallback(() => { + return ( + <View style={[a.gap_xl, a.align_center]}> + <EmptyState icon="hashtag" message={_(msg`This feed is empty.`)} /> + {isOwner && ( + <Button + label={_(msg`Start adding people`)} + onPress={onPressAddUser} + color="primary" + size="small"> + <ButtonIcon icon={PersonPlusIcon} /> + <ButtonText> + <Trans>Start adding people!</Trans> + </ButtonText> + </Button> + )} + </View> + ) + }, [_, onPressAddUser, isOwner]) + + return ( + <View> + <PostFeed + testID="listFeed" + enabled={isFocused} + feed={feed} + pollInterval={60e3} + disablePoll={hasNew} + scrollElRef={scrollElRef} + onHasNew={setHasNew} + onScrolledDownChange={setIsScrolledDown} + renderEmptyState={renderPostsEmpty} + headerOffset={headerHeight} + /> + {(isScrolledDown || hasNew) && ( + <LoadLatestBtn + onPress={onScrollToTop} + label={_(msg`Load new posts`)} + showIndicator={hasNew} + /> + )} + </View> + ) +} |