Aleksander Machniak
2016-03-24 ce3105c58f921f33654c738fa7460d3d107813ce
Reply/Reply-All/Forward/Change-format buttons for message/rfc822 preview
10 files modified
198 ■■■■ changed files
program/js/app.js 8 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_message.php 64 ●●●● patch | view | raw | blame | history
program/steps/mail/compose.inc 12 ●●●● patch | view | raw | blame | history
program/steps/mail/sendmail.inc 26 ●●●● patch | view | raw | blame | history
program/steps/mail/show.inc 2 ●●● patch | view | raw | blame | history
skins/classic/addressbook.css 8 ●●●● patch | view | raw | blame | history
skins/classic/common.css 12 ●●●●● patch | view | raw | blame | history
skins/classic/templates/addressbook.html 2 ●●● patch | view | raw | blame | history
skins/classic/templates/messagepart.html 32 ●●●●● patch | view | raw | blame | history
skins/larry/templates/messagepart.html 32 ●●●●● patch | view | raw | blame | history
program/js/app.js
@@ -339,8 +339,14 @@
          // init message compose form
          this.init_messageform();
        }
        else if (this.env.action == 'get')
        else if (this.env.action == 'get') {
          this.enable_command('download', 'print', true);
          if (this.env.mimetype == 'message/rfc822') {
            this.enable_command('reply', 'reply-all', 'forward', 'forward-inline', 'forward-attachment', true);
            if (this.env.list_post)
              this.enable_command('reply-list', true);
          }
        }
        // show printing dialog
        else if (this.env.action == 'print' && this.env.uid
          && !this.env.is_pgp_content && !this.env.pgp_mime_part
program/lib/Roundcube/rcube_message.php
@@ -339,13 +339,17 @@
    {
        // check all message parts
        foreach ($this->mime_parts as $part) {
            if (!$this->check_context($part)) {
                continue;
            }
            if ($part->mimetype == 'text/html' || ($enriched && $part->mimetype == 'text/enriched')) {
                // Skip if part is an attachment, don't use is_attachment() here
                if ($part->filename) {
                    continue;
                }
                if (!$part->size) {
                    continue;
                }
                if (!$this->check_context($part)) {
                    continue;
                }
@@ -361,19 +365,22 @@
                        return true;
                    }
                    $parent    = $this->mime_parts[join('.', $level)];
                    $max_delta = $depth - (1 + ($last == 'multipart/alternative' ? 1 : 0));
                    $last      = $parent->mimetype;
                    $parent = $this->mime_parts[join('.', $level)];
                    if (!preg_match('/^multipart\/(alternative|related|signed|encrypted|mixed)$/', $parent->mimetype)
                        || ($parent->mimetype == 'multipart/mixed' && $parent_depth < $max_delta)) {
                    if (!$this->check_context($parent)) {
                        return true;
                    }
                    $max_delta = $depth - (1 + ($last == 'multipart/alternative' ? 1 : 0));
                    $last      = $parent->real_mimetype ?: $parent->mimetype;
                    if (!preg_match('/^multipart\/(alternative|related|signed|encrypted|mixed)$/', $last)
                        || ($last == 'multipart/mixed' && $parent_depth < $max_delta)) {
                        continue 2;
                    }
                }
                if ($part->size) {
                    return true;
                }
                return true;
            }
        }
@@ -400,6 +407,10 @@
                    continue;
                }
                if (!$part->size) {
                    continue;
                }
                if (!$this->check_context($part)) {
                    continue;
                }
@@ -413,14 +424,17 @@
                    }
                    $parent = $this->mime_parts[join('.', $level)];
                    if (!$this->check_context($parent)) {
                        return true;
                    }
                    if ($parent->mimetype != 'multipart/alternative' && $parent->mimetype != 'multipart/related') {
                        continue 2;
                    }
                }
                if ($part->size) {
                    return true;
                }
                return true;
            }
        }
