Changeset View
Changeset View
Standalone View
Standalone View
native/chat/composed-message.react.js
// @flow | // @flow | ||||
import Icon from '@expo/vector-icons/Feather.js'; | import Icon from '@expo/vector-icons/Feather.js'; | ||||
import invariant from 'invariant'; | import invariant from 'invariant'; | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { StyleSheet, View } from 'react-native'; | import { StyleSheet, View } from 'react-native'; | ||||
import Animated from 'react-native-reanimated'; | import Animated from 'react-native-reanimated'; | ||||
import { getAvatarForUser } from 'lib/shared/avatar-utils.js'; | |||||
import { createMessageReply } from 'lib/shared/message-utils.js'; | import { createMessageReply } from 'lib/shared/message-utils.js'; | ||||
import { assertComposableMessageType } from 'lib/types/message-types.js'; | import { assertComposableMessageType } from 'lib/types/message-types.js'; | ||||
import { | import { | ||||
clusterEndHeight, | clusterEndHeight, | ||||
inlineEngagementStyle, | inlineEngagementStyle, | ||||
inlineEngagementLeftStyle, | inlineEngagementLeftStyle, | ||||
inlineEngagementRightStyle, | inlineEngagementRightStyle, | ||||
composedMessageStyle, | composedMessageStyle, | ||||
avatarOffset, | |||||
} from './chat-constants.js'; | } from './chat-constants.js'; | ||||
import { useComposedMessageMaxWidth } from './composed-message-width.js'; | import { useComposedMessageMaxWidth } from './composed-message-width.js'; | ||||
import { FailedSend } from './failed-send.react.js'; | import { FailedSend } from './failed-send.react.js'; | ||||
import { InlineEngagement } from './inline-engagement.react.js'; | import { InlineEngagement } from './inline-engagement.react.js'; | ||||
import { MessageHeader } from './message-header.react.js'; | import { MessageHeader } from './message-header.react.js'; | ||||
import { useNavigateToSidebar } from './sidebar-navigation.js'; | import { useNavigateToSidebar } from './sidebar-navigation.js'; | ||||
import SwipeableMessage from './swipeable-message.react.js'; | import SwipeableMessage from './swipeable-message.react.js'; | ||||
import { useContentAndHeaderOpacity, useDeliveryIconOpacity } from './utils.js'; | import { useContentAndHeaderOpacity, useDeliveryIconOpacity } from './utils.js'; | ||||
import Avatar from '../components/avatar.react.js'; | |||||
import { type InputState, InputStateContext } from '../input/input-state.js'; | import { type InputState, InputStateContext } from '../input/input-state.js'; | ||||
import { type Colors, useColors } from '../themes/colors.js'; | import { type Colors, useColors } from '../themes/colors.js'; | ||||
import type { ChatMessageInfoItemWithHeight } from '../types/chat-types.js'; | import type { ChatMessageInfoItemWithHeight } from '../types/chat-types.js'; | ||||
import { type AnimatedStyleObj, AnimatedView } from '../types/styles.js'; | import { type AnimatedStyleObj, AnimatedView } from '../types/styles.js'; | ||||
/* eslint-disable import/no-named-as-default-member */ | /* eslint-disable import/no-named-as-default-member */ | ||||
const { Node } = Animated; | const { Node } = Animated; | ||||
/* eslint-enable import/no-named-as-default-member */ | /* eslint-enable import/no-named-as-default-member */ | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | render() { | ||||
const triggerReply = | const triggerReply = | ||||
swipeOptions === 'reply' || swipeOptions === 'both' | swipeOptions === 'reply' || swipeOptions === 'both' | ||||
? this.reply | ? this.reply | ||||
: undefined; | : undefined; | ||||
const triggerSidebar = | const triggerSidebar = | ||||
swipeOptions === 'sidebar' || swipeOptions === 'both' | swipeOptions === 'sidebar' || swipeOptions === 'both' | ||||
? navigateToSidebar | ? navigateToSidebar | ||||
: undefined; | : undefined; | ||||
let avatar; | |||||
if (!isViewer && item.endsCluster) { | |||||
const avatarInfo = getAvatarForUser(item.messageInfo.creator); | |||||
avatar = ( | |||||
<View style={styles.avatarContainer}> | |||||
<Avatar size="small" avatarInfo={avatarInfo} /> | |||||
</View> | |||||
); | |||||
} else if (!isViewer) { | |||||
avatar = <View style={styles.avatarOffset} />; | |||||
} | |||||
const messageBox = ( | const messageBox = ( | ||||
<View style={styles.messageBox}> | <View style={styles.messageBox}> | ||||
<SwipeableMessage | <SwipeableMessage | ||||
triggerReply={triggerReply} | triggerReply={triggerReply} | ||||
triggerSidebar={triggerSidebar} | triggerSidebar={triggerSidebar} | ||||
isViewer={isViewer} | isViewer={isViewer} | ||||
messageBoxStyle={messageBoxStyle} | messageBoxStyle={messageBoxStyle} | ||||
threadColor={item.threadInfo.color} | threadColor={item.threadInfo.color} | ||||
> | > | ||||
<View style={styles.swipeableContainer}> | |||||
{avatar} | |||||
<AnimatedView style={{ opacity: contentAndHeaderOpacity }}> | <AnimatedView style={{ opacity: contentAndHeaderOpacity }}> | ||||
{children} | {children} | ||||
</AnimatedView> | </AnimatedView> | ||||
</View> | |||||
</SwipeableMessage> | </SwipeableMessage> | ||||
</View> | </View> | ||||
); | ); | ||||
let inlineEngagement = null; | let inlineEngagement = null; | ||||
if ( | if ( | ||||
item.threadCreatedFromMessage || | item.threadCreatedFromMessage || | ||||
Object.keys(item.reactions).length > 0 | Object.keys(item.reactions).length > 0 | ||||
Show All 38 Lines | class ComposedMessage extends React.PureComponent<Props> { | ||||
}; | }; | ||||
} | } | ||||
const styles = StyleSheet.create({ | const styles = StyleSheet.create({ | ||||
alignment: { | alignment: { | ||||
marginLeft: composedMessageStyle.marginLeft, | marginLeft: composedMessageStyle.marginLeft, | ||||
marginRight: composedMessageStyle.marginRight, | marginRight: composedMessageStyle.marginRight, | ||||
}, | }, | ||||
avatarContainer: { | |||||
marginRight: 8, | |||||
}, | |||||
avatarOffset: { | |||||
width: avatarOffset, | |||||
}, | |||||
content: { | content: { | ||||
alignItems: 'center', | alignItems: 'center', | ||||
flexDirection: 'row-reverse', | flexDirection: 'row-reverse', | ||||
}, | }, | ||||
icon: { | icon: { | ||||
fontSize: 16, | fontSize: 16, | ||||
textAlign: 'center', | textAlign: 'center', | ||||
}, | }, | ||||
iconContainer: { | iconContainer: { | ||||
marginLeft: 2, | marginLeft: 2, | ||||
width: 16, | width: 16, | ||||
}, | }, | ||||
inlineEngagement: { | inlineEngagement: { | ||||
marginBottom: inlineEngagementStyle.marginBottom, | marginBottom: inlineEngagementStyle.marginBottom, | ||||
marginTop: inlineEngagementStyle.marginTop, | marginTop: inlineEngagementStyle.marginTop, | ||||
}, | }, | ||||
leftChatBubble: { | leftChatBubble: { | ||||
justifyContent: 'flex-end', | justifyContent: 'flex-end', | ||||
}, | }, | ||||
leftInlineEngagement: { | leftInlineEngagement: { | ||||
justifyContent: 'flex-start', | justifyContent: 'flex-start', | ||||
marginLeft: 32, | |||||
position: 'relative', | position: 'relative', | ||||
top: inlineEngagementLeftStyle.topOffset, | top: inlineEngagementLeftStyle.topOffset, | ||||
}, | }, | ||||
messageBox: { | messageBox: { | ||||
marginRight: 5, | marginRight: 5, | ||||
}, | }, | ||||
rightChatBubble: { | rightChatBubble: { | ||||
justifyContent: 'flex-start', | justifyContent: 'flex-start', | ||||
}, | }, | ||||
rightInlineEngagement: { | rightInlineEngagement: { | ||||
alignSelf: 'flex-end', | alignSelf: 'flex-end', | ||||
position: 'relative', | position: 'relative', | ||||
right: inlineEngagementRightStyle.marginRight, | right: inlineEngagementRightStyle.marginRight, | ||||
top: inlineEngagementRightStyle.topOffset, | top: inlineEngagementRightStyle.topOffset, | ||||
}, | }, | ||||
swipeableContainer: { | |||||
alignItems: 'flex-end', | |||||
flexDirection: 'row', | |||||
}, | |||||
}); | }); | ||||
const ConnectedComposedMessage: React.ComponentType<BaseProps> = | const ConnectedComposedMessage: React.ComponentType<BaseProps> = | ||||
React.memo<BaseProps>(function ConnectedComposedMessage(props: BaseProps) { | React.memo<BaseProps>(function ConnectedComposedMessage(props: BaseProps) { | ||||
const composedMessageMaxWidth = useComposedMessageMaxWidth(); | const composedMessageMaxWidth = useComposedMessageMaxWidth(); | ||||
const colors = useColors(); | const colors = useColors(); | ||||
const inputState = React.useContext(InputStateContext); | const inputState = React.useContext(InputStateContext); | ||||
const navigateToSidebar = useNavigateToSidebar(props.item); | const navigateToSidebar = useNavigateToSidebar(props.item); | ||||
Show All 16 Lines |