From 26a3c2c9843c214f7bc662cecc354a505868146f Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Mon, 27 May 2024 15:02:28 +0200 Subject: [PATCH] Rework skeleton to use reanimated instead of moti --- front/packages/primitives/src/skeleton.tsx | 86 +++++++++++++--------- 1 file changed, 52 insertions(+), 34 deletions(-) diff --git a/front/packages/primitives/src/skeleton.tsx b/front/packages/primitives/src/skeleton.tsx index 3470a75d..7dacc764 100644 --- a/front/packages/primitives/src/skeleton.tsx +++ b/front/packages/primitives/src/skeleton.tsx @@ -19,12 +19,20 @@ */ import { LinearGradient as LG } from "expo-linear-gradient"; -import { MotiView, motify } from "moti"; -import { useState } from "react"; -import { Platform, View, type ViewProps } from "react-native"; +import { memo, useEffect } from "react"; +import { Platform, StyleSheet, View, type ViewProps } from "react-native"; +import Animated, { + SharedValue, + useAnimatedStyle, + useDerivedValue, + useSharedValue, + withDelay, + withRepeat, + withTiming, +} from "react-native-reanimated"; import { em, percent, px, rem, useYoshiki } from "yoshiki/native"; -const LinearGradient = motify(LG)(); +const LinearGradient = Animated.createAnimatedComponent(LG); export const SkeletonCss = () => ( ); +const AnimatedGradient = memo( + function Gradient({ color, width }: { color: string; width: SharedValue }) { + const mult = useSharedValue(-1); + const animated = useAnimatedStyle(() => ({ + transform: [ + { + translateX: width.value * mult.value, + }, + ], + })); + + useEffect(() => { + mult.value = withRepeat(withDelay(800, withTiming(1, { duration: 800 })), 0); + }); + + return ( + + ); + }, + function propsAreEqual(prev, next) { + return prev.color === next.color; + }, +); + export const Skeleton = ({ children, show: forcedShow, @@ -55,8 +96,7 @@ export const Skeleton = ({ variant?: "text" | "header" | "round" | "custom" | "fill" | "filltext"; }) => { const { css, theme } = useYoshiki(); - const [width, setWidth] = useState(undefined); - const perc = (v: number) => (v / 100) * width!; + const width = useSharedValue(0); if (forcedShow === undefined && children && children !== true) return <>{children}; @@ -100,13 +140,11 @@ export const Skeleton = ({ > {(forcedShow || !children || children === true) && [...Array(lines)].map((_, i) => ( - setWidth(e.nativeEvent.layout.width)} + onLayout={(e) => { + width.value = e.nativeEvent.layout.width; + }} {...css([ { bg: (theme) => theme.overlay0, @@ -127,28 +165,8 @@ export const Skeleton = ({ }, ])} > - - + + ))} {children}