about summary refs log tree commit diff
path: root/src/state
diff options
context:
space:
mode:
Diffstat (limited to 'src/state')
-rw-r--r--src/state/queries/feed.ts53
-rw-r--r--src/state/queries/profile-feedgens.ts22
-rw-r--r--src/state/queries/profile-lists.ts37
3 files changed, 80 insertions, 32 deletions
diff --git a/src/state/queries/feed.ts b/src/state/queries/feed.ts
index 36555c181..2b6751e89 100644
--- a/src/state/queries/feed.ts
+++ b/src/state/queries/feed.ts
@@ -5,6 +5,7 @@ import {
   AppBskyGraphDefs,
   AppBskyUnspeccedGetPopularFeedGenerators,
   AtUri,
+  moderateFeedGenerator,
   RichText,
 } from '@atproto/api'
 import {
@@ -26,6 +27,7 @@ import {RQKEY as listQueryKey} from '#/state/queries/list'
 import {usePreferencesQuery} from '#/state/queries/preferences'
 import {useAgent, useSession} from '#/state/session'
 import {router} from '#/routes'
+import {useModerationOpts} from '../preferences/moderation-opts'
 import {FeedDescriptor} from './post-feed'
 import {precacheResolvedUri} from './resolve-uri'
 
@@ -207,14 +209,16 @@ export function useGetPopularFeedsQuery(options?: GetPopularFeedsOptions) {
   const limit = options?.limit || 10
   const {data: preferences} = usePreferencesQuery()
   const queryClient = useQueryClient()
+  const moderationOpts = useModerationOpts()
 
   // Make sure this doesn't invalidate unless really needed.
   const selectArgs = useMemo(
     () => ({
       hasSession,
       savedFeeds: preferences?.savedFeeds || [],
+      moderationOpts,
     }),
-    [hasSession, preferences?.savedFeeds],
+    [hasSession, preferences?.savedFeeds, moderationOpts],
   )
   const lastPageCountRef = useRef(0)
 
@@ -225,6 +229,7 @@ export function useGetPopularFeedsQuery(options?: GetPopularFeedsOptions) {
     QueryKey,
     string | undefined
   >({
+    enabled: Boolean(moderationOpts),
     queryKey: createGetPopularFeedsQueryKey(options),
     queryFn: async ({pageParam}) => {
       const res = await agent.app.bsky.unspecced.getPopularFeedGenerators({
@@ -246,7 +251,11 @@ export function useGetPopularFeedsQuery(options?: GetPopularFeedsOptions) {
       (
         data: InfiniteData<AppBskyUnspeccedGetPopularFeedGenerators.OutputSchema>,
       ) => {
-        const {savedFeeds, hasSession: hasSessionInner} = selectArgs
+        const {
+          savedFeeds,
+          hasSession: hasSessionInner,
+          moderationOpts,
+        } = selectArgs
         return {
           ...data,
           pages: data.pages.map(page => {
@@ -264,7 +273,8 @@ export function useGetPopularFeedsQuery(options?: GetPopularFeedsOptions) {
                     return f.value === feed.uri
                   }),
                 )
-                return !alreadySaved
+                const decision = moderateFeedGenerator(feed, moderationOpts!)
+                return !alreadySaved && !decision.ui('contentList').filter
               }),
             }
           }),
@@ -304,6 +314,8 @@ export function useGetPopularFeedsQuery(options?: GetPopularFeedsOptions) {
 
 export function useSearchPopularFeedsMutation() {
   const agent = useAgent()
+  const moderationOpts = useModerationOpts()
+
   return useMutation({
     mutationFn: async (query: string) => {
       const res = await agent.app.bsky.unspecced.getPopularFeedGenerators({
@@ -311,24 +323,15 @@ export function useSearchPopularFeedsMutation() {
         query: query,
       })
 
-      return res.data.feeds
-    },
-  })
-}
-
-export function useSearchPopularFeedsQuery({q}: {q: string}) {
-  const agent = useAgent()
-  return useQuery({
-    queryKey: ['searchPopularFeeds', q],
-    queryFn: async () => {
-      const res = await agent.app.bsky.unspecced.getPopularFeedGenerators({
-        limit: 15,
-        query: q,
-      })
+      if (moderationOpts) {
+        return res.data.feeds.filter(feed => {
+          const decision = moderateFeedGenerator(feed, moderationOpts)
+          return !decision.ui('contentList').filter
+        })
+      }
 
       return res.data.feeds
     },
-    placeholderData: keepPreviousData,
   })
 }
 
@@ -346,17 +349,27 @@ export function usePopularFeedsSearch({
   enabled?: boolean
 }) {
   const agent = useAgent()
+  const moderationOpts = useModerationOpts()
+  const enabledInner = enabled ?? Boolean(moderationOpts)
+
   return useQuery({
-    enabled,
+    enabled: enabledInner,
     queryKey: createPopularFeedsSearchQueryKey(query),
     queryFn: async () => {
       const res = await agent.app.bsky.unspecced.getPopularFeedGenerators({
-        limit: 10,
+        limit: 15,
         query: query,
       })
 
       return res.data.feeds
     },
+    placeholderData: keepPreviousData,
+    select(data) {
+      return data.filter(feed => {
+        const decision = moderateFeedGenerator(feed, moderationOpts!)
+        return !decision.ui('contentList').filter
+      })
+    },
   })
 }
 
diff --git a/src/state/queries/profile-feedgens.ts b/src/state/queries/profile-feedgens.ts
index 8ad12ab61..b50a2a289 100644
--- a/src/state/queries/profile-feedgens.ts
+++ b/src/state/queries/profile-feedgens.ts
@@ -1,7 +1,8 @@
-import {AppBskyFeedGetActorFeeds} from '@atproto/api'
+import {AppBskyFeedGetActorFeeds, moderateFeedGenerator} from '@atproto/api'
 import {InfiniteData, QueryKey, useInfiniteQuery} from '@tanstack/react-query'
 
 import {useAgent} from '#/state/session'
+import {useModerationOpts} from '../preferences/moderation-opts'
 
 const PAGE_SIZE = 50
 type RQPageParam = string | undefined
@@ -14,7 +15,8 @@ export function useProfileFeedgensQuery(
   did: string,
   opts?: {enabled?: boolean},
 ) {
-  const enabled = opts?.enabled !== false
+  const moderationOpts = useModerationOpts()
+  const enabled = opts?.enabled !== false && Boolean(moderationOpts)
   const agent = useAgent()
   return useInfiniteQuery<
     AppBskyFeedGetActorFeeds.OutputSchema,
@@ -38,5 +40,21 @@ export function useProfileFeedgensQuery(
     initialPageParam: undefined,
     getNextPageParam: lastPage => lastPage.cursor,
     enabled,
+    select(data) {
+      return {
+        ...data,
+        pages: data.pages.map(page => {
+          return {
+            ...page,
+            feeds: page.feeds
+              // filter by labels
+              .filter(list => {
+                const decision = moderateFeedGenerator(list, moderationOpts!)
+                return !decision.ui('contentList').filter
+              }),
+          }
+        }),
+      }
+    },
   })
 }
diff --git a/src/state/queries/profile-lists.ts b/src/state/queries/profile-lists.ts
index 112a62c83..75e3dd6e4 100644
--- a/src/state/queries/profile-lists.ts
+++ b/src/state/queries/profile-lists.ts
@@ -1,7 +1,8 @@
-import {AppBskyGraphGetLists} from '@atproto/api'
+import {AppBskyGraphGetLists, moderateUserList} from '@atproto/api'
 import {InfiniteData, QueryKey, useInfiniteQuery} from '@tanstack/react-query'
 
 import {useAgent} from '#/state/session'
+import {useModerationOpts} from '../preferences/moderation-opts'
 
 const PAGE_SIZE = 30
 type RQPageParam = string | undefined
@@ -10,7 +11,8 @@ const RQKEY_ROOT = 'profile-lists'
 export const RQKEY = (did: string) => [RQKEY_ROOT, did]
 
 export function useProfileListsQuery(did: string, opts?: {enabled?: boolean}) {
-  const enabled = opts?.enabled !== false
+  const moderationOpts = useModerationOpts()
+  const enabled = opts?.enabled !== false && Boolean(moderationOpts)
   const agent = useAgent()
   return useInfiniteQuery<
     AppBskyGraphGetLists.OutputSchema,
@@ -27,17 +29,32 @@ export function useProfileListsQuery(did: string, opts?: {enabled?: boolean}) {
         cursor: pageParam,
       })
 
-      // Starter packs use a reference list, which we do not want to show on profiles. At some point we could probably
-      // just filter this out on the backend instead of in the client.
-      return {
-        ...res.data,
-        lists: res.data.lists.filter(
-          l => l.purpose !== 'app.bsky.graph.defs#referencelist',
-        ),
-      }
+      return res.data
     },
     initialPageParam: undefined,
     getNextPageParam: lastPage => lastPage.cursor,
     enabled,
+    select(data) {
+      return {
+        ...data,
+        pages: data.pages.map(page => {
+          return {
+            ...page,
+            lists: page.lists
+              /*
+               * Starter packs use a reference list, which we do not want to
+               * show on profiles. At some point we could probably just filter
+               * this out on the backend instead of in the client.
+               */
+              .filter(l => l.purpose !== 'app.bsky.graph.defs#referencelist')
+              // filter by labels
+              .filter(list => {
+                const decision = moderateUserList(list, moderationOpts!)
+                return !decision.ui('contentList').filter
+              }),
+          }
+        }),
+      }
+    },
   })
 }