From fb7ec576ab3a353b6eb99614e9636a9096462807 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Thu, 25 Mar 2010 12:29:02 -0400
Subject: [PATCH] - Added possibility to select all messages in a folder (#1484756)

---
 CHANGELOG                             |    1 
 skins/default/templates/mail.html     |    1 
 skins/default/images/mail_footer.png  |    0 
 program/include/rcube_imap.php        |   32 ++++++++--
 skins/default/mail.css                |    8 ++
 program/localization/en_US/labels.inc |    1 
 program/lib/imap.inc                  |   15 ++--
 program/localization/pl_PL/labels.inc |    1 
 program/steps/mail/mark.inc           |   18 +++---
 program/js/app.js                     |   81 ++++++++++++++------------
 program/steps/mail/move_del.inc       |   12 ++--
 11 files changed, 103 insertions(+), 67 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index bbd0a88..f7905dd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
 CHANGELOG RoundCube Webmail
 ===========================
 
+- Added possibility to select all messages in a folder (#1484756)
 - Added 'imap_force_caps' option for after-login CAPABILITY checking (#1485750)
 - Password: Support dovecotpw encryption
 - TinyMCE 3.3.1
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index 64b300c..24080d6 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -2115,7 +2115,7 @@
     $mailbox = $mbox_name ? $this->mod_mailbox($mbox_name) : $this->mailbox;
 
     $flag = strtoupper($flag);
-    list($uids, $all_mode) = $this->_parse_uids($uids);
+    list($uids, $all_mode) = $this->_parse_uids($uids, $mailbox);
 
     if (strpos($flag, 'UN') === 0)
       $result = iil_C_UnFlag($this->conn, $mailbox, $uids, substr($flag, 2));
@@ -2209,7 +2209,7 @@
     $to_mbox = $this->mod_mailbox($to_mbox);
     $from_mbox = $from_mbox ? $this->mod_mailbox($from_mbox) : $this->mailbox;
 
-    list($uids, $all_mode) = $this->_parse_uids($uids);
+    list($uids, $all_mode) = $this->_parse_uids($uids, $from_mbox);
 
     // exit if no message uids are specified
     if (empty($uids))
@@ -2291,7 +2291,7 @@
     $to_mbox = $this->mod_mailbox($to_mbox);
     $from_mbox = $from_mbox ? $this->mod_mailbox($from_mbox) : $this->mailbox;
 
-    list($uids, $all_mode) = $this->_parse_uids($uids);
+    list($uids, $all_mode) = $this->_parse_uids($uids, $from_mbox);
 
     // exit if no message uids are specified
     if (empty($uids))
@@ -2329,7 +2329,7 @@
   {
     $mailbox = $mbox_name ? $this->mod_mailbox($mbox_name) : $this->mailbox;
 
-    list($uids, $all_mode) = $this->_parse_uids($uids);
+    list($uids, $all_mode) = $this->_parse_uids($uids, $mailbox);
 
     // exit if no message uids are specified
     if (empty($uids))
@@ -2450,14 +2450,32 @@
    * Parse message UIDs input
    *
    * @param mixed  UIDs array or comma-separated list or '*' or '1:*'
+   * @param string Mailbox name
    * @return array Two elements array with UIDs converted to list and ALL flag 
    * @access private
    */
-  private function _parse_uids($uids)
+  private function _parse_uids($uids, $mailbox)
     {
     if ($uids === '*' || $uids === '1:*') {
-      $uids = '1:*';
-      $all = true;
+      if (empty($this->search_set)) {
+        $uids = '1:*';
+        $all = true;
+        }
+      // get UIDs from current search set
+      // @TODO: skip iil_C_FetchUIDs() and work with IDs instead of UIDs (?)
+      else {
+        if ($this->search_threads)
+          $uids = iil_C_FetchUIDs($this->conn, $mailbox, array_keys($this->search_set['depth']));
+        else
+          $uids = iil_C_FetchUIDs($this->conn, $mailbox, $this->search_set);
+      
+        // save ID-to-UID mapping in local cache
+        if (is_array($uids))
+          foreach ($uids as $id => $uid)
+            $this->uid_id_map[$mailbox][$uid] = $id;
+
+        $uids = join(',', $uids);
+        }
       }
     else {
       if (is_array($uids))
diff --git a/program/js/app.js b/program/js/app.js
index 1f72909..0fc5e76 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -489,8 +489,8 @@
 
       case 'menu-open':
       case 'menu-save':
-	this.triggerEvent(command, {props:props});
-	return false;
+	    this.triggerEvent(command, {props:props});
+	    return false;
         break;
 
       case 'open':
@@ -753,10 +753,11 @@
         break;
         
       case 'select-all':
+        this.select_all_mode = props ? false : true;
         if (props == 'invert')
           this.message_list.invert_selection();
         else
-          this.message_list.select_all(props);
+          this.message_list.select_all(props == 'page' ? '' : props);
         break;
 
       case 'select-none':
@@ -1833,9 +1834,10 @@
 
     // unselect selected messages
     this.last_selected = 0;
-    if (this.message_list)
+    if (this.message_list) {
       this.message_list.clear_selection();
-    
+      this.select_all_mode = false;
+    }
     this.select_folder(mbox, this.env.mailbox);
     this.env.mailbox = mbox;
 
@@ -2254,8 +2256,8 @@
   // @private
   this._with_selected_messages = function(action, lock, add_url)
   {
-    var a_uids = new Array();
-    var count = 0;
+    var a_uids = new Array(),
+      count = 0;
 
     if (this.env.uid)
       a_uids[0] = this.env.uid;
@@ -2287,8 +2289,10 @@
       // remove threads from the end of the list
       this.delete_excessive_thread_rows();
 
+    add_url += '&_uid='+this.uids_to_list(a_uids);
+
     // send request to server
-    this.http_post(action, '_uid='+a_uids.join(',')+'&_mbox='+urlencode(this.env.mailbox)+add_url, lock);
+    this.http_post(action, '_mbox='+urlencode(this.env.mailbox)+add_url, lock);
   };
 
   // set a specific flag to one or more messages
@@ -2355,7 +2359,7 @@
     for (var i=0; i<a_uids.length; i++)
       this.set_message(a_uids[i], 'unread', (flag=='unread' ? true : false));
 
-    this.http_post('mark', '_uid='+a_uids.join(',')+'&_flag='+flag);
+    this.http_post('mark', '_uid='+this.uids_to_list(a_uids)+'&_flag='+flag);
 
     for (var i=0; i<a_uids.length; i++)
       this.update_thread_root(a_uids[i], flag);
@@ -2368,7 +2372,7 @@
     for (var i=0; i<a_uids.length; i++)
       this.set_message(a_uids[i], 'flagged', (flag=='flagged' ? true : false));
 
-    this.http_post('mark', '_uid='+a_uids.join(',')+'&_flag='+flag);
+    this.http_post('mark', '_uid='+this.uids_to_list(a_uids)+'&_flag='+flag);
   };
   
   // mark all message rows as deleted/undeleted
@@ -2412,49 +2416,48 @@
     for (var i=0; i<a_uids.length; i++)
       this.set_message(a_uids[i], 'deleted', false);
 
-    this.http_post('mark', '_uid='+a_uids.join(',')+'&_flag=undelete');
+    this.http_post('mark', '_uid='+this.uids_to_list(a_uids)+'&_flag=undelete');
     return true;
   };
 
   this.flag_as_deleted = function(a_uids)
   {
-    var add_url = '';
-    var r_uids = new Array();
-    var rows = this.message_list ? this.message_list.rows : new Array();
-    var count = 0;
+    var add_url = '',
+      r_uids = new Array(),
+      rows = this.message_list ? this.message_list.rows : new Array(),
+      count = 0;
 
-    for (var i=0; i<a_uids.length; i++)
-      {
+    for (var i=0; i<a_uids.length; i++) {
       uid = a_uids[i];
-      if (rows[uid])
-        {
+      if (rows[uid]) {
         if (rows[uid].unread)
           r_uids[r_uids.length] = uid;
 
-	if (this.env.skip_deleted) {
-	  count += this.update_thread(uid);
+	    if (this.env.skip_deleted) {
+	      count += this.update_thread(uid);
           this.message_list.remove_row(uid, (this.env.display_next && i == this.message_list.selection.length-1));
-	  }
-	else
-	  this.set_message(uid, 'deleted', true);
-        }
+	    }
+	    else
+	      this.set_message(uid, 'deleted', true);
       }
+    }
 
     // make sure there are no selected rows
     if (this.env.skip_deleted && this.message_list) {
       if(!this.env.display_next)
-      this.message_list.clear_selection();
+        this.message_list.clear_selection();
       if (count < 0)
         add_url += '&_count='+(count*-1);
       else if (count > 0) 
         // remove threads from the end of the list
         this.delete_excessive_thread_rows();
-      }
+    }
 
     add_url = '&_from='+(this.env.action ? this.env.action : '');
     
+    // ??
     if (r_uids.length)
-      add_url += '&_ruid='+r_uids.join(',');
+      add_url += '&_ruid='+this.uids_to_list(r_uids);
 
     if (this.env.skip_deleted) {
       // also send search request to get the right messages 
@@ -2464,7 +2467,7 @@
         add_url += '&_next_uid='+this.env.next_uid;
     }
     
-    this.http_post('mark', '_uid='+a_uids.join(',')+'&_flag=delete'+add_url);
+    this.http_post('mark', '_uid='+this.uids_to_list(a_uids)+'&_flag=delete'+add_url);
     return true;  
   };
 
@@ -2472,21 +2475,25 @@
   // argument should be a coma-separated list of uids
   this.flag_deleted_as_read = function(uids)
   {
-    var icn_src;
-    var rows = this.message_list ? this.message_list.rows : new Array();
-    var str = String(uids);
-    var a_uids = new Array();
+    var icn_src, uid,
+      rows = this.message_list ? this.message_list.rows : new Array(),
+      str = String(uids),
+      a_uids = str.split(',');
 
-    a_uids = str.split(',');
-
-    for (var uid, i=0; i<a_uids.length; i++)
-      {
+    for (var i=0; i<a_uids.length; i++) {
       uid = a_uids[i];
       if (rows[uid])
         this.set_message(uid, 'unread', false);
       }
   };
 
+  // Converts array of message UIDs to comma-separated list for use in URL
+  // with select_all mode checking
+  this.uids_to_list = function(uids)
+  {
+    return this.select_all_mode ? '*' : uids.join(',');
+  };
+  
 
   /*********************************************************/
   /*********       mailbox folders methods         *********/
diff --git a/program/lib/imap.inc b/program/lib/imap.inc
index b7c0b69..fc55d73 100644
--- a/program/lib/imap.inc
+++ b/program/lib/imap.inc
@@ -1066,16 +1066,15 @@
         return false;
 }
 
-function iil_C_FetchUIDs(&$conn,$mailbox) {
+function iil_C_FetchUIDs(&$conn, $mailbox, $message_set=null) {
 	global $clock;
+
+	if (is_array($message_set))
+		$message_set = join(',', $message_set);
+    else if (empty($message_set))
+		$message_set = '1:*';
 	
-	$num = iil_C_CountMessages($conn, $mailbox);
-	if ($num == 0) {
-	    return array();
-	}
-	$message_set = '1' . ($num>1?':' . $num:'');
-	
-	return iil_C_FetchHeaderIndex($conn, $mailbox, $message_set, 'UID');
+	return iil_C_FetchHeaderIndex($conn, $mailbox, $message_set, 'UID', false);
 }
 
 function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bodystr=false, $add='')
diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc
index 1a1291c..b8c36ec 100644
--- a/program/localization/en_US/labels.inc
+++ b/program/localization/en_US/labels.inc
@@ -146,6 +146,7 @@
 $labels['select'] = 'Select';
 $labels['all'] = 'All';
 $labels['none'] = 'None';
+$labels['currpage'] = 'Current page';
 $labels['unread'] = 'Unread';
 $labels['flagged'] = 'Flagged';
 $labels['unanswered'] = 'Unanswered';
diff --git a/program/localization/pl_PL/labels.inc b/program/localization/pl_PL/labels.inc
index d6af5ac..18dfffb 100644
--- a/program/localization/pl_PL/labels.inc
+++ b/program/localization/pl_PL/labels.inc
@@ -132,6 +132,7 @@
 $labels['messageactions'] = 'Więcej akcji...';
 $labels['select'] = 'Zaznacz';
 $labels['all'] = 'Wszystkie';
+$labels['currpage'] = 'Bieżąca strona';
 $labels['none'] = 'Brak';
 $labels['unread'] = 'Nieprzeczytane';
 $labels['flagged'] = 'Oznaczone';
diff --git a/program/steps/mail/mark.inc b/program/steps/mail/mark.inc
index c37a6e4..1a2838c 100644
--- a/program/steps/mail/mark.inc
+++ b/program/steps/mail/mark.inc
@@ -52,14 +52,14 @@
     exit;
   }
 
-  if($flag == 'DELETED' && $CONFIG['read_when_deleted'] && !empty($_POST['_ruid'])) {
-    $uids = get_input_value('_ruid', RCUBE_INPUT_POST);
-    $read = $IMAP->set_flag($uids, 'SEEN');
+  if ($flag == 'DELETED' && $CONFIG['read_when_deleted'] && !empty($_POST['_ruid'])) {
+    $ruids = get_input_value('_ruid', RCUBE_INPUT_POST);
+    $read = $IMAP->set_flag($ruids, 'SEEN');
     
     if ($read != -1 && !$CONFIG['skip_deleted'])
-      $OUTPUT->command('flag_deleted_as_read', $uids);
+      $OUTPUT->command('flag_deleted_as_read', $ruids);
   }
-    
+
   if ($flag == 'SEEN' || $flag == 'UNSEEN' || ($flag == 'DELETED' && !$CONFIG['skip_deleted'])) {
     rcmail_send_unread_count($IMAP->get_mailbox_name());
   }
@@ -99,20 +99,20 @@
 
       if ($old_unseen != $unseen_count) {
         $OUTPUT->command('set_unread_count', $mbox, $unseen_count, ($mbox == 'INBOX'));
-	$_SESSION['unseen_count'][$mbox] = $unseen_count;
+	    $_SESSION['unseen_count'][$mbox] = $unseen_count;
       }
       $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count));
 
       if ($IMAP->threading)
-	$count = get_input_value('_count', RCUBE_INPUT_POST);
+	    $count = get_input_value('_count', RCUBE_INPUT_POST);
 
       // add new rows from next page (if any)
-      if ($count && ($jump_back || $nextpage_count > 0)) {
+      if ($count && $uids != '*' && ($jump_back || $nextpage_count > 0)) {
         $sort_col   = isset($_SESSION['sort_col'])   ? $_SESSION['sort_col']   : $CONFIG['message_sort_col'];
         $sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order'];
   
         $a_headers = $IMAP->list_headers($mbox, NULL, $sort_col, $sort_order,
-	  $jump_back ? NULL : $count);
+	    $jump_back ? NULL : $count);
       
         rcmail_js_message_list($a_headers, false, false);
       }
diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc
index f884a78..f6d8d98 100644
--- a/program/steps/mail/move_del.inc
+++ b/program/steps/mail/move_del.inc
@@ -34,11 +34,11 @@
     $mbox = get_input_value('_mbox', RCUBE_INPUT_POST);
 
     $moved = $IMAP->move_message($uids, $target, $mbox);
-  
+
     if (!$moved) {
         // send error message
-	if ($_POST['_from'] != 'show')
-          $OUTPUT->command('list_mailbox');
+	    if ($_POST['_from'] != 'show')
+            $OUTPUT->command('list_mailbox');
         $OUTPUT->show_message('errormoving', 'error');
         $OUTPUT->send();
         exit;
@@ -55,8 +55,8 @@
   
     if (!$del) {
         // send error message
-	if ($_POST['_from'] != 'show')
-          $OUTPUT->command('list_mailbox');
+	    if ($_POST['_from'] != 'show')
+            $OUTPUT->command('list_mailbox');
         $OUTPUT->show_message('errordeleting', 'error');
         $OUTPUT->send();
         exit;
@@ -121,7 +121,7 @@
     $count = get_input_value('_count', RCUBE_INPUT_POST);
 
   // add new rows from next page (if any)
-  if ($addrows && $count && ($jump_back || $nextpage_count > 0)) {
+  if ($addrows && $count && $uids != '*' && ($jump_back || $nextpage_count > 0)) {
     $sort_col   = isset($_SESSION['sort_col'])   ? $_SESSION['sort_col']   : $CONFIG['message_sort_col'];
     $sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order'];
 
diff --git a/skins/default/images/mail_footer.png b/skins/default/images/mail_footer.png
index ab56b83..7e08677 100644
--- a/skins/default/images/mail_footer.png
+++ b/skins/default/images/mail_footer.png
Binary files differ
diff --git a/skins/default/mail.css b/skins/default/mail.css
index 0e35046..7b233f8 100644
--- a/skins/default/mail.css
+++ b/skins/default/mail.css
@@ -579,6 +579,14 @@
   background-position: -30px -15px;
 }
 
+#listcontrols a.page {
+  background-position: -135px 0;
+}
+
+#listcontrols a.pagesel {
+  background-position: -135px -15px;
+}
+
 #listcontrols a.unread {
   background-position: -45px 0;
 }
diff --git a/skins/default/templates/mail.html b/skins/default/templates/mail.html
index f82aca4..a1084b0 100644
--- a/skins/default/templates/mail.html
+++ b/skins/default/templates/mail.html
@@ -81,6 +81,7 @@
 <div id="listcontrols">
       <span><roundcube:label name="select" />:&nbsp;</span>
       <roundcube:button command="select-all" type="link" title="all" class="buttonPas all" classAct="button all" classSel="button allsel" content=" " />
+      <roundcube:button command="select-all" type="link" prop="page" title="currpage" class="buttonPas page" classAct="button page" classSel="button pagesel" content=" " />
       <roundcube:button command="select-all" type="link" prop="unread" title="unread" class="buttonPas unread" classAct="button unread" classSel="button unreadsel" content=" " />
       <roundcube:button command="select-all" type="link" prop="invert" title="invert" class="buttonPas invert" classAct="button invert" classSel="button invertsel" content=" " />
       <roundcube:button command="select-none" type="link" title="none" class="buttonPas none" classAct="button none" classSel="button nonesel" content=" " />

--
Gitblit v1.9.1