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 118 lines 2.9 kB view raw
1import {useEffect, useRef} from 'react' 2import {View} from 'react-native' 3import {useReducedMotion} from 'react-native-reanimated' 4 5import {useTheme} from '#/alf' 6import { 7 Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled, 8 Heart2_Stroke2_Corner0_Rounded as HeartIconOutline, 9} from '#/components/icons/Heart2' 10 11const animationConfig = { 12 duration: 600, 13 easing: 'cubic-bezier(0.4, 0, 0.2, 1)', 14 fill: 'forwards' as FillMode, 15} 16 17const keyframe = [ 18 {transform: 'scale(1)'}, 19 {transform: 'scale(0.7)'}, 20 {transform: 'scale(1.2)'}, 21 {transform: 'scale(1)'}, 22] 23 24const circle1Keyframe = [ 25 {opacity: 0, transform: 'scale(0)'}, 26 {opacity: 0.4}, 27 {transform: 'scale(1.5)'}, 28 {opacity: 0.4}, 29 {opacity: 0, transform: 'scale(1.5)'}, 30] 31 32const circle2Keyframe = [ 33 {opacity: 0, transform: 'scale(0)'}, 34 {opacity: 1}, 35 {transform: 'scale(0)'}, 36 {opacity: 1}, 37 {opacity: 0, transform: 'scale(1.5)'}, 38] 39 40export function AnimatedLikeIcon({ 41 isLiked, 42 big, 43 hasBeenToggled, 44}: { 45 isLiked: boolean 46 big?: boolean 47 hasBeenToggled: boolean 48}) { 49 const t = useTheme() 50 const size = big ? 22 : 18 51 const shouldAnimate = !useReducedMotion() && hasBeenToggled 52 const prevIsLiked = useRef(isLiked) 53 54 const likeIconRef = useRef<HTMLDivElement>(null) 55 const circle1Ref = useRef<HTMLDivElement>(null) 56 const circle2Ref = useRef<HTMLDivElement>(null) 57 58 useEffect(() => { 59 if (prevIsLiked.current === isLiked) { 60 return 61 } 62 63 if (shouldAnimate && isLiked) { 64 likeIconRef.current?.animate?.(keyframe, animationConfig) 65 circle1Ref.current?.animate?.(circle1Keyframe, animationConfig) 66 circle2Ref.current?.animate?.(circle2Keyframe, animationConfig) 67 } 68 prevIsLiked.current = isLiked 69 }, [shouldAnimate, isLiked]) 70 71 return ( 72 <View> 73 {isLiked ? ( 74 // @ts-expect-error is div 75 <View ref={likeIconRef}> 76 <HeartIconFilled style={{color: t.palette.pink}} width={size} /> 77 </View> 78 ) : ( 79 <HeartIconOutline 80 style={[{color: t.palette.contrast_500}, {pointerEvents: 'none'}]} 81 width={size} 82 /> 83 )} 84 <View 85 // @ts-expect-error is div 86 ref={circle1Ref} 87 style={{ 88 position: 'absolute', 89 backgroundColor: t.palette.pink, 90 top: 0, 91 left: 0, 92 width: size, 93 height: size, 94 zIndex: -1, 95 pointerEvents: 'none', 96 borderRadius: size / 2, 97 opacity: 0, 98 }} 99 /> 100 <View 101 // @ts-expect-error is div 102 ref={circle2Ref} 103 style={{ 104 position: 'absolute', 105 backgroundColor: t.atoms.bg.backgroundColor, 106 top: 0, 107 left: 0, 108 width: size, 109 height: size, 110 zIndex: -1, 111 pointerEvents: 'none', 112 borderRadius: size / 2, 113 opacity: 0, 114 }} 115 /> 116 </View> 117 ) 118}