diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index e058e2883..1d6bc4f45 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -1,342 +1,139 @@ import React from 'react' -import {ActivityIndicator, StyleSheet} from 'react-native' -import {useFocusEffect} from '@react-navigation/native' - -import {PROD_DEFAULT_FEED} from '#/lib/constants' -import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' -import {useOTAUpdates} from '#/lib/hooks/useOTAUpdates' -import {useSetTitle} from '#/lib/hooks/useSetTitle' -import {useRequestNotificationsPermission} from '#/lib/notifications/notifications' -import { - type HomeTabNavigatorParams, - type NativeStackScreenProps, -} from '#/lib/routes/types' -import {logEvent} from '#/lib/statsig/statsig' -import {isWeb} from '#/platform/detection' -import {emitSoftReset} from '#/state/events' -import { - type SavedFeedSourceInfo, - usePinnedFeedsInfos, -} from '#/state/queries/feed' -import {type FeedDescriptor, type FeedParams} from '#/state/queries/post-feed' -import {usePreferencesQuery} from '#/state/queries/preferences' -import {type UsePreferencesQueryResponse} from '#/state/queries/preferences/types' -import {useSession} from '#/state/session' -import {useSetMinimalShellMode} from '#/state/shell' -import {useLoggedOutViewControls} from '#/state/shell/logged-out' -import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed' -import {FeedPage} from '#/view/com/feeds/FeedPage' -import {HomeHeader} from '#/view/com/home/HomeHeader' -import { - Pager, - type PagerRef, - type RenderTabBarFnProps, -} from '#/view/com/pager/Pager' -import {CustomFeedEmptyState} from '#/view/com/posts/CustomFeedEmptyState' -import {FollowingEmptyState} from '#/view/com/posts/FollowingEmptyState' -import {FollowingEndOfFeed} from '#/view/com/posts/FollowingEndOfFeed' -import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned' +import { ActivityIndicator, StyleSheet } from 'react-native' +import { useFocusEffect } from '@react-navigation/native' +import { PROD_DEFAULT_FEED } from '#/lib/constants' +import { useNonReactiveCallback } from '#/lib/hooks/useNonReactiveCallback' +import { useOTAUpdates } from '#/lib/hooks/useOTAUpdates' +import { useSetTitle } from '#/lib/hooks/useSetTitle' +import { useRequestNotificationsPermission } from '#/lib/notifications/notifications' +import { type HomeTabNavigatorParams, type NativeStackScreenProps } from '#/lib/routes/types' +import { logEvent } from '#/lib/statsig/statsig' +import { isWeb } from '#/platform/detection' +import { emitSoftReset } from '#/state/events' +import { type SavedFeedSourceInfo, usePinnedFeedsInfos } from '#/state/queries/feed' +import { type FeedDescriptor, type FeedParams } from '#/state/queries/post-feed' +import { usePreferencesQuery } from '#/state/queries/preferences' +import { type UsePreferencesQueryResponse } from '#/state/queries/preferences/types' +import { useSession } from '#/state/session' +import { useSetMinimalShellMode } from '#/state/shell' +import { useLoggedOutViewControls } from '#/state/shell/logged-out' +import { useSelectedFeed, useSetSelectedFeed } from '#/state/shell/selected-feed' +import { FeedPage } from '#/view/com/feeds/FeedPage' +import { HomeHeader } from '#/view/com/home/HomeHeader' +import { Pager, type PagerRef, type RenderTabBarFnProps } from '#/view/com/pager/Pager' +import { CustomFeedEmptyState } from '#/view/com/posts/CustomFeedEmptyState' +import { FollowingEmptyState } from '#/view/com/posts/FollowingEmptyState' +import { FollowingEndOfFeed } from '#/view/com/posts/FollowingEndOfFeed' +import { NoFeedsPinned } from '#/screens/Home/NoFeedsPinned' import * as Layout from '#/components/Layout' -import {useDemoMode} from '#/storage/hooks/demo-mode' +import { useDemoMode } from '#/storage/hooks/demo-mode' + +const DEFAULT_PINNED_FEEDS = [{ + feedDescriptor: 'following', + displayName: 'Following', + id: 'following', + type: 'feed', + savedFeed: undefined, + pinned: true, +}] type Props = NativeStackScreenProps export function HomeScreen(props: Props) { - const {setShowLoggedOut} = useLoggedOutViewControls() - const {data: preferences} = usePreferencesQuery() - const {currentAccount} = useSession() - const {data: pinnedFeedInfos, isLoading: isPinnedFeedsLoading} = - usePinnedFeedsInfos() + const { setShowLoggedOut } = useLoggedOutViewControls() + const { data: preferences } = usePreferencesQuery() + const { currentAccount } = useSession() + const { data: pinnedFeedInfos } = usePinnedFeedsInfos() + + const safePreferences = preferences || { feedViewPrefs: { lab_mergeFeedEnabled: false }, savedFeeds: [] } as any + const safePinnedFeedInfos = [{ + feedDescriptor: 'following', + displayName: 'Following', + id: 'following', + type: 'feed', + savedFeed: undefined, + pinned: true, + }] React.useEffect(() => { if (isWeb && !currentAccount) { const getParams = new URLSearchParams(window.location.search) const splash = getParams.get('splash') - if (splash === 'true') { - setShowLoggedOut(true) - return - } + if (splash === 'true') { setShowLoggedOut(true); return } } - const params = props.route.params - if ( - currentAccount && - props.route.name === 'Start' && - params?.name && - params?.rkey - ) { - props.navigation.navigate('StarterPack', { - rkey: params.rkey, - name: params.name, - }) + if (currentAccount && props.route.name === 'Start' && params?.name && params?.rkey) { + props.navigation.navigate('StarterPack', { rkey: params.rkey, name: params.name }) } - }, [ - currentAccount, - props.navigation, - props.route.name, - props.route.params, - setShowLoggedOut, - ]) + }, [currentAccount, props.navigation, props.route.name, props.route.params, setShowLoggedOut]) - if (preferences && pinnedFeedInfos && !isPinnedFeedsLoading) { - return ( - - - - ) - } else { - return ( - - - - - - ) - } + return ( + + + + ) } -function HomeScreenReady({ - preferences, - pinnedFeedInfos, -}: Props & { - preferences: UsePreferencesQueryResponse - pinnedFeedInfos: SavedFeedSourceInfo[] -}) { - const allFeeds = React.useMemo( - () => pinnedFeedInfos.map(f => f.feedDescriptor), - [pinnedFeedInfos], - ) - const maybeRawSelectedFeed: FeedDescriptor | undefined = - useSelectedFeed() ?? allFeeds[0] +function HomeScreenReady({ preferences, pinnedFeedInfos }: any) { + const allFeeds = React.useMemo(() => pinnedFeedInfos.map(f => f.feedDescriptor), [pinnedFeedInfos]) + const maybeRawSelectedFeed = useSelectedFeed() ?? allFeeds[0] const setSelectedFeed = useSetSelectedFeed() const maybeFoundIndex = allFeeds.indexOf(maybeRawSelectedFeed) const selectedIndex = Math.max(0, maybeFoundIndex) - const maybeSelectedFeed: FeedDescriptor | undefined = allFeeds[selectedIndex] + const maybeSelectedFeed = allFeeds[selectedIndex] const requestNotificationsPermission = useRequestNotificationsPermission() useSetTitle(pinnedFeedInfos[selectedIndex]?.displayName) useOTAUpdates() - - React.useEffect(() => { - requestNotificationsPermission('Home') - }, [requestNotificationsPermission]) + React.useEffect(() => { requestNotificationsPermission('Home') }, [requestNotificationsPermission]) const pagerRef = React.useRef(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 { hasSession } = useSession() const setMinimalShellMode = useSetMinimalShellMode() - useFocusEffect( - React.useCallback(() => { - setMinimalShellMode(false) - }, [setMinimalShellMode]), - ) - - useFocusEffect( - useNonReactiveCallback(() => { - if (maybeSelectedFeed) { - logEvent('home:feedDisplayed', { - index: selectedIndex, - feedType: maybeSelectedFeed.split('|')[0], - feedUrl: maybeSelectedFeed, - reason: 'focus', - }) - } - }), - ) + useFocusEffect(React.useCallback(() => { setMinimalShellMode(false) }, [setMinimalShellMode])) - const onPageSelected = React.useCallback( - (index: number) => { - setMinimalShellMode(false) - const maybeFeed = allFeeds[index] - - // Mutate the ref before setting state to avoid the imperative syncing effect - // above from starting a loop on Android when swiping back and forth. - lastPagerReportedIndexRef.current = index - setSelectedFeed(maybeFeed) - - if (maybeFeed) { - logEvent('home:feedDisplayed', { - index, - feedType: maybeFeed.split('|')[0], - feedUrl: maybeFeed, - }) - } - }, - [setSelectedFeed, setMinimalShellMode, allFeeds], - ) + const onPageSelected = React.useCallback((index) => { + setMinimalShellMode(false) + const maybeFeed = allFeeds[index] + lastPagerReportedIndexRef.current = index + setSelectedFeed(maybeFeed) + }, [setSelectedFeed, setMinimalShellMode, allFeeds]) - const onPressSelected = React.useCallback(() => { - emitSoftReset() - }, []) - - const onPageScrollStateChanged = React.useCallback( - (state: 'idle' | 'dragging' | 'settling') => { - 'worklet' - if (state === 'dragging') { - setMinimalShellMode(false) - } - }, - [setMinimalShellMode], - ) + const onPressSelected = React.useCallback(() => { emitSoftReset() }, []) + const onPageScrollStateChanged = React.useCallback((state) => { + 'worklet' + if (state === 'dragging') setMinimalShellMode(false) + }, [setMinimalShellMode]) const [demoMode] = useDemoMode() - - const renderTabBar = React.useCallback( - (props: RenderTabBarFnProps) => { - if (demoMode) { - return ( - - ) - } - return ( - - ) - }, - [onPressSelected, pinnedFeedInfos, demoMode], - ) - - const renderFollowingEmptyState = React.useCallback(() => { - return - }, []) - - const renderCustomFeedEmptyState = React.useCallback(() => { - return - }, []) - - const homeFeedParams = React.useMemo(() => { - return { - mergeFeedEnabled: Boolean(preferences.feedViewPrefs.lab_mergeFeedEnabled), - mergeFeedSources: preferences.feedViewPrefs.lab_mergeFeedEnabled - ? preferences.savedFeeds - .filter(f => f.type === 'feed' || f.type === 'list') - .map(f => f.value) - : [], - } - }, [preferences]) - - if (demoMode) { - return ( - - - - - ) - } - - return hasSession ? ( - - {pinnedFeedInfos.length ? ( - pinnedFeedInfos.map((feedInfo, index) => { - const feed = feedInfo.feedDescriptor - if (feed === 'following') { - return ( - - ) - } - const savedFeedConfig = feedInfo.savedFeed - return ( - - ) - }) - ) : ( - - )} - - ) : ( - - + const renderTabBar = React.useCallback((props) => { + return + }, [onPressSelected, pinnedFeedInfos]) + + const renderFollowingEmptyState = React.useCallback(() => , []) + const renderCustomFeedEmptyState = React.useCallback(() => , []) + + const homeFeedParams = React.useMemo(() => ({ + mergeFeedEnabled: false, mergeFeedSources: [] + }), [preferences]) + + return ( + + {pinnedFeedInfos.map((feedInfo, index) => { + const feed = feedInfo.feedDescriptor + if (feed === 'following') { + return + } + return + })} ) } - -const styles = StyleSheet.create({ - loading: { - height: '100%', - alignContent: 'center', - justifyContent: 'center', - paddingBottom: 100, - }, -}) +const styles = StyleSheet.create({ loading: { height: '100%', alignContent: 'center', justifyContent: 'center', paddingBottom: 100 } })