about summary refs log tree commit diff
path: root/src/view/screens
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/screens')
-rw-r--r--src/view/screens/Home.tsx48
-rw-r--r--src/view/screens/Profile.tsx1
-rw-r--r--src/view/screens/ProfileFeed.tsx25
-rw-r--r--src/view/screens/ProfileList.tsx45
4 files changed, 55 insertions, 64 deletions
diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx
index d6603a936..53813f822 100644
--- a/src/view/screens/Home.tsx
+++ b/src/view/screens/Home.tsx
@@ -1,10 +1,9 @@
 import React from 'react'
-import {useWindowDimensions} from 'react-native'
 import {useFocusEffect} from '@react-navigation/native'
 import {observer} from 'mobx-react-lite'
 import isEqual from 'lodash.isequal'
 import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types'
-import {PostsFeedModel} from 'state/models/feeds/posts'
+import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
 import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState'
 import {FollowingEndOfFeed} from 'view/com/posts/FollowingEndOfFeed'
@@ -12,12 +11,9 @@ import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState'
 import {FeedsTabBar} from '../com/pager/FeedsTabBar'
 import {Pager, PagerRef, RenderTabBarFnProps} from 'view/com/pager/Pager'
 import {useStores} from 'state/index'
-import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
 import {FeedPage} from 'view/com/feeds/FeedPage'
 import {useSetMinimalShellMode, useSetDrawerSwipeDisabled} from '#/state/shell'
 
