Bluesky app fork with some witchin' additions 馃挮
at main 254 lines 8.5 kB view raw
1import {useEffect, useState} from 'react' 2import {Pressable, View} from 'react-native' 3import {ImageBackground} from 'expo-image' 4import {msg} from '@lingui/core/macro' 5import {useLingui} from '@lingui/react' 6import {Trans} from '@lingui/react/macro' 7import {FocusGuards, FocusScope} from 'radix-ui/internal' 8 9import {useLoggedOutViewControls} from '#/state/shell/logged-out' 10import {Logo} from '#/view/icons/Logo' 11import {atoms as a, flatten, useBreakpoints, useTheme, web} from '#/alf' 12import {Button, ButtonText} from '#/components/Button' 13import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times' 14import {Text} from '#/components/Typography' 15import {useAnalytics} from '#/analytics' 16 17const welcomeModalBg = require('../../assets/images/welcome-modal-bg.webp') 18 19interface WelcomeModalProps { 20 control: { 21 isOpen: boolean 22 open: () => void 23 close: () => void 24 } 25} 26 27export function WelcomeModal({control}: WelcomeModalProps) { 28 const {_} = useLingui() 29 const ax = useAnalytics() 30 const {requestSwitchToAccount} = useLoggedOutViewControls() 31 const {gtMobile} = useBreakpoints() 32 const [isExiting, setIsExiting] = useState(false) 33 const [signInLinkHovered, setSignInLinkHovered] = useState(false) 34 const t = useTheme() 35 36 const fadeOutAndClose = (callback?: () => void) => { 37 setIsExiting(true) 38 setTimeout(() => { 39 control.close() 40 if (callback) callback() 41 }, 150) 42 } 43 44 useEffect(() => { 45 if (control.isOpen) { 46 ax.metric('welcomeModal:presented', {}) 47 } 48 // eslint-disable-next-line react-hooks/exhaustive-deps 49 }, [control.isOpen]) 50 51 const onPressCreateAccount = () => { 52 ax.metric('welcomeModal:signupClicked', {}) 53 control.close() 54 requestSwitchToAccount({requestedAccount: 'new'}) 55 } 56 57 const onPressExplore = () => { 58 ax.metric('welcomeModal:exploreClicked', {}) 59 fadeOutAndClose() 60 } 61 62 const onPressSignIn = () => { 63 ax.metric('welcomeModal:signinClicked', {}) 64 control.close() 65 requestSwitchToAccount({requestedAccount: 'existing'}) 66 } 67 68 FocusGuards.useFocusGuards() 69 70 return ( 71 <View 72 role="dialog" 73 aria-modal 74 style={[ 75 a.fixed, 76 a.inset_0, 77 a.justify_center, 78 a.align_center, 79 {zIndex: 9999, backgroundColor: 'rgba(0,0,0,0.2)'}, 80 web({backdropFilter: 'blur(15px)'}), 81 isExiting ? a.fade_out : a.fade_in, 82 ]}> 83 <FocusScope.FocusScope asChild loop trapped> 84 <View 85 style={flatten([ 86 { 87 maxWidth: 800, 88 maxHeight: 600, 89 width: '90%', 90 height: '90%', 91 backgroundColor: '#c0cdec', 92 }, 93 a.rounded_lg, 94 a.overflow_hidden, 95 a.zoom_in, 96 ])}> 97 <ImageBackground 98 source={welcomeModalBg} 99 style={[a.flex_1, a.justify_center]} 100 contentFit="cover"> 101 <View style={[a.gap_2xl, a.align_center, a.p_4xl]}> 102 <View 103 style={[ 104 a.flex_row, 105 a.align_center, 106 a.justify_center, 107 a.w_full, 108 a.p_0, 109 ]}> 110 <View style={[a.flex_row, a.align_center, a.gap_xs]}> 111 <Logo width={26} /> 112 <Text 113 style={[ 114 a.text_2xl, 115 a.font_semi_bold, 116 a.user_select_none, 117 {color: 'rgb(42, 40, 40)', letterSpacing: -0.5}, 118 ]}> 119 Witchsky 120 </Text> 121 </View> 122 </View> 123 <View 124 style={[ 125 a.gap_sm, 126 a.align_center, 127 a.pt_5xl, 128 a.pb_3xl, 129 a.mt_2xl, 130 ]}> 131 <Text 132 style={[ 133 gtMobile ? a.text_4xl : a.text_3xl, 134 a.font_semi_bold, 135 a.text_center, 136 {color: 'rgb(55, 45, 45)'}, 137 web({ 138 backgroundImage: 139 'linear-gradient(180deg, rgb(87, 77, 77) 0%, rgb(95, 68, 68) 83.65%, rgba(107, 68, 68, 0.47) 100%)', 140 backgroundClip: 'text', 141 WebkitBackgroundClip: 'text', 142 WebkitTextFillColor: 'transparent', 143 color: 'transparent', 144 lineHeight: 1.2, 145 letterSpacing: -0.5, 146 }), 147 ]}> 148 <Trans>Real talk.</Trans> 149 {'\n'} 150 <Trans>Real creatures.</Trans> 151 {'\n'} 152 <Trans>Social media if it was good.</Trans> 153 </Text> 154 </View> 155 <View style={[a.gap_md, a.align_center]}> 156 <View> 157 <Button 158 onPress={onPressCreateAccount} 159 label={_(msg`Create account`)} 160 size="large" 161 color="primary" 162 style={{ 163 width: 200, 164 backgroundColor: t.palette.primary_500, 165 }}> 166 <ButtonText> 167 <Trans>Create account</Trans> 168 </ButtonText> 169 </Button> 170 <Button 171 onPress={onPressExplore} 172 label={_(msg`Explore the app`)} 173 size="large" 174 color="primary" 175 variant="ghost" 176 style={[a.bg_transparent, {width: 200}]} 177 hoverStyle={[a.bg_transparent]}> 178 {({hovered}) => ( 179 <ButtonText 180 style={[ 181 hovered && [a.underline], 182 {color: t.palette.primary_500}, 183 ]}> 184 <Trans>Explore the app</Trans> 185 </ButtonText> 186 )} 187 </Button> 188 </View> 189 <View style={[a.align_center, {minWidth: 200}]}> 190 <Text 191 style={[ 192 a.text_md, 193 a.text_center, 194 {color: 'rgb(58, 50, 50)', lineHeight: 24}, 195 ]}> 196 <Trans>Already have an account?</Trans>{' '} 197 <Pressable 198 onPointerEnter={() => setSignInLinkHovered(true)} 199 onPointerLeave={() => setSignInLinkHovered(false)} 200 accessibilityRole="button" 201 accessibilityLabel={_(msg`Sign in`)} 202 accessibilityHint=""> 203 <Text 204 style={[ 205 a.font_medium, 206 { 207 color: t.palette.primary_500, 208 fontSize: undefined, 209 }, 210 signInLinkHovered && a.underline, 211 ]} 212 onPress={onPressSignIn}> 213 <Trans>Sign in</Trans> 214 </Text> 215 </Pressable> 216 </Text> 217 </View> 218 </View> 219 </View> 220 <Button 221 label={_(msg`Close welcome modal`)} 222 style={[ 223 a.absolute, 224 { 225 top: 8, 226 right: 8, 227 }, 228 a.bg_transparent, 229 ]} 230 hoverStyle={[a.bg_transparent]} 231 onPress={() => { 232 ax.metric('welcomeModal:dismissed', {}) 233 fadeOutAndClose() 234 }} 235 color="secondary" 236 size="small" 237 variant="ghost" 238 shape="round"> 239 {({hovered, pressed, focused}) => ( 240 <XIcon 241 size="md" 242 style={{ 243 color: 'rgb(77, 47, 47)', 244 opacity: hovered || pressed || focused ? 1 : 0.7, 245 }} 246 /> 247 )} 248 </Button> 249 </ImageBackground> 250 </View> 251 </FocusScope.FocusScope> 252 </View> 253 ) 254}