Properly handle long message attachments for edited messages
This commit is contained in:
parent
4daa1e4569
commit
304287efef
3 changed files with 114 additions and 19 deletions
|
@ -517,25 +517,89 @@ async function _addAttachmentToMessage(
|
||||||
const attachmentSignature = getAttachmentSignature(attachment);
|
const attachmentSignature = getAttachmentSignature(attachment);
|
||||||
|
|
||||||
if (type === 'long-message') {
|
if (type === 'long-message') {
|
||||||
// Attachment wasn't downloaded yet.
|
let handledAnywhere = false;
|
||||||
if (!attachment.path) {
|
let attachmentData: Uint8Array | undefined;
|
||||||
message.set({
|
|
||||||
bodyAttachment: attachment,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { data } = await window.Signal.Migrations.loadAttachmentData(
|
if (attachment.path) {
|
||||||
attachment
|
const loaded = await window.Signal.Migrations.loadAttachmentData(
|
||||||
);
|
attachment
|
||||||
|
);
|
||||||
|
attachmentData = loaded.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const editHistory = message.get('editHistory');
|
||||||
|
if (editHistory) {
|
||||||
|
let handledInEditHistory = false;
|
||||||
|
|
||||||
|
const newEditHistory = editHistory.map(edit => {
|
||||||
|
// We've already downloaded a bodyAttachment for this edit
|
||||||
|
if (!edit.bodyAttachment) {
|
||||||
|
return edit;
|
||||||
|
}
|
||||||
|
// This attachment isn't destined for this edit
|
||||||
|
if (
|
||||||
|
getAttachmentSignature(edit.bodyAttachment) !== attachmentSignature
|
||||||
|
) {
|
||||||
|
return edit;
|
||||||
|
}
|
||||||
|
|
||||||
|
handledInEditHistory = true;
|
||||||
|
handledAnywhere = true;
|
||||||
|
|
||||||
|
// Attachment wasn't downloaded yet.
|
||||||
|
if (!attachmentData) {
|
||||||
|
return {
|
||||||
|
...edit,
|
||||||
|
bodyAttachment: attachment,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...edit,
|
||||||
|
body: Bytes.toString(attachmentData),
|
||||||
|
bodyAttachment: undefined,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (handledInEditHistory) {
|
||||||
|
message.set({ editHistory: newEditHistory });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingBodyAttachment = message.get('bodyAttachment');
|
||||||
|
// A bodyAttachment download might apply only to an edit, and not the top-level
|
||||||
|
if (!existingBodyAttachment) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
getAttachmentSignature(existingBodyAttachment) !== attachmentSignature
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handledAnywhere = true;
|
||||||
|
|
||||||
|
// Attachment wasn't downloaded yet.
|
||||||
|
if (!attachmentData) {
|
||||||
|
message.set({
|
||||||
|
bodyAttachment: attachment,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
message.set({
|
message.set({
|
||||||
body: Bytes.toString(data),
|
body: Bytes.toString(attachmentData),
|
||||||
bodyAttachment: undefined,
|
bodyAttachment: undefined,
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
if (attachment.path) {
|
if (attachment.path) {
|
||||||
void window.Signal.Migrations.deleteAttachmentData(attachment.path);
|
await window.Signal.Migrations.deleteAttachmentData(attachment.path);
|
||||||
|
}
|
||||||
|
if (!handledAnywhere) {
|
||||||
|
logger.warn(
|
||||||
|
`${logPrefix}: Long message attachment found no matching place to apply`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -556,6 +620,7 @@ async function _addAttachmentToMessage(
|
||||||
if (type === 'attachment') {
|
if (type === 'attachment') {
|
||||||
const attachments = message.get('attachments');
|
const attachments = message.get('attachments');
|
||||||
|
|
||||||
|
let handledAnywhere = false;
|
||||||
let handledInEditHistory = false;
|
let handledInEditHistory = false;
|
||||||
|
|
||||||
const editHistory = message.get('editHistory');
|
const editHistory = message.get('editHistory');
|
||||||
|
@ -572,6 +637,7 @@ async function _addAttachmentToMessage(
|
||||||
attachments: edit.attachments.map(item => {
|
attachments: edit.attachments.map(item => {
|
||||||
const newItem = maybeReplaceAttachment(item);
|
const newItem = maybeReplaceAttachment(item);
|
||||||
handledInEditHistory ||= item !== newItem;
|
handledInEditHistory ||= item !== newItem;
|
||||||
|
handledAnywhere ||= handledInEditHistory;
|
||||||
return newItem;
|
return newItem;
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
@ -584,10 +650,20 @@ async function _addAttachmentToMessage(
|
||||||
|
|
||||||
if (attachments) {
|
if (attachments) {
|
||||||
message.set({
|
message.set({
|
||||||
attachments: attachments.map(item => maybeReplaceAttachment(item)),
|
attachments: attachments.map(item => {
|
||||||
|
const newItem = maybeReplaceAttachment(item);
|
||||||
|
handledAnywhere ||= item !== newItem;
|
||||||
|
return newItem;
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!handledAnywhere) {
|
||||||
|
logger.warn(
|
||||||
|
`${logPrefix}: 'attachment' type found no matching place to apply`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,7 +719,7 @@ async function _addAttachmentToMessage(
|
||||||
const contact = message.get('contact');
|
const contact = message.get('contact');
|
||||||
if (!contact || contact.length <= index) {
|
if (!contact || contact.length <= index) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`_addAttachmentToMessage: contact didn't exist or ${index} was too large`
|
`${logPrefix}: contact didn't exist or ${index} was too large`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,7 +739,7 @@ async function _addAttachmentToMessage(
|
||||||
message.set({ contact: newContact });
|
message.set({ contact: newContact });
|
||||||
} else {
|
} else {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`_addAttachmentToMessage: Couldn't update contact with avatar attachment for message ${message.idForLogging()}`
|
`${logPrefix}: Couldn't update contact with avatar attachment for message`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,7 +806,7 @@ async function _addAttachmentToMessage(
|
||||||
if (type === 'sticker') {
|
if (type === 'sticker') {
|
||||||
const sticker = message.get('sticker');
|
const sticker = message.get('sticker');
|
||||||
if (!sticker) {
|
if (!sticker) {
|
||||||
throw new Error("_addAttachmentToMessage: sticker didn't exist");
|
throw new Error(`${logPrefix}: sticker didn't exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
message.set({
|
message.set({
|
||||||
|
@ -742,9 +818,7 @@ async function _addAttachmentToMessage(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(
|
throw new Error(`${logPrefix}: Unknown job type ${type}`);
|
||||||
`_addAttachmentToMessage: Unknown job type ${type} for message ${message.idForLogging()}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _checkOldAttachment(
|
function _checkOldAttachment(
|
||||||
|
|
1
ts/model-types.d.ts
vendored
1
ts/model-types.d.ts
vendored
|
@ -119,6 +119,7 @@ export type MessageReactionType = {
|
||||||
export type EditHistoryType = {
|
export type EditHistoryType = {
|
||||||
attachments?: Array<AttachmentType>;
|
attachments?: Array<AttachmentType>;
|
||||||
body?: string;
|
body?: string;
|
||||||
|
bodyAttachment?: AttachmentType;
|
||||||
bodyRanges?: ReadonlyArray<RawBodyRange>;
|
bodyRanges?: ReadonlyArray<RawBodyRange>;
|
||||||
preview?: Array<LinkPreviewType>;
|
preview?: Array<LinkPreviewType>;
|
||||||
quote?: QuotedMessageType;
|
quote?: QuotedMessageType;
|
||||||
|
|
|
@ -115,6 +115,7 @@ export async function handleEditMessage(
|
||||||
{
|
{
|
||||||
attachments: mainMessage.attachments,
|
attachments: mainMessage.attachments,
|
||||||
body: mainMessage.body,
|
body: mainMessage.body,
|
||||||
|
bodyAttachment: mainMessage.bodyAttachment,
|
||||||
bodyRanges: mainMessage.bodyRanges,
|
bodyRanges: mainMessage.bodyRanges,
|
||||||
preview: mainMessage.preview,
|
preview: mainMessage.preview,
|
||||||
quote: mainMessage.quote,
|
quote: mainMessage.quote,
|
||||||
|
@ -278,6 +279,25 @@ export async function handleEditMessage(
|
||||||
const updatedFields = await queueAttachmentDownloads(
|
const updatedFields = await queueAttachmentDownloads(
|
||||||
mainMessageModel.attributes
|
mainMessageModel.attributes
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// If we've scheduled a bodyAttachment download, we need that edit to know about it
|
||||||
|
if (updatedFields?.bodyAttachment) {
|
||||||
|
const existing =
|
||||||
|
updatedFields.editHistory || mainMessageModel.get('editHistory') || [];
|
||||||
|
|
||||||
|
updatedFields.editHistory = existing.map(item => {
|
||||||
|
if (item.timestamp !== editedMessage.timestamp) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
attachments: updatedFields.attachments,
|
||||||
|
bodyAttachment: updatedFields.bodyAttachment,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (updatedFields) {
|
if (updatedFields) {
|
||||||
mainMessageModel.set(updatedFields);
|
mainMessageModel.set(updatedFields);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue