[SDK] Migrate search, bookmarks, contacts and feed queries to the lex clients (#11360)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
import {useCallback, useEffect, useState} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import {type DidString} from '@atproto/syntax'
|
||||
import {useLingui} from '@lingui/react/macro'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {PressableScale} from '#/lib/custom-animations/PressableScale'
|
||||
import {STALE} from '#/state/queries'
|
||||
import {profilesQueryKey} from '#/state/queries/profile'
|
||||
import {useAgent, useSession} from '#/state/session'
|
||||
import {useAppviewClient, useSession} from '#/state/session'
|
||||
import {useSetActiveLanding} from '#/state/shell/landing'
|
||||
import {
|
||||
useLoggedOutView,
|
||||
@@ -23,6 +24,7 @@ import {atoms as a, native, tokens, useTheme} from '#/alf'
|
||||
import {Button, ButtonIcon} from '#/components/Button'
|
||||
import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {app} from '#/lexicons'
|
||||
import {SplashScreen} from './SplashScreen'
|
||||
|
||||
enum ScreenState {
|
||||
@@ -65,19 +67,18 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const {accounts} = useSession()
|
||||
const agent = useAgent()
|
||||
const client = useAppviewClient()
|
||||
useEffect(() => {
|
||||
const actors = accounts.map(acc => acc.did)
|
||||
const actors = accounts.map(acc => acc.did as DidString)
|
||||
if (actors.length === 0) return
|
||||
void queryClient.prefetchQuery({
|
||||
queryKey: profilesQueryKey(actors),
|
||||
staleTime: STALE.MINUTES.FIVE,
|
||||
queryFn: async () => {
|
||||
const res = await agent.getProfiles({actors})
|
||||
return res.data
|
||||
return await client.call(app.bsky.actor.getProfiles, {actors})
|
||||
},
|
||||
})
|
||||
}, [accounts, agent, queryClient])
|
||||
}, [accounts, client, queryClient])
|
||||
|
||||
const onPressDismiss = useCallback(() => {
|
||||
if (onDismiss) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {AppBskyDraftCreateDraft, AppBskyDraftDefs} from '@atproto/api'
|
||||
import {AppBskyDraftDefs} from '@atproto/api'
|
||||
import {
|
||||
useInfiniteQuery,
|
||||
useMutation,
|
||||
@@ -6,10 +6,12 @@ import {
|
||||
} from '@tanstack/react-query'
|
||||
|
||||
import {isNetworkError} from '#/lib/strings/errors'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {matchXrpcError} from '#/lib/xrpc-error'
|
||||
import {useAppviewClient} from '#/state/session'
|
||||
import {type ComposerState} from '#/view/com/composer/state/composer'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {getDeviceId} from '#/analytics/identifiers'
|
||||
import {app} from '#/lexicons'
|
||||
import {composerStateToDraft, draftViewToSummary} from './api'
|
||||
import {logger} from './logger'
|
||||
import * as storage from './storage'
|
||||
@@ -20,7 +22,7 @@ const DRAFTS_QUERY_KEY = ['drafts']
|
||||
* Hook to list all drafts for the current account
|
||||
*/
|
||||
export function useDraftsQuery() {
|
||||
const agent = useAgent()
|
||||
const client = useAppviewClient()
|
||||
const ax = useAnalytics()
|
||||
|
||||
return useInfiniteQuery({
|
||||
@@ -28,10 +30,12 @@ export function useDraftsQuery() {
|
||||
queryFn: async ({pageParam}) => {
|
||||
// Ensure media cache is populated before checking which media exists
|
||||
await storage.ensureMediaCachePopulated()
|
||||
const res = await agent.app.bsky.draft.getDrafts({cursor: pageParam})
|
||||
const data = await client.call(app.bsky.draft.getDrafts, {
|
||||
cursor: pageParam,
|
||||
})
|
||||
return {
|
||||
cursor: res.data.cursor,
|
||||
drafts: res.data.drafts.map(view =>
|
||||
cursor: data.cursor,
|
||||
drafts: data.drafts.map(view =>
|
||||
draftViewToSummary({
|
||||
view,
|
||||
analytics: ax,
|
||||
@@ -116,7 +120,7 @@ export async function loadDraftMedia(draft: AppBskyDraftDefs.Draft): Promise<{
|
||||
* This ensures we don't lose data if the network request fails.
|
||||
*/
|
||||
export function useSaveDraftMutation() {
|
||||
const agent = useAgent()
|
||||
const client = useAppviewClient()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
@@ -132,7 +136,14 @@ export function useSaveDraftMutation() {
|
||||
originalLocalRefs: Set<string> | undefined
|
||||
}> => {
|
||||
// Convert composer state to server draft format
|
||||
const {draft, localRefPaths} = await composerStateToDraft(composerState)
|
||||
const {draft: apiDraft, localRefPaths} =
|
||||
await composerStateToDraft(composerState)
|
||||
/*
|
||||
* `composerStateToDraft` builds the draft against the `@atproto/api`
|
||||
* types, whose string fields are unbranded, so it is asserted once here
|
||||
* to the vendored input type.
|
||||
*/
|
||||
const draft = apiDraft as unknown as app.bsky.draft.defs.Draft
|
||||
|
||||
logger.debug('saving draft', {
|
||||
existingDraftId,
|
||||
@@ -147,7 +158,7 @@ export function useSaveDraftMutation() {
|
||||
logger.debug('updating existing draft on server', {
|
||||
draftId: existingDraftId,
|
||||
})
|
||||
await agent.app.bsky.draft.updateDraft({
|
||||
await client.call(app.bsky.draft.updateDraft, {
|
||||
draft: {
|
||||
id: existingDraftId,
|
||||
draft,
|
||||
@@ -157,8 +168,8 @@ export function useSaveDraftMutation() {
|
||||
} else {
|
||||
// Create new draft
|
||||
logger.debug('creating new draft on server')
|
||||
const res = await agent.app.bsky.draft.createDraft({draft})
|
||||
draftId = res.data.id
|
||||
const data = await client.call(app.bsky.draft.createDraft, {draft})
|
||||
draftId = data.id
|
||||
logger.debug('created new draft', {draftId})
|
||||
}
|
||||
|
||||
@@ -203,7 +214,7 @@ export function useSaveDraftMutation() {
|
||||
},
|
||||
onError: error => {
|
||||
// Check for draft limit error
|
||||
if (error instanceof AppBskyDraftCreateDraft.DraftLimitReachedError) {
|
||||
if (matchXrpcError(error, app.bsky.draft.createDraft)) {
|
||||
logger.error('Draft limit reached', {safeMessage: error.message})
|
||||
// Error will be handled by caller
|
||||
} else if (!isNetworkError(error)) {
|
||||
@@ -220,7 +231,7 @@ export function useSaveDraftMutation() {
|
||||
* Takes the full draft data to avoid re-fetching for media cleanup.
|
||||
*/
|
||||
export function useDeleteDraftMutation() {
|
||||
const agent = useAgent()
|
||||
const client = useAppviewClient()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
@@ -231,7 +242,7 @@ export function useDeleteDraftMutation() {
|
||||
draft: AppBskyDraftDefs.Draft
|
||||
}) => {
|
||||
// Delete from server first - if this fails, we keep local media for retry
|
||||
await agent.app.bsky.draft.deleteDraft({id: draftId})
|
||||
await client.call(app.bsky.draft.deleteDraft, {id: draftId})
|
||||
},
|
||||
onSuccess: async (_, {draft}) => {
|
||||
// Only delete local media after server deletion succeeds
|
||||
@@ -264,7 +275,7 @@ export function useDeleteDraftMutation() {
|
||||
* Takes draftId and originalLocalRefs from composer state.
|
||||
*/
|
||||
export function useCleanupPublishedDraftMutation() {
|
||||
const agent = useAgent()
|
||||
const client = useAppviewClient()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
@@ -280,7 +291,9 @@ export function useCleanupPublishedDraftMutation() {
|
||||
mediaFileCount: originalLocalRefs.size,
|
||||
})
|
||||
// Delete from server first
|
||||
await agent.app.bsky.draft.deleteDraft({id: draftId})
|
||||
await client.call(app.bsky.draft.deleteDraft, {
|
||||
id: draftId,
|
||||
})
|
||||
logger.debug('deleted draft from server', {draftId})
|
||||
},
|
||||
onSuccess: async (_, {originalLocalRefs}) => {
|
||||
|
||||
Reference in New Issue
Block a user