Rev 1 | AutorÃa | Comparar con el anterior | Ultima modificación | Ver Log |
{"version":3,"file":"message_drawer_view_conversation_renderer.min.js","sources":["../src/message_drawer_view_conversation_renderer.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * This module updates the UI for the conversation page in the message\n * drawer.\n *\n * The module will take a patch from the message_drawer_view_conversation_p
atcher\n * module and update the UI to reflect the changes.\n *\n * This is the only module that ever modifies the UI of the conversation page.\n *\n * @module core_message/message_drawer_view_conversation_renderer\n * @copyright 2018 Ryan Wyllie <ryan@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/notification',\n 'core/str',\n 'core/templates',\n 'core/user_date',\n 'core_message/message_drawer_view_conversation_constants',\n 'core/aria',\n 'core/truncate',\n],\nfunction(\n $,\n Notification,\n Str,\n Templates,\n UserDate,\n Constants,\n Aria,\n Truncate,\n) {\n var SELECTORS = Constants.SELECTORS;\n var TEMPLATES = Constants.TEMPLATES;\n var CONVERSATION_TYPES = Constants.CONVERSATION_TYPES;\n\n /**\n * Get the messages container element.\n *\n * @param {Object} body Conversation body container element.\n * @return {Object} The messages container ele
ment.\n */\n var getMessagesContainer = function(body) {\n return body.find(SELECTORS.CONTENT_MESSAGES_CONTAINER);\n };\n\n /**\n * Show the messages container element.\n *\n * @param {Object} body Conversation body container element.\n */\n var showMessagesContainer = function(body) {\n getMessagesContainer(body).removeClass('hidden');\n };\n\n /**\n * Hide the messages container element.\n *\n * @param {Object} body Conversation body container element.\n */\n var hideMessagesContainer = function(body) {\n getMessagesContainer(body).addClass('hidden');\n };\n\n /**\n * Get the self-conversation message container element.\n *\n * @param {Object} body Conversation body container element.\n * @return {Object} The messages container element.\n */\n var getSelfConversationMessageContainer = function(body) {\n return body.find(SELECTORS.SELF_CONVERSATION_MESSAGE_CONTAINER);\n };\n\n /**\n
* Hide the self-conversation message container element.\n *\n * @param {Object} body Conversation body container element.\n * @return {Object} The messages container element.\n */\n var hideSelfConversationMessageContainer = function(body) {\n return getSelfConversationMessageContainer(body).addClass('hidden');\n };\n\n /**\n * Get the contact request sent container element.\n *\n * @param {Object} body Conversation body container element.\n * @return {Object} The messages container element.\n */\n var getContactRequestSentContainer = function(body) {\n return body.find(SELECTORS.CONTACT_REQUEST_SENT_MESSAGE_CONTAINER);\n };\n\n /**\n * Hide the contact request sent container element.\n *\n * @param {Object} body Conversation body container element.\n * @return {Object} The messages container element.\n */\n var hideContactRequestSentContainer = function(body) {\n return getContactRequestSentContainer(body).
addClass('hidden');\n };\n\n /**\n * Get the footer container element.\n *\n * @param {Object} footer Conversation footer container element.\n * @return {Object} The footer container element.\n */\n var getFooterContentContainer = function(footer) {\n return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_CONTAINER);\n };\n\n /**\n * Show the footer container element.\n *\n * @param {Object} footer Conversation footer container element.\n */\n var showFooterContent = function(footer) {\n getFooterContentContainer(footer).removeClass('hidden');\n };\n\n /**\n * Hide the footer container element.\n *\n * @param {Object} footer Conversation footer container element.\n */\n var hideFooterContent = function(footer) {\n getFooterContentContainer(footer).addClass('hidden');\n };\n\n /**\n * Get the footer edit mode container element.\n *\n * @param {Object} footer Conversation footer container ele
ment.\n * @return {Object} The footer container element.\n */\n var getFooterEditModeContainer = function(footer) {\n return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER);\n };\n\n /**\n * Show the footer edit mode container element.\n *\n * @param {Object} footer Conversation footer container element.\n */\n var showFooterEditMode = function(footer) {\n getFooterEditModeContainer(footer).removeClass('hidden');\n };\n\n /**\n * Hide the footer edit mode container element.\n *\n * @param {Object} footer Conversation footer container element.\n */\n var hideFooterEditMode = function(footer) {\n getFooterEditModeContainer(footer).addClass('hidden');\n };\n\n /**\n * Get the footer placeholder.\n *\n * @param {Object} footer Conversation footer container element.\n * @return {Object} The footer placeholder container element.\n */\n var getFooterPlaceholderContainer = function(foo
ter) {\n return footer.find(SELECTORS.PLACEHOLDER_CONTAINER);\n };\n\n /**\n * Show the footer placeholder\n *\n * @param {Object} footer Conversation footer container element.\n */\n var showFooterPlaceholder = function(footer) {\n getFooterPlaceholderContainer(footer).removeClass('hidden');\n };\n\n /**\n * Hide the footer placeholder\n *\n * @param {Object} footer Conversation footer container element.\n */\n var hideFooterPlaceholder = function(footer) {\n getFooterPlaceholderContainer(footer).addClass('hidden');\n };\n\n /**\n * Get the footer Require add as contact container element.\n *\n * @param {Object} footer Conversation footer container element.\n * @return {Object} The footer Require add as contact container element.\n */\n var getFooterRequireContactContainer = function(footer) {\n return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER);\n };\n\n /**\n
* Show the footer add as contact dialogue.\n *\n * @param {Object} footer Conversation footer container element.\n */\n var showFooterRequireContact = function(footer) {\n getFooterRequireContactContainer(footer).removeClass('hidden');\n };\n\n /**\n * Hide the footer add as contact dialogue.\n *\n * @param {Object} footer Conversation footer container element.\n */\n var hideFooterRequireContact = function(footer) {\n getFooterRequireContactContainer(footer).addClass('hidden');\n };\n\n /**\n * Get the footer Required to unblock contact container element.\n *\n * @param {Object} footer Conversation footer container element.\n * @return {Object} The footer Required to unblock contact container element.\n */\n var getFooterRequireUnblockContainer = function(footer) {\n return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER);\n };\n\n /**\n * Show the footer Required to unblock contac
t container element.\n *\n * @param {Object} footer Conversation footer container element.\n */\n var showFooterRequireUnblock = function(footer) {\n getFooterRequireUnblockContainer(footer).removeClass('hidden');\n };\n\n /**\n * Hide the footer Required to unblock contact container element.\n *\n * @param {Object} footer Conversation footer container element.\n */\n var hideFooterRequireUnblock = function(footer) {\n getFooterRequireUnblockContainer(footer).addClass('hidden');\n };\n\n /**\n * Get the footer Unable to message contact container element.\n *\n * @param {Object} footer Conversation footer container element.\n * @return {Object} The footer Unable to message contact container element.\n */\n var getFooterUnableToMessageContainer = function(footer) {\n return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER);\n };\n\n /**\n * Show the footer Unable to message contact co
ntainer element.\n *\n * @param {Object} footer Conversation footer container element.\n */\n var showFooterUnableToMessage = function(footer) {\n getFooterUnableToMessageContainer(footer).removeClass('hidden');\n };\n\n /**\n * Hide the footer Unable to message contact container element.\n *\n * @param {Object} footer Conversation footer container element.\n */\n var hideFooterUnableToMessage = function(footer) {\n getFooterUnableToMessageContainer(footer).addClass('hidden');\n };\n\n /**\n * Hide all header elements.\n *\n * @param {Object} header Conversation header container element.\n */\n var hideAllHeaderElements = function(header) {\n hideHeaderContent(header);\n hideHeaderEditMode(header);\n hideHeaderPlaceholder(header);\n };\n\n /**\n * Hide all footer dialogues and messages.\n *\n * @param {Object} footer Conversation footer container element.\n */\n var hideAllFooterEl
ements = function(footer) {\n hideFooterContent(footer);\n hideFooterEditMode(footer);\n hideFooterPlaceholder(footer);\n hideFooterRequireContact(footer);\n hideFooterRequireUnblock(footer);\n hideFooterUnableToMessage(footer);\n };\n\n /**\n * Get the content placeholder container element.\n *\n * @param {Object} body Conversation body container element.\n * @return {Object} The body placeholder container element.\n */\n var getContentPlaceholderContainer = function(body) {\n return body.find(SELECTORS.CONTENT_PLACEHOLDER_CONTAINER);\n };\n\n /**\n * Show the content placeholder.\n *\n * @param {Object} body Conversation body container element.\n */\n var showContentPlaceholder = function(body) {\n getContentPlaceholderContainer(body).removeClass('hidden');\n };\n\n /**\n * Hide the content placeholder.\n *\n * @param {Object} body Conversation body container element.\n */\
n var hideContentPlaceholder = function(body) {\n getContentPlaceholderContainer(body).addClass('hidden');\n };\n\n /**\n * Get the header content container element.\n *\n * @param {Object} header Conversation header container element.\n * @return {Object} The header content container element.\n */\n var getHeaderContent = function(header) {\n return header.find(SELECTORS.HEADER);\n };\n\n /**\n * Show the header content.\n *\n * @param {Object} header Conversation header container element.\n */\n var showHeaderContent = function(header) {\n getHeaderContent(header).removeClass('hidden');\n };\n\n /**\n * Hide the header content.\n *\n * @param {Object} header Conversation header container element.\n */\n var hideHeaderContent = function(header) {\n getHeaderContent(header).addClass('hidden');\n };\n\n /**\n * Get the header edit mode container element.\n *\n * @param {Object} h
eader Conversation header container element.\n * @return {Object} The header content container element.\n */\n var getHeaderEditMode = function(header) {\n return header.find(SELECTORS.HEADER_EDIT_MODE);\n };\n\n /**\n * Show the header edit mode container.\n *\n * @param {Object} header Conversation header container element.\n */\n var showHeaderEditMode = function(header) {\n getHeaderEditMode(header).removeClass('hidden');\n };\n\n /**\n * Hide the header edit mode container.\n *\n * @param {Object} header Conversation header container element.\n */\n var hideHeaderEditMode = function(header) {\n getHeaderEditMode(header).addClass('hidden');\n };\n\n /**\n * Get the header placeholder container element.\n *\n * @param {Object} header Conversation header container element.\n * @return {Object} The header placeholder container element.\n */\n var getHeaderPlaceholderContainer = function(header)
{\n return header.find(SELECTORS.HEADER_PLACEHOLDER_CONTAINER);\n };\n\n /**\n * Show the header placeholder.\n *\n * @param {Object} header Conversation header container element.\n */\n var showHeaderPlaceholder = function(header) {\n getHeaderPlaceholderContainer(header).removeClass('hidden');\n };\n\n /**\n * Hide the header placeholder.\n *\n * @param {Object} header Conversation header container element.\n */\n var hideHeaderPlaceholder = function(header) {\n getHeaderPlaceholderContainer(header).addClass('hidden');\n };\n\n /**\n * Get the emoji picker container element.\n *\n * @param {Object} footer Conversation footer container element.\n * @return {Object} The emoji picker container element.\n */\n var getEmojiPickerContainer = function(footer) {\n return footer.find(SELECTORS.EMOJI_PICKER_CONTAINER);\n };\n\n /**\n * Get the emoji picker container element.\n *\n * @param
{Object} footer Conversation footer container element.\n * @return {Object} The emoji picker container element.\n */\n var getEmojiAutoCompleteContainer = function(footer) {\n return footer.find(SELECTORS.EMOJI_AUTO_COMPLETE_CONTAINER);\n };\n\n /**\n * Get a message element.\n *\n * @param {Object} body Conversation body container element.\n * @param {Number} messageId the Message id.\n * @return {Object} A message element from the conversation.\n */\n var getMessageElement = function(body, messageId) {\n var messagesContainer = getMessagesContainer(body);\n return messagesContainer.find('[data-message-id=\"' + messageId + '\"]');\n };\n\n /**\n * Get the day container element. The day container element holds a list of messages for that day.\n *\n * @param {Object} body Conversation body container element.\n * @param {Number} dayTimeCreated Midnight timestamp for the day.\n * @return {Object} jQuery object\n
*/\n var getDayElement = function(body, dayTimeCreated) {\n var messagesContainer = getMessagesContainer(body);\n return messagesContainer.find('[data-day-id=\"' + dayTimeCreated + '\"]');\n };\n\n /**\n * Get the more messages loading icon container element.\n *\n * @param {Object} body Conversation body container element.\n * @return {Object} The more messages loading container element.\n */\n var getMoreMessagesLoadingIconContainer = function(body) {\n return body.find(SELECTORS.MORE_MESSAGES_LOADING_ICON_CONTAINER);\n };\n\n /**\n * Show the more messages loading icon.\n *\n * @param {Object} body Conversation body container element.\n */\n var showMoreMessagesLoadingIcon = function(body) {\n getMoreMessagesLoadingIconContainer(body).removeClass('hidden');\n };\n\n /**\n * Hide the more messages loading icon.\n *\n * @param {Object} body Conversation body container element.\n */\n var hideMore
MessagesLoadingIcon = function(body) {\n getMoreMessagesLoadingIconContainer(body).addClass('hidden');\n };\n\n /**\n * Get the confirm dialogue container element.\n *\n * @param {Object} root The container element to search.\n * @return {Object} The confirm dialogue container element.\n */\n var getConfirmDialogueContainer = function(root) {\n return root.find(SELECTORS.CONFIRM_DIALOGUE_CONTAINER);\n };\n\n /**\n * Show the confirm dialogue container element.\n *\n * @param {Object} root The container element containing a dialogue.\n */\n var showConfirmDialogueContainer = function(root) {\n var container = getConfirmDialogueContainer(root);\n var siblings = container.siblings(':not(.hidden)');\n Aria.hide(siblings.get());\n siblings.attr('data-confirm-dialogue-hidden', true);\n\n container.removeClass('hidden');\n };\n\n /**\n * Hide the confirm dialogue container element.\n *\n * @par
am {Object} root The container element containing a dialogue.\n */\n var hideConfirmDialogueContainer = function(root) {\n var container = getConfirmDialogueContainer(root);\n var siblings = container.siblings('[data-confirm-dialogue-hidden=\"true\"]');\n Aria.unhide(siblings.get());\n siblings.removeAttr('data-confirm-dialogue-hidden');\n\n container.addClass('hidden');\n };\n\n /**\n * Set the number of selected messages.\n *\n * @param {Object} header The header container element.\n * @param {Number} value The new number to display.\n */\n var setMessagesSelectedCount = function(header, value) {\n getHeaderEditMode(header).find(SELECTORS.MESSAGES_SELECTED_COUNT).text(value);\n };\n\n /**\n * Format message for the mustache template, transform camelCase properties to lowercase properties.\n *\n * @param {Array} messages Array of message objects.\n * @param {Object} datesCache Cache timestamps and their fo
rmatted date string.\n * @return {Array} Messages formated for mustache template.\n */\n var formatMessagesForTemplate = function(messages, datesCache) {\n return messages.map(function(message) {\n return {\n id: message.id,\n isread: message.isRead,\n fromloggedinuser: message.fromLoggedInUser,\n userfrom: message.userFrom,\n text: message.text,\n formattedtime: message.timeCreated ? datesCache[message.timeCreated] : null\n };\n });\n };\n\n /**\n * Create rendering promises for each day containing messages.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Array} days Array of days containing messages.\n * @param {Object} datesCache Cache timestamps and their formatted date string.\n * @return {Prom
ise} Days rendering promises.\n */\n var renderAddDays = function(header, body, footer, days, datesCache) {\n var messagesContainer = getMessagesContainer(body);\n var daysRenderPromises = days.map(function(data) {\n var timestampDate = new Date(data.value.timestamp * 1000);\n return Templates.render(TEMPLATES.DAY, {\n timestamp: data.value.timestamp,\n currentyear: timestampDate.getFullYear() === (new Date()).getFullYear(),\n messages: formatMessagesForTemplate(data.value.messages, datesCache)\n });\n });\n\n return $.when.apply($, daysRenderPromises).then(function() {\n // Wait until all of the rendering is done for each of the days\n // to ensure they are added to the page in the correct order.\n days.forEach(function(data, index) {\n daysRenderPromises[index]\n .then(function(html) {\n if (data.before) {\
n var element = getDayElement(body, data.before.timestamp);\n return $(html).insertBefore(element);\n } else {\n return messagesContainer.append(html);\n }\n })\n .catch(function() {\n // Fail silently.\n });\n });\n\n return;\n });\n };\n\n /**\n * Add (more) messages to day containers.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Array} messages List of messages.\n * @param {Object} datesCache Cache timestamps and their formatted date string.\n * @return {Promise} Messages rendering promises.\n */\n var renderAddMessages = function(header, body, footer, messages, datesCache) {\n var
messagesData = messages.map(function(data) {\n return data.value;\n });\n var formattedMessages = formatMessagesForTemplate(messagesData, datesCache);\n\n return Templates.render(TEMPLATES.MESSAGES, {messages: formattedMessages})\n .then(function(html) {\n var messageList = $(html);\n messages.forEach(function(data) {\n var messageHtml = messageList.find('[data-message-id=\"' + data.value.id + '\"]');\n if (data.before) {\n var element = getMessageElement(body, data.before.id);\n return messageHtml.insertBefore(element);\n } else {\n var dayContainer = getDayElement(body, data.day.timestamp);\n var dayMessagesContainer = dayContainer.find(SELECTORS.DAY_MESSAGES_CONTAINER);\n return dayMessagesContainer.append(messageHtml);\n }\n });\n
\n return;\n });\n };\n\n /**\n * Update existing messages.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Array} messages List of messages.\n * @param {Object} datesCache Cache timestamps and their formatted date string.\n */\n var renderUpdateMessages = function(header, body, footer, messages, datesCache) {\n messages.forEach(function(message) {\n var before = message.before;\n var after = message.after;\n var element = getMessageElement(body, before.id);\n\n if (before.id != after.id) {\n element.attr('data-message-id', after.id);\n }\n\n if (before.timeCreated != after.timeCreated) {\n var formattedTime = datesCache[after.timeCreated];\n element.find(SELECTORS.LOADING_ICON_CONTAINER).
addClass('hidden');\n element.find(SELECTORS.TIME_CREATED).text(formattedTime).removeClass('hidden');\n }\n\n if (before.sendState != after.sendState) {\n var loading = element.find(SELECTORS.LOADING_ICON_CONTAINER);\n var time = element.find(SELECTORS.TIME_CREATED);\n var retry = element.find(SELECTORS.RETRY_SEND);\n\n loading.addClass('hidden');\n Aria.hide(loading.get());\n\n time.addClass('hidden');\n Aria.hide(time.get());\n\n retry.addClass('hidden');\n Aria.hide(retry.get());\n\n element.removeClass('border border-danger');\n\n switch (after.sendState) {\n case 'pending':\n loading.removeClass('hidden');\n Aria.unhide(loading.get());\n break;\n case 'error':\n retry.removeCla
ss('hidden');\n Aria.unhide(retry.get());\n element.addClass('border border-danger');\n break;\n case 'sent':\n time.removeClass('hidden');\n Aria.unhide(time.get());\n break;\n }\n }\n\n if (before.text != after.text) {\n element.find(SELECTORS.TEXT_CONTAINER).html(after.text);\n }\n\n if (before.errorMessage != after.errorMessage) {\n var messageContainer = element.find(SELECTORS.ERROR_MESSAGE_CONTAINER);\n var message = messageContainer.find(SELECTORS.ERROR_MESSAGE);\n\n if (after.errorMessage) {\n messageContainer.removeClass('hidden');\n Aria.unhide(messageContainer.get());\n message.text(after.errorMessage);\n } else {\n messageContainer.addC
lass('hidden');\n Aria.unhide(messageContainer.get());\n message.text('');\n }\n }\n });\n };\n\n /**\n * Remove days from conversation.\n *\n * @param {Object} body The body container element.\n * @param {Array} days Array of days to be removed.\n */\n var renderRemoveDays = function(body, days) {\n days.forEach(function(data) {\n getDayElement(body, data.timestamp).remove();\n });\n };\n\n /**\n * Remove messages from conversation.\n *\n * @param {Object} body The body container element.\n * @param {Array} messages Array of messages to be removed.\n */\n var renderRemoveMessages = function(body, messages) {\n messages.forEach(function(data) {\n getMessageElement(body, data.id).remove();\n });\n };\n\n /**\n * Render the full conversation base on input from the statemanager.\n *\n * This will pre-load all of t
he formatted timestamps for each message that\n * needs to render to reduce the number of networks requests.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} data The conversation diff.\n * @return {Object} jQuery promise.\n */\n var renderConversation = function(header, body, footer, data) {\n var renderingPromises = [];\n var hasAddDays = data.days.add.length > 0;\n var hasAddMessages = data.messages.add.length > 0;\n var hasUpdateMessages = data.messages.update.length > 0;\n var timestampsToFormat = [];\n var datesCachePromise = $.Deferred().resolve({}).promise();\n\n if (hasAddDays) {\n // Search for all of the timeCreated values in all of the messages in all of\n // the days that we need to render.\n timestampsToFormat = timestampsToFormat.conca
t(data.days.add.reduce(function(carry, day) {\n return carry.concat(day.value.messages.reduce(function(timestamps, message) {\n if (message.timeCreated) {\n timestamps.push(message.timeCreated);\n }\n return timestamps;\n }, []));\n }, []));\n }\n\n if (hasAddMessages) {\n // Search for all of the timeCreated values in all of the messages that we\n // need to render.\n timestampsToFormat = timestampsToFormat.concat(data.messages.add.reduce(function(timestamps, message) {\n if (message.value.timeCreated) {\n timestamps.push(message.value.timeCreated);\n }\n return timestamps;\n }, []));\n }\n\n if (hasUpdateMessages) {\n timestampsToFormat = timestampsToFormat.concat(data.messages.update.reduce(function(timestamps, message) {\n if
(message.before.timeCreated != message.after.timeCreated) {\n timestamps.push(message.after.timeCreated);\n }\n return timestamps;\n }, []));\n }\n\n if (timestampsToFormat.length) {\n // If we have timestamps then pre-load the formatted version of each of them\n // in a single request to the server. This saves the templates doing multiple\n // individual requests.\n datesCachePromise = Str.get_string('strftimetime24', 'core_langconfig')\n .then(function(format) {\n var requests = timestampsToFormat.map(function(timestamp) {\n return {\n timestamp: timestamp,\n format: format\n };\n });\n\n return UserDate.get(requests);\n })\n .then(function(formattedTimes) {\n return timest
ampsToFormat.reduce(function(carry, timestamp, index) {\n carry[timestamp] = formattedTimes[index];\n return carry;\n }, {});\n });\n }\n\n if (hasAddDays) {\n renderingPromises.push(datesCachePromise.then(function(datesCache) {\n return renderAddDays(header, body, footer, data.days.add, datesCache);\n }));\n }\n\n if (hasAddMessages) {\n renderingPromises.push(datesCachePromise.then(function(datesCache) {\n return renderAddMessages(header, body, footer, data.messages.add, datesCache);\n }));\n }\n\n if (hasUpdateMessages) {\n renderingPromises.push(datesCachePromise.then(function(datesCache) {\n return renderUpdateMessages(header, body, footer, data.messages.update, datesCache);\n }));\n }\n\n if (data.days.remove.length > 0) {\n renderRemoveDays(body, d
ata.days.remove);\n }\n\n if (data.messages.remove.length > 0) {\n renderRemoveMessages(body, data.messages.remove);\n }\n\n return $.when.apply($, renderingPromises);\n };\n\n /**\n * Render the conversation header.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} data Data for header.\n * @return {Object} jQuery promise\n */\n var renderHeader = function(header, body, footer, data) {\n var headerContainer = getHeaderContent(header);\n var template = TEMPLATES.HEADER_PUBLIC;\n data.context.showrouteback = (header.attr('data-from-panel') === \"false\");\n if (data.type == CONVERSATION_TYPES.PRIVATE) {\n template = data.showControls ? TEMPLATES.HEADER_PRIVATE : TEMPLATES.HEADER_PRIVATE_NO_CONTROLS;\n } else if (data.type == CONVERSATION_TYPES.SEL
F) {\n template = TEMPLATES.HEADER_SELF;\n }\n\n return Templates.render(template, data.context)\n .then(function(html, js) {\n Templates.replaceNodeContents(headerContainer, html, js);\n return;\n });\n };\n\n /**\n * Render the conversation footer.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} data Data for footer.\n * @return {Object} jQuery promise.\n */\n var renderFooter = function(header, body, footer, data) {\n hideAllFooterElements(footer);\n\n switch (data.type) {\n case 'placeholder':\n return showFooterPlaceholder(footer);\n case 'add-contact':\n return Str.get_strings([\n {\n key: 'requirecontacttomessage',\n
component: 'core_message',\n param: data.user.fullname\n },\n {\n key: 'isnotinyourcontacts',\n component: 'core_message',\n param: data.user.fullname\n }\n ])\n .then(function(strings) {\n var title = strings[1];\n var text = strings[0];\n var footerContainer = getFooterRequireContactContainer(footer);\n footerContainer.find(SELECTORS.TITLE).text(title);\n footerContainer.find(SELECTORS.TEXT).text(text);\n showFooterRequireContact(footer);\n return strings;\n });\n case 'edit-mode':\n return showFooterEditMode(footer);\n case 'content':\n return showFooter
Content(footer);\n case 'unblock':\n return showFooterRequireUnblock(footer);\n case 'unable-to-message':\n return showFooterUnableToMessage(footer);\n }\n\n return true;\n };\n\n /**\n * Scroll to a message in the conversation.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Number} messageId Message id.\n */\n var renderScrollToMessage = function(header, body, footer, messageId) {\n var messagesContainer = getMessagesContainer(body);\n var messageElement = getMessageElement(body, messageId);\n var position = messageElement.position();\n // Scroll the message container down to the top of the message element.\n if (position) {\n var scrollTop = messagesContainer.scrollTop() + position.top;\n messagesContainer.scrollTop
(scrollTop);\n }\n };\n\n /**\n * Hide or show the conversation header.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Bool} isLoadingMembers Members loading.\n */\n var renderLoadingMembers = function(header, body, footer, isLoadingMembers) {\n if (isLoadingMembers) {\n hideHeaderContent(header);\n showHeaderPlaceholder(header);\n } else {\n showHeaderContent(header);\n hideHeaderPlaceholder(header);\n }\n };\n\n /**\n * Hide or show loading conversation messages.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Bool} isLoadingFirstMessages Messages loading.\n */\n var renderLoadingFirstMessages = f
unction(header, body, footer, isLoadingFirstMessages) {\n if (isLoadingFirstMessages) {\n hideMessagesContainer(body);\n showContentPlaceholder(body);\n } else {\n showMessagesContainer(body);\n hideContentPlaceholder(body);\n }\n };\n\n /**\n * Hide or show loading more messages.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Bool} isLoading Messages loading.\n */\n var renderLoadingMessages = function(header, body, footer, isLoading) {\n if (isLoading) {\n showMoreMessagesLoadingIcon(body);\n } else {\n hideMoreMessagesLoadingIcon(body);\n }\n };\n\n /**\n * Hide or show the emoji picker.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n *
@param {Object} footer The footer container element.\n * @param {Bool} show Should the emoji picker be visible.\n */\n var renderShowEmojiPicker = function(header, body, footer, show) {\n var container = getEmojiPickerContainer(footer);\n\n if (show) {\n container.removeClass('hidden');\n Aria.unhide(container.get());\n container.find(SELECTORS.EMOJI_PICKER_SEARCH_INPUT).focus();\n } else {\n container.addClass('hidden');\n Aria.hide(container.get());\n }\n };\n\n /**\n * Hide or show the emoji auto complete.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Bool} show Should the emoji picker be visible.\n */\n var renderShowEmojiAutoComplete = function(header, body, footer, show) {\n var container = getEmojiAutoCompleteContainer(footer);\n\n
if (show) {\n container.removeClass('hidden');\n Aria.unhide(container.get());\n } else {\n container.addClass('hidden');\n Aria.hide(container.get());\n }\n };\n\n /**\n * Show a confirmation dialogue\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {String} buttonSelectors Selectors for the buttons to show.\n * @param {String} bodyText Text to show in dialogue.\n * @param {String} headerText Text to show in dialogue header.\n * @param {Bool} canCancel Can this dialogue be cancelled.\n * @param {Bool} skipHeader Skip blanking out the header\n * @param {Bool} showOk Show an 'Okay' button for a dialogue which will close it\n */\n var showConfirmDialogue = function(\n header,\n body,\n footer,\n buttonSelectors,\n bodyText,\
n headerText,\n canCancel,\n skipHeader,\n showOk\n ) {\n var dialogue = getConfirmDialogueContainer(body);\n var buttons = buttonSelectors.map(function(selector) {\n return dialogue.find(selector);\n });\n var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);\n var okayButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_OKAY_BUTTON);\n var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);\n var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);\n\n dialogue.find('button').addClass('hidden');\n\n if (canCancel) {\n cancelButton.removeClass('hidden');\n } else {\n cancelButton.addClass('hidden');\n }\n\n if (showOk) {\n okayButton.removeClass('hidden');\n } else {\n okayButton.addClass('hidden');\n }\n\n if (headerText) {\n // Create the dialogue header.\n dia
logueHeader = $('<h3 class=\"h6\" data-region=\"dialogue-header\"></h3>');\n dialogueHeader.text(headerText);\n // Prepend it to the confirmation body.\n var confirmDialogue = dialogue.find(SELECTORS.CONFIRM_DIALOGUE);\n confirmDialogue.prepend(dialogueHeader);\n } else if (dialogueHeader.length) {\n // Header text is empty but dialogue header is present, so remove it.\n dialogueHeader.remove();\n }\n\n buttons.forEach(function(button) {\n button.removeClass('hidden');\n });\n text.text(bodyText);\n showConfirmDialogueContainer(footer);\n showConfirmDialogueContainer(body);\n\n if (!skipHeader) {\n showConfirmDialogueContainer(header);\n }\n\n dialogue.find(SELECTORS.CAN_RECEIVE_FOCUS).filter(':visible').first().focus();\n };\n\n /**\n * Hide the dialogue\n *\n * @param {Object} header The header container element.\n * @param {Obje
ct} body The body container element.\n * @param {Object} footer The footer container element.\n * @return {Bool} always true.\n */\n var hideConfirmDialogue = function(header, body, footer) {\n var dialogue = getConfirmDialogueContainer(body);\n var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);\n var okayButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_OKAY_BUTTON);\n var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);\n var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);\n\n hideCheckDeleteDialogue(body);\n hideConfirmDialogueContainer(body);\n hideConfirmDialogueContainer(footer);\n hideConfirmDialogueContainer(header);\n dialogue.find('button').addClass('hidden');\n cancelButton.removeClass('hidden');\n okayButton.removeClass('hidden');\n text.text('');\n\n // Remove dialogue header if present.\n if (dialogueHeader.length) {\n
dialogueHeader.remove();\n }\n\n header.find(SELECTORS.CAN_RECEIVE_FOCUS).first().focus();\n return true;\n };\n\n /**\n * Render the confirm block user dialogue.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} user User to block.\n * @return {Object} jQuery promise\n */\n var renderConfirmBlockUser = function(header, body, footer, user) {\n if (user) {\n const username = truncateUsername(user.fullname);\n if (user.canmessageevenifblocked) {\n return Str.get_string('cantblockuser', 'core_message', username)\n .then(function(string) {\n return showConfirmDialogue(header, body, footer, [], string, '', false, false, true);\n });\n } else {\n return Str.get_string('blockuserconfi
rm', 'core_message', username)\n .then(function(string) {\n return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_BLOCK], string, '', true, false);\n });\n }\n } else {\n return hideConfirmDialogue(header, body, footer);\n }\n };\n\n /**\n * Render the confirm unblock user dialogue.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} user User to unblock.\n * @return {Object} jQuery promise\n */\n var renderConfirmUnblockUser = function(header, body, footer, user) {\n if (user) {\n return Str.get_string('unblockuserconfirm', 'core_message', truncateUsername(user.fullname))\n .then(function(string) {\n return showConfirmDialogue(header, body, footer, [SELECTORS.ACTI
ON_CONFIRM_UNBLOCK], string, '', true, false);\n });\n } else {\n return hideConfirmDialogue(header, body, footer);\n }\n };\n\n /**\n * Render the add user as contact dialogue.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} user User to add as contact.\n * @return {Object} jQuery promise\n */\n var renderConfirmAddContact = function(header, body, footer, user) {\n if (user) {\n // Truncate long usernames.\n const userFullName = Truncate.truncate(user.fullname, {\n length: 30,\n words: true,\n ellipsis: '...'\n });\n return Str.get_string('addcontactconfirm', 'core_message', userFullName)\n .then(function(string) {\n return showConfirmDialogue(\n
header,\n body,\n footer,\n [SELECTORS.ACTION_CONFIRM_ADD_CONTACT],\n string,\n '',\n true,\n false\n );\n });\n } else {\n return hideConfirmDialogue(header, body, footer);\n }\n };\n\n /**\n * Render the remove user from contacts dialogue.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} user User to remove from contacts.\n * @return {Object} jQuery promise\n */\n var renderConfirmRemoveContact = function(header, body, footer, user) {\n if (user) {\n return Str.get_string('removecontactconfirm', 'core_message', truncateUsername(user.fullname))\n .then(function(string)
{\n return showConfirmDialogue(\n header,\n body,\n footer,\n [SELECTORS.ACTION_CONFIRM_REMOVE_CONTACT],\n string,\n '',\n true,\n false\n );\n });\n } else {\n return hideConfirmDialogue(header, body, footer);\n }\n };\n\n /**\n * Render the delete selected messages dialogue.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} data If the dialogue should show and checkbox shows to delete message for all users.\n * @return {Object} jQuery promise\n */\n var renderConfirmDeleteSelectedMessages = function(header, body, footer, data) {\n var showmessage = null;\n
if (data.type == CONVERSATION_TYPES.SELF) {\n // Message displayed to self-conversations is slighly different.\n showmessage = 'deleteselectedmessagesconfirmselfconversation';\n } else {\n // This other message should be displayed.\n if (data.canDeleteMessagesForAllUsers) {\n showCheckDeleteDialogue(body);\n showmessage = 'deleteforeveryoneselectedmessagesconfirm';\n } else {\n showmessage = 'deleteselectedmessagesconfirm';\n }\n }\n\n if (data.show) {\n return Str.get_string(showmessage, 'core_message')\n .then(function(string) {\n return showConfirmDialogue(\n header,\n body,\n footer,\n [SELECTORS.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES],\n string,\n '',\n true,\n
false\n );\n });\n } else {\n return hideConfirmDialogue(header, body, footer);\n }\n };\n\n /**\n * Render the confirm delete conversation dialogue.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {int|Null} type The conversation type to be removed.\n * @return {Object} jQuery promise\n */\n var renderConfirmDeleteConversation = function(header, body, footer, type) {\n var showmessage = null;\n if (type == CONVERSATION_TYPES.SELF) {\n // Message displayed to self-conversations is slighly different.\n showmessage = 'deleteallselfconfirm';\n } else if (type) {\n // This other message should be displayed.\n showmessage = 'deleteallconfirm';\n }\n\n if (showmessage) {\n return St
r.get_string(showmessage, 'core_message')\n .then(function(string) {\n return showConfirmDialogue(\n header,\n body,\n footer,\n [SELECTORS.ACTION_CONFIRM_DELETE_CONVERSATION],\n string,\n '',\n true,\n false\n );\n });\n } else {\n return hideConfirmDialogue(header, body, footer);\n }\n };\n\n /**\n * Render the confirm delete conversation dialogue.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} user The other user object.\n * @return {Object} jQuery promise\n */\n var renderConfirmContactRequest = function(header, body, footer, user) {\n if (user
) {\n return Str.get_string('userwouldliketocontactyou', 'core_message', truncateUsername(user.fullname))\n .then(function(string) {\n var buttonSelectors = [\n SELECTORS.ACTION_ACCEPT_CONTACT_REQUEST,\n SELECTORS.ACTION_DECLINE_CONTACT_REQUEST\n ];\n return showConfirmDialogue(header, body, footer, buttonSelectors, string, '', false, true);\n });\n } else {\n return hideConfirmDialogue(header, body, footer);\n }\n };\n\n /**\n * Show the checkbox to allow delete message for all.\n *\n * @param {Object} body The body container element.\n */\n var showCheckDeleteDialogue = function(body) {\n var dialogue = getConfirmDialogueContainer(body);\n var checkboxRegion = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);\n checkboxRegion.removeClass('hidden');\n };\n\n /**\n
* Hide the checkbox to allow delete message for all.\n *\n * @param {Object} body The body container element.\n */\n var hideCheckDeleteDialogue = function(body) {\n var dialogue = getConfirmDialogueContainer(body);\n var checkboxRegion = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);\n var checkbox = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE);\n checkbox.prop('checked', false);\n checkboxRegion.addClass('hidden');\n };\n\n /**\n * Show or hide the block / unblock option in the header dropdown menu.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Bool} isBlocked is user blocked.\n */\n var renderIsBlocked = function(header, body, footer, isBlocked) {\n if (isBlocked) {\n header.find(SELECTORS.ACTION_REQUEST_BLOCK).addClass('hid
den');\n header.find(SELECTORS.ACTION_REQUEST_UNBLOCK).removeClass('hidden');\n } else {\n header.find(SELECTORS.ACTION_REQUEST_BLOCK).removeClass('hidden');\n header.find(SELECTORS.ACTION_REQUEST_UNBLOCK).addClass('hidden');\n }\n };\n\n /**\n * Show or hide the favourite / unfavourite option in the header dropdown menu\n * and the favourite star in the header title.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Bool} state is this conversation a favourite.\n */\n var renderIsFavourite = function(header, body, footer, state) {\n var favouriteIcon = header.find(SELECTORS.FAVOURITE_ICON_CONTAINER);\n var addFavourite = header.find(SELECTORS.ACTION_CONFIRM_FAVOURITE);\n var removeFavourite = header.find(SELECTORS.ACTION_CONFIRM_UNFAVOURITE);\n\n switch (state) {
\n case 'hide':\n favouriteIcon.addClass('hidden');\n addFavourite.addClass('hidden');\n removeFavourite.addClass('hidden');\n break;\n case 'show-add':\n favouriteIcon.addClass('hidden');\n addFavourite.removeClass('hidden');\n removeFavourite.addClass('hidden');\n break;\n case 'show-remove':\n favouriteIcon.removeClass('hidden');\n addFavourite.addClass('hidden');\n removeFavourite.removeClass('hidden');\n break;\n }\n };\n\n /**\n * Show or hide the mute / unmute option in the header dropdown menu\n * and the muted icon in the header title.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {string} state The state of the conv
ersation as defined by the patcher.\n */\n var renderIsMuted = function(header, body, footer, state) {\n var muteIcon = header.find(SELECTORS.MUTED_ICON_CONTAINER);\n var setMuted = header.find(SELECTORS.ACTION_CONFIRM_MUTE);\n var unsetMuted = header.find(SELECTORS.ACTION_CONFIRM_UNMUTE);\n\n switch (state) {\n case 'hide':\n muteIcon.addClass('hidden');\n setMuted.addClass('hidden');\n unsetMuted.addClass('hidden');\n break;\n case 'show-mute':\n muteIcon.addClass('hidden');\n setMuted.removeClass('hidden');\n unsetMuted.addClass('hidden');\n break;\n case 'show-unmute':\n muteIcon.removeClass('hidden');\n setMuted.addClass('hidden');\n unsetMuted.removeClass('hidden');\n break;\n }\n };\n\n /**\n * Show or hide the add / remove user as contact o
ption in the header dropdown menu.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Bool} state the contact state.\n */\n var renderIsContact = function(header, body, footer, state) {\n var addContact = header.find(SELECTORS.ACTION_REQUEST_ADD_CONTACT);\n var removeContact = header.find(SELECTORS.ACTION_REQUEST_REMOVE_CONTACT);\n\n switch (state) {\n case 'pending-contact':\n addContact.addClass('hidden');\n removeContact.addClass('hidden');\n break;\n case 'contact':\n addContact.addClass('hidden');\n removeContact.removeClass('hidden');\n break;\n case 'non-contact':\n addContact.removeClass('hidden');\n removeContact.addClass('hidden');\n break;\n }\n
};\n\n /**\n * Show or hide confirm action from confirm dialogue is loading.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Bool} isLoading confirm action is loading.\n */\n var renderLoadingConfirmAction = function(header, body, footer, isLoading) {\n var dialogue = getConfirmDialogueContainer(body);\n var buttons = dialogue.find('button');\n var buttonText = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_BUTTON_TEXT);\n var loadingIcon = dialogue.find(SELECTORS.LOADING_ICON_CONTAINER);\n\n if (isLoading) {\n buttons.prop('disabled', true);\n buttonText.addClass('hidden');\n loadingIcon.removeClass('hidden');\n } else {\n buttons.prop('disabled', false);\n buttonText.removeClass('hidden');\n loadingIcon.addClass('hidden');\n }\n }
;\n\n /**\n * Show or hide the header and footer content for edit mode.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Bool} inEditMode In edit mode or not.\n */\n var renderInEditMode = function(header, body, footer, inEditMode) {\n var messages = null;\n\n if (inEditMode) {\n messages = body.find(SELECTORS.MESSAGE_NOT_SELECTED);\n messages.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).removeClass('hidden');\n hideHeaderContent(header);\n showHeaderEditMode(header);\n } else {\n messages = getMessagesContainer(body);\n messages.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).addClass('hidden');\n messages.find(SELECTORS.MESSAGE_SELECTED_ICON).addClass('hidden');\n showHeaderContent(header);\n hideHeaderEditMode(header);\n }\n
};\n\n /**\n * Select or unselect messages.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} data The messages to select or unselect.\n */\n var renderSelectedMessages = function(header, body, footer, data) {\n var hasSelectedMessages = data.count > 0;\n\n if (data.add.length) {\n data.add.forEach(function(messageId) {\n var message = getMessageElement(body, messageId);\n message.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).addClass('hidden');\n message.find(SELECTORS.MESSAGE_SELECTED_ICON).removeClass('hidden');\n message.attr('aria-checked', true);\n });\n }\n\n if (data.remove.length) {\n data.remove.forEach(function(messageId) {\n var message = getMessageElement(body, messageId);\n\n
if (hasSelectedMessages) {\n message.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).removeClass('hidden');\n }\n\n message.find(SELECTORS.MESSAGE_SELECTED_ICON).addClass('hidden');\n message.attr('aria-checked', false);\n });\n }\n\n setMessagesSelectedCount(header, data.count);\n };\n\n /**\n * Show or hide the require add contact panel.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} data Whether the user has to be added a a contact.\n * @return {Object} jQuery promise\n */\n var renderRequireAddContact = function(header, body, footer, data) {\n if (data.show && !data.hasMessages) {\n return Str.get_strings([\n {\n key: 'requirecontacttomessage',\n component:
'core_message',\n param: data.user.fullname\n },\n {\n key: 'isnotinyourcontacts',\n component: 'core_message',\n param: data.user.fullname\n }\n ])\n .then(function(strings) {\n var title = strings[1];\n var text = strings[0];\n return showConfirmDialogue(\n header,\n body,\n footer,\n [SELECTORS.ACTION_REQUEST_ADD_CONTACT],\n text,\n title,\n false,\n true\n );\n });\n } else {\n return hideConfirmDialogue(header, body, footer);\n }\n };\n\n /**\n * Show or hide the self-conversation message.\n *\n * @param {Object} he
ader The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {Object} displayMessage should the message be displayed?.\n * @return {Object|true} jQuery promise\n */\n var renderSelfConversationMessage = function(header, body, footer, displayMessage) {\n var container = getSelfConversationMessageContainer(body);\n if (displayMessage) {\n container.removeClass('hidden');\n } else {\n container.addClass('hidden');\n }\n return true;\n };\n\n /**\n * Show or hide the require add contact panel.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @param {String} userFullName Full name of the other user.\n * @return {Object|true} jQuery promise\n */\n var renderContactRequestSent =
function(header, body, footer, userFullName) {\n var container = getContactRequestSentContainer(body);\n if (userFullName) {\n return Str.get_string('yourcontactrequestpending', 'core_message', truncateUsername(userFullName))\n .then(function(string) {\n container.find(SELECTORS.TEXT).text(string);\n container.removeClass('hidden');\n return string;\n });\n } else {\n container.addClass('hidden');\n return true;\n }\n };\n\n /**\n * Reset the UI to the initial state.\n *\n * @param {Object} header The header container element.\n * @param {Object} body The body container element.\n * @param {Object} footer The footer container element.\n * @return {Bool}\n */\n var renderReset = function(header, body, footer) {\n hideConfirmDialogue(header, body, footer);\n hideContactRequestSentContainer(body);\n hideSelfC
onversationMessageContainer(body);\n hideAllHeaderElements(header);\n showHeaderPlaceholder(header);\n hideAllFooterElements(footer);\n showFooterPlaceholder(footer);\n return true;\n };\n\n var render = function(header, body, footer, patch) {\n var configs = [\n {\n // Resetting the UI needs to come first, if it's required.\n reset: renderReset\n },\n {\n // Any async rendering (stuff that requires templates, strings etc) should\n // go in here.\n conversation: renderConversation,\n header: renderHeader,\n footer: renderFooter,\n confirmBlockUser: renderConfirmBlockUser,\n confirmUnblockUser: renderConfirmUnblockUser,\n confirmAddContact: renderConfirmAddContact,\n confirmRemoveContact: renderConfirmRemoveContact,\n confirmDeleteSelectedMessages: rend
erConfirmDeleteSelectedMessages,\n confirmDeleteConversation: renderConfirmDeleteConversation,\n confirmContactRequest: renderConfirmContactRequest,\n requireAddContact: renderRequireAddContact,\n selfConversationMessage: renderSelfConversationMessage,\n contactRequestSent: renderContactRequestSent\n },\n {\n loadingMembers: renderLoadingMembers,\n loadingFirstMessages: renderLoadingFirstMessages,\n loadingMessages: renderLoadingMessages,\n isBlocked: renderIsBlocked,\n isContact: renderIsContact,\n isFavourite: renderIsFavourite,\n isMuted: renderIsMuted,\n loadingConfirmAction: renderLoadingConfirmAction,\n inEditMode: renderInEditMode,\n showEmojiPicker: renderShowEmojiPicker,\n showEmojiAutoComplete: renderShowEmojiAutoComplete,\n },\n
{\n // Scrolling should be last to make sure everything\n // on the page is visible.\n scrollToMessage: renderScrollToMessage,\n selectedMessages: renderSelectedMessages\n }\n ];\n // Helper function to process each of the configs above.\n var processConfig = function(config) {\n var results = [];\n\n for (var key in patch) {\n if (config.hasOwnProperty(key)) {\n var renderFunc = config[key];\n var patchValue = patch[key];\n results.push(renderFunc(header, body, footer, patchValue));\n }\n }\n\n return results;\n };\n\n // The first config is special because it resets the UI.\n var renderingPromises = processConfig(configs[0]);\n // The second config is special because it contains async rendering.\n renderingPromises = renderingPromises.concat(
processConfig(configs[1]));\n\n // Wait for the async rendering to complete before processing the\n // rest of the configs, in order.\n return $.when.apply($, renderingPromises)\n .then(function() {\n for (var i = 2; i < configs.length; i++) {\n processConfig(configs[i]);\n }\n\n return;\n })\n .catch(Notification.exception);\n };\n\n /**\n * Truncate long usernames.\n *\n * @param {String} username Text to truncate.\n * @return {String} Truncated string.\n */\n var truncateUsername = function(username) {\n return Truncate.truncate(username, {\n length: 30,\n words: true,\n ellipsis: '...'\n });\n };\n\n return {\n render: render,\n };\n});\n"],"names":["define","$","Notification","Str","Templates","UserDate","Constants","Aria","Truncate","SELECTORS","TEMPLATES","CONVERSATION_TYPES","getMessagesContain
er","body","find","CONTENT_MESSAGES_CONTAINER","getSelfConversationMessageContainer","SELF_CONVERSATION_MESSAGE_CONTAINER","getContactRequestSentContainer","CONTACT_REQUEST_SENT_MESSAGE_CONTAINER","getFooterContentContainer","footer","CONTENT_MESSAGES_FOOTER_CONTAINER","getFooterEditModeContainer","CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER","getFooterPlaceholderContainer","PLACEHOLDER_CONTAINER","showFooterPlaceholder","removeClass","getFooterRequireContactContainer","CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER","getFooterRequireUnblockContainer","CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER","getFooterUnableToMessageContainer","CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER","hideAllFooterElements","addClass","hideFooterContent","hideFooterEditMode","hideFooterPlaceholder","hideFooterRequireContact","hideFooterRequireUnblock","hideFooterUnableToMessage","getContentPlaceholderContainer","CONTENT_PLACEHOLDER_CONTAINER","getHeaderContent","header","HEADER","showHeaderContent","hideHeaderConte
nt","getHeaderEditMode","HEADER_EDIT_MODE","hideHeaderEditMode","getHeaderPlaceholderContainer","HEADER_PLACEHOLDER_CONTAINER","showHeaderPlaceholder","hideHeaderPlaceholder","getMessageElement","messageId","getDayElement","dayTimeCreated","getMoreMessagesLoadingIconContainer","MORE_MESSAGES_LOADING_ICON_CONTAINER","getConfirmDialogueContainer","root","CONFIRM_DIALOGUE_CONTAINER","showConfirmDialogueContainer","container","siblings","hide","get","attr","hideConfirmDialogueContainer","unhide","removeAttr","formatMessagesForTemplate","messages","datesCache","map","message","id","isread","isRead","fromloggedinuser","fromLoggedInUser","userfrom","userFrom","text","formattedtime","timeCreated","renderConversation","data","renderingPromises","hasAddDays","days","add","length","hasAddMessages","hasUpdateMessages","update","timestampsToFormat","datesCachePromise","Deferred","resolve","promise","concat","reduce","carry","day","value","timestamps","push","before","after","get_string","then","format","requests","timest
amp","formattedTimes","index","messagesContainer","daysRenderPromises","timestampDate","Date","render","DAY","currentyear","getFullYear","when","apply","forEach","html","element","insertBefore","append","catch","renderAddDays","messagesData","formattedMessages","MESSAGES","messageList","messageHtml","DAY_MESSAGES_CONTAINER","renderAddMessages","formattedTime","LOADING_ICON_CONTAINER","TIME_CREATED","sendState","loading","time","retry","RETRY_SEND","TEXT_CONTAINER","errorMessage","messageContainer","ERROR_MESSAGE_CONTAINER","ERROR_MESSAGE","renderUpdateMessages","remove","renderRemoveDays","renderRemoveMessages","renderHeader","headerContainer","template","HEADER_PUBLIC","context","showrouteback","type","PRIVATE","showControls","HEADER_PRIVATE","HEADER_PRIVATE_NO_CONTROLS","SELF","HEADER_SELF","js","replaceNodeContents","renderFooter","get_strings","key","component","param","user","fullname","strings","title","footerContainer","TITLE","TEXT","showFooterRequireContact","showFooterEditMode","showFooterContent",
"showFooterRequireUnblock","showFooterUnableToMessage","renderScrollToMessage","position","scrollTop","top","renderLoadingMembers","isLoadingMembers","renderLoadingFirstMessages","isLoadingFirstMessages","hideMessagesContainer","showContentPlaceholder","showMessagesContainer","hideContentPlaceholder","renderLoadingMessages","isLoading","showMoreMessagesLoadingIcon","hideMoreMessagesLoadingIcon","renderShowEmojiPicker","show","EMOJI_PICKER_CONTAINER","getEmojiPickerContainer","EMOJI_PICKER_SEARCH_INPUT","focus","renderShowEmojiAutoComplete","EMOJI_AUTO_COMPLETE_CONTAINER","getEmojiAutoCompleteContainer","showConfirmDialogue","buttonSelectors","bodyText","headerText","canCancel","skipHeader","showOk","dialogue","buttons","selector","cancelButton","CONFIRM_DIALOGUE_CANCEL_BUTTON","okayButton","CONFIRM_DIALOGUE_OKAY_BUTTON","CONFIRM_DIALOGUE_TEXT","dialogueHeader","CONFIRM_DIALOGUE_HEADER","CONFIRM_DIALOGUE","prepend","button","CAN_RECEIVE_FOCUS","filter","first","hideConfirmDialogue","hideCheckDeleteDialogue","
renderConfirmBlockUser","username","truncateUsername","canmessageevenifblocked","string","ACTION_CONFIRM_BLOCK","renderConfirmUnblockUser","ACTION_CONFIRM_UNBLOCK","renderConfirmAddContact","userFullName","truncate","words","ellipsis","ACTION_CONFIRM_ADD_CONTACT","renderConfirmRemoveContact","ACTION_CONFIRM_REMOVE_CONTACT","renderConfirmDeleteSelectedMessages","showmessage","canDeleteMessagesForAllUsers","showCheckDeleteDialogue","ACTION_CONFIRM_DELETE_SELECTED_MESSAGES","renderConfirmDeleteConversation","ACTION_CONFIRM_DELETE_CONVERSATION","renderConfirmContactRequest","ACTION_ACCEPT_CONTACT_REQUEST","ACTION_DECLINE_CONTACT_REQUEST","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER","checkboxRegion","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE","prop","renderIsBlocked","isBlocked","ACTION_REQUEST_BLOCK","ACTION_REQUEST_UNBLOCK","renderIsFavourite","state","favouriteIcon","FAVOURITE_ICON_CONTAINER","addFavourite","ACTION_CONFIRM_FAVOURITE","removeFavourite","ACTION_CONFIRM_UNFAVOURITE","renderIsMuted","muteIcon","MUT
ED_ICON_CONTAINER","setMuted","ACTION_CONFIRM_MUTE","unsetMuted","ACTION_CONFIRM_UNMUTE","renderIsContact","addContact","ACTION_REQUEST_ADD_CONTACT","removeContact","ACTION_REQUEST_REMOVE_CONTACT","renderLoadingConfirmAction","buttonText","CONFIRM_DIALOGUE_BUTTON_TEXT","loadingIcon","renderInEditMode","inEditMode","MESSAGE_NOT_SELECTED","MESSAGE_NOT_SELECTED_ICON","showHeaderEditMode","MESSAGE_SELECTED_ICON","renderSelectedMessages","hasSelectedMessages","count","MESSAGES_SELECTED_COUNT","setMessagesSelectedCount","renderRequireAddContact","hasMessages","renderSelfConversationMessage","displayMessage","renderContactRequestSent","renderReset","hideContactRequestSentContainer","hideSelfConversationMessageContainer","hideAllHeaderElements","patch","configs","reset","conversation","confirmBlockUser","confirmUnblockUser","confirmAddContact","confirmRemoveContact","confirmDeleteSelectedMessages","confirmDeleteConversation","confirmContactRequest","requireAddContact","selfConversationMessage","contactRequestSent","
loadingMembers","loadingFirstMessages","loadingMessages","isContact","isFavourite","isMuted","loadingConfirmAction","showEmojiPicker","showEmojiAutoComplete","scrollToMessage","selectedMessages","processConfig","config","results","hasOwnProperty","renderFunc","patchValue","i","exception"],"mappings":"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"}