From e1848dca63f46c5ed50685a78471e043c9aba2c3 Mon Sep 17 00:00:00 2001 From: Enes Ozturk Date: Sun, 7 Mar 2021 09:45:27 +0300 Subject: [PATCH] fix: disable calling animations again when they are already active --- example/src/screens/Playground/Playground.tsx | 2 +- src/components/holdItem/HoldItem.tsx | 58 +++++++++++++------ 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/example/src/screens/Playground/Playground.tsx b/example/src/screens/Playground/Playground.tsx index 306dbf9..b4eaf09 100644 --- a/example/src/screens/Playground/Playground.tsx +++ b/example/src/screens/Playground/Playground.tsx @@ -69,7 +69,7 @@ const Playground = ({}: PlaygroundProps) => { ), withSeperator: true, diff --git a/src/components/holdItem/HoldItem.tsx b/src/components/holdItem/HoldItem.tsx index 4d96588..f0d1ea2 100644 --- a/src/components/holdItem/HoldItem.tsx +++ b/src/components/holdItem/HoldItem.tsx @@ -59,6 +59,7 @@ const HoldItemComponent = ({ }: HoldItemProps) => { const { state, menuProps } = useInternal(); const isActive = useSharedValue(false); + const isAnimationStarted = useSharedValue(false); const containerRef = useAnimatedRef(); const itemRectY = useSharedValue(0); @@ -161,6 +162,8 @@ const HoldItemComponent = ({ scaleBack(); } + isAnimationStarted.value = false; + // TODO: Warn user if item list is empty or not given }; @@ -175,6 +178,8 @@ const HoldItemComponent = ({ const scaleTap = () => { 'worklet'; + isAnimationStarted.value = true; + itemScale.value = withSequence( withTiming(HOLD_ITEM_SCALE_DOWN_VALUE, { duration: HOLD_ITEM_SCALE_DOWN_DURATION, @@ -189,23 +194,40 @@ const HoldItemComponent = ({ ); }; + /** + * When use tap activation ("tap") and trying to tap multiple times, + * scale animation is called again despite it is started. This causes a bug. + * To prevent this, it is better to check is animation already started. + */ + const canCallActivateFunctions = () => { + 'worklet'; + const willActivateWithTap = + activateOn === 'double-tap' || activateOn === 'tap'; + + return ( + (willActivateWithTap && !isAnimationStarted.value) || !willActivateWithTap + ); + }; + const gestureEvent = useAnimatedGestureHandler< LongPressGestureHandlerGestureEvent | TapGestureHandlerGestureEvent, Context >({ onActive: (_, context) => { - if (!context.didMeasureLayout) { - activateAnimation(context); - transformValue.value = calculateTransformValue(); - setMenuProps(); - context.didMeasureLayout = true; - } + if (canCallActivateFunctions()) { + if (!context.didMeasureLayout) { + activateAnimation(context); + transformValue.value = calculateTransformValue(); + setMenuProps(); + context.didMeasureLayout = true; + } - if (!isActive.value) { - if (isHold) { - scaleHold(); - } else { - scaleTap(); + if (!isActive.value) { + if (isHold) { + scaleHold(); + } else { + scaleTap(); + } } } }, @@ -290,35 +312,35 @@ const HoldItemComponent = ({ const GestureHandler = useMemo(() => { switch (activateOn) { case `double-tap`: - return ({ children }: GestureHandlerProps) => ( + return ({ children: handlerChildren }: GestureHandlerProps) => ( - {children} + {handlerChildren} ); case `tap`: - return ({ children }: GestureHandlerProps) => ( + return ({ children: handlerChildren }: GestureHandlerProps) => ( - {children} + {handlerChildren} ); // default is hold default: - return ({ children }: GestureHandlerProps) => ( + return ({ children: handlerChildren }: GestureHandlerProps) => ( - {children} + {handlerChildren} ); } - }, [activateOn]); + }, [activateOn, gestureEvent]); return ( <>