diff options
Diffstat (limited to 'src/view/screens')
-rw-r--r-- | src/view/screens/Feeds.tsx | 4 | ||||
-rw-r--r-- | src/view/screens/Notifications.tsx | 25 | ||||
-rw-r--r-- | src/view/screens/Profile.tsx | 82 | ||||
-rw-r--r-- | src/view/screens/ProfileFeed.tsx | 46 | ||||
-rw-r--r-- | src/view/screens/ProfileList.tsx | 63 | ||||
-rw-r--r-- | src/view/screens/Search/Search.tsx | 9 |
6 files changed, 70 insertions, 159 deletions
diff --git a/src/view/screens/Feeds.tsx b/src/view/screens/Feeds.tsx index f319fbc39..d2d0aafb8 100644 --- a/src/view/screens/Feeds.tsx +++ b/src/view/screens/Feeds.tsx @@ -19,7 +19,7 @@ import { import {ErrorMessage} from 'view/com/util/error/ErrorMessage' import debounce from 'lodash.debounce' import {Text} from 'view/com/util/text/Text' -import {FlatList} from 'view/com/util/Views' +import {List} from 'view/com/util/List' import {useFocusEffect} from '@react-navigation/native' import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard' import {Trans, msg} from '@lingui/macro' @@ -481,7 +481,7 @@ export function FeedsScreen(_props: Props) { {preferences ? <View /> : <ActivityIndicator />} - <FlatList + <List style={[!isTabletOrDesktop && s.flex1, styles.list]} data={items} keyExtractor={item => item.key} diff --git a/src/view/screens/Notifications.tsx b/src/view/screens/Notifications.tsx index fceaa60c2..e28a67e37 100644 --- a/src/view/screens/Notifications.tsx +++ b/src/view/screens/Notifications.tsx @@ -1,5 +1,5 @@ import React from 'react' -import {FlatList, View} from 'react-native' +import {View} from 'react-native' import {useFocusEffect} from '@react-navigation/native' import {useQueryClient} from '@tanstack/react-query' import { @@ -9,8 +9,9 @@ import { import {ViewHeader} from '../com/util/ViewHeader' import {Feed} from '../com/notifications/Feed' import {TextLink} from 'view/com/util/Link' +import {ListMethods} from 'view/com/util/List' import {LoadLatestBtn} from 'view/com/util/load-latest/LoadLatestBtn' -import {useOnMainScroll} from 'lib/hooks/useOnMainScroll' +import {MainScrollProvider} from '../com/util/MainScrollProvider' import {usePalette} from 'lib/hooks/usePalette' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {s, colors} from 'lib/styles' @@ -35,8 +36,8 @@ type Props = NativeStackScreenProps< export function NotificationsScreen({}: Props) { const {_} = useLingui() const setMinimalShellMode = useSetMinimalShellMode() - const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll() - const scrollElRef = React.useRef<FlatList>(null) + const [isScrolledDown, setIsScrolledDown] = React.useState(false) + const scrollElRef = React.useRef<ListMethods>(null) const checkLatestRef = React.useRef<() => void | null>() const {screen} = useAnalytics() const pal = usePalette('default') @@ -50,8 +51,8 @@ export function NotificationsScreen({}: Props) { // = const scrollToTop = React.useCallback(() => { scrollElRef.current?.scrollToOffset({animated: isNative, offset: 0}) - resetMainScroll() - }, [scrollElRef, resetMainScroll]) + setMinimalShellMode(false) + }, [scrollElRef, setMinimalShellMode]) const onPressLoadLatest = React.useCallback(() => { scrollToTop() @@ -130,11 +131,13 @@ export function NotificationsScreen({}: Props) { return ( <View testID="notificationsScreen" style={s.hContentRegion}> <ViewHeader title={_(msg`Notifications`)} canGoBack={false} /> - <Feed - onScroll={onMainScroll} - scrollElRef={scrollElRef} - ListHeaderComponent={ListHeaderComponent} - /> + <MainScrollProvider> + <Feed + onScrolledDownChange={setIsScrolledDown} + scrollElRef={scrollElRef} + ListHeaderComponent={ListHeaderComponent} + /> + </MainScrollProvider> {(isScrolledDown || hasNew) && ( <LoadLatestBtn onPress={onPressLoadLatest} diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx index b7dac8c6d..3f2dd773e 100644 --- a/src/view/screens/Profile.tsx +++ b/src/view/screens/Profile.tsx @@ -5,7 +5,8 @@ import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' -import {CenteredView, FlatList} from '../com/util/Views' +import {CenteredView} from '../com/util/Views' +import {ListRef} from '../com/util/List' import {ScreenHider} from 'view/com/util/moderation/ScreenHider' import {Feed} from 'view/com/posts/Feed' import {ProfileLists} from '../com/lists/ProfileLists' @@ -20,7 +21,6 @@ import {useAnalytics} from 'lib/analytics/analytics' import {ComposeIcon2} from 'lib/icons' import {useSetTitle} from 'lib/hooks/useSetTitle' import {combinedDisplayName} from 'lib/strings/display-names' -import {OnScrollHandler} from '#/lib/hooks/useOnMainScroll' import {FeedDescriptor} from '#/state/queries/post-feed' import {useResolveDidQuery} from '#/state/queries/resolve-uri' import {useProfileQuery} from '#/state/queries/profile' @@ -277,103 +277,67 @@ function ProfileScreenLoaded({ onPageSelected={onPageSelected} onCurrentPageSelected={onCurrentPageSelected} renderHeader={renderHeader}> - {({onScroll, headerHeight, isFocused, isScrolledDown, scrollElRef}) => ( + {({headerHeight, isFocused, scrollElRef}) => ( <FeedSection ref={postsSectionRef} feed={`author|${profile.did}|posts_and_author_threads`} - onScroll={onScroll} headerHeight={headerHeight} isFocused={isFocused} - isScrolledDown={isScrolledDown} - scrollElRef={ - scrollElRef as React.MutableRefObject<FlatList<any> | null> - } + scrollElRef={scrollElRef as ListRef} ignoreFilterFor={profile.did} /> )} {showRepliesTab - ? ({ - onScroll, - headerHeight, - isFocused, - isScrolledDown, - scrollElRef, - }) => ( + ? ({headerHeight, isFocused, scrollElRef}) => ( <FeedSection ref={repliesSectionRef} feed={`author|${profile.did}|posts_with_replies`} - onScroll={onScroll} headerHeight={headerHeight} isFocused={isFocused} - isScrolledDown={isScrolledDown} - scrollElRef={ - scrollElRef as React.MutableRefObject<FlatList<any> | null> - } + scrollElRef={scrollElRef as ListRef} ignoreFilterFor={profile.did} /> ) : null} - {({onScroll, headerHeight, isFocused, isScrolledDown, scrollElRef}) => ( + {({headerHeight, isFocused, scrollElRef}) => ( <FeedSection ref={mediaSectionRef} feed={`author|${profile.did}|posts_with_media`} - onScroll={onScroll} headerHeight={headerHeight} isFocused={isFocused} - isScrolledDown={isScrolledDown} - scrollElRef={ - scrollElRef as React.MutableRefObject<FlatList<any> | null> - } + scrollElRef={scrollElRef as ListRef} ignoreFilterFor={profile.did} /> )} {showLikesTab - ? ({ - onScroll, - headerHeight, - isFocused, - isScrolledDown, - scrollElRef, - }) => ( + ? ({headerHeight, isFocused, scrollElRef}) => ( <FeedSection ref={likesSectionRef} feed={`likes|${profile.did}`} - onScroll={onScroll} headerHeight={headerHeight} isFocused={isFocused} - isScrolledDown={isScrolledDown} - scrollElRef={ - scrollElRef as React.MutableRefObject<FlatList<any> | null> - } + scrollElRef={scrollElRef as ListRef} ignoreFilterFor={profile.did} /> ) : null} {showFeedsTab - ? ({onScroll, headerHeight, isFocused, scrollElRef}) => ( + ? ({headerHeight, isFocused, scrollElRef}) => ( <ProfileFeedgens ref={feedsSectionRef} did={profile.did} - scrollElRef={ - scrollElRef as React.MutableRefObject<FlatList<any> | null> - } - onScroll={onScroll} - scrollEventThrottle={1} + scrollElRef={scrollElRef as ListRef} headerOffset={headerHeight} enabled={isFocused} /> ) : null} {showListsTab - ? ({onScroll, headerHeight, isFocused, scrollElRef}) => ( + ? ({headerHeight, isFocused, scrollElRef}) => ( <ProfileLists ref={listsSectionRef} did={profile.did} - scrollElRef={ - scrollElRef as React.MutableRefObject<FlatList<any> | null> - } - onScroll={onScroll} - scrollEventThrottle={1} + scrollElRef={scrollElRef as ListRef} headerOffset={headerHeight} enabled={isFocused} /> @@ -396,28 +360,19 @@ function ProfileScreenLoaded({ interface FeedSectionProps { feed: FeedDescriptor - onScroll: OnScrollHandler headerHeight: number isFocused: boolean - isScrolledDown: boolean - scrollElRef: React.MutableRefObject<FlatList<any> | null> + scrollElRef: ListRef ignoreFilterFor?: string } const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>( function FeedSectionImpl( - { - feed, - onScroll, - headerHeight, - isFocused, - isScrolledDown, - scrollElRef, - ignoreFilterFor, - }, + {feed, headerHeight, isFocused, scrollElRef, ignoreFilterFor}, ref, ) { const queryClient = useQueryClient() const [hasNew, setHasNew] = React.useState(false) + const [isScrolledDown, setIsScrolledDown] = React.useState(false) const onScrollToTop = React.useCallback(() => { scrollElRef.current?.scrollToOffset({ @@ -443,8 +398,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>( feed={feed} scrollElRef={scrollElRef} onHasNew={setHasNew} - onScroll={onScroll} - scrollEventThrottle={1} + onScrolledDownChange={setIsScrolledDown} renderEmptyState={renderPostsEmpty} headerOffset={headerHeight} renderEndOfFeed={ProfileEndOfFeed} diff --git a/src/view/screens/ProfileFeed.tsx b/src/view/screens/ProfileFeed.tsx index 620b1814a..ea92ebab1 100644 --- a/src/view/screens/ProfileFeed.tsx +++ b/src/view/screens/ProfileFeed.tsx @@ -1,11 +1,5 @@ import React, {useMemo, useCallback} from 'react' -import { - Dimensions, - StyleSheet, - View, - ActivityIndicator, - FlatList, -} from 'react-native' +import {Dimensions, StyleSheet, View, ActivityIndicator} from 'react-native' import {NativeStackScreenProps} from '@react-navigation/native-stack' import {useNavigation} from '@react-navigation/native' import {useQueryClient} from '@tanstack/react-query' @@ -20,6 +14,7 @@ import {PagerWithHeader} from 'view/com/pager/PagerWithHeader' import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader' import {Feed} from 'view/com/posts/Feed' import {TextLink} from 'view/com/util/Link' +import {ListRef} from 'view/com/util/List' import {Button} from 'view/com/util/forms/Button' import {Text} from 'view/com/util/text/Text' import {RichText} from 'view/com/util/text/RichText' @@ -29,12 +24,13 @@ import {EmptyState} from 'view/com/util/EmptyState' import * as Toast from 'view/com/util/Toast' import {useSetTitle} from 'lib/hooks/useSetTitle' import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed' -import {OnScrollHandler} from 'lib/hooks/useOnMainScroll' import {shareUrl} from 'lib/sharing' import {toShareUrl} from 'lib/strings/url-helpers' import {Haptics} from 'lib/haptics' import {useAnalytics} from 'lib/analytics/analytics' import {NativeDropdown, DropdownItem} from 'view/com/util/forms/NativeDropdown' +import {useScrollHandlers} from '#/lib/ScrollContext' +import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED' import {makeCustomFeedLink} from 'lib/routes/links' import {pluralize} from 'lib/strings/helpers' import {CenteredView, ScrollView} from 'view/com/util/Views' @@ -46,7 +42,6 @@ import {logger} from '#/logger' import {Trans, msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useModalControls} from '#/state/modals' -import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED' import { useFeedSourceInfoQuery, FeedSourceFeedInfo, @@ -403,17 +398,13 @@ export function ProfileFeedScreenInner({ isHeaderReady={true} renderHeader={renderHeader} onCurrentPageSelected={onCurrentPageSelected}> - {({onScroll, headerHeight, isScrolledDown, scrollElRef, isFocused}) => + {({headerHeight, scrollElRef, isFocused}) => isPublicResponse?.isPublic ? ( <FeedSection ref={feedSectionRef} feed={`feedgen|${feedInfo.uri}`} - onScroll={onScroll} headerHeight={headerHeight} - isScrolledDown={isScrolledDown} - scrollElRef={ - scrollElRef as React.MutableRefObject<FlatList<any> | null> - } + scrollElRef={scrollElRef as ListRef} isFocused={isFocused} /> ) : ( @@ -422,13 +413,12 @@ export function ProfileFeedScreenInner({ </CenteredView> ) } - {({onScroll, headerHeight, scrollElRef}) => ( + {({headerHeight, scrollElRef}) => ( <AboutSection feedOwnerDid={feedInfo.creatorDid} feedRkey={feedInfo.route.params.rkey} feedInfo={feedInfo} headerHeight={headerHeight} - onScroll={onScroll} scrollElRef={ scrollElRef as React.MutableRefObject<ScrollView | null> } @@ -497,18 +487,14 @@ function NonPublicFeedMessage({rawError}: {rawError?: Error}) { interface FeedSectionProps { feed: FeedDescriptor - onScroll: OnScrollHandler headerHeight: number - isScrolledDown: boolean - scrollElRef: React.MutableRefObject<FlatList<any> | null> + scrollElRef: ListRef isFocused: boolean } const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>( - function FeedSectionImpl( - {feed, onScroll, headerHeight, isScrolledDown, scrollElRef, isFocused}, - ref, - ) { + function FeedSectionImpl({feed, headerHeight, scrollElRef, isFocused}, ref) { const [hasNew, setHasNew] = React.useState(false) + const [isScrolledDown, setIsScrolledDown] = React.useState(false) const queryClient = useQueryClient() const onScrollToTop = useCallback(() => { @@ -536,8 +522,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>( pollInterval={30e3} scrollElRef={scrollElRef} onHasNew={setHasNew} - onScroll={onScroll} - scrollEventThrottle={5} + onScrolledDownChange={setIsScrolledDown} renderEmptyState={renderPostsEmpty} headerOffset={headerHeight} /> @@ -558,7 +543,6 @@ function AboutSection({ feedRkey, feedInfo, headerHeight, - onScroll, scrollElRef, isOwner, }: { @@ -566,13 +550,13 @@ function AboutSection({ feedRkey: string feedInfo: FeedSourceFeedInfo headerHeight: number - onScroll: OnScrollHandler scrollElRef: React.MutableRefObject<ScrollView | null> isOwner: boolean }) { const pal = usePalette('default') const {_} = useLingui() - const scrollHandler = useAnimatedScrollHandler(onScroll) + const scrollHandlers = useScrollHandlers() + const onScroll = useAnimatedScrollHandler(scrollHandlers) const [likeUri, setLikeUri] = React.useState(feedInfo.likeUri) const {hasSession} = useSession() const {track} = useAnalytics() @@ -608,12 +592,12 @@ function AboutSection({ return ( <ScrollView ref={scrollElRef} + onScroll={onScroll} scrollEventThrottle={1} contentContainerStyle={{ paddingTop: headerHeight, minHeight: Dimensions.get('window').height * 1.5, - }} - onScroll={scrollHandler}> + }}> <View style={[ { diff --git a/src/view/screens/ProfileList.tsx b/src/view/screens/ProfileList.tsx index 3dcc7121f..7f922e5b4 100644 --- a/src/view/screens/ProfileList.tsx +++ b/src/view/screens/ProfileList.tsx @@ -1,11 +1,5 @@ import React, {useCallback, useMemo} from 'react' -import { - ActivityIndicator, - FlatList, - Pressable, - StyleSheet, - View, -} from 'react-native' +import {ActivityIndicator, Pressable, StyleSheet, View} from 'react-native' import {useFocusEffect} from '@react-navigation/native' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {useNavigation} from '@react-navigation/native' @@ -22,6 +16,7 @@ import {EmptyState} from 'view/com/util/EmptyState' import {RichText} from 'view/com/util/text/RichText' import {Button} from 'view/com/util/forms/Button' import {TextLink} from 'view/com/util/Link' +import {ListRef} from 'view/com/util/List' import * as Toast from 'view/com/util/Toast' import {LoadLatestBtn} from 'view/com/util/load-latest/LoadLatestBtn' import {FAB} from 'view/com/util/fab/FAB' @@ -31,7 +26,6 @@ import {usePalette} from 'lib/hooks/usePalette' import {useSetTitle} from 'lib/hooks/useSetTitle' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed' -import {OnScrollHandler} from 'lib/hooks/useOnMainScroll' import {NavigationProp} from 'lib/routes/types' import {toShareUrl} from 'lib/strings/url-helpers' import {shareUrl} from 'lib/sharing' @@ -165,36 +159,22 @@ function ProfileListScreenLoaded({ isHeaderReady={true} renderHeader={renderHeader} onCurrentPageSelected={onCurrentPageSelected}> - {({ - onScroll, - headerHeight, - isScrolledDown, - scrollElRef, - isFocused, - }) => ( + {({headerHeight, scrollElRef, isFocused}) => ( <FeedSection ref={feedSectionRef} feed={`list|${uri}`} - scrollElRef={ - scrollElRef as React.MutableRefObject<FlatList<any> | null> - } - onScroll={onScroll} + scrollElRef={scrollElRef as ListRef} headerHeight={headerHeight} - isScrolledDown={isScrolledDown} isFocused={isFocused} /> )} - {({onScroll, headerHeight, isScrolledDown, scrollElRef}) => ( + {({headerHeight, scrollElRef}) => ( <AboutSection ref={aboutSectionRef} - scrollElRef={ - scrollElRef as React.MutableRefObject<FlatList<any> | null> - } + scrollElRef={scrollElRef as ListRef} list={list} onPressAddUser={onPressAddUser} - onScroll={onScroll} headerHeight={headerHeight} - isScrolledDown={isScrolledDown} /> )} </PagerWithHeader> @@ -221,16 +201,12 @@ function ProfileListScreenLoaded({ items={SECTION_TITLES_MOD} isHeaderReady={true} renderHeader={renderHeader}> - {({onScroll, headerHeight, isScrolledDown, scrollElRef}) => ( + {({headerHeight, scrollElRef}) => ( <AboutSection list={list} - scrollElRef={ - scrollElRef as React.MutableRefObject<FlatList<any> | null> - } + scrollElRef={scrollElRef as ListRef} onPressAddUser={onPressAddUser} - onScroll={onScroll} headerHeight={headerHeight} - isScrolledDown={isScrolledDown} /> )} </PagerWithHeader> @@ -615,19 +591,15 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) { interface FeedSectionProps { feed: FeedDescriptor - onScroll: OnScrollHandler headerHeight: number - isScrolledDown: boolean - scrollElRef: React.MutableRefObject<FlatList<any> | null> + scrollElRef: ListRef isFocused: boolean } const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>( - function FeedSectionImpl( - {feed, scrollElRef, onScroll, headerHeight, isScrolledDown, isFocused}, - ref, - ) { + function FeedSectionImpl({feed, scrollElRef, headerHeight, isFocused}, ref) { const queryClient = useQueryClient() const [hasNew, setHasNew] = React.useState(false) + const [isScrolledDown, setIsScrolledDown] = React.useState(false) const onScrollToTop = useCallback(() => { scrollElRef.current?.scrollToOffset({ @@ -654,8 +626,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>( pollInterval={30e3} scrollElRef={scrollElRef} onHasNew={setHasNew} - onScroll={onScroll} - scrollEventThrottle={1} + onScrolledDownChange={setIsScrolledDown} renderEmptyState={renderPostsEmpty} headerOffset={headerHeight} /> @@ -674,20 +645,19 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>( interface AboutSectionProps { list: AppBskyGraphDefs.ListView onPressAddUser: () => void - onScroll: OnScrollHandler headerHeight: number - isScrolledDown: boolean - scrollElRef: React.MutableRefObject<FlatList<any> | null> + scrollElRef: ListRef } const AboutSection = React.forwardRef<SectionRef, AboutSectionProps>( function AboutSectionImpl( - {list, onPressAddUser, onScroll, headerHeight, isScrolledDown, scrollElRef}, + {list, onPressAddUser, headerHeight, scrollElRef}, ref, ) { const pal = usePalette('default') const {_} = useLingui() const {isMobile} = useWebMediaQueries() const {currentAccount} = useSession() + const [isScrolledDown, setIsScrolledDown] = React.useState(false) const isCurateList = list.purpose === 'app.bsky.graph.defs#curatelist' const isOwner = list.creator.did === currentAccount?.did @@ -817,8 +787,7 @@ const AboutSection = React.forwardRef<SectionRef, AboutSectionProps>( renderHeader={renderHeader} renderEmptyState={renderEmptyState} headerOffset={headerHeight} - onScroll={onScroll} - scrollEventThrottle={1} + onScrolledDownChange={setIsScrolledDown} /> {isScrolledDown && ( <LoadLatestBtn diff --git a/src/view/screens/Search/Search.tsx b/src/view/screens/Search/Search.tsx index b4db270b3..7d7b4098f 100644 --- a/src/view/screens/Search/Search.tsx +++ b/src/view/screens/Search/Search.tsx @@ -8,7 +8,8 @@ import { Pressable, Platform, } from 'react-native' -import {FlatList, ScrollView, CenteredView} from '#/view/com/util/Views' +import {ScrollView, CenteredView} from '#/view/com/util/Views' +import {List} from '#/view/com/util/List' import {AppBskyActorDefs, AppBskyFeedDefs, moderateProfile} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -155,7 +156,7 @@ function SearchScreenSuggestedFollows() { }, [currentAccount, setSuggestions, getSuggestedFollowsByActor]) return suggestions.length ? ( - <FlatList + <List data={suggestions} renderItem={({item}) => <ProfileCardWithFollowBtn profile={item} noBg />} keyExtractor={item => item.did} @@ -243,7 +244,7 @@ function SearchScreenPostResults({query}: {query: string}) { {isFetched ? ( <> {posts.length ? ( - <FlatList + <List data={items} renderItem={({item}) => { if (item.type === 'post') { @@ -284,7 +285,7 @@ function SearchScreenUserResults({query}: {query: string}) { return isFetched && results ? ( <> {results.length ? ( - <FlatList + <List data={results} renderItem={({item}) => ( <ProfileCardWithFollowBtn profile={item} noBg /> |