Keep pager feeds in sync with the right pane (#2775)

* Hoist selected feed state

* Seed state from params

* Refine and fix logic

* Fix scroll restoration

* Soft reset on second click
This commit is contained in:
dan 2024-02-08 20:37:08 +00:00 committed by GitHub
parent 80c482b026
commit 06f81d6948
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 148 additions and 63 deletions

View file

@ -7,7 +7,7 @@ import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState'
import {FollowingEndOfFeed} from 'view/com/posts/FollowingEndOfFeed'
import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState'
import {FeedsTabBar} from '../com/pager/FeedsTabBar'
import {Pager, RenderTabBarFnProps} from 'view/com/pager/Pager'
import {Pager, RenderTabBarFnProps, PagerRef} from 'view/com/pager/Pager'
import {FeedPage} from 'view/com/feeds/FeedPage'
import {HomeLoggedOutCTA} from '../com/auth/HomeLoggedOutCTA'
import {useSetMinimalShellMode, useSetDrawerSwipeDisabled} from '#/state/shell'
@ -16,25 +16,19 @@ import {usePinnedFeedsInfos, FeedSourceInfo} from '#/state/queries/feed'
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
import {emitSoftReset} from '#/state/events'
import {useSession} from '#/state/session'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import * as persisted from '#/state/persisted'
import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed'
type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
export function HomeScreen(props: Props) {
const {data: preferences} = usePreferencesQuery()
const {feeds: pinnedFeedInfos, isLoading: isPinnedFeedsLoading} =
usePinnedFeedsInfos()
const {isDesktop} = useWebMediaQueries()
const [rawInitialFeed] = React.useState<string>(
() => persisted.get('lastSelectedHomeFeed') ?? 'home',
)
if (preferences && pinnedFeedInfos && !isPinnedFeedsLoading) {
return (
<HomeScreenReady
{...props}
preferences={preferences}
pinnedFeedInfos={pinnedFeedInfos}
rawInitialFeed={isDesktop ? 'home' : rawInitialFeed}
/>
)
} else {
@ -49,11 +43,9 @@ export function HomeScreen(props: Props) {
function HomeScreenReady({
preferences,
pinnedFeedInfos,
rawInitialFeed,
}: Props & {
preferences: UsePreferencesQueryResponse
pinnedFeedInfos: FeedSourceInfo[]
rawInitialFeed: string
}) {
const allFeeds = React.useMemo(() => {
const feeds: FeedDescriptor[] = []
@ -68,12 +60,24 @@ function HomeScreenReady({
return feeds
}, [pinnedFeedInfos])
const [rawSelectedFeed, setSelectedFeed] =
React.useState<string>(rawInitialFeed)
const rawSelectedFeed = useSelectedFeed()
const setSelectedFeed = useSetSelectedFeed()
const maybeFoundIndex = allFeeds.indexOf(rawSelectedFeed as FeedDescriptor)
const selectedIndex = Math.max(0, maybeFoundIndex)
const selectedFeed = allFeeds[selectedIndex]
const pagerRef = React.useRef<PagerRef>(null)
const lastPagerReportedIndexRef = React.useRef(selectedIndex)
React.useLayoutEffect(() => {
// Since the pager is not a controlled component, adjust it imperatively
// if the selected index gets out of sync with what it last reported.
// This is supposed to only happen on the web when you use the right nav.
if (selectedIndex !== lastPagerReportedIndexRef.current) {
lastPagerReportedIndexRef.current = selectedIndex
pagerRef.current?.setPage(selectedIndex)
}
}, [selectedIndex])
const {hasSession} = useSession()
const setMinimalShellMode = useSetMinimalShellMode()
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
@ -93,7 +97,7 @@ function HomeScreenReady({
setDrawerSwipeDisabled(index > 0)
const feed = allFeeds[index]
setSelectedFeed(feed)
persisted.write('lastSelectedHomeFeed', feed)
lastPagerReportedIndexRef.current = index
},
[setDrawerSwipeDisabled, setSelectedFeed, setMinimalShellMode, allFeeds],
)
@ -147,6 +151,7 @@ function HomeScreenReady({
return hasSession ? (
<Pager
key={allFeeds.join(',')}
ref={pagerRef}
testID="homeScreen"
initialPage={selectedIndex}
onPageSelected={onPageSelected}