diff --git a/native/navigation/tooltip.react.js b/native/navigation/tooltip.react.js --- a/native/navigation/tooltip.react.js +++ b/native/navigation/tooltip.react.js @@ -15,7 +15,13 @@ TouchableOpacity, Keyboard, } from 'react-native'; -import Animated from 'react-native-reanimated'; +import Animated, { + SlideInDown, + SlideOutDown, + runOnJS, + useSharedValue, + type SharedValue, +} from 'react-native-reanimated'; import { useDispatch } from 'react-redux'; import { @@ -118,8 +124,10 @@ +inputState: ?InputState, +chatContext: ?ChatContextType, +showActionSheetWithOptions: ShowActionSheetWithOptions, - +actionSheetShown: boolean, - +setActionSheetShown: (actionSheetShown: boolean) => void, + +actionSheetShown: SharedValue, + +hideTooltip: boolean, + +setHideTooltip: (hideTooltip: boolean) => void, + +exitAnimationWorklet: (finished: boolean) => void, +styles: typeof unboundStyles, }; @@ -327,7 +335,10 @@ style.position = 'absolute'; (style.alignItems = 'center'), (style.opacity = this.tooltipContainerOpacity); - style.transform = [{ translateX: this.tooltipHorizontal }]; + + if (location !== 'fixed') { + style.transform = [{ translateX: this.tooltipHorizontal }]; + } const extraLeftSpace = x; const extraRightSpace = dimensions.width - width - x; @@ -364,7 +375,9 @@ style.transform.push({ translateY: this.tooltipVerticalBelow }); } - style.transform.push({ scale: this.tooltipScale }); + if (location !== 'fixed') { + style.transform.push({ scale: this.tooltipScale }); + } return style; } @@ -381,7 +394,9 @@ chatContext, showActionSheetWithOptions, actionSheetShown, - setActionSheetShown, + hideTooltip, + setHideTooltip, + exitAnimationWorklet, styles, ...navAndRouteForFlow } = this.props; @@ -471,15 +486,36 @@ isOpeningSidebar, }; - const itemsStyle = [styles.items]; + const itemsStyles = [styles.items, styles.itemsFixed]; - if (this.location === 'fixed') { - itemsStyle.push(styles.itemsFixed); - } + const animationDelay = Platform.OS === 'ios' ? 200 : 500; + const enterAnimation = SlideInDown.delay(animationDelay); - let tooltip = {items}; - if (this.props.actionSheetShown) { - tooltip = null; + const exitAnimation = SlideOutDown.withCallback(exitAnimationWorklet); + + let tooltip = null; + + if (this.location !== 'fixed') { + tooltip = ( + + {triangleUp} + {items} + {triangleDown} + + ); + } else if (this.location === 'fixed' && !this.props.hideTooltip) { + tooltip = ( + + {items} + + ); } return ( @@ -491,25 +527,27 @@ - - {triangleUp} - {tooltip} - {triangleDown} - + {tooltip} ); } onPressBackdrop = () => { - this.props.navigation.goBackOnce(); + if (this.location !== 'fixed') { + this.props.navigation.goBackOnce(); + } else { + this.props.setHideTooltip(true); + } }; onPressEntry = (entry: TooltipEntry) => { - this.props.navigation.goBackOnce(); + if (this.location !== 'fixed' || this.props.actionSheetShown.value) { + this.props.navigation.goBackOnce(); + } else { + this.props.setHideTooltip(true); + } + const dispatchFunctions = { dispatch: this.props.dispatch, dispatchActionPromise: this.props.dispatchActionPromise, @@ -527,7 +565,8 @@ onPressMore = () => { Keyboard.dismiss(); - this.props.setActionSheetShown(true); + this.props.actionSheetShown.value = true; + this.props.setHideTooltip(true); const { entries } = this; const options = entries.map(entry => entry.text); @@ -658,8 +697,23 @@ const inputState = React.useContext(InputStateContext); const chatContext = React.useContext(ChatContext); - const [actionSheetShown, setActionSheetShown] = React.useState( - false, + const actionSheetShown = useSharedValue(false); + const [hideTooltip, setHideTooltip] = React.useState(false); + + const goBackCallback = React.useCallback(() => { + if (!actionSheetShown.value) { + props.navigation.goBackOnce(); + } + }, [actionSheetShown.value, props.navigation]); + + const exitAnimationWorklet = React.useCallback( + finished => { + 'worklet'; + if (finished) { + runOnJS(goBackCallback)(); + } + }, + [goBackCallback], ); const styles = useStyles(unboundStyles); @@ -677,7 +731,9 @@ chatContext={chatContext} showActionSheetWithOptions={showActionSheetWithOptions} actionSheetShown={actionSheetShown} - setActionSheetShown={setActionSheetShown} + hideTooltip={hideTooltip} + setHideTooltip={setHideTooltip} + exitAnimationWorklet={exitAnimationWorklet} styles={styles} /> ); diff --git a/native/types/styles.js b/native/types/styles.js --- a/native/types/styles.js +++ b/native/types/styles.js @@ -2,7 +2,10 @@ import * as React from 'react'; import { View, Text, Image } from 'react-native'; -import Animated from 'react-native-reanimated'; +import Animated, { + type ReanimatedAnimationBuilder, + type EntryExitAnimationFunction, +} from 'react-native-reanimated'; type ViewProps = React.ElementConfig; export type ViewStyle = $PropertyType; @@ -30,6 +33,11 @@ const AnimatedView: React.ComponentType<{ ...$Diff, +style: AnimatedViewStyle, + +entering?: + | ReanimatedAnimationBuilder + | EntryExitAnimationFunction + | Keyframe, + +exiting?: ReanimatedAnimationBuilder | EntryExitAnimationFunction | Keyframe, }> = Animated.View; export type AnimatedTextStyle =