diff options
Diffstat (limited to 'src/view/screens/Home.tsx')
-rw-r--r-- | src/view/screens/Home.tsx | 220 |
1 files changed, 9 insertions, 211 deletions
diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index cce62f498..ad47e9f9b 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -1,33 +1,22 @@ import React from 'react' -import {FlatList, View, useWindowDimensions} from 'react-native' -import {useFocusEffect, useIsFocused} from '@react-navigation/native' -import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' -import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome' +import {useWindowDimensions} from 'react-native' +import {useFocusEffect} from '@react-navigation/native' import {AppBskyFeedGetFeed as GetCustomFeed} from '@atproto/api' import {observer} from 'mobx-react-lite' -import useAppState from 'react-native-appstate-hook' import isEqual from 'lodash.isequal' import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types' import {PostsFeedModel} from 'state/models/feeds/posts' import {withAuthRequired} from 'view/com/auth/withAuthRequired' -import {TextLink} from 'view/com/util/Link' -import {Feed} from '../com/posts/Feed' import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState' import {FollowingEndOfFeed} from 'view/com/posts/FollowingEndOfFeed' import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState' -import {LoadLatestBtn} from '../com/util/load-latest/LoadLatestBtn' import {FeedsTabBar} from '../com/pager/FeedsTabBar' import {Pager, PagerRef, RenderTabBarFnProps} from 'view/com/pager/Pager' -import {FAB} from '../com/util/fab/FAB' import {useStores} from 'state/index' -import {usePalette} from 'lib/hooks/usePalette' -import {s, colors} from 'lib/styles' -import {useOnMainScroll} from 'lib/hooks/useOnMainScroll' -import {useAnalytics} from 'lib/analytics/analytics' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' -import {ComposeIcon2} from 'lib/icons' +import {FeedPage} from 'view/com/feeds/FeedPage' -const POLL_FREQ = 30e3 // 30sec +export const POLL_FREQ = 30e3 // 30sec type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'> export const HomeScreen = withAuthRequired( @@ -98,7 +87,9 @@ export const HomeScreen = withAuthRequired( (props: RenderTabBarFnProps) => { return ( <FeedsTabBar - {...props} + key="FEEDS_TAB_BAR" + selectedPage={props.selectedPage} + onSelect={props.onSelect} testID="homeScreenFeedTabs" onPressSelected={onPressSelected} /> @@ -111,10 +102,6 @@ export const HomeScreen = withAuthRequired( return <FollowingEmptyState /> }, []) - const renderFollowingEndOfFeed = React.useCallback(() => { - return <FollowingEndOfFeed /> - }, []) - const renderCustomFeedEmptyState = React.useCallback(() => { return <CustomFeedEmptyState /> }, []) @@ -132,7 +119,7 @@ export const HomeScreen = withAuthRequired( isPageFocused={selectedPage === 0} feed={store.me.mainFeed} renderEmptyState={renderFollowingEmptyState} - renderEndOfFeed={renderFollowingEndOfFeed} + renderEndOfFeed={FollowingEndOfFeed} /> {customFeeds.map((f, index) => { return ( @@ -150,196 +137,7 @@ export const HomeScreen = withAuthRequired( }), ) -const FeedPage = observer(function FeedPageImpl({ - testID, - isPageFocused, - feed, - renderEmptyState, - renderEndOfFeed, -}: { - testID?: string - feed: PostsFeedModel - isPageFocused: boolean - renderEmptyState: () => JSX.Element - renderEndOfFeed?: () => JSX.Element -}) { - const store = useStores() - const pal = usePalette('default') - const {isDesktop} = useWebMediaQueries() - const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll(store) - 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 - } - store.log.debug('HomeScreen: Polling for new posts') - feed.checkForLatest() - }, - [appState, isScreenFocused, isPageFocused, store, feed], - ) - - const scrollToTop = React.useCallback(() => { - scrollElRef.current?.scrollToOffset({offset: -headerOffset}) - resetMainScroll() - }, [headerOffset, resetMainScroll]) - - const onSoftReset = React.useCallback(() => { - if (isPageFocused) { - scrollToTop() - feed.refresh() - } - }, [isPageFocused, scrollToTop, feed]) - - // 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') - store.log.debug('HomeScreen: Updating feed') - feed.checkForLatest() - - return () => { - clearInterval(pollInterval) - softResetSub.remove() - feedCleanup() - } - }, [store, doPoll, onSoftReset, screen, feed, isPageFocused, isScreenFocused]) - - const onPressCompose = React.useCallback(() => { - track('HomeScreen:PressCompose') - store.shell.openComposer({}) - }, [store, track]) - - const onPressTryAgain = React.useCallback(() => { - feed.refresh() - }, [feed]) - - const onPressLoadLatest = React.useCallback(() => { - scrollToTop() - feed.refresh() - }, [feed, scrollToTop]) - - const ListHeaderComponent = React.useCallback(() => { - if (isDesktop) { - return ( - <View - style={[ - pal.view, - { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - paddingHorizontal: 18, - paddingVertical: 12, - }, - ]}> - <TextLink - type="title-lg" - href="/" - style={[pal.text, {fontWeight: 'bold'}]} - text={ - <> - {store.session.isSandbox ? 'SANDBOX' : 'Bluesky'}{' '} - {hasNew && ( - <View - style={{ - top: -8, - backgroundColor: colors.blue3, - width: 8, - height: 8, - borderRadius: 4, - }} - /> - )} - </> - } - onPress={() => store.emitScreenSoftReset()} - /> - <TextLink - type="title-lg" - href="/settings/home-feed" - style={{fontWeight: 'bold'}} - accessibilityLabel="Feed Preferences" - accessibilityHint="" - text={ - <FontAwesomeIcon - icon="sliders" - style={pal.textLight as FontAwesomeIconStyle} - /> - } - /> - </View> - ) - } - return <></> - }, [isDesktop, pal, store, hasNew]) - - return ( - <View testID={testID} style={s.h100pct}> - <Feed - testID={testID ? `${testID}-feed` : undefined} - key="default" - feed={feed} - scrollElRef={scrollElRef} - onPressTryAgain={onPressTryAgain} - onScroll={onMainScroll} - scrollEventThrottle={100} - renderEmptyState={renderEmptyState} - renderEndOfFeed={renderEndOfFeed} - ListHeaderComponent={ListHeaderComponent} - headerOffset={headerOffset} - /> - {(isScrolledDown || hasNew) && ( - <LoadLatestBtn - onPress={onPressLoadLatest} - label="Load new posts" - showIndicator={hasNew} - minimalShellMode={store.shell.minimalShellMode} - /> - )} - <FAB - testID="composeFAB" - onPress={onPressCompose} - icon={<ComposeIcon2 strokeWidth={1.5} size={29} style={s.white} />} - accessibilityRole="button" - accessibilityLabel="New post" - accessibilityHint="" - /> - </View> - ) -}) - -function useHeaderOffset() { +export function useHeaderOffset() { const {isDesktop, isTablet} = useWebMediaQueries() const {fontScale} = useWindowDimensions() if (isDesktop) { |