MDL-65896 admin: add admin setting to show emoji picker
[moodle.git] / message / amd / build / message_drawer_view_conversation.min.js.map
1 {"version":3,"sources":["../src/message_drawer_view_conversation.js"],"names":["define","$","AutoRows","BackOffTimer","CustomEvents","Notification","PubSub","Str","Repository","MessageDrawerEvents","Constants","Patcher","Renderer","StateManager","MessageDrawerRouter","MessageDrawerRoutes","initialiseEmojiAutoComplete","initialiseEmojiPicker","stateCache","viewState","loadedAllMessages","messagesOffset","newMessagesPollTimer","isRendering","renderBuffer","isResetting","isSendingMessage","sendMessageBuffer","render","renderers","NEWEST_FIRST","NEWEST_MESSAGES_FIRST","LOAD_MESSAGE_LIMIT","MILLISECONDS_IN_SEC","SELECTORS","CONVERSATION_TYPES","getOtherUserId","type","PUBLIC","loggedInUserId","SELF","otherUserIds","Object","keys","members","filter","userId","length","getCachedPrivateConversationIdFromUserId","reduce","carry","id","state","getLoggedInUserProfile","body","parseInt","attr","fullname","profileimageurl","profileimageurlsmall","isonline","showonlinestatus","isblocked","iscontact","isdeleted","canmessage","canmessageevenifblocked","requirescontact","contactrequests","getMessagesOffset","setMessagesOffset","value","hasLoadedAllMessages","setLoadedAllMessages","getMessagesContainer","find","MESSAGES_CONTAINER","formatConversationForEvent","name","subname","imageUrl","isFavourite","isMuted","totalMemberCount","messages","map","message","extend","formattedMember","request","loadEmptyPrivateConversation","loggedInUserProfile","otherUserId","conversationType","PRIVATE","newState","setLoadingMembers","setLoadingMessages","getMemberInfo","then","profiles","Error","profile","addMembers","setName","setType","setImageUrl","setTotalMemberCount","catch","error","exception","updateStateFromConversation","conversation","otherUser","otherUsers","member","imageurl","setSubname","membercount","setIsFavourite","isfavourite","setIsMuted","ismuted","addMessages","setCanDeleteMessagesForAllUsers","candeletemessagesforallusers","loadNewConversation","conversationId","messageLimit","messageOffset","newestFirst","getConversation","slice","hasLoggedInUser","concat","markConversationAsRead","loadExistingConversation","messageCount","hasLoadedEnoughMessages","renderPromise","loadMessages","limit","offset","ignoreList","timeFrom","getMessages","result","indexOf","membersToAdd","getLoadNewMessagesCallback","mostRecentMessage","lastTimeCreated","timeCreated","ignoreMessageIds","i","push","restart","publish","CONVERSATION_NEW_LAST_MESSAGE","Deferred","resolve","promise","markAllConversationMessagesAsRead","markMessagesAsRead","CONVERSATION_READ","requestBlockUser","cancelRequest","addPendingBlockUsersById","blockUser","setLoadingConfirmAction","removePendingBlockUsersById","CONTACT_BLOCKED","requestUnblockUser","addPendingUnblockUsersById","unblockUser","removePendingUnblockUsersById","CONTACT_UNBLOCKED","requestRemoveContact","addPendingRemoveContactsById","removeContact","deleteContacts","removePendingRemoveContactsById","CONTACT_REMOVED","requestAddContact","addPendingAddContactsById","addContact","createContactRequest","response","warnings","removePendingAddContactsById","addContactRequests","setFavourite","setFavouriteConversations","CONVERSATION_SET_FAVOURITE","unsetFavourite","unsetFavouriteConversations","CONVERSATION_UNSET_FAVOURITE","setMuted","setMutedConversations","CONVERSATION_SET_MUTED","unsetMuted","unsetMutedConversations","CONVERSATION_UNSET_MUTED","requestDeleteSelectedMessages","selectedMessageIds","addPendingDeleteMessagesById","deleteSelectedMessages","messageIds","pendingDeleteMessageIds","sentMessages","sendState","deleteMessagesPromise","sentMessageIds","deleteMessagesForAllUsers","deleteMessages","removeMessagesById","removePendingDeleteMessagesById","removeSelectedMessagesById","setDeleteMessagesForAllUsers","prevLastMessage","newLastMessage","CONVERSATION_DELETED","requestDeleteConversation","setPendingDeleteConversation","deleteConversation","removeMessages","acceptContactRequest","requests","requesteduserid","removeContactRequests","CONTACT_ADDED","CONTACT_REQUEST_ACCEPTED","declineContactRequest","CONTACT_REQUEST_DECLINED","processSendMessageBuffer","messagesToSend","newConversationId","messagesText","text","sendMessagePromise","newCanDeleteMessagesForAllUsers","sendMessagesToUser","conversationid","sendMessagesToConversation","newMessageIds","data","selectedToRemove","selectedToAdd","forEach","oldMessage","index","newMessage","updateMessages","setMessagesSendSuccessById","addSelectedMessagesById","setId","resetMessagePollTimer","CONVERSATION_CREATED","e","errorMessage","get_string","handleFailedMessages","setMessagesSendFailById","finalError","sendMessage","Date","now","useridfrom","timecreated","retrySendMessage","setMessagesSendPendingById","toggleSelectMessage","messageId","cancelEditMode","processRenderBuffer","header","footer","renderable","shift","renderPromises","renderFunc","patch","when","apply","deferred","reject","generateRenderFunction","isNewConversation","rendererFunc","initialState","buildInitialState","midnight","syncPatch","buildPatch","generateConfirmActionHandler","actionCallback","loadingConfirmAction","originalEvent","preventDefault","handleSendMessage","target","footerContainer","closest","FOOTER_CONTAINER","textArea","MESSAGE_TEXT_AREA","val","trim","focus","handleSelectMessage","selection","window","getSelection","toString","is","element","MESSAGE","handleRetrySendMessage","stopPropagation","handleCancelEditMode","generateHandleViewContact","namespace","go","VIEW_CONTACT","handleSetFavourite","handleUnsetFavourite","handleSetMuted","handleUnsetMuted","handleDeleteMessagesForAllUsersToggle","newValue","prop","generateHandleViewGroupInfo","VIEW_GROUP_INFO","handleToggleEmojiPicker","setShowEmojiPicker","showEmojiPicker","handleCloseEmojiPicker","EMOJI_PICKER_CONTAINER","TOGGLE_EMOJI_PICKER_BUTTON","registerEventListeners","isLoadingMoreMessages","messagesContainer","emojiPickerElement","EMOJI_PICKER","emojiAutoCompleteContainer","EMOJI_AUTO_COMPLETE_CONTAINER","messageTextArea","headerActivateHandlers","ACTION_REQUEST_BLOCK","ACTION_REQUEST_UNBLOCK","ACTION_REQUEST_ADD_CONTACT","ACTION_REQUEST_REMOVE_CONTACT","ACTION_REQUEST_DELETE_CONVERSATION","ACTION_CANCEL_EDIT_MODE","ACTION_VIEW_CONTACT","ACTION_VIEW_GROUP_INFO","ACTION_CONFIRM_FAVOURITE","ACTION_CONFIRM_MUTE","ACTION_CONFIRM_UNFAVOURITE","ACTION_CONFIRM_UNMUTE","bodyActivateHandlers","ACTION_CANCEL_CONFIRM","ACTION_CONFIRM_BLOCK","ACTION_CONFIRM_UNBLOCK","ACTION_CONFIRM_ADD_CONTACT","ACTION_CONFIRM_REMOVE_CONTACT","ACTION_CONFIRM_DELETE_SELECTED_MESSAGES","ACTION_CONFIRM_DELETE_CONVERSATION","ACTION_OKAY_CONFIRM","ACTION_ACCEPT_CONTACT_REQUEST","ACTION_DECLINE_CONTACT_REQUEST","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE","RETRY_SEND","footerActivateHandlers","SEND_MESSAGE_BUTTON","ACTION_REQUEST_DELETE_SELECTED_MESSAGES","init","hasSuggestions","setShowEmojiAutoComplete","emoji","cursorPos","currentText","textBefore","substring","replace","textAfter","events","activate","enter","escape","scrollTop","scrollLock","on","hasMembers","handler","selector","handlerFunction","enterToSend","document","subscribe","ROUTE_CHANGED","newRouteData","route","VIEW_CONVERSATION","stop","getIncrementalCallback","messagePollMin","messagePollMax","messagePollAfterMax","start","resetState","resetNoConversation","resetNoConversationPromise","getConversationBetweenUsers","getSelfConversation","resetByConversation","resetById","cache","show","conversationOrId","action","isNaN","CAN_RECEIVE_FOCUS","first","currentOtherUserId","description"],"mappings":"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","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 * Controls the conversation page in the message drawer.\n *\n * This function handles all of the user actions that the user can take\n * when interacting with the conversation page.\n *\n * It maintains a view state which is a data representation of the view\n * and only operates on that data.\n *\n * The view state is immutable and should never be modified directly. Instead\n * all changes to the view state should be done using the StateManager which\n * will generate a new version of the view state with the requested changes.\n *\n * After any changes to the view state the module will call the render function\n * to ask the renderer to update the UI.\n *\n * General rules for this module:\n * 1.) Never modify viewState directly. All changes should be via the StateManager.\n * 2.) Call render() with the new state when you want to update the UI\n * 3.) Never modify the UI directly in this module. This module is only concerned\n *     with the data in the view state.\n *\n * The general flow for a user interaction will be something like:\n * User interaction: User clicks \"confirm block\" button to block the other user\n *      1.) This module is hears the click\n *      2.) This module sends a request to the server to block the user\n *      3.) The server responds with the new user profile\n *      4.) This module generates a new state using the StateManager with the updated\n *          user profile.\n *      5.) This module asks the Patcher to generate a patch from the current state and\n *          the newly generated state. This patch tells the renderer what has changed\n *          between the states.\n *      6.) This module gives the Renderer the generated patch. The renderer updates\n *          the UI with changes according to the patch.\n *\n * @module     core_message/message_drawer_view_conversation\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/auto_rows',\n    'core/backoff_timer',\n    'core/custom_interaction_events',\n    'core/notification',\n    'core/pubsub',\n    'core/str',\n    'core_message/message_repository',\n    'core_message/message_drawer_events',\n    'core_message/message_drawer_view_conversation_constants',\n    'core_message/message_drawer_view_conversation_patcher',\n    'core_message/message_drawer_view_conversation_renderer',\n    'core_message/message_drawer_view_conversation_state_manager',\n    'core_message/message_drawer_router',\n    'core_message/message_drawer_routes',\n    'core/emoji/auto_complete',\n    'core/emoji/picker'\n],\nfunction(\n    $,\n    AutoRows,\n    BackOffTimer,\n    CustomEvents,\n    Notification,\n    PubSub,\n    Str,\n    Repository,\n    MessageDrawerEvents,\n    Constants,\n    Patcher,\n    Renderer,\n    StateManager,\n    MessageDrawerRouter,\n    MessageDrawerRoutes,\n    initialiseEmojiAutoComplete,\n    initialiseEmojiPicker\n) {\n\n    // Contains a cache of all view states that have been loaded so far\n    // which saves us having to reload stuff with network requests when\n    // switching between conversations.\n    var stateCache = {};\n    // The current data representation of the view.\n    var viewState = null;\n    var loadedAllMessages = false;\n    var messagesOffset = 0;\n    var newMessagesPollTimer = null;\n    var isRendering = false;\n    var renderBuffer = [];\n    // If the UI is currently resetting.\n    var isResetting = true;\n    // If the UI is currently sending a message.\n    var isSendingMessage = false;\n    // A buffer of messages to send.\n    var sendMessageBuffer = [];\n    // These functions which will be generated when this module is\n    // first called. See generateRenderFunction for details.\n    var render = null;\n    // The list of renderers that have been registered to render\n    // this conversation. See generateRenderFunction for details.\n    var renderers = [];\n\n    var NEWEST_FIRST = Constants.NEWEST_MESSAGES_FIRST;\n    var LOAD_MESSAGE_LIMIT = Constants.LOAD_MESSAGE_LIMIT;\n    var MILLISECONDS_IN_SEC = Constants.MILLISECONDS_IN_SEC;\n    var SELECTORS = Constants.SELECTORS;\n    var CONVERSATION_TYPES = Constants.CONVERSATION_TYPES;\n\n    /**\n     * Get the other user userid.\n     *\n     * @return {Number} Userid.\n     */\n    var getOtherUserId = function() {\n        if (!viewState || viewState.type == CONVERSATION_TYPES.PUBLIC) {\n            return null;\n        }\n\n        var loggedInUserId = viewState.loggedInUserId;\n        if (viewState.type == CONVERSATION_TYPES.SELF) {\n            // It's a self-conversation, so the other user is the one logged in.\n            return loggedInUserId;\n        }\n\n        var otherUserIds = Object.keys(viewState.members).filter(function(userId) {\n            return loggedInUserId != userId;\n        });\n\n        return otherUserIds.length ? otherUserIds[0] : null;\n    };\n\n    /**\n     * Search the cache to see if we've already loaded a private conversation\n     * with the given user id.\n     *\n     * @param {Number} userId The id of the other user.\n     * @return {Number|null} Conversation id.\n     */\n    var getCachedPrivateConversationIdFromUserId = function(userId) {\n        return Object.keys(stateCache).reduce(function(carry, id) {\n            if (!carry) {\n                var state = stateCache[id].state;\n\n                if (state.type != CONVERSATION_TYPES.PUBLIC) {\n                    if (userId in state.members) {\n                        // We've found a cached conversation for this user!\n                        carry = state.id;\n                    }\n                }\n            }\n\n            return carry;\n        }, null);\n    };\n\n    /**\n     * Get profile info for logged in user.\n     *\n     * @param {Object} body Conversation body container element.\n     * @return {Object}\n     */\n    var getLoggedInUserProfile = function(body) {\n        return {\n            id: parseInt(body.attr('data-user-id'), 10),\n            fullname: null,\n            profileimageurl: null,\n            profileimageurlsmall: null,\n            isonline:  null,\n            showonlinestatus: null,\n            isblocked: null,\n            iscontact: null,\n            isdeleted: null,\n            canmessage: null,\n            canmessageevenifblocked: null,\n            requirescontact: null,\n            contactrequests: []\n        };\n    };\n\n    /**\n     * Get the messages offset value to load more messages.\n     *\n     * @return {Number}\n     */\n    var getMessagesOffset = function() {\n        return messagesOffset;\n    };\n\n    /**\n     * Set the messages offset value for loading more messages.\n     *\n     * @param {Number} value The offset value\n     */\n    var setMessagesOffset = function(value) {\n        messagesOffset = value;\n        stateCache[viewState.id].messagesOffset = value;\n    };\n\n    /**\n     * Check if all messages have been loaded.\n     *\n     * @return {Bool}\n     */\n    var hasLoadedAllMessages = function() {\n        return loadedAllMessages;\n    };\n\n    /**\n     * Set whether all messages have been loaded or not.\n     *\n     * @param {Bool} value If all messages have been loaded.\n     */\n    var setLoadedAllMessages = function(value) {\n        loadedAllMessages = value;\n        stateCache[viewState.id].loadedAllMessages = value;\n    };\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 getMessagesContainer = function(body) {\n        return body.find(SELECTORS.MESSAGES_CONTAINER);\n    };\n\n    /**\n     * Reformat the conversation for an event payload.\n     *\n     * @param  {Object} state The view state.\n     * @return {Object} New formatted conversation.\n     */\n    var formatConversationForEvent = function(state) {\n        return {\n            id: state.id,\n            name: state.name,\n            subname: state.subname,\n            imageUrl: state.imageUrl,\n            isFavourite: state.isFavourite,\n            isMuted: state.isMuted,\n            type: state.type,\n            totalMemberCount: state.totalMemberCount,\n            loggedInUserId: state.loggedInUserId,\n            messages: state.messages.map(function(message) {\n                return $.extend({}, message);\n            }),\n            members: Object.keys(state.members).map(function(id) {\n                var formattedMember = $.extend({}, state.members[id]);\n                formattedMember.contactrequests = state.members[id].contactrequests.map(function(request) {\n                    return $.extend({}, request);\n                });\n                return formattedMember;\n            })\n        };\n    };\n\n    /**\n     * Load up an empty private conversation between the logged in user and the\n     * other user. Sets all of the conversation details based on the other user.\n     *\n     * A conversation isn't created until the user sends the first message.\n     *\n     * @param  {Object} loggedInUserProfile The logged in user profile.\n     * @param  {Number} otherUserId The other user id.\n     * @return {Object} Profile returned from repository.\n     */\n    var loadEmptyPrivateConversation = function(loggedInUserProfile, otherUserId) {\n        var loggedInUserId = loggedInUserProfile.id;\n        // If the other user id is the same as the logged in user then this is a self\n        // conversation.\n        var conversationType = loggedInUserId == otherUserId ? CONVERSATION_TYPES.SELF : CONVERSATION_TYPES.PRIVATE;\n        var newState = StateManager.setLoadingMembers(viewState, true);\n        newState = StateManager.setLoadingMessages(newState, true);\n        render(newState);\n\n        return Repository.getMemberInfo(loggedInUserId, [otherUserId], true, true)\n            .then(function(profiles) {\n                if (profiles.length) {\n                    return profiles[0];\n                } else {\n                    throw new Error('Unable to load other user profile');\n                }\n            })\n            .then(function(profile) {\n                // If the conversation is a self conversation then the profile loaded is the\n                // logged in user so only add that to the members array.\n                var members = conversationType == CONVERSATION_TYPES.SELF ? [profile] : [profile, loggedInUserProfile];\n                var newState = StateManager.addMembers(viewState, members);\n                newState = StateManager.setLoadingMembers(newState, false);\n                newState = StateManager.setLoadingMessages(newState, false);\n                newState = StateManager.setName(newState, profile.fullname);\n                newState = StateManager.setType(newState, conversationType);\n                newState = StateManager.setImageUrl(newState, profile.profileimageurl);\n                newState = StateManager.setTotalMemberCount(newState, members.length);\n                render(newState);\n                return profile;\n            })\n            .catch(function(error) {\n                var newState = StateManager.setLoadingMembers(viewState, false);\n                render(newState);\n                Notification.exception(error);\n            });\n    };\n\n    /**\n     * Create a new state from a conversation object.\n     *\n     * @param {Object} conversation The conversation object.\n     * @param {Number} loggedInUserId The logged in user id.\n     * @return {Object} new state.\n     */\n    var updateStateFromConversation = function(conversation, loggedInUserId) {\n        var otherUser = null;\n        if (conversation.type == CONVERSATION_TYPES.PRIVATE) {\n            // For private conversations, remove current logged in user from the members list to get the other user.\n            var otherUsers = conversation.members.filter(function(member) {\n                return member.id != loggedInUserId;\n            });\n            otherUser = otherUsers.length ? otherUsers[0] : null;\n        } else if (conversation.type == CONVERSATION_TYPES.SELF) {\n            // Self-conversations have only one member.\n            otherUser = conversation.members[0];\n        }\n\n        var name = conversation.name;\n        var imageUrl = conversation.imageurl;\n\n        if (conversation.type != CONVERSATION_TYPES.PUBLIC) {\n            name = name || otherUser ? otherUser.fullname : '';\n            imageUrl = imageUrl || otherUser ? otherUser.profileimageurl : '';\n        }\n\n        var newState = StateManager.addMembers(viewState, conversation.members);\n        newState = StateManager.setName(newState, name);\n        newState = StateManager.setSubname(newState, conversation.subname);\n        newState = StateManager.setType(newState, conversation.type);\n        newState = StateManager.setImageUrl(newState, imageUrl);\n        newState = StateManager.setTotalMemberCount(newState, conversation.membercount);\n        newState = StateManager.setIsFavourite(newState, conversation.isfavourite);\n        newState = StateManager.setIsMuted(newState, conversation.ismuted);\n        newState = StateManager.addMessages(newState, conversation.messages);\n        newState = StateManager.setCanDeleteMessagesForAllUsers(newState, conversation.candeletemessagesforallusers);\n        return newState;\n    };\n\n    /**\n     * Get the details for a conversation from the conversation id.\n     *\n     * @param  {Number} conversationId The conversation id.\n     * @param  {Object} loggedInUserProfile The logged in user profile.\n     * @param  {Number} messageLimit The number of messages to include.\n     * @param  {Number} messageOffset The number of messages to skip.\n     * @param  {Bool} newestFirst Order messages newest first.\n     * @return {Object} Promise resolved when loaded.\n     */\n    var loadNewConversation = function(\n        conversationId,\n        loggedInUserProfile,\n        messageLimit,\n        messageOffset,\n        newestFirst\n    ) {\n        var loggedInUserId = loggedInUserProfile.id;\n        var newState = StateManager.setLoadingMembers(viewState, true);\n        newState = StateManager.setLoadingMessages(newState, true);\n        render(newState);\n\n        return Repository.getConversation(\n            loggedInUserId,\n            conversationId,\n            true,\n            true,\n            0,\n            0,\n            messageLimit + 1,\n            messageOffset,\n            newestFirst\n        )\n            .then(function(conversation) {\n                if (conversation.messages.length > messageLimit) {\n                    conversation.messages = conversation.messages.slice(1);\n                } else {\n                    setLoadedAllMessages(true);\n                }\n\n                setMessagesOffset(messageOffset + messageLimit);\n\n                return conversation;\n            })\n            .then(function(conversation) {\n                var hasLoggedInUser = conversation.members.filter(function(member) {\n                    return member.id == loggedInUserProfile.id;\n                });\n\n                if (hasLoggedInUser.length < 1) {\n                    conversation.members = conversation.members.concat([loggedInUserProfile]);\n                }\n\n                var newState = updateStateFromConversation(conversation, loggedInUserProfile.id);\n                newState = StateManager.setLoadingMembers(newState, false);\n                newState = StateManager.setLoadingMessages(newState, false);\n                return render(newState)\n                    .then(function() {\n                        return conversation;\n                    });\n            })\n            .then(function() {\n                return markConversationAsRead(conversationId);\n            })\n            .catch(function(error) {\n                var newState = StateManager.setLoadingMembers(viewState, false);\n                newState = StateManager.setLoadingMessages(newState, false);\n                render(newState);\n                Notification.exception(error);\n            });\n    };\n\n    /**\n     * Get the details for a conversation from and existing conversation object.\n     *\n     * @param  {Object} conversation The conversation object.\n     * @param  {Object} loggedInUserProfile The logged in user profile.\n     * @param  {Number} messageLimit The number of messages to include.\n     * @param  {Bool} newestFirst Order messages newest first.\n     * @return {Object} Promise resolved when loaded.\n     */\n    var loadExistingConversation = function(\n        conversation,\n        loggedInUserProfile,\n        messageLimit,\n        newestFirst\n    ) {\n        var hasLoggedInUser = conversation.members.filter(function(member) {\n            return member.id == loggedInUserProfile.id;\n        });\n\n        if (hasLoggedInUser.length < 1) {\n            conversation.members = conversation.members.concat([loggedInUserProfile]);\n        }\n\n        var messageCount = conversation.messages.length;\n        var hasLoadedEnoughMessages = messageCount >= messageLimit;\n        var newState = updateStateFromConversation(conversation, loggedInUserProfile.id);\n        newState = StateManager.setLoadingMembers(newState, false);\n        newState = StateManager.setLoadingMessages(newState, !hasLoadedEnoughMessages);\n        var renderPromise = render(newState);\n\n        return renderPromise.then(function() {\n                if (!hasLoadedEnoughMessages) {\n                    // We haven't got enough messages so let's load some more.\n                    return loadMessages(conversation.id, messageLimit, messageCount, newestFirst, []);\n                } else {\n                    // We've got enough messages. No need to load any more for now.\n                    return {messages: conversation.messages};\n                }\n            })\n            .then(function() {\n                var messages = viewState.messages;\n                // Update the offset to reflect the number of messages we've loaded.\n                setMessagesOffset(messages.length);\n                markConversationAsRead(viewState.id);\n\n                return messages;\n            })\n            .catch(Notification.exception);\n    };\n\n    /**\n     * Load messages for this conversation and pass them to the renderer.\n     *\n     * @param  {Number} conversationId Conversation id.\n     * @param  {Number} limit Number of messages to load.\n     * @param  {Number} offset Get messages from offset.\n     * @param  {Bool} newestFirst Get newest messages first.\n     * @param  {Array} ignoreList Ignore any messages with ids in this list.\n     * @param  {Number|null} timeFrom Only get messages from this time onwards.\n     * @return {Promise} renderer promise.\n     */\n    var loadMessages = function(conversationId, limit, offset, newestFirst, ignoreList, timeFrom) {\n        return Repository.getMessages(\n                viewState.loggedInUserId,\n                conversationId,\n                limit ? limit + 1 : limit,\n                offset,\n                newestFirst,\n                timeFrom\n            )\n            .then(function(result) {\n                if (result.messages.length && ignoreList.length) {\n                    result.messages = result.messages.filter(function(message) {\n                        // Skip any messages in our ignore list.\n                        return ignoreList.indexOf(parseInt(message.id, 10)) < 0;\n                    });\n                }\n\n                return result;\n            })\n            .then(function(result) {\n                if (!limit) {\n                    return result;\n                } else if (result.messages.length > limit) {\n                    // Ignore the last result which was just to test if there are more\n                    // to load.\n                    result.messages = result.messages.slice(0, -1);\n                } else {\n                    setLoadedAllMessages(true);\n                }\n\n                return result;\n            })\n            .then(function(result) {\n                var membersToAdd = result.members.filter(function(member) {\n                    return !(member.id in viewState.members);\n                });\n                var newState = StateManager.addMembers(viewState, membersToAdd);\n                newState = StateManager.addMessages(newState, result.messages);\n                newState = StateManager.setLoadingMessages(newState, false);\n                return render(newState)\n                    .then(function() {\n                        return result;\n                    });\n            })\n            .catch(function(error) {\n                var newState = StateManager.setLoadingMessages(viewState, false);\n                render(newState);\n                // Re-throw the error for other error handlers.\n                throw error;\n            });\n    };\n\n    /**\n     * Create a callback function for getting new messages for this conversation.\n     *\n     * @param  {Number} conversationId Conversation id.\n     * @param  {Bool} newestFirst Show newest messages first\n     * @return {Function} Callback function that returns a renderer promise.\n     */\n    var getLoadNewMessagesCallback = function(conversationId, newestFirst) {\n        return function() {\n            var messages = viewState.messages;\n            var mostRecentMessage = messages.length ? messages[messages.length - 1] : null;\n            var lastTimeCreated = mostRecentMessage ? mostRecentMessage.timeCreated : null;\n\n            if (lastTimeCreated && !isResetting && !isSendingMessage) {\n                // There may be multiple messages with the same time created value since\n                // the accuracy is only down to the second. The server will include these\n                // messages in the result (since it does a >= comparison on time from) so\n                // we need to filter them back out of the result so that we're left only\n                // with the new messages.\n                var ignoreMessageIds = [];\n                for (var i = messages.length - 1; i >= 0; i--) {\n                    var message = messages[i];\n                    if (message.timeCreated === lastTimeCreated) {\n                        ignoreMessageIds.push(message.id);\n                    } else {\n                        // Since the messages are ordered in ascending order of time created\n                        // we can break as soon as we hit a message with a different time created\n                        // because we know all other messages will have lower values.\n                        break;\n                    }\n                }\n\n                return loadMessages(\n                        conversationId,\n                        0,\n                        0,\n                        newestFirst,\n                        ignoreMessageIds,\n                        lastTimeCreated\n                    )\n                    .then(function(result) {\n                        if (result.messages.length) {\n                            // If we found some results then restart the polling timer\n                            // because the other user might be sending messages.\n                            newMessagesPollTimer.restart();\n                            // We've also got a new last message so publish that for other\n                            // components to update.\n                            var conversation = formatConversationForEvent(viewState);\n                            PubSub.publish(MessageDrawerEvents.CONVERSATION_NEW_LAST_MESSAGE, conversation);\n                            return markConversationAsRead(conversationId);\n                        } else {\n                            return result;\n                        }\n                    });\n            }\n\n            return $.Deferred().resolve().promise();\n        };\n    };\n\n    /**\n     * Mark a conversation as read.\n     *\n     * @param  {Number} conversationId The conversation id.\n     * @return {Promise} The renderer promise.\n     */\n    var markConversationAsRead = function(conversationId) {\n        var loggedInUserId = viewState.loggedInUserId;\n\n        return Repository.markAllConversationMessagesAsRead(loggedInUserId, conversationId)\n            .then(function() {\n                var newState = StateManager.markMessagesAsRead(viewState, viewState.messages);\n                PubSub.publish(MessageDrawerEvents.CONVERSATION_READ, conversationId);\n                return render(newState);\n            });\n    };\n\n    /**\n     * Tell the statemanager there is request to block a user and run the renderer\n     * to show the block user dialogue.\n     *\n     * @param {Number} userId User id.\n     */\n    var requestBlockUser = function(userId) {\n        cancelRequest(userId);\n        var newState = StateManager.addPendingBlockUsersById(viewState, [userId]);\n        render(newState);\n    };\n\n    /**\n     * Send the repository a request to block a user, update the statemanager and publish\n     * a contact has been blocked.\n     *\n     * @param  {Number} userId User id of user to block.\n     * @return {Promise} Renderer promise.\n     */\n    var blockUser = function(userId) {\n        var newState = StateManager.setLoadingConfirmAction(viewState, true);\n        render(newState);\n\n        return Repository.blockUser(viewState.loggedInUserId, userId)\n            .then(function(profile) {\n                var newState = StateManager.addMembers(viewState, [profile]);\n                newState = StateManager.removePendingBlockUsersById(newState, [userId]);\n                newState = StateManager.setLoadingConfirmAction(newState, false);\n                PubSub.publish(MessageDrawerEvents.CONTACT_BLOCKED, userId);\n                return render(newState);\n            });\n    };\n\n    /**\n     * Tell the statemanager there is a request to unblock a user and run the renderer\n     * to show the unblock user dialogue.\n     *\n     * @param {Number} userId User id of user to unblock.\n     */\n    var requestUnblockUser = function(userId) {\n        cancelRequest(userId);\n        var newState = StateManager.addPendingUnblockUsersById(viewState, [userId]);\n        render(newState);\n    };\n\n    /**\n     * Send the repository a request to unblock a user, update the statemanager and publish\n     * a contact has been unblocked.\n     *\n     * @param  {Number} userId User id of user to unblock.\n     * @return {Promise} Renderer promise.\n     */\n    var unblockUser = function(userId) {\n        var newState = StateManager.setLoadingConfirmAction(viewState, true);\n        render(newState);\n\n        return Repository.unblockUser(viewState.loggedInUserId, userId)\n            .then(function(profile) {\n                var newState = StateManager.addMembers(viewState, [profile]);\n                newState = StateManager.removePendingUnblockUsersById(newState, [userId]);\n                newState = StateManager.setLoadingConfirmAction(newState, false);\n                PubSub.publish(MessageDrawerEvents.CONTACT_UNBLOCKED, userId);\n                return render(newState);\n            });\n    };\n\n    /**\n     * Tell the statemanager there is a request to remove a user from the contact list\n     * and run the renderer to show the remove user from contacts dialogue.\n     *\n     * @param {Number} userId User id of user to remove from contacts.\n     */\n    var requestRemoveContact = function(userId) {\n        cancelRequest(userId);\n        var newState = StateManager.addPendingRemoveContactsById(viewState, [userId]);\n        render(newState);\n    };\n\n    /**\n     * Send the repository a request to remove a user from the contacts list. update the statemanager\n     * and publish a contact has been removed.\n     *\n     * @param  {Number} userId User id of user to remove from contacts.\n     * @return {Promise} Renderer promise.\n     */\n    var removeContact = function(userId) {\n        var newState = StateManager.setLoadingConfirmAction(viewState, true);\n        render(newState);\n\n        return Repository.deleteContacts(viewState.loggedInUserId, [userId])\n            .then(function(profiles) {\n                var newState = StateManager.addMembers(viewState, profiles);\n                newState = StateManager.removePendingRemoveContactsById(newState, [userId]);\n                newState = StateManager.setLoadingConfirmAction(newState, false);\n                PubSub.publish(MessageDrawerEvents.CONTACT_REMOVED, userId);\n                return render(newState);\n            });\n    };\n\n    /**\n     * Tell the statemanager there is a request to add a user to the contact list\n     * and run the renderer to show the add user to contacts dialogue.\n     *\n     * @param {Number} userId User id of user to add to contacts.\n     */\n    var requestAddContact = function(userId) {\n        cancelRequest(userId);\n        var newState = StateManager.addPendingAddContactsById(viewState, [userId]);\n        render(newState);\n    };\n\n    /**\n     * Send the repository a request to add a user to the contacts list. update the statemanager\n     * and publish a contact has been added.\n     *\n     * @param  {Number} userId User id of user to add to contacts.\n     * @return {Promise} Renderer promise.\n     */\n    var addContact = function(userId) {\n        var newState = StateManager.setLoadingConfirmAction(viewState, true);\n        render(newState);\n\n        return Repository.createContactRequest(viewState.loggedInUserId, userId)\n            .then(function(response) {\n                if (!response.request) {\n                    throw new Error(response.warnings[0].message);\n                }\n\n                return response.request;\n            })\n            .then(function(request) {\n                var newState = StateManager.removePendingAddContactsById(viewState, [userId]);\n                newState = StateManager.addContactRequests(newState, [request]);\n                newState = StateManager.setLoadingConfirmAction(newState, false);\n                return render(newState);\n            });\n    };\n\n    /**\n     * Set the current conversation as a favourite conversation.\n     *\n     * @return {Promise} Renderer promise.\n     */\n    var setFavourite = function() {\n        var userId = viewState.loggedInUserId;\n        var conversationId = viewState.id;\n\n        return Repository.setFavouriteConversations(userId, [conversationId])\n            .then(function() {\n                var newState = StateManager.setIsFavourite(viewState, true);\n                return render(newState);\n            })\n            .then(function() {\n                return PubSub.publish(\n                    MessageDrawerEvents.CONVERSATION_SET_FAVOURITE,\n                    formatConversationForEvent(viewState)\n                );\n            });\n    };\n\n    /**\n     * Unset the current conversation as a favourite conversation.\n     *\n     * @return {Promise} Renderer promise.\n     */\n    var unsetFavourite = function() {\n        var userId = viewState.loggedInUserId;\n        var conversationId = viewState.id;\n\n        return Repository.unsetFavouriteConversations(userId, [conversationId])\n            .then(function() {\n                var newState = StateManager.setIsFavourite(viewState, false);\n                return render(newState);\n            })\n            .then(function() {\n                return PubSub.publish(\n                    MessageDrawerEvents.CONVERSATION_UNSET_FAVOURITE,\n                    formatConversationForEvent(viewState)\n                );\n            });\n    };\n\n    /**\n     * Set the current conversation as a muted conversation.\n     *\n     * @return {Promise} Renderer promise.\n     */\n    var setMuted = function() {\n        var userId = viewState.loggedInUserId;\n        var conversationId = viewState.id;\n\n        return Repository.setMutedConversations(userId, [conversationId])\n            .then(function() {\n                var newState = StateManager.setIsMuted(viewState, true);\n                return render(newState);\n            })\n            .then(function() {\n                return PubSub.publish(\n                    MessageDrawerEvents.CONVERSATION_SET_MUTED,\n                    formatConversationForEvent(viewState)\n                );\n            });\n    };\n\n    /**\n     * Unset the current conversation as a muted conversation.\n     *\n     * @return {Promise} Renderer promise.\n     */\n    var unsetMuted = function() {\n        var userId = viewState.loggedInUserId;\n        var conversationId = viewState.id;\n\n        return Repository.unsetMutedConversations(userId, [conversationId])\n            .then(function() {\n                var newState = StateManager.setIsMuted(viewState, false);\n                return render(newState);\n            })\n            .then(function() {\n                return PubSub.publish(\n                    MessageDrawerEvents.CONVERSATION_UNSET_MUTED,\n                    formatConversationForEvent(viewState)\n                );\n            });\n    };\n\n    /**\n     * Tell the statemanager there is a request to delete the selected messages\n     * and run the renderer to show confirm delete messages dialogue.\n     *\n     * @param {Number} userId User id.\n     */\n    var requestDeleteSelectedMessages = function(userId) {\n        var selectedMessageIds = viewState.selectedMessageIds;\n        cancelRequest(userId);\n        var newState = StateManager.addPendingDeleteMessagesById(viewState, selectedMessageIds);\n        render(newState);\n    };\n\n    /**\n     * Send the repository a request to delete the messages pending deletion. Update the statemanager\n     * and publish a message deletion event.\n     *\n     * @return {Promise} Renderer promise.\n     */\n    var deleteSelectedMessages = function() {\n        var messageIds = viewState.pendingDeleteMessageIds;\n        var sentMessages = viewState.messages.filter(function(message) {\n            // If a message sendState is null then it means it was loaded from the server or if it's\n            // set to sent then it means the user has successfully sent it in this page load.\n            return messageIds.indexOf(message.id) >= 0 && (message.sendState == 'sent' || message.sendState === null);\n        });\n        var newState = StateManager.setLoadingConfirmAction(viewState, true);\n\n        render(newState);\n\n        var deleteMessagesPromise = $.Deferred().resolve().promise();\n\n        if (sentMessages.length) {\n            // We only need to send a request to the server if we're trying to delete messages that\n            // have successfully been sent.\n            var sentMessageIds = sentMessages.map(function(message) {\n                return message.id;\n            });\n            if (newState.deleteMessagesForAllUsers) {\n                deleteMessagesPromise = Repository.deleteMessagesForAllUsers(viewState.loggedInUserId, sentMessageIds);\n            } else {\n                deleteMessagesPromise = Repository.deleteMessages(viewState.loggedInUserId, sentMessageIds);\n            }\n        }\n\n        return deleteMessagesPromise.then(function() {\n                var newState = StateManager.removeMessagesById(viewState, messageIds);\n                newState = StateManager.removePendingDeleteMessagesById(newState, messageIds);\n                newState = StateManager.removeSelectedMessagesById(newState, messageIds);\n                newState = StateManager.setLoadingConfirmAction(newState, false);\n                newState = StateManager.setDeleteMessagesForAllUsers(newState, false);\n\n                var prevLastMessage = viewState.messages[viewState.messages.length - 1];\n                var newLastMessage = newState.messages.length ? newState.messages[newState.messages.length - 1] : null;\n\n                if (newLastMessage && newLastMessage.id != prevLastMessage.id) {\n                    var conversation = formatConversationForEvent(newState);\n                    PubSub.publish(MessageDrawerEvents.CONVERSATION_NEW_LAST_MESSAGE, conversation);\n                } else if (!newState.messages.length) {\n                    PubSub.publish(MessageDrawerEvents.CONVERSATION_DELETED, newState.id);\n                }\n\n                return render(newState);\n            })\n            .catch(Notification.exception);\n    };\n\n    /**\n     * Tell the statemanager there is a request to delete a conversation\n     * and run the renderer to show confirm delete conversation dialogue.\n     *\n     * @param {Number} userId User id of other user.\n     */\n    var requestDeleteConversation = function(userId) {\n        cancelRequest(userId);\n        var newState = StateManager.setPendingDeleteConversation(viewState, true);\n        render(newState);\n    };\n\n    /**\n     * Send the repository a request to delete a conversation. Update the statemanager\n     * and publish a conversation deleted event.\n     *\n     * @return {Promise} Renderer promise.\n     */\n    var deleteConversation = function() {\n        var newState = StateManager.setLoadingConfirmAction(viewState, true);\n        render(newState);\n\n        return Repository.deleteConversation(viewState.loggedInUserId, viewState.id)\n            .then(function() {\n                var newState = StateManager.removeMessages(viewState, viewState.messages);\n                newState = StateManager.removeSelectedMessagesById(newState, viewState.selectedMessageIds);\n                newState = StateManager.setPendingDeleteConversation(newState, false);\n                newState = StateManager.setLoadingConfirmAction(newState, false);\n                PubSub.publish(MessageDrawerEvents.CONVERSATION_DELETED, newState.id);\n\n                return render(newState);\n            });\n    };\n\n    /**\n     * Tell the statemanager to cancel all pending actions.\n     *\n     * @param  {Number} userId User id.\n     */\n    var cancelRequest = function(userId) {\n        var pendingDeleteMessageIds = viewState.pendingDeleteMessageIds;\n        var newState = StateManager.removePendingAddContactsById(viewState, [userId]);\n        newState = StateManager.removePendingRemoveContactsById(newState, [userId]);\n        newState = StateManager.removePendingUnblockUsersById(newState, [userId]);\n        newState = StateManager.removePendingBlockUsersById(newState, [userId]);\n        newState = StateManager.removePendingDeleteMessagesById(newState, pendingDeleteMessageIds);\n        newState = StateManager.setPendingDeleteConversation(newState, false);\n        newState = StateManager.setDeleteMessagesForAllUsers(newState, false);\n        render(newState);\n    };\n\n    /**\n     * Accept the contact request from the given user.\n     *\n     * @param  {Number} userId User id of other user.\n     * @return {Promise} Renderer promise.\n     */\n    var acceptContactRequest = function(userId) {\n        // Search the list of the logged in user's contact requests to find the\n        // one from this user.\n        var loggedInUserId = viewState.loggedInUserId;\n        var requests = viewState.members[userId].contactrequests.filter(function(request) {\n            return request.requesteduserid == loggedInUserId;\n        });\n        var request = requests[0];\n        var newState = StateManager.setLoadingConfirmAction(viewState, true);\n        render(newState);\n\n        return Repository.acceptContactRequest(userId, loggedInUserId)\n            .then(function(profile) {\n                var newState = StateManager.removeContactRequests(viewState, [request]);\n                newState = StateManager.addMembers(viewState, [profile]);\n                newState = StateManager.setLoadingConfirmAction(newState, false);\n                return render(newState);\n            })\n            .then(function() {\n                PubSub.publish(MessageDrawerEvents.CONTACT_ADDED, viewState.members[userId]);\n                PubSub.publish(MessageDrawerEvents.CONTACT_REQUEST_ACCEPTED, request);\n                return;\n            });\n    };\n\n    /**\n     * Decline the contact request from the given user.\n     *\n     * @param  {Number} userId User id of other user.\n     * @return {Promise} Renderer promise.\n     */\n    var declineContactRequest = function(userId) {\n        // Search the list of the logged in user's contact requests to find the\n        // one from this user.\n        var loggedInUserId = viewState.loggedInUserId;\n        var requests = viewState.members[userId].contactrequests.filter(function(request) {\n            return request.requesteduserid == loggedInUserId;\n        });\n        var request = requests[0];\n        var newState = StateManager.setLoadingConfirmAction(viewState, true);\n        render(newState);\n\n        return Repository.declineContactRequest(userId, loggedInUserId)\n            .then(function(profile) {\n                var newState = StateManager.removeContactRequests(viewState, [request]);\n                newState = StateManager.addMembers(viewState, [profile]);\n                newState = StateManager.setLoadingConfirmAction(newState, false);\n                return render(newState);\n            })\n            .then(function() {\n                PubSub.publish(MessageDrawerEvents.CONTACT_REQUEST_DECLINED, request);\n                return;\n            });\n    };\n\n    /**\n     * Send all of the messages in the buffer to the server to be created. Update the\n     * UI with the newly created message information.\n     *\n     * This function will recursively call itself in order to make sure the buffer is\n     * always being processed.\n     */\n    var processSendMessageBuffer = function() {\n        if (isSendingMessage) {\n            // We're already sending messages so nothing to do.\n            return;\n        }\n        if (!sendMessageBuffer.length) {\n            // No messages waiting to send. Nothing to do.\n            return;\n        }\n\n        // Flag that we're processing the queue.\n        isSendingMessage = true;\n        // Grab all of the messages in the buffer.\n        var messagesToSend = sendMessageBuffer.slice();\n        // Empty the buffer since we're processing it.\n        sendMessageBuffer = [];\n        var conversationId = viewState.id;\n        var newConversationId = null;\n        var messagesText = messagesToSend.map(function(message) {\n            return message.text;\n        });\n        var messageIds = messagesToSend.map(function(message) {\n            return message.id;\n        });\n        var sendMessagePromise = null;\n        var newCanDeleteMessagesForAllUsers = null;\n        if (!conversationId && (viewState.type != CONVERSATION_TYPES.PUBLIC)) {\n            // If it's a new private conversation then we need to use the old\n            // web service function to create the conversation.\n            var otherUserId = getOtherUserId();\n            sendMessagePromise = Repository.sendMessagesToUser(otherUserId, messagesText)\n                .then(function(messages) {\n                    if (messages.length) {\n                        newConversationId = parseInt(messages[0].conversationid, 10);\n                        newCanDeleteMessagesForAllUsers = messages[0].candeletemessagesforallusers;\n                    }\n                    return messages;\n                });\n        } else {\n            sendMessagePromise = Repository.sendMessagesToConversation(conversationId, messagesText);\n        }\n\n        sendMessagePromise\n            .then(function(messages) {\n                var newMessageIds = messages.map(function(message) {\n                    return message.id;\n                });\n                var data = [];\n                var selectedToRemove = [];\n                var selectedToAdd = [];\n\n                messagesToSend.forEach(function(oldMessage, index) {\n                    var newMessage = messages[index];\n                    // Update messages expects and array of arrays where the first value\n                    // is the old message to update and the second value is the new values\n                    // to set.\n                    data.push([oldMessage, newMessage]);\n\n                    if (viewState.selectedMessageIds.indexOf(oldMessage.id) >= 0) {\n                        // If the message was added to the \"selected messages\" list while it was still\n                        // being sent then we should update it's id in that list now to make sure future\n                        // actions work.\n                        selectedToRemove.push(oldMessage.id);\n                        selectedToAdd.push(newMessage.id);\n                    }\n                });\n                var newState = StateManager.updateMessages(viewState, data);\n                newState = StateManager.setMessagesSendSuccessById(newState, newMessageIds);\n\n                if (selectedToRemove.length) {\n                    newState = StateManager.removeSelectedMessagesById(newState, selectedToRemove);\n                }\n\n                if (selectedToAdd.length) {\n                    newState = StateManager.addSelectedMessagesById(newState, selectedToAdd);\n                }\n\n                var conversation = formatConversationForEvent(newState);\n\n                if (!newState.id) {\n                    // If this message created the conversation then save the conversation\n                    // id.\n                    newState = StateManager.setId(newState, newConversationId);\n                    conversation.id = newConversationId;\n                    resetMessagePollTimer(newConversationId);\n                    PubSub.publish(MessageDrawerEvents.CONVERSATION_CREATED, conversation);\n                    newState = StateManager.setCanDeleteMessagesForAllUsers(newState, newCanDeleteMessagesForAllUsers);\n                }\n\n                // Update the UI with the new message values from the server.\n                render(newState);\n                // Recurse just in case there has been more messages added to the buffer.\n                isSendingMessage = false;\n                processSendMessageBuffer();\n                PubSub.publish(MessageDrawerEvents.CONVERSATION_NEW_LAST_MESSAGE, conversation);\n                return;\n            })\n            .catch(function(e) {\n                if (e.message) {\n                    var errorMessage =  $.Deferred().resolve(e.message).promise();\n                } else {\n                    var errorMessage =  Str.get_string('unknownerror', 'core');\n                }\n\n                var handleFailedMessages = function(errorMessage) {\n                    // We failed to create messages so remove the old messages from the pending queue\n                    // and update the UI to indicate that the message failed.\n                    var newState = StateManager.setMessagesSendFailById(viewState, messageIds, errorMessage);\n                    render(newState);\n                    isSendingMessage = false;\n                    processSendMessageBuffer();\n                };\n\n                errorMessage.then(handleFailedMessages)\n                    .catch(function(e) {\n                        // Hrmm, we can't even load the error messages string! We'll have to\n                        // hard code something in English here if we still haven't got a message\n                        // to show.\n                        var finalError = e.message || 'Something went wrong!';\n                        handleFailedMessages(finalError);\n                    });\n            });\n    };\n\n    /**\n     * Buffers messages to be sent to the server. We use a buffer here to allow the\n     * user to freely input messages without blocking the interface for them.\n     *\n     * Instead we just queue all of their messages up and send them as fast as we can.\n     *\n     * @param {String} text Text to send.\n     */\n    var sendMessage = function(text) {\n        var id = 'temp' + Date.now();\n        var message = {\n            id: id,\n            useridfrom: viewState.loggedInUserId,\n            text: text,\n            timecreated: null\n        };\n        var newState = StateManager.addMessages(viewState, [message]);\n        render(newState);\n        sendMessageBuffer.push(message);\n        processSendMessageBuffer();\n    };\n\n    /**\n     * Retry sending a message that failed.\n     *\n     * @param {Object} message The message to send.\n     */\n    var retrySendMessage = function(message) {\n        var newState = StateManager.setMessagesSendPendingById(viewState, [message.id]);\n        render(newState);\n        sendMessageBuffer.push(message);\n        processSendMessageBuffer();\n    };\n\n    /**\n     * Toggle the selected messages update the statemanager and render the result.\n     *\n     * @param  {Number} messageId The id of the message to be toggled\n     */\n    var toggleSelectMessage = function(messageId) {\n        var newState = viewState;\n\n        if (viewState.selectedMessageIds.indexOf(messageId) > -1) {\n            newState = StateManager.removeSelectedMessagesById(viewState, [messageId]);\n        } else {\n            newState = StateManager.addSelectedMessagesById(viewState, [messageId]);\n        }\n\n        render(newState);\n    };\n\n    /**\n     * Cancel edit mode (selecting the messages).\n     *\n     * @return {Promise} Renderer promise.\n     */\n    var cancelEditMode = function() {\n        cancelRequest(getOtherUserId());\n        var newState = StateManager.removeSelectedMessagesById(viewState, viewState.selectedMessageIds);\n        render(newState);\n    };\n\n    /**\n     * Process the patches in the render buffer one at a time in order until the\n     * buffer is empty.\n     *\n     * @param {Object} header The conversation header container element.\n     * @param {Object} body The conversation body container element.\n     * @param {Object} footer The conversation footer container element.\n     */\n    var processRenderBuffer = function(header, body, footer) {\n        if (isRendering) {\n            return;\n        }\n\n        if (!renderBuffer.length) {\n            return;\n        }\n\n        isRendering = true;\n        var renderable = renderBuffer.shift();\n        var renderPromises = renderers.map(function(renderFunc) {\n            return renderFunc(renderable.patch);\n        });\n\n        $.when.apply(null, renderPromises)\n            .then(function() {\n                isRendering = false;\n                renderable.deferred.resolve(true);\n                // Keep processing the buffer until it's empty.\n                processRenderBuffer(header, body, footer);\n            })\n            .catch(function(error) {\n                isRendering = false;\n                renderable.deferred.reject(error);\n                Notification.exception(error);\n            });\n    };\n\n    /**\n     * Create a function to render the Conversation.\n     *\n     * @param  {Object} header The conversation header container element.\n     * @param  {Object} body The conversation body container element.\n     * @param  {Object} footer The conversation footer container element.\n     * @param  {Bool} isNewConversation Has someone else already initialised a conversation?\n     * @return {Promise} Renderer promise.\n     */\n    var generateRenderFunction = function(header, body, footer, isNewConversation) {\n        var rendererFunc = function(patch) {\n            return Renderer.render(header, body, footer, patch);\n        };\n\n        if (!isNewConversation) {\n            // Looks like someone got here before us! We'd better update our\n            // UI to make sure it matches.\n            var initialState = StateManager.buildInitialState(viewState.midnight, viewState.loggedInUserId, viewState.id);\n            var syncPatch = Patcher.buildPatch(initialState, viewState);\n            rendererFunc(syncPatch);\n        }\n\n        renderers.push(rendererFunc);\n\n        return function(newState) {\n            var patch = Patcher.buildPatch(viewState, newState);\n            var deferred = $.Deferred();\n\n            // Check if the patch has any data. Ignore empty patches.\n            if (Object.keys(patch).length) {\n                // Add the patch to the render buffer which gets processed in order.\n                renderBuffer.push({\n                    patch: patch,\n                    deferred: deferred\n                });\n            } else {\n                deferred.resolve(true);\n            }\n            // This is a great place to add in some console logging if you need\n            // to debug something. You can log the current state, the next state,\n            // and the generated patch and see exactly what will be updated.\n\n            // Optimistically update the state. We're going to assume that the rendering\n            // will always succeed. The rendering is asynchronous (annoyingly) so it's buffered\n            // but it'll reach eventual consistency with the current state.\n            viewState = newState;\n            if (newState.id) {\n                // Only cache created conversations.\n                stateCache[newState.id] = {\n                    state: newState,\n                    messagesOffset: getMessagesOffset(),\n                    loadedAllMessages: hasLoadedAllMessages()\n                };\n            }\n\n            // Start processing the buffer.\n            processRenderBuffer(header, body, footer);\n\n            return deferred.promise();\n        };\n    };\n\n    /**\n     * Create a confirm action function.\n     *\n     * @param {Function} actionCallback The callback function.\n     * @return {Function} Confirm action handler.\n     */\n    var generateConfirmActionHandler = function(actionCallback) {\n        return function(e, data) {\n            if (!viewState.loadingConfirmAction) {\n                actionCallback(getOtherUserId());\n                var newState = StateManager.setLoadingConfirmAction(viewState, false);\n                render(newState);\n            }\n            data.originalEvent.preventDefault();\n        };\n    };\n\n    /**\n     * Send message event handler.\n     *\n     * @param {Object} e Element this event handler is called on.\n     * @param {Object} data Data for this event.\n     */\n    var handleSendMessage = function(e, data) {\n        var target = $(e.target);\n        var footerContainer = target.closest(SELECTORS.FOOTER_CONTAINER);\n        var textArea = footerContainer.find(SELECTORS.MESSAGE_TEXT_AREA);\n        var text = textArea.val().trim();\n\n        if (text !== '') {\n            sendMessage(text);\n            textArea.val('');\n            textArea.focus();\n        }\n\n        data.originalEvent.preventDefault();\n    };\n\n    /**\n     * Select message event handler.\n     *\n     * @param {Object} e Element this event handler is called on.\n     * @param {Object} data Data for this event.\n     */\n    var handleSelectMessage = function(e, data) {\n        var selection = window.getSelection();\n        var target = $(e.target);\n\n        if (selection.toString() != '') {\n            // Bail if we're selecting.\n            return;\n        }\n\n        if (target.is('a')) {\n            // Clicking on a link in the message so ignore it.\n            return;\n        }\n\n        var element = target.closest(SELECTORS.MESSAGE);\n        var messageId = element.attr('data-message-id');\n\n        toggleSelectMessage(messageId);\n\n        data.originalEvent.preventDefault();\n    };\n\n    /**\n     * Handle retry sending of message.\n     *\n     * @param {Object} e Element this event handler is called on.\n     * @param {Object} data Data for this event.\n     */\n    var handleRetrySendMessage = function(e, data) {\n        var target = $(e.target);\n        var element = target.closest(SELECTORS.MESSAGE);\n        var messageId = element.attr('data-message-id');\n        var messages = viewState.messages.filter(function(message) {\n            return message.id == messageId;\n        });\n        var message = messages.length ? messages[0] : null;\n\n        if (message) {\n            retrySendMessage(message);\n        }\n\n        data.originalEvent.preventDefault();\n        data.originalEvent.stopPropagation();\n        e.stopPropagation();\n    };\n\n    /**\n     * Cancel edit mode event handler.\n     *\n     * @param {Object} e Element this event handler is called on.\n     * @param {Object} data Data for this event.\n     */\n    var handleCancelEditMode = function(e, data) {\n        cancelEditMode();\n        data.originalEvent.preventDefault();\n    };\n\n    /**\n     * Show the view contact page.\n     *\n     * @param {String} namespace Unique identifier for the Routes\n     * @return {Function} View contact handler.\n     */\n    var generateHandleViewContact = function(namespace) {\n        return function(e, data) {\n            var otherUserId = getOtherUserId();\n            var otherUser = viewState.members[otherUserId];\n            MessageDrawerRouter.go(namespace, MessageDrawerRoutes.VIEW_CONTACT, otherUser);\n            data.originalEvent.preventDefault();\n        };\n    };\n\n    /**\n     * Set this conversation as a favourite.\n     *\n     * @param {Object} e Element this event handler is called on.\n     * @param {Object} data Data for this event.\n     */\n    var handleSetFavourite = function(e, data) {\n        setFavourite().catch(Notification.exception);\n        data.originalEvent.preventDefault();\n    };\n\n    /**\n     * Unset this conversation as a favourite.\n     *\n     * @param {Object} e Element this event handler is called on.\n     * @param {Object} data Data for this event.\n     */\n    var handleUnsetFavourite = function(e, data) {\n        unsetFavourite().catch(Notification.exception);\n        data.originalEvent.preventDefault();\n    };\n\n    /**\n     * Show the view group info page.\n     * Set this conversation as muted.\n     *\n     * @param {Object} e Element this event handler is called on.\n     * @param {Object} data Data for this event.\n     */\n    var handleSetMuted = function(e, data) {\n        setMuted().catch(Notification.exception);\n        data.originalEvent.preventDefault();\n    };\n\n    /**\n     * Unset this conversation as muted.\n     *\n     * @param {Object} e Element this event handler is called on.\n     * @param {Object} data Data for this event.\n     */\n    var handleUnsetMuted = function(e, data) {\n        unsetMuted().catch(Notification.exception);\n        data.originalEvent.preventDefault();\n    };\n\n    /**\n     * Handle clicking on the checkbox that toggles deleting messages for\n     * all users.\n     *\n     * @param {Object} e Element this event handler is called on.\n     */\n    var handleDeleteMessagesForAllUsersToggle = function(e) {\n        var newValue = $(e.target).prop('checked');\n        var newState = StateManager.setDeleteMessagesForAllUsers(viewState, newValue);\n        render(newState);\n    };\n\n    /**\n     * Show the view contact page.\n     *\n     * @param {String} namespace Unique identifier for the Routes\n     * @return {Function} View group info handler.\n     */\n    var generateHandleViewGroupInfo = function(namespace) {\n        return function(e, data) {\n            MessageDrawerRouter.go(\n                namespace,\n                MessageDrawerRoutes.VIEW_GROUP_INFO,\n                {\n                    id: viewState.id,\n                    name: viewState.name,\n                    subname: viewState.subname,\n                    imageUrl: viewState.imageUrl,\n                    totalMemberCount: viewState.totalMemberCount\n                },\n                viewState.loggedInUserId\n            );\n            data.originalEvent.preventDefault();\n        };\n    };\n\n    /**\n     * Handle clicking on the emoji toggle button.\n     *\n     * @param {Object} e The event\n     * @param {Object} data The custom interaction event data\n     */\n    var handleToggleEmojiPicker = function(e, data) {\n        var newState = StateManager.setShowEmojiPicker(viewState, !viewState.showEmojiPicker);\n        render(newState);\n        data.originalEvent.preventDefault();\n    };\n\n    /**\n     * Handle clicking outside the emoji picker to close it.\n     *\n     * @param {Object} e The event\n     */\n    var handleCloseEmojiPicker = function(e) {\n        var target = $(e.target);\n\n        if (\n            viewState.showEmojiPicker &&\n            !target.closest(SELECTORS.EMOJI_PICKER_CONTAINER).length &&\n            !target.closest(SELECTORS.TOGGLE_EMOJI_PICKER_BUTTON).length\n        ) {\n            var newState = StateManager.setShowEmojiPicker(viewState, false);\n            render(newState);\n        }\n    };\n\n    /**\n     * Listen to, and handle events for conversations.\n     *\n     * @param {string} namespace The route namespace.\n     * @param {Object} header Conversation header container element.\n     * @param {Object} body Conversation body container element.\n     * @param {Object} footer Conversation footer container element.\n     */\n    var registerEventListeners = function(namespace, header, body, footer) {\n        var isLoadingMoreMessages = false;\n        var messagesContainer = getMessagesContainer(body);\n        var emojiPickerElement = footer.find(SELECTORS.EMOJI_PICKER);\n        var emojiAutoCompleteContainer = footer.find(SELECTORS.EMOJI_AUTO_COMPLETE_CONTAINER);\n        var messageTextArea = footer.find(SELECTORS.MESSAGE_TEXT_AREA);\n        var headerActivateHandlers = [\n            [SELECTORS.ACTION_REQUEST_BLOCK, generateConfirmActionHandler(requestBlockUser)],\n            [SELECTORS.ACTION_REQUEST_UNBLOCK, generateConfirmActionHandler(requestUnblockUser)],\n            [SELECTORS.ACTION_REQUEST_ADD_CONTACT, generateConfirmActionHandler(requestAddContact)],\n            [SELECTORS.ACTION_REQUEST_REMOVE_CONTACT, generateConfirmActionHandler(requestRemoveContact)],\n            [SELECTORS.ACTION_REQUEST_DELETE_CONVERSATION, generateConfirmActionHandler(requestDeleteConversation)],\n            [SELECTORS.ACTION_CANCEL_EDIT_MODE, handleCancelEditMode],\n            [SELECTORS.ACTION_VIEW_CONTACT, generateHandleViewContact(namespace)],\n            [SELECTORS.ACTION_VIEW_GROUP_INFO, generateHandleViewGroupInfo(namespace)],\n            [SELECTORS.ACTION_CONFIRM_FAVOURITE, handleSetFavourite],\n            [SELECTORS.ACTION_CONFIRM_MUTE, handleSetMuted],\n            [SELECTORS.ACTION_CONFIRM_UNFAVOURITE, handleUnsetFavourite],\n            [SELECTORS.ACTION_CONFIRM_UNMUTE, handleUnsetMuted]\n        ];\n        var bodyActivateHandlers = [\n            [SELECTORS.ACTION_CANCEL_CONFIRM, generateConfirmActionHandler(cancelRequest)],\n            [SELECTORS.ACTION_CONFIRM_BLOCK, generateConfirmActionHandler(blockUser)],\n            [SELECTORS.ACTION_CONFIRM_UNBLOCK, generateConfirmActionHandler(unblockUser)],\n            [SELECTORS.ACTION_CONFIRM_ADD_CONTACT, generateConfirmActionHandler(addContact)],\n            [SELECTORS.ACTION_CONFIRM_REMOVE_CONTACT, generateConfirmActionHandler(removeContact)],\n            [SELECTORS.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES, generateConfirmActionHandler(deleteSelectedMessages)],\n            [SELECTORS.ACTION_CONFIRM_DELETE_CONVERSATION, generateConfirmActionHandler(deleteConversation)],\n            [SELECTORS.ACTION_OKAY_CONFIRM, generateConfirmActionHandler(cancelRequest)],\n            [SELECTORS.ACTION_REQUEST_ADD_CONTACT, generateConfirmActionHandler(requestAddContact)],\n            [SELECTORS.ACTION_ACCEPT_CONTACT_REQUEST, generateConfirmActionHandler(acceptContactRequest)],\n            [SELECTORS.ACTION_DECLINE_CONTACT_REQUEST, generateConfirmActionHandler(declineContactRequest)],\n            [SELECTORS.MESSAGE, handleSelectMessage],\n            [SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE, handleDeleteMessagesForAllUsersToggle],\n            [SELECTORS.RETRY_SEND, handleRetrySendMessage]\n        ];\n        var footerActivateHandlers = [\n            [SELECTORS.SEND_MESSAGE_BUTTON, handleSendMessage],\n            [SELECTORS.TOGGLE_EMOJI_PICKER_BUTTON, handleToggleEmojiPicker],\n            [SELECTORS.ACTION_REQUEST_DELETE_SELECTED_MESSAGES, generateConfirmActionHandler(requestDeleteSelectedMessages)],\n            [SELECTORS.ACTION_REQUEST_ADD_CONTACT, generateConfirmActionHandler(requestAddContact)],\n            [SELECTORS.ACTION_REQUEST_UNBLOCK, generateConfirmActionHandler(requestUnblockUser)],\n        ];\n\n        AutoRows.init(footer);\n\n        if (emojiAutoCompleteContainer.length) {\n            initialiseEmojiAutoComplete(\n                emojiAutoCompleteContainer[0],\n                messageTextArea[0],\n                function(hasSuggestions) {\n                    var newState = StateManager.setShowEmojiAutoComplete(viewState, hasSuggestions);\n                    render(newState);\n                },\n                function(emoji) {\n                    var newState = StateManager.setShowEmojiAutoComplete(viewState, false);\n                    render(newState);\n\n                    messageTextArea.focus();\n                    var cursorPos = messageTextArea.prop('selectionStart');\n                    var currentText = messageTextArea.val();\n                    var textBefore = currentText.substring(0, cursorPos).replace(/\\S*$/, '');\n                    var textAfter = currentText.substring(cursorPos).replace(/^\\S*/, '');\n\n                    messageTextArea.val(textBefore + emoji + textAfter);\n                    // Set the cursor position to after the inserted emoji.\n                    messageTextArea.prop('selectionStart', textBefore.length + emoji.length);\n                    messageTextArea.prop('selectionEnd', textBefore.length + emoji.length);\n                }\n            );\n        }\n\n        if (emojiPickerElement.length) {\n            initialiseEmojiPicker(emojiPickerElement[0], function(emoji) {\n                var newState = StateManager.setShowEmojiPicker(viewState, !viewState.showEmojiPicker);\n                render(newState);\n\n                messageTextArea.focus();\n                var cursorPos = messageTextArea.prop('selectionStart');\n                var currentText = messageTextArea.val();\n                var textBefore = currentText.substring(0, cursorPos);\n                var textAfter = currentText.substring(cursorPos, currentText.length);\n\n                messageTextArea.val(textBefore + emoji + textAfter);\n                // Set the cursor position to after the inserted emoji.\n                messageTextArea.prop('selectionStart', cursorPos + emoji.length);\n                messageTextArea.prop('selectionEnd', cursorPos + emoji.length);\n            });\n        }\n\n        CustomEvents.define(header, [\n            CustomEvents.events.activate\n        ]);\n        CustomEvents.define(body, [\n            CustomEvents.events.activate\n        ]);\n        CustomEvents.define(footer, [\n            CustomEvents.events.activate,\n            CustomEvents.events.enter,\n            CustomEvents.events.escape\n        ]);\n        CustomEvents.define(messagesContainer, [\n            CustomEvents.events.scrollTop,\n            CustomEvents.events.scrollLock\n        ]);\n\n        messagesContainer.on(CustomEvents.events.scrollTop, function(e, data) {\n            var hasMembers = Object.keys(viewState.members).length > 1;\n\n            if (!isResetting && !isLoadingMoreMessages && !hasLoadedAllMessages() && hasMembers) {\n                isLoadingMoreMessages = true;\n                var newState = StateManager.setLoadingMessages(viewState, true);\n                render(newState);\n\n                loadMessages(viewState.id, LOAD_MESSAGE_LIMIT, getMessagesOffset(), NEWEST_FIRST, [])\n                    .then(function() {\n                        isLoadingMoreMessages = false;\n                        setMessagesOffset(getMessagesOffset() + LOAD_MESSAGE_LIMIT);\n                        return;\n                    })\n                    .catch(function(error) {\n                        isLoadingMoreMessages = false;\n                        Notification.exception(error);\n                    });\n            }\n\n            data.originalEvent.preventDefault();\n        });\n\n        headerActivateHandlers.forEach(function(handler) {\n            var selector = handler[0];\n            var handlerFunction = handler[1];\n            header.on(CustomEvents.events.activate, selector, handlerFunction);\n        });\n\n        bodyActivateHandlers.forEach(function(handler) {\n            var selector = handler[0];\n            var handlerFunction = handler[1];\n            body.on(CustomEvents.events.activate, selector, handlerFunction);\n        });\n\n        footerActivateHandlers.forEach(function(handler) {\n            var selector = handler[0];\n            var handlerFunction = handler[1];\n            footer.on(CustomEvents.events.activate, selector, handlerFunction);\n        });\n\n        footer.on(CustomEvents.events.enter, SELECTORS.MESSAGE_TEXT_AREA, function(e, data) {\n            var enterToSend = footer.attr('data-enter-to-send');\n            if (enterToSend && enterToSend != 'false' && enterToSend != '0') {\n                handleSendMessage(e, data);\n            }\n        });\n\n        footer.on(CustomEvents.events.escape, SELECTORS.EMOJI_PICKER_CONTAINER, handleToggleEmojiPicker);\n        $(document.body).on('click', handleCloseEmojiPicker);\n\n        PubSub.subscribe(MessageDrawerEvents.ROUTE_CHANGED, function(newRouteData) {\n            if (newMessagesPollTimer) {\n                if (newRouteData.route != MessageDrawerRoutes.VIEW_CONVERSATION) {\n                    newMessagesPollTimer.stop();\n                }\n            }\n        });\n    };\n\n    /**\n     * Reset the timer that polls for new messages.\n     *\n     * @param  {Number} conversationId The conversation id\n     */\n    var resetMessagePollTimer = function(conversationId) {\n        if (newMessagesPollTimer) {\n            newMessagesPollTimer.stop();\n        }\n\n        newMessagesPollTimer = new BackOffTimer(\n            getLoadNewMessagesCallback(conversationId, NEWEST_FIRST),\n            BackOffTimer.getIncrementalCallback(\n                viewState.messagePollMin * MILLISECONDS_IN_SEC,\n                MILLISECONDS_IN_SEC,\n                viewState.messagePollMax * MILLISECONDS_IN_SEC,\n                viewState.messagePollAfterMax * MILLISECONDS_IN_SEC\n            )\n        );\n\n        newMessagesPollTimer.start();\n    };\n\n    /**\n     * Reset the state to the initial state and render the UI.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Number|null} conversationId The conversation id.\n     * @param  {Object} loggedInUserProfile The logged in user's profile.\n     */\n    var resetState = function(body, conversationId, loggedInUserProfile) {\n        // Reset all of the states back to the beginning if we're loading a new\n        // conversation.\n        loadedAllMessages = false;\n        messagesOffset = 0;\n        newMessagesPollTimer = null;\n        isRendering = false;\n        renderBuffer = [];\n        isResetting = true;\n        isSendingMessage = false;\n        sendMessageBuffer = [];\n\n        var loggedInUserId = loggedInUserProfile.id;\n        var midnight = parseInt(body.attr('data-midnight'), 10);\n        var messagePollMin = parseInt(body.attr('data-message-poll-min'), 10);\n        var messagePollMax = parseInt(body.attr('data-message-poll-max'), 10);\n        var messagePollAfterMax = parseInt(body.attr('data-message-poll-after-max'), 10);\n        var initialState = StateManager.buildInitialState(\n            midnight,\n            loggedInUserId,\n            conversationId,\n            messagePollMin,\n            messagePollMax,\n            messagePollAfterMax\n        );\n\n        if (!viewState) {\n            viewState = initialState;\n        }\n\n        if (newMessagesPollTimer) {\n            newMessagesPollTimer.stop();\n        }\n\n        render(initialState);\n    };\n\n    /**\n     * Load a new empty private conversation between two users or self-conversation.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Object} loggedInUserProfile The logged in user's profile.\n     * @param  {Int} otherUserId The other user's id.\n     * @return {Promise} Renderer promise.\n     */\n    var resetNoConversation = function(body, loggedInUserProfile, otherUserId) {\n        // Always reset the state back to the initial state so that the\n        // state manager and patcher can work correctly.\n        resetState(body, null, loggedInUserProfile);\n\n        var resetNoConversationPromise = null;\n\n        if (loggedInUserProfile.id != otherUserId) {\n            // Private conversation between two different users.\n            resetNoConversationPromise = Repository.getConversationBetweenUsers(\n                loggedInUserProfile.id,\n                otherUserId,\n                true,\n                true,\n                0,\n                0,\n                LOAD_MESSAGE_LIMIT,\n                0,\n                NEWEST_FIRST\n            );\n        } else {\n            // Self conversation.\n            resetNoConversationPromise = Repository.getSelfConversation(\n                loggedInUserProfile.id,\n                LOAD_MESSAGE_LIMIT,\n                0,\n                NEWEST_FIRST\n            );\n        }\n\n        return resetNoConversationPromise.then(function(conversation) {\n                // Looks like we have a conversation after all! Let's use that.\n                return resetByConversation(body, conversation, loggedInUserProfile);\n            })\n            .catch(function() {\n                // Can't find a conversation. Oh well. Just load up a blank one.\n                return loadEmptyPrivateConversation(loggedInUserProfile, otherUserId);\n            });\n    };\n\n    /**\n     * Load new messages into the conversation based on a time interval.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Number} conversationId The conversation id.\n     * @param  {Object} loggedInUserProfile The logged in user's profile.\n     * @return {Promise} Renderer promise.\n     */\n    var resetById = function(body, conversationId, loggedInUserProfile) {\n        var cache = null;\n        if (conversationId in stateCache) {\n            cache = stateCache[conversationId];\n        }\n\n        // Always reset the state back to the initial state so that the\n        // state manager and patcher can work correctly.\n        resetState(body, conversationId, loggedInUserProfile);\n\n        var promise = $.Deferred().resolve({}).promise();\n        if (cache) {\n            // We've seen this conversation before so there is no need to\n            // send any network requests.\n            var newState = cache.state;\n            // Reset some loading states just in case they were left weirdly.\n            newState = StateManager.setLoadingMessages(newState, false);\n            newState = StateManager.setLoadingMembers(newState, false);\n            setMessagesOffset(cache.messagesOffset);\n            setLoadedAllMessages(cache.loadedAllMessages);\n            render(newState);\n        } else {\n            promise = loadNewConversation(\n                conversationId,\n                loggedInUserProfile,\n                LOAD_MESSAGE_LIMIT,\n                0,\n                NEWEST_FIRST\n            );\n        }\n\n        return promise.then(function() {\n            return resetMessagePollTimer(conversationId);\n        });\n    };\n\n    /**\n     * Load new messages into the conversation based on a time interval.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Object} conversation The conversation.\n     * @param  {Object} loggedInUserProfile The logged in user's profile.\n     * @return {Promise} Renderer promise.\n     */\n    var resetByConversation = function(body, conversation, loggedInUserProfile) {\n        var cache = null;\n        if (conversation.id in stateCache) {\n            cache = stateCache[conversation.id];\n        }\n\n        // Always reset the state back to the initial state so that the\n        // state manager and patcher can work correctly.\n        resetState(body, conversation.id, loggedInUserProfile);\n\n        var promise = $.Deferred().resolve({}).promise();\n        if (cache) {\n            // We've seen this conversation before so there is no need to\n            // send any network requests.\n            var newState = cache.state;\n            // Reset some loading states just in case they were left weirdly.\n            newState = StateManager.setLoadingMessages(newState, false);\n            newState = StateManager.setLoadingMembers(newState, false);\n            setMessagesOffset(cache.messagesOffset);\n            setLoadedAllMessages(cache.loadedAllMessages);\n            render(newState);\n        } else {\n            promise = loadExistingConversation(\n                conversation,\n                loggedInUserProfile,\n                LOAD_MESSAGE_LIMIT,\n                NEWEST_FIRST\n            );\n        }\n\n        return promise.then(function() {\n            return resetMessagePollTimer(conversation.id);\n        });\n    };\n\n    /**\n     * Setup the conversation page. This is a rather complex function because there are a\n     * few combinations of arguments that can be provided to this function to show the\n     * conversation.\n     *\n     * There are:\n     * 1.) A conversation object with no action or other user id (e.g. from the overview page)\n     * 2.) A conversation id with no action or other user id (e.g. from the contacts page)\n     * 3.) No conversation/id with an action and other other user id. (e.g. from contact page)\n     *\n     * @param {string} namespace The route namespace.\n     * @param {Object} header Conversation header container element.\n     * @param {Object} body Conversation body container element.\n     * @param {Object} footer Conversation footer container element.\n     * @param {Object|Number|null} conversationOrId Conversation or id or null\n     * @param {String} action An action to take on the conversation\n     * @param {Number} otherUserId The other user id for a private conversation\n     * @return {Object} jQuery promise\n     */\n    var show = function(namespace, header, body, footer, conversationOrId, action, otherUserId) {\n        var conversation = null;\n        var conversationId = null;\n\n        // Check what we were given to identify the conversation.\n        if (conversationOrId && conversationOrId !== null && typeof conversationOrId == 'object') {\n            conversation = conversationOrId;\n            conversationId = parseInt(conversation.id, 10);\n        } else {\n            conversation = null;\n            conversationId = parseInt(conversationOrId, 10);\n            conversationId = isNaN(conversationId) ? null : conversationId;\n        }\n\n        if (!conversationId && action && otherUserId) {\n            // If we didn't get a conversation id got a user id then let's see if we've\n            // previously loaded a private conversation with this user.\n            conversationId = getCachedPrivateConversationIdFromUserId(otherUserId);\n        }\n\n        // This is a new conversation if:\n        // 1. We don't already have a state\n        // 2. The given conversation doesn't match the one currently loaded\n        // 3. We have a view state without a conversation id and we weren't given one\n        //    but we were given a different other user id. This happens when the user\n        //    goes from viewing a user that they haven't yet initialised a conversation\n        //    with to viewing a different user that they also haven't initialised a\n        //    conversation with.\n        var isNewConversation = !viewState || (viewState.id != conversationId) || (otherUserId && otherUserId != getOtherUserId());\n\n        if (!body.attr('data-init')) {\n            // Generate the render function to bind the header, body, and footer\n            // elements to it so that we don't need to pass them around this module.\n            render = generateRenderFunction(header, body, footer, isNewConversation);\n            registerEventListeners(namespace, header, body, footer);\n            body.attr('data-init', true);\n        }\n\n        if (isNewConversation) {\n            var renderPromise = null;\n            var loggedInUserProfile = getLoggedInUserProfile(body);\n\n            if (conversation) {\n                renderPromise = resetByConversation(body, conversation, loggedInUserProfile, otherUserId);\n            } else if (conversationId) {\n                renderPromise = resetById(body, conversationId, loggedInUserProfile, otherUserId);\n            } else {\n                renderPromise = resetNoConversation(body, loggedInUserProfile, otherUserId);\n            }\n\n            return renderPromise\n                .then(function() {\n                    isResetting = false;\n                    // Focus the first element that can receieve it in the header.\n                    header.find(Constants.SELECTORS.CAN_RECEIVE_FOCUS).first().focus();\n                    return;\n                })\n                .catch(function(error) {\n                    isResetting = false;\n                    Notification.exception(error);\n                });\n        }\n\n        // We're not loading a new conversation so we should reset the poll timer to try to load\n        // new messages.\n        resetMessagePollTimer(conversationId);\n\n        if (viewState.type == CONVERSATION_TYPES.PRIVATE && action) {\n            // There are special actions that the user can perform in a private (aka 1-to-1)\n            // conversation.\n            var currentOtherUserId = getOtherUserId();\n\n            switch (action) {\n                case 'block':\n                    return requestBlockUser(currentOtherUserId);\n                case 'unblock':\n                    return requestUnblockUser(currentOtherUserId);\n                case 'add-contact':\n                    return requestAddContact(currentOtherUserId);\n                case 'remove-contact':\n                    return requestRemoveContact(currentOtherUserId);\n            }\n        }\n\n        // Final fallback to return a promise if we didn't need to do anything.\n        return $.Deferred().resolve().promise();\n    };\n\n    /**\n     * String describing this page used for aria-labels.\n     *\n     * @return {Object} jQuery promise\n     */\n    var description = function() {\n        return Str.get_string('messagedrawerviewconversation', 'core_message', viewState.name);\n    };\n\n    return {\n        show: show,\n        description: description\n    };\n});\n"],"file":"message_drawer_view_conversation.min.js"}