Remove messageCollection from Conversation model
This commit is contained in:
parent
61ad1231df
commit
1520c80013
19 changed files with 332 additions and 431 deletions
|
@ -136,8 +136,6 @@ export class ConversationModel extends window.Backbone
|
|||
|
||||
jobQueue?: typeof window.PQueueType;
|
||||
|
||||
messageCollection?: MessageModelCollectionType;
|
||||
|
||||
ourNumber?: string;
|
||||
|
||||
ourUuid?: string;
|
||||
|
@ -168,6 +166,8 @@ export class ConversationModel extends window.Backbone
|
|||
|
||||
private isFetchingUUID?: boolean;
|
||||
|
||||
private hasAddedHistoryDisclaimer?: boolean;
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
defaults(): Partial<ConversationAttributesType> {
|
||||
return {
|
||||
|
@ -198,10 +198,6 @@ export class ConversationModel extends window.Backbone
|
|||
return this.get('uuid') || this.get('e164');
|
||||
}
|
||||
|
||||
handleMessageError(message: unknown, errors: unknown): void {
|
||||
this.trigger('messageError', message, errors);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
getContactCollection(): Backbone.Collection<ConversationModel> {
|
||||
const collection = new window.Backbone.Collection<ConversationModel>();
|
||||
|
@ -252,30 +248,9 @@ export class ConversationModel extends window.Backbone
|
|||
);
|
||||
}
|
||||
|
||||
this.messageCollection = new window.Whisper.MessageCollection([], {
|
||||
conversation: this,
|
||||
});
|
||||
|
||||
this.messageCollection.on('change:errors', this.handleMessageError, this);
|
||||
this.messageCollection.on('send-error', this.onMessageError, this);
|
||||
|
||||
this.listenTo(
|
||||
this.messageCollection,
|
||||
'add remove destroy content-changed',
|
||||
this.debouncedUpdateLastMessage
|
||||
);
|
||||
this.listenTo(this.messageCollection, 'sent', this.updateLastMessage);
|
||||
this.listenTo(this.messageCollection, 'send-error', this.updateLastMessage);
|
||||
|
||||
this.on('newmessage', this.onNewMessage);
|
||||
this.on('change:profileKey', this.onChangeProfileKey);
|
||||
|
||||
// Listening for out-of-band data updates
|
||||
this.on('delivered', this.updateAndMerge);
|
||||
this.on('read', this.updateAndMerge);
|
||||
this.on('expiration-change', this.updateAndMerge);
|
||||
this.on('expired', this.onExpired);
|
||||
|
||||
const sealedSender = this.get('sealedSender');
|
||||
if (sealedSender === undefined) {
|
||||
this.set({ sealedSender: SEALED_SENDER.UNKNOWN });
|
||||
|
@ -1238,64 +1213,10 @@ export class ConversationModel extends window.Backbone
|
|||
);
|
||||
}
|
||||
|
||||
async updateAndMerge(message: MessageModel): Promise<void> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this.debouncedUpdateLastMessage!();
|
||||
|
||||
const mergeMessage = () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const existing = this.messageCollection!.get(message.id);
|
||||
if (!existing) {
|
||||
return;
|
||||
}
|
||||
|
||||
existing.merge(message.attributes);
|
||||
};
|
||||
|
||||
await this.inProgressFetch;
|
||||
mergeMessage();
|
||||
}
|
||||
|
||||
async onExpired(message: MessageModel): Promise<void> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this.debouncedUpdateLastMessage!();
|
||||
|
||||
const removeMessage = () => {
|
||||
const { id } = message;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const existing = this.messageCollection!.get(id);
|
||||
if (!existing) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.log.info('Remove expired message from collection', {
|
||||
sentAt: existing.get('sent_at'),
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this.messageCollection!.remove(id);
|
||||
existing.trigger('expired');
|
||||
existing.cleanup();
|
||||
|
||||
// An expired message only counts as decrementing the message count, not
|
||||
// the sent message count
|
||||
this.decrementMessageCount();
|
||||
};
|
||||
|
||||
// If a fetch is in progress, then we need to wait until that's complete to
|
||||
// do this removal. Otherwise we could remove from messageCollection, then
|
||||
// the async database fetch could include the removed message.
|
||||
|
||||
await this.inProgressFetch;
|
||||
removeMessage();
|
||||
}
|
||||
|
||||
async onNewMessage(message: WhatIsThis): Promise<void> {
|
||||
const uuid = message.get ? message.get('sourceUuid') : message.sourceUuid;
|
||||
const e164 = message.get ? message.get('source') : message.source;
|
||||
const sourceDevice = message.get
|
||||
? message.get('sourceDevice')
|
||||
: message.sourceDevice;
|
||||
async onNewMessage(message: MessageModel): Promise<void> {
|
||||
const uuid = message.get('sourceUuid');
|
||||
const e164 = message.get('source');
|
||||
const sourceDevice = message.get('sourceDevice');
|
||||
|
||||
const sourceId = window.ConversationController.ensureContactIds({
|
||||
uuid,
|
||||
|
@ -1306,33 +1227,26 @@ export class ConversationModel extends window.Backbone
|
|||
// Clear typing indicator for a given contact if we receive a message from them
|
||||
this.clearContactTypingTimer(typingToken);
|
||||
|
||||
this.addSingleMessage(message);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this.debouncedUpdateLastMessage!();
|
||||
}
|
||||
|
||||
// For outgoing messages, we can call this directly. We're already loaded.
|
||||
addSingleMessage(message: MessageModel): MessageModel {
|
||||
const { id } = message;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const existing = this.messageCollection!.get(id);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const model = this.messageCollection!.add(message, { merge: true });
|
||||
// TODO use MessageUpdater.setToExpire
|
||||
model.setToExpire();
|
||||
message.setToExpire();
|
||||
|
||||
if (!existing) {
|
||||
const { messagesAdded } = window.reduxActions.conversations;
|
||||
const isNewMessage = true;
|
||||
messagesAdded(
|
||||
this.id,
|
||||
[model.getReduxData()],
|
||||
isNewMessage,
|
||||
window.isActive()
|
||||
);
|
||||
}
|
||||
const { messagesAdded } = window.reduxActions.conversations;
|
||||
const isNewMessage = true;
|
||||
messagesAdded(
|
||||
this.id,
|
||||
[message.getReduxData()],
|
||||
isNewMessage,
|
||||
window.isActive()
|
||||
);
|
||||
|
||||
return model;
|
||||
return message;
|
||||
}
|
||||
|
||||
// For incoming messages, they might arrive while we're in the middle of a bulk fetch
|
||||
|
@ -2119,10 +2033,6 @@ export class ConversationModel extends window.Backbone
|
|||
return true;
|
||||
}
|
||||
|
||||
onMessageError(): void {
|
||||
this.updateVerified();
|
||||
}
|
||||
|
||||
async safeGetVerified(): Promise<number> {
|
||||
const promise = window.textsecure.storage.protocol.getVerified(this.id);
|
||||
return promise.catch(
|
||||
|
@ -3629,12 +3539,14 @@ export class ConversationModel extends window.Backbone
|
|||
if (isDirectConversation(this.attributes)) {
|
||||
messageWithSchema.destination = destination;
|
||||
}
|
||||
const attributes: MessageModel = {
|
||||
const attributes: MessageAttributesType = {
|
||||
...messageWithSchema,
|
||||
id: window.getGuid(),
|
||||
};
|
||||
|
||||
const model = this.addSingleMessage(attributes);
|
||||
const model = this.addSingleMessage(
|
||||
new window.Whisper.Message(attributes)
|
||||
);
|
||||
if (sticker) {
|
||||
await addStickerPackReference(model.id, sticker.packId);
|
||||
}
|
||||
|
@ -4205,16 +4117,17 @@ export class ConversationModel extends window.Backbone
|
|||
return message;
|
||||
}
|
||||
|
||||
async addMessageHistoryDisclaimer(): Promise<MessageModel> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const lastMessage = this.messageCollection!.last();
|
||||
if (lastMessage && lastMessage.get('type') === 'message-history-unsynced') {
|
||||
// We do not need another message history disclaimer
|
||||
return lastMessage;
|
||||
}
|
||||
|
||||
async addMessageHistoryDisclaimer(): Promise<void> {
|
||||
const timestamp = Date.now();
|
||||
|
||||
if (this.hasAddedHistoryDisclaimer) {
|
||||
window.log.warn(
|
||||
`addMessageHistoryDisclaimer/${this.idForLogging()}: Refusing to add another this session`
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.hasAddedHistoryDisclaimer = true;
|
||||
|
||||
const model = new window.Whisper.Message(({
|
||||
type: 'message-history-unsynced',
|
||||
// Even though this isn't reflected to the user, we want to place the last seen
|
||||
|
@ -4238,8 +4151,6 @@ export class ConversationModel extends window.Backbone
|
|||
|
||||
const message = window.MessageController.register(id, model);
|
||||
this.addSingleMessage(message);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
isSearchable(): boolean {
|
||||
|
@ -4816,9 +4727,6 @@ export class ConversationModel extends window.Backbone
|
|||
}
|
||||
|
||||
async destroyMessages(): Promise<void> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
this.messageCollection!.reset([]);
|
||||
|
||||
this.set({
|
||||
lastMessage: null,
|
||||
timestamp: null,
|
||||
|
|
|
@ -284,7 +284,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
this.on('change:expirationStartTimestamp', this.setToExpire);
|
||||
this.on('change:expireTimer', this.setToExpire);
|
||||
this.on('unload', this.unload);
|
||||
this.on('expired', this.onExpired);
|
||||
this.setToExpire();
|
||||
|
||||
this.on('change', this.notifyRedux);
|
||||
|
@ -517,9 +516,6 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
errors: errorsForContact,
|
||||
isOutgoingKeyError,
|
||||
isUnidentifiedDelivery,
|
||||
onSendAnyway: () =>
|
||||
this.trigger('force-send', { contactId: id, messageId: this.id }),
|
||||
onShowSafetyNumber: () => this.trigger('show-identity', id),
|
||||
};
|
||||
}
|
||||
);
|
||||
|
@ -1797,6 +1793,9 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
async cleanup(): Promise<void> {
|
||||
const { messageDeleted } = window.reduxActions.conversations;
|
||||
messageDeleted(this.id, this.get('conversationId'));
|
||||
|
||||
this.getConversation()?.debouncedUpdateLastMessage?.();
|
||||
|
||||
window.MessageController.unregister(this.id);
|
||||
this.unload();
|
||||
await this.deleteData();
|
||||
|
@ -1953,7 +1952,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
preview: [],
|
||||
...additionalProperties,
|
||||
});
|
||||
this.trigger('content-changed');
|
||||
this.getConversation()?.debouncedUpdateLastMessage?.();
|
||||
|
||||
if (shouldPersist) {
|
||||
await window.Signal.Data.saveMessage(this.attributes, {
|
||||
|
@ -2625,10 +2624,17 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
async send(
|
||||
promise: Promise<CallbackResultType | void | null>
|
||||
): Promise<void | Array<void>> {
|
||||
this.trigger('pending');
|
||||
const conversation = this.getConversation();
|
||||
const updateLeftPane = conversation?.debouncedUpdateLastMessage;
|
||||
if (updateLeftPane) {
|
||||
updateLeftPane();
|
||||
}
|
||||
|
||||
return (promise as Promise<CallbackResultType>)
|
||||
.then(async result => {
|
||||
this.trigger('done');
|
||||
if (updateLeftPane) {
|
||||
updateLeftPane();
|
||||
}
|
||||
|
||||
// This is used by sendSyncMessage, then set to null
|
||||
if (result.dataMessage) {
|
||||
|
@ -2652,11 +2658,15 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
});
|
||||
}
|
||||
|
||||
this.trigger('sent', this);
|
||||
if (updateLeftPane) {
|
||||
updateLeftPane();
|
||||
}
|
||||
this.sendSyncMessage();
|
||||
})
|
||||
.catch((result: CustomError | CallbackResultType) => {
|
||||
this.trigger('done');
|
||||
if (updateLeftPane) {
|
||||
updateLeftPane();
|
||||
}
|
||||
|
||||
if ('dataMessage' in result && result.dataMessage) {
|
||||
this.set({ dataMessage: result.dataMessage });
|
||||
|
@ -2756,7 +2766,9 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
);
|
||||
}
|
||||
|
||||
this.trigger('send-error', this.get('errors'));
|
||||
if (updateLeftPane) {
|
||||
updateLeftPane();
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
});
|
||||
|
@ -2820,6 +2832,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
const conv = this.getConversation()!;
|
||||
this.set({ dataMessage });
|
||||
|
||||
const updateLeftPane = conv?.debouncedUpdateLastMessage;
|
||||
|
||||
try {
|
||||
this.set({
|
||||
// These are the same as a normal send()
|
||||
|
@ -2846,13 +2860,9 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
|||
await window.Signal.Data.saveMessage(this.attributes, {
|
||||
Message: window.Whisper.Message,
|
||||
});
|
||||
this.trigger('done');
|
||||
|
||||
const errors = this.get('errors');
|
||||
if (errors) {
|
||||
this.trigger('send-error', errors);
|
||||
} else {
|
||||
this.trigger('sent');
|
||||
if (updateLeftPane) {
|
||||
updateLeftPane();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue