about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/state/preferences/feed-tuners.tsx22
-rw-r--r--src/state/queries/post-feed.ts148
-rw-r--r--src/state/queries/post-thread.ts17
3 files changed, 102 insertions, 85 deletions
diff --git a/src/state/preferences/feed-tuners.tsx b/src/state/preferences/feed-tuners.tsx
index 96770055c..c4954d20a 100644
--- a/src/state/preferences/feed-tuners.tsx
+++ b/src/state/preferences/feed-tuners.tsx
@@ -2,9 +2,13 @@ import {useMemo} from 'react'
 import {FeedTuner} from '#/lib/api/feed-manip'
 import {FeedDescriptor} from '../queries/post-feed'
 import {useLanguagePrefs} from './languages'
+import {usePreferencesQuery} from '../queries/preferences'
+import {useSession} from '../session'
 
 export function useFeedTuners(feedDesc: FeedDescriptor) {
   const langPrefs = useLanguagePrefs()
+  const {data: preferences} = usePreferencesQuery()
+  const {currentAccount} = useSession()
 
   return useMemo(() => {
     if (feedDesc.startsWith('feedgen')) {
@@ -19,30 +23,30 @@ export function useFeedTuners(feedDesc: FeedDescriptor) {
     if (feedDesc === 'home' || feedDesc === 'following') {
       const feedTuners = []
 
-      if (false /*TODOthis.homeFeed.hideReposts*/) {
+      if (preferences?.feedViewPrefs.hideReposts) {
         feedTuners.push(FeedTuner.removeReposts)
       } else {
         feedTuners.push(FeedTuner.dedupReposts)
       }
 
-      if (true /*TODOthis.homeFeed.hideReplies*/) {
+      if (preferences?.feedViewPrefs.hideReplies) {
         feedTuners.push(FeedTuner.removeReplies)
-      } /* TODO else {
+      } else {
         feedTuners.push(
           FeedTuner.thresholdRepliesOnly({
-            userDid: this.rootStore.session.data?.did || '',
-            minLikes: this.homeFeed.hideRepliesByLikeCount,
-            followedOnly: !!this.homeFeed.hideRepliesByUnfollowed,
+            userDid: currentAccount?.did || '',
+            minLikes: preferences?.feedViewPrefs.hideRepliesByLikeCount || 0,
+            followedOnly: !!preferences?.feedViewPrefs.hideRepliesByUnfollowed,
           }),
         )
-      }*/
+      }
 
-      if (false /*TODOthis.homeFeed.hideQuotePosts*/) {
+      if (preferences?.feedViewPrefs.hideQuotePosts) {
         feedTuners.push(FeedTuner.removeQuotePosts)
       }
 
       return feedTuners
     }
     return []
-  }, [feedDesc, langPrefs])
+  }, [feedDesc, currentAccount, preferences, langPrefs])
 }
diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts
index 2595e762b..7cf315ef6 100644
--- a/src/state/queries/post-feed.ts
+++ b/src/state/queries/post-feed.ts
@@ -43,9 +43,7 @@ export interface FeedParams {
   mergeFeedSources?: string[]
 }
 
-type RQPageParam =
-  | {cursor: string | undefined; api: FeedAPI; tuner: FeedTuner | NoopFeedTuner}
-  | undefined
+type RQPageParam = {cursor: string | undefined; api: FeedAPI} | undefined
 
 export function RQKEY(feedDesc: FeedDescriptor, params?: FeedParams) {
   return ['post-feed', feedDesc, params || {}]
@@ -66,6 +64,12 @@ export interface FeedPostSlice {
   items: FeedPostSliceItem[]
 }
 
+export interface FeedPageUnselected {
+  api: FeedAPI
+  cursor: string | undefined
+  feed: AppBskyFeedDefs.FeedViewPost[]
+}
+
 export interface FeedPage {
   api: FeedAPI
   tuner: FeedTuner | NoopFeedTuner
@@ -83,30 +87,27 @@ export function usePostFeedQuery(
   const enabled = opts?.enabled !== false
 
   return useInfiniteQuery<
-    FeedPage,
+    FeedPageUnselected,
     Error,
     InfiniteData<FeedPage>,
     QueryKey,
     RQPageParam
   >({
+    enabled,
     staleTime: STALE.INFINITY,
     queryKey: RQKEY(feedDesc, params),
     async queryFn({pageParam}: {pageParam: RQPageParam}) {
       logger.debug('usePostFeedQuery', {feedDesc, pageParam})
 
-      const {api, tuner, cursor} = pageParam
+      const {api, cursor} = pageParam
         ? pageParam
         : {
             api: createApi(feedDesc, params || {}, feedTuners),
-            tuner: params?.disableTuner
-              ? new NoopFeedTuner()
-              : new FeedTuner(feedTuners),
             cursor: undefined,
           }
 
       const res = await api.fetch({cursor, limit: 30})
       precacheResolvedUris(queryClient, res.feed) // precache the handle->did resolution
-      const slices = tuner.tune(res.feed)
 
       /*
        * If this is a public view, we need to check if posts fail moderation.
@@ -115,69 +116,60 @@ export function usePostFeedQuery(
        * some not.
        */
       if (!getAgent().session) {
-        // assume false
-        let somePostsPassModeration = false
-
-        for (const slice of slices) {
-          for (let i = 0; i < slice.items.length; i++) {
-            const item = slice.items[i]
-            const moderationOpts = getModerationOpts({
-              userDid: '',
-              preferences: DEFAULT_LOGGED_OUT_PREFERENCES,
-            })
-            const moderation = moderatePost(item.post, moderationOpts)
-
-            if (!moderation.content.filter) {
-              // we have a sfw post
-              somePostsPassModeration = true
-            }
-          }
-        }
-
-        if (!somePostsPassModeration) {
-          throw new Error(KnownError.FeedNSFPublic)
-        }
+        assertSomePostsPassModeration(res.feed)
       }
 
       return {
         api,
-        tuner,
         cursor: res.cursor,
-        slices: slices.map(slice => ({
-          _reactKey: slice._reactKey,
-          rootUri: slice.rootItem.post.uri,
-          isThread:
-            slice.items.length > 1 &&
-            slice.items.every(
-              item => item.post.author.did === slice.items[0].post.author.did,
-            ),
-          items: slice.items
-            .map((item, i) => {
-              if (
-                AppBskyFeedPost.isRecord(item.post.record) &&
-                AppBskyFeedPost.validateRecord(item.post.record).success
-              ) {
-                return {
-                  _reactKey: `${slice._reactKey}-${i}`,
-                  uri: item.post.uri,
-                  post: item.post,
-                  record: item.post.record,
-                  reason: i === 0 && slice.source ? slice.source : item.reason,
-                }
-              }
-              return undefined
-            })
-            .filter(Boolean) as FeedPostSliceItem[],
-        })),
+        feed: res.feed,
       }
     },
     initialPageParam: undefined,
     getNextPageParam: lastPage => ({
       api: lastPage.api,
-      tuner: lastPage.tuner,
       cursor: lastPage.cursor,
     }),
-    enabled,
+    select(data) {
+      const tuner = params?.disableTuner
+        ? new NoopFeedTuner()
+        : new FeedTuner(feedTuners)
+      return {
+        pageParams: data.pageParams,
+        pages: data.pages.map(page => ({
+          api: page.api,
+          tuner,
+          cursor: page.cursor,
+          slices: tuner.tune(page.feed).map(slice => ({
+            _reactKey: slice._reactKey,
+            rootUri: slice.rootItem.post.uri,
+            isThread:
+              slice.items.length > 1 &&
+              slice.items.every(
+                item => item.post.author.did === slice.items[0].post.author.did,
+              ),
+            items: slice.items
+              .map((item, i) => {
+                if (
+                  AppBskyFeedPost.isRecord(item.post.record) &&
+                  AppBskyFeedPost.validateRecord(item.post.record).success
+                ) {
+                  return {
+                    _reactKey: `${slice._reactKey}-${i}`,
+                    uri: item.post.uri,
+                    post: item.post,
+                    record: item.post.record,
+                    reason:
+                      i === 0 && slice.source ? slice.source : item.reason,
+                  }
+                }
+                return undefined
+              })
+              .filter(Boolean) as FeedPostSliceItem[],
+          })),
+        })),
+      }
+    },
   })
 }
 
@@ -235,8 +227,10 @@ function createApi(
 export function findPostInQueryData(
   queryClient: QueryClient,
   uri: string,
-): FeedPostSliceItem | undefined {
-  const queryDatas = queryClient.getQueriesData<InfiniteData<FeedPage>>({
+): AppBskyFeedDefs.FeedViewPost | undefined {
+  const queryDatas = queryClient.getQueriesData<
+    InfiniteData<FeedPageUnselected>
+  >({
     queryKey: ['post-feed'],
   })
   for (const [_queryKey, queryData] of queryDatas) {
@@ -244,14 +238,34 @@ export function findPostInQueryData(
       continue
     }
     for (const page of queryData?.pages) {
-      for (const slice of page.slices) {
-        for (const item of slice.items) {
-          if (item.uri === uri) {
-            return item
-          }
+      for (const item of page.feed) {
+        if (item.post.uri === uri) {
+          return item
         }
       }
     }
   }
   return undefined
 }
+
+function assertSomePostsPassModeration(feed: AppBskyFeedDefs.FeedViewPost[]) {
+  // assume false
+  let somePostsPassModeration = false
+
+  for (const item of feed) {
+    const moderationOpts = getModerationOpts({
+      userDid: '',
+      preferences: DEFAULT_LOGGED_OUT_PREFERENCES,
+    })
+    const moderation = moderatePost(item.post, moderationOpts)
+
+    if (!moderation.content.filter) {
+      // we have a sfw post
+      somePostsPassModeration = true
+    }
+  }
+
+  if (!somePostsPassModeration) {
+    throw new Error(KnownError.FeedNSFPublic)
+  }
+}
diff --git a/src/state/queries/post-thread.ts b/src/state/queries/post-thread.ts
index c616b05cc..4b586c862 100644
--- a/src/state/queries/post-thread.ts
+++ b/src/state/queries/post-thread.ts
@@ -8,10 +8,7 @@ import {useQuery, useQueryClient, QueryClient} from '@tanstack/react-query'
 import {getAgent} from '#/state/session'
 import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
 import {STALE} from '#/state/queries'
-import {
-  findPostInQueryData as findPostInFeedQueryData,
-  FeedPostSliceItem,
-} from './post-feed'
+import {findPostInQueryData as findPostInFeedQueryData} from './post-feed'
 import {findPostInQueryData as findPostInNotifsQueryData} from './notifications/feed'
 import {precacheThreadPosts as precacheResolvedUris} from './resolve-uri'
 
@@ -93,7 +90,7 @@ export function usePostThreadQuery(uri: string | undefined) {
       {
         const item = findPostInFeedQueryData(queryClient, uri)
         if (item) {
-          return feedItemToPlaceholderThread(item)
+          return feedViewPostToPlaceholderThread(item)
         }
       }
       {
@@ -275,13 +272,15 @@ function threadNodeToPlaceholderThread(
   }
 }
 
-function feedItemToPlaceholderThread(item: FeedPostSliceItem): ThreadNode {
+function feedViewPostToPlaceholderThread(
+  item: AppBskyFeedDefs.FeedViewPost,
+): ThreadNode {
   return {
     type: 'post',
     _reactKey: item.post.uri,
     uri: item.post.uri,
     post: item.post,
-    record: item.record,
+    record: item.post.record as AppBskyFeedPost.Record, // validated in post-feed
     parent: undefined,
     replies: undefined,
     viewer: item.post.viewer,
@@ -291,7 +290,7 @@ function feedItemToPlaceholderThread(item: FeedPostSliceItem): ThreadNode {
       hasMore: false,
       showChildReplyLine: false,
       showParentReplyLine: false,
-      isParentLoading: !!item.record.reply,
+      isParentLoading: !!(item.post.record as AppBskyFeedPost.Record).reply,
       isChildLoading: !!item.post.replyCount,
     },
   }
@@ -305,7 +304,7 @@ function postViewToPlaceholderThread(
     _reactKey: post.uri,
     uri: post.uri,
     post: post,
-    record: post.record as AppBskyFeedPost.Record, // validate in notifs
+    record: post.record as AppBskyFeedPost.Record, // validated in notifs
     parent: undefined,
     replies: undefined,
     viewer: post.viewer,