Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

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