UNPKG

react-native-gifted-chat

Version:
269 lines 10.8 kB
import React, { useCallback, useMemo } from 'react'; import { View, Pressable, } from 'react-native'; import { Text } from 'react-native-gesture-handler'; import { MessageReply } from '../components/MessageReply'; import { useChatContext } from '../GiftedChatContext'; import { MessageAudio } from '../MessageAudio'; import { MessageImage } from '../MessageImage'; import { MessageText } from '../MessageText'; import { MessageVideo } from '../MessageVideo'; import { QuickReplies } from '../QuickReplies'; import { getStyleWithPosition } from '../styles'; import { Time } from '../Time'; import { isSameUser, isSameDay, renderComponentOrElement } from '../utils'; import styles from './styles'; export * from './types'; export const Bubble = (props) => { const { currentMessage, nextMessage, position, containerToNextStyle, previousMessage, containerToPreviousStyle, onQuickReply, renderQuickReplySend, quickReplyStyle, quickReplyTextStyle, quickReplyContainerStyle, containerStyle, wrapperStyle, bottomContainerStyle, onPressMessage: onPressMessageProp, onLongPressMessage: onLongPressMessageProp, } = props; const context = useChatContext(); const onPress = useCallback(() => { onPressMessageProp?.(context, currentMessage); }, [onPressMessageProp, context, currentMessage]); const onLongPress = useCallback(() => { onLongPressMessageProp?.(context, currentMessage); }, [ currentMessage, context, onLongPressMessageProp, ]); const styledBubbleToNext = useMemo(() => { if (currentMessage && nextMessage && position && isSameUser(currentMessage, nextMessage) && isSameDay(currentMessage, nextMessage)) return [ getStyleWithPosition(styles, 'containerToNext', position), containerToNextStyle?.[position], ]; return null; }, [ currentMessage, nextMessage, position, containerToNextStyle, ]); const styledBubbleToPrevious = useMemo(() => { if (currentMessage && previousMessage && position && isSameUser(currentMessage, previousMessage) && isSameDay(currentMessage, previousMessage)) return [ getStyleWithPosition(styles, 'containerToPrevious', position), containerToPreviousStyle?.[position], ]; return null; }, [ currentMessage, previousMessage, position, containerToPreviousStyle, ]); const renderQuickReplies = useCallback(() => { if (currentMessage?.quickReplies) { const { /* eslint-disable @typescript-eslint/no-unused-vars */ containerStyle, wrapperStyle, /* eslint-enable @typescript-eslint/no-unused-vars */ ...quickReplyProps } = props; if (props.renderQuickReplies) return renderComponentOrElement(props.renderQuickReplies, quickReplyProps); return (<QuickReplies currentMessage={currentMessage} onQuickReply={onQuickReply} renderQuickReplySend={renderQuickReplySend} quickReplyStyle={quickReplyStyle} quickReplyTextStyle={quickReplyTextStyle} quickReplyContainerStyle={quickReplyContainerStyle} nextMessage={nextMessage}/>); } return null; }, [ currentMessage, onQuickReply, renderQuickReplySend, quickReplyStyle, quickReplyTextStyle, quickReplyContainerStyle, nextMessage, props, ]); const renderMessageText = useCallback(() => { if (currentMessage?.text) { const { /* eslint-disable @typescript-eslint/no-unused-vars */ containerStyle, wrapperStyle, messageTextProps, /* eslint-enable @typescript-eslint/no-unused-vars */ ...messageTextPropsRest } = props; const combinedProps = { ...messageTextPropsRest, ...messageTextProps, }; if (props.renderMessageText) return renderComponentOrElement(props.renderMessageText, combinedProps); return <MessageText {...combinedProps}/>; } return null; }, [props, currentMessage]); const renderMessageImage = useCallback(() => { if (currentMessage?.image) { const { /* eslint-disable @typescript-eslint/no-unused-vars */ containerStyle, wrapperStyle, /* eslint-enable @typescript-eslint/no-unused-vars */ ...messageImageProps } = props; if (props.renderMessageImage) return renderComponentOrElement(props.renderMessageImage, messageImageProps); return <MessageImage {...messageImageProps}/>; } return null; }, [props, currentMessage]); const renderMessageVideo = useCallback(() => { if (!currentMessage?.video) return null; const { /* eslint-disable @typescript-eslint/no-unused-vars */ containerStyle, wrapperStyle, /* eslint-enable @typescript-eslint/no-unused-vars */ ...messageVideoProps } = props; if (props.renderMessageVideo) return renderComponentOrElement(props.renderMessageVideo, messageVideoProps); return <MessageVideo />; }, [props, currentMessage]); const renderMessageAudio = useCallback(() => { if (!currentMessage?.audio) return null; const { /* eslint-disable @typescript-eslint/no-unused-vars */ containerStyle, wrapperStyle, /* eslint-enable @typescript-eslint/no-unused-vars */ ...messageAudioProps } = props; if (props.renderMessageAudio) return renderComponentOrElement(props.renderMessageAudio, messageAudioProps); return <MessageAudio />; }, [props, currentMessage]); const renderTicks = useCallback(() => { const { renderTicks, user, } = props; if (renderTicks && currentMessage) return renderComponentOrElement(renderTicks, currentMessage); if (user && currentMessage?.user && currentMessage.user._id !== user._id) return null; if (currentMessage && (currentMessage.sent || currentMessage.received || currentMessage.pending)) return (<View style={styles.messageStatusContainer}> {!!currentMessage.sent && (<Text style={[styles.messageStatus, props.tickStyle]}> {'✓'} </Text>)} {!!currentMessage.received && (<Text style={[styles.messageStatus, props.tickStyle]}> {'✓'} </Text>)} {!!currentMessage.pending && (<Text style={[styles.messageStatus, props.tickStyle]}> {'🕓'} </Text>)} </View>); return null; }, [ props, currentMessage, ]); const renderTime = useCallback(() => { if (currentMessage?.createdAt) { const { /* eslint-disable @typescript-eslint/no-unused-vars */ containerStyle, wrapperStyle, textStyle, /* eslint-enable @typescript-eslint/no-unused-vars */ ...timeProps } = props; if (props.renderTime) return renderComponentOrElement(props.renderTime, timeProps); return <Time {...timeProps}/>; } return null; }, [props, currentMessage]); const renderUsername = useCallback(() => { const { user, renderUsername, } = props; if (props.isUsernameVisible && currentMessage) { if (user && currentMessage.user._id === user._id) return null; if (renderUsername) return renderComponentOrElement(renderUsername, currentMessage.user); return (<View style={styles.usernameContainer}> <Text style={[styles.username, props.usernameStyle]}> {currentMessage.user.name} </Text> </View>); } return null; }, [ currentMessage, props, ]); const renderCustomView = useCallback(() => { if (props.renderCustomView) return renderComponentOrElement(props.renderCustomView, props); return null; }, [props]); const renderMessageReply = useCallback(() => { if (!currentMessage?.replyMessage) return null; const { messageReply } = props; const messageReplyProps = { replyMessage: currentMessage.replyMessage, currentMessage, position, onPress: messageReply?.onPress, containerStyle: position === 'left' ? messageReply?.containerStyleLeft ?? messageReply?.containerStyle : messageReply?.containerStyleRight ?? messageReply?.containerStyle, textStyle: position === 'left' ? messageReply?.textStyleLeft ?? messageReply?.textStyle : messageReply?.textStyleRight ?? messageReply?.textStyle, imageStyle: messageReply?.imageStyle, }; if (messageReply?.renderMessageReply) return renderComponentOrElement(messageReply.renderMessageReply, messageReplyProps); return <MessageReply {...messageReplyProps}/>; }, [ props, currentMessage, position, ]); const renderBubbleContent = useCallback(() => { return (<> {!props.isCustomViewBottom && renderCustomView()} {renderMessageReply()} {renderMessageImage()} {renderMessageVideo()} {renderMessageAudio()} {renderMessageText()} {props.isCustomViewBottom && renderCustomView()} </>); }, [ renderMessageReply, renderCustomView, renderMessageImage, renderMessageVideo, renderMessageAudio, renderMessageText, props.isCustomViewBottom, ]); return (<View style={containerStyle?.[position]}> <View style={[ getStyleWithPosition(styles, 'wrapper', position), styledBubbleToNext, styledBubbleToPrevious, wrapperStyle?.[position], ]}> <Pressable onPress={onPress} onLongPress={onLongPress} {...props.touchableProps}> {renderBubbleContent()} <View style={[ styles.bottom, bottomContainerStyle?.[position], ]}> {renderUsername()} <View style={styles.messageTimeAndStatusContainer}> {renderTime()} {renderTicks()} </View> </View> </Pressable> </View> {renderQuickReplies()} </View>); }; //# sourceMappingURL=index.js.map