diff options
Diffstat (limited to 'program/steps')
-rw-r--r-- | program/steps/mail/check_recent.inc | 33 | ||||
-rw-r--r-- | program/steps/mail/func.inc | 358 | ||||
-rw-r--r-- | program/steps/mail/list.inc | 21 | ||||
-rw-r--r-- | program/steps/mail/mark.inc | 9 | ||||
-rw-r--r-- | program/steps/mail/move_del.inc | 10 | ||||
-rw-r--r-- | program/steps/mail/search.inc | 4 | ||||
-rw-r--r-- | program/steps/mail/show.inc | 4 | ||||
-rw-r--r-- | program/steps/mail/viewsource.inc | 2 | ||||
-rw-r--r-- | program/steps/settings/func.inc | 24 | ||||
-rw-r--r-- | program/steps/settings/manage_folders.inc | 84 | ||||
-rw-r--r-- | program/steps/settings/save_prefs.inc | 2 |
11 files changed, 281 insertions, 270 deletions
diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc index 9bc9e6f92..3c2827502 100644 --- a/program/steps/mail/check_recent.inc +++ b/program/steps/mail/check_recent.inc @@ -32,13 +32,12 @@ foreach ($a_mailboxes as $mbox_name) { } // get overall message count; allow caching because rcube_imap::recent_uids() did a refresh - $all_count = $IMAP->messagecount(); + $all_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL'); $unread_count = $IMAP->messagecount(NULL, 'UNSEEN', TRUE); $_SESSION['unseen_count'][$mbox_name] = $unread_count; $OUTPUT->set_env('messagecount', $all_count); - $OUTPUT->set_env('pagesize', $IMAP->page_size); $OUTPUT->set_env('pagecount', ceil($all_count/$IMAP->page_size)); $OUTPUT->command('set_unread_count', $mbox_name, $unread_count, ($mbox_name == 'INBOX')); $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($all_count)); @@ -56,17 +55,27 @@ foreach ($a_mailboxes as $mbox_name) { if (empty($_GET['_list'])) continue; - // use SEARCH/SORT to find recent messages - $search_str = 'UID '.min($recents).':'.max($recents); - if ($search_request) - $search_str .= ' '.$IMAP->search_string; + if ($IMAP->threading) { + $OUTPUT->command('message_list.clear'); + $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']; + $result_h = $IMAP->list_headers($mbox_name, NULL, $sort_col, $sort_order); + // add to the list + rcmail_js_message_list($result_h); + } + else { + // use SEARCH/SORT to find recent messages + $search_str = 'UID '.min($recents).':'.max($recents); + if ($search_request) + $search_str .= ' '.$IMAP->search_string; - if ($IMAP->search($mbox_name, $search_str, NULL, 'date')) { - // revert sort order - $order = $_SESSION['sort_col'] == 'date' && $_SESSION['sort_order'] == 'DESC' ? 'ASC' : 'DESC'; - // get the headers and add them to the list - $result_h = $IMAP->list_headers($mbox_name, 1, 'date', $order); - rcmail_js_message_list($result_h, true, false); + if ($IMAP->search($mbox_name, $search_str, NULL, 'date')) { + // revert sort order + $order = $_SESSION['sort_col'] == 'date' && $_SESSION['sort_order'] == 'DESC' ? 'ASC' : 'DESC'; + // get the headers and add them to the list + $result_h = $IMAP->list_headers($mbox_name, 1, 'date', $order); + rcmail_js_message_list($result_h, true, false); + } } } else { diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 1968d20b2..5f52161c4 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -59,6 +59,17 @@ if (!isset($_SESSION['sort_col'])) if (!isset($_SESSION['sort_order'])) $_SESSION['sort_order'] = $CONFIG['message_sort_order']; +// set threads mode +$a_threading = $RCMAIL->config->get('message_threading', array()); +if (isset($_GET['_threads'])) { + if ($_GET['_threads']) + $a_threading[$_SESSION['mbox']] = true; + else + unset($a_threading[$_SESSION['mbox']]); + $RCMAIL->user->save_prefs(array('message_threading' => $a_threading)); +} +$IMAP->set_threading($a_threading[$_SESSION['mbox']]); + // set message set for search result if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) { @@ -88,13 +99,20 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') $OUTPUT->set_env('search_mods', $search_mods); // make sure the message count is refreshed (for default view) - $IMAP->messagecount($mbox_name, 'ALL', true); + $IMAP->messagecount($mbox_name, $IMAP->threading ? 'THREADS' : 'ALL', true); } - // set current mailbox in client environment + // set current mailbox and some other vars in client environment $OUTPUT->set_env('mailbox', $mbox_name); + $OUTPUT->set_env('pagesize', $IMAP->page_size); $OUTPUT->set_env('quota', $IMAP->get_capability('quota')); $OUTPUT->set_env('delimiter', $IMAP->get_hierarchy_delimiter()); + $OUTPUT->set_env('threading', (bool) $IMAP->threading); + $OUTPUT->set_env('threads', $IMAP->threading + || $IMAP->get_capability('thread=references') + || $IMAP->get_capability('thread=orderedsubject') + || $IMAP->get_capability('thread=refs') + ); if ($CONFIG['flag_for_deletion']) $OUTPUT->set_env('flag_for_deletion', true); @@ -123,43 +141,26 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') * return the message list as HTML table */ function rcmail_message_list($attrib) - { - global $IMAP, $CONFIG, $COMM_PATH, $OUTPUT; - - $skin_path = $CONFIG['skin_path']; - $image_tag = '<img src="%s%s" alt="%s" />'; +{ + global $IMAP, $CONFIG, $OUTPUT; - // check to see if we have some settings for sorting - $sort_col = $_SESSION['sort_col']; - $sort_order = $_SESSION['sort_order']; - // add some labels to client $OUTPUT->add_label('from', 'to'); - // get message headers - $a_headers = $IMAP->list_headers('', '', $sort_col, $sort_order); - // add id to message list table if not specified if (!strlen($attrib['id'])) $attrib['id'] = 'rcubemessagelist'; - // allow the following attributes to be added to the <table> tag - $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary')); - - $out = '<table' . $attrib_str . ">\n"; - // define list of cols to be displayed based on parameter or config if (empty($attrib['columns'])) $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject'); else $a_show_cols = preg_split('/[\s,;]+/', strip_quotes($attrib['columns'])); - // store column list in a session-variable + // save some variables for use in ajax list $_SESSION['list_columns'] = $a_show_cols; + $_SESSION['list_attrib'] = $attrib; - // define sortable columns - $a_sort_cols = array('subject', 'date', 'from', 'to', 'size'); - $mbox = $IMAP->get_mailbox_name(); $delim = $IMAP->get_hierarchy_delimiter(); @@ -167,198 +168,19 @@ function rcmail_message_list($attrib) if ((strpos($mbox.$delim, $CONFIG['sent_mbox'].$delim)===0 || strpos($mbox.$delim, $CONFIG['drafts_mbox'].$delim)===0) && (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false) $a_show_cols[$f] = 'to'; - - // add col definition - $out .= '<colgroup>'; - $out .= '<col class="icon" />'; - - foreach ($a_show_cols as $col) - $out .= ($col!='attachment') ? sprintf('<col class="%s" />', $col) : '<col class="icon" />'; - $out .= "</colgroup>\n"; - - // add table title - $out .= "<thead><tr>\n<td class=\"icon\"> </td>\n"; - - $javascript = ''; - foreach ($a_show_cols as $col) - { - // get column name - switch ($col) - { - case 'flag': - $col_name = sprintf($image_tag, $skin_path, $attrib['unflaggedicon'], ''); - break; - case 'attachment': - $col_name = sprintf($image_tag, $skin_path, $attrib['attachmenticon'], ''); - break; - default: - $col_name = Q(rcube_label($col)); - } - - // make sort links - $sort = ''; - if (in_array($col, $a_sort_cols)) - { - // have buttons configured - if (!empty($attrib['sortdescbutton']) || !empty($attrib['sortascbutton'])) - { - $sort = ' '; - - // asc link - if (!empty($attrib['sortascbutton'])) - { - $sort .= $OUTPUT->button(array( - 'command' => 'sort', - 'prop' => $col.'_ASC', - 'image' => $attrib['sortascbutton'], - 'align' => 'absmiddle', - 'title' => 'sortasc')); - } - - // desc link - if (!empty($attrib['sortdescbutton'])) - { - $sort .= $OUTPUT->button(array( - 'command' => 'sort', - 'prop' => $col.'_DESC', - 'image' => $attrib['sortdescbutton'], - 'align' => 'absmiddle', - 'title' => 'sortdesc')); - } - } - // just add a link tag to the header - else - { - $col_name = sprintf( - '<a href="./#sort" onclick="return %s.command(\'sort\',\'%s\',this)" title="%s">%s</a>', - JS_OBJECT_NAME, - $col, - rcube_label('sortby'), - $col_name); - } - } - - $sort_class = $col==$sort_col ? " sorted$sort_order" : ''; - - // put it all together - if ($col!='attachment') - $out .= '<td class="'.$col.$sort_class.'" id="rcm'.$col.'">' . "$col_name$sort</td>\n"; - else - $out .= '<td class="icon" id="rcm'.$col.'">' . "$col_name$sort</td>\n"; - } - - $out .= "</tr></thead>\n<tbody>\n"; - - // no messages in this mailbox - if (!sizeof($a_headers)) - $OUTPUT->show_message('nomessagesfound', 'notice'); - - $a_js_message_arr = array(); - - // create row for each message - foreach ($a_headers as $i => $header) //while (list($i, $header) = each($a_headers)) - { - $message_icon = $attach_icon = $flagged_icon = ''; - $js_row_arr = array(); - $zebra_class = $i%2 ? ' even' : ' odd'; - - // set messag attributes to javascript array - if ($header->deleted) - $js_row_arr['deleted'] = true; - if (!$header->seen) - $js_row_arr['unread'] = true; - if ($header->answered) - $js_row_arr['replied'] = true; - if ($header->forwarded) - $js_row_arr['forwarded'] = true; - if ($header->flagged) - $js_row_arr['flagged'] = true; - - // set message icon - if ($attrib['deletedicon'] && $header->deleted) - $message_icon = $attrib['deletedicon']; - else if ($attrib['repliedicon'] && $header->answered) - { - if ($attrib['forwardedrepliedicon'] && $header->forwarded) - $message_icon = $attrib['forwardedrepliedicon']; - else - $message_icon = $attrib['repliedicon']; - } - else if ($attrib['forwardedicon'] && $header->forwarded) - $message_icon = $attrib['forwardedicon']; - else if ($attrib['unreadicon'] && !$header->seen) - $message_icon = $attrib['unreadicon']; - else if ($attrib['messageicon']) - $message_icon = $attrib['messageicon']; - - if ($attrib['flaggedicon'] && $header->flagged) - $flagged_icon = $attrib['flaggedicon']; - else if ($attrib['unflaggedicon'] && !$header->flagged) - $flagged_icon = $attrib['unflaggedicon']; - - // set attachment icon - if ($attrib['attachmenticon'] && preg_match("/multipart\/m/i", $header->ctype)) - $attach_icon = $attrib['attachmenticon']; - - $out .= sprintf('<tr id="rcmrow%d" class="message%s%s%s%s">'."\n", - $header->uid, - $header->seen ? '' : ' unread', - $header->deleted ? ' deleted' : '', - $header->flagged ? ' flagged' : '', - $zebra_class); - - $out .= sprintf("<td class=\"icon\">%s</td>\n", $message_icon ? sprintf($image_tag, $skin_path, $message_icon, '') : ''); - - $IMAP->set_charset(!empty($header->charset) ? $header->charset : $CONFIG['default_charset']); - - // format each col - foreach ($a_show_cols as $col) - { - if (in_array($col, array('from', 'to', 'cc', 'replyto'))) - $cont = Q(rcmail_address_string($header->$col, 3, false, $attrib['addicon']), 'show'); - else if ($col=='subject') - { - $action = $mbox==$CONFIG['drafts_mbox'] ? 'compose' : 'show'; - $uid_param = $mbox==$CONFIG['drafts_mbox'] ? '_draft_uid' : '_uid'; - $cont = abbreviate_string(trim($IMAP->decode_header($header->$col)), 160); - if (empty($cont)) $cont = rcube_label('nosubject'); - $cont = $OUTPUT->browser->ie ? Q($cont) : sprintf('<a href="%s" onclick="return rcube_event.cancel(event)">%s</a>', Q(rcmail_url($action, array($uid_param=>$header->uid, '_mbox'=>$mbox))), Q($cont)); - } - else if ($col=='flag') - $cont = $flagged_icon ? sprintf($image_tag, $skin_path, $flagged_icon, '') : ''; - else if ($col=='size') - $cont = show_bytes($header->$col); - else if ($col=='date') - $cont = format_date($header->date); - else - $cont = Q($header->$col); - - if ($col!='attachment') - $out .= '<td class="'.$col.'">' . $cont . "</td>\n"; - else - $out .= sprintf("<td class=\"icon\">%s</td>\n", $attach_icon ? sprintf($image_tag, $skin_path, $attach_icon, '') : ' '); - } - - $out .= "</tr>\n"; - - if (sizeof($js_row_arr)) - $a_js_message_arr[$header->uid] = $js_row_arr; - } - - // complete message table - $out .= "</tbody></table>\n"; - - $message_count = $IMAP->messagecount(); + $skin_path = $_SESSION['skin_path'] = $CONFIG['skin_path']; + $message_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL'); // set client env $OUTPUT->add_gui_object('mailcontframe', 'mailcontframe'); $OUTPUT->add_gui_object('messagelist', $attrib['id']); + $OUTPUT->set_env('autoexpand_threads', intval($CONFIG['autoexpand_threads'])); $OUTPUT->set_env('messagecount', $message_count); $OUTPUT->set_env('current_page', $IMAP->list_page); $OUTPUT->set_env('pagecount', ceil($message_count/$IMAP->page_size)); - $OUTPUT->set_env('sort_col', $sort_col); - $OUTPUT->set_env('sort_order', $sort_order); + $OUTPUT->set_env('sort_col', $_SESSION['sort_col']); + $OUTPUT->set_env('sort_order', $_SESSION['sort_order']); if ($attrib['messageicon']) $OUTPUT->set_env('messageicon', $skin_path . $attrib['messageicon']); @@ -378,22 +200,35 @@ function rcmail_message_list($attrib) $OUTPUT->set_env('flaggedicon', $skin_path . $attrib['flaggedicon']); if ($attrib['unflaggedicon']) $OUTPUT->set_env('unflaggedicon', $skin_path . $attrib['unflaggedicon']); + if ($attrib['unreadchildrenicon']) + $OUTPUT->set_env('unreadchildrenicon', $skin_path . $attrib['unreadchildrenicon']); - $OUTPUT->set_env('messages', $a_js_message_arr); + $OUTPUT->set_env('messages', array()); $OUTPUT->set_env('coltypes', $a_show_cols); + if (!$message_count) + $OUTPUT->show_message('nomessagesfound', 'notice'); + $OUTPUT->include_script('list.js'); - return $out; - } + $thead = ''; + foreach (rcmail_message_list_head($attrib, $a_show_cols) as $cell) + $thead .= html::tag('td', array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']); + + return html::tag('table', + $attrib, + html::tag('thead', null, html::tag('tr', null, $thead)) . + html::tag('tbody', null, ''), + array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary')); +} /** * return javascript commands to add rows to the message list * or to replace the whole list (IE only) */ -function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE) - { +function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE, $head_replace=FALSE) +{ global $CONFIG, $IMAP, $OUTPUT; if (empty($_SESSION['list_columns'])) @@ -409,9 +244,12 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE) && (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false) $a_show_cols[$f] = 'to'; - $browser = new rcube_browser; + $thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : NULL; + + $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead); - $OUTPUT->command('set_message_coltypes', $a_show_cols); + if (empty($a_headers)) + return; // remove 'attachment' and 'flag' columns, we don't need them here if(($key = array_search('attachment', $a_show_cols)) !== FALSE) @@ -419,7 +257,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE) if(($key = array_search('flag', $a_show_cols)) !== FALSE) unset($a_show_cols[$key]); - if ($browser->ie && $replace) + if ($OUTPUT->browser->ie && $replace) $OUTPUT->command('offline_message_list', true); // loop through message headers @@ -440,10 +278,9 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE) $cont = Q(rcmail_address_string($header->$col, 3), 'show'); else if ($col=='subject') { - $cont = abbreviate_string(trim($IMAP->decode_header($header->$col)), 160); + $cont = abbreviate_string(trim($IMAP->decode_header($header->$col)), 160); if (!$cont) $cont = rcube_label('nosubject'); - $cont = Q($cont); - $a_msg_cols['mbox'] = $mbox; + $cont = Q($cont); } else if ($col=='size') $cont = show_bytes($header->$col); @@ -455,6 +292,14 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE) $a_msg_cols[$col] = $cont; } + if ($header->depth) + $a_msg_flags['depth'] = $header->depth; + if ($header->parent_uid) + $a_msg_flags['parent_uid'] = $header->parent_uid; + if ($header->has_children) + $a_msg_flags['has_children'] = $header->has_children; + if ($header->unread_children) + $a_msg_flags['unread_children'] = $header->unread_children; if ($header->deleted) $a_msg_flags['deleted'] = 1; if (!$header->seen) @@ -465,12 +310,14 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE) $a_msg_flags['forwarded'] = 1; if ($header->flagged) $a_msg_flags['flagged'] = 1; - + if(preg_match("/multipart\/m/i", $header->ctype)) + $a_msg_flags['attachment'] = 1; + $a_msg_flags['mbox'] = $mbox; + $OUTPUT->command('add_message_row', $header->uid, $a_msg_cols, $a_msg_flags, - preg_match("/multipart\/m/i", $header->ctype), $insert_top); } @@ -479,6 +326,61 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $replace=TRUE) } +/* + * Creates <THEAD> for message list table + */ +function rcmail_message_list_head($attrib, $a_show_cols) +{ + global $CONFIG; + + $skin_path = $_SESSION['skin_path']; + $image_tag = html::img(array('src' => "%s%s", 'alt' => "%s")); + + // check to see if we have some settings for sorting + $sort_col = $_SESSION['sort_col']; + $sort_order = $_SESSION['sort_order']; + + // define sortable columns + $a_sort_cols = array('subject', 'date', 'from', 'to', 'size', 'cc'); + + if (!empty($attrib['optionsmenuicon'])) + $list_menu = html::a( + array('href' => '#', 'onclick' => 'return '.JS_OBJECT_NAME.".command('menu-open', 'messagelistmenu')"), + html::img(array('src' => $skin_path . $attrib['optionsmenuicon'], 'id' => 'listmenulink', 'title' => rcube_label('listoptions'))) + ); + else + $list_menu = ''; + + $cells = array(array('className' => 'threads', 'html' => $list_menu)); + + foreach ($a_show_cols as $col) { + // get column name + switch ($col) { + case 'flag': + $col_name = sprintf($image_tag, $skin_path, $attrib['unflaggedicon'], ''); + break; + case 'attachment': + $col_name = sprintf($image_tag, $skin_path, $attrib['attachmenticon'], ''); + break; + default: + $col_name = Q(rcube_label($col)); + } + + // make sort links + if (in_array($col, $a_sort_cols)) + $col_name = html::a(array('href'=>"./#sort", 'onclick' => 'return '.JS_OBJECT_NAME.".command('sort','".$col."',this)", 'title' => rcube_label('sortby')), $col_name); + + $sort_class = $col == $sort_col ? " sorted$sort_order" : ''; + $class_name = $col == 'attachment' ? 'icon' : $col.$sort_class; + + // put it all together + $cells[] = array('className' => $class_name, 'id' => "rcm$col", 'html' => $col_name); + } + + return $cells; +} + + /** * return an HTML iframe for loading mail content */ @@ -513,7 +415,7 @@ function rcmail_messagecount_display($attrib) function rcmail_quota_display($attrib) { - global $OUTPUT, $COMM_PATH; + global $OUTPUT; if (!$attrib['id']) $attrib['id'] = 'rcmquotadisplay'; @@ -582,23 +484,23 @@ function rcmail_get_messagecount_text($count=NULL, $page=NULL) if (isset($MESSAGE->index)) { return rcube_label(array('name' => 'messagenrof', - 'vars' => array('nr' => $MESSAGE->index+1, - 'count' => $count!==NULL ? $count : $IMAP->messagecount()))); + 'vars' => array('nr' => $MESSAGE->index+1, + 'count' => $count!==NULL ? $count : $IMAP->messagecount(NULL, 'ALL')))); // Only messages, no threads here } if ($page===NULL) $page = $IMAP->list_page; $start_msg = ($page-1) * $IMAP->page_size + 1; - $max = $count!==NULL ? $count : $IMAP->messagecount(); + $max = $count!==NULL ? $count : $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL'); if ($max==0) $out = rcube_label('mailboxempty'); else - $out = rcube_label(array('name' => 'messagesfromto', - 'vars' => array('from' => $start_msg, - 'to' => min($max, $start_msg + $IMAP->page_size - 1), - 'count' => $max))); + $out = rcube_label(array('name' => $IMAP->threading ? 'threadsfromto' : 'messagesfromto', + 'vars' => array('from' => $start_msg, + 'to' => min($max, $start_msg + $IMAP->page_size - 1), + 'count' => $max))); return Q($out); } diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc index cd1a3142d..89d127cdc 100644 --- a/program/steps/mail/list.inc +++ b/program/steps/mail/list.inc @@ -33,8 +33,6 @@ if ($sort = get_input_value('_sort', RCUBE_INPUT_GET)) $save_arr = array(); $_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col; $_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order; - - $RCMAIL->user->save_prefs($save_arr); } else { @@ -43,6 +41,16 @@ else $sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order']; } +// is there a set of columns for this request? +if ($cols = get_input_value('_cols', RCUBE_INPUT_GET)) +{ + $save_arr = array(); + $_SESSION['list_columns'] = $save_arr['list_cols'] = explode(',', $cols); +} + +if ($save_arr) + $RCMAIL->user->save_prefs($save_arr); + $mbox_name = $IMAP->get_mailbox_name(); // initialize searching result if search_filter is used @@ -55,9 +63,13 @@ if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') } // fetch message headers -if ($count = $IMAP->messagecount($mbox_name, 'ALL', !empty($_REQUEST['_refresh']))) +if ($count = $IMAP->messagecount($mbox_name, $IMAP->threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh']))) $a_headers = $IMAP->list_headers($mbox_name, NULL, $sort_col, $sort_order); +// update search set (possible change of threading mode) +if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) + $_SESSION['search'][$_REQUEST['_search']] = $IMAP->get_search_set(); + // update mailboxlist rcmail_send_unread_count($mbox_name, !empty($_REQUEST['_refresh'])); @@ -65,13 +77,14 @@ rcmail_send_unread_count($mbox_name, !empty($_REQUEST['_refresh'])); $pages = ceil($count/$IMAP->page_size); $OUTPUT->set_env('messagecount', $count); $OUTPUT->set_env('pagecount', $pages); +$OUTPUT->set_env('threading', (bool) $IMAP->threading); $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count)); $OUTPUT->command('set_mailboxname', rcmail_get_mailbox_name_text()); // add message rows +rcmail_js_message_list($a_headers, FALSE, TRUE, (bool) $cols); if (isset($a_headers) && count($a_headers)) { - rcmail_js_message_list($a_headers); if ($search_request) $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count)); } diff --git a/program/steps/mail/mark.inc b/program/steps/mail/mark.inc index 3e0ee9ecb..c37a6e47c 100644 --- a/program/steps/mail/mark.inc +++ b/program/steps/mail/mark.inc @@ -36,7 +36,7 @@ if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_va if ($flag == 'DELETED' && $CONFIG['skip_deleted'] && $_POST['_from'] != 'show') { // count messages before changing anything - $old_count = $IMAP->messagecount(); + $old_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL'); $old_pages = ceil($old_count / $IMAP->page_size); $count = sizeof(explode(',', $uids)); } @@ -75,7 +75,7 @@ if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_va $_SESSION['search'][$search_request] = $IMAP->refresh_search(); } - $msg_count = $IMAP->messagecount(); + $msg_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL'); $pages = ceil($msg_count / $IMAP->page_size); $nextpage_count = $old_count - $IMAP->page_size * $IMAP->list_page; $remaining = $msg_count - $IMAP->page_size * ($IMAP->list_page - 1); @@ -103,8 +103,11 @@ if (($uids = get_input_value('_uid', RCUBE_INPUT_POST)) && ($flag = get_input_va } $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count)); + if ($IMAP->threading) + $count = get_input_value('_count', RCUBE_INPUT_POST); + // add new rows from next page (if any) - if (($jump_back || $nextpage_count > 0)) { + if ($count && ($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/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc index b8bd16557..f884a781e 100644 --- a/program/steps/mail/move_del.inc +++ b/program/steps/mail/move_del.inc @@ -24,7 +24,7 @@ if (!$OUTPUT->ajax_call) return; // count messages before changing anything -$old_count = $IMAP->messagecount(); +$old_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL'); $old_pages = ceil($old_count / $IMAP->page_size); // move messages @@ -50,6 +50,7 @@ if ($RCMAIL->action=='moveto' && !empty($_POST['_uid']) && !empty($_POST['_targe else if ($RCMAIL->action=='delete' && !empty($_POST['_uid'])) { $count = sizeof(explode(',', ($uids = get_input_value('_uid', RCUBE_INPUT_POST)))); $mbox = get_input_value('_mbox', RCUBE_INPUT_POST); + $del = $IMAP->delete_message($uids, $mbox); if (!$del) { @@ -82,7 +83,7 @@ if ($_POST['_from'] == 'show') } else { - $msg_count = $IMAP->messagecount(); + $msg_count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL'); $pages = ceil($msg_count / $IMAP->page_size); $nextpage_count = $old_count - $IMAP->page_size * $IMAP->list_page; $remaining = $msg_count - $IMAP->page_size * ($IMAP->list_page - 1); @@ -116,8 +117,11 @@ else $OUTPUT->command('set_quota', rcmail_quota_content()); $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count)); + if ($IMAP->threading) + $count = get_input_value('_count', RCUBE_INPUT_POST); + // add new rows from next page (if any) - if ($addrows && ($jump_back || $nextpage_count > 0)) { + if ($addrows && $count && ($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/program/steps/mail/search.inc b/program/steps/mail/search.inc index 54c765047..52469952a 100644 --- a/program/steps/mail/search.inc +++ b/program/steps/mail/search.inc @@ -104,7 +104,7 @@ if ($search_str) // Get the headers $result_h = $IMAP->list_headers($mbox, 1, $_SESSION['sort_col'], $_SESSION['sort_order']); -$count = $IMAP->messagecount(); +$count = $IMAP->messagecount(NULL, $IMAP->threading ? 'THREADS' : 'ALL'); // save search results in session if (!is_array($_SESSION['search'])) @@ -120,7 +120,7 @@ if (!empty($result_h)) { rcmail_js_message_list($result_h); if ($search_str) - $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count)); + $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $IMAP->messagecount(NULL, 'ALL'))); } else { diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc index 33e87d5bc..02e1f4824 100644 --- a/program/steps/mail/show.inc +++ b/program/steps/mail/show.inc @@ -104,7 +104,7 @@ if ($_GET['_uid']) { $next = $prev = $first = $last = -1; if ($_SESSION['sort_col'] == 'date' && $_SESSION['sort_order'] != 'DESC' - && empty($_REQUEST['_search']) && !$IMAP->skip_deleted) + && empty($_REQUEST['_search']) && !$CONFIG['skip_deleted'] && !$IMAP->threading) { // this assumes that we are sorted by date_DESC $cnt = $IMAP->messagecount(); @@ -142,7 +142,7 @@ if ($_GET['_uid']) { if (!$MESSAGE->headers->seen) $RCMAIL->plugins->exec_hook('message_read', array('uid' => $MESSAGE->uid, - 'mailbox' => $IMAP->mailbox, 'message' => $MESSAGE)); + 'mailbox' => $mbox_name, 'message' => $MESSAGE)); } diff --git a/program/steps/mail/viewsource.inc b/program/steps/mail/viewsource.inc index 17e382456..2e2228ab6 100644 --- a/program/steps/mail/viewsource.inc +++ b/program/steps/mail/viewsource.inc @@ -25,7 +25,7 @@ ob_end_clean(); if ($uid = get_input_value('_uid', RCUBE_INPUT_GET)) { $headers = $IMAP->get_headers($uid); - $charset = $headers->charset ? $headers->charset : $IMAP->default_charset; + $charset = $headers->charset ? $headers->charset : $CONFIG['default_charset']; header("Content-Type: text/plain; charset={$charset}"); if (!empty($_GET['_save'])) { diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index 44225c715..421fb37bf 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -248,17 +248,6 @@ function rcmail_user_prefs($current=null) ); } - // Show checkbox for toggling 'index_sort' - if (!isset($no_override['index_sort'])) { - $field_id = 'rcmfd_indexsort'; - $input_indexsort = new html_checkbox(array('name' => '_index_sort', 'id' => $field_id, 'value' => 1)); - - $blocks['list']['options']['index_sort'] = array( - 'title' => html::label($field_id, Q(rcube_label('indexsort'))), - 'content' => $input_indexsort->show($config['index_sort']?1:0), - ); - } - // show drop-down for available skins if (!isset($no_override['skin'])) { $skins = rcmail_get_skins(); @@ -311,6 +300,19 @@ function rcmail_user_prefs($current=null) ); } + if (!isset($no_override['autoexpand_threads'])) { + $field_id = 'rcmfd_autoexpand_threads'; + $select_autoexpand_threads = new html_select(array('name' => '_autoexpand_threads', 'id' => $field_id)); + $select_autoexpand_threads->add(rcube_label('never'), 0); + $select_autoexpand_threads->add(rcube_label('do_expand'), 1); + $select_autoexpand_threads->add(rcube_label('expand_only_unread'), 2); + + $blocks['main']['options']['autoexpand_threads'] = array( + 'title' => html::label($field_id, Q(rcube_label('autoexpand_threads'))), + 'content' => $select_autoexpand_threads->show($config['autoexpand_threads']), + ); + } + if (!isset($no_override['focus_on_new_message'])) { $field_id = 'rcmfd_focus_on_new_message'; $input_focus_on_new_message = new html_checkbox(array('name' => '_focus_on_new_message', 'id' => $field_id, 'value' => 1)); diff --git a/program/steps/settings/manage_folders.inc b/program/steps/settings/manage_folders.inc index 06fee7a87..fa5a4db70 100644 --- a/program/steps/settings/manage_folders.inc +++ b/program/steps/settings/manage_folders.inc @@ -38,6 +38,20 @@ else if ($RCMAIL->action=='unsubscribe') $IMAP->unsubscribe(array($mbox)); } +// enable threading for one or more mailboxes +else if ($RCMAIL->action=='enable-threading') + { + if ($mbox = get_input_value('_mbox', RCUBE_INPUT_POST, false, 'UTF7-IMAP')) + rcube_set_threading($mbox, true); + } + +// enable threading for one or more mailboxes +else if ($RCMAIL->action=='disable-threading') + { + if ($mbox = get_input_value('_mbox', RCUBE_INPUT_POST, false, 'UTF7-IMAP')) + rcube_set_threading($mbox, false); + } + // create a new mailbox else if ($RCMAIL->action=='create-folder') { @@ -79,6 +93,24 @@ else if ($RCMAIL->action=='rename-folder') $rename = $IMAP->rename_mailbox($oldname, $name); } + // update per-folder options for modified folder and its subfolders + if ($rename) { + $a_threaded = $RCMAIL->config->get('message_threading', array()); + $delimiter = $IMAP->get_hierarchy_delimiter(); + $oldprefix = '/^' . preg_quote($oldname . $delimiter, '/') . '/'; + foreach ($a_threaded as $key => $val) + if ($key == $oldname) { + unset($a_threaded[$key]); + $a_threaded[$name] = true; + } + else if (preg_match($oldprefix, $key)) { + unset($a_threaded[$key]); + $a_threaded[preg_replace($oldprefix, $name.$delimiter, $key)] = true; + } + + $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded)); + } + if ($rename && $OUTPUT->ajax_call) { $folderlist = $IMAP->list_unsubscribed(); @@ -159,7 +191,11 @@ if ($OUTPUT->ajax_call) // build table with all folders listed by server function rcube_subscription_form($attrib) { - global $IMAP, $CONFIG, $OUTPUT; + global $RCMAIL, $IMAP, $CONFIG, $OUTPUT; + + $threading_supported = $IMAP->get_capability('thread=references') + || $IMAP->get_capability('thread=orderedsubject') + || $IMAP->get_capability('thread=refs'); list($form_start, $form_end) = get_form_tags($attrib, 'folders'); unset($attrib['form']); @@ -173,15 +209,17 @@ function rcube_subscription_form($attrib) $table->add_header('name', rcube_label('foldername')); $table->add_header('msgcount', rcube_label('messagecount')); $table->add_header('subscribed', rcube_label('subscribed')); + if ($threading_supported) + $table->add_header('threaded', rcube_label('threaded')); $table->add_header('rename', ' '); $table->add_header('delete', ' '); - // get folders from server $IMAP->clear_cache('mailboxes'); $a_unsubscribed = $IMAP->list_unsubscribed(); $a_subscribed = $IMAP->list_mailboxes(); + $a_threaded = $a_threaded_copy = $RCMAIL->config->get('message_threading', array()); $delimiter = $IMAP->get_hierarchy_delimiter(); $a_js_folders = $seen_folders = $list_folders = array(); @@ -203,14 +241,28 @@ function rcube_subscription_form($attrib) } } + unset($a_threaded_copy[$folder]); + $list_folders[] = array('id' => $folder, 'name' => $name, 'level' => $level); $seen[$folder]++; } + // remove 'message_threading' option for not existing folders + if ($a_threaded_copy) { + foreach ($a_threaded_copy as $key => $val) + unset($a_threaded[$key]); + unset($a_threaded_copy); + $RCMAIL->user->save_prefs(array('message_threading' => $a_threaded)); + } + $checkbox_subscribe = new html_checkbox(array( 'name' => '_subscribed[]', 'onclick' => JS_OBJECT_NAME.".command(this.checked?'subscribe':'unsubscribe',this.value)", )); + $checkbox_threaded = new html_checkbox(array( + 'name' => '_threaded[]', + 'onclick' => JS_OBJECT_NAME.".command(this.checked?'enable-threading':'disable-threading',this.value)", + )); if (!empty($attrib['deleteicon'])) $del_button = html::img(array('src' => $CONFIG['skin_path'] . $attrib['deleteicon'], 'alt' => rcube_label('delete'))); @@ -226,6 +278,7 @@ function rcube_subscription_form($attrib) foreach ($list_folders as $i => $folder) { $idx = $i + 1; $subscribed = in_array($folder['id'], $a_subscribed); + $threaded = $a_threaded[$folder['id']]; $protected = ($CONFIG['protect_default_folders'] == true && in_array($folder['id'], $CONFIG['default_imap_folders'])); $classes = array($i%2 ? 'even' : 'odd'); $folder_js = JQ($folder['id']); @@ -238,9 +291,13 @@ function rcube_subscription_form($attrib) $table->add_row(array('id' => 'rcmrow'.$idx, 'class' => join(' ', $classes))); $table->add('name', Q($display_folder)); - $table->add('msgcount', ($folder['virtual'] ? '' : $IMAP->messagecount($folder['id']))); + $table->add('msgcount', ($folder['virtual'] ? '' : $IMAP->messagecount($folder['id']))); // XXX: Use THREADS or ALL? $table->add('subscribed', ($protected || $folder['virtual']) ? ($subscribed ? ' •' : ' ') : $checkbox_subscribe->show(($subscribed ? $folder_utf8 : ''), array('value' => $folder_utf8))); + if ($IMAP->get_capability('thread=references')) { + $table->add('threaded', + $checkbox_threaded->show(($threaded ? $folder_utf8 : ''), array('value' => $folder_utf8))); + } // add rename and delete buttons if (!$protected && !$folder['virtual']) { @@ -335,6 +392,27 @@ function rcube_rename_folder_form($attrib) return $out; } + +// (un)set 'threading' for selected folder +function rcube_set_threading($mbox, $state=true) + { + global $RCMAIL; + $mbox = (array)$mbox; + $a_prefs = (array)$RCMAIL->config->get('message_threading'); + + if ($state) { + foreach ($mbox as $box) + $a_prefs[$box] = true; + } + else { + foreach ($mbox as $box) + unset($a_prefs[$box]); + } + + $RCMAIL->user->save_prefs(array('message_threading' => $a_prefs)); + } + + $OUTPUT->set_pagetitle(rcube_label('folders')); $OUTPUT->include_script('list.js'); diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc index eeb64034c..4eebef291 100644 --- a/program/steps/settings/save_prefs.inc +++ b/program/steps/settings/save_prefs.inc @@ -32,7 +32,6 @@ switch ($CURR_SECTION) 'timezone' => isset($_POST['_timezone']) ? (is_numeric($_POST['_timezone']) ? floatval($_POST['_timezone']) : get_input_value('_timezone', RCUBE_INPUT_POST)) : $CONFIG['timezone'], 'dst_active' => isset($_POST['_dst_active']) ? TRUE : FALSE, 'pagesize' => is_numeric($_POST['_pagesize']) ? max(2, intval($_POST['_pagesize'])) : $CONFIG['pagesize'], - 'index_sort' => isset($_POST['_index_sort']) ? TRUE : FALSE, 'prettydate' => isset($_POST['_pretty_date']) ? TRUE : FALSE, 'skin' => isset($_POST['_skin']) ? get_input_value('_skin', RCUBE_INPUT_POST) : $CONFIG['skin'], ); @@ -42,6 +41,7 @@ switch ($CURR_SECTION) $a_user_prefs = array( 'focus_on_new_message' => isset($_POST['_focus_on_new_message']) ? TRUE : FALSE, 'preview_pane' => isset($_POST['_preview_pane']) ? TRUE : FALSE, + 'autoexpand_threads' => isset($_POST['_autoexpand_threads']) ? intval($_POST['_autoexpand_threads']) : 0, 'mdn_requests' => isset($_POST['_mdn_requests']) ? intval($_POST['_mdn_requests']) : 0, 'keep_alive' => isset($_POST['_keep_alive']) ? intval($_POST['_keep_alive'])*60 : $CONFIG['keep_alive'], 'check_all_folders' => isset($_POST['_check_all_folders']) ? TRUE : FALSE, |