about summary refs log tree commit diff
path: root/src/view
diff options
context:
space:
mode:
Diffstat (limited to 'src/view')
-rw-r--r--src/view/com/feeds/FeedPage.tsx2
-rw-r--r--src/view/com/posts/Feed.tsx26
-rw-r--r--src/view/screens/ProfileFeed.tsx84
-rw-r--r--src/view/screens/ProfileList.tsx7
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}