about summary refs log tree commit diff
path: root/src/state/queries/preferences/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/queries/preferences/index.ts')
-rw-r--r--src/state/queries/preferences/index.ts162
1 files changed, 114 insertions, 48 deletions
diff --git a/src/state/queries/preferences/index.ts b/src/state/queries/preferences/index.ts
index 632d31a13..f9cd59cda 100644
--- a/src/state/queries/preferences/index.ts
+++ b/src/state/queries/preferences/index.ts
@@ -1,25 +1,29 @@
-import {useMemo} from 'react'
+import {useMemo, createContext, useContext} from 'react'
 import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query'
-import {LabelPreference, BskyFeedViewPreference} from '@atproto/api'
+import {
+  LabelPreference,
+  BskyFeedViewPreference,
+  ModerationOpts,
+  AppBskyActorDefs,
+  BSKY_LABELER_DID,
+} from '@atproto/api'
 
 import {track} from '#/lib/analytics/analytics'
 import {getAge} from '#/lib/strings/time'
-import {useSession, getAgent} from '#/state/session'
-import {DEFAULT_LABEL_PREFERENCES} from '#/state/queries/preferences/moderation'
+import {getAgent, useSession} from '#/state/session'
 import {
-  ConfigurableLabelGroup,
   UsePreferencesQueryResponse,
   ThreadViewPreferences,
 } from '#/state/queries/preferences/types'
-import {temp__migrateLabelPref} from '#/state/queries/preferences/util'
 import {
   DEFAULT_HOME_FEED_PREFS,
   DEFAULT_THREAD_VIEW_PREFS,
   DEFAULT_LOGGED_OUT_PREFERENCES,
 } from '#/state/queries/preferences/const'
-import {getModerationOpts} from '#/state/queries/preferences/moderation'
+import {DEFAULT_LOGGED_OUT_LABEL_PREFERENCES} from '#/state/queries/preferences/moderation'
 import {STALE} from '#/state/queries'
-import {useHiddenPosts} from '#/state/preferences/hidden-posts'
+import {useHiddenPosts, useLabelDefinitions} from '#/state/preferences'
+import {saveLabelers} from '#/state/session/agent-config'
 
 export * from '#/state/queries/preferences/types'
 export * from '#/state/queries/preferences/moderation'
@@ -40,6 +44,13 @@ export function usePreferencesQuery() {
         return DEFAULT_LOGGED_OUT_PREFERENCES
       } else {
         const res = await agent.getPreferences()
+
+        // save to local storage to ensure there are labels on initial requests
+        saveLabelers(
+          agent.session.did,
+          res.moderationPrefs.labelers.map(l => l.did),
+        )
+
         const preferences: UsePreferencesQueryResponse = {
           ...res,
           feeds: {
@@ -50,32 +61,6 @@ export function usePreferencesQuery() {
                 return !res.feeds.pinned?.includes(f)
               }) || [],
           },
-          // labels are undefined until set by user
-          contentLabels: {
-            nsfw: temp__migrateLabelPref(
-              res.contentLabels?.nsfw || DEFAULT_LABEL_PREFERENCES.nsfw,
-            ),
-            nudity: temp__migrateLabelPref(
-              res.contentLabels?.nudity || DEFAULT_LABEL_PREFERENCES.nudity,
-            ),
-            suggestive: temp__migrateLabelPref(
-              res.contentLabels?.suggestive ||
-                DEFAULT_LABEL_PREFERENCES.suggestive,
-            ),
-            gore: temp__migrateLabelPref(
-              res.contentLabels?.gore || DEFAULT_LABEL_PREFERENCES.gore,
-            ),
-            hate: temp__migrateLabelPref(
-              res.contentLabels?.hate || DEFAULT_LABEL_PREFERENCES.hate,
-            ),
-            spam: temp__migrateLabelPref(
-              res.contentLabels?.spam || DEFAULT_LABEL_PREFERENCES.spam,
-            ),
-            impersonation: temp__migrateLabelPref(
-              res.contentLabels?.impersonation ||
-                DEFAULT_LABEL_PREFERENCES.impersonation,
-            ),
-          },
           feedViewPrefs: {
             ...DEFAULT_HOME_FEED_PREFS,
             ...(res.feedViewPrefs.home || {}),
@@ -92,24 +77,41 @@ export function usePreferencesQuery() {
   })
 }
 
