migrate the contact queries and phone verification to the appview client
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,6 @@ import {useState} from 'react'
|
|||||||
import {Keyboard, View} from 'react-native'
|
import {Keyboard, View} from 'react-native'
|
||||||
import {KeyboardAvoidingView} from 'react-native-keyboard-controller'
|
import {KeyboardAvoidingView} from 'react-native-keyboard-controller'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import {AppBskyContactStartPhoneVerification} from '@atproto/api'
|
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {Trans} from '@lingui/react/macro'
|
import {Trans} from '@lingui/react/macro'
|
||||||
@@ -14,8 +13,9 @@ import {
|
|||||||
getDefaultCountry,
|
getDefaultCountry,
|
||||||
} from '#/lib/international-telephone-codes'
|
} from '#/lib/international-telephone-codes'
|
||||||
import {cleanError, isNetworkError} from '#/lib/strings/errors'
|
import {cleanError, isNetworkError} from '#/lib/strings/errors'
|
||||||
|
import {matchXrpcError} from '#/lib/xrpc-error'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAppviewClient} from '#/state/session'
|
||||||
import {OnboardingPosition} from '#/screens/Onboarding/Layout'
|
import {OnboardingPosition} from '#/screens/Onboarding/Layout'
|
||||||
import {
|
import {
|
||||||
android,
|
android,
|
||||||
@@ -34,6 +34,7 @@ import {Loader} from '#/components/Loader'
|
|||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {useAnalytics} from '#/analytics'
|
import {useAnalytics} from '#/analytics'
|
||||||
import {useGeolocation} from '#/geolocation'
|
import {useGeolocation} from '#/geolocation'
|
||||||
|
import {app} from '#/lexicons'
|
||||||
import {isFindContactsFeatureEnabled} from '../country-allowlist'
|
import {isFindContactsFeatureEnabled} from '../country-allowlist'
|
||||||
import {
|
import {
|
||||||
constructFullPhoneNumber,
|
constructFullPhoneNumber,
|
||||||
@@ -56,7 +57,7 @@ export function PhoneInput({
|
|||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
const location = useGeolocation()
|
const location = useGeolocation()
|
||||||
const [countryCode, setCountryCode] = useState(
|
const [countryCode, setCountryCode] = useState(
|
||||||
() => state.phoneCountryCode ?? getDefaultCountry(location),
|
() => state.phoneCountryCode ?? getDefaultCountry(location),
|
||||||
@@ -78,7 +79,7 @@ export function PhoneInput({
|
|||||||
phoneNumber: string
|
phoneNumber: string
|
||||||
}) => {
|
}) => {
|
||||||
// sends a onetime code to the user's phone number
|
// sends a onetime code to the user's phone number
|
||||||
await agent.app.bsky.contact.startPhoneVerification({
|
await client.call(app.bsky.contact.startPhoneVerification, {
|
||||||
phone: constructFullPhoneNumber(phoneCountryCode, phoneNumber),
|
phone: constructFullPhoneNumber(phoneCountryCode, phoneNumber),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -102,23 +103,22 @@ export function PhoneInput({
|
|||||||
msg`A network error occurred. Please check your internet connection`,
|
msg`A network error occurred. Please check your internet connection`,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else if (
|
return
|
||||||
err instanceof
|
|
||||||
AppBskyContactStartPhoneVerification.RateLimitExceededError
|
|
||||||
) {
|
|
||||||
setError(_(msg`Rate limit exceeded. Please try again later.`))
|
|
||||||
} else if (
|
|
||||||
err instanceof AppBskyContactStartPhoneVerification.InvalidPhoneError
|
|
||||||
) {
|
|
||||||
setError(
|
|
||||||
_(
|
|
||||||
msg`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
logger.error('Verify phone number failed', {safeMessage: err})
|
|
||||||
setError(_(msg`An error occurred. ${cleanError(err)}`))
|
|
||||||
}
|
}
|
||||||
|
switch (matchXrpcError(err, app.bsky.contact.startPhoneVerification)) {
|
||||||
|
case 'RateLimitExceeded':
|
||||||
|
setError(_(msg`Rate limit exceeded. Please try again later.`))
|
||||||
|
return
|
||||||
|
case 'InvalidPhone':
|
||||||
|
setError(
|
||||||
|
_(
|
||||||
|
msg`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.error('Verify phone number failed', {safeMessage: err})
|
||||||
|
setError(_(msg`An error occurred. ${cleanError(err)}`))
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
import {useEffect, useMemo, useState} from 'react'
|
import {useEffect, useMemo, useState} from 'react'
|
||||||
import {Text as NestedText, View} from 'react-native'
|
import {Text as NestedText, View} from 'react-native'
|
||||||
import {
|
|
||||||
AppBskyContactStartPhoneVerification,
|
|
||||||
AppBskyContactVerifyPhone,
|
|
||||||
} from '@atproto/api'
|
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {Trans} from '@lingui/react/macro'
|
import {Trans} from '@lingui/react/macro'
|
||||||
@@ -11,8 +7,9 @@ import {useMutation} from '@tanstack/react-query'
|
|||||||
|
|
||||||
import {clamp} from '#/lib/numbers'
|
import {clamp} from '#/lib/numbers'
|
||||||
import {cleanError, isNetworkError} from '#/lib/strings/errors'
|
import {cleanError, isNetworkError} from '#/lib/strings/errors'
|
||||||
|
import {matchXrpcError} from '#/lib/xrpc-error'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAppviewClient} from '#/state/session'
|
||||||
import {OnboardingPosition} from '#/screens/Onboarding/Layout'
|
import {OnboardingPosition} from '#/screens/Onboarding/Layout'
|
||||||
import {atoms as a, useGutters, useTheme} from '#/alf'
|
import {atoms as a, useGutters, useTheme} from '#/alf'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
@@ -25,6 +22,7 @@ import {Loader} from '#/components/Loader'
|
|||||||
import * as Toast from '#/components/Toast'
|
import * as Toast from '#/components/Toast'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {useAnalytics} from '#/analytics'
|
import {useAnalytics} from '#/analytics'
|
||||||
|
import {app} from '#/lexicons'
|
||||||
import {OTPInput} from '../components/OTPInput'
|
import {OTPInput} from '../components/OTPInput'
|
||||||
import {constructFullPhoneNumber, prettyPhoneNumber} from '../phone-number'
|
import {constructFullPhoneNumber, prettyPhoneNumber} from '../phone-number'
|
||||||
import {type Action, type State, useOnPressBackButton} from '../state'
|
import {type Action, type State, useOnPressBackButton} from '../state'
|
||||||
@@ -43,7 +41,7 @@ export function VerifyNumber({
|
|||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
const gutters = useGutters([0, 'wide'])
|
const gutters = useGutters([0, 'wide'])
|
||||||
|
|
||||||
const [otpCode, setOtpCode] = useState('')
|
const [otpCode, setOtpCode] = useState('')
|
||||||
@@ -72,8 +70,11 @@ export function VerifyNumber({
|
|||||||
isSuccess,
|
isSuccess,
|
||||||
} = useMutation({
|
} = useMutation({
|
||||||
mutationFn: async (code: string) => {
|
mutationFn: async (code: string) => {
|
||||||
const res = await agent.app.bsky.contact.verifyPhone({code, phone})
|
const data = await client.call(app.bsky.contact.verifyPhone, {
|
||||||
return res.data.token
|
code,
|
||||||
|
phone,
|
||||||
|
})
|
||||||
|
return data.token
|
||||||
},
|
},
|
||||||
onSuccess: async token => {
|
onSuccess: async token => {
|
||||||
// let the success state show for a moment
|
// let the success state show for a moment
|
||||||
@@ -99,44 +100,47 @@ export function VerifyNumber({
|
|||||||
msg`A network error occurred. Please check your internet connection.`,
|
msg`A network error occurred. Please check your internet connection.`,
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
} else if (err instanceof AppBskyContactVerifyPhone.InvalidCodeError) {
|
return
|
||||||
setError({
|
|
||||||
retryable: true,
|
|
||||||
isResendError: true,
|
|
||||||
message: _(msg`This code is invalid. Resend to get a new code.`),
|
|
||||||
})
|
|
||||||
} else if (err instanceof AppBskyContactVerifyPhone.InvalidPhoneError) {
|
|
||||||
setError({
|
|
||||||
retryable: false,
|
|
||||||
isResendError: false,
|
|
||||||
message: _(
|
|
||||||
msg`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
|
||||||
),
|
|
||||||
})
|
|
||||||
} else if (
|
|
||||||
err instanceof AppBskyContactVerifyPhone.RateLimitExceededError
|
|
||||||
) {
|
|
||||||
setError({
|
|
||||||
retryable: true,
|
|
||||||
isResendError: false,
|
|
||||||
message: _(
|
|
||||||
msg`Too many attempts. Please wait a few minutes and try again.`,
|
|
||||||
),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
logger.error('Verify phone number failed', {safeMessage: err})
|
|
||||||
setError({
|
|
||||||
retryable: true,
|
|
||||||
isResendError: false,
|
|
||||||
message: _(msg`An error occurred. ${cleanError(err)}`),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
switch (matchXrpcError(err, app.bsky.contact.verifyPhone)) {
|
||||||
|
case 'InvalidCode':
|
||||||
|
setError({
|
||||||
|
retryable: true,
|
||||||
|
isResendError: true,
|
||||||
|
message: _(msg`This code is invalid. Resend to get a new code.`),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
case 'InvalidPhone':
|
||||||
|
setError({
|
||||||
|
retryable: false,
|
||||||
|
isResendError: false,
|
||||||
|
message: _(
|
||||||
|
msg`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
case 'RateLimitExceeded':
|
||||||
|
setError({
|
||||||
|
retryable: true,
|
||||||
|
isResendError: false,
|
||||||
|
message: _(
|
||||||
|
msg`Too many attempts. Please wait a few minutes and try again.`,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.error('Verify phone number failed', {safeMessage: err})
|
||||||
|
setError({
|
||||||
|
retryable: true,
|
||||||
|
isResendError: false,
|
||||||
|
message: _(msg`An error occurred. ${cleanError(err)}`),
|
||||||
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const {mutate: resendCode, isPending: isResendingCode} = useMutation({
|
const {mutate: resendCode, isPending: isResendingCode} = useMutation({
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
await agent.app.bsky.contact.startPhoneVerification({phone: phone})
|
await client.call(app.bsky.contact.startPhoneVerification, {phone: phone})
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
dispatch({type: 'RESEND_VERIFICATION_CODE'})
|
dispatch({type: 'RESEND_VERIFICATION_CODE'})
|
||||||
@@ -155,35 +159,34 @@ export function VerifyNumber({
|
|||||||
msg`A network error occurred. Please check your internet connection.`,
|
msg`A network error occurred. Please check your internet connection.`,
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
} else if (
|
return
|
||||||
err instanceof AppBskyContactStartPhoneVerification.InvalidPhoneError
|
|
||||||
) {
|
|
||||||
setError({
|
|
||||||
retryable: false,
|
|
||||||
isResendError: true,
|
|
||||||
message: _(
|
|
||||||
msg`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
|
||||||
),
|
|
||||||
})
|
|
||||||
} else if (
|
|
||||||
err instanceof
|
|
||||||
AppBskyContactStartPhoneVerification.RateLimitExceededError
|
|
||||||
) {
|
|
||||||
setError({
|
|
||||||
retryable: true,
|
|
||||||
isResendError: true,
|
|
||||||
message: _(
|
|
||||||
msg`Too many codes sent. Please wait a few minutes and try again.`,
|
|
||||||
),
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
logger.error('Resend failed', {safeMessage: err})
|
|
||||||
setError({
|
|
||||||
retryable: true,
|
|
||||||
isResendError: true,
|
|
||||||
message: _(msg`An error occurred. ${cleanError(err)}`),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
switch (matchXrpcError(err, app.bsky.contact.startPhoneVerification)) {
|
||||||
|
case 'InvalidPhone':
|
||||||
|
setError({
|
||||||
|
retryable: false,
|
||||||
|
isResendError: true,
|
||||||
|
message: _(
|
||||||
|
msg`The verification provider was unable to send a code to your phone number. Please check your phone number and try again.`,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
case 'RateLimitExceeded':
|
||||||
|
setError({
|
||||||
|
retryable: true,
|
||||||
|
isResendError: true,
|
||||||
|
message: _(
|
||||||
|
msg`Too many codes sent. Please wait a few minutes and try again.`,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.error('Resend failed', {safeMessage: err})
|
||||||
|
setError({
|
||||||
|
retryable: true,
|
||||||
|
isResendError: true,
|
||||||
|
message: _(msg`An error occurred. ${cleanError(err)}`),
|
||||||
|
})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {View} from 'react-native'
|
|||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||||
import * as SMS from 'expo-sms'
|
import * as SMS from 'expo-sms'
|
||||||
import {type ModerationOpts} from '@atproto/api'
|
import {type ModerationOpts} from '@atproto/api'
|
||||||
|
import {type DidString} from '@atproto/syntax'
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {Plural, Trans} from '@lingui/react/macro'
|
import {Plural, Trans} from '@lingui/react/macro'
|
||||||
@@ -20,7 +21,7 @@ import {
|
|||||||
optimisticRemoveMatch,
|
optimisticRemoveMatch,
|
||||||
useMatchesPassthroughQuery,
|
useMatchesPassthroughQuery,
|
||||||
} from '#/state/queries/find-contacts'
|
} from '#/state/queries/find-contacts'
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useAppviewClient, useSession} from '#/state/session'
|
||||||
import {List, type ListMethods} from '#/view/com/util/List'
|
import {List, type ListMethods} from '#/view/com/util/List'
|
||||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||||
import {OnboardingPosition} from '#/screens/Onboarding/Layout'
|
import {OnboardingPosition} from '#/screens/Onboarding/Layout'
|
||||||
@@ -41,6 +42,7 @@ import * as ProfileCard from '#/components/ProfileCard'
|
|||||||
import * as Toast from '#/components/Toast'
|
import * as Toast from '#/components/Toast'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import {useAnalytics} from '#/analytics'
|
import {useAnalytics} from '#/analytics'
|
||||||
|
import {app} from '#/lexicons'
|
||||||
import type * as bsky from '#/types/bsky'
|
import type * as bsky from '#/types/bsky'
|
||||||
import {InviteInfo} from '../components/InviteInfo'
|
import {InviteInfo} from '../components/InviteInfo'
|
||||||
import {type Action, type Contact, type Match, type State} from '../state'
|
import {type Action, type Contact, type Match, type State} from '../state'
|
||||||
@@ -90,6 +92,7 @@ export function ViewMatches({
|
|||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
|
const client = useAppviewClient()
|
||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
const listRef = useRef<ListMethods>(null)
|
const listRef = useRef<ListMethods>(null)
|
||||||
|
|
||||||
@@ -218,7 +221,9 @@ export function ViewMatches({
|
|||||||
|
|
||||||
const {mutate: dismissMatch} = useMutation({
|
const {mutate: dismissMatch} = useMutation({
|
||||||
mutationFn: async (did: string) => {
|
mutationFn: async (did: string) => {
|
||||||
await agent.app.bsky.contact.dismissMatch({subject: did})
|
await client.call(app.bsky.contact.dismissMatch, {
|
||||||
|
subject: did as DidString,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onMutate: did => {
|
onMutate: did => {
|
||||||
ax.metric('contacts:matches:dismiss', {entryPoint: context})
|
ax.metric('contacts:matches:dismiss', {entryPoint: context})
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import {useCallback, useEffect, useState} from 'react'
|
import {useCallback, useEffect, useState} from 'react'
|
||||||
import {type ListRenderItemInfo, View} from 'react-native'
|
import {type ListRenderItemInfo, View} from 'react-native'
|
||||||
import * as Contacts from 'expo-contacts'
|
import * as Contacts from 'expo-contacts'
|
||||||
import {
|
import {type AppBskyContactDefs, type ModerationOpts} from '@atproto/api'
|
||||||
type AppBskyContactDefs,
|
import {type DidString} from '@atproto/syntax'
|
||||||
type AppBskyContactGetSyncStatus,
|
|
||||||
type ModerationOpts,
|
|
||||||
} from '@atproto/api'
|
|
||||||
import {msg} from '@lingui/core/macro'
|
import {msg} from '@lingui/core/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {Plural, Trans} from '@lingui/react/macro'
|
import {Plural, Trans} from '@lingui/react/macro'
|
||||||
@@ -32,7 +29,7 @@ import {
|
|||||||
useContactsMatchesQuery,
|
useContactsMatchesQuery,
|
||||||
useContactsSyncStatusQuery,
|
useContactsSyncStatusQuery,
|
||||||
} from '#/state/queries/find-contacts'
|
} from '#/state/queries/find-contacts'
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useAppviewClient, useSession} from '#/state/session'
|
||||||
import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
|
import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
|
||||||
import {List} from '#/view/com/util/List'
|
import {List} from '#/view/com/util/List'
|
||||||
import {atoms as a, tokens, useGutters, useTheme} from '#/alf'
|
import {atoms as a, tokens, useGutters, useTheme} from '#/alf'
|
||||||
@@ -52,6 +49,7 @@ import {Text} from '#/components/Typography'
|
|||||||
import {useAnalytics} from '#/analytics'
|
import {useAnalytics} from '#/analytics'
|
||||||
import {IS_NATIVE} from '#/env'
|
import {IS_NATIVE} from '#/env'
|
||||||
import {InviteFriendsDialog} from '#/features/inviteFriends'
|
import {InviteFriendsDialog} from '#/features/inviteFriends'
|
||||||
|
import {app} from '#/lexicons'
|
||||||
import type * as bsky from '#/types/bsky'
|
import type * as bsky from '#/types/bsky'
|
||||||
import {bulkWriteFollows} from '../Onboarding/util'
|
import {bulkWriteFollows} from '../Onboarding/util'
|
||||||
|
|
||||||
@@ -194,7 +192,7 @@ function SyncStatus({
|
|||||||
refetchStatus: () => Promise<any>
|
refetchStatus: () => Promise<any>
|
||||||
}) {
|
}) {
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
@@ -219,7 +217,9 @@ function SyncStatus({
|
|||||||
|
|
||||||
const {mutate: dismissMatch} = useMutation({
|
const {mutate: dismissMatch} = useMutation({
|
||||||
mutationFn: async (did: string) => {
|
mutationFn: async (did: string) => {
|
||||||
await agent.app.bsky.contact.dismissMatch({subject: did})
|
await client.call(app.bsky.contact.dismissMatch, {
|
||||||
|
subject: did as DidString,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onMutate: async (did: string) => {
|
onMutate: async (did: string) => {
|
||||||
ax.metric('contacts:settings:dismiss', {})
|
ax.metric('contacts:settings:dismiss', {})
|
||||||
@@ -371,6 +371,7 @@ function StatusHeader({
|
|||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
|
const client = useAppviewClient()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
@@ -384,12 +385,12 @@ function StatusHeader({
|
|||||||
|
|
||||||
let cursor: string | undefined
|
let cursor: string | undefined
|
||||||
do {
|
do {
|
||||||
const page = await agent.app.bsky.contact.getMatches({
|
const page = await client.call(app.bsky.contact.getMatches, {
|
||||||
limit: 100,
|
limit: 100,
|
||||||
cursor,
|
cursor,
|
||||||
})
|
})
|
||||||
cursor = page.data.cursor
|
cursor = page.cursor
|
||||||
for (const profile of page.data.matches) {
|
for (const profile of page.matches) {
|
||||||
if (
|
if (
|
||||||
profile.did !== currentAccount?.did &&
|
profile.did !== currentAccount?.did &&
|
||||||
!isBlockedOrBlocking(profile) &&
|
!isBlockedOrBlocking(profile) &&
|
||||||
@@ -487,17 +488,17 @@ function StatusFooter({syncedAt}: {syncedAt: string}) {
|
|||||||
const {_, i18n} = useLingui()
|
const {_, i18n} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const ax = useAnalytics()
|
const ax = useAnalytics()
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
const {mutate: removeData, isPending} = useMutation({
|
const {mutate: removeData, isPending} = useMutation({
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
await agent.app.bsky.contact.removeData({})
|
await client.call(app.bsky.contact.removeData, {})
|
||||||
},
|
},
|
||||||
onMutate: () => ax.metric('contacts:settings:removeData', {}),
|
onMutate: () => ax.metric('contacts:settings:removeData', {}),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
Toast.show(_(msg`Contacts removed`))
|
Toast.show(_(msg`Contacts removed`))
|
||||||
queryClient.setQueryData<AppBskyContactGetSyncStatus.OutputSchema>(
|
queryClient.setQueryData<app.bsky.contact.getSyncStatus.$OutputBody>(
|
||||||
findContactsStatusQueryKey,
|
findContactsStatusQueryKey,
|
||||||
{syncStatus: undefined},
|
{syncStatus: undefined},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import {type AppBskyContactGetMatches} from '@atproto/api'
|
|
||||||
import {
|
import {
|
||||||
type InfiniteData,
|
type InfiniteData,
|
||||||
type QueryClient,
|
type QueryClient,
|
||||||
@@ -6,8 +5,9 @@ import {
|
|||||||
useQuery,
|
useQuery,
|
||||||
} from '@tanstack/react-query'
|
} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {useAgent} from '#/state/session'
|
import {useAppviewClient} from '#/state/session'
|
||||||
import {type Match} from '#/components/contacts/state'
|
import {type Match} from '#/components/contacts/state'
|
||||||
|
import {app} from '#/lexicons'
|
||||||
import type * as bsky from '#/types/bsky'
|
import type * as bsky from '#/types/bsky'
|
||||||
import {STALE} from '.'
|
import {STALE} from '.'
|
||||||
|
|
||||||
@@ -15,13 +15,12 @@ const RQ_KEY_ROOT = 'find-contacts'
|
|||||||
export const findContactsStatusQueryKey = [RQ_KEY_ROOT, 'sync-status']
|
export const findContactsStatusQueryKey = [RQ_KEY_ROOT, 'sync-status']
|
||||||
|
|
||||||
export function useContactsSyncStatusQuery() {
|
export function useContactsSyncStatusQuery() {
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: findContactsStatusQueryKey,
|
queryKey: findContactsStatusQueryKey,
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const status = await agent.app.bsky.contact.getSyncStatus()
|
return await client.call(app.bsky.contact.getSyncStatus, {})
|
||||||
return status.data
|
|
||||||
},
|
},
|
||||||
staleTime: STALE.SECONDS.THIRTY,
|
staleTime: STALE.SECONDS.THIRTY,
|
||||||
})
|
})
|
||||||
@@ -30,15 +29,14 @@ export function useContactsSyncStatusQuery() {
|
|||||||
export const findContactsGetMatchesQueryKey = [RQ_KEY_ROOT, 'matches']
|
export const findContactsGetMatchesQueryKey = [RQ_KEY_ROOT, 'matches']
|
||||||
|
|
||||||
export function useContactsMatchesQuery() {
|
export function useContactsMatchesQuery() {
|
||||||
const agent = useAgent()
|
const client = useAppviewClient()
|
||||||
|
|
||||||
return useInfiniteQuery({
|
return useInfiniteQuery({
|
||||||
queryKey: findContactsGetMatchesQueryKey,
|
queryKey: findContactsGetMatchesQueryKey,
|
||||||
queryFn: async ({pageParam}) => {
|
queryFn: async ({pageParam}) => {
|
||||||
const matches = await agent.app.bsky.contact.getMatches({
|
return await client.call(app.bsky.contact.getMatches, {
|
||||||
cursor: pageParam,
|
cursor: pageParam,
|
||||||
})
|
})
|
||||||
return matches.data
|
|
||||||
},
|
},
|
||||||
initialPageParam: undefined as string | undefined,
|
initialPageParam: undefined as string | undefined,
|
||||||
getNextPageParam: lastPage => lastPage.cursor,
|
getNextPageParam: lastPage => lastPage.cursor,
|
||||||
@@ -47,20 +45,19 @@ export function useContactsMatchesQuery() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function optimisticRemoveMatch(queryClient: QueryClient, did: string) {
|
export function optimisticRemoveMatch(queryClient: QueryClient, did: string) {
|
||||||
queryClient.setQueryData<InfiniteData<AppBskyContactGetMatches.OutputSchema>>(
|
queryClient.setQueryData<
|
||||||
findContactsGetMatchesQueryKey,
|
InfiniteData<app.bsky.contact.getMatches.$OutputBody>
|
||||||
old => {
|
>(findContactsGetMatchesQueryKey, old => {
|
||||||
if (!old) return old
|
if (!old) return old
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...old,
|
...old,
|
||||||
pages: old.pages.map(page => ({
|
pages: old.pages.map(page => ({
|
||||||
...page,
|
...page,
|
||||||
matches: page.matches.filter(match => match.did !== did),
|
matches: page.matches.filter(match => match.did !== did),
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const findContactsMatchesPassthroughQueryKey = (dids: string[]) => [
|
export const findContactsMatchesPassthroughQueryKey = (dids: string[]) => [
|
||||||
@@ -95,7 +92,7 @@ export function* findAllProfilesInQueryData(
|
|||||||
did: string,
|
did: string,
|
||||||
): Generator<bsky.profile.AnyProfileView, void> {
|
): Generator<bsky.profile.AnyProfileView, void> {
|
||||||
const queryDatas = queryClient.getQueriesData<
|
const queryDatas = queryClient.getQueriesData<
|
||||||
InfiniteData<AppBskyContactGetMatches.OutputSchema>
|
InfiniteData<app.bsky.contact.getMatches.$OutputBody>
|
||||||
>({
|
>({
|
||||||
queryKey: findContactsGetMatchesQueryKey,
|
queryKey: findContactsGetMatchesQueryKey,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user