From 06d046c1ffc642d3f513ca6cf14535bd01d8c4d9 Mon Sep 17 00:00:00 2001
From: Mark Nelson <mdjnelson@gmail.com>
Date: Thu, 25 Jul 2019 14:22:20 +0800
Subject: [PATCH 1/4] MDL-65093 core_message: deprecate can_post_message()

---
 lib/deprecatedlib.php      |   2 +-
 message/classes/api.php    |  23 +++-
 message/classes/helper.php |   9 +-
 message/externallib.php    |   2 +-
 message/index.php          |   4 +-
 message/tests/api_test.php | 212 +++++++++++++++++++++++++++++++++++++
 message/upgrade.txt        |   1 +
 7 files changed, 237 insertions(+), 16 deletions(-)

diff --git a/lib/deprecatedlib.php b/lib/deprecatedlib.php
index e51ed4c3e4a..afc91d429f0 100644
--- a/lib/deprecatedlib.php
+++ b/lib/deprecatedlib.php
@@ -2412,7 +2412,7 @@ function message_page_type_list() {
  */
 function message_can_post_message() {
     throw new coding_exception('message_can_post_message() can not be used anymore. Please use ' .
-        '\core_message\api::can_post_message() instead.');
+        '\core_message\api::can_send_message() instead.');
 }
 
 /**
diff --git a/message/classes/api.php b/message/classes/api.php
index 661c5718f41..49824d7fb1c 100644
--- a/message/classes/api.php
+++ b/message/classes/api.php
@@ -1844,6 +1844,8 @@ class api {
      * Determines if a user is permitted to send another user a private message.
      * If no sender is provided then it defaults to the logged in user.
      *
+     * @deprecated since 3.8
+     * @todo Final deprecation in MDL-66266
      * @param \stdClass $recipient The user object.
      * @param \stdClass|null $sender The user object.
      * @return bool true if user is permitted, false otherwise.
@@ -1851,22 +1853,37 @@ class api {
     public static function can_post_message($recipient, $sender = null) {
         global $USER;
 
+        debugging('\core_message\api::can_post_message is deprecated, please use ' .
+            '\core_message\api::can_send_message instead.', DEBUG_DEVELOPER);
+
         if (is_null($sender)) {
             // The message is from the logged in user, unless otherwise specified.
             $sender = $USER;
         }
 
+        return self::can_send_message($recipient->id, $sender->id);
+    }
+
+    /**
+     * Determines if a user is permitted to send another user a private message.
+     *
+     * @param int $recipientid The recipient user id.
+     * @param int $senderid The sender user id.
+     * @return bool true if user is permitted, false otherwise.
+     */
+    public static function can_send_message(int $recipientid, int $senderid) : bool {
         $systemcontext = \context_system::instance();
-        if (!has_capability('moodle/site:sendmessage', $systemcontext, $sender)) {
+
+        if (!has_capability('moodle/site:sendmessage', $systemcontext, $senderid)) {
             return false;
         }
 
-        if (has_capability('moodle/site:readallmessages', $systemcontext, $sender->id)) {
+        if (has_capability('moodle/site:readallmessages', $systemcontext, $senderid)) {
             return true;
         }
 
         // Check if the recipient can be messaged by the sender.
-        return (self::can_contact_user($recipient->id, $sender->id));
+        return self::can_contact_user($recipientid, $senderid);
     }
 
     /**
diff --git a/message/classes/helper.php b/message/classes/helper.php
index 5136ce81f2c..e1440ee6738 100644
--- a/message/classes/helper.php
+++ b/message/classes/helper.php
@@ -592,14 +592,7 @@ class helper {
             if ($includeprivacyinfo) {
                 $privacysetting = api::get_user_privacy_messaging_preference($member->id);
                 $data->requirescontact = $privacysetting == api::MESSAGE_PRIVACY_ONLYCONTACTS;
-
-                $recipient = new \stdClass();
-                $recipient->id = $member->id;
-
-                $sender = new \stdClass();
-                $sender->id = $referenceuserid;
-
-                $data->canmessage = !$data->isdeleted && api::can_post_message($recipient, $sender);
+                $data->canmessage = !$data->isdeleted && api::can_send_message($member->id, $referenceuserid);
             }
 
             // Populate the contact requests, even if we don't need them.
diff --git a/message/externallib.php b/message/externallib.php
index 9e61d2b087d..6933c20208d 100644
--- a/message/externallib.php
+++ b/message/externallib.php
@@ -189,7 +189,7 @@ class core_message_external extends external_api {
 
             // TODO MDL-31118 performance improvement - edit the function so we can pass an array instead userid
             // Check if the recipient can be messaged by the sender.
-            if ($success && !\core_message\api::can_post_message($tousers[$message['touserid']], $USER)) {
+            if ($success && !\core_message\api::can_send_message($tousers[$message['touserid']]->id, $USER->id)) {
                 $success = false;
                 $errormessage = get_string('usercantbemessaged', 'message', fullname(\core_user::get_user($message['touserid'])));
             }
diff --git a/message/index.php b/message/index.php
index ebc1f2776cb..03c60bc2965 100644
--- a/message/index.php
+++ b/message/index.php
@@ -56,9 +56,7 @@ if ($userid) {
 }
 
 if ($userid) {
-    $recipient = new stdClass();
-    $recipient->id = $userid;
-    if (!\core_message\api::can_post_message($recipient)) {
+    if (!\core_message\api::can_send_message($userid, $USER->id)) {
         throw new moodle_exception('Can not contact user');
     }
 }
diff --git a/message/tests/api_test.php b/message/tests/api_test.php
index 5d13640ac19..ad5d59e93cb 100644
--- a/message/tests/api_test.php
+++ b/message/tests/api_test.php
@@ -3418,6 +3418,201 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
         $this->assertEquals(1, $prefs->mod_assign_assign_notification_loggedoff['email']);
     }
 
+    /**
+     * Tests the user can send a message.
+     */
+    public function test_can_send_message() {
+        // Create some users.
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        // Set as the first user.
+        $this->setUser($user1);
+
+        // With the default privacy setting, users can't message them.
+        $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
+
+        // Enrol users to the same course.
+        $course = $this->getDataGenerator()->create_course();
+        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
+        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
+        // After enrolling users to the course, they should be able to message them with the default privacy setting.
+        $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id));
+    }
+
+    /**
+     * Tests the user can't send a message without proper capability.
+     */
+    public function test_can_send_message_without_sendmessage_cap() {
+        global $DB;
+
+        // Create some users.
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        // Set as the user 1.
+        $this->setUser($user1);
+
+        // Remove the capability to send a message.
+        $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
+        unassign_capability('moodle/site:sendmessage', $roleids['user'],
+            context_system::instance());
+
+        // Check that we can not post a message without the capability.
+        $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
+    }
+
+    /**
+     * Tests the user can send a message when they are contact.
+     */
+    public function test_can_send_message_when_contact() {
+        // Create some users.
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        // Set as the first user.
+        $this->setUser($user1);
+
+        // Check that we can not send user2 a message.
+        $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
+
+        // Add users as contacts.
+        \core_message\api::add_contact($user1->id, $user2->id);
+
+        // Check that the return result is now true.
+        $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id));
+    }
+
+    /**
+     * Tests the user can't send a message if they are not a contact and the user
+     * has requested messages only from contacts.
+     */
+    public function test_can_send_message_when_not_contact() {
+        // Create some users.
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        // Set as the first user.
+        $this->setUser($user1);
+
+        // Set the second user's preference to not receive messages from non-contacts.
+        set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
+
+        // Check that we can not send user 2 a message.
+        $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
+    }
+
+    /**
+     * Tests the user can't send a message if they are blocked.
+     */
+    public function test_can_send_message_when_blocked() {
+        // Create some users.
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        // Set the user.
+        $this->setUser($user1);
+
+        // Block the second user.
+        \core_message\api::block_user($user1->id, $user2->id);
+
+        // Check that the second user can no longer send the first user a message.
+        $this->assertFalse(\core_message\api::can_send_message($user1->id, $user2->id));
+    }
+
+    /**
+     * Tests the user can send a message when site-wide messaging setting is enabled,
+     * even if they are not a contact and are not members of the same course.
+     */
+    public function test_can_send_message_site_messaging_setting() {
+        // Create some users.
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        // Set as the first user.
+        $this->setUser($user1);
+
+        // By default, user only can be messaged by contacts and members of any of his/her courses.
+        $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
+
+        // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody.
+        set_config('messagingallusers', true);
+
+        // Set the second user's preference to receive messages from everybody.
+        set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_SITE, $user2->id);
+
+        // Check that we can send user2 a message.
+        $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id));
+
+        // Disable site-wide messagging privacy setting. The user will be able to receive messages from contacts
+        // and members sharing a course with her.
+        set_config('messagingallusers', false);
+
+        // As site-wide messaging setting is disabled, the value for user2 will be changed to MESSAGE_PRIVACY_COURSEMEMBER.
+        $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
+
+        // Enrol users to the same course.
+        $course = $this->getDataGenerator()->create_course();
+        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
+        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
+        // Check that we can send user2 a message because they are sharing a course.
+        $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id));
+
+        // Set the second user's preference to receive messages only from contacts.
+        set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
+        // Check that now the user2 can't be contacted because user1 is not their contact.
+        $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id));
+
+        // Make contacts user1 and user2.
+        \core_message\api::add_contact($user2->id, $user1->id);
+        // Check that we can send user2 a message because they are contacts.
+        $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id));
+    }
+
+    /**
+     * Tests the user with the messageanyuser capability can send a message.
+     */
+    public function test_can_send_message_with_messageanyuser_cap() {
+        global $DB;
+
+        // Create some users.
+        $teacher1 = self::getDataGenerator()->create_user();
+        $student1 = self::getDataGenerator()->create_user();
+        $student2 = self::getDataGenerator()->create_user();
+
+        // Create users not enrolled in any course.
+        $user1 = self::getDataGenerator()->create_user();
+
+        // Create a course.
+        $course1 = $this->getDataGenerator()->create_course();
+
+        // Enrol the users in the course.
+        $this->getDataGenerator()->enrol_user($teacher1->id, $course1->id, 'editingteacher');
+        $this->getDataGenerator()->enrol_user($student1->id, $course1->id, 'student');
+        $this->getDataGenerator()->enrol_user($student2->id, $course1->id, 'student');
+
+        // Set some student preferences to not receive messages from non-contacts.
+        set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $student1->id);
+
+        // Check that we can send student1 a message because teacher has the messageanyuser cap by default.
+        $this->assertTrue(\core_message\api::can_send_message($student1->id, $teacher1->id));
+
+        // Check that the teacher can't contact user1 because it's not his teacher.
+        $this->assertFalse(\core_message\api::can_send_message($user1->id, $teacher1->id));
+
+        // Remove the messageanyuser capability from the course1 for teachers.
+        $coursecontext = context_course::instance($course1->id);
+        $teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
+        assign_capability('moodle/site:messageanyuser', CAP_PROHIBIT, $teacherrole->id, $coursecontext->id);
+        $coursecontext->mark_dirty();
+
+        // Check that we can't send user1 a message because they are not contacts.
+        $this->assertFalse(\core_message\api::can_send_message($student1->id, $teacher1->id));
+
+        // However, teacher can message student2 because they are sharing a course.
+        $this->assertTrue(\core_message\api::can_send_message($student2->id, $teacher1->id));
+    }
+
     /**
      * Tests the user can post a message.
      */
@@ -3431,6 +3626,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
 
         // With the default privacy setting, users can't message them.
         $this->assertFalse(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
 
         // Enrol users to the same course.
         $course = $this->getDataGenerator()->create_course();
@@ -3438,6 +3634,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
         // After enrolling users to the course, they should be able to message them with the default privacy setting.
         $this->assertTrue(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
     }
 
     /**
@@ -3460,6 +3657,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
 
         // Check that we can not post a message without the capability.
         $this->assertFalse(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
     }
 
     /**
@@ -3475,12 +3673,14 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
 
         // Check that we can not send user2 a message.
         $this->assertFalse(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
 
         // Add users as contacts.
         \core_message\api::add_contact($user1->id, $user2->id);
 
         // Check that the return result is now true.
         $this->assertTrue(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
     }
 
     /**
@@ -3500,6 +3700,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
 
         // Check that we can not send user 2 a message.
         $this->assertFalse(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
     }
 
     /**
@@ -3518,6 +3719,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
 
         // Check that the second user can no longer send the first user a message.
         $this->assertFalse(\core_message\api::can_post_message($user1, $user2));
+        $this->assertDebuggingCalled();
     }
 
     /**
@@ -3534,6 +3736,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
 
         // By default, user only can be messaged by contacts and members of any of his/her courses.
         $this->assertFalse(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
 
         // Enable site-wide messagging privacy setting. The user will be able to receive messages from everybody.
         set_config('messagingallusers', true);
@@ -3543,6 +3746,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
 
         // Check that we can send user2 a message.
         $this->assertTrue(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
 
         // Disable site-wide messagging privacy setting. The user will be able to receive messages from contacts
         // and members sharing a course with her.
@@ -3550,6 +3754,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
 
         // As site-wide messaging setting is disabled, the value for user2 will be changed to MESSAGE_PRIVACY_COURSEMEMBER.
         $this->assertFalse(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
 
         // Enrol users to the same course.
         $course = $this->getDataGenerator()->create_course();
@@ -3557,16 +3762,19 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
         $this->getDataGenerator()->enrol_user($user2->id, $course->id);
         // Check that we can send user2 a message because they are sharing a course.
         $this->assertTrue(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
 
         // Set the second user's preference to receive messages only from contacts.
         set_user_preference('message_blocknoncontacts', \core_message\api::MESSAGE_PRIVACY_ONLYCONTACTS, $user2->id);
         // Check that now the user2 can't be contacted because user1 is not their contact.
         $this->assertFalse(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
 
         // Make contacts user1 and user2.
         \core_message\api::add_contact($user2->id, $user1->id);
         // Check that we can send user2 a message because they are contacts.
         $this->assertTrue(\core_message\api::can_post_message($user2));
+        $this->assertDebuggingCalled();
     }
 
     /**
@@ -3596,8 +3804,10 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
 
         // Check that we can send student1 a message because teacher has the messageanyuser cap by default.
         $this->assertTrue(\core_message\api::can_post_message($student1, $teacher1));
+        $this->assertDebuggingCalled();
         // Check that the teacher can't contact user1 because it's not his teacher.
         $this->assertFalse(\core_message\api::can_post_message($user1, $teacher1));
+        $this->assertDebuggingCalled();
 
         // Remove the messageanyuser capability from the course1 for teachers.
         $coursecontext = context_course::instance($course1->id);
@@ -3607,8 +3817,10 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
 
         // Check that we can't send user1 a message because they are not contacts.
         $this->assertFalse(\core_message\api::can_post_message($student1, $teacher1));
+        $this->assertDebuggingCalled();
         // However, teacher can message student2 because they are sharing a course.
         $this->assertTrue(\core_message\api::can_post_message($student2, $teacher1));
+        $this->assertDebuggingCalled();
     }
 
     /**
diff --git a/message/upgrade.txt b/message/upgrade.txt
index 041fa20deb9..078b0641110 100644
--- a/message/upgrade.txt
+++ b/message/upgrade.txt
@@ -5,6 +5,7 @@ information provided here is intended especially for developers.
 
 * The following methods have been deprecated and should not be used any more:
   - \core_message\api::get_individual_conversations_between_users()
+  - \core_message\api::can_post_message()
 
 === 3.7 ===
 

From 90403c5d9decd165b88d5cfd1903849f9a60555e Mon Sep 17 00:00:00 2001
From: Mark Nelson <mdjnelson@gmail.com>
Date: Thu, 4 Jul 2019 14:55:30 +0800
Subject: [PATCH 2/4] MDL-65093 core_message: users can't block any user they
 want

If blocking will have no effect (ie. you are attempting to block
the admin) the 'Block' button will not be shown and instead a
message will be shown explaining why you can not block the user.
---
 lang/en/message.php                           |  1 +
 .../message_drawer_view_conversation.min.js   |  2 +-
 ...essage_drawer_view_conversation.min.js.map |  2 +-
 ...e_drawer_view_conversation_renderer.min.js |  2 +-
 ...awer_view_conversation_renderer.min.js.map |  2 +-
 ...wer_view_conversation_state_manager.min.js |  2 +-
 ...view_conversation_state_manager.min.js.map |  2 +-
 .../src/message_drawer_view_conversation.js   |  3 +-
 ...ssage_drawer_view_conversation_renderer.js | 15 ++-
 ..._drawer_view_conversation_state_manager.js |  3 +-
 message/classes/api.php                       | 12 ++-
 message/classes/helper.php                    |  5 +
 message/externallib.php                       |  7 ++
 message/tests/api_test.php                    | 92 +++++++++++++++++++
 message/tests/behat/block_user.feature        | 43 +++++++++
 message/tests/externallib_test.php            | 24 +++++
 16 files changed, 201 insertions(+), 16 deletions(-)
 create mode 100644 message/tests/behat/block_user.feature

diff --git a/lang/en/message.php b/lang/en/message.php
index e7b4d215e47..21389c4fcaf 100644
--- a/lang/en/message.php
+++ b/lang/en/message.php
@@ -39,6 +39,7 @@ $string['blockuserconfirm'] = 'Are you sure you want to block {$a}?';
 $string['blockuserconfirmbutton'] = 'Block';
 $string['blocknoncontacts'] = 'Prevent non-contacts from messaging me';
 $string['cancelselection'] = 'Cancel message selection';
+$string['cantblockuser'] = 'You are unable to block {$a} because they have a role with permission to message all users';
 $string['contactableprivacy'] = 'Accept messages from:';
 $string['contactableprivacy_onlycontacts'] = 'My contacts only';
 $string['contactableprivacy_coursemember'] = 'My contacts and anyone in my courses';
diff --git a/message/amd/build/message_drawer_view_conversation.min.js b/message/amd/build/message_drawer_view_conversation.min.js
index 65d31336d77..aa9cb9fd17b 100644
--- a/message/amd/build/message_drawer_view_conversation.min.js
+++ b/message/amd/build/message_drawer_view_conversation.min.js
@@ -1,2 +1,2 @@
-function _typeof(e){if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(e){return typeof e}}else{_typeof=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e}}return _typeof(e)}define ("core_message/message_drawer_view_conversation",["jquery","core/auto_rows","core/backoff_timer","core/custom_interaction_events","core/notification","core/pubsub","core/str","core_message/message_repository","core_message/message_drawer_events","core_message/message_drawer_view_conversation_constants","core_message/message_drawer_view_conversation_patcher","core_message/message_drawer_view_conversation_renderer","core_message/message_drawer_view_conversation_state_manager","core_message/message_drawer_router","core_message/message_drawer_routes"],function(s,e,t,n,d,a,i,r,o,g,l,m,c,E,I){var C={},u=null,_=!1,T=0,A=null,f=!1,h=[],M=!0,O=!1,N=[],v=null,S=[],p=g.NEWEST_MESSAGES_FIRST,b=g.LOAD_MESSAGE_LIMIT,U=g.MILLISECONDS_IN_SEC,L=g.SELECTORS,R=g.CONVERSATION_TYPES,D=function(){if(!u||u.type==R.PUBLIC){return null}var e=u.loggedInUserId;if(u.type==R.SELF){return e}var s=Object.keys(u.members).filter(function(s){return e!=s});return s.length?s[0]:null},y=function(e){return Object.keys(C).reduce(function(s,t){if(!s){var n=C[t].state;if(n.type!=R.PUBLIC){if(e in n.members){s=n.id}}}return s},null)},B=function(e){return{id:parseInt(e.attr("data-user-id"),10),fullname:null,profileimageurl:null,profileimageurlsmall:null,isonline:null,showonlinestatus:null,isblocked:null,iscontact:null,isdeleted:null,canmessage:null,requirescontact:null,contactrequests:[]}},F=function(){return T},P=function(e){T=e;C[u.id].messagesOffset=e},V=function(){return _},x=function(e){_=e;C[u.id].loadedAllMessages=e},w=function(e){return e.find(L.MESSAGES_CONTAINER)},k=function(e){return{id:e.id,name:e.name,subname:e.subname,imageUrl:e.imageUrl,isFavourite:e.isFavourite,isMuted:e.isMuted,type:e.type,totalMemberCount:e.totalMemberCount,loggedInUserId:e.loggedInUserId,messages:e.messages.map(function(e){return s.extend({},e)}),members:Object.keys(e.members).map(function(t){var n=s.extend({},e.members[t]);n.contactrequests=e.members[t].contactrequests.map(function(e){return s.extend({},e)});return n})}},G=function(e,s){var t=e.id,n=t==s?R.SELF:R.PRIVATE,a=c.setLoadingMembers(u,!0);a=c.setLoadingMessages(a,!0);v(a);return r.getMemberInfo(t,[s],!0,!0).then(function(e){if(e.length){return e[0]}else{throw new Error("Unable to load other user profile")}}).then(function(s){var t=n==R.SELF?[s]:[s,e],d=c.addMembers(u,t);d=c.setLoadingMembers(d,!1);d=c.setLoadingMessages(d,!1);d=c.setName(d,s.fullname);d=c.setType(d,n);d=c.setImageUrl(d,s.profileimageurl);d=c.setTotalMemberCount(d,t.length);v(d);return s}).catch(function(e){var s=c.setLoadingMembers(u,!1);v(s);d.exception(e)})},q=function(e,s){var t=null;if(e.type==R.PRIVATE){var n=e.members.filter(function(e){return e.id!=s});t=n.length?n[0]:null}else if(e.type==R.SELF){t=e.members[0]}var d=e.name,a=e.imageurl;if(e.type!=R.PUBLIC){d=d||t?t.fullname:"";a=a||t?t.profileimageurl:""}var i=c.addMembers(u,e.members);i=c.setName(i,d);i=c.setSubname(i,e.subname);i=c.setType(i,e.type);i=c.setImageUrl(i,a);i=c.setTotalMemberCount(i,e.membercount);i=c.setIsFavourite(i,e.isfavourite);i=c.setIsMuted(i,e.ismuted);i=c.addMessages(i,e.messages);i=c.setCanDeleteMessagesForAllUsers(i,e.candeletemessagesforallusers);return i},Q=function(e,s,t,n,a){var i=s.id,o=c.setLoadingMembers(u,!0);o=c.setLoadingMessages(o,!0);v(o);return r.getConversation(i,e,!0,!0,0,0,t+1,n,a).then(function(e){if(e.messages.length>t){e.messages=e.messages.slice(1)}else{x(!0)}P(n+t);return e}).then(function(e){var t=e.members.filter(function(e){return e.id==s.id});if(1>t.length){e.members=e.members.concat([s])}var n=q(e,s.id);n=c.setLoadingMembers(n,!1);n=c.setLoadingMessages(n,!1);return v(n).then(function(){return e})}).then(function(){return X(e)}).catch(function(e){var s=c.setLoadingMembers(u,!1);s=c.setLoadingMessages(s,!1);v(s);d.exception(e)})},W=function(e,s,t,n){var a=e.members.filter(function(e){return e.id==s.id});if(1>a.length){e.members=e.members.concat([s])}var i=e.messages.length,r=i>=t,o=q(e,s.id);o=c.setLoadingMembers(o,!1);o=c.setLoadingMessages(o,!r);var g=v(o);return g.then(function(){if(!r){return K(e.id,t,i,n,[])}else{return{messages:e.messages}}}).then(function(){var e=u.messages;P(e.length);X(u.id);return e}).catch(d.exception)},K=function(e,s,t,n,d,a){return r.getMessages(u.loggedInUserId,e,s?s+1:s,t,n,a).then(function(e){if(e.messages.length&&d.length){e.messages=e.messages.filter(function(e){return 0>d.indexOf(parseInt(e.id,10))})}return e}).then(function(e){if(!s){return e}else if(e.messages.length>s){e.messages=e.messages.slice(0,-1)}else{x(!0)}return e}).then(function(e){var s=e.members.filter(function(e){return!(e.id in u.members)}),t=c.addMembers(u,s);t=c.addMessages(t,e.messages);t=c.setLoadingMessages(t,!1);return v(t).then(function(){return e})}).catch(function(e){var s=c.setLoadingMessages(u,!1);v(s);throw e})},j=function(e,t){return function(){var n=u.messages,d=n.length?n[n.length-1]:null,r=d?d.timeCreated:null;if(r&&!M&&!O){for(var g=[],l=n.length-1,m;0<=l;l--){m=n[l];if(m.timeCreated===r){g.push(m.id)}else{break}}return K(e,0,0,t,g,r).then(function(s){if(s.messages.length){A.restart();var t=k(u);a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,t);return X(e)}else{return s}})}return s.Deferred().resolve().promise()}},X=function(e){var s=u.loggedInUserId;return r.markAllConversationMessagesAsRead(s,e).then(function(){var s=c.markMessagesAsRead(u,u.messages);a.publish(o.CONVERSATION_READ,e);return v(s)})},Y=function(e){le(e);var s=c.addPendingBlockUsersById(u,[e]);v(s)},H=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.blockUser(u.loggedInUserId,e).then(function(s){var t=c.addMembers(u,[s]);t=c.removePendingBlockUsersById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_BLOCKED,e);return v(t)})},z=function(e){le(e);var s=c.addPendingUnblockUsersById(u,[e]);v(s)},J=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.unblockUser(u.loggedInUserId,e).then(function(s){var t=c.addMembers(u,[s]);t=c.removePendingUnblockUsersById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_UNBLOCKED,e);return v(t)})},Z=function(e){le(e);var s=c.addPendingRemoveContactsById(u,[e]);v(s)},$=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.deleteContacts(u.loggedInUserId,[e]).then(function(s){var t=c.addMembers(u,s);t=c.removePendingRemoveContactsById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_REMOVED,e);return v(t)})},ee=function(e){le(e);var s=c.addPendingAddContactsById(u,[e]);v(s)},se=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.createContactRequest(u.loggedInUserId,e).then(function(e){if(!e.request){throw new Error(e.warnings[0].message)}return e.request}).then(function(s){var t=c.removePendingAddContactsById(u,[e]);t=c.addContactRequests(t,[s]);t=c.setLoadingConfirmAction(t,!1);return v(t)})},te=function(){var e=u.loggedInUserId,s=u.id;return r.setFavouriteConversations(e,[s]).then(function(){var e=c.setIsFavourite(u,!0);return v(e)}).then(function(){return a.publish(o.CONVERSATION_SET_FAVOURITE,k(u))})},ne=function(){var e=u.loggedInUserId,s=u.id;return r.unsetFavouriteConversations(e,[s]).then(function(){var e=c.setIsFavourite(u,!1);return v(e)}).then(function(){return a.publish(o.CONVERSATION_UNSET_FAVOURITE,k(u))})},de=function(){var e=u.loggedInUserId,s=u.id;return r.setMutedConversations(e,[s]).then(function(){var e=c.setIsMuted(u,!0);return v(e)}).then(function(){return a.publish(o.CONVERSATION_SET_MUTED,k(u))})},ae=function(){var e=u.loggedInUserId,s=u.id;return r.unsetMutedConversations(e,[s]).then(function(){var e=c.setIsMuted(u,!1);return v(e)}).then(function(){return a.publish(o.CONVERSATION_UNSET_MUTED,k(u))})},ie=function(e){var s=u.selectedMessageIds;le(e);var t=c.addPendingDeleteMessagesById(u,s);v(t)},re=function(){var e=u.pendingDeleteMessageIds,t=u.messages.filter(function(s){return 0<=e.indexOf(s.id)&&("sent"==s.sendState||null===s.sendState)}),n=c.setLoadingConfirmAction(u,!0);v(n);var i=s.Deferred().resolve().promise();if(t.length){var g=t.map(function(e){return e.id});if(n.deleteMessagesForAllUsers){i=r.deleteMessagesForAllUsers(u.loggedInUserId,g)}else{i=r.deleteMessages(u.loggedInUserId,g)}}return i.then(function(){var s=c.removeMessagesById(u,e);s=c.removePendingDeleteMessagesById(s,e);s=c.removeSelectedMessagesById(s,e);s=c.setLoadingConfirmAction(s,!1);s=c.setDeleteMessagesForAllUsers(s,!1);var t=u.messages[u.messages.length-1],n=s.messages.length?s.messages[s.messages.length-1]:null;if(n&&n.id!=t.id){var d=k(s);a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,d)}else if(!s.messages.length){a.publish(o.CONVERSATION_DELETED,s.id)}return v(s)}).catch(d.exception)},oe=function(e){le(e);var s=c.setPendingDeleteConversation(u,!0);v(s)},ge=function(){var e=c.setLoadingConfirmAction(u,!0);v(e);return r.deleteConversation(u.loggedInUserId,u.id).then(function(){var e=c.removeMessages(u,u.messages);e=c.removeSelectedMessagesById(e,u.selectedMessageIds);e=c.setPendingDeleteConversation(e,!1);e=c.setLoadingConfirmAction(e,!1);a.publish(o.CONVERSATION_DELETED,e.id);return v(e)})},le=function(e){var s=u.pendingDeleteMessageIds,t=c.removePendingAddContactsById(u,[e]);t=c.removePendingRemoveContactsById(t,[e]);t=c.removePendingUnblockUsersById(t,[e]);t=c.removePendingBlockUsersById(t,[e]);t=c.removePendingDeleteMessagesById(t,s);t=c.setPendingDeleteConversation(t,!1);t=c.setDeleteMessagesForAllUsers(t,!1);v(t)},me=function(e){var s=u.loggedInUserId,t=u.members[e].contactrequests.filter(function(e){return e.requesteduserid==s}),n=t[0],d=c.setLoadingConfirmAction(u,!0);v(d);return r.acceptContactRequest(e,s).then(function(e){var s=c.removeContactRequests(u,[n]);s=c.addMembers(u,[e]);s=c.setLoadingConfirmAction(s,!1);return v(s)}).then(function(){a.publish(o.CONTACT_ADDED,u.members[e]);a.publish(o.CONTACT_REQUEST_ACCEPTED,n)})},ce=function(e){var s=u.loggedInUserId,t=u.members[e].contactrequests.filter(function(e){return e.requesteduserid==s}),n=t[0],d=c.setLoadingConfirmAction(u,!0);v(d);return r.declineContactRequest(e,s).then(function(e){var s=c.removeContactRequests(u,[n]);s=c.addMembers(u,[e]);s=c.setLoadingConfirmAction(s,!1);return v(s)}).then(function(){a.publish(o.CONTACT_REQUEST_DECLINED,n)})},Ee=function(){if(O){return}if(!N.length){return}O=!0;var e=N.slice();N=[];var t=u.id,n=null,d=e.map(function(e){return e.text}),g=e.map(function(e){return e.id}),l=null,m=null;if(!t&&u.type!=R.PUBLIC){var E=D();l=r.sendMessagesToUser(E,d).then(function(e){if(e.length){n=parseInt(e[0].conversationid,10);m=e[0].candeletemessagesforallusers}return e})}else{l=r.sendMessagesToConversation(t,d)}l.then(function(s){var t=s.map(function(e){return e.id}),d=[],i=[],r=[];e.forEach(function(e,t){var n=s[t];d.push([e,n]);if(0<=u.selectedMessageIds.indexOf(e.id)){i.push(e.id);r.push(n.id)}});var g=c.updateMessages(u,d);g=c.setMessagesSendSuccessById(g,t);if(i.length){g=c.removeSelectedMessagesById(g,i)}if(r.length){g=c.addSelectedMessagesById(g,r)}var l=k(g);if(!g.id){g=c.setId(g,n);l.id=n;ye(n);a.publish(o.CONVERSATION_CREATED,l);g=c.setCanDeleteMessagesForAllUsers(g,m)}v(g);O=!1;Ee();a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,l)}).catch(function(t){if(t.message){var e=s.Deferred().resolve(t.message).promise()}else{var e=i.get_string("unknownerror","core")}var n=function(e){var s=c.setMessagesSendFailById(u,g,e);v(s);O=!1;Ee()};e.then(n).catch(function(s){var e=s.message||"Something went wrong!";n(e)})})},Ie=function(e){var s="temp"+Date.now(),t={id:s,useridfrom:u.loggedInUserId,text:e,timecreated:null},n=c.addMessages(u,[t]);v(n);N.push(t);Ee()},Ce=function(e){var s=c.setMessagesSendPendingById(u,[e.id]);v(s);N.push(e);Ee()},ue=function(e){var s=u;if(-1<u.selectedMessageIds.indexOf(e)){s=c.removeSelectedMessagesById(u,[e])}else{s=c.addSelectedMessagesById(u,[e])}v(s)},_e=function(){le(D());var e=c.removeSelectedMessagesById(u,u.selectedMessageIds);v(e)},Te=function(e,t,n){if(f){return}if(!h.length){return}f=!0;var a=h.shift(),i=S.map(function(e){return e(a.patch)});s.when.apply(null,i).then(function(){f=!1;a.deferred.resolve(!0);Te(e,t,n)}).catch(function(e){f=!1;a.deferred.reject(e);d.exception(e)})},Ae=function(e,t,n,d){var a=function(s){return m.render(e,t,n,s)};if(!d){var i=c.buildInitialState(u.midnight,u.loggedInUserId,u.id),r=l.buildPatch(i,u);a(r)}S.push(a);return function(d){var a=l.buildPatch(u,d),i=s.Deferred();if(Object.keys(a).length){h.push({patch:a,deferred:i})}else{i.resolve(!0)}u=d;if(d.id){C[d.id]={state:d,messagesOffset:F(),loadedAllMessages:V()}}Te(e,t,n);return i.promise()}},fe=function(e){return function(s,t){if(!u.loadingConfirmAction){e(D());var n=c.setLoadingConfirmAction(u,!1);v(n)}t.originalEvent.preventDefault()}},he=function(t,e){var n=s(t.target),d=n.closest(L.FOOTER_CONTAINER),a=d.find(L.MESSAGE_TEXT_AREA),i=a.val().trim();if(""!==i){Ie(i);a.val("");a.focus()}e.originalEvent.preventDefault()},Me=function(t,e){var n=window.getSelection(),d=s(t.target);if(""!=n.toString()){return}if(d.is("a")){return}var a=d.closest(L.MESSAGE),i=a.attr("data-message-id");ue(i);e.originalEvent.preventDefault()},Oe=function(t,e){var n=s(t.target),d=n.closest(L.MESSAGE),a=d.attr("data-message-id"),i=u.messages.filter(function(e){return e.id==a}),r=i.length?i[0]:null;if(r){Ce(r)}e.originalEvent.preventDefault();e.originalEvent.stopPropagation();t.stopPropagation()},Ne=function(s,e){_e();e.originalEvent.preventDefault()},ve=function(s){return function(t,e){var n=D(),d=u.members[n];E.go(s,I.VIEW_CONTACT,d);e.originalEvent.preventDefault()}},Se=function(s,e){te().catch(d.exception);e.originalEvent.preventDefault()},pe=function(s,e){ne().catch(d.exception);e.originalEvent.preventDefault()},be=function(s,e){de().catch(d.exception);e.originalEvent.preventDefault()},Ue=function(s,e){ae().catch(d.exception);e.originalEvent.preventDefault()},Le=function(t){var e=s(t.target).prop("checked"),n=c.setDeleteMessagesForAllUsers(u,e);v(n)},Re=function(s){return function(t,e){E.go(s,I.VIEW_GROUP_INFO,{id:u.id,name:u.name,subname:u.subname,imageUrl:u.imageUrl,totalMemberCount:u.totalMemberCount},u.loggedInUserId);e.originalEvent.preventDefault()}},De=function(s,t,i,r){var g=!1,l=w(i),m=[[L.ACTION_REQUEST_BLOCK,fe(Y)],[L.ACTION_REQUEST_UNBLOCK,fe(z)],[L.ACTION_REQUEST_ADD_CONTACT,fe(ee)],[L.ACTION_REQUEST_REMOVE_CONTACT,fe(Z)],[L.ACTION_REQUEST_DELETE_CONVERSATION,fe(oe)],[L.ACTION_CANCEL_EDIT_MODE,Ne],[L.ACTION_VIEW_CONTACT,ve(s)],[L.ACTION_VIEW_GROUP_INFO,Re(s)],[L.ACTION_CONFIRM_FAVOURITE,Se],[L.ACTION_CONFIRM_MUTE,be],[L.ACTION_CONFIRM_UNFAVOURITE,pe],[L.ACTION_CONFIRM_UNMUTE,Ue]],E=[[L.ACTION_CANCEL_CONFIRM,fe(le)],[L.ACTION_CONFIRM_BLOCK,fe(H)],[L.ACTION_CONFIRM_UNBLOCK,fe(J)],[L.ACTION_CONFIRM_ADD_CONTACT,fe(se)],[L.ACTION_CONFIRM_REMOVE_CONTACT,fe($)],[L.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES,fe(re)],[L.ACTION_CONFIRM_DELETE_CONVERSATION,fe(ge)],[L.ACTION_REQUEST_ADD_CONTACT,fe(ee)],[L.ACTION_ACCEPT_CONTACT_REQUEST,fe(me)],[L.ACTION_DECLINE_CONTACT_REQUEST,fe(ce)],[L.MESSAGE,Me],[L.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE,Le],[L.RETRY_SEND,Oe]],C=[[L.SEND_MESSAGE_BUTTON,he],[L.ACTION_REQUEST_DELETE_SELECTED_MESSAGES,fe(ie)],[L.ACTION_REQUEST_ADD_CONTACT,fe(ee)],[L.ACTION_REQUEST_UNBLOCK,fe(z)]];e.init(r);n.define(t,[n.events.activate]);n.define(i,[n.events.activate]);n.define(r,[n.events.activate,n.events.enter]);n.define(l,[n.events.scrollTop,n.events.scrollLock]);l.on(n.events.scrollTop,function(s,e){var t=1<Object.keys(u.members).length;if(!M&&!g&&!V()&&t){g=!0;var n=c.setLoadingMessages(u,!0);v(n);K(u.id,b,F(),p,[]).then(function(){g=!1;P(F()+b)}).catch(function(e){g=!1;d.exception(e)})}e.originalEvent.preventDefault()});m.forEach(function(e){var s=e[0],d=e[1];t.on(n.events.activate,s,d)});E.forEach(function(e){var s=e[0],t=e[1];i.on(n.events.activate,s,t)});C.forEach(function(e){var s=e[0],t=e[1];r.on(n.events.activate,s,t)});r.on(n.events.enter,L.MESSAGE_TEXT_AREA,function(s,e){var t=r.attr("data-enter-to-send");if(t&&"false"!=t&&"0"!=t){he(s,e)}});a.subscribe(o.ROUTE_CHANGED,function(e){if(A){if(e.route!=I.VIEW_CONVERSATION){A.stop()}}})},ye=function(e){if(A){A.stop()}A=new t(j(e,p),t.getIncrementalCallback(u.messagePollMin*U,U,u.messagePollMax*U,u.messagePollAfterMax*U));A.start()},Be=function(e,s,t){_=!1;T=0;A=null;f=!1;h=[];M=!0;O=!1;N=[];var n=t.id,d=parseInt(e.attr("data-midnight"),10),a=parseInt(e.attr("data-message-poll-min"),10),i=parseInt(e.attr("data-message-poll-max"),10),r=parseInt(e.attr("data-message-poll-after-max"),10),o=c.buildInitialState(d,n,s,a,i,r);if(!u){u=o}if(A){A.stop()}v(o)},Fe=function(e,s,t){Be(e,null,s);var n=null;if(s.id!=t){n=r.getConversationBetweenUsers(s.id,t,!0,!0,0,0,b,0,p)}else{n=r.getSelfConversation(s.id,b,0,p)}return n.then(function(t){return Ve(e,t,s)}).catch(function(){return G(s,t)})},Pe=function(e,t,n){var d=null;if(t in C){d=C[t]}Be(e,t,n);var a=s.Deferred().resolve({}).promise();if(d){var i=d.state;i=c.setLoadingMessages(i,!1);i=c.setLoadingMembers(i,!1);P(d.messagesOffset);x(d.loadedAllMessages);v(i)}else{a=Q(t,n,b,0,p)}return a.then(function(){return ye(t)})},Ve=function(e,t,n){var d=null;if(t.id in C){d=C[t.id]}Be(e,t.id,n);var a=s.Deferred().resolve({}).promise();if(d){var i=d.state;i=c.setLoadingMessages(i,!1);i=c.setLoadingMembers(i,!1);P(d.messagesOffset);x(d.loadedAllMessages);v(i)}else{a=W(t,n,b,p)}return a.then(function(){return ye(t.id)})},xe=function(e,t,n,a,i,r,o){var l=null,m=null;if(i&&null!==i&&"object"==_typeof(i)){l=i;m=parseInt(l.id,10)}else{l=null;m=parseInt(i,10);m=isNaN(m)?null:m}if(!m&&r&&o){m=y(o)}var c=!u||u.id!=m||o&&o!=D();if(!n.attr("data-init")){v=Ae(t,n,a,c);De(e,t,n,a);n.attr("data-init",!0)}if(c){var E=null,I=B(n);if(l){E=Ve(n,l,I,o)}else if(m){E=Pe(n,m,I,o)}else{E=Fe(n,I,o)}return E.then(function(){M=!1;t.find(g.SELECTORS.CAN_RECEIVE_FOCUS).first().focus()}).catch(function(e){M=!1;d.exception(e)})}ye(m);if(u.type==R.PRIVATE&&r){var C=D();switch(r){case"block":return Y(C);case"unblock":return z(C);case"add-contact":return ee(C);case"remove-contact":return Z(C);}}return s.Deferred().resolve().promise()},we=function(){return i.get_string("messagedrawerviewconversation","core_message",u.name)};return{show:xe,description:we}});
+function _typeof(e){if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(e){return typeof e}}else{_typeof=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e}}return _typeof(e)}define ("core_message/message_drawer_view_conversation",["jquery","core/auto_rows","core/backoff_timer","core/custom_interaction_events","core/notification","core/pubsub","core/str","core_message/message_repository","core_message/message_drawer_events","core_message/message_drawer_view_conversation_constants","core_message/message_drawer_view_conversation_patcher","core_message/message_drawer_view_conversation_renderer","core_message/message_drawer_view_conversation_state_manager","core_message/message_drawer_router","core_message/message_drawer_routes"],function(s,e,t,n,d,a,i,r,o,g,l,m,c,E,I){var C={},u=null,_=!1,T=0,f=null,A=!1,h=[],M=!0,O=!1,N=[],v=null,S=[],p=g.NEWEST_MESSAGES_FIRST,b=g.LOAD_MESSAGE_LIMIT,U=g.MILLISECONDS_IN_SEC,L=g.SELECTORS,R=g.CONVERSATION_TYPES,D=function(){if(!u||u.type==R.PUBLIC){return null}var e=u.loggedInUserId;if(u.type==R.SELF){return e}var s=Object.keys(u.members).filter(function(s){return e!=s});return s.length?s[0]:null},y=function(e){return Object.keys(C).reduce(function(s,t){if(!s){var n=C[t].state;if(n.type!=R.PUBLIC){if(e in n.members){s=n.id}}}return s},null)},B=function(e){return{id:parseInt(e.attr("data-user-id"),10),fullname:null,profileimageurl:null,profileimageurlsmall:null,isonline:null,showonlinestatus:null,isblocked:null,iscontact:null,isdeleted:null,canmessage:null,canmessageevenifblocked:null,requirescontact:null,contactrequests:[]}},F=function(){return T},P=function(e){T=e;C[u.id].messagesOffset=e},V=function(){return _},x=function(e){_=e;C[u.id].loadedAllMessages=e},w=function(e){return e.find(L.MESSAGES_CONTAINER)},k=function(e){return{id:e.id,name:e.name,subname:e.subname,imageUrl:e.imageUrl,isFavourite:e.isFavourite,isMuted:e.isMuted,type:e.type,totalMemberCount:e.totalMemberCount,loggedInUserId:e.loggedInUserId,messages:e.messages.map(function(e){return s.extend({},e)}),members:Object.keys(e.members).map(function(t){var n=s.extend({},e.members[t]);n.contactrequests=e.members[t].contactrequests.map(function(e){return s.extend({},e)});return n})}},G=function(e,s){var t=e.id,n=t==s?R.SELF:R.PRIVATE,a=c.setLoadingMembers(u,!0);a=c.setLoadingMessages(a,!0);v(a);return r.getMemberInfo(t,[s],!0,!0).then(function(e){if(e.length){return e[0]}else{throw new Error("Unable to load other user profile")}}).then(function(s){var t=n==R.SELF?[s]:[s,e],d=c.addMembers(u,t);d=c.setLoadingMembers(d,!1);d=c.setLoadingMessages(d,!1);d=c.setName(d,s.fullname);d=c.setType(d,n);d=c.setImageUrl(d,s.profileimageurl);d=c.setTotalMemberCount(d,t.length);v(d);return s}).catch(function(e){var s=c.setLoadingMembers(u,!1);v(s);d.exception(e)})},q=function(e,s){var t=null;if(e.type==R.PRIVATE){var n=e.members.filter(function(e){return e.id!=s});t=n.length?n[0]:null}else if(e.type==R.SELF){t=e.members[0]}var d=e.name,a=e.imageurl;if(e.type!=R.PUBLIC){d=d||t?t.fullname:"";a=a||t?t.profileimageurl:""}var i=c.addMembers(u,e.members);i=c.setName(i,d);i=c.setSubname(i,e.subname);i=c.setType(i,e.type);i=c.setImageUrl(i,a);i=c.setTotalMemberCount(i,e.membercount);i=c.setIsFavourite(i,e.isfavourite);i=c.setIsMuted(i,e.ismuted);i=c.addMessages(i,e.messages);i=c.setCanDeleteMessagesForAllUsers(i,e.candeletemessagesforallusers);return i},Q=function(e,s,t,n,a){var i=s.id,o=c.setLoadingMembers(u,!0);o=c.setLoadingMessages(o,!0);v(o);return r.getConversation(i,e,!0,!0,0,0,t+1,n,a).then(function(e){if(e.messages.length>t){e.messages=e.messages.slice(1)}else{x(!0)}P(n+t);return e}).then(function(e){var t=e.members.filter(function(e){return e.id==s.id});if(1>t.length){e.members=e.members.concat([s])}var n=q(e,s.id);n=c.setLoadingMembers(n,!1);n=c.setLoadingMessages(n,!1);return v(n).then(function(){return e})}).then(function(){return X(e)}).catch(function(e){var s=c.setLoadingMembers(u,!1);s=c.setLoadingMessages(s,!1);v(s);d.exception(e)})},W=function(e,s,t,n){var a=e.members.filter(function(e){return e.id==s.id});if(1>a.length){e.members=e.members.concat([s])}var i=e.messages.length,r=i>=t,o=q(e,s.id);o=c.setLoadingMembers(o,!1);o=c.setLoadingMessages(o,!r);var g=v(o);return g.then(function(){if(!r){return K(e.id,t,i,n,[])}else{return{messages:e.messages}}}).then(function(){var e=u.messages;P(e.length);X(u.id);return e}).catch(d.exception)},K=function(e,s,t,n,d,a){return r.getMessages(u.loggedInUserId,e,s?s+1:s,t,n,a).then(function(e){if(e.messages.length&&d.length){e.messages=e.messages.filter(function(e){return 0>d.indexOf(parseInt(e.id,10))})}return e}).then(function(e){if(!s){return e}else if(e.messages.length>s){e.messages=e.messages.slice(0,-1)}else{x(!0)}return e}).then(function(e){var s=e.members.filter(function(e){return!(e.id in u.members)}),t=c.addMembers(u,s);t=c.addMessages(t,e.messages);t=c.setLoadingMessages(t,!1);return v(t).then(function(){return e})}).catch(function(e){var s=c.setLoadingMessages(u,!1);v(s);throw e})},j=function(e,t){return function(){var n=u.messages,d=n.length?n[n.length-1]:null,r=d?d.timeCreated:null;if(r&&!M&&!O){for(var g=[],l=n.length-1,m;0<=l;l--){m=n[l];if(m.timeCreated===r){g.push(m.id)}else{break}}return K(e,0,0,t,g,r).then(function(s){if(s.messages.length){f.restart();var t=k(u);a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,t);return X(e)}else{return s}})}return s.Deferred().resolve().promise()}},X=function(e){var s=u.loggedInUserId;return r.markAllConversationMessagesAsRead(s,e).then(function(){var s=c.markMessagesAsRead(u,u.messages);a.publish(o.CONVERSATION_READ,e);return v(s)})},Y=function(e){le(e);var s=c.addPendingBlockUsersById(u,[e]);v(s)},H=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.blockUser(u.loggedInUserId,e).then(function(s){var t=c.addMembers(u,[s]);t=c.removePendingBlockUsersById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_BLOCKED,e);return v(t)})},z=function(e){le(e);var s=c.addPendingUnblockUsersById(u,[e]);v(s)},J=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.unblockUser(u.loggedInUserId,e).then(function(s){var t=c.addMembers(u,[s]);t=c.removePendingUnblockUsersById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_UNBLOCKED,e);return v(t)})},Z=function(e){le(e);var s=c.addPendingRemoveContactsById(u,[e]);v(s)},$=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.deleteContacts(u.loggedInUserId,[e]).then(function(s){var t=c.addMembers(u,s);t=c.removePendingRemoveContactsById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_REMOVED,e);return v(t)})},ee=function(e){le(e);var s=c.addPendingAddContactsById(u,[e]);v(s)},se=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.createContactRequest(u.loggedInUserId,e).then(function(e){if(!e.request){throw new Error(e.warnings[0].message)}return e.request}).then(function(s){var t=c.removePendingAddContactsById(u,[e]);t=c.addContactRequests(t,[s]);t=c.setLoadingConfirmAction(t,!1);return v(t)})},te=function(){var e=u.loggedInUserId,s=u.id;return r.setFavouriteConversations(e,[s]).then(function(){var e=c.setIsFavourite(u,!0);return v(e)}).then(function(){return a.publish(o.CONVERSATION_SET_FAVOURITE,k(u))})},ne=function(){var e=u.loggedInUserId,s=u.id;return r.unsetFavouriteConversations(e,[s]).then(function(){var e=c.setIsFavourite(u,!1);return v(e)}).then(function(){return a.publish(o.CONVERSATION_UNSET_FAVOURITE,k(u))})},de=function(){var e=u.loggedInUserId,s=u.id;return r.setMutedConversations(e,[s]).then(function(){var e=c.setIsMuted(u,!0);return v(e)}).then(function(){return a.publish(o.CONVERSATION_SET_MUTED,k(u))})},ae=function(){var e=u.loggedInUserId,s=u.id;return r.unsetMutedConversations(e,[s]).then(function(){var e=c.setIsMuted(u,!1);return v(e)}).then(function(){return a.publish(o.CONVERSATION_UNSET_MUTED,k(u))})},ie=function(e){var s=u.selectedMessageIds;le(e);var t=c.addPendingDeleteMessagesById(u,s);v(t)},re=function(){var e=u.pendingDeleteMessageIds,t=u.messages.filter(function(s){return 0<=e.indexOf(s.id)&&("sent"==s.sendState||null===s.sendState)}),n=c.setLoadingConfirmAction(u,!0);v(n);var i=s.Deferred().resolve().promise();if(t.length){var g=t.map(function(e){return e.id});if(n.deleteMessagesForAllUsers){i=r.deleteMessagesForAllUsers(u.loggedInUserId,g)}else{i=r.deleteMessages(u.loggedInUserId,g)}}return i.then(function(){var s=c.removeMessagesById(u,e);s=c.removePendingDeleteMessagesById(s,e);s=c.removeSelectedMessagesById(s,e);s=c.setLoadingConfirmAction(s,!1);s=c.setDeleteMessagesForAllUsers(s,!1);var t=u.messages[u.messages.length-1],n=s.messages.length?s.messages[s.messages.length-1]:null;if(n&&n.id!=t.id){var d=k(s);a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,d)}else if(!s.messages.length){a.publish(o.CONVERSATION_DELETED,s.id)}return v(s)}).catch(d.exception)},oe=function(e){le(e);var s=c.setPendingDeleteConversation(u,!0);v(s)},ge=function(){var e=c.setLoadingConfirmAction(u,!0);v(e);return r.deleteConversation(u.loggedInUserId,u.id).then(function(){var e=c.removeMessages(u,u.messages);e=c.removeSelectedMessagesById(e,u.selectedMessageIds);e=c.setPendingDeleteConversation(e,!1);e=c.setLoadingConfirmAction(e,!1);a.publish(o.CONVERSATION_DELETED,e.id);return v(e)})},le=function(e){var s=u.pendingDeleteMessageIds,t=c.removePendingAddContactsById(u,[e]);t=c.removePendingRemoveContactsById(t,[e]);t=c.removePendingUnblockUsersById(t,[e]);t=c.removePendingBlockUsersById(t,[e]);t=c.removePendingDeleteMessagesById(t,s);t=c.setPendingDeleteConversation(t,!1);t=c.setDeleteMessagesForAllUsers(t,!1);v(t)},me=function(e){var s=u.loggedInUserId,t=u.members[e].contactrequests.filter(function(e){return e.requesteduserid==s}),n=t[0],d=c.setLoadingConfirmAction(u,!0);v(d);return r.acceptContactRequest(e,s).then(function(e){var s=c.removeContactRequests(u,[n]);s=c.addMembers(u,[e]);s=c.setLoadingConfirmAction(s,!1);return v(s)}).then(function(){a.publish(o.CONTACT_ADDED,u.members[e]);a.publish(o.CONTACT_REQUEST_ACCEPTED,n)})},ce=function(e){var s=u.loggedInUserId,t=u.members[e].contactrequests.filter(function(e){return e.requesteduserid==s}),n=t[0],d=c.setLoadingConfirmAction(u,!0);v(d);return r.declineContactRequest(e,s).then(function(e){var s=c.removeContactRequests(u,[n]);s=c.addMembers(u,[e]);s=c.setLoadingConfirmAction(s,!1);return v(s)}).then(function(){a.publish(o.CONTACT_REQUEST_DECLINED,n)})},Ee=function(){if(O){return}if(!N.length){return}O=!0;var e=N.slice();N=[];var t=u.id,n=null,d=e.map(function(e){return e.text}),g=e.map(function(e){return e.id}),l=null,m=null;if(!t&&u.type!=R.PUBLIC){var E=D();l=r.sendMessagesToUser(E,d).then(function(e){if(e.length){n=parseInt(e[0].conversationid,10);m=e[0].candeletemessagesforallusers}return e})}else{l=r.sendMessagesToConversation(t,d)}l.then(function(s){var t=s.map(function(e){return e.id}),d=[],i=[],r=[];e.forEach(function(e,t){var n=s[t];d.push([e,n]);if(0<=u.selectedMessageIds.indexOf(e.id)){i.push(e.id);r.push(n.id)}});var g=c.updateMessages(u,d);g=c.setMessagesSendSuccessById(g,t);if(i.length){g=c.removeSelectedMessagesById(g,i)}if(r.length){g=c.addSelectedMessagesById(g,r)}var l=k(g);if(!g.id){g=c.setId(g,n);l.id=n;ye(n);a.publish(o.CONVERSATION_CREATED,l);g=c.setCanDeleteMessagesForAllUsers(g,m)}v(g);O=!1;Ee();a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,l)}).catch(function(t){if(t.message){var e=s.Deferred().resolve(t.message).promise()}else{var e=i.get_string("unknownerror","core")}var n=function(e){var s=c.setMessagesSendFailById(u,g,e);v(s);O=!1;Ee()};e.then(n).catch(function(s){var e=s.message||"Something went wrong!";n(e)})})},Ie=function(e){var s="temp"+Date.now(),t={id:s,useridfrom:u.loggedInUserId,text:e,timecreated:null},n=c.addMessages(u,[t]);v(n);N.push(t);Ee()},Ce=function(e){var s=c.setMessagesSendPendingById(u,[e.id]);v(s);N.push(e);Ee()},ue=function(e){var s=u;if(-1<u.selectedMessageIds.indexOf(e)){s=c.removeSelectedMessagesById(u,[e])}else{s=c.addSelectedMessagesById(u,[e])}v(s)},_e=function(){le(D());var e=c.removeSelectedMessagesById(u,u.selectedMessageIds);v(e)},Te=function(e,t,n){if(A){return}if(!h.length){return}A=!0;var a=h.shift(),i=S.map(function(e){return e(a.patch)});s.when.apply(null,i).then(function(){A=!1;a.deferred.resolve(!0);Te(e,t,n)}).catch(function(e){A=!1;a.deferred.reject(e);d.exception(e)})},fe=function(e,t,n,d){var a=function(s){return m.render(e,t,n,s)};if(!d){var i=c.buildInitialState(u.midnight,u.loggedInUserId,u.id),r=l.buildPatch(i,u);a(r)}S.push(a);return function(d){var a=l.buildPatch(u,d),i=s.Deferred();if(Object.keys(a).length){h.push({patch:a,deferred:i})}else{i.resolve(!0)}u=d;if(d.id){C[d.id]={state:d,messagesOffset:F(),loadedAllMessages:V()}}Te(e,t,n);return i.promise()}},Ae=function(e){return function(s,t){if(!u.loadingConfirmAction){e(D());var n=c.setLoadingConfirmAction(u,!1);v(n)}t.originalEvent.preventDefault()}},he=function(t,e){var n=s(t.target),d=n.closest(L.FOOTER_CONTAINER),a=d.find(L.MESSAGE_TEXT_AREA),i=a.val().trim();if(""!==i){Ie(i);a.val("");a.focus()}e.originalEvent.preventDefault()},Me=function(t,e){var n=window.getSelection(),d=s(t.target);if(""!=n.toString()){return}if(d.is("a")){return}var a=d.closest(L.MESSAGE),i=a.attr("data-message-id");ue(i);e.originalEvent.preventDefault()},Oe=function(t,e){var n=s(t.target),d=n.closest(L.MESSAGE),a=d.attr("data-message-id"),i=u.messages.filter(function(e){return e.id==a}),r=i.length?i[0]:null;if(r){Ce(r)}e.originalEvent.preventDefault();e.originalEvent.stopPropagation();t.stopPropagation()},Ne=function(s,e){_e();e.originalEvent.preventDefault()},ve=function(s){return function(t,e){var n=D(),d=u.members[n];E.go(s,I.VIEW_CONTACT,d);e.originalEvent.preventDefault()}},Se=function(s,e){te().catch(d.exception);e.originalEvent.preventDefault()},pe=function(s,e){ne().catch(d.exception);e.originalEvent.preventDefault()},be=function(s,e){de().catch(d.exception);e.originalEvent.preventDefault()},Ue=function(s,e){ae().catch(d.exception);e.originalEvent.preventDefault()},Le=function(t){var e=s(t.target).prop("checked"),n=c.setDeleteMessagesForAllUsers(u,e);v(n)},Re=function(s){return function(t,e){E.go(s,I.VIEW_GROUP_INFO,{id:u.id,name:u.name,subname:u.subname,imageUrl:u.imageUrl,totalMemberCount:u.totalMemberCount},u.loggedInUserId);e.originalEvent.preventDefault()}},De=function(s,t,i,r){var g=!1,l=w(i),m=[[L.ACTION_REQUEST_BLOCK,Ae(Y)],[L.ACTION_REQUEST_UNBLOCK,Ae(z)],[L.ACTION_REQUEST_ADD_CONTACT,Ae(ee)],[L.ACTION_REQUEST_REMOVE_CONTACT,Ae(Z)],[L.ACTION_REQUEST_DELETE_CONVERSATION,Ae(oe)],[L.ACTION_CANCEL_EDIT_MODE,Ne],[L.ACTION_VIEW_CONTACT,ve(s)],[L.ACTION_VIEW_GROUP_INFO,Re(s)],[L.ACTION_CONFIRM_FAVOURITE,Se],[L.ACTION_CONFIRM_MUTE,be],[L.ACTION_CONFIRM_UNFAVOURITE,pe],[L.ACTION_CONFIRM_UNMUTE,Ue]],E=[[L.ACTION_CANCEL_CONFIRM,Ae(le)],[L.ACTION_CONFIRM_BLOCK,Ae(H)],[L.ACTION_CONFIRM_UNBLOCK,Ae(J)],[L.ACTION_CONFIRM_ADD_CONTACT,Ae(se)],[L.ACTION_CONFIRM_REMOVE_CONTACT,Ae($)],[L.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES,Ae(re)],[L.ACTION_CONFIRM_DELETE_CONVERSATION,Ae(ge)],[L.ACTION_REQUEST_ADD_CONTACT,Ae(ee)],[L.ACTION_ACCEPT_CONTACT_REQUEST,Ae(me)],[L.ACTION_DECLINE_CONTACT_REQUEST,Ae(ce)],[L.MESSAGE,Me],[L.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE,Le],[L.RETRY_SEND,Oe]],C=[[L.SEND_MESSAGE_BUTTON,he],[L.ACTION_REQUEST_DELETE_SELECTED_MESSAGES,Ae(ie)],[L.ACTION_REQUEST_ADD_CONTACT,Ae(ee)],[L.ACTION_REQUEST_UNBLOCK,Ae(z)]];e.init(r);n.define(t,[n.events.activate]);n.define(i,[n.events.activate]);n.define(r,[n.events.activate,n.events.enter]);n.define(l,[n.events.scrollTop,n.events.scrollLock]);l.on(n.events.scrollTop,function(s,e){var t=1<Object.keys(u.members).length;if(!M&&!g&&!V()&&t){g=!0;var n=c.setLoadingMessages(u,!0);v(n);K(u.id,b,F(),p,[]).then(function(){g=!1;P(F()+b)}).catch(function(e){g=!1;d.exception(e)})}e.originalEvent.preventDefault()});m.forEach(function(e){var s=e[0],d=e[1];t.on(n.events.activate,s,d)});E.forEach(function(e){var s=e[0],t=e[1];i.on(n.events.activate,s,t)});C.forEach(function(e){var s=e[0],t=e[1];r.on(n.events.activate,s,t)});r.on(n.events.enter,L.MESSAGE_TEXT_AREA,function(s,e){var t=r.attr("data-enter-to-send");if(t&&"false"!=t&&"0"!=t){he(s,e)}});a.subscribe(o.ROUTE_CHANGED,function(e){if(f){if(e.route!=I.VIEW_CONVERSATION){f.stop()}}})},ye=function(e){if(f){f.stop()}f=new t(j(e,p),t.getIncrementalCallback(u.messagePollMin*U,U,u.messagePollMax*U,u.messagePollAfterMax*U));f.start()},Be=function(e,s,t){_=!1;T=0;f=null;A=!1;h=[];M=!0;O=!1;N=[];var n=t.id,d=parseInt(e.attr("data-midnight"),10),a=parseInt(e.attr("data-message-poll-min"),10),i=parseInt(e.attr("data-message-poll-max"),10),r=parseInt(e.attr("data-message-poll-after-max"),10),o=c.buildInitialState(d,n,s,a,i,r);if(!u){u=o}if(f){f.stop()}v(o)},Fe=function(e,s,t){Be(e,null,s);var n=null;if(s.id!=t){n=r.getConversationBetweenUsers(s.id,t,!0,!0,0,0,b,0,p)}else{n=r.getSelfConversation(s.id,b,0,p)}return n.then(function(t){return Ve(e,t,s)}).catch(function(){return G(s,t)})},Pe=function(e,t,n){var d=null;if(t in C){d=C[t]}Be(e,t,n);var a=s.Deferred().resolve({}).promise();if(d){var i=d.state;i=c.setLoadingMessages(i,!1);i=c.setLoadingMembers(i,!1);P(d.messagesOffset);x(d.loadedAllMessages);v(i)}else{a=Q(t,n,b,0,p)}return a.then(function(){return ye(t)})},Ve=function(e,t,n){var d=null;if(t.id in C){d=C[t.id]}Be(e,t.id,n);var a=s.Deferred().resolve({}).promise();if(d){var i=d.state;i=c.setLoadingMessages(i,!1);i=c.setLoadingMembers(i,!1);P(d.messagesOffset);x(d.loadedAllMessages);v(i)}else{a=W(t,n,b,p)}return a.then(function(){return ye(t.id)})},xe=function(e,t,n,a,i,r,o){var l=null,m=null;if(i&&null!==i&&"object"==_typeof(i)){l=i;m=parseInt(l.id,10)}else{l=null;m=parseInt(i,10);m=isNaN(m)?null:m}if(!m&&r&&o){m=y(o)}var c=!u||u.id!=m||o&&o!=D();if(!n.attr("data-init")){v=fe(t,n,a,c);De(e,t,n,a);n.attr("data-init",!0)}if(c){var E=null,I=B(n);if(l){E=Ve(n,l,I,o)}else if(m){E=Pe(n,m,I,o)}else{E=Fe(n,I,o)}return E.then(function(){M=!1;t.find(g.SELECTORS.CAN_RECEIVE_FOCUS).first().focus()}).catch(function(e){M=!1;d.exception(e)})}ye(m);if(u.type==R.PRIVATE&&r){var C=D();switch(r){case"block":return Y(C);case"unblock":return z(C);case"add-contact":return ee(C);case"remove-contact":return Z(C);}}return s.Deferred().resolve().promise()},we=function(){return i.get_string("messagedrawerviewconversation","core_message",u.name)};return{show:xe,description:we}});
 //# sourceMappingURL=message_drawer_view_conversation.min.js.map
diff --git a/message/amd/build/message_drawer_view_conversation.min.js.map b/message/amd/build/message_drawer_view_conversation.min.js.map
index 703107bad94..0cada90032e 100644
--- a/message/amd/build/message_drawer_view_conversation.min.js.map
+++ b/message/amd/build/message_drawer_view_conversation.min.js.map
@@ -1 +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","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","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","registerEventListeners","isLoadingMoreMessages","messagesContainer","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_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","events","activate","enter","scrollTop","scrollLock","on","hasMembers","handler","selector","handlerFunction","enterToSend","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],\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) {\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            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     * 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 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_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.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        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        ]);\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        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"}
\ No newline at end of file
+{"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","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","registerEventListeners","isLoadingMoreMessages","messagesContainer","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_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","events","activate","enter","scrollTop","scrollLock","on","hasMembers","handler","selector","handlerFunction","enterToSend","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],\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) {\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     * 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 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_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.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        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        ]);\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        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"}
\ No newline at end of file
diff --git a/message/amd/build/message_drawer_view_conversation_renderer.min.js b/message/amd/build/message_drawer_view_conversation_renderer.min.js
index 78699a41aeb..b9d05dddb91 100644
--- a/message/amd/build/message_drawer_view_conversation_renderer.min.js
+++ b/message/amd/build/message_drawer_view_conversation_renderer.min.js
@@ -1,2 +1,2 @@
-define ("core_message/message_drawer_view_conversation_renderer",["jquery","core/notification","core/str","core/templates","core/user_date","core_message/message_drawer_view_conversation_constants"],function(a,b,c,d,e,f){var g=f.SELECTORS,h=f.TEMPLATES,i=f.CONVERSATION_TYPES,j=function(a){return a.find(g.CONTENT_MESSAGES_CONTAINER)},k=function(a){j(a).removeClass("hidden")},l=function(a){j(a).addClass("hidden")},m=function(a){return a.find(g.SELF_CONVERSATION_MESSAGE_CONTAINER)},n=function(a){return m(a).addClass("hidden")},o=function(a){return a.find(g.CONTACT_REQUEST_SENT_MESSAGE_CONTAINER)},p=function(a){return o(a).addClass("hidden")},q=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_CONTAINER)},r=function(a){q(a).removeClass("hidden")},s=function(a){q(a).addClass("hidden")},t=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER)},u=function(a){t(a).removeClass("hidden")},v=function(a){t(a).addClass("hidden")},w=function(a){return a.find(g.PLACEHOLDER_CONTAINER)},x=function(a){w(a).removeClass("hidden")},y=function(a){w(a).addClass("hidden")},z=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER)},A=function(a){z(a).removeClass("hidden")},B=function(a){z(a).addClass("hidden")},C=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER)},D=function(a){C(a).removeClass("hidden")},E=function(a){C(a).addClass("hidden")},F=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER)},G=function(a){F(a).removeClass("hidden")},H=function(a){F(a).addClass("hidden")},I=function(a){P(a);S(a);V(a)},J=function(a){s(a);v(a);y(a);B(a);E(a);H(a)},K=function(a){return a.find(g.CONTENT_PLACEHOLDER_CONTAINER)},L=function(a){K(a).removeClass("hidden")},M=function(a){K(a).addClass("hidden")},N=function(a){return a.find(g.HEADER)},O=function(a){N(a).removeClass("hidden")},P=function(a){N(a).addClass("hidden")},Q=function(a){return a.find(g.HEADER_EDIT_MODE)},R=function(a){Q(a).removeClass("hidden")},S=function(a){Q(a).addClass("hidden")},T=function(a){return a.find(g.HEADER_PLACEHOLDER_CONTAINER)},U=function(a){T(a).removeClass("hidden")},V=function(a){T(a).addClass("hidden")},W=function(a,b){var c=j(a);return c.find("[data-message-id=\""+b+"\"]")},X=function(a,b){var c=j(a);return c.find("[data-day-id=\""+b+"\"]")},Y=function(a){return a.find(g.MORE_MESSAGES_LOADING_ICON_CONTAINER)},Z=function(a){Y(a).removeClass("hidden")},$=function(a){Y(a).addClass("hidden")},_=function(a){return a.find(g.CONFIRM_DIALOGUE_CONTAINER)},aa=function(a){var b=_(a),c=b.siblings(":not(.hidden)");c.attr("aria-hidden",!0);c.attr("tabindex",-1);c.attr("data-confirm-dialogue-hidden",!0);b.removeClass("hidden")},ba=function(a){var b=_(a),c=b.siblings("[data-confirm-dialogue-hidden=\"true\"]");c.removeAttr("aria-hidden");c.removeAttr("tabindex");c.removeAttr("data-confirm-dialogue-hidden");b.addClass("hidden")},ca=function(a,b){Q(a).find(g.MESSAGES_SELECTED_COUNT).text(b)},da=function(a,b){return a.map(function(a){return{id:a.id,isread:a.isRead,fromloggedinuser:a.fromLoggedInUser,userfrom:a.userFrom,text:a.text,formattedtime:a.timeCreated?b[a.timeCreated]:null}})},ea=function(b,c,e,f,g){var i=j(c),k=f.map(function(a){return d.render(h.DAY,{timestamp:a.value.timestamp,messages:da(a.value.messages,g)})});return a.when.apply(a,k).then(function(){f.forEach(function(b,d){k[d].then(function(d){if(b.before){var e=X(c,b.before.timestamp);return a(d).insertBefore(e)}else{return i.append(d)}}).catch(function(){})})})},fa=function(b,c,e,f,i){var j=f.map(function(a){return a.value}),k=da(j,i);return d.render(h.MESSAGES,{messages:k}).then(function(b){var d=a(b);f.forEach(function(a){var b=d.find("[data-message-id=\""+a.value.id+"\"]");if(a.before){var e=W(c,a.before.id);return b.insertBefore(e)}else{var f=X(c,a.day.timestamp),h=f.find(g.DAY_MESSAGES_CONTAINER);return h.append(b)}})})},ga=function(a,b,c,d,e){d.forEach(function(a){var c=a.before,d=a.after,f=W(b,c.id);if(c.id!=d.id){f.attr("data-message-id",d.id)}if(c.timeCreated!=d.timeCreated){var h=e[d.timeCreated];f.find(g.LOADING_ICON_CONTAINER).addClass("hidden");f.find(g.TIME_CREATED).text(h).removeClass("hidden")}if(c.sendState!=d.sendState){var i=f.find(g.LOADING_ICON_CONTAINER),j=f.find(g.TIME_CREATED),k=f.find(g.RETRY_SEND);i.addClass("hidden");i.attr("aria-hidden","true");j.addClass("hidden");j.attr("aria-hidden","true");k.addClass("hidden");k.attr("aria-hidden","true");f.removeClass("border border-danger");switch(d.sendState){case"pending":i.removeClass("hidden");i.attr("aria-hidden","false");break;case"error":k.removeClass("hidden");k.attr("aria-hidden","false");f.addClass("border border-danger");break;case"sent":j.removeClass("hidden");j.attr("aria-hidden","false");break;}}if(c.text!=d.text){f.find(g.TEXT_CONTAINER).html(d.text)}if(c.errorMessage!=d.errorMessage){var l=f.find(g.ERROR_MESSAGE_CONTAINER),a=l.find(g.ERROR_MESSAGE);if(d.errorMessage){l.removeClass("hidden");l.attr("aria-hidden","false");a.text(d.errorMessage)}else{l.addClass("hidden");l.attr("aria-hidden","true");a.text("")}}})},ha=function(a,b){b.forEach(function(b){X(a,b.timestamp).remove()})},ia=function(a,b){b.forEach(function(b){W(a,b.id).remove()})},ja=function(b,d,f,g){var h=[],i=0<g.days.add.length,j=0<g.messages.add.length,k=0<g.messages.update.length,l=[],m=a.Deferred().resolve({}).promise();if(i){l=l.concat(g.days.add.reduce(function(a,b){return a.concat(b.value.messages.reduce(function(a,b){if(b.timeCreated){a.push(b.timeCreated)}return a},[]))},[]))}if(j){l=l.concat(g.messages.add.reduce(function(a,b){if(b.value.timeCreated){a.push(b.value.timeCreated)}return a},[]))}if(k){l=l.concat(g.messages.update.reduce(function(a,b){if(b.before.timeCreated!=b.after.timeCreated){a.push(b.after.timeCreated)}return a},[]))}if(l.length){m=c.get_string("strftimetime24","core_langconfig").then(function(a){var b=l.map(function(b){return{timestamp:b,format:a}});return e.get(b)}).then(function(a){return l.reduce(function(b,c,d){b[c]=a[d];return b},{})})}if(i){h.push(m.then(function(a){return ea(b,d,f,g.days.add,a)}))}if(j){h.push(m.then(function(a){return fa(b,d,f,g.messages.add,a)}))}if(k){h.push(m.then(function(a){return ga(b,d,f,g.messages.update,a)}))}if(0<g.days.remove.length){ha(d,g.days.remove)}if(0<g.messages.remove.length){ia(d,g.messages.remove)}return a.when.apply(a,h)},ka=function(a,b,c,e){var f=N(a),g=h.HEADER_PUBLIC;e.context.showrouteback="false"===a.attr("data-from-panel");if(e.type==i.PRIVATE){g=e.showControls?h.HEADER_PRIVATE:h.HEADER_PRIVATE_NO_CONTROLS}else if(e.type==i.SELF){g=h.HEADER_SELF}return d.render(g,e.context).then(function(a,b){d.replaceNodeContents(f,a,b)})},la=function(a,b,d,e){J(d);switch(e.type){case"placeholder":return x(d);case"add-contact":return c.get_strings([{key:"requirecontacttomessage",component:"core_message",param:e.user.fullname},{key:"isnotinyourcontacts",component:"core_message",param:e.user.fullname}]).then(function(a){var b=a[1],c=a[0],e=z(d);e.find(g.TITLE).text(b);e.find(g.TEXT).text(c);A(d);return a});case"edit-mode":return u(d);case"content":return r(d);case"unblock":return D(d);case"unable-to-message":return G(d);}return!0},ma=function(a,b,c,d){var e=j(b),f=W(b,d),g=f.position();if(g){var h=e.scrollTop()+g.top;e.scrollTop(h)}},na=function(a,b,c,d){if(d){P(a);U(a)}else{O(a);V(a)}},oa=function(a,b,c,d){if(d){l(b);L(b)}else{k(b);M(b)}},pa=function(a,b,c,d){if(d){Z(b)}else{$(b)}},qa=function(a,b,c,d,e,f,h,i){var j=_(b),k=d.map(function(a){return j.find(a)}),l=j.find(g.CONFIRM_DIALOGUE_CANCEL_BUTTON),m=j.find(g.CONFIRM_DIALOGUE_TEXT),n=j.find(g.CONFIRM_DIALOGUE_HEADER);j.find("button").addClass("hidden");if(h){l.removeClass("hidden")}else{l.addClass("hidden")}if(f){n.removeClass("hidden");n.text(f)}else{n.addClass("hidden");n.text("")}k.forEach(function(a){a.removeClass("hidden")});m.text(e);aa(c);aa(b);if(!i){aa(a)}j.find(g.CAN_RECEIVE_FOCUS).filter(":visible").first().focus()},ra=function(a,b,c){var d=_(b),e=d.find(g.CONFIRM_DIALOGUE_CANCEL_BUTTON),f=d.find(g.CONFIRM_DIALOGUE_TEXT),h=d.find(g.CONFIRM_DIALOGUE_HEADER);Aa(b);ba(b);ba(c);ba(a);d.find("button").addClass("hidden");e.removeClass("hidden");f.text("");h.addClass("hidden");h.text("");a.find(g.CAN_RECEIVE_FOCUS).first().focus();return!0},sa=function(a,b,d,e){if(e){return c.get_string("blockuserconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_BLOCK],c,"",!0,!1)})}else{return ra(a,b,d)}},ta=function(a,b,d,e){if(e){return c.get_string("unblockuserconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_UNBLOCK],c,"",!0,!1)})}else{return ra(a,b,d)}},ua=function(a,b,d,e){if(e){return c.get_string("addcontactconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_ADD_CONTACT],c,"",!0,!1)})}else{return ra(a,b,d)}},va=function(a,b,d,e){if(e){return c.get_string("removecontactconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_REMOVE_CONTACT],c,"",!0,!1)})}else{return ra(a,b,d)}},wa=function(a,b,d,e){var f=null;if(e.type==i.SELF){f="deleteselectedmessagesconfirmselfconversation"}else{if(e.canDeleteMessagesForAllUsers){za(b);f="deleteforeveryoneselectedmessagesconfirm"}else{f="deleteselectedmessagesconfirm"}}if(e.show){return c.get_string(f,"core_message").then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES],c,"",!0,!1)})}else{return ra(a,b,d)}},xa=function(a,b,d,e){var f=null;if(e==i.SELF){f="deleteallselfconfirm"}else if(e){f="deleteallconfirm"}if(f){return c.get_string(f,"core_message").then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_DELETE_CONVERSATION],c,"",!0,!1)})}else{return ra(a,b,d)}},ya=function(a,b,d,e){if(e){return c.get_string("userwouldliketocontactyou","core_message",e.fullname).then(function(c){var e=[g.ACTION_ACCEPT_CONTACT_REQUEST,g.ACTION_DECLINE_CONTACT_REQUEST];return qa(a,b,d,e,c,"",!1,!0)})}else{return ra(a,b,d)}},za=function(a){var b=_(a),c=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);c.removeClass("hidden")},Aa=function(a){var b=_(a),c=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER),d=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE);d.prop("checked",!1);c.addClass("hidden")},Ba=function(a,b,c,d){if(d){a.find(g.ACTION_REQUEST_BLOCK).addClass("hidden");a.find(g.ACTION_REQUEST_UNBLOCK).removeClass("hidden")}else{a.find(g.ACTION_REQUEST_BLOCK).removeClass("hidden");a.find(g.ACTION_REQUEST_UNBLOCK).addClass("hidden")}},Ca=function(a,b,c,d){var e=a.find(g.FAVOURITE_ICON_CONTAINER),f=a.find(g.ACTION_CONFIRM_FAVOURITE),h=a.find(g.ACTION_CONFIRM_UNFAVOURITE);switch(d){case"hide":e.addClass("hidden");f.addClass("hidden");h.addClass("hidden");break;case"show-add":e.addClass("hidden");f.removeClass("hidden");h.addClass("hidden");break;case"show-remove":e.removeClass("hidden");f.addClass("hidden");h.removeClass("hidden");break;}},Da=function(a,b,c,d){var e=a.find(g.MUTED_ICON_CONTAINER),f=a.find(g.ACTION_CONFIRM_MUTE),h=a.find(g.ACTION_CONFIRM_UNMUTE);switch(d){case"hide":e.addClass("hidden");f.addClass("hidden");h.addClass("hidden");break;case"show-mute":e.addClass("hidden");f.removeClass("hidden");h.addClass("hidden");break;case"show-unmute":e.removeClass("hidden");f.addClass("hidden");h.removeClass("hidden");break;}},Ea=function(a,b,c,d){var e=a.find(g.ACTION_REQUEST_ADD_CONTACT),f=a.find(g.ACTION_REQUEST_REMOVE_CONTACT);switch(d){case"pending-contact":e.addClass("hidden");f.addClass("hidden");break;case"contact":e.addClass("hidden");f.removeClass("hidden");break;case"non-contact":e.removeClass("hidden");f.addClass("hidden");break;}},Fa=function(a,b,c,d){var e=_(b),f=e.find("button"),h=e.find(g.CONFIRM_DIALOGUE_BUTTON_TEXT),i=e.find(g.LOADING_ICON_CONTAINER);if(d){f.prop("disabled",!0);h.addClass("hidden");i.removeClass("hidden")}else{f.prop("disabled",!1);h.removeClass("hidden");i.addClass("hidden")}},Ga=function(a,b,c,d){var e=null;if(d){e=b.find(g.MESSAGE_NOT_SELECTED);e.find(g.MESSAGE_NOT_SELECTED_ICON).removeClass("hidden");P(a);R(a)}else{e=j(b);e.find(g.MESSAGE_NOT_SELECTED_ICON).addClass("hidden");e.find(g.MESSAGE_SELECTED_ICON).addClass("hidden");O(a);S(a)}},Ha=function(a,b,c,d){var e=0<d.count;if(d.add.length){d.add.forEach(function(a){var c=W(b,a);c.find(g.MESSAGE_NOT_SELECTED_ICON).addClass("hidden");c.find(g.MESSAGE_SELECTED_ICON).removeClass("hidden");c.attr("aria-checked",!0)})}if(d.remove.length){d.remove.forEach(function(a){var c=W(b,a);if(e){c.find(g.MESSAGE_NOT_SELECTED_ICON).removeClass("hidden")}c.find(g.MESSAGE_SELECTED_ICON).addClass("hidden");c.attr("aria-checked",!1)})}ca(a,d.count)},Ia=function(a,b,d,e){if(e.show&&!e.hasMessages){return c.get_strings([{key:"requirecontacttomessage",component:"core_message",param:e.user.fullname},{key:"isnotinyourcontacts",component:"core_message",param:e.user.fullname}]).then(function(c){var e=c[1],f=c[0];return qa(a,b,d,[g.ACTION_REQUEST_ADD_CONTACT],f,e,!1,!0)})}else{return ra(a,b,d)}},Ja=function(a,b,c,d){var e=m(b);if(d){e.removeClass("hidden")}else{e.addClass("hidden")}return!0},Ka=function(a,b,d,e){var f=o(b);if(e){return c.get_string("yourcontactrequestpending","core_message",e).then(function(a){f.find(g.TEXT).text(a);f.removeClass("hidden");return a})}else{f.addClass("hidden");return!0}},La=function(a,b,c){ra(a,b,c);p(b);n(b);I(a);U(a);J(c);x(c);return!0};return{render:function render(c,d,e,f){var g=[{reset:La},{conversation:ja,header:ka,footer:la,confirmBlockUser:sa,confirmUnblockUser:ta,confirmAddContact:ua,confirmRemoveContact:va,confirmDeleteSelectedMessages:wa,confirmDeleteConversation:xa,confirmContactRequest:ya,requireAddContact:Ia,selfConversationMessage:Ja,contactRequestSent:Ka},{loadingMembers:na,loadingFirstMessages:oa,loadingMessages:pa,isBlocked:Ba,isContact:Ea,isFavourite:Ca,isMuted:Da,loadingConfirmAction:Fa,inEditMode:Ga},{scrollToMessage:ma,selectedMessages:Ha}],h=function(a){var b=[];for(var g in f){if(a.hasOwnProperty(g)){var h=a[g],i=f[g];b.push(h(c,d,e,i))}}return b},i=h(g[0]);i=i.concat(h(g[1]));return a.when.apply(a,i).then(function(){for(var a=2;a<g.length;a++){h(g[a])}}).catch(b.exception)}}});
+define ("core_message/message_drawer_view_conversation_renderer",["jquery","core/notification","core/str","core/templates","core/user_date","core_message/message_drawer_view_conversation_constants"],function(a,b,c,d,e,f){var g=f.SELECTORS,h=f.TEMPLATES,i=f.CONVERSATION_TYPES,j=function(a){return a.find(g.CONTENT_MESSAGES_CONTAINER)},k=function(a){j(a).removeClass("hidden")},l=function(a){j(a).addClass("hidden")},m=function(a){return a.find(g.SELF_CONVERSATION_MESSAGE_CONTAINER)},n=function(a){return m(a).addClass("hidden")},o=function(a){return a.find(g.CONTACT_REQUEST_SENT_MESSAGE_CONTAINER)},p=function(a){return o(a).addClass("hidden")},q=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_CONTAINER)},r=function(a){q(a).removeClass("hidden")},s=function(a){q(a).addClass("hidden")},t=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER)},u=function(a){t(a).removeClass("hidden")},v=function(a){t(a).addClass("hidden")},w=function(a){return a.find(g.PLACEHOLDER_CONTAINER)},x=function(a){w(a).removeClass("hidden")},y=function(a){w(a).addClass("hidden")},z=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER)},A=function(a){z(a).removeClass("hidden")},B=function(a){z(a).addClass("hidden")},C=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER)},D=function(a){C(a).removeClass("hidden")},E=function(a){C(a).addClass("hidden")},F=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER)},G=function(a){F(a).removeClass("hidden")},H=function(a){F(a).addClass("hidden")},I=function(a){P(a);S(a);V(a)},J=function(a){s(a);v(a);y(a);B(a);E(a);H(a)},K=function(a){return a.find(g.CONTENT_PLACEHOLDER_CONTAINER)},L=function(a){K(a).removeClass("hidden")},M=function(a){K(a).addClass("hidden")},N=function(a){return a.find(g.HEADER)},O=function(a){N(a).removeClass("hidden")},P=function(a){N(a).addClass("hidden")},Q=function(a){return a.find(g.HEADER_EDIT_MODE)},R=function(a){Q(a).removeClass("hidden")},S=function(a){Q(a).addClass("hidden")},T=function(a){return a.find(g.HEADER_PLACEHOLDER_CONTAINER)},U=function(a){T(a).removeClass("hidden")},V=function(a){T(a).addClass("hidden")},W=function(a,b){var c=j(a);return c.find("[data-message-id=\""+b+"\"]")},X=function(a,b){var c=j(a);return c.find("[data-day-id=\""+b+"\"]")},Y=function(a){return a.find(g.MORE_MESSAGES_LOADING_ICON_CONTAINER)},Z=function(a){Y(a).removeClass("hidden")},$=function(a){Y(a).addClass("hidden")},_=function(a){return a.find(g.CONFIRM_DIALOGUE_CONTAINER)},aa=function(a){var b=_(a),c=b.siblings(":not(.hidden)");c.attr("aria-hidden",!0);c.attr("tabindex",-1);c.attr("data-confirm-dialogue-hidden",!0);b.removeClass("hidden")},ba=function(a){var b=_(a),c=b.siblings("[data-confirm-dialogue-hidden=\"true\"]");c.removeAttr("aria-hidden");c.removeAttr("tabindex");c.removeAttr("data-confirm-dialogue-hidden");b.addClass("hidden")},ca=function(a,b){Q(a).find(g.MESSAGES_SELECTED_COUNT).text(b)},da=function(a,b){return a.map(function(a){return{id:a.id,isread:a.isRead,fromloggedinuser:a.fromLoggedInUser,userfrom:a.userFrom,text:a.text,formattedtime:a.timeCreated?b[a.timeCreated]:null}})},ea=function(b,c,e,f,g){var i=j(c),k=f.map(function(a){return d.render(h.DAY,{timestamp:a.value.timestamp,messages:da(a.value.messages,g)})});return a.when.apply(a,k).then(function(){f.forEach(function(b,d){k[d].then(function(d){if(b.before){var e=X(c,b.before.timestamp);return a(d).insertBefore(e)}else{return i.append(d)}}).catch(function(){})})})},fa=function(b,c,e,f,i){var j=f.map(function(a){return a.value}),k=da(j,i);return d.render(h.MESSAGES,{messages:k}).then(function(b){var d=a(b);f.forEach(function(a){var b=d.find("[data-message-id=\""+a.value.id+"\"]");if(a.before){var e=W(c,a.before.id);return b.insertBefore(e)}else{var f=X(c,a.day.timestamp),h=f.find(g.DAY_MESSAGES_CONTAINER);return h.append(b)}})})},ga=function(a,b,c,d,e){d.forEach(function(a){var c=a.before,d=a.after,f=W(b,c.id);if(c.id!=d.id){f.attr("data-message-id",d.id)}if(c.timeCreated!=d.timeCreated){var h=e[d.timeCreated];f.find(g.LOADING_ICON_CONTAINER).addClass("hidden");f.find(g.TIME_CREATED).text(h).removeClass("hidden")}if(c.sendState!=d.sendState){var i=f.find(g.LOADING_ICON_CONTAINER),j=f.find(g.TIME_CREATED),k=f.find(g.RETRY_SEND);i.addClass("hidden");i.attr("aria-hidden","true");j.addClass("hidden");j.attr("aria-hidden","true");k.addClass("hidden");k.attr("aria-hidden","true");f.removeClass("border border-danger");switch(d.sendState){case"pending":i.removeClass("hidden");i.attr("aria-hidden","false");break;case"error":k.removeClass("hidden");k.attr("aria-hidden","false");f.addClass("border border-danger");break;case"sent":j.removeClass("hidden");j.attr("aria-hidden","false");break;}}if(c.text!=d.text){f.find(g.TEXT_CONTAINER).html(d.text)}if(c.errorMessage!=d.errorMessage){var l=f.find(g.ERROR_MESSAGE_CONTAINER),a=l.find(g.ERROR_MESSAGE);if(d.errorMessage){l.removeClass("hidden");l.attr("aria-hidden","false");a.text(d.errorMessage)}else{l.addClass("hidden");l.attr("aria-hidden","true");a.text("")}}})},ha=function(a,b){b.forEach(function(b){X(a,b.timestamp).remove()})},ia=function(a,b){b.forEach(function(b){W(a,b.id).remove()})},ja=function(b,d,f,g){var h=[],i=0<g.days.add.length,j=0<g.messages.add.length,k=0<g.messages.update.length,l=[],m=a.Deferred().resolve({}).promise();if(i){l=l.concat(g.days.add.reduce(function(a,b){return a.concat(b.value.messages.reduce(function(a,b){if(b.timeCreated){a.push(b.timeCreated)}return a},[]))},[]))}if(j){l=l.concat(g.messages.add.reduce(function(a,b){if(b.value.timeCreated){a.push(b.value.timeCreated)}return a},[]))}if(k){l=l.concat(g.messages.update.reduce(function(a,b){if(b.before.timeCreated!=b.after.timeCreated){a.push(b.after.timeCreated)}return a},[]))}if(l.length){m=c.get_string("strftimetime24","core_langconfig").then(function(a){var b=l.map(function(b){return{timestamp:b,format:a}});return e.get(b)}).then(function(a){return l.reduce(function(b,c,d){b[c]=a[d];return b},{})})}if(i){h.push(m.then(function(a){return ea(b,d,f,g.days.add,a)}))}if(j){h.push(m.then(function(a){return fa(b,d,f,g.messages.add,a)}))}if(k){h.push(m.then(function(a){return ga(b,d,f,g.messages.update,a)}))}if(0<g.days.remove.length){ha(d,g.days.remove)}if(0<g.messages.remove.length){ia(d,g.messages.remove)}return a.when.apply(a,h)},ka=function(a,b,c,e){var f=N(a),g=h.HEADER_PUBLIC;e.context.showrouteback="false"===a.attr("data-from-panel");if(e.type==i.PRIVATE){g=e.showControls?h.HEADER_PRIVATE:h.HEADER_PRIVATE_NO_CONTROLS}else if(e.type==i.SELF){g=h.HEADER_SELF}return d.render(g,e.context).then(function(a,b){d.replaceNodeContents(f,a,b)})},la=function(a,b,d,e){J(d);switch(e.type){case"placeholder":return x(d);case"add-contact":return c.get_strings([{key:"requirecontacttomessage",component:"core_message",param:e.user.fullname},{key:"isnotinyourcontacts",component:"core_message",param:e.user.fullname}]).then(function(a){var b=a[1],c=a[0],e=z(d);e.find(g.TITLE).text(b);e.find(g.TEXT).text(c);A(d);return a});case"edit-mode":return u(d);case"content":return r(d);case"unblock":return D(d);case"unable-to-message":return G(d);}return!0},ma=function(a,b,c,d){var e=j(b),f=W(b,d),g=f.position();if(g){var h=e.scrollTop()+g.top;e.scrollTop(h)}},na=function(a,b,c,d){if(d){P(a);U(a)}else{O(a);V(a)}},oa=function(a,b,c,d){if(d){l(b);L(b)}else{k(b);M(b)}},pa=function(a,b,c,d){if(d){Z(b)}else{$(b)}},qa=function(a,b,c,d,e,f,h,i){var j=_(b),k=d.map(function(a){return j.find(a)}),l=j.find(g.CONFIRM_DIALOGUE_CANCEL_BUTTON),m=j.find(g.CONFIRM_DIALOGUE_TEXT),n=j.find(g.CONFIRM_DIALOGUE_HEADER);j.find("button").addClass("hidden");if(h){l.removeClass("hidden")}else{l.addClass("hidden")}if(f){n.removeClass("hidden");n.text(f)}else{n.addClass("hidden");n.text("")}k.forEach(function(a){a.removeClass("hidden")});m.text(e);aa(c);aa(b);if(!i){aa(a)}j.find(g.CAN_RECEIVE_FOCUS).filter(":visible").first().focus()},ra=function(a,b,c){var d=_(b),e=d.find(g.CONFIRM_DIALOGUE_CANCEL_BUTTON),f=d.find(g.CONFIRM_DIALOGUE_TEXT),h=d.find(g.CONFIRM_DIALOGUE_HEADER);Aa(b);ba(b);ba(c);ba(a);d.find("button").addClass("hidden");e.removeClass("hidden");f.text("");h.addClass("hidden");h.text("");a.find(g.CAN_RECEIVE_FOCUS).first().focus();return!0},sa=function(a,b,d,e){if(e){if(e.canmessageevenifblocked){return c.get_string("cantblockuser","core_message",e.fullname).then(function(c){return qa(a,b,d,[],c,"",!0,!1)})}else{return c.get_string("blockuserconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_BLOCK],c,"",!0,!1)})}}else{return ra(a,b,d)}},ta=function(a,b,d,e){if(e){return c.get_string("unblockuserconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_UNBLOCK],c,"",!0,!1)})}else{return ra(a,b,d)}},ua=function(a,b,d,e){if(e){return c.get_string("addcontactconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_ADD_CONTACT],c,"",!0,!1)})}else{return ra(a,b,d)}},va=function(a,b,d,e){if(e){return c.get_string("removecontactconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_REMOVE_CONTACT],c,"",!0,!1)})}else{return ra(a,b,d)}},wa=function(a,b,d,e){var f=null;if(e.type==i.SELF){f="deleteselectedmessagesconfirmselfconversation"}else{if(e.canDeleteMessagesForAllUsers){za(b);f="deleteforeveryoneselectedmessagesconfirm"}else{f="deleteselectedmessagesconfirm"}}if(e.show){return c.get_string(f,"core_message").then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES],c,"",!0,!1)})}else{return ra(a,b,d)}},xa=function(a,b,d,e){var f=null;if(e==i.SELF){f="deleteallselfconfirm"}else if(e){f="deleteallconfirm"}if(f){return c.get_string(f,"core_message").then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_DELETE_CONVERSATION],c,"",!0,!1)})}else{return ra(a,b,d)}},ya=function(a,b,d,e){if(e){return c.get_string("userwouldliketocontactyou","core_message",e.fullname).then(function(c){var e=[g.ACTION_ACCEPT_CONTACT_REQUEST,g.ACTION_DECLINE_CONTACT_REQUEST];return qa(a,b,d,e,c,"",!1,!0)})}else{return ra(a,b,d)}},za=function(a){var b=_(a),c=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);c.removeClass("hidden")},Aa=function(a){var b=_(a),c=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER),d=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE);d.prop("checked",!1);c.addClass("hidden")},Ba=function(a,b,c,d){if(d){a.find(g.ACTION_REQUEST_BLOCK).addClass("hidden");a.find(g.ACTION_REQUEST_UNBLOCK).removeClass("hidden")}else{a.find(g.ACTION_REQUEST_BLOCK).removeClass("hidden");a.find(g.ACTION_REQUEST_UNBLOCK).addClass("hidden")}},Ca=function(a,b,c,d){var e=a.find(g.FAVOURITE_ICON_CONTAINER),f=a.find(g.ACTION_CONFIRM_FAVOURITE),h=a.find(g.ACTION_CONFIRM_UNFAVOURITE);switch(d){case"hide":e.addClass("hidden");f.addClass("hidden");h.addClass("hidden");break;case"show-add":e.addClass("hidden");f.removeClass("hidden");h.addClass("hidden");break;case"show-remove":e.removeClass("hidden");f.addClass("hidden");h.removeClass("hidden");break;}},Da=function(a,b,c,d){var e=a.find(g.MUTED_ICON_CONTAINER),f=a.find(g.ACTION_CONFIRM_MUTE),h=a.find(g.ACTION_CONFIRM_UNMUTE);switch(d){case"hide":e.addClass("hidden");f.addClass("hidden");h.addClass("hidden");break;case"show-mute":e.addClass("hidden");f.removeClass("hidden");h.addClass("hidden");break;case"show-unmute":e.removeClass("hidden");f.addClass("hidden");h.removeClass("hidden");break;}},Ea=function(a,b,c,d){var e=a.find(g.ACTION_REQUEST_ADD_CONTACT),f=a.find(g.ACTION_REQUEST_REMOVE_CONTACT);switch(d){case"pending-contact":e.addClass("hidden");f.addClass("hidden");break;case"contact":e.addClass("hidden");f.removeClass("hidden");break;case"non-contact":e.removeClass("hidden");f.addClass("hidden");break;}},Fa=function(a,b,c,d){var e=_(b),f=e.find("button"),h=e.find(g.CONFIRM_DIALOGUE_BUTTON_TEXT),i=e.find(g.LOADING_ICON_CONTAINER);if(d){f.prop("disabled",!0);h.addClass("hidden");i.removeClass("hidden")}else{f.prop("disabled",!1);h.removeClass("hidden");i.addClass("hidden")}},Ga=function(a,b,c,d){var e=null;if(d){e=b.find(g.MESSAGE_NOT_SELECTED);e.find(g.MESSAGE_NOT_SELECTED_ICON).removeClass("hidden");P(a);R(a)}else{e=j(b);e.find(g.MESSAGE_NOT_SELECTED_ICON).addClass("hidden");e.find(g.MESSAGE_SELECTED_ICON).addClass("hidden");O(a);S(a)}},Ha=function(a,b,c,d){var e=0<d.count;if(d.add.length){d.add.forEach(function(a){var c=W(b,a);c.find(g.MESSAGE_NOT_SELECTED_ICON).addClass("hidden");c.find(g.MESSAGE_SELECTED_ICON).removeClass("hidden");c.attr("aria-checked",!0)})}if(d.remove.length){d.remove.forEach(function(a){var c=W(b,a);if(e){c.find(g.MESSAGE_NOT_SELECTED_ICON).removeClass("hidden")}c.find(g.MESSAGE_SELECTED_ICON).addClass("hidden");c.attr("aria-checked",!1)})}ca(a,d.count)},Ia=function(a,b,d,e){if(e.show&&!e.hasMessages){return c.get_strings([{key:"requirecontacttomessage",component:"core_message",param:e.user.fullname},{key:"isnotinyourcontacts",component:"core_message",param:e.user.fullname}]).then(function(c){var e=c[1],f=c[0];return qa(a,b,d,[g.ACTION_REQUEST_ADD_CONTACT],f,e,!1,!0)})}else{return ra(a,b,d)}},Ja=function(a,b,c,d){var e=m(b);if(d){e.removeClass("hidden")}else{e.addClass("hidden")}return!0},Ka=function(a,b,d,e){var f=o(b);if(e){return c.get_string("yourcontactrequestpending","core_message",e).then(function(a){f.find(g.TEXT).text(a);f.removeClass("hidden");return a})}else{f.addClass("hidden");return!0}},La=function(a,b,c){ra(a,b,c);p(b);n(b);I(a);U(a);J(c);x(c);return!0};return{render:function render(c,d,e,f){var g=[{reset:La},{conversation:ja,header:ka,footer:la,confirmBlockUser:sa,confirmUnblockUser:ta,confirmAddContact:ua,confirmRemoveContact:va,confirmDeleteSelectedMessages:wa,confirmDeleteConversation:xa,confirmContactRequest:ya,requireAddContact:Ia,selfConversationMessage:Ja,contactRequestSent:Ka},{loadingMembers:na,loadingFirstMessages:oa,loadingMessages:pa,isBlocked:Ba,isContact:Ea,isFavourite:Ca,isMuted:Da,loadingConfirmAction:Fa,inEditMode:Ga},{scrollToMessage:ma,selectedMessages:Ha}],h=function(a){var b=[];for(var g in f){if(a.hasOwnProperty(g)){var h=a[g],i=f[g];b.push(h(c,d,e,i))}}return b},i=h(g[0]);i=i.concat(h(g[1]));return a.when.apply(a,i).then(function(){for(var a=2;a<g.length;a++){h(g[a])}}).catch(b.exception)}}});
 //# sourceMappingURL=message_drawer_view_conversation_renderer.min.js.map
diff --git a/message/amd/build/message_drawer_view_conversation_renderer.min.js.map b/message/amd/build/message_drawer_view_conversation_renderer.min.js.map
index 3d58f3bbaaf..e1744691539 100644
--- a/message/amd/build/message_drawer_view_conversation_renderer.min.js.map
+++ b/message/amd/build/message_drawer_view_conversation_renderer.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/message_drawer_view_conversation_renderer.js"],"names":["define","$","Notification","Str","Templates","UserDate","Constants","SELECTORS","TEMPLATES","CONVERSATION_TYPES","getMessagesContainer","body","find","CONTENT_MESSAGES_CONTAINER","showMessagesContainer","removeClass","hideMessagesContainer","addClass","getSelfConversationMessageContainer","SELF_CONVERSATION_MESSAGE_CONTAINER","hideSelfConversationMessageContainer","getContactRequestSentContainer","CONTACT_REQUEST_SENT_MESSAGE_CONTAINER","hideContactRequestSentContainer","getFooterContentContainer","footer","CONTENT_MESSAGES_FOOTER_CONTAINER","showFooterContent","hideFooterContent","getFooterEditModeContainer","CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER","showFooterEditMode","hideFooterEditMode","getFooterPlaceholderContainer","PLACEHOLDER_CONTAINER","showFooterPlaceholder","hideFooterPlaceholder","getFooterRequireContactContainer","CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER","showFooterRequireContact","hideFooterRequireContact","getFooterRequireUnblockContainer","CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER","showFooterRequireUnblock","hideFooterRequireUnblock","getFooterUnableToMessageContainer","CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER","showFooterUnableToMessage","hideFooterUnableToMessage","hideAllHeaderElements","header","hideHeaderContent","hideHeaderEditMode","hideHeaderPlaceholder","hideAllFooterElements","getContentPlaceholderContainer","CONTENT_PLACEHOLDER_CONTAINER","showContentPlaceholder","hideContentPlaceholder","getHeaderContent","HEADER","showHeaderContent","getHeaderEditMode","HEADER_EDIT_MODE","showHeaderEditMode","getHeaderPlaceholderContainer","HEADER_PLACEHOLDER_CONTAINER","showHeaderPlaceholder","getMessageElement","messageId","messagesContainer","getDayElement","dayTimeCreated","getMoreMessagesLoadingIconContainer","MORE_MESSAGES_LOADING_ICON_CONTAINER","showMoreMessagesLoadingIcon","hideMoreMessagesLoadingIcon","getConfirmDialogueContainer","root","CONFIRM_DIALOGUE_CONTAINER","showConfirmDialogueContainer","container","siblings","attr","hideConfirmDialogueContainer","removeAttr","setMessagesSelectedCount","value","MESSAGES_SELECTED_COUNT","text","formatMessagesForTemplate","messages","datesCache","map","message","id","isread","isRead","fromloggedinuser","fromLoggedInUser","userfrom","userFrom","formattedtime","timeCreated","renderAddDays","days","daysRenderPromises","data","render","DAY","timestamp","when","apply","then","forEach","index","html","before","element","insertBefore","append","catch","renderAddMessages","messagesData","formattedMessages","MESSAGES","messageList","messageHtml","dayContainer","day","dayMessagesContainer","DAY_MESSAGES_CONTAINER","renderUpdateMessages","after","formattedTime","LOADING_ICON_CONTAINER","TIME_CREATED","sendState","loading","time","retry","RETRY_SEND","TEXT_CONTAINER","errorMessage","messageContainer","ERROR_MESSAGE_CONTAINER","ERROR_MESSAGE","renderRemoveDays","remove","renderRemoveMessages","renderConversation","renderingPromises","hasAddDays","add","length","hasAddMessages","hasUpdateMessages","update","timestampsToFormat","datesCachePromise","Deferred","resolve","promise","concat","reduce","carry","timestamps","push","get_string","format","requests","get","formattedTimes","renderHeader","headerContainer","template","HEADER_PUBLIC","context","showrouteback","type","PRIVATE","showControls","HEADER_PRIVATE","HEADER_PRIVATE_NO_CONTROLS","SELF","HEADER_SELF","js","replaceNodeContents","renderFooter","get_strings","key","component","param","user","fullname","strings","title","footerContainer","TITLE","TEXT","renderScrollToMessage","messageElement","position","scrollTop","top","renderLoadingMembers","isLoadingMembers","renderLoadingFirstMessages","isLoadingFirstMessages","renderLoadingMessages","isLoading","showConfirmDialogue","buttonSelectors","bodyText","headerText","canCancel","skipHeader","dialogue","buttons","selector","cancelButton","CONFIRM_DIALOGUE_CANCEL_BUTTON","CONFIRM_DIALOGUE_TEXT","dialogueHeader","CONFIRM_DIALOGUE_HEADER","button","CAN_RECEIVE_FOCUS","filter","first","focus","hideConfirmDialogue","hideCheckDeleteDialogue","renderConfirmBlockUser","string","ACTION_CONFIRM_BLOCK","renderConfirmUnblockUser","ACTION_CONFIRM_UNBLOCK","renderConfirmAddContact","ACTION_CONFIRM_ADD_CONTACT","renderConfirmRemoveContact","ACTION_CONFIRM_REMOVE_CONTACT","renderConfirmDeleteSelectedMessages","showmessage","canDeleteMessagesForAllUsers","showCheckDeleteDialogue","show","ACTION_CONFIRM_DELETE_SELECTED_MESSAGES","renderConfirmDeleteConversation","ACTION_CONFIRM_DELETE_CONVERSATION","renderConfirmContactRequest","ACTION_ACCEPT_CONTACT_REQUEST","ACTION_DECLINE_CONTACT_REQUEST","checkboxRegion","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER","checkbox","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE","prop","renderIsBlocked","isBlocked","ACTION_REQUEST_BLOCK","ACTION_REQUEST_UNBLOCK","renderIsFavourite","state","favouriteIcon","FAVOURITE_ICON_CONTAINER","addFavourite","ACTION_CONFIRM_FAVOURITE","removeFavourite","ACTION_CONFIRM_UNFAVOURITE","renderIsMuted","muteIcon","MUTED_ICON_CONTAINER","setMuted","ACTION_CONFIRM_MUTE","unsetMuted","ACTION_CONFIRM_UNMUTE","renderIsContact","addContact","ACTION_REQUEST_ADD_CONTACT","removeContact","ACTION_REQUEST_REMOVE_CONTACT","renderLoadingConfirmAction","buttonText","CONFIRM_DIALOGUE_BUTTON_TEXT","loadingIcon","renderInEditMode","inEditMode","MESSAGE_NOT_SELECTED","MESSAGE_NOT_SELECTED_ICON","MESSAGE_SELECTED_ICON","renderSelectedMessages","hasSelectedMessages","count","renderRequireAddContact","hasMessages","renderSelfConversationMessage","displayMessage","renderContactRequestSent","userFullName","renderReset","patch","configs","reset","conversation","confirmBlockUser","confirmUnblockUser","confirmAddContact","confirmRemoveContact","confirmDeleteSelectedMessages","confirmDeleteConversation","confirmContactRequest","requireAddContact","selfConversationMessage","contactRequestSent","loadingMembers","loadingFirstMessages","loadingMessages","isContact","isFavourite","isMuted","loadingConfirmAction","scrollToMessage","selectedMessages","processConfig","config","results","hasOwnProperty","renderFunc","patchValue","i","exception"],"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 * This module updates the UI for the conversation page in the message\n * drawer.\n *\n * The module will take a patch from the message_drawer_view_conversation_patcher\n * module and update the UI to reflect the changes.\n *\n * This is the only module that ever modifies the UI of the conversation page.\n *\n * @module     core_message/message_drawer_view_conversation_renderer\n * @copyright  2018 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n    'jquery',\n    'core/notification',\n    'core/str',\n    'core/templates',\n    'core/user_date',\n    'core_message/message_drawer_view_conversation_constants'\n],\nfunction(\n    $,\n    Notification,\n    Str,\n    Templates,\n    UserDate,\n    Constants\n) {\n    var SELECTORS = Constants.SELECTORS;\n    var TEMPLATES = Constants.TEMPLATES;\n    var CONVERSATION_TYPES = Constants.CONVERSATION_TYPES;\n\n    /**\n     * Get the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getMessagesContainer = function(body) {\n        return body.find(SELECTORS.CONTENT_MESSAGES_CONTAINER);\n    };\n\n    /**\n     * Show the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showMessagesContainer = function(body) {\n        getMessagesContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideMessagesContainer = function(body) {\n        getMessagesContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the self-conversation message container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getSelfConversationMessageContainer = function(body) {\n        return body.find(SELECTORS.SELF_CONVERSATION_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Hide the self-conversation message container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var hideSelfConversationMessageContainer = function(body) {\n        return getSelfConversationMessageContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the contact request sent container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getContactRequestSentContainer = function(body) {\n        return body.find(SELECTORS.CONTACT_REQUEST_SENT_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Hide the contact request sent container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var hideContactRequestSentContainer = function(body) {\n        return getContactRequestSentContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer container element.\n     */\n    var getFooterContentContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_CONTAINER);\n    };\n\n    /**\n     * Show the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterContent = function(footer) {\n        getFooterContentContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterContent = function(footer) {\n        getFooterContentContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer container element.\n     */\n    var getFooterEditModeContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER);\n    };\n\n    /**\n     * Show the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterEditMode = function(footer) {\n        getFooterEditModeContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterEditMode = function(footer) {\n        getFooterEditModeContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer placeholder.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer placeholder container element.\n     */\n    var getFooterPlaceholderContainer = function(footer) {\n        return footer.find(SELECTORS.PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the footer placeholder\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterPlaceholder = function(footer) {\n        getFooterPlaceholderContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer placeholder\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterPlaceholder = function(footer) {\n        getFooterPlaceholderContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Require add as contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Require add as contact container element.\n     */\n    var getFooterRequireContactContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER);\n    };\n\n    /**\n     * Show the footer add as contact dialogue.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterRequireContact = function(footer) {\n        getFooterRequireContactContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer add as contact dialogue.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterRequireContact = function(footer) {\n        getFooterRequireContactContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Required to unblock contact container element.\n     */\n    var getFooterRequireUnblockContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER);\n    };\n\n    /**\n     * Show the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterRequireUnblock = function(footer) {\n        getFooterRequireUnblockContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterRequireUnblock = function(footer) {\n        getFooterRequireUnblockContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Unable to message contact container element.\n     */\n    var getFooterUnableToMessageContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Show the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterUnableToMessage = function(footer) {\n        getFooterUnableToMessageContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterUnableToMessage = function(footer) {\n        getFooterUnableToMessageContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Hide all header elements.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideAllHeaderElements = function(header) {\n        hideHeaderContent(header);\n        hideHeaderEditMode(header);\n        hideHeaderPlaceholder(header);\n    };\n\n    /**\n     * Hide all footer dialogues and messages.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideAllFooterElements = function(footer) {\n        hideFooterContent(footer);\n        hideFooterEditMode(footer);\n        hideFooterPlaceholder(footer);\n        hideFooterRequireContact(footer);\n        hideFooterRequireUnblock(footer);\n        hideFooterUnableToMessage(footer);\n    };\n\n    /**\n     * Get the content placeholder container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The body placeholder container element.\n     */\n    var getContentPlaceholderContainer = function(body) {\n        return body.find(SELECTORS.CONTENT_PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the content placeholder.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showContentPlaceholder = function(body) {\n        getContentPlaceholderContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the content placeholder.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideContentPlaceholder = function(body) {\n        getContentPlaceholderContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the header content container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header content container element.\n     */\n    var getHeaderContent = function(header) {\n        return header.find(SELECTORS.HEADER);\n    };\n\n    /**\n     * Show the header content.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderContent = function(header) {\n        getHeaderContent(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header content.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderContent = function(header) {\n        getHeaderContent(header).addClass('hidden');\n    };\n\n    /**\n     * Get the header edit mode container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header content container element.\n     */\n    var getHeaderEditMode = function(header) {\n        return header.find(SELECTORS.HEADER_EDIT_MODE);\n    };\n\n    /**\n     * Show the header edit mode container.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderEditMode = function(header) {\n        getHeaderEditMode(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header edit mode container.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderEditMode = function(header) {\n        getHeaderEditMode(header).addClass('hidden');\n    };\n\n    /**\n     * Get the header placeholder container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header placeholder container element.\n     */\n    var getHeaderPlaceholderContainer = function(header) {\n        return header.find(SELECTORS.HEADER_PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the header placeholder.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderPlaceholder = function(header) {\n        getHeaderPlaceholderContainer(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header placeholder.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderPlaceholder = function(header) {\n        getHeaderPlaceholderContainer(header).addClass('hidden');\n    };\n\n    /**\n     * Get a message element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Number} messageId the Message id.\n     * @return {Object} A message element from the conversation.\n     */\n    var getMessageElement = function(body, messageId) {\n        var messagesContainer = getMessagesContainer(body);\n        return messagesContainer.find('[data-message-id=\"' + messageId + '\"]');\n    };\n\n    /**\n     * Get the day container element. The day container element holds a list of messages for that day.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Number} dayTimeCreated Midnight timestamp for the day.\n     * @return {Object} jQuery object\n     */\n    var getDayElement = function(body, dayTimeCreated) {\n        var messagesContainer = getMessagesContainer(body);\n        return messagesContainer.find('[data-day-id=\"' + dayTimeCreated + '\"]');\n    };\n\n    /**\n     * Get the more messages loading icon container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The more messages loading container element.\n     */\n    var getMoreMessagesLoadingIconContainer = function(body) {\n        return body.find(SELECTORS.MORE_MESSAGES_LOADING_ICON_CONTAINER);\n    };\n\n    /**\n     * Show the more messages loading icon.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showMoreMessagesLoadingIcon = function(body) {\n        getMoreMessagesLoadingIconContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the more messages loading icon.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideMoreMessagesLoadingIcon = function(body) {\n        getMoreMessagesLoadingIconContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element to search.\n     * @return {Object} The confirm dialogue container element.\n     */\n    var getConfirmDialogueContainer = function(root) {\n        return root.find(SELECTORS.CONFIRM_DIALOGUE_CONTAINER);\n    };\n\n    /**\n     * Show the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element containing a dialogue.\n     */\n    var showConfirmDialogueContainer = function(root) {\n        var container = getConfirmDialogueContainer(root);\n        var siblings = container.siblings(':not(.hidden)');\n        siblings.attr('aria-hidden', true);\n        siblings.attr('tabindex', -1);\n        siblings.attr('data-confirm-dialogue-hidden', true);\n\n        container.removeClass('hidden');\n    };\n\n    /**\n     * Hide the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element containing a dialogue.\n     */\n    var hideConfirmDialogueContainer = function(root) {\n        var container = getConfirmDialogueContainer(root);\n        var siblings = container.siblings('[data-confirm-dialogue-hidden=\"true\"]');\n        siblings.removeAttr('aria-hidden');\n        siblings.removeAttr('tabindex');\n        siblings.removeAttr('data-confirm-dialogue-hidden');\n\n        container.addClass('hidden');\n    };\n\n    /**\n     * Set the number of selected messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Number} value The new number to display.\n     */\n    var setMessagesSelectedCount = function(header, value) {\n        getHeaderEditMode(header).find(SELECTORS.MESSAGES_SELECTED_COUNT).text(value);\n    };\n\n    /**\n     * Format message for the mustache template, transform camelCase properties to lowercase properties.\n     *\n     * @param  {Array} messages Array of message objects.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Array} Messages formated for mustache template.\n     */\n    var formatMessagesForTemplate = function(messages, datesCache) {\n        return messages.map(function(message) {\n            return {\n                id: message.id,\n                isread: message.isRead,\n                fromloggedinuser: message.fromLoggedInUser,\n                userfrom: message.userFrom,\n                text: message.text,\n                formattedtime: message.timeCreated ? datesCache[message.timeCreated] : null\n            };\n        });\n    };\n\n    /**\n     * Create rendering promises for each day containing messages.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} days Array of days containing messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Promise} Days rendering promises.\n     */\n    var renderAddDays = function(header, body, footer, days, datesCache) {\n        var messagesContainer = getMessagesContainer(body);\n        var daysRenderPromises = days.map(function(data) {\n            return Templates.render(TEMPLATES.DAY, {\n                timestamp: data.value.timestamp,\n                messages: formatMessagesForTemplate(data.value.messages, datesCache)\n            });\n        });\n\n        return $.when.apply($, daysRenderPromises).then(function() {\n            // Wait until all of the rendering is done for each of the days\n            // to ensure they are added to the page in the correct order.\n            days.forEach(function(data, index) {\n                daysRenderPromises[index]\n                    .then(function(html) {\n                        if (data.before) {\n                            var element = getDayElement(body, data.before.timestamp);\n                            return $(html).insertBefore(element);\n                        } else {\n                            return messagesContainer.append(html);\n                        }\n                    })\n                    .catch(function() {\n                        // Fail silently.\n                    });\n            });\n\n            return;\n        });\n    };\n\n    /**\n     * Add (more) messages to day containers.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} messages List of messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Promise} Messages rendering promises.\n     */\n    var renderAddMessages = function(header, body, footer, messages, datesCache) {\n        var messagesData = messages.map(function(data) {\n            return data.value;\n        });\n        var formattedMessages = formatMessagesForTemplate(messagesData, datesCache);\n\n        return Templates.render(TEMPLATES.MESSAGES, {messages: formattedMessages})\n            .then(function(html) {\n                var messageList = $(html);\n                messages.forEach(function(data) {\n                    var messageHtml = messageList.find('[data-message-id=\"' + data.value.id + '\"]');\n                    if (data.before) {\n                        var element = getMessageElement(body, data.before.id);\n                        return messageHtml.insertBefore(element);\n                    } else {\n                        var dayContainer = getDayElement(body, data.day.timestamp);\n                        var dayMessagesContainer = dayContainer.find(SELECTORS.DAY_MESSAGES_CONTAINER);\n                        return dayMessagesContainer.append(messageHtml);\n                    }\n                });\n\n                return;\n            });\n    };\n\n    /**\n     * Update existing messages.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} messages List of messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     */\n    var renderUpdateMessages = function(header, body, footer, messages, datesCache) {\n        messages.forEach(function(message) {\n            var before = message.before;\n            var after = message.after;\n            var element = getMessageElement(body, before.id);\n\n            if (before.id != after.id) {\n                element.attr('data-message-id', after.id);\n            }\n\n            if (before.timeCreated != after.timeCreated) {\n                var formattedTime = datesCache[after.timeCreated];\n                element.find(SELECTORS.LOADING_ICON_CONTAINER).addClass('hidden');\n                element.find(SELECTORS.TIME_CREATED).text(formattedTime).removeClass('hidden');\n            }\n\n            if (before.sendState != after.sendState) {\n                var loading = element.find(SELECTORS.LOADING_ICON_CONTAINER);\n                var time = element.find(SELECTORS.TIME_CREATED);\n                var retry = element.find(SELECTORS.RETRY_SEND);\n\n                loading.addClass('hidden');\n                loading.attr('aria-hidden', 'true');\n                time.addClass('hidden');\n                time.attr('aria-hidden', 'true');\n                retry.addClass('hidden');\n                retry.attr('aria-hidden', 'true');\n                element.removeClass('border border-danger');\n\n                switch (after.sendState) {\n                    case 'pending':\n                        loading.removeClass('hidden');\n                        loading.attr('aria-hidden', 'false');\n                        break;\n                    case 'error':\n                        retry.removeClass('hidden');\n                        retry.attr('aria-hidden', 'false');\n                        element.addClass('border border-danger');\n                        break;\n                    case 'sent':\n                        time.removeClass('hidden');\n                        time.attr('aria-hidden', 'false');\n                        break;\n                }\n            }\n\n            if (before.text != after.text) {\n                element.find(SELECTORS.TEXT_CONTAINER).html(after.text);\n            }\n\n            if (before.errorMessage != after.errorMessage) {\n                var messageContainer = element.find(SELECTORS.ERROR_MESSAGE_CONTAINER);\n                var message = messageContainer.find(SELECTORS.ERROR_MESSAGE);\n\n                if (after.errorMessage) {\n                    messageContainer.removeClass('hidden');\n                    messageContainer.attr('aria-hidden', 'false');\n                    message.text(after.errorMessage);\n                } else {\n                    messageContainer.addClass('hidden');\n                    messageContainer.attr('aria-hidden', 'true');\n                    message.text('');\n                }\n            }\n        });\n    };\n\n    /**\n     * Remove days from conversation.\n     *\n     * @param  {Object} body The body container element.\n     * @param  {Array} days Array of days to be removed.\n     */\n    var renderRemoveDays = function(body, days) {\n        days.forEach(function(data) {\n            getDayElement(body, data.timestamp).remove();\n        });\n    };\n\n    /**\n     * Remove messages from conversation.\n     *\n     * @param  {Object} body The body container element.\n     * @param  {Array} messages Array of messages to be removed.\n     */\n    var renderRemoveMessages = function(body, messages) {\n        messages.forEach(function(data) {\n            getMessageElement(body, data.id).remove();\n        });\n    };\n\n    /**\n     * Render the full conversation base on input from the statemanager.\n     *\n     * This will pre-load all of the formatted timestamps for each message that\n     * needs to render to reduce the number of networks requests.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Object} data The conversation diff.\n     * @return {Object} jQuery promise.\n     */\n    var renderConversation = function(header, body, footer, data) {\n        var renderingPromises = [];\n        var hasAddDays = data.days.add.length > 0;\n        var hasAddMessages = data.messages.add.length > 0;\n        var hasUpdateMessages = data.messages.update.length > 0;\n        var timestampsToFormat = [];\n        var datesCachePromise = $.Deferred().resolve({}).promise();\n\n        if (hasAddDays) {\n            // Search for all of the timeCreated values in all of the messages in all of\n            // the days that we need to render.\n            timestampsToFormat = timestampsToFormat.concat(data.days.add.reduce(function(carry, day) {\n                return carry.concat(day.value.messages.reduce(function(timestamps, message) {\n                    if (message.timeCreated) {\n                        timestamps.push(message.timeCreated);\n                    }\n                    return timestamps;\n                }, []));\n            }, []));\n        }\n\n        if (hasAddMessages) {\n            // Search for all of the timeCreated values in all of the messages that we\n            // need to render.\n            timestampsToFormat = timestampsToFormat.concat(data.messages.add.reduce(function(timestamps, message) {\n                if (message.value.timeCreated) {\n                    timestamps.push(message.value.timeCreated);\n                }\n                return timestamps;\n            }, []));\n        }\n\n        if (hasUpdateMessages) {\n            timestampsToFormat = timestampsToFormat.concat(data.messages.update.reduce(function(timestamps, message) {\n                if (message.before.timeCreated != message.after.timeCreated) {\n                    timestamps.push(message.after.timeCreated);\n                }\n                return timestamps;\n            }, []));\n        }\n\n        if (timestampsToFormat.length) {\n            // If we have timestamps then pre-load the formatted version of each of them\n            // in a single request to the server. This saves the templates doing multiple\n            // individual requests.\n            datesCachePromise = Str.get_string('strftimetime24', 'core_langconfig')\n                .then(function(format) {\n                    var requests = timestampsToFormat.map(function(timestamp) {\n                        return {\n                            timestamp: timestamp,\n                            format: format\n                        };\n                    });\n\n                    return UserDate.get(requests);\n                })\n                .then(function(formattedTimes) {\n                    return timestampsToFormat.reduce(function(carry, timestamp, index) {\n                        carry[timestamp] = formattedTimes[index];\n                        return carry;\n                    }, {});\n                });\n        }\n\n        if (hasAddDays) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderAddDays(header, body, footer, data.days.add, datesCache);\n            }));\n        }\n\n        if (hasAddMessages) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderAddMessages(header, body, footer, data.messages.add, datesCache);\n            }));\n        }\n\n        if (hasUpdateMessages) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderUpdateMessages(header, body, footer, data.messages.update, datesCache);\n            }));\n        }\n\n        if (data.days.remove.length > 0) {\n            renderRemoveDays(body, data.days.remove);\n        }\n\n        if (data.messages.remove.length > 0) {\n            renderRemoveMessages(body, data.messages.remove);\n        }\n\n        return $.when.apply($, renderingPromises);\n    };\n\n    /**\n     * Render the conversation header.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Data for header.\n     * @return {Object} jQuery promise\n     */\n    var renderHeader = function(header, body, footer, data) {\n        var headerContainer = getHeaderContent(header);\n        var template = TEMPLATES.HEADER_PUBLIC;\n        data.context.showrouteback = (header.attr('data-from-panel') === \"false\");\n        if (data.type == CONVERSATION_TYPES.PRIVATE) {\n            template = data.showControls ? TEMPLATES.HEADER_PRIVATE : TEMPLATES.HEADER_PRIVATE_NO_CONTROLS;\n        } else if (data.type == CONVERSATION_TYPES.SELF) {\n            template = TEMPLATES.HEADER_SELF;\n        }\n\n        return Templates.render(template, data.context)\n            .then(function(html, js) {\n                Templates.replaceNodeContents(headerContainer, html, js);\n                return;\n            });\n    };\n\n    /**\n     * Render the conversation footer.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Data for footer.\n     * @return {Object} jQuery promise.\n     */\n    var renderFooter = function(header, body, footer, data) {\n        hideAllFooterElements(footer);\n\n        switch (data.type) {\n            case 'placeholder':\n                return showFooterPlaceholder(footer);\n            case 'add-contact':\n                return Str.get_strings([\n                        {\n                            key: 'requirecontacttomessage',\n                            component: 'core_message',\n                            param: data.user.fullname\n                        },\n                        {\n                            key: 'isnotinyourcontacts',\n                            component: 'core_message',\n                            param: data.user.fullname\n                        }\n                    ])\n                    .then(function(strings) {\n                        var title = strings[1];\n                        var text = strings[0];\n                        var footerContainer = getFooterRequireContactContainer(footer);\n                        footerContainer.find(SELECTORS.TITLE).text(title);\n                        footerContainer.find(SELECTORS.TEXT).text(text);\n                        showFooterRequireContact(footer);\n                        return strings;\n                    });\n            case 'edit-mode':\n                return showFooterEditMode(footer);\n            case 'content':\n                return showFooterContent(footer);\n            case 'unblock':\n                return showFooterRequireUnblock(footer);\n            case 'unable-to-message':\n                return showFooterUnableToMessage(footer);\n        }\n\n        return true;\n    };\n\n    /**\n     * Scroll to a message in the conversation.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Number} messageId Message id.\n     */\n    var renderScrollToMessage = function(header, body, footer, messageId) {\n        var messagesContainer = getMessagesContainer(body);\n        var messageElement = getMessageElement(body, messageId);\n        var position = messageElement.position();\n        // Scroll the message container down to the top of the message element.\n        if (position) {\n            var scrollTop = messagesContainer.scrollTop() + position.top;\n            messagesContainer.scrollTop(scrollTop);\n        }\n    };\n\n    /**\n     * Hide or show the conversation header.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoadingMembers Members loading.\n     */\n    var renderLoadingMembers = function(header, body, footer, isLoadingMembers) {\n        if (isLoadingMembers) {\n            hideHeaderContent(header);\n            showHeaderPlaceholder(header);\n        } else {\n            showHeaderContent(header);\n            hideHeaderPlaceholder(header);\n        }\n    };\n\n    /**\n     * Hide or show loading conversation messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoadingFirstMessages Messages loading.\n     */\n    var renderLoadingFirstMessages = function(header, body, footer, isLoadingFirstMessages) {\n        if (isLoadingFirstMessages) {\n            hideMessagesContainer(body);\n            showContentPlaceholder(body);\n        } else {\n            showMessagesContainer(body);\n            hideContentPlaceholder(body);\n        }\n    };\n\n    /**\n     * Hide or show loading more messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoading Messages loading.\n     */\n    var renderLoadingMessages = function(header, body, footer, isLoading) {\n        if (isLoading) {\n            showMoreMessagesLoadingIcon(body);\n        } else {\n            hideMoreMessagesLoadingIcon(body);\n        }\n    };\n\n    /**\n     * Show a confirmation dialogue\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {String} buttonSelectors Selectors for the buttons to show.\n     * @param {String} bodyText Text to show in dialogue.\n     * @param {String} headerText Text to show in dialogue header.\n     * @param {Bool} canCancel Can this dialogue be cancelled.\n     * @param {Bool} skipHeader Skip blanking out the header\n     */\n    var showConfirmDialogue = function(\n        header,\n        body,\n        footer,\n        buttonSelectors,\n        bodyText,\n        headerText,\n        canCancel,\n        skipHeader\n    ) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var buttons = buttonSelectors.map(function(selector) {\n            return dialogue.find(selector);\n        });\n        var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);\n        var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);\n        var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);\n\n        dialogue.find('button').addClass('hidden');\n\n        if (canCancel) {\n            cancelButton.removeClass('hidden');\n        } else {\n            cancelButton.addClass('hidden');\n        }\n\n        if (headerText) {\n            dialogueHeader.removeClass('hidden');\n            dialogueHeader.text(headerText);\n        } else {\n            dialogueHeader.addClass('hidden');\n            dialogueHeader.text('');\n        }\n\n        buttons.forEach(function(button) {\n            button.removeClass('hidden');\n        });\n        text.text(bodyText);\n        showConfirmDialogueContainer(footer);\n        showConfirmDialogueContainer(body);\n\n        if (!skipHeader) {\n            showConfirmDialogueContainer(header);\n        }\n\n        dialogue.find(SELECTORS.CAN_RECEIVE_FOCUS).filter(':visible').first().focus();\n    };\n\n    /**\n     * Hide the dialogue\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @return {Bool} always true.\n     */\n    var hideConfirmDialogue = function(header, body, footer) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);\n        var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);\n        var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);\n\n        hideCheckDeleteDialogue(body);\n        hideConfirmDialogueContainer(body);\n        hideConfirmDialogueContainer(footer);\n        hideConfirmDialogueContainer(header);\n        dialogue.find('button').addClass('hidden');\n        cancelButton.removeClass('hidden');\n        text.text('');\n        dialogueHeader.addClass('hidden');\n        dialogueHeader.text('');\n\n        header.find(SELECTORS.CAN_RECEIVE_FOCUS).first().focus();\n        return true;\n    };\n\n    /**\n     * Render the confirm block user dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to block.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmBlockUser = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('blockuserconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_BLOCK], string, '', true, false);\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm unblock user dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to unblock.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmUnblockUser = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('unblockuserconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_UNBLOCK], string, '', true, false);\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the add user as contact dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to add as contact.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmAddContact = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('addcontactconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_ADD_CONTACT],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the remove user from contacts dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to remove from contacts.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmRemoveContact = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('removecontactconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_REMOVE_CONTACT],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the delete selected messages dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data If the dialogue should show and checkbox shows to delete message for all users.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmDeleteSelectedMessages = function(header, body, footer, data) {\n        var showmessage = null;\n        if (data.type == CONVERSATION_TYPES.SELF) {\n            // Message displayed to self-conversations is slighly different.\n            showmessage = 'deleteselectedmessagesconfirmselfconversation';\n        } else {\n            // This other message should be displayed.\n            if (data.canDeleteMessagesForAllUsers) {\n                showCheckDeleteDialogue(body);\n                showmessage = 'deleteforeveryoneselectedmessagesconfirm';\n            } else {\n                showmessage = 'deleteselectedmessagesconfirm';\n            }\n        }\n\n        if (data.show) {\n            return Str.get_string(showmessage, 'core_message')\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm delete conversation dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {int|Null} type The conversation type to be removed.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmDeleteConversation = function(header, body, footer, type) {\n        var showmessage = null;\n        if (type == CONVERSATION_TYPES.SELF) {\n            // Message displayed to self-conversations is slighly different.\n            showmessage = 'deleteallselfconfirm';\n        } else if (type) {\n            // This other message should be displayed.\n            showmessage = 'deleteallconfirm';\n        }\n\n        if (showmessage) {\n            return Str.get_string(showmessage, 'core_message')\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_DELETE_CONVERSATION],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm delete conversation dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} user The other user object.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmContactRequest = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('userwouldliketocontactyou', 'core_message', user.fullname)\n                .then(function(string) {\n                    var buttonSelectors = [\n                        SELECTORS.ACTION_ACCEPT_CONTACT_REQUEST,\n                        SELECTORS.ACTION_DECLINE_CONTACT_REQUEST\n                    ];\n                    return showConfirmDialogue(header, body, footer, buttonSelectors, string, '', false, true);\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Show the checkbox to allow delete message for all.\n     *\n     * @param {Object} body The body container element.\n     */\n    var showCheckDeleteDialogue = function(body) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var checkboxRegion = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);\n        checkboxRegion.removeClass('hidden');\n    };\n\n    /**\n     * Hide the checkbox to allow delete message for all.\n     *\n     * @param {Object} body The body container element.\n     */\n    var hideCheckDeleteDialogue = function(body) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var checkboxRegion = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);\n        var checkbox = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE);\n        checkbox.prop('checked', false);\n        checkboxRegion.addClass('hidden');\n    };\n\n    /**\n     * Show or hide the block / unblock option in the header dropdown menu.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isBlocked is user blocked.\n     */\n    var renderIsBlocked = function(header, body, footer, isBlocked) {\n        if (isBlocked) {\n            header.find(SELECTORS.ACTION_REQUEST_BLOCK).addClass('hidden');\n            header.find(SELECTORS.ACTION_REQUEST_UNBLOCK).removeClass('hidden');\n        } else {\n            header.find(SELECTORS.ACTION_REQUEST_BLOCK).removeClass('hidden');\n            header.find(SELECTORS.ACTION_REQUEST_UNBLOCK).addClass('hidden');\n        }\n    };\n\n    /**\n     * Show or hide the favourite / unfavourite option in the header dropdown menu\n     * and the favourite star in the header title.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isFavourite is this conversation a favourite.\n     */\n    var renderIsFavourite = function(header, body, footer, state) {\n        var favouriteIcon = header.find(SELECTORS.FAVOURITE_ICON_CONTAINER);\n        var addFavourite = header.find(SELECTORS.ACTION_CONFIRM_FAVOURITE);\n        var removeFavourite = header.find(SELECTORS.ACTION_CONFIRM_UNFAVOURITE);\n\n        switch (state) {\n            case 'hide':\n                favouriteIcon.addClass('hidden');\n                addFavourite.addClass('hidden');\n                removeFavourite.addClass('hidden');\n                break;\n            case 'show-add':\n                favouriteIcon.addClass('hidden');\n                addFavourite.removeClass('hidden');\n                removeFavourite.addClass('hidden');\n                break;\n            case 'show-remove':\n                favouriteIcon.removeClass('hidden');\n                addFavourite.addClass('hidden');\n                removeFavourite.removeClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide the mute / unmute option in the header dropdown menu\n     * and the muted icon in the header title.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {string} state The state of the conversation as defined by the patcher.\n     */\n    var renderIsMuted = function(header, body, footer, state) {\n        var muteIcon = header.find(SELECTORS.MUTED_ICON_CONTAINER);\n        var setMuted = header.find(SELECTORS.ACTION_CONFIRM_MUTE);\n        var unsetMuted = header.find(SELECTORS.ACTION_CONFIRM_UNMUTE);\n\n        switch (state) {\n            case 'hide':\n                muteIcon.addClass('hidden');\n                setMuted.addClass('hidden');\n                unsetMuted.addClass('hidden');\n                break;\n            case 'show-mute':\n                muteIcon.addClass('hidden');\n                setMuted.removeClass('hidden');\n                unsetMuted.addClass('hidden');\n                break;\n            case 'show-unmute':\n                muteIcon.removeClass('hidden');\n                setMuted.addClass('hidden');\n                unsetMuted.removeClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide the add / remove user as contact option in the header dropdown menu.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} state the contact state.\n     */\n    var renderIsContact = function(header, body, footer, state) {\n        var addContact = header.find(SELECTORS.ACTION_REQUEST_ADD_CONTACT);\n        var removeContact = header.find(SELECTORS.ACTION_REQUEST_REMOVE_CONTACT);\n\n        switch (state) {\n            case 'pending-contact':\n                addContact.addClass('hidden');\n                removeContact.addClass('hidden');\n                break;\n            case 'contact':\n                addContact.addClass('hidden');\n                removeContact.removeClass('hidden');\n                break;\n            case 'non-contact':\n                addContact.removeClass('hidden');\n                removeContact.addClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide confirm action from confirm dialogue is loading.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoading confirm action is loading.\n     */\n    var renderLoadingConfirmAction = function(header, body, footer, isLoading) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var buttons = dialogue.find('button');\n        var buttonText = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_BUTTON_TEXT);\n        var loadingIcon = dialogue.find(SELECTORS.LOADING_ICON_CONTAINER);\n\n        if (isLoading) {\n            buttons.prop('disabled', true);\n            buttonText.addClass('hidden');\n            loadingIcon.removeClass('hidden');\n        } else {\n            buttons.prop('disabled', false);\n            buttonText.removeClass('hidden');\n            loadingIcon.addClass('hidden');\n        }\n    };\n\n    /**\n     * Show or hide the header and footer content for edit mode.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} inEditMode In edit mode or not.\n     */\n    var renderInEditMode = function(header, body, footer, inEditMode) {\n        var messages = null;\n\n        if (inEditMode) {\n            messages = body.find(SELECTORS.MESSAGE_NOT_SELECTED);\n            messages.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).removeClass('hidden');\n            hideHeaderContent(header);\n            showHeaderEditMode(header);\n        } else {\n            messages = getMessagesContainer(body);\n            messages.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).addClass('hidden');\n            messages.find(SELECTORS.MESSAGE_SELECTED_ICON).addClass('hidden');\n            showHeaderContent(header);\n            hideHeaderEditMode(header);\n        }\n    };\n\n    /**\n     * Select or unselect messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data The messages to select or unselect.\n     */\n    var renderSelectedMessages = function(header, body, footer, data) {\n        var hasSelectedMessages = data.count > 0;\n\n        if (data.add.length) {\n            data.add.forEach(function(messageId) {\n                var message = getMessageElement(body, messageId);\n                message.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).addClass('hidden');\n                message.find(SELECTORS.MESSAGE_SELECTED_ICON).removeClass('hidden');\n                message.attr('aria-checked', true);\n            });\n        }\n\n        if (data.remove.length) {\n            data.remove.forEach(function(messageId) {\n                var message = getMessageElement(body, messageId);\n\n                if (hasSelectedMessages) {\n                    message.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).removeClass('hidden');\n                }\n\n                message.find(SELECTORS.MESSAGE_SELECTED_ICON).addClass('hidden');\n                message.attr('aria-checked', false);\n            });\n        }\n\n        setMessagesSelectedCount(header, data.count);\n    };\n\n    /**\n     * Show or hide the require add contact panel.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Whether the user has to be added a a contact.\n     * @return {Object} jQuery promise\n     */\n    var renderRequireAddContact = function(header, body, footer, data) {\n        if (data.show && !data.hasMessages) {\n            return Str.get_strings([\n                    {\n                        key: 'requirecontacttomessage',\n                        component: 'core_message',\n                        param: data.user.fullname\n                    },\n                    {\n                        key: 'isnotinyourcontacts',\n                        component: 'core_message',\n                        param: data.user.fullname\n                    }\n                ])\n                .then(function(strings) {\n                    var title = strings[1];\n                    var text = strings[0];\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_REQUEST_ADD_CONTACT],\n                        text,\n                        title,\n                        false,\n                        true\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Show or hide the self-conversation message.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} displayMessage should the message be displayed?.\n     * @return {Object|true} jQuery promise\n     */\n    var renderSelfConversationMessage = function(header, body, footer, displayMessage) {\n        var container = getSelfConversationMessageContainer(body);\n        if (displayMessage) {\n            container.removeClass('hidden');\n        } else {\n            container.addClass('hidden');\n        }\n        return true;\n    };\n\n    /**\n     * Show or hide the require add contact panel.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} userFullName Full name of the other user.\n     * @return {Object|true} jQuery promise\n     */\n    var renderContactRequestSent = function(header, body, footer, userFullName) {\n        var container = getContactRequestSentContainer(body);\n        if (userFullName) {\n            return Str.get_string('yourcontactrequestpending', 'core_message', userFullName)\n                .then(function(string) {\n                    container.find(SELECTORS.TEXT).text(string);\n                    container.removeClass('hidden');\n                    return string;\n                });\n        } else {\n            container.addClass('hidden');\n            return true;\n        }\n    };\n\n    /**\n     * Reset the UI to the initial state.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @return {Bool}\n     */\n    var renderReset = function(header, body, footer) {\n        hideConfirmDialogue(header, body, footer);\n        hideContactRequestSentContainer(body);\n        hideSelfConversationMessageContainer(body);\n        hideAllHeaderElements(header);\n        showHeaderPlaceholder(header);\n        hideAllFooterElements(footer);\n        showFooterPlaceholder(footer);\n        return true;\n    };\n\n    var render = function(header, body, footer, patch) {\n        var configs = [\n            {\n                // Resetting the UI needs to come first, if it's required.\n                reset: renderReset\n            },\n            {\n                // Any async rendering (stuff that requires templates, strings etc) should\n                // go in here.\n                conversation: renderConversation,\n                header: renderHeader,\n                footer: renderFooter,\n                confirmBlockUser: renderConfirmBlockUser,\n                confirmUnblockUser: renderConfirmUnblockUser,\n                confirmAddContact: renderConfirmAddContact,\n                confirmRemoveContact: renderConfirmRemoveContact,\n                confirmDeleteSelectedMessages: renderConfirmDeleteSelectedMessages,\n                confirmDeleteConversation: renderConfirmDeleteConversation,\n                confirmContactRequest: renderConfirmContactRequest,\n                requireAddContact: renderRequireAddContact,\n                selfConversationMessage: renderSelfConversationMessage,\n                contactRequestSent: renderContactRequestSent\n            },\n            {\n                loadingMembers: renderLoadingMembers,\n                loadingFirstMessages: renderLoadingFirstMessages,\n                loadingMessages: renderLoadingMessages,\n                isBlocked: renderIsBlocked,\n                isContact: renderIsContact,\n                isFavourite: renderIsFavourite,\n                isMuted: renderIsMuted,\n                loadingConfirmAction: renderLoadingConfirmAction,\n                inEditMode: renderInEditMode\n            },\n            {\n                // Scrolling should be last to make sure everything\n                // on the page is visible.\n                scrollToMessage: renderScrollToMessage,\n                selectedMessages: renderSelectedMessages\n            }\n        ];\n        // Helper function to process each of the configs above.\n        var processConfig = function(config) {\n            var results = [];\n\n            for (var key in patch) {\n                if (config.hasOwnProperty(key)) {\n                    var renderFunc = config[key];\n                    var patchValue = patch[key];\n                    results.push(renderFunc(header, body, footer, patchValue));\n                }\n            }\n\n            return results;\n        };\n\n        // The first config is special because it resets the UI.\n        var renderingPromises = processConfig(configs[0]);\n        // The second config is special because it contains async rendering.\n        renderingPromises = renderingPromises.concat(processConfig(configs[1]));\n\n        // Wait for the async rendering to complete before processing the\n        // rest of the configs, in order.\n        return $.when.apply($, renderingPromises)\n            .then(function() {\n                for (var i = 2; i < configs.length; i++) {\n                    processConfig(configs[i]);\n                }\n\n                return;\n            })\n            .catch(Notification.exception);\n    };\n\n    return {\n        render: render,\n    };\n});\n"],"file":"message_drawer_view_conversation_renderer.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../src/message_drawer_view_conversation_renderer.js"],"names":["define","$","Notification","Str","Templates","UserDate","Constants","SELECTORS","TEMPLATES","CONVERSATION_TYPES","getMessagesContainer","body","find","CONTENT_MESSAGES_CONTAINER","showMessagesContainer","removeClass","hideMessagesContainer","addClass","getSelfConversationMessageContainer","SELF_CONVERSATION_MESSAGE_CONTAINER","hideSelfConversationMessageContainer","getContactRequestSentContainer","CONTACT_REQUEST_SENT_MESSAGE_CONTAINER","hideContactRequestSentContainer","getFooterContentContainer","footer","CONTENT_MESSAGES_FOOTER_CONTAINER","showFooterContent","hideFooterContent","getFooterEditModeContainer","CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER","showFooterEditMode","hideFooterEditMode","getFooterPlaceholderContainer","PLACEHOLDER_CONTAINER","showFooterPlaceholder","hideFooterPlaceholder","getFooterRequireContactContainer","CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER","showFooterRequireContact","hideFooterRequireContact","getFooterRequireUnblockContainer","CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER","showFooterRequireUnblock","hideFooterRequireUnblock","getFooterUnableToMessageContainer","CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER","showFooterUnableToMessage","hideFooterUnableToMessage","hideAllHeaderElements","header","hideHeaderContent","hideHeaderEditMode","hideHeaderPlaceholder","hideAllFooterElements","getContentPlaceholderContainer","CONTENT_PLACEHOLDER_CONTAINER","showContentPlaceholder","hideContentPlaceholder","getHeaderContent","HEADER","showHeaderContent","getHeaderEditMode","HEADER_EDIT_MODE","showHeaderEditMode","getHeaderPlaceholderContainer","HEADER_PLACEHOLDER_CONTAINER","showHeaderPlaceholder","getMessageElement","messageId","messagesContainer","getDayElement","dayTimeCreated","getMoreMessagesLoadingIconContainer","MORE_MESSAGES_LOADING_ICON_CONTAINER","showMoreMessagesLoadingIcon","hideMoreMessagesLoadingIcon","getConfirmDialogueContainer","root","CONFIRM_DIALOGUE_CONTAINER","showConfirmDialogueContainer","container","siblings","attr","hideConfirmDialogueContainer","removeAttr","setMessagesSelectedCount","value","MESSAGES_SELECTED_COUNT","text","formatMessagesForTemplate","messages","datesCache","map","message","id","isread","isRead","fromloggedinuser","fromLoggedInUser","userfrom","userFrom","formattedtime","timeCreated","renderAddDays","days","daysRenderPromises","data","render","DAY","timestamp","when","apply","then","forEach","index","html","before","element","insertBefore","append","catch","renderAddMessages","messagesData","formattedMessages","MESSAGES","messageList","messageHtml","dayContainer","day","dayMessagesContainer","DAY_MESSAGES_CONTAINER","renderUpdateMessages","after","formattedTime","LOADING_ICON_CONTAINER","TIME_CREATED","sendState","loading","time","retry","RETRY_SEND","TEXT_CONTAINER","errorMessage","messageContainer","ERROR_MESSAGE_CONTAINER","ERROR_MESSAGE","renderRemoveDays","remove","renderRemoveMessages","renderConversation","renderingPromises","hasAddDays","add","length","hasAddMessages","hasUpdateMessages","update","timestampsToFormat","datesCachePromise","Deferred","resolve","promise","concat","reduce","carry","timestamps","push","get_string","format","requests","get","formattedTimes","renderHeader","headerContainer","template","HEADER_PUBLIC","context","showrouteback","type","PRIVATE","showControls","HEADER_PRIVATE","HEADER_PRIVATE_NO_CONTROLS","SELF","HEADER_SELF","js","replaceNodeContents","renderFooter","get_strings","key","component","param","user","fullname","strings","title","footerContainer","TITLE","TEXT","renderScrollToMessage","messageElement","position","scrollTop","top","renderLoadingMembers","isLoadingMembers","renderLoadingFirstMessages","isLoadingFirstMessages","renderLoadingMessages","isLoading","showConfirmDialogue","buttonSelectors","bodyText","headerText","canCancel","skipHeader","dialogue","buttons","selector","cancelButton","CONFIRM_DIALOGUE_CANCEL_BUTTON","CONFIRM_DIALOGUE_TEXT","dialogueHeader","CONFIRM_DIALOGUE_HEADER","button","CAN_RECEIVE_FOCUS","filter","first","focus","hideConfirmDialogue","hideCheckDeleteDialogue","renderConfirmBlockUser","canmessageevenifblocked","string","ACTION_CONFIRM_BLOCK","renderConfirmUnblockUser","ACTION_CONFIRM_UNBLOCK","renderConfirmAddContact","ACTION_CONFIRM_ADD_CONTACT","renderConfirmRemoveContact","ACTION_CONFIRM_REMOVE_CONTACT","renderConfirmDeleteSelectedMessages","showmessage","canDeleteMessagesForAllUsers","showCheckDeleteDialogue","show","ACTION_CONFIRM_DELETE_SELECTED_MESSAGES","renderConfirmDeleteConversation","ACTION_CONFIRM_DELETE_CONVERSATION","renderConfirmContactRequest","ACTION_ACCEPT_CONTACT_REQUEST","ACTION_DECLINE_CONTACT_REQUEST","checkboxRegion","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER","checkbox","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE","prop","renderIsBlocked","isBlocked","ACTION_REQUEST_BLOCK","ACTION_REQUEST_UNBLOCK","renderIsFavourite","state","favouriteIcon","FAVOURITE_ICON_CONTAINER","addFavourite","ACTION_CONFIRM_FAVOURITE","removeFavourite","ACTION_CONFIRM_UNFAVOURITE","renderIsMuted","muteIcon","MUTED_ICON_CONTAINER","setMuted","ACTION_CONFIRM_MUTE","unsetMuted","ACTION_CONFIRM_UNMUTE","renderIsContact","addContact","ACTION_REQUEST_ADD_CONTACT","removeContact","ACTION_REQUEST_REMOVE_CONTACT","renderLoadingConfirmAction","buttonText","CONFIRM_DIALOGUE_BUTTON_TEXT","loadingIcon","renderInEditMode","inEditMode","MESSAGE_NOT_SELECTED","MESSAGE_NOT_SELECTED_ICON","MESSAGE_SELECTED_ICON","renderSelectedMessages","hasSelectedMessages","count","renderRequireAddContact","hasMessages","renderSelfConversationMessage","displayMessage","renderContactRequestSent","userFullName","renderReset","patch","configs","reset","conversation","confirmBlockUser","confirmUnblockUser","confirmAddContact","confirmRemoveContact","confirmDeleteSelectedMessages","confirmDeleteConversation","confirmContactRequest","requireAddContact","selfConversationMessage","contactRequestSent","loadingMembers","loadingFirstMessages","loadingMessages","isContact","isFavourite","isMuted","loadingConfirmAction","scrollToMessage","selectedMessages","processConfig","config","results","hasOwnProperty","renderFunc","patchValue","i","exception"],"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 * This module updates the UI for the conversation page in the message\n * drawer.\n *\n * The module will take a patch from the message_drawer_view_conversation_patcher\n * module and update the UI to reflect the changes.\n *\n * This is the only module that ever modifies the UI of the conversation page.\n *\n * @module     core_message/message_drawer_view_conversation_renderer\n * @copyright  2018 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n    'jquery',\n    'core/notification',\n    'core/str',\n    'core/templates',\n    'core/user_date',\n    'core_message/message_drawer_view_conversation_constants'\n],\nfunction(\n    $,\n    Notification,\n    Str,\n    Templates,\n    UserDate,\n    Constants\n) {\n    var SELECTORS = Constants.SELECTORS;\n    var TEMPLATES = Constants.TEMPLATES;\n    var CONVERSATION_TYPES = Constants.CONVERSATION_TYPES;\n\n    /**\n     * Get the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getMessagesContainer = function(body) {\n        return body.find(SELECTORS.CONTENT_MESSAGES_CONTAINER);\n    };\n\n    /**\n     * Show the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showMessagesContainer = function(body) {\n        getMessagesContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideMessagesContainer = function(body) {\n        getMessagesContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the self-conversation message container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getSelfConversationMessageContainer = function(body) {\n        return body.find(SELECTORS.SELF_CONVERSATION_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Hide the self-conversation message container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var hideSelfConversationMessageContainer = function(body) {\n        return getSelfConversationMessageContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the contact request sent container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getContactRequestSentContainer = function(body) {\n        return body.find(SELECTORS.CONTACT_REQUEST_SENT_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Hide the contact request sent container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var hideContactRequestSentContainer = function(body) {\n        return getContactRequestSentContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer container element.\n     */\n    var getFooterContentContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_CONTAINER);\n    };\n\n    /**\n     * Show the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterContent = function(footer) {\n        getFooterContentContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterContent = function(footer) {\n        getFooterContentContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer container element.\n     */\n    var getFooterEditModeContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER);\n    };\n\n    /**\n     * Show the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterEditMode = function(footer) {\n        getFooterEditModeContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterEditMode = function(footer) {\n        getFooterEditModeContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer placeholder.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer placeholder container element.\n     */\n    var getFooterPlaceholderContainer = function(footer) {\n        return footer.find(SELECTORS.PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the footer placeholder\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterPlaceholder = function(footer) {\n        getFooterPlaceholderContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer placeholder\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterPlaceholder = function(footer) {\n        getFooterPlaceholderContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Require add as contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Require add as contact container element.\n     */\n    var getFooterRequireContactContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER);\n    };\n\n    /**\n     * Show the footer add as contact dialogue.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterRequireContact = function(footer) {\n        getFooterRequireContactContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer add as contact dialogue.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterRequireContact = function(footer) {\n        getFooterRequireContactContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Required to unblock contact container element.\n     */\n    var getFooterRequireUnblockContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER);\n    };\n\n    /**\n     * Show the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterRequireUnblock = function(footer) {\n        getFooterRequireUnblockContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterRequireUnblock = function(footer) {\n        getFooterRequireUnblockContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Unable to message contact container element.\n     */\n    var getFooterUnableToMessageContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Show the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterUnableToMessage = function(footer) {\n        getFooterUnableToMessageContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterUnableToMessage = function(footer) {\n        getFooterUnableToMessageContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Hide all header elements.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideAllHeaderElements = function(header) {\n        hideHeaderContent(header);\n        hideHeaderEditMode(header);\n        hideHeaderPlaceholder(header);\n    };\n\n    /**\n     * Hide all footer dialogues and messages.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideAllFooterElements = function(footer) {\n        hideFooterContent(footer);\n        hideFooterEditMode(footer);\n        hideFooterPlaceholder(footer);\n        hideFooterRequireContact(footer);\n        hideFooterRequireUnblock(footer);\n        hideFooterUnableToMessage(footer);\n    };\n\n    /**\n     * Get the content placeholder container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The body placeholder container element.\n     */\n    var getContentPlaceholderContainer = function(body) {\n        return body.find(SELECTORS.CONTENT_PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the content placeholder.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showContentPlaceholder = function(body) {\n        getContentPlaceholderContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the content placeholder.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideContentPlaceholder = function(body) {\n        getContentPlaceholderContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the header content container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header content container element.\n     */\n    var getHeaderContent = function(header) {\n        return header.find(SELECTORS.HEADER);\n    };\n\n    /**\n     * Show the header content.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderContent = function(header) {\n        getHeaderContent(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header content.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderContent = function(header) {\n        getHeaderContent(header).addClass('hidden');\n    };\n\n    /**\n     * Get the header edit mode container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header content container element.\n     */\n    var getHeaderEditMode = function(header) {\n        return header.find(SELECTORS.HEADER_EDIT_MODE);\n    };\n\n    /**\n     * Show the header edit mode container.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderEditMode = function(header) {\n        getHeaderEditMode(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header edit mode container.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderEditMode = function(header) {\n        getHeaderEditMode(header).addClass('hidden');\n    };\n\n    /**\n     * Get the header placeholder container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header placeholder container element.\n     */\n    var getHeaderPlaceholderContainer = function(header) {\n        return header.find(SELECTORS.HEADER_PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the header placeholder.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderPlaceholder = function(header) {\n        getHeaderPlaceholderContainer(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header placeholder.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderPlaceholder = function(header) {\n        getHeaderPlaceholderContainer(header).addClass('hidden');\n    };\n\n    /**\n     * Get a message element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Number} messageId the Message id.\n     * @return {Object} A message element from the conversation.\n     */\n    var getMessageElement = function(body, messageId) {\n        var messagesContainer = getMessagesContainer(body);\n        return messagesContainer.find('[data-message-id=\"' + messageId + '\"]');\n    };\n\n    /**\n     * Get the day container element. The day container element holds a list of messages for that day.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Number} dayTimeCreated Midnight timestamp for the day.\n     * @return {Object} jQuery object\n     */\n    var getDayElement = function(body, dayTimeCreated) {\n        var messagesContainer = getMessagesContainer(body);\n        return messagesContainer.find('[data-day-id=\"' + dayTimeCreated + '\"]');\n    };\n\n    /**\n     * Get the more messages loading icon container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The more messages loading container element.\n     */\n    var getMoreMessagesLoadingIconContainer = function(body) {\n        return body.find(SELECTORS.MORE_MESSAGES_LOADING_ICON_CONTAINER);\n    };\n\n    /**\n     * Show the more messages loading icon.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showMoreMessagesLoadingIcon = function(body) {\n        getMoreMessagesLoadingIconContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the more messages loading icon.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideMoreMessagesLoadingIcon = function(body) {\n        getMoreMessagesLoadingIconContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element to search.\n     * @return {Object} The confirm dialogue container element.\n     */\n    var getConfirmDialogueContainer = function(root) {\n        return root.find(SELECTORS.CONFIRM_DIALOGUE_CONTAINER);\n    };\n\n    /**\n     * Show the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element containing a dialogue.\n     */\n    var showConfirmDialogueContainer = function(root) {\n        var container = getConfirmDialogueContainer(root);\n        var siblings = container.siblings(':not(.hidden)');\n        siblings.attr('aria-hidden', true);\n        siblings.attr('tabindex', -1);\n        siblings.attr('data-confirm-dialogue-hidden', true);\n\n        container.removeClass('hidden');\n    };\n\n    /**\n     * Hide the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element containing a dialogue.\n     */\n    var hideConfirmDialogueContainer = function(root) {\n        var container = getConfirmDialogueContainer(root);\n        var siblings = container.siblings('[data-confirm-dialogue-hidden=\"true\"]');\n        siblings.removeAttr('aria-hidden');\n        siblings.removeAttr('tabindex');\n        siblings.removeAttr('data-confirm-dialogue-hidden');\n\n        container.addClass('hidden');\n    };\n\n    /**\n     * Set the number of selected messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Number} value The new number to display.\n     */\n    var setMessagesSelectedCount = function(header, value) {\n        getHeaderEditMode(header).find(SELECTORS.MESSAGES_SELECTED_COUNT).text(value);\n    };\n\n    /**\n     * Format message for the mustache template, transform camelCase properties to lowercase properties.\n     *\n     * @param  {Array} messages Array of message objects.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Array} Messages formated for mustache template.\n     */\n    var formatMessagesForTemplate = function(messages, datesCache) {\n        return messages.map(function(message) {\n            return {\n                id: message.id,\n                isread: message.isRead,\n                fromloggedinuser: message.fromLoggedInUser,\n                userfrom: message.userFrom,\n                text: message.text,\n                formattedtime: message.timeCreated ? datesCache[message.timeCreated] : null\n            };\n        });\n    };\n\n    /**\n     * Create rendering promises for each day containing messages.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} days Array of days containing messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Promise} Days rendering promises.\n     */\n    var renderAddDays = function(header, body, footer, days, datesCache) {\n        var messagesContainer = getMessagesContainer(body);\n        var daysRenderPromises = days.map(function(data) {\n            return Templates.render(TEMPLATES.DAY, {\n                timestamp: data.value.timestamp,\n                messages: formatMessagesForTemplate(data.value.messages, datesCache)\n            });\n        });\n\n        return $.when.apply($, daysRenderPromises).then(function() {\n            // Wait until all of the rendering is done for each of the days\n            // to ensure they are added to the page in the correct order.\n            days.forEach(function(data, index) {\n                daysRenderPromises[index]\n                    .then(function(html) {\n                        if (data.before) {\n                            var element = getDayElement(body, data.before.timestamp);\n                            return $(html).insertBefore(element);\n                        } else {\n                            return messagesContainer.append(html);\n                        }\n                    })\n                    .catch(function() {\n                        // Fail silently.\n                    });\n            });\n\n            return;\n        });\n    };\n\n    /**\n     * Add (more) messages to day containers.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} messages List of messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Promise} Messages rendering promises.\n     */\n    var renderAddMessages = function(header, body, footer, messages, datesCache) {\n        var messagesData = messages.map(function(data) {\n            return data.value;\n        });\n        var formattedMessages = formatMessagesForTemplate(messagesData, datesCache);\n\n        return Templates.render(TEMPLATES.MESSAGES, {messages: formattedMessages})\n            .then(function(html) {\n                var messageList = $(html);\n                messages.forEach(function(data) {\n                    var messageHtml = messageList.find('[data-message-id=\"' + data.value.id + '\"]');\n                    if (data.before) {\n                        var element = getMessageElement(body, data.before.id);\n                        return messageHtml.insertBefore(element);\n                    } else {\n                        var dayContainer = getDayElement(body, data.day.timestamp);\n                        var dayMessagesContainer = dayContainer.find(SELECTORS.DAY_MESSAGES_CONTAINER);\n                        return dayMessagesContainer.append(messageHtml);\n                    }\n                });\n\n                return;\n            });\n    };\n\n    /**\n     * Update existing messages.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} messages List of messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     */\n    var renderUpdateMessages = function(header, body, footer, messages, datesCache) {\n        messages.forEach(function(message) {\n            var before = message.before;\n            var after = message.after;\n            var element = getMessageElement(body, before.id);\n\n            if (before.id != after.id) {\n                element.attr('data-message-id', after.id);\n            }\n\n            if (before.timeCreated != after.timeCreated) {\n                var formattedTime = datesCache[after.timeCreated];\n                element.find(SELECTORS.LOADING_ICON_CONTAINER).addClass('hidden');\n                element.find(SELECTORS.TIME_CREATED).text(formattedTime).removeClass('hidden');\n            }\n\n            if (before.sendState != after.sendState) {\n                var loading = element.find(SELECTORS.LOADING_ICON_CONTAINER);\n                var time = element.find(SELECTORS.TIME_CREATED);\n                var retry = element.find(SELECTORS.RETRY_SEND);\n\n                loading.addClass('hidden');\n                loading.attr('aria-hidden', 'true');\n                time.addClass('hidden');\n                time.attr('aria-hidden', 'true');\n                retry.addClass('hidden');\n                retry.attr('aria-hidden', 'true');\n                element.removeClass('border border-danger');\n\n                switch (after.sendState) {\n                    case 'pending':\n                        loading.removeClass('hidden');\n                        loading.attr('aria-hidden', 'false');\n                        break;\n                    case 'error':\n                        retry.removeClass('hidden');\n                        retry.attr('aria-hidden', 'false');\n                        element.addClass('border border-danger');\n                        break;\n                    case 'sent':\n                        time.removeClass('hidden');\n                        time.attr('aria-hidden', 'false');\n                        break;\n                }\n            }\n\n            if (before.text != after.text) {\n                element.find(SELECTORS.TEXT_CONTAINER).html(after.text);\n            }\n\n            if (before.errorMessage != after.errorMessage) {\n                var messageContainer = element.find(SELECTORS.ERROR_MESSAGE_CONTAINER);\n                var message = messageContainer.find(SELECTORS.ERROR_MESSAGE);\n\n                if (after.errorMessage) {\n                    messageContainer.removeClass('hidden');\n                    messageContainer.attr('aria-hidden', 'false');\n                    message.text(after.errorMessage);\n                } else {\n                    messageContainer.addClass('hidden');\n                    messageContainer.attr('aria-hidden', 'true');\n                    message.text('');\n                }\n            }\n        });\n    };\n\n    /**\n     * Remove days from conversation.\n     *\n     * @param  {Object} body The body container element.\n     * @param  {Array} days Array of days to be removed.\n     */\n    var renderRemoveDays = function(body, days) {\n        days.forEach(function(data) {\n            getDayElement(body, data.timestamp).remove();\n        });\n    };\n\n    /**\n     * Remove messages from conversation.\n     *\n     * @param  {Object} body The body container element.\n     * @param  {Array} messages Array of messages to be removed.\n     */\n    var renderRemoveMessages = function(body, messages) {\n        messages.forEach(function(data) {\n            getMessageElement(body, data.id).remove();\n        });\n    };\n\n    /**\n     * Render the full conversation base on input from the statemanager.\n     *\n     * This will pre-load all of the formatted timestamps for each message that\n     * needs to render to reduce the number of networks requests.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Object} data The conversation diff.\n     * @return {Object} jQuery promise.\n     */\n    var renderConversation = function(header, body, footer, data) {\n        var renderingPromises = [];\n        var hasAddDays = data.days.add.length > 0;\n        var hasAddMessages = data.messages.add.length > 0;\n        var hasUpdateMessages = data.messages.update.length > 0;\n        var timestampsToFormat = [];\n        var datesCachePromise = $.Deferred().resolve({}).promise();\n\n        if (hasAddDays) {\n            // Search for all of the timeCreated values in all of the messages in all of\n            // the days that we need to render.\n            timestampsToFormat = timestampsToFormat.concat(data.days.add.reduce(function(carry, day) {\n                return carry.concat(day.value.messages.reduce(function(timestamps, message) {\n                    if (message.timeCreated) {\n                        timestamps.push(message.timeCreated);\n                    }\n                    return timestamps;\n                }, []));\n            }, []));\n        }\n\n        if (hasAddMessages) {\n            // Search for all of the timeCreated values in all of the messages that we\n            // need to render.\n            timestampsToFormat = timestampsToFormat.concat(data.messages.add.reduce(function(timestamps, message) {\n                if (message.value.timeCreated) {\n                    timestamps.push(message.value.timeCreated);\n                }\n                return timestamps;\n            }, []));\n        }\n\n        if (hasUpdateMessages) {\n            timestampsToFormat = timestampsToFormat.concat(data.messages.update.reduce(function(timestamps, message) {\n                if (message.before.timeCreated != message.after.timeCreated) {\n                    timestamps.push(message.after.timeCreated);\n                }\n                return timestamps;\n            }, []));\n        }\n\n        if (timestampsToFormat.length) {\n            // If we have timestamps then pre-load the formatted version of each of them\n            // in a single request to the server. This saves the templates doing multiple\n            // individual requests.\n            datesCachePromise = Str.get_string('strftimetime24', 'core_langconfig')\n                .then(function(format) {\n                    var requests = timestampsToFormat.map(function(timestamp) {\n                        return {\n                            timestamp: timestamp,\n                            format: format\n                        };\n                    });\n\n                    return UserDate.get(requests);\n                })\n                .then(function(formattedTimes) {\n                    return timestampsToFormat.reduce(function(carry, timestamp, index) {\n                        carry[timestamp] = formattedTimes[index];\n                        return carry;\n                    }, {});\n                });\n        }\n\n        if (hasAddDays) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderAddDays(header, body, footer, data.days.add, datesCache);\n            }));\n        }\n\n        if (hasAddMessages) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderAddMessages(header, body, footer, data.messages.add, datesCache);\n            }));\n        }\n\n        if (hasUpdateMessages) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderUpdateMessages(header, body, footer, data.messages.update, datesCache);\n            }));\n        }\n\n        if (data.days.remove.length > 0) {\n            renderRemoveDays(body, data.days.remove);\n        }\n\n        if (data.messages.remove.length > 0) {\n            renderRemoveMessages(body, data.messages.remove);\n        }\n\n        return $.when.apply($, renderingPromises);\n    };\n\n    /**\n     * Render the conversation header.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Data for header.\n     * @return {Object} jQuery promise\n     */\n    var renderHeader = function(header, body, footer, data) {\n        var headerContainer = getHeaderContent(header);\n        var template = TEMPLATES.HEADER_PUBLIC;\n        data.context.showrouteback = (header.attr('data-from-panel') === \"false\");\n        if (data.type == CONVERSATION_TYPES.PRIVATE) {\n            template = data.showControls ? TEMPLATES.HEADER_PRIVATE : TEMPLATES.HEADER_PRIVATE_NO_CONTROLS;\n        } else if (data.type == CONVERSATION_TYPES.SELF) {\n            template = TEMPLATES.HEADER_SELF;\n        }\n\n        return Templates.render(template, data.context)\n            .then(function(html, js) {\n                Templates.replaceNodeContents(headerContainer, html, js);\n                return;\n            });\n    };\n\n    /**\n     * Render the conversation footer.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Data for footer.\n     * @return {Object} jQuery promise.\n     */\n    var renderFooter = function(header, body, footer, data) {\n        hideAllFooterElements(footer);\n\n        switch (data.type) {\n            case 'placeholder':\n                return showFooterPlaceholder(footer);\n            case 'add-contact':\n                return Str.get_strings([\n                        {\n                            key: 'requirecontacttomessage',\n                            component: 'core_message',\n                            param: data.user.fullname\n                        },\n                        {\n                            key: 'isnotinyourcontacts',\n                            component: 'core_message',\n                            param: data.user.fullname\n                        }\n                    ])\n                    .then(function(strings) {\n                        var title = strings[1];\n                        var text = strings[0];\n                        var footerContainer = getFooterRequireContactContainer(footer);\n                        footerContainer.find(SELECTORS.TITLE).text(title);\n                        footerContainer.find(SELECTORS.TEXT).text(text);\n                        showFooterRequireContact(footer);\n                        return strings;\n                    });\n            case 'edit-mode':\n                return showFooterEditMode(footer);\n            case 'content':\n                return showFooterContent(footer);\n            case 'unblock':\n                return showFooterRequireUnblock(footer);\n            case 'unable-to-message':\n                return showFooterUnableToMessage(footer);\n        }\n\n        return true;\n    };\n\n    /**\n     * Scroll to a message in the conversation.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Number} messageId Message id.\n     */\n    var renderScrollToMessage = function(header, body, footer, messageId) {\n        var messagesContainer = getMessagesContainer(body);\n        var messageElement = getMessageElement(body, messageId);\n        var position = messageElement.position();\n        // Scroll the message container down to the top of the message element.\n        if (position) {\n            var scrollTop = messagesContainer.scrollTop() + position.top;\n            messagesContainer.scrollTop(scrollTop);\n        }\n    };\n\n    /**\n     * Hide or show the conversation header.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoadingMembers Members loading.\n     */\n    var renderLoadingMembers = function(header, body, footer, isLoadingMembers) {\n        if (isLoadingMembers) {\n            hideHeaderContent(header);\n            showHeaderPlaceholder(header);\n        } else {\n            showHeaderContent(header);\n            hideHeaderPlaceholder(header);\n        }\n    };\n\n    /**\n     * Hide or show loading conversation messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoadingFirstMessages Messages loading.\n     */\n    var renderLoadingFirstMessages = function(header, body, footer, isLoadingFirstMessages) {\n        if (isLoadingFirstMessages) {\n            hideMessagesContainer(body);\n            showContentPlaceholder(body);\n        } else {\n            showMessagesContainer(body);\n            hideContentPlaceholder(body);\n        }\n    };\n\n    /**\n     * Hide or show loading more messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoading Messages loading.\n     */\n    var renderLoadingMessages = function(header, body, footer, isLoading) {\n        if (isLoading) {\n            showMoreMessagesLoadingIcon(body);\n        } else {\n            hideMoreMessagesLoadingIcon(body);\n        }\n    };\n\n    /**\n     * Show a confirmation dialogue\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {String} buttonSelectors Selectors for the buttons to show.\n     * @param {String} bodyText Text to show in dialogue.\n     * @param {String} headerText Text to show in dialogue header.\n     * @param {Bool} canCancel Can this dialogue be cancelled.\n     * @param {Bool} skipHeader Skip blanking out the header\n     */\n    var showConfirmDialogue = function(\n        header,\n        body,\n        footer,\n        buttonSelectors,\n        bodyText,\n        headerText,\n        canCancel,\n        skipHeader\n    ) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var buttons = buttonSelectors.map(function(selector) {\n            return dialogue.find(selector);\n        });\n        var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);\n        var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);\n        var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);\n\n        dialogue.find('button').addClass('hidden');\n\n        if (canCancel) {\n            cancelButton.removeClass('hidden');\n        } else {\n            cancelButton.addClass('hidden');\n        }\n\n        if (headerText) {\n            dialogueHeader.removeClass('hidden');\n            dialogueHeader.text(headerText);\n        } else {\n            dialogueHeader.addClass('hidden');\n            dialogueHeader.text('');\n        }\n\n        buttons.forEach(function(button) {\n            button.removeClass('hidden');\n        });\n        text.text(bodyText);\n        showConfirmDialogueContainer(footer);\n        showConfirmDialogueContainer(body);\n\n        if (!skipHeader) {\n            showConfirmDialogueContainer(header);\n        }\n\n        dialogue.find(SELECTORS.CAN_RECEIVE_FOCUS).filter(':visible').first().focus();\n    };\n\n    /**\n     * Hide the dialogue\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @return {Bool} always true.\n     */\n    var hideConfirmDialogue = function(header, body, footer) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);\n        var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);\n        var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);\n\n        hideCheckDeleteDialogue(body);\n        hideConfirmDialogueContainer(body);\n        hideConfirmDialogueContainer(footer);\n        hideConfirmDialogueContainer(header);\n        dialogue.find('button').addClass('hidden');\n        cancelButton.removeClass('hidden');\n        text.text('');\n        dialogueHeader.addClass('hidden');\n        dialogueHeader.text('');\n\n        header.find(SELECTORS.CAN_RECEIVE_FOCUS).first().focus();\n        return true;\n    };\n\n    /**\n     * Render the confirm block user dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to block.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmBlockUser = function(header, body, footer, user) {\n        if (user) {\n            if (user.canmessageevenifblocked) {\n                return Str.get_string('cantblockuser', 'core_message', user.fullname)\n                    .then(function(string) {\n                        return showConfirmDialogue(header, body, footer, [], string, '', true, false);\n                    });\n            } else {\n                return Str.get_string('blockuserconfirm', 'core_message', user.fullname)\n                    .then(function(string) {\n                        return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_BLOCK], string, '', true, false);\n                    });\n            }\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm unblock user dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to unblock.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmUnblockUser = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('unblockuserconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_UNBLOCK], string, '', true, false);\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the add user as contact dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to add as contact.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmAddContact = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('addcontactconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_ADD_CONTACT],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the remove user from contacts dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to remove from contacts.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmRemoveContact = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('removecontactconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_REMOVE_CONTACT],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the delete selected messages dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data If the dialogue should show and checkbox shows to delete message for all users.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmDeleteSelectedMessages = function(header, body, footer, data) {\n        var showmessage = null;\n        if (data.type == CONVERSATION_TYPES.SELF) {\n            // Message displayed to self-conversations is slighly different.\n            showmessage = 'deleteselectedmessagesconfirmselfconversation';\n        } else {\n            // This other message should be displayed.\n            if (data.canDeleteMessagesForAllUsers) {\n                showCheckDeleteDialogue(body);\n                showmessage = 'deleteforeveryoneselectedmessagesconfirm';\n            } else {\n                showmessage = 'deleteselectedmessagesconfirm';\n            }\n        }\n\n        if (data.show) {\n            return Str.get_string(showmessage, 'core_message')\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm delete conversation dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {int|Null} type The conversation type to be removed.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmDeleteConversation = function(header, body, footer, type) {\n        var showmessage = null;\n        if (type == CONVERSATION_TYPES.SELF) {\n            // Message displayed to self-conversations is slighly different.\n            showmessage = 'deleteallselfconfirm';\n        } else if (type) {\n            // This other message should be displayed.\n            showmessage = 'deleteallconfirm';\n        }\n\n        if (showmessage) {\n            return Str.get_string(showmessage, 'core_message')\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_DELETE_CONVERSATION],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm delete conversation dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} user The other user object.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmContactRequest = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('userwouldliketocontactyou', 'core_message', user.fullname)\n                .then(function(string) {\n                    var buttonSelectors = [\n                        SELECTORS.ACTION_ACCEPT_CONTACT_REQUEST,\n                        SELECTORS.ACTION_DECLINE_CONTACT_REQUEST\n                    ];\n                    return showConfirmDialogue(header, body, footer, buttonSelectors, string, '', false, true);\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Show the checkbox to allow delete message for all.\n     *\n     * @param {Object} body The body container element.\n     */\n    var showCheckDeleteDialogue = function(body) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var checkboxRegion = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);\n        checkboxRegion.removeClass('hidden');\n    };\n\n    /**\n     * Hide the checkbox to allow delete message for all.\n     *\n     * @param {Object} body The body container element.\n     */\n    var hideCheckDeleteDialogue = function(body) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var checkboxRegion = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);\n        var checkbox = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE);\n        checkbox.prop('checked', false);\n        checkboxRegion.addClass('hidden');\n    };\n\n    /**\n     * Show or hide the block / unblock option in the header dropdown menu.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isBlocked is user blocked.\n     */\n    var renderIsBlocked = function(header, body, footer, isBlocked) {\n        if (isBlocked) {\n            header.find(SELECTORS.ACTION_REQUEST_BLOCK).addClass('hidden');\n            header.find(SELECTORS.ACTION_REQUEST_UNBLOCK).removeClass('hidden');\n        } else {\n            header.find(SELECTORS.ACTION_REQUEST_BLOCK).removeClass('hidden');\n            header.find(SELECTORS.ACTION_REQUEST_UNBLOCK).addClass('hidden');\n        }\n    };\n\n    /**\n     * Show or hide the favourite / unfavourite option in the header dropdown menu\n     * and the favourite star in the header title.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isFavourite is this conversation a favourite.\n     */\n    var renderIsFavourite = function(header, body, footer, state) {\n        var favouriteIcon = header.find(SELECTORS.FAVOURITE_ICON_CONTAINER);\n        var addFavourite = header.find(SELECTORS.ACTION_CONFIRM_FAVOURITE);\n        var removeFavourite = header.find(SELECTORS.ACTION_CONFIRM_UNFAVOURITE);\n\n        switch (state) {\n            case 'hide':\n                favouriteIcon.addClass('hidden');\n                addFavourite.addClass('hidden');\n                removeFavourite.addClass('hidden');\n                break;\n            case 'show-add':\n                favouriteIcon.addClass('hidden');\n                addFavourite.removeClass('hidden');\n                removeFavourite.addClass('hidden');\n                break;\n            case 'show-remove':\n                favouriteIcon.removeClass('hidden');\n                addFavourite.addClass('hidden');\n                removeFavourite.removeClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide the mute / unmute option in the header dropdown menu\n     * and the muted icon in the header title.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {string} state The state of the conversation as defined by the patcher.\n     */\n    var renderIsMuted = function(header, body, footer, state) {\n        var muteIcon = header.find(SELECTORS.MUTED_ICON_CONTAINER);\n        var setMuted = header.find(SELECTORS.ACTION_CONFIRM_MUTE);\n        var unsetMuted = header.find(SELECTORS.ACTION_CONFIRM_UNMUTE);\n\n        switch (state) {\n            case 'hide':\n                muteIcon.addClass('hidden');\n                setMuted.addClass('hidden');\n                unsetMuted.addClass('hidden');\n                break;\n            case 'show-mute':\n                muteIcon.addClass('hidden');\n                setMuted.removeClass('hidden');\n                unsetMuted.addClass('hidden');\n                break;\n            case 'show-unmute':\n                muteIcon.removeClass('hidden');\n                setMuted.addClass('hidden');\n                unsetMuted.removeClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide the add / remove user as contact option in the header dropdown menu.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} state the contact state.\n     */\n    var renderIsContact = function(header, body, footer, state) {\n        var addContact = header.find(SELECTORS.ACTION_REQUEST_ADD_CONTACT);\n        var removeContact = header.find(SELECTORS.ACTION_REQUEST_REMOVE_CONTACT);\n\n        switch (state) {\n            case 'pending-contact':\n                addContact.addClass('hidden');\n                removeContact.addClass('hidden');\n                break;\n            case 'contact':\n                addContact.addClass('hidden');\n                removeContact.removeClass('hidden');\n                break;\n            case 'non-contact':\n                addContact.removeClass('hidden');\n                removeContact.addClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide confirm action from confirm dialogue is loading.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoading confirm action is loading.\n     */\n    var renderLoadingConfirmAction = function(header, body, footer, isLoading) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var buttons = dialogue.find('button');\n        var buttonText = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_BUTTON_TEXT);\n        var loadingIcon = dialogue.find(SELECTORS.LOADING_ICON_CONTAINER);\n\n        if (isLoading) {\n            buttons.prop('disabled', true);\n            buttonText.addClass('hidden');\n            loadingIcon.removeClass('hidden');\n        } else {\n            buttons.prop('disabled', false);\n            buttonText.removeClass('hidden');\n            loadingIcon.addClass('hidden');\n        }\n    };\n\n    /**\n     * Show or hide the header and footer content for edit mode.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} inEditMode In edit mode or not.\n     */\n    var renderInEditMode = function(header, body, footer, inEditMode) {\n        var messages = null;\n\n        if (inEditMode) {\n            messages = body.find(SELECTORS.MESSAGE_NOT_SELECTED);\n            messages.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).removeClass('hidden');\n            hideHeaderContent(header);\n            showHeaderEditMode(header);\n        } else {\n            messages = getMessagesContainer(body);\n            messages.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).addClass('hidden');\n            messages.find(SELECTORS.MESSAGE_SELECTED_ICON).addClass('hidden');\n            showHeaderContent(header);\n            hideHeaderEditMode(header);\n        }\n    };\n\n    /**\n     * Select or unselect messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data The messages to select or unselect.\n     */\n    var renderSelectedMessages = function(header, body, footer, data) {\n        var hasSelectedMessages = data.count > 0;\n\n        if (data.add.length) {\n            data.add.forEach(function(messageId) {\n                var message = getMessageElement(body, messageId);\n                message.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).addClass('hidden');\n                message.find(SELECTORS.MESSAGE_SELECTED_ICON).removeClass('hidden');\n                message.attr('aria-checked', true);\n            });\n        }\n\n        if (data.remove.length) {\n            data.remove.forEach(function(messageId) {\n                var message = getMessageElement(body, messageId);\n\n                if (hasSelectedMessages) {\n                    message.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).removeClass('hidden');\n                }\n\n                message.find(SELECTORS.MESSAGE_SELECTED_ICON).addClass('hidden');\n                message.attr('aria-checked', false);\n            });\n        }\n\n        setMessagesSelectedCount(header, data.count);\n    };\n\n    /**\n     * Show or hide the require add contact panel.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Whether the user has to be added a a contact.\n     * @return {Object} jQuery promise\n     */\n    var renderRequireAddContact = function(header, body, footer, data) {\n        if (data.show && !data.hasMessages) {\n            return Str.get_strings([\n                    {\n                        key: 'requirecontacttomessage',\n                        component: 'core_message',\n                        param: data.user.fullname\n                    },\n                    {\n                        key: 'isnotinyourcontacts',\n                        component: 'core_message',\n                        param: data.user.fullname\n                    }\n                ])\n                .then(function(strings) {\n                    var title = strings[1];\n                    var text = strings[0];\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_REQUEST_ADD_CONTACT],\n                        text,\n                        title,\n                        false,\n                        true\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Show or hide the self-conversation message.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} displayMessage should the message be displayed?.\n     * @return {Object|true} jQuery promise\n     */\n    var renderSelfConversationMessage = function(header, body, footer, displayMessage) {\n        var container = getSelfConversationMessageContainer(body);\n        if (displayMessage) {\n            container.removeClass('hidden');\n        } else {\n            container.addClass('hidden');\n        }\n        return true;\n    };\n\n    /**\n     * Show or hide the require add contact panel.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} userFullName Full name of the other user.\n     * @return {Object|true} jQuery promise\n     */\n    var renderContactRequestSent = function(header, body, footer, userFullName) {\n        var container = getContactRequestSentContainer(body);\n        if (userFullName) {\n            return Str.get_string('yourcontactrequestpending', 'core_message', userFullName)\n                .then(function(string) {\n                    container.find(SELECTORS.TEXT).text(string);\n                    container.removeClass('hidden');\n                    return string;\n                });\n        } else {\n            container.addClass('hidden');\n            return true;\n        }\n    };\n\n    /**\n     * Reset the UI to the initial state.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @return {Bool}\n     */\n    var renderReset = function(header, body, footer) {\n        hideConfirmDialogue(header, body, footer);\n        hideContactRequestSentContainer(body);\n        hideSelfConversationMessageContainer(body);\n        hideAllHeaderElements(header);\n        showHeaderPlaceholder(header);\n        hideAllFooterElements(footer);\n        showFooterPlaceholder(footer);\n        return true;\n    };\n\n    var render = function(header, body, footer, patch) {\n        var configs = [\n            {\n                // Resetting the UI needs to come first, if it's required.\n                reset: renderReset\n            },\n            {\n                // Any async rendering (stuff that requires templates, strings etc) should\n                // go in here.\n                conversation: renderConversation,\n                header: renderHeader,\n                footer: renderFooter,\n                confirmBlockUser: renderConfirmBlockUser,\n                confirmUnblockUser: renderConfirmUnblockUser,\n                confirmAddContact: renderConfirmAddContact,\n                confirmRemoveContact: renderConfirmRemoveContact,\n                confirmDeleteSelectedMessages: renderConfirmDeleteSelectedMessages,\n                confirmDeleteConversation: renderConfirmDeleteConversation,\n                confirmContactRequest: renderConfirmContactRequest,\n                requireAddContact: renderRequireAddContact,\n                selfConversationMessage: renderSelfConversationMessage,\n                contactRequestSent: renderContactRequestSent\n            },\n            {\n                loadingMembers: renderLoadingMembers,\n                loadingFirstMessages: renderLoadingFirstMessages,\n                loadingMessages: renderLoadingMessages,\n                isBlocked: renderIsBlocked,\n                isContact: renderIsContact,\n                isFavourite: renderIsFavourite,\n                isMuted: renderIsMuted,\n                loadingConfirmAction: renderLoadingConfirmAction,\n                inEditMode: renderInEditMode\n            },\n            {\n                // Scrolling should be last to make sure everything\n                // on the page is visible.\n                scrollToMessage: renderScrollToMessage,\n                selectedMessages: renderSelectedMessages\n            }\n        ];\n        // Helper function to process each of the configs above.\n        var processConfig = function(config) {\n            var results = [];\n\n            for (var key in patch) {\n                if (config.hasOwnProperty(key)) {\n                    var renderFunc = config[key];\n                    var patchValue = patch[key];\n                    results.push(renderFunc(header, body, footer, patchValue));\n                }\n            }\n\n            return results;\n        };\n\n        // The first config is special because it resets the UI.\n        var renderingPromises = processConfig(configs[0]);\n        // The second config is special because it contains async rendering.\n        renderingPromises = renderingPromises.concat(processConfig(configs[1]));\n\n        // Wait for the async rendering to complete before processing the\n        // rest of the configs, in order.\n        return $.when.apply($, renderingPromises)\n            .then(function() {\n                for (var i = 2; i < configs.length; i++) {\n                    processConfig(configs[i]);\n                }\n\n                return;\n            })\n            .catch(Notification.exception);\n    };\n\n    return {\n        render: render,\n    };\n});\n"],"file":"message_drawer_view_conversation_renderer.min.js"}
\ No newline at end of file
diff --git a/message/amd/build/message_drawer_view_conversation_state_manager.min.js b/message/amd/build/message_drawer_view_conversation_state_manager.min.js
index a2a59b9a1d4..c827c077429 100644
--- a/message/amd/build/message_drawer_view_conversation_state_manager.min.js
+++ b/message/amd/build/message_drawer_view_conversation_state_manager.min.js
@@ -1,2 +1,2 @@
-define ("core_message/message_drawer_view_conversation_state_manager",["jquery"],function(a){var b=function(b){return a.extend(!0,{},b)},c=function(a,b,c){return a.map(function(a){var d=a.useridfrom==b;return{id:""+a.id,fromLoggedInUser:d,userFrom:c[a.useridfrom],text:a.text,timeCreated:a.timecreated?parseInt(a.timecreated,10):null}})},d=function(a){return a.map(function(a){return{id:a.id,fullname:a.fullname,profileurl:a.profileurl,profileimageurl:a.profileimageurl,profileimageurlsmall:a.profileimageurlsmall,isonline:a.isonline,showonlinestatus:a.showonlinestatus,isblocked:a.isblocked,iscontact:a.iscontact,isdeleted:a.isdeleted,canmessage:a.canmessage,requirescontact:a.requirescontact,contactrequests:a.contactrequests||[]}})};return{buildInitialState:function buildInitialState(a,b,c,d,e,f){return{midnight:a,loggedInUserId:b,id:c,messagePollMin:d,messagePollMax:e,messagePollAfterMax:f,name:null,subname:null,type:null,totalMemberCount:null,imageUrl:null,isFavourite:null,isMuted:null,canDeleteMessagesForAllUsers:!1,deleteMessagesForAllUsers:!1,members:{},messages:[],hasTriedToLoadMessages:!1,loadingMessages:!0,loadingMembers:!0,loadingConfirmAction:!1,pendingBlockUserIds:[],pendingUnblockUserIds:[],pendingRemoveContactIds:[],pendingAddContactIds:[],pendingDeleteMessageIds:[],pendingSendMessageIds:[],pendingDeleteConversation:!1,selectedMessageIds:[]}},addMessages:function addMessages(a,d){var e=b(a),f=c(d,a.loggedInUserId,a.members);f=f.map(function(a){a.sendState=null;a.timeAdded=Date.now();a.errorMessage=null;return a});var g=a.messages.concat(f);g.sort(function(c,a){if(null===c.timeCreated&&null===a.timeCreated){if(c.timeAdded<a.timeAdded){return-1}else if(c.timeAdded>a.timeAdded){return 1}}if(null===c.timeCreated&&null!==a.timeCreated){return 1}else if(null!==c.timeCreated&&null===a.timeCreated){return-1}else if(c.timeCreated<a.timeCreated){return-1}else if(c.timeCreated>a.timeCreated){return 1}else if(c.id<a.id){return-1}else if(c.id>a.id){return 1}else{return 0}});e.messages=g.filter(function(a,b,c){return!b||a.id!=c[b-1].id});return e},updateMessages:function updateMessages(d,e){var f=b(d),g=e.reduce(function(a,b){var e=b[0],f=b[1],g=c([f],d.loggedInUserId,d.members),h=g[0];a[e.id]=h;return a},{});f.messages=f.messages.map(function(b){if(b.id in g){return a.extend(b,g[b.id])}else{return b}});return f},removeMessages:function removeMessages(a,c){var d=b(a),e=c.map(function(a){return""+a.id});d.messages=d.messages.filter(function(a){return 0>e.indexOf(a.id)});return d},removeMessagesById:function removeMessagesById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.messages=d.messages.filter(function(a){return 0>c.indexOf(a.id)});return d},addMembers:function addMembers(a,c){var e=b(a),f=d(c);f.forEach(function(a){e.members[a.id]=a});return e},removeMembers:function removeMembers(a,c){var d=b(a);c.forEach(function(a){delete d.members[a.id]});return d},setLoadingMessages:function setLoadingMessages(a,c){var d=b(a);d.loadingMessages=c;if(a.loadingMessages&&!c){d.hasTriedToLoadMessages=!0}return d},setLoadingMembers:function setLoadingMembers(a,c){var d=b(a);d.loadingMembers=c;return d},setId:function setId(a,c){var d=b(a);d.id=c;return d},setName:function setName(a,c){var d=b(a);d.name=c;return d},setSubname:function setSubname(a,c){var d=b(a);d.subname=c;return d},setType:function setType(a,c){var d=b(a);d.type=c;return d},setIsFavourite:function setIsFavourite(a,c){var d=b(a);d.isFavourite=c;return d},setIsMuted:function setIsMuted(a,c){var d=b(a);d.isMuted=c;return d},setCanDeleteMessagesForAllUsers:function setCanDeleteMessagesForAllUsers(a,c){var d=b(a);d.canDeleteMessagesForAllUsers=c;return d},setDeleteMessagesForAllUsers:function setDeleteMessagesForAllUsers(a,c){var d=b(a);d.deleteMessagesForAllUsers=c;return d},setTotalMemberCount:function setTotalMemberCount(a,c){var d=b(a);d.totalMemberCount=c;return d},setImageUrl:function setImageUrl(a,c){var d=b(a);d.imageUrl=c;return d},setLoadingConfirmAction:function setLoadingConfirmAction(a,c){var d=b(a);d.loadingConfirmAction=c;return d},setPendingDeleteConversation:function setPendingDeleteConversation(a,c){var d=b(a);d.pendingDeleteConversation=c;return d},setMessagesSendPendingById:function setMessagesSendPendingById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.messages.forEach(function(a){if(0<=c.indexOf(a.id)){a.sendState="pending";a.errorMessage=null}});return d},setMessagesSendSuccessById:function setMessagesSendSuccessById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.messages.forEach(function(a){if(0<=c.indexOf(a.id)){a.sendState="sent";a.errorMessage=null}});return d},setMessagesSendFailById:function setMessagesSendFailById(a,c,d){var e=b(a);c=c.map(function(a){return""+a});e.messages.forEach(function(a){if(0<=c.indexOf(a.id)){a.sendState="error";a.errorMessage=d}});return e},addPendingBlockUsersById:function addPendingBlockUsersById(a,c){var d=b(a);c.forEach(function(a){d.pendingBlockUserIds.push(a)});return d},addPendingRemoveContactsById:function addPendingRemoveContactsById(a,c){var d=b(a);c.forEach(function(a){d.pendingRemoveContactIds.push(a)});return d},addPendingUnblockUsersById:function addPendingUnblockUsersById(a,c){var d=b(a);c.forEach(function(a){d.pendingUnblockUserIds.push(a)});return d},addPendingAddContactsById:function addPendingAddContactsById(a,c){var d=b(a);c.forEach(function(a){d.pendingAddContactIds.push(a)});return d},addPendingDeleteMessagesById:function addPendingDeleteMessagesById(a,c){var d=b(a);c.forEach(function(a){d.pendingDeleteMessageIds.push(a)});return d},removePendingBlockUsersById:function removePendingBlockUsersById(a,c){var d=b(a);d.pendingBlockUserIds=d.pendingBlockUserIds.filter(function(a){return 0>c.indexOf(a)});return d},removePendingRemoveContactsById:function removePendingRemoveContactsById(a,c){var d=b(a);d.pendingRemoveContactIds=d.pendingRemoveContactIds.filter(function(a){return 0>c.indexOf(a)});return d},removePendingUnblockUsersById:function removePendingUnblockUsersById(a,c){var d=b(a);d.pendingUnblockUserIds=d.pendingUnblockUserIds.filter(function(a){return 0>c.indexOf(a)});return d},removePendingAddContactsById:function removePendingAddContactsById(a,c){var d=b(a);d.pendingAddContactIds=d.pendingAddContactIds.filter(function(a){return 0>c.indexOf(a)});return d},removePendingDeleteMessagesById:function removePendingDeleteMessagesById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.pendingDeleteMessageIds=d.pendingDeleteMessageIds.filter(function(a){return 0>c.indexOf(a)});return d},addSelectedMessagesById:function addSelectedMessagesById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.selectedMessageIds=d.selectedMessageIds.concat(c);return d},removeSelectedMessagesById:function removeSelectedMessagesById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.selectedMessageIds=d.selectedMessageIds.filter(function(a){return 0>c.indexOf(a)});return d},markMessagesAsRead:function markMessagesAsRead(a,c){var d=b(a),e=c.map(function(a){return a.id});d.messages=d.messages.map(function(a){if(0<=e.indexOf(a.id)){a.isRead=!0}return a});return d},addContactRequests:function addContactRequests(a,c){var d=b(a);c.forEach(function(a){var b=a.userid,c=a.requesteduserid;d.members[b].contactrequests.push(a);d.members[c].contactrequests.push(a)});return d},removeContactRequests:function removeContactRequests(a,c){var d=b(a);c.forEach(function(a){var b=a.userid,c=a.requesteduserid;d.members[b].contactrequests=d.members[b].contactrequests.filter(function(a){return a.userid!=b});d.members[c].contactrequests=d.members[c].contactrequests.filter(function(a){return a.requesteduserid!=c})});return d}}});
+define ("core_message/message_drawer_view_conversation_state_manager",["jquery"],function(a){var b=function(b){return a.extend(!0,{},b)},c=function(a,b,c){return a.map(function(a){var d=a.useridfrom==b;return{id:""+a.id,fromLoggedInUser:d,userFrom:c[a.useridfrom],text:a.text,timeCreated:a.timecreated?parseInt(a.timecreated,10):null}})},d=function(a){return a.map(function(a){return{id:a.id,fullname:a.fullname,profileurl:a.profileurl,profileimageurl:a.profileimageurl,profileimageurlsmall:a.profileimageurlsmall,isonline:a.isonline,showonlinestatus:a.showonlinestatus,isblocked:a.isblocked,iscontact:a.iscontact,isdeleted:a.isdeleted,canmessage:a.canmessage,canmessageevenifblocked:a.canmessageevenifblocked,requirescontact:a.requirescontact,contactrequests:a.contactrequests||[]}})};return{buildInitialState:function buildInitialState(a,b,c,d,e,f){return{midnight:a,loggedInUserId:b,id:c,messagePollMin:d,messagePollMax:e,messagePollAfterMax:f,name:null,subname:null,type:null,totalMemberCount:null,imageUrl:null,isFavourite:null,isMuted:null,canDeleteMessagesForAllUsers:!1,deleteMessagesForAllUsers:!1,members:{},messages:[],hasTriedToLoadMessages:!1,loadingMessages:!0,loadingMembers:!0,loadingConfirmAction:!1,pendingBlockUserIds:[],pendingUnblockUserIds:[],pendingRemoveContactIds:[],pendingAddContactIds:[],pendingDeleteMessageIds:[],pendingSendMessageIds:[],pendingDeleteConversation:!1,selectedMessageIds:[]}},addMessages:function addMessages(a,d){var e=b(a),f=c(d,a.loggedInUserId,a.members);f=f.map(function(a){a.sendState=null;a.timeAdded=Date.now();a.errorMessage=null;return a});var g=a.messages.concat(f);g.sort(function(c,a){if(null===c.timeCreated&&null===a.timeCreated){if(c.timeAdded<a.timeAdded){return-1}else if(c.timeAdded>a.timeAdded){return 1}}if(null===c.timeCreated&&null!==a.timeCreated){return 1}else if(null!==c.timeCreated&&null===a.timeCreated){return-1}else if(c.timeCreated<a.timeCreated){return-1}else if(c.timeCreated>a.timeCreated){return 1}else if(c.id<a.id){return-1}else if(c.id>a.id){return 1}else{return 0}});e.messages=g.filter(function(a,b,c){return!b||a.id!=c[b-1].id});return e},updateMessages:function updateMessages(d,e){var f=b(d),g=e.reduce(function(a,b){var e=b[0],f=b[1],g=c([f],d.loggedInUserId,d.members),h=g[0];a[e.id]=h;return a},{});f.messages=f.messages.map(function(b){if(b.id in g){return a.extend(b,g[b.id])}else{return b}});return f},removeMessages:function removeMessages(a,c){var d=b(a),e=c.map(function(a){return""+a.id});d.messages=d.messages.filter(function(a){return 0>e.indexOf(a.id)});return d},removeMessagesById:function removeMessagesById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.messages=d.messages.filter(function(a){return 0>c.indexOf(a.id)});return d},addMembers:function addMembers(a,c){var e=b(a),f=d(c);f.forEach(function(a){e.members[a.id]=a});return e},removeMembers:function removeMembers(a,c){var d=b(a);c.forEach(function(a){delete d.members[a.id]});return d},setLoadingMessages:function setLoadingMessages(a,c){var d=b(a);d.loadingMessages=c;if(a.loadingMessages&&!c){d.hasTriedToLoadMessages=!0}return d},setLoadingMembers:function setLoadingMembers(a,c){var d=b(a);d.loadingMembers=c;return d},setId:function setId(a,c){var d=b(a);d.id=c;return d},setName:function setName(a,c){var d=b(a);d.name=c;return d},setSubname:function setSubname(a,c){var d=b(a);d.subname=c;return d},setType:function setType(a,c){var d=b(a);d.type=c;return d},setIsFavourite:function setIsFavourite(a,c){var d=b(a);d.isFavourite=c;return d},setIsMuted:function setIsMuted(a,c){var d=b(a);d.isMuted=c;return d},setCanDeleteMessagesForAllUsers:function setCanDeleteMessagesForAllUsers(a,c){var d=b(a);d.canDeleteMessagesForAllUsers=c;return d},setDeleteMessagesForAllUsers:function setDeleteMessagesForAllUsers(a,c){var d=b(a);d.deleteMessagesForAllUsers=c;return d},setTotalMemberCount:function setTotalMemberCount(a,c){var d=b(a);d.totalMemberCount=c;return d},setImageUrl:function setImageUrl(a,c){var d=b(a);d.imageUrl=c;return d},setLoadingConfirmAction:function setLoadingConfirmAction(a,c){var d=b(a);d.loadingConfirmAction=c;return d},setPendingDeleteConversation:function setPendingDeleteConversation(a,c){var d=b(a);d.pendingDeleteConversation=c;return d},setMessagesSendPendingById:function setMessagesSendPendingById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.messages.forEach(function(a){if(0<=c.indexOf(a.id)){a.sendState="pending";a.errorMessage=null}});return d},setMessagesSendSuccessById:function setMessagesSendSuccessById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.messages.forEach(function(a){if(0<=c.indexOf(a.id)){a.sendState="sent";a.errorMessage=null}});return d},setMessagesSendFailById:function setMessagesSendFailById(a,c,d){var e=b(a);c=c.map(function(a){return""+a});e.messages.forEach(function(a){if(0<=c.indexOf(a.id)){a.sendState="error";a.errorMessage=d}});return e},addPendingBlockUsersById:function addPendingBlockUsersById(a,c){var d=b(a);c.forEach(function(a){d.pendingBlockUserIds.push(a)});return d},addPendingRemoveContactsById:function addPendingRemoveContactsById(a,c){var d=b(a);c.forEach(function(a){d.pendingRemoveContactIds.push(a)});return d},addPendingUnblockUsersById:function addPendingUnblockUsersById(a,c){var d=b(a);c.forEach(function(a){d.pendingUnblockUserIds.push(a)});return d},addPendingAddContactsById:function addPendingAddContactsById(a,c){var d=b(a);c.forEach(function(a){d.pendingAddContactIds.push(a)});return d},addPendingDeleteMessagesById:function addPendingDeleteMessagesById(a,c){var d=b(a);c.forEach(function(a){d.pendingDeleteMessageIds.push(a)});return d},removePendingBlockUsersById:function removePendingBlockUsersById(a,c){var d=b(a);d.pendingBlockUserIds=d.pendingBlockUserIds.filter(function(a){return 0>c.indexOf(a)});return d},removePendingRemoveContactsById:function removePendingRemoveContactsById(a,c){var d=b(a);d.pendingRemoveContactIds=d.pendingRemoveContactIds.filter(function(a){return 0>c.indexOf(a)});return d},removePendingUnblockUsersById:function removePendingUnblockUsersById(a,c){var d=b(a);d.pendingUnblockUserIds=d.pendingUnblockUserIds.filter(function(a){return 0>c.indexOf(a)});return d},removePendingAddContactsById:function removePendingAddContactsById(a,c){var d=b(a);d.pendingAddContactIds=d.pendingAddContactIds.filter(function(a){return 0>c.indexOf(a)});return d},removePendingDeleteMessagesById:function removePendingDeleteMessagesById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.pendingDeleteMessageIds=d.pendingDeleteMessageIds.filter(function(a){return 0>c.indexOf(a)});return d},addSelectedMessagesById:function addSelectedMessagesById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.selectedMessageIds=d.selectedMessageIds.concat(c);return d},removeSelectedMessagesById:function removeSelectedMessagesById(a,c){var d=b(a);c=c.map(function(a){return""+a});d.selectedMessageIds=d.selectedMessageIds.filter(function(a){return 0>c.indexOf(a)});return d},markMessagesAsRead:function markMessagesAsRead(a,c){var d=b(a),e=c.map(function(a){return a.id});d.messages=d.messages.map(function(a){if(0<=e.indexOf(a.id)){a.isRead=!0}return a});return d},addContactRequests:function addContactRequests(a,c){var d=b(a);c.forEach(function(a){var b=a.userid,c=a.requesteduserid;d.members[b].contactrequests.push(a);d.members[c].contactrequests.push(a)});return d},removeContactRequests:function removeContactRequests(a,c){var d=b(a);c.forEach(function(a){var b=a.userid,c=a.requesteduserid;d.members[b].contactrequests=d.members[b].contactrequests.filter(function(a){return a.userid!=b});d.members[c].contactrequests=d.members[c].contactrequests.filter(function(a){return a.requesteduserid!=c})});return d}}});
 //# sourceMappingURL=message_drawer_view_conversation_state_manager.min.js.map
diff --git a/message/amd/build/message_drawer_view_conversation_state_manager.min.js.map b/message/amd/build/message_drawer_view_conversation_state_manager.min.js.map
index 598219488c1..7da84f3a9b4 100644
--- a/message/amd/build/message_drawer_view_conversation_state_manager.min.js.map
+++ b/message/amd/build/message_drawer_view_conversation_state_manager.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/message_drawer_view_conversation_state_manager.js"],"names":["define","$","cloneState","state","extend","formatMessages","messages","loggedInUserId","members","map","message","fromLoggedInUser","useridfrom","id","userFrom","text","timeCreated","timecreated","parseInt","formatMembers","member","fullname","profileurl","profileimageurl","profileimageurlsmall","isonline","showonlinestatus","isblocked","iscontact","isdeleted","canmessage","requirescontact","contactrequests","buildInitialState","midnight","messagePollMin","messagePollMax","messagePollAfterMax","name","subname","type","totalMemberCount","imageUrl","isFavourite","isMuted","canDeleteMessagesForAllUsers","deleteMessagesForAllUsers","hasTriedToLoadMessages","loadingMessages","loadingMembers","loadingConfirmAction","pendingBlockUserIds","pendingUnblockUserIds","pendingRemoveContactIds","pendingAddContactIds","pendingDeleteMessageIds","pendingSendMessageIds","pendingDeleteConversation","selectedMessageIds","addMessages","newState","formattedMessages","sendState","timeAdded","Date","now","errorMessage","allMessages","concat","sort","a","b","filter","index","sortedMessages","updateMessages","data","updatesById","reduce","carry","messageData","oldMessage","newMessage","formattedMessage","removeMessages","removeMessageIds","indexOf","removeMessagesById","messageIds","addMembers","formattedMembers","forEach","removeMembers","setLoadingMessages","value","setLoadingMembers","setId","setName","setSubname","setType","setIsFavourite","setIsMuted","setCanDeleteMessagesForAllUsers","setDeleteMessagesForAllUsers","setTotalMemberCount","count","setImageUrl","url","setLoadingConfirmAction","setPendingDeleteConversation","setMessagesSendPendingById","setMessagesSendSuccessById","setMessagesSendFailById","addPendingBlockUsersById","userIds","push","addPendingRemoveContactsById","addPendingUnblockUsersById","addPendingAddContactsById","addPendingDeleteMessagesById","removePendingBlockUsersById","removePendingRemoveContactsById","removePendingUnblockUsersById","removePendingAddContactsById","removePendingDeleteMessagesById","addSelectedMessagesById","removeSelectedMessagesById","markMessagesAsRead","readMessages","readMessageIds","isRead","addContactRequests","requests","request","fromUserId","userid","toUserId","requesteduserid","removeContactRequests","existing"],"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 * This module operates on the view states from the message_drawer_view_conversation module.\n * It exposes functions that can be used to generate new version of the state.\n *\n * Important notes for this module:\n * 1.) The existing state is always immutable. It should never be modified.\n * 2.) All functions that operate on the state should always clone the state and\n *     modify the cloned state before returning it.\n *\n * It's important that the states remain immutable because they are diff'd in\n * the message_drawer_view_conversation_patcher module in order to work out what\n * has changed.\n *\n * @module     core_message/message_drawer_view_conversation_state_manager\n * @copyright  2018 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery'], function($) {\n\n    /**\n     * Clone a state, a state is a collection of information about the variables required to build\n     * the conversation user interface.\n     *\n     * @param  {Object} state State to clone\n     * @return {Object} newstate A copy of the state to clone.\n     */\n    var cloneState = function(state) {\n        // Do a deep extend to make sure we recursively copy objects and\n        // arrays so that the new state doesn't contain any references to\n        // the old state, e.g. adding a value to an array in the new state\n        // shouldn't also add it to the old state.\n        return $.extend(true, {}, state);\n    };\n\n    /**\n     * Format messages to be used in a state.\n     *\n     * @param  {Array} messages The messages to format.\n     * @param  {Number} loggedInUserId The logged in user id.\n     * @param  {Array} members The converstation members.\n     * @return {Array} Formatted messages.\n     */\n    var formatMessages = function(messages, loggedInUserId, members) {\n        return messages.map(function(message) {\n            var fromLoggedInUser = message.useridfrom == loggedInUserId;\n            return {\n                // Stringify the id.\n                id: \"\" + message.id,\n                fromLoggedInUser: fromLoggedInUser,\n                userFrom: members[message.useridfrom],\n                text: message.text,\n                timeCreated: message.timecreated ? parseInt(message.timecreated, 10) : null\n            };\n        });\n    };\n\n    /**\n     * Format members to be used in a state.\n     *\n     * @param  {Array} members The messages to format.\n     * @return {Array} Formatted members.\n     */\n    var formatMembers = function(members) {\n        return members.map(function(member) {\n            return {\n                id: member.id,\n                fullname: member.fullname,\n                profileurl: member.profileurl,\n                profileimageurl: member.profileimageurl,\n                profileimageurlsmall: member.profileimageurlsmall,\n                isonline:  member.isonline,\n                showonlinestatus: member.showonlinestatus,\n                isblocked: member.isblocked,\n                iscontact: member.iscontact,\n                isdeleted: member.isdeleted,\n                canmessage:  member.canmessage,\n                requirescontact: member.requirescontact,\n                contactrequests: member.contactrequests || []\n            };\n        });\n    };\n\n    /**\n     * Create an initial (blank) state.\n     *\n     * @param  {Number} midnight Midnight time.\n     * @param  {Number} loggedInUserId The logged in user id.\n     * @param  {Number} id The conversation id.\n     * @param  {Number} messagePollMin The message poll start timeout in seconds.\n     * @param  {Number} messagePollMax The message poll max timeout limit in seconds.\n     * @param  {Number} messagePollAfterMax The message poll frequency in seconds to reset to after max limit is reached.\n     * @return {Object} Initial state.\n     */\n    var buildInitialState = function(\n        midnight,\n        loggedInUserId,\n        id,\n        messagePollMin,\n        messagePollMax,\n        messagePollAfterMax\n    ) {\n        return {\n            midnight: midnight,\n            loggedInUserId: loggedInUserId,\n            id: id,\n            messagePollMin: messagePollMin,\n            messagePollMax: messagePollMax,\n            messagePollAfterMax: messagePollAfterMax,\n            name: null,\n            subname: null,\n            type: null,\n            totalMemberCount: null,\n            imageUrl: null,\n            isFavourite: null,\n            isMuted: null,\n            canDeleteMessagesForAllUsers: false,\n            deleteMessagesForAllUsers: false,\n            members: {},\n            messages: [],\n            hasTriedToLoadMessages: false,\n            loadingMessages: true,\n            loadingMembers: true,\n            loadingConfirmAction: false,\n            pendingBlockUserIds: [],\n            pendingUnblockUserIds: [],\n            pendingRemoveContactIds: [],\n            pendingAddContactIds: [],\n            pendingDeleteMessageIds: [],\n            pendingSendMessageIds: [],\n            pendingDeleteConversation: false,\n            selectedMessageIds: []\n        };\n    };\n\n    /**\n     * Add messages to a state and sort them by timecreated.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messages Messages to add to state.\n     * @return {Object} state New state with added messages.\n     */\n    var addMessages = function(state, messages) {\n        var newState = cloneState(state);\n        var formattedMessages = formatMessages(messages, state.loggedInUserId, state.members);\n        formattedMessages = formattedMessages.map(function(message) {\n            message.sendState = null;\n            message.timeAdded = Date.now();\n            message.errorMessage = null;\n            return message;\n        });\n        var allMessages = state.messages.concat(formattedMessages);\n        // Sort the messages. Oldest to newest.\n        allMessages.sort(function(a, b) {\n            if (a.timeCreated === null && b.timeCreated === null) {\n                if (a.timeAdded < b.timeAdded) {\n                    return -1;\n                } else if (a.timeAdded > b.timeAdded) {\n                    return 1;\n                }\n            }\n\n            if (a.timeCreated === null && b.timeCreated !== null) {\n                // A comes after b.\n                return 1;\n            } else if (a.timeCreated !== null && b.timeCreated === null) {\n                // A comes before b.\n                return -1;\n            } else if (a.timeCreated < b.timeCreated) {\n                // A comes before b.\n                return -1;\n            } else if (a.timeCreated > b.timeCreated) {\n                // A comes after b.\n                return 1;\n            } else if (a.id < b.id) {\n                return -1;\n            } else if (a.id > b.id) {\n                return 1;\n            } else {\n                return 0;\n            }\n        });\n\n        // Filter out any duplicate messages.\n        newState.messages = allMessages.filter(function(message, index, sortedMessages) {\n            return !index || message.id != sortedMessages[index - 1].id;\n        });\n\n        return newState;\n    };\n\n    /**\n     * Update existing messages.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} data 2D array of old and new messages\n     * @return {Object} state.\n     */\n    var updateMessages = function(state, data) {\n        var newState = cloneState(state);\n        var updatesById = data.reduce(function(carry, messageData) {\n            var oldMessage = messageData[0];\n            var newMessage = messageData[1];\n            var formattedMessages = formatMessages([newMessage], state.loggedInUserId, state.members);\n            var formattedMessage = formattedMessages[0];\n\n            carry[oldMessage.id] = formattedMessage;\n            return carry;\n        }, {});\n\n        newState.messages = newState.messages.map(function(message) {\n            if (message.id in updatesById) {\n                return $.extend(message, updatesById[message.id]);\n            } else {\n                return message;\n            }\n        });\n\n        return newState;\n    };\n\n    /**\n     * Remove messages from state.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messages Messages to remove from state.\n     * @return {Object} state New state with removed messages.\n     */\n    var removeMessages = function(state, messages) {\n        var newState = cloneState(state);\n        var removeMessageIds = messages.map(function(message) {\n            return \"\" + message.id;\n        });\n        newState.messages = newState.messages.filter(function(message) {\n            return removeMessageIds.indexOf(message.id) < 0;\n        });\n\n        return newState;\n    };\n\n    /**\n     * Remove messages from state by message id.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Message ids to remove from state.\n     * @return {Object} state New state with removed messages.\n     */\n    var removeMessagesById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.messages = newState.messages.filter(function(message) {\n            return messageIds.indexOf(message.id) < 0;\n        });\n\n        return newState;\n    };\n\n    /**\n     * Add conversation member to state.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} members Conversation members to be added to state.\n     * @return {Object} New state with added members.\n     */\n    var addMembers = function(state, members) {\n        var newState = cloneState(state);\n        var formattedMembers = formatMembers(members);\n        formattedMembers.forEach(function(member) {\n            newState.members[member.id] = member;\n        });\n        return newState;\n    };\n\n    /**\n     * Remove members from state.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} members Members to be removed from state.\n     * @return {Object} New state with removed members.\n     */\n    var removeMembers = function(state, members) {\n        var newState = cloneState(state);\n        members.forEach(function(member) {\n            delete newState.members[member.id];\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state loading messages attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value New loading messages value.\n     * @return {Object} New state with loading messages attribute.\n     */\n    var setLoadingMessages = function(state, value) {\n        var newState = cloneState(state);\n        newState.loadingMessages = value;\n        if (state.loadingMessages && !value) {\n            // If we're going from loading to not loading then\n            // it means we've tried to load.\n            newState.hasTriedToLoadMessages = true;\n        }\n        return newState;\n    };\n\n    /**\n     * Set the state loading members attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value New loading members value.\n     * @return {Object} New state with loading members attribute.\n     */\n    var setLoadingMembers = function(state, value) {\n        var newState = cloneState(state);\n        newState.loadingMembers = value;\n        return newState;\n    };\n\n    /**\n     * Set the conversation id.\n     *\n     * @param  {Object} state Current state.\n     * @param  {String} value The ID.\n     * @return {Object} New state.\n     */\n    var setId = function(state, value) {\n        var newState = cloneState(state);\n        newState.id = value;\n        return newState;\n    };\n\n    /**\n     * Set the state name attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {String} value New name value.\n     * @return {Object} New state with name attribute.\n     */\n    var setName = function(state, value) {\n        var newState = cloneState(state);\n        newState.name = value;\n        return newState;\n    };\n\n    /**\n     * Set the state subname attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {String} value New subname value.\n     * @return {Object} New state.\n     */\n    var setSubname = function(state, value) {\n        var newState = cloneState(state);\n        newState.subname = value;\n        return newState;\n    };\n\n    /**\n     * Set the conversation type.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Int} type Conversation type.\n     * @return {Object} New state.\n     */\n    var setType = function(state, type) {\n        var newState = cloneState(state);\n        newState.type = type;\n        return newState;\n    };\n\n    /**\n     * Set whether the conversation is a favourite conversation.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} isFavourite If it's a favourite.\n     * @return {Object} New state.\n     */\n    var setIsFavourite = function(state, isFavourite) {\n        var newState = cloneState(state);\n        newState.isFavourite = isFavourite;\n        return newState;\n    };\n\n    /**\n     * Set whether the conversation is a muted conversation.\n     *\n     * @param  {Object} state Current state.\n     * @param  {bool} isMuted If it's muted.\n     * @return {Object} New state.\n     */\n    var setIsMuted = function(state, isMuted) {\n        var newState = cloneState(state);\n        newState.isMuted = isMuted;\n        return newState;\n    };\n\n    /**\n     * Set the total member count.\n     *\n     * @param  {Object} state Current state.\n     * @param  {String} count The count.\n     * @return {Object} New state.\n     */\n    var setTotalMemberCount = function(state, count) {\n        var newState = cloneState(state);\n        newState.totalMemberCount = count;\n        return newState;\n    };\n\n    /**\n     * Set the conversation image url.\n     *\n     * @param  {Object} state Current state.\n     * @param  {String} url The url to the image.\n     * @return {Object} New state.\n     */\n    var setImageUrl = function(state, url) {\n        var newState = cloneState(state);\n        newState.imageUrl = url;\n        return newState;\n    };\n\n    /**\n     * Set the state loading confirm action attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value New loading confirm action value.\n     * @return {Object} New state with loading confirm action attribute.\n     */\n    var setLoadingConfirmAction = function(state, value) {\n        var newState = cloneState(state);\n        newState.loadingConfirmAction = value;\n        return newState;\n    };\n\n    /**\n     * Set the state pending delete conversation attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value New pending delete conversation value.\n     * @return {Object} New state with pending delete conversation attribute.\n     */\n    var setPendingDeleteConversation = function(state, value) {\n        var newState = cloneState(state);\n        newState.pendingDeleteConversation = value;\n        return newState;\n    };\n\n    /**\n     * Set the state of message to pending.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages to delete.\n     * @return {Object} New state with array of pending delete message ids.\n     */\n    var setMessagesSendPendingById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.messages.forEach(function(message) {\n            if (messageIds.indexOf(message.id) >= 0) {\n                message.sendState = 'pending';\n                message.errorMessage = null;\n            }\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state of message to sent.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages to delete.\n     * @return {Object} New state with array of pending delete message ids.\n     */\n    var setMessagesSendSuccessById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.messages.forEach(function(message) {\n            if (messageIds.indexOf(message.id) >= 0) {\n                message.sendState = 'sent';\n                message.errorMessage = null;\n            }\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state of messages to error.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages to delete.\n     * @return {Object} New state with array of pending delete message ids.\n     */\n    var setMessagesSendFailById = function(state, messageIds, errorMessage) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.messages.forEach(function(message) {\n            if (messageIds.indexOf(message.id) >= 0) {\n                message.sendState = 'error';\n                message.errorMessage = errorMessage;\n            }\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state pending block userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to block.\n     * @return {Object} New state with array of pending block userids.\n     */\n    var addPendingBlockUsersById = function(state, userIds) {\n        var newState = cloneState(state);\n        userIds.forEach(function(id) {\n            newState.pendingBlockUserIds.push(id);\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state pending remove userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to remove.\n     * @return {Object} New state with array of pending remove userids.\n     */\n    var addPendingRemoveContactsById = function(state, userIds) {\n        var newState = cloneState(state);\n        userIds.forEach(function(id) {\n            newState.pendingRemoveContactIds.push(id);\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state pending unblock userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to unblock.\n     * @return {Object} New state with array of pending unblock userids.\n     */\n    var addPendingUnblockUsersById = function(state, userIds) {\n        var newState = cloneState(state);\n        userIds.forEach(function(id) {\n            newState.pendingUnblockUserIds.push(id);\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state pending add users to contacts userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to add users to contacts.\n     * @return {Object} New state with array of pending add users to contacts userids.\n     */\n    var addPendingAddContactsById = function(state, userIds) {\n        var newState = cloneState(state);\n        userIds.forEach(function(id) {\n            newState.pendingAddContactIds.push(id);\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state pending delete messages.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages to delete.\n     * @return {Object} New state with array of pending delete message ids.\n     */\n    var addPendingDeleteMessagesById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds.forEach(function(id) {\n            newState.pendingDeleteMessageIds.push(id);\n        });\n        return newState;\n    };\n\n    /**\n     * Update the state pending block userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to remove from the list of user ids to block.\n     * @return {Object} New state with array of pending block userids.\n     */\n    var removePendingBlockUsersById = function(state, userIds) {\n        var newState = cloneState(state);\n        newState.pendingBlockUserIds = newState.pendingBlockUserIds.filter(function(id) {\n            return userIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Update the state pending remove userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to remove from the list of user ids to remove.\n     * @return {Object} New state with array of pending remove userids.\n     */\n    var removePendingRemoveContactsById = function(state, userIds) {\n        var newState = cloneState(state);\n        newState.pendingRemoveContactIds = newState.pendingRemoveContactIds.filter(function(id) {\n            return userIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Update the state pending unblock userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to remove from the list of user ids to unblock.\n     * @return {Object} New state with array of pending unblock userids.\n     */\n    var removePendingUnblockUsersById = function(state, userIds) {\n        var newState = cloneState(state);\n        newState.pendingUnblockUserIds = newState.pendingUnblockUserIds.filter(function(id) {\n            return userIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Update the state pending add to contacts userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to remove from the list of user ids to add to contacts.\n     * @return {Object} New state with array of pending add to contacts userids.\n     */\n    var removePendingAddContactsById = function(state, userIds) {\n        var newState = cloneState(state);\n        newState.pendingAddContactIds = newState.pendingAddContactIds.filter(function(id) {\n            return userIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Update the state pending delete messages userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Message ids to remove from the list of messages to delete.\n     * @return {Object} New state with array of messages to delete.\n     */\n    var removePendingDeleteMessagesById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.pendingDeleteMessageIds = newState.pendingDeleteMessageIds.filter(function(id) {\n            return messageIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Add messages to state selected messages.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages that are selected.\n     * @return {Object} New state with array of not blocked members.\n     */\n    var addSelectedMessagesById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.selectedMessageIds = newState.selectedMessageIds.concat(messageIds);\n        return newState;\n    };\n\n    /**\n     * Remove messages from the state selected messages.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages to remove from selected messages.\n     * @return {Object} New state with array of selected messages.\n     */\n    var removeSelectedMessagesById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.selectedMessageIds = newState.selectedMessageIds.filter(function(id) {\n            return messageIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Mark messages as read.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} readMessages Messages that are read.\n     * @return {Object} New state with array of messages that have the isread attribute set.\n     */\n    var markMessagesAsRead = function(state, readMessages) {\n        var newState = cloneState(state);\n        var readMessageIds = readMessages.map(function(message) {\n            return message.id;\n        });\n        newState.messages = newState.messages.map(function(message) {\n            if (readMessageIds.indexOf(message.id) >= 0) {\n                message.isRead = true;\n            }\n\n            return message;\n        });\n        return newState;\n    };\n\n    /**\n     * Add a contact request to each of the members that the request is for.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} requests The contact requests\n     * @return {Object} New state\n     */\n    var addContactRequests = function(state, requests) {\n        var newState = cloneState(state);\n\n        requests.forEach(function(request) {\n            var fromUserId = request.userid;\n            var toUserId = request.requesteduserid;\n            newState.members[fromUserId].contactrequests.push(request);\n            newState.members[toUserId].contactrequests.push(request);\n        });\n\n        return newState;\n    };\n\n    /**\n     * Remove a contact request from the members of that request.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} requests The contact requests\n     * @return {Object} New state\n     */\n    var removeContactRequests = function(state, requests) {\n        var newState = cloneState(state);\n        requests.forEach(function(request) {\n            var fromUserId = request.userid;\n            var toUserId = request.requesteduserid;\n\n            newState.members[fromUserId].contactrequests = newState.members[fromUserId].contactrequests.filter(function(existing) {\n                return existing.userid != fromUserId;\n            });\n            newState.members[toUserId].contactrequests = newState.members[toUserId].contactrequests.filter(function(existing) {\n                return existing.requesteduserid != toUserId;\n            });\n        });\n\n        return newState;\n    };\n\n    /**\n     * Set wheter the message of the conversation can delete for all users.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value If it can delete for all users.\n     * @return {Object} New state.\n     */\n    var setCanDeleteMessagesForAllUsers = function(state, value) {\n        var newState = cloneState(state);\n        newState.canDeleteMessagesForAllUsers = value;\n        return newState;\n    };\n\n    /**\n     * Set wheter the messages of the conversation delete for all users.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value Delete messages for all users.\n     * @return {Object} New state.\n     */\n    var setDeleteMessagesForAllUsers = function(state, value) {\n        var newState = cloneState(state);\n        newState.deleteMessagesForAllUsers = value;\n        return newState;\n    };\n\n    return {\n        buildInitialState: buildInitialState,\n        addMessages: addMessages,\n        updateMessages: updateMessages,\n        removeMessages: removeMessages,\n        removeMessagesById: removeMessagesById,\n        addMembers: addMembers,\n        removeMembers: removeMembers,\n        setLoadingMessages: setLoadingMessages,\n        setLoadingMembers: setLoadingMembers,\n        setId: setId,\n        setName: setName,\n        setSubname: setSubname,\n        setType: setType,\n        setIsFavourite: setIsFavourite,\n        setIsMuted: setIsMuted,\n        setCanDeleteMessagesForAllUsers: setCanDeleteMessagesForAllUsers,\n        setDeleteMessagesForAllUsers: setDeleteMessagesForAllUsers,\n        setTotalMemberCount: setTotalMemberCount,\n        setImageUrl: setImageUrl,\n        setLoadingConfirmAction: setLoadingConfirmAction,\n        setPendingDeleteConversation: setPendingDeleteConversation,\n        setMessagesSendPendingById: setMessagesSendPendingById,\n        setMessagesSendSuccessById: setMessagesSendSuccessById,\n        setMessagesSendFailById: setMessagesSendFailById,\n        addPendingBlockUsersById: addPendingBlockUsersById,\n        addPendingRemoveContactsById: addPendingRemoveContactsById,\n        addPendingUnblockUsersById: addPendingUnblockUsersById,\n        addPendingAddContactsById: addPendingAddContactsById,\n        addPendingDeleteMessagesById: addPendingDeleteMessagesById,\n        removePendingBlockUsersById: removePendingBlockUsersById,\n        removePendingRemoveContactsById: removePendingRemoveContactsById,\n        removePendingUnblockUsersById: removePendingUnblockUsersById,\n        removePendingAddContactsById: removePendingAddContactsById,\n        removePendingDeleteMessagesById: removePendingDeleteMessagesById,\n        addSelectedMessagesById: addSelectedMessagesById,\n        removeSelectedMessagesById: removeSelectedMessagesById,\n        markMessagesAsRead: markMessagesAsRead,\n        addContactRequests: addContactRequests,\n        removeContactRequests: removeContactRequests\n    };\n});\n"],"file":"message_drawer_view_conversation_state_manager.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../src/message_drawer_view_conversation_state_manager.js"],"names":["define","$","cloneState","state","extend","formatMessages","messages","loggedInUserId","members","map","message","fromLoggedInUser","useridfrom","id","userFrom","text","timeCreated","timecreated","parseInt","formatMembers","member","fullname","profileurl","profileimageurl","profileimageurlsmall","isonline","showonlinestatus","isblocked","iscontact","isdeleted","canmessage","canmessageevenifblocked","requirescontact","contactrequests","buildInitialState","midnight","messagePollMin","messagePollMax","messagePollAfterMax","name","subname","type","totalMemberCount","imageUrl","isFavourite","isMuted","canDeleteMessagesForAllUsers","deleteMessagesForAllUsers","hasTriedToLoadMessages","loadingMessages","loadingMembers","loadingConfirmAction","pendingBlockUserIds","pendingUnblockUserIds","pendingRemoveContactIds","pendingAddContactIds","pendingDeleteMessageIds","pendingSendMessageIds","pendingDeleteConversation","selectedMessageIds","addMessages","newState","formattedMessages","sendState","timeAdded","Date","now","errorMessage","allMessages","concat","sort","a","b","filter","index","sortedMessages","updateMessages","data","updatesById","reduce","carry","messageData","oldMessage","newMessage","formattedMessage","removeMessages","removeMessageIds","indexOf","removeMessagesById","messageIds","addMembers","formattedMembers","forEach","removeMembers","setLoadingMessages","value","setLoadingMembers","setId","setName","setSubname","setType","setIsFavourite","setIsMuted","setCanDeleteMessagesForAllUsers","setDeleteMessagesForAllUsers","setTotalMemberCount","count","setImageUrl","url","setLoadingConfirmAction","setPendingDeleteConversation","setMessagesSendPendingById","setMessagesSendSuccessById","setMessagesSendFailById","addPendingBlockUsersById","userIds","push","addPendingRemoveContactsById","addPendingUnblockUsersById","addPendingAddContactsById","addPendingDeleteMessagesById","removePendingBlockUsersById","removePendingRemoveContactsById","removePendingUnblockUsersById","removePendingAddContactsById","removePendingDeleteMessagesById","addSelectedMessagesById","removeSelectedMessagesById","markMessagesAsRead","readMessages","readMessageIds","isRead","addContactRequests","requests","request","fromUserId","userid","toUserId","requesteduserid","removeContactRequests","existing"],"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 * This module operates on the view states from the message_drawer_view_conversation module.\n * It exposes functions that can be used to generate new version of the state.\n *\n * Important notes for this module:\n * 1.) The existing state is always immutable. It should never be modified.\n * 2.) All functions that operate on the state should always clone the state and\n *     modify the cloned state before returning it.\n *\n * It's important that the states remain immutable because they are diff'd in\n * the message_drawer_view_conversation_patcher module in order to work out what\n * has changed.\n *\n * @module     core_message/message_drawer_view_conversation_state_manager\n * @copyright  2018 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery'], function($) {\n\n    /**\n     * Clone a state, a state is a collection of information about the variables required to build\n     * the conversation user interface.\n     *\n     * @param  {Object} state State to clone\n     * @return {Object} newstate A copy of the state to clone.\n     */\n    var cloneState = function(state) {\n        // Do a deep extend to make sure we recursively copy objects and\n        // arrays so that the new state doesn't contain any references to\n        // the old state, e.g. adding a value to an array in the new state\n        // shouldn't also add it to the old state.\n        return $.extend(true, {}, state);\n    };\n\n    /**\n     * Format messages to be used in a state.\n     *\n     * @param  {Array} messages The messages to format.\n     * @param  {Number} loggedInUserId The logged in user id.\n     * @param  {Array} members The converstation members.\n     * @return {Array} Formatted messages.\n     */\n    var formatMessages = function(messages, loggedInUserId, members) {\n        return messages.map(function(message) {\n            var fromLoggedInUser = message.useridfrom == loggedInUserId;\n            return {\n                // Stringify the id.\n                id: \"\" + message.id,\n                fromLoggedInUser: fromLoggedInUser,\n                userFrom: members[message.useridfrom],\n                text: message.text,\n                timeCreated: message.timecreated ? parseInt(message.timecreated, 10) : null\n            };\n        });\n    };\n\n    /**\n     * Format members to be used in a state.\n     *\n     * @param  {Array} members The messages to format.\n     * @return {Array} Formatted members.\n     */\n    var formatMembers = function(members) {\n        return members.map(function(member) {\n            return {\n                id: member.id,\n                fullname: member.fullname,\n                profileurl: member.profileurl,\n                profileimageurl: member.profileimageurl,\n                profileimageurlsmall: member.profileimageurlsmall,\n                isonline:  member.isonline,\n                showonlinestatus: member.showonlinestatus,\n                isblocked: member.isblocked,\n                iscontact: member.iscontact,\n                isdeleted: member.isdeleted,\n                canmessage: member.canmessage,\n                canmessageevenifblocked: member.canmessageevenifblocked,\n                requirescontact: member.requirescontact,\n                contactrequests: member.contactrequests || []\n            };\n        });\n    };\n\n    /**\n     * Create an initial (blank) state.\n     *\n     * @param  {Number} midnight Midnight time.\n     * @param  {Number} loggedInUserId The logged in user id.\n     * @param  {Number} id The conversation id.\n     * @param  {Number} messagePollMin The message poll start timeout in seconds.\n     * @param  {Number} messagePollMax The message poll max timeout limit in seconds.\n     * @param  {Number} messagePollAfterMax The message poll frequency in seconds to reset to after max limit is reached.\n     * @return {Object} Initial state.\n     */\n    var buildInitialState = function(\n        midnight,\n        loggedInUserId,\n        id,\n        messagePollMin,\n        messagePollMax,\n        messagePollAfterMax\n    ) {\n        return {\n            midnight: midnight,\n            loggedInUserId: loggedInUserId,\n            id: id,\n            messagePollMin: messagePollMin,\n            messagePollMax: messagePollMax,\n            messagePollAfterMax: messagePollAfterMax,\n            name: null,\n            subname: null,\n            type: null,\n            totalMemberCount: null,\n            imageUrl: null,\n            isFavourite: null,\n            isMuted: null,\n            canDeleteMessagesForAllUsers: false,\n            deleteMessagesForAllUsers: false,\n            members: {},\n            messages: [],\n            hasTriedToLoadMessages: false,\n            loadingMessages: true,\n            loadingMembers: true,\n            loadingConfirmAction: false,\n            pendingBlockUserIds: [],\n            pendingUnblockUserIds: [],\n            pendingRemoveContactIds: [],\n            pendingAddContactIds: [],\n            pendingDeleteMessageIds: [],\n            pendingSendMessageIds: [],\n            pendingDeleteConversation: false,\n            selectedMessageIds: []\n        };\n    };\n\n    /**\n     * Add messages to a state and sort them by timecreated.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messages Messages to add to state.\n     * @return {Object} state New state with added messages.\n     */\n    var addMessages = function(state, messages) {\n        var newState = cloneState(state);\n        var formattedMessages = formatMessages(messages, state.loggedInUserId, state.members);\n        formattedMessages = formattedMessages.map(function(message) {\n            message.sendState = null;\n            message.timeAdded = Date.now();\n            message.errorMessage = null;\n            return message;\n        });\n        var allMessages = state.messages.concat(formattedMessages);\n        // Sort the messages. Oldest to newest.\n        allMessages.sort(function(a, b) {\n            if (a.timeCreated === null && b.timeCreated === null) {\n                if (a.timeAdded < b.timeAdded) {\n                    return -1;\n                } else if (a.timeAdded > b.timeAdded) {\n                    return 1;\n                }\n            }\n\n            if (a.timeCreated === null && b.timeCreated !== null) {\n                // A comes after b.\n                return 1;\n            } else if (a.timeCreated !== null && b.timeCreated === null) {\n                // A comes before b.\n                return -1;\n            } else if (a.timeCreated < b.timeCreated) {\n                // A comes before b.\n                return -1;\n            } else if (a.timeCreated > b.timeCreated) {\n                // A comes after b.\n                return 1;\n            } else if (a.id < b.id) {\n                return -1;\n            } else if (a.id > b.id) {\n                return 1;\n            } else {\n                return 0;\n            }\n        });\n\n        // Filter out any duplicate messages.\n        newState.messages = allMessages.filter(function(message, index, sortedMessages) {\n            return !index || message.id != sortedMessages[index - 1].id;\n        });\n\n        return newState;\n    };\n\n    /**\n     * Update existing messages.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} data 2D array of old and new messages\n     * @return {Object} state.\n     */\n    var updateMessages = function(state, data) {\n        var newState = cloneState(state);\n        var updatesById = data.reduce(function(carry, messageData) {\n            var oldMessage = messageData[0];\n            var newMessage = messageData[1];\n            var formattedMessages = formatMessages([newMessage], state.loggedInUserId, state.members);\n            var formattedMessage = formattedMessages[0];\n\n            carry[oldMessage.id] = formattedMessage;\n            return carry;\n        }, {});\n\n        newState.messages = newState.messages.map(function(message) {\n            if (message.id in updatesById) {\n                return $.extend(message, updatesById[message.id]);\n            } else {\n                return message;\n            }\n        });\n\n        return newState;\n    };\n\n    /**\n     * Remove messages from state.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messages Messages to remove from state.\n     * @return {Object} state New state with removed messages.\n     */\n    var removeMessages = function(state, messages) {\n        var newState = cloneState(state);\n        var removeMessageIds = messages.map(function(message) {\n            return \"\" + message.id;\n        });\n        newState.messages = newState.messages.filter(function(message) {\n            return removeMessageIds.indexOf(message.id) < 0;\n        });\n\n        return newState;\n    };\n\n    /**\n     * Remove messages from state by message id.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Message ids to remove from state.\n     * @return {Object} state New state with removed messages.\n     */\n    var removeMessagesById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.messages = newState.messages.filter(function(message) {\n            return messageIds.indexOf(message.id) < 0;\n        });\n\n        return newState;\n    };\n\n    /**\n     * Add conversation member to state.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} members Conversation members to be added to state.\n     * @return {Object} New state with added members.\n     */\n    var addMembers = function(state, members) {\n        var newState = cloneState(state);\n        var formattedMembers = formatMembers(members);\n        formattedMembers.forEach(function(member) {\n            newState.members[member.id] = member;\n        });\n        return newState;\n    };\n\n    /**\n     * Remove members from state.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} members Members to be removed from state.\n     * @return {Object} New state with removed members.\n     */\n    var removeMembers = function(state, members) {\n        var newState = cloneState(state);\n        members.forEach(function(member) {\n            delete newState.members[member.id];\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state loading messages attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value New loading messages value.\n     * @return {Object} New state with loading messages attribute.\n     */\n    var setLoadingMessages = function(state, value) {\n        var newState = cloneState(state);\n        newState.loadingMessages = value;\n        if (state.loadingMessages && !value) {\n            // If we're going from loading to not loading then\n            // it means we've tried to load.\n            newState.hasTriedToLoadMessages = true;\n        }\n        return newState;\n    };\n\n    /**\n     * Set the state loading members attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value New loading members value.\n     * @return {Object} New state with loading members attribute.\n     */\n    var setLoadingMembers = function(state, value) {\n        var newState = cloneState(state);\n        newState.loadingMembers = value;\n        return newState;\n    };\n\n    /**\n     * Set the conversation id.\n     *\n     * @param  {Object} state Current state.\n     * @param  {String} value The ID.\n     * @return {Object} New state.\n     */\n    var setId = function(state, value) {\n        var newState = cloneState(state);\n        newState.id = value;\n        return newState;\n    };\n\n    /**\n     * Set the state name attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {String} value New name value.\n     * @return {Object} New state with name attribute.\n     */\n    var setName = function(state, value) {\n        var newState = cloneState(state);\n        newState.name = value;\n        return newState;\n    };\n\n    /**\n     * Set the state subname attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {String} value New subname value.\n     * @return {Object} New state.\n     */\n    var setSubname = function(state, value) {\n        var newState = cloneState(state);\n        newState.subname = value;\n        return newState;\n    };\n\n    /**\n     * Set the conversation type.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Int} type Conversation type.\n     * @return {Object} New state.\n     */\n    var setType = function(state, type) {\n        var newState = cloneState(state);\n        newState.type = type;\n        return newState;\n    };\n\n    /**\n     * Set whether the conversation is a favourite conversation.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} isFavourite If it's a favourite.\n     * @return {Object} New state.\n     */\n    var setIsFavourite = function(state, isFavourite) {\n        var newState = cloneState(state);\n        newState.isFavourite = isFavourite;\n        return newState;\n    };\n\n    /**\n     * Set whether the conversation is a muted conversation.\n     *\n     * @param  {Object} state Current state.\n     * @param  {bool} isMuted If it's muted.\n     * @return {Object} New state.\n     */\n    var setIsMuted = function(state, isMuted) {\n        var newState = cloneState(state);\n        newState.isMuted = isMuted;\n        return newState;\n    };\n\n    /**\n     * Set the total member count.\n     *\n     * @param  {Object} state Current state.\n     * @param  {String} count The count.\n     * @return {Object} New state.\n     */\n    var setTotalMemberCount = function(state, count) {\n        var newState = cloneState(state);\n        newState.totalMemberCount = count;\n        return newState;\n    };\n\n    /**\n     * Set the conversation image url.\n     *\n     * @param  {Object} state Current state.\n     * @param  {String} url The url to the image.\n     * @return {Object} New state.\n     */\n    var setImageUrl = function(state, url) {\n        var newState = cloneState(state);\n        newState.imageUrl = url;\n        return newState;\n    };\n\n    /**\n     * Set the state loading confirm action attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value New loading confirm action value.\n     * @return {Object} New state with loading confirm action attribute.\n     */\n    var setLoadingConfirmAction = function(state, value) {\n        var newState = cloneState(state);\n        newState.loadingConfirmAction = value;\n        return newState;\n    };\n\n    /**\n     * Set the state pending delete conversation attribute.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value New pending delete conversation value.\n     * @return {Object} New state with pending delete conversation attribute.\n     */\n    var setPendingDeleteConversation = function(state, value) {\n        var newState = cloneState(state);\n        newState.pendingDeleteConversation = value;\n        return newState;\n    };\n\n    /**\n     * Set the state of message to pending.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages to delete.\n     * @return {Object} New state with array of pending delete message ids.\n     */\n    var setMessagesSendPendingById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.messages.forEach(function(message) {\n            if (messageIds.indexOf(message.id) >= 0) {\n                message.sendState = 'pending';\n                message.errorMessage = null;\n            }\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state of message to sent.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages to delete.\n     * @return {Object} New state with array of pending delete message ids.\n     */\n    var setMessagesSendSuccessById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.messages.forEach(function(message) {\n            if (messageIds.indexOf(message.id) >= 0) {\n                message.sendState = 'sent';\n                message.errorMessage = null;\n            }\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state of messages to error.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages to delete.\n     * @return {Object} New state with array of pending delete message ids.\n     */\n    var setMessagesSendFailById = function(state, messageIds, errorMessage) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.messages.forEach(function(message) {\n            if (messageIds.indexOf(message.id) >= 0) {\n                message.sendState = 'error';\n                message.errorMessage = errorMessage;\n            }\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state pending block userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to block.\n     * @return {Object} New state with array of pending block userids.\n     */\n    var addPendingBlockUsersById = function(state, userIds) {\n        var newState = cloneState(state);\n        userIds.forEach(function(id) {\n            newState.pendingBlockUserIds.push(id);\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state pending remove userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to remove.\n     * @return {Object} New state with array of pending remove userids.\n     */\n    var addPendingRemoveContactsById = function(state, userIds) {\n        var newState = cloneState(state);\n        userIds.forEach(function(id) {\n            newState.pendingRemoveContactIds.push(id);\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state pending unblock userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to unblock.\n     * @return {Object} New state with array of pending unblock userids.\n     */\n    var addPendingUnblockUsersById = function(state, userIds) {\n        var newState = cloneState(state);\n        userIds.forEach(function(id) {\n            newState.pendingUnblockUserIds.push(id);\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state pending add users to contacts userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to add users to contacts.\n     * @return {Object} New state with array of pending add users to contacts userids.\n     */\n    var addPendingAddContactsById = function(state, userIds) {\n        var newState = cloneState(state);\n        userIds.forEach(function(id) {\n            newState.pendingAddContactIds.push(id);\n        });\n        return newState;\n    };\n\n    /**\n     * Set the state pending delete messages.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages to delete.\n     * @return {Object} New state with array of pending delete message ids.\n     */\n    var addPendingDeleteMessagesById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds.forEach(function(id) {\n            newState.pendingDeleteMessageIds.push(id);\n        });\n        return newState;\n    };\n\n    /**\n     * Update the state pending block userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to remove from the list of user ids to block.\n     * @return {Object} New state with array of pending block userids.\n     */\n    var removePendingBlockUsersById = function(state, userIds) {\n        var newState = cloneState(state);\n        newState.pendingBlockUserIds = newState.pendingBlockUserIds.filter(function(id) {\n            return userIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Update the state pending remove userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to remove from the list of user ids to remove.\n     * @return {Object} New state with array of pending remove userids.\n     */\n    var removePendingRemoveContactsById = function(state, userIds) {\n        var newState = cloneState(state);\n        newState.pendingRemoveContactIds = newState.pendingRemoveContactIds.filter(function(id) {\n            return userIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Update the state pending unblock userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to remove from the list of user ids to unblock.\n     * @return {Object} New state with array of pending unblock userids.\n     */\n    var removePendingUnblockUsersById = function(state, userIds) {\n        var newState = cloneState(state);\n        newState.pendingUnblockUserIds = newState.pendingUnblockUserIds.filter(function(id) {\n            return userIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Update the state pending add to contacts userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} userIds User ids to remove from the list of user ids to add to contacts.\n     * @return {Object} New state with array of pending add to contacts userids.\n     */\n    var removePendingAddContactsById = function(state, userIds) {\n        var newState = cloneState(state);\n        newState.pendingAddContactIds = newState.pendingAddContactIds.filter(function(id) {\n            return userIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Update the state pending delete messages userids.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Message ids to remove from the list of messages to delete.\n     * @return {Object} New state with array of messages to delete.\n     */\n    var removePendingDeleteMessagesById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.pendingDeleteMessageIds = newState.pendingDeleteMessageIds.filter(function(id) {\n            return messageIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Add messages to state selected messages.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages that are selected.\n     * @return {Object} New state with array of not blocked members.\n     */\n    var addSelectedMessagesById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.selectedMessageIds = newState.selectedMessageIds.concat(messageIds);\n        return newState;\n    };\n\n    /**\n     * Remove messages from the state selected messages.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} messageIds Messages to remove from selected messages.\n     * @return {Object} New state with array of selected messages.\n     */\n    var removeSelectedMessagesById = function(state, messageIds) {\n        var newState = cloneState(state);\n        messageIds = messageIds.map(function(id) {\n            return \"\" + id;\n        });\n        newState.selectedMessageIds = newState.selectedMessageIds.filter(function(id) {\n            return messageIds.indexOf(id) < 0;\n        });\n        return newState;\n    };\n\n    /**\n     * Mark messages as read.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} readMessages Messages that are read.\n     * @return {Object} New state with array of messages that have the isread attribute set.\n     */\n    var markMessagesAsRead = function(state, readMessages) {\n        var newState = cloneState(state);\n        var readMessageIds = readMessages.map(function(message) {\n            return message.id;\n        });\n        newState.messages = newState.messages.map(function(message) {\n            if (readMessageIds.indexOf(message.id) >= 0) {\n                message.isRead = true;\n            }\n\n            return message;\n        });\n        return newState;\n    };\n\n    /**\n     * Add a contact request to each of the members that the request is for.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} requests The contact requests\n     * @return {Object} New state\n     */\n    var addContactRequests = function(state, requests) {\n        var newState = cloneState(state);\n\n        requests.forEach(function(request) {\n            var fromUserId = request.userid;\n            var toUserId = request.requesteduserid;\n            newState.members[fromUserId].contactrequests.push(request);\n            newState.members[toUserId].contactrequests.push(request);\n        });\n\n        return newState;\n    };\n\n    /**\n     * Remove a contact request from the members of that request.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Array} requests The contact requests\n     * @return {Object} New state\n     */\n    var removeContactRequests = function(state, requests) {\n        var newState = cloneState(state);\n        requests.forEach(function(request) {\n            var fromUserId = request.userid;\n            var toUserId = request.requesteduserid;\n\n            newState.members[fromUserId].contactrequests = newState.members[fromUserId].contactrequests.filter(function(existing) {\n                return existing.userid != fromUserId;\n            });\n            newState.members[toUserId].contactrequests = newState.members[toUserId].contactrequests.filter(function(existing) {\n                return existing.requesteduserid != toUserId;\n            });\n        });\n\n        return newState;\n    };\n\n    /**\n     * Set wheter the message of the conversation can delete for all users.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value If it can delete for all users.\n     * @return {Object} New state.\n     */\n    var setCanDeleteMessagesForAllUsers = function(state, value) {\n        var newState = cloneState(state);\n        newState.canDeleteMessagesForAllUsers = value;\n        return newState;\n    };\n\n    /**\n     * Set wheter the messages of the conversation delete for all users.\n     *\n     * @param  {Object} state Current state.\n     * @param  {Bool} value Delete messages for all users.\n     * @return {Object} New state.\n     */\n    var setDeleteMessagesForAllUsers = function(state, value) {\n        var newState = cloneState(state);\n        newState.deleteMessagesForAllUsers = value;\n        return newState;\n    };\n\n    return {\n        buildInitialState: buildInitialState,\n        addMessages: addMessages,\n        updateMessages: updateMessages,\n        removeMessages: removeMessages,\n        removeMessagesById: removeMessagesById,\n        addMembers: addMembers,\n        removeMembers: removeMembers,\n        setLoadingMessages: setLoadingMessages,\n        setLoadingMembers: setLoadingMembers,\n        setId: setId,\n        setName: setName,\n        setSubname: setSubname,\n        setType: setType,\n        setIsFavourite: setIsFavourite,\n        setIsMuted: setIsMuted,\n        setCanDeleteMessagesForAllUsers: setCanDeleteMessagesForAllUsers,\n        setDeleteMessagesForAllUsers: setDeleteMessagesForAllUsers,\n        setTotalMemberCount: setTotalMemberCount,\n        setImageUrl: setImageUrl,\n        setLoadingConfirmAction: setLoadingConfirmAction,\n        setPendingDeleteConversation: setPendingDeleteConversation,\n        setMessagesSendPendingById: setMessagesSendPendingById,\n        setMessagesSendSuccessById: setMessagesSendSuccessById,\n        setMessagesSendFailById: setMessagesSendFailById,\n        addPendingBlockUsersById: addPendingBlockUsersById,\n        addPendingRemoveContactsById: addPendingRemoveContactsById,\n        addPendingUnblockUsersById: addPendingUnblockUsersById,\n        addPendingAddContactsById: addPendingAddContactsById,\n        addPendingDeleteMessagesById: addPendingDeleteMessagesById,\n        removePendingBlockUsersById: removePendingBlockUsersById,\n        removePendingRemoveContactsById: removePendingRemoveContactsById,\n        removePendingUnblockUsersById: removePendingUnblockUsersById,\n        removePendingAddContactsById: removePendingAddContactsById,\n        removePendingDeleteMessagesById: removePendingDeleteMessagesById,\n        addSelectedMessagesById: addSelectedMessagesById,\n        removeSelectedMessagesById: removeSelectedMessagesById,\n        markMessagesAsRead: markMessagesAsRead,\n        addContactRequests: addContactRequests,\n        removeContactRequests: removeContactRequests\n    };\n});\n"],"file":"message_drawer_view_conversation_state_manager.min.js"}
\ No newline at end of file
diff --git a/message/amd/src/message_drawer_view_conversation.js b/message/amd/src/message_drawer_view_conversation.js
index f70634364b3..a3cd6b7000f 100644
--- a/message/amd/src/message_drawer_view_conversation.js
+++ b/message/amd/src/message_drawer_view_conversation.js
@@ -182,7 +182,8 @@ function(
             isblocked: null,
             iscontact: null,
             isdeleted: null,
-            canmessage:  null,
+            canmessage: null,
+            canmessageevenifblocked: null,
             requirescontact: null,
             contactrequests: []
         };
diff --git a/message/amd/src/message_drawer_view_conversation_renderer.js b/message/amd/src/message_drawer_view_conversation_renderer.js
index b4b3226b9fe..4639d0f0bbb 100644
--- a/message/amd/src/message_drawer_view_conversation_renderer.js
+++ b/message/amd/src/message_drawer_view_conversation_renderer.js
@@ -1069,10 +1069,17 @@ function(
      */
     var renderConfirmBlockUser = function(header, body, footer, user) {
         if (user) {
-            return Str.get_string('blockuserconfirm', 'core_message', user.fullname)
-                .then(function(string) {
-                    return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_BLOCK], string, '', true, false);
-                });
+            if (user.canmessageevenifblocked) {
+                return Str.get_string('cantblockuser', 'core_message', user.fullname)
+                    .then(function(string) {
+                        return showConfirmDialogue(header, body, footer, [], string, '', true, false);
+                    });
+            } else {
+                return Str.get_string('blockuserconfirm', 'core_message', user.fullname)
+                    .then(function(string) {
+                        return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_BLOCK], string, '', true, false);
+                    });
+            }
         } else {
             return hideConfirmDialogue(header, body, footer);
         }
diff --git a/message/amd/src/message_drawer_view_conversation_state_manager.js b/message/amd/src/message_drawer_view_conversation_state_manager.js
index 61c7a28610f..f6b61e8568c 100644
--- a/message/amd/src/message_drawer_view_conversation_state_manager.js
+++ b/message/amd/src/message_drawer_view_conversation_state_manager.js
@@ -88,7 +88,8 @@ define(['jquery'], function($) {
                 isblocked: member.isblocked,
                 iscontact: member.iscontact,
                 isdeleted: member.isdeleted,
-                canmessage:  member.canmessage,
+                canmessage: member.canmessage,
+                canmessageevenifblocked: member.canmessageevenifblocked,
                 requirescontact: member.requirescontact,
                 contactrequests: member.contactrequests || []
             };
diff --git a/message/classes/api.php b/message/classes/api.php
index 49824d7fb1c..851e38d4b12 100644
--- a/message/classes/api.php
+++ b/message/classes/api.php
@@ -1869,9 +1869,11 @@ class api {
      *
      * @param int $recipientid The recipient user id.
      * @param int $senderid The sender user id.
+     * @param bool $evenifblocked This lets the user know, that even if the recipient has blocked the user
+     *        the user is still able to send a message.
      * @return bool true if user is permitted, false otherwise.
      */
-    public static function can_send_message(int $recipientid, int $senderid) : bool {
+    public static function can_send_message(int $recipientid, int $senderid, bool $evenifblocked = false) : bool {
         $systemcontext = \context_system::instance();
 
         if (!has_capability('moodle/site:sendmessage', $systemcontext, $senderid)) {
@@ -1883,7 +1885,7 @@ class api {
         }
 
         // Check if the recipient can be messaged by the sender.
-        return self::can_contact_user($recipientid, $senderid);
+        return self::can_contact_user($recipientid, $senderid, $evenifblocked);
     }
 
     /**
@@ -2966,9 +2968,11 @@ class api {
      *
      * @param int $recipientid
      * @param int $senderid
+     * @param bool $evenifblocked This lets the user know, that even if the recipient has blocked the user
+     *        the user is still able to send a message.
      * @return bool true if recipient hasn't blocked sender and sender can contact to recipient, false otherwise.
      */
-    protected static function can_contact_user(int $recipientid, int $senderid) : bool {
+    protected static function can_contact_user(int $recipientid, int $senderid, bool $evenifblocked = false) : bool {
         if (has_capability('moodle/site:messageanyuser', \context_system::instance(), $senderid) ||
             $recipientid == $senderid) {
             // The sender has the ability to contact any user across the entire site or themselves.
@@ -2978,7 +2982,7 @@ class api {
         // The initial value of $cancontact is null to indicate that a value has not been determined.
         $cancontact = null;
 
-        if (self::is_blocked($recipientid, $senderid)) {
+        if (self::is_blocked($recipientid, $senderid) || $evenifblocked) {
             // The recipient has specifically blocked this sender.
             $cancontact = false;
         }
diff --git a/message/classes/helper.php b/message/classes/helper.php
index e1440ee6738..99daf9045ae 100644
--- a/message/classes/helper.php
+++ b/message/classes/helper.php
@@ -589,9 +589,14 @@ class helper {
 
             $data->requirescontact = null;
             $data->canmessage = null;
+            $data->canmessageevenifblocked = null;
             if ($includeprivacyinfo) {
                 $privacysetting = api::get_user_privacy_messaging_preference($member->id);
                 $data->requirescontact = $privacysetting == api::MESSAGE_PRIVACY_ONLYCONTACTS;
+
+                // Here we check that if the sender wanted to block the recipient, the recipient would
+                // still be able to message them regardless.
+                $data->canmessageevenifblocked = api::can_send_message($referenceuserid, $member->id, true);
                 $data->canmessage = !$data->isdeleted && api::can_send_message($member->id, $referenceuserid);
             }
 
diff --git a/message/externallib.php b/message/externallib.php
index 6933c20208d..3fbff4d2a2c 100644
--- a/message/externallib.php
+++ b/message/externallib.php
@@ -583,6 +583,11 @@ class core_message_external extends external_api {
             throw new required_capability_exception($context, $capability, 'nopermissions', '');
         }
 
+        // If the blocking is going to be useless then don't do it.
+        if (\core_message\api::can_send_message($userid, $blockeduserid, true)) {
+            return [];
+        }
+
         if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
             \core_message\api::block_user($params['userid'], $params['blockeduserid']);
         }
@@ -1290,6 +1295,8 @@ class core_message_external extends external_api {
             'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
             'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?'),
             'isdeleted' => new external_value(PARAM_BOOL, 'Is the user deleted?'),
+            'canmessageevenifblocked' => new external_value(PARAM_BOOL,
+                'If the user can still message even if they get blocked'),
             'canmessage' => new external_value(PARAM_BOOL, 'If the user can be messaged'),
             'requirescontact' => new external_value(PARAM_BOOL, 'If the user requires to be contacts'),
         ];
diff --git a/message/tests/api_test.php b/message/tests/api_test.php
index ad5d59e93cb..3fe5c337688 100644
--- a/message/tests/api_test.php
+++ b/message/tests/api_test.php
@@ -3613,6 +3613,98 @@ class core_message_api_testcase extends core_message_messagelib_testcase {
         $this->assertTrue(\core_message\api::can_send_message($student2->id, $teacher1->id));
     }
 
+    /**
+     * Tests the user when blocked will not be able to send messages if they are blocked.
+     */
+    public function test_can_send_message_even_if_blocked() {
+        $this->resetAfterTest();
+
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id, true));
+    }
+
+    /**
+     * Tests the user will be able to send a message even if they are blocked as the user
+     * has the capability 'moodle/site:messageanyuser'.
+     */
+    public function test_can_send_message_even_if_blocked_with_message_any_user_cap() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        $authenticateduserrole = $DB->get_record('role', array('shortname' => 'user'));
+        assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduserrole->id, context_system::instance(), true);
+
+        $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id, true));
+    }
+
+    /**
+     * Tests the user will be able to send a message even if they are blocked as the user
+     * has the capability 'moodle/site:readallmessages'.
+     */
+    public function test_can_send_message_even_if_blocked_with_read_all_message_cap() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        $authenticateduserrole = $DB->get_record('role', array('shortname' => 'user'));
+        assign_capability('moodle/site:readallmessages', CAP_ALLOW, $authenticateduserrole->id, context_system::instance(), true);
+
+        $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id, true));
+    }
+
+    /**
+     * Tests the user can not always send a message if they are blocked just because they share a course.
+     */
+    public function test_can_send_message_even_if_blocked_shared_course() {
+        $this->resetAfterTest();
+
+        // Create some users.
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        $course = self::getDataGenerator()->create_course();
+
+        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
+        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
+
+        $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id, true));
+    }
+
+    /**
+     * Tests the user can always send a message even if they are blocked because they share a course and
+     * have the capability 'moodle/site:messageanyuser' at the course context.
+     */
+    public function test_can_send_message_even_if_blocked_shared_course_with_message_any_user_cap() {
+        global $DB;
+
+        $this->resetAfterTest();
+
+        $editingteacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
+
+        $teacher = self::getDataGenerator()->create_user();
+        $student = self::getDataGenerator()->create_user();
+
+        $course = self::getDataGenerator()->create_course();
+
+        $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $editingteacherrole->id);
+        $this->getDataGenerator()->enrol_user($student->id, $course->id);
+
+        assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $editingteacherrole->id,
+            context_course::instance($course->id), true);
+
+        // Check that the second user can no longer send the first user a message.
+        $this->assertTrue(\core_message\api::can_send_message($student->id, $teacher->id, true));
+    }
+
     /**
      * Tests the user can post a message.
      */
diff --git a/message/tests/behat/block_user.feature b/message/tests/behat/block_user.feature
new file mode 100644
index 00000000000..02fd075c433
--- /dev/null
+++ b/message/tests/behat/block_user.feature
@@ -0,0 +1,43 @@
+@core @core_message @javascript
+Feature: To be able to block users that we are able to or to see a message if we can not
+  In order to attempt to block a user
+  As a user
+  I need to be able to block a user or to see a message if we can not
+
+  Background:
+    Given the following "courses" exist:
+      | fullname | shortname | category |
+      | Course 1 | C1        | 0        |
+    And the following "users" exist:
+      | username | firstname | lastname | email                |
+      | teacher1 | Teacher   | 1        | teacher1@emample.com |
+      | student1 | Student   | 1        | student1@example.com |
+      | student2 | Student   | 2        | student2@example.com |
+    And the following "course enrolments" exist:
+      | user     | course | role    |
+      | teacher1 | C1     | teacher |
+      | student1 | C1     | student |
+      | student2 | C1     | student |
+    And the following config values are set as admin:
+      | messaging | 1 |
+
+  Scenario: Block a user
+    Given I log in as "student1"
+    And I select "Student 2" user in messaging
+    And I open contact menu
+    And I click on "Block" "link" in the "[data-region='header-container']" "css_element"
+    And I should see "Are you sure you want to block Student 2?"
+    And I click on "Block" "button" in the "[data-region='confirm-dialogue']" "css_element"
+    And I should see "You have blocked this user."
+    And I log out
+    When I log in as "student2"
+    And I open messaging
+    And I select "Student 1" user in messaging
+    Then I should see "You are unable to message this user"
+
+  Scenario: Unable to block a user
+    Given I log in as "student1"
+    And I select "Teacher 1" user in messaging
+    And I open contact menu
+    When I click on "Block" "link" in the "[data-region='header-container']" "css_element"
+    Then I should see "You are unable to block Teacher 1"
diff --git a/message/tests/externallib_test.php b/message/tests/externallib_test.php
index 207eea78be7..224a5878cc3 100644
--- a/message/tests/externallib_test.php
+++ b/message/tests/externallib_test.php
@@ -1216,6 +1216,30 @@ class core_message_externallib_testcase extends externallib_advanced_testcase {
         $this->assertEquals(1, $DB->count_records('message_users_blocked'));
     }
 
+    /**
+     * Test blocking a user.
+     */
+    public function test_block_user_when_ineffective() {
+        global $DB;
+
+        $this->resetAfterTest(true);
+
+        $user1 = self::getDataGenerator()->create_user();
+        $user2 = self::getDataGenerator()->create_user();
+
+        $this->setUser($user1);
+
+        $authenticateduser = $DB->get_record('role', array('shortname' => 'user'));
+        assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduser->id, context_system::instance(), true);
+
+        // Blocking a user.
+        $return = core_message_external::block_user($user1->id, $user2->id);
+        $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
+        $this->assertEquals(array(), $return);
+
+        $this->assertEquals(0, $DB->count_records('message_users_blocked'));
+    }
+
     /**
      * Test blocking a user with messaging disabled.
      */

From 66fffdbce5f85ced3f4e69f217f9ef212a8c8df1 Mon Sep 17 00:00:00 2001
From: Mark Nelson <mdjnelson@gmail.com>
Date: Thu, 11 Jul 2019 15:30:16 +0800
Subject: [PATCH 3/4] MDL-65093 core_message: dont show users with cap as
 blocked

It is possible that before this patch the user blocked a
teacher from messaging them, even though this would have
no effect. It is also possible for a user to block a user,
then that user gets 'promoted' to a teacher role and the
block becoming ineffective. In these cases we dont show the
user's status as blocked.
---
 message/classes/helper.php             | 11 +++++++----
 message/tests/behat/block_user.feature | 24 ++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/message/classes/helper.php b/message/classes/helper.php
index 99daf9045ae..69a705426f9 100644
--- a/message/classes/helper.php
+++ b/message/classes/helper.php
@@ -583,7 +583,10 @@ class helper {
 
             // Set contact and blocked status indicators.
             $data->iscontact = ($member->contactid) ? true : false;
-            $data->isblocked = ($member->blockedid) ? true : false;
+
+            // We don't want that a user has been blocked if they can message the user anyways.
+            $canmessageifblocked = api::can_send_message($referenceuserid, $member->id, true);
+            $data->isblocked = ($member->blockedid && !$canmessageifblocked) ? true : false;
 
             $data->isdeleted = ($member->deleted) ? true : false;
 
@@ -594,9 +597,9 @@ class helper {
                 $privacysetting = api::get_user_privacy_messaging_preference($member->id);
                 $data->requirescontact = $privacysetting == api::MESSAGE_PRIVACY_ONLYCONTACTS;
 
-                // Here we check that if the sender wanted to block the recipient, the recipient would
-                // still be able to message them regardless.
-                $data->canmessageevenifblocked = api::can_send_message($referenceuserid, $member->id, true);
+                // Here we check that if the sender wanted to block the recipient, the
+                // recipient would still be able to message them regardless.
+                $data->canmessageevenifblocked = !$data->isdeleted && $canmessageifblocked;
                 $data->canmessage = !$data->isdeleted && api::can_send_message($member->id, $referenceuserid);
             }
 
diff --git a/message/tests/behat/block_user.feature b/message/tests/behat/block_user.feature
index 02fd075c433..0de9db972fd 100644
--- a/message/tests/behat/block_user.feature
+++ b/message/tests/behat/block_user.feature
@@ -41,3 +41,27 @@ Feature: To be able to block users that we are able to or to see a message if we
     And I open contact menu
     When I click on "Block" "link" in the "[data-region='header-container']" "css_element"
     Then I should see "You are unable to block Teacher 1"
+
+  Scenario: Block a user who then gets an elevated role
+    Given I log in as "student1"
+    And I select "Student 2" user in messaging
+    And I open contact menu
+    And I click on "Block" "link" in the "[data-region='header-container']" "css_element"
+    And I click on "Block" "button" in the "[data-region='confirm-dialogue']" "css_element"
+    And I log out
+    And I log in as "admin"
+    And I am on "Course 1" course homepage
+    And I navigate to course participants
+    And I click on "Unenrol" "icon" in the "student2" "table_row"
+    And I click on "Unenrol" "button" in the "Unenrol" "dialogue"
+    And I enrol "Student 2" user as "Teacher"
+    And I log out
+    And I log in as "student2"
+    And I select "Student 1" user in messaging
+    And I should not see "You are unable to message this user"
+    And I log out
+    And I log in as "student1"
+    And I select "Student 2" user in messaging
+    And I open contact menu
+    When I click on "Block" "link" in the "[data-region='header-container']" "css_element"
+    Then I should see "You are unable to block Student 2"

From 386634bab38c98612daf34cf2bbe80fe7ae7d50c Mon Sep 17 00:00:00 2001
From: Mark Nelson <mdjnelson@gmail.com>
Date: Wed, 17 Jul 2019 14:08:51 +0800
Subject: [PATCH 4/4] MDL-65093 core_message: show 'OK' dialogue

---
 .../build/message_drawer_view_conversation.min.js |  2 +-
 .../message_drawer_view_conversation.min.js.map   |  2 +-
 ...sage_drawer_view_conversation_constants.min.js |  2 +-
 ..._drawer_view_conversation_constants.min.js.map |  2 +-
 ...ssage_drawer_view_conversation_renderer.min.js |  2 +-
 ...e_drawer_view_conversation_renderer.min.js.map |  2 +-
 .../amd/src/message_drawer_view_conversation.js   |  1 +
 .../message_drawer_view_conversation_constants.js |  2 ++
 .../message_drawer_view_conversation_renderer.js  | 15 +++++++++++++--
 ...ew_conversation_body_confirm_dialogue.mustache |  1 +
 10 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/message/amd/build/message_drawer_view_conversation.min.js b/message/amd/build/message_drawer_view_conversation.min.js
index aa9cb9fd17b..c127aeda610 100644
--- a/message/amd/build/message_drawer_view_conversation.min.js
+++ b/message/amd/build/message_drawer_view_conversation.min.js
@@ -1,2 +1,2 @@
-function _typeof(e){if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(e){return typeof e}}else{_typeof=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e}}return _typeof(e)}define ("core_message/message_drawer_view_conversation",["jquery","core/auto_rows","core/backoff_timer","core/custom_interaction_events","core/notification","core/pubsub","core/str","core_message/message_repository","core_message/message_drawer_events","core_message/message_drawer_view_conversation_constants","core_message/message_drawer_view_conversation_patcher","core_message/message_drawer_view_conversation_renderer","core_message/message_drawer_view_conversation_state_manager","core_message/message_drawer_router","core_message/message_drawer_routes"],function(s,e,t,n,d,a,i,r,o,g,l,m,c,E,I){var C={},u=null,_=!1,T=0,f=null,A=!1,h=[],M=!0,O=!1,N=[],v=null,S=[],p=g.NEWEST_MESSAGES_FIRST,b=g.LOAD_MESSAGE_LIMIT,U=g.MILLISECONDS_IN_SEC,L=g.SELECTORS,R=g.CONVERSATION_TYPES,D=function(){if(!u||u.type==R.PUBLIC){return null}var e=u.loggedInUserId;if(u.type==R.SELF){return e}var s=Object.keys(u.members).filter(function(s){return e!=s});return s.length?s[0]:null},y=function(e){return Object.keys(C).reduce(function(s,t){if(!s){var n=C[t].state;if(n.type!=R.PUBLIC){if(e in n.members){s=n.id}}}return s},null)},B=function(e){return{id:parseInt(e.attr("data-user-id"),10),fullname:null,profileimageurl:null,profileimageurlsmall:null,isonline:null,showonlinestatus:null,isblocked:null,iscontact:null,isdeleted:null,canmessage:null,canmessageevenifblocked:null,requirescontact:null,contactrequests:[]}},F=function(){return T},P=function(e){T=e;C[u.id].messagesOffset=e},V=function(){return _},x=function(e){_=e;C[u.id].loadedAllMessages=e},w=function(e){return e.find(L.MESSAGES_CONTAINER)},k=function(e){return{id:e.id,name:e.name,subname:e.subname,imageUrl:e.imageUrl,isFavourite:e.isFavourite,isMuted:e.isMuted,type:e.type,totalMemberCount:e.totalMemberCount,loggedInUserId:e.loggedInUserId,messages:e.messages.map(function(e){return s.extend({},e)}),members:Object.keys(e.members).map(function(t){var n=s.extend({},e.members[t]);n.contactrequests=e.members[t].contactrequests.map(function(e){return s.extend({},e)});return n})}},G=function(e,s){var t=e.id,n=t==s?R.SELF:R.PRIVATE,a=c.setLoadingMembers(u,!0);a=c.setLoadingMessages(a,!0);v(a);return r.getMemberInfo(t,[s],!0,!0).then(function(e){if(e.length){return e[0]}else{throw new Error("Unable to load other user profile")}}).then(function(s){var t=n==R.SELF?[s]:[s,e],d=c.addMembers(u,t);d=c.setLoadingMembers(d,!1);d=c.setLoadingMessages(d,!1);d=c.setName(d,s.fullname);d=c.setType(d,n);d=c.setImageUrl(d,s.profileimageurl);d=c.setTotalMemberCount(d,t.length);v(d);return s}).catch(function(e){var s=c.setLoadingMembers(u,!1);v(s);d.exception(e)})},q=function(e,s){var t=null;if(e.type==R.PRIVATE){var n=e.members.filter(function(e){return e.id!=s});t=n.length?n[0]:null}else if(e.type==R.SELF){t=e.members[0]}var d=e.name,a=e.imageurl;if(e.type!=R.PUBLIC){d=d||t?t.fullname:"";a=a||t?t.profileimageurl:""}var i=c.addMembers(u,e.members);i=c.setName(i,d);i=c.setSubname(i,e.subname);i=c.setType(i,e.type);i=c.setImageUrl(i,a);i=c.setTotalMemberCount(i,e.membercount);i=c.setIsFavourite(i,e.isfavourite);i=c.setIsMuted(i,e.ismuted);i=c.addMessages(i,e.messages);i=c.setCanDeleteMessagesForAllUsers(i,e.candeletemessagesforallusers);return i},Q=function(e,s,t,n,a){var i=s.id,o=c.setLoadingMembers(u,!0);o=c.setLoadingMessages(o,!0);v(o);return r.getConversation(i,e,!0,!0,0,0,t+1,n,a).then(function(e){if(e.messages.length>t){e.messages=e.messages.slice(1)}else{x(!0)}P(n+t);return e}).then(function(e){var t=e.members.filter(function(e){return e.id==s.id});if(1>t.length){e.members=e.members.concat([s])}var n=q(e,s.id);n=c.setLoadingMembers(n,!1);n=c.setLoadingMessages(n,!1);return v(n).then(function(){return e})}).then(function(){return X(e)}).catch(function(e){var s=c.setLoadingMembers(u,!1);s=c.setLoadingMessages(s,!1);v(s);d.exception(e)})},W=function(e,s,t,n){var a=e.members.filter(function(e){return e.id==s.id});if(1>a.length){e.members=e.members.concat([s])}var i=e.messages.length,r=i>=t,o=q(e,s.id);o=c.setLoadingMembers(o,!1);o=c.setLoadingMessages(o,!r);var g=v(o);return g.then(function(){if(!r){return K(e.id,t,i,n,[])}else{return{messages:e.messages}}}).then(function(){var e=u.messages;P(e.length);X(u.id);return e}).catch(d.exception)},K=function(e,s,t,n,d,a){return r.getMessages(u.loggedInUserId,e,s?s+1:s,t,n,a).then(function(e){if(e.messages.length&&d.length){e.messages=e.messages.filter(function(e){return 0>d.indexOf(parseInt(e.id,10))})}return e}).then(function(e){if(!s){return e}else if(e.messages.length>s){e.messages=e.messages.slice(0,-1)}else{x(!0)}return e}).then(function(e){var s=e.members.filter(function(e){return!(e.id in u.members)}),t=c.addMembers(u,s);t=c.addMessages(t,e.messages);t=c.setLoadingMessages(t,!1);return v(t).then(function(){return e})}).catch(function(e){var s=c.setLoadingMessages(u,!1);v(s);throw e})},j=function(e,t){return function(){var n=u.messages,d=n.length?n[n.length-1]:null,r=d?d.timeCreated:null;if(r&&!M&&!O){for(var g=[],l=n.length-1,m;0<=l;l--){m=n[l];if(m.timeCreated===r){g.push(m.id)}else{break}}return K(e,0,0,t,g,r).then(function(s){if(s.messages.length){f.restart();var t=k(u);a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,t);return X(e)}else{return s}})}return s.Deferred().resolve().promise()}},X=function(e){var s=u.loggedInUserId;return r.markAllConversationMessagesAsRead(s,e).then(function(){var s=c.markMessagesAsRead(u,u.messages);a.publish(o.CONVERSATION_READ,e);return v(s)})},Y=function(e){le(e);var s=c.addPendingBlockUsersById(u,[e]);v(s)},H=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.blockUser(u.loggedInUserId,e).then(function(s){var t=c.addMembers(u,[s]);t=c.removePendingBlockUsersById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_BLOCKED,e);return v(t)})},z=function(e){le(e);var s=c.addPendingUnblockUsersById(u,[e]);v(s)},J=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.unblockUser(u.loggedInUserId,e).then(function(s){var t=c.addMembers(u,[s]);t=c.removePendingUnblockUsersById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_UNBLOCKED,e);return v(t)})},Z=function(e){le(e);var s=c.addPendingRemoveContactsById(u,[e]);v(s)},$=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.deleteContacts(u.loggedInUserId,[e]).then(function(s){var t=c.addMembers(u,s);t=c.removePendingRemoveContactsById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_REMOVED,e);return v(t)})},ee=function(e){le(e);var s=c.addPendingAddContactsById(u,[e]);v(s)},se=function(e){var s=c.setLoadingConfirmAction(u,!0);v(s);return r.createContactRequest(u.loggedInUserId,e).then(function(e){if(!e.request){throw new Error(e.warnings[0].message)}return e.request}).then(function(s){var t=c.removePendingAddContactsById(u,[e]);t=c.addContactRequests(t,[s]);t=c.setLoadingConfirmAction(t,!1);return v(t)})},te=function(){var e=u.loggedInUserId,s=u.id;return r.setFavouriteConversations(e,[s]).then(function(){var e=c.setIsFavourite(u,!0);return v(e)}).then(function(){return a.publish(o.CONVERSATION_SET_FAVOURITE,k(u))})},ne=function(){var e=u.loggedInUserId,s=u.id;return r.unsetFavouriteConversations(e,[s]).then(function(){var e=c.setIsFavourite(u,!1);return v(e)}).then(function(){return a.publish(o.CONVERSATION_UNSET_FAVOURITE,k(u))})},de=function(){var e=u.loggedInUserId,s=u.id;return r.setMutedConversations(e,[s]).then(function(){var e=c.setIsMuted(u,!0);return v(e)}).then(function(){return a.publish(o.CONVERSATION_SET_MUTED,k(u))})},ae=function(){var e=u.loggedInUserId,s=u.id;return r.unsetMutedConversations(e,[s]).then(function(){var e=c.setIsMuted(u,!1);return v(e)}).then(function(){return a.publish(o.CONVERSATION_UNSET_MUTED,k(u))})},ie=function(e){var s=u.selectedMessageIds;le(e);var t=c.addPendingDeleteMessagesById(u,s);v(t)},re=function(){var e=u.pendingDeleteMessageIds,t=u.messages.filter(function(s){return 0<=e.indexOf(s.id)&&("sent"==s.sendState||null===s.sendState)}),n=c.setLoadingConfirmAction(u,!0);v(n);var i=s.Deferred().resolve().promise();if(t.length){var g=t.map(function(e){return e.id});if(n.deleteMessagesForAllUsers){i=r.deleteMessagesForAllUsers(u.loggedInUserId,g)}else{i=r.deleteMessages(u.loggedInUserId,g)}}return i.then(function(){var s=c.removeMessagesById(u,e);s=c.removePendingDeleteMessagesById(s,e);s=c.removeSelectedMessagesById(s,e);s=c.setLoadingConfirmAction(s,!1);s=c.setDeleteMessagesForAllUsers(s,!1);var t=u.messages[u.messages.length-1],n=s.messages.length?s.messages[s.messages.length-1]:null;if(n&&n.id!=t.id){var d=k(s);a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,d)}else if(!s.messages.length){a.publish(o.CONVERSATION_DELETED,s.id)}return v(s)}).catch(d.exception)},oe=function(e){le(e);var s=c.setPendingDeleteConversation(u,!0);v(s)},ge=function(){var e=c.setLoadingConfirmAction(u,!0);v(e);return r.deleteConversation(u.loggedInUserId,u.id).then(function(){var e=c.removeMessages(u,u.messages);e=c.removeSelectedMessagesById(e,u.selectedMessageIds);e=c.setPendingDeleteConversation(e,!1);e=c.setLoadingConfirmAction(e,!1);a.publish(o.CONVERSATION_DELETED,e.id);return v(e)})},le=function(e){var s=u.pendingDeleteMessageIds,t=c.removePendingAddContactsById(u,[e]);t=c.removePendingRemoveContactsById(t,[e]);t=c.removePendingUnblockUsersById(t,[e]);t=c.removePendingBlockUsersById(t,[e]);t=c.removePendingDeleteMessagesById(t,s);t=c.setPendingDeleteConversation(t,!1);t=c.setDeleteMessagesForAllUsers(t,!1);v(t)},me=function(e){var s=u.loggedInUserId,t=u.members[e].contactrequests.filter(function(e){return e.requesteduserid==s}),n=t[0],d=c.setLoadingConfirmAction(u,!0);v(d);return r.acceptContactRequest(e,s).then(function(e){var s=c.removeContactRequests(u,[n]);s=c.addMembers(u,[e]);s=c.setLoadingConfirmAction(s,!1);return v(s)}).then(function(){a.publish(o.CONTACT_ADDED,u.members[e]);a.publish(o.CONTACT_REQUEST_ACCEPTED,n)})},ce=function(e){var s=u.loggedInUserId,t=u.members[e].contactrequests.filter(function(e){return e.requesteduserid==s}),n=t[0],d=c.setLoadingConfirmAction(u,!0);v(d);return r.declineContactRequest(e,s).then(function(e){var s=c.removeContactRequests(u,[n]);s=c.addMembers(u,[e]);s=c.setLoadingConfirmAction(s,!1);return v(s)}).then(function(){a.publish(o.CONTACT_REQUEST_DECLINED,n)})},Ee=function(){if(O){return}if(!N.length){return}O=!0;var e=N.slice();N=[];var t=u.id,n=null,d=e.map(function(e){return e.text}),g=e.map(function(e){return e.id}),l=null,m=null;if(!t&&u.type!=R.PUBLIC){var E=D();l=r.sendMessagesToUser(E,d).then(function(e){if(e.length){n=parseInt(e[0].conversationid,10);m=e[0].candeletemessagesforallusers}return e})}else{l=r.sendMessagesToConversation(t,d)}l.then(function(s){var t=s.map(function(e){return e.id}),d=[],i=[],r=[];e.forEach(function(e,t){var n=s[t];d.push([e,n]);if(0<=u.selectedMessageIds.indexOf(e.id)){i.push(e.id);r.push(n.id)}});var g=c.updateMessages(u,d);g=c.setMessagesSendSuccessById(g,t);if(i.length){g=c.removeSelectedMessagesById(g,i)}if(r.length){g=c.addSelectedMessagesById(g,r)}var l=k(g);if(!g.id){g=c.setId(g,n);l.id=n;ye(n);a.publish(o.CONVERSATION_CREATED,l);g=c.setCanDeleteMessagesForAllUsers(g,m)}v(g);O=!1;Ee();a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,l)}).catch(function(t){if(t.message){var e=s.Deferred().resolve(t.message).promise()}else{var e=i.get_string("unknownerror","core")}var n=function(e){var s=c.setMessagesSendFailById(u,g,e);v(s);O=!1;Ee()};e.then(n).catch(function(s){var e=s.message||"Something went wrong!";n(e)})})},Ie=function(e){var s="temp"+Date.now(),t={id:s,useridfrom:u.loggedInUserId,text:e,timecreated:null},n=c.addMessages(u,[t]);v(n);N.push(t);Ee()},Ce=function(e){var s=c.setMessagesSendPendingById(u,[e.id]);v(s);N.push(e);Ee()},ue=function(e){var s=u;if(-1<u.selectedMessageIds.indexOf(e)){s=c.removeSelectedMessagesById(u,[e])}else{s=c.addSelectedMessagesById(u,[e])}v(s)},_e=function(){le(D());var e=c.removeSelectedMessagesById(u,u.selectedMessageIds);v(e)},Te=function(e,t,n){if(A){return}if(!h.length){return}A=!0;var a=h.shift(),i=S.map(function(e){return e(a.patch)});s.when.apply(null,i).then(function(){A=!1;a.deferred.resolve(!0);Te(e,t,n)}).catch(function(e){A=!1;a.deferred.reject(e);d.exception(e)})},fe=function(e,t,n,d){var a=function(s){return m.render(e,t,n,s)};if(!d){var i=c.buildInitialState(u.midnight,u.loggedInUserId,u.id),r=l.buildPatch(i,u);a(r)}S.push(a);return function(d){var a=l.buildPatch(u,d),i=s.Deferred();if(Object.keys(a).length){h.push({patch:a,deferred:i})}else{i.resolve(!0)}u=d;if(d.id){C[d.id]={state:d,messagesOffset:F(),loadedAllMessages:V()}}Te(e,t,n);return i.promise()}},Ae=function(e){return function(s,t){if(!u.loadingConfirmAction){e(D());var n=c.setLoadingConfirmAction(u,!1);v(n)}t.originalEvent.preventDefault()}},he=function(t,e){var n=s(t.target),d=n.closest(L.FOOTER_CONTAINER),a=d.find(L.MESSAGE_TEXT_AREA),i=a.val().trim();if(""!==i){Ie(i);a.val("");a.focus()}e.originalEvent.preventDefault()},Me=function(t,e){var n=window.getSelection(),d=s(t.target);if(""!=n.toString()){return}if(d.is("a")){return}var a=d.closest(L.MESSAGE),i=a.attr("data-message-id");ue(i);e.originalEvent.preventDefault()},Oe=function(t,e){var n=s(t.target),d=n.closest(L.MESSAGE),a=d.attr("data-message-id"),i=u.messages.filter(function(e){return e.id==a}),r=i.length?i[0]:null;if(r){Ce(r)}e.originalEvent.preventDefault();e.originalEvent.stopPropagation();t.stopPropagation()},Ne=function(s,e){_e();e.originalEvent.preventDefault()},ve=function(s){return function(t,e){var n=D(),d=u.members[n];E.go(s,I.VIEW_CONTACT,d);e.originalEvent.preventDefault()}},Se=function(s,e){te().catch(d.exception);e.originalEvent.preventDefault()},pe=function(s,e){ne().catch(d.exception);e.originalEvent.preventDefault()},be=function(s,e){de().catch(d.exception);e.originalEvent.preventDefault()},Ue=function(s,e){ae().catch(d.exception);e.originalEvent.preventDefault()},Le=function(t){var e=s(t.target).prop("checked"),n=c.setDeleteMessagesForAllUsers(u,e);v(n)},Re=function(s){return function(t,e){E.go(s,I.VIEW_GROUP_INFO,{id:u.id,name:u.name,subname:u.subname,imageUrl:u.imageUrl,totalMemberCount:u.totalMemberCount},u.loggedInUserId);e.originalEvent.preventDefault()}},De=function(s,t,i,r){var g=!1,l=w(i),m=[[L.ACTION_REQUEST_BLOCK,Ae(Y)],[L.ACTION_REQUEST_UNBLOCK,Ae(z)],[L.ACTION_REQUEST_ADD_CONTACT,Ae(ee)],[L.ACTION_REQUEST_REMOVE_CONTACT,Ae(Z)],[L.ACTION_REQUEST_DELETE_CONVERSATION,Ae(oe)],[L.ACTION_CANCEL_EDIT_MODE,Ne],[L.ACTION_VIEW_CONTACT,ve(s)],[L.ACTION_VIEW_GROUP_INFO,Re(s)],[L.ACTION_CONFIRM_FAVOURITE,Se],[L.ACTION_CONFIRM_MUTE,be],[L.ACTION_CONFIRM_UNFAVOURITE,pe],[L.ACTION_CONFIRM_UNMUTE,Ue]],E=[[L.ACTION_CANCEL_CONFIRM,Ae(le)],[L.ACTION_CONFIRM_BLOCK,Ae(H)],[L.ACTION_CONFIRM_UNBLOCK,Ae(J)],[L.ACTION_CONFIRM_ADD_CONTACT,Ae(se)],[L.ACTION_CONFIRM_REMOVE_CONTACT,Ae($)],[L.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES,Ae(re)],[L.ACTION_CONFIRM_DELETE_CONVERSATION,Ae(ge)],[L.ACTION_REQUEST_ADD_CONTACT,Ae(ee)],[L.ACTION_ACCEPT_CONTACT_REQUEST,Ae(me)],[L.ACTION_DECLINE_CONTACT_REQUEST,Ae(ce)],[L.MESSAGE,Me],[L.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE,Le],[L.RETRY_SEND,Oe]],C=[[L.SEND_MESSAGE_BUTTON,he],[L.ACTION_REQUEST_DELETE_SELECTED_MESSAGES,Ae(ie)],[L.ACTION_REQUEST_ADD_CONTACT,Ae(ee)],[L.ACTION_REQUEST_UNBLOCK,Ae(z)]];e.init(r);n.define(t,[n.events.activate]);n.define(i,[n.events.activate]);n.define(r,[n.events.activate,n.events.enter]);n.define(l,[n.events.scrollTop,n.events.scrollLock]);l.on(n.events.scrollTop,function(s,e){var t=1<Object.keys(u.members).length;if(!M&&!g&&!V()&&t){g=!0;var n=c.setLoadingMessages(u,!0);v(n);K(u.id,b,F(),p,[]).then(function(){g=!1;P(F()+b)}).catch(function(e){g=!1;d.exception(e)})}e.originalEvent.preventDefault()});m.forEach(function(e){var s=e[0],d=e[1];t.on(n.events.activate,s,d)});E.forEach(function(e){var s=e[0],t=e[1];i.on(n.events.activate,s,t)});C.forEach(function(e){var s=e[0],t=e[1];r.on(n.events.activate,s,t)});r.on(n.events.enter,L.MESSAGE_TEXT_AREA,function(s,e){var t=r.attr("data-enter-to-send");if(t&&"false"!=t&&"0"!=t){he(s,e)}});a.subscribe(o.ROUTE_CHANGED,function(e){if(f){if(e.route!=I.VIEW_CONVERSATION){f.stop()}}})},ye=function(e){if(f){f.stop()}f=new t(j(e,p),t.getIncrementalCallback(u.messagePollMin*U,U,u.messagePollMax*U,u.messagePollAfterMax*U));f.start()},Be=function(e,s,t){_=!1;T=0;f=null;A=!1;h=[];M=!0;O=!1;N=[];var n=t.id,d=parseInt(e.attr("data-midnight"),10),a=parseInt(e.attr("data-message-poll-min"),10),i=parseInt(e.attr("data-message-poll-max"),10),r=parseInt(e.attr("data-message-poll-after-max"),10),o=c.buildInitialState(d,n,s,a,i,r);if(!u){u=o}if(f){f.stop()}v(o)},Fe=function(e,s,t){Be(e,null,s);var n=null;if(s.id!=t){n=r.getConversationBetweenUsers(s.id,t,!0,!0,0,0,b,0,p)}else{n=r.getSelfConversation(s.id,b,0,p)}return n.then(function(t){return Ve(e,t,s)}).catch(function(){return G(s,t)})},Pe=function(e,t,n){var d=null;if(t in C){d=C[t]}Be(e,t,n);var a=s.Deferred().resolve({}).promise();if(d){var i=d.state;i=c.setLoadingMessages(i,!1);i=c.setLoadingMembers(i,!1);P(d.messagesOffset);x(d.loadedAllMessages);v(i)}else{a=Q(t,n,b,0,p)}return a.then(function(){return ye(t)})},Ve=function(e,t,n){var d=null;if(t.id in C){d=C[t.id]}Be(e,t.id,n);var a=s.Deferred().resolve({}).promise();if(d){var i=d.state;i=c.setLoadingMessages(i,!1);i=c.setLoadingMembers(i,!1);P(d.messagesOffset);x(d.loadedAllMessages);v(i)}else{a=W(t,n,b,p)}return a.then(function(){return ye(t.id)})},xe=function(e,t,n,a,i,r,o){var l=null,m=null;if(i&&null!==i&&"object"==_typeof(i)){l=i;m=parseInt(l.id,10)}else{l=null;m=parseInt(i,10);m=isNaN(m)?null:m}if(!m&&r&&o){m=y(o)}var c=!u||u.id!=m||o&&o!=D();if(!n.attr("data-init")){v=fe(t,n,a,c);De(e,t,n,a);n.attr("data-init",!0)}if(c){var E=null,I=B(n);if(l){E=Ve(n,l,I,o)}else if(m){E=Pe(n,m,I,o)}else{E=Fe(n,I,o)}return E.then(function(){M=!1;t.find(g.SELECTORS.CAN_RECEIVE_FOCUS).first().focus()}).catch(function(e){M=!1;d.exception(e)})}ye(m);if(u.type==R.PRIVATE&&r){var C=D();switch(r){case"block":return Y(C);case"unblock":return z(C);case"add-contact":return ee(C);case"remove-contact":return Z(C);}}return s.Deferred().resolve().promise()},we=function(){return i.get_string("messagedrawerviewconversation","core_message",u.name)};return{show:xe,description:we}});
+function _typeof(e){if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(e){return typeof e}}else{_typeof=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e}}return _typeof(e)}define ("core_message/message_drawer_view_conversation",["jquery","core/auto_rows","core/backoff_timer","core/custom_interaction_events","core/notification","core/pubsub","core/str","core_message/message_repository","core_message/message_drawer_events","core_message/message_drawer_view_conversation_constants","core_message/message_drawer_view_conversation_patcher","core_message/message_drawer_view_conversation_renderer","core_message/message_drawer_view_conversation_state_manager","core_message/message_drawer_router","core_message/message_drawer_routes"],function(s,e,t,n,d,a,i,r,o,g,l,m,c,E,I){var C={},_=null,u=!1,T=0,f=null,A=!1,h=[],M=!0,O=!1,N=[],v=null,S=[],p=g.NEWEST_MESSAGES_FIRST,b=g.LOAD_MESSAGE_LIMIT,U=g.MILLISECONDS_IN_SEC,R=g.SELECTORS,L=g.CONVERSATION_TYPES,D=function(){if(!_||_.type==L.PUBLIC){return null}var e=_.loggedInUserId;if(_.type==L.SELF){return e}var s=Object.keys(_.members).filter(function(s){return e!=s});return s.length?s[0]:null},y=function(e){return Object.keys(C).reduce(function(s,t){if(!s){var n=C[t].state;if(n.type!=L.PUBLIC){if(e in n.members){s=n.id}}}return s},null)},B=function(e){return{id:parseInt(e.attr("data-user-id"),10),fullname:null,profileimageurl:null,profileimageurlsmall:null,isonline:null,showonlinestatus:null,isblocked:null,iscontact:null,isdeleted:null,canmessage:null,canmessageevenifblocked:null,requirescontact:null,contactrequests:[]}},F=function(){return T},P=function(e){T=e;C[_.id].messagesOffset=e},V=function(){return u},x=function(e){u=e;C[_.id].loadedAllMessages=e},w=function(e){return e.find(R.MESSAGES_CONTAINER)},k=function(e){return{id:e.id,name:e.name,subname:e.subname,imageUrl:e.imageUrl,isFavourite:e.isFavourite,isMuted:e.isMuted,type:e.type,totalMemberCount:e.totalMemberCount,loggedInUserId:e.loggedInUserId,messages:e.messages.map(function(e){return s.extend({},e)}),members:Object.keys(e.members).map(function(t){var n=s.extend({},e.members[t]);n.contactrequests=e.members[t].contactrequests.map(function(e){return s.extend({},e)});return n})}},G=function(e,s){var t=e.id,n=t==s?L.SELF:L.PRIVATE,a=c.setLoadingMembers(_,!0);a=c.setLoadingMessages(a,!0);v(a);return r.getMemberInfo(t,[s],!0,!0).then(function(e){if(e.length){return e[0]}else{throw new Error("Unable to load other user profile")}}).then(function(s){var t=n==L.SELF?[s]:[s,e],d=c.addMembers(_,t);d=c.setLoadingMembers(d,!1);d=c.setLoadingMessages(d,!1);d=c.setName(d,s.fullname);d=c.setType(d,n);d=c.setImageUrl(d,s.profileimageurl);d=c.setTotalMemberCount(d,t.length);v(d);return s}).catch(function(e){var s=c.setLoadingMembers(_,!1);v(s);d.exception(e)})},q=function(e,s){var t=null;if(e.type==L.PRIVATE){var n=e.members.filter(function(e){return e.id!=s});t=n.length?n[0]:null}else if(e.type==L.SELF){t=e.members[0]}var d=e.name,a=e.imageurl;if(e.type!=L.PUBLIC){d=d||t?t.fullname:"";a=a||t?t.profileimageurl:""}var i=c.addMembers(_,e.members);i=c.setName(i,d);i=c.setSubname(i,e.subname);i=c.setType(i,e.type);i=c.setImageUrl(i,a);i=c.setTotalMemberCount(i,e.membercount);i=c.setIsFavourite(i,e.isfavourite);i=c.setIsMuted(i,e.ismuted);i=c.addMessages(i,e.messages);i=c.setCanDeleteMessagesForAllUsers(i,e.candeletemessagesforallusers);return i},Q=function(e,s,t,n,a){var i=s.id,o=c.setLoadingMembers(_,!0);o=c.setLoadingMessages(o,!0);v(o);return r.getConversation(i,e,!0,!0,0,0,t+1,n,a).then(function(e){if(e.messages.length>t){e.messages=e.messages.slice(1)}else{x(!0)}P(n+t);return e}).then(function(e){var t=e.members.filter(function(e){return e.id==s.id});if(1>t.length){e.members=e.members.concat([s])}var n=q(e,s.id);n=c.setLoadingMembers(n,!1);n=c.setLoadingMessages(n,!1);return v(n).then(function(){return e})}).then(function(){return Y(e)}).catch(function(e){var s=c.setLoadingMembers(_,!1);s=c.setLoadingMessages(s,!1);v(s);d.exception(e)})},W=function(e,s,t,n){var a=e.members.filter(function(e){return e.id==s.id});if(1>a.length){e.members=e.members.concat([s])}var i=e.messages.length,r=i>=t,o=q(e,s.id);o=c.setLoadingMembers(o,!1);o=c.setLoadingMessages(o,!r);var g=v(o);return g.then(function(){if(!r){return K(e.id,t,i,n,[])}else{return{messages:e.messages}}}).then(function(){var e=_.messages;P(e.length);Y(_.id);return e}).catch(d.exception)},K=function(e,s,t,n,d,a){return r.getMessages(_.loggedInUserId,e,s?s+1:s,t,n,a).then(function(e){if(e.messages.length&&d.length){e.messages=e.messages.filter(function(e){return 0>d.indexOf(parseInt(e.id,10))})}return e}).then(function(e){if(!s){return e}else if(e.messages.length>s){e.messages=e.messages.slice(0,-1)}else{x(!0)}return e}).then(function(e){var s=e.members.filter(function(e){return!(e.id in _.members)}),t=c.addMembers(_,s);t=c.addMessages(t,e.messages);t=c.setLoadingMessages(t,!1);return v(t).then(function(){return e})}).catch(function(e){var s=c.setLoadingMessages(_,!1);v(s);throw e})},j=function(e,t){return function(){var n=_.messages,d=n.length?n[n.length-1]:null,r=d?d.timeCreated:null;if(r&&!M&&!O){for(var g=[],l=n.length-1,m;0<=l;l--){m=n[l];if(m.timeCreated===r){g.push(m.id)}else{break}}return K(e,0,0,t,g,r).then(function(s){if(s.messages.length){f.restart();var t=k(_);a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,t);return Y(e)}else{return s}})}return s.Deferred().resolve().promise()}},Y=function(e){var s=_.loggedInUserId;return r.markAllConversationMessagesAsRead(s,e).then(function(){var s=c.markMessagesAsRead(_,_.messages);a.publish(o.CONVERSATION_READ,e);return v(s)})},X=function(e){le(e);var s=c.addPendingBlockUsersById(_,[e]);v(s)},H=function(e){var s=c.setLoadingConfirmAction(_,!0);v(s);return r.blockUser(_.loggedInUserId,e).then(function(s){var t=c.addMembers(_,[s]);t=c.removePendingBlockUsersById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_BLOCKED,e);return v(t)})},z=function(e){le(e);var s=c.addPendingUnblockUsersById(_,[e]);v(s)},Z=function(e){var s=c.setLoadingConfirmAction(_,!0);v(s);return r.unblockUser(_.loggedInUserId,e).then(function(s){var t=c.addMembers(_,[s]);t=c.removePendingUnblockUsersById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_UNBLOCKED,e);return v(t)})},$=function(e){le(e);var s=c.addPendingRemoveContactsById(_,[e]);v(s)},J=function(e){var s=c.setLoadingConfirmAction(_,!0);v(s);return r.deleteContacts(_.loggedInUserId,[e]).then(function(s){var t=c.addMembers(_,s);t=c.removePendingRemoveContactsById(t,[e]);t=c.setLoadingConfirmAction(t,!1);a.publish(o.CONTACT_REMOVED,e);return v(t)})},ee=function(e){le(e);var s=c.addPendingAddContactsById(_,[e]);v(s)},se=function(e){var s=c.setLoadingConfirmAction(_,!0);v(s);return r.createContactRequest(_.loggedInUserId,e).then(function(e){if(!e.request){throw new Error(e.warnings[0].message)}return e.request}).then(function(s){var t=c.removePendingAddContactsById(_,[e]);t=c.addContactRequests(t,[s]);t=c.setLoadingConfirmAction(t,!1);return v(t)})},te=function(){var e=_.loggedInUserId,s=_.id;return r.setFavouriteConversations(e,[s]).then(function(){var e=c.setIsFavourite(_,!0);return v(e)}).then(function(){return a.publish(o.CONVERSATION_SET_FAVOURITE,k(_))})},ne=function(){var e=_.loggedInUserId,s=_.id;return r.unsetFavouriteConversations(e,[s]).then(function(){var e=c.setIsFavourite(_,!1);return v(e)}).then(function(){return a.publish(o.CONVERSATION_UNSET_FAVOURITE,k(_))})},de=function(){var e=_.loggedInUserId,s=_.id;return r.setMutedConversations(e,[s]).then(function(){var e=c.setIsMuted(_,!0);return v(e)}).then(function(){return a.publish(o.CONVERSATION_SET_MUTED,k(_))})},ae=function(){var e=_.loggedInUserId,s=_.id;return r.unsetMutedConversations(e,[s]).then(function(){var e=c.setIsMuted(_,!1);return v(e)}).then(function(){return a.publish(o.CONVERSATION_UNSET_MUTED,k(_))})},ie=function(e){var s=_.selectedMessageIds;le(e);var t=c.addPendingDeleteMessagesById(_,s);v(t)},re=function(){var e=_.pendingDeleteMessageIds,t=_.messages.filter(function(s){return 0<=e.indexOf(s.id)&&("sent"==s.sendState||null===s.sendState)}),n=c.setLoadingConfirmAction(_,!0);v(n);var i=s.Deferred().resolve().promise();if(t.length){var g=t.map(function(e){return e.id});if(n.deleteMessagesForAllUsers){i=r.deleteMessagesForAllUsers(_.loggedInUserId,g)}else{i=r.deleteMessages(_.loggedInUserId,g)}}return i.then(function(){var s=c.removeMessagesById(_,e);s=c.removePendingDeleteMessagesById(s,e);s=c.removeSelectedMessagesById(s,e);s=c.setLoadingConfirmAction(s,!1);s=c.setDeleteMessagesForAllUsers(s,!1);var t=_.messages[_.messages.length-1],n=s.messages.length?s.messages[s.messages.length-1]:null;if(n&&n.id!=t.id){var d=k(s);a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,d)}else if(!s.messages.length){a.publish(o.CONVERSATION_DELETED,s.id)}return v(s)}).catch(d.exception)},oe=function(e){le(e);var s=c.setPendingDeleteConversation(_,!0);v(s)},ge=function(){var e=c.setLoadingConfirmAction(_,!0);v(e);return r.deleteConversation(_.loggedInUserId,_.id).then(function(){var e=c.removeMessages(_,_.messages);e=c.removeSelectedMessagesById(e,_.selectedMessageIds);e=c.setPendingDeleteConversation(e,!1);e=c.setLoadingConfirmAction(e,!1);a.publish(o.CONVERSATION_DELETED,e.id);return v(e)})},le=function(e){var s=_.pendingDeleteMessageIds,t=c.removePendingAddContactsById(_,[e]);t=c.removePendingRemoveContactsById(t,[e]);t=c.removePendingUnblockUsersById(t,[e]);t=c.removePendingBlockUsersById(t,[e]);t=c.removePendingDeleteMessagesById(t,s);t=c.setPendingDeleteConversation(t,!1);t=c.setDeleteMessagesForAllUsers(t,!1);v(t)},me=function(e){var s=_.loggedInUserId,t=_.members[e].contactrequests.filter(function(e){return e.requesteduserid==s}),n=t[0],d=c.setLoadingConfirmAction(_,!0);v(d);return r.acceptContactRequest(e,s).then(function(e){var s=c.removeContactRequests(_,[n]);s=c.addMembers(_,[e]);s=c.setLoadingConfirmAction(s,!1);return v(s)}).then(function(){a.publish(o.CONTACT_ADDED,_.members[e]);a.publish(o.CONTACT_REQUEST_ACCEPTED,n)})},ce=function(e){var s=_.loggedInUserId,t=_.members[e].contactrequests.filter(function(e){return e.requesteduserid==s}),n=t[0],d=c.setLoadingConfirmAction(_,!0);v(d);return r.declineContactRequest(e,s).then(function(e){var s=c.removeContactRequests(_,[n]);s=c.addMembers(_,[e]);s=c.setLoadingConfirmAction(s,!1);return v(s)}).then(function(){a.publish(o.CONTACT_REQUEST_DECLINED,n)})},Ee=function(){if(O){return}if(!N.length){return}O=!0;var e=N.slice();N=[];var t=_.id,n=null,d=e.map(function(e){return e.text}),g=e.map(function(e){return e.id}),l=null,m=null;if(!t&&_.type!=L.PUBLIC){var E=D();l=r.sendMessagesToUser(E,d).then(function(e){if(e.length){n=parseInt(e[0].conversationid,10);m=e[0].candeletemessagesforallusers}return e})}else{l=r.sendMessagesToConversation(t,d)}l.then(function(s){var t=s.map(function(e){return e.id}),d=[],i=[],r=[];e.forEach(function(e,t){var n=s[t];d.push([e,n]);if(0<=_.selectedMessageIds.indexOf(e.id)){i.push(e.id);r.push(n.id)}});var g=c.updateMessages(_,d);g=c.setMessagesSendSuccessById(g,t);if(i.length){g=c.removeSelectedMessagesById(g,i)}if(r.length){g=c.addSelectedMessagesById(g,r)}var l=k(g);if(!g.id){g=c.setId(g,n);l.id=n;ye(n);a.publish(o.CONVERSATION_CREATED,l);g=c.setCanDeleteMessagesForAllUsers(g,m)}v(g);O=!1;Ee();a.publish(o.CONVERSATION_NEW_LAST_MESSAGE,l)}).catch(function(t){if(t.message){var e=s.Deferred().resolve(t.message).promise()}else{var e=i.get_string("unknownerror","core")}var n=function(e){var s=c.setMessagesSendFailById(_,g,e);v(s);O=!1;Ee()};e.then(n).catch(function(s){var e=s.message||"Something went wrong!";n(e)})})},Ie=function(e){var s="temp"+Date.now(),t={id:s,useridfrom:_.loggedInUserId,text:e,timecreated:null},n=c.addMessages(_,[t]);v(n);N.push(t);Ee()},Ce=function(e){var s=c.setMessagesSendPendingById(_,[e.id]);v(s);N.push(e);Ee()},_e=function(e){var s=_;if(-1<_.selectedMessageIds.indexOf(e)){s=c.removeSelectedMessagesById(_,[e])}else{s=c.addSelectedMessagesById(_,[e])}v(s)},ue=function(){le(D());var e=c.removeSelectedMessagesById(_,_.selectedMessageIds);v(e)},Te=function(e,t,n){if(A){return}if(!h.length){return}A=!0;var a=h.shift(),i=S.map(function(e){return e(a.patch)});s.when.apply(null,i).then(function(){A=!1;a.deferred.resolve(!0);Te(e,t,n)}).catch(function(e){A=!1;a.deferred.reject(e);d.exception(e)})},fe=function(e,t,n,d){var a=function(s){return m.render(e,t,n,s)};if(!d){var i=c.buildInitialState(_.midnight,_.loggedInUserId,_.id),r=l.buildPatch(i,_);a(r)}S.push(a);return function(d){var a=l.buildPatch(_,d),i=s.Deferred();if(Object.keys(a).length){h.push({patch:a,deferred:i})}else{i.resolve(!0)}_=d;if(d.id){C[d.id]={state:d,messagesOffset:F(),loadedAllMessages:V()}}Te(e,t,n);return i.promise()}},Ae=function(e){return function(s,t){if(!_.loadingConfirmAction){e(D());var n=c.setLoadingConfirmAction(_,!1);v(n)}t.originalEvent.preventDefault()}},he=function(t,e){var n=s(t.target),d=n.closest(R.FOOTER_CONTAINER),a=d.find(R.MESSAGE_TEXT_AREA),i=a.val().trim();if(""!==i){Ie(i);a.val("");a.focus()}e.originalEvent.preventDefault()},Me=function(t,e){var n=window.getSelection(),d=s(t.target);if(""!=n.toString()){return}if(d.is("a")){return}var a=d.closest(R.MESSAGE),i=a.attr("data-message-id");_e(i);e.originalEvent.preventDefault()},Oe=function(t,e){var n=s(t.target),d=n.closest(R.MESSAGE),a=d.attr("data-message-id"),i=_.messages.filter(function(e){return e.id==a}),r=i.length?i[0]:null;if(r){Ce(r)}e.originalEvent.preventDefault();e.originalEvent.stopPropagation();t.stopPropagation()},Ne=function(s,e){ue();e.originalEvent.preventDefault()},ve=function(s){return function(t,e){var n=D(),d=_.members[n];E.go(s,I.VIEW_CONTACT,d);e.originalEvent.preventDefault()}},Se=function(s,e){te().catch(d.exception);e.originalEvent.preventDefault()},pe=function(s,e){ne().catch(d.exception);e.originalEvent.preventDefault()},be=function(s,e){de().catch(d.exception);e.originalEvent.preventDefault()},Ue=function(s,e){ae().catch(d.exception);e.originalEvent.preventDefault()},Re=function(t){var e=s(t.target).prop("checked"),n=c.setDeleteMessagesForAllUsers(_,e);v(n)},Le=function(s){return function(t,e){E.go(s,I.VIEW_GROUP_INFO,{id:_.id,name:_.name,subname:_.subname,imageUrl:_.imageUrl,totalMemberCount:_.totalMemberCount},_.loggedInUserId);e.originalEvent.preventDefault()}},De=function(s,t,i,r){var g=!1,l=w(i),m=[[R.ACTION_REQUEST_BLOCK,Ae(X)],[R.ACTION_REQUEST_UNBLOCK,Ae(z)],[R.ACTION_REQUEST_ADD_CONTACT,Ae(ee)],[R.ACTION_REQUEST_REMOVE_CONTACT,Ae($)],[R.ACTION_REQUEST_DELETE_CONVERSATION,Ae(oe)],[R.ACTION_CANCEL_EDIT_MODE,Ne],[R.ACTION_VIEW_CONTACT,ve(s)],[R.ACTION_VIEW_GROUP_INFO,Le(s)],[R.ACTION_CONFIRM_FAVOURITE,Se],[R.ACTION_CONFIRM_MUTE,be],[R.ACTION_CONFIRM_UNFAVOURITE,pe],[R.ACTION_CONFIRM_UNMUTE,Ue]],E=[[R.ACTION_CANCEL_CONFIRM,Ae(le)],[R.ACTION_CONFIRM_BLOCK,Ae(H)],[R.ACTION_CONFIRM_UNBLOCK,Ae(Z)],[R.ACTION_CONFIRM_ADD_CONTACT,Ae(se)],[R.ACTION_CONFIRM_REMOVE_CONTACT,Ae(J)],[R.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES,Ae(re)],[R.ACTION_CONFIRM_DELETE_CONVERSATION,Ae(ge)],[R.ACTION_OKAY_CONFIRM,Ae(le)],[R.ACTION_REQUEST_ADD_CONTACT,Ae(ee)],[R.ACTION_ACCEPT_CONTACT_REQUEST,Ae(me)],[R.ACTION_DECLINE_CONTACT_REQUEST,Ae(ce)],[R.MESSAGE,Me],[R.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE,Re],[R.RETRY_SEND,Oe]],C=[[R.SEND_MESSAGE_BUTTON,he],[R.ACTION_REQUEST_DELETE_SELECTED_MESSAGES,Ae(ie)],[R.ACTION_REQUEST_ADD_CONTACT,Ae(ee)],[R.ACTION_REQUEST_UNBLOCK,Ae(z)]];e.init(r);n.define(t,[n.events.activate]);n.define(i,[n.events.activate]);n.define(r,[n.events.activate,n.events.enter]);n.define(l,[n.events.scrollTop,n.events.scrollLock]);l.on(n.events.scrollTop,function(s,e){var t=1<Object.keys(_.members).length;if(!M&&!g&&!V()&&t){g=!0;var n=c.setLoadingMessages(_,!0);v(n);K(_.id,b,F(),p,[]).then(function(){g=!1;P(F()+b)}).catch(function(e){g=!1;d.exception(e)})}e.originalEvent.preventDefault()});m.forEach(function(e){var s=e[0],d=e[1];t.on(n.events.activate,s,d)});E.forEach(function(e){var s=e[0],t=e[1];i.on(n.events.activate,s,t)});C.forEach(function(e){var s=e[0],t=e[1];r.on(n.events.activate,s,t)});r.on(n.events.enter,R.MESSAGE_TEXT_AREA,function(s,e){var t=r.attr("data-enter-to-send");if(t&&"false"!=t&&"0"!=t){he(s,e)}});a.subscribe(o.ROUTE_CHANGED,function(e){if(f){if(e.route!=I.VIEW_CONVERSATION){f.stop()}}})},ye=function(e){if(f){f.stop()}f=new t(j(e,p),t.getIncrementalCallback(_.messagePollMin*U,U,_.messagePollMax*U,_.messagePollAfterMax*U));f.start()},Be=function(e,s,t){u=!1;T=0;f=null;A=!1;h=[];M=!0;O=!1;N=[];var n=t.id,d=parseInt(e.attr("data-midnight"),10),a=parseInt(e.attr("data-message-poll-min"),10),i=parseInt(e.attr("data-message-poll-max"),10),r=parseInt(e.attr("data-message-poll-after-max"),10),o=c.buildInitialState(d,n,s,a,i,r);if(!_){_=o}if(f){f.stop()}v(o)},Fe=function(e,s,t){Be(e,null,s);var n=null;if(s.id!=t){n=r.getConversationBetweenUsers(s.id,t,!0,!0,0,0,b,0,p)}else{n=r.getSelfConversation(s.id,b,0,p)}return n.then(function(t){return Ve(e,t,s)}).catch(function(){return G(s,t)})},Pe=function(e,t,n){var d=null;if(t in C){d=C[t]}Be(e,t,n);var a=s.Deferred().resolve({}).promise();if(d){var i=d.state;i=c.setLoadingMessages(i,!1);i=c.setLoadingMembers(i,!1);P(d.messagesOffset);x(d.loadedAllMessages);v(i)}else{a=Q(t,n,b,0,p)}return a.then(function(){return ye(t)})},Ve=function(e,t,n){var d=null;if(t.id in C){d=C[t.id]}Be(e,t.id,n);var a=s.Deferred().resolve({}).promise();if(d){var i=d.state;i=c.setLoadingMessages(i,!1);i=c.setLoadingMembers(i,!1);P(d.messagesOffset);x(d.loadedAllMessages);v(i)}else{a=W(t,n,b,p)}return a.then(function(){return ye(t.id)})},xe=function(e,t,n,a,i,r,o){var l=null,m=null;if(i&&null!==i&&"object"==_typeof(i)){l=i;m=parseInt(l.id,10)}else{l=null;m=parseInt(i,10);m=isNaN(m)?null:m}if(!m&&r&&o){m=y(o)}var c=!_||_.id!=m||o&&o!=D();if(!n.attr("data-init")){v=fe(t,n,a,c);De(e,t,n,a);n.attr("data-init",!0)}if(c){var E=null,I=B(n);if(l){E=Ve(n,l,I,o)}else if(m){E=Pe(n,m,I,o)}else{E=Fe(n,I,o)}return E.then(function(){M=!1;t.find(g.SELECTORS.CAN_RECEIVE_FOCUS).first().focus()}).catch(function(e){M=!1;d.exception(e)})}ye(m);if(_.type==L.PRIVATE&&r){var C=D();switch(r){case"block":return X(C);case"unblock":return z(C);case"add-contact":return ee(C);case"remove-contact":return $(C);}}return s.Deferred().resolve().promise()},we=function(){return i.get_string("messagedrawerviewconversation","core_message",_.name)};return{show:xe,description:we}});
 //# sourceMappingURL=message_drawer_view_conversation.min.js.map
diff --git a/message/amd/build/message_drawer_view_conversation.min.js.map b/message/amd/build/message_drawer_view_conversation.min.js.map
index 0cada90032e..6407753e46a 100644
--- a/message/amd/build/message_drawer_view_conversation.min.js.map
+++ b/message/amd/build/message_drawer_view_conversation.min.js.map
@@ -1 +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","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","registerEventListeners","isLoadingMoreMessages","messagesContainer","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_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","events","activate","enter","scrollTop","scrollLock","on","hasMembers","handler","selector","handlerFunction","enterToSend","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],\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) {\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     * 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 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_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.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        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        ]);\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        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"}
\ No newline at end of file
+{"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","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","registerEventListeners","isLoadingMoreMessages","messagesContainer","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","events","activate","enter","scrollTop","scrollLock","on","hasMembers","handler","selector","handlerFunction","enterToSend","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],\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) {\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     * 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 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.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        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        ]);\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        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"}
\ No newline at end of file
diff --git a/message/amd/build/message_drawer_view_conversation_constants.min.js b/message/amd/build/message_drawer_view_conversation_constants.min.js
index d3a2448f5fd..6620624dbca 100644
--- a/message/amd/build/message_drawer_view_conversation_constants.min.js
+++ b/message/amd/build/message_drawer_view_conversation_constants.min.js
@@ -1,2 +1,2 @@
-define ("core_message/message_drawer_view_conversation_constants",[],function(){return{SELECTORS:{ACTION_ACCEPT_CONTACT_REQUEST:"[data-action=\"accept-contact-request\"]",ACTION_CANCEL_CONFIRM:"[data-action=\"cancel-confirm\"]",ACTION_CANCEL_EDIT_MODE:"[data-action=\"cancel-edit-mode\"]",ACTION_CONFIRM_ADD_CONTACT:"[data-action=\"confirm-add-contact\"]",ACTION_CONFIRM_BLOCK:"[data-action=\"confirm-block\"]",ACTION_CONFIRM_DELETE_SELECTED_MESSAGES:"[data-action=\"confirm-delete-selected-messages\"]",ACTION_CONFIRM_DELETE_CONVERSATION:"[data-action=\"confirm-delete-conversation\"]",ACTION_CONFIRM_FAVOURITE:"[data-action=\"confirm-favourite\"]",ACTION_CONFIRM_MUTE:"[data-action=\"confirm-mute\"]",ACTION_CONFIRM_UNFAVOURITE:"[data-action=\"confirm-unfavourite\"]",ACTION_CONFIRM_REMOVE_CONTACT:"[data-action=\"confirm-remove-contact\"]",ACTION_CONFIRM_UNBLOCK:"[data-action=\"confirm-unblock\"]",ACTION_CONFIRM_UNMUTE:"[data-action=\"confirm-unmute\"]",ACTION_DECLINE_CONTACT_REQUEST:"[data-action=\"decline-contact-request\"]",ACTION_REQUEST_ADD_CONTACT:"[data-action=\"request-add-contact\"]",ACTION_REQUEST_BLOCK:"[data-action=\"request-block\"]",ACTION_REQUEST_DELETE_CONVERSATION:"[data-action=\"request-delete-conversation\"]",ACTION_REQUEST_DELETE_SELECTED_MESSAGES:"[data-action=\"delete-selected-messages\"]",ACTION_REQUEST_REMOVE_CONTACT:"[data-action=\"request-remove-contact\"]",ACTION_REQUEST_UNBLOCK:"[data-action=\"request-unblock\"]",ACTION_VIEW_CONTACT:"[data-action=\"view-contact\"]",ACTION_VIEW_GROUP_INFO:"[data-action=\"view-group-info\"]",CAN_RECEIVE_FOCUS:"input:not([type=\"hidden\"]), a[href], button, textarea, select, [tabindex]",CONFIRM_DIALOGUE_BUTTON_TEXT:"[data-region=\"dialogue-button-text\"]",CONFIRM_DIALOGUE_CANCEL_BUTTON:"[data-action=\"cancel-confirm\"]",CONFIRM_DIALOGUE_CONTAINER:"[data-region=\"confirm-dialogue-container\"]",CONFIRM_DIALOGUE_HEADER:"[data-region=\"dialogue-header\"]",CONFIRM_DIALOGUE_TEXT:"[data-region=\"dialogue-text\"]",CONTACT_REQUEST_SENT_MESSAGE_CONTAINER:"[data-region=\"contact-request-sent-message-container\"]",CONTENT_PLACEHOLDER_CONTAINER:"[data-region=\"content-placeholder\"]",CONTENT_CONTAINER:"[data-region=\"content-container\"]",CONTENT_MESSAGES_CONTAINER:"[data-region=\"content-message-container\"]",CONTENT_MESSAGES_FOOTER_CONTAINER:"[data-region=\"content-messages-footer-container\"]",CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER:"[data-region=\"content-messages-footer-edit-mode-container\"]",CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER:"[data-region=\"content-messages-footer-require-contact-container\"]",CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER:"[data-region=\"content-messages-footer-require-unblock-container\"]",CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER:"[data-region=\"content-messages-footer-unable-to-message\"]",DAY_MESSAGES_CONTAINER:"[data-region=\"day-messages-container\"]",DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE:"[data-region=\"delete-messages-for-all-users-toggle\"]",DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER:"[data-region=\"delete-messages-for-all-users-toggle-container\"]",ERROR_MESSAGE_CONTAINER:"[data-region=\"error-message-container\"]",ERROR_MESSAGE:"[data-region=\"error-message\"]",FAVOURITE_ICON_CONTAINER:"[data-region=\"favourite-icon-container\"]",FOOTER_CONTAINER:"[data-region=\"content-messages-footer-container\"]",HEADER:"[data-region=\"header-content\"]",HEADER_EDIT_MODE:"[data-region=\"header-edit-mode\"]",HEADER_PLACEHOLDER_CONTAINER:"[data-region=\"header-placeholder\"]",LOADING_ICON_CONTAINER:"[data-region=\"loading-icon-container\"]",MESSAGE:"[data-region=\"message\"]",MESSAGE_NOT_SELECTED:"[data-region=\"message\"][aria-checked=\"false\"]",MESSAGE_NOT_SELECTED_ICON:"[data-region=\"not-selected-icon\"]",MESSAGE_SELECTED_ICON:"[data-region=\"selected-icon\"]",MESSAGES:"[data-region=\"content-message-container\"]",MESSAGES_CONTAINER:"[data-region=\"content-message-container\"]",MESSAGES_SELECTED_COUNT:"[data-region=\"message-selected-court\"]",MESSAGE_TEXT_AREA:"[data-region=\"send-message-txt\"]",MORE_MESSAGES_LOADING_ICON_CONTAINER:"[data-region=\"more-messages-loading-icon-container\"]",MUTED_ICON_CONTAINER:"[data-region=\"muted-icon-container\"]",PLACEHOLDER_CONTAINER:"[data-region=\"placeholder-container\"]",RETRY_SEND:"[data-region=\"retry-send\"]",SELF_CONVERSATION_MESSAGE_CONTAINER:"[data-region=\"self-conversation-message-container\"]",SEND_MESSAGE_BUTTON:"[data-action=\"send-message\"]",SEND_MESSAGE_ICON_CONTAINER:"[data-region=\"send-icon-container\"]",TEXT:"[data-region=\"text\"]",TEXT_CONTAINER:"[data-region=\"text-container\"]",TIME_CREATED:"[data-region=\"time-created\"]",TITLE:"[data-region=\"title\"]"},TEMPLATES:{HEADER_PRIVATE:"core_message/message_drawer_view_conversation_header_content_type_private",HEADER_PRIVATE_NO_CONTROLS:"core_message/message_drawer_view_conversation_header_content_type_private_no_controls",HEADER_PUBLIC:"core_message/message_drawer_view_conversation_header_content_type_public",HEADER_SELF:"core_message/message_drawer_view_conversation_header_content_type_self",DAY:"core_message/message_drawer_view_conversation_body_day",MESSAGE:"core_message/message_drawer_view_conversation_body_message",MESSAGES:"core_message/message_drawer_view_conversation_body_messages"},CONVERSATION_TYPES:{PRIVATE:1,PUBLIC:2,SELF:3},NEWEST_MESSAGES_FIRST:!0,LOAD_MESSAGE_LIMIT:100,MILLISECONDS_IN_SEC:1e3}});
+define ("core_message/message_drawer_view_conversation_constants",[],function(){return{SELECTORS:{ACTION_ACCEPT_CONTACT_REQUEST:"[data-action=\"accept-contact-request\"]",ACTION_CANCEL_CONFIRM:"[data-action=\"cancel-confirm\"]",ACTION_OKAY_CONFIRM:"[data-action=\"okay-confirm\"]",ACTION_CANCEL_EDIT_MODE:"[data-action=\"cancel-edit-mode\"]",ACTION_CONFIRM_ADD_CONTACT:"[data-action=\"confirm-add-contact\"]",ACTION_CONFIRM_BLOCK:"[data-action=\"confirm-block\"]",ACTION_CONFIRM_DELETE_SELECTED_MESSAGES:"[data-action=\"confirm-delete-selected-messages\"]",ACTION_CONFIRM_DELETE_CONVERSATION:"[data-action=\"confirm-delete-conversation\"]",ACTION_CONFIRM_FAVOURITE:"[data-action=\"confirm-favourite\"]",ACTION_CONFIRM_MUTE:"[data-action=\"confirm-mute\"]",ACTION_CONFIRM_UNFAVOURITE:"[data-action=\"confirm-unfavourite\"]",ACTION_CONFIRM_REMOVE_CONTACT:"[data-action=\"confirm-remove-contact\"]",ACTION_CONFIRM_UNBLOCK:"[data-action=\"confirm-unblock\"]",ACTION_CONFIRM_UNMUTE:"[data-action=\"confirm-unmute\"]",ACTION_DECLINE_CONTACT_REQUEST:"[data-action=\"decline-contact-request\"]",ACTION_REQUEST_ADD_CONTACT:"[data-action=\"request-add-contact\"]",ACTION_REQUEST_BLOCK:"[data-action=\"request-block\"]",ACTION_REQUEST_DELETE_CONVERSATION:"[data-action=\"request-delete-conversation\"]",ACTION_REQUEST_DELETE_SELECTED_MESSAGES:"[data-action=\"delete-selected-messages\"]",ACTION_REQUEST_REMOVE_CONTACT:"[data-action=\"request-remove-contact\"]",ACTION_REQUEST_UNBLOCK:"[data-action=\"request-unblock\"]",ACTION_VIEW_CONTACT:"[data-action=\"view-contact\"]",ACTION_VIEW_GROUP_INFO:"[data-action=\"view-group-info\"]",CAN_RECEIVE_FOCUS:"input:not([type=\"hidden\"]), a[href], button, textarea, select, [tabindex]",CONFIRM_DIALOGUE_BUTTON_TEXT:"[data-region=\"dialogue-button-text\"]",CONFIRM_DIALOGUE_CANCEL_BUTTON:"[data-action=\"cancel-confirm\"]",CONFIRM_DIALOGUE_CONTAINER:"[data-region=\"confirm-dialogue-container\"]",CONFIRM_DIALOGUE_HEADER:"[data-region=\"dialogue-header\"]",CONFIRM_DIALOGUE_OKAY_BUTTON:"[data-action=\"okay-confirm\"]",CONFIRM_DIALOGUE_TEXT:"[data-region=\"dialogue-text\"]",CONTACT_REQUEST_SENT_MESSAGE_CONTAINER:"[data-region=\"contact-request-sent-message-container\"]",CONTENT_PLACEHOLDER_CONTAINER:"[data-region=\"content-placeholder\"]",CONTENT_CONTAINER:"[data-region=\"content-container\"]",CONTENT_MESSAGES_CONTAINER:"[data-region=\"content-message-container\"]",CONTENT_MESSAGES_FOOTER_CONTAINER:"[data-region=\"content-messages-footer-container\"]",CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER:"[data-region=\"content-messages-footer-edit-mode-container\"]",CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER:"[data-region=\"content-messages-footer-require-contact-container\"]",CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER:"[data-region=\"content-messages-footer-require-unblock-container\"]",CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER:"[data-region=\"content-messages-footer-unable-to-message\"]",DAY_MESSAGES_CONTAINER:"[data-region=\"day-messages-container\"]",DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE:"[data-region=\"delete-messages-for-all-users-toggle\"]",DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER:"[data-region=\"delete-messages-for-all-users-toggle-container\"]",ERROR_MESSAGE_CONTAINER:"[data-region=\"error-message-container\"]",ERROR_MESSAGE:"[data-region=\"error-message\"]",FAVOURITE_ICON_CONTAINER:"[data-region=\"favourite-icon-container\"]",FOOTER_CONTAINER:"[data-region=\"content-messages-footer-container\"]",HEADER:"[data-region=\"header-content\"]",HEADER_EDIT_MODE:"[data-region=\"header-edit-mode\"]",HEADER_PLACEHOLDER_CONTAINER:"[data-region=\"header-placeholder\"]",LOADING_ICON_CONTAINER:"[data-region=\"loading-icon-container\"]",MESSAGE:"[data-region=\"message\"]",MESSAGE_NOT_SELECTED:"[data-region=\"message\"][aria-checked=\"false\"]",MESSAGE_NOT_SELECTED_ICON:"[data-region=\"not-selected-icon\"]",MESSAGE_SELECTED_ICON:"[data-region=\"selected-icon\"]",MESSAGES:"[data-region=\"content-message-container\"]",MESSAGES_CONTAINER:"[data-region=\"content-message-container\"]",MESSAGES_SELECTED_COUNT:"[data-region=\"message-selected-court\"]",MESSAGE_TEXT_AREA:"[data-region=\"send-message-txt\"]",MORE_MESSAGES_LOADING_ICON_CONTAINER:"[data-region=\"more-messages-loading-icon-container\"]",MUTED_ICON_CONTAINER:"[data-region=\"muted-icon-container\"]",PLACEHOLDER_CONTAINER:"[data-region=\"placeholder-container\"]",RETRY_SEND:"[data-region=\"retry-send\"]",SELF_CONVERSATION_MESSAGE_CONTAINER:"[data-region=\"self-conversation-message-container\"]",SEND_MESSAGE_BUTTON:"[data-action=\"send-message\"]",SEND_MESSAGE_ICON_CONTAINER:"[data-region=\"send-icon-container\"]",TEXT:"[data-region=\"text\"]",TEXT_CONTAINER:"[data-region=\"text-container\"]",TIME_CREATED:"[data-region=\"time-created\"]",TITLE:"[data-region=\"title\"]"},TEMPLATES:{HEADER_PRIVATE:"core_message/message_drawer_view_conversation_header_content_type_private",HEADER_PRIVATE_NO_CONTROLS:"core_message/message_drawer_view_conversation_header_content_type_private_no_controls",HEADER_PUBLIC:"core_message/message_drawer_view_conversation_header_content_type_public",HEADER_SELF:"core_message/message_drawer_view_conversation_header_content_type_self",DAY:"core_message/message_drawer_view_conversation_body_day",MESSAGE:"core_message/message_drawer_view_conversation_body_message",MESSAGES:"core_message/message_drawer_view_conversation_body_messages"},CONVERSATION_TYPES:{PRIVATE:1,PUBLIC:2,SELF:3},NEWEST_MESSAGES_FIRST:!0,LOAD_MESSAGE_LIMIT:100,MILLISECONDS_IN_SEC:1e3}});
 //# sourceMappingURL=message_drawer_view_conversation_constants.min.js.map
diff --git a/message/amd/build/message_drawer_view_conversation_constants.min.js.map b/message/amd/build/message_drawer_view_conversation_constants.min.js.map
index f06b406c24a..9db88ba557b 100644
--- a/message/amd/build/message_drawer_view_conversation_constants.min.js.map
+++ b/message/amd/build/message_drawer_view_conversation_constants.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/message_drawer_view_conversation_constants.js"],"names":["define","SELECTORS","ACTION_ACCEPT_CONTACT_REQUEST","ACTION_CANCEL_CONFIRM","ACTION_CANCEL_EDIT_MODE","ACTION_CONFIRM_ADD_CONTACT","ACTION_CONFIRM_BLOCK","ACTION_CONFIRM_DELETE_SELECTED_MESSAGES","ACTION_CONFIRM_DELETE_CONVERSATION","ACTION_CONFIRM_FAVOURITE","ACTION_CONFIRM_MUTE","ACTION_CONFIRM_UNFAVOURITE","ACTION_CONFIRM_REMOVE_CONTACT","ACTION_CONFIRM_UNBLOCK","ACTION_CONFIRM_UNMUTE","ACTION_DECLINE_CONTACT_REQUEST","ACTION_REQUEST_ADD_CONTACT","ACTION_REQUEST_BLOCK","ACTION_REQUEST_DELETE_CONVERSATION","ACTION_REQUEST_DELETE_SELECTED_MESSAGES","ACTION_REQUEST_REMOVE_CONTACT","ACTION_REQUEST_UNBLOCK","ACTION_VIEW_CONTACT","ACTION_VIEW_GROUP_INFO","CAN_RECEIVE_FOCUS","CONFIRM_DIALOGUE_BUTTON_TEXT","CONFIRM_DIALOGUE_CANCEL_BUTTON","CONFIRM_DIALOGUE_CONTAINER","CONFIRM_DIALOGUE_HEADER","CONFIRM_DIALOGUE_TEXT","CONTACT_REQUEST_SENT_MESSAGE_CONTAINER","CONTENT_PLACEHOLDER_CONTAINER","CONTENT_CONTAINER","CONTENT_MESSAGES_CONTAINER","CONTENT_MESSAGES_FOOTER_CONTAINER","CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER","CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER","CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER","CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER","DAY_MESSAGES_CONTAINER","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER","ERROR_MESSAGE_CONTAINER","ERROR_MESSAGE","FAVOURITE_ICON_CONTAINER","FOOTER_CONTAINER","HEADER","HEADER_EDIT_MODE","HEADER_PLACEHOLDER_CONTAINER","LOADING_ICON_CONTAINER","MESSAGE","MESSAGE_NOT_SELECTED","MESSAGE_NOT_SELECTED_ICON","MESSAGE_SELECTED_ICON","MESSAGES","MESSAGES_CONTAINER","MESSAGES_SELECTED_COUNT","MESSAGE_TEXT_AREA","MORE_MESSAGES_LOADING_ICON_CONTAINER","MUTED_ICON_CONTAINER","PLACEHOLDER_CONTAINER","RETRY_SEND","SELF_CONVERSATION_MESSAGE_CONTAINER","SEND_MESSAGE_BUTTON","SEND_MESSAGE_ICON_CONTAINER","TEXT","TEXT_CONTAINER","TIME_CREATED","TITLE","TEMPLATES","HEADER_PRIVATE","HEADER_PRIVATE_NO_CONTROLS","HEADER_PUBLIC","HEADER_SELF","DAY","CONVERSATION_TYPES","PRIVATE","PUBLIC","SELF","NEWEST_MESSAGES_FIRST","LOAD_MESSAGE_LIMIT","MILLISECONDS_IN_SEC"],"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 * Constant values for the conversation page in the message drawer.\n *\n * @module     core_message/message_drawer_view_conversation_constants\n * @copyright  2018 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n\n    var SELECTORS = {\n        ACTION_ACCEPT_CONTACT_REQUEST: '[data-action=\"accept-contact-request\"]',\n        ACTION_CANCEL_CONFIRM: '[data-action=\"cancel-confirm\"]',\n        ACTION_CANCEL_EDIT_MODE: '[data-action=\"cancel-edit-mode\"]',\n        ACTION_CONFIRM_ADD_CONTACT: '[data-action=\"confirm-add-contact\"]',\n        ACTION_CONFIRM_BLOCK: '[data-action=\"confirm-block\"]',\n        ACTION_CONFIRM_DELETE_SELECTED_MESSAGES: '[data-action=\"confirm-delete-selected-messages\"]',\n        ACTION_CONFIRM_DELETE_CONVERSATION: '[data-action=\"confirm-delete-conversation\"]',\n        ACTION_CONFIRM_FAVOURITE: '[data-action=\"confirm-favourite\"]',\n        ACTION_CONFIRM_MUTE: '[data-action=\"confirm-mute\"]',\n        ACTION_CONFIRM_UNFAVOURITE: '[data-action=\"confirm-unfavourite\"]',\n        ACTION_CONFIRM_REMOVE_CONTACT: '[data-action=\"confirm-remove-contact\"]',\n        ACTION_CONFIRM_UNBLOCK: '[data-action=\"confirm-unblock\"]',\n        ACTION_CONFIRM_UNMUTE: '[data-action=\"confirm-unmute\"]',\n        ACTION_DECLINE_CONTACT_REQUEST: '[data-action=\"decline-contact-request\"]',\n        ACTION_REQUEST_ADD_CONTACT: '[data-action=\"request-add-contact\"]',\n        ACTION_REQUEST_BLOCK: '[data-action=\"request-block\"]',\n        ACTION_REQUEST_DELETE_CONVERSATION: '[data-action=\"request-delete-conversation\"]',\n        ACTION_REQUEST_DELETE_SELECTED_MESSAGES: '[data-action=\"delete-selected-messages\"]',\n        ACTION_REQUEST_REMOVE_CONTACT: '[data-action=\"request-remove-contact\"]',\n        ACTION_REQUEST_UNBLOCK: '[data-action=\"request-unblock\"]',\n        ACTION_VIEW_CONTACT: '[data-action=\"view-contact\"]',\n        ACTION_VIEW_GROUP_INFO: '[data-action=\"view-group-info\"]',\n        CAN_RECEIVE_FOCUS: 'input:not([type=\"hidden\"]), a[href], button, textarea, select, [tabindex]',\n        CONFIRM_DIALOGUE_BUTTON_TEXT: '[data-region=\"dialogue-button-text\"]',\n        CONFIRM_DIALOGUE_CANCEL_BUTTON: '[data-action=\"cancel-confirm\"]',\n        CONFIRM_DIALOGUE_CONTAINER: '[data-region=\"confirm-dialogue-container\"]',\n        CONFIRM_DIALOGUE_HEADER: '[data-region=\"dialogue-header\"]',\n        CONFIRM_DIALOGUE_TEXT: '[data-region=\"dialogue-text\"]',\n        CONTACT_REQUEST_SENT_MESSAGE_CONTAINER: '[data-region=\"contact-request-sent-message-container\"]',\n        CONTENT_PLACEHOLDER_CONTAINER: '[data-region=\"content-placeholder\"]',\n        CONTENT_CONTAINER: '[data-region=\"content-container\"]',\n        CONTENT_MESSAGES_CONTAINER: '[data-region=\"content-message-container\"]',\n        CONTENT_MESSAGES_FOOTER_CONTAINER: '[data-region=\"content-messages-footer-container\"]',\n        CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER: '[data-region=\"content-messages-footer-edit-mode-container\"]',\n        CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER: '[data-region=\"content-messages-footer-require-contact-container\"]',\n        CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER: '[data-region=\"content-messages-footer-require-unblock-container\"]',\n        CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER: '[data-region=\"content-messages-footer-unable-to-message\"]',\n        DAY_MESSAGES_CONTAINER: '[data-region=\"day-messages-container\"]',\n        DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE: '[data-region=\"delete-messages-for-all-users-toggle\"]',\n        DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER: '[data-region=\"delete-messages-for-all-users-toggle-container\"]',\n        ERROR_MESSAGE_CONTAINER: '[data-region=\"error-message-container\"]',\n        ERROR_MESSAGE: '[data-region=\"error-message\"]',\n        FAVOURITE_ICON_CONTAINER: '[data-region=\"favourite-icon-container\"]',\n        FOOTER_CONTAINER: '[data-region=\"content-messages-footer-container\"]',\n        HEADER: '[data-region=\"header-content\"]',\n        HEADER_EDIT_MODE: '[data-region=\"header-edit-mode\"]',\n        HEADER_PLACEHOLDER_CONTAINER: '[data-region=\"header-placeholder\"]',\n        LOADING_ICON_CONTAINER: '[data-region=\"loading-icon-container\"]',\n        MESSAGE: '[data-region=\"message\"]',\n        MESSAGE_NOT_SELECTED: '[data-region=\"message\"][aria-checked=\"false\"]',\n        MESSAGE_NOT_SELECTED_ICON: '[data-region=\"not-selected-icon\"]',\n        MESSAGE_SELECTED_ICON: '[data-region=\"selected-icon\"]',\n        MESSAGES: '[data-region=\"content-message-container\"]',\n        MESSAGES_CONTAINER: '[data-region=\"content-message-container\"]',\n        MESSAGES_SELECTED_COUNT: '[data-region=\"message-selected-court\"]',\n        MESSAGE_TEXT_AREA: '[data-region=\"send-message-txt\"]',\n        MORE_MESSAGES_LOADING_ICON_CONTAINER: '[data-region=\"more-messages-loading-icon-container\"]',\n        MUTED_ICON_CONTAINER: '[data-region=\"muted-icon-container\"]',\n        PLACEHOLDER_CONTAINER: '[data-region=\"placeholder-container\"]',\n        RETRY_SEND: '[data-region=\"retry-send\"]',\n        SELF_CONVERSATION_MESSAGE_CONTAINER: '[data-region=\"self-conversation-message-container\"]',\n        SEND_MESSAGE_BUTTON: '[data-action=\"send-message\"]',\n        SEND_MESSAGE_ICON_CONTAINER: '[data-region=\"send-icon-container\"]',\n        TEXT: '[data-region=\"text\"]',\n        TEXT_CONTAINER: '[data-region=\"text-container\"]',\n        TIME_CREATED: '[data-region=\"time-created\"]',\n        TITLE: '[data-region=\"title\"]'\n    };\n\n    var TEMPLATES = {\n        HEADER_PRIVATE: 'core_message/message_drawer_view_conversation_header_content_type_private',\n        HEADER_PRIVATE_NO_CONTROLS: 'core_message/message_drawer_view_conversation_header_content_type_private_no_controls',\n        HEADER_PUBLIC: 'core_message/message_drawer_view_conversation_header_content_type_public',\n        HEADER_SELF: 'core_message/message_drawer_view_conversation_header_content_type_self',\n        DAY: 'core_message/message_drawer_view_conversation_body_day',\n        MESSAGE: 'core_message/message_drawer_view_conversation_body_message',\n        MESSAGES: 'core_message/message_drawer_view_conversation_body_messages'\n    };\n\n    // Conversation types. They must have the same values defined in \\core_message\\api.\n    var CONVERSATION_TYPES = {\n        PRIVATE: 1,\n        PUBLIC: 2,\n        SELF: 3\n    };\n\n    return {\n        SELECTORS: SELECTORS,\n        TEMPLATES: TEMPLATES,\n        CONVERSATION_TYPES: CONVERSATION_TYPES,\n        NEWEST_MESSAGES_FIRST: true,\n        LOAD_MESSAGE_LIMIT: 100,\n        MILLISECONDS_IN_SEC: 1000\n    };\n});\n"],"file":"message_drawer_view_conversation_constants.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../src/message_drawer_view_conversation_constants.js"],"names":["define","SELECTORS","ACTION_ACCEPT_CONTACT_REQUEST","ACTION_CANCEL_CONFIRM","ACTION_OKAY_CONFIRM","ACTION_CANCEL_EDIT_MODE","ACTION_CONFIRM_ADD_CONTACT","ACTION_CONFIRM_BLOCK","ACTION_CONFIRM_DELETE_SELECTED_MESSAGES","ACTION_CONFIRM_DELETE_CONVERSATION","ACTION_CONFIRM_FAVOURITE","ACTION_CONFIRM_MUTE","ACTION_CONFIRM_UNFAVOURITE","ACTION_CONFIRM_REMOVE_CONTACT","ACTION_CONFIRM_UNBLOCK","ACTION_CONFIRM_UNMUTE","ACTION_DECLINE_CONTACT_REQUEST","ACTION_REQUEST_ADD_CONTACT","ACTION_REQUEST_BLOCK","ACTION_REQUEST_DELETE_CONVERSATION","ACTION_REQUEST_DELETE_SELECTED_MESSAGES","ACTION_REQUEST_REMOVE_CONTACT","ACTION_REQUEST_UNBLOCK","ACTION_VIEW_CONTACT","ACTION_VIEW_GROUP_INFO","CAN_RECEIVE_FOCUS","CONFIRM_DIALOGUE_BUTTON_TEXT","CONFIRM_DIALOGUE_CANCEL_BUTTON","CONFIRM_DIALOGUE_CONTAINER","CONFIRM_DIALOGUE_HEADER","CONFIRM_DIALOGUE_OKAY_BUTTON","CONFIRM_DIALOGUE_TEXT","CONTACT_REQUEST_SENT_MESSAGE_CONTAINER","CONTENT_PLACEHOLDER_CONTAINER","CONTENT_CONTAINER","CONTENT_MESSAGES_CONTAINER","CONTENT_MESSAGES_FOOTER_CONTAINER","CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER","CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER","CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER","CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER","DAY_MESSAGES_CONTAINER","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER","ERROR_MESSAGE_CONTAINER","ERROR_MESSAGE","FAVOURITE_ICON_CONTAINER","FOOTER_CONTAINER","HEADER","HEADER_EDIT_MODE","HEADER_PLACEHOLDER_CONTAINER","LOADING_ICON_CONTAINER","MESSAGE","MESSAGE_NOT_SELECTED","MESSAGE_NOT_SELECTED_ICON","MESSAGE_SELECTED_ICON","MESSAGES","MESSAGES_CONTAINER","MESSAGES_SELECTED_COUNT","MESSAGE_TEXT_AREA","MORE_MESSAGES_LOADING_ICON_CONTAINER","MUTED_ICON_CONTAINER","PLACEHOLDER_CONTAINER","RETRY_SEND","SELF_CONVERSATION_MESSAGE_CONTAINER","SEND_MESSAGE_BUTTON","SEND_MESSAGE_ICON_CONTAINER","TEXT","TEXT_CONTAINER","TIME_CREATED","TITLE","TEMPLATES","HEADER_PRIVATE","HEADER_PRIVATE_NO_CONTROLS","HEADER_PUBLIC","HEADER_SELF","DAY","CONVERSATION_TYPES","PRIVATE","PUBLIC","SELF","NEWEST_MESSAGES_FIRST","LOAD_MESSAGE_LIMIT","MILLISECONDS_IN_SEC"],"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 * Constant values for the conversation page in the message drawer.\n *\n * @module     core_message/message_drawer_view_conversation_constants\n * @copyright  2018 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n\n    var SELECTORS = {\n        ACTION_ACCEPT_CONTACT_REQUEST: '[data-action=\"accept-contact-request\"]',\n        ACTION_CANCEL_CONFIRM: '[data-action=\"cancel-confirm\"]',\n        ACTION_OKAY_CONFIRM: '[data-action=\"okay-confirm\"]',\n        ACTION_CANCEL_EDIT_MODE: '[data-action=\"cancel-edit-mode\"]',\n        ACTION_CONFIRM_ADD_CONTACT: '[data-action=\"confirm-add-contact\"]',\n        ACTION_CONFIRM_BLOCK: '[data-action=\"confirm-block\"]',\n        ACTION_CONFIRM_DELETE_SELECTED_MESSAGES: '[data-action=\"confirm-delete-selected-messages\"]',\n        ACTION_CONFIRM_DELETE_CONVERSATION: '[data-action=\"confirm-delete-conversation\"]',\n        ACTION_CONFIRM_FAVOURITE: '[data-action=\"confirm-favourite\"]',\n        ACTION_CONFIRM_MUTE: '[data-action=\"confirm-mute\"]',\n        ACTION_CONFIRM_UNFAVOURITE: '[data-action=\"confirm-unfavourite\"]',\n        ACTION_CONFIRM_REMOVE_CONTACT: '[data-action=\"confirm-remove-contact\"]',\n        ACTION_CONFIRM_UNBLOCK: '[data-action=\"confirm-unblock\"]',\n        ACTION_CONFIRM_UNMUTE: '[data-action=\"confirm-unmute\"]',\n        ACTION_DECLINE_CONTACT_REQUEST: '[data-action=\"decline-contact-request\"]',\n        ACTION_REQUEST_ADD_CONTACT: '[data-action=\"request-add-contact\"]',\n        ACTION_REQUEST_BLOCK: '[data-action=\"request-block\"]',\n        ACTION_REQUEST_DELETE_CONVERSATION: '[data-action=\"request-delete-conversation\"]',\n        ACTION_REQUEST_DELETE_SELECTED_MESSAGES: '[data-action=\"delete-selected-messages\"]',\n        ACTION_REQUEST_REMOVE_CONTACT: '[data-action=\"request-remove-contact\"]',\n        ACTION_REQUEST_UNBLOCK: '[data-action=\"request-unblock\"]',\n        ACTION_VIEW_CONTACT: '[data-action=\"view-contact\"]',\n        ACTION_VIEW_GROUP_INFO: '[data-action=\"view-group-info\"]',\n        CAN_RECEIVE_FOCUS: 'input:not([type=\"hidden\"]), a[href], button, textarea, select, [tabindex]',\n        CONFIRM_DIALOGUE_BUTTON_TEXT: '[data-region=\"dialogue-button-text\"]',\n        CONFIRM_DIALOGUE_CANCEL_BUTTON: '[data-action=\"cancel-confirm\"]',\n        CONFIRM_DIALOGUE_CONTAINER: '[data-region=\"confirm-dialogue-container\"]',\n        CONFIRM_DIALOGUE_HEADER: '[data-region=\"dialogue-header\"]',\n        CONFIRM_DIALOGUE_OKAY_BUTTON: '[data-action=\"okay-confirm\"]',\n        CONFIRM_DIALOGUE_TEXT: '[data-region=\"dialogue-text\"]',\n        CONTACT_REQUEST_SENT_MESSAGE_CONTAINER: '[data-region=\"contact-request-sent-message-container\"]',\n        CONTENT_PLACEHOLDER_CONTAINER: '[data-region=\"content-placeholder\"]',\n        CONTENT_CONTAINER: '[data-region=\"content-container\"]',\n        CONTENT_MESSAGES_CONTAINER: '[data-region=\"content-message-container\"]',\n        CONTENT_MESSAGES_FOOTER_CONTAINER: '[data-region=\"content-messages-footer-container\"]',\n        CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER: '[data-region=\"content-messages-footer-edit-mode-container\"]',\n        CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER: '[data-region=\"content-messages-footer-require-contact-container\"]',\n        CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER: '[data-region=\"content-messages-footer-require-unblock-container\"]',\n        CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER: '[data-region=\"content-messages-footer-unable-to-message\"]',\n        DAY_MESSAGES_CONTAINER: '[data-region=\"day-messages-container\"]',\n        DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE: '[data-region=\"delete-messages-for-all-users-toggle\"]',\n        DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER: '[data-region=\"delete-messages-for-all-users-toggle-container\"]',\n        ERROR_MESSAGE_CONTAINER: '[data-region=\"error-message-container\"]',\n        ERROR_MESSAGE: '[data-region=\"error-message\"]',\n        FAVOURITE_ICON_CONTAINER: '[data-region=\"favourite-icon-container\"]',\n        FOOTER_CONTAINER: '[data-region=\"content-messages-footer-container\"]',\n        HEADER: '[data-region=\"header-content\"]',\n        HEADER_EDIT_MODE: '[data-region=\"header-edit-mode\"]',\n        HEADER_PLACEHOLDER_CONTAINER: '[data-region=\"header-placeholder\"]',\n        LOADING_ICON_CONTAINER: '[data-region=\"loading-icon-container\"]',\n        MESSAGE: '[data-region=\"message\"]',\n        MESSAGE_NOT_SELECTED: '[data-region=\"message\"][aria-checked=\"false\"]',\n        MESSAGE_NOT_SELECTED_ICON: '[data-region=\"not-selected-icon\"]',\n        MESSAGE_SELECTED_ICON: '[data-region=\"selected-icon\"]',\n        MESSAGES: '[data-region=\"content-message-container\"]',\n        MESSAGES_CONTAINER: '[data-region=\"content-message-container\"]',\n        MESSAGES_SELECTED_COUNT: '[data-region=\"message-selected-court\"]',\n        MESSAGE_TEXT_AREA: '[data-region=\"send-message-txt\"]',\n        MORE_MESSAGES_LOADING_ICON_CONTAINER: '[data-region=\"more-messages-loading-icon-container\"]',\n        MUTED_ICON_CONTAINER: '[data-region=\"muted-icon-container\"]',\n        PLACEHOLDER_CONTAINER: '[data-region=\"placeholder-container\"]',\n        RETRY_SEND: '[data-region=\"retry-send\"]',\n        SELF_CONVERSATION_MESSAGE_CONTAINER: '[data-region=\"self-conversation-message-container\"]',\n        SEND_MESSAGE_BUTTON: '[data-action=\"send-message\"]',\n        SEND_MESSAGE_ICON_CONTAINER: '[data-region=\"send-icon-container\"]',\n        TEXT: '[data-region=\"text\"]',\n        TEXT_CONTAINER: '[data-region=\"text-container\"]',\n        TIME_CREATED: '[data-region=\"time-created\"]',\n        TITLE: '[data-region=\"title\"]'\n    };\n\n    var TEMPLATES = {\n        HEADER_PRIVATE: 'core_message/message_drawer_view_conversation_header_content_type_private',\n        HEADER_PRIVATE_NO_CONTROLS: 'core_message/message_drawer_view_conversation_header_content_type_private_no_controls',\n        HEADER_PUBLIC: 'core_message/message_drawer_view_conversation_header_content_type_public',\n        HEADER_SELF: 'core_message/message_drawer_view_conversation_header_content_type_self',\n        DAY: 'core_message/message_drawer_view_conversation_body_day',\n        MESSAGE: 'core_message/message_drawer_view_conversation_body_message',\n        MESSAGES: 'core_message/message_drawer_view_conversation_body_messages'\n    };\n\n    // Conversation types. They must have the same values defined in \\core_message\\api.\n    var CONVERSATION_TYPES = {\n        PRIVATE: 1,\n        PUBLIC: 2,\n        SELF: 3\n    };\n\n    return {\n        SELECTORS: SELECTORS,\n        TEMPLATES: TEMPLATES,\n        CONVERSATION_TYPES: CONVERSATION_TYPES,\n        NEWEST_MESSAGES_FIRST: true,\n        LOAD_MESSAGE_LIMIT: 100,\n        MILLISECONDS_IN_SEC: 1000\n    };\n});\n"],"file":"message_drawer_view_conversation_constants.min.js"}
\ No newline at end of file
diff --git a/message/amd/build/message_drawer_view_conversation_renderer.min.js b/message/amd/build/message_drawer_view_conversation_renderer.min.js
index b9d05dddb91..33f04aa9120 100644
--- a/message/amd/build/message_drawer_view_conversation_renderer.min.js
+++ b/message/amd/build/message_drawer_view_conversation_renderer.min.js
@@ -1,2 +1,2 @@
-define ("core_message/message_drawer_view_conversation_renderer",["jquery","core/notification","core/str","core/templates","core/user_date","core_message/message_drawer_view_conversation_constants"],function(a,b,c,d,e,f){var g=f.SELECTORS,h=f.TEMPLATES,i=f.CONVERSATION_TYPES,j=function(a){return a.find(g.CONTENT_MESSAGES_CONTAINER)},k=function(a){j(a).removeClass("hidden")},l=function(a){j(a).addClass("hidden")},m=function(a){return a.find(g.SELF_CONVERSATION_MESSAGE_CONTAINER)},n=function(a){return m(a).addClass("hidden")},o=function(a){return a.find(g.CONTACT_REQUEST_SENT_MESSAGE_CONTAINER)},p=function(a){return o(a).addClass("hidden")},q=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_CONTAINER)},r=function(a){q(a).removeClass("hidden")},s=function(a){q(a).addClass("hidden")},t=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER)},u=function(a){t(a).removeClass("hidden")},v=function(a){t(a).addClass("hidden")},w=function(a){return a.find(g.PLACEHOLDER_CONTAINER)},x=function(a){w(a).removeClass("hidden")},y=function(a){w(a).addClass("hidden")},z=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER)},A=function(a){z(a).removeClass("hidden")},B=function(a){z(a).addClass("hidden")},C=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER)},D=function(a){C(a).removeClass("hidden")},E=function(a){C(a).addClass("hidden")},F=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER)},G=function(a){F(a).removeClass("hidden")},H=function(a){F(a).addClass("hidden")},I=function(a){P(a);S(a);V(a)},J=function(a){s(a);v(a);y(a);B(a);E(a);H(a)},K=function(a){return a.find(g.CONTENT_PLACEHOLDER_CONTAINER)},L=function(a){K(a).removeClass("hidden")},M=function(a){K(a).addClass("hidden")},N=function(a){return a.find(g.HEADER)},O=function(a){N(a).removeClass("hidden")},P=function(a){N(a).addClass("hidden")},Q=function(a){return a.find(g.HEADER_EDIT_MODE)},R=function(a){Q(a).removeClass("hidden")},S=function(a){Q(a).addClass("hidden")},T=function(a){return a.find(g.HEADER_PLACEHOLDER_CONTAINER)},U=function(a){T(a).removeClass("hidden")},V=function(a){T(a).addClass("hidden")},W=function(a,b){var c=j(a);return c.find("[data-message-id=\""+b+"\"]")},X=function(a,b){var c=j(a);return c.find("[data-day-id=\""+b+"\"]")},Y=function(a){return a.find(g.MORE_MESSAGES_LOADING_ICON_CONTAINER)},Z=function(a){Y(a).removeClass("hidden")},$=function(a){Y(a).addClass("hidden")},_=function(a){return a.find(g.CONFIRM_DIALOGUE_CONTAINER)},aa=function(a){var b=_(a),c=b.siblings(":not(.hidden)");c.attr("aria-hidden",!0);c.attr("tabindex",-1);c.attr("data-confirm-dialogue-hidden",!0);b.removeClass("hidden")},ba=function(a){var b=_(a),c=b.siblings("[data-confirm-dialogue-hidden=\"true\"]");c.removeAttr("aria-hidden");c.removeAttr("tabindex");c.removeAttr("data-confirm-dialogue-hidden");b.addClass("hidden")},ca=function(a,b){Q(a).find(g.MESSAGES_SELECTED_COUNT).text(b)},da=function(a,b){return a.map(function(a){return{id:a.id,isread:a.isRead,fromloggedinuser:a.fromLoggedInUser,userfrom:a.userFrom,text:a.text,formattedtime:a.timeCreated?b[a.timeCreated]:null}})},ea=function(b,c,e,f,g){var i=j(c),k=f.map(function(a){return d.render(h.DAY,{timestamp:a.value.timestamp,messages:da(a.value.messages,g)})});return a.when.apply(a,k).then(function(){f.forEach(function(b,d){k[d].then(function(d){if(b.before){var e=X(c,b.before.timestamp);return a(d).insertBefore(e)}else{return i.append(d)}}).catch(function(){})})})},fa=function(b,c,e,f,i){var j=f.map(function(a){return a.value}),k=da(j,i);return d.render(h.MESSAGES,{messages:k}).then(function(b){var d=a(b);f.forEach(function(a){var b=d.find("[data-message-id=\""+a.value.id+"\"]");if(a.before){var e=W(c,a.before.id);return b.insertBefore(e)}else{var f=X(c,a.day.timestamp),h=f.find(g.DAY_MESSAGES_CONTAINER);return h.append(b)}})})},ga=function(a,b,c,d,e){d.forEach(function(a){var c=a.before,d=a.after,f=W(b,c.id);if(c.id!=d.id){f.attr("data-message-id",d.id)}if(c.timeCreated!=d.timeCreated){var h=e[d.timeCreated];f.find(g.LOADING_ICON_CONTAINER).addClass("hidden");f.find(g.TIME_CREATED).text(h).removeClass("hidden")}if(c.sendState!=d.sendState){var i=f.find(g.LOADING_ICON_CONTAINER),j=f.find(g.TIME_CREATED),k=f.find(g.RETRY_SEND);i.addClass("hidden");i.attr("aria-hidden","true");j.addClass("hidden");j.attr("aria-hidden","true");k.addClass("hidden");k.attr("aria-hidden","true");f.removeClass("border border-danger");switch(d.sendState){case"pending":i.removeClass("hidden");i.attr("aria-hidden","false");break;case"error":k.removeClass("hidden");k.attr("aria-hidden","false");f.addClass("border border-danger");break;case"sent":j.removeClass("hidden");j.attr("aria-hidden","false");break;}}if(c.text!=d.text){f.find(g.TEXT_CONTAINER).html(d.text)}if(c.errorMessage!=d.errorMessage){var l=f.find(g.ERROR_MESSAGE_CONTAINER),a=l.find(g.ERROR_MESSAGE);if(d.errorMessage){l.removeClass("hidden");l.attr("aria-hidden","false");a.text(d.errorMessage)}else{l.addClass("hidden");l.attr("aria-hidden","true");a.text("")}}})},ha=function(a,b){b.forEach(function(b){X(a,b.timestamp).remove()})},ia=function(a,b){b.forEach(function(b){W(a,b.id).remove()})},ja=function(b,d,f,g){var h=[],i=0<g.days.add.length,j=0<g.messages.add.length,k=0<g.messages.update.length,l=[],m=a.Deferred().resolve({}).promise();if(i){l=l.concat(g.days.add.reduce(function(a,b){return a.concat(b.value.messages.reduce(function(a,b){if(b.timeCreated){a.push(b.timeCreated)}return a},[]))},[]))}if(j){l=l.concat(g.messages.add.reduce(function(a,b){if(b.value.timeCreated){a.push(b.value.timeCreated)}return a},[]))}if(k){l=l.concat(g.messages.update.reduce(function(a,b){if(b.before.timeCreated!=b.after.timeCreated){a.push(b.after.timeCreated)}return a},[]))}if(l.length){m=c.get_string("strftimetime24","core_langconfig").then(function(a){var b=l.map(function(b){return{timestamp:b,format:a}});return e.get(b)}).then(function(a){return l.reduce(function(b,c,d){b[c]=a[d];return b},{})})}if(i){h.push(m.then(function(a){return ea(b,d,f,g.days.add,a)}))}if(j){h.push(m.then(function(a){return fa(b,d,f,g.messages.add,a)}))}if(k){h.push(m.then(function(a){return ga(b,d,f,g.messages.update,a)}))}if(0<g.days.remove.length){ha(d,g.days.remove)}if(0<g.messages.remove.length){ia(d,g.messages.remove)}return a.when.apply(a,h)},ka=function(a,b,c,e){var f=N(a),g=h.HEADER_PUBLIC;e.context.showrouteback="false"===a.attr("data-from-panel");if(e.type==i.PRIVATE){g=e.showControls?h.HEADER_PRIVATE:h.HEADER_PRIVATE_NO_CONTROLS}else if(e.type==i.SELF){g=h.HEADER_SELF}return d.render(g,e.context).then(function(a,b){d.replaceNodeContents(f,a,b)})},la=function(a,b,d,e){J(d);switch(e.type){case"placeholder":return x(d);case"add-contact":return c.get_strings([{key:"requirecontacttomessage",component:"core_message",param:e.user.fullname},{key:"isnotinyourcontacts",component:"core_message",param:e.user.fullname}]).then(function(a){var b=a[1],c=a[0],e=z(d);e.find(g.TITLE).text(b);e.find(g.TEXT).text(c);A(d);return a});case"edit-mode":return u(d);case"content":return r(d);case"unblock":return D(d);case"unable-to-message":return G(d);}return!0},ma=function(a,b,c,d){var e=j(b),f=W(b,d),g=f.position();if(g){var h=e.scrollTop()+g.top;e.scrollTop(h)}},na=function(a,b,c,d){if(d){P(a);U(a)}else{O(a);V(a)}},oa=function(a,b,c,d){if(d){l(b);L(b)}else{k(b);M(b)}},pa=function(a,b,c,d){if(d){Z(b)}else{$(b)}},qa=function(a,b,c,d,e,f,h,i){var j=_(b),k=d.map(function(a){return j.find(a)}),l=j.find(g.CONFIRM_DIALOGUE_CANCEL_BUTTON),m=j.find(g.CONFIRM_DIALOGUE_TEXT),n=j.find(g.CONFIRM_DIALOGUE_HEADER);j.find("button").addClass("hidden");if(h){l.removeClass("hidden")}else{l.addClass("hidden")}if(f){n.removeClass("hidden");n.text(f)}else{n.addClass("hidden");n.text("")}k.forEach(function(a){a.removeClass("hidden")});m.text(e);aa(c);aa(b);if(!i){aa(a)}j.find(g.CAN_RECEIVE_FOCUS).filter(":visible").first().focus()},ra=function(a,b,c){var d=_(b),e=d.find(g.CONFIRM_DIALOGUE_CANCEL_BUTTON),f=d.find(g.CONFIRM_DIALOGUE_TEXT),h=d.find(g.CONFIRM_DIALOGUE_HEADER);Aa(b);ba(b);ba(c);ba(a);d.find("button").addClass("hidden");e.removeClass("hidden");f.text("");h.addClass("hidden");h.text("");a.find(g.CAN_RECEIVE_FOCUS).first().focus();return!0},sa=function(a,b,d,e){if(e){if(e.canmessageevenifblocked){return c.get_string("cantblockuser","core_message",e.fullname).then(function(c){return qa(a,b,d,[],c,"",!0,!1)})}else{return c.get_string("blockuserconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_BLOCK],c,"",!0,!1)})}}else{return ra(a,b,d)}},ta=function(a,b,d,e){if(e){return c.get_string("unblockuserconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_UNBLOCK],c,"",!0,!1)})}else{return ra(a,b,d)}},ua=function(a,b,d,e){if(e){return c.get_string("addcontactconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_ADD_CONTACT],c,"",!0,!1)})}else{return ra(a,b,d)}},va=function(a,b,d,e){if(e){return c.get_string("removecontactconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_REMOVE_CONTACT],c,"",!0,!1)})}else{return ra(a,b,d)}},wa=function(a,b,d,e){var f=null;if(e.type==i.SELF){f="deleteselectedmessagesconfirmselfconversation"}else{if(e.canDeleteMessagesForAllUsers){za(b);f="deleteforeveryoneselectedmessagesconfirm"}else{f="deleteselectedmessagesconfirm"}}if(e.show){return c.get_string(f,"core_message").then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES],c,"",!0,!1)})}else{return ra(a,b,d)}},xa=function(a,b,d,e){var f=null;if(e==i.SELF){f="deleteallselfconfirm"}else if(e){f="deleteallconfirm"}if(f){return c.get_string(f,"core_message").then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_DELETE_CONVERSATION],c,"",!0,!1)})}else{return ra(a,b,d)}},ya=function(a,b,d,e){if(e){return c.get_string("userwouldliketocontactyou","core_message",e.fullname).then(function(c){var e=[g.ACTION_ACCEPT_CONTACT_REQUEST,g.ACTION_DECLINE_CONTACT_REQUEST];return qa(a,b,d,e,c,"",!1,!0)})}else{return ra(a,b,d)}},za=function(a){var b=_(a),c=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);c.removeClass("hidden")},Aa=function(a){var b=_(a),c=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER),d=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE);d.prop("checked",!1);c.addClass("hidden")},Ba=function(a,b,c,d){if(d){a.find(g.ACTION_REQUEST_BLOCK).addClass("hidden");a.find(g.ACTION_REQUEST_UNBLOCK).removeClass("hidden")}else{a.find(g.ACTION_REQUEST_BLOCK).removeClass("hidden");a.find(g.ACTION_REQUEST_UNBLOCK).addClass("hidden")}},Ca=function(a,b,c,d){var e=a.find(g.FAVOURITE_ICON_CONTAINER),f=a.find(g.ACTION_CONFIRM_FAVOURITE),h=a.find(g.ACTION_CONFIRM_UNFAVOURITE);switch(d){case"hide":e.addClass("hidden");f.addClass("hidden");h.addClass("hidden");break;case"show-add":e.addClass("hidden");f.removeClass("hidden");h.addClass("hidden");break;case"show-remove":e.removeClass("hidden");f.addClass("hidden");h.removeClass("hidden");break;}},Da=function(a,b,c,d){var e=a.find(g.MUTED_ICON_CONTAINER),f=a.find(g.ACTION_CONFIRM_MUTE),h=a.find(g.ACTION_CONFIRM_UNMUTE);switch(d){case"hide":e.addClass("hidden");f.addClass("hidden");h.addClass("hidden");break;case"show-mute":e.addClass("hidden");f.removeClass("hidden");h.addClass("hidden");break;case"show-unmute":e.removeClass("hidden");f.addClass("hidden");h.removeClass("hidden");break;}},Ea=function(a,b,c,d){var e=a.find(g.ACTION_REQUEST_ADD_CONTACT),f=a.find(g.ACTION_REQUEST_REMOVE_CONTACT);switch(d){case"pending-contact":e.addClass("hidden");f.addClass("hidden");break;case"contact":e.addClass("hidden");f.removeClass("hidden");break;case"non-contact":e.removeClass("hidden");f.addClass("hidden");break;}},Fa=function(a,b,c,d){var e=_(b),f=e.find("button"),h=e.find(g.CONFIRM_DIALOGUE_BUTTON_TEXT),i=e.find(g.LOADING_ICON_CONTAINER);if(d){f.prop("disabled",!0);h.addClass("hidden");i.removeClass("hidden")}else{f.prop("disabled",!1);h.removeClass("hidden");i.addClass("hidden")}},Ga=function(a,b,c,d){var e=null;if(d){e=b.find(g.MESSAGE_NOT_SELECTED);e.find(g.MESSAGE_NOT_SELECTED_ICON).removeClass("hidden");P(a);R(a)}else{e=j(b);e.find(g.MESSAGE_NOT_SELECTED_ICON).addClass("hidden");e.find(g.MESSAGE_SELECTED_ICON).addClass("hidden");O(a);S(a)}},Ha=function(a,b,c,d){var e=0<d.count;if(d.add.length){d.add.forEach(function(a){var c=W(b,a);c.find(g.MESSAGE_NOT_SELECTED_ICON).addClass("hidden");c.find(g.MESSAGE_SELECTED_ICON).removeClass("hidden");c.attr("aria-checked",!0)})}if(d.remove.length){d.remove.forEach(function(a){var c=W(b,a);if(e){c.find(g.MESSAGE_NOT_SELECTED_ICON).removeClass("hidden")}c.find(g.MESSAGE_SELECTED_ICON).addClass("hidden");c.attr("aria-checked",!1)})}ca(a,d.count)},Ia=function(a,b,d,e){if(e.show&&!e.hasMessages){return c.get_strings([{key:"requirecontacttomessage",component:"core_message",param:e.user.fullname},{key:"isnotinyourcontacts",component:"core_message",param:e.user.fullname}]).then(function(c){var e=c[1],f=c[0];return qa(a,b,d,[g.ACTION_REQUEST_ADD_CONTACT],f,e,!1,!0)})}else{return ra(a,b,d)}},Ja=function(a,b,c,d){var e=m(b);if(d){e.removeClass("hidden")}else{e.addClass("hidden")}return!0},Ka=function(a,b,d,e){var f=o(b);if(e){return c.get_string("yourcontactrequestpending","core_message",e).then(function(a){f.find(g.TEXT).text(a);f.removeClass("hidden");return a})}else{f.addClass("hidden");return!0}},La=function(a,b,c){ra(a,b,c);p(b);n(b);I(a);U(a);J(c);x(c);return!0};return{render:function render(c,d,e,f){var g=[{reset:La},{conversation:ja,header:ka,footer:la,confirmBlockUser:sa,confirmUnblockUser:ta,confirmAddContact:ua,confirmRemoveContact:va,confirmDeleteSelectedMessages:wa,confirmDeleteConversation:xa,confirmContactRequest:ya,requireAddContact:Ia,selfConversationMessage:Ja,contactRequestSent:Ka},{loadingMembers:na,loadingFirstMessages:oa,loadingMessages:pa,isBlocked:Ba,isContact:Ea,isFavourite:Ca,isMuted:Da,loadingConfirmAction:Fa,inEditMode:Ga},{scrollToMessage:ma,selectedMessages:Ha}],h=function(a){var b=[];for(var g in f){if(a.hasOwnProperty(g)){var h=a[g],i=f[g];b.push(h(c,d,e,i))}}return b},i=h(g[0]);i=i.concat(h(g[1]));return a.when.apply(a,i).then(function(){for(var a=2;a<g.length;a++){h(g[a])}}).catch(b.exception)}}});
+define ("core_message/message_drawer_view_conversation_renderer",["jquery","core/notification","core/str","core/templates","core/user_date","core_message/message_drawer_view_conversation_constants"],function(a,b,c,d,e,f){var g=f.SELECTORS,h=f.TEMPLATES,i=f.CONVERSATION_TYPES,j=function(a){return a.find(g.CONTENT_MESSAGES_CONTAINER)},k=function(a){j(a).removeClass("hidden")},l=function(a){j(a).addClass("hidden")},m=function(a){return a.find(g.SELF_CONVERSATION_MESSAGE_CONTAINER)},n=function(a){return m(a).addClass("hidden")},o=function(a){return a.find(g.CONTACT_REQUEST_SENT_MESSAGE_CONTAINER)},p=function(a){return o(a).addClass("hidden")},q=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_CONTAINER)},r=function(a){q(a).removeClass("hidden")},s=function(a){q(a).addClass("hidden")},t=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER)},u=function(a){t(a).removeClass("hidden")},v=function(a){t(a).addClass("hidden")},w=function(a){return a.find(g.PLACEHOLDER_CONTAINER)},x=function(a){w(a).removeClass("hidden")},y=function(a){w(a).addClass("hidden")},z=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER)},A=function(a){z(a).removeClass("hidden")},B=function(a){z(a).addClass("hidden")},C=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER)},D=function(a){C(a).removeClass("hidden")},E=function(a){C(a).addClass("hidden")},F=function(a){return a.find(g.CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER)},G=function(a){F(a).removeClass("hidden")},H=function(a){F(a).addClass("hidden")},I=function(a){P(a);S(a);V(a)},J=function(a){s(a);v(a);y(a);B(a);E(a);H(a)},K=function(a){return a.find(g.CONTENT_PLACEHOLDER_CONTAINER)},L=function(a){K(a).removeClass("hidden")},M=function(a){K(a).addClass("hidden")},N=function(a){return a.find(g.HEADER)},O=function(a){N(a).removeClass("hidden")},P=function(a){N(a).addClass("hidden")},Q=function(a){return a.find(g.HEADER_EDIT_MODE)},R=function(a){Q(a).removeClass("hidden")},S=function(a){Q(a).addClass("hidden")},T=function(a){return a.find(g.HEADER_PLACEHOLDER_CONTAINER)},U=function(a){T(a).removeClass("hidden")},V=function(a){T(a).addClass("hidden")},W=function(a,b){var c=j(a);return c.find("[data-message-id=\""+b+"\"]")},X=function(a,b){var c=j(a);return c.find("[data-day-id=\""+b+"\"]")},Y=function(a){return a.find(g.MORE_MESSAGES_LOADING_ICON_CONTAINER)},Z=function(a){Y(a).removeClass("hidden")},$=function(a){Y(a).addClass("hidden")},_=function(a){return a.find(g.CONFIRM_DIALOGUE_CONTAINER)},aa=function(a){var b=_(a),c=b.siblings(":not(.hidden)");c.attr("aria-hidden",!0);c.attr("tabindex",-1);c.attr("data-confirm-dialogue-hidden",!0);b.removeClass("hidden")},ba=function(a){var b=_(a),c=b.siblings("[data-confirm-dialogue-hidden=\"true\"]");c.removeAttr("aria-hidden");c.removeAttr("tabindex");c.removeAttr("data-confirm-dialogue-hidden");b.addClass("hidden")},ca=function(a,b){Q(a).find(g.MESSAGES_SELECTED_COUNT).text(b)},da=function(a,b){return a.map(function(a){return{id:a.id,isread:a.isRead,fromloggedinuser:a.fromLoggedInUser,userfrom:a.userFrom,text:a.text,formattedtime:a.timeCreated?b[a.timeCreated]:null}})},ea=function(b,c,e,f,g){var i=j(c),k=f.map(function(a){return d.render(h.DAY,{timestamp:a.value.timestamp,messages:da(a.value.messages,g)})});return a.when.apply(a,k).then(function(){f.forEach(function(b,d){k[d].then(function(d){if(b.before){var e=X(c,b.before.timestamp);return a(d).insertBefore(e)}else{return i.append(d)}}).catch(function(){})})})},fa=function(b,c,e,f,i){var j=f.map(function(a){return a.value}),k=da(j,i);return d.render(h.MESSAGES,{messages:k}).then(function(b){var d=a(b);f.forEach(function(a){var b=d.find("[data-message-id=\""+a.value.id+"\"]");if(a.before){var e=W(c,a.before.id);return b.insertBefore(e)}else{var f=X(c,a.day.timestamp),h=f.find(g.DAY_MESSAGES_CONTAINER);return h.append(b)}})})},ga=function(a,b,c,d,e){d.forEach(function(a){var c=a.before,d=a.after,f=W(b,c.id);if(c.id!=d.id){f.attr("data-message-id",d.id)}if(c.timeCreated!=d.timeCreated){var h=e[d.timeCreated];f.find(g.LOADING_ICON_CONTAINER).addClass("hidden");f.find(g.TIME_CREATED).text(h).removeClass("hidden")}if(c.sendState!=d.sendState){var i=f.find(g.LOADING_ICON_CONTAINER),j=f.find(g.TIME_CREATED),k=f.find(g.RETRY_SEND);i.addClass("hidden");i.attr("aria-hidden","true");j.addClass("hidden");j.attr("aria-hidden","true");k.addClass("hidden");k.attr("aria-hidden","true");f.removeClass("border border-danger");switch(d.sendState){case"pending":i.removeClass("hidden");i.attr("aria-hidden","false");break;case"error":k.removeClass("hidden");k.attr("aria-hidden","false");f.addClass("border border-danger");break;case"sent":j.removeClass("hidden");j.attr("aria-hidden","false");break;}}if(c.text!=d.text){f.find(g.TEXT_CONTAINER).html(d.text)}if(c.errorMessage!=d.errorMessage){var l=f.find(g.ERROR_MESSAGE_CONTAINER),a=l.find(g.ERROR_MESSAGE);if(d.errorMessage){l.removeClass("hidden");l.attr("aria-hidden","false");a.text(d.errorMessage)}else{l.addClass("hidden");l.attr("aria-hidden","true");a.text("")}}})},ha=function(a,b){b.forEach(function(b){X(a,b.timestamp).remove()})},ia=function(a,b){b.forEach(function(b){W(a,b.id).remove()})},ja=function(b,d,f,g){var h=[],i=0<g.days.add.length,j=0<g.messages.add.length,k=0<g.messages.update.length,l=[],m=a.Deferred().resolve({}).promise();if(i){l=l.concat(g.days.add.reduce(function(a,b){return a.concat(b.value.messages.reduce(function(a,b){if(b.timeCreated){a.push(b.timeCreated)}return a},[]))},[]))}if(j){l=l.concat(g.messages.add.reduce(function(a,b){if(b.value.timeCreated){a.push(b.value.timeCreated)}return a},[]))}if(k){l=l.concat(g.messages.update.reduce(function(a,b){if(b.before.timeCreated!=b.after.timeCreated){a.push(b.after.timeCreated)}return a},[]))}if(l.length){m=c.get_string("strftimetime24","core_langconfig").then(function(a){var b=l.map(function(b){return{timestamp:b,format:a}});return e.get(b)}).then(function(a){return l.reduce(function(b,c,d){b[c]=a[d];return b},{})})}if(i){h.push(m.then(function(a){return ea(b,d,f,g.days.add,a)}))}if(j){h.push(m.then(function(a){return fa(b,d,f,g.messages.add,a)}))}if(k){h.push(m.then(function(a){return ga(b,d,f,g.messages.update,a)}))}if(0<g.days.remove.length){ha(d,g.days.remove)}if(0<g.messages.remove.length){ia(d,g.messages.remove)}return a.when.apply(a,h)},ka=function(a,b,c,e){var f=N(a),g=h.HEADER_PUBLIC;e.context.showrouteback="false"===a.attr("data-from-panel");if(e.type==i.PRIVATE){g=e.showControls?h.HEADER_PRIVATE:h.HEADER_PRIVATE_NO_CONTROLS}else if(e.type==i.SELF){g=h.HEADER_SELF}return d.render(g,e.context).then(function(a,b){d.replaceNodeContents(f,a,b)})},la=function(a,b,d,e){J(d);switch(e.type){case"placeholder":return x(d);case"add-contact":return c.get_strings([{key:"requirecontacttomessage",component:"core_message",param:e.user.fullname},{key:"isnotinyourcontacts",component:"core_message",param:e.user.fullname}]).then(function(a){var b=a[1],c=a[0],e=z(d);e.find(g.TITLE).text(b);e.find(g.TEXT).text(c);A(d);return a});case"edit-mode":return u(d);case"content":return r(d);case"unblock":return D(d);case"unable-to-message":return G(d);}return!0},ma=function(a,b,c,d){var e=j(b),f=W(b,d),g=f.position();if(g){var h=e.scrollTop()+g.top;e.scrollTop(h)}},na=function(a,b,c,d){if(d){P(a);U(a)}else{O(a);V(a)}},oa=function(a,b,c,d){if(d){l(b);L(b)}else{k(b);M(b)}},pa=function(a,b,c,d){if(d){Z(b)}else{$(b)}},qa=function(a,b,c,d,e,f,h,i,j){var k=_(b),l=d.map(function(a){return k.find(a)}),m=k.find(g.CONFIRM_DIALOGUE_CANCEL_BUTTON),n=k.find(g.CONFIRM_DIALOGUE_OKAY_BUTTON),o=k.find(g.CONFIRM_DIALOGUE_TEXT),p=k.find(g.CONFIRM_DIALOGUE_HEADER);k.find("button").addClass("hidden");if(h){m.removeClass("hidden")}else{m.addClass("hidden")}if(j){n.removeClass("hidden")}else{n.addClass("hidden")}if(f){p.removeClass("hidden");p.text(f)}else{p.addClass("hidden");p.text("")}l.forEach(function(a){a.removeClass("hidden")});o.text(e);aa(c);aa(b);if(!i){aa(a)}k.find(g.CAN_RECEIVE_FOCUS).filter(":visible").first().focus()},ra=function(a,b,c){var d=_(b),e=d.find(g.CONFIRM_DIALOGUE_CANCEL_BUTTON),f=d.find(g.CONFIRM_DIALOGUE_OKAY_BUTTON),h=d.find(g.CONFIRM_DIALOGUE_TEXT),i=d.find(g.CONFIRM_DIALOGUE_HEADER);Aa(b);ba(b);ba(c);ba(a);d.find("button").addClass("hidden");e.removeClass("hidden");f.removeClass("hidden");h.text("");i.addClass("hidden");i.text("");a.find(g.CAN_RECEIVE_FOCUS).first().focus();return!0},sa=function(a,b,d,e){if(e){if(e.canmessageevenifblocked){return c.get_string("cantblockuser","core_message",e.fullname).then(function(c){return qa(a,b,d,[],c,"",!1,!1,!0)})}else{return c.get_string("blockuserconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_BLOCK],c,"",!0,!1)})}}else{return ra(a,b,d)}},ta=function(a,b,d,e){if(e){return c.get_string("unblockuserconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_UNBLOCK],c,"",!0,!1)})}else{return ra(a,b,d)}},ua=function(a,b,d,e){if(e){return c.get_string("addcontactconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_ADD_CONTACT],c,"",!0,!1)})}else{return ra(a,b,d)}},va=function(a,b,d,e){if(e){return c.get_string("removecontactconfirm","core_message",e.fullname).then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_REMOVE_CONTACT],c,"",!0,!1)})}else{return ra(a,b,d)}},wa=function(a,b,d,e){var f=null;if(e.type==i.SELF){f="deleteselectedmessagesconfirmselfconversation"}else{if(e.canDeleteMessagesForAllUsers){za(b);f="deleteforeveryoneselectedmessagesconfirm"}else{f="deleteselectedmessagesconfirm"}}if(e.show){return c.get_string(f,"core_message").then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES],c,"",!0,!1)})}else{return ra(a,b,d)}},xa=function(a,b,d,e){var f=null;if(e==i.SELF){f="deleteallselfconfirm"}else if(e){f="deleteallconfirm"}if(f){return c.get_string(f,"core_message").then(function(c){return qa(a,b,d,[g.ACTION_CONFIRM_DELETE_CONVERSATION],c,"",!0,!1)})}else{return ra(a,b,d)}},ya=function(a,b,d,e){if(e){return c.get_string("userwouldliketocontactyou","core_message",e.fullname).then(function(c){var e=[g.ACTION_ACCEPT_CONTACT_REQUEST,g.ACTION_DECLINE_CONTACT_REQUEST];return qa(a,b,d,e,c,"",!1,!0)})}else{return ra(a,b,d)}},za=function(a){var b=_(a),c=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);c.removeClass("hidden")},Aa=function(a){var b=_(a),c=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER),d=b.find(g.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE);d.prop("checked",!1);c.addClass("hidden")},Ba=function(a,b,c,d){if(d){a.find(g.ACTION_REQUEST_BLOCK).addClass("hidden");a.find(g.ACTION_REQUEST_UNBLOCK).removeClass("hidden")}else{a.find(g.ACTION_REQUEST_BLOCK).removeClass("hidden");a.find(g.ACTION_REQUEST_UNBLOCK).addClass("hidden")}},Ca=function(a,b,c,d){var e=a.find(g.FAVOURITE_ICON_CONTAINER),f=a.find(g.ACTION_CONFIRM_FAVOURITE),h=a.find(g.ACTION_CONFIRM_UNFAVOURITE);switch(d){case"hide":e.addClass("hidden");f.addClass("hidden");h.addClass("hidden");break;case"show-add":e.addClass("hidden");f.removeClass("hidden");h.addClass("hidden");break;case"show-remove":e.removeClass("hidden");f.addClass("hidden");h.removeClass("hidden");break;}},Da=function(a,b,c,d){var e=a.find(g.MUTED_ICON_CONTAINER),f=a.find(g.ACTION_CONFIRM_MUTE),h=a.find(g.ACTION_CONFIRM_UNMUTE);switch(d){case"hide":e.addClass("hidden");f.addClass("hidden");h.addClass("hidden");break;case"show-mute":e.addClass("hidden");f.removeClass("hidden");h.addClass("hidden");break;case"show-unmute":e.removeClass("hidden");f.addClass("hidden");h.removeClass("hidden");break;}},Ea=function(a,b,c,d){var e=a.find(g.ACTION_REQUEST_ADD_CONTACT),f=a.find(g.ACTION_REQUEST_REMOVE_CONTACT);switch(d){case"pending-contact":e.addClass("hidden");f.addClass("hidden");break;case"contact":e.addClass("hidden");f.removeClass("hidden");break;case"non-contact":e.removeClass("hidden");f.addClass("hidden");break;}},Fa=function(a,b,c,d){var e=_(b),f=e.find("button"),h=e.find(g.CONFIRM_DIALOGUE_BUTTON_TEXT),i=e.find(g.LOADING_ICON_CONTAINER);if(d){f.prop("disabled",!0);h.addClass("hidden");i.removeClass("hidden")}else{f.prop("disabled",!1);h.removeClass("hidden");i.addClass("hidden")}},Ga=function(a,b,c,d){var e=null;if(d){e=b.find(g.MESSAGE_NOT_SELECTED);e.find(g.MESSAGE_NOT_SELECTED_ICON).removeClass("hidden");P(a);R(a)}else{e=j(b);e.find(g.MESSAGE_NOT_SELECTED_ICON).addClass("hidden");e.find(g.MESSAGE_SELECTED_ICON).addClass("hidden");O(a);S(a)}},Ha=function(a,b,c,d){var e=0<d.count;if(d.add.length){d.add.forEach(function(a){var c=W(b,a);c.find(g.MESSAGE_NOT_SELECTED_ICON).addClass("hidden");c.find(g.MESSAGE_SELECTED_ICON).removeClass("hidden");c.attr("aria-checked",!0)})}if(d.remove.length){d.remove.forEach(function(a){var c=W(b,a);if(e){c.find(g.MESSAGE_NOT_SELECTED_ICON).removeClass("hidden")}c.find(g.MESSAGE_SELECTED_ICON).addClass("hidden");c.attr("aria-checked",!1)})}ca(a,d.count)},Ia=function(a,b,d,e){if(e.show&&!e.hasMessages){return c.get_strings([{key:"requirecontacttomessage",component:"core_message",param:e.user.fullname},{key:"isnotinyourcontacts",component:"core_message",param:e.user.fullname}]).then(function(c){var e=c[1],f=c[0];return qa(a,b,d,[g.ACTION_REQUEST_ADD_CONTACT],f,e,!1,!0)})}else{return ra(a,b,d)}},Ja=function(a,b,c,d){var e=m(b);if(d){e.removeClass("hidden")}else{e.addClass("hidden")}return!0},Ka=function(a,b,d,e){var f=o(b);if(e){return c.get_string("yourcontactrequestpending","core_message",e).then(function(a){f.find(g.TEXT).text(a);f.removeClass("hidden");return a})}else{f.addClass("hidden");return!0}},La=function(a,b,c){ra(a,b,c);p(b);n(b);I(a);U(a);J(c);x(c);return!0};return{render:function render(c,d,e,f){var g=[{reset:La},{conversation:ja,header:ka,footer:la,confirmBlockUser:sa,confirmUnblockUser:ta,confirmAddContact:ua,confirmRemoveContact:va,confirmDeleteSelectedMessages:wa,confirmDeleteConversation:xa,confirmContactRequest:ya,requireAddContact:Ia,selfConversationMessage:Ja,contactRequestSent:Ka},{loadingMembers:na,loadingFirstMessages:oa,loadingMessages:pa,isBlocked:Ba,isContact:Ea,isFavourite:Ca,isMuted:Da,loadingConfirmAction:Fa,inEditMode:Ga},{scrollToMessage:ma,selectedMessages:Ha}],h=function(a){var b=[];for(var g in f){if(a.hasOwnProperty(g)){var h=a[g],i=f[g];b.push(h(c,d,e,i))}}return b},i=h(g[0]);i=i.concat(h(g[1]));return a.when.apply(a,i).then(function(){for(var a=2;a<g.length;a++){h(g[a])}}).catch(b.exception)}}});
 //# sourceMappingURL=message_drawer_view_conversation_renderer.min.js.map
diff --git a/message/amd/build/message_drawer_view_conversation_renderer.min.js.map b/message/amd/build/message_drawer_view_conversation_renderer.min.js.map
index e1744691539..e32f25ceb42 100644
--- a/message/amd/build/message_drawer_view_conversation_renderer.min.js.map
+++ b/message/amd/build/message_drawer_view_conversation_renderer.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/message_drawer_view_conversation_renderer.js"],"names":["define","$","Notification","Str","Templates","UserDate","Constants","SELECTORS","TEMPLATES","CONVERSATION_TYPES","getMessagesContainer","body","find","CONTENT_MESSAGES_CONTAINER","showMessagesContainer","removeClass","hideMessagesContainer","addClass","getSelfConversationMessageContainer","SELF_CONVERSATION_MESSAGE_CONTAINER","hideSelfConversationMessageContainer","getContactRequestSentContainer","CONTACT_REQUEST_SENT_MESSAGE_CONTAINER","hideContactRequestSentContainer","getFooterContentContainer","footer","CONTENT_MESSAGES_FOOTER_CONTAINER","showFooterContent","hideFooterContent","getFooterEditModeContainer","CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER","showFooterEditMode","hideFooterEditMode","getFooterPlaceholderContainer","PLACEHOLDER_CONTAINER","showFooterPlaceholder","hideFooterPlaceholder","getFooterRequireContactContainer","CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER","showFooterRequireContact","hideFooterRequireContact","getFooterRequireUnblockContainer","CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER","showFooterRequireUnblock","hideFooterRequireUnblock","getFooterUnableToMessageContainer","CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER","showFooterUnableToMessage","hideFooterUnableToMessage","hideAllHeaderElements","header","hideHeaderContent","hideHeaderEditMode","hideHeaderPlaceholder","hideAllFooterElements","getContentPlaceholderContainer","CONTENT_PLACEHOLDER_CONTAINER","showContentPlaceholder","hideContentPlaceholder","getHeaderContent","HEADER","showHeaderContent","getHeaderEditMode","HEADER_EDIT_MODE","showHeaderEditMode","getHeaderPlaceholderContainer","HEADER_PLACEHOLDER_CONTAINER","showHeaderPlaceholder","getMessageElement","messageId","messagesContainer","getDayElement","dayTimeCreated","getMoreMessagesLoadingIconContainer","MORE_MESSAGES_LOADING_ICON_CONTAINER","showMoreMessagesLoadingIcon","hideMoreMessagesLoadingIcon","getConfirmDialogueContainer","root","CONFIRM_DIALOGUE_CONTAINER","showConfirmDialogueContainer","container","siblings","attr","hideConfirmDialogueContainer","removeAttr","setMessagesSelectedCount","value","MESSAGES_SELECTED_COUNT","text","formatMessagesForTemplate","messages","datesCache","map","message","id","isread","isRead","fromloggedinuser","fromLoggedInUser","userfrom","userFrom","formattedtime","timeCreated","renderAddDays","days","daysRenderPromises","data","render","DAY","timestamp","when","apply","then","forEach","index","html","before","element","insertBefore","append","catch","renderAddMessages","messagesData","formattedMessages","MESSAGES","messageList","messageHtml","dayContainer","day","dayMessagesContainer","DAY_MESSAGES_CONTAINER","renderUpdateMessages","after","formattedTime","LOADING_ICON_CONTAINER","TIME_CREATED","sendState","loading","time","retry","RETRY_SEND","TEXT_CONTAINER","errorMessage","messageContainer","ERROR_MESSAGE_CONTAINER","ERROR_MESSAGE","renderRemoveDays","remove","renderRemoveMessages","renderConversation","renderingPromises","hasAddDays","add","length","hasAddMessages","hasUpdateMessages","update","timestampsToFormat","datesCachePromise","Deferred","resolve","promise","concat","reduce","carry","timestamps","push","get_string","format","requests","get","formattedTimes","renderHeader","headerContainer","template","HEADER_PUBLIC","context","showrouteback","type","PRIVATE","showControls","HEADER_PRIVATE","HEADER_PRIVATE_NO_CONTROLS","SELF","HEADER_SELF","js","replaceNodeContents","renderFooter","get_strings","key","component","param","user","fullname","strings","title","footerContainer","TITLE","TEXT","renderScrollToMessage","messageElement","position","scrollTop","top","renderLoadingMembers","isLoadingMembers","renderLoadingFirstMessages","isLoadingFirstMessages","renderLoadingMessages","isLoading","showConfirmDialogue","buttonSelectors","bodyText","headerText","canCancel","skipHeader","dialogue","buttons","selector","cancelButton","CONFIRM_DIALOGUE_CANCEL_BUTTON","CONFIRM_DIALOGUE_TEXT","dialogueHeader","CONFIRM_DIALOGUE_HEADER","button","CAN_RECEIVE_FOCUS","filter","first","focus","hideConfirmDialogue","hideCheckDeleteDialogue","renderConfirmBlockUser","canmessageevenifblocked","string","ACTION_CONFIRM_BLOCK","renderConfirmUnblockUser","ACTION_CONFIRM_UNBLOCK","renderConfirmAddContact","ACTION_CONFIRM_ADD_CONTACT","renderConfirmRemoveContact","ACTION_CONFIRM_REMOVE_CONTACT","renderConfirmDeleteSelectedMessages","showmessage","canDeleteMessagesForAllUsers","showCheckDeleteDialogue","show","ACTION_CONFIRM_DELETE_SELECTED_MESSAGES","renderConfirmDeleteConversation","ACTION_CONFIRM_DELETE_CONVERSATION","renderConfirmContactRequest","ACTION_ACCEPT_CONTACT_REQUEST","ACTION_DECLINE_CONTACT_REQUEST","checkboxRegion","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER","checkbox","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE","prop","renderIsBlocked","isBlocked","ACTION_REQUEST_BLOCK","ACTION_REQUEST_UNBLOCK","renderIsFavourite","state","favouriteIcon","FAVOURITE_ICON_CONTAINER","addFavourite","ACTION_CONFIRM_FAVOURITE","removeFavourite","ACTION_CONFIRM_UNFAVOURITE","renderIsMuted","muteIcon","MUTED_ICON_CONTAINER","setMuted","ACTION_CONFIRM_MUTE","unsetMuted","ACTION_CONFIRM_UNMUTE","renderIsContact","addContact","ACTION_REQUEST_ADD_CONTACT","removeContact","ACTION_REQUEST_REMOVE_CONTACT","renderLoadingConfirmAction","buttonText","CONFIRM_DIALOGUE_BUTTON_TEXT","loadingIcon","renderInEditMode","inEditMode","MESSAGE_NOT_SELECTED","MESSAGE_NOT_SELECTED_ICON","MESSAGE_SELECTED_ICON","renderSelectedMessages","hasSelectedMessages","count","renderRequireAddContact","hasMessages","renderSelfConversationMessage","displayMessage","renderContactRequestSent","userFullName","renderReset","patch","configs","reset","conversation","confirmBlockUser","confirmUnblockUser","confirmAddContact","confirmRemoveContact","confirmDeleteSelectedMessages","confirmDeleteConversation","confirmContactRequest","requireAddContact","selfConversationMessage","contactRequestSent","loadingMembers","loadingFirstMessages","loadingMessages","isContact","isFavourite","isMuted","loadingConfirmAction","scrollToMessage","selectedMessages","processConfig","config","results","hasOwnProperty","renderFunc","patchValue","i","exception"],"mappings":"AA4BAA,OAAM,0DACN,CACI,QADJ,CAEI,mBAFJ,CAGI,UAHJ,CAII,gBAJJ,CAKI,gBALJ,CAMI,yDANJ,CADM,CASN,SACIC,CADJ,CAEIC,CAFJ,CAGIC,CAHJ,CAIIC,CAJJ,CAKIC,CALJ,CAMIC,CANJ,CAOE,IACMC,CAAAA,CAAS,CAAGD,CAAS,CAACC,SAD5B,CAEMC,CAAS,CAAGF,CAAS,CAACE,SAF5B,CAGMC,CAAkB,CAAGH,CAAS,CAACG,kBAHrC,CAWMC,CAAoB,CAAG,SAASC,CAAT,CAAe,CACtC,MAAOA,CAAAA,CAAI,CAACC,IAAL,CAAUL,CAAS,CAACM,0BAApB,CACV,CAbH,CAoBMC,CAAqB,CAAG,SAASH,CAAT,CAAe,CACvCD,CAAoB,CAACC,CAAD,CAApB,CAA2BI,WAA3B,CAAuC,QAAvC,CACH,CAtBH,CA6BMC,CAAqB,CAAG,SAASL,CAAT,CAAe,CACvCD,CAAoB,CAACC,CAAD,CAApB,CAA2BM,QAA3B,CAAoC,QAApC,CACH,CA/BH,CAuCMC,CAAmC,CAAG,SAASP,CAAT,CAAe,CACrD,MAAOA,CAAAA,CAAI,CAACC,IAAL,CAAUL,CAAS,CAACY,mCAApB,CACV,CAzCH,CAiDMC,CAAoC,CAAG,SAAST,CAAT,CAAe,CACtD,MAAOO,CAAAA,CAAmC,CAACP,CAAD,CAAnC,CAA0CM,QAA1C,CAAmD,QAAnD,CACV,CAnDH,CA2DMI,CAA8B,CAAG,SAASV,CAAT,CAAe,CAChD,MAAOA,CAAAA,CAAI,CAACC,IAAL,CAAUL,CAAS,CAACe,sCAApB,CACV,CA7DH,CAqEMC,CAA+B,CAAG,SAASZ,CAAT,CAAe,CACjD,MAAOU,CAAAA,CAA8B,CAACV,CAAD,CAA9B,CAAqCM,QAArC,CAA8C,QAA9C,CACV,CAvEH,CA+EMO,CAAyB,CAAG,SAASC,CAAT,CAAiB,CAC7C,MAAOA,CAAAA,CAAM,CAACb,IAAP,CAAYL,CAAS,CAACmB,iCAAtB,CACV,CAjFH,CAwFMC,CAAiB,CAAG,SAASF,CAAT,CAAiB,CACrCD,CAAyB,CAACC,CAAD,CAAzB,CAAkCV,WAAlC,CAA8C,QAA9C,CACH,CA1FH,CAiGMa,CAAiB,CAAG,SAASH,CAAT,CAAiB,CACrCD,CAAyB,CAACC,CAAD,CAAzB,CAAkCR,QAAlC,CAA2C,QAA3C,CACH,CAnGH,CA2GMY,CAA0B,CAAG,SAASJ,CAAT,CAAiB,CAC9C,MAAOA,CAAAA,CAAM,CAACb,IAAP,CAAYL,CAAS,CAACuB,2CAAtB,CACV,CA7GH,CAoHMC,CAAkB,CAAG,SAASN,CAAT,CAAiB,CACtCI,CAA0B,CAACJ,CAAD,CAA1B,CAAmCV,WAAnC,CAA+C,QAA/C,CACH,CAtHH,CA6HMiB,CAAkB,CAAG,SAASP,CAAT,CAAiB,CACtCI,CAA0B,CAACJ,CAAD,CAA1B,CAAmCR,QAAnC,CAA4C,QAA5C,CACH,CA/HH,CAuIMgB,CAA6B,CAAG,SAASR,CAAT,CAAiB,CACjD,MAAOA,CAAAA,CAAM,CAACb,IAAP,CAAYL,CAAS,CAAC2B,qBAAtB,CACV,CAzIH,CAgJMC,CAAqB,CAAG,SAASV,CAAT,CAAiB,CACzCQ,CAA6B,CAACR,CAAD,CAA7B,CAAsCV,WAAtC,CAAkD,QAAlD,CACH,CAlJH,CAyJMqB,CAAqB,CAAG,SAASX,CAAT,CAAiB,CACzCQ,CAA6B,CAACR,CAAD,CAA7B,CAAsCR,QAAtC,CAA+C,QAA/C,CACH,CA3JH,CAmKMoB,CAAgC,CAAG,SAASZ,CAAT,CAAiB,CACpD,MAAOA,CAAAA,CAAM,CAACb,IAAP,CAAYL,CAAS,CAAC+B,iDAAtB,CACV,CArKH,CA4KMC,CAAwB,CAAG,SAASd,CAAT,CAAiB,CAC5CY,CAAgC,CAACZ,CAAD,CAAhC,CAAyCV,WAAzC,CAAqD,QAArD,CACH,CA9KH,CAqLMyB,CAAwB,CAAG,SAASf,CAAT,CAAiB,CAC5CY,CAAgC,CAACZ,CAAD,CAAhC,CAAyCR,QAAzC,CAAkD,QAAlD,CACH,CAvLH,CA+LMwB,CAAgC,CAAG,SAAShB,CAAT,CAAiB,CACpD,MAAOA,CAAAA,CAAM,CAACb,IAAP,CAAYL,CAAS,CAACmC,iDAAtB,CACV,CAjMH,CAwMMC,CAAwB,CAAG,SAASlB,CAAT,CAAiB,CAC5CgB,CAAgC,CAAChB,CAAD,CAAhC,CAAyCV,WAAzC,CAAqD,QAArD,CACH,CA1MH,CAiNM6B,CAAwB,CAAG,SAASnB,CAAT,CAAiB,CAC5CgB,CAAgC,CAAChB,CAAD,CAAhC,CAAyCR,QAAzC,CAAkD,QAAlD,CACH,CAnNH,CA2NM4B,CAAiC,CAAG,SAASpB,CAAT,CAAiB,CACrD,MAAOA,CAAAA,CAAM,CAACb,IAAP,CAAYL,CAAS,CAACuC,mDAAtB,CACV,CA7NH,CAoOMC,CAAyB,CAAG,SAAStB,CAAT,CAAiB,CAC7CoB,CAAiC,CAACpB,CAAD,CAAjC,CAA0CV,WAA1C,CAAsD,QAAtD,CACH,CAtOH,CA6OMiC,CAAyB,CAAG,SAASvB,CAAT,CAAiB,CAC7CoB,CAAiC,CAACpB,CAAD,CAAjC,CAA0CR,QAA1C,CAAmD,QAAnD,CACH,CA/OH,CAsPMgC,CAAqB,CAAG,SAASC,CAAT,CAAiB,CACzCC,CAAiB,CAACD,CAAD,CAAjB,CACAE,CAAkB,CAACF,CAAD,CAAlB,CACAG,CAAqB,CAACH,CAAD,CACxB,CA1PH,CAiQMI,CAAqB,CAAG,SAAS7B,CAAT,CAAiB,CACzCG,CAAiB,CAACH,CAAD,CAAjB,CACAO,CAAkB,CAACP,CAAD,CAAlB,CACAW,CAAqB,CAACX,CAAD,CAArB,CACAe,CAAwB,CAACf,CAAD,CAAxB,CACAmB,CAAwB,CAACnB,CAAD,CAAxB,CACAuB,CAAyB,CAACvB,CAAD,CAC5B,CAxQH,CAgRM8B,CAA8B,CAAG,SAAS5C,CAAT,CAAe,CAChD,MAAOA,CAAAA,CAAI,CAACC,IAAL,CAAUL,CAAS,CAACiD,6BAApB,CACV,CAlRH,CAyRMC,CAAsB,CAAG,SAAS9C,CAAT,CAAe,CACxC4C,CAA8B,CAAC5C,CAAD,CAA9B,CAAqCI,WAArC,CAAiD,QAAjD,CACH,CA3RH,CAkSM2C,CAAsB,CAAG,SAAS/C,CAAT,CAAe,CACxC4C,CAA8B,CAAC5C,CAAD,CAA9B,CAAqCM,QAArC,CAA8C,QAA9C,CACH,CApSH,CA4SM0C,CAAgB,CAAG,SAAST,CAAT,CAAiB,CACpC,MAAOA,CAAAA,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAACqD,MAAtB,CACV,CA9SH,CAqTMC,CAAiB,CAAG,SAASX,CAAT,CAAiB,CACrCS,CAAgB,CAACT,CAAD,CAAhB,CAAyBnC,WAAzB,CAAqC,QAArC,CACH,CAvTH,CA8TMoC,CAAiB,CAAG,SAASD,CAAT,CAAiB,CACrCS,CAAgB,CAACT,CAAD,CAAhB,CAAyBjC,QAAzB,CAAkC,QAAlC,CACH,CAhUH,CAwUM6C,CAAiB,CAAG,SAASZ,CAAT,CAAiB,CACrC,MAAOA,CAAAA,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAACwD,gBAAtB,CACV,CA1UH,CAiVMC,CAAkB,CAAG,SAASd,CAAT,CAAiB,CACtCY,CAAiB,CAACZ,CAAD,CAAjB,CAA0BnC,WAA1B,CAAsC,QAAtC,CACH,CAnVH,CA0VMqC,CAAkB,CAAG,SAASF,CAAT,CAAiB,CACtCY,CAAiB,CAACZ,CAAD,CAAjB,CAA0BjC,QAA1B,CAAmC,QAAnC,CACH,CA5VH,CAoWMgD,CAA6B,CAAG,SAASf,CAAT,CAAiB,CACjD,MAAOA,CAAAA,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAAC2D,4BAAtB,CACV,CAtWH,CA6WMC,CAAqB,CAAG,SAASjB,CAAT,CAAiB,CACzCe,CAA6B,CAACf,CAAD,CAA7B,CAAsCnC,WAAtC,CAAkD,QAAlD,CACH,CA/WH,CAsXMsC,CAAqB,CAAG,SAASH,CAAT,CAAiB,CACzCe,CAA6B,CAACf,CAAD,CAA7B,CAAsCjC,QAAtC,CAA+C,QAA/C,CACH,CAxXH,CAiYMmD,CAAiB,CAAG,SAASzD,CAAT,CAAe0D,CAAf,CAA0B,CAC9C,GAAIC,CAAAA,CAAiB,CAAG5D,CAAoB,CAACC,CAAD,CAA5C,CACA,MAAO2D,CAAAA,CAAiB,CAAC1D,IAAlB,CAAuB,sBAAuByD,CAAvB,CAAmC,KAA1D,CACV,CApYH,CA6YME,CAAa,CAAG,SAAS5D,CAAT,CAAe6D,CAAf,CAA+B,CAC/C,GAAIF,CAAAA,CAAiB,CAAG5D,CAAoB,CAACC,CAAD,CAA5C,CACA,MAAO2D,CAAAA,CAAiB,CAAC1D,IAAlB,CAAuB,kBAAmB4D,CAAnB,CAAoC,KAA3D,CACV,CAhZH,CAwZMC,CAAmC,CAAG,SAAS9D,CAAT,CAAe,CACrD,MAAOA,CAAAA,CAAI,CAACC,IAAL,CAAUL,CAAS,CAACmE,oCAApB,CACV,CA1ZH,CAiaMC,CAA2B,CAAG,SAAShE,CAAT,CAAe,CAC7C8D,CAAmC,CAAC9D,CAAD,CAAnC,CAA0CI,WAA1C,CAAsD,QAAtD,CACH,CAnaH,CA0aM6D,CAA2B,CAAG,SAASjE,CAAT,CAAe,CAC7C8D,CAAmC,CAAC9D,CAAD,CAAnC,CAA0CM,QAA1C,CAAmD,QAAnD,CACH,CA5aH,CAobM4D,CAA2B,CAAG,SAASC,CAAT,CAAe,CAC7C,MAAOA,CAAAA,CAAI,CAAClE,IAAL,CAAUL,CAAS,CAACwE,0BAApB,CACV,CAtbH,CA6bMC,EAA4B,CAAG,SAASF,CAAT,CAAe,IAC1CG,CAAAA,CAAS,CAAGJ,CAA2B,CAACC,CAAD,CADG,CAE1CI,CAAQ,CAAGD,CAAS,CAACC,QAAV,CAAmB,eAAnB,CAF+B,CAG9CA,CAAQ,CAACC,IAAT,CAAc,aAAd,KACAD,CAAQ,CAACC,IAAT,CAAc,UAAd,CAA0B,CAAC,CAA3B,EACAD,CAAQ,CAACC,IAAT,CAAc,8BAAd,KAEAF,CAAS,CAAClE,WAAV,CAAsB,QAAtB,CACH,CArcH,CA4cMqE,EAA4B,CAAG,SAASN,CAAT,CAAe,IAC1CG,CAAAA,CAAS,CAAGJ,CAA2B,CAACC,CAAD,CADG,CAE1CI,CAAQ,CAAGD,CAAS,CAACC,QAAV,CAAmB,yCAAnB,CAF+B,CAG9CA,CAAQ,CAACG,UAAT,CAAoB,aAApB,EACAH,CAAQ,CAACG,UAAT,CAAoB,UAApB,EACAH,CAAQ,CAACG,UAAT,CAAoB,8BAApB,EAEAJ,CAAS,CAAChE,QAAV,CAAmB,QAAnB,CACH,CApdH,CA4dMqE,EAAwB,CAAG,SAASpC,CAAT,CAAiBqC,CAAjB,CAAwB,CACnDzB,CAAiB,CAACZ,CAAD,CAAjB,CAA0BtC,IAA1B,CAA+BL,CAAS,CAACiF,uBAAzC,EAAkEC,IAAlE,CAAuEF,CAAvE,CACH,CA9dH,CAueMG,EAAyB,CAAG,SAASC,CAAT,CAAmBC,CAAnB,CAA+B,CAC3D,MAAOD,CAAAA,CAAQ,CAACE,GAAT,CAAa,SAASC,CAAT,CAAkB,CAClC,MAAO,CACHC,EAAE,CAAED,CAAO,CAACC,EADT,CAEHC,MAAM,CAAEF,CAAO,CAACG,MAFb,CAGHC,gBAAgB,CAAEJ,CAAO,CAACK,gBAHvB,CAIHC,QAAQ,CAAEN,CAAO,CAACO,QAJf,CAKHZ,IAAI,CAAEK,CAAO,CAACL,IALX,CAMHa,aAAa,CAAER,CAAO,CAACS,WAAR,CAAsBX,CAAU,CAACE,CAAO,CAACS,WAAT,CAAhC,CAAwD,IANpE,CAQV,CATM,CAUV,CAlfH,CA8fMC,EAAa,CAAG,SAAStD,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BgF,CAA/B,CAAqCb,CAArC,CAAiD,IAC7DtB,CAAAA,CAAiB,CAAG5D,CAAoB,CAACC,CAAD,CADqB,CAE7D+F,CAAkB,CAAGD,CAAI,CAACZ,GAAL,CAAS,SAASc,CAAT,CAAe,CAC7C,MAAOvG,CAAAA,CAAS,CAACwG,MAAV,CAAiBpG,CAAS,CAACqG,GAA3B,CAAgC,CACnCC,SAAS,CAAEH,CAAI,CAACpB,KAAL,CAAWuB,SADa,CAEnCnB,QAAQ,CAAED,EAAyB,CAACiB,CAAI,CAACpB,KAAL,CAAWI,QAAZ,CAAsBC,CAAtB,CAFA,CAAhC,CAIV,CALwB,CAFwC,CASjE,MAAO3F,CAAAA,CAAC,CAAC8G,IAAF,CAAOC,KAAP,CAAa/G,CAAb,CAAgByG,CAAhB,EAAoCO,IAApC,CAAyC,UAAW,CAGvDR,CAAI,CAACS,OAAL,CAAa,SAASP,CAAT,CAAeQ,CAAf,CAAsB,CAC/BT,CAAkB,CAACS,CAAD,CAAlB,CACKF,IADL,CACU,SAASG,CAAT,CAAe,CACjB,GAAIT,CAAI,CAACU,MAAT,CAAiB,CACb,GAAIC,CAAAA,CAAO,CAAG/C,CAAa,CAAC5D,CAAD,CAAOgG,CAAI,CAACU,MAAL,CAAYP,SAAnB,CAA3B,CACA,MAAO7G,CAAAA,CAAC,CAACmH,CAAD,CAAD,CAAQG,YAAR,CAAqBD,CAArB,CACV,CAHD,IAGO,CACH,MAAOhD,CAAAA,CAAiB,CAACkD,MAAlB,CAAyBJ,CAAzB,CACV,CACJ,CARL,EASKK,KATL,CASW,UAAW,CAEjB,CAXL,CAYH,CAbD,CAgBH,CAnBM,CAoBV,CA3hBH,CAuiBMC,EAAiB,CAAG,SAASxE,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BkE,CAA/B,CAAyCC,CAAzC,CAAqD,IACrE+B,CAAAA,CAAY,CAAGhC,CAAQ,CAACE,GAAT,CAAa,SAASc,CAAT,CAAe,CAC3C,MAAOA,CAAAA,CAAI,CAACpB,KACf,CAFkB,CADsD,CAIrEqC,CAAiB,CAAGlC,EAAyB,CAACiC,CAAD,CAAe/B,CAAf,CAJwB,CAMzE,MAAOxF,CAAAA,CAAS,CAACwG,MAAV,CAAiBpG,CAAS,CAACqH,QAA3B,CAAqC,CAAClC,QAAQ,CAAEiC,CAAX,CAArC,EACFX,IADE,CACG,SAASG,CAAT,CAAe,CACjB,GAAIU,CAAAA,CAAW,CAAG7H,CAAC,CAACmH,CAAD,CAAnB,CACAzB,CAAQ,CAACuB,OAAT,CAAiB,SAASP,CAAT,CAAe,CAC5B,GAAIoB,CAAAA,CAAW,CAAGD,CAAW,CAAClH,IAAZ,CAAiB,sBAAuB+F,CAAI,CAACpB,KAAL,CAAWQ,EAAlC,CAAuC,KAAxD,CAAlB,CACA,GAAIY,CAAI,CAACU,MAAT,CAAiB,CACb,GAAIC,CAAAA,CAAO,CAAGlD,CAAiB,CAACzD,CAAD,CAAOgG,CAAI,CAACU,MAAL,CAAYtB,EAAnB,CAA/B,CACA,MAAOgC,CAAAA,CAAW,CAACR,YAAZ,CAAyBD,CAAzB,CACV,CAHD,IAGO,IACCU,CAAAA,CAAY,CAAGzD,CAAa,CAAC5D,CAAD,CAAOgG,CAAI,CAACsB,GAAL,CAASnB,SAAhB,CAD7B,CAECoB,CAAoB,CAAGF,CAAY,CAACpH,IAAb,CAAkBL,CAAS,CAAC4H,sBAA5B,CAFxB,CAGH,MAAOD,CAAAA,CAAoB,CAACV,MAArB,CAA4BO,CAA5B,CACV,CACJ,CAVD,CAaH,CAhBE,CAiBV,CA9jBH,CAykBMK,EAAoB,CAAG,SAASlF,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BkE,CAA/B,CAAyCC,CAAzC,CAAqD,CAC5ED,CAAQ,CAACuB,OAAT,CAAiB,SAASpB,CAAT,CAAkB,IAC3BuB,CAAAA,CAAM,CAAGvB,CAAO,CAACuB,MADU,CAE3BgB,CAAK,CAAGvC,CAAO,CAACuC,KAFW,CAG3Bf,CAAO,CAAGlD,CAAiB,CAACzD,CAAD,CAAO0G,CAAM,CAACtB,EAAd,CAHA,CAK/B,GAAIsB,CAAM,CAACtB,EAAP,EAAasC,CAAK,CAACtC,EAAvB,CAA2B,CACvBuB,CAAO,CAACnC,IAAR,CAAa,iBAAb,CAAgCkD,CAAK,CAACtC,EAAtC,CACH,CAED,GAAIsB,CAAM,CAACd,WAAP,EAAsB8B,CAAK,CAAC9B,WAAhC,CAA6C,CACzC,GAAI+B,CAAAA,CAAa,CAAG1C,CAAU,CAACyC,CAAK,CAAC9B,WAAP,CAA9B,CACAe,CAAO,CAAC1G,IAAR,CAAaL,CAAS,CAACgI,sBAAvB,EAA+CtH,QAA/C,CAAwD,QAAxD,EACAqG,CAAO,CAAC1G,IAAR,CAAaL,CAAS,CAACiI,YAAvB,EAAqC/C,IAArC,CAA0C6C,CAA1C,EAAyDvH,WAAzD,CAAqE,QAArE,CACH,CAED,GAAIsG,CAAM,CAACoB,SAAP,EAAoBJ,CAAK,CAACI,SAA9B,CAAyC,IACjCC,CAAAA,CAAO,CAAGpB,CAAO,CAAC1G,IAAR,CAAaL,CAAS,CAACgI,sBAAvB,CADuB,CAEjCI,CAAI,CAAGrB,CAAO,CAAC1G,IAAR,CAAaL,CAAS,CAACiI,YAAvB,CAF0B,CAGjCI,CAAK,CAAGtB,CAAO,CAAC1G,IAAR,CAAaL,CAAS,CAACsI,UAAvB,CAHyB,CAKrCH,CAAO,CAACzH,QAAR,CAAiB,QAAjB,EACAyH,CAAO,CAACvD,IAAR,CAAa,aAAb,CAA4B,MAA5B,EACAwD,CAAI,CAAC1H,QAAL,CAAc,QAAd,EACA0H,CAAI,CAACxD,IAAL,CAAU,aAAV,CAAyB,MAAzB,EACAyD,CAAK,CAAC3H,QAAN,CAAe,QAAf,EACA2H,CAAK,CAACzD,IAAN,CAAW,aAAX,CAA0B,MAA1B,EACAmC,CAAO,CAACvG,WAAR,CAAoB,sBAApB,EAEA,OAAQsH,CAAK,CAACI,SAAd,EACI,IAAK,SAAL,CACIC,CAAO,CAAC3H,WAAR,CAAoB,QAApB,EACA2H,CAAO,CAACvD,IAAR,CAAa,aAAb,CAA4B,OAA5B,EACA,MACJ,IAAK,OAAL,CACIyD,CAAK,CAAC7H,WAAN,CAAkB,QAAlB,EACA6H,CAAK,CAACzD,IAAN,CAAW,aAAX,CAA0B,OAA1B,EACAmC,CAAO,CAACrG,QAAR,CAAiB,sBAAjB,EACA,MACJ,IAAK,MAAL,CACI0H,CAAI,CAAC5H,WAAL,CAAiB,QAAjB,EACA4H,CAAI,CAACxD,IAAL,CAAU,aAAV,CAAyB,OAAzB,EACA,MAbR,CAeH,CAED,GAAIkC,CAAM,CAAC5B,IAAP,EAAe4C,CAAK,CAAC5C,IAAzB,CAA+B,CAC3B6B,CAAO,CAAC1G,IAAR,CAAaL,CAAS,CAACuI,cAAvB,EAAuC1B,IAAvC,CAA4CiB,CAAK,CAAC5C,IAAlD,CACH,CAED,GAAI4B,CAAM,CAAC0B,YAAP,EAAuBV,CAAK,CAACU,YAAjC,CAA+C,IACvCC,CAAAA,CAAgB,CAAG1B,CAAO,CAAC1G,IAAR,CAAaL,CAAS,CAAC0I,uBAAvB,CADoB,CAEvCnD,CAAO,CAAGkD,CAAgB,CAACpI,IAAjB,CAAsBL,CAAS,CAAC2I,aAAhC,CAF6B,CAI3C,GAAIb,CAAK,CAACU,YAAV,CAAwB,CACpBC,CAAgB,CAACjI,WAAjB,CAA6B,QAA7B,EACAiI,CAAgB,CAAC7D,IAAjB,CAAsB,aAAtB,CAAqC,OAArC,EACAW,CAAO,CAACL,IAAR,CAAa4C,CAAK,CAACU,YAAnB,CACH,CAJD,IAIO,CACHC,CAAgB,CAAC/H,QAAjB,CAA0B,QAA1B,EACA+H,CAAgB,CAAC7D,IAAjB,CAAsB,aAAtB,CAAqC,MAArC,EACAW,CAAO,CAACL,IAAR,CAAa,EAAb,CACH,CACJ,CACJ,CA/DD,CAgEH,CA1oBH,CAkpBM0D,EAAgB,CAAG,SAASxI,CAAT,CAAe8F,CAAf,CAAqB,CACxCA,CAAI,CAACS,OAAL,CAAa,SAASP,CAAT,CAAe,CACxBpC,CAAa,CAAC5D,CAAD,CAAOgG,CAAI,CAACG,SAAZ,CAAb,CAAoCsC,MAApC,EACH,CAFD,CAGH,CAtpBH,CA8pBMC,EAAoB,CAAG,SAAS1I,CAAT,CAAegF,CAAf,CAAyB,CAChDA,CAAQ,CAACuB,OAAT,CAAiB,SAASP,CAAT,CAAe,CAC5BvC,CAAiB,CAACzD,CAAD,CAAOgG,CAAI,CAACZ,EAAZ,CAAjB,CAAiCqD,MAAjC,EACH,CAFD,CAGH,CAlqBH,CAgrBME,EAAkB,CAAG,SAASpG,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BkF,CAA/B,CAAqC,IACtD4C,CAAAA,CAAiB,CAAG,EADkC,CAEtDC,CAAU,CAA0B,CAAvB,CAAA7C,CAAI,CAACF,IAAL,CAAUgD,GAAV,CAAcC,MAF2B,CAGtDC,CAAc,CAA8B,CAA3B,CAAAhD,CAAI,CAAChB,QAAL,CAAc8D,GAAd,CAAkBC,MAHmB,CAItDE,CAAiB,CAAiC,CAA9B,CAAAjD,CAAI,CAAChB,QAAL,CAAckE,MAAd,CAAqBH,MAJa,CAKtDI,CAAkB,CAAG,EALiC,CAMtDC,CAAiB,CAAG9J,CAAC,CAAC+J,QAAF,GAAaC,OAAb,CAAqB,EAArB,EAAyBC,OAAzB,EANkC,CAQ1D,GAAIV,CAAJ,CAAgB,CAGZM,CAAkB,CAAGA,CAAkB,CAACK,MAAnB,CAA0BxD,CAAI,CAACF,IAAL,CAAUgD,GAAV,CAAcW,MAAd,CAAqB,SAASC,CAAT,CAAgBpC,CAAhB,CAAqB,CACrF,MAAOoC,CAAAA,CAAK,CAACF,MAAN,CAAalC,CAAG,CAAC1C,KAAJ,CAAUI,QAAV,CAAmByE,MAAnB,CAA0B,SAASE,CAAT,CAAqBxE,CAArB,CAA8B,CACxE,GAAIA,CAAO,CAACS,WAAZ,CAAyB,CACrB+D,CAAU,CAACC,IAAX,CAAgBzE,CAAO,CAACS,WAAxB,CACH,CACD,MAAO+D,CAAAA,CACV,CALmB,CAKjB,EALiB,CAAb,CAMV,CAP8C,CAO5C,EAP4C,CAA1B,CAQxB,CAED,GAAIX,CAAJ,CAAoB,CAGhBG,CAAkB,CAAGA,CAAkB,CAACK,MAAnB,CAA0BxD,CAAI,CAAChB,QAAL,CAAc8D,GAAd,CAAkBW,MAAlB,CAAyB,SAASE,CAAT,CAAqBxE,CAArB,CAA8B,CAClG,GAAIA,CAAO,CAACP,KAAR,CAAcgB,WAAlB,CAA+B,CAC3B+D,CAAU,CAACC,IAAX,CAAgBzE,CAAO,CAACP,KAAR,CAAcgB,WAA9B,CACH,CACD,MAAO+D,CAAAA,CACV,CAL8C,CAK5C,EAL4C,CAA1B,CAMxB,CAED,GAAIV,CAAJ,CAAuB,CACnBE,CAAkB,CAAGA,CAAkB,CAACK,MAAnB,CAA0BxD,CAAI,CAAChB,QAAL,CAAckE,MAAd,CAAqBO,MAArB,CAA4B,SAASE,CAAT,CAAqBxE,CAArB,CAA8B,CACrG,GAAIA,CAAO,CAACuB,MAAR,CAAed,WAAf,EAA8BT,CAAO,CAACuC,KAAR,CAAc9B,WAAhD,CAA6D,CACzD+D,CAAU,CAACC,IAAX,CAAgBzE,CAAO,CAACuC,KAAR,CAAc9B,WAA9B,CACH,CACD,MAAO+D,CAAAA,CACV,CAL8C,CAK5C,EAL4C,CAA1B,CAMxB,CAED,GAAIR,CAAkB,CAACJ,MAAvB,CAA+B,CAI3BK,CAAiB,CAAG5J,CAAG,CAACqK,UAAJ,CAAe,gBAAf,CAAiC,iBAAjC,EACfvD,IADe,CACV,SAASwD,CAAT,CAAiB,CACnB,GAAIC,CAAAA,CAAQ,CAAGZ,CAAkB,CAACjE,GAAnB,CAAuB,SAASiB,CAAT,CAAoB,CACtD,MAAO,CACHA,SAAS,CAAEA,CADR,CAEH2D,MAAM,CAAEA,CAFL,CAIV,CALc,CAAf,CAOA,MAAOpK,CAAAA,CAAQ,CAACsK,GAAT,CAAaD,CAAb,CACV,CAVe,EAWfzD,IAXe,CAWV,SAAS2D,CAAT,CAAyB,CAC3B,MAAOd,CAAAA,CAAkB,CAACM,MAAnB,CAA0B,SAASC,CAAT,CAAgBvD,CAAhB,CAA2BK,CAA3B,CAAkC,CAC/DkD,CAAK,CAACvD,CAAD,CAAL,CAAmB8D,CAAc,CAACzD,CAAD,CAAjC,CACA,MAAOkD,CAAAA,CACV,CAHM,CAGJ,EAHI,CAIV,CAhBe,CAiBvB,CAED,GAAIb,CAAJ,CAAgB,CACZD,CAAiB,CAACgB,IAAlB,CAAuBR,CAAiB,CAAC9C,IAAlB,CAAuB,SAASrB,CAAT,CAAqB,CAC/D,MAAOY,CAAAA,EAAa,CAACtD,CAAD,CAASvC,CAAT,CAAec,CAAf,CAAuBkF,CAAI,CAACF,IAAL,CAAUgD,GAAjC,CAAsC7D,CAAtC,CACvB,CAFsB,CAAvB,CAGH,CAED,GAAI+D,CAAJ,CAAoB,CAChBJ,CAAiB,CAACgB,IAAlB,CAAuBR,CAAiB,CAAC9C,IAAlB,CAAuB,SAASrB,CAAT,CAAqB,CAC/D,MAAO8B,CAAAA,EAAiB,CAACxE,CAAD,CAASvC,CAAT,CAAec,CAAf,CAAuBkF,CAAI,CAAChB,QAAL,CAAc8D,GAArC,CAA0C7D,CAA1C,CAC3B,CAFsB,CAAvB,CAGH,CAED,GAAIgE,CAAJ,CAAuB,CACnBL,CAAiB,CAACgB,IAAlB,CAAuBR,CAAiB,CAAC9C,IAAlB,CAAuB,SAASrB,CAAT,CAAqB,CAC/D,MAAOwC,CAAAA,EAAoB,CAAClF,CAAD,CAASvC,CAAT,CAAec,CAAf,CAAuBkF,CAAI,CAAChB,QAAL,CAAckE,MAArC,CAA6CjE,CAA7C,CAC9B,CAFsB,CAAvB,CAGH,CAED,GAA8B,CAA1B,CAAAe,CAAI,CAACF,IAAL,CAAU2C,MAAV,CAAiBM,MAArB,CAAiC,CAC7BP,EAAgB,CAACxI,CAAD,CAAOgG,CAAI,CAACF,IAAL,CAAU2C,MAAjB,CACnB,CAED,GAAkC,CAA9B,CAAAzC,CAAI,CAAChB,QAAL,CAAcyD,MAAd,CAAqBM,MAAzB,CAAqC,CACjCL,EAAoB,CAAC1I,CAAD,CAAOgG,CAAI,CAAChB,QAAL,CAAcyD,MAArB,CACvB,CAED,MAAOnJ,CAAAA,CAAC,CAAC8G,IAAF,CAAOC,KAAP,CAAa/G,CAAb,CAAgBsJ,CAAhB,CACV,CA3wBH,CAsxBMsB,EAAY,CAAG,SAAS3H,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BkF,CAA/B,CAAqC,IAChDmE,CAAAA,CAAe,CAAGnH,CAAgB,CAACT,CAAD,CADc,CAEhD6H,CAAQ,CAAGvK,CAAS,CAACwK,aAF2B,CAGpDrE,CAAI,CAACsE,OAAL,CAAaC,aAAb,CAAiE,OAAnC,GAAAhI,CAAM,CAACiC,IAAP,CAAY,iBAAZ,CAA9B,CACA,GAAIwB,CAAI,CAACwE,IAAL,EAAa1K,CAAkB,CAAC2K,OAApC,CAA6C,CACzCL,CAAQ,CAAGpE,CAAI,CAAC0E,YAAL,CAAoB7K,CAAS,CAAC8K,cAA9B,CAA+C9K,CAAS,CAAC+K,0BACvE,CAFD,IAEO,IAAI5E,CAAI,CAACwE,IAAL,EAAa1K,CAAkB,CAAC+K,IAApC,CAA0C,CAC7CT,CAAQ,CAAGvK,CAAS,CAACiL,WACxB,CAED,MAAOrL,CAAAA,CAAS,CAACwG,MAAV,CAAiBmE,CAAjB,CAA2BpE,CAAI,CAACsE,OAAhC,EACFhE,IADE,CACG,SAASG,CAAT,CAAesE,CAAf,CAAmB,CACrBtL,CAAS,CAACuL,mBAAV,CAA8Bb,CAA9B,CAA+C1D,CAA/C,CAAqDsE,CAArD,CAEH,CAJE,CAKV,CAryBH,CAgzBME,EAAY,CAAG,SAAS1I,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BkF,CAA/B,CAAqC,CACpDrD,CAAqB,CAAC7B,CAAD,CAArB,CAEA,OAAQkF,CAAI,CAACwE,IAAb,EACI,IAAK,aAAL,CACI,MAAOhJ,CAAAA,CAAqB,CAACV,CAAD,CAA5B,CACJ,IAAK,aAAL,CACI,MAAOtB,CAAAA,CAAG,CAAC0L,WAAJ,CAAgB,CACf,CACIC,GAAG,CAAE,yBADT,CAEIC,SAAS,CAAE,cAFf,CAGIC,KAAK,CAAErF,CAAI,CAACsF,IAAL,CAAUC,QAHrB,CADe,CAMf,CACIJ,GAAG,CAAE,qBADT,CAEIC,SAAS,CAAE,cAFf,CAGIC,KAAK,CAAErF,CAAI,CAACsF,IAAL,CAAUC,QAHrB,CANe,CAAhB,EAYFjF,IAZE,CAYG,SAASkF,CAAT,CAAkB,IAChBC,CAAAA,CAAK,CAAGD,CAAO,CAAC,CAAD,CADC,CAEhB1G,CAAI,CAAG0G,CAAO,CAAC,CAAD,CAFE,CAGhBE,CAAe,CAAGhK,CAAgC,CAACZ,CAAD,CAHlC,CAIpB4K,CAAe,CAACzL,IAAhB,CAAqBL,CAAS,CAAC+L,KAA/B,EAAsC7G,IAAtC,CAA2C2G,CAA3C,EACAC,CAAe,CAACzL,IAAhB,CAAqBL,CAAS,CAACgM,IAA/B,EAAqC9G,IAArC,CAA0CA,CAA1C,EACAlD,CAAwB,CAACd,CAAD,CAAxB,CACA,MAAO0K,CAAAA,CACV,CApBE,CAAP,CAqBJ,IAAK,WAAL,CACI,MAAOpK,CAAAA,CAAkB,CAACN,CAAD,CAAzB,CACJ,IAAK,SAAL,CACI,MAAOE,CAAAA,CAAiB,CAACF,CAAD,CAAxB,CACJ,IAAK,SAAL,CACI,MAAOkB,CAAAA,CAAwB,CAAClB,CAAD,CAA/B,CACJ,IAAK,mBAAL,CACI,MAAOsB,CAAAA,CAAyB,CAACtB,CAAD,CAAhC,CAhCR,CAmCA,QACH,CAv1BH,CAi2BM+K,EAAqB,CAAG,SAAStJ,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+B4C,CAA/B,CAA0C,IAC9DC,CAAAA,CAAiB,CAAG5D,CAAoB,CAACC,CAAD,CADsB,CAE9D8L,CAAc,CAAGrI,CAAiB,CAACzD,CAAD,CAAO0D,CAAP,CAF4B,CAG9DqI,CAAQ,CAAGD,CAAc,CAACC,QAAf,EAHmD,CAKlE,GAAIA,CAAJ,CAAc,CACV,GAAIC,CAAAA,CAAS,CAAGrI,CAAiB,CAACqI,SAAlB,GAAgCD,CAAQ,CAACE,GAAzD,CACAtI,CAAiB,CAACqI,SAAlB,CAA4BA,CAA5B,CACH,CACJ,CA12BH,CAo3BME,EAAoB,CAAG,SAAS3J,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BqL,CAA/B,CAAiD,CACxE,GAAIA,CAAJ,CAAsB,CAClB3J,CAAiB,CAACD,CAAD,CAAjB,CACAiB,CAAqB,CAACjB,CAAD,CACxB,CAHD,IAGO,CACHW,CAAiB,CAACX,CAAD,CAAjB,CACAG,CAAqB,CAACH,CAAD,CACxB,CACJ,CA53BH,CAs4BM6J,EAA0B,CAAG,SAAS7J,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BuL,CAA/B,CAAuD,CACpF,GAAIA,CAAJ,CAA4B,CACxBhM,CAAqB,CAACL,CAAD,CAArB,CACA8C,CAAsB,CAAC9C,CAAD,CACzB,CAHD,IAGO,CACHG,CAAqB,CAACH,CAAD,CAArB,CACA+C,CAAsB,CAAC/C,CAAD,CACzB,CACJ,CA94BH,CAw5BMsM,EAAqB,CAAG,SAAS/J,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+ByL,CAA/B,CAA0C,CAClE,GAAIA,CAAJ,CAAe,CACXvI,CAA2B,CAAChE,CAAD,CAC9B,CAFD,IAEO,CACHiE,CAA2B,CAACjE,CAAD,CAC9B,CACJ,CA95BH,CA46BMwM,EAAmB,CAAG,SACtBjK,CADsB,CAEtBvC,CAFsB,CAGtBc,CAHsB,CAItB2L,CAJsB,CAKtBC,CALsB,CAMtBC,CANsB,CAOtBC,CAPsB,CAQtBC,CARsB,CASxB,IACMC,CAAAA,CAAQ,CAAG5I,CAA2B,CAAClE,CAAD,CAD5C,CAEM+M,CAAO,CAAGN,CAAe,CAACvH,GAAhB,CAAoB,SAAS8H,CAAT,CAAmB,CACjD,MAAOF,CAAAA,CAAQ,CAAC7M,IAAT,CAAc+M,CAAd,CACV,CAFa,CAFhB,CAKMC,CAAY,CAAGH,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAACsN,8BAAxB,CALrB,CAMMpI,CAAI,CAAGgI,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAACuN,qBAAxB,CANb,CAOMC,CAAc,CAAGN,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAACyN,uBAAxB,CAPvB,CASEP,CAAQ,CAAC7M,IAAT,CAAc,QAAd,EAAwBK,QAAxB,CAAiC,QAAjC,EAEA,GAAIsM,CAAJ,CAAe,CACXK,CAAY,CAAC7M,WAAb,CAAyB,QAAzB,CACH,CAFD,IAEO,CACH6M,CAAY,CAAC3M,QAAb,CAAsB,QAAtB,CACH,CAED,GAAIqM,CAAJ,CAAgB,CACZS,CAAc,CAAChN,WAAf,CAA2B,QAA3B,EACAgN,CAAc,CAACtI,IAAf,CAAoB6H,CAApB,CACH,CAHD,IAGO,CACHS,CAAc,CAAC9M,QAAf,CAAwB,QAAxB,EACA8M,CAAc,CAACtI,IAAf,CAAoB,EAApB,CACH,CAEDiI,CAAO,CAACxG,OAAR,CAAgB,SAAS+G,CAAT,CAAiB,CAC7BA,CAAM,CAAClN,WAAP,CAAmB,QAAnB,CACH,CAFD,EAGA0E,CAAI,CAACA,IAAL,CAAU4H,CAAV,EACArI,EAA4B,CAACvD,CAAD,CAA5B,CACAuD,EAA4B,CAACrE,CAAD,CAA5B,CAEA,GAAI,CAAC6M,CAAL,CAAiB,CACbxI,EAA4B,CAAC9B,CAAD,CAC/B,CAEDuK,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAAC2N,iBAAxB,EAA2CC,MAA3C,CAAkD,UAAlD,EAA8DC,KAA9D,GAAsEC,KAAtE,EACH,CA19BH,CAo+BMC,EAAmB,CAAG,SAASpL,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+B,IACjDgM,CAAAA,CAAQ,CAAG5I,CAA2B,CAAClE,CAAD,CADW,CAEjDiN,CAAY,CAAGH,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAACsN,8BAAxB,CAFkC,CAGjDpI,CAAI,CAAGgI,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAACuN,qBAAxB,CAH0C,CAIjDC,CAAc,CAAGN,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAACyN,uBAAxB,CAJgC,CAMrDO,EAAuB,CAAC5N,CAAD,CAAvB,CACAyE,EAA4B,CAACzE,CAAD,CAA5B,CACAyE,EAA4B,CAAC3D,CAAD,CAA5B,CACA2D,EAA4B,CAAClC,CAAD,CAA5B,CACAuK,CAAQ,CAAC7M,IAAT,CAAc,QAAd,EAAwBK,QAAxB,CAAiC,QAAjC,EACA2M,CAAY,CAAC7M,WAAb,CAAyB,QAAzB,EACA0E,CAAI,CAACA,IAAL,CAAU,EAAV,EACAsI,CAAc,CAAC9M,QAAf,CAAwB,QAAxB,EACA8M,CAAc,CAACtI,IAAf,CAAoB,EAApB,EAEAvC,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAAC2N,iBAAtB,EAAyCE,KAAzC,GAAiDC,KAAjD,GACA,QACH,CAt/BH,CAigCMG,EAAsB,CAAG,SAAStL,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BwK,CAA/B,CAAqC,CAC9D,GAAIA,CAAJ,CAAU,CACN,GAAIA,CAAI,CAACwC,uBAAT,CAAkC,CAC9B,MAAOtO,CAAAA,CAAG,CAACqK,UAAJ,CAAe,eAAf,CAAgC,cAAhC,CAAgDyB,CAAI,CAACC,QAArD,EACFjF,IADE,CACG,SAASyH,CAAT,CAAiB,CACnB,MAAOvB,CAAAA,EAAmB,CAACjK,CAAD,CAASvC,CAAT,CAAec,CAAf,CAAuB,EAAvB,CAA2BiN,CAA3B,CAAmC,EAAnC,OAC7B,CAHE,CAIV,CALD,IAKO,CACH,MAAOvO,CAAAA,CAAG,CAACqK,UAAJ,CAAe,kBAAf,CAAmC,cAAnC,CAAmDyB,CAAI,CAACC,QAAxD,EACFjF,IADE,CACG,SAASyH,CAAT,CAAiB,CACnB,MAAOvB,CAAAA,EAAmB,CAACjK,CAAD,CAASvC,CAAT,CAAec,CAAf,CAAuB,CAAClB,CAAS,CAACoO,oBAAX,CAAvB,CAAyDD,CAAzD,CAAiE,EAAjE,OAC7B,CAHE,CAIV,CACJ,CAZD,IAYO,CACH,MAAOJ,CAAAA,EAAmB,CAACpL,CAAD,CAASvC,CAAT,CAAec,CAAf,CAC7B,CACJ,CAjhCH,CA4hCMmN,EAAwB,CAAG,SAAS1L,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BwK,CAA/B,CAAqC,CAChE,GAAIA,CAAJ,CAAU,CACN,MAAO9L,CAAAA,CAAG,CAACqK,UAAJ,CAAe,oBAAf,CAAqC,cAArC,CAAqDyB,CAAI,CAACC,QAA1D,EACFjF,IADE,CACG,SAASyH,CAAT,CAAiB,CACnB,MAAOvB,CAAAA,EAAmB,CAACjK,CAAD,CAASvC,CAAT,CAAec,CAAf,CAAuB,CAAClB,CAAS,CAACsO,sBAAX,CAAvB,CAA2DH,CAA3D,CAAmE,EAAnE,OAC7B,CAHE,CAIV,CALD,IAKO,CACH,MAAOJ,CAAAA,EAAmB,CAACpL,CAAD,CAASvC,CAAT,CAAec,CAAf,CAC7B,CACJ,CAriCH,CAgjCMqN,EAAuB,CAAG,SAAS5L,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BwK,CAA/B,CAAqC,CAC/D,GAAIA,CAAJ,CAAU,CACN,MAAO9L,CAAAA,CAAG,CAACqK,UAAJ,CAAe,mBAAf,CAAoC,cAApC,CAAoDyB,CAAI,CAACC,QAAzD,EACFjF,IADE,CACG,SAASyH,CAAT,CAAiB,CACnB,MAAOvB,CAAAA,EAAmB,CACtBjK,CADsB,CAEtBvC,CAFsB,CAGtBc,CAHsB,CAItB,CAAClB,CAAS,CAACwO,0BAAX,CAJsB,CAKtBL,CALsB,CAMtB,EANsB,OAU7B,CAZE,CAaV,CAdD,IAcO,CACH,MAAOJ,CAAAA,EAAmB,CAACpL,CAAD,CAASvC,CAAT,CAAec,CAAf,CAC7B,CACJ,CAlkCH,CA6kCMuN,EAA0B,CAAG,SAAS9L,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BwK,CAA/B,CAAqC,CAClE,GAAIA,CAAJ,CAAU,CACN,MAAO9L,CAAAA,CAAG,CAACqK,UAAJ,CAAe,sBAAf,CAAuC,cAAvC,CAAuDyB,CAAI,CAACC,QAA5D,EACFjF,IADE,CACG,SAASyH,CAAT,CAAiB,CACnB,MAAOvB,CAAAA,EAAmB,CACtBjK,CADsB,CAEtBvC,CAFsB,CAGtBc,CAHsB,CAItB,CAAClB,CAAS,CAAC0O,6BAAX,CAJsB,CAKtBP,CALsB,CAMtB,EANsB,OAU7B,CAZE,CAaV,CAdD,IAcO,CACH,MAAOJ,CAAAA,EAAmB,CAACpL,CAAD,CAASvC,CAAT,CAAec,CAAf,CAC7B,CACJ,CA/lCH,CA0mCMyN,EAAmC,CAAG,SAAShM,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BkF,CAA/B,CAAqC,CAC3E,GAAIwI,CAAAA,CAAW,CAAG,IAAlB,CACA,GAAIxI,CAAI,CAACwE,IAAL,EAAa1K,CAAkB,CAAC+K,IAApC,CAA0C,CAEtC2D,CAAW,CAAG,+CACjB,CAHD,IAGO,CAEH,GAAIxI,CAAI,CAACyI,4BAAT,CAAuC,CACnCC,EAAuB,CAAC1O,CAAD,CAAvB,CACAwO,CAAW,CAAG,0CACjB,CAHD,IAGO,CACHA,CAAW,CAAG,+BACjB,CACJ,CAED,GAAIxI,CAAI,CAAC2I,IAAT,CAAe,CACX,MAAOnP,CAAAA,CAAG,CAACqK,UAAJ,CAAe2E,CAAf,CAA4B,cAA5B,EACFlI,IADE,CACG,SAASyH,CAAT,CAAiB,CACnB,MAAOvB,CAAAA,EAAmB,CACtBjK,CADsB,CAEtBvC,CAFsB,CAGtBc,CAHsB,CAItB,CAAClB,CAAS,CAACgP,uCAAX,CAJsB,CAKtBb,CALsB,CAMtB,EANsB,OAU7B,CAZE,CAaV,CAdD,IAcO,CACH,MAAOJ,CAAAA,EAAmB,CAACpL,CAAD,CAASvC,CAAT,CAAec,CAAf,CAC7B,CACJ,CA1oCH,CAqpCM+N,EAA+B,CAAG,SAAStM,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+B0J,CAA/B,CAAqC,CACvE,GAAIgE,CAAAA,CAAW,CAAG,IAAlB,CACA,GAAIhE,CAAI,EAAI1K,CAAkB,CAAC+K,IAA/B,CAAqC,CAEjC2D,CAAW,CAAG,sBACjB,CAHD,IAGO,IAAIhE,CAAJ,CAAU,CAEbgE,CAAW,CAAG,kBACjB,CAED,GAAIA,CAAJ,CAAiB,CACb,MAAOhP,CAAAA,CAAG,CAACqK,UAAJ,CAAe2E,CAAf,CAA4B,cAA5B,EACFlI,IADE,CACG,SAASyH,CAAT,CAAiB,CACnB,MAAOvB,CAAAA,EAAmB,CACtBjK,CADsB,CAEtBvC,CAFsB,CAGtBc,CAHsB,CAItB,CAAClB,CAAS,CAACkP,kCAAX,CAJsB,CAKtBf,CALsB,CAMtB,EANsB,OAU7B,CAZE,CAaV,CAdD,IAcO,CACH,MAAOJ,CAAAA,EAAmB,CAACpL,CAAD,CAASvC,CAAT,CAAec,CAAf,CAC7B,CACJ,CAhrCH,CA2rCMiO,EAA2B,CAAG,SAASxM,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BwK,CAA/B,CAAqC,CACnE,GAAIA,CAAJ,CAAU,CACN,MAAO9L,CAAAA,CAAG,CAACqK,UAAJ,CAAe,2BAAf,CAA4C,cAA5C,CAA4DyB,CAAI,CAACC,QAAjE,EACFjF,IADE,CACG,SAASyH,CAAT,CAAiB,CACnB,GAAItB,CAAAA,CAAe,CAAG,CAClB7M,CAAS,CAACoP,6BADQ,CAElBpP,CAAS,CAACqP,8BAFQ,CAAtB,CAIA,MAAOzC,CAAAA,EAAmB,CAACjK,CAAD,CAASvC,CAAT,CAAec,CAAf,CAAuB2L,CAAvB,CAAwCsB,CAAxC,CAAgD,EAAhD,OAC7B,CAPE,CAQV,CATD,IASO,CACH,MAAOJ,CAAAA,EAAmB,CAACpL,CAAD,CAASvC,CAAT,CAAec,CAAf,CAC7B,CACJ,CAxsCH,CA+sCM4N,EAAuB,CAAG,SAAS1O,CAAT,CAAe,IACrC8M,CAAAA,CAAQ,CAAG5I,CAA2B,CAAClE,CAAD,CADD,CAErCkP,CAAc,CAAGpC,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAACuP,8CAAxB,CAFoB,CAGzCD,CAAc,CAAC9O,WAAf,CAA2B,QAA3B,CACH,CAntCH,CA0tCMwN,EAAuB,CAAG,SAAS5N,CAAT,CAAe,IACrC8M,CAAAA,CAAQ,CAAG5I,CAA2B,CAAClE,CAAD,CADD,CAErCkP,CAAc,CAAGpC,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAACuP,8CAAxB,CAFoB,CAGrCC,CAAQ,CAAGtC,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAACyP,oCAAxB,CAH0B,CAIzCD,CAAQ,CAACE,IAAT,CAAc,SAAd,KACAJ,CAAc,CAAC5O,QAAf,CAAwB,QAAxB,CACH,CAhuCH,CA0uCMiP,EAAe,CAAG,SAAShN,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+B0O,CAA/B,CAA0C,CAC5D,GAAIA,CAAJ,CAAe,CACXjN,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAAC6P,oBAAtB,EAA4CnP,QAA5C,CAAqD,QAArD,EACAiC,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAAC8P,sBAAtB,EAA8CtP,WAA9C,CAA0D,QAA1D,CACH,CAHD,IAGO,CACHmC,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAAC6P,oBAAtB,EAA4CrP,WAA5C,CAAwD,QAAxD,EACAmC,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAAC8P,sBAAtB,EAA8CpP,QAA9C,CAAuD,QAAvD,CACH,CACJ,CAlvCH,CA6vCMqP,EAAiB,CAAG,SAASpN,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+B8O,CAA/B,CAAsC,IACtDC,CAAAA,CAAa,CAAGtN,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAACkQ,wBAAtB,CADsC,CAEtDC,CAAY,CAAGxN,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAACoQ,wBAAtB,CAFuC,CAGtDC,CAAe,CAAG1N,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAACsQ,0BAAtB,CAHoC,CAK1D,OAAQN,CAAR,EACI,IAAK,MAAL,CACIC,CAAa,CAACvP,QAAd,CAAuB,QAAvB,EACAyP,CAAY,CAACzP,QAAb,CAAsB,QAAtB,EACA2P,CAAe,CAAC3P,QAAhB,CAAyB,QAAzB,EACA,MACJ,IAAK,UAAL,CACIuP,CAAa,CAACvP,QAAd,CAAuB,QAAvB,EACAyP,CAAY,CAAC3P,WAAb,CAAyB,QAAzB,EACA6P,CAAe,CAAC3P,QAAhB,CAAyB,QAAzB,EACA,MACJ,IAAK,aAAL,CACIuP,CAAa,CAACzP,WAAd,CAA0B,QAA1B,EACA2P,CAAY,CAACzP,QAAb,CAAsB,QAAtB,EACA2P,CAAe,CAAC7P,WAAhB,CAA4B,QAA5B,EACA,MAfR,CAiBH,CAnxCH,CA8xCM+P,EAAa,CAAG,SAAS5N,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+B8O,CAA/B,CAAsC,IAClDQ,CAAAA,CAAQ,CAAG7N,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAACyQ,oBAAtB,CADuC,CAElDC,CAAQ,CAAG/N,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAAC2Q,mBAAtB,CAFuC,CAGlDC,CAAU,CAAGjO,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAAC6Q,qBAAtB,CAHqC,CAKtD,OAAQb,CAAR,EACI,IAAK,MAAL,CACIQ,CAAQ,CAAC9P,QAAT,CAAkB,QAAlB,EACAgQ,CAAQ,CAAChQ,QAAT,CAAkB,QAAlB,EACAkQ,CAAU,CAAClQ,QAAX,CAAoB,QAApB,EACA,MACJ,IAAK,WAAL,CACI8P,CAAQ,CAAC9P,QAAT,CAAkB,QAAlB,EACAgQ,CAAQ,CAAClQ,WAAT,CAAqB,QAArB,EACAoQ,CAAU,CAAClQ,QAAX,CAAoB,QAApB,EACA,MACJ,IAAK,aAAL,CACI8P,CAAQ,CAAChQ,WAAT,CAAqB,QAArB,EACAkQ,CAAQ,CAAChQ,QAAT,CAAkB,QAAlB,EACAkQ,CAAU,CAACpQ,WAAX,CAAuB,QAAvB,EACA,MAfR,CAiBH,CApzCH,CA8zCMsQ,EAAe,CAAG,SAASnO,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+B8O,CAA/B,CAAsC,IACpDe,CAAAA,CAAU,CAAGpO,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAACgR,0BAAtB,CADuC,CAEpDC,CAAa,CAAGtO,CAAM,CAACtC,IAAP,CAAYL,CAAS,CAACkR,6BAAtB,CAFoC,CAIxD,OAAQlB,CAAR,EACI,IAAK,iBAAL,CACIe,CAAU,CAACrQ,QAAX,CAAoB,QAApB,EACAuQ,CAAa,CAACvQ,QAAd,CAAuB,QAAvB,EACA,MACJ,IAAK,SAAL,CACIqQ,CAAU,CAACrQ,QAAX,CAAoB,QAApB,EACAuQ,CAAa,CAACzQ,WAAd,CAA0B,QAA1B,EACA,MACJ,IAAK,aAAL,CACIuQ,CAAU,CAACvQ,WAAX,CAAuB,QAAvB,EACAyQ,CAAa,CAACvQ,QAAd,CAAuB,QAAvB,EACA,MAZR,CAcH,CAh1CH,CA01CMyQ,EAA0B,CAAG,SAASxO,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+ByL,CAA/B,CAA0C,IACnEO,CAAAA,CAAQ,CAAG5I,CAA2B,CAAClE,CAAD,CAD6B,CAEnE+M,CAAO,CAAGD,CAAQ,CAAC7M,IAAT,CAAc,QAAd,CAFyD,CAGnE+Q,CAAU,CAAGlE,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAACqR,4BAAxB,CAHsD,CAInEC,CAAW,CAAGpE,CAAQ,CAAC7M,IAAT,CAAcL,CAAS,CAACgI,sBAAxB,CAJqD,CAMvE,GAAI2E,CAAJ,CAAe,CACXQ,CAAO,CAACuC,IAAR,CAAa,UAAb,KACA0B,CAAU,CAAC1Q,QAAX,CAAoB,QAApB,EACA4Q,CAAW,CAAC9Q,WAAZ,CAAwB,QAAxB,CACH,CAJD,IAIO,CACH2M,CAAO,CAACuC,IAAR,CAAa,UAAb,KACA0B,CAAU,CAAC5Q,WAAX,CAAuB,QAAvB,EACA8Q,CAAW,CAAC5Q,QAAZ,CAAqB,QAArB,CACH,CACJ,CAz2CH,CAm3CM6Q,EAAgB,CAAG,SAAS5O,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BsQ,CAA/B,CAA2C,CAC9D,GAAIpM,CAAAA,CAAQ,CAAG,IAAf,CAEA,GAAIoM,CAAJ,CAAgB,CACZpM,CAAQ,CAAGhF,CAAI,CAACC,IAAL,CAAUL,CAAS,CAACyR,oBAApB,CAAX,CACArM,CAAQ,CAAC/E,IAAT,CAAcL,CAAS,CAAC0R,yBAAxB,EAAmDlR,WAAnD,CAA+D,QAA/D,EACAoC,CAAiB,CAACD,CAAD,CAAjB,CACAc,CAAkB,CAACd,CAAD,CACrB,CALD,IAKO,CACHyC,CAAQ,CAAGjF,CAAoB,CAACC,CAAD,CAA/B,CACAgF,CAAQ,CAAC/E,IAAT,CAAcL,CAAS,CAAC0R,yBAAxB,EAAmDhR,QAAnD,CAA4D,QAA5D,EACA0E,CAAQ,CAAC/E,IAAT,CAAcL,CAAS,CAAC2R,qBAAxB,EAA+CjR,QAA/C,CAAwD,QAAxD,EACA4C,CAAiB,CAACX,CAAD,CAAjB,CACAE,CAAkB,CAACF,CAAD,CACrB,CACJ,CAl4CH,CA44CMiP,EAAsB,CAAG,SAASjP,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BkF,CAA/B,CAAqC,CAC9D,GAAIyL,CAAAA,CAAmB,CAAgB,CAAb,CAAAzL,CAAI,CAAC0L,KAA/B,CAEA,GAAI1L,CAAI,CAAC8C,GAAL,CAASC,MAAb,CAAqB,CACjB/C,CAAI,CAAC8C,GAAL,CAASvC,OAAT,CAAiB,SAAS7C,CAAT,CAAoB,CACjC,GAAIyB,CAAAA,CAAO,CAAG1B,CAAiB,CAACzD,CAAD,CAAO0D,CAAP,CAA/B,CACAyB,CAAO,CAAClF,IAAR,CAAaL,CAAS,CAAC0R,yBAAvB,EAAkDhR,QAAlD,CAA2D,QAA3D,EACA6E,CAAO,CAAClF,IAAR,CAAaL,CAAS,CAAC2R,qBAAvB,EAA8CnR,WAA9C,CAA0D,QAA1D,EACA+E,CAAO,CAACX,IAAR,CAAa,cAAb,IACH,CALD,CAMH,CAED,GAAIwB,CAAI,CAACyC,MAAL,CAAYM,MAAhB,CAAwB,CACpB/C,CAAI,CAACyC,MAAL,CAAYlC,OAAZ,CAAoB,SAAS7C,CAAT,CAAoB,CACpC,GAAIyB,CAAAA,CAAO,CAAG1B,CAAiB,CAACzD,CAAD,CAAO0D,CAAP,CAA/B,CAEA,GAAI+N,CAAJ,CAAyB,CACrBtM,CAAO,CAAClF,IAAR,CAAaL,CAAS,CAAC0R,yBAAvB,EAAkDlR,WAAlD,CAA8D,QAA9D,CACH,CAED+E,CAAO,CAAClF,IAAR,CAAaL,CAAS,CAAC2R,qBAAvB,EAA8CjR,QAA9C,CAAuD,QAAvD,EACA6E,CAAO,CAACX,IAAR,CAAa,cAAb,IACH,CATD,CAUH,CAEDG,EAAwB,CAACpC,CAAD,CAASyD,CAAI,CAAC0L,KAAd,CAC3B,CAt6CH,CAi7CMC,EAAuB,CAAG,SAASpP,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BkF,CAA/B,CAAqC,CAC/D,GAAIA,CAAI,CAAC2I,IAAL,EAAa,CAAC3I,CAAI,CAAC4L,WAAvB,CAAoC,CAChC,MAAOpS,CAAAA,CAAG,CAAC0L,WAAJ,CAAgB,CACf,CACIC,GAAG,CAAE,yBADT,CAEIC,SAAS,CAAE,cAFf,CAGIC,KAAK,CAAErF,CAAI,CAACsF,IAAL,CAAUC,QAHrB,CADe,CAMf,CACIJ,GAAG,CAAE,qBADT,CAEIC,SAAS,CAAE,cAFf,CAGIC,KAAK,CAAErF,CAAI,CAACsF,IAAL,CAAUC,QAHrB,CANe,CAAhB,EAYFjF,IAZE,CAYG,SAASkF,CAAT,CAAkB,IAChBC,CAAAA,CAAK,CAAGD,CAAO,CAAC,CAAD,CADC,CAEhB1G,CAAI,CAAG0G,CAAO,CAAC,CAAD,CAFE,CAGpB,MAAOgB,CAAAA,EAAmB,CACtBjK,CADsB,CAEtBvC,CAFsB,CAGtBc,CAHsB,CAItB,CAAClB,CAAS,CAACgR,0BAAX,CAJsB,CAKtB9L,CALsB,CAMtB2G,CANsB,OAU7B,CAzBE,CA0BV,CA3BD,IA2BO,CACH,MAAOkC,CAAAA,EAAmB,CAACpL,CAAD,CAASvC,CAAT,CAAec,CAAf,CAC7B,CACJ,CAh9CH,CA29CM+Q,EAA6B,CAAG,SAAStP,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BgR,CAA/B,CAA+C,CAC/E,GAAIxN,CAAAA,CAAS,CAAG/D,CAAmC,CAACP,CAAD,CAAnD,CACA,GAAI8R,CAAJ,CAAoB,CAChBxN,CAAS,CAAClE,WAAV,CAAsB,QAAtB,CACH,CAFD,IAEO,CACHkE,CAAS,CAAChE,QAAV,CAAmB,QAAnB,CACH,CACD,QACH,CAn+CH,CA8+CMyR,EAAwB,CAAG,SAASxP,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BkR,CAA/B,CAA6C,CACxE,GAAI1N,CAAAA,CAAS,CAAG5D,CAA8B,CAACV,CAAD,CAA9C,CACA,GAAIgS,CAAJ,CAAkB,CACd,MAAOxS,CAAAA,CAAG,CAACqK,UAAJ,CAAe,2BAAf,CAA4C,cAA5C,CAA4DmI,CAA5D,EACF1L,IADE,CACG,SAASyH,CAAT,CAAiB,CACnBzJ,CAAS,CAACrE,IAAV,CAAeL,CAAS,CAACgM,IAAzB,EAA+B9G,IAA/B,CAAoCiJ,CAApC,EACAzJ,CAAS,CAAClE,WAAV,CAAsB,QAAtB,EACA,MAAO2N,CAAAA,CACV,CALE,CAMV,CAPD,IAOO,CACHzJ,CAAS,CAAChE,QAAV,CAAmB,QAAnB,EACA,QACH,CACJ,CA3/CH,CAqgDM2R,EAAW,CAAG,SAAS1P,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+B,CAC7C6M,EAAmB,CAACpL,CAAD,CAASvC,CAAT,CAAec,CAAf,CAAnB,CACAF,CAA+B,CAACZ,CAAD,CAA/B,CACAS,CAAoC,CAACT,CAAD,CAApC,CACAsC,CAAqB,CAACC,CAAD,CAArB,CACAiB,CAAqB,CAACjB,CAAD,CAArB,CACAI,CAAqB,CAAC7B,CAAD,CAArB,CACAU,CAAqB,CAACV,CAAD,CAArB,CACA,QACH,CA9gDH,CA0lDE,MAAO,CACHmF,MAAM,CA3EG,QAATA,CAAAA,MAAS,CAAS1D,CAAT,CAAiBvC,CAAjB,CAAuBc,CAAvB,CAA+BoR,CAA/B,CAAsC,IAC3CC,CAAAA,CAAO,CAAG,CACV,CAEIC,KAAK,CAAEH,EAFX,CADU,CAKV,CAGII,YAAY,CAAE1J,EAHlB,CAIIpG,MAAM,CAAE2H,EAJZ,CAKIpJ,MAAM,CAAEmK,EALZ,CAMIqH,gBAAgB,CAAEzE,EANtB,CAOI0E,kBAAkB,CAAEtE,EAPxB,CAQIuE,iBAAiB,CAAErE,EARvB,CASIsE,oBAAoB,CAAEpE,EAT1B,CAUIqE,6BAA6B,CAAEnE,EAVnC,CAWIoE,yBAAyB,CAAE9D,EAX/B,CAYI+D,qBAAqB,CAAE7D,EAZ3B,CAaI8D,iBAAiB,CAAElB,EAbvB,CAcImB,uBAAuB,CAAEjB,EAd7B,CAeIkB,kBAAkB,CAAEhB,EAfxB,CALU,CAsBV,CACIiB,cAAc,CAAE9G,EADpB,CAEI+G,oBAAoB,CAAE7G,EAF1B,CAGI8G,eAAe,CAAE5G,EAHrB,CAIIkD,SAAS,CAAED,EAJf,CAKI4D,SAAS,CAAEzC,EALf,CAMI0C,WAAW,CAAEzD,EANjB,CAOI0D,OAAO,CAAElD,EAPb,CAQImD,oBAAoB,CAAEvC,EAR1B,CASIK,UAAU,CAAED,EAThB,CAtBU,CAiCV,CAGIoC,eAAe,CAAE1H,EAHrB,CAII2H,gBAAgB,CAAEhC,EAJtB,CAjCU,CADiC,CA0C3CiC,CAAa,CAAG,SAASC,CAAT,CAAiB,CACjC,GAAIC,CAAAA,CAAO,CAAG,EAAd,CAEA,IAAK,GAAIxI,CAAAA,CAAT,GAAgB+G,CAAAA,CAAhB,CAAuB,CACnB,GAAIwB,CAAM,CAACE,cAAP,CAAsBzI,CAAtB,CAAJ,CAAgC,IACxB0I,CAAAA,CAAU,CAAGH,CAAM,CAACvI,CAAD,CADK,CAExB2I,CAAU,CAAG5B,CAAK,CAAC/G,CAAD,CAFM,CAG5BwI,CAAO,CAAC/J,IAAR,CAAaiK,CAAU,CAACtR,CAAD,CAASvC,CAAT,CAAec,CAAf,CAAuBgT,CAAvB,CAAvB,CACH,CACJ,CAED,MAAOH,CAAAA,CACV,CAtD8C,CAyD3C/K,CAAiB,CAAG6K,CAAa,CAACtB,CAAO,CAAC,CAAD,CAAR,CAzDU,CA2D/CvJ,CAAiB,CAAGA,CAAiB,CAACY,MAAlB,CAAyBiK,CAAa,CAACtB,CAAO,CAAC,CAAD,CAAR,CAAtC,CAApB,CAIA,MAAO7S,CAAAA,CAAC,CAAC8G,IAAF,CAAOC,KAAP,CAAa/G,CAAb,CAAgBsJ,CAAhB,EACFtC,IADE,CACG,UAAW,CACb,IAAK,GAAIyN,CAAAA,CAAC,CAAG,CAAb,CAAgBA,CAAC,CAAG5B,CAAO,CAACpJ,MAA5B,CAAoCgL,CAAC,EAArC,CAAyC,CACrCN,CAAa,CAACtB,CAAO,CAAC4B,CAAD,CAAR,CAChB,CAGJ,CAPE,EAQFjN,KARE,CAQIvH,CAAY,CAACyU,SARjB,CASV,CAEM,CAGV,CA7mDK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * This module updates the UI for the conversation page in the message\n * drawer.\n *\n * The module will take a patch from the message_drawer_view_conversation_patcher\n * module and update the UI to reflect the changes.\n *\n * This is the only module that ever modifies the UI of the conversation page.\n *\n * @module     core_message/message_drawer_view_conversation_renderer\n * @copyright  2018 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n    'jquery',\n    'core/notification',\n    'core/str',\n    'core/templates',\n    'core/user_date',\n    'core_message/message_drawer_view_conversation_constants'\n],\nfunction(\n    $,\n    Notification,\n    Str,\n    Templates,\n    UserDate,\n    Constants\n) {\n    var SELECTORS = Constants.SELECTORS;\n    var TEMPLATES = Constants.TEMPLATES;\n    var CONVERSATION_TYPES = Constants.CONVERSATION_TYPES;\n\n    /**\n     * Get the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getMessagesContainer = function(body) {\n        return body.find(SELECTORS.CONTENT_MESSAGES_CONTAINER);\n    };\n\n    /**\n     * Show the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showMessagesContainer = function(body) {\n        getMessagesContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideMessagesContainer = function(body) {\n        getMessagesContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the self-conversation message container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getSelfConversationMessageContainer = function(body) {\n        return body.find(SELECTORS.SELF_CONVERSATION_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Hide the self-conversation message container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var hideSelfConversationMessageContainer = function(body) {\n        return getSelfConversationMessageContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the contact request sent container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getContactRequestSentContainer = function(body) {\n        return body.find(SELECTORS.CONTACT_REQUEST_SENT_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Hide the contact request sent container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var hideContactRequestSentContainer = function(body) {\n        return getContactRequestSentContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer container element.\n     */\n    var getFooterContentContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_CONTAINER);\n    };\n\n    /**\n     * Show the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterContent = function(footer) {\n        getFooterContentContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterContent = function(footer) {\n        getFooterContentContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer container element.\n     */\n    var getFooterEditModeContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER);\n    };\n\n    /**\n     * Show the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterEditMode = function(footer) {\n        getFooterEditModeContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterEditMode = function(footer) {\n        getFooterEditModeContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer placeholder.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer placeholder container element.\n     */\n    var getFooterPlaceholderContainer = function(footer) {\n        return footer.find(SELECTORS.PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the footer placeholder\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterPlaceholder = function(footer) {\n        getFooterPlaceholderContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer placeholder\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterPlaceholder = function(footer) {\n        getFooterPlaceholderContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Require add as contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Require add as contact container element.\n     */\n    var getFooterRequireContactContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER);\n    };\n\n    /**\n     * Show the footer add as contact dialogue.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterRequireContact = function(footer) {\n        getFooterRequireContactContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer add as contact dialogue.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterRequireContact = function(footer) {\n        getFooterRequireContactContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Required to unblock contact container element.\n     */\n    var getFooterRequireUnblockContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER);\n    };\n\n    /**\n     * Show the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterRequireUnblock = function(footer) {\n        getFooterRequireUnblockContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterRequireUnblock = function(footer) {\n        getFooterRequireUnblockContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Unable to message contact container element.\n     */\n    var getFooterUnableToMessageContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Show the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterUnableToMessage = function(footer) {\n        getFooterUnableToMessageContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterUnableToMessage = function(footer) {\n        getFooterUnableToMessageContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Hide all header elements.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideAllHeaderElements = function(header) {\n        hideHeaderContent(header);\n        hideHeaderEditMode(header);\n        hideHeaderPlaceholder(header);\n    };\n\n    /**\n     * Hide all footer dialogues and messages.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideAllFooterElements = function(footer) {\n        hideFooterContent(footer);\n        hideFooterEditMode(footer);\n        hideFooterPlaceholder(footer);\n        hideFooterRequireContact(footer);\n        hideFooterRequireUnblock(footer);\n        hideFooterUnableToMessage(footer);\n    };\n\n    /**\n     * Get the content placeholder container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The body placeholder container element.\n     */\n    var getContentPlaceholderContainer = function(body) {\n        return body.find(SELECTORS.CONTENT_PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the content placeholder.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showContentPlaceholder = function(body) {\n        getContentPlaceholderContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the content placeholder.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideContentPlaceholder = function(body) {\n        getContentPlaceholderContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the header content container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header content container element.\n     */\n    var getHeaderContent = function(header) {\n        return header.find(SELECTORS.HEADER);\n    };\n\n    /**\n     * Show the header content.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderContent = function(header) {\n        getHeaderContent(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header content.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderContent = function(header) {\n        getHeaderContent(header).addClass('hidden');\n    };\n\n    /**\n     * Get the header edit mode container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header content container element.\n     */\n    var getHeaderEditMode = function(header) {\n        return header.find(SELECTORS.HEADER_EDIT_MODE);\n    };\n\n    /**\n     * Show the header edit mode container.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderEditMode = function(header) {\n        getHeaderEditMode(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header edit mode container.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderEditMode = function(header) {\n        getHeaderEditMode(header).addClass('hidden');\n    };\n\n    /**\n     * Get the header placeholder container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header placeholder container element.\n     */\n    var getHeaderPlaceholderContainer = function(header) {\n        return header.find(SELECTORS.HEADER_PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the header placeholder.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderPlaceholder = function(header) {\n        getHeaderPlaceholderContainer(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header placeholder.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderPlaceholder = function(header) {\n        getHeaderPlaceholderContainer(header).addClass('hidden');\n    };\n\n    /**\n     * Get a message element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Number} messageId the Message id.\n     * @return {Object} A message element from the conversation.\n     */\n    var getMessageElement = function(body, messageId) {\n        var messagesContainer = getMessagesContainer(body);\n        return messagesContainer.find('[data-message-id=\"' + messageId + '\"]');\n    };\n\n    /**\n     * Get the day container element. The day container element holds a list of messages for that day.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Number} dayTimeCreated Midnight timestamp for the day.\n     * @return {Object} jQuery object\n     */\n    var getDayElement = function(body, dayTimeCreated) {\n        var messagesContainer = getMessagesContainer(body);\n        return messagesContainer.find('[data-day-id=\"' + dayTimeCreated + '\"]');\n    };\n\n    /**\n     * Get the more messages loading icon container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The more messages loading container element.\n     */\n    var getMoreMessagesLoadingIconContainer = function(body) {\n        return body.find(SELECTORS.MORE_MESSAGES_LOADING_ICON_CONTAINER);\n    };\n\n    /**\n     * Show the more messages loading icon.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showMoreMessagesLoadingIcon = function(body) {\n        getMoreMessagesLoadingIconContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the more messages loading icon.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideMoreMessagesLoadingIcon = function(body) {\n        getMoreMessagesLoadingIconContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element to search.\n     * @return {Object} The confirm dialogue container element.\n     */\n    var getConfirmDialogueContainer = function(root) {\n        return root.find(SELECTORS.CONFIRM_DIALOGUE_CONTAINER);\n    };\n\n    /**\n     * Show the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element containing a dialogue.\n     */\n    var showConfirmDialogueContainer = function(root) {\n        var container = getConfirmDialogueContainer(root);\n        var siblings = container.siblings(':not(.hidden)');\n        siblings.attr('aria-hidden', true);\n        siblings.attr('tabindex', -1);\n        siblings.attr('data-confirm-dialogue-hidden', true);\n\n        container.removeClass('hidden');\n    };\n\n    /**\n     * Hide the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element containing a dialogue.\n     */\n    var hideConfirmDialogueContainer = function(root) {\n        var container = getConfirmDialogueContainer(root);\n        var siblings = container.siblings('[data-confirm-dialogue-hidden=\"true\"]');\n        siblings.removeAttr('aria-hidden');\n        siblings.removeAttr('tabindex');\n        siblings.removeAttr('data-confirm-dialogue-hidden');\n\n        container.addClass('hidden');\n    };\n\n    /**\n     * Set the number of selected messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Number} value The new number to display.\n     */\n    var setMessagesSelectedCount = function(header, value) {\n        getHeaderEditMode(header).find(SELECTORS.MESSAGES_SELECTED_COUNT).text(value);\n    };\n\n    /**\n     * Format message for the mustache template, transform camelCase properties to lowercase properties.\n     *\n     * @param  {Array} messages Array of message objects.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Array} Messages formated for mustache template.\n     */\n    var formatMessagesForTemplate = function(messages, datesCache) {\n        return messages.map(function(message) {\n            return {\n                id: message.id,\n                isread: message.isRead,\n                fromloggedinuser: message.fromLoggedInUser,\n                userfrom: message.userFrom,\n                text: message.text,\n                formattedtime: message.timeCreated ? datesCache[message.timeCreated] : null\n            };\n        });\n    };\n\n    /**\n     * Create rendering promises for each day containing messages.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} days Array of days containing messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Promise} Days rendering promises.\n     */\n    var renderAddDays = function(header, body, footer, days, datesCache) {\n        var messagesContainer = getMessagesContainer(body);\n        var daysRenderPromises = days.map(function(data) {\n            return Templates.render(TEMPLATES.DAY, {\n                timestamp: data.value.timestamp,\n                messages: formatMessagesForTemplate(data.value.messages, datesCache)\n            });\n        });\n\n        return $.when.apply($, daysRenderPromises).then(function() {\n            // Wait until all of the rendering is done for each of the days\n            // to ensure they are added to the page in the correct order.\n            days.forEach(function(data, index) {\n                daysRenderPromises[index]\n                    .then(function(html) {\n                        if (data.before) {\n                            var element = getDayElement(body, data.before.timestamp);\n                            return $(html).insertBefore(element);\n                        } else {\n                            return messagesContainer.append(html);\n                        }\n                    })\n                    .catch(function() {\n                        // Fail silently.\n                    });\n            });\n\n            return;\n        });\n    };\n\n    /**\n     * Add (more) messages to day containers.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} messages List of messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Promise} Messages rendering promises.\n     */\n    var renderAddMessages = function(header, body, footer, messages, datesCache) {\n        var messagesData = messages.map(function(data) {\n            return data.value;\n        });\n        var formattedMessages = formatMessagesForTemplate(messagesData, datesCache);\n\n        return Templates.render(TEMPLATES.MESSAGES, {messages: formattedMessages})\n            .then(function(html) {\n                var messageList = $(html);\n                messages.forEach(function(data) {\n                    var messageHtml = messageList.find('[data-message-id=\"' + data.value.id + '\"]');\n                    if (data.before) {\n                        var element = getMessageElement(body, data.before.id);\n                        return messageHtml.insertBefore(element);\n                    } else {\n                        var dayContainer = getDayElement(body, data.day.timestamp);\n                        var dayMessagesContainer = dayContainer.find(SELECTORS.DAY_MESSAGES_CONTAINER);\n                        return dayMessagesContainer.append(messageHtml);\n                    }\n                });\n\n                return;\n            });\n    };\n\n    /**\n     * Update existing messages.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} messages List of messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     */\n    var renderUpdateMessages = function(header, body, footer, messages, datesCache) {\n        messages.forEach(function(message) {\n            var before = message.before;\n            var after = message.after;\n            var element = getMessageElement(body, before.id);\n\n            if (before.id != after.id) {\n                element.attr('data-message-id', after.id);\n            }\n\n            if (before.timeCreated != after.timeCreated) {\n                var formattedTime = datesCache[after.timeCreated];\n                element.find(SELECTORS.LOADING_ICON_CONTAINER).addClass('hidden');\n                element.find(SELECTORS.TIME_CREATED).text(formattedTime).removeClass('hidden');\n            }\n\n            if (before.sendState != after.sendState) {\n                var loading = element.find(SELECTORS.LOADING_ICON_CONTAINER);\n                var time = element.find(SELECTORS.TIME_CREATED);\n                var retry = element.find(SELECTORS.RETRY_SEND);\n\n                loading.addClass('hidden');\n                loading.attr('aria-hidden', 'true');\n                time.addClass('hidden');\n                time.attr('aria-hidden', 'true');\n                retry.addClass('hidden');\n                retry.attr('aria-hidden', 'true');\n                element.removeClass('border border-danger');\n\n                switch (after.sendState) {\n                    case 'pending':\n                        loading.removeClass('hidden');\n                        loading.attr('aria-hidden', 'false');\n                        break;\n                    case 'error':\n                        retry.removeClass('hidden');\n                        retry.attr('aria-hidden', 'false');\n                        element.addClass('border border-danger');\n                        break;\n                    case 'sent':\n                        time.removeClass('hidden');\n                        time.attr('aria-hidden', 'false');\n                        break;\n                }\n            }\n\n            if (before.text != after.text) {\n                element.find(SELECTORS.TEXT_CONTAINER).html(after.text);\n            }\n\n            if (before.errorMessage != after.errorMessage) {\n                var messageContainer = element.find(SELECTORS.ERROR_MESSAGE_CONTAINER);\n                var message = messageContainer.find(SELECTORS.ERROR_MESSAGE);\n\n                if (after.errorMessage) {\n                    messageContainer.removeClass('hidden');\n                    messageContainer.attr('aria-hidden', 'false');\n                    message.text(after.errorMessage);\n                } else {\n                    messageContainer.addClass('hidden');\n                    messageContainer.attr('aria-hidden', 'true');\n                    message.text('');\n                }\n            }\n        });\n    };\n\n    /**\n     * Remove days from conversation.\n     *\n     * @param  {Object} body The body container element.\n     * @param  {Array} days Array of days to be removed.\n     */\n    var renderRemoveDays = function(body, days) {\n        days.forEach(function(data) {\n            getDayElement(body, data.timestamp).remove();\n        });\n    };\n\n    /**\n     * Remove messages from conversation.\n     *\n     * @param  {Object} body The body container element.\n     * @param  {Array} messages Array of messages to be removed.\n     */\n    var renderRemoveMessages = function(body, messages) {\n        messages.forEach(function(data) {\n            getMessageElement(body, data.id).remove();\n        });\n    };\n\n    /**\n     * Render the full conversation base on input from the statemanager.\n     *\n     * This will pre-load all of the formatted timestamps for each message that\n     * needs to render to reduce the number of networks requests.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Object} data The conversation diff.\n     * @return {Object} jQuery promise.\n     */\n    var renderConversation = function(header, body, footer, data) {\n        var renderingPromises = [];\n        var hasAddDays = data.days.add.length > 0;\n        var hasAddMessages = data.messages.add.length > 0;\n        var hasUpdateMessages = data.messages.update.length > 0;\n        var timestampsToFormat = [];\n        var datesCachePromise = $.Deferred().resolve({}).promise();\n\n        if (hasAddDays) {\n            // Search for all of the timeCreated values in all of the messages in all of\n            // the days that we need to render.\n            timestampsToFormat = timestampsToFormat.concat(data.days.add.reduce(function(carry, day) {\n                return carry.concat(day.value.messages.reduce(function(timestamps, message) {\n                    if (message.timeCreated) {\n                        timestamps.push(message.timeCreated);\n                    }\n                    return timestamps;\n                }, []));\n            }, []));\n        }\n\n        if (hasAddMessages) {\n            // Search for all of the timeCreated values in all of the messages that we\n            // need to render.\n            timestampsToFormat = timestampsToFormat.concat(data.messages.add.reduce(function(timestamps, message) {\n                if (message.value.timeCreated) {\n                    timestamps.push(message.value.timeCreated);\n                }\n                return timestamps;\n            }, []));\n        }\n\n        if (hasUpdateMessages) {\n            timestampsToFormat = timestampsToFormat.concat(data.messages.update.reduce(function(timestamps, message) {\n                if (message.before.timeCreated != message.after.timeCreated) {\n                    timestamps.push(message.after.timeCreated);\n                }\n                return timestamps;\n            }, []));\n        }\n\n        if (timestampsToFormat.length) {\n            // If we have timestamps then pre-load the formatted version of each of them\n            // in a single request to the server. This saves the templates doing multiple\n            // individual requests.\n            datesCachePromise = Str.get_string('strftimetime24', 'core_langconfig')\n                .then(function(format) {\n                    var requests = timestampsToFormat.map(function(timestamp) {\n                        return {\n                            timestamp: timestamp,\n                            format: format\n                        };\n                    });\n\n                    return UserDate.get(requests);\n                })\n                .then(function(formattedTimes) {\n                    return timestampsToFormat.reduce(function(carry, timestamp, index) {\n                        carry[timestamp] = formattedTimes[index];\n                        return carry;\n                    }, {});\n                });\n        }\n\n        if (hasAddDays) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderAddDays(header, body, footer, data.days.add, datesCache);\n            }));\n        }\n\n        if (hasAddMessages) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderAddMessages(header, body, footer, data.messages.add, datesCache);\n            }));\n        }\n\n        if (hasUpdateMessages) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderUpdateMessages(header, body, footer, data.messages.update, datesCache);\n            }));\n        }\n\n        if (data.days.remove.length > 0) {\n            renderRemoveDays(body, data.days.remove);\n        }\n\n        if (data.messages.remove.length > 0) {\n            renderRemoveMessages(body, data.messages.remove);\n        }\n\n        return $.when.apply($, renderingPromises);\n    };\n\n    /**\n     * Render the conversation header.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Data for header.\n     * @return {Object} jQuery promise\n     */\n    var renderHeader = function(header, body, footer, data) {\n        var headerContainer = getHeaderContent(header);\n        var template = TEMPLATES.HEADER_PUBLIC;\n        data.context.showrouteback = (header.attr('data-from-panel') === \"false\");\n        if (data.type == CONVERSATION_TYPES.PRIVATE) {\n            template = data.showControls ? TEMPLATES.HEADER_PRIVATE : TEMPLATES.HEADER_PRIVATE_NO_CONTROLS;\n        } else if (data.type == CONVERSATION_TYPES.SELF) {\n            template = TEMPLATES.HEADER_SELF;\n        }\n\n        return Templates.render(template, data.context)\n            .then(function(html, js) {\n                Templates.replaceNodeContents(headerContainer, html, js);\n                return;\n            });\n    };\n\n    /**\n     * Render the conversation footer.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Data for footer.\n     * @return {Object} jQuery promise.\n     */\n    var renderFooter = function(header, body, footer, data) {\n        hideAllFooterElements(footer);\n\n        switch (data.type) {\n            case 'placeholder':\n                return showFooterPlaceholder(footer);\n            case 'add-contact':\n                return Str.get_strings([\n                        {\n                            key: 'requirecontacttomessage',\n                            component: 'core_message',\n                            param: data.user.fullname\n                        },\n                        {\n                            key: 'isnotinyourcontacts',\n                            component: 'core_message',\n                            param: data.user.fullname\n                        }\n                    ])\n                    .then(function(strings) {\n                        var title = strings[1];\n                        var text = strings[0];\n                        var footerContainer = getFooterRequireContactContainer(footer);\n                        footerContainer.find(SELECTORS.TITLE).text(title);\n                        footerContainer.find(SELECTORS.TEXT).text(text);\n                        showFooterRequireContact(footer);\n                        return strings;\n                    });\n            case 'edit-mode':\n                return showFooterEditMode(footer);\n            case 'content':\n                return showFooterContent(footer);\n            case 'unblock':\n                return showFooterRequireUnblock(footer);\n            case 'unable-to-message':\n                return showFooterUnableToMessage(footer);\n        }\n\n        return true;\n    };\n\n    /**\n     * Scroll to a message in the conversation.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Number} messageId Message id.\n     */\n    var renderScrollToMessage = function(header, body, footer, messageId) {\n        var messagesContainer = getMessagesContainer(body);\n        var messageElement = getMessageElement(body, messageId);\n        var position = messageElement.position();\n        // Scroll the message container down to the top of the message element.\n        if (position) {\n            var scrollTop = messagesContainer.scrollTop() + position.top;\n            messagesContainer.scrollTop(scrollTop);\n        }\n    };\n\n    /**\n     * Hide or show the conversation header.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoadingMembers Members loading.\n     */\n    var renderLoadingMembers = function(header, body, footer, isLoadingMembers) {\n        if (isLoadingMembers) {\n            hideHeaderContent(header);\n            showHeaderPlaceholder(header);\n        } else {\n            showHeaderContent(header);\n            hideHeaderPlaceholder(header);\n        }\n    };\n\n    /**\n     * Hide or show loading conversation messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoadingFirstMessages Messages loading.\n     */\n    var renderLoadingFirstMessages = function(header, body, footer, isLoadingFirstMessages) {\n        if (isLoadingFirstMessages) {\n            hideMessagesContainer(body);\n            showContentPlaceholder(body);\n        } else {\n            showMessagesContainer(body);\n            hideContentPlaceholder(body);\n        }\n    };\n\n    /**\n     * Hide or show loading more messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoading Messages loading.\n     */\n    var renderLoadingMessages = function(header, body, footer, isLoading) {\n        if (isLoading) {\n            showMoreMessagesLoadingIcon(body);\n        } else {\n            hideMoreMessagesLoadingIcon(body);\n        }\n    };\n\n    /**\n     * Show a confirmation dialogue\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {String} buttonSelectors Selectors for the buttons to show.\n     * @param {String} bodyText Text to show in dialogue.\n     * @param {String} headerText Text to show in dialogue header.\n     * @param {Bool} canCancel Can this dialogue be cancelled.\n     * @param {Bool} skipHeader Skip blanking out the header\n     */\n    var showConfirmDialogue = function(\n        header,\n        body,\n        footer,\n        buttonSelectors,\n        bodyText,\n        headerText,\n        canCancel,\n        skipHeader\n    ) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var buttons = buttonSelectors.map(function(selector) {\n            return dialogue.find(selector);\n        });\n        var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);\n        var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);\n        var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);\n\n        dialogue.find('button').addClass('hidden');\n\n        if (canCancel) {\n            cancelButton.removeClass('hidden');\n        } else {\n            cancelButton.addClass('hidden');\n        }\n\n        if (headerText) {\n            dialogueHeader.removeClass('hidden');\n            dialogueHeader.text(headerText);\n        } else {\n            dialogueHeader.addClass('hidden');\n            dialogueHeader.text('');\n        }\n\n        buttons.forEach(function(button) {\n            button.removeClass('hidden');\n        });\n        text.text(bodyText);\n        showConfirmDialogueContainer(footer);\n        showConfirmDialogueContainer(body);\n\n        if (!skipHeader) {\n            showConfirmDialogueContainer(header);\n        }\n\n        dialogue.find(SELECTORS.CAN_RECEIVE_FOCUS).filter(':visible').first().focus();\n    };\n\n    /**\n     * Hide the dialogue\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @return {Bool} always true.\n     */\n    var hideConfirmDialogue = function(header, body, footer) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);\n        var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);\n        var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);\n\n        hideCheckDeleteDialogue(body);\n        hideConfirmDialogueContainer(body);\n        hideConfirmDialogueContainer(footer);\n        hideConfirmDialogueContainer(header);\n        dialogue.find('button').addClass('hidden');\n        cancelButton.removeClass('hidden');\n        text.text('');\n        dialogueHeader.addClass('hidden');\n        dialogueHeader.text('');\n\n        header.find(SELECTORS.CAN_RECEIVE_FOCUS).first().focus();\n        return true;\n    };\n\n    /**\n     * Render the confirm block user dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to block.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmBlockUser = function(header, body, footer, user) {\n        if (user) {\n            if (user.canmessageevenifblocked) {\n                return Str.get_string('cantblockuser', 'core_message', user.fullname)\n                    .then(function(string) {\n                        return showConfirmDialogue(header, body, footer, [], string, '', true, false);\n                    });\n            } else {\n                return Str.get_string('blockuserconfirm', 'core_message', user.fullname)\n                    .then(function(string) {\n                        return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_BLOCK], string, '', true, false);\n                    });\n            }\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm unblock user dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to unblock.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmUnblockUser = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('unblockuserconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_UNBLOCK], string, '', true, false);\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the add user as contact dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to add as contact.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmAddContact = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('addcontactconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_ADD_CONTACT],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the remove user from contacts dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to remove from contacts.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmRemoveContact = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('removecontactconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_REMOVE_CONTACT],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the delete selected messages dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data If the dialogue should show and checkbox shows to delete message for all users.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmDeleteSelectedMessages = function(header, body, footer, data) {\n        var showmessage = null;\n        if (data.type == CONVERSATION_TYPES.SELF) {\n            // Message displayed to self-conversations is slighly different.\n            showmessage = 'deleteselectedmessagesconfirmselfconversation';\n        } else {\n            // This other message should be displayed.\n            if (data.canDeleteMessagesForAllUsers) {\n                showCheckDeleteDialogue(body);\n                showmessage = 'deleteforeveryoneselectedmessagesconfirm';\n            } else {\n                showmessage = 'deleteselectedmessagesconfirm';\n            }\n        }\n\n        if (data.show) {\n            return Str.get_string(showmessage, 'core_message')\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm delete conversation dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {int|Null} type The conversation type to be removed.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmDeleteConversation = function(header, body, footer, type) {\n        var showmessage = null;\n        if (type == CONVERSATION_TYPES.SELF) {\n            // Message displayed to self-conversations is slighly different.\n            showmessage = 'deleteallselfconfirm';\n        } else if (type) {\n            // This other message should be displayed.\n            showmessage = 'deleteallconfirm';\n        }\n\n        if (showmessage) {\n            return Str.get_string(showmessage, 'core_message')\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_DELETE_CONVERSATION],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm delete conversation dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} user The other user object.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmContactRequest = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('userwouldliketocontactyou', 'core_message', user.fullname)\n                .then(function(string) {\n                    var buttonSelectors = [\n                        SELECTORS.ACTION_ACCEPT_CONTACT_REQUEST,\n                        SELECTORS.ACTION_DECLINE_CONTACT_REQUEST\n                    ];\n                    return showConfirmDialogue(header, body, footer, buttonSelectors, string, '', false, true);\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Show the checkbox to allow delete message for all.\n     *\n     * @param {Object} body The body container element.\n     */\n    var showCheckDeleteDialogue = function(body) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var checkboxRegion = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);\n        checkboxRegion.removeClass('hidden');\n    };\n\n    /**\n     * Hide the checkbox to allow delete message for all.\n     *\n     * @param {Object} body The body container element.\n     */\n    var hideCheckDeleteDialogue = function(body) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var checkboxRegion = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);\n        var checkbox = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE);\n        checkbox.prop('checked', false);\n        checkboxRegion.addClass('hidden');\n    };\n\n    /**\n     * Show or hide the block / unblock option in the header dropdown menu.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isBlocked is user blocked.\n     */\n    var renderIsBlocked = function(header, body, footer, isBlocked) {\n        if (isBlocked) {\n            header.find(SELECTORS.ACTION_REQUEST_BLOCK).addClass('hidden');\n            header.find(SELECTORS.ACTION_REQUEST_UNBLOCK).removeClass('hidden');\n        } else {\n            header.find(SELECTORS.ACTION_REQUEST_BLOCK).removeClass('hidden');\n            header.find(SELECTORS.ACTION_REQUEST_UNBLOCK).addClass('hidden');\n        }\n    };\n\n    /**\n     * Show or hide the favourite / unfavourite option in the header dropdown menu\n     * and the favourite star in the header title.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isFavourite is this conversation a favourite.\n     */\n    var renderIsFavourite = function(header, body, footer, state) {\n        var favouriteIcon = header.find(SELECTORS.FAVOURITE_ICON_CONTAINER);\n        var addFavourite = header.find(SELECTORS.ACTION_CONFIRM_FAVOURITE);\n        var removeFavourite = header.find(SELECTORS.ACTION_CONFIRM_UNFAVOURITE);\n\n        switch (state) {\n            case 'hide':\n                favouriteIcon.addClass('hidden');\n                addFavourite.addClass('hidden');\n                removeFavourite.addClass('hidden');\n                break;\n            case 'show-add':\n                favouriteIcon.addClass('hidden');\n                addFavourite.removeClass('hidden');\n                removeFavourite.addClass('hidden');\n                break;\n            case 'show-remove':\n                favouriteIcon.removeClass('hidden');\n                addFavourite.addClass('hidden');\n                removeFavourite.removeClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide the mute / unmute option in the header dropdown menu\n     * and the muted icon in the header title.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {string} state The state of the conversation as defined by the patcher.\n     */\n    var renderIsMuted = function(header, body, footer, state) {\n        var muteIcon = header.find(SELECTORS.MUTED_ICON_CONTAINER);\n        var setMuted = header.find(SELECTORS.ACTION_CONFIRM_MUTE);\n        var unsetMuted = header.find(SELECTORS.ACTION_CONFIRM_UNMUTE);\n\n        switch (state) {\n            case 'hide':\n                muteIcon.addClass('hidden');\n                setMuted.addClass('hidden');\n                unsetMuted.addClass('hidden');\n                break;\n            case 'show-mute':\n                muteIcon.addClass('hidden');\n                setMuted.removeClass('hidden');\n                unsetMuted.addClass('hidden');\n                break;\n            case 'show-unmute':\n                muteIcon.removeClass('hidden');\n                setMuted.addClass('hidden');\n                unsetMuted.removeClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide the add / remove user as contact option in the header dropdown menu.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} state the contact state.\n     */\n    var renderIsContact = function(header, body, footer, state) {\n        var addContact = header.find(SELECTORS.ACTION_REQUEST_ADD_CONTACT);\n        var removeContact = header.find(SELECTORS.ACTION_REQUEST_REMOVE_CONTACT);\n\n        switch (state) {\n            case 'pending-contact':\n                addContact.addClass('hidden');\n                removeContact.addClass('hidden');\n                break;\n            case 'contact':\n                addContact.addClass('hidden');\n                removeContact.removeClass('hidden');\n                break;\n            case 'non-contact':\n                addContact.removeClass('hidden');\n                removeContact.addClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide confirm action from confirm dialogue is loading.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoading confirm action is loading.\n     */\n    var renderLoadingConfirmAction = function(header, body, footer, isLoading) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var buttons = dialogue.find('button');\n        var buttonText = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_BUTTON_TEXT);\n        var loadingIcon = dialogue.find(SELECTORS.LOADING_ICON_CONTAINER);\n\n        if (isLoading) {\n            buttons.prop('disabled', true);\n            buttonText.addClass('hidden');\n            loadingIcon.removeClass('hidden');\n        } else {\n            buttons.prop('disabled', false);\n            buttonText.removeClass('hidden');\n            loadingIcon.addClass('hidden');\n        }\n    };\n\n    /**\n     * Show or hide the header and footer content for edit mode.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} inEditMode In edit mode or not.\n     */\n    var renderInEditMode = function(header, body, footer, inEditMode) {\n        var messages = null;\n\n        if (inEditMode) {\n            messages = body.find(SELECTORS.MESSAGE_NOT_SELECTED);\n            messages.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).removeClass('hidden');\n            hideHeaderContent(header);\n            showHeaderEditMode(header);\n        } else {\n            messages = getMessagesContainer(body);\n            messages.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).addClass('hidden');\n            messages.find(SELECTORS.MESSAGE_SELECTED_ICON).addClass('hidden');\n            showHeaderContent(header);\n            hideHeaderEditMode(header);\n        }\n    };\n\n    /**\n     * Select or unselect messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data The messages to select or unselect.\n     */\n    var renderSelectedMessages = function(header, body, footer, data) {\n        var hasSelectedMessages = data.count > 0;\n\n        if (data.add.length) {\n            data.add.forEach(function(messageId) {\n                var message = getMessageElement(body, messageId);\n                message.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).addClass('hidden');\n                message.find(SELECTORS.MESSAGE_SELECTED_ICON).removeClass('hidden');\n                message.attr('aria-checked', true);\n            });\n        }\n\n        if (data.remove.length) {\n            data.remove.forEach(function(messageId) {\n                var message = getMessageElement(body, messageId);\n\n                if (hasSelectedMessages) {\n                    message.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).removeClass('hidden');\n                }\n\n                message.find(SELECTORS.MESSAGE_SELECTED_ICON).addClass('hidden');\n                message.attr('aria-checked', false);\n            });\n        }\n\n        setMessagesSelectedCount(header, data.count);\n    };\n\n    /**\n     * Show or hide the require add contact panel.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Whether the user has to be added a a contact.\n     * @return {Object} jQuery promise\n     */\n    var renderRequireAddContact = function(header, body, footer, data) {\n        if (data.show && !data.hasMessages) {\n            return Str.get_strings([\n                    {\n                        key: 'requirecontacttomessage',\n                        component: 'core_message',\n                        param: data.user.fullname\n                    },\n                    {\n                        key: 'isnotinyourcontacts',\n                        component: 'core_message',\n                        param: data.user.fullname\n                    }\n                ])\n                .then(function(strings) {\n                    var title = strings[1];\n                    var text = strings[0];\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_REQUEST_ADD_CONTACT],\n                        text,\n                        title,\n                        false,\n                        true\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Show or hide the self-conversation message.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} displayMessage should the message be displayed?.\n     * @return {Object|true} jQuery promise\n     */\n    var renderSelfConversationMessage = function(header, body, footer, displayMessage) {\n        var container = getSelfConversationMessageContainer(body);\n        if (displayMessage) {\n            container.removeClass('hidden');\n        } else {\n            container.addClass('hidden');\n        }\n        return true;\n    };\n\n    /**\n     * Show or hide the require add contact panel.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} userFullName Full name of the other user.\n     * @return {Object|true} jQuery promise\n     */\n    var renderContactRequestSent = function(header, body, footer, userFullName) {\n        var container = getContactRequestSentContainer(body);\n        if (userFullName) {\n            return Str.get_string('yourcontactrequestpending', 'core_message', userFullName)\n                .then(function(string) {\n                    container.find(SELECTORS.TEXT).text(string);\n                    container.removeClass('hidden');\n                    return string;\n                });\n        } else {\n            container.addClass('hidden');\n            return true;\n        }\n    };\n\n    /**\n     * Reset the UI to the initial state.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @return {Bool}\n     */\n    var renderReset = function(header, body, footer) {\n        hideConfirmDialogue(header, body, footer);\n        hideContactRequestSentContainer(body);\n        hideSelfConversationMessageContainer(body);\n        hideAllHeaderElements(header);\n        showHeaderPlaceholder(header);\n        hideAllFooterElements(footer);\n        showFooterPlaceholder(footer);\n        return true;\n    };\n\n    var render = function(header, body, footer, patch) {\n        var configs = [\n            {\n                // Resetting the UI needs to come first, if it's required.\n                reset: renderReset\n            },\n            {\n                // Any async rendering (stuff that requires templates, strings etc) should\n                // go in here.\n                conversation: renderConversation,\n                header: renderHeader,\n                footer: renderFooter,\n                confirmBlockUser: renderConfirmBlockUser,\n                confirmUnblockUser: renderConfirmUnblockUser,\n                confirmAddContact: renderConfirmAddContact,\n                confirmRemoveContact: renderConfirmRemoveContact,\n                confirmDeleteSelectedMessages: renderConfirmDeleteSelectedMessages,\n                confirmDeleteConversation: renderConfirmDeleteConversation,\n                confirmContactRequest: renderConfirmContactRequest,\n                requireAddContact: renderRequireAddContact,\n                selfConversationMessage: renderSelfConversationMessage,\n                contactRequestSent: renderContactRequestSent\n            },\n            {\n                loadingMembers: renderLoadingMembers,\n                loadingFirstMessages: renderLoadingFirstMessages,\n                loadingMessages: renderLoadingMessages,\n                isBlocked: renderIsBlocked,\n                isContact: renderIsContact,\n                isFavourite: renderIsFavourite,\n                isMuted: renderIsMuted,\n                loadingConfirmAction: renderLoadingConfirmAction,\n                inEditMode: renderInEditMode\n            },\n            {\n                // Scrolling should be last to make sure everything\n                // on the page is visible.\n                scrollToMessage: renderScrollToMessage,\n                selectedMessages: renderSelectedMessages\n            }\n        ];\n        // Helper function to process each of the configs above.\n        var processConfig = function(config) {\n            var results = [];\n\n            for (var key in patch) {\n                if (config.hasOwnProperty(key)) {\n                    var renderFunc = config[key];\n                    var patchValue = patch[key];\n                    results.push(renderFunc(header, body, footer, patchValue));\n                }\n            }\n\n            return results;\n        };\n\n        // The first config is special because it resets the UI.\n        var renderingPromises = processConfig(configs[0]);\n        // The second config is special because it contains async rendering.\n        renderingPromises = renderingPromises.concat(processConfig(configs[1]));\n\n        // Wait for the async rendering to complete before processing the\n        // rest of the configs, in order.\n        return $.when.apply($, renderingPromises)\n            .then(function() {\n                for (var i = 2; i < configs.length; i++) {\n                    processConfig(configs[i]);\n                }\n\n                return;\n            })\n            .catch(Notification.exception);\n    };\n\n    return {\n        render: render,\n    };\n});\n"],"file":"message_drawer_view_conversation_renderer.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../src/message_drawer_view_conversation_renderer.js"],"names":["define","$","Notification","Str","Templates","UserDate","Constants","SELECTORS","TEMPLATES","CONVERSATION_TYPES","getMessagesContainer","body","find","CONTENT_MESSAGES_CONTAINER","showMessagesContainer","removeClass","hideMessagesContainer","addClass","getSelfConversationMessageContainer","SELF_CONVERSATION_MESSAGE_CONTAINER","hideSelfConversationMessageContainer","getContactRequestSentContainer","CONTACT_REQUEST_SENT_MESSAGE_CONTAINER","hideContactRequestSentContainer","getFooterContentContainer","footer","CONTENT_MESSAGES_FOOTER_CONTAINER","showFooterContent","hideFooterContent","getFooterEditModeContainer","CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER","showFooterEditMode","hideFooterEditMode","getFooterPlaceholderContainer","PLACEHOLDER_CONTAINER","showFooterPlaceholder","hideFooterPlaceholder","getFooterRequireContactContainer","CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER","showFooterRequireContact","hideFooterRequireContact","getFooterRequireUnblockContainer","CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER","showFooterRequireUnblock","hideFooterRequireUnblock","getFooterUnableToMessageContainer","CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER","showFooterUnableToMessage","hideFooterUnableToMessage","hideAllHeaderElements","header","hideHeaderContent","hideHeaderEditMode","hideHeaderPlaceholder","hideAllFooterElements","getContentPlaceholderContainer","CONTENT_PLACEHOLDER_CONTAINER","showContentPlaceholder","hideContentPlaceholder","getHeaderContent","HEADER","showHeaderContent","getHeaderEditMode","HEADER_EDIT_MODE","showHeaderEditMode","getHeaderPlaceholderContainer","HEADER_PLACEHOLDER_CONTAINER","showHeaderPlaceholder","getMessageElement","messageId","messagesContainer","getDayElement","dayTimeCreated","getMoreMessagesLoadingIconContainer","MORE_MESSAGES_LOADING_ICON_CONTAINER","showMoreMessagesLoadingIcon","hideMoreMessagesLoadingIcon","getConfirmDialogueContainer","root","CONFIRM_DIALOGUE_CONTAINER","showConfirmDialogueContainer","container","siblings","attr","hideConfirmDialogueContainer","removeAttr","setMessagesSelectedCount","value","MESSAGES_SELECTED_COUNT","text","formatMessagesForTemplate","messages","datesCache","map","message","id","isread","isRead","fromloggedinuser","fromLoggedInUser","userfrom","userFrom","formattedtime","timeCreated","renderAddDays","days","daysRenderPromises","data","render","DAY","timestamp","when","apply","then","forEach","index","html","before","element","insertBefore","append","catch","renderAddMessages","messagesData","formattedMessages","MESSAGES","messageList","messageHtml","dayContainer","day","dayMessagesContainer","DAY_MESSAGES_CONTAINER","renderUpdateMessages","after","formattedTime","LOADING_ICON_CONTAINER","TIME_CREATED","sendState","loading","time","retry","RETRY_SEND","TEXT_CONTAINER","errorMessage","messageContainer","ERROR_MESSAGE_CONTAINER","ERROR_MESSAGE","renderRemoveDays","remove","renderRemoveMessages","renderConversation","renderingPromises","hasAddDays","add","length","hasAddMessages","hasUpdateMessages","update","timestampsToFormat","datesCachePromise","Deferred","resolve","promise","concat","reduce","carry","timestamps","push","get_string","format","requests","get","formattedTimes","renderHeader","headerContainer","template","HEADER_PUBLIC","context","showrouteback","type","PRIVATE","showControls","HEADER_PRIVATE","HEADER_PRIVATE_NO_CONTROLS","SELF","HEADER_SELF","js","replaceNodeContents","renderFooter","get_strings","key","component","param","user","fullname","strings","title","footerContainer","TITLE","TEXT","renderScrollToMessage","messageElement","position","scrollTop","top","renderLoadingMembers","isLoadingMembers","renderLoadingFirstMessages","isLoadingFirstMessages","renderLoadingMessages","isLoading","showConfirmDialogue","buttonSelectors","bodyText","headerText","canCancel","skipHeader","showOk","dialogue","buttons","selector","cancelButton","CONFIRM_DIALOGUE_CANCEL_BUTTON","okayButton","CONFIRM_DIALOGUE_OKAY_BUTTON","CONFIRM_DIALOGUE_TEXT","dialogueHeader","CONFIRM_DIALOGUE_HEADER","button","CAN_RECEIVE_FOCUS","filter","first","focus","hideConfirmDialogue","hideCheckDeleteDialogue","renderConfirmBlockUser","canmessageevenifblocked","string","ACTION_CONFIRM_BLOCK","renderConfirmUnblockUser","ACTION_CONFIRM_UNBLOCK","renderConfirmAddContact","ACTION_CONFIRM_ADD_CONTACT","renderConfirmRemoveContact","ACTION_CONFIRM_REMOVE_CONTACT","renderConfirmDeleteSelectedMessages","showmessage","canDeleteMessagesForAllUsers","showCheckDeleteDialogue","show","ACTION_CONFIRM_DELETE_SELECTED_MESSAGES","renderConfirmDeleteConversation","ACTION_CONFIRM_DELETE_CONVERSATION","renderConfirmContactRequest","ACTION_ACCEPT_CONTACT_REQUEST","ACTION_DECLINE_CONTACT_REQUEST","checkboxRegion","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER","checkbox","DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE","prop","renderIsBlocked","isBlocked","ACTION_REQUEST_BLOCK","ACTION_REQUEST_UNBLOCK","renderIsFavourite","state","favouriteIcon","FAVOURITE_ICON_CONTAINER","addFavourite","ACTION_CONFIRM_FAVOURITE","removeFavourite","ACTION_CONFIRM_UNFAVOURITE","renderIsMuted","muteIcon","MUTED_ICON_CONTAINER","setMuted","ACTION_CONFIRM_MUTE","unsetMuted","ACTION_CONFIRM_UNMUTE","renderIsContact","addContact","ACTION_REQUEST_ADD_CONTACT","removeContact","ACTION_REQUEST_REMOVE_CONTACT","renderLoadingConfirmAction","buttonText","CONFIRM_DIALOGUE_BUTTON_TEXT","loadingIcon","renderInEditMode","inEditMode","MESSAGE_NOT_SELECTED","MESSAGE_NOT_SELECTED_ICON","MESSAGE_SELECTED_ICON","renderSelectedMessages","hasSelectedMessages","count","renderRequireAddContact","hasMessages","renderSelfConversationMessage","displayMessage","renderContactRequestSent","userFullName","renderReset","patch","configs","reset","conversation","confirmBlockUser","confirmUnblockUser","confirmAddContact","confirmRemoveContact","confirmDeleteSelectedMessages","confirmDeleteConversation","confirmContactRequest","requireAddContact","selfConversationMessage","contactRequestSent","loadingMembers","loadingFirstMessages","loadingMessages","isContact","isFavourite","isMuted","loadingConfirmAction","scrollToMessage","selectedMessages","processConfig","config","results","hasOwnProperty","renderFunc","patchValue","i","exception"],"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 * This module updates the UI for the conversation page in the message\n * drawer.\n *\n * The module will take a patch from the message_drawer_view_conversation_patcher\n * module and update the UI to reflect the changes.\n *\n * This is the only module that ever modifies the UI of the conversation page.\n *\n * @module     core_message/message_drawer_view_conversation_renderer\n * @copyright  2018 Ryan Wyllie <ryan@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n    'jquery',\n    'core/notification',\n    'core/str',\n    'core/templates',\n    'core/user_date',\n    'core_message/message_drawer_view_conversation_constants'\n],\nfunction(\n    $,\n    Notification,\n    Str,\n    Templates,\n    UserDate,\n    Constants\n) {\n    var SELECTORS = Constants.SELECTORS;\n    var TEMPLATES = Constants.TEMPLATES;\n    var CONVERSATION_TYPES = Constants.CONVERSATION_TYPES;\n\n    /**\n     * Get the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getMessagesContainer = function(body) {\n        return body.find(SELECTORS.CONTENT_MESSAGES_CONTAINER);\n    };\n\n    /**\n     * Show the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showMessagesContainer = function(body) {\n        getMessagesContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the messages container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideMessagesContainer = function(body) {\n        getMessagesContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the self-conversation message container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getSelfConversationMessageContainer = function(body) {\n        return body.find(SELECTORS.SELF_CONVERSATION_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Hide the self-conversation message container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var hideSelfConversationMessageContainer = function(body) {\n        return getSelfConversationMessageContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the contact request sent container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var getContactRequestSentContainer = function(body) {\n        return body.find(SELECTORS.CONTACT_REQUEST_SENT_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Hide the contact request sent container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The messages container element.\n     */\n    var hideContactRequestSentContainer = function(body) {\n        return getContactRequestSentContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer container element.\n     */\n    var getFooterContentContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_CONTAINER);\n    };\n\n    /**\n     * Show the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterContent = function(footer) {\n        getFooterContentContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterContent = function(footer) {\n        getFooterContentContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer container element.\n     */\n    var getFooterEditModeContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_EDIT_MODE_CONTAINER);\n    };\n\n    /**\n     * Show the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterEditMode = function(footer) {\n        getFooterEditModeContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer edit mode container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterEditMode = function(footer) {\n        getFooterEditModeContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer placeholder.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer placeholder container element.\n     */\n    var getFooterPlaceholderContainer = function(footer) {\n        return footer.find(SELECTORS.PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the footer placeholder\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterPlaceholder = function(footer) {\n        getFooterPlaceholderContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer placeholder\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterPlaceholder = function(footer) {\n        getFooterPlaceholderContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Require add as contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Require add as contact container element.\n     */\n    var getFooterRequireContactContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_REQUIRE_CONTACT_CONTAINER);\n    };\n\n    /**\n     * Show the footer add as contact dialogue.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterRequireContact = function(footer) {\n        getFooterRequireContactContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer add as contact dialogue.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterRequireContact = function(footer) {\n        getFooterRequireContactContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Required to unblock contact container element.\n     */\n    var getFooterRequireUnblockContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_REQUIRE_UNBLOCK_CONTAINER);\n    };\n\n    /**\n     * Show the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterRequireUnblock = function(footer) {\n        getFooterRequireUnblockContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer Required to unblock contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterRequireUnblock = function(footer) {\n        getFooterRequireUnblockContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Get the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     * @return {Object} The footer Unable to message contact container element.\n     */\n    var getFooterUnableToMessageContainer = function(footer) {\n        return footer.find(SELECTORS.CONTENT_MESSAGES_FOOTER_UNABLE_TO_MESSAGE_CONTAINER);\n    };\n\n    /**\n     * Show the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var showFooterUnableToMessage = function(footer) {\n        getFooterUnableToMessageContainer(footer).removeClass('hidden');\n    };\n\n    /**\n     * Hide the footer Unable to message contact container element.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideFooterUnableToMessage = function(footer) {\n        getFooterUnableToMessageContainer(footer).addClass('hidden');\n    };\n\n    /**\n     * Hide all header elements.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideAllHeaderElements = function(header) {\n        hideHeaderContent(header);\n        hideHeaderEditMode(header);\n        hideHeaderPlaceholder(header);\n    };\n\n    /**\n     * Hide all footer dialogues and messages.\n     *\n     * @param  {Object} footer Conversation footer container element.\n     */\n    var hideAllFooterElements = function(footer) {\n        hideFooterContent(footer);\n        hideFooterEditMode(footer);\n        hideFooterPlaceholder(footer);\n        hideFooterRequireContact(footer);\n        hideFooterRequireUnblock(footer);\n        hideFooterUnableToMessage(footer);\n    };\n\n    /**\n     * Get the content placeholder container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The body placeholder container element.\n     */\n    var getContentPlaceholderContainer = function(body) {\n        return body.find(SELECTORS.CONTENT_PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the content placeholder.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showContentPlaceholder = function(body) {\n        getContentPlaceholderContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the content placeholder.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideContentPlaceholder = function(body) {\n        getContentPlaceholderContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the header content container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header content container element.\n     */\n    var getHeaderContent = function(header) {\n        return header.find(SELECTORS.HEADER);\n    };\n\n    /**\n     * Show the header content.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderContent = function(header) {\n        getHeaderContent(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header content.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderContent = function(header) {\n        getHeaderContent(header).addClass('hidden');\n    };\n\n    /**\n     * Get the header edit mode container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header content container element.\n     */\n    var getHeaderEditMode = function(header) {\n        return header.find(SELECTORS.HEADER_EDIT_MODE);\n    };\n\n    /**\n     * Show the header edit mode container.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderEditMode = function(header) {\n        getHeaderEditMode(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header edit mode container.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderEditMode = function(header) {\n        getHeaderEditMode(header).addClass('hidden');\n    };\n\n    /**\n     * Get the header placeholder container element.\n     *\n     * @param  {Object} header Conversation header container element.\n     * @return {Object} The header placeholder container element.\n     */\n    var getHeaderPlaceholderContainer = function(header) {\n        return header.find(SELECTORS.HEADER_PLACEHOLDER_CONTAINER);\n    };\n\n    /**\n     * Show the header placeholder.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var showHeaderPlaceholder = function(header) {\n        getHeaderPlaceholderContainer(header).removeClass('hidden');\n    };\n\n    /**\n     * Hide the header placeholder.\n     *\n     * @param  {Object} header Conversation header container element.\n     */\n    var hideHeaderPlaceholder = function(header) {\n        getHeaderPlaceholderContainer(header).addClass('hidden');\n    };\n\n    /**\n     * Get a message element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Number} messageId the Message id.\n     * @return {Object} A message element from the conversation.\n     */\n    var getMessageElement = function(body, messageId) {\n        var messagesContainer = getMessagesContainer(body);\n        return messagesContainer.find('[data-message-id=\"' + messageId + '\"]');\n    };\n\n    /**\n     * Get the day container element. The day container element holds a list of messages for that day.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @param  {Number} dayTimeCreated Midnight timestamp for the day.\n     * @return {Object} jQuery object\n     */\n    var getDayElement = function(body, dayTimeCreated) {\n        var messagesContainer = getMessagesContainer(body);\n        return messagesContainer.find('[data-day-id=\"' + dayTimeCreated + '\"]');\n    };\n\n    /**\n     * Get the more messages loading icon container element.\n     *\n     * @param  {Object} body Conversation body container element.\n     * @return {Object} The more messages loading container element.\n     */\n    var getMoreMessagesLoadingIconContainer = function(body) {\n        return body.find(SELECTORS.MORE_MESSAGES_LOADING_ICON_CONTAINER);\n    };\n\n    /**\n     * Show the more messages loading icon.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var showMoreMessagesLoadingIcon = function(body) {\n        getMoreMessagesLoadingIconContainer(body).removeClass('hidden');\n    };\n\n    /**\n     * Hide the more messages loading icon.\n     *\n     * @param  {Object} body Conversation body container element.\n     */\n    var hideMoreMessagesLoadingIcon = function(body) {\n        getMoreMessagesLoadingIconContainer(body).addClass('hidden');\n    };\n\n    /**\n     * Get the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element to search.\n     * @return {Object} The confirm dialogue container element.\n     */\n    var getConfirmDialogueContainer = function(root) {\n        return root.find(SELECTORS.CONFIRM_DIALOGUE_CONTAINER);\n    };\n\n    /**\n     * Show the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element containing a dialogue.\n     */\n    var showConfirmDialogueContainer = function(root) {\n        var container = getConfirmDialogueContainer(root);\n        var siblings = container.siblings(':not(.hidden)');\n        siblings.attr('aria-hidden', true);\n        siblings.attr('tabindex', -1);\n        siblings.attr('data-confirm-dialogue-hidden', true);\n\n        container.removeClass('hidden');\n    };\n\n    /**\n     * Hide the confirm dialogue container element.\n     *\n     * @param  {Object} root The container element containing a dialogue.\n     */\n    var hideConfirmDialogueContainer = function(root) {\n        var container = getConfirmDialogueContainer(root);\n        var siblings = container.siblings('[data-confirm-dialogue-hidden=\"true\"]');\n        siblings.removeAttr('aria-hidden');\n        siblings.removeAttr('tabindex');\n        siblings.removeAttr('data-confirm-dialogue-hidden');\n\n        container.addClass('hidden');\n    };\n\n    /**\n     * Set the number of selected messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Number} value The new number to display.\n     */\n    var setMessagesSelectedCount = function(header, value) {\n        getHeaderEditMode(header).find(SELECTORS.MESSAGES_SELECTED_COUNT).text(value);\n    };\n\n    /**\n     * Format message for the mustache template, transform camelCase properties to lowercase properties.\n     *\n     * @param  {Array} messages Array of message objects.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Array} Messages formated for mustache template.\n     */\n    var formatMessagesForTemplate = function(messages, datesCache) {\n        return messages.map(function(message) {\n            return {\n                id: message.id,\n                isread: message.isRead,\n                fromloggedinuser: message.fromLoggedInUser,\n                userfrom: message.userFrom,\n                text: message.text,\n                formattedtime: message.timeCreated ? datesCache[message.timeCreated] : null\n            };\n        });\n    };\n\n    /**\n     * Create rendering promises for each day containing messages.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} days Array of days containing messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Promise} Days rendering promises.\n     */\n    var renderAddDays = function(header, body, footer, days, datesCache) {\n        var messagesContainer = getMessagesContainer(body);\n        var daysRenderPromises = days.map(function(data) {\n            return Templates.render(TEMPLATES.DAY, {\n                timestamp: data.value.timestamp,\n                messages: formatMessagesForTemplate(data.value.messages, datesCache)\n            });\n        });\n\n        return $.when.apply($, daysRenderPromises).then(function() {\n            // Wait until all of the rendering is done for each of the days\n            // to ensure they are added to the page in the correct order.\n            days.forEach(function(data, index) {\n                daysRenderPromises[index]\n                    .then(function(html) {\n                        if (data.before) {\n                            var element = getDayElement(body, data.before.timestamp);\n                            return $(html).insertBefore(element);\n                        } else {\n                            return messagesContainer.append(html);\n                        }\n                    })\n                    .catch(function() {\n                        // Fail silently.\n                    });\n            });\n\n            return;\n        });\n    };\n\n    /**\n     * Add (more) messages to day containers.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} messages List of messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     * @return {Promise} Messages rendering promises.\n     */\n    var renderAddMessages = function(header, body, footer, messages, datesCache) {\n        var messagesData = messages.map(function(data) {\n            return data.value;\n        });\n        var formattedMessages = formatMessagesForTemplate(messagesData, datesCache);\n\n        return Templates.render(TEMPLATES.MESSAGES, {messages: formattedMessages})\n            .then(function(html) {\n                var messageList = $(html);\n                messages.forEach(function(data) {\n                    var messageHtml = messageList.find('[data-message-id=\"' + data.value.id + '\"]');\n                    if (data.before) {\n                        var element = getMessageElement(body, data.before.id);\n                        return messageHtml.insertBefore(element);\n                    } else {\n                        var dayContainer = getDayElement(body, data.day.timestamp);\n                        var dayMessagesContainer = dayContainer.find(SELECTORS.DAY_MESSAGES_CONTAINER);\n                        return dayMessagesContainer.append(messageHtml);\n                    }\n                });\n\n                return;\n            });\n    };\n\n    /**\n     * Update existing messages.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Array} messages List of messages.\n     * @param  {Object} datesCache Cache timestamps and their formatted date string.\n     */\n    var renderUpdateMessages = function(header, body, footer, messages, datesCache) {\n        messages.forEach(function(message) {\n            var before = message.before;\n            var after = message.after;\n            var element = getMessageElement(body, before.id);\n\n            if (before.id != after.id) {\n                element.attr('data-message-id', after.id);\n            }\n\n            if (before.timeCreated != after.timeCreated) {\n                var formattedTime = datesCache[after.timeCreated];\n                element.find(SELECTORS.LOADING_ICON_CONTAINER).addClass('hidden');\n                element.find(SELECTORS.TIME_CREATED).text(formattedTime).removeClass('hidden');\n            }\n\n            if (before.sendState != after.sendState) {\n                var loading = element.find(SELECTORS.LOADING_ICON_CONTAINER);\n                var time = element.find(SELECTORS.TIME_CREATED);\n                var retry = element.find(SELECTORS.RETRY_SEND);\n\n                loading.addClass('hidden');\n                loading.attr('aria-hidden', 'true');\n                time.addClass('hidden');\n                time.attr('aria-hidden', 'true');\n                retry.addClass('hidden');\n                retry.attr('aria-hidden', 'true');\n                element.removeClass('border border-danger');\n\n                switch (after.sendState) {\n                    case 'pending':\n                        loading.removeClass('hidden');\n                        loading.attr('aria-hidden', 'false');\n                        break;\n                    case 'error':\n                        retry.removeClass('hidden');\n                        retry.attr('aria-hidden', 'false');\n                        element.addClass('border border-danger');\n                        break;\n                    case 'sent':\n                        time.removeClass('hidden');\n                        time.attr('aria-hidden', 'false');\n                        break;\n                }\n            }\n\n            if (before.text != after.text) {\n                element.find(SELECTORS.TEXT_CONTAINER).html(after.text);\n            }\n\n            if (before.errorMessage != after.errorMessage) {\n                var messageContainer = element.find(SELECTORS.ERROR_MESSAGE_CONTAINER);\n                var message = messageContainer.find(SELECTORS.ERROR_MESSAGE);\n\n                if (after.errorMessage) {\n                    messageContainer.removeClass('hidden');\n                    messageContainer.attr('aria-hidden', 'false');\n                    message.text(after.errorMessage);\n                } else {\n                    messageContainer.addClass('hidden');\n                    messageContainer.attr('aria-hidden', 'true');\n                    message.text('');\n                }\n            }\n        });\n    };\n\n    /**\n     * Remove days from conversation.\n     *\n     * @param  {Object} body The body container element.\n     * @param  {Array} days Array of days to be removed.\n     */\n    var renderRemoveDays = function(body, days) {\n        days.forEach(function(data) {\n            getDayElement(body, data.timestamp).remove();\n        });\n    };\n\n    /**\n     * Remove messages from conversation.\n     *\n     * @param  {Object} body The body container element.\n     * @param  {Array} messages Array of messages to be removed.\n     */\n    var renderRemoveMessages = function(body, messages) {\n        messages.forEach(function(data) {\n            getMessageElement(body, data.id).remove();\n        });\n    };\n\n    /**\n     * Render the full conversation base on input from the statemanager.\n     *\n     * This will pre-load all of the formatted timestamps for each message that\n     * needs to render to reduce the number of networks requests.\n     *\n     * @param  {Object} header The header container element.\n     * @param  {Object} body The body container element.\n     * @param  {Object} footer The footer container element.\n     * @param  {Object} data The conversation diff.\n     * @return {Object} jQuery promise.\n     */\n    var renderConversation = function(header, body, footer, data) {\n        var renderingPromises = [];\n        var hasAddDays = data.days.add.length > 0;\n        var hasAddMessages = data.messages.add.length > 0;\n        var hasUpdateMessages = data.messages.update.length > 0;\n        var timestampsToFormat = [];\n        var datesCachePromise = $.Deferred().resolve({}).promise();\n\n        if (hasAddDays) {\n            // Search for all of the timeCreated values in all of the messages in all of\n            // the days that we need to render.\n            timestampsToFormat = timestampsToFormat.concat(data.days.add.reduce(function(carry, day) {\n                return carry.concat(day.value.messages.reduce(function(timestamps, message) {\n                    if (message.timeCreated) {\n                        timestamps.push(message.timeCreated);\n                    }\n                    return timestamps;\n                }, []));\n            }, []));\n        }\n\n        if (hasAddMessages) {\n            // Search for all of the timeCreated values in all of the messages that we\n            // need to render.\n            timestampsToFormat = timestampsToFormat.concat(data.messages.add.reduce(function(timestamps, message) {\n                if (message.value.timeCreated) {\n                    timestamps.push(message.value.timeCreated);\n                }\n                return timestamps;\n            }, []));\n        }\n\n        if (hasUpdateMessages) {\n            timestampsToFormat = timestampsToFormat.concat(data.messages.update.reduce(function(timestamps, message) {\n                if (message.before.timeCreated != message.after.timeCreated) {\n                    timestamps.push(message.after.timeCreated);\n                }\n                return timestamps;\n            }, []));\n        }\n\n        if (timestampsToFormat.length) {\n            // If we have timestamps then pre-load the formatted version of each of them\n            // in a single request to the server. This saves the templates doing multiple\n            // individual requests.\n            datesCachePromise = Str.get_string('strftimetime24', 'core_langconfig')\n                .then(function(format) {\n                    var requests = timestampsToFormat.map(function(timestamp) {\n                        return {\n                            timestamp: timestamp,\n                            format: format\n                        };\n                    });\n\n                    return UserDate.get(requests);\n                })\n                .then(function(formattedTimes) {\n                    return timestampsToFormat.reduce(function(carry, timestamp, index) {\n                        carry[timestamp] = formattedTimes[index];\n                        return carry;\n                    }, {});\n                });\n        }\n\n        if (hasAddDays) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderAddDays(header, body, footer, data.days.add, datesCache);\n            }));\n        }\n\n        if (hasAddMessages) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderAddMessages(header, body, footer, data.messages.add, datesCache);\n            }));\n        }\n\n        if (hasUpdateMessages) {\n            renderingPromises.push(datesCachePromise.then(function(datesCache) {\n                return renderUpdateMessages(header, body, footer, data.messages.update, datesCache);\n            }));\n        }\n\n        if (data.days.remove.length > 0) {\n            renderRemoveDays(body, data.days.remove);\n        }\n\n        if (data.messages.remove.length > 0) {\n            renderRemoveMessages(body, data.messages.remove);\n        }\n\n        return $.when.apply($, renderingPromises);\n    };\n\n    /**\n     * Render the conversation header.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Data for header.\n     * @return {Object} jQuery promise\n     */\n    var renderHeader = function(header, body, footer, data) {\n        var headerContainer = getHeaderContent(header);\n        var template = TEMPLATES.HEADER_PUBLIC;\n        data.context.showrouteback = (header.attr('data-from-panel') === \"false\");\n        if (data.type == CONVERSATION_TYPES.PRIVATE) {\n            template = data.showControls ? TEMPLATES.HEADER_PRIVATE : TEMPLATES.HEADER_PRIVATE_NO_CONTROLS;\n        } else if (data.type == CONVERSATION_TYPES.SELF) {\n            template = TEMPLATES.HEADER_SELF;\n        }\n\n        return Templates.render(template, data.context)\n            .then(function(html, js) {\n                Templates.replaceNodeContents(headerContainer, html, js);\n                return;\n            });\n    };\n\n    /**\n     * Render the conversation footer.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Data for footer.\n     * @return {Object} jQuery promise.\n     */\n    var renderFooter = function(header, body, footer, data) {\n        hideAllFooterElements(footer);\n\n        switch (data.type) {\n            case 'placeholder':\n                return showFooterPlaceholder(footer);\n            case 'add-contact':\n                return Str.get_strings([\n                        {\n                            key: 'requirecontacttomessage',\n                            component: 'core_message',\n                            param: data.user.fullname\n                        },\n                        {\n                            key: 'isnotinyourcontacts',\n                            component: 'core_message',\n                            param: data.user.fullname\n                        }\n                    ])\n                    .then(function(strings) {\n                        var title = strings[1];\n                        var text = strings[0];\n                        var footerContainer = getFooterRequireContactContainer(footer);\n                        footerContainer.find(SELECTORS.TITLE).text(title);\n                        footerContainer.find(SELECTORS.TEXT).text(text);\n                        showFooterRequireContact(footer);\n                        return strings;\n                    });\n            case 'edit-mode':\n                return showFooterEditMode(footer);\n            case 'content':\n                return showFooterContent(footer);\n            case 'unblock':\n                return showFooterRequireUnblock(footer);\n            case 'unable-to-message':\n                return showFooterUnableToMessage(footer);\n        }\n\n        return true;\n    };\n\n    /**\n     * Scroll to a message in the conversation.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Number} messageId Message id.\n     */\n    var renderScrollToMessage = function(header, body, footer, messageId) {\n        var messagesContainer = getMessagesContainer(body);\n        var messageElement = getMessageElement(body, messageId);\n        var position = messageElement.position();\n        // Scroll the message container down to the top of the message element.\n        if (position) {\n            var scrollTop = messagesContainer.scrollTop() + position.top;\n            messagesContainer.scrollTop(scrollTop);\n        }\n    };\n\n    /**\n     * Hide or show the conversation header.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoadingMembers Members loading.\n     */\n    var renderLoadingMembers = function(header, body, footer, isLoadingMembers) {\n        if (isLoadingMembers) {\n            hideHeaderContent(header);\n            showHeaderPlaceholder(header);\n        } else {\n            showHeaderContent(header);\n            hideHeaderPlaceholder(header);\n        }\n    };\n\n    /**\n     * Hide or show loading conversation messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoadingFirstMessages Messages loading.\n     */\n    var renderLoadingFirstMessages = function(header, body, footer, isLoadingFirstMessages) {\n        if (isLoadingFirstMessages) {\n            hideMessagesContainer(body);\n            showContentPlaceholder(body);\n        } else {\n            showMessagesContainer(body);\n            hideContentPlaceholder(body);\n        }\n    };\n\n    /**\n     * Hide or show loading more messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoading Messages loading.\n     */\n    var renderLoadingMessages = function(header, body, footer, isLoading) {\n        if (isLoading) {\n            showMoreMessagesLoadingIcon(body);\n        } else {\n            hideMoreMessagesLoadingIcon(body);\n        }\n    };\n\n    /**\n     * Show a confirmation dialogue\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {String} buttonSelectors Selectors for the buttons to show.\n     * @param {String} bodyText Text to show in dialogue.\n     * @param {String} headerText Text to show in dialogue header.\n     * @param {Bool} canCancel Can this dialogue be cancelled.\n     * @param {Bool} skipHeader Skip blanking out the header\n     * @param {Bool} showOk Show an 'Okay' button for a dialogue which will close it\n     */\n    var showConfirmDialogue = function(\n        header,\n        body,\n        footer,\n        buttonSelectors,\n        bodyText,\n        headerText,\n        canCancel,\n        skipHeader,\n        showOk\n    ) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var buttons = buttonSelectors.map(function(selector) {\n            return dialogue.find(selector);\n        });\n        var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);\n        var okayButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_OKAY_BUTTON);\n        var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);\n        var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);\n\n        dialogue.find('button').addClass('hidden');\n\n        if (canCancel) {\n            cancelButton.removeClass('hidden');\n        } else {\n            cancelButton.addClass('hidden');\n        }\n\n        if (showOk) {\n            okayButton.removeClass('hidden');\n        } else {\n            okayButton.addClass('hidden');\n        }\n\n        if (headerText) {\n            dialogueHeader.removeClass('hidden');\n            dialogueHeader.text(headerText);\n        } else {\n            dialogueHeader.addClass('hidden');\n            dialogueHeader.text('');\n        }\n\n        buttons.forEach(function(button) {\n            button.removeClass('hidden');\n        });\n        text.text(bodyText);\n        showConfirmDialogueContainer(footer);\n        showConfirmDialogueContainer(body);\n\n        if (!skipHeader) {\n            showConfirmDialogueContainer(header);\n        }\n\n        dialogue.find(SELECTORS.CAN_RECEIVE_FOCUS).filter(':visible').first().focus();\n    };\n\n    /**\n     * Hide the dialogue\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @return {Bool} always true.\n     */\n    var hideConfirmDialogue = function(header, body, footer) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);\n        var okayButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_OKAY_BUTTON);\n        var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);\n        var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);\n\n        hideCheckDeleteDialogue(body);\n        hideConfirmDialogueContainer(body);\n        hideConfirmDialogueContainer(footer);\n        hideConfirmDialogueContainer(header);\n        dialogue.find('button').addClass('hidden');\n        cancelButton.removeClass('hidden');\n        okayButton.removeClass('hidden');\n        text.text('');\n        dialogueHeader.addClass('hidden');\n        dialogueHeader.text('');\n\n        header.find(SELECTORS.CAN_RECEIVE_FOCUS).first().focus();\n        return true;\n    };\n\n    /**\n     * Render the confirm block user dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to block.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmBlockUser = function(header, body, footer, user) {\n        if (user) {\n            if (user.canmessageevenifblocked) {\n                return Str.get_string('cantblockuser', 'core_message', user.fullname)\n                    .then(function(string) {\n                        return showConfirmDialogue(header, body, footer, [], string, '', false, false, true);\n                    });\n            } else {\n                return Str.get_string('blockuserconfirm', 'core_message', user.fullname)\n                    .then(function(string) {\n                        return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_BLOCK], string, '', true, false);\n                    });\n            }\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm unblock user dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to unblock.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmUnblockUser = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('unblockuserconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_UNBLOCK], string, '', true, false);\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the add user as contact dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to add as contact.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmAddContact = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('addcontactconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_ADD_CONTACT],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the remove user from contacts dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} user User to remove from contacts.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmRemoveContact = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('removecontactconfirm', 'core_message', user.fullname)\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_REMOVE_CONTACT],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the delete selected messages dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data If the dialogue should show and checkbox shows to delete message for all users.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmDeleteSelectedMessages = function(header, body, footer, data) {\n        var showmessage = null;\n        if (data.type == CONVERSATION_TYPES.SELF) {\n            // Message displayed to self-conversations is slighly different.\n            showmessage = 'deleteselectedmessagesconfirmselfconversation';\n        } else {\n            // This other message should be displayed.\n            if (data.canDeleteMessagesForAllUsers) {\n                showCheckDeleteDialogue(body);\n                showmessage = 'deleteforeveryoneselectedmessagesconfirm';\n            } else {\n                showmessage = 'deleteselectedmessagesconfirm';\n            }\n        }\n\n        if (data.show) {\n            return Str.get_string(showmessage, 'core_message')\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm delete conversation dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {int|Null} type The conversation type to be removed.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmDeleteConversation = function(header, body, footer, type) {\n        var showmessage = null;\n        if (type == CONVERSATION_TYPES.SELF) {\n            // Message displayed to self-conversations is slighly different.\n            showmessage = 'deleteallselfconfirm';\n        } else if (type) {\n            // This other message should be displayed.\n            showmessage = 'deleteallconfirm';\n        }\n\n        if (showmessage) {\n            return Str.get_string(showmessage, 'core_message')\n                .then(function(string) {\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_CONFIRM_DELETE_CONVERSATION],\n                        string,\n                        '',\n                        true,\n                        false\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Render the confirm delete conversation dialogue.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} user The other user object.\n     * @return {Object} jQuery promise\n     */\n    var renderConfirmContactRequest = function(header, body, footer, user) {\n        if (user) {\n            return Str.get_string('userwouldliketocontactyou', 'core_message', user.fullname)\n                .then(function(string) {\n                    var buttonSelectors = [\n                        SELECTORS.ACTION_ACCEPT_CONTACT_REQUEST,\n                        SELECTORS.ACTION_DECLINE_CONTACT_REQUEST\n                    ];\n                    return showConfirmDialogue(header, body, footer, buttonSelectors, string, '', false, true);\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Show the checkbox to allow delete message for all.\n     *\n     * @param {Object} body The body container element.\n     */\n    var showCheckDeleteDialogue = function(body) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var checkboxRegion = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);\n        checkboxRegion.removeClass('hidden');\n    };\n\n    /**\n     * Hide the checkbox to allow delete message for all.\n     *\n     * @param {Object} body The body container element.\n     */\n    var hideCheckDeleteDialogue = function(body) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var checkboxRegion = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE_CONTAINER);\n        var checkbox = dialogue.find(SELECTORS.DELETE_MESSAGES_FOR_ALL_USERS_TOGGLE);\n        checkbox.prop('checked', false);\n        checkboxRegion.addClass('hidden');\n    };\n\n    /**\n     * Show or hide the block / unblock option in the header dropdown menu.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isBlocked is user blocked.\n     */\n    var renderIsBlocked = function(header, body, footer, isBlocked) {\n        if (isBlocked) {\n            header.find(SELECTORS.ACTION_REQUEST_BLOCK).addClass('hidden');\n            header.find(SELECTORS.ACTION_REQUEST_UNBLOCK).removeClass('hidden');\n        } else {\n            header.find(SELECTORS.ACTION_REQUEST_BLOCK).removeClass('hidden');\n            header.find(SELECTORS.ACTION_REQUEST_UNBLOCK).addClass('hidden');\n        }\n    };\n\n    /**\n     * Show or hide the favourite / unfavourite option in the header dropdown menu\n     * and the favourite star in the header title.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isFavourite is this conversation a favourite.\n     */\n    var renderIsFavourite = function(header, body, footer, state) {\n        var favouriteIcon = header.find(SELECTORS.FAVOURITE_ICON_CONTAINER);\n        var addFavourite = header.find(SELECTORS.ACTION_CONFIRM_FAVOURITE);\n        var removeFavourite = header.find(SELECTORS.ACTION_CONFIRM_UNFAVOURITE);\n\n        switch (state) {\n            case 'hide':\n                favouriteIcon.addClass('hidden');\n                addFavourite.addClass('hidden');\n                removeFavourite.addClass('hidden');\n                break;\n            case 'show-add':\n                favouriteIcon.addClass('hidden');\n                addFavourite.removeClass('hidden');\n                removeFavourite.addClass('hidden');\n                break;\n            case 'show-remove':\n                favouriteIcon.removeClass('hidden');\n                addFavourite.addClass('hidden');\n                removeFavourite.removeClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide the mute / unmute option in the header dropdown menu\n     * and the muted icon in the header title.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {string} state The state of the conversation as defined by the patcher.\n     */\n    var renderIsMuted = function(header, body, footer, state) {\n        var muteIcon = header.find(SELECTORS.MUTED_ICON_CONTAINER);\n        var setMuted = header.find(SELECTORS.ACTION_CONFIRM_MUTE);\n        var unsetMuted = header.find(SELECTORS.ACTION_CONFIRM_UNMUTE);\n\n        switch (state) {\n            case 'hide':\n                muteIcon.addClass('hidden');\n                setMuted.addClass('hidden');\n                unsetMuted.addClass('hidden');\n                break;\n            case 'show-mute':\n                muteIcon.addClass('hidden');\n                setMuted.removeClass('hidden');\n                unsetMuted.addClass('hidden');\n                break;\n            case 'show-unmute':\n                muteIcon.removeClass('hidden');\n                setMuted.addClass('hidden');\n                unsetMuted.removeClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide the add / remove user as contact option in the header dropdown menu.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} state the contact state.\n     */\n    var renderIsContact = function(header, body, footer, state) {\n        var addContact = header.find(SELECTORS.ACTION_REQUEST_ADD_CONTACT);\n        var removeContact = header.find(SELECTORS.ACTION_REQUEST_REMOVE_CONTACT);\n\n        switch (state) {\n            case 'pending-contact':\n                addContact.addClass('hidden');\n                removeContact.addClass('hidden');\n                break;\n            case 'contact':\n                addContact.addClass('hidden');\n                removeContact.removeClass('hidden');\n                break;\n            case 'non-contact':\n                addContact.removeClass('hidden');\n                removeContact.addClass('hidden');\n                break;\n        }\n    };\n\n    /**\n     * Show or hide confirm action from confirm dialogue is loading.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} isLoading confirm action is loading.\n     */\n    var renderLoadingConfirmAction = function(header, body, footer, isLoading) {\n        var dialogue = getConfirmDialogueContainer(body);\n        var buttons = dialogue.find('button');\n        var buttonText = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_BUTTON_TEXT);\n        var loadingIcon = dialogue.find(SELECTORS.LOADING_ICON_CONTAINER);\n\n        if (isLoading) {\n            buttons.prop('disabled', true);\n            buttonText.addClass('hidden');\n            loadingIcon.removeClass('hidden');\n        } else {\n            buttons.prop('disabled', false);\n            buttonText.removeClass('hidden');\n            loadingIcon.addClass('hidden');\n        }\n    };\n\n    /**\n     * Show or hide the header and footer content for edit mode.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Bool} inEditMode In edit mode or not.\n     */\n    var renderInEditMode = function(header, body, footer, inEditMode) {\n        var messages = null;\n\n        if (inEditMode) {\n            messages = body.find(SELECTORS.MESSAGE_NOT_SELECTED);\n            messages.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).removeClass('hidden');\n            hideHeaderContent(header);\n            showHeaderEditMode(header);\n        } else {\n            messages = getMessagesContainer(body);\n            messages.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).addClass('hidden');\n            messages.find(SELECTORS.MESSAGE_SELECTED_ICON).addClass('hidden');\n            showHeaderContent(header);\n            hideHeaderEditMode(header);\n        }\n    };\n\n    /**\n     * Select or unselect messages.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data The messages to select or unselect.\n     */\n    var renderSelectedMessages = function(header, body, footer, data) {\n        var hasSelectedMessages = data.count > 0;\n\n        if (data.add.length) {\n            data.add.forEach(function(messageId) {\n                var message = getMessageElement(body, messageId);\n                message.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).addClass('hidden');\n                message.find(SELECTORS.MESSAGE_SELECTED_ICON).removeClass('hidden');\n                message.attr('aria-checked', true);\n            });\n        }\n\n        if (data.remove.length) {\n            data.remove.forEach(function(messageId) {\n                var message = getMessageElement(body, messageId);\n\n                if (hasSelectedMessages) {\n                    message.find(SELECTORS.MESSAGE_NOT_SELECTED_ICON).removeClass('hidden');\n                }\n\n                message.find(SELECTORS.MESSAGE_SELECTED_ICON).addClass('hidden');\n                message.attr('aria-checked', false);\n            });\n        }\n\n        setMessagesSelectedCount(header, data.count);\n    };\n\n    /**\n     * Show or hide the require add contact panel.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} data Whether the user has to be added a a contact.\n     * @return {Object} jQuery promise\n     */\n    var renderRequireAddContact = function(header, body, footer, data) {\n        if (data.show && !data.hasMessages) {\n            return Str.get_strings([\n                    {\n                        key: 'requirecontacttomessage',\n                        component: 'core_message',\n                        param: data.user.fullname\n                    },\n                    {\n                        key: 'isnotinyourcontacts',\n                        component: 'core_message',\n                        param: data.user.fullname\n                    }\n                ])\n                .then(function(strings) {\n                    var title = strings[1];\n                    var text = strings[0];\n                    return showConfirmDialogue(\n                        header,\n                        body,\n                        footer,\n                        [SELECTORS.ACTION_REQUEST_ADD_CONTACT],\n                        text,\n                        title,\n                        false,\n                        true\n                    );\n                });\n        } else {\n            return hideConfirmDialogue(header, body, footer);\n        }\n    };\n\n    /**\n     * Show or hide the self-conversation message.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} displayMessage should the message be displayed?.\n     * @return {Object|true} jQuery promise\n     */\n    var renderSelfConversationMessage = function(header, body, footer, displayMessage) {\n        var container = getSelfConversationMessageContainer(body);\n        if (displayMessage) {\n            container.removeClass('hidden');\n        } else {\n            container.addClass('hidden');\n        }\n        return true;\n    };\n\n    /**\n     * Show or hide the require add contact panel.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @param {Object} userFullName Full name of the other user.\n     * @return {Object|true} jQuery promise\n     */\n    var renderContactRequestSent = function(header, body, footer, userFullName) {\n        var container = getContactRequestSentContainer(body);\n        if (userFullName) {\n            return Str.get_string('yourcontactrequestpending', 'core_message', userFullName)\n                .then(function(string) {\n                    container.find(SELECTORS.TEXT).text(string);\n                    container.removeClass('hidden');\n                    return string;\n                });\n        } else {\n            container.addClass('hidden');\n            return true;\n        }\n    };\n\n    /**\n     * Reset the UI to the initial state.\n     *\n     * @param {Object} header The header container element.\n     * @param {Object} body The body container element.\n     * @param {Object} footer The footer container element.\n     * @return {Bool}\n     */\n    var renderReset = function(header, body, footer) {\n        hideConfirmDialogue(header, body, footer);\n        hideContactRequestSentContainer(body);\n        hideSelfConversationMessageContainer(body);\n        hideAllHeaderElements(header);\n        showHeaderPlaceholder(header);\n        hideAllFooterElements(footer);\n        showFooterPlaceholder(footer);\n        return true;\n    };\n\n    var render = function(header, body, footer, patch) {\n        var configs = [\n            {\n                // Resetting the UI needs to come first, if it's required.\n                reset: renderReset\n            },\n            {\n                // Any async rendering (stuff that requires templates, strings etc) should\n                // go in here.\n                conversation: renderConversation,\n                header: renderHeader,\n                footer: renderFooter,\n                confirmBlockUser: renderConfirmBlockUser,\n                confirmUnblockUser: renderConfirmUnblockUser,\n                confirmAddContact: renderConfirmAddContact,\n                confirmRemoveContact: renderConfirmRemoveContact,\n                confirmDeleteSelectedMessages: renderConfirmDeleteSelectedMessages,\n                confirmDeleteConversation: renderConfirmDeleteConversation,\n                confirmContactRequest: renderConfirmContactRequest,\n                requireAddContact: renderRequireAddContact,\n                selfConversationMessage: renderSelfConversationMessage,\n                contactRequestSent: renderContactRequestSent\n            },\n            {\n                loadingMembers: renderLoadingMembers,\n                loadingFirstMessages: renderLoadingFirstMessages,\n                loadingMessages: renderLoadingMessages,\n                isBlocked: renderIsBlocked,\n                isContact: renderIsContact,\n                isFavourite: renderIsFavourite,\n                isMuted: renderIsMuted,\n                loadingConfirmAction: renderLoadingConfirmAction,\n                inEditMode: renderInEditMode\n            },\n            {\n                // Scrolling should be last to make sure everything\n                // on the page is visible.\n                scrollToMessage: renderScrollToMessage,\n                selectedMessages: renderSelectedMessages\n            }\n        ];\n        // Helper function to process each of the configs above.\n        var processConfig = function(config) {\n            var results = [];\n\n            for (var key in patch) {\n                if (config.hasOwnProperty(key)) {\n                    var renderFunc = config[key];\n                    var patchValue = patch[key];\n                    results.push(renderFunc(header, body, footer, patchValue));\n                }\n            }\n\n            return results;\n        };\n\n        // The first config is special because it resets the UI.\n        var renderingPromises = processConfig(configs[0]);\n        // The second config is special because it contains async rendering.\n        renderingPromises = renderingPromises.concat(processConfig(configs[1]));\n\n        // Wait for the async rendering to complete before processing the\n        // rest of the configs, in order.\n        return $.when.apply($, renderingPromises)\n            .then(function() {\n                for (var i = 2; i < configs.length; i++) {\n                    processConfig(configs[i]);\n                }\n\n                return;\n            })\n            .catch(Notification.exception);\n    };\n\n    return {\n        render: render,\n    };\n});\n"],"file":"message_drawer_view_conversation_renderer.min.js"}
\ No newline at end of file
diff --git a/message/amd/src/message_drawer_view_conversation.js b/message/amd/src/message_drawer_view_conversation.js
index a3cd6b7000f..b6b96dfda72 100644
--- a/message/amd/src/message_drawer_view_conversation.js
+++ b/message/amd/src/message_drawer_view_conversation.js
@@ -1545,6 +1545,7 @@ function(
             [SELECTORS.ACTION_CONFIRM_REMOVE_CONTACT, generateConfirmActionHandler(removeContact)],
             [SELECTORS.ACTION_CONFIRM_DELETE_SELECTED_MESSAGES, generateConfirmActionHandler(deleteSelectedMessages)],
             [SELECTORS.ACTION_CONFIRM_DELETE_CONVERSATION, generateConfirmActionHandler(deleteConversation)],
+            [SELECTORS.ACTION_OKAY_CONFIRM, generateConfirmActionHandler(cancelRequest)],
             [SELECTORS.ACTION_REQUEST_ADD_CONTACT, generateConfirmActionHandler(requestAddContact)],
             [SELECTORS.ACTION_ACCEPT_CONTACT_REQUEST, generateConfirmActionHandler(acceptContactRequest)],
             [SELECTORS.ACTION_DECLINE_CONTACT_REQUEST, generateConfirmActionHandler(declineContactRequest)],
diff --git a/message/amd/src/message_drawer_view_conversation_constants.js b/message/amd/src/message_drawer_view_conversation_constants.js
index d3384121273..03aaa445cee 100644
--- a/message/amd/src/message_drawer_view_conversation_constants.js
+++ b/message/amd/src/message_drawer_view_conversation_constants.js
@@ -25,6 +25,7 @@ define([], function() {
     var SELECTORS = {
         ACTION_ACCEPT_CONTACT_REQUEST: '[data-action="accept-contact-request"]',
         ACTION_CANCEL_CONFIRM: '[data-action="cancel-confirm"]',
+        ACTION_OKAY_CONFIRM: '[data-action="okay-confirm"]',
         ACTION_CANCEL_EDIT_MODE: '[data-action="cancel-edit-mode"]',
         ACTION_CONFIRM_ADD_CONTACT: '[data-action="confirm-add-contact"]',
         ACTION_CONFIRM_BLOCK: '[data-action="confirm-block"]',
@@ -50,6 +51,7 @@ define([], function() {
         CONFIRM_DIALOGUE_CANCEL_BUTTON: '[data-action="cancel-confirm"]',
         CONFIRM_DIALOGUE_CONTAINER: '[data-region="confirm-dialogue-container"]',
         CONFIRM_DIALOGUE_HEADER: '[data-region="dialogue-header"]',
+        CONFIRM_DIALOGUE_OKAY_BUTTON: '[data-action="okay-confirm"]',
         CONFIRM_DIALOGUE_TEXT: '[data-region="dialogue-text"]',
         CONTACT_REQUEST_SENT_MESSAGE_CONTAINER: '[data-region="contact-request-sent-message-container"]',
         CONTENT_PLACEHOLDER_CONTAINER: '[data-region="content-placeholder"]',
diff --git a/message/amd/src/message_drawer_view_conversation_renderer.js b/message/amd/src/message_drawer_view_conversation_renderer.js
index 4639d0f0bbb..7f3192301ee 100644
--- a/message/amd/src/message_drawer_view_conversation_renderer.js
+++ b/message/amd/src/message_drawer_view_conversation_renderer.js
@@ -981,6 +981,7 @@ function(
      * @param {String} headerText Text to show in dialogue header.
      * @param {Bool} canCancel Can this dialogue be cancelled.
      * @param {Bool} skipHeader Skip blanking out the header
+     * @param {Bool} showOk Show an 'Okay' button for a dialogue which will close it
      */
     var showConfirmDialogue = function(
         header,
@@ -990,13 +991,15 @@ function(
         bodyText,
         headerText,
         canCancel,
-        skipHeader
+        skipHeader,
+        showOk
     ) {
         var dialogue = getConfirmDialogueContainer(body);
         var buttons = buttonSelectors.map(function(selector) {
             return dialogue.find(selector);
         });
         var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);
+        var okayButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_OKAY_BUTTON);
         var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);
         var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);
 
@@ -1008,6 +1011,12 @@ function(
             cancelButton.addClass('hidden');
         }
 
+        if (showOk) {
+            okayButton.removeClass('hidden');
+        } else {
+            okayButton.addClass('hidden');
+        }
+
         if (headerText) {
             dialogueHeader.removeClass('hidden');
             dialogueHeader.text(headerText);
@@ -1041,6 +1050,7 @@ function(
     var hideConfirmDialogue = function(header, body, footer) {
         var dialogue = getConfirmDialogueContainer(body);
         var cancelButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_CANCEL_BUTTON);
+        var okayButton = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_OKAY_BUTTON);
         var text = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_TEXT);
         var dialogueHeader = dialogue.find(SELECTORS.CONFIRM_DIALOGUE_HEADER);
 
@@ -1050,6 +1060,7 @@ function(
         hideConfirmDialogueContainer(header);
         dialogue.find('button').addClass('hidden');
         cancelButton.removeClass('hidden');
+        okayButton.removeClass('hidden');
         text.text('');
         dialogueHeader.addClass('hidden');
         dialogueHeader.text('');
@@ -1072,7 +1083,7 @@ function(
             if (user.canmessageevenifblocked) {
                 return Str.get_string('cantblockuser', 'core_message', user.fullname)
                     .then(function(string) {
-                        return showConfirmDialogue(header, body, footer, [], string, '', true, false);
+                        return showConfirmDialogue(header, body, footer, [], string, '', false, false, true);
                     });
             } else {
                 return Str.get_string('blockuserconfirm', 'core_message', user.fullname)
diff --git a/message/templates/message_drawer_view_conversation_body_confirm_dialogue.mustache b/message/templates/message_drawer_view_conversation_body_confirm_dialogue.mustache
index 58adafa83f8..e1e2f659fbc 100644
--- a/message/templates/message_drawer_view_conversation_body_confirm_dialogue.mustache
+++ b/message/templates/message_drawer_view_conversation_body_confirm_dialogue.mustache
@@ -80,5 +80,6 @@
         <span data-region="dialogue-button-text">{{#str}} decline, core_message {{/str}}</span>
         <span class="hidden" data-region="loading-icon-container">{{> core/loading }}</span>
     </button>
+    <button type="button" class="btn btn-primary btn-block" data-action="okay-confirm">{{#str}} ok, core {{/str}}</button>
     <button type="button" class="btn btn-secondary btn-block" data-action="cancel-confirm">{{#str}} cancel, core {{/str}}</button>
 </div>