From a7ccaf53e0559e53c464815931999bfc9e47aa12 Mon Sep 17 00:00:00 2001 From: PhilReact Date: Wed, 18 Sep 2024 06:59:39 +0300 Subject: [PATCH] leave sending msg until new one --- src/MessageQueueContext.tsx | 66 ++++++++++++++++++++---------- src/background.ts | 6 ++- src/components/Chat/ChatDirect.tsx | 19 ++++++--- src/components/Chat/ChatGroup.tsx | 31 ++++++++++---- 4 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/MessageQueueContext.tsx b/src/MessageQueueContext.tsx index 2284da0..166a4c3 100644 --- a/src/MessageQueueContext.tsx +++ b/src/MessageQueueContext.tsx @@ -12,12 +12,11 @@ export const MessageQueueProvider = ({ children }) => { const [queueChats, setQueueChats] = useState({}); // Stores chats and status for display const isProcessingRef = useRef(false); // To track if the queue is being processed const maxRetries = 4; - const clearStatesMessageQueueProvider = useCallback(() => { - setQueueChats({}) - messageQueue = [] - isProcessingRef.current = false - }, []) + setQueueChats({}); + messageQueue = []; + isProcessingRef.current = false; + }, []); // Function to add a message to the queue const addToQueue = useCallback((sendMessageFunc, messageObj, type, groupDirectId) => { @@ -40,16 +39,43 @@ export const MessageQueueProvider = ({ children }) => { // Add the message to the global messageQueue messageQueue = [ ...messageQueue, - { func: sendMessageFunc, identifier: tempId, groupDirectId } + { func: sendMessageFunc, identifier: tempId, groupDirectId, specialId: messageObj?.message?.specialId } ]; // Start processing the queue if not already processing processQueue(); }, []); - // Function to process the messageQueue - // Function to process the messageQueue -const processQueue = useCallback(async () => { + // Method to process with new messages and groupDirectId + const processWithNewMessages = (newMessages, groupDirectId) => { + processQueue(newMessages, groupDirectId); + }; + + // Function to process the messageQueue and handle new messages + const processQueue = useCallback(async (newMessages = [], groupDirectId) => { + // Filter out any message in the queue that matches the specialId from newMessages + messageQueue = messageQueue.filter((msg) => { + return !newMessages.some(newMsg => newMsg?.specialId === msg?.specialId); + }); + + // Remove any corresponding entries in queueChats for the provided groupDirectId + setQueueChats((prev) => { + const updatedChats = { ...prev }; + if (updatedChats[groupDirectId]) { + // Remove any message in queueChats that has a matching specialId + updatedChats[groupDirectId] = updatedChats[groupDirectId].filter((chat) => { + + return !newMessages.some(newMsg => newMsg?.specialId === chat?.message?.specialId); + }); + + // If no more chats for this group, delete the groupDirectId entry + if (updatedChats[groupDirectId].length === 0) { + delete updatedChats[groupDirectId]; + } + } + return updatedChats; + }); + // If currently processing or the queue is empty, return if (isProcessingRef.current || messageQueue.length === 0) return; @@ -77,18 +103,17 @@ const processQueue = useCallback(async () => { // Execute the function stored in the messageQueue await currentMessage.func(); - // Remove the message from the messageQueue after successful sending - messageQueue = messageQueue.slice(1); + messageQueue = messageQueue.slice(1); // Slice here remains for successful messages // Remove the message from queueChats after success - setQueueChats((prev) => { - const updatedChats = { ...prev }; - updatedChats[groupDirectId] = updatedChats[groupDirectId].filter( - (item) => item.identifier !== identifier - ); - return updatedChats; - }); + // setQueueChats((prev) => { + // const updatedChats = { ...prev }; + // updatedChats[groupDirectId] = updatedChats[groupDirectId].filter( + // (item) => item.identifier !== identifier + // ); + // return updatedChats; + // }); } catch (error) { console.error('Message sending failed', error); @@ -109,7 +134,7 @@ const processQueue = useCallback(async () => { updatedChats[groupDirectId][chatIndex].status = 'failed-permanent'; // Remove the message from the messageQueue after max retries - messageQueue = messageQueue.slice(1); + messageQueue = messageQueue.slice(1); // Slice for failed messages after max retries // Remove the message from queueChats after failure updatedChats[groupDirectId] = updatedChats[groupDirectId].filter( @@ -129,9 +154,8 @@ const processQueue = useCallback(async () => { isProcessingRef.current = false; }, []); - return ( - + {children} ); diff --git a/src/background.ts b/src/background.ts index 00ceffc..86b1f11 100644 --- a/src/background.ts +++ b/src/background.ts @@ -1583,6 +1583,7 @@ async function sendChatDirect({ chatReference, messageText, publicKeyOfRecipient, + otherData }) { let recipientPublicKey; let recipientAddress = address; @@ -1618,6 +1619,7 @@ async function sendChatDirect({ const finalJson = { message: messageText, version: 2, + ...(otherData || {}) }; const messageStringified = JSON.stringify(finalJson); const tx = await createTransaction(18, keyPair, { @@ -1667,7 +1669,7 @@ async function decryptSingleFunc({ const decryptToUnit8Array = base64ToUint8Array(res); const responseData = uint8ArrayToObject(decryptToUnit8Array); - holdMessages.push({ ...message, text: responseData }); + holdMessages.push({ ...message, decryptedData: responseData }); } catch (error) {} } return holdMessages; @@ -3996,6 +3998,7 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { messageText, publicKeyOfRecipient, address, + otherData } = request.payload; sendChatDirect({ @@ -4005,6 +4008,7 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => { typeMessage, publicKeyOfRecipient, address, + otherData }) .then((res) => { sendResponse(res); diff --git a/src/components/Chat/ChatDirect.tsx b/src/components/Chat/ChatDirect.tsx index da49ba4..33325c8 100644 --- a/src/components/Chat/ChatDirect.tsx +++ b/src/components/Chat/ChatDirect.tsx @@ -16,12 +16,14 @@ import { getPublicKey } from '../../background'; import { useMessageQueue } from '../../MessageQueueContext'; import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from '../../utils/events'; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import ShortUniqueId from "short-unique-id"; +const uid = new ShortUniqueId({ length: 5 }); export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDirect, setNewChat, getTimestampEnterChat, myName, balance, close}) => { - const { queueChats, addToQueue, } = useMessageQueue(); + const { queueChats, addToQueue, processWithNewMessages} = useMessageQueue(); const [isFocusedParent, setIsFocusedParent] = useState(false); const [messages, setMessages] = useState([]) @@ -79,6 +81,9 @@ export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDi }}, (response) => { if (!response?.error) { + + processWithNewMessages(response, selectedDirect?.address) + res(response) if(hasInitialized.current){ @@ -210,14 +215,14 @@ export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDi -const sendChatDirect = async ({ chatReference = undefined, messageText}: any, address, publicKeyOfRecipient, isNewChatVar)=> { +const sendChatDirect = async ({ chatReference = undefined, messageText, otherData}: any, address, publicKeyOfRecipient, isNewChatVar)=> { try { const directTo = isNewChatVar ? directToValue : address if(!directTo) return return new Promise((res, rej)=> { chrome?.runtime?.sendMessage({ action: "sendChatDirect", payload: { - directTo, chatReference, messageText, publicKeyOfRecipient, address: directTo + directTo, chatReference, messageText, otherData, publicKeyOfRecipient, address: directTo }}, async (response) => { if (!response?.error) { @@ -290,8 +295,11 @@ const clearEditorContent = () => { await sendChatDirect({ messageText: htmlContent}, null, null, true) return } + const otherData = { + specialId: uid.rnd() + } const sendMessageFunc = async () => { - await sendChatDirect({ messageText: htmlContent}, selectedDirect?.address, publicKeyOfRecipient, false) + await sendChatDirect({ messageText: htmlContent, otherData}, selectedDirect?.address, publicKeyOfRecipient, false) }; // Add the function to the queue @@ -300,7 +308,8 @@ const clearEditorContent = () => { text: htmlContent, timestamp: Date.now(), senderName: myName, - sender: myAddress + sender: myAddress, + ...(otherData || {}) }, } diff --git a/src/components/Chat/ChatGroup.tsx b/src/components/Chat/ChatGroup.tsx index d7de9c4..162e415 100644 --- a/src/components/Chat/ChatGroup.tsx +++ b/src/components/Chat/ChatGroup.tsx @@ -16,6 +16,10 @@ import { PUBLIC_NOTIFICATION_CODE_FIRST_SECRET_KEY } from '../../constants/codes import { useMessageQueue } from '../../MessageQueueContext' import { executeEvent } from '../../utils/events' import { Box } from '@mui/material' +import ShortUniqueId from "short-unique-id"; + + +const uid = new ShortUniqueId({ length: 5 }); @@ -36,7 +40,7 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, const timeoutIdRef = useRef(null); // Timeout ID reference const groupSocketTimeoutRef = useRef(null); // Group Socket Timeout reference const editorRef = useRef(null); - const { queueChats, addToQueue, } = useMessageQueue(); + const { queueChats, addToQueue, processWithNewMessages } = useMessageQueue(); const setEditorRef = (editorInstance) => { editorRef.current = editorInstance; @@ -92,8 +96,13 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, data: encryptedMessages, secretKeyObject: secretKey }}, (response) => { - if (!response?.error) { + processWithNewMessages(response?.map((item)=> { + return { + ...item, + ...(item?.decryptedData || {}) + } + }), selectedGroup) res(response) if(hasInitialized.current){ @@ -101,7 +110,7 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, return { ...item, id: item.signature, - text: item.text, + text: item?.decryptedData?.message || "", unread: item?.sender === myAddress ? false : true } } ) @@ -111,7 +120,7 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey, return { ...item, id: item.signature, - text: item.text, + text: item?.decryptedData?.message || "", unread: false } } ) @@ -296,11 +305,18 @@ const clearEditorContent = () => { setIsSending(true) const message = htmlContent const secretKeyObject = await getSecretKey(false, true) - const message64: any = await objectToBase64(message) + const otherData = { + specialId: uid.rnd() + } + const objectMessage = { + message, + ...(otherData || {}) + } + const message64: any = await objectToBase64(objectMessage) const encryptSingle = await encryptChatMessage(message64, secretKeyObject) // const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle}) - + const sendMessageFunc = async () => { await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle}) }; @@ -311,7 +327,8 @@ const clearEditorContent = () => { text: message, timestamp: Date.now(), senderName: myName, - sender: myAddress + sender: myAddress, + ...(otherData || {}) }, }