migrate the preference read-modify-writes to sdk actions
The preferences hooks, nuxs, labeler subscriptions, list mute/block, post interaction settings, interests and live event preferences move onto @bsky.app/sdk actions. Preference reads and writes route through the pds client because they live on the account's actor store, not behind the appview proxy; the list mute writes stay on the appview client, which is where that graph endpoint lives. BskyAgent.getPreferences configured the agent's labelers as a side effect, so a labeler subscription took effect on the next appview read. The sdk action does not, so the query now calls configureLabelers explicitly. Exported hook signatures, query keys and the usePreferencesQuery response shape are unchanged: the sdk's BskyPreferences is field-for-field identical to the legacy one apart from branded strings, so the response is cast at that single seam and the muted-word and nux mutation inputs stay legacy-typed with a cast into the action.
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import {useEffect} from 'react'
|
||||
import {type Agent, AppBskyActorDefs, asPredicate} from '@atproto/api'
|
||||
import {getPreferences, updateLiveEventPreferences} from '@bsky.app/sdk'
|
||||
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {
|
||||
preferencesQueryKey,
|
||||
usePreferencesQuery,
|
||||
} from '#/state/queries/preferences'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {usePdsClient} from '#/state/session'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import * as env from '#/env'
|
||||
import {IS_WEB} from '#/env'
|
||||
@@ -14,10 +14,11 @@ import {
|
||||
type LiveEventFeed,
|
||||
type LiveEventFeedMetricContext,
|
||||
} from '#/features/liveEvents/types'
|
||||
import {type app} from '#/lexicons'
|
||||
|
||||
export type LiveEventPreferencesAction = Parameters<
|
||||
Agent['updateLiveEventPreferences']
|
||||
>[0] & {
|
||||
typeof updateLiveEventPreferences
|
||||
>[1] & {
|
||||
/**
|
||||
* Flag that is internal to this hook, do not set when updating prefs
|
||||
*/
|
||||
@@ -38,7 +39,7 @@ export function useLiveEventPreferences() {
|
||||
|
||||
function useWebOnlyDebugLiveEventPreferences() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
|
||||
useEffect(() => {
|
||||
if (env.IS_DEV && IS_WEB && typeof window !== 'undefined') {
|
||||
@@ -46,14 +47,14 @@ function useWebOnlyDebugLiveEventPreferences() {
|
||||
window.__updateLiveEventPreferences = async (
|
||||
action: LiveEventPreferencesAction,
|
||||
) => {
|
||||
await agent.updateLiveEventPreferences(action)
|
||||
await pdsClient.call(updateLiveEventPreferences, action)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [agent, queryClient])
|
||||
}, [pdsClient, queryClient])
|
||||
}
|
||||
|
||||
export function useUpdateLiveEventPreferences(props: {
|
||||
@@ -65,10 +66,10 @@ export function useUpdateLiveEventPreferences(props: {
|
||||
}) {
|
||||
const ax = useAnalytics()
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
|
||||
return useMutation<
|
||||
AppBskyActorDefs.LiveEventPreferences,
|
||||
app.bsky.actor.defs.LiveEventPreferences,
|
||||
Error,
|
||||
LiveEventPreferencesAction,
|
||||
{undoAction: LiveEventPreferencesAction | null}
|
||||
@@ -108,10 +109,14 @@ export function useUpdateLiveEventPreferences(props: {
|
||||
}
|
||||
},
|
||||
mutationFn: async action => {
|
||||
const updated = await agent.updateLiveEventPreferences(action)
|
||||
const prefs = updated.find(p =>
|
||||
asPredicate(AppBskyActorDefs.validateLiveEventPreferences)(p),
|
||||
)
|
||||
/*
|
||||
* The SDK action returns void, so after applying the update we read the
|
||||
* fresh, interpreted preferences back to obtain the updated
|
||||
* `liveEventPreferences` (the SDK extracts it from the raw prefs array for
|
||||
* us, replacing the old `asPredicate(...).find(...)` lookup).
|
||||
*/
|
||||
await pdsClient.call(updateLiveEventPreferences, action)
|
||||
const {liveEventPreferences: prefs} = await pdsClient.call(getPreferences)
|
||||
|
||||
switch (action.type) {
|
||||
case 'hideFeed':
|
||||
@@ -138,7 +143,7 @@ export function useUpdateLiveEventPreferences(props: {
|
||||
break
|
||||
}
|
||||
case 'toggleHideAllFeeds': {
|
||||
if (prefs!.hideAllFeeds) {
|
||||
if (prefs.hideAllFeeds) {
|
||||
ax.metric('liveEvents:hideAllFeedBanners', {
|
||||
context: props.metricContext,
|
||||
})
|
||||
@@ -156,7 +161,7 @@ export function useUpdateLiveEventPreferences(props: {
|
||||
queryKey: preferencesQueryKey,
|
||||
})
|
||||
|
||||
return prefs!
|
||||
return prefs
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {useMemo, useState} from 'react'
|
||||
import {type TextStyle, View, type ViewStyle} from 'react-native'
|
||||
import {setInterestsPref} from '@bsky.app/sdk'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
@@ -23,7 +24,7 @@ import {createGetSuggestedUsersForDiscoverQueryKey} from '#/state/queries/trendi
|
||||
import {createGetSuggestedUsersForExploreQueryKey} from '#/state/queries/trending/useGetSuggestedUsersForExploreQuery'
|
||||
import {createGetSuggestedUsersForSeeMoreQueryKey} from '#/state/queries/trending/useGetSuggestedUsersForSeeMoreQuery'
|
||||
import {createSuggestedStarterPacksQueryKey} from '#/state/queries/useSuggestedStarterPacksQuery'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {usePdsClient} from '#/state/session'
|
||||
import {atoms as a, useGutters, useTheme} from '#/alf'
|
||||
import {Admonition} from '#/components/Admonition'
|
||||
import {Divider} from '#/components/Divider'
|
||||
@@ -88,7 +89,7 @@ function Inner({
|
||||
setIsSaving: (isSaving: boolean) => void
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
const qc = useQueryClient()
|
||||
const interestsDisplayNames = useInterestsDisplayNames()
|
||||
const preselectedInterests = useMemo(
|
||||
@@ -110,7 +111,7 @@ function Inner({
|
||||
setIsSaving(true)
|
||||
|
||||
try {
|
||||
await agent.setInterestsPref({tags: interests})
|
||||
await pdsClient.call(setInterestsPref, {tags: interests})
|
||||
qc.setQueriesData(
|
||||
{queryKey: preferencesQueryKey},
|
||||
(old?: UsePreferencesQueryResponse) => {
|
||||
@@ -157,7 +158,7 @@ function Inner({
|
||||
setIsSaving(false)
|
||||
}
|
||||
}, 1500)
|
||||
}, [_, agent, setIsSaving, qc, preselectedInterests])
|
||||
}, [_, pdsClient, setIsSaving, qc, preselectedInterests])
|
||||
|
||||
const onChangeInterests = async (interests: string[]) => {
|
||||
setInterests(interests)
|
||||
|
||||
@@ -2,6 +2,7 @@ import {useState} from 'react'
|
||||
import {Alert, LayoutAnimation, Linking, Pressable, View} from 'react-native'
|
||||
import {useReducedMotion} from 'react-native-reanimated'
|
||||
import {type AppBskyActorDefs, moderateProfile} from '@atproto/api'
|
||||
import {removeNuxs} from '@bsky.app/sdk'
|
||||
import {Trans, useLingui} from '@lingui/react/macro'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||
@@ -21,7 +22,7 @@ import {clearStorage} from '#/state/persisted'
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {useDeleteActorDeclaration} from '#/state/queries/messages/actor-declaration'
|
||||
import {useProfileQuery, useProfilesQuery} from '#/state/queries/profile'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {usePdsClient} from '#/state/session'
|
||||
import {type SessionAccount, useSession, useSessionApi} from '#/state/session'
|
||||
import {useOnboardingDispatch} from '#/state/shell'
|
||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||
@@ -385,7 +386,7 @@ function ProfilePreview({
|
||||
|
||||
function DevOptions() {
|
||||
const {t: l} = useLingui()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
const [override, setOverride] = useStorage(device, [
|
||||
'policyUpdateDebugOverride',
|
||||
])
|
||||
@@ -560,7 +561,7 @@ function DevOptions() {
|
||||
<Button
|
||||
onPress={() => {
|
||||
device.set([PolicyUpdate202508], false)
|
||||
void agent.bskyAppRemoveNuxs([PolicyUpdate202508])
|
||||
void pdsClient.call(removeNuxs, [PolicyUpdate202508])
|
||||
Toast.show(`Done`, {
|
||||
type: 'info',
|
||||
})
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import {type AppBskyLabelerDefs} from '@atproto/api'
|
||||
import {type DidString} from '@atproto/syntax'
|
||||
import {addLabeler, removeLabeler} from '@bsky.app/sdk'
|
||||
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
|
||||
import {z} from 'zod'
|
||||
|
||||
@@ -9,7 +11,7 @@ import {
|
||||
usePreferencesQuery,
|
||||
} from '#/state/queries/preferences'
|
||||
import {createQueryKey} from '#/state/queries/util'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {useAgent, usePdsClient} from '#/state/session'
|
||||
|
||||
const labelerInfoQueryKeyRoot = 'labeler-info'
|
||||
export const labelerInfoQueryKey = (did: string) => [
|
||||
@@ -78,11 +80,13 @@ export function useLabelersDetailedInfoQuery({dids}: {dids: string[]}) {
|
||||
|
||||
export function useRemoveLabelersMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
async mutationFn({dids}: {dids: string[]}) {
|
||||
await Promise.all(dids.map(did => agent.removeLabeler(did)))
|
||||
await Promise.all(
|
||||
dids.map(did => client.call(removeLabeler, did as DidString)),
|
||||
)
|
||||
},
|
||||
async onSuccess() {
|
||||
await queryClient.invalidateQueries({
|
||||
@@ -95,6 +99,7 @@ export function useRemoveLabelersMutation() {
|
||||
export function useLabelerSubscriptionMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
const preferences = usePreferencesQuery()
|
||||
|
||||
return useMutation({
|
||||
@@ -136,7 +141,11 @@ export function useLabelerSubscriptionMutation() {
|
||||
}
|
||||
}
|
||||
if (invalidLabelers.length) {
|
||||
await Promise.all(invalidLabelers.map(did => agent.removeLabeler(did)))
|
||||
await Promise.all(
|
||||
invalidLabelers.map(did =>
|
||||
pdsClient.call(removeLabeler, did as DidString),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
if (subscribe) {
|
||||
@@ -144,9 +153,9 @@ export function useLabelerSubscriptionMutation() {
|
||||
if (labelerCount >= MAX_LABELERS) {
|
||||
throw new Error('MAX_LABELERS')
|
||||
}
|
||||
await agent.addLabeler(did)
|
||||
await pdsClient.call(addLabeler, did as DidString)
|
||||
} else {
|
||||
await agent.removeLabeler(did)
|
||||
await pdsClient.call(removeLabeler, did as DidString)
|
||||
}
|
||||
},
|
||||
async onSuccess() {
|
||||
|
||||
+12
-14
@@ -6,6 +6,12 @@ import {
|
||||
type AtUriString,
|
||||
toDatetimeString,
|
||||
} from '@atproto/syntax'
|
||||
import {
|
||||
blockActorList,
|
||||
muteActorList,
|
||||
unblockActorList,
|
||||
unmuteActorList,
|
||||
} from '@bsky.app/sdk'
|
||||
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
|
||||
import chunk from 'lodash.chunk'
|
||||
|
||||
@@ -13,12 +19,7 @@ import {uploadBlob} from '#/lib/api'
|
||||
import {until} from '#/lib/async/until'
|
||||
import {type ImageMeta} from '#/state/gallery'
|
||||
import {STALE} from '#/state/queries'
|
||||
import {
|
||||
useAgent,
|
||||
useAppviewClient,
|
||||
usePdsClient,
|
||||
useSession,
|
||||
} from '#/state/session'
|
||||
import {useAppviewClient, usePdsClient, useSession} from '#/state/session'
|
||||
import {app, com} from '#/lexicons'
|
||||
import {FEED_INFO_RQKEY_ROOT} from './feed'
|
||||
import {invalidate as invalidateMyLists} from './my-lists'
|
||||
@@ -255,15 +256,13 @@ export function useListDeleteMutation() {
|
||||
|
||||
export function useListMuteMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const appviewClient = useAppviewClient()
|
||||
return useMutation<void, Error, {uri: string; mute: boolean}>({
|
||||
mutationFn: async ({uri, mute}) => {
|
||||
// `muteModList`/`unmuteModList` are preference writes, migrated in wave B
|
||||
if (mute) {
|
||||
await agent.muteModList(uri)
|
||||
await appviewClient.call(muteActorList, {list: uri as AtUriString})
|
||||
} else {
|
||||
await agent.unmuteModList(uri)
|
||||
await appviewClient.call(unmuteActorList, {list: uri as AtUriString})
|
||||
}
|
||||
|
||||
await whenAppViewReady(appviewClient, uri, v => {
|
||||
@@ -280,15 +279,14 @@ export function useListMuteMutation() {
|
||||
|
||||
export function useListBlockMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const appviewClient = useAppviewClient()
|
||||
const pdsClient = usePdsClient()
|
||||
return useMutation<void, Error, {uri: string; block: boolean}>({
|
||||
mutationFn: async ({uri, block}) => {
|
||||
// `blockModList`/`unblockModList` write a block record, migrated in wave B
|
||||
if (block) {
|
||||
await agent.blockModList(uri)
|
||||
await pdsClient.call(blockActorList, {list: uri as AtUriString})
|
||||
} else {
|
||||
await agent.unblockModList(uri)
|
||||
await pdsClient.call(unblockActorList, {list: uri as AtUriString})
|
||||
}
|
||||
|
||||
await whenAppViewReady(appviewClient, uri, v => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {removeNuxs, upsertNux} from '@bsky.app/sdk'
|
||||
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {type AppNux, type Nux} from '#/state/queries/nuxs/definitions'
|
||||
@@ -6,7 +7,8 @@ import {
|
||||
preferencesQueryKey,
|
||||
usePreferencesQuery,
|
||||
} from '#/state/queries/preferences'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {usePdsClient} from '#/state/session'
|
||||
import {type app} from '#/lexicons'
|
||||
|
||||
export {Nux} from '#/state/queries/nuxs/definitions'
|
||||
|
||||
@@ -42,11 +44,11 @@ export function useNuxs():
|
||||
|
||||
// if (__DEV__) {
|
||||
// const queryClient = useQueryClient()
|
||||
// const agent = useAgent()
|
||||
// const pdsClient = usePdsClient()
|
||||
|
||||
// // @ts-ignore
|
||||
// window.clearNux = async (ids: string[]) => {
|
||||
// await agent.bskyAppRemoveNuxs(ids)
|
||||
// await pdsClient.call(removeNuxs, ids)
|
||||
// // triggers a refetch
|
||||
// await queryClient.invalidateQueries({
|
||||
// queryKey: preferencesQueryKey,
|
||||
@@ -97,12 +99,19 @@ export function useNux<T extends Nux>(
|
||||
|
||||
export function useSaveNux() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
retry: 3,
|
||||
mutationFn: async (nux: AppNux) => {
|
||||
await agent.bskyAppUpsertNux(serializeAppNux(nux))
|
||||
/*
|
||||
* `serializeAppNux` still returns the legacy `Nux`, whose strings are
|
||||
* unbranded; it is validated against the same schema the action expects.
|
||||
*/
|
||||
await pdsClient.call(
|
||||
upsertNux,
|
||||
serializeAppNux(nux) as app.bsky.actor.defs.Nux,
|
||||
)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -113,12 +122,12 @@ export function useSaveNux() {
|
||||
|
||||
export function useResetNuxs() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
retry: 3,
|
||||
mutationFn: async (ids: string[]) => {
|
||||
await agent.bskyAppRemoveNuxs(ids)
|
||||
await pdsClient.call(removeNuxs, ids)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import {type AppBskyActorDefs} from '@atproto/api'
|
||||
import {setPostInteractionSettings} from '@bsky.app/sdk'
|
||||
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {preferencesQueryKey} from '#/state/queries/preferences'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {usePdsClient} from '#/state/session'
|
||||
import {type app} from '#/lexicons'
|
||||
|
||||
export function usePostInteractionSettingsMutation({
|
||||
onError,
|
||||
@@ -12,10 +13,10 @@ export function usePostInteractionSettingsMutation({
|
||||
onSettled?: () => void
|
||||
} = {}) {
|
||||
const qc = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
return useMutation({
|
||||
async mutationFn(props: AppBskyActorDefs.PostInteractionSettingsPref) {
|
||||
await agent.setPostInteractionSettings(props)
|
||||
async mutationFn(props: app.bsky.actor.defs.PostInteractionSettingsPref) {
|
||||
await client.call(setPostInteractionSettings, props)
|
||||
},
|
||||
async onSuccess() {
|
||||
await qc.invalidateQueries({
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
import {useCallback} from 'react'
|
||||
import {type AppBskyActorDefs} from '@atproto/api'
|
||||
import {type DidString} from '@atproto/syntax'
|
||||
import {
|
||||
type AppBskyActorDefs,
|
||||
addSavedFeeds,
|
||||
type BskyFeedViewPreference,
|
||||
type LabelPreference,
|
||||
} from '@atproto/api'
|
||||
dismissNudges,
|
||||
getPreferences,
|
||||
overwriteSavedFeeds,
|
||||
queueNudges,
|
||||
removeMutedWord,
|
||||
removeMutedWords,
|
||||
removeSavedFeeds,
|
||||
setActiveProgressGuide,
|
||||
setAdultContentEnabled,
|
||||
setContentLabelPref,
|
||||
setFeedViewPrefs,
|
||||
setIsBetaUser,
|
||||
setThreadViewPrefs,
|
||||
setVerificationPrefs,
|
||||
updateMutedWord,
|
||||
updateSavedFeeds,
|
||||
upsertMutedWords,
|
||||
} from '@bsky.app/sdk'
|
||||
import {type LabelPreference} from '@bsky.app/sdk/moderation'
|
||||
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {PROD_DEFAULT_FEED} from '#/lib/constants'
|
||||
@@ -20,11 +39,12 @@ import {
|
||||
type UsePreferencesQueryResponse,
|
||||
} from '#/state/queries/preferences/types'
|
||||
import {createQueryKey} from '#/state/queries/util'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {useAgent, usePdsClient} from '#/state/session'
|
||||
import {saveLabelers} from '#/state/session/moderation'
|
||||
import {useAgeAssurance} from '#/ageAssurance'
|
||||
import {makeAgeRestrictedModerationPrefs} from '#/ageAssurance/util'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {app} from '#/lexicons'
|
||||
|
||||
export * from '#/state/queries/preferences/const'
|
||||
export * from '#/state/queries/preferences/moderation'
|
||||
@@ -37,6 +57,7 @@ export const preferencesQueryKey = createQueryKey(
|
||||
)
|
||||
|
||||
export function usePreferencesQuery() {
|
||||
const client = usePdsClient()
|
||||
const agent = useAgent()
|
||||
const aa = useAgeAssurance()
|
||||
|
||||
@@ -47,18 +68,34 @@ export function usePreferencesQuery() {
|
||||
queryKey: preferencesQueryKey,
|
||||
gcTime: GCTIME.INFINITY,
|
||||
queryFn: async () => {
|
||||
if (!agent.did) {
|
||||
if (!client.did) {
|
||||
return DEFAULT_LOGGED_OUT_PREFERENCES
|
||||
} else {
|
||||
const res = await agent.getPreferences()
|
||||
const res = await client.call(getPreferences)
|
||||
|
||||
const labelerDids = res.moderationPrefs.labelers.map(l => l.did)
|
||||
|
||||
// save to local storage to ensure there are labels on initial requests
|
||||
saveLabelers(
|
||||
agent.did,
|
||||
res.moderationPrefs.labelers.map(l => l.did),
|
||||
)
|
||||
saveLabelers(client.did, labelerDids)
|
||||
|
||||
const preferences: UsePreferencesQueryResponse = {
|
||||
/*
|
||||
* `BskyAgent.getPreferences` used to call `configureLabelers` itself,
|
||||
* so subscribing to a labeler took effect on the very next appview
|
||||
* read. The sdk action has no such side effect, and appview reads still
|
||||
* inherit `atproto-accept-labelers` from the agent's fetch handler, so
|
||||
* apply the subscriptions there rather than on the wrapping client -
|
||||
* setting them on both would emit the header twice.
|
||||
*/
|
||||
agent.configureLabelers(labelerDids)
|
||||
|
||||
/*
|
||||
* The sdk's `BskyPreferences` is field-for-field identical to the
|
||||
* legacy one that `UsePreferencesQueryResponse` is still derived from;
|
||||
* only its strings are branded (`AtUriString`, `DidString`). Cast at
|
||||
* this one seam so every downstream consumer of the response - notably
|
||||
* the `moderationPrefs` readers - keeps its current types.
|
||||
*/
|
||||
const preferences = {
|
||||
...res,
|
||||
savedFeeds: res.savedFeeds.filter(f => f.type !== 'unknown'),
|
||||
/**
|
||||
@@ -74,7 +111,7 @@ export function usePreferencesQuery() {
|
||||
...(res.threadViewPrefs ?? {}),
|
||||
},
|
||||
userAge: res.birthDate ? getAge(res.birthDate) : undefined,
|
||||
}
|
||||
} as UsePreferencesQueryResponse
|
||||
return preferences
|
||||
}
|
||||
},
|
||||
@@ -113,11 +150,11 @@ export function usePreferencesQuery() {
|
||||
|
||||
export function useClearPreferencesMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async () => {
|
||||
await agent.app.bsky.actor.putPreferences({preferences: []})
|
||||
await client.call(app.bsky.actor.putPreferences, {preferences: []})
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -128,7 +165,7 @@ export function useClearPreferencesMutation() {
|
||||
|
||||
export function usePreferencesSetContentLabelMutation() {
|
||||
const ax = useAnalytics()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation<
|
||||
@@ -137,7 +174,11 @@ export function usePreferencesSetContentLabelMutation() {
|
||||
{label: string; visibility: LabelPreference; labelerDid: string | undefined}
|
||||
>({
|
||||
mutationFn: async ({label, visibility, labelerDid}) => {
|
||||
await agent.setContentLabelPref(label, visibility, labelerDid)
|
||||
await client.call(setContentLabelPref, {
|
||||
key: label,
|
||||
value: visibility,
|
||||
labelerDid: labelerDid as DidString | undefined,
|
||||
})
|
||||
ax.metric('moderation:changeLabelPreference', {preference: visibility})
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
@@ -149,7 +190,7 @@ export function usePreferencesSetContentLabelMutation() {
|
||||
|
||||
export function useSetContentLabelMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({
|
||||
@@ -161,7 +202,11 @@ export function useSetContentLabelMutation() {
|
||||
visibility: LabelPreference
|
||||
labelerDid?: string
|
||||
}) => {
|
||||
await agent.setContentLabelPref(label, visibility, labelerDid)
|
||||
await client.call(setContentLabelPref, {
|
||||
key: label,
|
||||
value: visibility,
|
||||
labelerDid: labelerDid as DidString | undefined,
|
||||
})
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -172,11 +217,11 @@ export function useSetContentLabelMutation() {
|
||||
|
||||
export function usePreferencesSetAdultContentMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation<void, unknown, {enabled: boolean}>({
|
||||
mutationFn: async ({enabled}) => {
|
||||
await agent.setAdultContentEnabled(enabled)
|
||||
await client.call(setAdultContentEnabled, enabled)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -187,7 +232,7 @@ export function usePreferencesSetAdultContentMutation() {
|
||||
|
||||
export function useSetFeedViewPreferencesMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation<void, unknown, Partial<BskyFeedViewPreference>>({
|
||||
mutationFn: async prefs => {
|
||||
@@ -195,7 +240,7 @@ export function useSetFeedViewPreferencesMutation() {
|
||||
* special handling here, merged into `feedViewPrefs` above, since
|
||||
* following was previously called `home`
|
||||
*/
|
||||
await agent.setFeedViewPrefs('home', prefs)
|
||||
await client.call(setFeedViewPrefs, {feed: 'home', ...prefs})
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -212,11 +257,11 @@ export function useSetThreadViewPreferencesMutation({
|
||||
onError?: (error: unknown) => void
|
||||
}) {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation<void, unknown, Partial<ThreadViewPreferences>>({
|
||||
mutationFn: async prefs => {
|
||||
await agent.setThreadViewPrefs(prefs)
|
||||
await client.call(setThreadViewPrefs, prefs)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -229,11 +274,11 @@ export function useSetThreadViewPreferencesMutation({
|
||||
|
||||
export function useOverwriteSavedFeedsMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation<void, unknown, AppBskyActorDefs.SavedFeed[]>({
|
||||
mutationFn: async savedFeeds => {
|
||||
await agent.overwriteSavedFeeds(savedFeeds)
|
||||
await client.call(overwriteSavedFeeds, savedFeeds)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -244,7 +289,7 @@ export function useOverwriteSavedFeedsMutation() {
|
||||
|
||||
export function useAddSavedFeedsMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation<
|
||||
void,
|
||||
@@ -252,7 +297,7 @@ export function useAddSavedFeedsMutation() {
|
||||
Pick<AppBskyActorDefs.SavedFeed, 'type' | 'value' | 'pinned'>[]
|
||||
>({
|
||||
mutationFn: async savedFeeds => {
|
||||
await agent.addSavedFeeds(savedFeeds)
|
||||
await client.call(addSavedFeeds, savedFeeds)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -263,11 +308,11 @@ export function useAddSavedFeedsMutation() {
|
||||
|
||||
export function useRemoveFeedMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation<void, unknown, Pick<AppBskyActorDefs.SavedFeed, 'id'>>({
|
||||
mutationFn: async savedFeed => {
|
||||
await agent.removeSavedFeeds([savedFeed.id])
|
||||
await client.call(removeSavedFeeds, [savedFeed.id])
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -278,7 +323,7 @@ export function useRemoveFeedMutation() {
|
||||
|
||||
export function useReplaceForYouWithDiscoverFeedMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({
|
||||
@@ -289,10 +334,10 @@ export function useReplaceForYouWithDiscoverFeedMutation() {
|
||||
discoverFeedConfig: AppBskyActorDefs.SavedFeed | undefined
|
||||
}) => {
|
||||
if (forYouFeedConfig) {
|
||||
await agent.removeSavedFeeds([forYouFeedConfig.id])
|
||||
await client.call(removeSavedFeeds, [forYouFeedConfig.id])
|
||||
}
|
||||
if (!discoverFeedConfig) {
|
||||
await agent.addSavedFeeds([
|
||||
await client.call(addSavedFeeds, [
|
||||
{
|
||||
type: 'feed',
|
||||
value: PROD_DEFAULT_FEED('whats-hot'),
|
||||
@@ -300,7 +345,7 @@ export function useReplaceForYouWithDiscoverFeedMutation() {
|
||||
},
|
||||
])
|
||||
} else {
|
||||
await agent.updateSavedFeeds([
|
||||
await client.call(updateSavedFeeds, [
|
||||
{
|
||||
...discoverFeedConfig,
|
||||
pinned: true,
|
||||
@@ -317,11 +362,11 @@ export function useReplaceForYouWithDiscoverFeedMutation() {
|
||||
|
||||
export function useUpdateSavedFeedsMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation<void, unknown, AppBskyActorDefs.SavedFeed[]>({
|
||||
mutationFn: async feeds => {
|
||||
await agent.updateSavedFeeds(feeds)
|
||||
await client.call(updateSavedFeeds, feeds)
|
||||
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
@@ -333,11 +378,14 @@ export function useUpdateSavedFeedsMutation() {
|
||||
|
||||
export function useUpsertMutedWordsMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (mutedWords: AppBskyActorDefs.MutedWord[]) => {
|
||||
await agent.upsertMutedWords(mutedWords)
|
||||
await client.call(
|
||||
upsertMutedWords,
|
||||
mutedWords as app.bsky.actor.defs.MutedWord[],
|
||||
)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -348,11 +396,14 @@ export function useUpsertMutedWordsMutation() {
|
||||
|
||||
export function useUpdateMutedWordMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (mutedWord: AppBskyActorDefs.MutedWord) => {
|
||||
await agent.updateMutedWord(mutedWord)
|
||||
await client.call(
|
||||
updateMutedWord,
|
||||
mutedWord as app.bsky.actor.defs.MutedWord,
|
||||
)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -363,11 +414,14 @@ export function useUpdateMutedWordMutation() {
|
||||
|
||||
export function useRemoveMutedWordMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (mutedWord: AppBskyActorDefs.MutedWord) => {
|
||||
await agent.removeMutedWord(mutedWord)
|
||||
await client.call(
|
||||
removeMutedWord,
|
||||
mutedWord as app.bsky.actor.defs.MutedWord,
|
||||
)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -378,11 +432,14 @@ export function useRemoveMutedWordMutation() {
|
||||
|
||||
export function useRemoveMutedWordsMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (mutedWords: AppBskyActorDefs.MutedWord[]) => {
|
||||
await agent.removeMutedWords(mutedWords)
|
||||
await client.call(
|
||||
removeMutedWords,
|
||||
mutedWords as app.bsky.actor.defs.MutedWord[],
|
||||
)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -393,11 +450,11 @@ export function useRemoveMutedWordsMutation() {
|
||||
|
||||
export function useQueueNudgesMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (nudges: string | string[]) => {
|
||||
await agent.bskyAppQueueNudges(nudges)
|
||||
await client.call(queueNudges, Array.isArray(nudges) ? nudges : [nudges])
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -408,11 +465,14 @@ export function useQueueNudgesMutation() {
|
||||
|
||||
export function useDismissNudgesMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (nudges: string | string[]) => {
|
||||
await agent.bskyAppDismissNudges(nudges)
|
||||
await client.call(
|
||||
dismissNudges,
|
||||
Array.isArray(nudges) ? nudges : [nudges],
|
||||
)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -423,13 +483,13 @@ export function useDismissNudgesMutation() {
|
||||
|
||||
export function useSetActiveProgressGuideMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (
|
||||
guide: AppBskyActorDefs.BskyAppProgressGuide | undefined,
|
||||
) => {
|
||||
await agent.bskyAppSetActiveProgressGuide(guide)
|
||||
await client.call(setActiveProgressGuide, guide)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -440,11 +500,11 @@ export function useSetActiveProgressGuideMutation() {
|
||||
|
||||
export function useSetIsBetaUserMutation() {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (isBetaUser: boolean) => {
|
||||
await agent.setIsBetaUser(isBetaUser)
|
||||
await client.call(setIsBetaUser, isBetaUser)
|
||||
// triggers a refetch
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: preferencesQueryKey,
|
||||
@@ -456,11 +516,11 @@ export function useSetIsBetaUserMutation() {
|
||||
export function useSetVerificationPrefsMutation() {
|
||||
const ax = useAnalytics()
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
const client = usePdsClient()
|
||||
|
||||
return useMutation<void, unknown, AppBskyActorDefs.VerificationPrefs>({
|
||||
mutationFn: async prefs => {
|
||||
await agent.setVerificationPrefs(prefs)
|
||||
await client.call(setVerificationPrefs, prefs)
|
||||
if (prefs.hideBadges) {
|
||||
ax.metric('verification:settings:hideBadges', {})
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user