diff --git a/src/state/birthdate.ts b/src/state/birthdate.ts index c405febe4e..8146836190 100644 --- a/src/state/birthdate.ts +++ b/src/state/birthdate.ts @@ -1,9 +1,10 @@ import {useMemo} from 'react' +import {setPersonalDetails} from '@bsky.app/sdk' import {useMutation, useQueryClient} from '@tanstack/react-query' import {restrictChatSettings} from '#/state/queries/messages/restrictChatSettings' import {preferencesQueryKey} from '#/state/queries/preferences' -import {useAgent, usePdsClient, useSession} from '#/state/session' +import {usePdsClient, useSession} from '#/state/session' import {usePatchAgeAssuranceOtherRequiredData} from '#/ageAssurance' import {isUnderAge} from '#/ageAssurance/util' import {IS_DEV} from '#/env' @@ -54,14 +55,14 @@ export function useIsBirthdateUpdateAllowed() { export function useBirthdateMutation() { const queryClient = useQueryClient() - const agent = useAgent() + const {currentAccount} = useSession() const pdsClient = usePdsClient() const patchOtherRequiredData = usePatchAgeAssuranceOtherRequiredData() return useMutation({ mutationFn: async ({birthDate}: {birthDate: Date}) => { const bday = birthDate.toISOString() - await agent.setPersonalDetails({birthDate: bday}) + await pdsClient.call(setPersonalDetails, {birthDate}) // triggers a refetch await queryClient.invalidateQueries({ queryKey: preferencesQueryKey, @@ -80,7 +81,9 @@ export function useBirthdateMutation() { * birthdate, which may change the user's age assurance access level. */ void patchOtherRequiredData({birthdate: bday}) - snoozeBirthdateUpdateAllowedForDid(agent.sessionManager.did!) + if (currentAccount) { + snoozeBirthdateUpdateAllowedForDid(currentAccount.did) + } }, }) } diff --git a/src/state/queries/like.ts b/src/state/queries/like.ts index fa40300a40..2f626cc428 100644 --- a/src/state/queries/like.ts +++ b/src/state/queries/like.ts @@ -1,22 +1,27 @@ +import {type AtUriString} from '@atproto/syntax' +import {deleteLike, like} from '@bsky.app/sdk' import {useMutation} from '@tanstack/react-query' -import {useAgent} from '#/state/session' +import {usePdsClient} from '#/state/session' export function useLikeMutation() { - const agent = useAgent() + const pdsClient = usePdsClient() return useMutation({ mutationFn: async ({uri, cid}: {uri: string; cid: string}) => { - const res = await agent.like(uri, cid) + const res = await pdsClient.call(like, { + uri: uri as AtUriString, + cid, + }) return {uri: res.uri} }, }) } export function useUnlikeMutation() { - const agent = useAgent() + const pdsClient = usePdsClient() return useMutation({ mutationFn: async ({uri}: {uri: string}) => { - await agent.deleteLike(uri) + await pdsClient.call(deleteLike, uri as AtUriString) }, }) } diff --git a/src/state/queries/pinned-post.ts b/src/state/queries/pinned-post.ts index d132127e68..cd3d0cb4a3 100644 --- a/src/state/queries/pinned-post.ts +++ b/src/state/queries/pinned-post.ts @@ -6,7 +6,7 @@ import {useMutation, useQueryClient} from '@tanstack/react-query' import {logger} from '#/logger' import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed' import * as Toast from '#/components/Toast' -import {app} from '#/lexicons' +import {app, type com} from '#/lexicons' import {updatePostShadow} from '../cache/post-shadow' import {useAppviewClient, useSession} from '../session' import {useProfileUpdateMutation} from './profile' @@ -47,7 +47,11 @@ export function usePinnedPostMutation() { profile, updates: existing => { existing.pinnedPost = pinCurrentPost - ? {uri: postUri, cid: postCid} + ? // the caller's uri/cid are unbranded strings + ({ + uri: postUri, + cid: postCid, + } as com.atproto.repo.strongRef.Main) : undefined return existing }, diff --git a/src/state/queries/post.ts b/src/state/queries/post.ts index 79df51d1bf..fd6ba752de 100644 --- a/src/state/queries/post.ts +++ b/src/state/queries/post.ts @@ -1,5 +1,7 @@ import {useCallback} from 'react' import {type AppBskyActorDefs, type AppBskyFeedDefs, AtUri} from '@atproto/api' +import {type AtUriString} from '@atproto/syntax' +import {deleteLike, deletePost, deleteRepost, like, repost} from '@bsky.app/sdk' import { type QueryClient, useMutation, @@ -10,10 +12,16 @@ import { import {useToggleMutationQueue} from '#/lib/hooks/useToggleMutationQueue' import {updatePostShadow} from '#/state/cache/post-shadow' import {type Shadow} from '#/state/cache/types' -import {useAgent, useSession} from '#/state/session' +import { + useAgent, + useAppviewClient, + usePdsClient, + useSession, +} from '#/state/session' import * as userActionHistory from '#/state/userActionHistory' import {useAnalytics} from '#/analytics' import {type Metrics, toClout} from '#/analytics/metrics' +import {app} from '#/lexicons' import {useIsThreadMuted, useSetThreadMute} from '../cache/thread-mutes' import {findProfileQueryData} from './profile' @@ -184,7 +192,7 @@ function usePostLikeMutation( const {currentAccount} = useSession() const queryClient = useQueryClient() const postAuthor = post.author - const agent = useAgent() + const pdsClient = usePdsClient() const ax = useAnalytics() return useMutation< {uri: string}, // responds with the uri of the like @@ -215,7 +223,11 @@ function usePostLikeMutation( : undefined, feedDescriptor: feedDescriptor, }) - return agent.like(uri, cid, via) + return pdsClient.call(like, { + uri: uri as AtUriString, + cid: cid, + via: via ? {uri: via.uri as AtUriString, cid: via.cid} : undefined, + }) }, }) } @@ -225,7 +237,7 @@ function usePostUnlikeMutation( logContext: Metrics['post:unlike']['logContext'], post: Shadow, ) { - const agent = useAgent() + const pdsClient = usePdsClient() const ax = useAnalytics() return useMutation({ mutationFn: ({postUri, likeUri}) => { @@ -235,7 +247,7 @@ function usePostUnlikeMutation( logContext, feedDescriptor, }) - return agent.deleteLike(likeUri) + return pdsClient.call(deleteLike, likeUri as AtUriString) }, }) } @@ -309,7 +321,7 @@ function usePostRepostMutation( logContext: Metrics['post:repost']['logContext'], post: Shadow, ) { - const agent = useAgent() + const pdsClient = usePdsClient() const ax = useAnalytics() return useMutation< {uri: string}, // responds with the uri of the repost @@ -323,7 +335,11 @@ function usePostRepostMutation( logContext, feedDescriptor, }) - return agent.repost(uri, cid, via) + return pdsClient.call(repost, { + uri: uri as AtUriString, + cid: cid, + via: via ? {uri: via.uri as AtUriString, cid: via.cid} : undefined, + }) }, }) } @@ -333,7 +349,7 @@ function usePostUnrepostMutation( logContext: Metrics['post:unrepost']['logContext'], post: Shadow, ) { - const agent = useAgent() + const pdsClient = usePdsClient() const ax = useAnalytics() return useMutation({ mutationFn: ({postUri, repostUri}) => { @@ -343,17 +359,17 @@ function usePostUnrepostMutation( logContext, feedDescriptor, }) - return agent.deleteRepost(repostUri) + return pdsClient.call(deleteRepost, repostUri as AtUriString) }, }) } export function usePostDeleteMutation() { const queryClient = useQueryClient() - const agent = useAgent() + const pdsClient = usePdsClient() return useMutation({ mutationFn: async ({uri}) => { - await agent.deletePost(uri) + await pdsClient.call(deletePost, uri as AtUriString) }, onSuccess(_, variables) { updatePostShadow(queryClient, variables.uri, {isDeleted: true}) @@ -407,23 +423,29 @@ export function useThreadMuteMutationQueue( } function useThreadMuteMutation() { - const agent = useAgent() + const appviewClient = useAppviewClient() return useMutation< {}, Error, {uri: string} // the root post's uri >({ - mutationFn: ({uri}) => { - return agent.api.app.bsky.graph.muteThread({root: uri}) + mutationFn: async ({uri}) => { + await appviewClient.call(app.bsky.graph.muteThread, { + root: uri as AtUriString, + }) + return {} }, }) } function useThreadUnmuteMutation() { - const agent = useAgent() + const appviewClient = useAppviewClient() return useMutation<{}, Error, {uri: string}>({ - mutationFn: ({uri}) => { - return agent.api.app.bsky.graph.unmuteThread({root: uri}) + mutationFn: async ({uri}) => { + await appviewClient.call(app.bsky.graph.unmuteThread, { + root: uri as AtUriString, + }) + return {} }, }) } diff --git a/src/state/queries/profile.ts b/src/state/queries/profile.ts index ae5d4b1ad6..bb3eda52f5 100644 --- a/src/state/queries/profile.ts +++ b/src/state/queries/profile.ts @@ -3,17 +3,24 @@ import { type AppBskyActorDefs, type AppBskyActorGetProfile, type AppBskyActorGetProfiles, - type AppBskyActorProfile, type AppBskyGraphGetFollows, - type AtpAgent, AtUri, type Un$Typed, } from '@atproto/api' +import {type Client} from '@atproto/lex' import { type AtIdentifierString, + type AtUriString, type DidString, toDatetimeString, } from '@atproto/syntax' +import { + deleteFollow, + follow, + muteActor, + unmuteActor, + upsertProfile, +} from '@bsky.app/sdk' import { type InfiniteData, keepPreviousData, @@ -24,7 +31,6 @@ import { } from '@tanstack/react-query' import {uploadBlob} from '#/lib/api' -import {toLegacyBlobRef} from '#/lib/api/legacy-blob' import {until} from '#/lib/async/until' import {useToggleMutationQueue} from '#/lib/hooks/useToggleMutationQueue' import {updateProfileShadow} from '#/state/cache/profile-shadow' @@ -38,7 +44,7 @@ import { useUnstableProfileViewCache, } from '#/state/queries/unstable-profile-cache' import {useUpdateProfileVerificationCache} from '#/state/queries/verification/useUpdateProfileVerificationCache' -import {useAgent, usePdsClient, useSession} from '#/state/session' +import {useAppviewClient, usePdsClient, useSession} from '#/state/session' import * as userActionHistory from '#/state/userActionHistory' import {useAnalytics} from '#/analytics' import {type Metrics, toClout} from '#/analytics/metrics' @@ -74,7 +80,7 @@ export function useProfileQuery({ did: string | undefined staleTime?: number }) { - const agent = useAgent() + const client = useAppviewClient() const {getUnstableProfile} = useUnstableProfileViewCache() return useQuery({ // WARNING @@ -85,8 +91,9 @@ export function useProfileQuery({ refetchOnWindowFocus: true, queryKey: RQKEY(did ?? ''), queryFn: async () => { - const res = await agent.getProfile({actor: did ?? ''}) - return res.data + return await client.call(app.bsky.actor.getProfile, { + actor: (did ?? '') as AtIdentifierString, + }) }, placeholderData: () => { if (!did) return @@ -103,21 +110,22 @@ export function useProfilesQuery({ handles: string[] maintainData?: boolean }) { - const agent = useAgent() + const client = useAppviewClient() return useQuery({ enabled: handles.length > 0, staleTime: STALE.MINUTES.FIVE, queryKey: profilesQueryKey(handles), queryFn: async () => { - const res = await agent.getProfiles({actors: handles}) - return res.data + return await client.call(app.bsky.actor.getProfiles, { + actors: handles as AtIdentifierString[], + }) }, placeholderData: maintainData ? keepPreviousData : undefined, }) } export function usePrefetchProfileQuery() { - const agent = useAgent() + const client = useAppviewClient() const queryClient = useQueryClient() const prefetchProfileQuery = useCallback( async (did: string) => { @@ -125,12 +133,13 @@ export function usePrefetchProfileQuery() { staleTime: STALE.SECONDS.THIRTY, queryKey: RQKEY(did), queryFn: async () => { - const res = await agent.getProfile({actor: did || ''}) - return res.data + return await client.call(app.bsky.actor.getProfile, { + actor: (did || '') as AtIdentifierString, + }) }, }) }, - [queryClient, agent], + [queryClient, client], ) return prefetchProfileQuery } @@ -138,18 +147,18 @@ export function usePrefetchProfileQuery() { interface ProfileUpdateParams { profile: AppBskyActorDefs.ProfileViewDetailed updates: - | Un$Typed + | Un$Typed | (( - existing: Un$Typed, - ) => Un$Typed) + existing: Un$Typed, + ) => Un$Typed) newUserAvatar?: ImageMeta | undefined | null newUserBanner?: ImageMeta | undefined | null checkCommitted?: (res: AppBskyActorGetProfile.Response) => boolean } export function useProfileUpdateMutation() { const queryClient = useQueryClient() - const agent = useAgent() const pdsClient = usePdsClient() + const appviewClient = useAppviewClient() const updateProfileVerificationCache = useUpdateProfileVerificationCache() return useMutation({ mutationFn: async ({ @@ -175,8 +184,8 @@ export function useProfileUpdateMutation() { newUserBanner.mime, ) } - await agent.upsertProfile(async existing => { - let next: Un$Typed = existing || {} + await pdsClient.call(upsertProfile, async existing => { + let next: Un$Typed = existing || {} if (typeof updates === 'function') { next = updates(next) } else { @@ -188,20 +197,20 @@ export function useProfileUpdateMutation() { } if (newUserAvatarPromise) { const res = await newUserAvatarPromise - next.avatar = toLegacyBlobRef(res.blob) + next.avatar = res.blob } else if (newUserAvatar === null) { next.avatar = undefined } if (newUserBannerPromise) { const res = await newUserBannerPromise - next.banner = toLegacyBlobRef(res.blob) + next.banner = res.blob } else if (newUserBanner === null) { next.banner = undefined } return next }) await whenAppViewReady( - agent, + appviewClient, profile.did, checkCommitted || (res => { @@ -252,7 +261,7 @@ export function useProfileFollowMutationQueue( position?: number, contextProfileDid?: string, ) { - const agent = useAgent() + const client = useAppviewClient() const queryClient = useQueryClient() const {currentAccount} = useSession() const did = profile.did @@ -333,12 +342,12 @@ export function useProfileFollowMutationQueue( } if (finalFollowingUri) { - void agent.app.bsky.graph - .getSuggestedFollowsByActor({ - actor: did, + void client + .call(app.bsky.graph.getSuggestedFollowsByActor, { + actor: did as AtIdentifierString, }) .then(res => { - const dids = res.data.suggestions + const dids = res.suggestions .filter(a => !a.viewer?.following) .map(a => a.did) .slice(0, 8) @@ -375,7 +384,7 @@ function useProfileFollowMutation( ) { const ax = useAnalytics() const {currentAccount} = useSession() - const agent = useAgent() + const pdsClient = usePdsClient() const queryClient = useQueryClient() const {captureAction} = useProgressGuideControls() @@ -400,7 +409,7 @@ function useProfileFollowMutation( position, contextProfileDid, }) - return await agent.follow(did) + return await pdsClient.call(follow, {did: did as DidString}) }, }) } @@ -409,11 +418,11 @@ function useProfileUnfollowMutation( logContext: Metrics['profile:unfollow']['logContext'], ) { const ax = useAnalytics() - const agent = useAgent() + const pdsClient = usePdsClient() return useMutation({ mutationFn: async ({followUri}) => { ax.metric('profile:unfollow', {logContext}) - return await agent.deleteFollow(followUri) + return await pdsClient.call(deleteFollow, followUri as AtUriString) }, }) } @@ -536,10 +545,10 @@ export function useProfileMuteRepostsMutationQueue( function useProfileMuteMutation() { const queryClient = useQueryClient() - const agent = useAgent() + const appviewClient = useAppviewClient() return useMutation({ mutationFn: async ({did}) => { - await agent.mute(did) + await appviewClient.call(muteActor, {actor: did as AtIdentifierString}) }, onSuccess() { void queryClient.invalidateQueries({queryKey: RQKEY_MY_MUTED()}) @@ -562,10 +571,10 @@ function useProfileMuteRepostsMutation() { function useProfileUnmuteMutation() { const queryClient = useQueryClient() - const agent = useAgent() + const appviewClient = useAppviewClient() return useMutation({ mutationFn: async ({did}) => { - await agent.unmute(did) + await appviewClient.call(unmuteActor, {actor: did as AtIdentifierString}) }, onSuccess() { void queryClient.invalidateQueries({queryKey: RQKEY_MY_MUTED()}) @@ -679,7 +688,7 @@ function useProfileUnblockMutation() { } async function whenAppViewReady( - agent: AtpAgent, + client: Client, actor: string, fn: (res: AppBskyActorGetProfile.Response) => boolean, ) { @@ -687,7 +696,17 @@ async function whenAppViewReady( 5, // 5 tries 1e3, // 1s delay between tries fn, - () => agent.app.bsky.actor.getProfile({actor}), + /* + * `checkCommitted` callbacks are still written against the legacy + * `Response` envelope, so wrap the lex output until those consumers move. + */ + async () => ({ + success: true, + headers: {}, + data: await client.call(app.bsky.actor.getProfile, { + actor: actor as AtIdentifierString, + }), + }), ) }