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:
Paul Frazee 2023-11-10 15:34:25 -08:00 committed by GitHub
parent 51f04b9620
commit c8c308e31e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 904 additions and 1081 deletions

View file

@ -1,10 +1,9 @@
import React from 'react'
import {useWindowDimensions} from 'react-native'
import {useFocusEffect} from '@react-navigation/native'
import {observer} from 'mobx-react-lite'
import isEqual from 'lodash.isequal'
import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types'
import {PostsFeedModel} from 'state/models/feeds/posts'
import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState'
import {FollowingEndOfFeed} from 'view/com/posts/FollowingEndOfFeed'
@ -12,12 +11,9 @@ import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState'
import {FeedsTabBar} from '../com/pager/FeedsTabBar'
import {Pager, PagerRef, RenderTabBarFnProps} from 'view/com/pager/Pager'
import {useStores} from 'state/index'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {FeedPage} from 'view/com/feeds/FeedPage'
import {useSetMinimalShellMode, useSetDrawerSwipeDisabled} from '#/state/shell'
export const POLL_FREQ = 30e3 // 30sec
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
export const HomeScreen = withAuthRequired(
observer(function HomeScreenImpl({}: Props) {
@ -26,7 +22,7 @@ export const HomeScreen = withAuthRequired(
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
const pagerRef = React.useRef<PagerRef>(null)
const [selectedPage, setSelectedPage] = React.useState(0)
const [customFeeds, setCustomFeeds] = React.useState<PostsFeedModel[]>([])
const [customFeeds, setCustomFeeds] = React.useState<FeedDescriptor[]>([])
const [requestedCustomFeeds, setRequestedCustomFeeds] = React.useState<
string[]
>([])
@ -39,14 +35,12 @@ export const HomeScreen = withAuthRequired(
return
}
const feeds = []
const feeds: FeedDescriptor[] = []
for (const uri of pinned) {
if (uri.includes('app.bsky.feed.generator')) {
const model = new PostsFeedModel(store, 'custom', {feed: uri})
feeds.push(model)
feeds.push(`feedgen|${uri}`)
} else if (uri.includes('app.bsky.graph.list')) {
const model = new PostsFeedModel(store, 'list', {list: uri})
feeds.push(model)
feeds.push(`list|${uri}`)
}
}
pagerRef.current?.setPage(0)
@ -62,6 +56,19 @@ export const HomeScreen = withAuthRequired(
setRequestedCustomFeeds,
])
const homeFeedParams = React.useMemo<FeedParams>(() => {
if (!store.preferences.homeFeed.lab_mergeFeedEnabled) {
return {}
}
return {
mergeFeedEnabled: true,
mergeFeedSources: store.preferences.savedFeeds,
}
}, [
store.preferences.homeFeed.lab_mergeFeedEnabled,
store.preferences.savedFeeds,
])
useFocusEffect(
React.useCallback(() => {
setMinimalShellMode(false)
@ -129,14 +136,15 @@ export const HomeScreen = withAuthRequired(
key="1"
testID="followingFeedPage"
isPageFocused={selectedPage === 0}
feed={store.me.mainFeed}
feed="home"
feedParams={homeFeedParams}
renderEmptyState={renderFollowingEmptyState}
renderEndOfFeed={FollowingEndOfFeed}
/>
{customFeeds.map((f, index) => {
return (
<FeedPage
key={f.reactKey}
key={f}
testID="customFeedPage"
isPageFocused={selectedPage === 1 + index}
feed={f}
@ -148,17 +156,3 @@ export const HomeScreen = withAuthRequired(
)
}),
)
export function useHeaderOffset() {
const {isDesktop, isTablet} = useWebMediaQueries()
const {fontScale} = useWindowDimensions()
if (isDesktop) {
return 0
}
if (isTablet) {
return 50
}
// default text takes 44px, plus 34px of pad
// scale the 44px by the font scale
return 34 + 44 * fontScale
}