summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG2
-rw-r--r--program/include/rcube_addressbook.php5
-rw-r--r--program/include/rcube_ldap.php59
-rw-r--r--program/include/rcube_vcard.php24
-rw-r--r--program/js/app.js26
-rw-r--r--program/localization/en_US/labels.inc3
-rw-r--r--program/steps/mail/func.inc88
-rw-r--r--program/steps/settings/folders.inc60
-rw-r--r--skins/larry/ie7hacks.css10
-rw-r--r--skins/larry/iehacks.css4
-rw-r--r--skins/larry/images/contactpic_32px.pngbin3422 -> 333 bytes
-rw-r--r--skins/larry/images/contactpic_48px.pngbin3812 -> 409 bytes
-rw-r--r--skins/larry/mail.css147
-rw-r--r--skins/larry/svggradients.css4
-rw-r--r--skins/larry/templates/message.html56
-rw-r--r--skins/larry/templates/messageerror.html16
-rw-r--r--skins/larry/templates/messagepreview.html13
-rw-r--r--skins/larry/ui.js35
18 files changed, 338 insertions, 214 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 598eff9fb..155e443e4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,8 @@
CHANGELOG Roundcube Webmail
===========================
+- Force fonts in compose fields to be all the same (#1488690)
+- Fix handling vCard entries with TEL;TYPE=CELL (#1488728)
- Integrated zipdownload plugin to download all attachments (#1445509)
- Fix HTML special characters handling in message list/header display (#1488523)
- List related text/html part as attachment in plain text mode (#1488677)
diff --git a/program/include/rcube_addressbook.php b/program/include/rcube_addressbook.php
index f4f255322..892ae263a 100644
--- a/program/include/rcube_addressbook.php
+++ b/program/include/rcube_addressbook.php
@@ -434,6 +434,11 @@ abstract class rcube_addressbook
}
}
+ // remove duplicates
+ if ($flat && !empty($out)) {
+ $out = array_unique($out);
+ }
+
return $out;
}
diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php
index ad2ccddeb..b9b6490fa 100644
--- a/program/include/rcube_ldap.php
+++ b/program/include/rcube_ldap.php
@@ -109,24 +109,22 @@ class rcube_ldap extends rcube_addressbook
if (!is_array($this->coltypes[$col])) {
$subtypes = $type ? array($type) : null;
- $this->coltypes[$col] = array('limit' => $limit, 'subtypes' => $subtypes);
+ $this->coltypes[$col] = array('limit' => $limit, 'subtypes' => $subtypes, 'attributes' => array($lf));
}
elseif ($type) {
$this->coltypes[$col]['subtypes'][] = $type;
+ $this->coltypes[$col]['attributes'][] = $lf;
$this->coltypes[$col]['limit'] += $limit;
}
if ($delim)
$this->coltypes[$col]['serialized'][$type] = $delim;
- if ($type && !$this->fieldmap[$col])
- $this->fieldmap[$col] = $lf;
-
- $this->fieldmap[$colv] = $lf;
+ $this->fieldmap[$colv] = $lf;
}
// support for composite address
- if ($this->fieldmap['street'] && $this->fieldmap['locality']) {
+ if ($this->coltypes['street'] && $this->coltypes['locality']) {
$this->coltypes['address'] = array(
'limit' => max(1, $this->coltypes['locality']['limit'] + $this->coltypes['address']['limit']),
'subtypes' => array_merge((array)$this->coltypes['address']['subtypes'], (array)$this->coltypes['locality']['subtypes']),
@@ -134,7 +132,7 @@ class rcube_ldap extends rcube_addressbook
) + (array)$this->coltypes['address'];
foreach (array('street','locality','zipcode','region','country') as $childcol) {
- if ($this->fieldmap[$childcol]) {
+ if ($this->coltypes[$childcol]) {
$this->coltypes['address']['childs'][$childcol] = array('type' => 'text');
unset($this->coltypes[$childcol]); // remove address child col from global coltypes list
}
@@ -468,8 +466,8 @@ class rcube_ldap extends rcube_addressbook
*/
function set_sort_order($sort_col, $sort_order = null)
{
- if ($this->fieldmap[$sort_col])
- $this->sort_col = $this->fieldmap[$sort_col];
+ if ($this->coltypes[$sort_col]['attributes'])
+ $this->sort_col = $this->coltypes[$sort_col]['attributes'][0];
}
@@ -858,8 +856,13 @@ class rcube_ldap extends rcube_addressbook
{
foreach ((array)$fields as $idx => $field) {
$val = is_array($value) ? $value[$idx] : $value;
- if ($f = $this->_map_field($field)) {
- $filter .= "($f=$wp" . $this->_quote_string($val) . "$ws)";
+ if ($attrs = $this->_map_field($field)) {
+ if (count($attrs) > 1)
+ $filter .= '(|';
+ foreach ($attrs as $f)
+ $filter .= "($f=$wp" . $this->_quote_string($val) . "$ws)";
+ if (count($attrs) > 1)
+ $filter .= ')';
}
}
}
@@ -867,9 +870,16 @@ class rcube_ldap extends rcube_addressbook
// add required (non empty) fields filter
$req_filter = '';
- foreach ((array)$required as $field)
- if ($f = $this->_map_field($field))
- $req_filter .= "($f=*)";
+ foreach ((array)$required as $field) {
+ if ($attrs = $this->_map_field($field)) {
+ if (count($attrs) > 1)
+ $req_filter .= '(|';
+ foreach ($attrs as $f)
+ $req_filter .= "($f=*)";
+ if (count($attrs) > 1)
+ $req_filter .= ')';
+ }
+ }
if (!empty($req_filter))
$filter = '(&' . $req_filter . $filter . ')';
@@ -1498,7 +1508,7 @@ class rcube_ldap extends rcube_addressbook
list($col, $subtype) = explode(':', $rf);
$out['_raw_attrib'][$lf][$i] = $value;
- if ($rf == 'email' && $this->mail_domain && !strpos($value, '@'))
+ if ($col == 'email' && $this->mail_domain && !strpos($value, '@'))
$out[$rf][] = sprintf('%s@%s', $value, $this->mail_domain);
else if (in_array($col, array('street','zipcode','locality','country','region')))
$out['address'.($subtype?':':'').$subtype][$i][$col] = $value;
@@ -1521,11 +1531,11 @@ class rcube_ldap extends rcube_addressbook
/**
- * Return real field name (from fields map)
+ * Return LDAP attribute(s) for the given field
*/
private function _map_field($field)
{
- return $this->fieldmap[$field];
+ return (array)$this->coltypes[$field]['attributes'];
}
@@ -1558,8 +1568,19 @@ class rcube_ldap extends rcube_addressbook
}
$ldap_data = array();
- foreach ($this->fieldmap as $col => $fld) {
- $val = $save_cols[$col];
+ foreach ($this->fieldmap as $rf => $fld) {
+ $val = $save_cols[$rf];
+
+ // check for value in base field (eg.g email instead of email:foo)
+ list($col, $subtype) = explode(':', $rf);
+ if (!$val && !empty($save_cols[$col])) {
+ $val = $save_cols[$col];
+ unset($save_cols[$col]); // only use this value once
+ }
+ else if (!$val && !$subtype) { // extract values from subtype cols
+ $val = $this->get_col_values($col, $save_cols, true);
+ }
+
if (is_array($val))
$val = array_filter($val); // remove empty entries
if ($fld && $val) {
diff --git a/program/include/rcube_vcard.php b/program/include/rcube_vcard.php
index 49b312c5c..00903c257 100644
--- a/program/include/rcube_vcard.php
+++ b/program/include/rcube_vcard.php
@@ -50,7 +50,7 @@ class rcube_vcard
'spouse' => 'X-SPOUSE',
'edit' => 'X-AB-EDIT',
);
- private $typemap = array('iPhone' => 'mobile', 'CELL' => 'mobile', 'WORK,FAX' => 'workfax');
+ private $typemap = array('IPHONE' => 'mobile', 'CELL' => 'mobile', 'WORK,FAX' => 'workfax');
private $phonetypemap = array('HOME1' => 'HOME', 'BUSINESS1' => 'WORK', 'BUSINESS2' => 'WORK2', 'BUSINESSFAX' => 'WORK,FAX');
private $addresstypemap = array('BUSINESS' => 'WORK');
private $immap = array('X-JABBER' => 'jabber', 'X-ICQ' => 'icq', 'X-MSN' => 'msn', 'X-AIM' => 'aim', 'X-YAHOO' => 'yahoo', 'X-SKYPE' => 'skype', 'X-SKYPE-USERNAME' => 'skype');
@@ -159,7 +159,18 @@ class rcube_vcard
if (!empty($raw['type'])) {
$combined = join(',', self::array_filter((array)$raw['type'], 'internet,pref', true));
- $subtype = $typemap[$combined] ? $typemap[$combined] : ($typemap[$raw['type'][++$k]] ? $typemap[$raw['type'][$k]] : strtolower($raw['type'][$k]));
+ $combined = strtoupper($combined);
+
+ if ($typemap[$combined]) {
+ $subtype = $typemap[$combined];
+ }
+ else if ($typemap[$raw['type'][++$k]]) {
+ $subtype = $typemap[$raw['type'][$k]];
+ }
+ else {
+ $subtype = strtolower($raw['type'][$k]);
+ }
+
while ($k < count($raw['type']) && ($subtype == 'internet' || $subtype == 'pref'))
$subtype = $typemap[$raw['type'][++$k]] ? $typemap[$raw['type'][$k]] : strtolower($raw['type'][$k]);
}
@@ -167,8 +178,11 @@ class rcube_vcard
// read vcard 2.1 subtype
if (!$subtype) {
foreach ($raw as $k => $v) {
- if (!is_numeric($k) && $v === true && !in_array(strtolower($k), array('pref','internet','voice','base64'))) {
- $subtype = $typemap[$k] ? $typemap[$k] : strtolower($k);
+ if (!is_numeric($k) && $v === true && ($k = strtolower($k))
+ && !in_array($k, array('pref','internet','voice','base64'))
+ ) {
+ $k_uc = strtoupper($k);
+ $subtype = $typemap[$k_uc] ? $typemap[$k_uc] : $k;
break;
}
}
@@ -335,7 +349,7 @@ class rcube_vcard
$index = count($this->raw[$tag]);
$this->raw[$tag][$index] = (array)$value;
if ($type)
- $this->raw[$tag][$index]['type'] = explode(',', ($typemap[$type] ? $typemap[$type] : $type));
+ $this->raw[$tag][$index]['type'] = explode(',', ($typemap[$type_uc] ? $typemap[$type_uc] : $type));
}
break;
}
diff --git a/program/js/app.js b/program/js/app.js
index 4d784e532..06eb9295c 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -5624,6 +5624,32 @@ function rcube_webmail()
this.messages = {};
};
+ // open a jquery UI dialog with the given content
+ this.show_popup_dialog = function(html, title)
+ {
+ // forward call to parent window
+ if (this.is_framed()) {
+ parent.rcmail.show_popup_dialog(html, title);
+ return;
+ }
+
+ var popup = $('<div class="popup">')
+ .html(html)
+ .dialog({
+ title: title,
+ modal: true,
+ resizable: true,
+ width: 580,
+ close: function(event, ui) { $(this).remove() }
+ });
+
+ // resize and center popup
+ var win = $(window), w = win.width(), h = win.height(),
+ width = popup.width(), height = popup.height();
+ popup.dialog('option', { height: Math.min(h-40, height+50), width: Math.min(w-20, width+50) })
+ .dialog('option', 'position', ['center', 'center']); // only works in a separate call (!?)
+ };
+
// enable/disable buttons for page shifting
this.set_page_buttons = function()
{
diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc
index 9882c19b5..fbc154b88 100644
--- a/program/localization/en_US/labels.inc
+++ b/program/localization/en_US/labels.inc
@@ -236,6 +236,9 @@ $labels['nosubject'] = '(no subject)';
$labels['showimages'] = 'Display images';
$labels['alwaysshow'] = 'Always show images from $sender';
$labels['isdraft'] = 'This is a draft message.';
+$labels['andnmore'] = '$nr more...';
+$labels['togglemoreheaders'] = 'Show more message headers';
+$labels['togglefullheaders'] = 'Toggle raw message headers';
$labels['htmltoggle'] = 'HTML';
$labels['plaintoggle'] = 'Plain text';
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index 8bf80a6ee..e3866aa57 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -319,7 +319,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null
$col_name = $col == 'fromto' ? $smart_col : $col;
if (in_array($col_name, array('from', 'to', 'cc', 'replyto')))
- $cont = Q(rcmail_address_string($header->$col_name, 3, false, null, $header->charset), 'show');
+ $cont = rcmail_address_string($header->$col_name, 3, false, null, $header->charset);
else if ($col == 'subject') {
$cont = trim(rcube_mime::decode_header($header->$col, $header->charset));
if (!$cont) $cont = rcube_label('nosubject');
@@ -957,6 +957,8 @@ function rcmail_message_headers($attrib, $headers=NULL)
$output_headers = array();
foreach ($standard_headers as $hkey) {
+ $ishtml = false;
+
if ($headers[$hkey])
$value = $headers[$hkey];
else if ($headers['others'][$hkey])
@@ -967,6 +969,8 @@ function rcmail_message_headers($attrib, $headers=NULL)
if (in_array($hkey, $exclude_headers))
continue;
+ $header_title = rcube_label(preg_replace('/(^mail-|-)/', '', $hkey));
+
if ($hkey == 'date') {
if ($PRINT_MODE)
$header_value = format_date($value, $RCMAIL->config->get('date_long', 'x'));
@@ -981,32 +985,41 @@ function rcmail_message_headers($attrib, $headers=NULL)
continue;
}
else if ($hkey == 'replyto') {
- if ($headers['replyto'] != $headers['from'])
- $header_value = rcmail_address_string($value, null, true, $attrib['addicon'], $headers['charset']);
+ if ($headers['replyto'] != $headers['from']) {
+ $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
+ $ishtml = true;
+ }
else
continue;
}
else if ($hkey == 'mail-reply-to') {
if ($headers['mail-replyto'] != $headers['reply-to']
&& $headers['reply-to'] != $headers['from']
- )
- $header_value = rcmail_address_string($value, null, true, $attrib['addicon'], $headers['charset']);
+ ) {
+ $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
+ $ishtml = true;
+ }
else
continue;
}
else if ($hkey == 'mail-followup-to') {
- $header_value = rcmail_address_string($value, null, true, $attrib['addicon'], $headers['charset']);
+ $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
+ $ishtml = true;
+ }
+ else if (in_array($hkey, array('from', 'to', 'cc', 'bcc'))) {
+ $header_value = rcmail_address_string($value, $attrib['max'], true, $attrib['addicon'], $headers['charset'], $header_title);
+ $ishtml = true;
}
- else if (in_array($hkey, array('from', 'to', 'cc', 'bcc')))
- $header_value = rcmail_address_string($value, null, true, $attrib['addicon'], $headers['charset']);
else if ($hkey == 'subject' && empty($value))
$header_value = rcube_label('nosubject');
else
$header_value = trim(rcube_mime::decode_header($value, $headers['charset']));
$output_headers[$hkey] = array(
- 'title' => rcube_label(preg_replace('/(^mail-|-)/', '', $hkey)),
- 'value' => $header_value, 'raw' => $value
+ 'title' => $header_title,
+ 'value' => $header_value,
+ 'raw' => $value,
+ 'html' => $ishtml,
);
}
@@ -1022,7 +1035,7 @@ function rcmail_message_headers($attrib, $headers=NULL)
foreach ($plugin['output'] as $hkey => $row) {
$table->add(array('class' => 'header-title'), Q($row['title']));
- $table->add(array('class' => 'header '.$hkey), Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show')));
+ $table->add(array('class' => 'header '.$hkey), $row['html'] ? $row['value'] : Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show')));
}
return $table->show($attrib);
@@ -1055,17 +1068,12 @@ function rcmail_message_full_headers($attrib, $headers=NULL)
global $OUTPUT;
$html = html::div(array('id' => "all-headers", 'class' => "all", 'style' => 'display:none'), html::div(array('id' => 'headers-source'), ''));
-
- if (!get_boolean($attrib['no-switch'])) {
- $html .= html::div(array('class' => "more-headers show-headers", 'onclick' => "return ".JS_OBJECT_NAME.".command('show-headers','',this)"), '');
- }
-
- unset($attrib['no-switch']);
+ $html .= html::div(array('class' => "more-headers show-headers", 'onclick' => "return ".JS_OBJECT_NAME.".command('show-headers','',this)", 'title' => rcube_label('togglefullheaders')), '');
$OUTPUT->add_gui_object('all_headers_row', 'all-headers');
$OUTPUT->add_gui_object('all_headers_box', 'headers-source');
- return count($attrib) > 1 ? html::div($attrib, $html) : $html;
+ return html::div($attrib, $html);
}
@@ -1399,7 +1407,7 @@ function rcmail_alter_html_link($matches)
/**
* decode address string and re-format it as HTML links
*/
-function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, $default_charset=null)
+function rcmail_address_string($input, $max=null, $linked=false, $addicon=null, $default_charset=null, $title=null)
{
global $RCMAIL, $PRINT_MODE, $CONFIG;
@@ -1411,6 +1419,7 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null,
$c = count($a_parts);
$j = 0;
$out = '';
+ $allvalues = array();
if ($addicon && !isset($_SESSION['writeable_abook'])) {
$_SESSION['writeable_abook'] = $RCMAIL->get_address_sources(true) ? true : false;
@@ -1418,7 +1427,6 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null,
foreach ($a_parts as $part) {
$j++;
-
$name = $part['name'];
$mailto = $part['mailto'];
$string = $part['string'];
@@ -1449,7 +1457,7 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null,
}
if ($addicon && $_SESSION['writeable_abook']) {
- $address = html::span(null, $address . html::a(array(
+ $address .= html::a(array(
'href' => "#add",
'onclick' => sprintf("return %s.command('add-contact','%s',this)", JS_OBJECT_NAME, $string),
'title' => rcube_label('addtoaddressbook'),
@@ -1458,26 +1466,46 @@ function rcmail_address_string($input, $max=null, $linked=false, $addicon=null,
html::img(array(
'src' => $CONFIG['skin_path'] . $addicon,
'alt' => "Add contact",
- ))));
+ )));
}
- $out .= $address;
}
else {
+ $address = '';
if ($name)
- $out .= Q($name);
+ $address .= Q($name);
if ($mailto)
- $out .= (strlen($out) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($mailto));
+ $address .= (strlen($address) ? ' ' : '') . sprintf('&lt;%s&gt;', Q($mailto));
}
- if ($c>$j)
- $out .= ','.($max ? '&nbsp;' : ' ');
+ $address = html::span('adr', $address);
+ $allvalues[] = $address;
- if ($max && $j==$max && $c>$j) {
- $out .= '...';
- break;
+ if (!$moreadrs)
+ $out .= ($out ? ', ' : '') . $address;
+
+ if ($max && $j == $max && $c > $j) {
+ if ($linked) {
+ $moreadrs = $c - $j;
+ }
+ else {
+ $out .= '...';
+ break;
+ }
}
}
+ if ($moreadrs) {
+ $out .= ' ' . html::a(array(
+ 'href' => '#more',
+ 'class' => 'morelink',
+ 'onclick' => sprintf("return %s.show_popup_dialog('%s','%s')",
+ JS_OBJECT_NAME,
+ JQ(join(', ', $allvalues)),
+ JQ($title))
+ ),
+ Q(rcube_label(array('name' => 'andnmore', 'vars' => array('nr' => $moreadrs)))));
+ }
+
return $out;
}
diff --git a/program/steps/settings/folders.inc b/program/steps/settings/folders.inc
index 3231ed644..12e449e80 100644
--- a/program/steps/settings/folders.inc
+++ b/program/steps/settings/folders.inc
@@ -299,40 +299,44 @@ function rcube_subscription_form($attrib)
$disabled = (($protected && $subscribed) || $noselect);
- // check if the folder is a namespace prefix, then disable subscription option on it
- if (!$disabled && $folder['virtual'] && $folder['level'] == 0 && !empty($namespace)) {
- $fname = $folder['id'] . $delimiter;
- foreach ($namespace as $ns) {
- if (is_array($ns)) {
- foreach ($ns as $item) {
- if ($item[0] === $fname) {
- $disabled = true;
- break 2;
+ // Below we will disable subscription option for "virtual" folders
+ // according to namespaces, but only if they aren't already subscribed.
+ // User should be able to unsubscribe from the folder
+ // even if it doesn't exists or is not accessible (OTRS:1000059)
+ if (!$subscribed && !$disabled && !empty($namespace) && $folder['virtual']) {
+ // check if the folder is a namespace prefix, then disable subscription option on it
+ if (!$disabled && $folder['level'] == 0) {
+ $fname = $folder['id'] . $delimiter;
+ foreach ($namespace as $ns) {
+ if (is_array($ns)) {
+ foreach ($ns as $item) {
+ if ($item[0] === $fname) {
+ $disabled = true;
+ break 2;
+ }
}
}
}
}
- }
- // check if the folder is an other users virtual-root folder, then disable subscription option on it
- if (!$disabled && $folder['virtual'] && $folder['level'] == 1
- && !empty($namespace) && !empty($namespace['other'])
- ) {
- $parts = explode($delimiter, $folder['id']);
- $fname = $parts[0] . $delimiter;
- foreach ($namespace['other'] as $item) {
- if ($item[0] === $fname) {
- $disabled = true;
- break;
+ // check if the folder is an other users virtual-root folder, then disable subscription option on it
+ if (!$disabled && $folder['level'] == 1 && !empty($namespace['other'])) {
+ $parts = explode($delimiter, $folder['id']);
+ $fname = $parts[0] . $delimiter;
+ foreach ($namespace['other'] as $item) {
+ if ($item[0] === $fname) {
+ $disabled = true;
+ break;
+ }
}
}
- }
- // check if the folder is shared, then disable subscription option on it (if not subscribed already)
- if (!$disabled && !$subscribed && $folder['virtual'] && !empty($namespace)) {
- $tmp_ns = array_merge((array)$namespace['other'], (array)$namespace['shared']);
- foreach ($tmp_ns as $item) {
- if (strpos($folder['id'], $item[0]) === 0) {
- $disabled = true;
- break;
+ // check if the folder is shared, then disable subscription option on it (if not subscribed already)
+ if (!$disabled) {
+ $tmp_ns = array_merge((array)$namespace['other'], (array)$namespace['shared']);
+ foreach ($tmp_ns as $item) {
+ if (strpos($folder['id'], $item[0]) === 0) {
+ $disabled = true;
+ break;
+ }
}
}
}
diff --git a/skins/larry/ie7hacks.css b/skins/larry/ie7hacks.css
index 935a504fe..893ffdfef 100644
--- a/skins/larry/ie7hacks.css
+++ b/skins/larry/ie7hacks.css
@@ -29,7 +29,7 @@ a.deletebutton,
.boxfooter .listbutton .inner,
.attachmentslist li a.delete,
.attachmentslist li a.cancelupload,
-#messageheader .iconlink {
+.previewheader .iconlink {
/* workaround for text-indent which also offsets the background image */
text-indent: 0;
font-size: 0;
@@ -45,7 +45,7 @@ a.deletebutton,
.pagenav a.button,
.pagenav a.button span.inner,
-#messageheader .iconlink,
+.previewheader .iconlink,
#uploadform a.iconlink {
display: inline;
}
@@ -58,6 +58,10 @@ a.deletebutton,
right: -2px;
}
+#login-form .box-inner form {
+ margin: 0;
+}
+
#login-form #message div {
float: left;
display: block;
@@ -67,7 +71,7 @@ a.deletebutton,
text-align: left;
}
-#messageheader .iconlink {
+#messageheader.previewheader .iconlink {
color: #fff;
height: 14px;
}
diff --git a/skins/larry/iehacks.css b/skins/larry/iehacks.css
index bba93dc33..93f483c11 100644
--- a/skins/larry/iehacks.css
+++ b/skins/larry/iehacks.css
@@ -143,8 +143,8 @@ ul.toolbarmenu li a.active:hover,
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#005d76', endColorstr='#004558', GradientType=0);
}
-#partheader, #composeheaders {
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e9e9e9', GradientType=0);
+#messageheader, #partheader, #composeheaders {
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f0f0f0', GradientType=0);
}
#previewheaderstoggle {
diff --git a/skins/larry/images/contactpic_32px.png b/skins/larry/images/contactpic_32px.png
index 25a81418d..233bb1496 100644
--- a/skins/larry/images/contactpic_32px.png
+++ b/skins/larry/images/contactpic_32px.png
Binary files differ
diff --git a/skins/larry/images/contactpic_48px.png b/skins/larry/images/contactpic_48px.png
index 9cd3bceaf..e536ddf0e 100644
--- a/skins/larry/images/contactpic_48px.png
+++ b/skins/larry/images/contactpic_48px.png
Binary files differ
diff --git a/skins/larry/mail.css b/skins/larry/mail.css
index 04f56e134..a2756638d 100644
--- a/skins/larry/mail.css
+++ b/skins/larry/mail.css
@@ -38,6 +38,10 @@
bottom: 28px;
}
+#mailview-top.fullheight {
+ border-radius: 4px 4px 0 0;
+}
+
#mailview-bottom {
position: absolute;
left: 0;
@@ -46,10 +50,6 @@
height: 26px;
}
-#mailview-top.fullheight {
- border-radius: 4px 4px 0 0;
-}
-
#folderlist-header {
width: 100%;
height: 12px;
@@ -675,24 +675,33 @@ a.iconbutton.threadmode.selected {
#messagecontent {
position: absolute;
- top: 0;
+ top: 110px;
left: 0;
width: 100%;
- bottom: 28px;
+ bottom: 27px;
overflow: auto;
- border-radius: 4px 4px 0 0;
}
+#messageheader,
#partheader,
#composeheaders {
position: relative;
padding: 3px 0;
background: #f9f9f9;
- background: -moz-linear-gradient(top, #fff 0%, #e9e9e9 100%);
- background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fff), color-stop(100%,#e9e9e9));
- background: -o-linear-gradient(top, #fff 0%, #e9e9e9 100%);
- background: -ms-linear-gradient(top, #fff 0%, #e9e9e9 100%);
- background: linear-gradient(top, #fff 0%, #e9e9e9 100%);
+ 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: -o-linear-gradient(top, #fff 0%, #f0f0f0 100%);
+ background: -ms-linear-gradient(top, #fff 0%, #f0f0f0 100%);
+ background: linear-gradient(top, #fff 0%, #f0f0f0 100%);
+ border-bottom: 1px solid #dfdfdf;
+}
+
+#mailview-right #messageheader {
+ border-radius: 4px 4px 0 0;
+ padding-left: 78px;
+ /* avoid headers eating up all the vertical space */
+ max-height: 50%;
+ overflow: auto;
}
h2.subject {
@@ -704,9 +713,13 @@ h2.subject {
text-overflow: ellipsis;
}
+#mailview-right #messageheader h2.subject {
+ margin-left: -56px;
+}
+
h3.subject {
font-size: 14px;
- margin: 0 13em 0 0;
+ margin: 0 8em 0 0;
padding: 8px 8px 4px 8px;
white-space: nowrap;
overflow: hidden;
@@ -718,16 +731,23 @@ h3.subject {
padding: 2px 8px;
}
-.headers-table td.header {
+.headers-table td.header,
+.ui-dialog-content.popup span.adr {
font-weight: bold;
}
-.headers-table td.header a {
+.headers-table td.header-title {
+ white-space: nowrap;
+}
+
+.headers-table td.header a,
+.ui-dialog-content.popup span.adr a {
color: #666;
text-decoration: none;
}
-.headers-table td.header a:hover {
+.headers-table td.header a:hover,
+.ui-dialog-content.popup span.adr a:hover {
text-decoration: underline;
}
@@ -737,8 +757,15 @@ h3.subject {
font-weight: bold;
}
-.headers-table td.header span {
+.headers-table td.header span,
+.ui-dialog-content.popup span.adr {
+ white-space: nowrap;
+}
+
+.headers-table td.header a.morelink {
+ color: #0069a6;
white-space: nowrap;
+ font-weight: normal;
}
.rcmaddcontact {
@@ -796,29 +823,40 @@ h3.subject {
#previewheaderstoggle.remove .iconlink {
top: auto;
- bottom: 15px;
+ bottom: 5px;
background-position: -5px -242px;
}
-#previewheaderstoggle .iconlink.allheaders {
- display: none;
+#full-headers {
+ position: relative;
}
-#previewheaderstoggle.remove .iconlink.allheaders {
- top: auto;
- bottom: 2px;
- display: inline-block;
- background-position: -27px -242px;
+div.more-headers {
+ position: absolute;
+ top: -12px;
+ right: 10px;
+ width: 12px;
+ height: 10px;
+ cursor: pointer;
+ background: url(images/buttons.png) center -1619px no-repeat;
+}
+
+div.hide-headers {
+ background-position: center -1629px;
}
#all-headers {
position: relative;
- margin: 2px 0;
+ margin: 4px 10px;
padding: 0;
height: 180px;
- background-color: #f0f0f0;
- overflow: hidden;
+ border: 1px solid #ccc;
border-radius: 4px;
+ background: #fdfdfd;
+ -moz-box-shadow: inset 0 0 1px 1px rgba(0,0,0, 0.1);
+ -webkit-box-shadow: inset 0 0 1px 1px rgba(0,0,0, 0.1);
+ -o-box-shadow: inset 0 0 1px 1px rgba(0,0,0, 0.1);
+ box-shadow: inset 0 0 1px 1px rgba(0,0,0, 0.1);
}
#headers-source {
@@ -828,31 +866,28 @@ h3.subject {
left: 0;
right: 0;
bottom: 0;
- padding: 2px;
+ padding: 3px 6px;
overflow: auto;
text-align: left;
- color: #666;
+ color: #333;
+}
+
+#messageheader.previewheader #all-headers {
+ margin-left: 0;
}
-#messageheader {
+#messageheader.previewheader {
position: relative;
height: auto;
min-height: 52px;
- margin: 0 8px 0 0;
- padding: 0 0 0 72px;
- border-bottom: 2px solid #f0f0f0;
-}
-
-#messagecontent #messageheader {
- padding: 0 0 0 90px;
- min-height: 68px;
+ padding: 0 0 3px 72px;
}
-#messageheader h3.subject {
+#messageheader.previewheader h3.subject {
padding: 8px 8px 2px 0;
}
-#messageheader #contactphoto {
+#messageheader.previewheader #contactphoto {
display: block;
position: absolute;
top: 11px;
@@ -864,22 +899,26 @@ h3.subject {
border-radius: 3px;
}
-#messageheader #contactphoto img {
+#messageheader.previewheader #contactphoto img {
width: 32px;
height: auto;
border-radius: 3px;
}
-#messagecontent #messageheader #contactphoto {
- top: 11px;
- left: 31px;
+#messageheader #contactphoto {
+ display: block;
+ position: absolute;
+ top: 34px;
+ left: 30px;
width: 48px;
height: 48px;
- background: url(images/contactpic_48px.png) center center no-repeat #fff;
+ overflow: hidden;
border-radius: 4px;
+ border: 1px solid #e6e6e6;
+ background: url(images/contactpic_48px.png) center center no-repeat #fff;
}
-#messagecontent #messageheader #contactphoto img {
+#messageheader #contactphoto img {
width: 48px;
height: auto;
border-radius: 4px;
@@ -888,16 +927,25 @@ h3.subject {
#messageheader #countcontrols {
position: absolute;
top: 8px;
- right: 0;
+ right: 8px;
+ width: 20em;
text-align: right;
white-space: nowrap;
}
+#messageheader .pagenav .countdisplay {
+ min-width: 0;
+ padding-right: 0.5em;
+ white-space: nowrap;
+}
+
+#messagecontent .leftcol,
#messagepreview .leftcol {
margin-right: 252px;
overflow-x: auto;
}
+#messagecontent .rightcol,
#messagepreview .rightcol {
float: right;
/*
@@ -1110,6 +1158,7 @@ div.message-part blockquote blockquote blockquote {
-webkit-box-shadow: 0 2px 3px 0 #999;
-moz-box-shadow: 0 2px 3px 0 #999;
box-shadow: 0 2px 3px 0 #999;
+ border-bottom: 0;
}
#composebuttons {
@@ -1168,6 +1217,8 @@ div.message-part blockquote blockquote blockquote {
.compose-headers td input {
width: 100%;
resize: none;
+ font-family: "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
+ font-size: 11px;
}
#compose-cc, #compose-bcc, #compose-replyto, #compose-followupto {
diff --git a/skins/larry/svggradients.css b/skins/larry/svggradients.css
index 4f1dd8a05..5b3fedbfc 100644
--- a/skins/larry/svggradients.css
+++ b/skins/larry/svggradients.css
@@ -133,8 +133,8 @@ ul.toolbarmenu li a.active:hover,
background-image: url(svggradient.php?c=005d76;004558);
}
-#partheader, #composeheaders {
- background-image: url(svggradient.php?c=ffffff;e9e9e9);
+#messageheader, #partheader, #composeheaders {
+ background-image: url(svggradient.php?c=ffffff;f0f0f0);
}
#previewheaderstoggle {
diff --git a/skins/larry/templates/message.html b/skins/larry/templates/message.html
index 89b7bd808..e99f2066a 100644
--- a/skins/larry/templates/message.html
+++ b/skins/larry/templates/message.html
@@ -24,38 +24,21 @@
<!-- folders list -->
<div id="mailboxcontainer" class="uibox listbox">
- <div class="scroller">
- <roundcube:object name="mailboxlist" id="mailboxlist" class="listing" folder_filter="mail" unreadwrap="%s" />
- </div>
+<div class="scroller">
+<roundcube:object name="mailboxlist" id="mailboxlist" class="listing" folder_filter="mail" unreadwrap="%s" />
+</div>
</div>
-</div><!-- end mailview-left -->
-
-<div id="mailview-right" class="uibox" style="top: 42px">
+</div>
-<div id="messagecontent">
+<div id="mailview-right" class="offset uibox">
<div id="messageheader">
-<h3 class="subject"><roundcube:object name="messageHeaders" valueOf="subject" /></h3>
-
-<a href="#details" id="previewheaderstoggle"><span class="iconlink"></span><span id="headerstoggleall" class="iconlink allheaders"></span></a>
-
-<div id="contactphoto"><roundcube:object name="contactphoto" /></div>
+<span id="previewheaderstoggle"></span>
-<table class="headers-table" id="preview-shortheaders"><tbody><tr>
-<roundcube:if condition="env:mailbox == config:drafts_mbox || env:mailbox == config:sent_mbox">
- <td class="header-title"><roundcube:label name="to" /></td>
- <td class="header from"><roundcube:object name="messageHeaders" valueOf="to" addicon="/images/addcontact.png" /></td>
-<roundcube:else />
- <td class="header-title"><roundcube:label name="from" /></td>
- <td class="header from"><roundcube:object name="messageHeaders" valueOf="from" addicon="/images/addcontact.png" /></td>
-<roundcube:endif />
- <td class="header-title"><roundcube:label name="date" /></td>
- <td class="header from"><roundcube:object name="messageHeaders" valueOf="date" /></td>
-</tr></tbody></table>
-
-<roundcube:object name="messageHeaders" id="preview-allheaders" class="headers-table" addicon="/images/addcontact.png" exclude="subject,replyto" />
-<roundcube:object name="messageFullHeaders" no-switch="true" />
+<h2 class="subject"><roundcube:object name="messageHeaders" valueOf="subject" /></h2>
+<roundcube:object name="messageHeaders" class="headers-table" addicon="/images/addcontact.png" exclude="subject" max="20" />
+<roundcube:object name="messageFullHeaders" id="full-headers" />
<!-- record navigation -->
<div id="countcontrols" class="pagenav">
@@ -64,19 +47,18 @@
<roundcube:button command="nextmessage" type="link" class="button nextpage disabled" classAct="button nextpage" classSel="button nextpage pressed" innerClass="inner" title="nextmessage" content="&amp;gt;" />
</div>
-</div><!-- end messageheader -->
-
-<div id="messagepreview">
- <div class="rightcol">
- <roundcube:object name="messageAttachments" id="attachment-list" class="attachmentslist" />
- </div>
- <div class="leftcol">
- <roundcube:object name="messageObjects" id="message-objects" />
- <roundcube:object name="messageBody" id="messagebody" />
- </div>
+<div id="contactphoto"><roundcube:object name="contactphoto" /></div>
</div>
-</div><!-- end messagecontent -->
+<div id="messagecontent">
+<div class="rightcol">
+<roundcube:object name="messageAttachments" id="attachment-list" class="attachmentslist" />
+</div>
+<div class="leftcol">
+<roundcube:object name="messageObjects" id="message-objects" />
+<roundcube:object name="messageBody" id="messagebody" />
+</div>
+</div>
<roundcube:object name="message" id="message" class="statusbar" />
diff --git a/skins/larry/templates/messageerror.html b/skins/larry/templates/messageerror.html
index 2f5243200..3c3c9acdb 100644
--- a/skins/larry/templates/messageerror.html
+++ b/skins/larry/templates/messageerror.html
@@ -16,6 +16,13 @@
<div id="mainscreen">
+<!-- toolbar -->
+<div id="messagetoolbar" class="fullwidth">
+ <div id="mailtoolbar" class="toolbar">
+ <roundcube:button command="list" type="link" class="button back disabled" classAct="button back" classSel="button back pressed" label="back" />
+ </div>
+</div>
+
<div id="mailview-left">
<!-- folders list -->
@@ -27,14 +34,7 @@
</div>
-<!-- toolbar -->
-<div id="messagetoolbar" class="fullwidth">
- <div id="mailtoolbar" class="toolbar">
- <roundcube:button command="list" type="link" class="button back disabled" classAct="button back" classSel="button back pressed" label="back" />
- </div>
-</div>
-
-<div id="mailview-right" class="uibox" style="top: 42px">
+<div id="mailview-right" class="offset uibox">
<div id="messagecontent" class="watermark"></div>
diff --git a/skins/larry/templates/messagepreview.html b/skins/larry/templates/messagepreview.html
index 74c414b0d..de02b050b 100644
--- a/skins/larry/templates/messagepreview.html
+++ b/skins/larry/templates/messagepreview.html
@@ -6,26 +6,27 @@
</head>
<body class="iframe fullheight">
-<div id="messageheader">
+<div id="messageheader" class="previewheader">
<h3 class="subject"><roundcube:object name="messageHeaders" valueOf="subject" /></h3>
-<a href="#details" id="previewheaderstoggle"><span class="iconlink"></span><span id="headerstoggleall" class="iconlink allheaders"></a>
+<a href="#details" id="previewheaderstoggle"><span class="iconlink" title="<roundcube:label name='togglemoreheaders' />"></span></a>
<div id="contactphoto"><roundcube:object name="contactphoto" /></div>
<table class="headers-table" id="preview-shortheaders"><tbody><tr>
<roundcube:if condition="env:mailbox == config:drafts_mbox || env:mailbox == config:sent_mbox">
<td class="header-title"><roundcube:label name="to" /></td>
- <td class="header from"><roundcube:object name="messageHeaders" valueOf="to" addicon="/images/addcontact.png" /></td>
+ <td class="header from"><roundcube:object name="messageHeaders" valueOf="to" max="3" addicon="/images/addcontact.png" /></td>
<roundcube:else />
<td class="header-title"><roundcube:label name="from" /></td>
<td class="header from"><roundcube:object name="messageHeaders" valueOf="from" addicon="/images/addcontact.png" /></td>
<roundcube:endif />
<td class="header-title"><roundcube:label name="date" /></td>
- <td class="header from"><roundcube:object name="messageHeaders" valueOf="date" /></td>
+ <td class="header date"><span><roundcube:object name="messageHeaders" valueOf="date" /></span></td>
</tr></tbody></table>
-<roundcube:object name="messageHeaders" id="preview-allheaders" class="headers-table" addicon="/images/addcontact.png" exclude="subject,replyto" />
-<roundcube:object name="messageFullHeaders" no-switch="true" />
+<roundcube:object name="messageHeaders" id="preview-allheaders" class="headers-table" addicon="/images/addcontact.png" max="10" exclude="subject,replyto" />
+
+<roundcube:object name="messageFullHeaders" id="full-headers" />
<!-- record navigation -->
<div id="countcontrols" class="pagenav">
diff --git a/skins/larry/ui.js b/skins/larry/ui.js
index c221b8681..9b5d8309c 100644
--- a/skins/larry/ui.js
+++ b/skins/larry/ui.js
@@ -73,9 +73,9 @@ function rcube_mail_ui()
}
if (rcmail.env.action == 'show' || rcmail.env.action == 'preview') {
- layout_messageview();
- $('#previewheaderstoggle').click(function(e){ toggle_preview_headers(this); return false; });
- $('#headerstoggleall').click(function(e){ toggle_all_headers(this); return false; });
+ rcmail.addEventListener('aftershow-headers', function() { layout_messageview(); });
+ rcmail.addEventListener('afterhide-headers', function() { layout_messageview(); });
+ $('#previewheaderstoggle').click(function(e){ toggle_preview_headers(this); return false });
}
else if (rcmail.env.action == 'compose') {
rcmail.addEventListener('aftertoggle-editor', function(){ window.setTimeout(function(){ layout_composeview() }, 200); });
@@ -320,6 +320,7 @@ function rcube_mail_ui()
*/
function layout_messageview()
{
+ $('#messagecontent').css('top', ($('#messageheader').outerHeight() + 1) + 'px');
$('#message-objects div a').addClass('button');
if (!$('#attachment-list li').length) {
@@ -512,31 +513,13 @@ function rcube_mail_ui()
{
$('#preview-shortheaders').toggle();
var full = $('#preview-allheaders').toggle(),
- button = $('#previewheaderstoggle');
-
- if (!$('#headerstoggleall').length)
- $('#all-headers').toggle();
+ button = $('a#previewheaderstoggle');
// add toggle button to full headers table
- if (full.is(':visible')) {
- button.attr('href', '#hide').removeClass('add').addClass('remove');
- }
- else {
- button.attr('href', '#details').removeClass('remove').addClass('add');
- }
- }
-
-
- /**
- * Show/hide all message headers
- */
- function toggle_all_headers(button)
- {
- rcmail.command('show-headers', '', button);
- $(button).remove();
- $('#previewheaderstoggle span').css({bottom: '5px'});
-
- return false;
+ if (full.is(':visible'))
+ button.attr('href', '#hide').removeClass('add').addClass('remove')
+ else
+ button.attr('href', '#details').removeClass('remove').addClass('add')
}