diff options
author | Paul Frazee <pfrazee@gmail.com> | 2023-11-10 15:34:25 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-10 15:34:25 -0800 |
commit | c8c308e31e63607280648e3e9f1f56a371adcd05 (patch) | |
tree | 09cea4c603968a1a0b4cab299af9a417880c8115 /src/view/com/feeds/FeedPage.tsx | |
parent | 51f04b96200e38d95e486628d3cbc43398c47980 (diff) | |
download | voidsky-c8c308e31e63607280648e3e9f1f56a371adcd05.tar.zst |
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
Diffstat (limited to 'src/view/com/feeds/FeedPage.tsx')
-rw-r--r-- | src/view/com/feeds/FeedPage.tsx | 91 |
1 files changed, 38 insertions, 53 deletions
diff --git a/src/view/com/feeds/FeedPage.tsx b/src/view/com/feeds/FeedPage.tsx index 6a846f677..8d6a4a3d0 100644 --- a/src/view/com/feeds/FeedPage.tsx +++ b/src/view/com/feeds/FeedPage.tsx @@ -4,36 +4,38 @@ import { } from '@fortawesome/react-native-fontawesome' import {useIsFocused} from '@react-navigation/native' import {useAnalytics} from '@segment/analytics-react-native' +import {useQueryClient} from '@tanstack/react-query' +import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed' import {useOnMainScroll} from 'lib/hooks/useOnMainScroll' import {usePalette} from 'lib/hooks/usePalette' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' +import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed' import {ComposeIcon2} from 'lib/icons' import {colors, s} from 'lib/styles' -import {observer} from 'mobx-react-lite' import React from 'react' -import {FlatList, View} from 'react-native' +import {FlatList, View, useWindowDimensions} from 'react-native' import {useStores} from 'state/index' -import {PostsFeedModel} from 'state/models/feeds/posts' -import {useHeaderOffset, POLL_FREQ} from 'view/screens/Home' import {Feed} from '../posts/Feed' import {TextLink} from '../util/Link' import {FAB} from '../util/fab/FAB' import {LoadLatestBtn} from '../util/load-latest/LoadLatestBtn' -import useAppState from 'react-native-appstate-hook' -import {logger} from '#/logger' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useSession} from '#/state/session' -export const FeedPage = observer(function FeedPageImpl({ +const POLL_FREQ = 30e3 // 30sec + +export function FeedPage({ testID, isPageFocused, feed, + feedParams, renderEmptyState, renderEndOfFeed, }: { testID?: string - feed: PostsFeedModel + feed: FeedDescriptor + feedParams?: FeedParams isPageFocused: boolean renderEmptyState: () => JSX.Element renderEndOfFeed?: () => JSX.Element @@ -43,40 +45,13 @@ export const FeedPage = observer(function FeedPageImpl({ const pal = usePalette('default') const {_} = useLingui() const {isDesktop} = useWebMediaQueries() + const queryClient = useQueryClient() const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll() const {screen, track} = useAnalytics() const headerOffset = useHeaderOffset() const scrollElRef = React.useRef<FlatList>(null) - const {appState} = useAppState({ - onForeground: () => doPoll(true), - }) const isScreenFocused = useIsFocused() - const hasNew = feed.hasNewLatest && !feed.isRefreshing - - React.useEffect(() => { - // called on first load - if (!feed.hasLoaded && isPageFocused) { - feed.setup() - } - }, [isPageFocused, feed]) - - const doPoll = React.useCallback( - (knownActive = false) => { - if ( - (!knownActive && appState !== 'active') || - !isScreenFocused || - !isPageFocused - ) { - return - } - if (feed.isLoading) { - return - } - logger.debug('HomeScreen: Polling for new posts') - feed.checkForLatest() - }, - [appState, isScreenFocused, isPageFocused, feed], - ) + const [hasNew, setHasNew] = React.useState(false) const scrollToTop = React.useCallback(() => { scrollElRef.current?.scrollToOffset({offset: -headerOffset}) @@ -86,31 +61,22 @@ export const FeedPage = observer(function FeedPageImpl({ const onSoftReset = React.useCallback(() => { if (isPageFocused) { scrollToTop() - feed.refresh() + queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)}) + setHasNew(false) } - }, [isPageFocused, scrollToTop, feed]) + }, [isPageFocused, scrollToTop, queryClient, feed, setHasNew]) // fires when page within screen is activated/deactivated - // - check for latest React.useEffect(() => { if (!isPageFocused || !isScreenFocused) { return } - const softResetSub = store.onScreenSoftReset(onSoftReset) - const feedCleanup = feed.registerListeners() - const pollInterval = setInterval(doPoll, POLL_FREQ) - screen('Feed') - logger.debug('HomeScreen: Updating feed') - feed.checkForLatest() - return () => { - clearInterval(pollInterval) softResetSub.remove() - feedCleanup() } - }, [store, doPoll, onSoftReset, screen, feed, isPageFocused, isScreenFocused]) + }, [store, onSoftReset, screen, feed, isPageFocused, isScreenFocused]) const onPressCompose = React.useCallback(() => { track('HomeScreen:PressCompose') @@ -119,8 +85,9 @@ export const FeedPage = observer(function FeedPageImpl({ const onPressLoadLatest = React.useCallback(() => { scrollToTop() - feed.refresh() - }, [feed, scrollToTop]) + queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)}) + setHasNew(false) + }, [scrollToTop, feed, queryClient, setHasNew]) const ListHeaderComponent = React.useCallback(() => { if (isDesktop) { @@ -191,8 +158,12 @@ export const FeedPage = observer(function FeedPageImpl({ <Feed testID={testID ? `${testID}-feed` : undefined} feed={feed} + feedParams={feedParams} + enabled={isPageFocused} + pollInterval={POLL_FREQ} scrollElRef={scrollElRef} onScroll={onMainScroll} + onHasNew={setHasNew} scrollEventThrottle={1} renderEmptyState={renderEmptyState} renderEndOfFeed={renderEndOfFeed} @@ -216,4 +187,18 @@ export const FeedPage = observer(function FeedPageImpl({ /> </View> ) -}) +} + +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 +} |