@@ -479,6 +493,26 @@
    }
    /**
     * Return message parts in current context
     */
    public function mime_parts()
    {
        if ($this->context === null) {
            return $this->mime_parts;
        }
        $parts = array();
        foreach ($this->mime_parts as $part_id => $part) {
            if ($this->check_context($part)) {
                $parts[$part_id] = $part;
            }
        }
        return $parts;
    }
    /**
     * Checks if part of the message is an attachment (or part of it)
     *
     * @param rcube_message_part $part Message part
program/steps/mail/compose.inc
@@ -5,7 +5,7 @@
 | program/steps/mail/compose.inc                                        |
 |                                                                       |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2005-2013, The Roundcube Dev Team                       |
 | Copyright (C) 2005-2016, The Roundcube Dev Team                       |
 |                                                                       |
 | Licensed under the GNU General Public License version 3 or            |
 | any later version with exceptions for skins & plugins.                |
@@ -179,7 +179,7 @@
    $MESSAGE = new rcube_message($msg_uid);
    // make sure message is marked as read
    if ($MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN'])) {
    if ($MESSAGE->headers && $MESSAGE->context === null && empty($MESSAGE->headers->flags['SEEN'])) {
        $RCMAIL->storage->set_flag($msg_uid, 'SEEN');
    }
@@ -192,7 +192,7 @@
    }
    else if ($compose_mode == RCUBE_COMPOSE_FORWARD || $compose_mode == RCUBE_COMPOSE_REPLY) {
        if ($compose_mode == RCUBE_COMPOSE_REPLY) {
            $COMPOSE['reply_uid'] = $msg_uid;
            $COMPOSE['reply_uid'] = $MESSAGE->context === null ? $msg_uid : null;
            if (!empty($COMPOSE['param']['all'])) {
                $MESSAGE->reply_all = $COMPOSE['param']['all'];
@@ -780,7 +780,7 @@
        if (!empty($MESSAGE->parts)) {
            // collect IDs of message/rfc822 parts
            foreach ($MESSAGE->mime_parts as $part) {
            foreach ($MESSAGE->mime_parts() as $part) {
                if ($part->mimetype == 'message/rfc822') {
                    $messages[] = $part->mime_id;
                }
@@ -1258,7 +1258,7 @@
        return $cid_map;
    }
    foreach ((array)$message->mime_parts as $pid => $part) {
    foreach ((array) $message->mime_parts() as $pid => $part) {
        if ($part->mimetype == 'message/rfc822') {
            $messages[] = $part->mime_id;
        }
@@ -1324,7 +1324,7 @@
        return $cid_map;
    }
    foreach ((array)$message->mime_parts as $pid => $part) {
    foreach ((array) $message->mime_parts() as $pid => $part) {
        if ($part->mimetype == 'message/rfc822') {
            $messages[] = $part->mime_id;
        }
program/steps/mail/sendmail.inc
@@ -189,11 +189,17 @@
}
// remember reply/forward UIDs in special headers
if (!empty($COMPOSE['reply_uid']) && $savedraft) {
    $headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $COMPOSE['reply_uid']);
}
else if (!empty($COMPOSE['forward_uid']) && $savedraft) {
    $headers['X-Draft-Info'] = array('type' => 'forward', 'uid' => rcube_imap_generic::compressMessageSet($COMPOSE['forward_uid']));
if ($savedraft) {
    // Note: We ignore <UID>.<PART> forwards/replies here
    if (($uid = $COMPOSE['reply_uid']) && !preg_match('/^\d+[0-9.]+$/', $uid)) {
        $headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $uid);
    }
    else if (!empty($COMPOSE['forward_uid'])
        && ($uid = rcube_imap_generic::compressMessageSet($COMPOSE['forward_uid']))
        && !preg_match('/^\d+[0-9.]+$/', $uid)
    ) {
        $headers['X-Draft-Info'] = array('type' => 'forward', 'uid' => $uid);
    }
}
if (!empty($COMPOSE['reply_msgid'])) {
@@ -550,12 +556,18 @@
    // set replied/forwarded flag
    if ($COMPOSE['reply_uid']) {
        foreach (rcmail::get_uids($COMPOSE['reply_uid'], $COMPOSE['mailbox']) as $mbox => $uids) {
            $RCMAIL->storage->set_flag($uids, 'ANSWERED', $mbox);
            // skip <UID>.<PART> replies
            if (!preg_match('/^\d+[0-9.]+$/', implode(',', (array) $uids))) {
                $RCMAIL->storage->set_flag($uids, 'ANSWERED', $mbox);
            }
        }
    }
    else if ($COMPOSE['forward_uid']) {
        foreach (rcmail::get_uids($COMPOSE['forward_uid'], $COMPOSE['mailbox']) as $mbox => $uids) {
            $RCMAIL->storage->set_flag($uids, 'FORWARDED', $mbox);
            // skip <UID>.<PART> forwards
            if (!preg_match('/^\d+[0-9.]+$/', implode(',', (array) $uids))) {
                $RCMAIL->storage->set_flag($uids, 'FORWARDED', $mbox);
            }
        }
    }
}
program/steps/mail/show.inc
@@ -71,7 +71,7 @@
    $OUTPUT->set_env('sender', $MESSAGE->sender['string']);
    $OUTPUT->set_env('mailbox', $mbox_name);
    $OUTPUT->set_env('username', $RCMAIL->get_user_name());
    $OUTPUT->set_env('permaurl', $RCMAIL->url(array('_action' => 'show', '_uid' => $MESSAGE->uid, '_mbox' => $mbox_name)));
    $OUTPUT->set_env('permaurl', $RCMAIL->url(array('_action' => 'show', '_uid' => $msg_id, '_mbox' => $mbox_name)));
    if ($MESSAGE->headers->get('list-post', false)) {
        $OUTPUT->set_env('list_post', true);
skins/classic/addressbook.css
@@ -14,8 +14,7 @@
}
#abooktoolbar a.button,
#abooktoolbar a.buttonPas,
#abooktoolbar span.separator {
#abooktoolbar a.buttonPas {
  display: block;
  float: left;
  width: 32px;
@@ -83,11 +82,6 @@
#abooktoolbar a.exportAllSel {
  background-position: -128px -32px;
}
#abooktoolbar span.separator {
  width: 5px;
  background-position: -162px 0;
}
#abooktoolbar a.search {
skins/classic/common.css
@@ -507,6 +507,18 @@
  font-size: 10px;
}
.toolbarseparator {
  display: block;
  float: left;
  width: 5px;
  height: 32px;
  padding: 0;
  margin: 0 5px;
  overflow: hidden;
  background: url(images/abook_toolbar.png) -162px 0 no-repeat transparent;
  opacity: 0.99; /* this is needed to make buttons appear correctly in Chrome */
}
.splitter
{
  user-select: none;
skins/classic/templates/addressbook.html
@@ -23,7 +23,7 @@
<roundcube:button command="compose" type="link" class="buttonPas compose" classAct="button compose" classSel="button composeSel" title="composeto" content=" " />
<roundcube:button command="print" type="link" class="buttonPas print" classAct="button print" classSel="button printSel" label="print" title="printcontact" content=" " />
<roundcube:button command="delete" type="link" class="buttonPas delete" classAct="button delete" classSel="button deleteSel" title="deletecontact" content=" " />
<span class="separator">&nbsp;</span>
<span class="toolbarseparator">&nbsp;</span>
<roundcube:button command="import" type="link" class="buttonPas import" classAct="button import" classSel="button importSel" title="importcontacts" content=" " />
<span class="dropbutton">
<roundcube:button command="export" type="link" class="buttonPas export" classAct="button export" classSel="button exportSel" title="exportvcards" content=" " />
skins/classic/templates/messagepart.html
@@ -17,6 +17,18 @@
    <roundcube:button command="download" type="link" class="button download" classAct="button download" classSel="button downloadSel" title="download" content=" " />
    <roundcube:button command="print" type="link" class="button print" classAct="button print" classSel="button printSel" title="print" content=" " />
    <roundcube:container name="toolbar" id="messagetoolbar" />
    <roundcube:if condition="env:mimetype == 'message/rfc822'" />
    <span class="toolbarseparator">&nbsp;</span>
    <roundcube:button command="reply" type="link" class="buttonPas reply" classAct="button reply" classSel="button replySel" title="replytomessage" content=" " />
    <span class="dropbutton">
        <roundcube:button command="reply-all" type="link" class="buttonPas replyAll" classAct="button replyAll" classSel="button replyAllSel" title="replytoallmessage" content=" " />
        <span id="replyallmenulink" onclick="rcmail_ui.show_popup('replyallmenu');return false"></span>
    </span>
    <span class="dropbutton">
        <roundcube:button command="forward" type="link" class="buttonPas forward" classAct="button forward" classSel="button forwardSel" title="forwardmessage" content=" " />
        <span id="forwardmenulink" onclick="rcmail_ui.show_popup('forwardmenu');return false"></span>
    </span>
    <roundcube:endif />
</div>
<div id="mainscreen">
@@ -30,9 +42,29 @@
        <roundcube:object name="messagePartFrame" id="messagepartframe" width="100%" height="100%" />
    </div>
</div>
<roundcube:if condition="env:mimetype == 'message/rfc822'" />
<div id="forwardmenu" class="popupmenu">
    <ul id="forwardmenumenu">
        <roundcube:button type="link-menuitem" command="forward-inline" label="forwardinline" prop="sub" classAct="forwardlink active" class="forwardlink" />
        <roundcube:button type="link-menuitem" command="forward-attachment" label="forwardattachment" prop="sub" classAct="forwardattachmentlink active" class="forwardattachmentlink" />
        <roundcube:container name="forwardmenu" id="forwardmenumenu" />
    </ul>
</div>
<div id="replyallmenu" class="popupmenu">
    <ul id="replyallmenumenu">
        <roundcube:button type="link-menuitem" command="reply-all" label="replyall" prop="sub" classAct="replyalllink active" class="replyalllink" />
        <roundcube:button type="link-menuitem" command="reply-list" label="replylist" prop="sub" classAct="replylistlink active" class="replylistlink" />
        <roundcube:container name="replyallmenu" id="replyallmenumenu" />
    </ul>
</div>
<roundcube:endif />
<script type="text/javascript">
var mailpartsplit = new rcube_splitter({id:'mailpartsplitter', p1: 'messagepartheader', p2: 'messagepartcontainer', orientation: 'v', relative: true, start: 165});
rcmail.add_onload('mailpartsplit.init()');
rcube_init_mail_ui();
</script>
</body>
skins/larry/templates/messagepart.html
@@ -17,6 +17,18 @@
    <roundcube:button command="download" type="link" class="button download disabled" classAct="button download" classSel="button download pressed" label="download" title="download" />
    <roundcube:button command="print" type="link" class="button print disabled" classAct="button print" classSel="button print pressed" label="print" title="print" />
    <roundcube:container name="toolbar" id="messagetoolbar" />
    <roundcube:if condition="env:mimetype == 'message/rfc822'" />
    <span class="spacer"></span>
    <roundcube:button command="reply" type="link" class="button reply disabled" classAct="button reply" classSel="button reply pressed" label="reply" title="replytomessage" />
    <span class="dropbutton">
        <roundcube:button command="reply-all" type="link" class="button reply-all disabled" classAct="button reply-all" classSel="button reply-all pressed" label="replyall" title="replytoallmessage" />
        <a href="#reply-all" class="dropbuttontip" id="replyallmenulink" onclick="UI.toggle_popup('replyallmenu',event);return false" aria-haspopup="true" aria-expanded="false" aria-owns="replyallmenu-menu" tabindex="0">Reply-all options</a>
    </span>
    <span class="dropbutton">
        <roundcube:button command="forward" type="link" class="button forward disabled" classAct="button forward" classSel="button forward pressed" label="forward" title="forwardmessage" />
        <a href="#forward" class="dropbuttontip" id="forwardmenulink" onclick="UI.toggle_popup('forwardmenu',event);return false" aria-haspopup="true" aria-expanded="false" aria-owns="forwardmenu-menu" tabindex="0">Forwarding options</a>
    </span>
    <roundcube:endif />
</div>
<div id="mainscreencontent">
@@ -38,6 +50,26 @@
</div>
</div>
<roundcube:if condition="env:mimetype == 'message/rfc822'" />
<div id="forwardmenu" class="popupmenu" aria-hidden="true">
    <h3 id="aria-label-forwardmenu" class="voice"><roundcube:label name="arialabelforwardingoptions" /></h3>
    <ul id="forwardmenu-menu" class="toolbarmenu" role="menu" aria-labelledby="aria-label-forwardmenu">
        <roundcube:button type="link-menuitem" command="forward-inline" label="forwardinline" prop="sub" classAct="forwardlink active" class="forwardlink" />
        <roundcube:button type="link-menuitem" command="forward-attachment" label="forwardattachment" prop="sub" classAct="forwardattachmentlink active" class="forwardattachmentlink" />
        <roundcube:container name="forwardmenu" id="forwardmenu-menu" />
    </ul>
</div>
<div id="replyallmenu" class="popupmenu" aria-hidden="true">
    <h3 id="aria-label-replyallmenu" class="voice"><roundcube:label name="arialabelreplyalloptions" /></h3>
    <ul id="replyallmenu-menu" class="toolbarmenu" role="menu" aria-labelledby="aria-label-replyallmenu">
        <roundcube:button type="link-menuitem" command="reply-all" label="replyall" prop="sub" class="replyalllink" classAct="replyalllink active" />
        <roundcube:button type="link-menuitem" command="reply-list" label="replylist" prop="sub" class="replylistlink" classAct="replylistlink active" />
        <roundcube:container name="replyallmenu" id="replyallmenu-menu" />
    </ul>
</div>
<roundcube:endif />
<roundcube:include file="/includes/footer.html" />
</body>