Placeholder component: ```jsx ``` ## MessageView (Backbone) ### Plain messages ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', body: 'How are you doing this fine day?', sent_at: Date.now() - 18000, }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` ### In a group conversation ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', body: 'How are you doing this fine day?', sent_at: Date.now() - 200000, }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` ### With an error #### General error ```jsx const error = new Error('Something went wrong!'); const outgoing = new Whisper.Message({ type: 'outgoing', body: "This message won't get through...", sent_at: Date.now() - 200000, errors: [error], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', body: null, }) ); const View = Whisper.MessageView; ; ``` #### Network error (outgoing only) ```jsx const error = new Error('Something went wrong!'); error.name = 'MessageError'; const outgoing = new Whisper.Message({ type: 'outgoing', sent_at: Date.now() - 200000, errors: [error], body: "This message won't get through...", }); const View = Whisper.MessageView; ; ``` #### Network error, partial send in group (outgoing only) ```jsx const error = new Error('Something went wrong!'); error.name = 'MessageError'; const outgoing = new Whisper.Message({ type: 'outgoing', sent_at: Date.now() - 200000, errors: [error], conversationId: util.groupNumber, body: "This message won't get through...", }); 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 const outgoing = new Whisper.Message({ type: 'outgoing', sent_at: Date.now() - 200000, expireTimer: 120, expirationStartTimestamp: Date.now() - 1000, body: 'This message will self-destruct in two minutes', }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` ### Notfications #### Timer change ```jsx const fromOther = new Whisper.Message({ type: 'incoming', flags: textsecure.protobuf.DataMessage.Flags.EXPIRATION_TIMER_UPDATE, source: '+12025550003', sent_at: Date.now() - 200000, expireTimer: 120, expirationStartTimestamp: Date.now() - 1000, expirationTimerUpdate: { source: '+12025550003', }, }); const fromUpdate = new Whisper.Message({ type: 'incoming', flags: textsecure.protobuf.DataMessage.Flags.EXPIRATION_TIMER_UPDATE, source: util.ourNumber, sent_at: Date.now() - 200000, expireTimer: 120, expirationStartTimestamp: Date.now() - 1000, expirationTimerUpdate: { fromSync: true, source: util.ourNumber, }, }); const fromMe = new Whisper.Message({ type: 'incoming', flags: textsecure.protobuf.DataMessage.Flags.EXPIRATION_TIMER_UPDATE, source: util.ourNumber, sent_at: Date.now() - 200000, expireTimer: 120, expirationStartTimestamp: Date.now() - 1000, expirationTimerUpdate: { source: util.ourNumber, }, }); const View = Whisper.ExpirationTimerUpdateView; ; ``` #### Safety number change ```js const incoming = new Whisper.Message({ type: 'keychange', sent_at: Date.now() - 200000, key_changed: '+12025550003', }); const View = Whisper.KeyChangeView; ; ``` #### Marking as verified ```js const fromPrimary = new Whisper.Message({ type: 'verified-change', sent_at: Date.now() - 200000, verifiedChanged: '+12025550003', verified: true, }); const local = new Whisper.Message({ type: 'verified-change', sent_at: Date.now() - 200000, verifiedChanged: '+12025550003', local: true, verified: true, }); const View = Whisper.VerifiedChangeView; ; ``` #### Marking as not verified ```js const fromPrimary = new Whisper.Message({ type: 'verified-change', sent_at: Date.now() - 200000, verifiedChanged: '+12025550003', }); const local = new Whisper.Message({ type: 'verified-change', sent_at: Date.now() - 200000, verifiedChanged: '+12025550003', local: true, }); 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 ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', body: 'I am pretty confused about Pi.', sent_at: Date.now() - 18000000, attachments: [ { data: util.gif, fileName: 'pi.gif', contentType: 'image/gif', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Image ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', sent_at: Date.now() - 18000000, attachments: [ { data: util.gif, fileName: 'pi.gif', contentType: 'image/gif', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Image with portrait aspect ratio ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', sent_at: Date.now() - 18000000, attachments: [ { data: util.portraitYellow, fileName: 'portraitYellow.png', contentType: 'image/png', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Image with portrait aspect ratio and caption ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', body: 'This is an odd yellow bar. Cool, huh?', sent_at: Date.now() - 18000000, attachments: [ { data: util.portraitYellow, fileName: 'portraitYellow.png', contentType: 'image/png', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Image with landscape aspect ratio ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', sent_at: Date.now() - 18000000, attachments: [ { data: util.landscapePurple, fileName: 'landscapePurple.jpg', contentType: 'image/jpeg', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Image with landscape aspect ratio and caption ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', body: "An interesting horizontal bar. It's art.", sent_at: Date.now() - 18000000, attachments: [ { data: util.landscapePurple, fileName: 'landscapePurple.jpg', contentType: 'image/jpeg', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Video with caption ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', body: "Beautiful, isn't it?", sent_at: Date.now() - 10000, attachments: [ { data: util.mp4, fileName: 'freezing_bubble.mp4', contentType: 'video/mp4', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Video ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', sent_at: Date.now() - 10000, attachments: [ { data: util.mp4, fileName: 'freezing_bubble.mp4', contentType: 'video/mp4', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Audio with caption ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', body: 'This is a nice song', sent_at: Date.now() - 15000, attachments: [ { data: util.mp3, fileName: 'agnus_dei.mp3', contentType: 'audio/mp3', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Audio ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', sent_at: Date.now() - 15000, attachments: [ { data: util.mp3, fileName: 'agnus_dei.mp3', contentType: 'audio/mp3', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Voice message ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', sent_at: Date.now() - 15000, attachments: [ { flags: SignalService.AttachmentPointer.Flags.VOICE_MESSAGE, data: util.mp3, fileName: 'agnus_dei.mp3', contentType: 'audio/mp3', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Other file type with caption ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', body: 'My manifesto is now complete!', sent_at: Date.now() - 15000, attachments: [ { data: util.txt, fileName: 'lorum_ipsum.txt', contentType: 'text/plain', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ``` #### Other file type ```jsx const outgoing = new Whisper.Message({ type: 'outgoing', sent_at: Date.now() - 15000, attachments: [ { data: util.txt, fileName: 'lorum_ipsum.txt', contentType: 'text/plain', }, ], }); const incoming = new Whisper.Message( Object.assign({}, outgoing.attributes, { source: '+12025550003', type: 'incoming', }) ); const View = Whisper.MessageView; ; ```