import { FontAwesomeIcon, FontAwesomeIconStyle, } 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 React from 'react' import {FlatList, View, useWindowDimensions} from 'react-native' import {useStores} from 'state/index' import {Feed} from '../posts/Feed' import {TextLink} from '../util/Link' import {FAB} from '../util/fab/FAB' import {LoadLatestBtn} from '../util/load-latest/LoadLatestBtn' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useSession} from '#/state/session' import {useComposerControls} from '#/state/shell/composer' const POLL_FREQ = 30e3 // 30sec export function FeedPage({ testID, isPageFocused, feed, feedParams, renderEmptyState, renderEndOfFeed, }: { testID?: string feed: FeedDescriptor feedParams?: FeedParams isPageFocused: boolean renderEmptyState: () => JSX.Element renderEndOfFeed?: () => JSX.Element }) { const store = useStores() const {isSandbox} = useSession() const pal = usePalette('default') const {_} = useLingui() const {isDesktop} = useWebMediaQueries() const queryClient = useQueryClient() const {openComposer} = useComposerControls() const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll() const {screen, track} = useAnalytics() const headerOffset = useHeaderOffset() const scrollElRef = React.useRef(null) const isScreenFocused = useIsFocused() const [hasNew, setHasNew] = React.useState(false) const scrollToTop = React.useCallback(() => { scrollElRef.current?.scrollToOffset({offset: -headerOffset}) resetMainScroll() }, [headerOffset, resetMainScroll]) const onSoftReset = React.useCallback(() => { if (isPageFocused) { scrollToTop() queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)}) setHasNew(false) } }, [isPageFocused, scrollToTop, queryClient, feed, setHasNew]) // fires when page within screen is activated/deactivated React.useEffect(() => { if (!isPageFocused || !isScreenFocused) { return } const softResetSub = store.onScreenSoftReset(onSoftReset) screen('Feed') return () => { softResetSub.remove() } }, [store, onSoftReset, screen, feed, isPageFocused, isScreenFocused]) const onPressCompose = React.useCallback(() => { track('HomeScreen:PressCompose') openComposer({}) }, [openComposer, track]) const onPressLoadLatest = React.useCallback(() => { scrollToTop() queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)}) setHasNew(false) }, [scrollToTop, feed, queryClient, setHasNew]) const ListHeaderComponent = React.useCallback(() => { if (isDesktop) { return ( {isSandbox ? 'SANDBOX' : 'Bluesky'}{' '} {hasNew && ( )} } onPress={() => store.emitScreenSoftReset()} /> } /> ) } return <> }, [ isDesktop, pal.view, pal.text, pal.textLight, store, hasNew, _, isSandbox, ]) return ( {(isScrolledDown || hasNew) && ( )} } accessibilityRole="button" accessibilityLabel={_(msg`New post`)} accessibilityHint="" /> ) } 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 }