diff --git a/native/chat/reaction-message-utils.js b/native/chat/reaction-message-utils.js --- a/native/chat/reaction-message-utils.js +++ b/native/chat/reaction-message-utils.js @@ -134,9 +134,7 @@ verticalBounds, margin, }: ReactionSelectionPopoverPositionArgs): ReactionSelectionPopoverPosition { - const reactionSelectionPopoverHeight = 56; - - const calculatedMargin = margin ?? 16; + const calculatedMargin = getCalculatedMargin(margin); const windowWidth = useSelector(state => state.dimensions.width); @@ -191,4 +189,15 @@ ); } -export { useSendReaction, useReactionSelectionPopoverPosition }; +function getCalculatedMargin(margin: ?number): number { + return margin ?? 16; +} + +const reactionSelectionPopoverHeight = 56; + +export { + useSendReaction, + useReactionSelectionPopoverPosition, + getCalculatedMargin, + reactionSelectionPopoverHeight, +}; diff --git a/native/chat/reaction-selection-popover.react.js b/native/chat/reaction-selection-popover.react.js --- a/native/chat/reaction-selection-popover.react.js +++ b/native/chat/reaction-selection-popover.react.js @@ -5,7 +5,11 @@ import { View, TouchableOpacity, Text } from 'react-native'; import Animated from 'react-native-reanimated'; -import { useReactionSelectionPopoverPosition } from './reaction-message-utils.js'; +import { + useReactionSelectionPopoverPosition, + getCalculatedMargin, + reactionSelectionPopoverHeight, +} from './reaction-message-utils.js'; import SWMansionIcon from '../components/swmansion-icon.react.js'; import type { AppNavigationProp } from '../navigation/app-navigator.react.js'; import { OverlayContext } from '../navigation/overlay-context.js'; @@ -32,7 +36,7 @@ const { navigation, route, openEmojiPicker, sendReaction } = props; const { verticalBounds, initialCoordinates, margin } = route.params; - const { containerStyle: popoverContainerStyle } = + const { containerStyle: popoverContainerStyle, popoverLocation } = useReactionSelectionPopoverPosition({ initialCoordinates, verticalBounds, @@ -46,25 +50,48 @@ ); const { position } = overlayContext; - const animationStyle = React.useMemo( - () => ({ - opacity: interpolateNode(position, { - inputRange: [0, 0.1], - outputRange: [0, 1], - extrapolate: Extrapolate.CLAMP, - }), - transform: [ - { - scale: interpolateNode(position, { - inputRange: [0.2, 0.8], - outputRange: [0, 1], - extrapolate: Extrapolate.CLAMP, - }), - }, - ], - }), - [position], - ); + const calculatedMargin = getCalculatedMargin(margin); + const animationStyle = React.useMemo(() => { + const style = {}; + style.opacity = interpolateNode(position, { + inputRange: [0, 0.1], + outputRange: [0, 1], + extrapolate: Extrapolate.CLAMP, + }); + style.transform = [ + { + scale: interpolateNode(position, { + inputRange: [0.2, 0.8], + outputRange: [0, 1], + extrapolate: Extrapolate.CLAMP, + }), + }, + ]; + if (popoverLocation === 'above') { + style.transform.push({ + translateY: interpolateNode(position, { + inputRange: [0, 1], + outputRange: [ + calculatedMargin + reactionSelectionPopoverHeight / 2, + 0, + ], + extrapolate: Extrapolate.CLAMP, + }), + }); + } else { + style.transform.push({ + translateY: interpolateNode(position, { + inputRange: [0, 1], + outputRange: [ + -calculatedMargin - reactionSelectionPopoverHeight / 2, + 0, + ], + extrapolate: Extrapolate.CLAMP, + }), + }); + } + return style; + }, [position, calculatedMargin, popoverLocation]); const styles = useStyles(unboundStyles);