Colocate invite dialog handoff in InviteFriendsAnnouncement instead of NUX context
This commit is contained in:
@@ -4,6 +4,7 @@ import {Image} from 'expo-image'
|
||||
import {Trans, useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {useCallOnce} from '#/lib/once'
|
||||
import {Nux} from '#/state/queries/nuxs'
|
||||
import {atoms as a, useTheme, web} from '#/alf'
|
||||
import {themes} from '#/alf/themes'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
@@ -13,6 +14,7 @@ import {Sparkle_Stroke2_Corner0_Rounded as SparkleIcon} from '#/components/icons
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_E2E, IS_NATIVE, IS_WEB} from '#/env'
|
||||
import {InviteFriendsDialog} from '#/features/inviteFriends'
|
||||
import {createIsEnabledCheck} from './utils'
|
||||
|
||||
export const enabled = createIsEnabledCheck(() => {
|
||||
@@ -22,6 +24,30 @@ export const enabled = createIsEnabledCheck(() => {
|
||||
})
|
||||
|
||||
export function InviteFriendsAnnouncement() {
|
||||
const {activeNux} = useNuxDialogContext()
|
||||
/*
|
||||
* The invite dialog's control lives here (outside the activeNux
|
||||
* conditional) so the dialog survives the announcement being dismissed
|
||||
* during the "Try it" handoff - the native bottom sheet cannot hand off to
|
||||
* a second sheet that unmounts along with the first.
|
||||
*/
|
||||
const inviteFriendsControl = Dialog.useDialogControl()
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeNux === Nux.InviteFriendsAnnouncement && (
|
||||
<Announcement inviteFriendsControl={inviteFriendsControl} />
|
||||
)}
|
||||
<InviteFriendsDialog control={inviteFriendsControl} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function Announcement({
|
||||
inviteFriendsControl,
|
||||
}: {
|
||||
inviteFriendsControl: Dialog.DialogControlProps
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
@@ -43,15 +69,18 @@ export function InviteFriendsAnnouncement() {
|
||||
|
||||
const onPressTryIt = useCallback(() => {
|
||||
ax.metric('invite:nux:tryItPressed', {})
|
||||
// Close this announcement (which dismisses + unmounts the NUX), then open
|
||||
// the invite dialog. The invite dialog is mounted persistently by NuxDialogs
|
||||
// (not here) so it survives the dismissal - the native bottom sheet cannot
|
||||
// hand off to a second sheet mounted in this same subtree. Defer the open to
|
||||
// the next frame so the announcement's teardown completes first.
|
||||
// Close this announcement (which dismisses the NUX and unmounts this
|
||||
// component), then open the invite dialog. Its control lives in the
|
||||
// parent, which stays mounted, so the dialog survives the dismissal.
|
||||
// Defer the open to the next frame so the announcement's teardown
|
||||
// completes first.
|
||||
control.close(() => {
|
||||
requestAnimationFrame(() => nuxDialogs.openInviteFriends())
|
||||
requestAnimationFrame(() => {
|
||||
ax.metric('invite:dialog:open', {logContext: 'NuxAnnouncement'})
|
||||
inviteFriendsControl.open()
|
||||
})
|
||||
})
|
||||
}, [ax, control, nuxDialogs])
|
||||
}, [ax, control, inviteFriendsControl])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
import {useProfileQuery} from '#/state/queries/profile'
|
||||
import {type SessionAccount, useSession} from '#/state/session'
|
||||
import {useOnboardingState} from '#/state/shell'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {
|
||||
DraftsAnnouncement,
|
||||
enabled as isDraftsAnnouncementEnabled,
|
||||
@@ -30,19 +29,11 @@ import {
|
||||
import {isSnoozed, snooze, unsnooze} from '#/components/dialogs/nuxs/snoozing'
|
||||
import {type EnabledCheckProps} from '#/components/dialogs/nuxs/utils'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {InviteFriendsDialog} from '#/features/inviteFriends'
|
||||
import {useGeolocation} from '#/geolocation'
|
||||
|
||||
type Context = {
|
||||
activeNux: Nux | undefined
|
||||
dismissActiveNux: () => void
|
||||
/**
|
||||
* Opens the invite-friends dialog. It is mounted persistently by NuxDialogs
|
||||
* (not inside the announcement NUX) so it survives the announcement being
|
||||
* dismissed - the native bottom sheet cannot hand off between two sheets
|
||||
* mounted in the same subtree.
|
||||
*/
|
||||
openInviteFriends: () => void
|
||||
}
|
||||
|
||||
const queuedNuxs: {
|
||||
@@ -62,7 +53,6 @@ const queuedNuxs: {
|
||||
const Context = createContext<Context>({
|
||||
activeNux: undefined,
|
||||
dismissActiveNux: () => {},
|
||||
openInviteFriends: () => {},
|
||||
})
|
||||
Context.displayName = 'NuxDialogContext'
|
||||
|
||||
@@ -115,7 +105,6 @@ function Inner({
|
||||
const [activeNux, setActiveNux] = useState<Nux | undefined>()
|
||||
const {mutateAsync: saveNux} = useSaveNux()
|
||||
const {mutate: resetNuxs} = useResetNuxs()
|
||||
const inviteFriendsControl = Dialog.useDialogControl()
|
||||
|
||||
const snoozeNuxDialog = useCallback(() => {
|
||||
snooze()
|
||||
@@ -199,26 +188,19 @@ function Inner({
|
||||
return {
|
||||
activeNux,
|
||||
dismissActiveNux,
|
||||
openInviteFriends: () => {
|
||||
ax.metric('invite:dialog:open', {logContext: 'NuxAnnouncement'})
|
||||
inviteFriendsControl.open()
|
||||
},
|
||||
}
|
||||
}, [ax, activeNux, dismissActiveNux, inviteFriendsControl])
|
||||
}, [activeNux, dismissActiveNux])
|
||||
|
||||
return (
|
||||
<Context.Provider value={ctx}>
|
||||
{/*For example, activeNux === Nux.NeueTypography && <NeueTypography />*/}
|
||||
{activeNux === Nux.DraftsAnnouncement && <DraftsAnnouncement />}
|
||||
{activeNux === Nux.InviteFriendsAnnouncement && (
|
||||
<InviteFriendsAnnouncement />
|
||||
)}
|
||||
{/*
|
||||
Mounted persistently (not inside the announcement) so the invite dialog
|
||||
survives the announcement NUX being dismissed during the "Try it"
|
||||
handoff.
|
||||
Mounted unconditionally: it gates the announcement on `activeNux`
|
||||
internally, so it can keep the invite-friends dialog mounted across
|
||||
the announcement's dismissal during the "Try it" handoff.
|
||||
*/}
|
||||
<InviteFriendsDialog control={inviteFriendsControl} />
|
||||
<InviteFriendsAnnouncement />
|
||||
</Context.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user