mirror of
https://github.com/Qortal/qortal-mobile.git
synced 2025-06-04 07:26:59 +00:00
fix double chat and parsed ui emoji
This commit is contained in:
parent
0a3b36f9aa
commit
0b05b59b90
@ -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,8 +27,8 @@ export const MessageQueueProvider = ({ children }) => {
|
|||||||
...messageObj,
|
...messageObj,
|
||||||
type,
|
type,
|
||||||
groupDirectId,
|
groupDirectId,
|
||||||
|
signature: uid.rnd(),
|
||||||
identifier: tempId,
|
identifier: tempId,
|
||||||
signature: uid.rnd(),
|
|
||||||
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}
|
||||||
|
@ -100,6 +100,7 @@ import {
|
|||||||
import { getData, removeKeysAndLogout, storeData } from "./utils/chromeStorage";
|
import { getData, removeKeysAndLogout, storeData } from "./utils/chromeStorage";
|
||||||
import {BackgroundFetch} from '@transistorsoft/capacitor-background-fetch';
|
import {BackgroundFetch} from '@transistorsoft/capacitor-background-fetch';
|
||||||
import { LocalNotifications } from '@capacitor/local-notifications';
|
import { LocalNotifications } from '@capacitor/local-notifications';
|
||||||
|
import { executeEvent } from "./utils/events";
|
||||||
|
|
||||||
const uid = new ShortUniqueId({ length: 9, dictionary: 'number' });
|
const uid = new ShortUniqueId({ length: 9, dictionary: 'number' });
|
||||||
|
|
||||||
@ -3255,7 +3256,10 @@ LocalNotifications.addListener('localNotificationActionPerformed', async (event)
|
|||||||
const initializeBackButton = () => {
|
const initializeBackButton = () => {
|
||||||
|
|
||||||
CapacitorApp.addListener('backButton', (event) => {
|
CapacitorApp.addListener('backButton', (event) => {
|
||||||
|
console.log('event', event)
|
||||||
// Prevent the app from closing on back button press
|
// Prevent the app from closing on back button press
|
||||||
|
executeEvent("handleMobileNativeBack", {
|
||||||
|
});
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -92,6 +92,7 @@ import { Apps } from "../Apps/Apps";
|
|||||||
import { AppsNavBar } from "../Apps/AppsNavBar";
|
import { AppsNavBar } from "../Apps/AppsNavBar";
|
||||||
import { AppsDesktop } from "../Apps/AppsDesktop";
|
import { AppsDesktop } from "../Apps/AppsDesktop";
|
||||||
import { formatEmailDate } from "./QMailMessages";
|
import { formatEmailDate } from "./QMailMessages";
|
||||||
|
import { useHandleMobileNativeBack } from "../../hooks/useHandleMobileNativeBack";
|
||||||
|
|
||||||
// let touchStartY = 0;
|
// let touchStartY = 0;
|
||||||
// let disablePullToRefresh = false;
|
// let disablePullToRefresh = false;
|
||||||
@ -380,7 +381,6 @@ export const Group = ({
|
|||||||
desktopViewMode
|
desktopViewMode
|
||||||
}: GroupProps) => {
|
}: GroupProps) => {
|
||||||
const [desktopSideView, setDesktopSideView] = useState('groups')
|
const [desktopSideView, setDesktopSideView] = useState('groups')
|
||||||
|
|
||||||
const [secretKey, setSecretKey] = useState(null);
|
const [secretKey, setSecretKey] = useState(null);
|
||||||
const [secretKeyPublishDate, setSecretKeyPublishDate] = useState(null);
|
const [secretKeyPublishDate, setSecretKeyPublishDate] = useState(null);
|
||||||
const lastFetchedSecretKey = useRef(null);
|
const lastFetchedSecretKey = useRef(null);
|
||||||
@ -1535,6 +1535,10 @@ export const Group = ({
|
|||||||
setIsOpenSideViewGroups(false)
|
setIsOpenSideViewGroups(false)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
useHandleMobileNativeBack({mobileViewMode, goToHome, setMobileViewMode})
|
||||||
|
|
||||||
|
|
||||||
const goToAnnouncements = async () => {
|
const goToAnnouncements = async () => {
|
||||||
setGroupSection("default");
|
setGroupSection("default");
|
||||||
await new Promise((res) => {
|
await new Promise((res) => {
|
||||||
|
23
src/hooks/useHandleMobileNativeBack.tsx
Normal file
23
src/hooks/useHandleMobileNativeBack.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import React, { useCallback, useEffect } from 'react'
|
||||||
|
import { subscribeToEvent, unsubscribeFromEvent } from '../utils/events';
|
||||||
|
|
||||||
|
export const useHandleMobileNativeBack = ({mobileViewMode, goToHome, setMobileViewMode}) => {
|
||||||
|
|
||||||
|
|
||||||
|
const handleMobileNativeBackFunc = useCallback((e) => {
|
||||||
|
if(mobileViewMode === 'groups'){
|
||||||
|
goToHome()
|
||||||
|
} else if(mobileViewMode === "group"){
|
||||||
|
setMobileViewMode('groups')
|
||||||
|
}
|
||||||
|
}, [mobileViewMode]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
subscribeToEvent("handleMobileNativeBack", handleMobileNativeBackFunc);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
unsubscribeFromEvent("handleMobileNativeBack", handleMobileNativeBackFunc);
|
||||||
|
};
|
||||||
|
}, [handleMobileNativeBackFunc]);
|
||||||
|
return null
|
||||||
|
}
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user