Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
119
fork

Configure Feed

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

at a876aae44ea07494ebea9727350aa060b81f317b 131 lines 2.8 kB view raw
1import {View} from 'react-native' 2import Animated, { 3 Keyframe, 4 LayoutAnimationConfig, 5 useReducedMotion, 6} from 'react-native-reanimated' 7 8import {useTheme} from '#/alf' 9import { 10 Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled, 11 Heart2_Stroke2_Corner0_Rounded as HeartIconOutline, 12} from '#/components/icons/Heart2' 13 14const keyframe = new Keyframe({ 15 0: { 16 transform: [{scale: 1}], 17 }, 18 10: { 19 transform: [{scale: 0.7}], 20 }, 21 40: { 22 transform: [{scale: 1.2}], 23 }, 24 100: { 25 transform: [{scale: 1}], 26 }, 27}) 28 29const circle1Keyframe = new Keyframe({ 30 0: { 31 opacity: 0, 32 transform: [{scale: 0}], 33 }, 34 10: { 35 opacity: 0.4, 36 }, 37 40: { 38 transform: [{scale: 1.5}], 39 }, 40 95: { 41 opacity: 0.4, 42 }, 43 100: { 44 opacity: 0, 45 transform: [{scale: 1.5}], 46 }, 47}) 48 49const circle2Keyframe = new Keyframe({ 50 0: { 51 opacity: 0, 52 transform: [{scale: 0}], 53 }, 54 10: { 55 opacity: 1, 56 }, 57 40: { 58 transform: [{scale: 0}], 59 }, 60 95: { 61 opacity: 1, 62 }, 63 100: { 64 opacity: 0, 65 transform: [{scale: 1.5}], 66 }, 67}) 68 69export function AnimatedLikeIcon({ 70 isLiked, 71 big, 72 hasBeenToggled, 73}: { 74 isLiked: boolean 75 big?: boolean 76 hasBeenToggled: boolean 77}) { 78 const t = useTheme() 79 const size = big ? 22 : 18 80 const shouldAnimate = !useReducedMotion() && hasBeenToggled 81 82 return ( 83 <View> 84 <LayoutAnimationConfig skipEntering> 85 {isLiked ? ( 86 <Animated.View 87 entering={shouldAnimate ? keyframe.duration(300) : undefined}> 88 <HeartIconFilled style={{color: t.palette.pink}} width={size} /> 89 </Animated.View> 90 ) : ( 91 <HeartIconOutline 92 style={[{color: t.palette.contrast_500}, {pointerEvents: 'none'}]} 93 width={size} 94 /> 95 )} 96 {isLiked && shouldAnimate ? ( 97 <> 98 <Animated.View 99 entering={circle1Keyframe.duration(300)} 100 style={{ 101 position: 'absolute', 102 backgroundColor: t.palette.pink, 103 top: 0, 104 left: 0, 105 width: size, 106 height: size, 107 zIndex: -1, 108 pointerEvents: 'none', 109 borderRadius: size / 2, 110 }} 111 /> 112 <Animated.View 113 entering={circle2Keyframe.duration(300)} 114 style={{ 115 position: 'absolute', 116 backgroundColor: t.atoms.bg.backgroundColor, 117 top: 0, 118 left: 0, 119 width: size, 120 height: size, 121 zIndex: -1, 122 pointerEvents: 'none', 123 borderRadius: size / 2, 124 }} 125 /> 126 </> 127 ) : null} 128 </LayoutAnimationConfig> 129 </View> 130 ) 131}