From 1f897f32b722ab43365ef5777e9e3ca526121803 Mon Sep 17 00:00:00 2001 From: lilia Date: Sun, 21 Feb 2016 21:37:47 -0800 Subject: [PATCH] Track and sync unread messages // FREEBIE --- js/background.js | 25 ++++++++++++++++++++- js/database.js | 10 +++++++++ js/models/conversations.js | 46 +++++++++++++++++++++++++++++++++----- js/models/messages.js | 4 ++++ 4 files changed, 78 insertions(+), 7 deletions(-) diff --git a/js/background.js b/js/background.js index b0e8dffb..f619271e 100644 --- a/js/background.js +++ b/js/background.js @@ -175,7 +175,8 @@ sent_at : timestamp, received_at : now, conversationId : source, - type : 'incoming' + type : 'incoming', + unread : true }); return message; @@ -232,7 +233,29 @@ function onReadReceipt(ev) { var timestamp = ev.timestamp.toNumber(); var sender = ev.sender; + var messages = new Whisper.MessageCollection(); + var groups = new Whisper.ConversationCollection(); console.log('read receipt ', sender, timestamp); + groups.fetchGroups(sender).then(function() { + messages.fetchSentAt(timestamp).then(function() { + var ids = groups.pluck('id'); + ids.push(sender); + var message = messages.find(function(message) { + return (message.get('type') === 'incoming' && + _.contains(ids, message.get('conversationId'))); + }); + if (message) { + message.markRead().then(function() { + var conversation = ConversationController.get({ + id: message.get('conversationId') + }); + + // notify frontend listeners + conversation.trigger('read', message); + }); + } + }); + }); } // lazy hack diff --git a/js/database.js b/js/database.js index eb720b89..5833b608 100644 --- a/js/database.js +++ b/js/database.js @@ -134,6 +134,16 @@ transaction.db.createObjectStore("debug"); next(); } + }, + { + version: "8.0", + migrate: function(transaction, next) { + console.log('migration 8.0'); + console.log('creating unread message index'); + var conversations = transaction.objectStore('messages'); + conversations.createIndex('unread', ['conversationId', 'unread'], { unique: false }); + next(); + } } ]; }()); diff --git a/js/models/conversations.js b/js/models/conversations.js index 9d17d7f6..6ee6d668 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -44,6 +44,31 @@ this.on('change:avatar', this.updateAvatarUrl); this.on('destroy', this.revokeAvatarUrl); + this.on('read', this.countUnread); + }, + + countUnread: function() { + return this.getUnread().then(function(unreadMessages) { + this.save({unreadCount: unreadMessages.length}); + }.bind(this)); + }, + + getUnread: function() { + var conversationId = this.id; + var unreadMessages = new Whisper.MessageCollection(); + return new Promise(function(resolve) { + return unreadMessages.fetch({ + index: { + // 'unread' index + name: 'unread', + lower: [conversationId, true], + upper: [conversationId, true] + } + }).always(function() { + resolve(unreadMessages); + }); + }); + }, validate: function(attributes, options) { @@ -182,13 +207,22 @@ markRead: function() { if (this.get('unreadCount') > 0) { - this.save({unreadCount: 0}); + this.save({ unreadCount: 0 }); var conversationId = this.id; - Whisper.Notifications.remove( - Whisper.Notifications.models.filter( - function(model) { - return model.attributes.conversationId===conversationId; - })); + Whisper.Notifications.remove(Whisper.Notifications.where({ + conversationId: conversationId + })); + + var readReceipts = this.messageCollection.where({ + type: 'incoming', unread: true + }).map(function(m) { + m.markRead(); + return { + sender: m.get('source'), + timestamp: m.get('sent_at') + }; + }.bind(this)); + textsecure.messaging.sendReadReceipts(readReceipts); } }, diff --git a/js/models/messages.js b/js/models/messages.js index 1ad9e768..11191e8a 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -363,6 +363,10 @@ }); }); }); + }, + markRead: function(sync) { + this.unset('unread'); + return this.save(); } });