From ef1d568a80e41e643202d9dda0574b6720357202 Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Mon, 23 Apr 2018 19:16:00 -0700 Subject: [PATCH] Restore rendering of group update and end session messages The previous work to refactor bubbles broke rendering for these message types. :0/ --- Gruntfile.js | 3 + _locales/en/messages.json | 4 ++ js/views/message_view.js | 32 +++++++++-- ts/components/conversation/Message.md | 83 +++++++++++++++++++++++++++ ts/components/conversation/Quote.md | 32 +++++++++++ 5 files changed, 149 insertions(+), 5 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 94ffff3406..cb875befdb 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -167,7 +167,10 @@ module.exports = function(grunt) { '!js/modules/**/*.js', '!js/models/conversations.js', '!js/models/messages.js', + '!js/views/conversation_search_view.js', '!js/views/conversation_view.js', + '!js/views/debug_log_view.js', + '!js/views/message_view.js', '!js/Mp3LameEncoder.min.js', '!js/WebAudioRecorderMp3.js', 'test/**/*.js', diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 1353ea19ea..85251a2b68 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -546,6 +546,10 @@ "message": "Secure session reset", "description": "This is a past tense, informational message. In other words, your secure session has been reset." }, + "noContents": { + "message": "No message contents", + "description": "Shown in a message bubble if we have nothing in the message to display, or a quote and nothing else" + }, "installWelcome": { "message": "Welcome to Signal Desktop", "description": "Welcome title on the install page" diff --git a/js/views/message_view.js b/js/views/message_view.js index 38bbcf3537..3c9a122b21 100644 --- a/js/views/message_view.js +++ b/js/views/message_view.js @@ -349,6 +349,12 @@ } this.errorIconView = new ErrorIconView({ model: errors[0] }); this.errorIconView.render().$el.appendTo(this.$('.bubble')); + } else if (!this.hasContents()) { + const el = this.$('.content'); + if (!el || el.length === 0) { + this.$('.inner-bubble').append("
"); + } + this.$('.content').text(i18n('noContents')).addClass('error-message'); } this.$('.meta .hasRetry').remove(); @@ -429,18 +435,34 @@ return false; }, + hasContents() { + const attachments = this.model.get('attachments'); + const hasAttachments = attachments && attachments.length > 0; + + return this.hasTextContents() || hasAttachments; + }, + hasTextContents() { + const body = this.model.get('body'); + const isGroupUpdate = this.model.isGroupUpdate(); + const isEndSession = this.model.isEndSession(); + + const errors = this.model.get('errors'); + const hasErrors = errors && errors.length > 0; + const errorsCanBeContents = this.model.isIncoming() && hasErrors; + + return body || isGroupUpdate || isEndSession || errorsCanBeContents; + }, render() { const contact = this.model.isIncoming() ? this.model.getContact() : null; - const errors = this.model.get('errors'); const attachments = this.model.get('attachments'); - const hasErrors = errors && errors.length > 0; + // TODO: used for the feature flag below + // const hasErrors = errors && errors.length > 0; const hasAttachments = attachments && attachments.length > 0; - const message = this.model.get('body'); - const hasBody = message || (this.model.isIncoming() && hasErrors); + const hasBody = this.hasTextContents(); this.$el.html(Mustache.render(_.result(this, 'template', ''), { - message, + message: this.model.get('body'), hasBody, timestamp: this.model.get('sent_at'), sender: (contact && contact.getTitle()) || '', diff --git a/ts/components/conversation/Message.md b/ts/components/conversation/Message.md index bf294bfb26..116d365b94 100644 --- a/ts/components/conversation/Message.md +++ b/ts/components/conversation/Message.md @@ -133,6 +133,31 @@ const View = Whisper.MessageView; ``` +#### No message contents + +```jsx +const outgoing = new Whisper.Message({ + type: 'outgoing', + sent_at: Date.now() - 200000, +}); +const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { + source: '+12025550003', + type: 'incoming', +})); + +const View = Whisper.MessageView; + + + + +``` + ### Disappearing ```jsx @@ -292,6 +317,64 @@ const View = Whisper.VerifiedChangeView; ``` +#### Group update + +```js +const outgoing = new Whisper.Message({ + type: 'outgoing', + sent_at: Date.now() - 200000, + group_update: { + joined: [ + '+12025550007', + '+12025550008', + '+12025550009', + ], + }, +}); +const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { + source: '+12025550003', + type: 'incoming', +})); + +const View = Whisper.MessageView; + + + + +``` + +#### End session + +```js +const outgoing = new Whisper.Message({ + type: 'outgoing', + sent_at: Date.now() - 200000, + flags: textsecure.protobuf.DataMessage.Flags.END_SESSION, +}); +const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { + source: '+12025550003', + type: 'incoming', +})); + +const View = Whisper.MessageView; + + + + +``` + ### With an attachment #### Image with caption diff --git a/ts/components/conversation/Quote.md b/ts/components/conversation/Quote.md index dce198604d..64678f9d18 100644 --- a/ts/components/conversation/Quote.md +++ b/ts/components/conversation/Quote.md @@ -964,6 +964,38 @@ const View = Whisper.MessageView; ``` +#### Quote, but no message + +```jsx +const outgoing = new Whisper.Message({ + type: 'outgoing', + sent_at: Date.now() - 18000000, + quote: { + text: 'How many ferrets do you have?', + author: '+12025550011', + id: Date.now() - 1000, + }, +}); +const incoming = new Whisper.Message(Object.assign({}, outgoing.attributes, { + source: '+12025550011', + type: 'incoming', + quote: Object.assign({}, outgoing.attributes.quote, { + author: '+12025550005', + }), +})); +const View = Whisper.MessageView; + + + + +``` + ### In bottom bar #### Plain text