Link Previews

This commit is contained in:
Scott Nonnenberg 2019-01-15 19:03:56 -08:00
parent 91ef39e482
commit 813924685e
36 changed files with 2298 additions and 134 deletions

View file

@ -759,6 +759,7 @@
const { getName } = Contact;
const contact = quotedMessage.getContact();
const attachments = quotedMessage.get('attachments');
const preview = quotedMessage.get('preview');
const body = quotedMessage.get('body');
const embeddedContact = quotedMessage.get('contact');
@ -767,32 +768,45 @@
? getName(embeddedContact[0])
: '';
const media =
attachments && attachments.length ? attachments : preview || [];
return {
author: contact.id,
id: quotedMessage.get('sent_at'),
text: body || embeddedContactName,
attachments: await Promise.all(
(attachments || []).map(async attachment => {
const { contentType, fileName, thumbnail } = attachment;
media
.filter(
attachment =>
(attachment && attachment.thumbnail) || attachment.message
)
.map(async attachment => {
const { fileName } = attachment;
return {
contentType,
// Our protos library complains about this field being undefined, so we
// force it to null
fileName: fileName || null,
thumbnail: thumbnail
? {
...(await loadAttachmentData(thumbnail)),
objectUrl: getAbsoluteAttachmentPath(thumbnail.path),
}
: null,
};
})
const thumbnail = attachment.thumbnail || attachment.image;
const contentType =
attachment.contentType ||
(attachment.image && attachment.image.contentType);
return {
contentType,
// Our protos library complains about this field being undefined, so we
// force it to null
fileName: fileName || null,
thumbnail: thumbnail
? {
...(await loadAttachmentData(thumbnail)),
objectUrl: getAbsoluteAttachmentPath(thumbnail.path),
}
: null,
};
})
),
};
},
sendMessage(body, attachments, quote) {
sendMessage(body, attachments, quote, preview) {
this.clearTypingTimers();
const destination = this.id;
@ -819,6 +833,7 @@
body,
conversationId: destination,
quote,
preview,
attachments,
sent_at: now,
received_at: now,
@ -885,6 +900,7 @@
body,
attachmentsWithData,
quote,
preview,
now,
expireTimer,
profileKey,
@ -1621,7 +1637,7 @@
const { attributes } = message;
const { schemaVersion } = attributes;
if (schemaVersion < Message.CURRENT_SCHEMA_VERSION) {
if (schemaVersion < Message.VERSION_NEEDED_FOR_DISPLAY) {
// Yep, we really do want to wait for each of these
// eslint-disable-next-line no-await-in-loop
const upgradedMessage = await upgradeMessageSchema(attributes);

View file

@ -24,6 +24,7 @@
getAbsoluteAttachmentPath,
loadAttachmentData,
loadQuoteData,
loadPreviewData,
writeNewAttachmentData,
} = window.Signal.Migrations;
@ -425,6 +426,7 @@
attachments: attachments.map(attachment =>
this.getPropsForAttachment(attachment)
),
previews: this.getPropsForPreview(),
quote: this.getPropsForQuote(),
authorAvatarPath,
isExpired: this.hasExpired,
@ -434,6 +436,7 @@
onRetrySend: () => this.retrySend(),
onShowDetail: () => this.trigger('show-message-detail', this),
onDelete: () => this.trigger('delete', this),
onClickLinkPreview: url => this.trigger('navigate-to', url),
onClickAttachment: attachment =>
this.trigger('show-lightbox', {
attachment,
@ -526,6 +529,15 @@
thumbnail: thumbnailWithObjectUrl,
});
},
getPropsForPreview() {
const previews = this.get('preview') || [];
return previews.map(preview => ({
...preview,
domain: window.Signal.LinkPreviews.getDomain(preview.url),
image: preview.image ? this.getPropsForAttachment(preview.image) : null,
}));
},
getPropsForQuote() {
const quote = this.get('quote');
if (!quote) {
@ -712,6 +724,7 @@
(this.get('attachments') || []).map(loadAttachmentData)
);
const quoteWithData = await loadQuoteData(this.get('quote'));
const previewWithData = await loadPreviewData(this.get('preview'));
const conversation = this.getConversation();
const options = conversation.getSendOptions();
@ -725,6 +738,7 @@
this.get('body'),
attachmentsWithData,
quoteWithData,
previewWithData,
this.get('sent_at'),
this.get('expireTimer'),
profileKey,
@ -741,6 +755,7 @@
timestamp: this.get('sent_at'),
attachments: attachmentsWithData,
quote: quoteWithData,
preview: previewWithData,
needsSync: !this.get('synced'),
expireTimer: this.get('expireTimer'),
profileKey,
@ -775,6 +790,7 @@
(this.get('attachments') || []).map(loadAttachmentData)
);
const quoteWithData = await loadQuoteData(this.get('quote'));
const previewWithData = await loadPreviewData(this.get('preview'));
const { wrap, sendOptions } = ConversationController.prepareForSend(
number
@ -784,6 +800,7 @@
this.get('body'),
attachmentsWithData,
quoteWithData,
previewWithData,
this.get('sent_at'),
this.get('expireTimer'),
profileKey,
@ -1146,6 +1163,22 @@
message.set({ group_update: groupUpdate });
}
}
const urls = window.Signal.LinkPreviews.findLinks(dataMessage.body);
const incomingPreview = dataMessage.preview || [];
const preview = incomingPreview.filter(
item =>
(item.image || item.title) &&
urls.includes(item.url) &&
window.Signal.LinkPreviews.isLinkInWhitelist(item.url)
);
if (preview.length > incomingPreview.length) {
window.log.info(
`${message.idForLogging()}: Eliminated ${preview.length -
incomingPreview.length} previews with invalid urls'`
);
}
message.set({
attachments: dataMessage.attachments,
body: dataMessage.body,
@ -1158,6 +1191,7 @@
hasFileAttachments: dataMessage.hasFileAttachments,
hasVisualMediaAttachments: dataMessage.hasVisualMediaAttachments,
quote: dataMessage.quote,
preview,
schemaVersion: dataMessage.schemaVersion,
});
if (type === 'outgoing') {