Browse Source

leave sending msg until new one

feature/mobile-responsiveness
PhilReact 2 days ago
parent
commit
a7ccaf53e0
  1. 66
      src/MessageQueueContext.tsx
  2. 6
      src/background.ts
  3. 19
      src/components/Chat/ChatDirect.tsx
  4. 31
      src/components/Chat/ChatGroup.tsx

66
src/MessageQueueContext.tsx

@ -12,12 +12,11 @@ export const MessageQueueProvider = ({ children }) => {
const [queueChats, setQueueChats] = useState({}); // Stores chats and status for display const [queueChats, setQueueChats] = useState({}); // Stores chats and status for display
const isProcessingRef = useRef(false); // To track if the queue is being processed const isProcessingRef = useRef(false); // To track if the queue is being processed
const maxRetries = 4; const maxRetries = 4;
const clearStatesMessageQueueProvider = useCallback(() => { const clearStatesMessageQueueProvider = useCallback(() => {
setQueueChats({}) setQueueChats({});
messageQueue = [] messageQueue = [];
isProcessingRef.current = false isProcessingRef.current = false;
}, []) }, []);
// Function to add a message to the queue // Function to add a message to the queue
const addToQueue = useCallback((sendMessageFunc, messageObj, type, groupDirectId) => { const addToQueue = useCallback((sendMessageFunc, messageObj, type, groupDirectId) => {
@ -40,16 +39,43 @@ export const MessageQueueProvider = ({ children }) => {
// Add the message to the global messageQueue // Add the message to the global messageQueue
messageQueue = [ 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 // Start processing the queue if not already processing
processQueue(); processQueue();
}, []); }, []);
// Function to process the messageQueue // Method to process with new messages and groupDirectId
// Function to process the messageQueue const processWithNewMessages = (newMessages, groupDirectId) => {
const processQueue = useCallback(async () => { 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 currently processing or the queue is empty, return
if (isProcessingRef.current || messageQueue.length === 0) return; if (isProcessingRef.current || messageQueue.length === 0) return;
@ -77,18 +103,17 @@ const processQueue = useCallback(async () => {
// Execute the function stored in the messageQueue // Execute the function stored in the messageQueue
await currentMessage.func(); await currentMessage.func();
// Remove the message from the messageQueue after successful sending // 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 // Remove the message from queueChats after success
setQueueChats((prev) => { // setQueueChats((prev) => {
const updatedChats = { ...prev }; // const updatedChats = { ...prev };
updatedChats[groupDirectId] = updatedChats[groupDirectId].filter( // updatedChats[groupDirectId] = updatedChats[groupDirectId].filter(
(item) => item.identifier !== identifier // (item) => item.identifier !== identifier
); // );
return updatedChats; // return updatedChats;
}); // });
} catch (error) { } catch (error) {
console.error('Message sending failed', error); console.error('Message sending failed', error);
@ -109,7 +134,7 @@ const processQueue = useCallback(async () => {
updatedChats[groupDirectId][chatIndex].status = 'failed-permanent'; updatedChats[groupDirectId][chatIndex].status = 'failed-permanent';
// Remove the message from the messageQueue after max retries // 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 // Remove the message from queueChats after failure
updatedChats[groupDirectId] = updatedChats[groupDirectId].filter( updatedChats[groupDirectId] = updatedChats[groupDirectId].filter(
@ -129,9 +154,8 @@ const processQueue = useCallback(async () => {
isProcessingRef.current = false; isProcessingRef.current = false;
}, []); }, []);
return ( return (
<MessageQueueContext.Provider value={{ addToQueue, queueChats, clearStatesMessageQueueProvider }}> <MessageQueueContext.Provider value={{ addToQueue, queueChats, clearStatesMessageQueueProvider, processWithNewMessages }}>
{children} {children}
</MessageQueueContext.Provider> </MessageQueueContext.Provider>
); );

6
src/background.ts

@ -1583,6 +1583,7 @@ async function sendChatDirect({
chatReference, chatReference,
messageText, messageText,
publicKeyOfRecipient, publicKeyOfRecipient,
otherData
}) { }) {
let recipientPublicKey; let recipientPublicKey;
let recipientAddress = address; let recipientAddress = address;
@ -1618,6 +1619,7 @@ async function sendChatDirect({
const finalJson = { const finalJson = {
message: messageText, message: messageText,
version: 2, version: 2,
...(otherData || {})
}; };
const messageStringified = JSON.stringify(finalJson); const messageStringified = JSON.stringify(finalJson);
const tx = await createTransaction(18, keyPair, { const tx = await createTransaction(18, keyPair, {
@ -1667,7 +1669,7 @@ async function decryptSingleFunc({
const decryptToUnit8Array = base64ToUint8Array(res); const decryptToUnit8Array = base64ToUint8Array(res);
const responseData = uint8ArrayToObject(decryptToUnit8Array); const responseData = uint8ArrayToObject(decryptToUnit8Array);
holdMessages.push({ ...message, text: responseData }); holdMessages.push({ ...message, decryptedData: responseData });
} catch (error) {} } catch (error) {}
} }
return holdMessages; return holdMessages;
@ -3996,6 +3998,7 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
messageText, messageText,
publicKeyOfRecipient, publicKeyOfRecipient,
address, address,
otherData
} = request.payload; } = request.payload;
sendChatDirect({ sendChatDirect({
@ -4005,6 +4008,7 @@ chrome?.runtime?.onMessage.addListener((request, sender, sendResponse) => {
typeMessage, typeMessage,
publicKeyOfRecipient, publicKeyOfRecipient,
address, address,
otherData
}) })
.then((res) => { .then((res) => {
sendResponse(res); sendResponse(res);

19
src/components/Chat/ChatDirect.tsx

@ -16,12 +16,14 @@ import { getPublicKey } from '../../background';
import { useMessageQueue } from '../../MessageQueueContext'; import { useMessageQueue } from '../../MessageQueueContext';
import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from '../../utils/events'; import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from '../../utils/events';
import ArrowBackIcon from '@mui/icons-material/ArrowBack'; 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}) => { 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 [isFocusedParent, setIsFocusedParent] = useState(false);
const [messages, setMessages] = useState([]) const [messages, setMessages] = useState([])
@ -79,6 +81,9 @@ export const ChatDirect = ({ myAddress, isNewChat, selectedDirect, setSelectedDi
}}, (response) => { }}, (response) => {
if (!response?.error) { if (!response?.error) {
processWithNewMessages(response, selectedDirect?.address)
res(response) res(response)
if(hasInitialized.current){ 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 { try {
const directTo = isNewChatVar ? directToValue : address const directTo = isNewChatVar ? directToValue : address
if(!directTo) return if(!directTo) return
return new Promise((res, rej)=> { return new Promise((res, rej)=> {
chrome?.runtime?.sendMessage({ action: "sendChatDirect", payload: { chrome?.runtime?.sendMessage({ action: "sendChatDirect", payload: {
directTo, chatReference, messageText, publicKeyOfRecipient, address: directTo directTo, chatReference, messageText, otherData, publicKeyOfRecipient, address: directTo
}}, async (response) => { }}, async (response) => {
if (!response?.error) { if (!response?.error) {
@ -290,8 +295,11 @@ const clearEditorContent = () => {
await sendChatDirect({ messageText: htmlContent}, null, null, true) await sendChatDirect({ messageText: htmlContent}, null, null, true)
return return
} }
const otherData = {
specialId: uid.rnd()
}
const sendMessageFunc = async () => { 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 // Add the function to the queue
@ -300,7 +308,8 @@ const clearEditorContent = () => {
text: htmlContent, text: htmlContent,
timestamp: Date.now(), timestamp: Date.now(),
senderName: myName, senderName: myName,
sender: myAddress sender: myAddress,
...(otherData || {})
}, },
} }

31
src/components/Chat/ChatGroup.tsx

@ -16,6 +16,10 @@ import { PUBLIC_NOTIFICATION_CODE_FIRST_SECRET_KEY } from '../../constants/codes
import { useMessageQueue } from '../../MessageQueueContext' import { useMessageQueue } from '../../MessageQueueContext'
import { executeEvent } from '../../utils/events' import { executeEvent } from '../../utils/events'
import { Box } from '@mui/material' 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 timeoutIdRef = useRef(null); // Timeout ID reference
const groupSocketTimeoutRef = useRef(null); // Group Socket Timeout reference const groupSocketTimeoutRef = useRef(null); // Group Socket Timeout reference
const editorRef = useRef(null); const editorRef = useRef(null);
const { queueChats, addToQueue, } = useMessageQueue(); const { queueChats, addToQueue, processWithNewMessages } = useMessageQueue();
const setEditorRef = (editorInstance) => { const setEditorRef = (editorInstance) => {
editorRef.current = editorInstance; editorRef.current = editorInstance;
@ -92,8 +96,13 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey,
data: encryptedMessages, data: encryptedMessages,
secretKeyObject: secretKey secretKeyObject: secretKey
}}, (response) => { }}, (response) => {
if (!response?.error) { if (!response?.error) {
processWithNewMessages(response?.map((item)=> {
return {
...item,
...(item?.decryptedData || {})
}
}), selectedGroup)
res(response) res(response)
if(hasInitialized.current){ if(hasInitialized.current){
@ -101,7 +110,7 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey,
return { return {
...item, ...item,
id: item.signature, id: item.signature,
text: item.text, text: item?.decryptedData?.message || "",
unread: item?.sender === myAddress ? false : true unread: item?.sender === myAddress ? false : true
} }
} ) } )
@ -111,7 +120,7 @@ export const ChatGroup = ({selectedGroup, secretKey, setSecretKey, getSecretKey,
return { return {
...item, ...item,
id: item.signature, id: item.signature,
text: item.text, text: item?.decryptedData?.message || "",
unread: false unread: false
} }
} ) } )
@ -296,11 +305,18 @@ const clearEditorContent = () => {
setIsSending(true) setIsSending(true)
const message = htmlContent const message = htmlContent
const secretKeyObject = await getSecretKey(false, true) 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 encryptSingle = await encryptChatMessage(message64, secretKeyObject)
// const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle}) // const res = await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
const sendMessageFunc = async () => { const sendMessageFunc = async () => {
await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle}) await sendChatGroup({groupId: selectedGroup,messageText: encryptSingle})
}; };
@ -311,7 +327,8 @@ const clearEditorContent = () => {
text: message, text: message,
timestamp: Date.now(), timestamp: Date.now(),
senderName: myName, senderName: myName,
sender: myAddress sender: myAddress,
...(otherData || {})
}, },
} }

Loading…
Cancel
Save