From df2fa3c7b10199acf32c3f2915b532d64518d5a2 Mon Sep 17 00:00:00 2001 From: Josh Perez <60019601+josh-signal@users.noreply.github.com> Date: Tue, 20 Oct 2020 19:26:58 -0400 Subject: [PATCH] updateLastMessage: Use MessageController for latest data --- test/index.html | 1 + test/models/conversations_test.js | 70 +++++++++++++++++++++++++++++++ ts/models/conversations.ts | 19 ++++++++- 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 test/models/conversations_test.js diff --git a/test/index.html b/test/index.html index 5b3edb4716..fb41bf32ed 100644 --- a/test/index.html +++ b/test/index.html @@ -376,6 +376,7 @@ + diff --git a/test/models/conversations_test.js b/test/models/conversations_test.js new file mode 100644 index 0000000000..7889bd2810 --- /dev/null +++ b/test/models/conversations_test.js @@ -0,0 +1,70 @@ +describe('Conversations', () => { + it('updates lastMessage even in race conditions with db', async () => { + // Creating a fake conversation + const conversation = new window.Whisper.Conversation({ + id: '8c45efca-67a4-4026-b990-9537d5d1a08f', + e164: '+15551234567', + uuid: '2f2734aa-f69d-4c1c-98eb-50eb0fc512d7', + type: 'private', + }); + + const destinationE164 = '+15557654321'; + + // Creating a fake message + const now = Date.now(); + let message = new window.Whisper.Message({ + attachments: [], + body: 'bananas', + conversationId: conversation.id, + delivered: 1, + delivered_to: [destinationE164], + destination: destinationE164, + expirationStartTimestamp: now, + hasAttachments: 0, + hasFileAttachments: 0, + hasVisualMediaAttachments: 0, + id: 'd8f2b435-e2ef-46e0-8481-07e68af251c6', + received_at: now, + recipients: [destinationE164], + sent: true, + sent_at: now, + sent_to: [destinationE164], + timestamp: now, + type: 'outgoing', + }); + + // Saving to db and updating the convo's last message + await window.Signal.Data.saveMessage(message.attributes, { + forceSave: true, + Message: window.Whisper.Message, + }); + message = window.MessageController.register(message.id, message); + await window.Signal.Data.saveConversation(conversation.attributes, { + Conversation: window.Whisper.Conversation, + }); + await conversation.updateLastMessage(); + + // Should be set to bananas because that's the last message sent. + assert.strictEqual(conversation.get('lastMessage'), 'bananas'); + + // Erasing message contents (DOE) + message.set({ + isErased: true, + body: '', + bodyRanges: undefined, + attachments: [], + quote: null, + contact: [], + sticker: null, + preview: [], + }); + + // Not saving the message to db on purpose + // to simulate that a save hasn't taken place yet. + + // Updating convo's last message, should pick it up from memory + await conversation.updateLastMessage(); + + assert.strictEqual(conversation.get('lastMessage'), ''); + }); +}); diff --git a/ts/models/conversations.ts b/ts/models/conversations.ts index e4d8e4214b..f31298ecd7 100644 --- a/ts/models/conversations.ts +++ b/ts/models/conversations.ts @@ -2874,7 +2874,7 @@ export class ConversationModel extends window.Backbone.Model< return; } - const [previewMessage, activityMessage] = await Promise.all([ + let [previewMessage, activityMessage] = await Promise.all([ window.Signal.Data.getLastConversationPreview(this.id, { Message: window.Whisper.Message, }), @@ -2883,6 +2883,23 @@ export class ConversationModel extends window.Backbone.Model< }), ]); + // Register the message with MessageController so that if it already exists + // in memory we use that data instead of the data from the db which may + // be out of date. + if (previewMessage) { + previewMessage = window.MessageController.register( + previewMessage.id, + previewMessage + ); + } + + if (activityMessage) { + activityMessage = window.MessageController.register( + activityMessage.id, + activityMessage + ); + } + if ( this.hasDraft() && this.get('draftTimestamp') &&