Skip to content

Commit

Permalink
Add possibility to preview and download attachments in mail compose (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
alecpl committed Jul 28, 2016
1 parent dcf877c commit 8a13615
Show file tree
Hide file tree
Showing 14 changed files with 706 additions and 459 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================

- Add possibility to preview and download attachments in mail compose (#5053)
- Remove backward compatibility "layer" of bc.php (#4902)
- Support WEBP images in mail messages (#5362)
- Support MathML in HTML message preview (#5182)
Expand Down
7 changes: 6 additions & 1 deletion program/include/rcmail.php
Original file line number Diff line number Diff line change
Expand Up @@ -2247,11 +2247,16 @@ public function message_part_size($part)
}
else {
$size = $part->size;

if ($part->encoding == 'base64') {
$size = $size / 1.33;
}

$size = '~' . $this->show_bytes($size);
$size = $this->show_bytes($size);
}

if (!$this->exact_size) {
$size = '~' . $size;
}

return $size;
Expand Down
30 changes: 24 additions & 6 deletions program/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,8 @@ function rcube_webmail()
this.env.address_group_stack = [];
this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'cancel',
'toggle-editor', 'list-addresses', 'pushgroup', 'search', 'reset-search', 'extwin',
'insert-response', 'save-response', 'menu-open', 'menu-close'];
'insert-response', 'save-response', 'menu-open', 'menu-close', 'load-attachment',
'download-attachment', 'open-attachment'];

if (this.env.drafts_mailbox)
this.env.compose_commands.push('savedraft')
Expand Down Expand Up @@ -777,6 +778,8 @@ function rcube_webmail()
case 'menu-open':
if (props && props.menu == 'attachmentmenu') {
var mimetype = this.env.attachments[props.id];
if (mimetype && mimetype.mimetype) // in compose format is different
mimetype = mimetype.mimetype;
this.enable_command('open-attachment', mimetype && this.env.mimetypes && $.inArray(mimetype, this.env.mimetypes) >= 0);
}
this.show_menu(props, props.show || undefined, event);
Expand Down Expand Up @@ -1018,16 +1021,29 @@ function rcube_webmail()
case 'load-attachment':
case 'open-attachment':
case 'download-attachment':
var qstring = '_mbox='+urlencode(this.env.mailbox)+'&_uid='+this.env.uid+'&_part='+props,
mimetype = this.env.attachments[props];
var params, mimetype = this.env.attachments[props];

if (this.env.action == 'compose') {
params = {_file: props, _id: this.env.compose_id};
mimetype = mimetype ? mimetype.mimetype : '';
}
else {
params = {_mbox: this.env.mailbox, _uid: this.env.uid, _part: props};
}

// open attachment in frame if it's of a supported mimetype
if (command != 'download-attachment' && mimetype && this.env.mimetypes && $.inArray(mimetype, this.env.mimetypes) >= 0) {
if (this.open_window(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1'))
if (this.open_window(this.url('get', $.extend({_frame: 1}, params))))
break;
}

this.goto_url('get', qstring+'&_download=1', false, true);
params._download = 1;

// prevent from page unload warning in compose
this.compose_skip_unsavedcheck = 1;
this.goto_url('get', params, false, true);
this.compose_skip_unsavedcheck = 0;

break;

case 'select-all':
Expand Down Expand Up @@ -4864,6 +4880,8 @@ function rcube_webmail()
var tabindex = $(this.gui_objects.attachmentlist).attr('data-tabindex') || '0';
li.find('a').attr('tabindex', tabindex);

this.triggerEvent('fileappended', {name: name, attachment: att, id: upload_id, item: li});

return true;
};

Expand All @@ -4880,7 +4898,7 @@ function rcube_webmail()
if (name && this.env.attachments[name])
this.http_post('remove-attachment', { _id:this.env.compose_id, _file:name });

return true;
return false;
};

this.cancel_attachment_upload = function(name, frame_name)
Expand Down
15 changes: 11 additions & 4 deletions program/steps/mail/attachments.inc
Original file line number Diff line number Diff line change
Expand Up @@ -195,16 +195,23 @@ function rcmail_attachment_success($attachment, $uploadid)
$button = '';
}

$content = html::a(array(
$link_content = sprintf('%s <span class="attachment-size">(%s)</span>',
rcube::Q($attachment['name']), $RCMAIL->show_bytes($attachment['size']));

$content_link = html::a(array(
'href' => "#load",
'onclick' => sprintf("return %s.command('load-attachment','rcmfile%s', this, event)", rcmail_output::JS_OBJECT_NAME, $id),
), $link_content);

$delete_link = html::a(array(
'href' => "#delete",
'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", rcmail_output::JS_OBJECT_NAME, $id),
'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this, event)", rcmail_output::JS_OBJECT_NAME, $id),
'title' => $RCMAIL->gettext('delete'),
'class' => 'delete',
'aria-label' => $RCMAIL->gettext('delete') . ' ' . $attachment['name'],
), $button);

$content .= sprintf('%s <span class="attachment-size">(%s)</span>',
rcube::Q($attachment['name']), $RCMAIL->show_bytes($attachment['size']));
$content = $COMPOSE['icon_pos'] == 'left' ? $delete_link.$content_link : $content_link.$delete_link;

$RCMAIL->output->command('add2attachment_list', "rcmfile$id", array(
'html' => $content,
Expand Down
31 changes: 20 additions & 11 deletions program/steps/mail/compose.inc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ $OUTPUT->set_env('sig_below', $RCMAIL->config->get('sig_below'));
$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ',')));
$OUTPUT->set_env('save_localstorage', (bool)$RCMAIL->config->get('compose_save_localstorage'));
$OUTPUT->set_env('is_sent', false);
$OUTPUT->set_env('mimetypes', rcmail_supported_mimetypes());

$drafts_mbox = $RCMAIL->config->get('drafts_mbox');
$config_show_sig = $RCMAIL->config->get('show_sig', 1);
Expand Down Expand Up @@ -1549,6 +1550,9 @@ function rcmail_compose_attachment_list($attrib)
$jslist = array();
$button = '';

if ($attrib['icon_pos'] == 'left')
$COMPOSE['icon_pos'] = 'left';

if (is_array($COMPOSE['attachments'])) {
if ($attrib['deleteicon']) {
$button = html::img(array(
Expand All @@ -1565,24 +1569,29 @@ function rcmail_compose_attachment_list($attrib)
continue;
}

$content = sprintf('%s <span class="attachment-size">(%s)</span>',
$link_content = sprintf('%s <span class="attachment-size">(%s)</span>',
rcube::Q($a_prop['name']), $RCMAIL->show_bytes($a_prop['size']));

$content_link = html::a(array(
'href' => "#load",
'onclick' => sprintf("return %s.command('load-attachment','rcmfile%s', this, event)", rcmail_output::JS_OBJECT_NAME, $id),
), $link_content);

$delete_link = html::a(array(
'href' => "#delete",
'title' => $RCMAIL->gettext('delete'),
'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this, event)", rcmail_output::JS_OBJECT_NAME, $id),
'class' => 'delete',
'tabindex' => $attrib['tabindex'] ?: '0',
'aria-label' => $RCMAIL->gettext('delete') . ' ' . $a_prop['name'],
), $button);

$out .= html::tag('li', array(
'id' => 'rcmfile'.$id,
'class' => rcube_utils::file2class($a_prop['mimetype'], $a_prop['name']),
'onmouseover' => "rcube_webmail.long_subject_title_ex(this, 0)",
),
html::a(array(
'href' => "#delete",
'title' => $RCMAIL->gettext('delete'),
'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", rcmail_output::JS_OBJECT_NAME, $id),
'class' => 'delete',
'tabindex' => $attrib['tabindex'] ?: '0',
'aria-label' => $RCMAIL->gettext('delete') . ' ' . $a_prop['name'],
),
$button
) . $content
$COMPOSE['icon_pos'] == 'left' ? $delete_link.$content_link : $content_link.$delete_link
);

$jslist['rcmfile'.$id] = array(
Expand Down
41 changes: 39 additions & 2 deletions program/steps/mail/func.inc
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ function rcmail_get_unseen_count($mbox_name)
*
* @param object rcube_message Message
*/
function rcmail_check_safe(&$message)
function rcmail_check_safe($message)
{
global $RCMAIL;

Expand Down Expand Up @@ -797,6 +797,8 @@ function rcmail_check_safe(&$message)
break;
}
}

return !empty($message->is_safe);
}

/**
Expand All @@ -807,7 +809,7 @@ function rcmail_check_safe(&$message)
* @param array CID map replaces (inline images)
* @return string Clean HTML
*/
function rcmail_wash_html($html, $p, $cid_replaces)
function rcmail_wash_html($html, $p, $cid_replaces = array())
{
global $REMOTE_OBJECTS;

Expand Down Expand Up @@ -2312,3 +2314,38 @@ function rcmail_save_attachment($message, $pid, $compose_id, $params = array())

return false;
}

// Return mimetypes supported by the browser
function rcmail_supported_mimetypes()
{
$rcmail = rcube::get_instance();

// mimetypes supported by the browser (default settings)
$mimetypes = (array) $rcmail->config->get('client_mimetypes');

// Remove unsupported types, which makes that attachment which cannot be
// displayed in a browser will be downloaded directly without displaying an overlay page
if (empty($_SESSION['browser_caps']['pdf']) && ($key = array_search('application/pdf', $mimetypes)) !== false) {
unset($mimetypes[$key]);
}

if (empty($_SESSION['browser_caps']['flash']) && ($key = array_search('application/x-shockwave-flash', $mimetypes)) !== false) {
unset($mimetypes[$key]);
}

foreach (array('tiff', 'webp') as $type) {
if (empty($_SESSION['browser_caps'][$type]) && ($key = array_search('image/' . $type, $mimetypes)) !== false) {
// can we convert it to jpeg?
if (!rcube_image::is_convertable('image/' . $type)) {
unset($mimetypes[$key]);
}
}
}

// @TODO: support mail preview for compose attachments
if ($rcmail->action != 'compose' && !in_array('message/rfc822', $mimetypes)) {
$mimetypes[] = 'message/rfc822';
}

return array_values($mimetypes);
}
Loading

0 comments on commit 8a13615

Please sign in to comment.