diff --git a/config/defaults.inc.php b/config/defaults.inc.php index bb0f8ecb5..5ef1a295d 100644 --- a/config/defaults.inc.php +++ b/config/defaults.inc.php @@ -664,7 +664,7 @@ $config['message_sort_col'] = ''; $config['message_sort_order'] = 'DESC'; // These cols are shown in the message list. Available cols are: -// subject, from, to, fromto, cc, replyto, date, size, status, flag, attachment, 'priority' +// subject, from, to, fromto, cc, replyto, date, size, status, flag, attachment, priority $config['list_cols'] = array('subject', 'status', 'fromto', 'date', 'size', 'flag', 'attachment'); // the default locale setting (leave empty for auto-detection) @@ -1088,12 +1088,15 @@ $config['prettydate'] = true; // save compose message every 300 seconds (5min) $config['draft_autosave'] = 300; -// default setting if preview pane is enabled -$config['preview_pane'] = false; +// Interface layout. Default: 'widescreen'. +// 'widescreen' - three columns +// 'desktop' - two columns, preview on bottom +// 'list' - two columns, no preview +$config['layout'] = 'widescreen'; -// Mark as read when viewed in preview pane (delay in seconds) -// Set to -1 if messages in preview pane should not be marked as read -$config['preview_pane_mark_read'] = 0; +// Mark as read when viewing a message (delay in seconds) +// Set to -1 if messages should not be marked as read +$config['mail_read_time'] = 0; // Clear Trash on logout $config['logout_purge'] = false; diff --git a/installer/config.php b/installer/config.php index b66476858..95057ef3c 100644 --- a/installer/config.php +++ b/installer/config.php @@ -11,7 +11,6 @@ $RCI->bool_config_props = array( 'auto_create_user' => 1, 'smtp_log' => 1, 'prefer_html' => 1, - 'preview_pane' => 1, 'debug_level' => 1, ); @@ -598,17 +597,6 @@ echo $check_htmlview->show(intval($RCI->getprop('prefer_html')));
-
preview_pane *
-
- '_preview_pane', 'id' => "cfgprevpane", 'value' => 1)); -echo $check_prevpane->show(intval($RCI->getprop('preview_pane'))); - -?> -
-
-
htmleditor *
diff --git a/plugins/zipdownload/skins/larry/zipdownload.css b/plugins/zipdownload/skins/larry/zipdownload.css index bb92631b1..f87670a3e 100644 --- a/plugins/zipdownload/skins/larry/zipdownload.css +++ b/plugins/zipdownload/skins/larry/zipdownload.css @@ -5,3 +5,10 @@ a.zipdownload { margin-top: .5em; padding: 3px 5px 4px 5px; } + +@media screen and (max-width: 800px) { + a.zipdownload { + margin-top: .15em; + margin-bottom: .2em; + } +} \ No newline at end of file diff --git a/program/include/rcmail_install.php b/program/include/rcmail_install.php index 6ce057ad8..ebc4fd165 100644 --- a/program/include/rcmail_install.php +++ b/program/include/rcmail_install.php @@ -33,7 +33,7 @@ class rcmail_install public $bool_config_props = array(); public $local_config = array('db_dsnw', 'default_host', 'support_url', 'des_key', 'plugins'); - public $obsolete_config = array('db_backend', 'db_max_length', 'double_auth'); + public $obsolete_config = array('db_backend', 'db_max_length', 'double_auth', 'preview_pane'); public $replaced_config = array( 'skin_path' => 'skin', 'locale_string' => 'language', diff --git a/program/js/app.js b/program/js/app.js index 84ad638b7..f193496e6 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -217,6 +217,12 @@ function rcube_webmail() this.enable_command('list', 'checkmail', 'add-contact', 'search', 'reset-search', 'collapse-folder', 'import-messages', true); if (this.gui_objects.messagelist) { + this.env.widescreen_list_template = [ + {className: 'threads', cells: ['threads']}, + {className: 'subject', cells: ['fromto', 'date', 'status', 'subject']}, + {className: 'flags', cells: ['flag', 'attachment']} + ]; + this.message_list = new rcube_list_widget(this.gui_objects.messagelist, { multiselect:true, multiexpand:true, draggable:true, keyboard:true, column_movable:this.env.col_movable, dblclick_time:this.dblclick_time @@ -265,6 +271,11 @@ function rcube_webmail() this.display_message('', 'loading')); } + if (this.env.mail_read_time > 0) + setTimeout(function() { + ref.http_post('mark', {_uid: ref.env.uid, _flag: 'read', _mbox: ref.env.mailbox, _quiet: 1}); + }, this.env.mail_read_time * 1000); + if (this.env.blockedobjects) { if (this.gui_objects.remoteobjectsmsg) this.gui_objects.remoteobjectsmsg.style.display = 'block'; @@ -1611,8 +1622,6 @@ function rcube_webmail() if (this.preview_timer) clearTimeout(this.preview_timer); - if (this.preview_read_timer) - clearTimeout(this.preview_read_timer); // prepare treelist widget for dragging interactions if (this.treelist) @@ -1806,8 +1815,6 @@ function rcube_webmail() { if (this.preview_timer) clearTimeout(this.preview_timer); - if (this.preview_read_timer) - clearTimeout(this.preview_read_timer); var selected = list.get_single_selection(); @@ -1832,7 +1839,7 @@ function rcube_webmail() // start timer for message preview (wait for double click) if (selected && this.env.contentframe && !list.multi_selecting && !this.dummy_select) - this.preview_timer = setTimeout(function() { ref.msglist_get_preview(); }, this.dblclick_time); + this.preview_timer = setTimeout(function() { ref.msglist_get_preview(); }, list.dblclick_time); else if (this.env.contentframe) this.show_contentframe(false); }; @@ -1851,10 +1858,8 @@ function rcube_webmail() if (win && win.location.href.indexOf(this.env.blankpage) >= 0) { if (this.preview_timer) clearTimeout(this.preview_timer); - if (this.preview_read_timer) - clearTimeout(this.preview_read_timer); - this.preview_timer = setTimeout(function() { ref.msglist_get_preview(); }, this.dblclick_time); + this.preview_timer = setTimeout(function() { ref.msglist_get_preview(); }, list.dblclick_time); } }; @@ -1862,8 +1867,6 @@ function rcube_webmail() { if (this.preview_timer) clearTimeout(this.preview_timer); - if (this.preview_read_timer) - clearTimeout(this.preview_read_timer); var uid = list.get_single_selection(); @@ -2146,7 +2149,7 @@ function rcube_webmail() } expando = '
  
'; - row_class += ' thread' + (message.expanded? ' expanded' : ''); + row_class += ' thread' + (message.expanded ? ' expanded' : ''); } if (flags.unread_children && flags.seen && !message.expanded) @@ -2216,8 +2219,6 @@ function rcube_webmail() else if (c == 'threads') html = expando; else if (c == 'subject') { - if (bw.ie) - col.events.mouseover = function() { rcube_webmail.long_subject_title_ex(this); }; html = tree + cols[c]; } else if (c == 'priority') { @@ -2238,6 +2239,9 @@ function rcube_webmail() row.cols.push(col); } + if (this.env.layout == 'widescreen') + row = this.widescreen_message_row(row, uid, message); + list.insert_row(row, attop); // remove 'old' row @@ -2248,6 +2252,52 @@ function rcube_webmail() } }; + // Converts standard message list record into "widescreen" (3-column) layout + this.widescreen_message_row = function(row, uid, message) + { + var domrow = document.createElement('tr'); + + domrow.id = row.id; + domrow.uid = row.uid; + domrow.className = row.className; + if (row.style) $.extend(domrow.style, row.style); + + $.each(this.env.widescreen_list_template, function() { + if (!ref.env.threading && this.className == 'threads') + return; + + var i, n, e, col, domcol, + domcell = document.createElement('td'); + + if (this.className) domcell.className = this.className; + + for (i=0; this.cells && i < this.cells.length; i++) { + for (n=0; row.cols && n < row.cols.length; n++) { + if (this.cells[i] == row.cols[n].className) { + col = row.cols[n]; + domcol = document.createElement('span'); + domcol.className = this.cells[i]; + if (this.className == 'subject' && domcol.className != 'subject') + domcol.className += ' skip-on-drag'; + if (col.innerHTML) + domcol.innerHTML = col.innerHTML; + domcell.appendChild(domcol); + break; + } + } + } + + domrow.appendChild(domcell); + }); + + if (this.env.threading && message.depth) { + $('td.subject', domrow).attr('style', 'padding-left:' + Math.min(90, message.depth * 15) + 'px !important'); + $('span.branch', domrow).remove(); + } + + return domrow; + }; + this.set_list_sorting = function(sort_col, sort_order) { var sort_old = this.env.sort_col == 'arrival' ? 'date' : this.env.sort_col, @@ -2265,7 +2315,7 @@ function rcube_webmail() this.env.sort_order = sort_order; }; - this.set_list_options = function(cols, sort_col, sort_order, threads) + this.set_list_options = function(cols, sort_col, sort_order, threads, layout) { var update, post_data = {}; @@ -2284,6 +2334,12 @@ function rcube_webmail() post_data._threads = threads; } + if (layout && this.env.layout != layout) { + this.triggerEvent('layout-change', {old_layout: this.env.layout, new_layout: layout}); + update = 1; + this.env.layout = post_data._layout = layout; + } + if (cols && cols.length) { // make sure new columns are added at the end of the list var i, idx, name, newcols = [], oldcols = this.env.listcols; @@ -2343,14 +2399,6 @@ function rcube_webmail() this.open_window(url, true); else this.location_href(url, target, true); - - // mark as read and change mbox unread counter - if (preview && this.message_list && this.message_list.rows[id] && this.message_list.rows[id].unread && this.env.preview_pane_mark_read > 0) { - this.preview_read_timer = setTimeout(function() { - ref.set_unread_message(id, ref.env.mailbox); - ref.http_post('mark', {_uid: id, _flag: 'read', _mbox: ref.env.mailbox, _quiet: 1}); - }, this.env.preview_pane_mark_read * 1000); - } } }; @@ -2562,6 +2610,11 @@ function rcube_webmail() if (page) url._page = page; + // disable double-click on the list when preview pane is on + // this eliminates delay when opening a message in preview pane (#5199) + if (this.message_list) + this.message_list.dblclick_time = this.env.layout != 'list' ? 10 : this.dblclick_time; + this.http_request('list', url, lock); this.update_state({ _mbox: mbox, _page: (page && page > 1 ? page : null) }); }; @@ -5667,9 +5720,9 @@ function rcube_webmail() selected = list.selection.length, source = this.env.source ? this.env.address_sources[this.env.source] : null; - // we don't have dblclick handler here, so use 200 instead of this.dblclick_time + // we don't have dblclick handler here, so use 50 instead of this.dblclick_time if (this.env.contentframe && (id = list.get_single_selection())) - this.preview_timer = setTimeout(function(){ ref.load_contact(id, 'show'); }, 200); + this.preview_timer = setTimeout(function(){ ref.load_contact(id, 'show'); }, 50); else if (this.env.contentframe) this.show_contentframe(false); @@ -8312,6 +8365,12 @@ function rcube_webmail() // process the response data according to the sent action switch (response.action) { + case 'mark': + // Mark the message as Seen also in the opener/parent + if ((this.env.action == 'show' || this.env.action == 'preview') && this.env.last_flag == 'SEEN') + this.set_unread_message(this.env.uid, this.env.mailbox); + break; + case 'delete': if (this.task == 'addressbook') { var sid, uid = this.contact_list.get_selection(), writable = false; diff --git a/program/js/list.js b/program/js/list.js index ad0ae3dc9..20e85d413 100644 --- a/program/js/list.js +++ b/program/js/list.js @@ -356,20 +356,24 @@ insert_row: function(row, before) // create a real dom node first if (row.nodeName === undefined) { // for performance reasons use DOM instead of jQuery here - var domrow = document.createElement(this.row_tagname()); + var i, e, domcell, col, + domrow = document.createElement(this.row_tagname()); if (row.id) domrow.id = row.id; if (row.uid) domrow.uid = row.uid; if (row.className) domrow.className = row.className; if (row.style) $.extend(domrow.style, row.style); - for (var e, domcell, col, i=0; row.cols && i < row.cols.length; i++) { + for (i=0; row.cols && i < row.cols.length; i++) { col = row.cols[i]; - domcell = document.createElement(this.col_tagname()); - if (col.className) domcell.className = col.className; - if (col.innerHTML) domcell.innerHTML = col.innerHTML; - for (e in col.events) - domcell['on' + e] = col.events[e]; + domcell = col.dom; + if (!domcell) { + domcell = document.createElement(this.col_tagname()); + if (col.className) domcell.className = col.className; + if (col.innerHTML) domcell.innerHTML = col.innerHTML; + for (e in col.events) + domcell['on' + e] = col.events[e]; + } domrow.appendChild(domcell); } diff --git a/program/lib/Roundcube/rcube_config.php b/program/lib/Roundcube/rcube_config.php index f80c7b42c..9aa6f281a 100644 --- a/program/lib/Roundcube/rcube_config.php +++ b/program/lib/Roundcube/rcube_config.php @@ -46,6 +46,7 @@ class rcube_config 'refresh_interval' => 'keep_alive', 'min_refresh_interval' => 'min_keep_alive', 'messages_cache_ttl' => 'message_cache_lifetime', + 'mail_read_time' => 'preview_pane_mark_read', 'redundant_attachments_cache_ttl' => 'redundant_attachments_memcache_ttl', ); diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc index 84a268894..043ea2ff2 100644 --- a/program/localization/en_US/labels.inc +++ b/program/localization/en_US/labels.inc @@ -203,6 +203,10 @@ $labels['listcolumns'] = 'List columns'; $labels['listsorting'] = 'Sorting column'; $labels['listorder'] = 'Sorting order'; $labels['listmode'] = 'List view mode'; +$labels['layout'] = 'Layout'; +$labels['layoutwidescreen'] = 'Widescreen'; +$labels['layoutdesktop'] = 'Desktop'; +$labels['layoutlist'] = 'List'; $labels['folderactions'] = 'Folder actions...'; $labels['compact'] = 'Compact'; diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 28d9e4a09..a20b5c8e4 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -83,7 +83,7 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') { $OUTPUT->set_env('threading', $threading); $OUTPUT->set_env('threads', $threading || $RCMAIL->storage->get_capability('THREAD')); $OUTPUT->set_env('reply_all_mode', (int) $RCMAIL->config->get('reply_all_mode')); - $OUTPUT->set_env('preview_pane_mark_read', (int) $RCMAIL->config->get('preview_pane_mark_read')); + $OUTPUT->set_env('layout', $RCMAIL->config->get('layout') ?: 'widescreen'); if ($RCMAIL->storage->get_capability('QUOTA')) { $OUTPUT->set_env('quota', true); @@ -120,6 +120,7 @@ $OUTPUT->add_handlers(array( 'quotadisplay' => array($RCMAIL, 'quota_display'), 'messages' => 'rcmail_message_list', 'messagecountdisplay' => 'rcmail_messagecount_display', + 'listmenulink' => 'rcmail_options_menu_link', 'mailboxname' => 'rcmail_mailbox_name_display', 'messageheaders' => 'rcmail_message_headers', 'messagefullheaders' => 'rcmail_message_full_headers', @@ -358,13 +359,22 @@ function rcmail_message_list($attrib) if (!in_array('threads', $a_show_cols)) array_unshift($a_show_cols, 'threads'); + $listcols = $a_show_cols; + + // Widescreen layout uses hardcoded list of columns + if ($RCMAIL->config->get('layout', 'widescreen') == 'widescreen') { + $a_show_cols = array('threads', 'subject', 'fromto', 'date', 'flag', 'attachment'); + $listcols = $a_show_cols; + array_shift($listcols); + } + // set client env $OUTPUT->add_gui_object('messagelist', $attrib['id']); $OUTPUT->set_env('autoexpand_threads', intval($RCMAIL->config->get('autoexpand_threads'))); $OUTPUT->set_env('sort_col', $_SESSION['sort_col']); $OUTPUT->set_env('sort_order', $_SESSION['sort_order']); $OUTPUT->set_env('messages', array()); - $OUTPUT->set_env('listcols', $a_show_cols); + $OUTPUT->set_env('listcols', $listcols); $OUTPUT->include_script('list.js'); @@ -426,6 +436,11 @@ function rcmail_js_message_list($a_headers, $insert_top=false, $a_show_cols=null $a_show_cols = array_unique($a_show_cols); $_SESSION['list_attrib']['columns'] = $a_show_cols; + // Widescreen layout uses hardcoded list of columns + if ($RCMAIL->config->get('layout', 'widescreen') == 'widescreen') { + $a_show_cols = array('threads', 'subject', 'fromto', 'date', 'flag', 'attachment'); + } + // Plugins may set header's list_cols/list_flags and other rcube_message_header variables // and list columns $plugin = $RCMAIL->plugins->exec_hook('messages_list', @@ -434,6 +449,14 @@ function rcmail_js_message_list($a_headers, $insert_top=false, $a_show_cols=null $a_show_cols = $plugin['cols']; $a_headers = $plugin['messages']; + if ($RCMAIL->config->get('layout', 'widescreen') == 'widescreen') { + if (!$OUTPUT->get_env('threading')) { + if (($idx = array_search('threads', $a_show_cols)) !== false) { + unset($a_show_cols[$idx]); + } + } + } + $thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : NULL; // get name of smart From/To column in folder context @@ -441,7 +464,7 @@ function rcmail_js_message_list($a_headers, $insert_top=false, $a_show_cols=null $smart_col = rcmail_message_list_smart_column_name(); } - $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead, $smart_col); + $OUTPUT->command('set_message_coltypes', array_values($a_show_cols), $thead, $smart_col); if ($multifolder && $_SESSION['search_scope'] == 'all') { $OUTPUT->command('select_folder', ''); @@ -569,22 +592,7 @@ function rcmail_message_list_head($attrib, $a_show_cols) $a_sort_cols = array('subject', 'date', 'from', 'to', 'fromto', 'size', 'cc'); if (!empty($attrib['optionsmenuicon'])) { - $onclick = 'return ' . rcmail_output::JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu', this, event)"; - $inner = $RCMAIL->gettext('listoptions'); - if (is_string($attrib['optionsmenuicon']) && $attrib['optionsmenuicon'] != 'true') { - $inner = html::img(array('src' => $RCMAIL->output->abs_url($attrib['optionsmenuicon'], true), 'alt' => $RCMAIL->gettext('listoptions'))); - } - $list_menu = html::a(array( - 'href' => '#list-options', - 'onclick' => $onclick, - 'class' => 'listmenu', - 'id' => 'listmenulink', - 'title' => $RCMAIL->gettext('listoptions'), - 'tabindex' => '0', - ), $inner); - } - else { - $list_menu = ''; + $list_menu = rcmail_options_menu_link($attrib); } $cells = $coltypes = array(); @@ -612,7 +620,7 @@ function rcmail_message_list_head($attrib, $a_show_cols) $col_name = html::span($col, $RCMAIL->gettext('readstatus')); break; case 'threads': - $col_name = $list_menu; + $col_name = (string) $list_menu; break; case 'fromto': $label = $RCMAIL->gettext($smart_col); @@ -649,6 +657,27 @@ function rcmail_message_list_head($attrib, $a_show_cols) return $cells; } +function rcmail_options_menu_link($attrib) +{ + global $RCMAIL; + + $onclick = 'return ' . rcmail_output::JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu', this, event)"; + $inner = $title = $RCMAIL->gettext('listoptions'); + + if (is_string($attrib['optionsmenuicon']) && $attrib['optionsmenuicon'] != 'true') { + $inner = html::img(array('src' => $RCMAIL->output->abs_url($attrib['optionsmenuicon'], true), 'alt' => $title)); + } + + return html::a(array( + 'href' => '#list-options', + 'onclick' => $onclick, + 'class' => 'listmenu', + 'id' => 'listmenulink', + 'title' => $title, + 'tabindex' => '0', + ), $inner); +} + /** * return an HTML iframe for loading mail content */ diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc index a317a83b6..215d09e73 100644 --- a/program/steps/mail/list.inc +++ b/program/steps/mail/list.inc @@ -40,8 +40,15 @@ if ($sort = rcube_utils::get_input_value('_sort', rcube_utils::INPUT_GET)) { } } +// register layout change +if ($layout = rcube_utils::get_input_value('_layout', rcube_utils::INPUT_GET)) { + $OUTPUT->set_env('layout', $layout); + $save_arr['layout'] = $layout; + // force header replace on layout change + $cols = $_SESSION['list_attrib']['columns']; +} // is there a set of columns for this request? -if ($cols = rcube_utils::get_input_value('_cols', rcube_utils::INPUT_GET)) { +else if ($cols = rcube_utils::get_input_value('_cols', rcube_utils::INPUT_GET)) { $_SESSION['list_attrib']['columns'] = explode(',', $cols); if (!in_array('list_cols', $dont_override)) { $save_arr['list_cols'] = explode(',', $cols); diff --git a/program/steps/mail/mark.inc b/program/steps/mail/mark.inc index c38403a75..50665e14e 100644 --- a/program/steps/mail/mark.inc +++ b/program/steps/mail/mark.inc @@ -102,6 +102,8 @@ if ($_uids && $flag) { foreach ($input as $mbox => $uids) { rcmail_send_unread_count($mbox); } + + $OUTPUT->set_env('last_flag', $flag); } else if ($flag == 'DELETED' && $skip_deleted) { if ($_POST['_from'] == 'show') { diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc index e1909a4d9..3d52e1c74 100644 --- a/program/steps/mail/show.inc +++ b/program/steps/mail/show.inc @@ -129,18 +129,21 @@ if ($uid) { } } - if (empty($MESSAGE->headers->flags['SEEN']) - && $MESSAGE->context === null - && ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($RCMAIL->config->get('preview_pane_mark_read')) == 0)) - ) { - $RCMAIL->output->command('set_unread_message', $MESSAGE->uid, $mbox_name); - $RCMAIL->plugins->exec_hook('message_read', array( - 'uid' => $MESSAGE->uid, - 'mailbox' => $mbox_name, - 'message' => $MESSAGE, - )); - - $set_seen_flag = true; + if (empty($MESSAGE->headers->flags['SEEN']) && $MESSAGE->context === null) { + $v = intval($RCMAIL->config->get('mail_read_time')); + if ($v > 0) { + $OUTPUT->set_env('mail_read_time', $v); + } + else if ($v == 0) { + $RCMAIL->output->command('set_unread_message', $MESSAGE->uid, $mbox_name); + $RCMAIL->plugins->exec_hook('message_read', array( + 'uid' => $MESSAGE->uid, + 'mailbox' => $mbox_name, + 'message' => $MESSAGE, + )); + + $set_seen_flag = true; + } } } @@ -170,11 +173,6 @@ if (!empty($set_seen_flag)) { } } -// Save preview_pane preference, if not set yet (#1490362) -if ($RCMAIL->action == 'preview' && !$RCMAIL->config->get('preview_pane')) { - $RCMAIL->user->save_prefs(array('preview_pane' => true)); -} - exit; diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index b712e61b0..6216a1c9d 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -408,36 +408,19 @@ function rcmail_user_prefs($current = null) 'advanced' => array('name' => rcube::Q($RCMAIL->gettext('advancedoptions'))), ); - // show config parameter for preview pane - if (!isset($no_override['preview_pane'])) { - if (!$current) { - continue 2; - } - - $field_id = 'rcmfd_preview'; - $input = new html_checkbox(array('name' => '_preview_pane', 'id' => $field_id, 'value' => 1, - 'onchange' => "$('#rcmfd_preview_pane_mark_read').prop('disabled', !this.checked)")); - - $blocks['main']['options']['preview_pane'] = array( - 'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('previewpane'))), - 'content' => $input->show($config['preview_pane']?1:0), - ); - } - - // show config parameter for preview pane auto mark as read delay - if (!isset($no_override['preview_pane_mark_read'])) { + // show config parameter for auto marking the previewed message as read + if (!isset($no_override['mail_read_time'])) { if (!$current) { continue 2; } // apply default if config option is not set at all - $config['preview_pane_mark_read'] = $RCMAIL->config->get('preview_pane_mark_read', 0); + $config['mail_read_time'] = intval($RCMAIL->config->get('mail_read_time')); - $field_id = 'rcmfd_preview_pane_mark_read'; - $select = new html_select(array('name' => '_preview_pane_mark_read', 'id' => $field_id, - 'disabled' => $config['preview_pane']?0:1)); + $field_id = 'rcmfd_mail_read_time'; + $select = new html_select(array('name' => '_mail_read_time', 'id' => $field_id)); - $select->add($RCMAIL->gettext('never'), '-1'); + $select->add($RCMAIL->gettext('never'), -1); $select->add($RCMAIL->gettext('immediately'), 0); foreach (array(5, 10, 20, 30) as $sec) { @@ -445,9 +428,9 @@ function rcmail_user_prefs($current = null) $select->add($label, $sec); } - $blocks['main']['options']['preview_pane_mark_read'] = array( + $blocks['main']['options']['mail_read_time'] = array( 'title' => html::label($field_id, rcube::Q($RCMAIL->gettext('previewpanemarkread'))), - 'content' => $select->show(intval($config['preview_pane_mark_read'])), + 'content' => $select->show($config['mail_read_time']), ); } diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc index a314aaf2b..ec5504fce 100644 --- a/program/steps/settings/save_prefs.inc +++ b/program/steps/settings/save_prefs.inc @@ -47,8 +47,7 @@ case 'general': case 'mailbox': $a_user_prefs = array( - 'preview_pane' => isset($_POST['_preview_pane']), - 'preview_pane_mark_read' => isset($_POST['_preview_pane_mark_read']) ? intval($_POST['_preview_pane_mark_read']) : $CONFIG['preview_pane_mark_read'], + 'mail_read_time' => isset($_POST['_mail_read_time']) ? intval($_POST['_mail_read_time']) : $CONFIG['mail_read_time'], 'autoexpand_threads' => isset($_POST['_autoexpand_threads']) ? intval($_POST['_autoexpand_threads']) : 0, 'mdn_requests' => isset($_POST['_mdn_requests']) ? intval($_POST['_mdn_requests']) : 0, 'check_all_folders' => isset($_POST['_check_all_folders']), diff --git a/program/steps/utils/save_pref.inc b/program/steps/utils/save_pref.inc index 35ece103c..165d86c58 100644 --- a/program/steps/utils/save_pref.inc +++ b/program/steps/utils/save_pref.inc @@ -26,7 +26,6 @@ $sessname = rcube_utils::get_input_value('_session', rcube_utils::INPUT_POST); // Whitelisted preferences and session variables, others // can be added by plugins $whitelist = array( - 'preview_pane', 'list_cols', 'collapsed_folders', 'collapsed_abooks', diff --git a/skins/classic/common.css b/skins/classic/common.css index 54b1c9cc9..01ed26845 100644 --- a/skins/classic/common.css +++ b/skins/classic/common.css @@ -26,10 +26,6 @@ select, input, textarea, button font-family: inherit; } -html.mozilla select { - padding: 2px 1px; -} - th { font-weight: normal; @@ -462,7 +458,6 @@ body.iframe .boxtitle height: 11px; padding: 0; margin: 1px; - margin-top: 2px; overflow: hidden; background: url(images/pagenav.gif) 0 0 no-repeat transparent; opacity: 0.99; /* this is needed to make buttons appear correctly in Chrome */ diff --git a/skins/classic/functions.js b/skins/classic/functions.js index 2e793394e..df181c730 100644 --- a/skins/classic/functions.js +++ b/skins/classic/functions.js @@ -317,6 +317,11 @@ show_listmenu: function(p) $(this).prop('checked', $.inArray(this.value, rcmail.env.listcols) != -1); }); + $.each(['widescreen', 'desktop', 'list'], function() { + $('input[name="layout"][value="' + this + '"]').prop('checked', rcmail.env.layout == this); + }); + $('#listoptions-columns', $dialog)[rcmail.env.layout == 'widescreen' ? 'hide' : 'show'](); + buttons[rcmail.gettext('save')] = function(e) { $dialog.dialog('close', e); self.save_listmenu(); @@ -354,10 +359,11 @@ save_listmenu: function() var sort = $('input[name="sort_col"]:checked').val(), ord = $('input[name="sort_ord"]:checked').val(), thread = $('input[name="view"]:checked').val(), + layout = $('input[name="layout"]:checked').val(), cols = $('input[name="list_col[]"]:checked') .map(function(){ return this.value; }).get(); - rcmail.set_list_options(cols, sort, ord, thread == 'thread' ? 1 : 0); + rcmail.set_list_options(cols, sort, ord, thread == 'thread' ? 1 : 0, layout); }, spellmenu: function(show) @@ -456,42 +462,61 @@ body_keydown: function(e) } }, -switch_preview_pane: function(elem) +// Mail view layout initialization and change handler +set_layout: function(p) { - var uid, prev_frm = $('#mailpreviewframe'); + var layout = p ? p.new_layout : rcmail.env.layout, + top = $('#mailcontframe'), + bottom = $('#mailpreviewframe'); - if (elem.checked) { - rcmail.env.contentframe = 'messagecontframe'; - if (mailviewsplit.layer) { - mailviewsplit.resize(); - mailviewsplit.layer.elm.style.display = ''; + if (p) + $('#mailrightcontainer').removeClass().addClass(layout); + + if (!this.mailviewsplitv) { + this.mailviewsplitv = new rcube_splitter({id:'mailviewsplitterv', p1: 'mailleftcontainer', p2: 'mailrightcontainer', + orientation: 'v', relative: true, start: 165, callback: rcube_render_mailboxlist }); + this.mailviewsplitv.init(); + } + + $('#mailviewsplitter')[layout == 'desktop' ? 'show' : 'hide'](); + $('#mailviewsplitter2')[layout == 'widescreen' ? 'show' : 'hide'](); + $('#mailpreviewframe')[layout != 'list' ? 'show' : 'hide'](); + rcmail.env.contentframe = layout == 'list' ? null : 'messagecontframe'; + + if (layout == 'widescreen') { + $('#countcontrols').detach().appendTo($('#messagelistheader')); + top.css({height: 'auto', width: 400}); + bottom.css({top: 0, left: 410, height: 'auto'}).show(); + if (!this.mailviewsplit2) { + this.mailviewsplit2 = new rcube_splitter({id:'mailviewsplitter2', p1: 'mailcontframe', p2: 'mailpreviewframe', + orientation: 'v', relative: true, start: 405}); + this.mailviewsplit2.init(); } else - mailviewsplit.init(); - - if (bw.opera) { - $('#messagelistcontainer').css({height: ''}); + this.mailviewsplit2.resize(); + } + else if (layout == 'desktop') { + top.css({height: 200, width: '100%'}); + bottom.css({left: 0, top: 210, height: 'auto'}).show(); + if (!this.mailviewsplit) { + this.mailviewsplit = new rcube_splitter({id:'mailviewsplitter', p1: 'mailcontframe', p2: 'mailpreviewframe', + orientation: 'h', relative: true, start: 205}); + this.mailviewsplit.init(); } - prev_frm.show(); - - if (uid = rcmail.message_list.get_single_selection()) - rcmail.show_message(uid, false, true); + else + this.mailviewsplit.resize(); } - else { - prev_frm.hide(); - $('#mailcontframe').css({height: 'auto', bottom: 0}); - if (bw.opera) - $('#messagelistcontainer').css({height: 'auto'}); - if (mailviewsplit.layer) - mailviewsplit.layer.elm.style.display = 'none'; - - rcmail.env.contentframe = null; - rcmail.show_contentframe(false); + else { // layout == 'list' + top.css({height: 'auto', width: '100%'}); + bottom.hide(); } - rcmail.command('save-pref', {name: 'preview_pane', value: (elem.checked?1:0)}); + if (p && p.old_layout == 'widescreen') { + $('#countcontrols').detach().appendTo($('#messagelistfooter')); + } }, + /* Message composing */ init_compose_form: function() { @@ -1031,7 +1056,11 @@ function rcube_init_mail_ui() setTimeout(function() { rcmail.message_list.resize(); }, 10); }); - if (rcmail.env.action == 'compose') { + if (rcmail.env.action == 'list' || !rcmail.env.action) { + rcmail.addEventListener('layout-change', 'set_layout', rcmail_ui); + rcmail_ui.set_layout(); + } + else if (rcmail.env.action == 'compose') { rcmail_ui.init_compose_form(); rcmail.addEventListener('compose-encrypted', function(e) { $("a.button.encrypt")[(e.active ? 'addClass' : 'removeClass')]('selected'); diff --git a/skins/classic/mail.css b/skins/classic/mail.css index f22623c95..d275c054a 100644 --- a/skins/classic/mail.css +++ b/skins/classic/mail.css @@ -368,11 +368,12 @@ #mailpreviewframe { position: absolute; - width: 100%; + right: 0; top: 205px; bottom: 0px; border: 1px solid #999999; background-color: #F9F9F9; + display: none; } #messagecontframe @@ -570,7 +571,6 @@ table.messagelist width: 100%; display: table; table-layout: fixed; - border-collapse: collapse; border-spacing: 0; z-index: 1; } @@ -668,10 +668,10 @@ table.messagelist.fixedcopy cursor: pointer; } -.messagelist tr > .flag span, -.messagelist tr > .status span, -.messagelist tr > .attachment span, -.messagelist tr > .priority span +.messagelist tr .flag span, +.messagelist tr .status span, +.messagelist tr .attachment span, +.messagelist tr .priority span { display: block; width: 15px; @@ -682,18 +682,18 @@ table.messagelist.fixedcopy .messagelist tr td div.collapsed, .messagelist tr td div.expanded, .messagelist tr > .threads .listmenu, -.messagelist tr > .attachment span.attachment, -.messagelist tr > .attachment span.report, -.messagelist tr > .attachment span.encrypted, +.messagelist tr .attachment span.attachment, +.messagelist tr .attachment span.report, +.messagelist tr .attachment span.encrypted, .messagelist tr > .priority span.priority, .messagelist tr > .priority span.prio1, .messagelist tr > .priority span.prio2, .messagelist tr > .priority span.prio3, .messagelist tr > .priority span.prio4, .messagelist tr > .priority span.prio5, -.messagelist tr > .flag span.flagged, -.messagelist tr > .flag span.unflagged, -.messagelist tr > .flag span.unflagged:hover, +.messagelist tr .flag span.flagged, +.messagelist tr .flag span.unflagged, +.messagelist tr:hover .flag span.unflagged, .messagelist tr > .status span.status, .messagelist tr > .status span.msgicon, .messagelist tr > .status span.deleted, @@ -713,17 +713,17 @@ table.messagelist.fixedcopy background: url(images/messageicons.png) center no-repeat; } -.messagelist tr > .attachment span.attachment +.messagelist tr .attachment span.attachment { background-position: 0 -170px; } -.messagelist tr > .attachment span.report +.messagelist tr .attachment span.report { background-position: 0 -255px; } -.messagelist tr > .attachment span.encrypted +.messagelist tr .attachment span.encrypted { background-position: 0 -418px; } @@ -758,17 +758,18 @@ table.messagelist.fixedcopy background-position: 0 -290px; } -.messagelist tr.flaggedroot td.flag span +.messagelist tr .flag span.flagged { - background-position: 0 -136px; + background-position: 0 -153px; } -.messagelist tr > .flag span.flagged +.messagelist tr:hover .flag span.unflagged { - background-position: 0 -153px; + background-position: 0 -136px; } -.messagelist tr > .flag span.unflagged:hover +.messagelist tr.flaggedroot .flag span, +.messagelist tr.flaggedroot .flag span.unflagged { background-position: 0 -136px; } @@ -796,10 +797,10 @@ table.messagelist.fixedcopy } .messagelist tr > .status span.msgicon, -.messagelist tr > .flag span.unflagged, +.messagelist tr .flag span.unflagged, .messagelist tr > .status span.unreadchildren { - background-position: 0 17px; /* no icon */ + background-position: 0 18px; /* no icon */ } .messagelist tr > .status span.msgicon:hover @@ -928,7 +929,7 @@ table.messagelist.fixedcopy /* because of border-collapse, we make the left border twice what we want it to be - half will be hidden to the left */ .messagelist tbody tr.focused > td:first-child { - border-left: 4px solid #d4d4d4; + border-left: 2px solid #d4d4d4; padding-left: 4px; } @@ -1751,3 +1752,139 @@ input.from_address top: 45px; position: absolute; } + +/**** Styles for widescreen (3-column) view ****/ + +.widescreen #mailview-top { + bottom: 0; + width: 400px; + height: auto; +} + +.widescreen #mailview-bottom { + left: 412px; + top:0; + border: 1px solid #a3a3a3; +} + +#messagelistheader, +.widescreen #messagelistfooter #countcontrols, +.widescreen .messagelist > thead, +.widescreen .messagelist .branch, +.widescreen table.fixedcopy { + display: none; +} + +#messagelistcontainer { + top: 0; +} + +.widescreen #messagelistcontainer { + top: 21px; + overflow-x: hidden; +} + +.widescreen #mailpreviewframe { + top: 0; +} + +.widescreen #messagelistheader { + display: block; + top: 0; + white-space: nowrap; + border-top: 0; + border-bottom: 1px solid #999; + height: 20px; +} + +.widescreen #messagelistheader .listmenu { + display: inline-block; + vertical-align: middle; + line-height: 16px; + width: 15px; + background: url(images/messageicons.png) 4px -236px no-repeat; + cursor: pointer; + overflow: hidden; + text-indent: -5000px; + padding: 2px 4px; +} + +.widescreen .messagelist td { + border-left: 0; + vertical-align: top; + padding: 3px 1px 1px !important; +} + +.widescreen .messagelist td.subject { + width: 99%; + white-space: wrap; + position: relative; /* for span.date positioning in Firefox */ +} + +.widescreen .messagelist td.threads { + width: 14px; + vertical-align: middle; +} + +.widescreen .messagelist td.flags { + width: 20px; +} + +.widescreen .messagelist td.subject span { + line-height: 16px; +} + +.widescreen .messagelist td.subject span.date { + right: 2px; + top: 3px; + position: absolute; + color: #666; +} + +.widescreen .messagelist td.subject span.fromto { + padding-left: 18px; + display: block; + margin-right: 90px; + overflow: hidden; + text-overflow: ellipsis; + color: #666; +} + +.widescreen .messagelist tr.flagged td.subject span.date, +.widescreen .messagelist tr.flagged td.subject span.fromto { + color: #ff0000; +} + +.widescreen .messagelist tr.selected td.subject span.date, +.widescreen .messagelist tr.selected td.subject span.fromto { + color: #fff; +} + +.widescreen .messagelist tr.deleted td.subject span.date, +.widescreen .messagelist tr.deleted td.subject span.fromto { + color: #ccc; +} + +.widescreen .messagelist td.subject span.subject { + clear: both; + display: block; + font-size: 13px; + overflow: hidden; + text-overflow: ellipsis; +} + +.widescreen .messagelist td.flags span { + width: 20px; + height: 18px; + display: block; +} + +.widescreen .messagelist td.flags span.flag { + cursor: pointer; +} + +.widescreen .messagelist tr td.subject span.msgicon, +.widescreen .messagelist tr td.subject span.unreadchildren { + width: 18px; + margin: 0; +} diff --git a/skins/classic/templates/mail.html b/skins/classic/templates/mail.html index 62fd13ed1..07558b588 100644 --- a/skins/classic/templates/mail.html +++ b/skins/classic/templates/mail.html @@ -6,9 +6,12 @@ - - - - -
- -
- + +
+ +
\ No newline at end of file diff --git a/skins/larry/images/listicons.png b/skins/larry/images/listicons.png index 0132765d4..f877ae27b 100644 Binary files a/skins/larry/images/listicons.png and b/skins/larry/images/listicons.png differ diff --git a/skins/larry/mail.css b/skins/larry/mail.css index 23c852a7a..9af0941e7 100644 --- a/skins/larry/mail.css +++ b/skins/larry/mail.css @@ -66,6 +66,7 @@ html.ie #mailview-top { left: 0; width: 100%; bottom: 0; + outline: none; } #messagelistcontainer { @@ -86,7 +87,7 @@ html>/**/body #messagelist { left: 0; right: 0; height: 22px; - padding: 4px 6px; + padding: 5px 6px 3px; border-top: 1px solid #ddd; background: #ebebeb; background: -moz-linear-gradient(top, #ebebeb 0%, #c6c6c6 100%); @@ -230,20 +231,6 @@ html.mozilla #mailboxlist > li:first-child { top: 0; } -#mailpreviewtoggle { - display: block; - position: absolute; - top: 7px; - right: 4px; - width: 20px; - height: 18px; - background: url(images/buttons.png) -3px -458px no-repeat; -} - -#mailpreviewtoggle.enabled { - background-position: -28px -458px; -} - #s_interval { margin: 3px 8px; } @@ -372,18 +359,18 @@ table.messagelist.fixedcopy { .messagelist tr td div.collapsed, .messagelist tr td div.expanded, .messagelist tr > .threads .listmenu, -.messagelist tr > .attachment span.attachment, -.messagelist tr > .attachment span.report, -.messagelist tr > .attachment span.encrypted, +.messagelist tr .attachment span.attachment, +.messagelist tr .attachment span.report, +.messagelist tr .attachment span.encrypted, .messagelist tr > .priority span.priority, .messagelist tr > .priority span.prio1, .messagelist tr > .priority span.prio2, .messagelist tr > .priority span.prio3, .messagelist tr > .priority span.prio4, .messagelist tr > .priority span.prio5, -.messagelist tr > .flag span.flagged, -.messagelist tr > .flag span.unflagged, -.messagelist tr > .flag span.unflagged:hover, +.messagelist tr .flag span.flagged, +.messagelist tr .flag span.unflagged, +.messagelist tr .flag span.unflagged:hover, .messagelist tr > .status span.status, .messagelist tr > .status span.msgicon, .messagelist tr > .status span.deleted, @@ -403,19 +390,19 @@ table.messagelist.fixedcopy { background: url(images/listicons.png) -100px 0 no-repeat; } -.messagelist tbody tr td.attachment span.attachment { +.messagelist tbody tr .attachment span.attachment { background-position: 0 -996px; } -.messagelist thead tr th.attachment span.attachment { +.messagelist thead tr .attachment span.attachment { background-position: -24px -996px; } -.messagelist tbody tr td.attachment span.report { +.messagelist tbody tr .attachment span.report { background-position: -24px -1116px; } -.messagelist tbody tr td.attachment span.encrypted { +.messagelist tbody tr .attachment span.encrypted { background-position: 0 -2272px; } @@ -440,11 +427,11 @@ table.messagelist.fixedcopy { } /* thread parent message with flagged children */ -.messagelist tbody tr.flaggedroot td.flag span { +.messagelist tbody tr.flaggedroot .flag span { background-position: -23px -1076px; } -.messagelist tbody tr td.flag span.flagged { +.messagelist tbody tr .flag span.flagged { background-position: 0 -1036px; } @@ -456,7 +443,7 @@ table.messagelist.fixedcopy { background-position: -23px -1057px; } -.messagelist tr:hover td.flag span.unflagged { +.messagelist tr:hover .flag span.unflagged { background-position: -23px -1076px; } @@ -1399,3 +1386,199 @@ div.message-partheaders .headers-table td.header { #uploadform form div { margin: 4px 0; } + + +/**** Styles for widescreen (3-column) view ****/ + +.widescreen #mailview-top { + bottom: 0; + width: 400px; + height: auto; +} + +.widescreen #mailview-bottom { + left: 412px; + top:0; + border: 1px solid #a3a3a3; +} + +#messagelistheader, +.widescreen #messagelistfooter #countcontrols, +.widescreen .messagelist > thead, +.widescreen .messagelist .branch, +.widescreen table.fixedcopy { + display: none; +} + +.widescreen #messagelistcontainer { + top: 34px; + overflow-x: hidden; +} + +.widescreen #messagelistheader { + display: block; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 34px; + padding: 6px 6px; + background: #f0f0f0; + background: -moz-linear-gradient(top, #fff 0%, #f0f0f0 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fff), color-stop(100%,#f0f0f0)); + background: -ms-linear-gradient(top, #fff 0%, #f0f0f0 100%); + background: linear-gradient(to bottom, #fff 0%, #f0f0f0 100%); + border-radius: 4px 4px 0 0; + white-space: nowrap; + border-bottom: 1px solid #dfdfdf; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.widescreen #messagelistheader .listmenu { + margin-right: 10px; + vertical-align: middle; + line-height: 22px; + width: 26px; + padding: 0; + text-indent: -5000px; + overflow: hidden; + display: inline-block; + background: url(images/listicons.png) 0 -2330px no-repeat; +} + +.widescreen #countcontrols { + line-height: 24px; + display: inline; + min-width: 0; +} + +.widescreen #countcontrols span { + padding: 0; +} + +.widescreen .pagenavbuttons { + position: absolute; + top: 4px; + right: 6px; +} + +.widescreen .pagenavbuttons a.button { + background: none; + border: 0; + box-shadow: none; + padding: 2px; + margin: 0; + height: 20px; +} + +.widescreen .pagenavbuttons a.button.pressed { + background: inherit; +} + +.widescreen a.listmenu:focus, +.widescreen .pagenav a.button:focus { + border-color: #4fadd5; + box-shadow: 0 0 4px 2px rgba(71,135,177, 0.8); + outline: none; +} + +.widescreen .messagelist td { + border-left: 0; + vertical-align: top; + padding: 3px 2px !important; +} + +.widescreen .messagelist td.subject { + width: 99%; + white-space: wrap; + position: relative; /* for span.date positioning in Firefox */ +} + +.widescreen .messagelist td.threads { + width: 20px; + vertical-align: top; +} + +.widescreen .messagelist td.flags { + width: 22px; +} + +.widescreen .messagelist td.subject span { + line-height: 20px; +} + +.widescreen .messagelist td.subject span.date { + right: 2px; + top: 3px; + position: absolute; + color: #666; +} + +.widescreen .messagelist td.subject span.fromto { + padding-left: 22px; + display: block; + margin-right: 10em; + overflow: hidden; + text-overflow: ellipsis; + color: #666; +} + +.widescreen .messagelist tr.flagged td.subject span.date, +.widescreen .messagelist tr.flagged td.subject span.fromto { + color: #ff5c33; +} + +.widescreen .messagelist tr.deleted td.subject span.date, +.widescreen .messagelist tr.deleted td.subject span.fromto { + color: #ccc; +} + +.widescreen .messagelist td.subject span.subject { + clear: both; + display: block; + font-size: 12px; + overflow: hidden; + text-overflow: ellipsis; +} + +.widescreen .messagelist td.flags span { + width: 20px; + height: 20px; + display: block; + margin-left: 1px; +} + +.widescreen .messagelist td.flags span.flag { + cursor: pointer; +} + +.widescreen .messagelist tr td.subject span.msgicon, +.widescreen .messagelist tr td.subject span.unreadchildren { + width: 20px; +} + +/* move attachments list to the bottom on narrow mail preview page */ +@media screen and (max-width: 800px) { + #messagepreview .leftcol { + margin-right: 0; + } + #messagepreview .rightcol { + min-height: 0; + width: auto; + right: 0; + position: relative; + border-radius: 0; + border-bottom: 1px solid #dfdfdf; + background-color: #f9f9f9; + padding: 5px; + } + ul.attachmentslist, + ul.attachmentslist > li, + div.rightcol > div > a.button { + vertical-align: middle; + display: inline-block; + margin-top: 0; + } +} diff --git a/skins/larry/styles.css b/skins/larry/styles.css index 143c135a6..9219d81a3 100644 --- a/skins/larry/styles.css +++ b/skins/larry/styles.css @@ -426,9 +426,7 @@ a.button.delete span.icon { .pagenav .pagejumper { text-align: center; - background: #f8f8f8; padding: 3px 0; - background: linear-gradient(to bottom, #dddddd 0%, #f8f8f8 100%); cursor: default; } diff --git a/skins/larry/templates/mail.html b/skins/larry/templates/mail.html index ce51fd2c2..6ab25c469 100644 --- a/skins/larry/templates/mail.html +++ b/skins/larry/templates/mail.html @@ -4,7 +4,7 @@ <roundcube:object name="pagetitle" />