Cable-Desktop/js/views/message_view.js
lilia f042378a37 Upgrade emoji support and switch to apple emoji
Use emojijs for replacing unicode with image tags for display. We were
already using it to replace colons with unicode. Additionally it has
a companion data repo that is kept up to date with images from all
the common image sets.

// FREEBIE
2016-09-01 11:51:53 -07:00

159 lines
5.9 KiB
JavaScript

/*
* vim: ts=4:sw=4:expandtab
*/
(function () {
'use strict';
window.Whisper = window.Whisper || {};
var URL_REGEX = /(^|[\s\n]|<br\/?>)((?:https?|ftp):\/\/[\-A-Z0-9\u00A0-\uD7FF\uE000-\uFDCF\uFDF0-\uFFFD+\u0026\u2019@#\/%?=()~_|!:,.;]*[\-A-Z0-9+\u0026@#\/%=~()_|])/gi;
var ErrorIconView = Whisper.View.extend({
templateName: 'error-icon',
className: 'error-icon-container',
initialize: function() {
if (this.model.name === 'UnregisteredUserError') {
this.$el.addClass('unregistered-user-error');
}
}
});
var NetworkErrorView = Whisper.View.extend({
tagName: 'span',
className: 'hasRetry',
templateName: 'hasRetry',
render_attributes: {
messageNotSent: i18n('messageNotSent'),
resend: i18n('resend')
}
});
Whisper.MessageView = Whisper.View.extend({
tagName: 'li',
templateName: 'message',
initialize: function() {
this.listenTo(this.model, 'change:errors', this.onErrorsChanged);
this.listenTo(this.model, 'change:body', this.render);
this.listenTo(this.model, 'change:delivered', this.renderDelivered);
this.listenTo(this.model, 'change', this.renderSent);
this.listenTo(this.model, 'change:flags change:group_update', this.renderControl);
this.listenTo(this.model, 'destroy', this.remove);
this.listenTo(this.model, 'pending', this.renderPending);
this.listenTo(this.model, 'done', this.renderDone);
this.timeStampView = new Whisper.ExtendedTimestampView();
},
events: {
'click .retry': 'retryMessage',
'click .error-icon': 'select',
'click .timestamp': 'select',
'click .status': 'select',
'click .error-message': 'select'
},
retryMessage: function() {
var retrys = _.filter(this.model.get('errors'), function(e) {
return (e.name === 'MessageError' ||
e.name === 'OutgoingMessageError' ||
e.name === 'SendMessageNetworkError');
});
_.map(retrys, 'number').forEach(function(number) {
this.model.resend(number);
}.bind(this));
},
select: function(e) {
this.$el.trigger('select', {message: this.model});
e.stopPropagation();
},
className: function() {
return ['entry', this.model.get('type')].join(' ');
},
renderPending: function() {
this.$el.addClass('pending');
},
renderDone: function() {
this.$el.removeClass('pending');
},
renderSent: function() {
if (this.model.isOutgoing()) {
this.$el.toggleClass('sent', !!this.model.get('sent'));
}
},
renderDelivered: function() {
if (this.model.get('delivered')) { this.$el.addClass('delivered'); }
},
onErrorsChanged: function() {
if (this.model.isIncoming()) {
this.render();
} else {
this.renderErrors();
}
},
renderErrors: function() {
var errors = this.model.get('errors');
if (_.size(errors) > 0) {
if (this.model.isIncoming()) {
this.$('.content').text(this.model.getDescription()).addClass('error-message');
}
var view = new ErrorIconView({ model: errors[0] });
view.render().$el.appendTo(this.$('.bubble'));
} else {
this.$('.error-icon-container').remove();
}
if (this.model.hasNetworkError()) {
this.$('.meta').prepend(new NetworkErrorView().render().el);
} else {
this.$('.meta .hasRetry').remove();
}
},
renderControl: function() {
if (this.model.isEndSession() || this.model.isGroupUpdate()) {
this.$el.addClass('control');
this.$('.content').text(this.model.getDescription());
} else {
this.$el.removeClass('control');
}
},
render: function() {
var contact = this.model.isIncoming() ? this.model.getContact() : null;
this.$el.html(
Mustache.render(_.result(this, 'template', ''), {
message: this.model.get('body'),
timestamp: this.model.get('sent_at'),
sender: (contact && contact.getTitle()) || '',
avatar: (contact && contact.getAvatar()),
}, this.render_partials())
);
this.timeStampView.setElement(this.$('.timestamp'));
this.timeStampView.update();
this.renderControl();
var body = this.$('.body');
emoji_util.parse(body);
if (body.length > 0) {
var escaped = body.html();
body.html(escaped.replace(/\n/g, '<br>').replace(URL_REGEX, "$1<a href='$2' target='_blank'>$2</a>"));
}
this.renderSent();
this.renderDelivered();
this.renderErrors();
this.loadAttachments();
return this;
},
loadAttachments: function() {
this.model.get('attachments').forEach(function(attachment) {
var view = new Whisper.AttachmentView({ model: attachment });
this.listenTo(view, 'update', function() {
if (!view.el.parentNode) {
this.trigger('beforeChangeHeight');
this.$('.attachments').append(view.el);
this.trigger('afterChangeHeight');
}
});
view.render();
}.bind(this));
}
});
})();