diff options
Diffstat (limited to 'src/view')
-rw-r--r-- | src/view/com/feeds/FeedPage.tsx | 2 | ||||
-rw-r--r-- | src/view/com/posts/Feed.tsx | 26 | ||||
-rw-r--r-- | src/view/screens/ProfileFeed.tsx | 84 | ||||
-rw-r--r-- | src/view/screens/ProfileList.tsx | 7 |
4 files changed, 44 insertions, 75 deletions
diff --git a/src/view/com/feeds/FeedPage.tsx b/src/view/com/feeds/FeedPage.tsx index 9c92a0dd5..84d49e3b0 100644 --- a/src/view/com/feeds/FeedPage.tsx +++ b/src/view/com/feeds/FeedPage.tsx @@ -29,7 +29,7 @@ import {truncateAndInvalidate} from '#/state/queries/util' import {TabState, getTabState, getRootNavigation} from '#/lib/routes/helpers' import {isNative} from '#/platform/detection' -const POLL_FREQ = 30e3 // 30sec +const POLL_FREQ = 60e3 // 60sec export function FeedPage({ testID, diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx index 9194bb163..8d5c11bda 100644 --- a/src/view/com/posts/Feed.tsx +++ b/src/view/com/posts/Feed.tsx @@ -29,12 +29,16 @@ import { import {isWeb} from '#/platform/detection' import {listenPostCreated} from '#/state/events' import {useSession} from '#/state/session' +import {STALE} from '#/state/queries' const LOADING_ITEM = {_reactKey: '__loading__'} const EMPTY_FEED_ITEM = {_reactKey: '__empty__'} const ERROR_ITEM = {_reactKey: '__error__'} const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'} +const REFRESH_AFTER = STALE.HOURS.ONE +const CHECK_LATEST_AFTER = STALE.SECONDS.THIRTY + let Feed = ({ feed, feedParams, @@ -77,6 +81,7 @@ let Feed = ({ const {currentAccount} = useSession() const [isPTRing, setIsPTRing] = React.useState(false) const checkForNewRef = React.useRef<(() => void) | null>(null) + const lastFetchRef = React.useRef<number>(Date.now()) const opts = React.useMemo( () => ({enabled, ignoreFilterFor}), @@ -94,6 +99,9 @@ let Feed = ({ fetchNextPage, } = usePostFeedQuery(feed, feedParams, opts) const isEmpty = !isFetching && !data?.pages[0]?.slices.length + if (data?.pages[0]) { + lastFetchRef.current = data?.pages[0].fetchedAt + } const checkForNew = React.useCallback(async () => { if (!data?.pages[0] || isFetching || !onHasNew || !enabled) { @@ -133,11 +141,21 @@ let Feed = ({ checkForNewRef.current = checkForNew }, [checkForNew]) React.useEffect(() => { - if (enabled && checkForNewRef.current) { - // check for new on enable (aka on focus) - checkForNewRef.current() + if (enabled) { + const timeSinceFirstLoad = Date.now() - lastFetchRef.current + if (timeSinceFirstLoad > REFRESH_AFTER) { + // do a full refresh + scrollElRef?.current?.scrollToOffset({offset: 0, animated: false}) + queryClient.resetQueries({queryKey: RQKEY(feed)}) + } else if ( + timeSinceFirstLoad > CHECK_LATEST_AFTER && + checkForNewRef.current + ) { + // check for new on enable (aka on focus) + checkForNewRef.current() + } } - }, [enabled]) + }, [enabled, feed, queryClient, scrollElRef]) React.useEffect(() => { let cleanup1: () => void | undefined, cleanup2: () => void | undefined const subscription = AppState.addEventListener('change', nextAppState => { diff --git a/src/view/screens/ProfileFeed.tsx b/src/view/screens/ProfileFeed.tsx index ea92ebab1..061de08f2 100644 --- a/src/view/screens/ProfileFeed.tsx +++ b/src/view/screens/ProfileFeed.tsx @@ -1,7 +1,7 @@ import React, {useMemo, useCallback} from 'react' import {Dimensions, StyleSheet, View, ActivityIndicator} from 'react-native' import {NativeStackScreenProps} from '@react-navigation/native-stack' -import {useNavigation} from '@react-navigation/native' +import {useIsFocused, useNavigation} from '@react-navigation/native' import {useQueryClient} from '@tanstack/react-query' import {usePalette} from 'lib/hooks/usePalette' import {HeartIcon, HeartIconSolid} from 'lib/icons' @@ -42,11 +42,7 @@ import {logger} from '#/logger' import {Trans, msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useModalControls} from '#/state/modals' -import { - useFeedSourceInfoQuery, - FeedSourceFeedInfo, - useIsFeedPublicQuery, -} from '#/state/queries/feed' +import {useFeedSourceInfoQuery, FeedSourceFeedInfo} from '#/state/queries/feed' import {useResolveUriQuery} from '#/state/queries/resolve-uri' import { UsePreferencesQueryResponse, @@ -132,10 +128,8 @@ export function ProfileFeedScreen(props: Props) { function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) { const {data: preferences} = usePreferencesQuery() const {data: info} = useFeedSourceInfoQuery({uri: feedUri}) - const {isLoading: isPublicStatusLoading, data: isPublicResponse} = - useIsFeedPublicQuery({uri: feedUri}) - if (!preferences || !info || isPublicStatusLoading) { + if (!preferences || !info) { return ( <CenteredView> <View style={s.p20}> @@ -149,7 +143,6 @@ function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) { <ProfileFeedScreenInner preferences={preferences} feedInfo={info as FeedSourceFeedInfo} - isPublicResponse={isPublicResponse} /> ) } @@ -157,11 +150,9 @@ function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) { export function ProfileFeedScreenInner({ preferences, feedInfo, - isPublicResponse, }: { preferences: UsePreferencesQueryResponse feedInfo: FeedSourceFeedInfo - isPublicResponse: ReturnType<typeof useIsFeedPublicQuery>['data'] }) { const {_} = useLingui() const pal = usePalette('default') @@ -170,6 +161,7 @@ export function ProfileFeedScreenInner({ const {openComposer} = useComposerControls() const {track} = useAnalytics() const feedSectionRef = React.useRef<SectionRef>(null) + const isScreenFocused = useIsFocused() const { mutateAsync: saveFeed, @@ -205,6 +197,9 @@ export function ProfileFeedScreenInner({ useSetTitle(feedInfo?.displayName) + // event handlers + // + const onToggleSaved = React.useCallback(async () => { try { Haptics.default() @@ -398,21 +393,15 @@ export function ProfileFeedScreenInner({ isHeaderReady={true} renderHeader={renderHeader} onCurrentPageSelected={onCurrentPageSelected}> - {({headerHeight, scrollElRef, isFocused}) => - isPublicResponse?.isPublic ? ( - <FeedSection - ref={feedSectionRef} - feed={`feedgen|${feedInfo.uri}`} - headerHeight={headerHeight} - scrollElRef={scrollElRef as ListRef} - isFocused={isFocused} - /> - ) : ( - <CenteredView sideBorders style={[{paddingTop: headerHeight}]}> - <NonPublicFeedMessage rawError={isPublicResponse?.error} /> - </CenteredView> - ) - } + {({headerHeight, scrollElRef, isFocused}) => ( + <FeedSection + ref={feedSectionRef} + feed={`feedgen|${feedInfo.uri}`} + headerHeight={headerHeight} + scrollElRef={scrollElRef as ListRef} + isFocused={isScreenFocused && isFocused} + /> + )} {({headerHeight, scrollElRef}) => ( <AboutSection feedOwnerDid={feedInfo.creatorDid} @@ -446,45 +435,6 @@ export function ProfileFeedScreenInner({ ) } -function NonPublicFeedMessage({rawError}: {rawError?: Error}) { - const pal = usePalette('default') - - return ( - <View - style={[ - pal.border, - { - padding: 18, - borderTopWidth: 1, - minHeight: Dimensions.get('window').height * 1.5, - }, - ]}> - <View - style={[ - pal.viewLight, - { - padding: 12, - borderRadius: 8, - gap: 12, - }, - ]}> - <Text style={[pal.text]}> - <Trans> - Looks like this feed is only available to users with a Bluesky - account. Please sign up or sign in to view this feed! - </Trans> - </Text> - - {rawError?.message && ( - <Text style={pal.textLight}> - <Trans>Message from server</Trans>: {rawError.message} - </Text> - )} - </View> - </View> - ) -} - interface FeedSectionProps { feed: FeedDescriptor headerHeight: number @@ -519,7 +469,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>( <Feed enabled={isFocused} feed={feed} - pollInterval={30e3} + pollInterval={60e3} scrollElRef={scrollElRef} onHasNew={setHasNew} onScrolledDownChange={setIsScrolledDown} diff --git a/src/view/screens/ProfileList.tsx b/src/view/screens/ProfileList.tsx index 7f922e5b4..2db768cc5 100644 --- a/src/view/screens/ProfileList.tsx +++ b/src/view/screens/ProfileList.tsx @@ -1,6 +1,6 @@ import React, {useCallback, useMemo} from 'react' import {ActivityIndicator, Pressable, StyleSheet, View} from 'react-native' -import {useFocusEffect} from '@react-navigation/native' +import {useFocusEffect, useIsFocused} from '@react-navigation/native' import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' import {useNavigation} from '@react-navigation/native' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' @@ -115,6 +115,7 @@ function ProfileListScreenLoaded({ const aboutSectionRef = React.useRef<SectionRef>(null) const {openModal} = useModalControls() const isCurateList = list.purpose === 'app.bsky.graph.defs#curatelist' + const isScreenFocused = useIsFocused() useSetTitle(list.name) @@ -165,7 +166,7 @@ function ProfileListScreenLoaded({ feed={`list|${uri}`} scrollElRef={scrollElRef as ListRef} headerHeight={headerHeight} - isFocused={isFocused} + isFocused={isScreenFocused && isFocused} /> )} {({headerHeight, scrollElRef}) => ( @@ -623,7 +624,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>( testID="listFeed" enabled={isFocused} feed={feed} - pollInterval={30e3} + pollInterval={60e3} scrollElRef={scrollElRef} onHasNew={setHasNew} onScrolledDownChange={setIsScrolledDown} |