diff options
Diffstat (limited to 'src/state/queries')
-rw-r--r-- | src/state/queries/actor-autocomplete.ts | 19 | ||||
-rw-r--r-- | src/state/queries/labeler.ts | 89 | ||||
-rw-r--r-- | src/state/queries/notifications/util.ts | 30 | ||||
-rw-r--r-- | src/state/queries/post-feed.ts | 26 | ||||
-rw-r--r-- | src/state/queries/post-liked-by.ts | 4 | ||||
-rw-r--r-- | src/state/queries/preferences/const.ts | 18 | ||||
-rw-r--r-- | src/state/queries/preferences/index.ts | 100 | ||||
-rw-r--r-- | src/state/queries/preferences/moderation.ts | 218 | ||||
-rw-r--r-- | src/state/queries/preferences/types.ts | 33 | ||||
-rw-r--r-- | src/state/queries/preferences/util.ts | 16 | ||||
-rw-r--r-- | src/state/queries/profile-extra-info.ts | 34 | ||||
-rw-r--r-- | src/state/queries/suggested-follows.ts | 3 |
12 files changed, 227 insertions, 363 deletions
diff --git a/src/state/queries/actor-autocomplete.ts b/src/state/queries/actor-autocomplete.ts index 3159ad7aa..f14b3d65f 100644 --- a/src/state/queries/actor-autocomplete.ts +++ b/src/state/queries/actor-autocomplete.ts @@ -6,17 +6,14 @@ import {logger} from '#/logger' import {getAgent} from '#/state/session' import {useMyFollowsQuery} from '#/state/queries/my-follows' import {STALE} from '#/state/queries' -import { - DEFAULT_LOGGED_OUT_PREFERENCES, - getModerationOpts, - useModerationOpts, -} from './preferences' +import {DEFAULT_LOGGED_OUT_PREFERENCES, useModerationOpts} from './preferences' import {isInvalidHandle} from '#/lib/strings/handles' +import {isJustAMute} from '#/lib/moderation' -const DEFAULT_MOD_OPTS = getModerationOpts({ - userDid: '', - preferences: DEFAULT_LOGGED_OUT_PREFERENCES, -}) +const DEFAULT_MOD_OPTS = { + userDid: undefined, + prefs: DEFAULT_LOGGED_OUT_PREFERENCES.moderationPrefs, +} export const RQKEY = (prefix: string) => ['actor-autocomplete', prefix] @@ -114,8 +111,8 @@ function computeSuggestions( } } return items.filter(profile => { - const mod = moderateProfile(profile, moderationOpts) - return !mod.account.filter && mod.account.cause?.type !== 'muted' + const modui = moderateProfile(profile, moderationOpts).ui('profileList') + return !modui.filter || isJustAMute(modui) }) } diff --git a/src/state/queries/labeler.ts b/src/state/queries/labeler.ts new file mode 100644 index 000000000..c405a6b57 --- /dev/null +++ b/src/state/queries/labeler.ts @@ -0,0 +1,89 @@ +import {z} from 'zod' +import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query' +import {AppBskyLabelerDefs} from '@atproto/api' + +import {getAgent} from '#/state/session' +import {preferencesQueryKey} from '#/state/queries/preferences' +import {STALE, PUBLIC_BSKY_AGENT} from '#/state/queries' + +export const labelerInfoQueryKey = (did: string) => ['labeler-info', did] +export const labelersInfoQueryKey = (dids: string[]) => [ + 'labelers-info', + dids.sort(), +] +export const labelersDetailedInfoQueryKey = (dids: string[]) => [ + 'labelers-detailed-info', + dids, +] + +export function useLabelerInfoQuery({ + did, + enabled, +}: { + did?: string + enabled?: boolean +}) { + return useQuery({ + enabled: !!did && enabled !== false, + queryKey: labelerInfoQueryKey(did as string), + queryFn: async () => { + const res = await PUBLIC_BSKY_AGENT.app.bsky.labeler.getServices({ + dids: [did as string], + detailed: true, + }) + return res.data.views[0] as AppBskyLabelerDefs.LabelerViewDetailed + }, + }) +} + +export function useLabelersInfoQuery({dids}: {dids: string[]}) { + return useQuery({ + enabled: !!dids.length, + queryKey: labelersInfoQueryKey(dids), + queryFn: async () => { + const res = await PUBLIC_BSKY_AGENT.app.bsky.labeler.getServices({dids}) + return res.data.views as AppBskyLabelerDefs.LabelerView[] + }, + }) +} + +export function useLabelersDetailedInfoQuery({dids}: {dids: string[]}) { + return useQuery({ + enabled: !!dids.length, + queryKey: labelersDetailedInfoQueryKey(dids), + gcTime: 1000 * 60 * 60 * 6, // 6 hours + staleTime: STALE.MINUTES.ONE, + queryFn: async () => { + const res = await PUBLIC_BSKY_AGENT.app.bsky.labeler.getServices({ + dids, + detailed: true, + }) + return res.data.views as AppBskyLabelerDefs.LabelerViewDetailed[] + }, + }) +} + +export function useLabelerSubscriptionMutation() { + const queryClient = useQueryClient() + + return useMutation({ + async mutationFn({did, subscribe}: {did: string; subscribe: boolean}) { + // TODO + z.object({ + did: z.string(), + subscribe: z.boolean(), + }).parse({did, subscribe}) + + if (subscribe) { + await getAgent().addLabeler(did) + } else { + await getAgent().removeLabeler(did) + } + }, + onSuccess() { + queryClient.invalidateQueries({ + queryKey: preferencesQueryKey, + }) + }, + }) +} diff --git a/src/state/queries/notifications/util.ts b/src/state/queries/notifications/util.ts index 626d3e911..97fc57dc1 100644 --- a/src/state/queries/notifications/util.ts +++ b/src/state/queries/notifications/util.ts @@ -1,14 +1,13 @@ import { AppBskyNotificationListNotifications, ModerationOpts, - moderateProfile, + moderateNotification, AppBskyFeedDefs, AppBskyFeedPost, AppBskyFeedRepost, AppBskyFeedLike, AppBskyEmbedRecord, } from '@atproto/api' -import {moderatePost_wrapped as moderatePost} from '#/lib/moderatePost_wrapped' import chunk from 'lodash.chunk' import {QueryClient} from '@tanstack/react-query' import {getAgent} from '../../session' @@ -88,37 +87,20 @@ export async function fetchPage({ // internal methods // = -// TODO this should be in the sdk as moderateNotification -prf -function shouldFilterNotif( +export function shouldFilterNotif( notif: AppBskyNotificationListNotifications.Notification, moderationOpts: ModerationOpts | undefined, ): boolean { if (!moderationOpts) { return false } - const profile = moderateProfile(notif.author, moderationOpts) - if ( - profile.account.filter || - profile.profile.filter || - notif.author.viewer?.muted - ) { - return true - } - if ( - notif.type === 'reply' || - notif.type === 'quote' || - notif.type === 'mention' - ) { - // NOTE: the notification overlaps the post enough for this to work - const post = moderatePost(notif, moderationOpts) - if (post.content.filter) { - return true - } + if (notif.author.viewer?.following) { + return false } - return false + return moderateNotification(notif, moderationOpts).ui('contentList').filter } -function groupNotifications( +export function groupNotifications( notifs: AppBskyNotificationListNotifications.Notification[], ): FeedNotification[] { const groupedNotifs: FeedNotification[] = [] diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts index c295ffcb0..0e6eef52c 100644 --- a/src/state/queries/post-feed.ts +++ b/src/state/queries/post-feed.ts @@ -3,8 +3,8 @@ import {AppState} from 'react-native' import { AppBskyFeedDefs, AppBskyFeedPost, + ModerationDecision, AtUri, - PostModeration, } from '@atproto/api' import { useInfiniteQuery, @@ -29,7 +29,6 @@ import {STALE} from '#/state/queries' import {precacheFeedPostProfiles} from './profile' import {getAgent} from '#/state/session' import {DEFAULT_LOGGED_OUT_PREFERENCES} from '#/state/queries/preferences/const' -import {getModerationOpts} from '#/state/queries/preferences/moderation' import {KnownError} from '#/view/com/posts/FeedErrorMessage' import {embedViewRecordToPostView, getEmbeddedPost} from './util' import {useModerationOpts} from './preferences' @@ -69,7 +68,7 @@ export interface FeedPostSliceItem { post: AppBskyFeedDefs.PostView record: AppBskyFeedPost.Record reason?: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource - moderation: PostModeration + moderation: ModerationDecision } export interface FeedPostSlice { @@ -250,9 +249,17 @@ export function usePostFeedQuery( // apply moderation filter for (let i = 0; i < slice.items.length; i++) { + const ignoreFilter = + slice.items[i].post.author.did === ignoreFilterFor + if (ignoreFilter) { + // remove mutes to avoid confused UIs + moderations[i].causes = moderations[i].causes.filter( + cause => cause.type !== 'muted', + ) + } if ( - moderations[i]?.content.filter && - slice.items[i].post.author.did !== ignoreFilterFor + !ignoreFilter && + moderations[i]?.ui('contentList').filter ) { return undefined } @@ -435,13 +442,12 @@ function assertSomePostsPassModeration(feed: AppBskyFeedDefs.FeedViewPost[]) { let somePostsPassModeration = false for (const item of feed) { - const moderationOpts = getModerationOpts({ - userDid: '', - preferences: DEFAULT_LOGGED_OUT_PREFERENCES, + const moderation = moderatePost(item.post, { + userDid: undefined, + prefs: DEFAULT_LOGGED_OUT_PREFERENCES.moderationPrefs, }) - const moderation = moderatePost(item.post, moderationOpts) - if (!moderation.content.filter) { + if (!moderation.ui('contentList').filter) { // we have a sfw post somePostsPassModeration = true } diff --git a/src/state/queries/post-liked-by.ts b/src/state/queries/post-liked-by.ts index 2cde07f28..a0498ada4 100644 --- a/src/state/queries/post-liked-by.ts +++ b/src/state/queries/post-liked-by.ts @@ -12,9 +12,9 @@ const PAGE_SIZE = 30 type RQPageParam = string | undefined // TODO refactor invalidate on mutate? -export const RQKEY = (resolvedUri: string) => ['post-liked-by', resolvedUri] +export const RQKEY = (resolvedUri: string) => ['liked-by', resolvedUri] -export function usePostLikedByQuery(resolvedUri: string | undefined) { +export function useLikedByQuery(resolvedUri: string | undefined) { return useInfiniteQuery< AppBskyFeedGetLikes.OutputSchema, Error, diff --git a/src/state/queries/preferences/const.ts b/src/state/queries/preferences/const.ts index 53c9e482a..4cb4d1e96 100644 --- a/src/state/queries/preferences/const.ts +++ b/src/state/queries/preferences/const.ts @@ -29,26 +29,20 @@ export const DEFAULT_PROD_FEEDS = { export const DEFAULT_LOGGED_OUT_PREFERENCES: UsePreferencesQueryResponse = { birthDate: new Date('2022-11-17'), // TODO(pwi) - adultContentEnabled: false, feeds: { saved: [], pinned: [], unpinned: [], }, - // labels are undefined until set by user - contentLabels: { - nsfw: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.nsfw, - nudity: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.nudity, - suggestive: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.suggestive, - gore: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.gore, - hate: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.hate, - spam: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.spam, - impersonation: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES.impersonation, + moderationPrefs: { + adultContentEnabled: false, + labels: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES, + labelers: [], + mutedWords: [], + hiddenPosts: [], }, feedViewPrefs: DEFAULT_HOME_FEED_PREFS, threadViewPrefs: DEFAULT_THREAD_VIEW_PREFS, userAge: 13, // TODO(pwi) interests: {tags: []}, - mutedWords: [], - hiddenPosts: [], } diff --git a/src/state/queries/preferences/index.ts b/src/state/queries/preferences/index.ts index 37ef10ae0..cfc5c5bbe 100644 --- a/src/state/queries/preferences/index.ts +++ b/src/state/queries/preferences/index.ts @@ -1,29 +1,27 @@ -import {useMemo} from 'react' +import {useMemo, createContext, useContext} from 'react' import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query' import { LabelPreference, BskyFeedViewPreference, + ModerationOpts, AppBskyActorDefs, } 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 {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' @@ -44,6 +42,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: { @@ -54,32 +59,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 || {}), @@ -96,25 +75,30 @@ 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, - mutedWords: prefs.data.mutedWords || [], + userDid: currentAccount?.did, + prefs: {...prefs.data.moderationPrefs, hiddenPosts: hiddenPosts || []}, + labelDefs, } - }, [currentAccount?.did, prefs.data, hiddenPosts]) + }, [override, currentAccount, labelDefs, prefs.data, hiddenPosts]) return opts } @@ -138,10 +122,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, diff --git a/src/state/queries/preferences/moderation.ts b/src/state/queries/preferences/moderation.ts index cdae52937..9cd183e8b 100644 --- a/src/state/queries/preferences/moderation.ts +++ b/src/state/queries/preferences/moderation.ts @@ -1,181 +1,53 @@ +import React from 'react' import { - LabelPreference, - ComAtprotoLabelDefs, - ModerationOpts, + DEFAULT_LABEL_SETTINGS, + BskyAgent, + interpretLabelValueDefinitions, } from '@atproto/api' -import { - LabelGroup, - ConfigurableLabelGroup, - UsePreferencesQueryResponse, -} from '#/state/queries/preferences/types' - -export type Label = ComAtprotoLabelDefs.Label - -export type LabelGroupConfig = { - id: LabelGroup - title: string - isAdultImagery?: boolean - subtitle?: string - warning: string - values: string[] -} - -export const DEFAULT_LABEL_PREFERENCES: Record< - ConfigurableLabelGroup, - LabelPreference -> = { - nsfw: 'hide', - nudity: 'warn', - suggestive: 'warn', - gore: 'warn', - hate: 'hide', - spam: 'hide', - impersonation: 'hide', -} +import {usePreferencesQuery} from './index' +import {useLabelersDetailedInfoQuery} from '../labeler' /** * More strict than our default settings for logged in users. - * - * TODO(pwi) */ -export const DEFAULT_LOGGED_OUT_LABEL_PREFERENCES: Record< - ConfigurableLabelGroup, - LabelPreference -> = { - nsfw: 'hide', - nudity: 'hide', - suggestive: 'hide', - gore: 'hide', - hate: 'hide', - spam: 'hide', - impersonation: 'hide', -} - -export const ILLEGAL_LABEL_GROUP: LabelGroupConfig = { - id: 'illegal', - title: 'Illegal Content', - warning: 'Illegal Content', - values: ['csam', 'dmca-violation', 'nudity-nonconsensual'], -} - -export const ALWAYS_FILTER_LABEL_GROUP: LabelGroupConfig = { - id: 'always-filter', - title: 'Content Warning', - warning: 'Content Warning', - values: ['!filter'], -} - -export const ALWAYS_WARN_LABEL_GROUP: LabelGroupConfig = { - id: 'always-warn', - title: 'Content Warning', - warning: 'Content Warning', - values: ['!warn', 'account-security'], -} - -export const UNKNOWN_LABEL_GROUP: LabelGroupConfig = { - id: 'unknown', - title: 'Unknown Label', - warning: 'Content Warning', - values: [], -} - -export const CONFIGURABLE_LABEL_GROUPS: Record< - ConfigurableLabelGroup, - LabelGroupConfig -> = { - nsfw: { - id: 'nsfw', - title: 'Explicit Sexual Images', - subtitle: 'i.e. pornography', - warning: 'Sexually Explicit', - values: ['porn', 'nsfl'], - isAdultImagery: true, - }, - nudity: { - id: 'nudity', - title: 'Other Nudity', - subtitle: 'Including non-sexual and artistic', - warning: 'Nudity', - values: ['nudity'], - isAdultImagery: true, - }, - suggestive: { - id: 'suggestive', - title: 'Sexually Suggestive', - subtitle: 'Does not include nudity', - warning: 'Sexually Suggestive', - values: ['sexual'], - isAdultImagery: true, - }, - gore: { - id: 'gore', - title: 'Violent / Bloody', - subtitle: 'Gore, self-harm, torture', - warning: 'Violence', - values: ['gore', 'self-harm', 'torture', 'nsfl', 'corpse'], - isAdultImagery: true, - }, - hate: { - id: 'hate', - title: 'Hate Group Iconography', - subtitle: 'Images of terror groups, articles covering events, etc.', - warning: 'Hate Groups', - values: ['icon-kkk', 'icon-nazi', 'icon-intolerant', 'behavior-intolerant'], - }, - spam: { - id: 'spam', - title: 'Spam', - subtitle: 'Excessive unwanted interactions', - warning: 'Spam', - values: ['spam'], - }, - impersonation: { - id: 'impersonation', - title: 'Impersonation', - subtitle: 'Accounts falsely claiming to be people or orgs', - warning: 'Impersonation', - values: ['impersonation'], - }, -} - -export function getModerationOpts({ - userDid, - preferences, -}: { - userDid: string - preferences: UsePreferencesQueryResponse -}): ModerationOpts { - return { - userDid: userDid, - adultContentEnabled: preferences.adultContentEnabled, - labels: { - porn: preferences.contentLabels.nsfw, - sexual: preferences.contentLabels.suggestive, - nudity: preferences.contentLabels.nudity, - nsfl: preferences.contentLabels.gore, - corpse: preferences.contentLabels.gore, - gore: preferences.contentLabels.gore, - torture: preferences.contentLabels.gore, - 'self-harm': preferences.contentLabels.gore, - 'intolerant-race': preferences.contentLabels.hate, - 'intolerant-gender': preferences.contentLabels.hate, - 'intolerant-sexual-orientation': preferences.contentLabels.hate, - 'intolerant-religion': preferences.contentLabels.hate, - intolerant: preferences.contentLabels.hate, - 'icon-intolerant': preferences.contentLabels.hate, - spam: preferences.contentLabels.spam, - impersonation: preferences.contentLabels.impersonation, - scam: 'warn', - }, - labelers: [ - { - labeler: { - did: '', - displayName: 'Bluesky Social', - }, - labels: {}, - }, - ], - } +export const DEFAULT_LOGGED_OUT_LABEL_PREFERENCES: typeof DEFAULT_LABEL_SETTINGS = + Object.fromEntries( + Object.entries(DEFAULT_LABEL_SETTINGS).map(([key, _pref]) => [key, 'hide']), + ) + +export function useMyLabelersQuery() { + const prefs = usePreferencesQuery() + const dids = Array.from( + new Set( + BskyAgent.appLabelers.concat( + prefs.data?.moderationPrefs.labelers.map(l => l.did) || [], + ), + ), + ) + const labelers = useLabelersDetailedInfoQuery({dids}) + const isLoading = prefs.isLoading || labelers.isLoading + const error = prefs.error || labelers.error + return React.useMemo(() => { + return { + isLoading, + error, + data: labelers.data, + } + }, [labelers, isLoading, error]) +} + +export function useLabelDefinitionsQuery() { + const labelers = useMyLabelersQuery() + return React.useMemo(() => { + return { + labelDefs: Object.fromEntries( + (labelers.data || []).map(labeler => [ + labeler.creator.did, + interpretLabelValueDefinitions(labeler), + ]), + ), + labelers: labelers.data || [], + } + }, [labelers]) } diff --git a/src/state/queries/preferences/types.ts b/src/state/queries/preferences/types.ts index 45c9eed7d..96da16f1a 100644 --- a/src/state/queries/preferences/types.ts +++ b/src/state/queries/preferences/types.ts @@ -1,46 +1,13 @@ import { BskyPreferences, - LabelPreference, BskyThreadViewPreference, BskyFeedViewPreference, } from '@atproto/api' -export const configurableAdultLabelGroups = [ - 'nsfw', - 'nudity', - 'suggestive', - 'gore', -] as const - -export const configurableOtherLabelGroups = [ - 'hate', - 'spam', - 'impersonation', -] as const - -export const configurableLabelGroups = [ - ...configurableAdultLabelGroups, - ...configurableOtherLabelGroups, -] as const -export type ConfigurableLabelGroup = (typeof configurableLabelGroups)[number] - -export type LabelGroup = - | ConfigurableLabelGroup - | 'illegal' - | 'always-filter' - | 'always-warn' - | 'unknown' - export type UsePreferencesQueryResponse = Omit< BskyPreferences, 'contentLabels' | 'feedViewPrefs' | 'feeds' > & { - /* - * Content labels previously included 'show', which has been deprecated in - * favor of 'ignore'. The API can return legacy data from the database, and - * we clean up the data in `usePreferencesQuery`. - */ - contentLabels: Record<ConfigurableLabelGroup, LabelPreference> feedViewPrefs: BskyFeedViewPreference & { lab_mergeFeedEnabled?: boolean } diff --git a/src/state/queries/preferences/util.ts b/src/state/queries/preferences/util.ts deleted file mode 100644 index 7b8160c28..000000000 --- a/src/state/queries/preferences/util.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {LabelPreference} from '@atproto/api' - -/** - * Content labels previously included 'show', which has been deprecated in - * favor of 'ignore'. The API can return legacy data from the database, and - * we clean up the data in `usePreferencesQuery`. - * - * @deprecated - */ -export function temp__migrateLabelPref( - pref: LabelPreference | 'show', -): LabelPreference { - // @ts-ignore - if (pref === 'show') return 'ignore' - return pref -} diff --git a/src/state/queries/profile-extra-info.ts b/src/state/queries/profile-extra-info.ts deleted file mode 100644 index 8fc32c33e..000000000 --- a/src/state/queries/profile-extra-info.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {useQuery} from '@tanstack/react-query' - -import {getAgent} from '#/state/session' -import {STALE} from '#/state/queries' - -// TODO refactor invalidate on mutate? -export const RQKEY = (did: string) => ['profile-extra-info', did] - -/** - * Fetches some additional information for the profile screen which - * is not available in the API's ProfileView - */ -export function useProfileExtraInfoQuery(did: string) { - return useQuery({ - staleTime: STALE.MINUTES.ONE, - queryKey: RQKEY(did), - async queryFn() { - const [listsRes, feedsRes] = await Promise.all([ - getAgent().app.bsky.graph.getLists({ - actor: did, - limit: 1, - }), - getAgent().app.bsky.feed.getActorFeeds({ - actor: did, - limit: 1, - }), - ]) - return { - hasLists: listsRes.data.lists.length > 0, - hasFeedgens: feedsRes.data.feeds.length > 0, - } - }, - }) -} diff --git a/src/state/queries/suggested-follows.ts b/src/state/queries/suggested-follows.ts index 932226b75..45b3ebb62 100644 --- a/src/state/queries/suggested-follows.ts +++ b/src/state/queries/suggested-follows.ts @@ -46,7 +46,8 @@ export function useSuggestedFollowsQuery() { res.data.actors = res.data.actors .filter( - actor => !moderateProfile(actor, moderationOpts!).account.filter, + actor => + !moderateProfile(actor, moderationOpts!).ui('profileList').filter, ) .filter(actor => { const viewer = actor.viewer |