+// used in the moderation state devtool
+export const moderationOptsOverrideContext = createContext<
+  ModerationOpts | undefined
+>(undefined)
+
 export function useModerationOpts() {
+  const override = useContext(moderationOptsOverrideContext)
   const {currentAccount} = useSession()
   const prefs = usePreferencesQuery()
-  const hiddenPosts = useHiddenPosts()
-  const opts = useMemo(() => {
+  const {labelDefs} = useLabelDefinitions()
+  const hiddenPosts = useHiddenPosts() // TODO move this into pds-stored prefs
+  const opts = useMemo<ModerationOpts | undefined>(() => {
+    if (override) {
+      return override
+    }
     if (!prefs.data) {
       return
     }
-    const moderationOpts = getModerationOpts({
-      userDid: currentAccount?.did || '',
-      preferences: prefs.data,
-    })
-
     return {
-      ...moderationOpts,
-      hiddenPosts,
+      userDid: currentAccount?.did,
+      prefs: {
+        ...prefs.data.moderationPrefs,
+        labelers: prefs.data.moderationPrefs.labelers.length
+          ? prefs.data.moderationPrefs.labelers
+          : [
+              {
+                did: BSKY_LABELER_DID,
+                labels: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES,
+              },
+            ],
+        hiddenPosts: hiddenPosts || [],
+      },
+      labelDefs,
     }
-  }, [currentAccount?.did, prefs.data, hiddenPosts])
+  }, [override, currentAccount, labelDefs, prefs.data, hiddenPosts])
   return opts
 }
 
@@ -133,10 +135,32 @@ export function usePreferencesSetContentLabelMutation() {
   return useMutation<
     void,
     unknown,
-    {labelGroup: ConfigurableLabelGroup; visibility: LabelPreference}
+    {label: string; visibility: LabelPreference; labelerDid: string | undefined}
   >({
-    mutationFn: async ({labelGroup, visibility}) => {
-      await getAgent().setContentLabelPref(labelGroup, visibility)
+    mutationFn: async ({label, visibility, labelerDid}) => {
+      await getAgent().setContentLabelPref(label, visibility, labelerDid)
+      // triggers a refetch
+      await queryClient.invalidateQueries({
+        queryKey: preferencesQueryKey,
+      })
+    },
+  })
+}
+
+export function useSetContentLabelMutation() {
+  const queryClient = useQueryClient()
+
+  return useMutation({
+    mutationFn: async ({
+      label,
+      visibility,
+      labelerDid,
+    }: {
+      label: string
+      visibility: LabelPreference
+      labelerDid?: string
+    }) => {
+      await getAgent().setContentLabelPref(label, visibility, labelerDid)
       // triggers a refetch
       await queryClient.invalidateQueries({
         queryKey: preferencesQueryKey,
@@ -164,7 +188,7 @@ export function usePreferencesSetBirthDateMutation() {
 
   return useMutation<void, unknown, {birthDate: Date}>({
     mutationFn: async ({birthDate}: {birthDate: Date}) => {
-      await getAgent().setPersonalDetails({birthDate})
+      await getAgent().setPersonalDetails({birthDate: birthDate.toISOString()})
       // triggers a refetch
       await queryClient.invalidateQueries({
         queryKey: preferencesQueryKey,
@@ -278,3 +302,45 @@ export function useUnpinFeedMutation() {
     },
   })
 }
+
+export function useUpsertMutedWordsMutation() {
+  const queryClient = useQueryClient()
+
+  return useMutation({
+    mutationFn: async (mutedWords: AppBskyActorDefs.MutedWord[]) => {
+      await getAgent().upsertMutedWords(mutedWords)
+      // triggers a refetch
+      await queryClient.invalidateQueries({
+        queryKey: preferencesQueryKey,
+      })
+    },
+  })
+}
+
+export function useUpdateMutedWordMutation() {
+  const queryClient = useQueryClient()
+
+  return useMutation({
+    mutationFn: async (mutedWord: AppBskyActorDefs.MutedWord) => {
+      await getAgent().updateMutedWord(mutedWord)
+      // triggers a refetch
+      await queryClient.invalidateQueries({
+        queryKey: preferencesQueryKey,
+      })
+    },
+  })
+}
+
+export function useRemoveMutedWordMutation() {
+  const queryClient = useQueryClient()
+
+  return useMutation({
+    mutationFn: async (mutedWord: AppBskyActorDefs.MutedWord) => {
+      await getAgent().removeMutedWord(mutedWord)
+      // triggers a refetch
+      await queryClient.invalidateQueries({
+        queryKey: preferencesQueryKey,
+      })
+    },
+  })
+}