Bug 1412843 - Add keyboard shortcut to cycle through unread channels. r=nhnt11
authorMartin Giger <martin@humanoids.be>
Thu, 02 Nov 2017 15:32:26 +0100
changeset 23147 c9eeebf68c0147796f4f3cb3e611c370359fd35b
parent 23146 836e8ded762fa62d4d802f297b439b29f7be8515
child 23148 52ede0a12556611d74475302dc3ca3750cdfaf72
push id14000
push usermozilla@jorgk.com
push dateTue, 23 Jan 2018 09:11:56 +0000
treeherdercomm-central@c05162c61c90 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnhnt11
bugs1412843
Bug 1412843 - Add keyboard shortcut to cycle through unread channels. r=nhnt11
mail/components/im/content/chat-messenger-overlay.js
--- a/mail/components/im/content/chat-messenger-overlay.js
+++ b/mail/components/im/content/chat-messenger-overlay.js
@@ -1080,16 +1080,62 @@ var chatHandler = {
   _addObserver: function(aTopic) {
     imServices.obs.addObserver(chatHandler, aTopic);
     chatHandler._observedTopics.push(aTopic);
   },
   _removeObservers: function() {
     for (let topic of this._observedTopics)
       imServices.obs.removeObserver(this, topic);
   },
+  // TODO move this function away from here and test it.
+  _getNextUnreadConversation(aConversations, aCurrent, aReverse) {
+    let convCount = aConversations.length;
+    if (!convCount)
+      return;
+
+    let direction = aReverse ? -1 : 1;
+    let next = (i) => {
+      i += direction;
+      if (i < 0)
+        return i + convCount;
+      if (i >= convCount)
+        return i - convCount;
+      return i;
+    };
+
+    // Find starting point
+    let start = 0;
+    if (Number.isInteger(aCurrent))
+      start = next(aCurrent);
+    else if (aReverse)
+      start = convCount - 1;
+
+    // Cycle through all conversations until we are at the start again.
+    let i = start;
+    do {
+      // If there is a conversation with unread messages, select it.
+      if (aConversations[i].unreadIncomingMessageCount)
+        return i;
+      i = next(i);
+    } while (i !== start && i !== aCurrent);
+    return -1;
+  },
+  _selectNextUnreadConversation(aReverse, aList) {
+    let conversations = document.getElementById("conversationsGroup").contacts;
+    if (!conversations.length)
+      return;
+
+    let rawConversations = conversations.map((c) => c.conv);
+    let current;
+    if (aList.selectedItem.localName === "imconv")
+      current = aList.selectedIndex - aList.getIndexOfItem(conversations[0]);
+    let newIndex = this._getNextUnreadConversation(rawConversations, current, aReverse);
+    if (newIndex !== -1)
+      aList.selectedItem = conversations[newIndex];
+  },
   init: function() {
     Notifications.init();
     if (!Services.prefs.getBoolPref("mail.chat.enabled")) {
       ["button-chat", "menu_goChat", "goChatSeparator",
        "imAccountsStatus", "joinChatMenuItem", "newIMAccountMenuItem",
        "newIMContactMenuItem", "appmenu_joinChatMenuItem", "appmenu_afterChatSeparator",
        "appmenu_goChat", "appmenu_imAccountsStatus", "appmenu_goChatSeparator",
        "appmenu_newIMAccountMenuItem", "appmenu_newIMContactMenuItem"].forEach(function(aId) {
@@ -1123,17 +1169,21 @@ var chatHandler = {
     listbox.addEventListener("select", this.onListItemSelected.bind(this));
     listbox.addEventListener("click", this.onListItemClick.bind(this));
     document.getElementById("chatTabPanel").addEventListener("keypress", function(aEvent) {
       let accelKeyPressed = (AppConstants.platform == "macosx") ? aEvent.metaKey : aEvent.ctrlKey;
       if (!accelKeyPressed ||
           (aEvent.keyCode != aEvent.DOM_VK_DOWN && aEvent.keyCode != aEvent.DOM_VK_UP))
         return;
       listbox._userSelecting = true;
-      listbox.moveByOffset(aEvent.keyCode == aEvent.DOM_VK_DOWN ? 1 : -1, true, false);
+      let reverse = aEvent.keyCode != aEvent.DOM_VK_DOWN;
+      if (aEvent.shiftKey)
+        chatHandler._selectNextUnreadConversation(reverse, listbox);
+      else
+        listbox.moveByOffset(reverse ? -1 : 1, true, false);
       listbox._userSelecting = false;
       let item = listbox.selectedItem;
       if (item.localName == "imconv" && item.convView)
         item.convView.focus();
       else
         listbox.focus();
     });
     window.addEventListener("resize", this.onConvResize.bind(this));