From 0adc398a6f245636678105bdf9a435ca2017fe71 Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Fri, 21 Jul 2017 10:59:41 -0700 Subject: [PATCH] Fetch conversation before saving in all sync handlers FREEBIE --- js/background.js | 123 +++++++++++++++++++--------------- js/conversation_controller.js | 32 ++++++--- js/models/conversations.js | 10 +-- 3 files changed, 98 insertions(+), 67 deletions(-) diff --git a/js/background.js b/js/background.js index 8bf752ee74..5f7cef83d1 100644 --- a/js/background.js +++ b/js/background.js @@ -146,42 +146,50 @@ } function onContactReceived(ev) { - var contactDetails = ev.contactDetails; + var details = ev.contactDetails; + var id = details.number; var c = new Whisper.Conversation({ - name: contactDetails.name, - id: contactDetails.number, - avatar: contactDetails.avatar, - color: contactDetails.color, - type: 'private', - active_at: Date.now() + id: id }); - var error; - if ((error = c.validateNumber())) { - console.log(error.stack); - return; + var error = c.validateNumber(); + if (error) { + console.log('Invalid contact received', error && error.stack ? error.stack : error); + return; } - ConversationController.create(c).save().then(ev.confirm); + ConversationController.findOrCreatePrivateById(id).then(function(conversation) { + return new Promise(function(resolve, reject) { + conversation.save({ + name: details.name, + avatar: details.avatar, + color: details.color, + active_at: conversation.get('active_at') || Date.now(), + }).then(resolve, reject); + }); + }).then(ev.confirm); } function onGroupReceived(ev) { - var groupDetails = ev.groupDetails; - var attributes = { - id: groupDetails.id, - name: groupDetails.name, - members: groupDetails.members, - avatar: groupDetails.avatar, - type: 'group', - }; - if (groupDetails.active) { - attributes.active_at = Date.now(); - } else { - attributes.left = true; - } + var details = ev.groupDetails; + var id = details.id; - var conversation = ConversationController.create(attributes); - conversation.save().then(ev.confirm); + return ConversationController.findOrCreateById(id).then(function(conversation) { + var updates = { + name: details.name, + members: details.members, + avatar: details.avatar, + type: 'group', + }; + if (details.active) { + updates.active_at = Date.now(); + } else { + updates.left = true; + } + return new Promise(function(resolve, reject) { + conversation.save(updates).then(resolve, reject); + }).then(ev.confirm); + }); } function onMessageReceived(ev) { @@ -344,39 +352,48 @@ var key = ev.verified.identityKey; var state; + var c = new Whisper.Conversation({ + id: number + }); + var error = c.validateNumber(); + if (error) { + console.log( + 'Invalid verified sync received', + error && error.stack ? error.stack : error + ); + return; + } + switch(ev.verified.state) { - case textsecure.protobuf.Verified.State.DEFAULT: - state = 'DEFAULT'; - break; - case textsecure.protobuf.Verified.State.VERIFIED: - state = 'VERIFIED'; - break; - case textsecure.protobuf.Verified.State.UNVERIFIED: - state = 'UNVERIFIED'; - break; + case textsecure.protobuf.Verified.State.DEFAULT: + state = 'DEFAULT'; + break; + case textsecure.protobuf.Verified.State.VERIFIED: + state = 'VERIFIED'; + break; + case textsecure.protobuf.Verified.State.UNVERIFIED: + state = 'UNVERIFIED'; + break; } console.log('got verified sync for', number, state, ev.viaContactSync ? 'via contact sync' : ''); - var contact = ConversationController.get(number); - if (!contact) { - return; - } + return ConversationController.findOrCreatePrivateById(number).then(function(contact) { + var options = { + viaSyncMessage: true, + viaContactSync: ev.viaContactSync, + key: key + }; - var options = { - viaSyncMessage: true, - viaContactSync: ev.viaContactSync, - key: key - }; - - if (state === 'VERIFIED') { - contact.setVerified(options).then(ev.confirm); - } else if (state === 'DEFAULT') { - contact.setVerifiedDefault(options).then(ev.confirm); - } else { - contact.setUnverified(options).then(ev.confirm); - } + if (state === 'VERIFIED') { + return contact.setVerified(options).then(ev.confirm); + } else if (state === 'DEFAULT') { + return contact.setVerifiedDefault(options).then(ev.confirm); + } else { + return contact.setUnverified(options).then(ev.confirm); + } + }); } function onDeliveryReceipt(ev) { diff --git a/js/conversation_controller.js b/js/conversation_controller.js index f217281310..edb6b69a40 100644 --- a/js/conversation_controller.js +++ b/js/conversation_controller.js @@ -87,19 +87,31 @@ return conversation; }, findOrCreatePrivateById: function(id) { - var conversation = conversations.add({ id: id, type: 'private' }); + var conversation = conversations.add({ + id: id, + type: 'private' + }); return new Promise(function(resolve, reject) { conversation.fetch().then(function() { resolve(conversation); - }).fail(function() { - var saved = conversation.save(); // false or indexedDBRequest - if (saved) { - saved.then(function() { - resolve(conversation); - }).fail(reject); - } else { - reject(); - } + }, function() { + conversation.save().then(function() { + resolve(conversation); + }, reject); + }); + }); + }, + findOrCreateById: function(id) { + var conversation = conversations.add({ + id: id + }); + return new Promise(function(resolve, reject) { + conversation.fetch().then(function() { + resolve(conversation); + }, function() { + conversation.save().then(function() { + resolve(conversation); + }, reject); }); }); }, diff --git a/js/models/conversations.js b/js/models/conversations.js index 8864087d21..ef148fe013 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -84,24 +84,26 @@ }, safeFetch: function() { // new Promise necessary because a fetch will fail if convo not in db yet - return new Promise(function(resolve) { this.fetch().always(resolve); }.bind(this)); + return new Promise(function(resolve) { + this.fetch().always(resolve); + }.bind(this)); }, setVerifiedDefault: function(options) { var DEFAULT = this.verifiedEnum.DEFAULT; return this.queueJob(function() { - return this.safeFetch().then(this._setVerified.bind(this, DEFAULT, options)); + return this._setVerified(DEFAULT, options); }.bind(this)); }, setVerified: function(options) { var VERIFIED = this.verifiedEnum.VERIFIED; return this.queueJob(function() { - return this.safeFetch().then(this._setVerified.bind(this, VERIFIED, options)); + return this._setVerified(VERIFIED, options); }.bind(this)); }, setUnverified: function(options) { var UNVERIFIED = this.verifiedEnum.UNVERIFIED; return this.queueJob(function() { - return this.safeFetch().then(this._setVerified.bind(this, UNVERIFIED, options)); + return this._setVerified(UNVERIFIED, options); }.bind(this)); }, _setVerified: function(verified, options) {