diff --git a/js/background.js b/js/background.js index d342e6f2a3bd..cfc50976b5dd 100644 --- a/js/background.js +++ b/js/background.js @@ -1109,9 +1109,10 @@ conversationId: data.destination, type: 'outgoing', sent: true, - expirationStartTimestamp: data.expirationStartTimestamp - ? Math.min(data.expirationStartTimestamp, Date.now()) - : null, + expirationStartTimestamp: Math.min( + data.expirationStartTimestamp || data.timestamp || Date.now(), + Date.now() + ), }); } diff --git a/js/models/messages.js b/js/models/messages.js index f2ac0e4d6238..70698ef69664 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -879,17 +879,33 @@ promises.push(c.getProfiles()); } } else { - this.saveErrors(result.errors); if (result.successfulNumbers.length > 0) { const sentTo = this.get('sent_to') || []; - // Note: In a partially-successful group send, we do not start - // the expiration timer. + // In groups, we don't treat unregistered users as a user-visible + // error. The message will look successful, but the details + // screen will show that we didn't send to these unregistered users. + const filteredErrors = _.reject( + result.errors, + error => error.name === 'UnregisteredUserError' + ); + + // We don't start the expiration timer if there are real errors + // left after filtering out all of the unregistered user errors. + const expirationStartTimestamp = filteredErrors.length + ? null + : Date.now(); + + this.saveErrors(filteredErrors); + this.set({ sent_to: _.union(sentTo, result.successfulNumbers), sent: true, + expirationStartTimestamp, }); promises.push(this.sendSyncMessage()); + } else { + this.saveErrors(result.errors); } promises = promises.concat( _.map(result.errors, error => {