Refactor: Prepare Message function props for conversation scope
This commit is contained in:
parent
7e58594038
commit
d342b23cbc
13 changed files with 300 additions and 256 deletions
|
@ -162,17 +162,8 @@
|
|||
isUnread() {
|
||||
return !!this.get('unread');
|
||||
},
|
||||
// Important to allow for this.unset('unread'), save to db, then fetch()
|
||||
// to propagate. We don't want the unset key in the db so our unread index
|
||||
// stays small.
|
||||
merge(model) {
|
||||
const attributes = model.attributes || model;
|
||||
|
||||
const { unread } = attributes;
|
||||
if (typeof unread === 'undefined') {
|
||||
this.unset('unread');
|
||||
}
|
||||
|
||||
this.set(attributes);
|
||||
},
|
||||
getNameForNumber(number) {
|
||||
|
@ -311,13 +302,12 @@
|
|||
const conversation = this.getConversation();
|
||||
const isGroup = conversation && !conversation.isPrivate();
|
||||
const phoneNumber = this.get('key_changed');
|
||||
const onVerify = () =>
|
||||
this.trigger('show-identity', this.findContact(phoneNumber));
|
||||
const showIdentity = id => this.trigger('show-identity', id);
|
||||
|
||||
return {
|
||||
isGroup,
|
||||
contact: this.findAndFormatContact(phoneNumber),
|
||||
onVerify,
|
||||
showIdentity,
|
||||
};
|
||||
},
|
||||
getPropsForVerificationNotification() {
|
||||
|
@ -339,21 +329,17 @@
|
|||
return ConversationController.get(phoneNumber);
|
||||
},
|
||||
findAndFormatContact(phoneNumber) {
|
||||
const contactModel = this.findContact(phoneNumber);
|
||||
if (contactModel) {
|
||||
return contactModel.getProps();
|
||||
}
|
||||
|
||||
const { format } = PhoneNumber;
|
||||
const regionCode = storage.get('regionCode');
|
||||
|
||||
const contactModel = this.findContact(phoneNumber);
|
||||
const color = contactModel ? contactModel.getColor() : null;
|
||||
|
||||
return {
|
||||
phoneNumber: format(phoneNumber, {
|
||||
ourRegionCode: regionCode,
|
||||
}),
|
||||
color,
|
||||
avatarPath: contactModel ? contactModel.getAvatarPath() : null,
|
||||
name: contactModel ? contactModel.getName() : null,
|
||||
profileName: contactModel ? contactModel.getProfileName() : null,
|
||||
title: contactModel ? contactModel.getTitle() : null,
|
||||
};
|
||||
},
|
||||
getPropsForGroupNotification() {
|
||||
|
@ -460,7 +446,7 @@
|
|||
snippet: this.get('snippet'),
|
||||
};
|
||||
},
|
||||
getPropsForMessage(options) {
|
||||
getPropsForMessage() {
|
||||
const phoneNumber = this.getSource();
|
||||
const contact = this.findAndFormatContact(phoneNumber);
|
||||
const contactModel = this.findContact(phoneNumber);
|
||||
|
@ -479,9 +465,7 @@
|
|||
|
||||
const conversation = this.getConversation();
|
||||
const isGroup = conversation && !conversation.isPrivate();
|
||||
|
||||
const attachments = this.get('attachments') || [];
|
||||
const firstAttachment = attachments[0];
|
||||
|
||||
return {
|
||||
text: this.createNonBreakingLastSeparator(this.get('body')),
|
||||
|
@ -500,28 +484,30 @@
|
|||
.filter(attachment => !attachment.error)
|
||||
.map(attachment => this.getPropsForAttachment(attachment)),
|
||||
previews: this.getPropsForPreview(),
|
||||
quote: this.getPropsForQuote(options),
|
||||
quote: this.getPropsForQuote(),
|
||||
authorAvatarPath,
|
||||
isExpired: this.hasExpired,
|
||||
expirationLength,
|
||||
expirationTimestamp,
|
||||
onReply: () => this.trigger('reply', this),
|
||||
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,
|
||||
message: this,
|
||||
}),
|
||||
|
||||
onDownload: isDangerous =>
|
||||
this.trigger('download', {
|
||||
attachment: firstAttachment,
|
||||
message: this,
|
||||
isDangerous,
|
||||
}),
|
||||
replyToMessage: id => this.trigger('reply', id),
|
||||
retrySend: id => this.trigger('retry', id),
|
||||
deleteMessage: id => this.trigger('delete', id),
|
||||
showMessageDetail: id => this.trigger('show-message-detail', id),
|
||||
|
||||
openConversation: conversationId =>
|
||||
this.trigger('open-conversation', conversationId),
|
||||
showContactDetail: contactOptions =>
|
||||
this.trigger('show-contact-detail', contactOptions),
|
||||
|
||||
showVisualAttachment: lightboxOptions =>
|
||||
this.trigger('show-lightbox', lightboxOptions),
|
||||
downloadAttachment: downloadOptions =>
|
||||
this.trigger('download', downloadOptions),
|
||||
|
||||
openLink: url => this.trigger('navigate-to', url),
|
||||
scrollToMessage: scrollOptions =>
|
||||
this.trigger('scroll-to-message', scrollOptions),
|
||||
};
|
||||
},
|
||||
createNonBreakingLastSeparator(text) {
|
||||
|
@ -551,20 +537,6 @@
|
|||
const contact = contacts[0];
|
||||
const firstNumber =
|
||||
contact.number && contact.number[0] && contact.number[0].value;
|
||||
const onSendMessage = firstNumber
|
||||
? () => {
|
||||
this.trigger('open-conversation', firstNumber);
|
||||
}
|
||||
: null;
|
||||
const onClick = async () => {
|
||||
// First let's be sure that the signal account check is complete.
|
||||
await window.checkForSignalAccount(firstNumber);
|
||||
|
||||
this.trigger('show-contact-detail', {
|
||||
contact,
|
||||
hasSignalAccount: window.hasSignalAccount(firstNumber),
|
||||
});
|
||||
};
|
||||
|
||||
// Would be nice to do this before render, on initial load of message
|
||||
if (!window.isSignalAccountCheckComplete(firstNumber)) {
|
||||
|
@ -576,9 +548,9 @@
|
|||
return contactSelector(contact, {
|
||||
regionCode,
|
||||
getAbsoluteAttachmentPath,
|
||||
onSendMessage,
|
||||
onClick,
|
||||
hasSignalAccount: window.hasSignalAccount(firstNumber),
|
||||
signalAccount: window.hasSignalAccount(firstNumber)
|
||||
? firstNumber
|
||||
: null,
|
||||
});
|
||||
},
|
||||
processQuoteAttachment(attachment) {
|
||||
|
@ -610,8 +582,7 @@
|
|||
image: preview.image ? this.getPropsForAttachment(preview.image) : null,
|
||||
}));
|
||||
},
|
||||
getPropsForQuote(options = {}) {
|
||||
const { noClick } = options;
|
||||
getPropsForQuote() {
|
||||
const quote = this.get('quote');
|
||||
if (!quote) {
|
||||
return null;
|
||||
|
@ -620,7 +591,7 @@
|
|||
const { format } = PhoneNumber;
|
||||
const regionCode = storage.get('regionCode');
|
||||
|
||||
const { author, id, referencedMessageNotFound } = quote;
|
||||
const { author, id: sentAt, referencedMessageNotFound } = quote;
|
||||
const contact = author && ConversationController.get(author);
|
||||
const authorColor = contact ? contact.getColor() : 'grey';
|
||||
|
||||
|
@ -630,16 +601,6 @@
|
|||
const authorProfileName = contact ? contact.getProfileName() : null;
|
||||
const authorName = contact ? contact.getName() : null;
|
||||
const isFromMe = contact ? contact.id === this.OUR_NUMBER : false;
|
||||
const onClick = noClick
|
||||
? null
|
||||
: () => {
|
||||
this.trigger('scroll-to-message', {
|
||||
author,
|
||||
id,
|
||||
referencedMessageNotFound,
|
||||
});
|
||||
};
|
||||
|
||||
const firstAttachment = quote.attachments && quote.attachments[0];
|
||||
|
||||
return {
|
||||
|
@ -648,11 +609,12 @@
|
|||
? this.processQuoteAttachment(firstAttachment)
|
||||
: null,
|
||||
isFromMe,
|
||||
sentAt,
|
||||
authorId: author,
|
||||
authorPhoneNumber,
|
||||
authorProfileName,
|
||||
authorName,
|
||||
authorColor,
|
||||
onClick,
|
||||
referencedMessageNotFound,
|
||||
};
|
||||
},
|
||||
|
@ -740,6 +702,7 @@
|
|||
|
||||
return {
|
||||
...this.findAndFormatContact(id),
|
||||
|
||||
status: this.getStatus(id),
|
||||
errors: errorsForContact,
|
||||
isOutgoingKeyError,
|
||||
|
@ -765,8 +728,9 @@
|
|||
sentAt: this.get('sent_at'),
|
||||
receivedAt: this.get('received_at'),
|
||||
message: {
|
||||
...this.getPropsForMessage({ noClick: true }),
|
||||
...this.getPropsForMessage(),
|
||||
disableMenu: true,
|
||||
disableScroll: true,
|
||||
// To ensure that group avatar doesn't show up
|
||||
conversationType: 'direct',
|
||||
},
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
'reply',
|
||||
this.setQuoteMessage
|
||||
);
|
||||
this.listenTo(this.model.messageCollection, 'retry', this.retrySend);
|
||||
this.listenTo(
|
||||
this.model.messageCollection,
|
||||
'show-contact-detail',
|
||||
|
@ -705,8 +706,16 @@
|
|||
}
|
||||
},
|
||||
|
||||
async retrySend(messageId) {
|
||||
const message = this.model.messageCollection.get(messageId);
|
||||
if (!message) {
|
||||
throw new Error(`retrySend: Did not find message for id ${messageId}`);
|
||||
}
|
||||
await message.retrySend();
|
||||
},
|
||||
|
||||
async scrollToMessage(options = {}) {
|
||||
const { author, id, referencedMessageNotFound } = options;
|
||||
const { author, sentAt, referencedMessageNotFound } = options;
|
||||
|
||||
// For simplicity's sake, we show the 'not found' toast no matter what if we were
|
||||
// not able to find the referenced message when the quote was received.
|
||||
|
@ -724,7 +733,7 @@
|
|||
if (!messageAuthor || author !== messageAuthor.id) {
|
||||
return false;
|
||||
}
|
||||
if (id !== item.get('sent_at')) {
|
||||
if (sentAt !== item.get('sent_at')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -734,13 +743,16 @@
|
|||
// If there's no message already in memory, we won't be scrolling. So we'll gather
|
||||
// some more information then show an informative toast to the user.
|
||||
if (!targetMessage) {
|
||||
const collection = await window.Signal.Data.getMessagesBySentAt(id, {
|
||||
MessageCollection: Whisper.MessageCollection,
|
||||
});
|
||||
const collection = await window.Signal.Data.getMessagesBySentAt(
|
||||
sentAt,
|
||||
{
|
||||
MessageCollection: Whisper.MessageCollection,
|
||||
}
|
||||
);
|
||||
|
||||
const found = Boolean(
|
||||
collection.find(item => {
|
||||
const messageAuthor = item.getContact();
|
||||
|
||||
return messageAuthor && author === messageAuthor.id;
|
||||
})
|
||||
);
|
||||
|
@ -765,7 +777,7 @@
|
|||
toast.render();
|
||||
|
||||
window.log.info(
|
||||
`Error: had target message ${id} in messageCollection, but it was not in DOM`
|
||||
`Error: had target message ${targetMessage.idForLogging()} in messageCollection, but it was not in DOM`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -1202,23 +1214,25 @@
|
|||
dialog.focusCancel();
|
||||
},
|
||||
|
||||
showSafetyNumber(providedModel) {
|
||||
let model = providedModel;
|
||||
showSafetyNumber(id) {
|
||||
let conversation;
|
||||
|
||||
if (!model && this.model.isPrivate()) {
|
||||
if (!id && this.model.isPrivate()) {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
model = this.model;
|
||||
conversation = this.model;
|
||||
} else {
|
||||
conversation = ConversationController.get(id);
|
||||
}
|
||||
if (model) {
|
||||
if (conversation) {
|
||||
const view = new Whisper.KeyVerificationPanelView({
|
||||
model,
|
||||
model: conversation,
|
||||
});
|
||||
this.listenBack(view);
|
||||
this.updateHeader();
|
||||
}
|
||||
},
|
||||
|
||||
downloadAttachment({ attachment, message, isDangerous }) {
|
||||
downloadAttachment({ attachment, timestamp, isDangerous }) {
|
||||
if (isDangerous) {
|
||||
const toast = new Whisper.DangerousFileTypeToast();
|
||||
toast.$el.appendTo(this.$el);
|
||||
|
@ -1230,11 +1244,18 @@
|
|||
attachment,
|
||||
document,
|
||||
getAbsolutePath: getAbsoluteAttachmentPath,
|
||||
timestamp: message.get('sent_at'),
|
||||
timestamp,
|
||||
});
|
||||
},
|
||||
|
||||
deleteMessage(message) {
|
||||
deleteMessage(messageId) {
|
||||
const message = this.model.messageCollection.get(messageId);
|
||||
if (!message) {
|
||||
throw new Error(
|
||||
`deleteMessage: Did not find message for id ${messageId}`
|
||||
);
|
||||
}
|
||||
|
||||
const dialog = new Whisper.ConfirmationDialogView({
|
||||
message: i18n('deleteWarning'),
|
||||
okText: i18n('delete'),
|
||||
|
@ -1253,7 +1274,13 @@
|
|||
dialog.focusCancel();
|
||||
},
|
||||
|
||||
showLightbox({ attachment, message }) {
|
||||
showLightbox({ attachment, messageId }) {
|
||||
const message = this.model.messageCollection.get(messageId);
|
||||
if (!message) {
|
||||
throw new Error(
|
||||
`showLightbox: did not find message for id ${messageId}`
|
||||
);
|
||||
}
|
||||
const { contentType, path } = attachment;
|
||||
|
||||
if (
|
||||
|
@ -1333,7 +1360,14 @@
|
|||
Signal.Backbone.Views.Lightbox.show(this.lightboxGalleryView.el);
|
||||
},
|
||||
|
||||
showMessageDetail(message) {
|
||||
showMessageDetail(messageId) {
|
||||
const message = this.model.messageCollection.get(messageId);
|
||||
if (!message) {
|
||||
throw new Error(
|
||||
`showMessageDetail: Did not find message for id ${messageId}`
|
||||
);
|
||||
}
|
||||
|
||||
const onClose = () => {
|
||||
this.stopListening(message, 'change', update);
|
||||
this.resetPanel();
|
||||
|
@ -1358,24 +1392,16 @@
|
|||
view.render();
|
||||
},
|
||||
|
||||
showContactDetail({ contact, hasSignalAccount }) {
|
||||
const regionCode = storage.get('regionCode');
|
||||
const { contactSelector } = Signal.Types.Contact;
|
||||
|
||||
showContactDetail({ contact, signalAccount }) {
|
||||
const view = new Whisper.ReactWrapperView({
|
||||
Component: Signal.Components.ContactDetail,
|
||||
className: 'contact-detail-pane panel',
|
||||
props: {
|
||||
contact: contactSelector(contact, {
|
||||
regionCode,
|
||||
getAbsoluteAttachmentPath,
|
||||
}),
|
||||
hasSignalAccount,
|
||||
contact,
|
||||
signalAccount,
|
||||
onSendMessage: () => {
|
||||
const number =
|
||||
contact.number && contact.number[0] && contact.number[0].value;
|
||||
if (number) {
|
||||
this.openConversation(number);
|
||||
if (signalAccount) {
|
||||
this.openConversation(signalAccount);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -1592,20 +1618,25 @@
|
|||
this.focusMessageField();
|
||||
},
|
||||
|
||||
async setQuoteMessage(message) {
|
||||
async setQuoteMessage(messageId) {
|
||||
this.quote = null;
|
||||
this.quotedMessage = message;
|
||||
this.quotedMessage = null;
|
||||
|
||||
if (this.quoteHolder) {
|
||||
this.quoteHolder.unload();
|
||||
this.quoteHolder = null;
|
||||
}
|
||||
|
||||
const message = this.model.messageCollection.get(messageId);
|
||||
if (message) {
|
||||
const quote = await this.model.makeQuote(this.quotedMessage);
|
||||
this.quote = quote;
|
||||
this.quotedMessage = message;
|
||||
|
||||
this.focusMessageFieldAndClearDisabled();
|
||||
if (message) {
|
||||
const quote = await this.model.makeQuote(this.quotedMessage);
|
||||
this.quote = quote;
|
||||
|
||||
this.focusMessageFieldAndClearDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
this.renderQuotedMessage();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue