AutorÃa | 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],\nfunction(\n $,\n Notification,\n Str,\n Templates,\n UserDate,\n Constants,\n Aria\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 element.\n */\n var getMessagesCon
tainer = 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 element.\n * @return {Object} The foo
ter 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(footer) {\n return footer.find(SEL
ECTORS.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 dial
ogue.\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 contact 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 container element.\n *\n * @para
m {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 hideAllFooterElements = function(footer) {\n h
ideFooterContent(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 = func
tion(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} header Conversation header container el
ement.\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(SELECTOR
S.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 c
ontainer 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(b
ody, 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 hideMoreMessagesLoadingIcon = 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 * @param {Object} root The container elemen
t 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 formatted 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 {Promise} 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 eleme
nt = 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(d
ata) {\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 e
lement.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.removeClass('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.addClass('hidden');\n A
ria.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 the formatted timestamps for each messa
ge 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.concat(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 timestampsToFormat.reduce(function(carry, ti
mestamp, 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, data.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.SELF) {\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 showFooterContent(footer);\n case 'un
block':\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 = function(header, body, footer, isLoadin
gFirstMessages) {\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 cont
ainer 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 conta
iner.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 canCance
l,\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 dialogueHeader = $('<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 {Object} 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 if (user.canmessageevenifblocked) {\n return Str.get_string('cantblockuser', 'core_message', user.fullname)\n .then(function(string) {\n return showConfirmDialogue(header, body, footer, [], string, '', false, false, true);\n });\n } else {\n return Str.get_string('blockuserconfirm', 'core_message', user.fullname)\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', user.fullname)\n .then(function(string) {\n return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_UNBLOCK], string, '', true, false);\n });\n } else {\n return hid
eConfirmDialogue(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 return Str.get_string('addcontactconfirm', 'core_message', user.fullname)\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', 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 sh
owCheckDeleteDialogue(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 conta
iner 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 Str.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 {Bool} 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', 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('hidden');\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 removeFav
ourite.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 conversation 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 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} state the contact state.\n */\n var renderIsContact = function(header, body, footer, state) {\n var addCont
act = 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 renderLoadingConf
irmAction = 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} header 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, displayMessag
e) {\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 {Object} 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', userFullName)\n .then(function(string) {\n container.find(SELECTORS.TEXT).text(string);\n con
tainer.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 hideSelfConversationMessageContainer(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: renderConfirmDeleteSelectedMessages,\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 return {\n render: render,\n };\n});\n"],"names":["define","$","Notification","Str","Templates","UserDate","Constants","Aria","SELECTORS","TEMPLATES","CONVERSATION_TYPES","getMessagesContainer","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","hideFo
oterContent","hideFooterEditMode","hideFooterPlaceholder","hideFooterRequireContact","hideFooterRequireUnblock","hideFooterUnableToMessage","getContentPlaceholderContainer","CONTENT_PLACEHOLDER_CONTAINER","getHeaderContent","header","HEADER","showHeaderContent","hideHeaderContent","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","timestamp","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","canc
elButton","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","canmessageevenifblocked","string","ACTION_CONFIRM_BLOCK","renderConfirmUnblockUser","ACTION_CONFIRM_UNBLOCK","renderConfirmAddContact","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_REQUE
ST_UNBLOCK","renderIsFavourite","state","favouriteIcon","FAVOURITE_ICON_CONTAINER","addFavourite","ACTION_CONFIRM_FAVOURITE","removeFavourite","ACTION_CONFIRM_UNFAVOURITE","renderIsMuted","muteIcon","MUTED_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","userFullName","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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"}