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 patch-version 179 lines 4.5 kB view raw
1import React from 'react' 2import {View} from 'react-native' 3import Animated, { 4 Easing, 5 LayoutAnimationConfig, 6 useReducedMotion, 7 withTiming, 8} from 'react-native-reanimated' 9import {i18n} from '@lingui/core' 10 11import {decideShouldRoll} from '#/lib/custom-animations/util' 12import {s} from '#/lib/styles' 13import {formatCount} from '#/view/com/util/numeric/format' 14import {Text} from '#/view/com/util/text/Text' 15import {atoms as a, useTheme} from '#/alf' 16 17const animationConfig = { 18 duration: 400, 19 easing: Easing.out(Easing.cubic), 20} 21 22function EnteringUp() { 23 'worklet' 24 const animations = { 25 opacity: withTiming(1, animationConfig), 26 transform: [{translateY: withTiming(0, animationConfig)}], 27 } 28 const initialValues = { 29 opacity: 0, 30 transform: [{translateY: 18}], 31 } 32 return { 33 animations, 34 initialValues, 35 } 36} 37 38function EnteringDown() { 39 'worklet' 40 const animations = { 41 opacity: withTiming(1, animationConfig), 42 transform: [{translateY: withTiming(0, animationConfig)}], 43 } 44 const initialValues = { 45 opacity: 0, 46 transform: [{translateY: -18}], 47 } 48 return { 49 animations, 50 initialValues, 51 } 52} 53 54function ExitingUp() { 55 'worklet' 56 const animations = { 57 opacity: withTiming(0, animationConfig), 58 transform: [ 59 { 60 translateY: withTiming(-18, animationConfig), 61 }, 62 ], 63 } 64 const initialValues = { 65 opacity: 1, 66 transform: [{translateY: 0}], 67 } 68 return { 69 animations, 70 initialValues, 71 } 72} 73 74function ExitingDown() { 75 'worklet' 76 const animations = { 77 opacity: withTiming(0, animationConfig), 78 transform: [{translateY: withTiming(18, animationConfig)}], 79 } 80 const initialValues = { 81 opacity: 1, 82 transform: [{translateY: 0}], 83 } 84 return { 85 animations, 86 initialValues, 87 } 88} 89 90export function CountWheel({ 91 likeCount, 92 big, 93 isLiked, 94 hasBeenToggled, 95}: { 96 likeCount: number 97 big?: boolean 98 isLiked: boolean 99 hasBeenToggled: boolean 100}) { 101 const t = useTheme() 102 const shouldAnimate = !useReducedMotion() && hasBeenToggled 103 const shouldRoll = decideShouldRoll(isLiked, likeCount) 104 105 // Incrementing the key will cause the `Animated.View` to re-render, with the newly selected entering/exiting 106 // animation 107 // The initial entering/exiting animations will get skipped, since these will happen on screen mounts and would 108 // be unnecessary 109 const [key, setKey] = React.useState(0) 110 const [prevCount, setPrevCount] = React.useState(likeCount) 111 const prevIsLiked = React.useRef(isLiked) 112 const formattedCount = formatCount(i18n, likeCount) 113 const formattedPrevCount = formatCount(i18n, prevCount) 114 115 React.useEffect(() => { 116 if (isLiked === prevIsLiked.current) { 117 return 118 } 119 120 const newPrevCount = isLiked ? likeCount - 1 : likeCount + 1 121 setKey(prev => prev + 1) 122 setPrevCount(newPrevCount) 123 prevIsLiked.current = isLiked 124 }, [isLiked, likeCount]) 125 126 const enteringAnimation = 127 shouldAnimate && shouldRoll 128 ? isLiked 129 ? EnteringUp 130 : EnteringDown 131 : undefined 132 const exitingAnimation = 133 shouldAnimate && shouldRoll 134 ? isLiked 135 ? ExitingUp 136 : ExitingDown 137 : undefined 138 139 return ( 140 <LayoutAnimationConfig skipEntering skipExiting> 141 {likeCount > 0 ? ( 142 <View style={[a.justify_center]}> 143 <Animated.View entering={enteringAnimation} key={key}> 144 <Text 145 testID="likeCount" 146 style={[ 147 big ? a.text_md : {fontSize: 15}, 148 a.user_select_none, 149 isLiked 150 ? [a.font_bold, s.likeColor] 151 : {color: t.palette.contrast_500}, 152 ]}> 153 {formattedCount} 154 </Text> 155 </Animated.View> 156 {shouldAnimate && (likeCount > 1 || !isLiked) ? ( 157 <Animated.View 158 entering={exitingAnimation} 159 // Add 2 to the key so there are never duplicates 160 key={key + 2} 161 style={[a.absolute, {width: 50, opacity: 0}]} 162 aria-disabled={true}> 163 <Text 164 style={[ 165 big ? a.text_md : {fontSize: 15}, 166 a.user_select_none, 167 isLiked 168 ? [a.font_bold, s.likeColor] 169 : {color: t.palette.contrast_500}, 170 ]}> 171 {formattedPrevCount} 172 </Text> 173 </Animated.View> 174 ) : null} 175 </View> 176 ) : null} 177 </LayoutAnimationConfig> 178 ) 179}