From ac0fc383fd43e8955b0ab22f70463159b14c74b0 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Mon, 23 Dec 2013 11:33:41 +0100 Subject: Fix so message flags modified by another client are applied on the list on refresh (#1485186) --- CHANGELOG | 1 + program/js/app.js | 19 ++++++++++++++++-- program/lib/Roundcube/rcube_imap.php | 35 +++++++++++++++++++++++++++++++++ program/lib/Roundcube/rcube_storage.php | 12 +++++++++++ program/steps/mail/check_recent.inc | 18 +++++++++++++++++ program/steps/mail/list.inc | 11 +++++++++-- program/steps/mail/search.inc | 7 +++++++ 7 files changed, 99 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b1eca46f2..ff09b2f62 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Fix so message flags modified by another client are applied on the list on refresh (#1485186) - Fix broken text/* attachments when forwarding/editing a message (#1489426) - Improved minified files handling, added css minification (#1486988) - Fix handling of X-Forwarded-For header with multiple addresses (#1489481) diff --git a/program/js/app.js b/program/js/app.js index 138fcbb13..a001a3bff 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -6923,6 +6923,16 @@ function rcube_webmail() case 'refresh': case 'check-recent': + // update message flags + $.each(this.env.recent_flags || {}, function(uid, flags) { + ref.set_message(uid, 'deleted', flags.deleted); + ref.set_message(uid, 'replied', flags.answered); + ref.set_message(uid, 'unread', !flags.seen); + ref.set_message(uid, 'forwarded', flags.forwarded); + ref.set_message(uid, 'flagged', flags.flagged); + }); + delete this.env.recent_flags; + case 'getunread': case 'search': this.env.qsearch = null; @@ -7246,13 +7256,18 @@ function rcube_webmail() if (this.gui_objects.mailboxlist) params._folderlist = 1; - if (this.gui_objects.messagelist) - params._list = 1; if (this.gui_objects.quotadisplay) params._quota = 1; if (this.env.search_request) params._search = this.env.search_request; + if (this.gui_objects.messagelist) { + params._list = 1; + + // message uids for flag updates check + params._uids = $.map(this.message_list.rows, function(row, uid) { return uid; }).join(','); + } + return params; }; diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php index f1363caf7..4c3bf6fcd 100644 --- a/program/lib/Roundcube/rcube_imap.php +++ b/program/lib/Roundcube/rcube_imap.php @@ -679,6 +679,41 @@ class rcube_imap extends rcube_storage } + /** + * Public method for listing message flags + * + * @param string $folder Folder name + * @param array $uids Message UIDs + * @param int $mod_seq Optional MODSEQ value (of last flag update) + * + * @return array Indexed array with message flags + */ + public function list_flags($folder, $uids, $mod_seq = null) + { + if (!strlen($folder)) { + $folder = $this->folder; + } + + if (!$this->check_connection()) { + return array(); + } + + // @TODO: when cache was synchronized in this request + // we might already have asked for flag updates, use it. + + $flags = $this->conn->fetch($folder, $uids, true, array('FLAGS'), $mod_seq); + $result = array(); + + if (!empty($flags)) { + foreach ($flags as $message) { + $result[$message->uid] = $message->flags; + } + } + + return $result; + } + + /** * Public method for listing headers * diff --git a/program/lib/Roundcube/rcube_storage.php b/program/lib/Roundcube/rcube_storage.php index e697b2c73..ca65af1cb 100644 --- a/program/lib/Roundcube/rcube_storage.php +++ b/program/lib/Roundcube/rcube_storage.php @@ -359,6 +359,18 @@ abstract class rcube_storage abstract function count($folder = null, $mode = 'ALL', $force = false, $status = true); + /** + * Public method for listing message flags + * + * @param string $folder Folder name + * @param array $uids Message UIDs + * @param int $mod_seq Optional MODSEQ value + * + * @return array Indexed array with message flags + */ + abstract function list_flags($folder, $uids, $mod_seq = null); + + /** * Public method for listing headers. * diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc index 3aa7b3e9c..60da68a96 100644 --- a/program/steps/mail/check_recent.inc +++ b/program/steps/mail/check_recent.inc @@ -114,6 +114,24 @@ foreach ($a_mailboxes as $mbox_name) { $OUTPUT->command('update_selection'); } } + // handle flag updates + else if ($is_current && ($uids = rcube_utils::get_input_value('_uids', rcube_utils::INPUT_GPC))) { + $data = $RCMAIL->storage->folder_data($mbox_name); + + if (empty($_SESSION['list_mod_seq']) || $_SESSION['list_mod_seq'] != $data['HIGHESTMODSEQ']) { + $flags = $RCMAIL->storage->list_flags($mbox_name, explode(',', $uids), $_SESSION['list_mod_seq']); + foreach ($flags as $idx => $row) { + $flags[$idx] = array_change_key_case(array_map('intval', $row)); + } + + // remember last HIGHESTMODSEQ value (if supported) + if (!empty($data['HIGHESTMODSEQ'])) { + $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ']; + } + + $RCMAIL->output->set_env('recent_flags', $flags); + } + } } // trigger refresh hook diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc index fe7991c29..91c53e852 100644 --- a/program/steps/mail/list.inc +++ b/program/steps/mail/list.inc @@ -23,8 +23,8 @@ if (!$OUTPUT->ajax_call) { return; } -$save_arr = array(); -$dont_override = (array) $RCMAIL->config->get('dont_override'); +$save_arr = array(); +$dont_override = (array) $RCMAIL->config->get('dont_override'); // is there a sort type for this request? if ($sort = rcube_utils::get_input_value('_sort', rcube_utils::INPUT_GET)) { @@ -104,6 +104,13 @@ if (isset($a_headers) && count($a_headers)) { if ($search_request) { $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count)); } + + // remember last HIGHESTMODSEQ value (if supported) + // we need it for flag updates in check-recent + $data = $RCMAIL->storage->folder_data($mbox_name); + if (!empty($data['HIGHESTMODSEQ'])) { + $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ']; + } } else { // handle IMAP errors (e.g. #1486905) diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc index 03d6de326..210bedbb8 100644 --- a/program/steps/mail/search.inc +++ b/program/steps/mail/search.inc @@ -131,6 +131,13 @@ if (!empty($result_h)) { rcmail_js_message_list($result_h); if ($search_str) $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $RCMAIL->storage->count(NULL, 'ALL'))); + + // remember last HIGHESTMODSEQ value (if supported) + // we need it for flag updates in check-recent + $data = $RCMAIL->storage->folder_data($mbox_name); + if (!empty($data['HIGHESTMODSEQ'])) { + $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ']; + } } // handle IMAP errors (e.g. #1486905) else if ($err_code = $RCMAIL->storage->get_error_code()) { -- cgit v1.2.3