From 0d17b3d1898c7cffeba7dde684523eaccdafe463 Mon Sep 17 00:00:00 2001 From: danhmaisgt Date: Fri, 11 Oct 2024 14:42:12 +0700 Subject: [PATCH] feat: media bubble handle upload itself --- src/chat/ChatScreen.tsx | 26 ++++++-- src/chat/components/bubble/CustomBubble.tsx | 70 ++++++++++++++++++++- 2 files changed, 89 insertions(+), 7 deletions(-) diff --git a/src/chat/ChatScreen.tsx b/src/chat/ChatScreen.tsx index d1e70c4..0efdc2e 100644 --- a/src/chat/ChatScreen.tsx +++ b/src/chat/ChatScreen.tsx @@ -29,7 +29,11 @@ import type { IUserInfo, MessageProps, } from '../interfaces'; -import { formatMessageText, isOtherUserTyping } from '../utilities'; +import { + formatMessageText, + isMediaMessage, + isOtherUserTyping, +} from '../utilities'; import SelectedImageModal from './components/SelectedImage'; import { CustomBubble, CustomImageVideoBubbleProps } from './components/bubble'; import { clearConversation } from '../reducer'; @@ -108,6 +112,7 @@ export const ChatScreen: React.FC = ({ const [selectedMessage, setSelectedMessage] = useState( null ); + const [mediaMessages, setMediaMessages] = useState([]); const conversationRef = useRef( conversationInfo @@ -180,11 +185,15 @@ export const ChatScreen: React.FC = ({ GiftedChat.append(previousMessages, [convertMessage as MessageProps]) ); - await firebaseInstance.sendMessage(messages); + if (!isMediaMessage(messages.type)) { + await firebaseInstance.sendMessage(messages); - timeoutMessageRef.current = setTimeout(() => { - sendMessageNotification?.(); - }, timeoutSendNotify); + timeoutMessageRef.current = setTimeout(() => { + sendMessageNotification?.(); + }, timeoutSendNotify); + } else { + setMediaMessages((prev) => [...prev, messages]); + } }, [ firebaseInstance, @@ -325,6 +334,13 @@ export const ChatScreen: React.FC = ({ isCurrentlyPlaying={ currentPlayingMessageId === bubble.currentMessage?.id } + mediaMessageIds={mediaMessages?.map((e) => e._id.toString())} + finishUploadCallback={(id) => { + setMediaMessages((prev) => + prev.filter((message) => message._id !== id) + ); + }} + notifyRef={timeoutMessageRef} /> ); }; diff --git a/src/chat/components/bubble/CustomBubble.tsx b/src/chat/components/bubble/CustomBubble.tsx index e6d87f3..755c9a9 100644 --- a/src/chat/components/bubble/CustomBubble.tsx +++ b/src/chat/components/bubble/CustomBubble.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { StyleProp, StyleSheet, Text, View, ViewStyle } from 'react-native'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'; import { MessageTypes, type MessageProps } from '../../../interfaces'; import { Bubble } from 'react-native-gifted-chat'; import { @@ -8,6 +8,8 @@ import { } from './CustomImageVideoBubble'; import MessageStatus from '../MessageStatus'; import { CustomBubbleVoice } from './CustomBubbleVoice'; +import { formatSendMessage } from '../../../utilities'; +import { FirestoreServices } from '../../../services/firebase'; interface CustomBubbleProps { bubbleMessage: Bubble['props']; @@ -23,6 +25,11 @@ interface CustomBubbleProps { customMessageStatus?: (hasUnread: boolean) => JSX.Element; onSetCurrentId: (id: string) => void; isCurrentlyPlaying: boolean; + mediaMessageIds: string[]; + finishUploadCallback: (id: string) => void; + sendMessageNotification?: () => void; + timeoutSendNotify?: number; + notifyRef?: React.MutableRefObject; } export const CustomBubble: React.FC = ({ @@ -39,7 +46,15 @@ export const CustomBubble: React.FC = ({ customMessageStatus, onSetCurrentId, isCurrentlyPlaying, + mediaMessageIds, + finishUploadCallback, + sendMessageNotification, + timeoutSendNotify, + notifyRef, }) => { + const [isUploading, setIsUploading] = useState(false); + const firebaseInstance = useRef(FirestoreServices.getInstance()).current; + const styleBuble = { left: { backgroundColor: 'transparent' }, right: { backgroundColor: 'transparent' }, @@ -129,6 +144,57 @@ export const CustomBubble: React.FC = ({ } } }; + + const uploadFileToStorage = useCallback(async () => { + if (bubbleMessage.currentMessage) { + const { text, type, path, extension, fileName, size, duration } = + bubbleMessage.currentMessage || {}; + const messageData = formatSendMessage( + firebaseInstance.userId, + text, + type, + path, + extension, + fileName, + size, + duration + ); + + await firebaseInstance.sendMessageWithFile(messageData); + finishUploadCallback(bubbleMessage.currentMessage._id.toString()); + setIsUploading(false); + + if (notifyRef) { + notifyRef.current = setTimeout(() => { + sendMessageNotification?.(); + }, timeoutSendNotify); + } + } + }, [ + bubbleMessage.currentMessage, + finishUploadCallback, + firebaseInstance, + notifyRef, + sendMessageNotification, + timeoutSendNotify, + ]); + + useEffect(() => { + if ( + !isUploading && + bubbleMessage.currentMessage?._id && + mediaMessageIds.includes(bubbleMessage.currentMessage._id.toString()) + ) { + setIsUploading(true); + uploadFileToStorage(); + } + }, [ + bubbleMessage?.currentMessage?._id, + isUploading, + mediaMessageIds, + uploadFileToStorage, + ]); + return ( {bubbleMessage.currentMessage &&