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

Configure Feed

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

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