If selected message(s) disappear from mailbox, gracefully handle in the UI
authorMichael M Slusarz <slusarz@curecanti.org>
Thu, 24 Dec 2009 09:04:30 +0000 (02:04 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Thu, 24 Dec 2009 09:07:28 +0000 (02:07 -0700)
This is a very subtle yet important issue. Goes together with
Request #7297 in that messages that may disappear from the search
mailbox (e.g. read messages in the Virtual Inbox) correctly causes all
selected message functions to be disabled and the preview pane to
clear.

imp/docs/CHANGES
imp/js/ViewPort.js
imp/lib/Views/ListMessages.php

index 05fb122..dddc680 100644 (file)
@@ -2,7 +2,10 @@
 v5.0-git
 --------
 
-[mms] Only update search mailbox on explicit user action (Request #7297).
+[mms] If selected message(s) disappear from mailbox, gracefully handle in the
+      user interface (DIMP).
+[mms] Only update search mailbox on explicit user action (Request #7297)
+      (DIMP).
 [mms] Add auto-save draft to IMP (Request #7656).
 [mms] Add keyboard shortcut to move to next unseen message (Request #8223).
 [mms] Add hook to dynamically change mailbox label (Request #6734).
index 9ee91df..3b1bd62 100644 (file)
  *       the viewable rows. Keys are a unique ID (see also the 'rowlist'
  *       entry). Values are the data objects. Internal keys for these data
  *       objects must NOT begin with the string 'VP_'.
+ * disappear: (array) If update is set, this is the list of unique IDs that
+ *            have been cached by the browser but no longer appear on the
+ *            server.
  * label: (string) [REQUIRED when initial is true] The label to use for the
  *        view.
  * metadata [optional]: (object) Metadata for the view. Entries in buffer are
@@ -828,6 +831,9 @@ var ViewPort = Class.create({
 
         if (r.reset) {
             this.select(new ViewPort_Selection());
+        } else if (r.update && r.disappear && r.disappear.size()) {
+            this.deselect(this.createSelection('uid', r.disappear, r.view));
+            buffer.removeData(r.disappear);
         }
 
         llist.unset(r.requestid);
@@ -1576,6 +1582,14 @@ ViewPort_Buffer = Class.create({
         }, this);
     },
 
+    removeData: function(uids)
+    {
+        uids.each(function(u) {
+            this.data.unset(u);
+            this.uidlist.unset(u);
+        }, this);
+    },
+
     resetRowlist: function()
     {
         this.rowlist = $H();
index 7799d2e..e407e60 100644 (file)
@@ -230,21 +230,37 @@ class IMP_Views_ListMessages
 
         /* Generate the message list and the UID -> rownumber list. */
         $data = $msglist = $rowlist = array();
-        foreach (range($slice_start, $slice_end) as $key) {
-            $uid = $sorted_list['s'][$key] .
-                (isset($sorted_list['m'][$key])
-                    ? IMP::IDX_SEP . $sorted_list['m'][$key]
-                    : '');
-            if ($uid) {
-                $msglist[$key] = $sorted_list['s'][$key];
-                $rowlist[$uid] = $key;
-                if (!isset($cached[$uid])) {
-                    $data[] = $key;
-                }
+        $uidlist = $this->_getUidList($slice_start, $slice_end, $sorted_list);
+        foreach ($uidlist as $uid => $seq) {
+            $msglist[$seq] = $sorted_list['s'][$seq];
+            $rowlist[$uid] = $seq;
+            if (!isset($cached[$uid])) {
+                $data[] = $seq;
             }
         }
         $result->rowlist = $rowlist;
 
+        /* If we are updating the rowlist on the browser, and we have cached
+         * browser data information, we need to send a list of messages that
+         * have 'disappeared'. */
+        if (isset($result->update)) {
+            if (($slice_start != 0) &&
+                ($slice_end != count($sorted_list['s']))) {
+                $uidlist = $this->_getUidList(0, count($sorted_list['s']), $sorted_list);
+            }
+
+            $disappear = array();
+            foreach (array_keys($cached) as $val) {
+                if (!isset($uidlist[$val])) {
+                    $disappear[] = $val;
+                }
+            }
+
+            if (!empty($disappear)) {
+                $result->disappear = $disappear;
+            }
+        }
+
         /* Build the list for rangeslice information. */
         if ($args['rangeslice']) {
             $slice = new stdClass;
@@ -278,6 +294,32 @@ class IMP_Views_ListMessages
     }
 
     /**
+     * Generates the list of unique UIDs for the current mailbox.
+     *
+     * @param integer $start      The slice start.
+     * @param integer $end        The slice end.
+     * @param array $sorted_list  The sorted list array.
+     *
+     * @param array  UIDs as the keys, and sequence numbers as the values.
+     */
+    protected function _getUidList($start, $end, $sorted_list)
+    {
+        $ret = array();
+
+        for ($i = $start; $i <= $end; ++$i) {
+            $uid = $sorted_list['s'][$i] .
+                (isset($sorted_list['m'][$i])
+                    ? IMP::IDX_SEP . $sorted_list['m'][$i]
+                    : '');
+            if ($uid) {
+                $ret[$uid] = $i;
+            }
+        }
+
+        return $ret;
+    }
+
+    /**
      * Obtains IMAP overview data for a given set of message UIDs.
      *
      * @param IMP_Mailbox $imp_mailbox  An IMP_Mailbox:: object.