Skip to content

Commit

Permalink
Move to react for newlines, emoji, and links in message body
Browse files Browse the repository at this point in the history
  • Loading branch information
scottnonnenberg-signal committed May 14, 2018
1 parent 721935b commit 4e5c896
Show file tree
Hide file tree
Showing 15 changed files with 399 additions and 28 deletions.
13 changes: 7 additions & 6 deletions background.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Security-Policy"
content="default-src 'none';
child-src 'self';
connect-src 'self' https: wss:;
script-src 'self';
style-src 'self' 'unsafe-inline';
img-src 'self' blob: data:;
font-src 'self';
frame-src 'none';
img-src 'self' blob: data:;
media-src 'self' blob:;
child-src 'self';
object-src 'none'"
script-src 'self';
style-src 'self' 'unsafe-inline';
>
<title>Signal</title>
<link href='images/icon_128.png' rel='shortcut icon'>
Expand Down Expand Up @@ -283,7 +284,7 @@ <h3>{{ welcomeToSignal }}</h3>
{{ #hasBody }}
<div class='content' dir='auto'>
{{ #message }}
<div class='body'>{{ message }}</div>
<div class='body'></div>
{{ /message }}
</div>
{{ /hasBody }}
Expand Down Expand Up @@ -375,7 +376,7 @@ <h3 class='name' dir='auto'>
<span class='unread-count'>{{ unreadCount }}</span>
{{ /unreadCount }}
{{ #last_message }}
<p class='last-message' dir='auto'> {{ last_message }} </p>
<p class='last-message' dir='auto'></p>
{{ /last_message }}
</div>
</script>
Expand Down
2 changes: 2 additions & 0 deletions js/signal.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const { LightboxGallery } = require('../ts/components/LightboxGallery');
const {
MediaGallery,
} = require('../ts/components/conversation/media-gallery/MediaGallery');
const { MessageBody } = require('../ts/components/conversation/MessageBody');
const { Quote } = require('../ts/components/conversation/Quote');

// Migrations
Expand Down Expand Up @@ -58,6 +59,7 @@ exports.setup = (options = {}) => {
Lightbox,
LightboxGallery,
MediaGallery,
MessageBody,
Types: {
Message: MediaGalleryMessage,
},
Expand Down
22 changes: 20 additions & 2 deletions js/views/conversation_list_item_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,14 @@
},

render: function() {
const lastMessage = this.model.get('lastMessage');

this.$el.html(
Mustache.render(
_.result(this, 'template', ''),
{
title: this.model.getTitle(),
last_message: this.model.get('lastMessage'),
last_message: Boolean(lastMessage),
last_message_timestamp: this.model.get('timestamp'),
number: this.model.getNumber(),
avatar: this.model.getAvatar(),
Expand All @@ -74,7 +76,23 @@
this.timeStampView.update();

emoji_util.parse(this.$('.name'));
emoji_util.parse(this.$('.last-message'));

if (lastMessage) {
if (this.bodyView) {
this.bodyView.remove();
this.bodyView = null;
}
this.bodyView = new Whisper.ReactWrapperView({
className: 'body-wrapper',
Component: window.Signal.Components.MessageBody,
props: {
text: lastMessage,
disableJumbomoji: true,
disableLinks: true,
},
});
this.$('.last-message').append(this.bodyView.el);
}

var unread = this.model.get('unreadCount');
if (unread > 0) {
Expand Down
2 changes: 1 addition & 1 deletion js/views/conversation_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -1293,7 +1293,7 @@
className: 'quote-wrapper',
Component: window.Signal.Components.Quote,
props: Object.assign({}, props, {
text: props.text ? window.emoji.signalReplace(props.text) : null,
text: props.text,
onClose: () => {
this.setQuoteMessage(null);
},
Expand Down
32 changes: 17 additions & 15 deletions js/views/message_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@

window.Whisper = window.Whisper || {};

const URL_REGEX = /(^|[\s\n]|<br\/?>)((?:https?|ftp):\/\/[-A-Z0-9\u00A0-\uD7FF\uE000-\uFDCF\uFDF0-\uFFFD+\u0026\u2019@#/%?=()~_|!:,.;]*[-A-Z0-9+\u0026@#/%=~()_|])/gi;

const ErrorIconView = Whisper.View.extend({
templateName: 'error-icon',
className: 'error-icon-container',
Expand Down Expand Up @@ -440,7 +438,7 @@
className: 'quote-wrapper',
Component: window.Signal.Components.Quote,
props: Object.assign({}, props, {
text: props.text ? window.emoji.signalReplace(props.text) : null,
text: props.text,
}),
});
this.$('.inner-bubble').prepend(this.quoteView.el);
Expand Down Expand Up @@ -566,11 +564,13 @@
const hasAttachments = attachments && attachments.length > 0;
const hasBody = this.hasTextContents();

const messageBody = this.model.get('body');

this.$el.html(
Mustache.render(
_.result(this, 'template', ''),
{
message: this.model.get('body'),
message: Boolean(messageBody),
hasBody,
timestamp: this.model.get('sent_at'),
sender: (contact && contact.getTitle()) || '',
Expand All @@ -589,17 +589,19 @@

this.renderControl();

const body = this.$('.body');

emoji_util.parse(body);

if (body.length > 0) {
const escapedBody = body.html();
body.html(
escapedBody
.replace(/\n/g, '<br>')
.replace(URL_REGEX, "$1<a href='$2' target='_blank'>$2</a>")
);
if (messageBody) {
if (this.bodyView) {
this.bodyView.remove();
this.bodyView = null;
}
this.bodyView = new Whisper.ReactWrapperView({
className: 'body-wrapper',
Component: window.Signal.Components.MessageBody,
props: {
text: messageBody,
},
});
this.$('.body').append(this.bodyView.el);
}

this.renderSent();
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"dependencies": {
"@sindresorhus/is": "^0.8.0",
"@types/google-libphonenumber": "^7.4.14",
"@types/linkify-it": "^2.0.3",
"archiver": "^2.1.1",
"blob-util": "^1.3.0",
"blueimp-canvas-to-blob": "^3.14.0",
Expand Down
2 changes: 2 additions & 0 deletions stylesheets/_global.scss
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,8 @@ $avatar-size: 44px;

p {
overflow-x: hidden;
overflow-y: hidden;
height: 1.2em;
text-overflow: ellipsis;
}

Expand Down
4 changes: 2 additions & 2 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ <h3>{{ welcomeToSignal }}</h3>
{{ #hasBody }}
<div class='content' dir='auto'>
{{ #message }}
<div class='body'>{{ message }}</div>
<div class='body'></div>
{{ /message }}
</div>
{{ /hasBody }}
Expand Down Expand Up @@ -298,7 +298,7 @@ <h3 class='name' dir='auto'> {{ title }} </h3>
<span class='unread-count'>{{ unreadCount }}</span>
{{ /unreadCount }}
{{ #last_message }}
<p class='last-message' dir='auto'> {{ last_message }} </p>
<p class='last-message' dir='auto'></p>
{{ /last_message }}
</div>
</script>
Expand Down
2 changes: 1 addition & 1 deletion test/styleguide/legacy_templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ window.Whisper.View.Templates = {
{{ #hasBody }}
<div class='content' dir='auto'>
{{ #message }}
<div class='body'>{{ message }}</div>
<div class='body'></div>
{{ /message }}
</div>
{{ /hasBody }}
Expand Down
40 changes: 40 additions & 0 deletions ts/components/conversation/AddNewLines.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';

interface Props {
text: string;
}

export class AddNewLines extends React.Component<Props, {}> {
public render() {
const { text } = this.props;
const results: Array<any> = [];
const FIND_NEWLINES = /\n/g;

let match = FIND_NEWLINES.exec(text);
let last = 0;
let count = 1;

if (!match) {
return <span>{text}</span>;
}

while (match) {
if (last < match.index) {
const textWithNoNewline = text.slice(last, match.index);
results.push(<span key={count++}>{textWithNoNewline}</span>);
}

results.push(<br key={count++} />);

// @ts-ignore
last = FIND_NEWLINES.lastIndex;
match = FIND_NEWLINES.exec(text);
}

if (last < text.length) {
results.push(<span key={count++}>{text.slice(last)}</span>);
}

return <span>{results}</span>;
}
}
Loading

0 comments on commit 4e5c896

Please sign in to comment.