Message display tweaking.
authorMichael M Slusarz <slusarz@curecanti.org>
Tue, 11 Nov 2008 03:42:57 +0000 (20:42 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Tue, 11 Nov 2008 03:42:57 +0000 (20:42 -0700)
IMP 5 now can successfully display simple messages containing text/plain
and text/html data.  Playing around with the formatting a bit, but my
desire is to *always* show the Mime part summary for every part we can
display inline and *never* show inline parts in the attachment list.
This is important because there is no other way to
strip/download/display in a new window the parts that are shown inline.
This goes back to the way we used to display things long ago (IMP 3),
but that is probably the better way to do this. However, this has much
work that can be done to it - for now, just need to be able to display
the parts so I can continue implementing other things.

imp/lib/Contents.php
imp/message.php
imp/templates/message/message.html
imp/themes/graphics/delete.png [new file with mode: 0644]
imp/themes/graphics/download.png [new file with mode: 0644]
imp/themes/graphics/gallery.png [new file with mode: 0644]
imp/themes/screen.css

index d672999..452953f 100644 (file)
@@ -25,6 +25,7 @@ class IMP_Contents
     const SUMMARY_IMAGE_SAVE = 256;
     const SUMMARY_STRIP_LINK = 512;
     const SUMMARY_DOWNLOAD_ALL = 1024;
+    const SUMMARY_TEXTBODY = 2048;
 
     /**
      * The IMAP index of the message.
@@ -321,11 +322,11 @@ class IMP_Contents
      */
     public function findBody($subtype = null)
     {
-        foreach ($this->_message->contentTypeMap() as $key => $val) {
-            if ((strpos($val, 'text/') === 0) &&
-                (intval($key) == 1) &&
-                (is_null($subtype) || (substr($val, 5) == $subtype))) {
-                return $key;
+        foreach ($this->_message->contentTypeMap() as $mime_id => $mime_type) {
+            if ((strpos($mime_type, 'text/') === 0) &&
+                (intval($mime_id) == 1) &&
+                (is_null($subtype) || (substr($mime_type, 5) == $subtype))) {
+                return $mime_id;
             }
         }
 
@@ -410,6 +411,9 @@ class IMP_Contents
      *
      * IMP_Contents::SUMMARY_DOWNLOAD_ALL
      *   Output: info = 'download_all'
+     *
+     * IMP_Contents::SUMMARY_TEXTBODY
+     *   Output: info = 'textbody'
      * </pre>
      *
      * @return array  An array with two keys: 'info' and 'parts'. See above
@@ -421,24 +425,15 @@ class IMP_Contents
         $info = array(
             'download_all' => array(),
             'has' => array(),
-            'render' => array()
+            'render' => array(),
+            'textbody' => null
         );
         $parts = array();
 
         // Cache some settings before we enter the loop.
         $download_zip = (($mask & self::SUMMARY_DOWNLOAD_ZIP) && Util::extensionExists('zlib'));
-        if ($download_zip) {
-            $zip_img = Horde::img('compressed.png', _("Download in .zip Format"), null, $GLOBALS['registry']->getImageDir('horde') . '/mime');
-        }
-
-        if (($mask && self::SUMMARY_IMAGE_SAVE) &&
-            $GLOBALS['registry']->hasMethod('images/selectGalleries') &&
-            ($image_app = $GLOBALS['registry']->hasMethod('images/saveImage'))) {
-            $image_img = '<img src="' . $GLOBALS['registry']->get('icon', $image_app) . '" alt="' . _("Save Image in Gallery") . '" title="' . _("Save Image in Gallery") . '" />';
-        } else {
-            $image_img = null;
-        }
-
+        $img_save = (($mask && self::SUMMARY_IMAGE_SAVE) &&
+            $GLOBALS['registry']->hasMethod('images/selectGalleries'));
         if ($mask && self::SUMMARY_STRIP_LINK) {
             $message_token = IMP::getRequestToken('imp.impcontents');
         }
@@ -454,10 +449,18 @@ class IMP_Contents
                 'render_info' => false,
                 'render_inline' => false,
                 'size' => null,
-                'strip' => null
+                'strip' => null,
+                'textbody' => null
             );
             $part = &$parts[$mime_id];
 
+            if (($mask & self::SUMMARY_TEXTBODY) &&
+                is_null($info['textbody']) &&
+                (strpos($mime_type, 'text/') === 0) &&
+                (intval($mime_id) == 1)) {
+                $info['textbody'] = $mime_id;
+            }
+
             $mime_part = $this->getMIMEPart($mime_id, array('nocontents' => true, 'nodecode' => true));
 
             /* If this is an attachment that has no specific MIME type info,
@@ -510,7 +513,7 @@ class IMP_Contents
             }
 
             /* Get part's icon. */
-            $part['icon'] = ($mask & self::SUMMARY_ICON) ? Horde::img(Horde_Mime_Viewer::getIcon($mime_type), '', array('title' => $mime_type)) : null;
+            $part['icon'] = ($mask & self::SUMMARY_ICON) ? Horde::img(Horde_Mime_Viewer::getIcon($mime_type), '', array('title' => $mime_type), '') : null;
 
             /* Get part's description. */
             $description = $mime_part->getDescription(true);
@@ -527,7 +530,7 @@ class IMP_Contents
             /* Download column. */
             if (($mask & self::SUMMARY_DOWNLOAD) &&
                 (is_null($part['bytes']) || $part['bytes'])) {
-                $part['download'] = $this->linkView($mime_part, 'download_attach', '', array('class' => 'download', 'dload' => true, 'jstext' => sprintf(_("Download %s"), $description)));
+                $part['download'] = $this->linkView($mime_part, 'download_attach', '', array('class' => 'downloadAtc', 'dload' => true, 'jstext' => sprintf(_("Download %s"), $description)));
                 $info['has']['download'] = true;
             }
 
@@ -536,20 +539,19 @@ class IMP_Contents
             if ($download_zip &&
                 ($part['bytes'] > 204800) &&
                 !in_array($mime_type, array('application/zip', 'application/x-zip-compressed'))) {
-                $part['download_zip'] = $this->linkView($mime_part, 'download_attach', $zip_img, array('dload' => true, 'jstext' => sprintf(_("Download %s in .zip Format"), $mime_part->getDescription(true)), 'params' => array('zip' => 1)));
+                $part['download_zip'] = $this->linkView($mime_part, 'download_attach', null, array('class' => 'downloadZipAtc', 'dload' => true, 'jstext' => sprintf(_("Download %s in .zip Format"), $mime_part->getDescription(true)), 'params' => array('zip' => 1)));
                 $info['has']['download_zip'] = true;
             }
 
             /* Display the image save link if the required registry calls are
              * present. */
-            if (!is_null($image_img) &&
-                ($mime_part->getPrimaryType() == 'image')) {
+            if ($img_save && ($mime_part->getPrimaryType() == 'image')) {
                 if (empty($info['has']['img_save'])) {
                     Horde::addScriptFile('prototype.js', 'horde', true);
                     Horde::addScriptFile('popup.js', 'imp', true);
                     $info['has']['img_save'] = true;
                 }
-                $part['img_save'] = Horde::link('#', _("Save Image in Gallery"), null, null, IMP::popupIMPString('saveimage.php', array('index' => ($this->_index . IMP::IDX_SEP . $this->_mailbox), 'id' => $mime_id), 450, 200) . "return false;") . $image_img . '</a>';
+                $part['img_save'] = Horde::link('#', _("Save Image in Gallery"), 'saveImgAtc', null, IMP::popupIMPString('saveimage.php', array('index' => ($this->_index . IMP::IDX_SEP . $this->_mailbox), 'id' => $mime_id), 450, 200) . "return false;") . '</a>';
             }
 
             /* Strip the Attachment? */
@@ -557,12 +559,12 @@ class IMP_Contents
                 // TODO: No stripping of RFC 822 parts.
                 $url = Util::removeParameter(Horde::selfUrl(true), array('actionID', 'imapid', 'index'));
                 $url = Util::addParameter($url, array('actionID' => 'strip_attachment', 'imapid' => $mime_id, 'index' => $this->_index, 'message_token' => $message_token));
-                $part['strip'] = Horde::link($url, _("Strip Attachment"), null, null, "return window.confirm('" . addslashes(_("Are you sure you wish to PERMANENTLY delete this attachment?")) . "');") . Horde::img('delete.png', _("Strip Attachment"), null, $GLOBALS['registry']->getImageDir('horde')) . '</a>';
+                $part['strip'] = Horde::link($url, _("Strip Attachment"), 'stripAtc', null, "return window.confirm('" . addslashes(_("Are you sure you wish to PERMANENTLY delete this attachment?")) . "');") . '</a>';
                 $info['has']['strip'] = true;
             }
 
             if ($mask && self::SUMMARY_DOWNLOAD_ALL) {
-                if ($download = $this->isDownloadable($mime_part)) {
+                if ($download = $this->isAttachment($mime_part)) {
                     $info['download_all'][] = $mime_id;
                 }
             }
@@ -668,27 +670,31 @@ class IMP_Contents
     }
 
     /**
-     * Determines if a MIME part is downloadable.
+     * Determines if a MIME part is an attachment.
+     * For IMP's purposes, an attachment is any MIME part that can be
+     * downloaded by itself (i.e. all the data needed to view the part is
+     * contained within the download data).
      *
      * @param Horde_Mime_Part $mime_part  The MIME part object.
      *
-     * @return boolean  True if downloadable.
+     * @return boolean  True if an attachment.
      */
-    public function isDownloadable($mime_part)
+    public function isAttachment($mime_part)
     {
         $type = $mime_part->getType();
-        $ptype = $mime_part->getPrimaryType();
 
-        if ($ptype == 'message') {
+        switch ($mime_part->getPrimaryType()) {
+        case 'message':
             return ($type == 'message/rfc822');
-        }
 
-        return ((($mime_part->getDisposition() == 'attachment') ||
-                 $mime_part->getContentTypeParameter('name')) &&
-                ($ptype != 'multipart') &&
-                ($type != 'application/applefile') &&
+        case 'multipart':
+            return false;
+
+        default:
+            return (($type != 'application/applefile') &&
                 ($type != 'application/x-pkcs7-signature') &&
                 ($type != 'application/pkcs7-signature'));
+        }
     }
 
     /**
index c63c00d..d647468 100644 (file)
@@ -251,7 +251,8 @@ if (is_a($imp_contents, 'PEAR_Error')) {
 $contents_mask = IMP_Contents::SUMMARY_RENDER |
     IMP_Contents::SUMMARY_BYTES |
     IMP_Contents::SUMMARY_SIZE |
-    IMP_Contents::SUMMARY_ICON;
+    IMP_Contents::SUMMARY_ICON |
+    IMP_Contents::SUMMARY_TEXTBODY;
 if ($printer_friendly) {
     $contents_mask |= IMP_Contents::SUMMARY_DESCRIP_NOLINK;
 } else {
@@ -631,11 +632,6 @@ if (!$printer_friendly) {
     echo $a_template->fetch(IMP_TEMPLATES . '/message/navbar_actions.html');
 }
 
-$atc_display = $prefs->getValue('attachment_display');
-$show_parts = (($atc_display == 'list') || ($atc_display == 'both'));
-$downloadall_link = empty($summary['info']['download_all'])
-    ? false
-    : $imp_contents->urlView($imp_contents->getMIMEMessage(), 'download_all', array('params' => array('download_ids' => serialize($summary['info']['download_all']))));
 $hdrs = array();
 $i = 1;
 
@@ -655,35 +651,52 @@ foreach ($all_list_headers as $head => $val) {
     $hdrs[] = array('name' => $list_headers_lookup[$head], 'val' => $val, 'i' => (++$i % 2));
 }
 
+/* Show attachment information in headers? */
+$download_all = $show_atc = false;
+reset($summary['parts']);
 if (!empty($summary['parts']) &&
-    ($show_parts || ($downloadall_link && !$printer_friendly))) {
+    ((count($summary['parts']) > 1) ||
+     (key($summary['parts']) != $summary['info']['textbody']))) {
+    $atc_display = $prefs->getValue('attachment_display');
+    $show_atc = (($atc_display == 'list') || ($atc_display == 'both'));
+    $download_all = (empty($summary['info']['download_all']) || !$printer_friendly)
+        ? false
+        : $imp_contents->urlView($imp_contents->getMIMEMessage(), 'download_all', array('params' => array('download_ids' => serialize($summary['info']['download_all']))));
+}
+
+$part_info = array('icon', 'description', 'type', 'size');
+foreach (array('download', 'download_zip', 'img_save', 'strip') as $val) {
+    if (isset($summary['info']['has'][$val])) {
+        $part_info[] = $val;
+    }
+}
+
+if ($show_atc || $download_all) {
     $val = '';
-    if ($show_parts) {
-        $part_info = array('icon', 'id', 'description', 'type', 'size');
-        foreach (array('download', 'download_zip', 'img_save', 'strip') as $val) {
-            if (isset($summary['info']['has'][$val])) {
-                $part_info[] = $val;
-            }
-        }
-        $tmp = array('<table>');
+
+    if ($show_atc) {
+        $tmp = array();
         foreach ($summary['parts'] as $key => $val) {
-            $tmp[] = '<tr>';
-            foreach ($part_info as $val2) {
-                $tmp[] = '<td>' . $val[$val2] . '</td>';
+            if ($key != $summary['info']['textbody']) {
+                $tmp[] = '<tr>';
+                foreach ($part_info as $val2) {
+                    $tmp[] = '<td>' . $val[$val2] . '</td>';
+                }
+                $tmp[] = '</tr>';
             }
-            $tmp[] = '</tr>';
         }
-        $tmp[] = '</table>';
-        $val = implode('', $tmp);
+        $val = '<table>' . implode('', $tmp) . '</table>';
     }
-    if ($downloadall_link && !$printer_friendly) {
-        $val .= Horde::link($downloadall_link, _("Download All Attachments (in .zip file)")) . _("Download All Attachments (in .zip file)") . ' ' . Horde::img('compressed.png', _("Download All Attachments (in .zip file)"), '', $registry->getImageDir('horde') . '/mime') . '</a>';
+
+    if ($download_all) {
+        $val .= Horde::link($download_all, _("Download All Attachments (in .zip file)")) . _("Download All Attachments (in .zip file)") . ' ' . Horde::img('compressed.png', _("Download All Attachments (in .zip file)"), '', $registry->getImageDir('horde') . '/mime') . '</a>';
         if ($prefs->getValue('strip_attachments')) {
             $url = Util::addParameter(Util::removeParameter(Horde::selfUrl(true), array('actionID')), array('actionID' => 'strip_all', 'message_token' => $message_token));
             $val .= '<br />' . Horde::link($url, _("Strip All Attachments"), null, null, "return window.confirm('" . addslashes(_("Are you sure you wish to PERMANENTLY delete all attachments?")) . "');") . _("Strip All Attachments") . ' ' . Horde::img('delete.png', _("Strip Attachments"), null, $registry->getImageDir('horde')) . '</a>';
         }
     }
-    $hdrs[] = array('name' => _("Part(s)"), 'val' => $val, 'i' => (++$i % 2));
+
+    $hdrs[] = array('name' => _("Attachment(s)"), 'val' => $val, 'i' => (++$i % 2));
 }
 
 if ($printer_friendly && !empty($conf['print']['add_printedby'])) {
@@ -691,8 +704,31 @@ if ($printer_friendly && !empty($conf['print']['add_printedby'])) {
 }
 
 $m_template->set('headers', $hdrs);
-// TODO
-//$m_template->set('msgtext', reset($inline_parts));
+
+/* Build body text. */
+$msgtext = '';
+foreach ($summary['info']['render'] as $mime_id => $type) {
+    $render_part = $imp_contents->renderMIMEPart($mime_id, $type);
+    $ptr = $summary['parts'][$mime_id];
+    $tmp_part = $tmp_status = array();
+
+    foreach ($part_info as $val) {
+        $tmp[] = $ptr[$val];
+    }
+
+    foreach ($render_part['status'] as $val) {
+        // TODO: status msgs.
+        $tmp_status[] = $render_part['status']['text'];
+    }
+
+    $msgtext .= '<span class="mimePartInfo">' .
+        implode(' ', $tmp) .
+        '</span>' .
+        implode(' ', $tmp_status) .
+        $render_part['data'];
+}
+$m_template->set('msgtext', $msgtext);
+
 echo $m_template->fetch(IMP_TEMPLATES . '/message/message.html');
 
 if (!$printer_friendly) {
index fac4278..b2b641f 100644 (file)
@@ -10,7 +10,5 @@
 </div>
 
 <div id="messageBody" class="messageBody">
- <table width="100%" cellspacing="3">
-  <tag:msgtext />
- </table>
+ <tag:msgtext />
 </div>
diff --git a/imp/themes/graphics/delete.png b/imp/themes/graphics/delete.png
new file mode 100644 (file)
index 0000000..f3076bc
Binary files /dev/null and b/imp/themes/graphics/delete.png differ
diff --git a/imp/themes/graphics/download.png b/imp/themes/graphics/download.png
new file mode 100644 (file)
index 0000000..de62aae
Binary files /dev/null and b/imp/themes/graphics/download.png differ
diff --git a/imp/themes/graphics/gallery.png b/imp/themes/graphics/gallery.png
new file mode 100644 (file)
index 0000000..f05b029
Binary files /dev/null and b/imp/themes/graphics/gallery.png differ
index 89e21b7..6ccc0ff 100644 (file)
@@ -129,6 +129,9 @@ ul.msgactions, ul.msgactions ul {
     background: #fff;
     padding: 8px;
 }
+.messageBody div.fixed {
+    padding-top: 8px;
+}
 
 /* Search page styling. */
 form#search div {
@@ -382,3 +385,53 @@ ul.nav-audio {
 .largeaddrlist:hover {
     text-decoration: underline;
 }
+
+/* MIME styles. */
+.mimeStatusMessage, .mimeStatusWarning, .mimeHeaders, .mimePartInfo {
+    padding: 1px;
+    margin-bottom: 2px;
+    font-size: 90%;
+}
+.mimeStatusMessage {
+    color: #000;
+    background: #ffc;
+    border: 1px solid #fff760;
+    width: 100%;
+}
+.mimeStatusWarning {
+    border: 1px solid #800;
+    background: #e81222;
+    color: #fff;
+    width: 100%;
+}
+.mimeHeaders {
+    border: 1px solid #ccc;
+    background: #f9f9f9;
+    width: 100%;
+    font-family: "Lucida Console",Courier,"Courier New";
+}
+.mimePartInfo {
+    border: 1px solid #ccc;
+    background: #f9f9f9;
+    padding-top: 4px;
+    padding-bottom: 3px;
+}
+.mimePartInfo img {
+    vertical-align: bottom;
+}
+.downloadAtc {
+    padding: 2px 20px 2px 0;
+    background: transparent url("graphics/download.png") center right no-repeat;
+}
+.downloadZipAtc {
+    padding: 2px 20px 2px 0;
+    background: transparent url("graphics/mime/compressed.png") center right no-repeat;
+}
+.saveImgAtc {
+    padding: 2px 20px 2px 0;
+    background: transparent url("graphics/gallery.png") center right no-repeat;
+}
+.stripAtc {
+    padding: 2px 20px 2px 0;
+    background: transparent url("graphics/delete.png") center right no-repeat;
+}