Changeset View
Changeset View
Standalone View
Standalone View
native/chat/text-message-tooltip-button.react.js
// @flow | // @flow | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { StyleSheet, View } from 'react-native'; | |||||
import Animated from 'react-native-reanimated'; | import Animated from 'react-native-reanimated'; | ||||
import EmojiPicker from 'rn-emoji-keyboard'; | import EmojiPicker from 'rn-emoji-keyboard'; | ||||
import { getAvatarForUser } from 'lib/shared/avatar-utils.js'; | |||||
import { localIDPrefix } from 'lib/shared/message-utils.js'; | import { localIDPrefix } from 'lib/shared/message-utils.js'; | ||||
import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js'; | import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js'; | ||||
import { avatarOffset } from './chat-constants.js'; | |||||
import { TooltipInlineEngagement } from './inline-engagement.react.js'; | import { TooltipInlineEngagement } from './inline-engagement.react.js'; | ||||
import { InnerTextMessage } from './inner-text-message.react.js'; | import { InnerTextMessage } from './inner-text-message.react.js'; | ||||
import { MessageHeader } from './message-header.react.js'; | import { MessageHeader } from './message-header.react.js'; | ||||
import { MessageListContextProvider } from './message-list-types.js'; | import { MessageListContextProvider } from './message-list-types.js'; | ||||
import { MessagePressResponderContext } from './message-press-responder-context.js'; | import { MessagePressResponderContext } from './message-press-responder-context.js'; | ||||
import { useSendReaction } from './reaction-message-utils.js'; | import { useSendReaction } from './reaction-message-utils.js'; | ||||
import ReactionSelectionPopover from './reaction-selection-popover.react.js'; | import ReactionSelectionPopover from './reaction-selection-popover.react.js'; | ||||
import SidebarInputBarHeightMeasurer from './sidebar-input-bar-height-measurer.react.js'; | import SidebarInputBarHeightMeasurer from './sidebar-input-bar-height-measurer.react.js'; | ||||
import { useAnimatedMessageTooltipButton } from './utils.js'; | import { useAnimatedMessageTooltipButton } from './utils.js'; | ||||
import Avatar from '../components/avatar.react.js'; | |||||
import type { AppNavigationProp } from '../navigation/app-navigator.react.js'; | import type { AppNavigationProp } from '../navigation/app-navigator.react.js'; | ||||
import { useSelector } from '../redux/redux-utils.js'; | import { useSelector } from '../redux/redux-utils.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 { useShouldRenderAvatars } from '../utils/avatar-utils.js'; | |||||
/* eslint-disable import/no-named-as-default-member */ | /* eslint-disable import/no-named-as-default-member */ | ||||
const { Node, interpolateNode, Extrapolate } = Animated; | const { Node, interpolateNode, Extrapolate } = Animated; | ||||
/* eslint-enable import/no-named-as-default-member */ | /* eslint-enable import/no-named-as-default-member */ | ||||
type Props = { | type Props = { | ||||
+navigation: AppNavigationProp<'TextMessageTooltipModal'>, | +navigation: AppNavigationProp<'TextMessageTooltipModal'>, | ||||
+route: TooltipRoute<'TextMessageTooltipModal'>, | +route: TooltipRoute<'TextMessageTooltipModal'>, | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | function TextMessageTooltipButton(props: Props): React.Node { | ||||
const onEmojiSelected = React.useCallback( | const onEmojiSelected = React.useCallback( | ||||
emoji => { | emoji => { | ||||
sendReaction(emoji.emoji); | sendReaction(emoji.emoji); | ||||
dismissTooltip(); | dismissTooltip(); | ||||
}, | }, | ||||
[sendReaction, dismissTooltip], | [sendReaction, dismissTooltip], | ||||
); | ); | ||||
const avatarInfo = React.useMemo( | |||||
() => getAvatarForUser(item.messageInfo.creator), | |||||
[item.messageInfo.creator], | |||||
); | |||||
const shouldRenderAvatars = useShouldRenderAvatars(); | |||||
const avatar = React.useMemo(() => { | |||||
if (item.messageInfo.creator.isViewer || !shouldRenderAvatars) { | |||||
return null; | |||||
} | |||||
return ( | |||||
<View style={styles.avatarContainer}> | |||||
<Avatar size="small" avatarInfo={avatarInfo} /> | |||||
</View> | |||||
); | |||||
}, [avatarInfo, item.messageInfo.creator.isViewer, shouldRenderAvatars]); | |||||
ashoat: Looks like you're copy-pasting this code in multiple places. When you find yourself copy… | |||||
ginsuAuthorUnsubmitted Done Inline ActionsGotcha will put up a diff to address factoring out shouldRenderAvatars logic into a AvatarFeatureFlagWrapper component ginsu: Gotcha will put up a diff to address factoring out `shouldRenderAvatars` logic into a… | |||||
ginsuAuthorUnsubmitted Done Inline ActionsSpoke to @ashoat IRL and we will just be factoring out this part of the code in only text-message-tooltip-button and multimedia-message-tooltip-button ginsu: Spoke to @ashoat IRL and we will just be factoring out this part of the code in only `text… | |||||
return ( | return ( | ||||
<MessageListContextProvider threadInfo={threadInfo}> | <MessageListContextProvider threadInfo={threadInfo}> | ||||
<SidebarInputBarHeightMeasurer | <SidebarInputBarHeightMeasurer | ||||
sourceMessage={item} | sourceMessage={item} | ||||
onInputBarMeasured={onInputBarMeasured} | onInputBarMeasured={onInputBarMeasured} | ||||
/> | /> | ||||
<Animated.View style={messageContainerStyle}> | <Animated.View style={messageContainerStyle}> | ||||
<Animated.View style={headerStyle}> | <Animated.View style={headerStyle}> | ||||
<MessageHeader item={item} focused={true} display="modal" /> | <MessageHeader item={item} focused={true} display="modal" /> | ||||
</Animated.View> | </Animated.View> | ||||
{avatar} | |||||
{reactionSelectionPopover} | {reactionSelectionPopover} | ||||
<MessagePressResponderContext.Provider | <MessagePressResponderContext.Provider | ||||
value={messagePressResponderContext} | value={messagePressResponderContext} | ||||
> | > | ||||
<InnerTextMessage | <InnerTextMessage | ||||
item={item} | item={item} | ||||
onPress={navigation.goBackOnce} | onPress={navigation.goBackOnce} | ||||
threadColorOverride={threadColorOverride} | threadColorOverride={threadColorOverride} | ||||
isThreadColorDarkOverride={isThreadColorDarkOverride} | isThreadColorDarkOverride={isThreadColorDarkOverride} | ||||
/> | /> | ||||
</MessagePressResponderContext.Provider> | </MessagePressResponderContext.Provider> | ||||
{inlineEngagement} | {inlineEngagement} | ||||
</Animated.View> | </Animated.View> | ||||
<EmojiPicker | <EmojiPicker | ||||
onEmojiSelected={onEmojiSelected} | onEmojiSelected={onEmojiSelected} | ||||
open={emojiPickerOpen} | open={emojiPickerOpen} | ||||
onClose={dismissTooltip} | onClose={dismissTooltip} | ||||
/> | /> | ||||
</MessageListContextProvider> | </MessageListContextProvider> | ||||
); | ); | ||||
} | } | ||||
const styles = StyleSheet.create({ | |||||
avatarContainer: { | |||||
bottom: 0, | |||||
left: -avatarOffset, | |||||
position: 'absolute', | |||||
}, | |||||
}); | |||||
export default TextMessageTooltipButton; | export default TextMessageTooltipButton; |
Looks like you're copy-pasting this code in multiple places. When you find yourself copy-pasting something, that should be a "red flag" that you're doing something wrong.
Can you factor this code out into its own component, and make sure you use that component in all of the places that you're doing this? (All places in this diff, and all places in other diffs)