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

Configure Feed

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

at main 127 lines 3.2 kB view raw
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}