Refactor feeds to use react-query (#1862)
* Update to react-query v5 * Introduce post-feed react query * Add feed refresh behaviors * Only fetch feeds of visible pages * Implement polling for latest on feeds * Add moderation filtering to slices * Handle block errors * Update feed error messages * Remove old models * Replace simple-feed option with disable-tuner option * Add missing useMemo * Implement the mergefeed and fixes to polling * Correctly handle failed load more state * Improve error and empty state behaviors * Clearer naming
This commit is contained in:
parent
51f04b9620
commit
c8c308e31e
31 changed files with 904 additions and 1081 deletions
|
@ -12,6 +12,7 @@ import {useNavigation} from '@react-navigation/native'
|
|||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {observer} from 'mobx-react-lite'
|
||||
import {RichText as RichTextAPI} from '@atproto/api'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
||||
import {PagerWithHeader} from 'view/com/pager/PagerWithHeader'
|
||||
import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader'
|
||||
|
@ -28,11 +29,12 @@ import {LoadLatestBtn} from 'view/com/util/load-latest/LoadLatestBtn'
|
|||
import {FAB} from 'view/com/util/fab/FAB'
|
||||
import {Haptics} from 'lib/haptics'
|
||||
import {ListModel} from 'state/models/content/list'
|
||||
import {PostsFeedModel} from 'state/models/feeds/posts'
|
||||
import {FeedDescriptor} from '#/state/queries/post-feed'
|
||||
import {useStores} from 'state/index'
|
||||
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'
|
||||
|
@ -109,34 +111,25 @@ export const ProfileListScreenInner = observer(
|
|||
}: Props & {listOwnerDid: string}) {
|
||||
const store = useStores()
|
||||
const {_} = useLingui()
|
||||
const queryClient = useQueryClient()
|
||||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
const {rkey} = route.params
|
||||
const listUri = `at://${listOwnerDid}/app.bsky.graph.list/${rkey}`
|
||||
const feedSectionRef = React.useRef<SectionRef>(null)
|
||||
const aboutSectionRef = React.useRef<SectionRef>(null)
|
||||
const {openModal} = useModalControls()
|
||||
|
||||
const list: ListModel = useMemo(() => {
|
||||
const model = new ListModel(
|
||||
store,
|
||||
`at://${listOwnerDid}/app.bsky.graph.list/${rkey}`,
|
||||
)
|
||||
const model = new ListModel(store, listUri)
|
||||
return model
|
||||
}, [store, listOwnerDid, rkey])
|
||||
const feed = useMemo(
|
||||
() => new PostsFeedModel(store, 'list', {list: list.uri}),
|
||||
[store, list],
|
||||
)
|
||||
}, [store, listUri])
|
||||
useSetTitle(list.data?.name)
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
setMinimalShellMode(false)
|
||||
list.loadMore(true).then(() => {
|
||||
if (list.isCuratelist) {
|
||||
feed.setup()
|
||||
}
|
||||
})
|
||||
}, [setMinimalShellMode, list, feed]),
|
||||
list.loadMore(true)
|
||||
}, [setMinimalShellMode, list]),
|
||||
)
|
||||
|
||||
const onPressAddUser = useCallback(() => {
|
||||
|
@ -145,11 +138,13 @@ export const ProfileListScreenInner = observer(
|
|||
list,
|
||||
onAdd() {
|
||||
if (list.isCuratelist) {
|
||||
feed.refresh()
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: FEED_RQKEY(`list|${listUri}`),
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
}, [openModal, list, feed])
|
||||
}, [openModal, list, queryClient, listUri])
|
||||
|
||||
const onCurrentPageSelected = React.useCallback(
|
||||
(index: number) => {
|
||||
|
@ -178,10 +173,10 @@ export const ProfileListScreenInner = observer(
|
|||
{({onScroll, headerHeight, isScrolledDown, scrollElRef}) => (
|
||||
<FeedSection
|
||||
ref={feedSectionRef}
|
||||
feed={`list|${listUri}`}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<FlatList<any> | null>
|
||||
}
|
||||
feed={feed}
|
||||
onScroll={onScroll}
|
||||
headerHeight={headerHeight}
|
||||
isScrolledDown={isScrolledDown}
|
||||
|
@ -562,7 +557,7 @@ const Header = observer(function HeaderImpl({
|
|||
})
|
||||
|
||||
interface FeedSectionProps {
|
||||
feed: PostsFeedModel
|
||||
feed: FeedDescriptor
|
||||
onScroll: OnScrollHandler
|
||||
headerHeight: number
|
||||
isScrolledDown: boolean
|
||||
|
@ -573,12 +568,14 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
|||
{feed, scrollElRef, onScroll, headerHeight, isScrolledDown},
|
||||
ref,
|
||||
) {
|
||||
const hasNew = feed.hasNewLatest && !feed.isRefreshing
|
||||
const queryClient = useQueryClient()
|
||||
const [hasNew, setHasNew] = React.useState(false)
|
||||
|
||||
const onScrollToTop = useCallback(() => {
|
||||
scrollElRef.current?.scrollToOffset({offset: -headerHeight})
|
||||
feed.refresh()
|
||||
}, [feed, scrollElRef, headerHeight])
|
||||
queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)})
|
||||
setHasNew(false)
|
||||
}, [scrollElRef, headerHeight, queryClient, feed, setHasNew])
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
scrollToTop: onScrollToTop,
|
||||
}))
|
||||
|
@ -592,7 +589,9 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
|||
<Feed
|
||||
testID="listFeed"
|
||||
feed={feed}
|
||||
pollInterval={30e3}
|
||||
scrollElRef={scrollElRef}
|
||||
onHasNew={setHasNew}
|
||||
onScroll={onScroll}
|
||||
scrollEventThrottle={1}
|
||||
renderEmptyState={renderPostsEmpty}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue