Onboarding fixes (#3966)

* Ensure prefs are up-to-date before leaving onboarding

* Parallelize upsertProfile call

* Don't upsertProfile if no image

* Don't waterfall blob upload

* Fix useProfileUpdateMutation to parallelize uploads

* Invalidate user profile before leaving onboarding

* Ungate setting the pic
zio/stable
dan 2024-05-11 19:54:58 +01:00 committed by GitHub
parent 6f5b551bda
commit 51b4b22dec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 32 deletions

View File

@ -3,13 +3,18 @@ import {View} from 'react-native'
import {TID} from '@atproto/common-web' import {TID} from '@atproto/common-web'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useQueryClient} from '@tanstack/react-query'
import {useAnalytics} from '#/lib/analytics/analytics' import {useAnalytics} from '#/lib/analytics/analytics'
import {BSKY_APP_ACCOUNT_DID, IS_PROD_SERVICE} from '#/lib/constants' import {BSKY_APP_ACCOUNT_DID, IS_PROD_SERVICE} from '#/lib/constants'
import {DISCOVER_SAVED_FEED, TIMELINE_SAVED_FEED} from '#/lib/constants' import {DISCOVER_SAVED_FEED, TIMELINE_SAVED_FEED} from '#/lib/constants'
import {logEvent, useGate} from '#/lib/statsig/statsig' import {logEvent, useGate} from '#/lib/statsig/statsig'
import {logger} from '#/logger' import {logger} from '#/logger'
import {useOverwriteSavedFeedsMutation} from '#/state/queries/preferences' import {
preferencesQueryKey,
useOverwriteSavedFeedsMutation,
} from '#/state/queries/preferences'
import {RQKEY as profileRQKey} from '#/state/queries/profile'
import {useAgent} from '#/state/session' import {useAgent} from '#/state/session'
import {useOnboardingDispatch} from '#/state/shell' import {useOnboardingDispatch} from '#/state/shell'
import {uploadBlob} from 'lib/api' import {uploadBlob} from 'lib/api'
@ -41,6 +46,7 @@ export function StepFinished() {
const onboardDispatch = useOnboardingDispatch() const onboardDispatch = useOnboardingDispatch()
const [saving, setSaving] = React.useState(false) const [saving, setSaving] = React.useState(false)
const {mutateAsync: overwriteSavedFeeds} = useOverwriteSavedFeedsMutation() const {mutateAsync: overwriteSavedFeeds} = useOverwriteSavedFeedsMutation()
const queryClient = useQueryClient()
const {getAgent} = useAgent() const {getAgent} = useAgent()
const gate = useGate() const gate = useGate()
@ -112,33 +118,41 @@ export function StepFinished() {
]) ])
} }
})(), })(),
])
if (gate('reduced_onboarding_and_home_algo')) { (async () => {
await getAgent().upsertProfile(async existing => { const {imageUri, imageMime} = profileStepResults
existing = existing ?? {} if (imageUri && imageMime) {
const blobPromise = uploadBlob(getAgent(), imageUri, imageMime)
if (profileStepResults.imageUri && profileStepResults.imageMime) { await getAgent().upsertProfile(async existing => {
const res = await uploadBlob( existing = existing ?? {}
getAgent(), const res = await blobPromise
profileStepResults.imageUri, if (res.data.blob) {
profileStepResults.imageMime, existing.avatar = res.data.blob
) }
return existing
if (res.data.blob) { })
existing.avatar = res.data.blob
}
} }
})(),
return existing ])
})
}
} catch (e: any) { } catch (e: any) {
logger.info(`onboarding: bulk save failed`) logger.info(`onboarding: bulk save failed`)
logger.error(e) logger.error(e)
// don't alert the user, just let them into their account // don't alert the user, just let them into their account
} }
// Try to ensure that prefs and profile are up-to-date by the time we render Home.
await Promise.all([
queryClient.invalidateQueries({
queryKey: preferencesQueryKey,
}),
queryClient.invalidateQueries({
queryKey: profileRQKey(getAgent().session?.did ?? ''),
}),
]).catch(e => {
logger.error(e)
// Keep going.
})
setSaving(false) setSaving(false)
dispatch({type: 'finish'}) dispatch({type: 'finish'})
onboardDispatch({type: 'finish'}) onboardDispatch({type: 'finish'})
@ -154,6 +168,7 @@ export function StepFinished() {
track, track,
getAgent, getAgent,
gate, gate,
queryClient,
]) ])
React.useEffect(() => { React.useEffect(() => {

View File

@ -6,6 +6,7 @@ import {
AppBskyActorProfile, AppBskyActorProfile,
AtUri, AtUri,
BskyAgent, BskyAgent,
ComAtprotoRepoUploadBlob,
} from '@atproto/api' } from '@atproto/api'
import { import {
QueryClient, QueryClient,
@ -124,6 +125,26 @@ export function useProfileUpdateMutation() {
newUserBanner, newUserBanner,
checkCommitted, checkCommitted,
}) => { }) => {
let newUserAvatarPromise:
| Promise<ComAtprotoRepoUploadBlob.Response>
| undefined
if (newUserAvatar) {
newUserAvatarPromise = uploadBlob(
getAgent(),
newUserAvatar.path,
newUserAvatar.mime,
)
}
let newUserBannerPromise:
| Promise<ComAtprotoRepoUploadBlob.Response>
| undefined
if (newUserBanner) {
newUserBannerPromise = uploadBlob(
getAgent(),
newUserBanner.path,
newUserBanner.mime,
)
}
await getAgent().upsertProfile(async existing => { await getAgent().upsertProfile(async existing => {
existing = existing || {} existing = existing || {}
if (typeof updates === 'function') { if (typeof updates === 'function') {
@ -132,22 +153,14 @@ export function useProfileUpdateMutation() {
existing.displayName = updates.displayName existing.displayName = updates.displayName
existing.description = updates.description existing.description = updates.description
} }
if (newUserAvatar) { if (newUserAvatarPromise) {
const res = await uploadBlob( const res = await newUserAvatarPromise
getAgent(),
newUserAvatar.path,
newUserAvatar.mime,
)
existing.avatar = res.data.blob existing.avatar = res.data.blob
} else if (newUserAvatar === null) { } else if (newUserAvatar === null) {
existing.avatar = undefined existing.avatar = undefined
} }
if (newUserBanner) { if (newUserBannerPromise) {
const res = await uploadBlob( const res = await newUserBannerPromise
getAgent(),
newUserBanner.path,
newUserBanner.mime,
)
existing.banner = res.data.blob existing.banner = res.data.blob
} else if (newUserBanner === null) { } else if (newUserBanner === null) {
existing.banner = undefined existing.banner = undefined