Changeset View
Changeset View
Standalone View
Standalone View
native/chat/reaction-selection-popover.react.js
// @flow | // @flow | ||||
import invariant from 'invariant'; | import invariant from 'invariant'; | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { View, TouchableOpacity, Text } from 'react-native'; | import { View, TouchableOpacity, Text } from 'react-native'; | ||||
import Animated from 'react-native-reanimated'; | 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 SWMansionIcon from '../components/swmansion-icon.react.js'; | ||||
import type { AppNavigationProp } from '../navigation/app-navigator.react.js'; | import type { AppNavigationProp } from '../navigation/app-navigator.react.js'; | ||||
import { OverlayContext } from '../navigation/overlay-context.js'; | import { OverlayContext } from '../navigation/overlay-context.js'; | ||||
import type { TooltipModalParamList } from '../navigation/route-names.js'; | import type { TooltipModalParamList } from '../navigation/route-names.js'; | ||||
import { useStyles } from '../themes/colors.js'; | import { useStyles } from '../themes/colors.js'; | ||||
import { useTooltipActions } from '../tooltip/tooltip-hooks.js'; | import { useTooltipActions } from '../tooltip/tooltip-hooks.js'; | ||||
import type { TooltipRoute } from '../tooltip/tooltip.react.js'; | import type { TooltipRoute } from '../tooltip/tooltip.react.js'; | ||||
import { AnimatedView } from '../types/styles.js'; | import { AnimatedView } from '../types/styles.js'; | ||||
Show All 10 Lines | |||||
/* eslint-enable import/no-named-as-default-member */ | /* eslint-enable import/no-named-as-default-member */ | ||||
function ReactionSelectionPopover<RouteName: $Keys<TooltipModalParamList>>( | function ReactionSelectionPopover<RouteName: $Keys<TooltipModalParamList>>( | ||||
props: Props<RouteName>, | props: Props<RouteName>, | ||||
): React.Node { | ): React.Node { | ||||
const { navigation, route, openEmojiPicker, sendReaction } = props; | const { navigation, route, openEmojiPicker, sendReaction } = props; | ||||
const { verticalBounds, initialCoordinates, margin } = route.params; | const { verticalBounds, initialCoordinates, margin } = route.params; | ||||
const { containerStyle: popoverContainerStyle } = | const { containerStyle: popoverContainerStyle, popoverLocation } = | ||||
useReactionSelectionPopoverPosition({ | useReactionSelectionPopoverPosition({ | ||||
initialCoordinates, | initialCoordinates, | ||||
verticalBounds, | verticalBounds, | ||||
margin, | margin, | ||||
}); | }); | ||||
const overlayContext = React.useContext(OverlayContext); | const overlayContext = React.useContext(OverlayContext); | ||||
invariant( | invariant( | ||||
overlayContext, | overlayContext, | ||||
'ReactionSelectionPopover should have OverlayContext', | 'ReactionSelectionPopover should have OverlayContext', | ||||
); | ); | ||||
const { position } = overlayContext; | const { position } = overlayContext; | ||||
const animationStyle = React.useMemo( | const calculatedMargin = getCalculatedMargin(margin); | ||||
() => ({ | const animationStyle = React.useMemo(() => { | ||||
opacity: interpolateNode(position, { | const style = {}; | ||||
style.opacity = interpolateNode(position, { | |||||
inputRange: [0, 0.1], | inputRange: [0, 0.1], | ||||
outputRange: [0, 1], | outputRange: [0, 1], | ||||
extrapolate: Extrapolate.CLAMP, | extrapolate: Extrapolate.CLAMP, | ||||
}), | }); | ||||
transform: [ | style.transform = [ | ||||
{ | { | ||||
scale: interpolateNode(position, { | scale: interpolateNode(position, { | ||||
inputRange: [0.2, 0.8], | inputRange: [0.2, 0.8], | ||||
outputRange: [0, 1], | outputRange: [0, 1], | ||||
extrapolate: Extrapolate.CLAMP, | extrapolate: Extrapolate.CLAMP, | ||||
}), | }), | ||||
}, | }, | ||||
]; | |||||
if (popoverLocation === 'above') { | |||||
style.transform.push({ | |||||
translateY: interpolateNode(position, { | |||||
inputRange: [0, 1], | |||||
outputRange: [ | |||||
calculatedMargin + reactionSelectionPopoverHeight / 2, | |||||
0, | |||||
], | ], | ||||
extrapolate: Extrapolate.CLAMP, | |||||
}), | }), | ||||
[position], | }); | ||||
); | } 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); | const styles = useStyles(unboundStyles); | ||||
const containerStyle = React.useMemo( | const containerStyle = React.useMemo( | ||||
() => ({ | () => ({ | ||||
...styles.reactionSelectionPopoverContainer, | ...styles.reactionSelectionPopoverContainer, | ||||
...popoverContainerStyle, | ...popoverContainerStyle, | ||||
...animationStyle, | ...animationStyle, | ||||
▲ Show 20 Lines • Show All 92 Lines • Show Last 20 Lines |