fabric: update scroll forwarder for profile headers (#8366)

* progress

* remove old module

* nil delegates

* clean up problems

* fix refreshing

* bump
This commit is contained in:
hailey
2025-05-13 13:01:47 -07:00
committed by Samuel Newman
parent 3d447cc841
commit 2c7cab5ae5
22 changed files with 576 additions and 288 deletions
+7 -1
View File
@@ -9,7 +9,7 @@ import {isIOS, isNative} from '#/platform/detection'
import {type FeedDescriptor} from '#/state/queries/post-feed'
import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed'
import {truncateAndInvalidate} from '#/state/queries/util'
import {PostFeed} from '#/view/com/posts/PostFeed'
import {PostFeed, type PostFeedRef} 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'
@@ -24,6 +24,8 @@ interface FeedSectionProps {
scrollElRef: ListRef
ignoreFilterFor?: string
setScrollViewTag: (tag: number | null) => void
postFeedRef?: React.RefObject<PostFeedRef | undefined>
onRefreshEnd?: () => void
}
export const ProfileFeedSection = React.forwardRef<
SectionRef,
@@ -36,6 +38,8 @@ export const ProfileFeedSection = React.forwardRef<
scrollElRef,
ignoreFilterFor,
setScrollViewTag,
postFeedRef,
onRefreshEnd,
},
ref,
) {
@@ -91,6 +95,8 @@ export const ProfileFeedSection = React.forwardRef<
shouldUseAdjustedNumToRender ? adjustedInitialNumToRender : undefined
}
isVideoFeed={isVideoFeed}
ref={postFeedRef}
onRefreshEnd={onRefreshEnd}
/>
{(isScrolledDown || hasNew) && (
<LoadLatestBtn
+27 -4
View File
@@ -1,4 +1,12 @@
import {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react'
import {
memo,
useCallback,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
} from 'react'
import {
ActivityIndicator,
AppState,
@@ -163,6 +171,10 @@ export function getItemsForFeedback(feedRow: FeedRow): {
}
}
export type PostFeedRef = {
refreshFeed: () => Promise<void>
}
// DISABLED need to check if this is causing random feed refreshes -prf
// const REFRESH_AFTER = STALE.HOURS.ONE
const CHECK_LATEST_AFTER = STALE.SECONDS.THIRTY
@@ -189,6 +201,7 @@ let PostFeed = ({
savedFeedConfig,
initialNumToRender: initialNumToRenderOverride,
isVideoFeed = false,
ref,
}: {
feed: FeedDescriptor
feedParams?: FeedParams
@@ -211,6 +224,7 @@ let PostFeed = ({
savedFeedConfig?: AppBskyActorDefs.SavedFeed
initialNumToRender?: number
isVideoFeed?: boolean
ref?: React.ForwardedRef<PostFeedRef>
}): React.ReactNode => {
const {_} = useLingui()
const queryClient = useQueryClient()
@@ -629,22 +643,31 @@ let PostFeed = ({
// events
// =
//
const onRefresh = useCallback(async () => {
const refreshFeed = async () => {
logEvent('feed:refresh', {
feedType: feedType,
feedUrl: feed,
reason: 'pull-to-refresh',
})
setIsPTRing(true)
try {
await refetch()
onHasNew?.(false)
} catch (err) {
logger.error('Failed to refresh posts feed', {message: err})
}
}
const onRefresh = async () => {
setIsPTRing(true)
await refreshFeed()
setIsPTRing(false)
}, [refetch, setIsPTRing, onHasNew, feed, feedType])
}
useImperativeHandle(ref, () => ({
refreshFeed,
}))
const onEndReached = useCallback(async () => {
if (isFetching || !hasNextPage || isError) return
+18 -4
View File
@@ -1,4 +1,4 @@
import React, {useCallback, useMemo} from 'react'
import React, {useCallback, useMemo, useRef, useState} from 'react'
import {StyleSheet} from 'react-native'
import {SafeAreaView} from 'react-native-safe-area-context'
import {
@@ -11,6 +11,7 @@ import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useFocusEffect} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query'
import {ScrollForwarderView} from 'modules/react-native-scroll-forwarder/src'
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
import {useSetTitle} from '#/lib/hooks/useSetTitle'
@@ -46,7 +47,7 @@ import * as Layout from '#/components/Layout'
import {ScreenHider} from '#/components/moderation/ScreenHider'
import {ProfileStarterPacks} from '#/components/StarterPack/ProfileStarterPacks'
import {navigate} from '#/Navigation'
import {ExpoScrollForwarderView} from '../../../modules/expo-scroll-forwarder'
import {type PostFeedRef} from '../com/posts/PostFeed'
interface SectionRef {
scrollToTop: () => void
@@ -178,6 +179,7 @@ function ProfileScreenLoaded({
enabled: !!profile.associated?.labeler,
})
const [currentPage, setCurrentPage] = React.useState(0)
const [isRefreshing, setIsRefreshing] = useState(false)
const {_} = useLingui()
const [scrollViewTag, setScrollViewTag] = React.useState<number | null>(null)
@@ -334,6 +336,14 @@ function ProfileScreenLoaded({
scrollSectionToTop(index)
}
const postFeedRef = useRef<PostFeedRef>()
const onRefresh = async () => {
setIsRefreshing(true)
await postFeedRef.current?.refreshFeed()
setIsRefreshing(false)
}
// rendering
// =
@@ -343,7 +353,10 @@ function ProfileScreenLoaded({
setMinimumHeight: (height: number) => void
}) => {
return (
<ExpoScrollForwarderView scrollViewTag={scrollViewTag}>
<ScrollForwarderView
scrollViewTag={scrollViewTag}
refreshing={isRefreshing}
onRefresh={onRefresh}>
<ProfileHeader
profile={profile}
labeler={labelerInfo}
@@ -353,7 +366,7 @@ function ProfileScreenLoaded({
isPlaceholderProfile={showPlaceholder}
setMinimumHeight={setMinimumHeight}
/>
</ExpoScrollForwarderView>
</ScrollForwarderView>
)
}
@@ -408,6 +421,7 @@ function ProfileScreenLoaded({
scrollElRef={scrollElRef as ListRef}
ignoreFilterFor={profile.did}
setScrollViewTag={setScrollViewTag}
postFeedRef={postFeedRef}
/>
)
: null}