| 
						
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -1,57 +1,59 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* eslint-disable */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* global Whisper: false */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* global i18n: false */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* global textsecure: false */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* global _: false */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* global emoji_util: false */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* global Mustache: false */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				// eslint-disable-next-line func-names
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				(function () {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  'use strict';
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    window.Whisper = window.Whisper || {};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const { HTML } = window.Signal;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    const { Attachment } = window.Signal.Types;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const { loadAttachmentData } = window.Signal.Migrations;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    var URL_REGEX = /(^|[\s\n]|<br\/?>)((?:https?|ftp):\/\/[\-A-Z0-9\u00A0-\uD7FF\uE000-\uFDCF\uFDF0-\uFFFD+\u0026\u2019@#\/%?=()~_|!:,.;]*[\-A-Z0-9+\u0026@#\/%=~()_|])/gi;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  window.Whisper = window.Whisper || {};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    var ErrorIconView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const ErrorIconView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    templateName: 'error-icon',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    className: 'error-icon-container',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        initialize: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    initialize() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.model.name === 'UnregisteredUserError') {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.$el.addClass('unregistered-user-error');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    var NetworkErrorView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const NetworkErrorView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    tagName: 'span',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    className: 'hasRetry',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    templateName: 'hasRetry',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        render_attributes: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var messageNotSent;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    render_attributes() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      let messageNotSent;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (!this.model.someRecipientsFailed()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        messageNotSent = i18n('messageNotSent');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                messageNotSent: messageNotSent,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                resend: i18n('resend')
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        messageNotSent,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        resend: i18n('resend'),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    var SomeFailedView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const SomeFailedView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    tagName: 'span',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    className: 'some-failed',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    templateName: 'some-failed',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    render_attributes: {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            someFailed: i18n('someRecipientsFailed')
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      someFailed: i18n('someRecipientsFailed'),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    var TimerView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  const TimerView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    templateName: 'hourglass',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        initialize: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    initialize() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.listenTo(this.model, 'unload', this.remove);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        update: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    update() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.timeout) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        clearTimeout(this.timeout);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.timeout = null;
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -61,35 +63,35 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.model.isExpiring()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.render();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                var totalTime = this.model.get('expireTimer') * 1000;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                var remainingTime = this.model.msTilExpire();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                var elapsed = (totalTime - remainingTime) / totalTime;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                this.$('.sand').css('transform', 'translateY(' + elapsed*100 + '%)');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        const totalTime = this.model.get('expireTimer') * 1000;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        const remainingTime = this.model.msTilExpire();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        const elapsed = (totalTime - remainingTime) / totalTime;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.$('.sand').css('transform', `translateY(${elapsed * 100}%)`);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.$el.css('display', 'inline-block');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.timeout = setTimeout(this.update.bind(this), Math.max(totalTime / 100, 500));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return this;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  Whisper.ExpirationTimerUpdateView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    tagName: 'li',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    className: 'expirationTimerUpdate advisory',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    templateName: 'expirationTimerUpdate',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        id: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    id() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return this.model.id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        initialize: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    initialize() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.conversation = this.model.getExpirationTimerUpdateSource();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.listenTo(this.conversation, 'change', this.render);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.listenTo(this.model, 'unload', this.remove);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        render_attributes: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var seconds = this.model.get('expirationTimerUpdate').expireTimer;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var timerMessage;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    render_attributes() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const seconds = this.model.get('expirationTimerUpdate').expireTimer;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      let timerMessage;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var timerUpdate = this.model.get('expirationTimerUpdate');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var prettySeconds = Whisper.ExpirationTimerOptions.getName(seconds);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const timerUpdate = this.model.get('expirationTimerUpdate');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const prettySeconds = Whisper.ExpirationTimerOptions.getName(seconds);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (timerUpdate && timerUpdate.fromSync) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        timerMessage = i18n('timerSetOnSync', prettySeconds);
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -102,51 +104,51 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        ]);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return { content: timerMessage };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  Whisper.KeyChangeView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    tagName: 'li',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    className: 'keychange advisory',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    templateName: 'keychange',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        id: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    id() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return this.model.id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        initialize: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    initialize() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.conversation = this.model.getModelForKeyChange();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.listenTo(this.conversation, 'change', this.render);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.listenTo(this.model, 'unload', this.remove);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    events: {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            'click .content': 'showIdentity'
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      'click .content': 'showIdentity',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        render_attributes: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    render_attributes() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				              content: this.model.getNotificationText()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        content: this.model.getNotificationText(),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        showIdentity: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    showIdentity() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.$el.trigger('show-identity', this.conversation);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  Whisper.VerifiedChangeView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    tagName: 'li',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    className: 'verified-change advisory',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    templateName: 'verified-change',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        id: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    id() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return this.model.id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        initialize: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    initialize() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.conversation = this.model.getModelForVerifiedChange();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.listenTo(this.conversation, 'change', this.render);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.listenTo(this.model, 'unload', this.remove);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    events: {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            'click .content': 'showIdentity'
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      'click .content': 'showIdentity',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        render_attributes: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var key;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    render_attributes() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      let key;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.model.get('verified')) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (this.model.get('local')) {
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -156,7 +158,7 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          icon: 'verified',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    content: i18n(key, this.conversation.getTitle())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          content: i18n(key, this.conversation.getTitle()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -168,21 +170,21 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        icon: 'shield',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                content: i18n(key, this.conversation.getTitle())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        content: i18n(key, this.conversation.getTitle()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        showIdentity: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    showIdentity() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.$el.trigger('show-identity', this.conversation);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  Whisper.MessageView = Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    tagName: 'li',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    templateName: 'message',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        id: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    id() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return this.model.id;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        initialize: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    initialize() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      //   loadedAttachmentViews :: Promise (Array AttachmentView) | null
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.loadedAttachmentViews = null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -211,28 +213,30 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      'click .timestamp': 'select',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      'click .status': 'select',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      'click .some-failed': 'select',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            'click .error-message': 'select'
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      'click .error-message': 'select',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        retryMessage: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var retrys = _.filter(this.model.get('errors'),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    this.model.isReplayableError.bind(this.model));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            _.map(retrys, 'number').forEach(function(number) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    retryMessage() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const retrys = _.filter(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.model.get('errors'),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.model.isReplayableError.bind(this.model)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      _.map(retrys, 'number').forEach((number) => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.model.resend(number);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }.bind(this));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        onExpired: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    onExpired() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.$el.addClass('expired');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            this.$el.find('.bubble').one('webkitAnimationEnd animationend', function(e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.$el.find('.bubble').one('webkitAnimationEnd animationend', (e) => {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (e.target === this.$('.bubble')[0]) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				          this.remove();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }.bind(this));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      // Failsafe: if in the background, animation events don't fire
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      setTimeout(this.remove.bind(this), 1000);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    /* jshint ignore:start */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        onUnload: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    onUnload() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.avatarView) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.avatarView.remove();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -262,47 +266,47 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.remove();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    /* jshint ignore:end */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        onDestroy: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    onDestroy() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.$el.hasClass('expired')) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.onUnload();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        select: function(e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            this.$el.trigger('select', {message: this.model});
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    select(e) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.$el.trigger('select', { message: this.model });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      e.stopPropagation();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        className: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    className() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return ['entry', this.model.get('type')].join(' ');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        renderPending: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    renderPending() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.$el.addClass('pending');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        renderDone: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    renderDone() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.$el.removeClass('pending');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        renderSent: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    renderSent() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.model.isOutgoing()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.$el.toggleClass('sent', !!this.model.get('sent'));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        renderDelivered: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    renderDelivered() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.model.get('delivered')) { this.$el.addClass('delivered'); }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        renderRead: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    renderRead() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (!_.isEmpty(this.model.get('read_by'))) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.$el.addClass('read');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        onErrorsChanged: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    onErrorsChanged() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.model.isIncoming()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.render();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.renderErrors();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        renderErrors: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var errors = this.model.get('errors');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    renderErrors() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const errors = this.model.get('errors');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.$('.error-icon-container').remove();
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -324,7 +328,7 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.networkErrorView = null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.model.hasNetworkError()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                this.networkErrorView = new NetworkErrorView({model: this.model});
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.networkErrorView = new NetworkErrorView({ model: this.model });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.$('.meta').prepend(this.networkErrorView.render().el);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -338,26 +342,26 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.$('.meta').prepend(this.someFailedView.render().el);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        renderControl: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    renderControl() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.model.isEndSession() || this.model.isGroupUpdate()) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.$el.addClass('control');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                var content = this.$('.content');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        const content = this.$('.content');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        content.text(this.model.getDescription());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        emoji_util.parse(content);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.$el.removeClass('control');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        renderExpiring: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    renderExpiring() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (!this.timerView) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        this.timerView = new TimerView({ model: this.model });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.timerView.setElement(this.$('.timer'));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.timerView.update();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        isImageWithoutCaption: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var attachments = this.model.get('attachments');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var body = this.model.get('body');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    isImageWithoutCaption() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const attachments = this.model.get('attachments');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const body = this.model.get('body');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (!attachments || attachments.length === 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -366,31 +370,29 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var first = attachments[0];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const first = attachments[0];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (first.contentType.startsWith('image/') && first.contentType !== 'image/tiff') {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        render: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var contact = this.model.isIncoming() ? this.model.getContact() : null;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            this.$el.html(
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                Mustache.render(_.result(this, 'template', ''), {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    render() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const 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()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        profileName: (contact && contact.getProfileName()),
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        innerBubbleClasses: this.isImageWithoutCaption() ? '' : 'with-tail',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }, this.render_partials())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            );
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }, this.render_partials()));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.timeStampView.setElement(this.$('.timestamp'));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.timeStampView.update();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.renderControl();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var body = this.$('.body');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const body = this.$('.body');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      emoji_util.parse(body);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -414,23 +416,21 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      return this;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        updateColor: function() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var bubble = this.$('.bubble');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    updateColor() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const bubble = this.$('.bubble');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      // this.contact is known to be non-null if we're registered for color changes
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            var color = this.contact.getColor();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      const color = this.contact.getColor();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (color) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        bubble.removeClass(Whisper.Conversation.COLORS);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        bubble.addClass(color);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.avatarView = new (Whisper.View.extend({
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        templateName: 'avatar',
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                render_attributes: { avatar: this.contact.getAvatar() }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        render_attributes: { avatar: this.contact.getAvatar() },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      }))();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.$('.avatar').replaceWith(this.avatarView.render().$('.avatar'));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    /* eslint-enable */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    /* jshint ignore:start */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    loadAttachmentViews() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      if (this.loadedAttachmentViews !== null) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return this.loadedAttachmentViews;
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -483,7 +483,5 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      view.setElement(view.el);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				      this.trigger('afterChangeHeight');
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    },
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    /* jshint ignore:end */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    /* eslint-disable */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				  });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				})();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}());
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |