diff --git a/app/providers/DialogProvider/DialogProvider.tsx b/app/providers/DialogProvider/DialogProvider.tsx index 38affed..94b3ce9 100644 --- a/app/providers/DialogProvider/DialogProvider.tsx +++ b/app/providers/DialogProvider/DialogProvider.tsx @@ -466,6 +466,87 @@ export function DialogProvider(props: DialogProviderProps) { setMessages((prev) => ([...prev, newMessage])); }, [privatePlain]); + /** + * Обработчик сообщений для синхронизации своих же сообщений в группе + */ + usePacket(0x06, async (packet: PacketMessage) => { + const fromPublicKey = packet.getFromPublicKey(); + const toPublicKey = packet.getToPublicKey(); + + if(fromPublicKey != publicKey){ + /** + * Это не синхронизация, игнорируем ее в этом обработчике + */ + return; + } + + if(toPublicKey != props.dialog){ + /** + * Исправление кросс диалогового сообщения + */ + return; + } + + if(!hasGroup(props.dialog)){ + /** + * Если это не групповое сообщение, то для него есть + * другой обработчик выше + */ + return; + } + const content = packet.getContent(); + const timestamp = packet.getTimestamp(); + /** + * Генерация рандомного ID сообщения по SEED нужна для того, + * чтобы сообщение записанное здесь в стек сообщений совпадало + * с тем что записывается в БД в файле useDialogFiber.ts + */ + const messageId = packet.getMessageId(); + + const groupKey = await getGroupKey(toPublicKey); + if(!groupKey){ + log("Group key not found for group " + toPublicKey); + error("Message dropped because group key not found for group " + toPublicKey); + return; + } + info("New group message packet received from " + fromPublicKey); + + let decryptedContent = ''; + + try{ + decryptedContent = await decodeWithPassword(groupKey, content); + }catch(e) { + decryptedContent = ''; + } + + let attachments: Attachment[] = []; + for(let i = 0; i < packet.getAttachments().length; i++) { + const attachment = packet.getAttachments()[i]; + attachments.push({ + id: attachment.id, + preview: attachment.preview, + type: attachment.type, + blob: attachment.type == AttachmentType.MESSAGES ? await decodeWithPassword(groupKey, attachment.blob) : "" + }); + } + + const newMessage : Message = { + from_public_key: fromPublicKey, + to_public_key: toPublicKey, + content: content, + timestamp: timestamp, + readed: 0, + chacha_key: groupKey, + from_me: 1, + plain_message: decryptedContent, + delivered: DeliveredMessageState.DELIVERED, + message_id: messageId, + attachments: attachments + }; + + setMessages((prev) => ([...prev, newMessage])); + }, [messages, idle, props.dialog]); + /** * Обработчик для личных сообщений */ diff --git a/app/providers/DialogProvider/useDialogFiber.ts b/app/providers/DialogProvider/useDialogFiber.ts index 112bb5c..c2399ce 100644 --- a/app/providers/DialogProvider/useDialogFiber.ts +++ b/app/providers/DialogProvider/useDialogFiber.ts @@ -391,15 +391,22 @@ export function useDialogFiber() { */ usePacket(0x07, async (packet: PacketRead) => { runTaskInQueue(async () => { - if (!hasGroup(packet.getToPublicKey())) { + const fromPublicKey = packet.getFromPublicKey(); + const toPublicKey = packet.getToPublicKey(); + if (!hasGroup(toPublicKey)) { /** * Если это не относится к группам, то игнорируем здесь, * для этого есть отдельный слушатель usePacket выше */ return; } - const fromPublicKey = packet.getFromPublicKey(); - const toPublicKey = packet.getToPublicKey(); + if(fromPublicKey == publicKey){ + /** + * Игнорируем если это наше прочтение + * которое получается при синхронизации + */ + return; + } await runQuery(`UPDATE messages SET read = 1 WHERE to_public_key = ? AND from_public_key = ? AND account = ?`, [toPublicKey, publicKey, publicKey]); await updateSyncTime(Date.now()); updateDialog(toPublicKey); diff --git a/app/providers/DialogProvider/useSynchronize.ts b/app/providers/DialogProvider/useSynchronize.ts index 1692014..82c5bef 100644 --- a/app/providers/DialogProvider/useSynchronize.ts +++ b/app/providers/DialogProvider/useSynchronize.ts @@ -27,7 +27,7 @@ import { useDialogsCache } from "./useDialogsCache"; import { PacketRead } from "../ProtocolProvider/protocol/packets/packet.read"; import { useLogger } from "@/app/hooks/useLogger"; import { useIdle } from "@mantine/hooks"; -import { useViewPanelsState, ViewPanelsState } from "@/app/hooks/useViewPanelsState"; +import { useViewPanelsState } from "@/app/hooks/useViewPanelsState"; import { useWindowFocus } from "@/app/hooks/useWindowFocus"; /** @@ -145,6 +145,13 @@ export function useSynchronize() { const content = packet.getContent(); const timestamp = packet.getTimestamp(); const messageId = packet.getMessageId(); + if(hasGroup(toPublicKey)){ + /** + * Игнорируем если это сообщение для группы, для них есть отдельный слушатель usePacket ниже + */ + return; + } + if (fromPublicKey != publicKey) { /** * Игнорируем если это не сообщение от нас @@ -262,6 +269,43 @@ export function useSynchronize() { })); }); }, [updateDialog, publicKey]); + + /** + * Обработчик синхронизации прочтения групповых сообщений + */ + usePacket(0x07, async (packet: PacketRead) => { + runTaskInQueue(async () => { + const fromPublicKey = packet.getFromPublicKey(); + const toPublicKey = packet.getToPublicKey(); + if (!hasGroup(toPublicKey)) { + /** + * Если это не относится к группам, то игнорируем здесь, + * для этого есть отдельный слушатель usePacket выше + */ + return; + } + if(fromPublicKey != publicKey){ + /** + * Игнорируем если это наше прочтение + * которое получается при синхронизации + */ + return; + } + await runQuery(`UPDATE messages SET read = 1 WHERE to_public_key = ? AND from_public_key != ? AND account = ?`, + [toPublicKey, publicKey, publicKey]); + await updateSyncTime(Date.now()); + updateDialog(toPublicKey); + addOrUpdateDialogCache(toPublicKey, getDialogCache(toPublicKey).map((message) => { + if (!message.readed && message.from_public_key != publicKey) { + return { + ...message, + readed: 1 + } + } + return message; + })); + }); + }, [updateDialog]); /** * Обработчик сообщений для синхронизации своих же сообщений в группе @@ -337,9 +381,9 @@ export function useSynchronize() { to_public_key: toPublicKey, content: content, timestamp: timestamp, - readed: idle ? 0 : 1, + readed: 0, chacha_key: groupKey, - from_me: fromPublicKey == publicKey ? 1 : 0, + from_me: 1, plain_message: decryptedContent, delivered: DeliveredMessageState.DELIVERED, message_id: messageId, @@ -353,10 +397,9 @@ export function useSynchronize() { toPublicKey, content, timestamp, - /**если текущий открытый диалог == беседе (которая приходит в toPublicKey) */ - (currentDialogPublicKeyView == toPublicKey && !idle && viewState != ViewPanelsState.DIALOGS_PANEL_ONLY) ? 1 : 0, - '', - 0, + 0, //по умолчанию не прочитаны + "", + 1, //Свои же сообщения всегда от нас await encodeWithPassword(privatePlain, decryptedContent), publicKey, messageId,