import { Group, Image, RoundedRect, Shadow, rect, rrect, type SkImage, } from '@shopify/react-native-skia'; import { colors } from '@/aesthetics/styles'; import { useEffect } from 'react'; import { Easing, runOnJS, useDerivedValue, useSharedValue, withDelay, withSpring, withTiming, } from 'react-native-reanimated'; type Position = { x: number; y: number }; type Size = { width: number; height: number }; type Props = { image: SkImage; origin: Position & Size; target: Position & Size; onComplete: () => void; }; const SPRING = { damping: 18, stiffness: 180, mass: 0.8 }; export function FlyingThumbnail({ image, origin, target, onComplete }: Props) { const opacity = useSharedValue(1); const x = useSharedValue(origin.x); const y = useSharedValue(origin.y); const size = useSharedValue(origin.width); const r = useSharedValue(24); useEffect(() => { x.value = withSpring(target.x, SPRING); y.value = withSpring(target.y, SPRING); size.value = withSpring(target.width, SPRING); r.value = withSpring(12, SPRING); opacity.value = withDelay( 350, withTiming(0, { duration: 150, easing: Easing.out(Easing.cubic) }, done => { if (done) runOnJS(onComplete)(); }) ); }, []); const clip = useDerivedValue(() => rrect(rect(0, 0, size.value, size.value), r.value, r.value)); const transform = useDerivedValue(() => [{ translateX: x.value }, { translateY: y.value }]); return ( ); }