From 177281fbeb31d6260f7f8a62ac8113a4ac0b670d Mon Sep 17 00:00:00 2001 From: Avinash Lingaloo Date: Fri, 29 Apr 2022 11:41:06 +0400 Subject: [PATCH] cancelled timers on panning start --- app/screens/snack_bar/index.tsx | 58 ++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/app/screens/snack_bar/index.tsx b/app/screens/snack_bar/index.tsx index 1838e5a03f..9b8e798d86 100644 --- a/app/screens/snack_bar/index.tsx +++ b/app/screens/snack_bar/index.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useCallback, useEffect, useMemo, useState} from 'react'; +import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {useIntl} from 'react-intl'; import {DeviceEventEmitter, Text, TouchableOpacity, useWindowDimensions, ViewStyle} from 'react-native'; import {Gesture, GestureDetector, GestureHandlerRootView} from 'react-native-gesture-handler'; @@ -44,8 +44,8 @@ const SnackBar = ({barType, componentId, onUndoPress, sourceScreen}: SnackBarPro const isTablet = useIsTablet(); const {width: windowWidth} = useWindowDimensions(); const offset = useSharedValue(0); - const startY = useSharedValue(0); - const isPanning = useSharedValue(false); + const baseTimer = useRef(); + const dismissTimer = useRef(); const config = SNACK_BAR_CONFIG[barType]; const styles = getStyleSheet(theme); @@ -114,52 +114,56 @@ const SnackBar = ({barType, componentId, onUndoPress, sourceScreen}: SnackBarPro setShowSnackBar(false); }; + const stopTimers = () => { + const timerRefs = [baseTimer, dismissTimer]; + timerRefs.forEach((ref) => { + if (ref.current) { + clearTimeout(ref.current); + } + }); + }; + const gesture = Gesture. // eslint-disable-next-line new-cap Pan(). - onStart((st) => { - startY.value = st.absoluteY; - isPanning.value = true; - }). activeOffsetY(20). - onUpdate((e) => { - if (e.absoluteY >= startY.value) { - offset.value = e.translationY; - } + onStart(() => { + offset.value = withTiming(100, {duration: 200}); + + // animated just started, we'll stop the timer + runOnJS(stopTimers)(); }). onEnd(() => { + // either dismiss it if the position is at the bottom runOnJS(hideSnackBar)(); - isPanning.value = false; + + // or reset the timer if the movement is upward ( translationY -ve ) , then reset the animation reverses... withDecay velocity }); const animateHiding = (forceHiding: boolean) => { const duration = forceHiding ? 0 : 200; - if (!isPanning.value || forceHiding) { - offset.value = withTiming(100, {duration}, () => runOnJS(hideSnackBar)()); - } + offset.value = withTiming(100, {duration}, () => runOnJS(hideSnackBar)()); }; // This effect hides the snack bar after 3 seconds useEffect(() => { setShowSnackBar(true); - const t = setTimeout(() => animateHiding(false), 3000); - return () => clearTimeout(t); + baseTimer.current = setTimeout(() => { + animateHiding(false); + console.log('>>> called from base timer in use effect'); + }, 3000); + return () => { + if (baseTimer.current) { + clearTimeout(baseTimer.current); + } + }; }, []); // This effect dismisses the Navigation Overlay after we have hidden the snack bar useEffect(() => { - let t: NodeJS.Timeout; if (showSnackBar === false) { - t = setTimeout(() => { - dismissOverlay(componentId); - }, 350); + dismissOverlay(componentId); } - - return () => { - if (t) { - clearTimeout(t); - } - }; }, [showSnackBar]); // This effect checks if we are navigating away and if so, it dismisses the snack bar