diff options
author | Ben Langfeld <ben@langfeld.me> | 2015-05-01 01:16:04 +0300 |
---|---|---|
committer | Ben Klang <bklang@mojolingo.com> | 2015-07-22 04:31:14 +0300 |
commit | 6a096d0913567fb82c06761e2eb919828dd43cb8 (patch) | |
tree | e0ac4aae3b00855dbf1fc5a7662d03a3b5f0289b | |
parent | 7e439479ccce1495ab51ed9c87d191ede195e725 (diff) |
Avoid rendering messages with duplicate IDsfeature/avoid-duplicate-message-ids
This is motivated by a race condition when loading archived messages (calling Candy.View.Pane.Message.show) at the same time as rendering an incoming message, such as when a 1-on-1 message arrives and auto-opens a new pane for the chat partner.
-rw-r--r-- | src/view/pane/message.js | 19 | ||||
-rw-r--r-- | src/view/template.js | 2 |
2 files changed, 18 insertions, 3 deletions
diff --git a/src/view/pane/message.js b/src/view/pane/message.js index b4bcbb6..27a2ffa 100644 --- a/src/view/pane/message.js +++ b/src/view/pane/message.js @@ -110,8 +110,20 @@ Candy.View.Pane = (function(self, $) { timestamp = Candy.Util.iso8601toDate(timestamp); } + var messagePane = self.Room.getPane(roomJid, ".message-pane"); + var messageId; + if (stanza) { + messageId = $(stanza).attr('id'); + if (messageId) { + var existingMessage = messagePane.find('[data-message-id="' + messageId + '"]'); + if (messageId && existingMessage.length > 0) { + // This message ID has already been rendered + return false; + } + } + } + // Before we add the new message, check to see if we should be automatically scrolling or not. - var messagePane = self.Room.getPane(roomJid, '.message-pane'); var enableScroll = ((messagePane.scrollTop() + messagePane.outerHeight()) === messagePane.prop('scrollHeight')) || !$(messagePane).is(':visible'); Candy.View.Pane.Chat.rooms[roomJid].enableScroll = enableScroll; @@ -158,7 +170,8 @@ Candy.View.Pane = (function(self, $) { time: Candy.Util.localizedTime(timestamp), timestamp: timestamp.toISOString(), roomjid: roomJid, - from: from + from: from, + id: messageId }, stanza: stanza }; @@ -246,6 +259,8 @@ Candy.View.Pane = (function(self, $) { * (String) message - Message text */ $(Candy).triggerHandler('candy:view.message.after-show', evtData); + + return true; } }; diff --git a/src/view/template.js b/src/view/template.js index d116709..95eb8d0 100644 --- a/src/view/template.js +++ b/src/view/template.js @@ -89,7 +89,7 @@ Candy.View.Template = (function(self){ self.Message = { pane: '<div class="message-pane-wrapper"><ul class="message-pane"></ul></div>', - item: '<li><small data-timestamp="{{timestamp}}">{{time}}</small><div>' + + item: '<li data-message-id="{{id}}"><small data-timestamp="{{timestamp}}">{{time}}</small><div>' + '<a class="label" href="#" class="name">{{displayName}}</a>' + '<span class="spacer">▸</span>{{{message}}}</div></li>' }; |