/* global autosize, Backbone, Handlebars, OC, OCA */ /** * * @copyright Copyright (c) 2017, Daniel Calviño Sánchez (danxuliu@gmail.com) * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * */ (function(OCA, OC, Backbone, Handlebars, autosize) { 'use strict'; OCA.SpreedMe = OCA.SpreedMe || {}; OCA.SpreedMe.Views = OCA.SpreedMe.Views || {}; var TEMPLATE = '' + '
' + '

{{emptyResultLabel}}

' + ''; var ADD_COMMENT_TEMPLATE = '
' + '
' + '
' + '
{{actorDisplayName}}
' + '
' + '
' + '
{{message}}
' + ' ' + ' '+ '
' + '
'; var COMMENT_TEMPLATE = '
  • ' + '
    ' + '
    ' + '
    {{actorDisplayName}}
    ' + '
    {{date}}
    ' + '
    ' + '
    {{{formattedMessage}}}
    ' + '
  • '; var ChatView = Backbone.View.extend({ events: { 'submit .newCommentForm': '_onSubmitComment', }, initialize: function() { this.listenTo(this.collection, 'reset', this.render); this.listenTo(this.collection, 'add', this._onAddModel); }, template: function(params) { if (!this._template) { this._template = Handlebars.compile(TEMPLATE); } return this._template(params); }, addCommentTemplate: function(params) { if (!this._addCommentTemplate) { this._addCommentTemplate = Handlebars.compile(ADD_COMMENT_TEMPLATE); } // FIXME handle guest users var currentUser = OC.getCurrentUser(); return this._addCommentTemplate(_.extend({ actorId: currentUser.uid, actorDisplayName: currentUser.displayName, newMessagePlaceholder: t('spreed', 'New message…'), submitText: t('spreed', 'Send') }, params)); }, commentTemplate: function(params) { if (!this._commentTemplate) { this._commentTemplate = Handlebars.compile(COMMENT_TEMPLATE); } return this._commentTemplate(params); }, render: function() { this.$el.html(this.template({ emptyResultLabel: t('spreed', 'No messages yet, start the conversation!') })); this.$el.find('.comments').before(this.addCommentTemplate({})); this.$el.find('.has-tooltip').tooltip(); this.$container = this.$el.find('ul.comments'); // FIXME handle guest users this.$el.find('.avatar').avatar(OC.getCurrentUser().uid, 32); this.delegateEvents(); this.$el.find('.message').on('keydown input change', this._onTypeComment); autosize(this.$el.find('.newCommentRow .message')); return this; }, _formatItem: function(commentModel) { // PHP timestamp is second-based; JavaScript timestamp is // millisecond based. var timestamp = commentModel.get('timestamp') * 1000; var actorDisplayName = commentModel.get('actorDisplayName'); if (commentModel.attributes.actorType === 'guests') { // FIXME get guest name from WebRTC or something like that actorDisplayName = 'Guest'; } if (actorDisplayName == null) { actorDisplayName = t('spreed', '[Unknown user name]'); } var data = _.extend({}, commentModel.attributes, { actorDisplayName: actorDisplayName, timestamp: timestamp, date: OC.Util.relativeModifiedDate(timestamp), altDate: OC.Util.formatDate(timestamp, 'LL LTS'), formattedMessage: escapeHTML(commentModel.get('message')).replace(/\n/g, '
    ') }); return data; }, _onAddModel: function(model, collection, options) { this.$el.find('.emptycontent').toggleClass('hidden', true); var $el = $(this.commentTemplate(this._formatItem(model))); if (!_.isUndefined(options.at) && collection.length > 1) { this.$container.find('li').eq(options.at).before($el); } else { this.$container.prepend($el); } this._postRenderItem($el); }, _postRenderItem: function($el) { $el.find('.has-tooltip').tooltip(); $el.find('.avatar').each(function() { var $this = $(this); $this.avatar($this.attr('data-username'), 32); }); // FIXME do not show contacts menu for guest users var username = $el.find('.avatar').data('username'); if (username !== oc_current_user) { $el.find('.authorRow .avatar, .authorRow .author').contactsMenu( username, 0, $el.find('.authorRow')); } var $message = $el.find('.message'); this._postRenderMessage($message); }, _postRenderMessage: function($el) { $el.find('.avatar').each(function() { var avatar = $(this); var strong = $(this).next(); var appendTo = $(this).parent(); $.merge(avatar, strong).contactsMenu(avatar.data('user'), 0, appendTo); }); }, _onTypeComment: function(ev) { var $field = $(ev.target); var $submitButton = $field.data('submitButtonEl'); if (!$submitButton) { $submitButton = $field.closest('form').find('.submit'); $field.data('submitButtonEl', $submitButton); } // Submits form with Enter, but Shift+Enter is a new line if (ev.keyCode === 13 && !ev.shiftKey) { $submitButton.click(); ev.preventDefault(); } }, _commentBodyHTML2Plain: function($el) { var $comment = $el.clone(); var oldHtml; var html = $comment.html(); do { // replace works one by one oldHtml = html; html = oldHtml.replace("
    ", "\n"); // preserve line breaks console.warn(html); } while(oldHtml !== html); $comment.html(html); return $comment.text(); }, _onSubmitComment: function(e) { var self = this; var $form = $(e.target); var comment = null; var $submit = $form.find('.submit'); var $loading = $form.find('.submitLoading'); var $commentField = $form.find('.message'); var message = $commentField.text().trim(); if (!message.length) { return false; } $commentField.prop('disabled', true); $submit.addClass('hidden'); $loading.removeClass('hidden'); message = this._commentBodyHTML2Plain($commentField); comment = new OCA.SpreedMe.Models.ChatMessage({ token: this.collection.token, message: message }); comment.save({}, { success: function(model) { self._onSubmitSuccess(model, $form); }, error: function() { self._onSubmitError($form); } }); return false; }, _onSubmitSuccess: function(model, $form) { $form.find('.submit').removeClass('hidden'); $form.find('.submitLoading').addClass('hidden'); $form.find('.message').text('').prop('disabled', false); // The new message does not need to be explicitly added to the list // of messages; it will be automatically fetched from the server // thanks to the auto-refresh of the list. }, _onSubmitError: function($form) { $form.find('.submit').removeClass('hidden'); $form.find('.submitLoading').addClass('hidden'); $form.find('.message').prop('disabled', false); OC.Notification.show(t('spreed', 'Error occurred while sending message'), {type: 'error'}); }, }); OCA.SpreedMe.Views.ChatView = ChatView; })(OCA, OC, Backbone, Handlebars, autosize);