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