Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
119
fork

Configure Feed

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

at a876aae44ea07494ebea9727350aa060b81f317b 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}