|
@@ -336,7 +336,6 @@ const ChatScreen = ({ route }: { route: any }) => {
|
|
</View>
|
|
</View>
|
|
) : null;
|
|
) : null;
|
|
}}
|
|
}}
|
|
- renderCustomView={renderReplyMessageView}
|
|
|
|
/>
|
|
/>
|
|
</ScrollView>
|
|
</ScrollView>
|
|
</View>
|
|
</View>
|
|
@@ -531,46 +530,6 @@ const ChatScreen = ({ route }: { route: any }) => {
|
|
[replyMessage]
|
|
[replyMessage]
|
|
);
|
|
);
|
|
|
|
|
|
- const renderCustomView = (props: BubbleProps<IMessage>) => {
|
|
|
|
- if (!props.currentMessage) {
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
- const { currentMessage } = props;
|
|
|
|
-
|
|
|
|
- if (!currentMessage) {
|
|
|
|
- return null;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return (
|
|
|
|
- <View style={{ position: 'relative' }}>
|
|
|
|
- {renderReplyMessageView(props)}
|
|
|
|
-
|
|
|
|
- {currentMessage.reactions &&
|
|
|
|
- Array.isArray(currentMessage.reactions) &&
|
|
|
|
- currentMessage.reactions.length > 0 && (
|
|
|
|
- <View
|
|
|
|
- style={[
|
|
|
|
- styles.reactionsContainer,
|
|
|
|
- currentMessage.user._id === id ? { right: -15 } : { left: -15 }
|
|
|
|
- ]}
|
|
|
|
- >
|
|
|
|
- {Object.entries(
|
|
|
|
- currentMessage.reactions.reduce((acc, { reaction }) => {
|
|
|
|
- acc[reaction] = (acc[reaction] || 0) + 1;
|
|
|
|
- return acc;
|
|
|
|
- }, {})
|
|
|
|
- ).map(([emoji, count]) => (
|
|
|
|
- <Text key={emoji} style={{}}>
|
|
|
|
- {emoji}
|
|
|
|
- {(count as number) > 1 ? ` ${count}` : ''}
|
|
|
|
- </Text>
|
|
|
|
- ))}
|
|
|
|
- </View>
|
|
|
|
- )}
|
|
|
|
- </View>
|
|
|
|
- );
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
const renderReplyMessageView = (props: BubbleProps<IMessage>) => {
|
|
const renderReplyMessageView = (props: BubbleProps<IMessage>) => {
|
|
if (!props.currentMessage) {
|
|
if (!props.currentMessage) {
|
|
return null;
|
|
return null;
|
|
@@ -633,6 +592,25 @@ const ChatScreen = ({ route }: { route: any }) => {
|
|
);
|
|
);
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ const renderTicks = (message: IMessage) => {
|
|
|
|
+ if (message.user._id === id) return null;
|
|
|
|
+
|
|
|
|
+ return message.received ? (
|
|
|
|
+ <View
|
|
|
|
+ >
|
|
|
|
+ <MaterialCommunityIcons name="check-all" size={16} color={Colors.WHITE} />
|
|
|
|
+ </View>
|
|
|
|
+ ) : message.sent ? (
|
|
|
|
+ <View>
|
|
|
|
+ <MaterialCommunityIcons name="check" size={16} color={Colors.WHITE} />
|
|
|
|
+ </View>
|
|
|
|
+ ) : message.pending ? (
|
|
|
|
+ <View>
|
|
|
|
+ <MaterialCommunityIcons name="check" size={16} color={Colors.LIGHT_GRAY} />
|
|
|
|
+ </View>
|
|
|
|
+ ) : null;
|
|
|
|
+ };
|
|
|
|
+
|
|
const renderBubble = (props: any) => {
|
|
const renderBubble = (props: any) => {
|
|
const { currentMessage } = props;
|
|
const { currentMessage } = props;
|
|
|
|
|
|
@@ -715,31 +693,89 @@ const ChatScreen = ({ route }: { route: any }) => {
|
|
}
|
|
}
|
|
}}
|
|
}}
|
|
onLongPress={() => handleLongPress(currentMessage, props)}
|
|
onLongPress={() => handleLongPress(currentMessage, props)}
|
|
- renderTicks={(message: IMessage) => {
|
|
|
|
- return message.user._id === +currentUserId && message.received ? (
|
|
|
|
- <View style={{ paddingRight: 8, bottom: 2 }}>
|
|
|
|
- <MaterialCommunityIcons name="check-all" size={16} color={Colors.WHITE} />
|
|
|
|
- </View>
|
|
|
|
- ) : message.user._id === +currentUserId && message.sent ? (
|
|
|
|
- <View style={{ paddingRight: 8, bottom: 2 }}>
|
|
|
|
- <MaterialCommunityIcons name="check" size={16} color={Colors.WHITE} />
|
|
|
|
- </View>
|
|
|
|
- ) : message.user._id === +currentUserId && message.pending ? (
|
|
|
|
- <View style={{ paddingRight: 8, bottom: 2 }}>
|
|
|
|
- <MaterialCommunityIcons name="check" size={16} color={Colors.LIGHT_GRAY} />
|
|
|
|
|
|
+ renderTicks={() => null}
|
|
|
|
+ renderTime={(time) => {
|
|
|
|
+ const createdAt = new Date(time.currentMessage.createdAt);
|
|
|
|
+
|
|
|
|
+ const formattedTime = createdAt.toLocaleTimeString([], {
|
|
|
|
+ hour: '2-digit',
|
|
|
|
+ minute: '2-digit',
|
|
|
|
+ hour12: true
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const hasReactions =
|
|
|
|
+ currentMessage.reactions &&
|
|
|
|
+ Array.isArray(currentMessage.reactions) &&
|
|
|
|
+ currentMessage.reactions.length > 0;
|
|
|
|
+
|
|
|
|
+ return (
|
|
|
|
+ <View
|
|
|
|
+ style={{
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
+ justifyContent: hasReactions ? 'space-between' : 'flex-end',
|
|
|
|
+ alignItems: 'center',
|
|
|
|
+ paddingHorizontal: 8,
|
|
|
|
+ paddingBottom: 6,
|
|
|
|
+ flexShrink: 1,
|
|
|
|
+ flexGrow: 1,
|
|
|
|
+ gap: 12
|
|
|
|
+ }}
|
|
|
|
+ >
|
|
|
|
+ {hasReactions && (
|
|
|
|
+ <View
|
|
|
|
+ style={[
|
|
|
|
+ {
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
+ alignItems: 'center',
|
|
|
|
+ flexShrink: 0,
|
|
|
|
+ backgroundColor:
|
|
|
|
+ time.position === 'left'
|
|
|
|
+ ? 'rgba(0, 0, 0, 0.2)'
|
|
|
|
+ : 'rgba(255, 255, 255, 0.2)',
|
|
|
|
+ borderRadius: 12,
|
|
|
|
+ paddingHorizontal: 6,
|
|
|
|
+ paddingVertical: 4,
|
|
|
|
+ gap: 6
|
|
|
|
+ }
|
|
|
|
+ ]}
|
|
|
|
+ >
|
|
|
|
+ {Object.entries(
|
|
|
|
+ currentMessage.reactions.reduce((acc, { reaction }) => {
|
|
|
|
+ acc[reaction] = (acc[reaction] || 0) + 1;
|
|
|
|
+ return acc;
|
|
|
|
+ }, {})
|
|
|
|
+ ).map(([emoji, count]) => (
|
|
|
|
+ <Text key={emoji} style={{}}>
|
|
|
|
+ {emoji}
|
|
|
|
+ {(count as number) > 1 ? ` ${count}` : ''}
|
|
|
|
+ </Text>
|
|
|
|
+ ))}
|
|
|
|
+ </View>
|
|
|
|
+ )}
|
|
|
|
+ <View
|
|
|
|
+ style={{
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
+ gap: 4,
|
|
|
|
+ alignItems: 'center',
|
|
|
|
+ alignSelf: 'flex-end'
|
|
|
|
+ }}
|
|
|
|
+ >
|
|
|
|
+ <Text
|
|
|
|
+ style={{
|
|
|
|
+ color: Colors.LIGHT_GRAY,
|
|
|
|
+ fontSize: getFontSize(10),
|
|
|
|
+ fontWeight: '600',
|
|
|
|
+ paddingLeft: 8,
|
|
|
|
+ flexShrink: 0
|
|
|
|
+ }}
|
|
|
|
+ >
|
|
|
|
+ {formattedTime}
|
|
|
|
+ </Text>
|
|
|
|
+ {renderTicks(currentMessage)}
|
|
|
|
+ </View>
|
|
</View>
|
|
</View>
|
|
- ) : null;
|
|
|
|
|
|
+ );
|
|
}}
|
|
}}
|
|
- renderCustomView={renderCustomView}
|
|
|
|
- isCustomViewBottom={true} // should be false to show reply on top
|
|
|
|
- // bottomContainerStyle={{
|
|
|
|
- // right: {
|
|
|
|
- // backgroundColor: 'red'
|
|
|
|
- // },
|
|
|
|
- // left: {
|
|
|
|
- // backgroundColor: 'red'
|
|
|
|
- // }
|
|
|
|
- // }}
|
|
|
|
/>
|
|
/>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
@@ -805,6 +841,8 @@ const ChatScreen = ({ route }: { route: any }) => {
|
|
renderBubble={renderBubble}
|
|
renderBubble={renderBubble}
|
|
renderMessageImage={renderMessageImage}
|
|
renderMessageImage={renderMessageImage}
|
|
renderInputToolbar={renderInputToolbar}
|
|
renderInputToolbar={renderInputToolbar}
|
|
|
|
+ renderCustomView={renderReplyMessageView}
|
|
|
|
+ isCustomViewBottom={false}
|
|
messageContainerRef={messageContainerRef}
|
|
messageContainerRef={messageContainerRef}
|
|
renderSend={(props) => (
|
|
renderSend={(props) => (
|
|
<View
|
|
<View
|
|
@@ -861,7 +899,6 @@ const ChatScreen = ({ route }: { route: any }) => {
|
|
renderAvatar={null}
|
|
renderAvatar={null}
|
|
maxComposerHeight={100}
|
|
maxComposerHeight={100}
|
|
renderComposer={(props) => <Composer {...props} />}
|
|
renderComposer={(props) => <Composer {...props} />}
|
|
- isCustomViewBottom={true}
|
|
|
|
keyboardShouldPersistTaps="handled"
|
|
keyboardShouldPersistTaps="handled"
|
|
shouldUpdateMessage={(props, nextProps) =>
|
|
shouldUpdateMessage={(props, nextProps) =>
|
|
highlightedMessageId === nextProps.currentMessage._id
|
|
highlightedMessageId === nextProps.currentMessage._id
|