mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
0
fork

Configure Feed

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

at push-notifications 134 lines 3.1 kB view raw
1import React, {createRef, useState, useMemo} from 'react' 2import { 3 Animated, 4 StyleSheet, 5 TouchableWithoutFeedback, 6 View, 7} from 'react-native' 8import {Text} from './text/Text' 9import {usePalette} from '../../lib/hooks/usePalette' 10 11interface Layout { 12 x: number 13 width: number 14} 15 16export function Selector({ 17 selectedIndex, 18 items, 19 panX, 20 onSelect, 21}: { 22 selectedIndex: number 23 items: string[] 24 panX: Animated.Value 25 onSelect?: (index: number) => void 26}) { 27 const pal = usePalette('default') 28 const [itemLayouts, setItemLayouts] = useState<undefined | Layout[]>( 29 undefined, 30 ) 31 const itemRefs = useMemo( 32 () => Array.from({length: items.length}).map(() => createRef<View>()), 33 [items.length], 34 ) 35 36 const currentLayouts = useMemo(() => { 37 const left = itemLayouts?.[selectedIndex - 1] || {x: 0, width: 0} 38 const middle = itemLayouts?.[selectedIndex] || {x: 0, width: 0} 39 const right = itemLayouts?.[selectedIndex + 1] || { 40 x: middle.x + 20, 41 width: middle.width, 42 } 43 return [left, middle, right] 44 }, [selectedIndex, itemLayouts]) 45 46 const underlineStyle = { 47 backgroundColor: pal.colors.text, 48 left: panX.interpolate({ 49 inputRange: [-1, 0, 1], 50 outputRange: [ 51 currentLayouts[0].x, 52 currentLayouts[1].x, 53 currentLayouts[2].x, 54 ], 55 }), 56 width: panX.interpolate({ 57 inputRange: [-1, 0, 1], 58 outputRange: [ 59 currentLayouts[0].width, 60 currentLayouts[1].width, 61 currentLayouts[2].width, 62 ], 63 }), 64 } 65 66 const onLayout = () => { 67 const promises = [] 68 for (let i = 0; i < items.length; i++) { 69 promises.push( 70 new Promise<Layout>(resolve => { 71 itemRefs[i].current?.measure( 72 (x: number, _y: number, width: number) => { 73 resolve({x, width}) 74 }, 75 ) 76 }), 77 ) 78 } 79 Promise.all(promises).then((layouts: Layout[]) => { 80 setItemLayouts(layouts) 81 }) 82 } 83 84 const onPressItem = (index: number) => { 85 onSelect?.(index) 86 } 87 88 return ( 89 <View style={[pal.view, styles.outer]} onLayout={onLayout}> 90 <Animated.View style={[styles.underline, underlineStyle]} /> 91 {items.map((item, i) => { 92 const selected = i === selectedIndex 93 return ( 94 <TouchableWithoutFeedback key={i} onPress={() => onPressItem(i)}> 95 <View style={styles.item} ref={itemRefs[i]}> 96 <Text 97 style={ 98 selected 99 ? [styles.labelSelected, pal.text] 100 : [styles.label, pal.textLight] 101 }> 102 {item} 103 </Text> 104 </View> 105 </TouchableWithoutFeedback> 106 ) 107 })} 108 </View> 109 ) 110} 111 112const styles = StyleSheet.create({ 113 outer: { 114 flexDirection: 'row', 115 paddingTop: 8, 116 paddingBottom: 12, 117 paddingHorizontal: 14, 118 }, 119 item: { 120 marginRight: 14, 121 paddingHorizontal: 10, 122 }, 123 label: { 124 fontWeight: '600', 125 }, 126 labelSelected: { 127 fontWeight: '600', 128 }, 129 underline: { 130 position: 'absolute', 131 height: 4, 132 bottom: 0, 133 }, 134})