Use minimal replacement class for MessageModel

This commit is contained in:
Scott Nonnenberg 2025-01-10 08:18:32 +10:00 committed by GitHub
parent 6b00cf756e
commit f846678b90
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
95 changed files with 3919 additions and 4457 deletions

View file

@ -32,6 +32,9 @@ import {
RECEIPT_BATCHER_WAIT_MS,
} from '../types/Receipt';
import { drop } from '../util/drop';
import { getMessageById } from '../messages/getMessageById';
import { postSaveUpdates } from '../util/cleanup';
import { MessageModel } from '../models/messages';
const { deleteSentProtoRecipient, removeSyncTaskById } = DataWriter;
@ -78,12 +81,11 @@ const processReceiptBatcher = createWaitBatcher({
> = new Map();
function addReceiptAndTargetMessage(
message: MessageAttributesType,
message: MessageModel,
receipt: MessageReceiptAttributesType
): void {
const existing = receiptsByMessageId.get(message.id);
if (!existing) {
window.MessageCache.toMessageAttributes(message);
receiptsByMessageId.set(message.id, [receipt]);
} else {
existing.push(receipt);
@ -151,9 +153,10 @@ const processReceiptBatcher = createWaitBatcher({
);
if (targetMessages.length) {
targetMessages.forEach(msg =>
addReceiptAndTargetMessage(msg, receipt)
);
targetMessages.forEach(msg => {
const model = window.MessageCache.register(new MessageModel(msg));
addReceiptAndTargetMessage(model, receipt);
});
} else {
// Nope, no target message was found
const { receiptSync } = receipt;
@ -188,53 +191,43 @@ async function processReceiptsForMessage(
}
// Get message from cache or DB
const message = await window.MessageCache.resolveAttributes(
'processReceiptsForMessage',
messageId
);
const message = await getMessageById(messageId);
if (!message) {
throw new Error(
`processReceiptsForMessage: Failed to find message ${messageId}`
);
}
// Note: it is important to have no `await` in between `resolveAttributes` and
// `setAttributes` since it might overwrite other updates otherwise.
const { updatedMessage, validReceipts, droppedReceipts } =
updateMessageWithReceipts(message, receipts);
const { validReceipts } = await updateMessageWithReceipts(message, receipts);
// Save it to cache & to DB, and remove dropped receipts
await Promise.all([
window.MessageCache.setAttributes({
messageId,
messageAttributes: updatedMessage,
skipSaveToDatabase: false,
}),
Promise.all(droppedReceipts.map(remove)),
]);
const ourAci = window.textsecure.storage.user.getCheckedAci();
await DataWriter.saveMessage(message.attributes, { ourAci, postSaveUpdates });
// Confirm/remove receipts, and delete sent protos
for (const receipt of validReceipts) {
// eslint-disable-next-line no-await-in-loop
await remove(receipt);
drop(addToDeleteSentProtoBatcher(receipt, updatedMessage));
drop(addToDeleteSentProtoBatcher(receipt, message.attributes));
}
// notify frontend listeners
const conversation = window.ConversationController.get(
message.conversationId
message.get('conversationId')
);
conversation?.debouncedUpdateLastMessage?.();
}
function updateMessageWithReceipts(
message: MessageAttributesType,
async function updateMessageWithReceipts(
message: MessageModel,
receipts: Array<MessageReceiptAttributesType>
): {
updatedMessage: MessageAttributesType;
): Promise<{
validReceipts: Array<MessageReceiptAttributesType>;
droppedReceipts: Array<MessageReceiptAttributesType>;
} {
const logId = `updateMessageWithReceipts(timestamp=${message.timestamp})`;
}> {
const logId = `updateMessageWithReceipts(timestamp=${message.get('timestamp')})`;
const droppedReceipts: Array<MessageReceiptAttributesType> = [];
const receiptsToProcess = receipts.filter(receipt => {
if (shouldDropReceipt(receipt, message)) {
if (shouldDropReceipt(receipt, message.attributes)) {
const { receiptSync } = receipt;
log.info(
`${logId}: Dropping a receipt ${receiptSync.type} for sentAt=${receiptSync.messageSentAt}`
@ -257,14 +250,16 @@ function updateMessageWithReceipts(
);
// Generate the updated message synchronously
let updatedMessage: MessageAttributesType = { ...message };
let { attributes } = message;
for (const receipt of receiptsToProcess) {
updatedMessage = {
...updatedMessage,
...updateMessageSendStateWithReceipt(updatedMessage, receipt),
attributes = {
...attributes,
...updateMessageSendStateWithReceipt(attributes, receipt),
};
}
return { updatedMessage, validReceipts: receiptsToProcess, droppedReceipts };
message.set(attributes);
return { validReceipts: receiptsToProcess };
}
const deleteSentProtoBatcher = createWaitBatcher({
@ -310,7 +305,7 @@ function getTargetMessage({
sourceConversationId: string;
messagesMatchingTimestamp: ReadonlyArray<MessageAttributesType>;
targetTimestamp: number;
}): MessageAttributesType | null {
}): MessageModel | null {
if (messagesMatchingTimestamp.length === 0) {
return null;
}
@ -366,7 +361,7 @@ function getTargetMessage({
}
const message = matchingMessages[0];
return window.MessageCache.toMessageAttributes(message);
return window.MessageCache.register(new MessageModel(message));
}
const wasDeliveredWithSealedSender = (
conversationId: string,