From 5b46ef35625d217c1327342f11f5a2b764e96597 Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Wed, 5 Jul 2017 12:17:55 -0700 Subject: [PATCH] Show last seen indicator for keychange/verification notifications FREEBIE --- js/models/conversations.js | 14 ++++++++++++-- js/views/conversation_view.js | 35 ++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/js/models/conversations.js b/js/models/conversations.js index b5f9fb01d..f7b3ba6f3 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -247,7 +247,8 @@ type : 'keychange', sent_at : this.get('timestamp'), received_at : timestamp, - key_changed : id + key_changed : id, + unread : 1 }); message.save().then(this.trigger.bind(this,'newmessage', message)); }, @@ -265,7 +266,8 @@ received_at : timestamp, verifiedChanged : id, verified : verified, - local : options.local + local : options.local, + unread : 1 }); message.save().then(this.trigger.bind(this,'newmessage', message)); @@ -548,6 +550,14 @@ }; }.bind(this)); + // Some messages we're marking read are local notifications with no sender + read = _.filter(read, function(m) { + return Boolean(m.sender); + }); + unreadMessages = unreadMessages.filter(function(m) { + return Boolean(m.get('sender')); + }); + var unreadCount = unreadMessages.length - read.length; this.save({ unreadCount: unreadCount }); diff --git a/js/views/conversation_view.js b/js/views/conversation_view.js index f76123254..daad70db7 100644 --- a/js/views/conversation_view.js +++ b/js/views/conversation_view.js @@ -388,14 +388,25 @@ options = options || {}; _.defaults(options, {scroll: true}); - var oldestUnread = this.model.messageCollection.find(function(model) { - return model.get('unread'); + var unreadCount = 0; + var oldestUnread = null; + + // We need to iterate here because unseen non-messages do not contribute to + // the badge number, but should be reflected in the indicator's count. + this.model.messageCollection.forEach(function(model) { + if (!model.get('unread')) { + return; + } + + unreadCount += 1; + if (!oldestUnread) { + oldestUnread = model; + } }); - var unreadCount = this.model.get('unreadCount'); this.removeLastSeenIndicator(); - if (oldestUnread && unreadCount > 0) { + if (oldestUnread) { this.lastSeenIndicator = new Whisper.LastSeenIndicatorView({count: unreadCount}); var lastSeenEl = this.lastSeenIndicator.render().$el; @@ -406,7 +417,7 @@ } // scrollIntoView is an async operation, but we have no way to listen for - // completion of the resultant scroll. + // completion of the resultant scroll. setTimeout(function() { if (!this.view.atBottom()) { this.addScrollDownButtonWithCount(unreadCount); @@ -523,18 +534,16 @@ var collection = this.model.messageCollection; var length = collection.length; var viewportBottom = this.view.outerHeight; - var unreadCount = this.model.get('unreadCount'); - - if (!unreadCount || unreadCount < 1) { - return; - } + var unreadCount = this.model.get('unreadCount') || 0; // Start with the most recent message, search backwards in time var foundUnread = 0; for (var i = length - 1; i >= 0; i -= 1) { - // We don't want to search through all messages, so we stop after we've - // hit all unread messages. The unread should be relatively recent. - if (foundUnread >= unreadCount) { + // Search the latest 30, then stop if we believe we've covered all known + // unread messages. The unread should be relatively recent. + // Why? local notifications can be unread but won't be reflected the + // conversation's unread count. + if (i > 30 && foundUnread >= unreadCount) { return; }