-export const POLL_FREQ = 30e3 // 30sec
-
 type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'>
 export const HomeScreen = withAuthRequired(
   observer(function HomeScreenImpl({}: Props) {
@@ -26,7 +22,7 @@ export const HomeScreen = withAuthRequired(
     const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
     const pagerRef = React.useRef<PagerRef>(null)
     const [selectedPage, setSelectedPage] = React.useState(0)
-    const [customFeeds, setCustomFeeds] = React.useState<PostsFeedModel[]>([])
+    const [customFeeds, setCustomFeeds] = React.useState<FeedDescriptor[]>([])
     const [requestedCustomFeeds, setRequestedCustomFeeds] = React.useState<
       string[]
     >([])
@@ -39,14 +35,12 @@ export const HomeScreen = withAuthRequired(
         return
       }
 
-      const feeds = []
+      const feeds: FeedDescriptor[] = []
       for (const uri of pinned) {
         if (uri.includes('app.bsky.feed.generator')) {
-          const model = new PostsFeedModel(store, 'custom', {feed: uri})
-          feeds.push(model)
+          feeds.push(`feedgen|${uri}`)
         } else if (uri.includes('app.bsky.graph.list')) {
-          const model = new PostsFeedModel(store, 'list', {list: uri})
-          feeds.push(model)
+          feeds.push(`list|${uri}`)
         }
       }
       pagerRef.current?.setPage(0)
@@ -62,6 +56,19 @@ export const HomeScreen = withAuthRequired(
       setRequestedCustomFeeds,
     ])
 
+    const homeFeedParams = React.useMemo<FeedParams>(() => {
+      if (!store.preferences.homeFeed.lab_mergeFeedEnabled) {
+        return {}
+      }
+      return {
+        mergeFeedEnabled: true,
+        mergeFeedSources: store.preferences.savedFeeds,
+      }
+    }, [
+      store.preferences.homeFeed.lab_mergeFeedEnabled,
+      store.preferences.savedFeeds,
+    ])
+
     useFocusEffect(
       React.useCallback(() => {
         setMinimalShellMode(false)
@@ -129,14 +136,15 @@ export const HomeScreen = withAuthRequired(
           key="1"
           testID="followingFeedPage"
           isPageFocused={selectedPage === 0}
-          feed={store.me.mainFeed}
+          feed="home"
+          feedParams={homeFeedParams}
           renderEmptyState={renderFollowingEmptyState}
           renderEndOfFeed={FollowingEndOfFeed}
         />
         {customFeeds.map((f, index) => {
           return (
             <FeedPage
-              key={f.reactKey}
+              key={f}
               testID="customFeedPage"
               isPageFocused={selectedPage === 1 + index}
               feed={f}
@@ -148,17 +156,3 @@ export const HomeScreen = withAuthRequired(
     )
   }),
 )
-
-export 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
-}
diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx
index f2aa7f05d..945a8cc20 100644
--- a/src/view/screens/Profile.tsx
+++ b/src/view/screens/Profile.tsx
@@ -9,7 +9,6 @@ import {CenteredView} from '../com/util/Views'
 import {ScreenHider} from 'view/com/util/moderation/ScreenHider'
 import {ProfileUiModel, Sections} from 'state/models/ui/profile'
 import {useStores} from 'state/index'
-import {PostsFeedSliceModel} from 'state/models/feeds/posts-slice'
 import {ProfileHeader} from '../com/profile/ProfileHeader'
 import {FeedSlice} from '../com/posts/FeedSlice'
 import {ListCard} from 'view/com/lists/ListCard'
diff --git a/src/view/screens/ProfileFeed.tsx b/src/view/screens/ProfileFeed.tsx
index 116979568..4c56b6674 100644
--- a/src/view/screens/ProfileFeed.tsx
+++ b/src/view/screens/ProfileFeed.tsx
@@ -8,6 +8,7 @@ import {
 } from 'react-native'
 import {NativeStackScreenProps} from '@react-navigation/native-stack'
 import {useNavigation} from '@react-navigation/native'
+import {useQueryClient} from '@tanstack/react-query'
 import {usePalette} from 'lib/hooks/usePalette'
 import {HeartIcon, HeartIconSolid} from 'lib/icons'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
@@ -17,7 +18,7 @@ import {colors, s} from 'lib/styles'
 import {observer} from 'mobx-react-lite'
 import {useStores} from 'state/index'
 import {FeedSourceModel} from 'state/models/content/feed-source'
-import {PostsFeedModel} from 'state/models/feeds/posts'
+import {FeedDescriptor} from '#/state/queries/post-feed'
 import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {PagerWithHeader} from 'view/com/pager/PagerWithHeader'
 import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader'
@@ -32,6 +33,7 @@ import {EmptyState} from 'view/com/util/EmptyState'
 import * as Toast from 'view/com/util/Toast'
 import {useSetTitle} from 'lib/hooks/useSetTitle'
 import {useCustomFeed} from 'lib/hooks/useCustomFeed'
+import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed'
 import {OnScrollHandler} from 'lib/hooks/useOnMainScroll'
 import {shareUrl} from 'lib/sharing'
 import {toShareUrl} from 'lib/strings/url-helpers'
@@ -154,13 +156,6 @@ export const ProfileFeedScreenInner = observer(
       [rkey, feedOwnerDid],
     )
     const feedInfo = useCustomFeed(uri)
-    const feed: PostsFeedModel = useMemo(() => {
-      const model = new PostsFeedModel(store, 'custom', {
-        feed: uri,
-      })
-      model.setup()
-      return model
-    }, [store, uri])
     const isPinned = store.preferences.isPinnedFeed(uri)
     useSetTitle(feedInfo?.displayName)
 
@@ -352,7 +347,7 @@ export const ProfileFeedScreenInner = observer(
           {({onScroll, headerHeight, isScrolledDown, scrollElRef}) => (
             <FeedSection
               ref={feedSectionRef}
-              feed={feed}
+              feed={`feedgen|${uri}`}
               onScroll={onScroll}
               headerHeight={headerHeight}
               isScrolledDown={isScrolledDown}
@@ -395,7 +390,7 @@ export const ProfileFeedScreenInner = observer(
 )
 
 interface FeedSectionProps {
-  feed: PostsFeedModel
+  feed: FeedDescriptor
   onScroll: OnScrollHandler
   headerHeight: number
   isScrolledDown: boolean
@@ -406,12 +401,14 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
     {feed, onScroll, headerHeight, isScrolledDown, scrollElRef},
     ref,
   ) {
-    const hasNew = feed.hasNewLatest && !feed.isRefreshing
+    const [hasNew, setHasNew] = React.useState(false)
+    const queryClient = useQueryClient()
 
     const onScrollToTop = useCallback(() => {
       scrollElRef.current?.scrollToOffset({offset: -headerHeight})
-      feed.refresh()
-    }, [feed, scrollElRef, headerHeight])
+      queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)})
+      setHasNew(false)
+    }, [scrollElRef, headerHeight, queryClient, feed, setHasNew])
 
     React.useImperativeHandle(ref, () => ({
       scrollToTop: onScrollToTop,
@@ -425,7 +422,9 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
       <View>
         <Feed
           feed={feed}
+          pollInterval={30e3}
           scrollElRef={scrollElRef}
+          onHasNew={setHasNew}
           onScroll={onScroll}
           scrollEventThrottle={5}
           renderEmptyState={renderPostsEmpty}
diff --git a/src/view/screens/ProfileList.tsx b/src/view/screens/ProfileList.tsx
index 9180d21d5..03c1703c1 100644
--- a/src/view/screens/ProfileList.tsx
+++ b/src/view/screens/ProfileList.tsx
@@ -12,6 +12,7 @@ import {useNavigation} from '@react-navigation/native'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {observer} from 'mobx-react-lite'
 import {RichText as RichTextAPI} from '@atproto/api'
+import {useQueryClient} from '@tanstack/react-query'
 import {withAuthRequired} from 'view/com/auth/withAuthRequired'
 import {PagerWithHeader} from 'view/com/pager/PagerWithHeader'
 import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader'
@@ -28,11 +29,12 @@ import {LoadLatestBtn} from 'view/com/util/load-latest/LoadLatestBtn'
 import {FAB} from 'view/com/util/fab/FAB'
 import {Haptics} from 'lib/haptics'
 import {ListModel} from 'state/models/content/list'
-import {PostsFeedModel} from 'state/models/feeds/posts'
+import {FeedDescriptor} from '#/state/queries/post-feed'
 import {useStores} from 'state/index'
 import {usePalette} from 'lib/hooks/usePalette'
 import {useSetTitle} from 'lib/hooks/useSetTitle'
 import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
+import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed'
 import {OnScrollHandler} from 'lib/hooks/useOnMainScroll'
 import {NavigationProp} from 'lib/routes/types'
 import {toShareUrl} from 'lib/strings/url-helpers'
@@ -109,34 +111,25 @@ export const ProfileListScreenInner = observer(
   }: Props & {listOwnerDid: string}) {
     const store = useStores()
     const {_} = useLingui()
+    const queryClient = useQueryClient()
     const setMinimalShellMode = useSetMinimalShellMode()
     const {rkey} = route.params
+    const listUri = `at://${listOwnerDid}/app.bsky.graph.list/${rkey}`
     const feedSectionRef = React.useRef<SectionRef>(null)
     const aboutSectionRef = React.useRef<SectionRef>(null)
     const {openModal} = useModalControls()
 
     const list: ListModel = useMemo(() => {
-      const model = new ListModel(
-        store,
-        `at://${listOwnerDid}/app.bsky.graph.list/${rkey}`,
-      )
+      const model = new ListModel(store, listUri)
       return model
-    }, [store, listOwnerDid, rkey])
-    const feed = useMemo(
-      () => new PostsFeedModel(store, 'list', {list: list.uri}),
-      [store, list],
-    )
+    }, [store, listUri])
     useSetTitle(list.data?.name)
 
     useFocusEffect(
       useCallback(() => {
         setMinimalShellMode(false)
-        list.loadMore(true).then(() => {
-          if (list.isCuratelist) {
-            feed.setup()
-          }
-        })
-      }, [setMinimalShellMode, list, feed]),
+        list.loadMore(true)
+      }, [setMinimalShellMode, list]),
     )
 
     const onPressAddUser = useCallback(() => {
@@ -145,11 +138,13 @@ export const ProfileListScreenInner = observer(
         list,
         onAdd() {
           if (list.isCuratelist) {
-            feed.refresh()
+            queryClient.invalidateQueries({
+              queryKey: FEED_RQKEY(`list|${listUri}`),
+            })
           }
         },
       })
-    }, [openModal, list, feed])
+    }, [openModal, list, queryClient, listUri])
 
     const onCurrentPageSelected = React.useCallback(
       (index: number) => {
@@ -178,10 +173,10 @@ export const ProfileListScreenInner = observer(
             {({onScroll, headerHeight, isScrolledDown, scrollElRef}) => (
               <FeedSection
                 ref={feedSectionRef}
+                feed={`list|${listUri}`}
                 scrollElRef={
                   scrollElRef as React.MutableRefObject<FlatList<any> | null>
                 }
-                feed={feed}
                 onScroll={onScroll}
                 headerHeight={headerHeight}
                 isScrolledDown={isScrolledDown}
@@ -562,7 +557,7 @@ const Header = observer(function HeaderImpl({
 })
 
 interface FeedSectionProps {
-  feed: PostsFeedModel
+  feed: FeedDescriptor
   onScroll: OnScrollHandler
   headerHeight: number
   isScrolledDown: boolean
@@ -573,12 +568,14 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
     {feed, scrollElRef, onScroll, headerHeight, isScrolledDown},
     ref,
   ) {
-    const hasNew = feed.hasNewLatest && !feed.isRefreshing
+    const queryClient = useQueryClient()
+    const [hasNew, setHasNew] = React.useState(false)
 
     const onScrollToTop = useCallback(() => {
       scrollElRef.current?.scrollToOffset({offset: -headerHeight})
-      feed.refresh()
-    }, [feed, scrollElRef, headerHeight])
+      queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)})
+      setHasNew(false)
+    }, [scrollElRef, headerHeight, queryClient, feed, setHasNew])
     React.useImperativeHandle(ref, () => ({
       scrollToTop: onScrollToTop,
     }))
@@ -592,7 +589,9 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
         <Feed
           testID="listFeed"
           feed={feed}
+          pollInterval={30e3}
           scrollElRef={scrollElRef}
+          onHasNew={setHasNew}
           onScroll={onScroll}
           scrollEventThrottle={1}
           renderEmptyState={renderPostsEmpty}