Make scroll handling contextual (#2200)
* Add an intermediate List component * Fix type * Add onScrolledDownChange * Port pager to use onScrolledDownChange * Fix on mobile * Don't pass down onScroll (replacement TBD) * Remove resetMainScroll * Replace onMainScroll with MainScrollProvider * Hook ScrollProvider to pager * Fix the remaining special case * Optimize a bit * Enforce that onScroll cannot be passed * Keep value updated even if no handler * Also memo it
This commit is contained in:
parent
fa3ccafa80
commit
7fd7970237
26 changed files with 280 additions and 354 deletions
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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={[
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue