From 2c33c7e38bc767330b4eebdc9e4d234caca72966 Mon Sep 17 00:00:00 2001
From: Thomas Bruederli <thomas@roundcube.net>
Date: Thu, 16 Jan 2014 09:41:19 -0500
Subject: [PATCH] Make message pagenav (prev/next) work with sorted multi-folder search results

---
 program/steps/mail/list.inc                        |    2 +
 program/lib/Roundcube/rcube_result_multifolder.php |   40 ++++++++++++++++++--
 program/steps/mail/search.inc                      |    8 ++--
 program/lib/Roundcube/rcube_imap.php               |   10 ++++
 program/steps/mail/func.inc                        |    4 +
 program/js/app.js                                  |    3 +
 6 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/program/js/app.js b/program/js/app.js
index 2717e35..5eae823 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -696,6 +696,7 @@
         break;
 
       case 'list':
+        // TODO: don't reset search but re-send for the new folder
         if (props && props != '')
           this.reset_qsearch();
         if (this.env.action == 'compose' && this.env.extwin)
@@ -1620,7 +1621,7 @@
 
     var uid = list.get_single_selection();
 
-    if (uid && this.env.mailbox == this.env.drafts_mailbox)
+    if (uid && (this.env.messages[uid].mbox || this.env.mailbox) == this.env.drafts_mailbox)
       this.open_compose_step({ _draft_uid: uid, _mbox: this.env.mailbox });
     else if (uid)
       this.show_message(uid, false, false);
diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php
index e265946..847bcfa 100644
--- a/program/lib/Roundcube/rcube_imap.php
+++ b/program/lib/Roundcube/rcube_imap.php
@@ -973,6 +973,9 @@
                 $a_msg_headers = $this->conn->sortHeaders($a_msg_headers, $sort_field, $this->sort_order);
             }
 
+            // store (sorted) message index
+            $search_set->set_message_index($a_msg_headers, $sort_field, $this->sort_order);
+
             // only return the requested part of the set
             $slice_length  = min($page_size, $cnt - ($to > $cnt ? $from : $to));
             $a_msg_headers = array_slice(array_values($a_msg_headers), $from, $slice_length);
@@ -1279,8 +1282,13 @@
                 return new rcube_result_index($folder, '* SORT');
             }
 
+            if ($this->search_set instanceof rcube_result_multifolder) {
+                $index = $this->search_set;
+                $index->folder = $folder;
+                // TODO: handle changed sorting
+            }
             // search result is an index with the same sorting?
-            if (($this->search_set instanceof rcube_result_index)
+            else if (($this->search_set instanceof rcube_result_index)
                 && ((!$this->sort_field && !$this->search_sorted) ||
                     ($this->search_sorted && $this->search_sort_field == $this->sort_field))
             ) {
diff --git a/program/lib/Roundcube/rcube_result_multifolder.php b/program/lib/Roundcube/rcube_result_multifolder.php
index 8d7ae5d..277a6d1 100644
--- a/program/lib/Roundcube/rcube_result_multifolder.php
+++ b/program/lib/Roundcube/rcube_result_multifolder.php
@@ -28,8 +28,11 @@
 {
     public $multi = true;
     public $sets = array();
+    public $folder;
 
     protected $meta = array();
+    protected $index = array();
+    protected $sorting;
     protected $order = 'ASC';
 
 
@@ -53,6 +56,19 @@
         $this->meta['count'] += $result->count();
     }
 
+    /**
+     * Store a global index of (sorted) message UIDs
+     */
+    public function set_message_index($headers, $sort_field, $sort_order)
+    {
+        $this->index = array();
+        foreach ($headers as $header) {
+            $this->index[] = $header->uid . '-' . $header->folder;
+        }
+
+        $this->sorting = $sort_field;
+        $this->order = $sort_order;
+    }
 
     /**
      * Checks the result from IMAP command
@@ -119,7 +135,10 @@
      */
     public function exists($msgid, $get_index = false)
     {
-        return false;
+        if (!empty($this->folder)) {
+            $msgid .= '-' . $this->folder;
+        }
+        return array_search($msgid, $this->index);
     }
 
 
@@ -157,7 +176,7 @@
      */
     public function get()
     {
-        return array();
+        return $this->index;
     }
 
 
@@ -179,9 +198,13 @@
      *
      * @return int Element value
      */
-    public function get_element($index)
+    public function get_element($idx)
     {
-        return null;
+        switch ($idx) {
+            case 'FIRST': return $this->index[0];
+            case 'LAST':  return end($this->index);
+            default:      return $this->index[$idx];
+        }
     }
 
 
@@ -195,6 +218,15 @@
      */
     public function get_parameters($param=null)
     {
+        $params = array(
+            'SORT' => $this->sorting,
+            'ORDER' => $this->order,
+        );
+
+        if ($param !== null) {
+            return $params[$param];
+        }
+
         return $params;
     }
 
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 3848ec5..45d4242 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -76,9 +76,11 @@
   $_REQUEST['_uid'] = $_uid;
   unset($_uid);
 
-  if (empty($_REQUEST['_mbox']) && !empty($mbox)) {
+  // override mbox
+  if (!empty($mbox)) {
     $_GET['_mbox']  = $mbox;
     $_POST['_mbox'] = $mbox;
+    $RCMAIL->storage->set_folder(($_SESSION['mbox'] = $mbox));
   }
 }
 
diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc
index 4b2a955..a77d60f 100644
--- a/program/steps/mail/list.inc
+++ b/program/steps/mail/list.inc
@@ -90,6 +90,8 @@
       if ($header->parent_uid)
         $header->parent_uid .= '-'.$header->folder;
     }
+
+    $OUTPUT->command('select_folder', '');
   }
 }
 // remove old search data
diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc
index 5ce9fe6..b45cdc0 100644
--- a/program/steps/mail/search.inc
+++ b/program/steps/mail/search.inc
@@ -114,6 +114,10 @@
     $RCMAIL->storage->search($mboxes, $search_str, $imap_charset, $sort_column);
 }
 
+// Get the headers
+$result_h = $RCMAIL->storage->list_messages($mbox, 1, $sort_column, rcmail_sort_order());
+$count    = $RCMAIL->storage->count($mbox, $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL');
+
 // save search results in session
 if (!is_array($_SESSION['search'])) {
     $_SESSION['search'] = array();
@@ -124,10 +128,6 @@
     $_SESSION['last_text_search'] = $str;
 }
 $_SESSION['search_request'] = $search_request;
-
-// Get the headers
-$result_h = $RCMAIL->storage->list_messages($mbox, 1, $sort_column, rcmail_sort_order());
-$count    = $RCMAIL->storage->count($mbox, $RCMAIL->storage->get_threading() ? 'THREADS' : 'ALL');
 
 // Add 'folder' column to list
 if ($_SESSION['search'][1]->multi) {

--
Gitblit v1.9.1