Files
bsky-social-app/src/components/dialogs/nuxs/InviteFriendsAnnouncement.tsx
T
2026-06-01 12:56:31 -04:00

159 lines
5.2 KiB
TypeScript

import {useCallback, useState} from 'react'
import {View} from 'react-native'
import {LinearGradient} from 'expo-linear-gradient'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {atoms as a, useTheme, web} from '#/alf'
import {Button, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
import {useNuxDialogContext} from '#/components/dialogs/nuxs'
import {Sparkle_Stroke2_Corner0_Rounded as SparkleIcon} from '#/components/icons/Sparkle'
import {Text} from '#/components/Typography'
import {IS_E2E, IS_NATIVE, IS_WEB} from '#/env'
import {InviteFriendsDialog} from '#/features/inviteFriends'
import {createIsEnabledCheck} from './utils'
export const enabled = createIsEnabledCheck(() => {
// Native-only feature (matches the rest of the invite-friends scope).
// Skipped in E2E to keep tests deterministic.
return !IS_E2E && IS_NATIVE
})
export function InviteFriendsAnnouncement() {
const t = useTheme()
const {_} = useLingui()
const nuxDialogs = useNuxDialogContext()
const control = Dialog.useDialogControl()
const inviteFriendsControl = Dialog.useDialogControl()
const [openInviteAfterClose, setOpenInviteAfterClose] = useState(false)
Dialog.useAutoOpen(control)
const onClose = useCallback(() => {
nuxDialogs.dismissActiveNux()
if (openInviteAfterClose) {
// Defer to the next tick so the close animation completes before
// we open the next dialog (avoids visual glitch on iOS).
setOpenInviteAfterClose(false)
inviteFriendsControl.open()
}
}, [nuxDialogs, openInviteAfterClose, inviteFriendsControl])
const onPressTryIt = useCallback(() => {
setOpenInviteAfterClose(true)
control.close()
}, [control])
return (
<>
<Dialog.Outer
control={control}
onClose={onClose}
nativeOptions={{preventExpansion: true}}>
<Dialog.Handle fill={t.palette.primary_400} />
<Dialog.ScrollableInner
label={_(msg`Invite your friends`)}
style={[web({maxWidth: 440})]}
contentContainerStyle={[
{paddingTop: 0, paddingLeft: 0, paddingRight: 0},
]}>
<View
style={[
a.align_center,
a.overflow_hidden,
{
paddingTop: IS_WEB ? 24 : 40,
paddingBottom: 16,
borderTopLeftRadius: a.rounded_md.borderRadius,
borderTopRightRadius: a.rounded_md.borderRadius,
},
]}>
<LinearGradient
colors={[t.palette.primary_100, t.palette.primary_200]}
locations={[0, 1]}
start={{x: 0, y: 0}}
end={{x: 0, y: 1}}
style={[a.absolute, a.inset_0]}
/>
<View style={[a.flex_row, a.align_center, a.gap_xs]}>
<SparkleIcon fill={t.palette.primary_800} size="sm" />
<Text style={[a.font_semi_bold, {color: t.palette.primary_800}]}>
<Trans>New Feature</Trans>
</Text>
</View>
{/*
TODO: drop promo image
*/}
<View
style={{
width: 220,
height: 140,
marginTop: 12,
}}
/>
</View>
<View style={[a.align_center, a.px_xl, a.pt_xl, a.gap_2xl, a.pb_sm]}>
<View style={[a.gap_sm, a.align_center]}>
<Text
style={[
a.text_3xl,
a.leading_tight,
a.font_bold,
a.text_center,
{fontSize: IS_WEB ? 28 : 32, maxWidth: 300},
]}>
<Trans>Invite your friends</Trans>
</Text>
<Text
style={[
a.text_md,
a.leading_snug,
a.text_center,
t.atoms.text_contrast_medium,
{maxWidth: 340},
]}>
<Trans>
You can now invite friends with a link or QR code. Share it
anywhere or let them scan to join you on Bluesky.
</Trans>
</Text>
</View>
{!IS_WEB && (
<View style={[a.w_full, a.gap_sm]}>
<Button
label={_(msg`Try it`)}
size="large"
color="primary"
onPress={onPressTryIt}
style={[a.w_full]}>
<ButtonText>
<Trans>Try it</Trans>
</ButtonText>
</Button>
<Button
label={_(msg`Cancel`)}
size="large"
color="secondary"
onPress={() => control.close()}
style={[a.w_full]}>
<ButtonText>
<Trans>Cancel</Trans>
</ButtonText>
</Button>
</View>
)}
</View>
<Dialog.Close />
</Dialog.ScrollableInner>
</Dialog.Outer>
<InviteFriendsDialog control={inviteFriendsControl} />
</>
)
}