From 91a8a82e39479fe4197a49d994ec35d25bf52bf2 Mon Sep 17 00:00:00 2001 From: Beaudan Date: Thu, 29 Nov 2018 17:05:58 +1100 Subject: [PATCH] More PR suggestions, now recover from early exit before friend request is sent --- js/conversation_controller.js | 2 ++ js/models/conversations.js | 37 ++++++++++++++++++++++++------- libtextsecure/outgoing_message.js | 9 +++----- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/js/conversation_controller.js b/js/conversation_controller.js index 54ca0f89c..816c3c4f4 100644 --- a/js/conversation_controller.js +++ b/js/conversation_controller.js @@ -257,6 +257,8 @@ conversation.updateLastMessage(), conversation.updateProfile(), conversation.updateProfileAvatar(), + conversation.resetPendingSend(), + conversation.updateProfile(), ]); }); await Promise.all(promises); diff --git a/js/models/conversations.js b/js/models/conversations.js index 66f773108..2de4beda0 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -43,12 +43,14 @@ const FriendRequestStatusEnum = Object.freeze({ // New conversation, no messages sent or received none: 0, + // This state is used to lock the input early while sending + pendingSend: 1, // Friend request sent, awaiting response - requestSent: 1, + requestSent: 2, // Friend request received, awaiting user input - requestReceived: 2, + requestReceived: 3, // We did it! - friends: 3, + friends: 4, }); const COLORS = [ @@ -435,10 +437,16 @@ isNone() { return this.get('friendRequestStatus') === FriendRequestStatusEnum.none; }, + hasInputBlocked() { + const status = this.get('friendRequestStatus'); + return status === FriendRequestStatusEnum.requestSent || + status === FriendRequestStatusEnum.requestReceived || + status === FriendRequestStatusEnum.pendingSend; + }, isPending() { const status = this.get('friendRequestStatus'); return status === FriendRequestStatusEnum.requestSent || - status === FriendRequestStatusEnum.requestSent; + status === FriendRequestStatusEnum.requestReceived; }, hasSentFriendRequest() { return this.get('friendRequestStatus') === FriendRequestStatusEnum.requestSent; @@ -455,6 +463,7 @@ this.trigger('disable:input', false); this.trigger('change:placeholder', 'friend-request'); return; + case FriendRequestStatusEnum.pendingSend: case FriendRequestStatusEnum.requestReceived: case FriendRequestStatusEnum.requestSent: this.trigger('disable:input', true); @@ -469,6 +478,9 @@ } }, async setFriendRequestStatus(newStatus) { + // Ensure that the new status is a valid FriendStatusEnum value + if (!Object.values(FriendRequestStatusEnum).some(v => v === newStatus)) + return; if (this.get('friendRequestStatus') !== newStatus) { this.set({ friendRequestStatus: newStatus }); await window.Signal.Data.updateConversation(this.id, this.attributes, { @@ -494,6 +506,11 @@ }) ); }, + async resetPendingSend() { + if (this.get('friendRequestStatus') === FriendRequestStatusEnum.pendingSend) { + await this.setFriendRequestStatus(FriendRequestStatusEnum.none); + } + }, // We have declined an incoming friend request async onDeclineFriendRequest() { this.setFriendRequestStatus(FriendRequestStatusEnum.none); @@ -949,7 +966,7 @@ async sendMessage(body, attachments, quote) { // Input should be blocked if there is a pending friend request - if (this.isPending()) + if (this.hasInputBlocked()) return; const destination = this.id; const expireTimer = this.get('expireTimer'); @@ -1007,6 +1024,7 @@ // because one of them was sent successfully if (friendRequestSent) return null; } + await this.setFriendRequestStatus(FriendRequestStatusEnum.pendingSend); // Send the friend request! messageWithSchema = await upgradeMessageSchema({ @@ -1089,7 +1107,8 @@ expireTimer, profileKey, options - ) + ), + message.isFriendRequest() ) ) ); @@ -1097,11 +1116,13 @@ return true; }); }, - wrapSend(promise) { + wrapSend(promise, isFriendRequest = false) { return promise.then( async result => { // success if (result) { + if (isFriendRequest) + this.onFriendRequestSent(); await this.handleMessageSendResult( result.failoverNumbers, result.unidentifiedDeliveries @@ -1903,12 +1924,12 @@ }, notify(message) { - if (message.isOutgoing()) return Promise.resolve(); if (message.isFriendRequest()) { if (this.hasSentFriendRequest()) return this.notifyFriendRequest(message.get('source'), 'accepted') return this.notifyFriendRequest(message.get('source'), 'requested'); } + if (!message.isIncoming()) return Promise.resolve(); const conversationId = this.id; return ConversationController.getOrCreateAndWait( diff --git a/libtextsecure/outgoing_message.js b/libtextsecure/outgoing_message.js index 75bc086f4..86131eceb 100644 --- a/libtextsecure/outgoing_message.js +++ b/libtextsecure/outgoing_message.js @@ -280,7 +280,7 @@ OutgoingMessage.prototype = { const address = new libsignal.SignalProtocolAddress(number, deviceId); const ourKey = textsecure.storage.user.getNumber(); const options = {}; - const fallBackEncryption = new libloki.FallBackSessionCipher(address); + const fallBackCipher = new libloki.FallBackSessionCipher(address); // Check if we need to attach the preKeys let sessionCipher; @@ -288,7 +288,7 @@ OutgoingMessage.prototype = { // Encrypt them with the fallback this.message.preKeyBundleMessage = await libloki.getPreKeyBundleForNumber(number); window.log.info('attaching prekeys to outgoing message'); - sessionCipher = fallBackEncryption; + sessionCipher = fallBackCipher; } else { sessionCipher = new libsignal.SessionCipher( textsecure.storage.protocol, @@ -453,13 +453,10 @@ OutgoingMessage.prototype = { log.info('Fallback encryption enabled'); this.fallBackEncryption = true; } - - if (this.fallBackEncryption && conversation) { - await conversation.onFriendRequestSent(); - } }) .then(this.reloadDevicesAndSend(number, true)) .catch(error => { + conversation.resetPendingSend(); if (error.message === 'Identity key changed') { // eslint-disable-next-line no-param-reassign error = new textsecure.OutgoingIdentityKeyError(