fix double chat and parsed ui emoji

This commit is contained in:
PhilReact 2024-11-24 05:49:33 +02:00
parent 84b6535750
commit 8cb88a6380
2 changed files with 87 additions and 75 deletions

View File

@ -10,14 +10,16 @@ const uid = new ShortUniqueId({ length: 8 });
export const MessageQueueProvider = ({ children }) => { export const MessageQueueProvider = ({ children }) => {
const messageQueueRef = useRef([]); const messageQueueRef = useRef([]);
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 maxRetries = 2; const maxRetries = 2;
const clearStatesMessageQueueProvider = useCallback(() => { const clearStatesMessageQueueProvider = useCallback(() => {
setQueueChats({}); setQueueChats({});
messageQueueRef.current = []; messageQueueRef.current = [];
isProcessingRef.current = false;
}, []); }, []);
// Promise-based lock to prevent concurrent executions
const processingPromiseRef = useRef(Promise.resolve());
// 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) => {
const tempId = uid.rnd(); const tempId = uid.rnd();
@ -25,7 +27,7 @@ export const MessageQueueProvider = ({ children }) => {
...messageObj, ...messageObj,
type, type,
groupDirectId, groupDirectId,
signature: uid.rnd(), signature: uid.rnd(),
identifier: tempId, identifier: tempId,
retries: 0, // Retry count for display purposes retries: 0, // Retry count for display purposes
status: 'pending' // Initial status is 'pending' status: 'pending' // Initial status is 'pending'
@ -37,59 +39,63 @@ export const MessageQueueProvider = ({ children }) => {
[groupDirectId]: [...(prev[groupDirectId] || []), chatData] [groupDirectId]: [...(prev[groupDirectId] || []), chatData]
})); }));
// Add the message to the global messageQueueRef.current // Add the message to the global messageQueueRef
messageQueueRef.current = [ messageQueueRef.current.push({
...messageQueueRef.current, func: sendMessageFunc,
{ func: sendMessageFunc, identifier: tempId, groupDirectId, specialId: messageObj?.message?.specialId } identifier: tempId,
]; groupDirectId,
specialId: messageObj?.message?.specialId
});
// Start processing the queue if not already processing // Start processing the queue
processQueue([], groupDirectId); processQueue([], groupDirectId);
}, []); }, []);
// Method to process with new messages and groupDirectId // Function to process the message queue
const processWithNewMessages = (newMessages, groupDirectId) => { const processQueue = useCallback((newMessages = [], groupDirectId) => {
processQueue(newMessages, groupDirectId); processingPromiseRef.current = processingPromiseRef.current
}; .then(() => processQueueInternal(newMessages, groupDirectId))
.catch((err) => console.error('Error in processQueue:', err));
}, []);
// Function to process the messageQueueRef.current and handle new messages // Internal function to handle queue processing
const processQueue = useCallback(async (newMessages = [], groupDirectId) => { const processQueueInternal = async (newMessages, groupDirectId) => {
// Filter out any message in the queue that matches the specialId from newMessages // Remove any messages from the queue that match the specialId from newMessages
messageQueueRef.current = messageQueueRef.current.filter((msg) => { if (newMessages.length > 0) {
return !newMessages.some(newMsg => newMsg?.specialId === msg?.specialId); messageQueueRef.current = messageQueueRef.current.filter((msg) => {
}); return !newMessages.some(newMsg => newMsg?.specialId === msg?.specialId);
});
// Remove any corresponding entries in queueChats for the provided groupDirectId // Remove corresponding entries in queueChats for the provided groupDirectId
setQueueChats((prev) => { setQueueChats((prev) => {
const updatedChats = { ...prev }; const updatedChats = { ...prev };
if (updatedChats[groupDirectId]) { if (updatedChats[groupDirectId]) {
// Remove any message in queueChats that has a matching specialId updatedChats[groupDirectId] = updatedChats[groupDirectId].filter((chat) => {
updatedChats[groupDirectId] = updatedChats[groupDirectId].filter((chat) => { return !newMessages.some(newMsg => newMsg?.specialId === chat?.message?.specialId);
});
return !newMessages.some(newMsg => newMsg?.specialId === chat?.message?.specialId);
});
updatedChats[groupDirectId] = updatedChats[groupDirectId].filter((chat) => { // Remove messages with status 'failed-permanent'
return chat?.status !== 'failed-permanent' updatedChats[groupDirectId] = updatedChats[groupDirectId].filter((chat) => {
}); return chat?.status !== 'failed-permanent';
});
// If no more chats for this group, delete the groupDirectId entry // If no more chats for this group, delete the groupDirectId entry
if (updatedChats[groupDirectId].length === 0) { if (updatedChats[groupDirectId].length === 0) {
delete updatedChats[groupDirectId]; delete updatedChats[groupDirectId];
}
} }
} return updatedChats;
return updatedChats; });
}); }
// If currently processing or the queue is empty, return // If the queue is empty, no need to process
if (isProcessingRef.current || messageQueueRef.current.length === 0) return; if (messageQueueRef.current.length === 0) return;
isProcessingRef.current = true; // Lock the queue for processing // Process messages sequentially
while (messageQueueRef.current.length > 0) { while (messageQueueRef.current.length > 0) {
const currentMessage = messageQueueRef.current[0]; // Get the first message in the queue const currentMessage = messageQueueRef.current[0]; // Get the first message in the queue
const { groupDirectId, identifier } = currentMessage; const { groupDirectId, identifier } = currentMessage;
// Update the chat status to 'sending' // Update the chat status to 'sending'
setQueueChats((prev) => { setQueueChats((prev) => {
const updatedChats = { ...prev }; const updatedChats = { ...prev };
@ -103,24 +109,33 @@ export const MessageQueueProvider = ({ children }) => {
} }
return updatedChats; return updatedChats;
}); });
try { try {
// Execute the function stored in the messageQueueRef.current // Execute the function stored in the messageQueueRef
await currentMessage.func(); await currentMessage.func();
// Remove the message from the messageQueueRef.current after successful sending
messageQueueRef.current.shift(); // Slice here remains for successful messages // Remove the message from the queue after successful sending
messageQueueRef.current.shift();
// Remove the message from queueChats after success
// setQueueChats((prev) => { // Remove the message from queueChats
// const updatedChats = { ...prev }; setQueueChats((prev) => {
// updatedChats[groupDirectId] = updatedChats[groupDirectId].filter( const updatedChats = { ...prev };
// (item) => item.identifier !== identifier if (updatedChats[groupDirectId]) {
// ); updatedChats[groupDirectId] = updatedChats[groupDirectId].filter(
// return updatedChats; (item) => item.identifier !== identifier
// }); );
// If no more chats for this group, delete the groupDirectId entry
if (updatedChats[groupDirectId].length === 0) {
delete updatedChats[groupDirectId];
}
}
return updatedChats;
});
} catch (error) { } catch (error) {
console.error('Message sending failed', error); console.error('Message sending failed', error);
// Retry logic // Retry logic
setQueueChats((prev) => { setQueueChats((prev) => {
const updatedChats = { ...prev }; const updatedChats = { ...prev };
@ -136,28 +151,25 @@ export const MessageQueueProvider = ({ children }) => {
} else { } else {
// Max retries reached, set status to 'failed-permanent' // Max retries reached, set status to 'failed-permanent'
updatedChats[groupDirectId][chatIndex].status = 'failed-permanent'; updatedChats[groupDirectId][chatIndex].status = 'failed-permanent';
// Remove the message from the messageQueueRef.current after max retries // Remove the message from the queue after max retries
messageQueueRef.current.shift();// Slice for failed messages after max retries messageQueueRef.current.shift();
// // Remove the message from queueChats after failure
// updatedChats[groupDirectId] = updatedChats[groupDirectId].filter(
// (item) => item.identifier !== identifier
// );
} }
} }
return updatedChats; return updatedChats;
}); });
} }
// Delay between processing each message to avoid overlap // Optional delay between processing messages
await new Promise((res) => setTimeout(res, 5000)); // await new Promise((res) => setTimeout(res, 5000));
} }
};
// Reset the processing lock once all messages are processed
isProcessingRef.current = false; // Method to process with new messages and groupDirectId
}, []); const processWithNewMessages = (newMessages, groupDirectId) => {
processQueue(newMessages, groupDirectId);
};
return ( return (
<MessageQueueContext.Provider value={{ addToQueue, queueChats, clearStatesMessageQueueProvider, processWithNewMessages }}> <MessageQueueContext.Provider value={{ addToQueue, queueChats, clearStatesMessageQueueProvider, processWithNewMessages }}>
{children} {children}

View File

@ -193,7 +193,7 @@ export const decodeBase64ForUIChatMessages = (messages)=> {
for(const msg of messages){ for(const msg of messages){
try { try {
const decoded = atob(msg?.data); const decoded = atob(msg?.data);
const parseDecoded = JSON.parse(decoded) const parseDecoded =JSON.parse(decodeURIComponent(escape(decoded)))
if(parseDecoded?.messageText){ if(parseDecoded?.messageText){
msgs.push({ msgs.push({
...msg, ...msg,