forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
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} 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.jpg') // TODO: Xan: Change background to something cuter
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
33 const fadeOutAndClose = (callback?: () => void) => {
34 setIsExiting(true)
35 setTimeout(() => {
36 control.close()
37 if (callback) callback()
38 }, 150)
39 }
40
41 useEffect(() => {
42 if (control.isOpen) {
43 logger.metric('welcomeModal:presented', {})
44 }
45 }, [control.isOpen])
46
47 const onPressCreateAccount = () => {
48 logger.metric('welcomeModal:signupClicked', {})
49 control.close()
50 requestSwitchToAccount({requestedAccount: 'new'})
51 }
52
53 const onPressExplore = () => {
54 logger.metric('welcomeModal:exploreClicked', {})
55 fadeOutAndClose()
56 }
57
58 const onPressSignIn = () => {
59 logger.metric('welcomeModal:signinClicked', {})
60 control.close()
61 requestSwitchToAccount({requestedAccount: 'existing'})
62 }
63
64 FocusGuards.useFocusGuards()
65
66 return (
67 <View
68 role="dialog"
69 aria-modal
70 style={[
71 a.fixed,
72 a.inset_0,
73 a.justify_center,
74 a.align_center,
75 {zIndex: 9999, backgroundColor: 'rgba(0,0,0,0.2)'},
76 web({backdropFilter: 'blur(15px)'}),
77 isExiting ? a.fade_out : a.fade_in,
78 ]}>
79 <FocusScope.FocusScope asChild loop trapped>
80 <View
81 style={flatten([
82 {
83 maxWidth: 800,
84 maxHeight: 600,
85 width: '90%',
86 height: '90%',
87 backgroundColor: '#716066',
88 },
89 a.rounded_lg,
90 a.overflow_hidden,
91 a.zoom_in,
92 ])}>
93 <ImageBackground
94 source={welcomeModalBg}
95 style={[a.flex_1, a.justify_center]}
96 contentFit="cover">
97 <View style={[a.gap_2xl, a.align_center, a.p_4xl]}>
98 <View
99 style={[
100 a.flex_row,
101 a.align_center,
102 a.justify_center,
103 a.w_full,
104 a.p_0,
105 ]}>
106 <View style={[a.flex_row, a.align_center, a.gap_xs]}>
107 <Logo width={26} />
108 <Text
109 style={[
110 a.text_2xl,
111 a.font_semi_bold,
112 a.user_select_none,
113 {color: '#ff9696ff', letterSpacing: -0.5},
114 ]}>
115 Witchsky
116 </Text>
117 </View>
118 </View>
119 <View
120 style={[
121 a.gap_sm,
122 a.align_center,
123 a.pt_5xl,
124 a.pb_3xl,
125 a.mt_2xl,
126 ]}>
127 <Text
128 style={[
129 gtMobile ? a.text_4xl : a.text_3xl,
130 a.font_semi_bold,
131 a.text_center,
132 {color: '#583535ff'},
133 web({
134 backgroundImage:
135 'linear-gradient(180deg, #ffd8d8ff 0%, #eca8a8ff 83.65%, rgba(233, 165, 165, 0.47) 100%)',
136 backgroundClip: 'text',
137 WebkitBackgroundClip: 'text',
138 WebkitTextFillColor: 'transparent',
139 color: 'transparent',
140 lineHeight: 1.2,
141 letterSpacing: -0.5,
142 }),
143 ]}>
144 <Trans>Real talk.</Trans>
145 {'\n'}
146 <Trans>Real creatures.</Trans>
147 {'\n'}
148 <Trans>Social media if it was good.</Trans>
149 </Text>
150 </View>
151 <View style={[a.gap_md, a.align_center]}>
152 <View>
153 <Button
154 onPress={onPressCreateAccount}
155 label={_(msg`Create account`)}
156 size="large"
157 color="primary"
158 style={{
159 width: 200,
160 backgroundColor: '#BB6868',
161 }}>
162 <ButtonText>
163 <Trans>Create account</Trans>
164 </ButtonText>
165 </Button>
166 <Button
167 onPress={onPressExplore}
168 label={_(msg`Explore the app`)}
169 size="large"
170 color="primary"
171 variant="ghost"
172 style={[a.bg_transparent, {width: 200}]}
173 hoverStyle={[a.bg_transparent]}>
174 {({hovered}) => (
175 <ButtonText
176 style={[hovered && [a.underline], {color: '#ff9191'}]}>
177 <Trans>Explore the app</Trans>
178 </ButtonText>
179 )}
180 </Button>
181 </View>
182 <View style={[a.align_center, {minWidth: 200}]}>
183 <Text
184 style={[
185 a.text_md,
186 a.text_center,
187 {color: '#ffe3e3ff', lineHeight: 24},
188 ]}>
189 <Trans>Already have an account?</Trans>{' '}
190 <Pressable
191 onPointerEnter={() => setSignInLinkHovered(true)}
192 onPointerLeave={() => setSignInLinkHovered(false)}
193 accessibilityRole="button"
194 accessibilityLabel={_(msg`Sign in`)}
195 accessibilityHint="">
196 <Text
197 style={[
198 a.font_medium,
199 {
200 color: '#ff9191',
201 fontSize: undefined,
202 },
203 signInLinkHovered && a.underline,
204 ]}
205 onPress={onPressSignIn}>
206 <Trans>Sign in</Trans>
207 </Text>
208 </Pressable>
209 </Text>
210 </View>
211 </View>
212 </View>
213 <Button
214 label={_(msg`Close welcome modal`)}
215 style={[
216 a.absolute,
217 {
218 top: 8,
219 right: 8,
220 },
221 a.bg_transparent,
222 ]}
223 hoverStyle={[a.bg_transparent]}
224 onPress={() => {
225 logger.metric('welcomeModal:dismissed', {})
226 fadeOutAndClose()
227 }}
228 color="secondary"
229 size="small"
230 variant="ghost"
231 shape="round">
232 {({hovered, pressed, focused}) => (
233 <XIcon
234 size="md"
235 style={{
236 color: '#ffe3e3ff',
237 opacity: hovered || pressed || focused ? 1 : 0.7,
238 }}
239 />
240 )}
241 </Button>
242 </ImageBackground>
243 </View>
244 </FocusScope.FocusScope>
245 </View>
246 )
247}