forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useRef, useState} from 'react'
2import {View} from 'react-native'
3import PagerView from 'react-native-pager-view'
4import {Image} from 'expo-image'
5import {msg} from '@lingui/core/macro'
6import {useLingui} from '@lingui/react'
7
8import {atoms as a, tokens, useTheme} from '#/alf'
9import {Text} from '#/components/Typography'
10import {PROP_1, PROP_2, PROP_3} from './images'
11import {Dot, useValuePropText} from './ValuePropositionPager.shared'
12
13export function ValuePropositionPager({
14 step,
15 setStep,
16 avatarUri,
17}: {
18 step: 0 | 1 | 2
19 setStep: (step: 0 | 1 | 2) => void
20 avatarUri?: string
21}) {
22 const t = useTheme()
23 const [activePage, setActivePage] = useState(step)
24 const ref = useRef<PagerView>(null)
25
26 if (step !== activePage) {
27 setActivePage(step)
28 ref.current?.setPage(step)
29 }
30
31 const images = [PROP_1[t.name], PROP_2[t.name], PROP_3[t.name]]
32
33 return (
34 <View style={[a.h_full, {marginHorizontal: tokens.space.xl * -1}]}>
35 <PagerView
36 ref={ref}
37 style={[a.flex_1]}
38 initialPage={step}
39 onPageSelected={evt => {
40 const page = evt.nativeEvent.position as 0 | 1 | 2
41 if (step !== page) {
42 setActivePage(page)
43 setStep(page)
44 }
45 }}>
46 {([0, 1, 2] as const).map(page => (
47 <Page
48 key={page}
49 page={page}
50 image={images[page]}
51 avatarUri={avatarUri}
52 />
53 ))}
54 </PagerView>
55 </View>
56 )
57}
58
59function Page({
60 page,
61 image,
62 avatarUri,
63}: {
64 page: 0 | 1 | 2
65 image: string
66 avatarUri?: string
67}) {
68 const {_} = useLingui()
69 const t = useTheme()
70 const {title, description, alt} = useValuePropText(page)
71
72 return (
73 <View key={page}>
74 <View
75 style={[
76 a.relative,
77 a.align_center,
78 a.justify_center,
79 a.pointer_events_none,
80 ]}>
81 <Image
82 source={image}
83 style={[a.w_full, a.aspect_square]}
84 alt={alt}
85 accessibilityIgnoresInvertColors={false} // I guess we do need it to blend into the background
86 />
87 {page === 1 && (
88 <Image
89 source={avatarUri}
90 style={[
91 a.z_10,
92 a.absolute,
93 a.rounded_full,
94 {
95 width: `${(80 / 393) * 100}%`,
96 height: `${(80 / 393) * 100}%`,
97 },
98 ]}
99 accessibilityIgnoresInvertColors
100 alt={_(msg`Your profile picture`)}
101 />
102 )}
103 </View>
104
105 <View style={[a.mt_4xl, a.gap_2xl, a.px_xl, a.align_center]}>
106 <View style={[a.flex_row, a.gap_sm]}>
107 <Dot active={page === 0} />
108 <Dot active={page === 1} />
109 <Dot active={page === 2} />
110 </View>
111
112 <View style={[a.gap_sm]}>
113 <Text style={[a.font_bold, a.text_3xl, a.text_center]}>{title}</Text>
114 <Text
115 style={[
116 t.atoms.text_contrast_medium,
117 a.text_md,
118 a.leading_snug,
119 a.text_center,
120 ]}>
121 {description}
122 </Text>
123 </View>
124 </View>
125 </View>
126 )
127}