phase 4: migrate account flows, trending queries, notifications, and report subjects off the bridge
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import {useCallback, useEffect, useState} from 'react'
|
||||
import {type ListRenderItemInfo, View} from 'react-native'
|
||||
import * as Contacts from 'expo-contacts'
|
||||
import {type DidString} from '@atproto/syntax'
|
||||
import {type ModerationOpts} from '@bsky.app/sdk/moderation'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
@@ -28,12 +29,7 @@ import {
|
||||
useContactsMatchesQuery,
|
||||
useContactsSyncStatusQuery,
|
||||
} from '#/state/queries/find-contacts'
|
||||
import {
|
||||
useAgent,
|
||||
useAppviewClient,
|
||||
usePdsClient,
|
||||
useSession,
|
||||
} from '#/state/session'
|
||||
import {useAppviewClient, usePdsClient, useSession} from '#/state/session'
|
||||
import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
|
||||
import {List} from '#/view/com/util/List'
|
||||
import {atoms as a, tokens, useGutters, useTheme} from '#/alf'
|
||||
@@ -196,7 +192,7 @@ function SyncStatus({
|
||||
refetchStatus: () => Promise<any>
|
||||
}) {
|
||||
const ax = useAnalytics()
|
||||
const agent = useAgent()
|
||||
const appviewClient = useAppviewClient()
|
||||
const queryClient = useQueryClient()
|
||||
const {_} = useLingui()
|
||||
const moderationOpts = useModerationOpts()
|
||||
@@ -221,7 +217,9 @@ function SyncStatus({
|
||||
|
||||
const {mutate: dismissMatch} = useMutation({
|
||||
mutationFn: async (did: string) => {
|
||||
await agent.app.bsky.contact.dismissMatch({subject: did})
|
||||
await appviewClient.call(app.bsky.contact.dismissMatch, {
|
||||
subject: did as DidString,
|
||||
})
|
||||
},
|
||||
onMutate: async (did: string) => {
|
||||
ax.metric('contacts:settings:dismiss', {})
|
||||
@@ -493,12 +491,12 @@ function StatusFooter({syncedAt}: {syncedAt: string}) {
|
||||
const {_, i18n} = useLingui()
|
||||
const t = useTheme()
|
||||
const ax = useAnalytics()
|
||||
const agent = useAgent()
|
||||
const appviewClient = useAppviewClient()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const {mutate: removeData, isPending} = useMutation({
|
||||
mutationFn: async () => {
|
||||
await agent.app.bsky.contact.removeData({})
|
||||
await appviewClient.call(app.bsky.contact.removeData, {})
|
||||
},
|
||||
onMutate: () => ax.metric('contacts:settings:removeData', {}),
|
||||
onSuccess: () => {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {useState} from 'react'
|
||||
import {Alert, LayoutAnimation, Linking, Pressable, View} from 'react-native'
|
||||
import {useReducedMotion} from 'react-native-reanimated'
|
||||
import {removeNuxs} from '@bsky.app/sdk'
|
||||
import {moderateProfile} from '@bsky.app/sdk/moderation'
|
||||
import {Trans, useLingui} from '@lingui/react/macro'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
@@ -21,8 +22,12 @@ 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 {type SessionAccount, useSession, useSessionApi} from '#/state/session'
|
||||
import {
|
||||
type SessionAccount,
|
||||
usePdsClient,
|
||||
useSession,
|
||||
useSessionApi,
|
||||
} from '#/state/session'
|
||||
import {useOnboardingDispatch} from '#/state/shell'
|
||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||
import {useCloseAllActiveElements} from '#/state/util'
|
||||
@@ -386,7 +391,7 @@ function ProfilePreview({
|
||||
|
||||
function DevOptions() {
|
||||
const {t: l} = useLingui()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
const [override, setOverride] = useStorage(device, [
|
||||
'policyUpdateDebugOverride',
|
||||
])
|
||||
@@ -561,7 +566,7 @@ function DevOptions() {
|
||||
<Button
|
||||
onPress={() => {
|
||||
device.set([PolicyUpdate202508], false)
|
||||
void agent.bskyAppRemoveNuxs([PolicyUpdate202508])
|
||||
void pdsClient.call(removeNuxs, [PolicyUpdate202508])
|
||||
Toast.show(`Done`, {
|
||||
type: 'info',
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@ import {useFetchDid, useUpdateHandleMutation} from '#/state/queries/handle'
|
||||
import {RQKEY as RQKEY_PROFILE} from '#/state/queries/profile'
|
||||
import {useServiceQuery} from '#/state/queries/service'
|
||||
import {useCurrentAccountProfile} from '#/state/queries/useCurrentAccountProfile'
|
||||
import {useAgent, useSession} from '#/state/session'
|
||||
import {useSession, useSessionApi} from '#/state/session'
|
||||
import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
|
||||
import {atoms as a, native, useBreakpoints, useTheme} from '#/alf'
|
||||
import {Admonition} from '#/components/Admonition'
|
||||
@@ -63,12 +63,12 @@ export function ChangeHandleDialog({
|
||||
function ChangeHandleDialogInner() {
|
||||
const control = Dialog.useDialogContext()
|
||||
const {_} = useLingui()
|
||||
const agent = useAgent()
|
||||
const {currentAccount} = useSession()
|
||||
const {
|
||||
data: serviceInfo,
|
||||
error: serviceInfoError,
|
||||
refetch,
|
||||
} = useServiceQuery(agent.serviceUrl.toString())
|
||||
} = useServiceQuery(currentAccount?.service ?? '')
|
||||
|
||||
const [page, setPage] = useState<'provided-handle' | 'own-handle'>(
|
||||
'provided-handle',
|
||||
@@ -152,7 +152,7 @@ function ProvidedHandlePage({
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const [subdomain, setSubdomain] = useState('')
|
||||
const agent = useAgent()
|
||||
const {refreshSession} = useSessionApi()
|
||||
const control = Dialog.useDialogContext()
|
||||
const {currentAccount} = useSession()
|
||||
const queryClient = useQueryClient()
|
||||
@@ -173,7 +173,7 @@ function ProvidedHandlePage({
|
||||
queryKey: RQKEY_PROFILE(currentAccount.did),
|
||||
})
|
||||
}
|
||||
agent.resumeSession(agent.session!).then(() => control.close())
|
||||
refreshSession().then(() => control.close())
|
||||
},
|
||||
})
|
||||
|
||||
@@ -311,7 +311,7 @@ function OwnHandlePage({goToServiceHandle}: {goToServiceHandle: () => void}) {
|
||||
const {currentAccount} = useSession()
|
||||
const [dnsPanel, setDNSPanel] = useState(true)
|
||||
const [domain, setDomain] = useState('')
|
||||
const agent = useAgent()
|
||||
const {refreshSession} = useSessionApi()
|
||||
const control = Dialog.useDialogContext()
|
||||
const fetchDid = useFetchDid()
|
||||
const queryClient = useQueryClient()
|
||||
@@ -328,7 +328,7 @@ function OwnHandlePage({goToServiceHandle}: {goToServiceHandle: () => void}) {
|
||||
queryKey: RQKEY_PROFILE(currentAccount.did),
|
||||
})
|
||||
}
|
||||
agent.resumeSession(agent.session!).then(() => control.close())
|
||||
refreshSession().then(() => control.close())
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as EmailValidator from 'email-validator'
|
||||
import {cleanError, isNetworkError} from '#/lib/strings/errors'
|
||||
import {checkAndFormatResetCode} from '#/lib/strings/password'
|
||||
import {logger} from '#/logger'
|
||||
import {useAgent, useSession} from '#/state/session'
|
||||
import {usePdsClient, useSession} from '#/state/session'
|
||||
import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
|
||||
import {android, atoms as a, web} from '#/alf'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
@@ -17,6 +17,7 @@ import * as TextField from '#/components/forms/TextField'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
import {com} from '#/lexicons'
|
||||
|
||||
enum Stages {
|
||||
RequestCode = 'RequestCode',
|
||||
@@ -44,7 +45,7 @@ export function ChangePasswordDialog({
|
||||
function Inner() {
|
||||
const {_} = useLingui()
|
||||
const {currentAccount} = useSession()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
const control = Dialog.useDialogContext()
|
||||
|
||||
const [stage, setStage] = useState(Stages.RequestCode)
|
||||
@@ -85,7 +86,7 @@ function Inner() {
|
||||
setError('')
|
||||
setIsProcessing(true)
|
||||
try {
|
||||
await agent.com.atproto.server.requestPasswordReset({
|
||||
await pdsClient.call(com.atproto.server.requestPasswordReset, {
|
||||
email: currentAccount.email,
|
||||
})
|
||||
setStage(Stages.ChangePassword)
|
||||
@@ -129,7 +130,7 @@ function Inner() {
|
||||
setError('')
|
||||
setIsProcessing(true)
|
||||
try {
|
||||
await agent.com.atproto.server.resetPassword({
|
||||
await pdsClient.call(com.atproto.server.resetPassword, {
|
||||
token: formattedCode,
|
||||
password: newPassword,
|
||||
})
|
||||
|
||||
@@ -5,7 +5,7 @@ import {useLingui} from '@lingui/react'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {logger} from '#/logger'
|
||||
import {useAgent, useSessionApi} from '#/state/session'
|
||||
import {usePdsClient, useSessionApi} from '#/state/session'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
import {type DialogOuterProps} from '#/components/Dialog'
|
||||
@@ -14,6 +14,7 @@ import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/ico
|
||||
import {Loader} from '#/components/Loader'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {com} from '#/lexicons'
|
||||
|
||||
export function DeactivateAccountDialog({
|
||||
control,
|
||||
@@ -34,7 +35,7 @@ function DeactivateAccountDialogInner({
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
const {logoutCurrentAccount} = useSessionApi()
|
||||
const [pending, setPending] = useState(false)
|
||||
const [error, setError] = useState<string | undefined>()
|
||||
@@ -42,7 +43,7 @@ function DeactivateAccountDialogInner({
|
||||
const handleDeactivate = useCallback(async () => {
|
||||
try {
|
||||
setPending(true)
|
||||
await agent.com.atproto.server.deactivateAccount({})
|
||||
await pdsClient.call(com.atproto.server.deactivateAccount, {})
|
||||
control.close(() => {
|
||||
logoutCurrentAccount('Deactivated')
|
||||
})
|
||||
@@ -66,7 +67,7 @@ function DeactivateAccountDialogInner({
|
||||
} finally {
|
||||
setPending(false)
|
||||
}
|
||||
}, [agent, control, logoutCurrentAccount, _, setPending])
|
||||
}, [pdsClient, control, logoutCurrentAccount, _, setPending])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {useCallback, useRef, useState} from 'react'
|
||||
import {type TextInput, View} from 'react-native'
|
||||
import {type DidString} from '@atproto/syntax'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
@@ -8,8 +9,8 @@ import {useCleanError} from '#/lib/hooks/useCleanError'
|
||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||
import {logger} from '#/logger'
|
||||
import {
|
||||
useAgent,
|
||||
useChatClient,
|
||||
usePdsClient,
|
||||
useSession,
|
||||
useSessionApi,
|
||||
} from '#/state/session'
|
||||
@@ -28,7 +29,7 @@ import {Loader} from '#/components/Loader'
|
||||
import * as Prompt from '#/components/Prompt'
|
||||
import * as toast from '#/components/Toast'
|
||||
import {Span, Text} from '#/components/Typography'
|
||||
import {chat} from '#/lexicons'
|
||||
import {chat, com} from '#/lexicons'
|
||||
import {resetToTab} from '#/Navigation'
|
||||
|
||||
const WHITESPACE_RE = /\s/gu
|
||||
@@ -77,7 +78,7 @@ function DeleteAccountDialogInner({
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const cleanError = useCleanError()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
const chatClient = useChatClient()
|
||||
const {currentAccount} = useSession()
|
||||
const {removeAccount} = useSessionApi()
|
||||
@@ -95,7 +96,7 @@ function DeleteAccountDialogInner({
|
||||
}
|
||||
try {
|
||||
setEmailState(EmailState.PENDING)
|
||||
await agent.com.atproto.server.requestAccountDelete()
|
||||
await pdsClient.call(com.atproto.server.requestAccountDelete)
|
||||
setError('')
|
||||
setEmailSentCount(prevCount => prevCount + 1)
|
||||
setStep(Step.VERIFY_CODE)
|
||||
@@ -109,7 +110,7 @@ function DeleteAccountDialogInner({
|
||||
} finally {
|
||||
setEmailState(EmailState.DEFAULT)
|
||||
}
|
||||
}, [agent, cleanError, emailState, setEmailState])
|
||||
}, [pdsClient, cleanError, emailState, setEmailState])
|
||||
|
||||
const confirmDeletion = useCallback(async () => {
|
||||
try {
|
||||
@@ -121,8 +122,8 @@ function DeleteAccountDialogInner({
|
||||
// Inform chat service of intent to delete account. The chat client is
|
||||
// proxied to the chat service; a failure throws.
|
||||
await chatClient.call(chat.bsky.actor.deleteAccount)
|
||||
await agent.com.atproto.server.deleteAccount({
|
||||
did: currentAccount.did,
|
||||
await pdsClient.call(com.atproto.server.deleteAccount, {
|
||||
did: currentAccount.did as DidString,
|
||||
password,
|
||||
token,
|
||||
})
|
||||
@@ -144,7 +145,8 @@ function DeleteAccountDialogInner({
|
||||
}
|
||||
}, [
|
||||
_,
|
||||
agent,
|
||||
pdsClient,
|
||||
chatClient,
|
||||
cleanError,
|
||||
confirmCode,
|
||||
control,
|
||||
|
||||
@@ -5,7 +5,7 @@ import {useLingui} from '@lingui/react'
|
||||
import {Trans} from '@lingui/react/macro'
|
||||
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
import {useAgent, useSession} from '#/state/session'
|
||||
import {usePdsClient, useSession, useSessionApi} from '#/state/session'
|
||||
import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
|
||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
@@ -16,6 +16,7 @@ import {Loader} from '#/components/Loader'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {P, Text} from '#/components/Typography'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
import {com} from '#/lexicons'
|
||||
|
||||
enum Stages {
|
||||
Email,
|
||||
@@ -31,7 +32,8 @@ export function DisableEmail2FADialog({
|
||||
const t = useTheme()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const {currentAccount} = useSession()
|
||||
const agent = useAgent()
|
||||
const pdsClient = usePdsClient()
|
||||
const {refreshSession} = useSessionApi()
|
||||
|
||||
const [stage, setStage] = useState<Stages>(Stages.Email)
|
||||
const [confirmationCode, setConfirmationCode] = useState<string>('')
|
||||
@@ -42,7 +44,7 @@ export function DisableEmail2FADialog({
|
||||
setError('')
|
||||
setIsProcessing(true)
|
||||
try {
|
||||
await agent.com.atproto.server.requestEmailUpdate()
|
||||
await pdsClient.call(com.atproto.server.requestEmailUpdate)
|
||||
setStage(Stages.ConfirmCode)
|
||||
} catch (e) {
|
||||
setError(cleanError(String(e)))
|
||||
@@ -56,12 +58,12 @@ export function DisableEmail2FADialog({
|
||||
setIsProcessing(true)
|
||||
try {
|
||||
if (currentAccount?.email) {
|
||||
await agent.com.atproto.server.updateEmail({
|
||||
await pdsClient.call(com.atproto.server.updateEmail, {
|
||||
email: currentAccount.email,
|
||||
token: confirmationCode.trim(),
|
||||
emailAuthFactor: false,
|
||||
})
|
||||
await agent.resumeSession(agent.session!)
|
||||
await refreshSession()
|
||||
Toast.show(_(msg({message: 'Email 2FA disabled', context: 'toast'})))
|
||||
}
|
||||
control.close()
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import {useCallback, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {type DidString} from '@atproto/syntax'
|
||||
import {Trans, useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {saveBytesToDisk} from '#/lib/media/manip'
|
||||
import {logger} from '#/logger'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {useChatClient, usePdsClient, useSession} from '#/state/session'
|
||||
import {atoms as a, useTheme, web} from '#/alf'
|
||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
@@ -13,7 +14,7 @@ import {InlineLinkText} from '#/components/Link'
|
||||
import {Loader} from '#/components/Loader'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {CHAT_PROXY_DID} from '#/env'
|
||||
import {com} from '#/lexicons'
|
||||
|
||||
export function ExportCarDialog({
|
||||
control,
|
||||
@@ -22,21 +23,28 @@ export function ExportCarDialog({
|
||||
}) {
|
||||
const {t: l} = useLingui()
|
||||
const t = useTheme()
|
||||
const agent = useAgent()
|
||||
const {currentAccount} = useSession()
|
||||
const pdsClient = usePdsClient()
|
||||
const chatClient = useChatClient()
|
||||
const [loading, setLoading] = useState<'repo' | 'chat' | false>(false)
|
||||
|
||||
const download = useCallback(async () => {
|
||||
if (!agent.session) {
|
||||
if (!currentAccount) {
|
||||
return // shouldn't ever happen
|
||||
}
|
||||
try {
|
||||
setLoading('repo')
|
||||
const did = agent.session.did
|
||||
const downloadRes = await agent.com.atproto.sync.getRepo({did})
|
||||
const did = currentAccount.did as DidString
|
||||
const data = await pdsClient.call(com.atproto.sync.getRepo, {did})
|
||||
/*
|
||||
* getRepo returns raw bytes; the lex client does not surface the response
|
||||
* content-type, and this endpoint always returns CAR data, so the constant
|
||||
* matches the old header-derived value in practice.
|
||||
*/
|
||||
const saveRes = await saveBytesToDisk(
|
||||
'repo.car',
|
||||
downloadRes.data,
|
||||
downloadRes.headers['content-type'] || 'application/vnd.ipld.car',
|
||||
data,
|
||||
'application/vnd.ipld.car',
|
||||
)
|
||||
|
||||
if (saveRes) {
|
||||
@@ -48,21 +56,24 @@ export function ExportCarDialog({
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [l, agent])
|
||||
}, [l, currentAccount, pdsClient])
|
||||
|
||||
const downloadChatData = useCallback(async () => {
|
||||
if (!agent.session) {
|
||||
if (!currentAccount) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
setLoading('chat')
|
||||
// Using raw fetch because the XRPC client incorrectly tries to JSON-parse
|
||||
// application/jsonl responses (substring match on application/json).
|
||||
// The chat-service proxy header is inlined here (the endpoint is proxied
|
||||
// to `did:web:api.bsky.chat`); this raw path bypasses the lex client.
|
||||
const res = await agent.sessionManager.fetchHandler(
|
||||
/*
|
||||
* Using the client's low-level fetchHandler because the XRPC client
|
||||
* incorrectly tries to JSON-parse application/jsonl responses (substring
|
||||
* match on application/json). The chat client already proxies to
|
||||
* `did:web:api.bsky.chat`, so no manual proxy header is needed - it would
|
||||
* otherwise be double-set.
|
||||
*/
|
||||
const res = await chatClient.fetchHandler(
|
||||
'/xrpc/chat.bsky.actor.exportAccountData',
|
||||
{headers: {'atproto-proxy': `${CHAT_PROXY_DID}#bsky_chat`}},
|
||||
{},
|
||||
)
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP ${res.status}`)
|
||||
@@ -83,7 +94,7 @@ export function ExportCarDialog({
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}, [l, agent])
|
||||
}, [l, currentAccount, chatClient])
|
||||
|
||||
return (
|
||||
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
|
||||
|
||||
Reference in New Issue
Block a user