a custom function to dynamically determine the icons shown for standard
folders on the folder page? If so, make sure you define
_imp_hook_mbox_icons() in hooks.php.">false</configboolean>
+ <configboolean name="mailboxarray" required="false" desc="Should we run a
+ custom function in which array elements can be added to use in the template
+ file, while processing the message lists? If so, make sure you define
+ _imp_hook_mailboxarray() in config/hooks.php.">false</configboolean>
<configboolean name="mbox_readonly" required="false" desc="Should we use a
custom function to dynamically determine whether a given folder is
read-only? If so, make sure you define _imp_hook_mbox_readonly() in
custom function to dynamically generate the email address to send spam
reporting emails to? If so, make sure you define _imp_hook_spam_email() in
hooks.php.">false</configboolean>
- <configboolean name="msglist_format" required="false" desc="Should we use
- a custom function to provide additional information/custom formatting of
- messages in the mailbox message list? If so, make sure you define
- _imp_hook_msglist_format() in hooks.php.">false</configboolean>
+ <configboolean name="msglist_flags" required="false" desc="Should we use
+ a custom function to provide additional flags to messages in the mailbox
+ message list? If so, make sure you define _imp_hook_msglist_flags() in
+ hooks.php.">false</configboolean>
<configboolean name="display_folder" required="false" desc="Should we use
a custom function to dynamically determine if we show a specified IMAP
mailbox in the folderlist ? If so, make sure you define
<configheader>Custom Hooks</configheader>
<configsection name="dimp">
<configsection name="hooks">
- <configboolean name="mailboxarray" required="false" desc="Should we
- run a custom function in which array elements can be added to use in the
- template file, while processing the message lists? If so, make sure
- you define _imp_hook_dimp_mailboxarray() in config/hooks.php. The elements
- will be available as template tags in the imp/templates/imp/mailbox.html
- template file.">false</configboolean>
<configboolean name="previewview" required="false" desc="Should we
run a custom function in which array elements can be modified, and
javascript code be provided to dynamically update page elements in the
// }
// }
-// This is an example hook function for displaying additional message
-// information in the message listing screen for a mailbox. This example hook
-// will add a icon if the message contains attachments and will change the
-// display of the message entry based on the X-Priority header.
-//
-// INPUT:
-// $mbox - (string) The mailbox.
-// $uids - (array) A list of UIDs.
-// $mode - (string) Either 'imp' or 'dimp'.
-//
-// OUTPUT:
-// An array of arrays, with UIDs as keys and the following array values:
-//
-// For IMP:
-// 'class' - (array) CSS classnames that will be added to the row.
-// 'flagbits' - (integer) Flag mask which will be OR'd with the current flags
-// set for the row. The flag constants used in IMP can be
-// found at the top of lib/IMP.php.
-// 'status' - (string) HTML code to add to the status column for the row.
-//
-// For DIMP:
-// 'atc' - (string) Attachment type (either 'signed', 'encrypted', or
-// 'attachment').
-// 'class' - (array) CSS classnames that will be added to the row.
-
-// if (!function_exists('_imp_hook_msglist_format')) {
-// function _imp_hook_msglist_format($mbox, $uids, $mode)
+// This is an example hook function for adding additional message flags
+// in the message listing screen for a mailbox. This example hook
+// will add a icon if the message was sent from a user within the same domain.
+//
+// @param array $data The overview information for a message as returned
+// from the IMP_Mailbox::getMailboxArray() call (see
+// lib/Mailbox.php for documentation on the structure of
+// the array).
+// @param string $mode Either 'imp' or 'dimp'.
+//
+// @return array An array of additional flags to add. These flags must be
+// defined in the 'msgflags' preference. On error, return an
+// empty array.
+
+// if (!function_exists('_imp_hook_msglist_flags')) {
+// function _imp_hook_msglist_flags($data, $mode)
// {
-// try {
-// $imap_res = $GLOBALS['imp_imap']->ob->fetch($mbox, array(
-// Horde_Imap_Client::FETCH_HEADERS => array(array('headers' => array('x-priority'), 'label' => 'hdr_search', 'parse' => true, 'peek' => true)),
-// Horde_Imap_Client::FETCH_STRUCTURE => array('parse' => true)
-// ), array('ids' => array_values($uids)));
-// } catch (Horde_Imap_Client_Exception $e) {
-// return array();
+// $flags = array();
+//
+// $from_ob = Horde_Mime_Address::getAddressesFromObject($ob['envelope']['from']);
+// if (!empty($from_ob) &&
+// (strcasecmp($from_ob[0]['hostname'], 'example.com') === 0)) {
+// /* The '$indomain' flag in this example must have already been
+// * created in the 'msgflags' preference. */
+// $flags = array('$indomain');
// }
//
-// $alt_list = IMP_UI_Mailbox::getAttachmentAltList();
-// $imp_ui = new IMP_UI_Mailbox($mbox);
-// $imp_msg_ui = new IMP_UI_Message();
-// $ret = array();
-//
-// foreach ($uids as $uid) {
-// $tmp = array('status' => '');
-// $res_ptr = &$imap_res[$uid];
-//
-// // Add attachment information
-// if (($attachment = $imp_ui->getAttachmentType($res_ptr['structure']->getType()))) {
-// switch ($mode) {
-// case 'imp':
-// $alt_text = (isset($alt_list[$attachment]))
-// ? $alt_list[$attachment]
-// : $alt_list['attachment'];
-// $tmp['status'] = Horde::img($attachment . '.png', $alt_text, array('title' => $alt_text));
-// break;
-//
-// case 'dimp':
-// $tmp['atc'] = $attachment;
-// break;
-// }
-// }
-//
-// // Add X-Priority information
-// switch ($imp_msg_ui->getXpriority($res_ptr['headers']['hdr_search']->getValue('x-priority'))) {
-// case 'high':
-// if ($mode == 'imp') {
-// $tmp['flagbits'] = IMP::FLAG_FLAGGED;
-// $tmp['status'] .= Horde::img('mail_priority_high.png', _("High Priority"), array('title' => _("High Priority")));
-// }
-// $tmp['class'][] = 'important';
-// break;
-//
-// case 'low':
-// if ($mode == 'imp') {
-// $tmp['status'] .= Horde::img('mail_priority_low.png', _("Low Priority"), array('title' => _("Low Priority")));
-// }
-// $tmp['class'][] = 'unimportant';
-// break;
-// }
-//
-// if (!empty($tmp)) {
-// $ret[$uid] = $tmp;
-// }
-// }
-//
-// return $ret;
+// return $flags;
// }
-// }
// This is an example hook function for the IMP redirection scheme. This
// function is called when the user opens a mailbox in IMP, and allows the
// }
// }
+// This is an example hook function for the mailbox view. This functions
+// allows additional information to be added/edited from the data that is
+// passed to the mailbox display template:
+// imp: TODO
+// dimp: imp/templates/javascript/mailbox-dimp.js.
+// The current entry array is passed in, the value returned should be the
+// altered array to use in the template. If you are going to add new columns,
+// you also have to update these fields:
+// imp: TODO
+// dimp: imp/templates/index/dimp.inc to contain the new field in the header
+// imp/themes/screen-dimp.css to specify the column width.
+
+// if (!function_exists('_imp_hook_mailboxarray')) {
+// function _imp_hook_mailboxarray($msgs, $view) {
+// switch ($view) {
+// case 'dimp':
+// foreach (array_keys($msgs) as $key) {
+// $msgs[$key]['foo'] = true;
+// }
+// break;
+//
+// case 'imp':
+// // TODO
+// break;
+// }
+//
+// return $msg;
+// }
+// }
+
// This is an example hook function to disable composing messages. If the hook
// returns true, message composition will be disabled.
}
}
-
-// This is an example hook function for the dynamic (dimp) mailbox view. This
-// function is allows additional information to be added to the array that is
-// is passed to the mailbox display template -
-// imp/templates/javascript/mailbox-dimp.js. The current entry array is
-// passed in, the value returned should be the altered array to use in the
-// template. If you are going to add new columns, you also have to update
-// imp/templates/index/dimp.inc to contain the new field in the header and
-// imp/themes/screen-dimp.css to specify the column width.
-
-// if (!function_exists('_imp_hook_dimp_mailboxarray')) {
-// function _imp_hook_dimp_mailboxarray($msgs) {
-// foreach (array_keys($msgs) as $key) {
-// $msgs[$key]['foo'] = true;
-// }
-//
-// return $msg;
-// }
-// }
-
// This is an example hook function for the dynamic (dimp) message view. This
// function allows additional information to be added to the array that is
// passed to the message text display template -
}
if (!$is_pop3) {
+ $prefGroups['flags'] = array(
+ 'column' => _("Message Options"),
+ 'label' => _("Message Flags"),
+ 'desc' => _("Customize flag highlighting."),
+ 'members' => array('flagmanagement')
+ );
+
$prefGroups['fetchmail'] = array(
'column' => _("Message Options"),
'label' => _("Fetch Mail"),
'label' => _("Mailbox and Folder Display Options"),
'desc' => _("Change display options such as how many messages you see on each page and how messages are sorted."),
'members' => array('mailbox_start', 'sortby', 'sortdir', 'max_msgs',
- 'from_link', 'time_format')
+ 'from_link', 'time_format', 'atc_flag')
);
if (!$is_pop3) {
$prefGroups['display']['members'] = array_merge(
'desc' => _("To the stationery and form responses."));
$_prefs['stationery'] = array(
+ // value = serialize(array())
'value' => 'a:0:{}',
'locked' => false,
'shared' => false,
// End Message Preview
+// IMAP Flag preferences
+
+// UI for flag management.
+$_prefs['flagmanagement'] = array(
+ 'type' => 'special'
+);
+
+// Message flags
+$_prefs['msgflags'] = array(
+ // Format:
+ // KEY: Flag name
+ // VALUE: Array with the following entries
+ // 'a' - (string) [abbreviation] The abbreviation used in
+ // the mimp (minimal) view.
+ // DEFAULT: Don't show flag
+ // 'b' - (string) [background] The CSS background color
+ // DEFAULT: Use value of 'msgflags_color'
+ // 'c' - (string) [class] The CSS background class (used to
+ // display status icon).
+ // NO DEFAULT (entry required)
+ // 'd' - (boolean) [delete] If true, entry can be deleted.
+ // DEFAULT: false
+ // 'l' - (string) [label] The flag text label.
+ // NO DEFAULT (entry required)
+ // 't' - (string) [type] The flag type:
+ // 'atc' - Attachment information
+ // 'imap' - IMAP flags (not user settable)
+ // 'imapp' - IMAP flags (personal flags - created by user
+ through the prefs interface)
+ // 'imapu' - IMAP flags (user settable)
+ // 'imp' - IMP defined flags
+ // NO DEFAULT (entry required)
+ 'value' => json_encode(array(
+ // Static internal imp flags (i.e. status icons)
+ // THESE ENTRIES MUST NOT BE DELETED
+ 'personal' => array(
+ 'a' => '+',
+ 'c' => 'flagPersonal',
+ 'l' => _("Personal"),
+ 't' => 'imp'
+ ),
+ 'highpri' => array(
+ 'a' => '^',
+ 'b' => '#ffcccc',
+ 'c' => 'flagHighpriority',
+ 'l' => _("High Priority"),
+ 't' => 'imp'
+ ),
+ 'lowpri' => array(
+ 'a' => 'v',
+ 'c' => 'flagLowpriority',
+ 'l' => _("Low Priority"),
+ 't' => 'imp'
+ ),
+
+ // Attachment flags
+ // THESE ENTRIES MUST NOT BE DELETED
+ 'signed' => array(
+ 'c' => 'flagSignedmsg',
+ 'l' => _("Message is Signed"),
+ 't' => 'atc'
+ ),
+ 'encrypt' => array(
+ 'c' => 'flagEncryptmsg',
+ 'l' => _("Message is Encrypted"),
+ 't' => 'atc'
+ ),
+ 'attach' => array(
+ 'c' => 'flagAttachmsg',
+ 'l' => _("Message has Attachments"),
+ 't' => 'atc'
+ ),
+
+ // IMAP flags
+ // KEY: IMAP flag as it exsits on the IMAP server
+ // VALUES (additional to base values):
+ // 'n' - (boolean) [NOT match] Don't match the flag.
+ // DEFAULT: false
+
+ // System IMAP flags (RFC 3501 [2.3.2])
+ '\\seen' => array(
+ 'a' => 'N',
+ 'b' => '#eeeeff',
+ 'c' => 'flagUnseen',
+ 'l' => _("Unseen"),
+ 'n' => true,
+ 't' => 'imap'
+ ),
+ '\\answered' => array(
+ 'a' => 'r',
+ 'b' => '#ccffcc',
+ 'c' => 'flagAnswered',
+ 'l' => _("Answered"),
+ 't' => 'imap'
+ ),
+ '\\draft' => array(
+ 'a' => 'd',
+ 'c' => 'flagDraft',
+ 'l' => _("Draft"),
+ 't' => 'imapu'
+ ),
+ '\\flagged' => array(
+ 'a' => '*',
+ 'b' => '#ffcccc',
+ 'c' => 'flagFlagged',
+ 'l' => _("Flagged for Followup"),
+ 't' => 'imapu'
+ ),
+ '\\deleted' => array(
+ 'a' => 'D',
+ 'b' => '#999999',
+ 'c' => 'flagDeleted',
+ 'l' => _("Deleted"),
+ 't' => 'imap'
+ ),
+
+ // Forwarded flag (RFC 4550 [2.8])
+ '$forwarded' => array(
+ 'a' => 'F',
+ 'b' => '#aadddd',
+ 'c' => 'flagForwarded',
+ 'l' => _("Forwarded"),
+ // Pursuant to RFC, this flag SHOULD NOT be changed by the user
+ 't' => 'imap'
+ )
+ )),
+ 'locked' => false,
+ 'shared' => false,
+ 'type' => 'implicit'
+);
+
+// The default color to use for flags that don't require row highlighting.
+$_prefs['msgflags_color'] = array(
+ 'value' => '#ffffff',
+ 'locked' => false,
+ 'shared' => false,
+ 'type' => 'implicit');
+
+// By default, don't allow user to alter flags set by system events.
+$_prefs['msgflags_hidesys'] = array(
+ 'value' => true,
+ 'locked' => false,
+ 'shared' => false,
+ 'type' => 'implicit');
+
+// End IMAP Flag preferences
+
+
// Fetch Mail preferences
// Change this if you want to customize how fetchmailprefs.php works.
// Don't change anything here.
$_prefs['fm_accounts'] = array(
+ // value = serialize(array())
'value' => 'a:0:{}',
'locked' => false,
'shared' => false,
// sort prefs for individual folders
$_prefs['sortpref'] = array(
+ // value = serialize(array())
'value' => 'a:0:{}',
'locked' => false,
'shared' => false,
),
'desc' => _("The From: column of the message should be linked:"));
+// Display attachment information in mailbox list.
+// Disabled by default, and not shown to user, because this display requires
+// substantial overhead to parse the message structures of all message in
+// the mailbox list at view time.
+$_prefs['atc_flag'] = array(
+ 'value' => 0,
+ 'locked' => true,
+ 'type' => 'checkbox',
+ 'desc' => _("Display attachment information about a message in the mailbox listing?"));
+
// Time format for messages dated today
$_prefs['time_format'] = array(
'value' => '%X',
// list of folders to expand by default
$_prefs['expanded_folders'] = array(
+ // value = serialize(array())
'value' => 'a:0:{}',
'locked' => false,
'shared' => false,
v5.0-git
--------
+[mms] Add support for defining and displaying custom IMAP flags and for
+ configuring the highlighting of system flags (Request #937).
+[mms] Move attachment dispaly on mailbox page from hook to preference.
+[mms] Always do X-Priority header processing by default.
[mms] Support $MDNSent keyword (RFC 3503) on IMAP server.
[mms] Link URLs/e-mails in subjects in message views (Request #7487).
[mms] Implement spellcheck on send in DIMP.
RFC 4315 UIDPLUS
RFC 4422 SASL Authentication (for DIGEST-MD5)
RFC 4466 Collected extensions (updates RFCs 2088, 3501, 3502, 3516)
+RFC 4550 Lemonade Profile (specifically [2.8] - $Forwarded flag)
RFC 4551 CONDSTORE
RFC 4731 ESEARCH
RFC 4959 SASL-IR
* imp_hook_vinfo has changed
* alternative_display, attachment_display, forward_default pref is gone.
* imp_hook_spam_bounce -> imp_hook_spam_email
-* imp_hook_msglist_format input has changed.
+* imp_hook_msglist_format hook has been removed - instead:
+* x-priority now handled in the core code
+* old attachment icon handling see atc_flag pref
+* imp_hook_msglist_flags hook now used to dynamically set flags on messages
+
Upgrading IMP From 4.1.x To 4.2.x
var ContextSensitive = Class.create({
+ queueSettings: {
+ limit: 5,
+ position: 'end',
+ scope: 'contextsensitive'
+ },
+
initialize: function(opts)
{
- this.basectx = this.target = null;
+ this.basectx = this.submenu = null;
this.elements = $H();
this.submenus = $H();
this.current = [];
/**
* Hide the currently displayed element(s).
*/
- close: function(immediate)
+ close: function()
{
- this._closeSubmenu(0, immediate);
+ this._closeSubmenu(0, true);
},
/**
{
if (this.current.size()) {
this.current.splice(idx, this.current.size() - idx).each(function(s) {
- if (immediate) {
- $(s).hide();
- } else {
- Effect.Fade(s, { duration: 0.2, queue: { position: 'end', scope: 'cm_' + s, limit: 2 } });
- }
- });
- this.target = this.current[idx];
- this.basectx = null;
+ Effect.Fade(s, {
+ duration: 0.15,
+ afterFinish: function() { this.basectx = this.submenu = null; }.bind(this),
+ queue: immediate ? 'global' : this.queueSettings
+ });
+ }, this);
}
},
*/
_leftClickHandler: function(e)
{
- var curr, elt, elt_up;
+ var base, elt, elt_up, submenu;
// Check for a right click. FF on Linux triggers an onclick event even
// w/a right click, so disregard.
elt_up.readAttribute('id') != this.currentmenu()) {
this._closeSubmenu(this.current.indexOf(elt.readAttribute('id')));
} else {
- curr = $(this.target);
- this.close(true);
+ base = this.current.first();
+ submenu = this.submenu;
+ this.close();
if (this.opts.onClick) {
- this.opts.onClick(elt.readAttribute('id'), curr);
+ this.opts.onClick(elt, base, submenu);
}
}
return;
// Register the current element that will be shown and the element
// that was clicked on.
this.close();
- this.target = ctx.id;
offset = ctx.opts.offset;
if (!offset && (Object.isUndefined(x) || Object.isUndefined(y))) {
/**
* Display the [sub]menu on the screen.
*/
- _displayMenu: function(elt, x, y)
+ _displayMenu: function(elt, x, y, submenu)
{
// Get window/element dimensions
var id = elt.readAttribute('id'),
this.opts.onShow(id, this.basectx);
}
- Effect.Appear(elt.setStyle({ left: x + 'px', top: y + 'px' }), { duration: 0.2, queue: { position: 'end', scope: 'cm_' + id, limit: 2 } });
-
- this.current.push(id);
+ Effect.Appear(elt, {
+ from: 0.0,
+ afterSetup: function() {
+ elt.setStyle({ left: x + 'px', top: y + 'px' })
+ this.current.push(id);
+ this.submenu = submenu;
+ }.bind(this),
+ duration: 0.15,
+ queue: this.queueSettings
+ });
},
/**
if (elt.hasClassName('contextSubmenu')) {
sub = this.submenus.get(id);
- if (sub != cm) {
+ if (sub != cm || this.submenu != id) {
if (id_div != cm) {
this._closeSubmenu(this.current.indexOf(id_div) + 1);
}
voffsets = document.viewport.getScrollOffsets();
x = offsets[0] + voffsets.left + elt.getWidth();
y = offsets[1] + voffsets.top;
- this._displayMenu($(sub), x, y);
+ this._displayMenu($(sub), x, y, id);
}
} else if ((this.current.size() > 1) &&
elt_up.hasClassName('contextMenu') &&
sf_subject: 'subject'
}),
- flags: $H({
- unseen: 'Unseen',
- flagged: 'Flagged',
- deletedmsg: 'Deleted',
- unimportant: 'LowPriority',
- important: 'HighPriority',
- answered: 'Answered',
- forwarded: 'Forwarded',
- draft: 'Draft'
- }),
-
// Message selection functions
// vs = (ViewPort_Selection) A ViewPort_Selection object.
// r = ViewPort row data
msgWindow: function(r)
{
- this.updateUnseenUID(r, 0);
+ this.updateSeenUID(r, 1);
var url = DIMP.conf.message_url;
url += (url.include('?') ? '&' : '?') +
$H({ folder: r.view,
search = this.sfilters.get(this._getSearchfilterField()).capitalize();
mf = new RegExp("(" + $F('msgList_filter') + ")", "i");
}
+
rows.get('dataob').each(function(row) {
var elt, tmp, u,
r = $(row.domid);
+ this.updateStatusFlags(row);
+
// Add thread graphics
if (thread && thread.get(row.imapuid)) {
elt = r.down('.msgSubject');
}
return this.cacheids[id];
}.bind(this),
- onUpdateClass: function(row) {
- this.updateStatusFlags(row);
- }.bind(this),
onSplitBarChange: function() {
this._updatePrefs('dimp_splitbar', this.viewport.getPageSize());
}.bind(this),
DimpCore.DMenu.removeElement($(elt).identify());
},
- contextOnClick: function(parentfunc, id, elt)
+ contextOnClick: function(parentfunc, elt, base, submenu)
{
+ var id = elt.readAttribute('id');
+
switch (id) {
case 'ctx_folder_create':
- this.createSubFolder(elt);
+ this.createSubFolder(base);
break;
case 'ctx_container_rename':
case 'ctx_folder_rename':
- this.renameFolder(elt);
+ this.renameFolder(base);
break;
case 'ctx_folder_empty':
- mbox = elt.readAttribute('mbox');
+ mbox = base.readAttribute('mbox');
if (window.confirm(DIMP.text.empty_folder)) {
DimpCore.doAction('EmptyFolder', { view: mbox }, null, this._emptyFolderCallback.bind(this));
}
break;
case 'ctx_folder_delete':
- mbox = elt.readAttribute('mbox');
+ mbox = base.readAttribute('mbox');
if (window.confirm(DIMP.text.delete_folder)) {
DimpCore.doAction('DeleteFolder', { view: mbox }, null, this.bcache.get('folderC') || this.bcache.set('folderC', this._folderCallback.bind(this)));
}
case 'ctx_folder_seen':
case 'ctx_folder_unseen':
- this.flag(id == 'ctx_folder_seen' ? 'allSeen' : 'allUnseen', { mailbox: elt.readAttribute('mbox') });
+ this.flag(id == 'ctx_folder_seen' ? 'allSeen' : 'allUnseen', { mailbox: base.readAttribute('mbox') });
break;
case 'ctx_folder_poll':
case 'ctx_folder_nopoll':
- this.modifyPollFolder(elt.readAttribute('mbox'), id == 'ctx_folder_poll');
+ this.modifyPollFolder(base.readAttribute('mbox'), id == 'ctx_folder_poll');
break;
case 'ctx_container_create':
- this.createSubFolder(elt);
+ this.createSubFolder(base);
break;
case 'ctx_message_spam':
case 'ctx_message_ham':
case 'ctx_message_blacklist':
case 'ctx_message_whitelist':
+ this.flag(id.substring(12));
+ break;
+
case 'ctx_message_deleted':
case 'ctx_message_undeleted':
- this.flag(id.substring(12));
+ this.flag('imapflag', { imap: '\\deleted', set: id == 'ctx_message_deleted' });
break;
case 'ctx_message_forward':
this.composeMailbox('resume');
break;
- case 'ctx_draft_flagged':
- case 'ctx_draft_clear':
case 'ctx_draft_deleted':
case 'ctx_draft_undeleted':
- this.flag(id.substring(10));
+ this.flag('imapflag', { imap: '\\deleted', set: id == 'ctx_draft_deleted' });
break;
case 'ctx_reply_reply':
this.togglePreviewPane();
break;
- case 'flag_seen':
- case 'flag_unseen':
- case 'flag_flagged':
- case 'flag_clear':
- case 'flag_answered':
- case 'flag_unanswered':
- case 'flag_draft':
- case 'flag_notdraft':
- this.flag(id.substring(5));
- break;
-
case 'oa_blacklist':
case 'oa_whitelist':
- case 'oa_undeleted':
this.flag(id.substring(3));
break;
+ case 'oa_undeleted':
+ this.flag('imapflag', { imap: '\\deleted', set: false });
+
case 'oa_selectall':
this.selectAll();
break;
break;
default:
- parentfunc(id, elt);
+ if (submenu == 'ctx_message_setflag' ||
+ submenu == 'ctx_draft_setflag' ||
+ submenu == 'oa_setflag') {
+ this.flag('imapflag', { imap: elt.readAttribute('flag'), set: true });
+ } else if (submenu == 'ctx_message_unsetflag' ||
+ submenu == 'ctx_draft_unsetflag' ||
+ submenu == 'oa_unsetflag') {
+ this.flag('imapflag', { imap: elt.readAttribute('flag'), set: false });
+ } else {
+ parentfunc(elt, base, submenu);
+ }
break;
}
},
folder = $(ctx.ctx);
if (folder.readAttribute('mbox') == 'INBOX') {
elts.invoke('hide');
- } else if (DIMP.conf.fixed_folders.indexOf(folder.readAttribute('mbox')) != -1) {
+ } else if (DIMP.conf.fixed_folders &&
+ DIMP.conf.fixed_folders.indexOf(folder.readAttribute('mbox')) != -1) {
elts.shift();
elts.invoke('hide');
} else {
// There is a chance that the message may have been marked
// as unseen since first being viewed. If so, we need to
// explicitly flag as seen here.
- if (data.bg.indexOf('unseen') != -1) {
- this.flag('seen');
+ if (this.isUnseen(data)) {
+ this.flag('imapflag', { imap: '\\seen', set: true });
}
return this._loadPreviewCallback(this.ppcache[pp_uid]);
}
search = this.viewport.getViewportSelection().search({ imapuid: { equal: [ r.index ] }, view: { equal: [ r.folder ] } });
if (search.size()) {
row = search.get('dataob').first();
- this.updateUnseenUID(row, 0);
+ this.updateSeenUID(row, 1);
}
}
switch (r.priority) {
case 'high':
case 'low':
- tmp.invoke('insert', { top: new Element('SPAN').addClassName('status' + r.priority.capitalize() + 'Priority') });
+ tmp.invoke('insert', { top: new Element('DIV').addClassName('flag' + r.priority.capitalize() + 'priority') });
break;
}
},
// Labeling functions
- updateUnseenUID: function(r, setflag)
+ updateSeenUID: function(r, setflag)
{
- var sel, unseen, unseenset;
- if (!r.bg) {
- return false;
- }
- unseenset = r.bg.indexOf('unseen') != -1;
- if ((setflag && unseenset) || (!setflag && !unseenset)) {
+ var isunseen = this.isUnseen(r),
+ sel, unseen;
+
+ if ((setflag && !isunseen) || (!setflag && isunseen)) {
return false;
}
sel = this.viewport.createSelection('dataob', r);
unseen = Number($(this.getFolderId(r.view)).readAttribute('u'));
+
if (setflag) {
- this.viewport.updateFlag(sel, 'unseen', true);
- ++unseen;
- } else {
- this.viewport.updateFlag(sel, 'unseen', false);
+ this.updateFlag(sel, '\\seen', true);
--unseen;
+ } else {
+ this.updateFlag(sel, '\\seen', false);
+ ++unseen;
}
this.updateUnseenStatus(r.view, unseen);
DimpCore.doAction('CopyMessage', this.viewport.addRequestParams({ tofld: foldername }), uids, this.bcache.get('pollFC') || this.bcache.set('pollFC', this._pollFoldersCallback.bind(this)));
} else if (this.folder != foldername) {
// Don't allow drag/drop to the current folder.
- this.viewport.updateFlag(uids, 'deletedmsg', true);
+ this.updateFlag(uids, '\\deleted', true);
DimpCore.doAction('MoveMessage', this.viewport.addRequestParams({ tofld: foldername }), uids, this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)));
}
}
if (e.shiftKey) {
this.moveSelected((r.last().rownum == this.viewport.getMetaData('total_rows')) ? (r.first().rownum - 1) : (r.last().rownum + 1), true);
}
- this.flag('deleted', { index: r });
+ this.flag('imapflag', { imap: '\\deleted', index: r, set: true });
e.stop();
break;
}
var elt = e.element(),
- id, mbox, tmp;
+ id, tmp;
while (Object.isElement(elt)) {
id = elt.readAttribute('id');
this.composeMailbox(id == 'button_reply' ? 'reply' : 'forward');
break;
- case 'button_deleted':
case 'button_ham':
case 'button_spam':
this.flag(id.substring(7));
e.stop();
return;
+ case 'button_deleted':
+ this.flag('imapflag', { imap: '\\deleted', set: true });
+ e.stop();
+ return;
+
case 'button_other':
DimpCore.DMenu.trigger(e.findElement('A').next(), true);
e.stop();
this._expirePPCache(uids);
} else {
// Need this to catch spam deletions.
- this.viewport.updateFlag(search, 'deletedmsg', true);
+ this.updateFlag(search, '\\deleted', true);
}
}
},
},
/* Flag actions for message list. */
- // opts = 'index', 'mailbox', 'noserver' (only for answered/unanswered)
+ // opts = 'imap' 'index', 'mailbox', 'noserver' (only for answered/unanswered), 'set'
flag: function(action, opts)
{
var actionCall, args, vs,
- obs = [],
- unseenstatus = 1;
+ flags = [];
opts = opts || {};
if (opts.index) {
case 'allSeen':
DimpCore.doAction((action == 'allUnseen') ? 'MarkFolderUnseen' : 'MarkFolderSeen', { view: opts.mailbox }, null, this.bcache.get('flagAC') || this.bcache.set('flagAC', this._flagAllCallback.bind(this)));
if (opts.mailbox == this.folder) {
- this.viewport.updateFlag(this.createSelection('rownum', $A($R(1, this.viewport.getMetaData('total_rows')))), 'unseen', action == 'allUnseen');
+ this.updateFlag(this.createSelection('rownum', $A($R(1, this.viewport.getMetaData('total_rows')))), '\\seen', action != 'allUnseen');
}
break;
- case 'deleted':
- case 'undeleted':
case 'spam':
case 'ham':
case 'blacklist':
break;
}
- // Make sure that any given row is not deleted more than once.
- // Need to explicitly mark here because message may already be
- // flagged deleted when we load page (i.e. switching to using
- // trash folder).
- if (action == 'deleted') {
- vs = vs.search({ isdel: { not: [ true ] } });
- if (!vs.size()) {
- break;
- }
- vs.set({ isdel: true });
- }
-
args = this.viewport.addRequestParams({});
- if (action == 'deleted' || action == 'undeleted') {
- this.viewport.updateFlag(vs, 'deletedmsg', action == 'deleted'); }
- if (action == 'undeleted') {
- DimpCore.doAction('UndeleteMessage', args, vs);
- vs.set({ isdel: false });
- } else {
- actionCall = { deleted: 'DeleteMessage', spam: 'ReportSpam', ham: 'ReportHam', blacklist: 'Blacklist', whitelist: 'Whitelist' };
- // This needs to be synchronous Ajax if we are calling from a
- // popup window because Mozilla will not correctly call the
- // callback function if the calling window has been closed.
- DimpCore.doAction(actionCall[action], args, vs, this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)), { asynchronous: !(opts.index && opts.mailbox) });
-
- // If reporting spam, to indicate to the user that something is
- // happening (since spam reporting may not be instantaneous).
- if (action == 'spam' || action == 'ham') {
- this.msgListLoading(true);
- }
- }
- break;
+ actionCall = {
+ spam: 'ReportSpam',
+ ham: 'ReportHam',
+ blacklist: 'Blacklist',
+ whitelist: 'Whitelist'
+ };
- case 'unseen':
- case 'seen':
- if (!vs.size()) {
- break;
- }
- args = { view: this.folder, flags: [ '-\\seen' ].toJSON() };
- if (action == 'seen') {
- unseenstatus = 0;
- args.flags = [ '\\seen' ].toJSON();
- }
- obs = vs.get('dataob');
- if (obs.size()) {
- obs.each(function(s) {
- this.updateUnseenUID(s, unseenstatus);
- }, this);
- DimpCore.doAction('MarkMessage', args, this.viewport.createSelection('dataob', obs));
+ // This needs to be synchronous Ajax if we are calling from a
+ // popup window because Mozilla will not correctly call the
+ // callback function if the calling window has been closed.
+ DimpCore.doAction(actionCall[action], this.viewport.addRequestParams({}), vs, this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)), { asynchronous: !(opts.index && opts.mailbox) });
+
+ // If reporting spam, to indicate to the user that something is
+ // happening (since spam reporting may not be instantaneous).
+ if (action == 'spam' || action == 'ham') {
+ this.msgListLoading(true);
}
break;
- case 'flagged':
- case 'clear':
+ case 'imapflag':
if (!vs.size()) {
break;
}
- args = {
- view: this.folder,
- flags: [ ((action == 'flagged') ? '' : '-') + '\\flagged' ].toJSON()
- };
- this.viewport.updateFlag(vs, 'flagged', action == 'flagged');
- DimpCore.doAction('MarkMessage', args, vs);
- break;
- case 'answered':
- if (!vs.size()) {
+ flags = [ (opts.set ? '' : '-') + opts.imap ];
+
+ switch (opts.imap) {
+ case '\\deleted':
+ // Make sure that any given row is not deleted more than once.
+ // Need to explicitly mark here because message may already be
+ // flagged deleted when we load page (i.e. switching to using
+ // trash folder).
+ if (opts.set) {
+ vs = vs.search({ isdel: { not: [ true ] } });
+ if (!vs.size()) {
+ return;
+ }
+ vs.set({ isdel: true });
+ } else {
+ vs.set({ isdel: false });
+ }
+
+ this.updateFlag(vs, opts.imap, opts.set);
+ DimpCore.doAction(opts.set ? 'DeleteMessage' : 'UndeleteMessage', this.viewport.addRequestParams({}), vs, this.bcache.get('deleteC') || this.bcache.set('deleteC', this._deleteCallback.bind(this)), { asynchronous: !(opts.index && opts.mailbox) });
+ return;
+
+ case '\\seen':
+ vs.get('dataob').each(function(s) {
+ this.updateSeenUID(s, opts.set);
+ }, this);
break;
- }
- this.viewport.updateFlag(vs, 'answered', true);
- this.viewport.updateFlag(vs, 'flagged', false);
- if (!opts.noserver) {
- args = {
- view: this.folder,
- flags: [ '\\answered', '-\\flagged' ].toJSON()
- };
- DimpCore.doAction('MarkMessage', args, vs);
- }
- break;
- case 'unanswered':
- if (!vs.size()) {
+ case '\\answered':
+ if (opts.set) {
+ this.updateFlag(vs, '\\flagged', false);
+ flags.push('-\\flagged');
+ }
break;
}
- this.viewport.updateFlag(vs, 'answered', false);
+
+ this.updateFlag(vs, opts.imap, opts.set);
if (!opts.noserver) {
- args = {
- view: this.folder,
- flags: [ '-\\answered' ].toJSON()
- };
- DimpCore.doAction('MarkMessage', args, vs);
+ DimpCore.doAction('MarkMessage', { flags: flags.toJSON(), view: this.folder }, vs);
}
- break;
+ }
+ },
- case 'draft':
- case 'notdraft':
- if (!vs.size()) {
- break;
- }
- args = {
- view: this.folder,
- flags: [ ((action == 'draft') ? '' : '-') + '\\draft' ].toJSON()
- };
- this.viewport.updateFlag(vs, 'draft', action == 'draft');
- DimpCore.doAction('MarkMessage', args, vs);
- break;
+ isUnseen: function(r)
+ {
+ /* Unseen is a weird flag. Since we are doing a reverse match on this
+ * flag (knowing a message is SEEN is not as important as knowing the
+ * message lacks the SEEN FLAG), the presence of \\seen indicates that
+ * the message is in reality unseen. */
+ return r.flag.include('\\seen');
+ },
- case 'forwarded':
- this.viewport.updateFlag(vs, 'forwarded', true);
- break;
+ updateFlag: function(vs, flag, add)
+ {
+ /* See isUnseen() - if flag is \\seen, need to do the opposite
+ * action. */
+ if (flag == '\\seen') {
+ add = !add;
}
+
+ vs.get('dataob').each(function(ob) {
+ ob.flag = ob.flag.without(flag);
+ if (add) {
+ ob.flag.push(flag);
+ } else {
+ var r = $(ob.domid);
+ if (r) {
+ r.removeClassName(DIMP.conf.flags[flag].c);
+ }
+ }
+ this.updateStatusFlags(ob);
+ }, this);
},
updateStatusFlags: function(row)
{
- var elt = new Element('DIV'),
+ var bg = null,
+ f = document.createDocumentFragment(),
r = $(row.domid),
- s = r.down('.msgStatus'),
- tmp;
+ s;
- // Add attachment graphic
- if (row.atc) {
- tmp = 'status' + row.atc.capitalize();
- if (!s.down('.' + tmp)) {
- s.insert($(elt.cloneNode(false)).writeAttribute({ className: tmp, title: DIMP.conf.atc_list[row.atc] || null }));
- }
+ if (!r) {
+ return;
}
- this.flags.each(function(c) {
- tmp = 'status' + c.value;
- var d = s.down('.' + tmp);
- if (r.hasClassName(c.key)) {
- if (!d) {
- s.insert($(elt.cloneNode(false)).writeAttribute({ className: tmp, title: DIMP.text[tmp] || null }));
- }
- } else if (d) {
- d.remove();
+ s = r.down('.msgStatus');
+
+ row.flag.each(function(a) {
+ var ptr = DIMP.conf.flags[a];
+ if (!ptr.elt) {
+ ptr.elt = new Element('DIV', { className: 'msgflags ' + ptr.c, title: ptr.l });
+ }
+ r.addClassName(ptr.c);
+ f.appendChild(ptr.elt.cloneNode(false));
+ if (ptr.b) {
+ bg = ptr.b;
}
});
+
+ /* Clear existing flags. */
+ s.down().nextSiblings().invoke('remove');
+
+ s.appendChild(f);
+ r.setStyle({ background: bg });
},
/* Miscellaneous folder actions. */
/* Add popdown menus. Check for disabled compose at the same time. */
this._addMouseEvents({ id: 'button_other', type: 'otheractions' }, true);
DM.addSubMenu('ctx_message_reply', 'ctx_reply');
- DM.addSubMenu('ctx_message_setflag', 'ctx_flag');
- DM.addSubMenu('oa_setflag', 'ctx_flag');
- DM.addSubMenu('ctx_draft_setflag', 'ctx_flag');
+ [ 'ctx_message_', 'oa_', 'ctx_draft_' ].each(function(i) {
+ if ($(i + 'setflag')) {
+ DM.addSubMenu(i + 'setflag', 'ctx_flag');
+ DM.addSubMenu(i + 'unsetflag', 'ctx_flag');
+ }
+ });
if (DIMP.conf.disable_compose) {
$('button_reply', 'button_forward').compact().invoke('up', 'SPAN').concat($('button_compose', 'composelink', 'ctx_contacts_new')).compact().invoke('remove');
// By default, no context onShow action
contextOnShow: Prototype.emptyFunction,
- contextOnClick: function(id, elt)
+ contextOnClick: function(elt, base, submenu)
{
- switch (id) {
+ switch (elt.readAttribute('id')) {
case 'ctx_contacts_new':
this.compose('new', { to: elt.readAttribute('address') });
break;
c_nodes.push(this.template.evaluate(r));
}, this);
c.update(c_nodes.join(''));
-
- if (this.opts.onUpdateClass) {
- rows.get('dataob').each(function(d) {
- this.opts.onUpdateClass(d);
- }, this);
- }
} else {
// If loading a viewport for the first time, show a blank
// viewport rather than the empty viewport status message.
},
// vs = (Viewport_Selection) A Viewport_Selection object.
- // flag = (string) Flag name.
- // add = (boolean) Whether to set/unset flag.
- updateFlag: function(vs, flag, add)
- {
- this._updateFlag(vs, flag, add, this.isFiltering());
- this._updateClass(vs, flag, add);
- },
-
- // vs = (Viewport_Selection) A Viewport_Selection object.
- // flag = (string) Flag name.
- // add = (boolean) Whether to set/unset flag.
- // filter = (boolean) Are we filtering results?
- _updateFlag: function(vs, flag, add, filter)
- {
- vs.get('dataob').each(function(r) {
- if (add) {
- r.bg.push(flag);
- } else {
- r.bg = r.bg.without(flag);
- }
- if (filter) {
- this._updateFlag(this.createSelection('uid', r.vp_id, r.view), flag, add);
- }
- }, this);
- },
-
- // vs = (Viewport_Selection) A Viewport_Selection object.
- // flag = (string) Flag name.
+ // cname = (string) Class name.
// add = (boolean) Whether to set/unset flag.
- _updateClass: function(vs, flag, add)
+ _updateClass: function(vs, cname, add)
{
- var divs = vs.get('div'),
- sel = new ViewPort_Selection(this._getBuffer(), 'div', divs);
-
- divs.each(function(d) {
- if (add) {
- d.addClassName(flag);
- } else {
- d.removeClassName(flag);
- }
- }, this);
-
-
- if (this.opts.onUpdateClass) {
- sel.get('dataob').each(function(d) {
- this.opts.onUpdateClass(d);
- }, this);
- }
+ vs.get('div').invoke(add ? 'addClassName' : 'removeClassName', cname);
},
_getLineHeight: function()
case 'send_message':
this.button_pressed = false;
if (DIMP.baseWindow) {
- switch (d.reply_type) {
- case 'reply':
- DIMP.baseWindow.DimpBase.flag('answered', { index: d.index, mailbox: d.reply_folder, noserver: true });
- break;
-
- case 'forward':
- DIMP.baseWindow.DimpBase.flag('forwarded', { index: d.index, mailbox: d.reply_folder, noserver: true });
- break;
- }
-
+ DIMP.baseWindow.DimpBase.flag('imapflag', { imap: d.reply_type == 'reply' ? '\\answered' : '$forwarded', index: d.index, mailbox: d.reply_folder, noserver: true, set: true });
if (d.folder) {
DIMP.baseWindow.DimpBase.createFolder(d.folder);
--- /dev/null
+/**
+ * Provides the javascript for managing message flags.
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ */
+
+var ImpFlagmanagement = {
+ // Variables set by other code: new_prompt
+
+ addFlag: function()
+ {
+ var category = window.prompt(this.new_prompt, '');
+ if (category) {
+ this._sendData('add', category);
+ }
+ },
+
+ _sendData: function(a, d)
+ {
+ $('flag_action').setValue(a)
+ $('flag_data').setValue(d);
+ $('prefs').submit();
+ },
+
+ clickHandler: function(e)
+ {
+ if (e.isRightClick()) {
+ return;
+ }
+
+ var elt = e.element(), elt2, id;
+
+ while (Object.isElement(elt)) {
+ if (elt.hasClassName('flagcolorpicker')) {
+ elt2 = elt.previous('INPUT');
+ id = elt2.readAttribute('id');
+ new ColorPicker({
+ color: $F(elt2),
+ offsetParent: elt,
+ update: [[ id, 'value' ], [ id, 'background' ]]
+ });
+ e.stop();
+ return;
+ }
+
+ if (elt.hasClassName('flagdelete')) {
+ this._sendData('delete', elt.previous('INPUT').readAttribute('id'));
+ e.stop();
+ return;
+ }
+
+ switch (elt.readAttribute('id')) {
+ case 'new_button':
+ this.addFlag();
+ break;
+ }
+
+ elt = elt.up();
+ }
+ },
+
+ resetHandler: function()
+ {
+ $('prefs').getInputs('text').each(function(i) {
+ if (i.readAttribute('id').startsWith('color_')) {
+ i.setStyle({ backgroundColor: $F(i) });
+ }
+ });
+ }
+
+};
+
+document.observe('dom:loaded', function() {
+ var fm = ImpFlagmanagement;
+ document.observe('click', fm.clickHandler.bindAsEventListener(fm));
+ $('prefs').observe('reset', function() { fm.resetHandler.defer(); });
+});
case 'button_deleted':
case 'button_ham':
case 'button_spam':
- DIMP.baseWindow.DimpBase.flag(id.substring(7), { index: DIMP.conf.msg_index, mailbox: DIMP.conf.msg_folder });
+ if (id == 'button_deleted') {
+ DIMP.baseWindow.DimpBase.flag('imapflag', { imap: '\\deleted', index: DIMP.conf.msg_index, mailbox: DIMP.conf.msg_folder, set: true });
+ } else {
+ DIMP.baseWindow.DimpBase.flag(id.substring(7), { index: DIMP.conf.msg_index, mailbox: DIMP.conf.msg_folder });
+ }
window.close();
e.stop();
return;
parentfunc(e);
},
- contextOnClick: function(parentfunc, id, elt)
+ contextOnClick: function(parentfunc, elt, base, submenu)
{
+ var id = elt.readAttribute('id');
+
switch (id) {
case 'ctx_reply_reply':
case 'ctx_reply_reply_all':
break;
default:
- parentfunc(id, elt);
+ parentfunc(elt, base, submenu);
break;
}
},
* did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
*/
-var ImpMessage = {
+var ImpMailbox = {
// The following variables are defined in mailbox.php:
- // messagelist, sortlimit, unread
- keyId: null,
- startrange: null,
+ // sortlimit, unread
anySelected: function()
{
- return $H(this.messagelist).keys().detect(function(e) {
- return $('check' + e).checked;
- });
+ return $('messages').select('[name="indices[]"]').detect(Form.Element.getValue);
},
selectRow: function(id, select)
{
- var rid = $(id.replace(/check/, 'row'));
-
if (select) {
- rid.addClassName('selectedRow');
+ id.addClassName('selectedRow');
} else {
// Make sure to remove both regular and -over versions.
- rid.removeClassName('selectedRow').removeClassName('selectedRow-over');
+ id.removeClassName('selectedRow').removeClassName('selectedRow-over');
}
- $(id).checked = select;
+ id.down('INPUT.checkbox').setValue(select);
},
confirmDialog: function(url, msg)
$('messages').submit();
},
- makeSelection: function(form)
- {
- var flag = '';
-
- switch (parseInt(form)) {
- case -1:
- if ($('checkAll').checked) {
- flag = '!';
- }
- flag += IMP.conf.IMP_ALL;
- break;
-
- case 1:
- flag = $F('filter1');
- break;
-
- default:
- flag = $F('filter2');
- }
-
- // Fixes Bug #6893
- if (flag.empty()) {
- return;
- } else if (flag.startsWith('!')) {
- this.selectFlagged(parseInt(flag.substring(1)), false);
- } else if (flag.startsWith('+')) {
- this.selectFlagged(flag.substring(0, 1), null);
- } else {
- this.selectFlagged(parseInt(flag), true);
- }
-
- // Reset the form.
- switch (parseInt(form)) {
- case 1:
- $('select1').reset();
- break;
-
- default:
- $('select2').reset();
- }
- },
-
selectRange: function(e)
{
- var id = e.element().readAttribute('id'),
- checkbox = $(id),
- count = 0,
- checked, elts;
-
- if (!checkbox) {
- return;
- }
-
- checked = checkbox.checked;
-
- if (this.startrange !== null && e.shiftKey) {
- elts = [ $(this.startrange).readAttribute('id'), checkbox.readAttribute('id') ];
- $H(this.messagelist).keys().detect(function(r) {
- r = 'check' + r;
- if (elts.indexOf(r) != -1) {
- ++count;
+ // elt = checkbox element
+ var elt = e.element(),
+ tr = elt.up('TR'),
+ checked = $F(elt),
+ end, start;
+
+ if (this.startrange && e.shiftKey) {
+ if (this.startrange != elt) {
+ // Dirty trick - use position in page to determine which way
+ // to traverse
+ if (this.startrange.offsetTop < tr.offsetTop) {
+ start = this.startrange.next();
+ end = tr;
+ } else {
+ start = tr;
+ end = this.startrange.previous();
}
- if (count) {
- this.selectRow(r, checked);
- if (count == 2) {
- return true;
+
+ do {
+ this.selectRow(start, checked);
+ if (start == end) {
+ break;
}
- }
- }, this);
+ start = start.next();
+ } while (start);
+ }
} else {
- this.selectRow(id, checked);
+ this.selectRow(tr, checked);
}
- this.startrange = id;
+ this.startrange = tr;
},
updateFolders: function(form)
}
},
- // Put everything reliant on IMAP flags in this section.
- selectFlagged: function(flag, val)
- {
- $H(this.messagelist).keys().each(function(e) {
- var check, elt = $('check' + e);
- if (flag == '+') {
- check = !elt.checked;
- } else if (flag & this.messagelist[e]) {
- check = val;
- } else {
- check = !val;
- }
- this.selectRow(elt.id, check);
- }, this);
- },
-
flagMessages: function(form)
{
var f1 = $('flag1'), f2 = $('flag2');
if ((form == 1 && $F(f1) != "") ||
(form == 2 && $F(f2) != "")) {
if (this.anySelected()) {
- // Can't use $() here. See Bug #4736.
- document.messages.flag.value = (form == 1) ? $F(f1) : $F(f2);
+ $('messages').down('[name=flag]').setValue((form == 1) ? $F(f1) : $F(f2));
this.submit('flag_messages');
} else {
if (form == 1) {
{
var id = e.element().readAttribute('id');
- if (id.startsWith('filter')) {
- this.makeSelection(id.substring(6));
- } else if (id.startsWith('flag')) {
- this.flagMessages(id.substring(4));
- } else if (id.startsWith('targetMailbox')) {
- this.updateFolders(id.substring(13));
+ if (id) {
+ if (id.startsWith('flag')) {
+ this.flagMessages(id.substring(4));
+ } else if (id.startsWith('targetMailbox')) {
+ this.updateFolders(id.substring(13));
+ }
}
},
var elt = e.element(), id;
while (Object.isElement(elt)) {
- id = elt.readAttribute('id');
-
if (elt.match('.msgactions A.widget')) {
if (elt.hasClassName('moveAction')) {
this._transfer('move_messages');
e.stop();
return;
- } else if (!id) {
+ } else if (elt.hasClassName('checkbox')) {
+ this.selectRange(e);
+ // Fall through to elt.up() call below.
+ }
+
+ id = elt.readAttribute('id');
+ if (!id) {
elt = elt.up();
continue;
}
if (id == 'checkheader') {
$('checkAll').checked = !$('checkAll').checked;
}
- this.makeSelection(-1);
+
+ $('messages').select('TABLE.messageList TR[id]').each(function(i, s) {
+ this.selectRow(i, $F('checkAll'));
+ }, this);
return;
}
- if (id.startsWith('check') && elt.hasClassName('checkbox')) {
- this.selectRange(e);
- } else if (!this.sortlimit &&
- elt.match('TH') &&
- elt.up('TABLE.messageList')) {
+ if (!this.sortlimit &&
+ elt.match('TH') &&
+ elt.up('TABLE.messageList')) {
document.location.href = elt.down('A').href;
}
keyDownHandler: function(e)
{
- var o = e.element(),
+ var elt = e.element(),
key = e.keyCode,
- checkinc, loc, next, nextId, old, row, subjinc;
+ loc, search;
if (e.altKey || e.ctrlKey) {
- switch (key) {
- case Event.KEY_UP:
- checkinc = -1;
- subjinc = -1;
- break;
-
- case Event.KEY_DOWN:
- checkinc = 1;
- subjinc = 1;
- break;
-
- default:
+ if (!(key == Event.KEY_UP || key == Event.KEY_DOWN)) {
return;
}
- if (typeof this.messagelist == 'undefined') {
- return;
+ if (!this.cursor) {
+ this.cursor = elt.up('TABLE.messageList TR');
}
- if (o.id.indexOf('check') == 0 && o.tagName == 'INPUT') {
- old = o.id.substring(5);
- this.keyId = this.getMessage(old, checkinc);
- next = $('subject' + this.keyId);
- } else if (o.id.indexOf('subject') == 0 && o.tagName == 'A') {
- old = o.id.substring(7);
- this.keyId = this.getMessage(old, subjinc);
- next = $('subject' + this.keyId);
- } else {
- this.keyId = ((checkinc + subjinc) > 0) ? $H(this.messagelist).keys().first() : $H(this.messagelist).keys().last();
- if (Event.KEY_UP || Event.KEY_DOWN) {
- next = $('subject' + this.keyId);
+ if (this.cursor) {
+ if (e.altKey) {
+ this.selectRow(this.cursor, !$F(this.cursor.down('INPUT.checkbox')));
}
+
+ switch (key) {
+ case Event.KEY_UP:
+ this.cursor = this.cursor.previous();
+ if (!this.cursor.readAttribute('id')) {
+ search = 'last';
+ }
+ break;
+
+ case Event.KEY_DOWN:
+ this.cursor = this.cursor.next();
+ if (!this.cursor) {
+ search = 'first';
+ }
+ break;
+ }
+ } else {
+ search = Event.KEY_DOWN ? 'first' : 'last';
+ }
+
+ if (search) {
+ this.cursor = (search == 'first')
+ ? $('messages').select('TABLE.messageList TR[id]').first()
+ : $('messages').select('TABLE.messageList TR[id]').last();
}
- } else if (key == 32 &&
- o.id.indexOf('subject') == 0 &&
- o.tagName == 'A') {
- // Space key - toggle selection of the current message.
- this.startrange = 'check' + this.keyId;
- this.selectRow(this.startrange, !$(this.startrange).checked);
+
+ this.cursor.down('TD a.mboxSubject').focus();
+ } else if (key == 32 && this.cursor) {
+ this.selectRow(this.cursor, !$F(this.cursor.down('INPUT.checkbox')));
} else if (!e.shiftKey) {
if (key == Event.KEY_LEFT && $('prev')) {
- loc = $('prev').href;
+ loc = $('prev');
} else if (key == Event.KEY_RIGHT && $('next')) {
- loc = $('next').href;
+ loc = $('next');
}
if (loc) {
- document.location.href = loc;
+ document.location.href = loc.readAttribute('href');
}
return;
} else {
return;
}
- if (next) {
- next.focus();
- row = $('row' + this.keyId);
- if (e.altKey) {
- nextId = next.id.replace(/subject/, 'check');
- this.selectRow(nextId, !$(nextId).checked);
- } else if (old != next.id && row.className.indexOf('-over') == -1) {
- row.className += '-over';
- }
- if (old) {
- row = $('row' + old);
- if (old != next.id) {
- row.className = row.className.replace(/-over/, '');
- }
- }
- }
-
e.stop();
},
};
-document.observe('change', ImpMessage.changeHandler.bindAsEventListener(ImpMessage));
-document.observe('click', ImpMessage.clickHandler.bindAsEventListener(ImpMessage));
-document.observe('keydown', ImpMessage.keyDownHandler.bindAsEventListener(ImpMessage));
-document.observe('submit', ImpMessage.submitHandler.bindAsEventListener(ImpMessage));
+document.observe('dom:loaded', function() {
+ var im = ImpMailbox;
+
+ document.observe('change', im.changeHandler.bindAsEventListener(im));
+ document.observe('click', im.clickHandler.bindAsEventListener(im));
+ document.observe('keydown', im.keyDownHandler.bindAsEventListener(im));
+ document.observe('submit', im.submitHandler.bindAsEventListener(im));
-Event.observe(window, 'load', function() {
if (window.fluid) {
try {
- window.fluid.setDockBadge(ImpMessage.unread);
+ window.fluid.setDockBadge(ImpMailbox.unread);
} catch (e) {}
}
});
flagMessage: function(form)
{
var f1 = $('flag1'), f2 = $('flag2');
- if ((form == 1 && $F(f1)) ||
- (form == 2 && $F(f2))) {
- $('flag').setValue((form == 1) ? $F(f1) : $F(f2));
+
+ if ((form == 1 && $F(f1) != "") ||
+ (form == 2 && $F(f2) != "")) {
+ $('messages').down('[name=flag]').setValue((form == 1) ? $F(f1) : $F(f2));
this.submit('flag_message');
}
},
}
}
+ /* Generate flag array. */
+ $flags = array();
+ $imp_flags = &IMP_Imap_Flags::singleton();
+ foreach ($imp_flags->getList() as $val) {
+ $flags[$val['flag']] = array_filter(array(
+ 'b' => isset($val['b']) ? $val['b'] : null,
+ 'c' => $val['c'],
+ 'l' => $val['l']
+ ));
+ }
+
/* Variables used in core javascript files. */
$code['conf'] = array_filter(array(
'URI_DIMP_INBOX' => Horde::applicationUrl('index-dimp.php', true, -1),
'popup_width' => 820,
'popup_height' => 610,
+ 'flags' => $flags,
+
'spam_folder' => IMP::folderPref($prefs->getValue('spam_folder'), true),
'spam_reporting' => intval(!empty($conf['spam']['reporting'])),
'spam_spamfolder' => intval(!empty($conf['spam']['spamfolder'])),
'background_inbox' => intval(!empty($conf['dimp']['viewport']['background_inbox'])),
'splitbar_pos' => $prefs->getValue('dimp_splitbar'),
- 'atc_list' => IMP_UI_Mailbox::getAttachmentAltList(),
-
// Turn debugging on?
'debug' => intval(!empty($conf['dimp']['js']['debug'])),
));
'alog_message' => _("Message"),
'alog_success' => _("Success"),
'alog_warning' => _("Warning"),
- 'statusAnswered' => _("Replied"),
- 'statusForwarded' => _("Forwarded"),
- 'statusUnseen' => _("Unseen"),
- 'statusFlagged' => _("Flagged"),
));
/* Gettext strings with individual escaping. */
const PGP_SYM_ENCRYPT = 8;
const PGP_SYM_SIGNENC = 9;
- /* IMAP flag constants. */
- const FLAG_ALL = 0;
- const FLAG_UNSEEN = 1;
- const FLAG_DELETED = 2;
- const FLAG_ANSWERED = 4;
- const FLAG_FLAGGED = 8;
- const FLAG_DRAFT = 16;
- const FLAG_PERSONAL = 32;
- const FLAG_FORWARDED = 64;
-
/* IMP Mailbox view constants. */
const MAILBOX_START_FIRSTUNSEEN = 1;
const MAILBOX_START_LASTUNSEEN = 2;
(!empty($GLOBALS['conf']['hooks']['permsdenied']) ||
(self::hasPermission('create_folders') &&
self::hasPermission('max_folders')))) {
- $text .= '<option value="" disabled="disabled">- - - - - - - - -</option>' . "\n";
+ $text .= '<option value="" disabled="disabled">- - - - - - - -</option>' . "\n";
$text .= '<option value="*new*">' . _("New Folder") . "</option>\n";
- $text .= '<option value="" disabled="disabled">- - - - - - - - -</option>' . "\n";
+ $text .= '<option value="" disabled="disabled">- - - - - - - -</option>' . "\n";
}
/* Add the list of mailboxes to the lists. */
--- /dev/null
+<?php
+/**
+ * The IMP_Imap_Flags class provides an interface to deal with display of
+ * flags/labels on messages.
+ *
+ * Copyright 2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @package IMP
+ */
+class IMP_Imap_Flags
+{
+ /* IMAP flag prefix for IMP-specific flags. */
+ const PREFIX = '$IMPFlag';
+
+ /**
+ * Singleton instance.
+ *
+ * @var IMP_Imap_Flags
+ */
+ static protected $_instance;
+
+ /**
+ * The cached list of flags.
+ *
+ * @var array
+ */
+ protected $_flags = null;
+
+ /**
+ * Attempts to return a reference to a concrete object instance.
+ * It will only create a new instance if no instance currently exists.
+ *
+ * @return IMP_Imap_Flags The created concrete instance.
+ */
+ static public function singleton()
+ {
+ if (!isset(self::$_instance)) {
+ self::$_instance = new IMP_Imap_Flags();
+ }
+
+ return self::$_instance;
+ }
+
+ /**
+ * Save the flag list to the prefs backend.
+ */
+ protected function _save()
+ {
+ $GLOBALS['prefs']->setValue('msgflags', json_encode($this->_flags));
+ }
+
+ /**
+ * Return the raw list of flags.
+ *
+ * @param array $options Additional options:
+ * <pre>
+ * 'div' - (boolean) If true, return a DIV tag containing the code
+ * necessary to display the icon.
+ * DEFAULT: false
+ * 'fgcolor' - (boolean) If true, add foreground color information to be
+ * used for text overlay purposes.
+ * DEFAULT: false
+ * 'imap' - (boolean) If true, only return IMAP flags.
+ * DEFAULT: false
+ * 'mailbox' - (string) A real (not virtual) IMAP mailbox. If set, will
+ * determine what flags are available in the mailbox.
+ * DEFAULT: '' (no mailbox check)
+ * </pre>
+ *
+ * @return array An array of flag information (see 'msgflags' preference
+ * for format). If 'fgcolor' option is true, also adds
+ * a 'f' key to each entry with foreground color info.
+ * If 'div' option is true, adds a 'div' key with HTML
+ * text.
+ */
+ public function getList($options = array())
+ {
+ $this->_loadList();
+
+ $def_color = $GLOBALS['prefs']->getValue('msgflags_color');
+ $ret = $this->_flags;
+ $avail_flags = array_keys($ret);
+
+ if (!empty($options['imap'])) {
+ $types = array('imapp', 'imapu');
+ if (!$GLOBALS['prefs']->getValue('msgflags_hidesys')) {
+ $types[] = 'imap';
+ }
+ }
+
+ /* Reduce the list of flags for the mailbox depending on the return
+ * from the PERMANENTFLAGS IMAP response. */
+ if (!empty($options['mailbox'])) {
+ try {
+ $status = $GLOBALS['imp_imap']->ob->status($options['mailbox'], Horde_Imap_Client::STATUS_PERMFLAGS);
+ if (!in_array('\\*', $status['permflags'])) {
+ $avail_flags = array_intersect($avail_flags, $status['permflags']);
+ }
+ } catch (Horde_Imap_Client_Exception $e) {}
+ }
+
+ foreach ($avail_flags as $key) {
+ $ret[$key]['flag'] = $key;
+
+ if (!empty($options['fgcolor'])) {
+ $ret[$key]['f'] = '#000';
+ if (!isset($ret[$key]['b'])) {
+ $ret[$key]['b'] = $def_color;
+ } elseif (Horde_Image::brightness($this->_flags[$key]['b']) < 128) {
+ $ret[$key]['f'] = '#f6f6f6';
+ }
+ }
+
+ if (!empty($options['imap']) &&
+ !in_array($ret[$key]['t'], $types)) {
+ unset($ret[$key]);
+ } elseif (!empty($options['div']) && isset($ret[$key]['c'])) {
+ $ret[$key]['div'] = $this->_getDiv($ret[$key]['c'], $ret[$key]['l']);
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Loads the flag list from the preferences into the local cache.
+ */
+ protected function _loadList()
+ {
+ if (!is_null($this->_flags)) {
+ return;
+ }
+
+ $this->_flags = json_decode($GLOBALS['prefs']->getValue('msgflags'), true);
+
+ /* Sanity checking. */
+ if (!is_array($this->_flags)) {
+ $this->_flags = array();
+ $this->_save();
+ }
+ }
+
+ /**
+ * Add a user-defined IMAP flag.
+ *
+ * @param string $label The label to use for the new flag.
+ *
+ * @return string The IMAP flag name.
+ */
+ public function addFlag($label)
+ {
+ if (strlen($label) == 0) {
+ return;
+ }
+
+ $this->_loadList();
+
+ /* Flags are named PREFIX{$i}. Keep incrementing until we find the
+ * next available flag. */
+ for ($i = 0; ; ++$i) {
+ $curr = self::PREFIX . $i;
+ if (!isset($this->_flags[$curr])) {
+ $this->_flags[$curr] = array(
+ // 'a' => These flags are not shown in mimp
+ // TODO: Generate random background
+ 'b' => '#ffffff',
+ 'c' => 'flagUser',
+ 'd' => true,
+ 'l' => $label,
+ 't' => 'imapp'
+ );
+
+ $this->_save();
+ return $curr;
+ }
+ }
+ }
+
+ /**
+ * Updates a flag.
+ *
+ * @param string $label The flag label.
+ * @param array $data The data to update.
+ */
+ public function updateFlag($label, $data)
+ {
+ $this->_loadList();
+
+ if (isset($this->_flags[$label])) {
+ foreach ($data as $key => $val) {
+ $this->_flags[$label][$key] = $val;
+ }
+
+ $this->_save();
+ }
+ }
+
+ /**
+ * Delete a flag from the list.
+ *
+ * @param string $label The flag label.
+ *
+ * @return boolean True on success.
+ */
+ public function deleteFlag($label)
+ {
+ $this->_loadList();
+
+ if (isset($this->_flags[$label]) &&
+ $this->_flags[$label]['l'] &&
+ !empty($this->_flags[$label]['d'])) {
+ unset($this->_flags[$label]);
+ $this->_save();
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Parse a list of flag information.
+ *
+ * @param array $options Additional options:
+ * <pre>
+ * 'atc' - (Horde_Mime_Part) Attachment info. A Horde_Mime_Part object
+ * representing the message structure.
+ * DEFAULT: not parsed
+ * 'div' - (boolean) If true, return a DIV tag containing the code
+ * necessary to display the icon.
+ * DEFAULT: false
+ * 'flags' - (array) [REQUIRED] IMAP flag info. A lowercase list of flags
+ * returned by the IMAP server.
+ * 'personal' - (mixed) Personal message info. Either an array of to
+ * addresses as returned by
+ * Horde_Mime_Address::getAddressesFromObject(), or the
+ * identity that matched the address list..
+ * 'priority' - (string) Message priority. The content of the X-Priority
+ * header.
+ * </pre>
+ *
+ * @return array A list of flags with the following keys:
+ * <pre>
+ * 'abbrev' - (string) The abbreviation to use.
+ * 'bg' - (string) The background to use.
+ * 'classname' - (string) If set, the flag classname to use.
+ * 'flag' - (string) The matched flag (lowercase).
+ * 'div' - (string) A DIV HTML element, if 'div' option is true and a
+ * classname is defined.
+ * 'label' - (string) The label of the flag.
+ * </pre>
+ */
+ public function parse($options = array())
+ {
+ $this->_loadList();
+
+ $process = $ret = array();
+ $f = $this->_flags;
+
+ if (isset($options['personal'])) {
+ if (is_array($options['personal'])) {
+ require_once 'Horde/Identity.php';
+ $identity = Identity::singleton(array('imp', 'imp'));
+ foreach ($options['personal'] as $val) {
+ if ($identity->hasAddress($val['inner'])) {
+ $process['personal'] = $f['personal'];
+ break;
+ }
+ }
+ } else if (!is_null($options['personal'])) {
+ $process['personal'] = $f['personal'];
+ }
+ }
+
+ if (!empty($options['priority'])) {
+ $imp_msg_ui = new IMP_UI_Message();
+ switch ($imp_msg_ui->getXpriority($options['priority'])) {
+ case 'high':
+ $process['highpri'] = $f['highpri'];
+ break;
+
+ case 'low':
+ $process['lowpri'] = $f['lowpri'];
+ break;
+ }
+ }
+
+ if (!empty($options['atc'])) {
+ $imp_mbox_ui = new IMP_UI_Mailbox();
+ if ($type = $imp_ui->getAttachmentType($ob['structure']->getType())) {
+ $process[$type] = $f[$type];
+ }
+ }
+
+ if (($_SESSION['imp']['protocol'] == 'imap') &&
+ isset($options['flags'])) {
+ if (!empty($options['flags'])) {
+ $options['flags'] = array_map('strtolower', $options['flags']);
+ }
+
+ foreach ($f as $k => $v) {
+ if (in_array($v['t'], array('imap', 'imapp', 'imapu', 'imp'))) {
+ if (empty($v['n'])) {
+ $match = in_array($k, $options['flags']);
+ } elseif (empty($options['flags'])) {
+ $match = true;
+ } else {
+ $match = !in_array($k, $options['flags']);
+ }
+
+ if ($match) {
+ $process[$k] = $v;
+ }
+ }
+ }
+ }
+
+ $def_color = $GLOBALS['prefs']->getValue('msgflags_color');
+
+ foreach ($process as $key => $val) {
+ $tmp = array(
+ 'bg' => isset($val['b']) ? $val['b'] : $def_color,
+ 'flag' => $key,
+ 'label' => $val['l']
+ );
+
+ if (isset($val['a'])) {
+ $tmp['abbrev'] = $val['a'];
+ }
+
+ if (isset($val['c'])) {
+ $tmp['classname'] = $val['c'];
+ if (!empty($options['div'])) {
+ $tmp['div'] = $this->_getDiv($val['c'], $val['l']);
+ }
+ }
+
+ $ret[] = $tmp;
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Output a DIV element to display the icon.
+ *
+ * @param string $c A classname.
+ * @param string $l The flag label.
+ *
+ * @return string A HTML DIV element.
+ */
+ protected function _getDiv($c, $l)
+ {
+ return '<div class="msgflags ' . $c . '" title="' . htmlspecialchars($l) . '"></div>';
+ }
+
+}
* Build the array of message information.
*
* @param array $msgnum An array of message sequence numbers.
- * @param mixed $preview Include preview information? If empty, add no
- * preview information. If 1, uses value from
- * prefs. If 2, forces addition of preview info.
- * @param array $headers A list of non-standard (non-envelope) headers to
- * return.
+ * @param array $options Additional options:
+ * <pre>
+ * 'headers' - (array) A list of non-standard (non-envelope) headers to
+ * return.
+ * DEFAULT: Only envelope headers returned.
+ * 'preview' - (mixed) Include preview information? If empty, add no
+ * preview information. If 1, uses value from prefs.
+ * If 2, forces addition of preview info.
+ * DEFAULT: No preview information.
+ * 'structure' - (boolean) Get structure information from server.
+ * Contained in the 'strucutre' entry.
+ * DEFAULT: false
+ * </pre>
*
* @return array An array with the following keys:
* <pre>
- * 'overview' - (array) The overview information.
+ * 'overview' - (array) The overview information. Contains the following:
+ * 'envelope' - (array) Envelope information returned from
+ * the IMAP server. See
+ * Horde_Imap_Client::fetch() for format.
+ * 'flags' - (array) The list of IMAP flags returned from
+ * the server. See Horde_Imap_Client::fetch() for
+ * the format.
+ * 'headers' - (array) Any headers requested in
+ * $options['headers']. Horde_Mime_Headers objects
+ * are returned. See Horde_Imap_Client::fetch()
+ * for the format.
+ * 'mailbox' - (string) The mailbox containing the message.
+ * 'preview' - (string) If requested in $options['preview'],
+ * the preview text.
+ * 'previewcut'- (boolean) Has the preview text been cut?
+ * 'seq' - (integer) The sequence number of the message.
+ * 'size' - (integer) The size of the message in bytes.
+ * 'structure'- (array) The structure of the message. Only
+ * set if $options['structure'] is true. See
+ * Horde_Imap_Client::fetch() for format.
+ * 'uid' - (string) The unique ID of the message.
+ *
* 'uids' - (array) The array of UIDs. It is in the same format as used
* for IMP::parseIndicesList().
* </pre>
*/
- public function getMailboxArray($msgnum, $preview = false,
- $headers = array())
+ public function getMailboxArray($msgnum, $options = array())
{
$this->_buildMailbox();
Horde_Imap_Client::FETCH_SEQ => true
);
- if (!empty($headers)) {
- $fetch_criteria[Horde_Imap_Client::FETCH_HEADERS] = array(array('headers' => $headers, 'label' => 'imp', 'parse' => true, 'peek' => true));
+ if (!empty($options['headers'])) {
+ $fetch_criteria[Horde_Imap_Client::FETCH_HEADERS] = array(array('headers' => $options['headers'], 'label' => 'imp', 'parse' => true, 'peek' => true));
}
- $cache = $preview ? $GLOBALS['imp_imap']->ob->getCache() : null;
+ if (!empty($options['structure'])) {
+ $fetch_criteria[Horde_Imap_Client::FETCH_STRUCTURE] = array('parse' => true);
+ }
+
+ if (empty($options['preview'])) {
+ $cache = null;
+ $options['preview'] = 0;
+ } else {
+ $cache = $GLOBALS['imp_imap']->ob->getCache();
+ }
/* Retrieve information from each mailbox. */
foreach ($to_process as $mbox => $ids) {
try {
$fetch_res = $GLOBALS['imp_imap']->ob->fetch($mbox, $fetch_criteria, array('ids' => array_keys($ids)));
- if ($preview) {
+ if ($options['preview']) {
$preview_info = $tostore = array();
if ($cache) {
try {
$v['headers'] = $v['headers']['imp'];
}
- if ($preview &&
- (($preview === 2) ||
- !$GLOBALS['prefs']->getValue('preview_show_unread') ||
- !in_array('\\seen', $v['flags']))) {
+ if (($options['preview'] === 2) ||
+ !$GLOBALS['prefs']->getValue('preview_show_unread') ||
+ !in_array('\\seen', $v['flags'])) {
if (empty($preview_info[$k])) {
try {
$imp_contents = IMP_Contents::singleton($k . IMP::IDX_SEP . $mbox);
}
/**
- * The list of ALT text to use for mailbox display icons.
- *
- * @return array Type -> ALT text mappings.
- */
- static public function getAttachmentAltList()
- {
- return array(
- 'signed' => _("Message is signed"),
- 'encrypted' => _("Message is encrypted"),
- 'attachment' => _("Message has attachments")
- );
- }
-
- /**
* Return the icon to use for a given attachment.
*
- * @return string The mailbox display icon type.
+ * @return string The mailbox display icon type (attach, encrypt,
+ * signed).
*/
public function getAttachmentType($type)
{
return 'signed';
case 'encrypted':
- return 'encrypted';
+ return 'encrypt';
case 'alternative':
case 'related':
break;
default:
- return 'attachment';
+ return 'attach';
}
} elseif ($type == 'application/pkcs7-mime') {
- return 'encrypted';
+ return 'encrypt';
}
return '';
* to process.
* @param boolean $search Is this a search mbox?
*
- * @return array TODO
+ * @return array TODO
*/
private function _getOverviewData($imp_mailbox, $folder, $msglist, $search)
{
- $lookup = $msgs = array();
+ $msgs = array();
if (empty($msglist)) {
return $msgs;
require_once 'Horde/Identity.php';
/* Get mailbox information. */
- $overview = $imp_mailbox->getMailboxArray($msglist, false, array('list-post'));
+ $overview = $imp_mailbox->getMailboxArray($msglist, array('headers' => array('list-post', 'x-priority'), 'structure' => $GLOBALS['prefs']->getValue('atc_flag')));
$charset = NLS::getCharset();
$imp_ui = new IMP_UI_Mailbox($folder);
while (list(,$ob) = each($overview['overview'])) {
/* Initialize the header fields. */
$msg = array(
+ 'bg' => array('msgRow'),
+ 'flag' => array(),
'imapuid' => $ob['uid'],
'menutype' => 'message',
'rownum' => $ob['seq'],
);
/* Get all the flag information. */
- $bg = array('msgRow');
- if ($_SESSION['imp']['protocol'] != 'pop') {
- if (!in_array('\\seen', $ob['flags'])) {
- $bg[] = 'unseen';
- }
- if (in_array('\\answered', $ob['flags'])) {
- $bg[] = 'answered';
- }
- if (in_array('\\draft', $ob['flags'])) {
- $bg[] = 'draft';
- $msg['menutype'] = 'draft';
- $msg['draft'] = 1;
- }
- if (in_array('\\flagged', $ob['flags'])) {
- $bg[] = 'flagged';
- }
- if (in_array('\\deleted', $ob['flags'])) {
- $bg[] = 'deletedmsg';
- }
- if (in_array('$forwarded', $ob['flags'])) {
- $bg[] = 'forwarded';
- }
+ if (!empty($GLOBALS['conf']['hooks']['msglist_flags'])) {
+ $ob['flags'] = array_merge($ob['flags'], Horde::callHook('_imp_hook_msglist_flags', array($ob, 'dimp'), 'imp'));
}
- $msg['bg'] = $bg;
+ $imp_flags = &IMP_Imap_Flags::singleton();
+ $flag_parse = $imp_flags->parse(array(
+ 'atc' => isset($ob['structure']) ? $ob['structure'] : null,
+ 'flags' => $ob['flags'],
+ 'personal' => Horde_Mime_Address::getAddressesFromObject($ob['envelope']['to']),
+ 'priority' => $ob['headers']->getValue('x-priority')
+ ));
+
+ foreach ($flag_parse as $val) {
+ $msg['flag'][] = $val['flag'];
+ }
+
+ /* Specific flag checking. */
+ if (in_array('\\draft', $ob['flags'])) {
+ $msg['menutype'] = 'draft';
+ $msg['draft'] = 1;
+ }
/* Format size information. */
$msg['size'] = htmlspecialchars($imp_ui->getSize($ob['size']), ENT_QUOTES, $charset);
} else {
$msgs[$ob['uid']] = $msg;
}
-
- if (!isset($lookup[$ob['mailbox']])) {
- $lookup[$ob['mailbox']] = array();
- }
- $lookup[$ob['mailbox']][] = $ob['uid'];
- }
-
- /* Add user supplied information from hook. */
- if (!empty($GLOBALS['conf']['imp']['hooks']['msglist_format'])) {
- foreach (array_keys($lookup) as $mbox) {
- $ob_f = Horde::callHook('_imp_hook_msglist_format', array($mbox, $lookup[$mbox], 'dimp'), 'imp');
-
- foreach ($ob_f as $uid => $val) {
- if ($search) {
- $ptr = &$msgs[$uid . $mbox];
- } else {
- $ptr = &$msgs[$uid];
- }
-
- if (!empty($val['atc'])) {
- $ptr['atc'] = $val['atc'];
- }
-
- if (!empty($val['class'])) {
- $ptr['bg'] = array_merge($ptr['bg'], $val['class']);
- }
- }
- }
}
/* Allow user to alter template array. */
- if (!empty($GLOBALS['conf']['imp']['dimp']['hooks']['mailboxarray'])) {
- $msgs = Horde::callHook('_imp_hook_dimp_mailboxarray', array($msgs), 'imp');
+ if (!empty($GLOBALS['conf']['imp']['hooks']['mailboxarray'])) {
+ $msgs = Horde::callHook('_imp_hook_mailboxarray', array($msgs, 'dimp'), 'imp');
}
return $msgs;
/* Set the current time zone. */
NLS::setTimeZone();
- /* Get envelope/flag/header information. */
+ /* Get envelope/header information. We don't use flags in this
+ * view. */
try {
- $flags_ret = $GLOBALS['imp_imap']->ob->fetch($folder, array(
- Horde_Imap_Client::FETCH_FLAGS => true,
- ), array('ids' => array($index)));
- if (!isset($flags_ret[$index])) {
- $result['error'] = $error_msg;
- $result['errortype'] = 'horde.error';
- return $result;
- }
$fetch_ret = $GLOBALS['imp_imap']->ob->fetch($folder, array(
Horde_Imap_Client::FETCH_ENVELOPE => true,
Horde_Imap_Client::FETCH_HEADERTEXT => array(array('parse' => true, 'peek' => false))
return $GLOBALS['prefs']->setValue('nav_audio', Util::getFormData('nav_audio'));
}
+function handle_flagmanagement($updated)
+{
+ $imp_flags = &IMP_Imap_Flags::singleton();
+ $flag_action = Util::getFormData('flag_action');
+ $flag_data = Util::getFormData('flag_data');
+
+ if ($flag_action == 'add') {
+ $imp_flags->addFlag($flag_data);
+ return false;
+ }
+
+ $def_color = $GLOBALS['prefs']->getValue('msgflags_color');
+
+ // Don't set updated on these actions. User may want to do more actions.
+ foreach ($imp_flags->getList() as $key => $val) {
+ $md5 = hash('md5', $key);
+
+ switch ($flag_action) {
+ case 'delete':
+ if ($flag_data == ('bg_' . $md5)) {
+ $imp_flags->deleteFlag($key);
+ return false;
+ }
+ break;
+
+ default:
+ /* Change labels for user-defined flags. */
+ if ($val['t'] == 'imapp') {
+ $label = Util::getFormData('label_' . $md5);
+ if (strlen($label) && ($label != $val['l'])) {
+ $imp_flags->updateFlag($key, array('l' => $label));
+ }
+ }
+
+ /* Change background for all flags. */
+ $bg = strtolower(Util::getFormData('bg_' . $md5));
+ if ((isset($val['b']) && ($bg != $val['b'])) ||
+ (!isset($val['b']) && ($bg != $def_color))) {
+ $imp_flags->updateFlag($key, array('b' => $bg));
+ }
+ break;
+ }
+ }
+
+ return false;
+}
+
function prefs_callback()
{
global $prefs;
$imp_ui = new IMP_UI_Mailbox($imp_mbox['mailbox']);
/* Build the array of message information. */
-$mbox_info = $imp_mailbox->getMailboxArray(range($pageOb['begin'], $pageOb['end']));
+$mbox_info = $imp_mailbox->getMailboxArray(range($pageOb['begin'], $pageOb['end']), array('headers' => array('x-priority')));
/* Get thread information. */
$threadob = ($sortpref['by'] == Horde_Imap_Client::SORT_THREAD)
while (list(,$ob) = each($mbox_info['overview'])) {
/* Initialize the header fields. */
$msg = array(
- 'number' => $ob['seq'],
+ 'subject' => $imp_ui->getSubject($ob['envelope']['subject']),
'status' => ''
);
$msg['from'] = String::substr($msg['from'], 0, $conf['mimp']['mailbox']['max_from_chars']) . '...';
}
- $msg['subject'] = $imp_ui->getSubject($ob['envelope']['subject']);
-
if (!is_null($threadob) && ($threadob->getThreadIndent($ob['uid']))) {
$msg['subject'] = '>> ' . ltrim($msg['subject']);
}
$msg['subject'] = String::substr($msg['subject'], 0, $conf['mimp']['mailbox']['max_subj_chars']) . '...';
}
- /* Generate the target link. */
- $target = IMP::generateIMPUrl('message-mimp.php', $imp_mbox['mailbox'], $ob['uid'], $ob['mailbox']);
-
/* Get flag information. */
- if ($_SESSION['imp']['protocol'] != 'pop') {
- $to_ob = Horde_Mime_Address::getAddressesFromObject($ob['envelope']['to']);
- if (!empty($to_ob) && $identity->hasAddress($to_ob[0]['inner'])) {
- $msg['status'] .= '+';
- }
- if (!in_array('\\seen', $ob['flags'])) {
- $msg['status'] .= 'N';
- }
- if (in_array('\\answered', $ob['flags'])) {
- $msg['status'] .= 'r';
- }
- if (in_array('\\draft', $ob['flags'])) {
- $target = IMP::composeLink(array(), array('a' => 'd', 'thismailbox' => $imp_mbox['mailbox'], 'index' => $ob['uid'], 'bodypart' => 1));
- }
- if (in_array('\\flagged', $ob['flags'])) {
- $msg['status'] .= 'I';
- }
- if (in_array('\\deleted', $ob['flags'])) {
- $msg['status'] .= 'D';
- }
-
- /* Support for the pseudo-standard '$Forwarded' flag. */
- if (in_array('$forwarded', $ob['flags'])) {
- $msg['status'] .= 'F';
+ $imp_flags = &IMP_Imap_Flags::singleton();
+ $flag_parse = $imp_flags->parse(array(
+ 'flags' => $ob['flags'],
+ 'personal' => Horde_Mime_Address::getAddressesFromObject($ob['envelope']['to']),
+ 'priority' => $ob['headers']->getValue('x-priority')
+ ));
+
+ foreach ($flag_parse as $val) {
+ if (isset($val['abbrev'])) {
+ $msg['status'] .= $val['abbrev'];
}
}
- $msg['target'] = $target;
+ /* Generate the target link. */
+ $msg['target'] = in_array('\\draft', $ob['flags'])
+ ? IMP::composeLink(array(), array('a' => 'd', 'thismailbox' => $imp_mbox['mailbox'], 'index' => $ob['uid'], 'bodypart' => 1))
+ : IMP::generateIMPUrl('message-mimp.php', $imp_mbox['mailbox'], $ob['uid'], $ob['mailbox']);
+
$msgs[] = $msg;
}
* @author Michael Slusarz <slusarz@horde.org>
*/
-function _outputSummaries($msgs, $mbox, &$ids)
+function _outputSummaries($msgs, $mbox)
{
static $template;
- if (!empty($GLOBALS['conf']['hooks']['msglist_format'])) {
- $ob_f = Horde::callHook('_imp_hook_msglist_format', array($mbox, array_keys($msgs), 'imp'), 'imp');
-
- foreach ($ob_f as $uid => $val) {
- $ptr = &$msgs[$uid];
-
- if (!empty($val['class'])) {
- $ptr['bg'] = implode(' ', array_keys(array_flip(array_merge(explode(' ', $ptr['bg']), $val['class']))));
- }
-
- if (!empty($val['flagbits'])) {
- $ids[$ptr['id']] |= $val['flagbits'];
- }
-
- if (!empty($val['status'])) {
- $ptr['status'] .= $val['status'];
- }
- }
+ /* Allow user to alter template array. */
+ if (!empty($GLOBALS['conf']['imp']['hooks']['mailboxarray'])) {
+ $msgs = Horde::callHook('_imp_hook_mailboxarray', array($msgs, 'imp'), 'imp');
}
if (!isset($template)) {
echo $template->fetch(IMP_TEMPLATES . '/mailbox/mailbox.html');
}
+
require_once dirname(__FILE__) . '/lib/base.php';
/* Call the mailbox redirection hook, if requested. */
/* Set the current time zone. */
NLS::setTimeZone();
-/* Initialize the user's identities. */
-require_once 'Horde/Identity.php';
-$identity = Identity::singleton(array('imp', 'imp'));
-
$do_filter = false;
$open_compose_window = null;
$pageOb = $imp_mailbox->buildMailboxPage(Util::getFormData('page'), $start);
$show_preview = ($conf['mailbox']['show_preview'] && $prefs->getValue('preview_enabled'));
-$overview_headers = empty($conf['fetchmail']['show_account_colors'])
- ? array()
- : array('x-color');
-$mbox_info = $imp_mailbox->getMailboxArray(range($pageOb['begin'], $pageOb['end']), $show_preview, $overview_headers);
+$overview_headers = array('x-priority');
+if (empty($conf['fetchmail']['show_account_colors'])) {
+ $fetchmail = false;
+} else {
+ $fetchmail = true;
+ $overview_headers[] = 'x-color';
+}
+$mbox_info = $imp_mailbox->getMailboxArray(range($pageOb['begin'], $pageOb['end']), array('preview' => $show_preview, 'headers' => $overview_headers, 'structure' => $prefs->getValue('atc_flag')));
/* Determine sorting preferences. */
$sortpref = IMP::getSort();
if (!$search_mbox) {
$hdr_template->set('search', Horde::link(Util::addParameter(Horde::applicationUrl('search.php'), 'search_mailbox', $imp_mbox['mailbox']), sprintf(_("Search %s"), $rawtitle)) . Horde::img('search.png', _("Search"), '', $graphicsdir) . '</a>');
if (!$readonly) {
- $hdr_template->set('empty', Horde::link(Util::addParameter($mailbox_imp_url, array('actionID' => 'empty_mailbox', 'mailbox' => $imp_mbox['mailbox'], 'mailbox_token' => $mailbox_token)), _("Empty folder"), '', '', "ImpMessage.confirmDialog(this.href, '" . addslashes(_("Are you sure you wish to delete all mail in this folder?")) . "'); return false;") . Horde::img('empty_spam.png', _("Empty folder")) . '</a>');
+ $hdr_template->set('empty', Horde::link(Util::addParameter($mailbox_imp_url, array('actionID' => 'empty_mailbox', 'mailbox' => $imp_mbox['mailbox'], 'mailbox_token' => $mailbox_token)), _("Empty folder"), '', '', "ImpMailbox.confirmDialog(this.href, '" . addslashes(_("Are you sure you wish to delete all mail in this folder?")) . "'); return false;") . Horde::img('empty_spam.png', _("Empty folder")) . '</a>');
}
} else {
if ($imp_search->isEditableVFolder()) {
exit;
}
+$imp_flags = &IMP_Imap_Flags::singleton();
+
/* Display the navbar and actions if there is at least 1 message in mailbox. */
if ($pageOb['msgcount']) {
$use_trash = $prefs->getValue('use_trash');
$n_template->set('use_folders', $conf['user']['allow_folders']);
$n_template->set('readonly', $readonly);
$n_template->set('use_pop', $_SESSION['imp']['protocol'] == 'pop');
- $n_template->set('use_trash', $use_trash);
- $n_template->set('imp_all', IMP::FLAG_ALL);
- $n_template->set('imp_unseen', IMP::FLAG_UNSEEN);
- $n_template->set('imp_flagged', IMP::FLAG_FLAGGED);
- $n_template->set('imp_answered', IMP::FLAG_ANSWERED);
- $n_template->set('imp_deleted', IMP::FLAG_DELETED);
- $n_template->set('imp_draft', IMP::FLAG_DRAFT);
- $n_template->set('imp_personal', IMP::FLAG_PERSONAL);
- $n_template->set('imp_forwarded', IMP::FLAG_FORWARDED);
- if ($n_template->get('use_folders')) {
- $n_template->set('move', Horde::widget('#', _("Move to folder"), 'widget moveAction', '', '', _("Move"), true));
- $n_template->set('copy', Horde::widget('#', _("Copy to folder"), 'widget copyAction', '', '', _("Copy"), true));
- $n_template->set('folder_options', $folder_options);
+ if (!$n_template->get('use_pop')) {
+ $flaglist_set = $flaglist_unset = array();
+ foreach ($imp_flags->getList(array('imap' => true, 'mailbox' => $search_mbox ? null : $imp_mbox['mailbox'])) as $val) {
+ $tmp = array(
+ 'f' => $val['flag'],
+ 'l' => $val['l']
+ );
+
+ /* These entries are 'opposite' flag actions. */
+ if (isset($val['n'])) {
+ $flaglist_unset[] = $tmp;
+ $tmp['f'] = '0' . $val['flag'];
+ $flaglist_set[] = $tmp;
+ } else {
+ $flaglist_set[] = $tmp;
+ $tmp['f'] = '0' . $val['flag'];
+ $flaglist_unset[] = $tmp;
+ }
+ }
+
+ $n_template->set('flaglist_set', $flaglist_set);
+ $n_template->set('flaglist_unset', $flaglist_unset);
+
+ if ($n_template->get('use_folders')) {
+ $n_template->set('move', Horde::widget('#', _("Move to folder"), 'widget moveAction', '', '', _("Move"), true));
+ $n_template->set('copy', Horde::widget('#', _("Copy to folder"), 'widget copyAction', '', '', _("Copy"), true));
+ $n_template->set('folder_options', $folder_options);
+ }
}
+
$n_template->set('mailbox_url', $mailbox_url);
$n_template->set('mailbox', htmlspecialchars($imp_mbox['mailbox']));
if ($pageOb['pagecount'] > 1) {
}
}
-/* Cache some repetitively used variables. */
+/* Initialize repetitively used variables. */
$fromlinkstyle = $prefs->getValue('from_link');
$imp_ui = new IMP_UI_Mailbox($imp_mbox['mailbox']);
/* Display message information. */
-$ids = $msgs = array();
+$msgs = array();
$search_template = null;
while (list(,$ob) = each($mbox_info['overview'])) {
if ($search_mbox) {
if (empty($lastMbox) || ($ob['mailbox'] != $lastMbox)) {
if (!empty($lastMbox)) {
- _outputSummaries($msgs, $lastMbox, $ids);
+ _outputSummaries($msgs, $lastMbox);
$msgs = array();
}
$folder_link = Horde::url(Util::addParameter('mailbox.php', 'mailbox', $ob['mailbox']));
$lastMbox = $ob['mailbox'];
- /* Initialize the header fields. */
+ /* Initialize the data fields. */
$msg = array(
'bg' => '',
+ 'class' => '',
'color' => '',
'date' => htmlspecialchars($imp_ui->getDate($ob['envelope']['date'])),
'number' => $ob['seq'],
'preview' => '',
- 'size' => htmlspecialchars($imp_ui->getSize($ob['size'])),
'status' => '',
+ 'size' => htmlspecialchars($imp_ui->getSize($ob['size'])),
'uid' => htmlspecialchars($ob['uid'] . IMP::IDX_SEP . $ob['mailbox']),
);
$target = IMP::generateIMPUrl('message.php', $imp_mbox['mailbox'], $ob['uid'], $ob['mailbox']);
/* Get all the flag information. */
- $bg = array();
- $flagbits = 0;
-
- $to_ob = Horde_Mime_Address::getAddressesFromObject($ob['envelope']['to']);
- if (!empty($to_ob) && $identity->hasAddress($to_ob[0]['inner'])) {
- $msg['status'] .= Horde::img('mail_personal.png', _("Personal"), array('title' => _("Personal")));
- $flagbits |= IMP::FLAG_PERSONAL;
+ if (!empty($GLOBALS['conf']['hooks']['msglist_flags'])) {
+ $ob['flags'] = array_merge($ob['flags'], Horde::callHook('_imp_hook_msglist_flags', array($ob, 'imp'), 'imp'));
}
- if ($_SESSION['imp']['protocol'] != 'pop') {
- if (!in_array('\\seen', $ob['flags'])) {
- $flagbits |= IMP::FLAG_UNSEEN;
- $msg['status'] .= Horde::img('mail_unseen.png', _("Unseen"), array('title' => _("Unseen")));
- $bg[] = 'unseen';
- } else {
- $bg[] = 'seen';
- }
- if (in_array('\\answered', $ob['flags'])) {
- $flagbits |= IMP::FLAG_ANSWERED;
- $msg['status'] .= Horde::img('mail_answered.png', _("Answered"), array('title' => _("Answered")));
- $bg[] = 'answered';
- }
- if (in_array('\\draft', $ob['flags'])) {
- $flagbits |= IMP::FLAG_DRAFT;
- $msg['status'] .= Horde::img('mail_draft.png', _("Draft"), array('title' => _("Draft")));
- $target = IMP::composeLink(array(), array('actionID' => 'draft', 'thismailbox' => $ob['mailbox'], 'index' => $ob['uid']));
- }
- if (in_array('\\flagged', $ob['flags'])) {
- $flagbits |= IMP::FLAG_FLAGGED;
- $msg['status'] .= Horde::img('mail_flagged.png', _("Flagged For Followup"), array('title' => _("Flagged For Followup")));
- $bg[] = 'flagged';
- }
- if (in_array('\\deleted', $ob['flags'])) {
- $flagbits |= IMP::FLAG_DELETED;
- $msg['status'] .= Horde::img('mail_deleted.png', _("Deleted"), array('title' => _("Deleted")));
- $bg[] = 'deleted';
- }
+ $flag_parse = $imp_flags->parse(array(
+ 'atc' => isset($ob['structure']) ? $ob['structure'] : null,
+ 'div' => true,
+ 'flags' => $ob['flags'],
+ 'personal' => Horde_Mime_Address::getAddressesFromObject($ob['envelope']['to']),
+ 'priority' => $ob['headers']->getValue('x-priority')
+ ));
- /* Support for the pseudo-standard '$Forwarded' flag. */
- if (in_array('$forwarded', $ob['flags'])) {
- $flagbits |= IMP::FLAG_FORWARDED;
- $msg['status'] .= Horde::img('mail_forwarded.png', _("Forwarded"), array('title' => _("Forwarded")));
- $bg[] = 'forwarded';
+ foreach ($flag_parse as $val) {
+ if (isset($val['div'])) {
+ $msg['status'] .= $val['div'];
+ }
+ if (isset($val['classname'])) {
+ $msg['class'] = $val['classname'];
}
+ $msg['bg'] = $val['bg'];
}
- $ids[$msg['id']] = $flagbits;
- $msg['bg'] = implode(' ', $bg);
-
/* Show colors for fetchmail messages? */
- if (!empty($ob['headers']['x-color'])) {
- $msg['color'] = htmlspecialchars($color);
+ if ($fetchmail) {
+ $color = $ob['headers']->getValue('x-color');
+ if ($color) {
+ $msg['color'] = htmlspecialchars($color);
+ }
}
/* Show message preview? */
/* Format the Subject: Header. */
$msg['subject'] = $imp_ui->getSubject($ob['envelope']['subject'], true);
if ($preview_tooltip) {
- $msg['subject'] = substr(Horde::linkTooltip($target, $msg['preview'], '', '', '', $msg['preview']), 0, -1) . ' id="subject' . $msg['id'] . '">' . $msg['subject'] . '</a>';
+ $msg['subject'] = substr(Horde::linkTooltip($target, $msg['preview'], '', '', '', $msg['preview']), 0, -1) . ' class="mboxSubject">' . $msg['subject'] . '</a>';
} else {
- $msg['subject'] = substr(Horde::link($target, $msg['preview']), 0, -1) . ' id="subject' . $msg['id'] . '">' . $msg['subject'] . '</a>' . (!empty($msg['preview']) ? '<br /><small>' . $msg['preview'] . '</small>' : '');
+ $msg['subject'] = substr(Horde::link($target, $msg['preview']), 0, -1) . ' class="mboxSubject">' . $msg['subject'] . '</a>' . (!empty($msg['preview']) ? '<br /><small>' . $msg['preview'] . '</small>' : '');
}
/* Set up threading tree now. */
$msgs[$ob['uid']] = $msg;
}
-_outputSummaries($msgs, $lastMbox, $ids);
+_outputSummaries($msgs, $lastMbox);
/* Prepare the message footers template. */
$mf_template = new IMP_Template();
}
IMP::addInlineScript(array(
- 'ImpMessage.messagelist = ' . Horde_Serialize::serialize($ids, Horde_Serialize::JSON, NLS::getCharset()),
- 'ImpMessage.sortlimit = ' . intval($sortpref['limit']),
- 'ImpMessage.unread = ' . strval($unread)
+ 'ImpMailbox.sortlimit = ' . intval($sortpref['limit']),
+ 'ImpMailbox.unread = ' . strval($unread)
));
require $registry->get('templates', 'horde') . '/common-footer.inc';
$envelope = $fetch_ret[$index]['envelope'];
$flags = $flags_ret[$index]['flags'];
-$mime_headers = $fetch_ret[$index]['headertext'][0];
+$mime_headers = reset($fetch_ret[$index]['headertext']);
$use_pop = ($_SESSION['imp']['protocol'] == 'pop');
/* Parse the message. */
/* Set the status information of the message. */
$status = '';
-$identity = null;
-if (!$use_pop) {
- if (!empty($msgAddresses)) {
- $identity = $user_identity->getMatchingIdentity($msgAddresses);
- if (!is_null($identity) ||
- ($user_identity->getMatchingIdentity($msgAddresses, false) !== null)) {
- $status .= '+';
- }
- if (is_null($identity)) {
- $identity = $user_identity->getDefault();
- }
- }
+$match_identity = $identity = null;
- /* Set status flags. */
- if (!in_array('\\seen', $flags)) {
- $status .= 'N';
+if (!empty($msgAddresses)) {
+ $match_identity = $identity = $user_identity->getMatchingIdentity($msgAddresses);
+ if (is_null($identity)) {
+ $identity = $user_identity->getDefault();
}
- $flag_array = array(
- '\\answered' => 'r',
- '\\draft' => 'D',
- '\\flagged' => '!',
- '\\deleted' => 'd',
- /* Support for the pseudo-standard '$Forwarded' flag. */
- '$forwarded' => 'F'
- );
- foreach ($flag_array as $flag => $desc) {
- if (in_array($flag, $flags)) {
- $status .= $desc;
- }
+}
+
+$imp_flags = &IMP_Imap_Flags::singleton();
+$flag_parse = $imp_flags->parse(array(
+ 'flags' => $flags,
+ 'personal' => $match_identity
+));
+
+foreach ($flag_parse as $val) {
+ if (isset($val['abbrev'])) {
+ $status .= $val['abbrev'];
}
}
case 'flag_message':
$flag = Util::getFormData('flag');
- if ($flag) {
+ if ($flag && !empty($indices_array)) {
+ $set = true;
if ($flag[0] == '0') {
$flag = substr($flag, 1);
$set = false;
- } else {
- $set = true;
}
$imp_message->flag(array($flag), $indices_array, $set);
if ($prefs->getValue('mailbox_return')) {
switch ($imp_ui->getXpriority($xpriority)) {
case 'high':
$basic_headers['priority'] = _("Priority");
- $display_headers['priority'] = Horde::img('mail_priority_high.png', _("High Priority")) . ' ' . $xpriority;
+ $display_headers['priority'] = '<div class="msgflags flagHighpriority" title="' . htmlspecialchars(_("High Priority")) . '"></div>' . ' ' . $xpriority;
break;
case 'low':
$basic_headers['priority'] = _("Priority");
- $display_headers['priority'] = Horde::img('mail_priority_low.png', _("Low Priority")) . ' ' . $xpriority;
+ $display_headers['priority'] = '<div class="msgflags flagLowpriority" title="' . htmlspecialchars(_("Low Priority")) . '"></div>' . ' ' . $xpriority;
break;
}
/* Everything below here is related to preparing the output. */
if (!IMP::$printMode) {
/* Set the status information of the message. */
- $identity = $status = null;
- if (!$use_pop) {
- if (!empty($msgAddresses)) {
- $identity = $user_identity->getMatchingIdentity($msgAddresses);
- if (($identity !== null) ||
- $user_identity->getMatchingIdentity($msgAddresses, false) !== null) {
- $status .= Horde::img('mail_personal.png', _("Personal"), array('title' => _("Personal")));
- }
- if ($identity === null) {
- $identity = $user_identity->getDefault();
- }
- }
+ $identity = $match_identity = $status = null;
- /* Set status flags. */
- if (!in_array('\\seen', $flags)) {
- $status .= Horde::img('mail_unseen.png', _("Unseen"), array('title' => _("Unseen")));
+ if (!empty($msgAddresses)) {
+ $identity = $match_identity = $user_identity->getMatchingIdentity($msgAddresses);
+ if (is_null($identity)) {
+ $identity = $user_identity->getDefault();
}
- $flag_array = array(
- '\\answered' => _("Answered"),
- '\\draft' => _("Draft"),
- '\\flagged' => _("Flagged For Followup"),
- '\\deleted' => _("Deleted"),
- /* Support for the pseudo-standard '$Forwarded' flag. */
- '$forwarded' => _("Forwarded")
- );
- foreach ($flag_array as $flag => $desc) {
- if (in_array($flag, $flags)) {
- $status .= Horde::img('mail_' . ltrim($flag, '\\$') . '.png', $desc, array('title' => $desc));
- }
+ }
+
+ $imp_flags = &IMP_Imap_Flags::singleton();
+ $flag_parse = $imp_flags->parse(array(
+ 'div' => true,
+ 'flags' => $flags,
+ 'personal' => $match_identity
+ ));
+
+ foreach ($flag_parse as $val) {
+ if (isset($val['div'])) {
+ $status .= $val['div'];
}
}
$n_template->set('usepop', $use_pop);
$n_template->set('id', 1);
- if ($conf['user']['allow_folders']) {
- $n_template->set('move', Horde::widget('#', _("Move to folder"), 'widget moveAction', '', '', _("Move"), true));
- $n_template->set('copy', Horde::widget('#', _("Copy to folder"), 'widget copyAction', '', '', _("Copy"), true));
- $n_template->set('options', IMP::flistSelect(array('heading' => _("This message to"), 'new_folder' => true, 'inc_tasklists' => true, 'inc_notepads' => true)));
+ if (!$use_pop) {
+ $n_template->set('flaglist', $imp_flags->getList(array('imap' => true, 'mailbox' => $imp_mbox['mailbox'])));
+
+ if ($conf['user']['allow_folders']) {
+ $n_template->set('move', Horde::widget('#', _("Move to folder"), 'widget moveAction', '', '', _("Move"), true));
+ $n_template->set('copy', Horde::widget('#', _("Copy to folder"), 'widget copyAction', '', '', _("Copy"), true));
+ $n_template->set('options', IMP::flistSelect(array('heading' => _("This message to"), 'new_folder' => true, 'inc_tasklists' => true, 'inc_notepads' => true)));
+ }
}
$n_template->set('back_to', Horde::widget($mailbox_url, sprintf(_("Back to %s"), $h_page_label), 'widget', '', '', sprintf(_("Bac_k to %s"), $h_page_label), true));
echo $m_template->fetch(IMP_TEMPLATES . '/message/message.html');
if (!IMP::$printMode) {
- echo '<input type="hidden" name="flag" id="flag" value="" />';
$a_template->set('isbottom', true);
echo $a_template->fetch(IMP_TEMPLATES . '/message/navbar_actions.html');
if (!empty($ids)) {
$imp_ui = new IMP_UI_Mailbox($imp_mbox['mailbox']);
- $overview = $imp_mailbox->getMailboxArray(array_slice($ids, 0, 20), $conf['mailbox']['show_preview'] && $prefs->getValue('preview_enabled'));
+ $overview = $imp_mailbox->getMailboxArray(array_slice($ids, 0, 20), array('preview' => $conf['mailbox']['show_preview'] && $prefs->getValue('preview_enabled')));
foreach ($overview['overview'] as $ob) {
$from_addr = $imp_ui->getFrom($ob['envelope'], array('fullfrom' => true));
// Quota information
$show_quota = (isset($_SESSION['imp']['quota']) && is_array($_SESSION['imp']['quota']));
+// Get the list of available IMAP flags
+$imp_flags = &IMP_Imap_Flags::singleton();
+$flag_list = $imp_flags->getList(array('imap' => true));
+
// Small utility functions to simplify creating dimpactions buttons.
// As of right now, we don't show text only links.
function _createDA($text, $image, $id = null, $class = '', $show_text = true)
<div class="context" id="ctx_message" style="display:none">
<a id="ctx_message_reply"><span class="contextImg"></span><?php echo _("Reply") ?></a>
<a id="ctx_message_forward" class="sep"><span class="contextImg"></span><?php echo _("Forward") ?></a>
- <a id="ctx_message_setflag" class="sep"><span class="contextImg"></span><?php echo _("Mark as") ?></a>
+<?php if (!empty($flag_list)): ?>
+ <a id="ctx_message_setflag"><span class="contextImg"></span><?php echo _("Mark as") ?></a>
+ <a id="ctx_message_unsetflag" class="sep"><span class="contextImg"></span><?php echo _("Unmark as") ?></a>
+<?php endif; ?>
<?php if (!empty($conf['spam']['reporting'])): ?>
- <a id="ctx_message_spam"><span class="contextImg"></span><?php echo _("Mark as Spam") ?></a>
+ <a id="ctx_message_spam"><span class="contextImg"></span><?php echo _("Report as Spam") ?></a>
<?php endif; ?>
<?php if (!empty($conf['notspam']['reporting'])): ?>
- <a id="ctx_message_ham"><span class="contextImg"></span><?php echo _("Mark as Innocent") ?></a>
+ <a id="ctx_message_ham"><span class="contextImg"></span><?php echo _("Report as Innocent") ?></a>
<?php endif; ?>
<?php if ($has_blacklist): ?>
<a id="ctx_message_blacklist"><span class="contextImg"></span><?php echo _("Blacklist") ?></a>
<div class="context" id="ctx_draft" style="display:none">
<a id="ctx_draft_resume" class="sep"><span class="contextImg"></span><?php echo _("Resume Draft") ?></a>
- <a id="ctx_draft_setflag" class="sep"><span class="contextImg"></span><?php echo _("Mark as") ?></a>
+<?php if (!empty($flag_list)): ?>
+ <a id="ctx_draft_setflag"><span class="contextImg"></span><?php echo _("Mark as") ?></a>
+ <a id="ctx_draft_unsetflag" class="sep"><span class="contextImg"></span><?php echo _("Unmark as") ?></a>
+<?php endif; ?>
<a id="ctx_draft_deleted"><span class="contextImg"></span><?php echo _("Delete") ?></a>
<?php if (!$usetrash): ?>
<a id="ctx_draft_undeleted"><span class="contextImg"></span><?php echo _("Undelete") ?></a>
<div class="context" id="ctx_otheractions" style="display:none">
<a id="previewtoggle" class="sep"><span class="contextImg"></span><?php echo ($prefs->getValue('dimp_show_preview') ? _("Hide Preview") : _("Show Preview")); ?></a>
- <a id="oa_setflag" class="sep"><span class="contextImg"></span><?php echo _("Mark as") ?></a>
+<?php if (!empty($flag_list)): ?>
+ <a id="oa_setflag"><span class="contextImg"></span><?php echo _("Mark as") ?></a>
+ <a id="oa_unsetflag" class="sep"><span class="contextImg"></span><?php echo _("Unmark as") ?></a>
+<?php endif; ?>
<?php if ($has_blacklist || $has_whitelist): ?>
<?php if ($has_blacklist): ?>
<a id="oa_blacklist"<?php if (!$has_whitelist): ?> class="sep"<?php endif; ?>><span class="contextImg"></span><?php echo _("Blacklist") ?></a>
<?php endif; ?>
</div>
+<?php if (!empty($flag_list)): ?>
<div class="context" id="ctx_flag" style="display:none">
- <a id="flag_seen"><span class="contextImg"></span><?php echo _("Seen") ?></a>
- <a id="flag_unseen"><span class="contextImg"></span><?php echo _("Unseen") ?></a>
- <a id="flag_flagged"><span class="contextImg"></span><?php echo _("Flagged For Followup") ?></a>
- <a id="flag_clear"><span class="contextImg"></span><?php echo _("Not Flagged") ?></a>
- <a id="flag_answered"><span class="contextImg"></span><?php echo _("Answered") ?></a>
- <a id="flag_unanswered"><span class="contextImg"></span><?php echo _("Not Answered") ?></a>
- <a id="flag_draft"><span class="contextImg"></span><?php echo _("Draft") ?></a>
- <a id="flag_notdraft"><span class="contextImg"></span><?php echo _("Not Draft") ?></a>
+<?php foreach ($flag_list as $key => $val): ?>
+ <a flag="<?php echo htmlspecialchars($key) ?>"><span class="contextImg <?php echo htmlspecialchars($val['c']) ?>"></span><?php echo htmlspecialchars($val['l']) ?></a>
+<?php endforeach; ?>
</div>
+<?php endif; ?>
<div class="context" id="ctx_contacts" style="display:none">
<a id="ctx_contacts_new"><span class="contextImg"></span><?php echo _("New Message") ?></a>
'<div class="msgSubject" title="#{subject}">#{subject}</div>' +
'<div class="msgDate">#{date}</div>' +
'<div class="msgSize">#{size}</div>' +
- '<div class="clear"> </div>' +
'</div>';
$code = array(
/* Variables used in core javascript files. */
'conf' => array(
- 'IMP_ALL' => IMP::FLAG_ALL,
'isIE' => intval($GLOBALS['browser']->isBrowser('msie')),
'pop3' => intval((isset($_SESSION['imp']) && ($_SESSION['imp']['protocol'] == 'pop'))),
'fixed_folders' => empty($GLOBALS['conf']['server']['fixed_folders'])
<loop:messages>
- <tr id="row<tag:messages.id />" class="<tag:messages.bg />">
+ <tr id="row<tag:messages.id />"<if:messages.class> class="<tag:messages.class />"</if:messages.class><if:messages.bg> style="background-color:<tag:messages.bg />"</if:messages.bg>>
<td>
- <tag:overflow_begin /><label><input id="check<tag:messages.id />" type="checkbox" class="checkbox" name="indices[]" value="<tag:messages.uid />" /><tag:messages.status /> </label><tag:overflow_end />
+ <tag:overflow_begin /><label><input type="checkbox" class="checkbox" name="indices[]" value="<tag:messages.uid />" /><tag:messages.status /> </label><tag:overflow_end />
</td>
<td<if:messages.color> style="background:<tag:messages.color />"</if:messages.color>>
<tag:overflow_begin /><tag:messages.number /><tag:overflow_end />
<table width="100%" cellspacing="0">
<tr class="mboxcontrol">
<td<if:isbottom> class="bottomborder"</if:isbottom>>
+<if:readonly><else:readonly>
+<if:use_pop><else:use_pop>
<div class="leftFloat">
<form id="select<tag:id />">
<input type="hidden" name="mailbox" value="<tag:mailbox />" />
- <label for="filter<tag:id />" class="hidden"><gettext>Select:</gettext></label>
- <select id="filter<tag:id />" name="filter">
- <option value="" selected="selected"><gettext>Select:</gettext></option>
- <option value="!<tag:imp_all />"><gettext>All</gettext></option>
- <option value="<tag:imp_all />"><gettext>None</gettext></option>
- <option value="+<tag:imp_all />"><gettext>Invert</gettext></option>
- <option value="<tag:imp_personal />"><gettext>Personal</gettext></option>
- <option value="!<tag:imp_personal />"><gettext>Not Personal</gettext></option>
-<if:use_pop><else:use_pop>
- <option value="!<tag:imp_unseen />"><gettext>Seen</gettext></option>
- <option value="<tag:imp_unseen />"><gettext>Unseen</gettext></option>
- <option value="<tag:imp_flagged />"><gettext>Flagged For Followup</gettext></option>
- <option value="!<tag:imp_flagged />"><gettext>Not Flagged</gettext></option>
- <option value="<tag:imp_answered />"><gettext>Answered</gettext></option>
- <option value="!<tag:imp_answered />"><gettext>Unanswered</gettext></option>
- <option value="<tag:imp_forwarded />"><gettext>Forwarded</gettext></option>
- <option value="!<tag:imp_forwarded />"><gettext>Not Forwarded</gettext></option>
- <option value="<tag:imp_deleted />"><gettext>Deleted</gettext></option>
- <option value="!<tag:imp_deleted />"><gettext>Not Deleted</gettext></option>
- <option value="<tag:imp_draft />"><gettext>Draft</gettext></option>
- <option value="!<tag:imp_draft />"><gettext>Not Draft</gettext></option>
- </select>
-<if:readonly><else:readonly>
- <label for="flag<tag:id />" class="hidden"><gettext>Mark as:</gettext></label>
+ <label for="flag<tag:id />" class="hidden"><gettext>Mark Messages</gettext></label>
<select id="flag<tag:id />" name="flag">
- <option value="" selected="selected"><gettext>Mark as:</gettext></option>
- <option value="\seen"><gettext>Seen</gettext></option>
- <option value="0\seen"><gettext>Unseen</gettext></option>
- <option value="\flagged"><gettext>Flagged For Followup</gettext></option>
- <option value="0\flagged"><gettext>Not Flagged</gettext></option>
- <option value="\answered"><gettext>Answered</gettext></option>
- <option value="0\answered"><gettext>Unanswered</gettext></option>
-<if:use_trash><else:use_trash>
- <option value="\deleted"><gettext>Deleted</gettext></option>
- <option value="0\deleted"><gettext>Not Deleted</gettext></option>
-</else:use_trash></if:use_trash>
- <option value="\draft"><gettext>Draft</gettext></option>
- <option value="0\draft"><gettext>Not Draft</gettext></option>
-</else:use_pop></if:use_pop>
+ <option value="" selected="selected"><gettext>Mark Messages</gettext></option>
+ <option value="" disabled="disabled">- - - - - - - -</option>
+ <option value=""><gettext>Mark as:</gettext></option>
+<loop:flaglist_set>
+ <option value="<tag:flaglist_set.f />"> <tag:flaglist_set.l /></option>
+</loop:flaglist_set>
+ <option value="" disabled="disabled">- - - - - - - -</option>
+ <option value=""><gettext>Unmark as:</gettext></option>
+<loop:flaglist_unset>
+ <option value="<tag:flaglist_unset.f />"> <tag:flaglist_unset.l /></option>
+</loop:flaglist_unset>
</select>
-</else:readonly></if:readonly>
</form>
</div>
+</else:use_pop></if:use_pop>
<if:use_folders>
-<if:readonly><else:readonly>
<div class="leftFloat" style="padding-left:10px">
<form method="post" action="<tag:mailbox_url />">
<input type="hidden" name="mailbox" value="<tag:mailbox />" />
</select>
</form>
</div>
-</else:readonly></if:readonly>
</if:use_folders>
+</else:readonly></if:readonly>
<div class="rightFloat">
<if:multiple_page>
<form method="get" action="<tag:mailbox_url />">
<if:readonly><else:readonly>
<if:usepop><else:usepop>
<div class="leftFloat">
- <label for="flag<tag:id />" class="hidden"><gettext>Mark as:</gettext></label>
- <select id="flag<tag:id />" name="flag<tag:id />">
- <option value="" selected="selected"><gettext>Mark as:</gettext></option>
- <option value="0\seen"><gettext>Unseen</gettext></option>
- <option value="\flagged"><gettext>Flagged For Followup</gettext></option>
- <option value="0\flagged"><gettext>Not Flagged</gettext></option>
- <option value="\answered"><gettext>Answered</gettext></option>
- <option value="0\answered"><gettext>Unanswered</gettext></option>
- <option value="\draft"><gettext>Draft</gettext></option>
- <option value="0\draft"><gettext>Not Draft</gettext></option>
+ <form id="select<tag:id />">
+ <input type="hidden" name="mailbox" value="<tag:mailbox />" />
+ <label for="flag<tag:id />" class="hidden"><gettext>Mark Messages</gettext></label>
+ <select id="flag<tag:id />" name="flag">
+ <option value="" selected="selected"><gettext>Mark Messages</gettext></option>
+ <option value="" disabled="disabled">- - - - - - - -</option>
+ <option value=""><gettext>Mark as:</gettext></option>
+<loop:flaglist>
+ <option value="<tag:flaglist.flag />"> <tag:flaglist.l /></option>
+</loop:flaglist>
+ <option value="" disabled="disabled">- - - - - - - -</option>
+ <option value=""><gettext>Unmark as:</gettext></option>
+<loop:flaglist>
+ <option value="0<tag:flaglist.flag />"> <tag:flaglist.l /></option>
+</loop:flaglist>
</select>
+ </form>
</div>
-</else:usepop></if:usepop>
<if:move>
<div class="leftFloat msgActions">
<ul class="msgactions">
</select>
</div>
</if:move>
+</else:usepop></if:usepop>
</else:readonly></if:readonly>
<div class="rightFloat nowrap">
<tag:back_to />
<form method="post" id="messages" name="messages" action="<tag:message_url />">
<tag:form_input />
-<input type="hidden" id="targetMbox" name="targetMbox" value="" />
-<input type="hidden" id="actionID" name="actionID" value="" />
+<input type="hidden" id="targetMbox" name="targetMbox" />
+<input type="hidden" id="actionID" name="actionID" />
<input type="hidden" id="message_token" name="message_token" value="<tag:message_token />" />
<input type="hidden" name="mailbox" value="<tag:mailbox />" />
<input type="hidden" name="thismailbox" value="<tag:thismailbox />" />
<input type="hidden" name="start" value="<tag:start />" />
<input type="hidden" name="index" value="<tag:index />" />
-<input type="hidden" id="newMbox" name="newMbox" value="0" />
+<input type="hidden" id="newMbox" name="newMbox" />
+<input type="hidden" name="flag" />
<h1 class="header">
<tag:label /> <span style="unicode-bidi: embed"><tag:msg_count /></span> <tag:status />
</h1>
--- /dev/null
+<?php
+/* Add necessary javascript files. */
+Horde::addScriptFile('prototype.js', 'horde', true);
+Horde::addScriptFile('colorpicker.js', 'horde', true);
+Horde::addScriptFile('flagmanagement.js', 'imp', true);
+
+/* Get the list of flags. */
+$imp_flags = &IMP_Imap_Flags::singleton();
+$flaglist = $imp_flags->getList(array('div' => true, 'fgcolor' => true));
+
+/* Get the graphics. */
+$picker_img = Horde::img('colorpicker.png', _("Color Picker"), '', $registry->getImageDir('horde'));
+$delete_img = Horde::img('delete.png');
+
+IMP::addInlineScript(array(
+ 'ImpFlagmanagement.new_prompt = ' . Horde_Serialize::serialize(_("Please enter the label for the new flag:"), Horde_Serialize::JSON, NLS::getCharset())
+));
+
+?>
+<input type="hidden" name="flag_action" id="flag_action" />
+<input type="hidden" name="flag_data" id="flag_data" />
+<input id="new_button" type="button" class="button" value="<?php echo _("New Flag") ?>" />
+<table>
+<?php foreach ($flaglist as $key => $val):
+ $hash = hash('md5', $key);
+ $bgid = 'bg_' . $hash;
+ $color = htmlspecialchars($val['b']);
+ $fgcolor = htmlspecialchars($val['f']);
+ $label = htmlspecialchars($val['l']);
+ $bgstyle = 'background-color:' . $color . ';color:' . $fgcolor;
+?>
+ <tr>
+<?php if ($val['t'] == 'imapp'): ?>
+ <td><input style="<?php echo $bgstyle ?>" name="<?php echo 'label_' . $hash ?>" value="<?php echo $label ?>" /></td>
+<?php else: ?>
+ <td style="<?php echo $bgstyle ?>"><strong><?php echo Horde::label($bgid, $label) ?></strong></td>
+<?php endif; ?>
+ <td>
+<?php if (isset($val['div'])) { echo $val['div']; } ?>
+ </td>
+ <td>
+ <input size="7" style="background:<?php echo $color ?>;color:<?php echo $fgcolor ?>" id="<?php echo $bgid ?>" name="<?php echo $bgid ?>" value="<?php echo $color ?>" />
+ <a class="flagcolorpicker" href="#"><?php echo $picker_img ?></a>
+<?php if (!empty($val['d'])): ?>
+ <a class="flagdelete" href="#"><?php echo $delete_img ?></a>
+<?php endif; ?>
+ </td>
+ </tr>
+<?php endforeach; ?>
+</table>
}
/* Columns */
-div.msgStatus, div.msgFrom, div.msgSubject, div.msgDate, div.msgSize {
- float: left;
- overflow: hidden;
-}
div.msgStatus {
+ float: left;
width: 8%;
}
div.msgStatus div, #msgHeadersContent .subject span {
vertical-align: inherit;
}
div.msgFrom {
+ float: left;
width: 20%;
}
div.msgSubject {
+ float: left;
width: 52%;
}
div.msgDate {
+ float: left;
width: 14%;
}
div.msgSize {
+ float: left;
width: 6%;
}
}
/* Rows */
-.msglist div.msgRow, .msglist div div {
+.msglist div.msgRow, .msglist div.msgRow div {
cursor: pointer;
font-size: 95%;
white-space: nowrap;
height: 16px;
margin-bottom: 1px;
}
-/* Flags */
-.msglist div.unseen {
- font-weight: bold;
-}
-.msglist div.important {
- background: #fcc;
-}
-.msglist div.answered {
- background: #cfc;
-}
-.msglist div.forwarded {
- background: #add;
-}
-.msglist div.flagged {
- background: #fcc;
-}
-.msglist div.unimportant {
- font-weight: normal;
-}
-.msglist div.deletedmsg {
- background: #999;
-}
-.msglist div.deletedmsg div.msgFrom, .msglist div.deletedmsg div.msgSubject, .msglist div.deletedmsg div.msgDate, .msglist div.deletedmsg div.msgSize {
- text-decoration: line-through;
-}
.msglist div.selectedRow {
- background: #ffc;
+ background: #ffc !important;
}
/* Checkbox images */
background-image: url("graphics/checkbox_on.png");
}
-/* Status images and flags selectors */
-.msglist div.statusUnseen {
- background-image: url("graphics/mail_unseen.png");
-}
-.msglist div.statusFlagged {
- background-image: url("graphics/mail_flagged.png");
-}
-.msglist div.statusDeleted {
- background-image: url("graphics/mail_deleted.png");
-}
-.msglist div.statusLowPriority, #msgHeadersContent span.statusLowPriority {
- background-image: url("graphics/mail_priority_low.png");
-}
-.msglist div.statusHighPriority, #msgHeadersContent span.statusHighPriority {
- background-image: url("graphics/mail_priority_high.png");
-}
-.msglist div.statusAnswered {
- background-image: url("graphics/mail_answered.png");
-}
-.msglist div.statusForwarded {
- background-image: url("graphics/mail_forwarded.png");
-}
-.msglist div.statusDraft {
- background-image: url("graphics/mail_draft.png");
-}
-.msglist div.statusAttachment {
- background-image: url("graphics/attachment.png");
-}
-.msglist div.statusEncrypted {
- background-image: url("graphics/encrypted.png");
-}
-.msglist div.statusSigned {
- background-image: url("graphics/signed.png");
-}
-
/* Scroller */
.sbdiv {
position: relative;
right: 0;
width: 14px;
overflow: hidden;
- background-image: url("graphics/scroller_back.png");
- background-repeat: repeat-y;
+ background: url("graphics/scroller_back.png") repeat-y;
}
.sbcursor {
width: 13px;
border-left: 1px solid silver;
- background-image: url("graphics/scroller.png");
- background-repeat: repeat-y;
+ background: url("graphics/scroller.png") repeat-y;
}
.sbup {
width: 13px;
#ctx_message_undeleted span.contextImg, #ctx_draft_undeleted span.contextImg, #oa_undeleted span.contextImg {
background-image: url("graphics/undelete.png");
}
-#flag_seen span.contextImg, #ctx_folder_seen span.contextImg {
+#ctx_folder_seen span.contextImg {
background-image: url("graphics/mail_seen.png");
}
-#flag_unseen span.contextImg, #ctx_folder_unseen span.contextImg, #ctx_folder_poll span.contextImg, #ctx_folder_nopoll span.contextImg {
+#ctx_folder_unseen span.contextImg, #ctx_folder_poll span.contextImg, #ctx_folder_nopoll span.contextImg {
background-image: url("graphics/mail_unseen.png");
}
-#ctx_message_setflag span.contextImg, #ctx_draft_setflag span.contextImg, #oa_setflag span.contextImg, #flag_flagged span.contextImg {
+#ctx_message_setflag span.contextImg, #ctx_draft_setflag span.contextImg, #oa_setflag span.contextImg {
background-image: url("graphics/mail_flagged.png");
}
-#flag_clear span.contextImg {
+#ctx_message_unsetflag span.contextImg, #ctx_draft_unsetflag span.contextImg, #oa_unsetflag span.contextImg {
background-image: url("graphics/mail_clearflag.png");
}
-#flag_answered span.contextImg {
- background-image: url("graphics/mail_answered.png");
-}
-#flag_unanswered span.contextImg {
- background-image: url("graphics/mail_notanswered.png");
-}
-#flag_draft span.contextImg, #ctx_draft_resume span.contextImg {
+#ctx_draft_resume span.contextImg {
background-image: url("graphics/mail_draft.png");
}
-#flag_notdraft span.contextImg {
- background-image: url("graphics/mail_notdraft.png");
-}
#previewtoggle span.contextImg {
background-image: url("graphics/preview.png");
}
.seen {
background: #fff;
}
-.seen:hover, .seen-over {
- background: #f3f3f3;
+
+/* Message flags definitions.
+ * For background color, see config/prefs.php [msgflags preference]. */
+div.msgflags {
+ display: -moz-inline-stack;
+ display: inline-block;
+ padding-right: 2px;
+ width: 16px;
+ height: 16px;
+ background-repeat: no-repeat;
+ vertical-align: inherit;
}
-.unseen {
- font-weight: bold;
- background: #eef;
+.header div.msgflags {
+ vertical-align: sub;
}
-tr.unseen:hover, tr.unseen-over {
- font-weight: bold;
- background: #ccf;
+
+div.msgflags.flagPersonal {
+ background-image: url("graphics/mail_personal.png");
+}
+div.msgflags.flagHighpriority {
+ background-image: url("graphics/mail_priority_high.png");
+}
+tr.flagLowpriority, div.msgRow.flagLowpriority {
+ font-weight: normal !important;
}
-.answered {
- background: #cfc;
+div.msgflags.flagLowpriority {
+ background-image: url("graphics/mail_priority_low.png");
}
-tr.answered:hover, tr.answered-over {
- background: #9e9;
+div.msgflags.flagSignedmsg {
+ background-image: url("graphics/signed.png");
}
-.forwarded {
- background: #add;
+div.msgflags.flagEncryptmsg {
+ background-image: url("graphics/encrypted.png");
}
-tr.forwarded:hover, tr.forwarded-over {
- background: #8bd;
+div.msgflags.flagAttachmsg {
+ background-image: url("graphics/attachment.png");
}
-.important, .flagged {
- background: #fcc;
+tr.flagUnseen, div.msgRow.flagUnseen {
+ font-weight: bold;
}
-tr.important:hover, tr.important-over, tr.flagged:hover, tr.flagged-over {
- background: #faa;
+div.msgflags.flagUnseen, span.contextImg.flagUnseen {
+ background-image: url("graphics/mail_unseen.png");
}
-.unimportant {
- font-weight: normal;
+div.msgflags.flagAnswered, span.contextImg.flagAnswered {
+ background-image: url("graphics/mail_answered.png");
}
-.deleted {
- background: #999;
+div.msgflags.flagDraft, span.contextImg.flagDraft {
+ background-image: url("graphics/mail_draft.png");
}
-tr.deleted:hover, tr.deleted-over {
- background: #777;
+div.msgflags.flagFlagged, span.contextImg.flagFlagged {
+ background-image: url("graphics/mail_flagged.png");
}
-.deleted * {
+tr.flagDeleted *, div.msgRow.flagDeleted {
text-decoration: line-through;
}
+div.msgflags.flagDeleted, span.contextImg.flagDeleted {
+ background-image: url("graphics/mail_deleted.png");
+}
+div.msgflags.flagForwarded, span.contextImg.flagForwarded {
+ background-image: url("graphics/mail_forwarded.png");
+}
+
.folderunsub {
background: #bbb;
font-style: italic;
-.msglist div.statusDeleted {
- background-image: url("graphics/mail_deleted.png");
-}
-.msglist div.statusForwarded, #hordeAlerts div.imp-forward, #hordeAlerts div.imp-redirect {
+#hordeAlerts div.imp-forward, #hordeAlerts div.imp-redirect {
background-image: url("graphics/mail_forwarded.png");
}
-.msglist div.statusLowPriority {
- background-image: url("graphics/mail_priority_low.png");
-}
-.msglist div.statusHighPriority {
- background-image: url("graphics/mail_priority_high.png");
-}
-.msglist div.statusAttachment {
- background-image: url("graphics/attachment.png");
-}
-.msglist div.statusEncrypted {
- background-image: url("graphics/encrypted.png");
-}
-.msglist div.statusSigned {
- background-image: url("graphics/signed.png");
-}
-
#sidebarPanel .base {
background-image: url("graphics/folder.png");
#ctx_message_undeleted span.contextImg, #ctx_draft_undeleted span.contextImg, #oa_undeleted span.contextImg {
background-image: url("graphics/undelete.png");
}
-#flag_seen span.contextImg, #ctx_folder_seen span.contextImg {
+#ctx_folder_seen span.contextImg {
background-image: url("graphics/mail_seen.png");
}
-.msglist div.statusUnseen, #flag_unseen span.contextImg, #ctx_folder_unseen span.contextImg, #ctx_folder_poll span.contextImg, #ctx_folder_nopoll span.contextImg {
+#ctx_folder_unseen span.contextImg, #ctx_folder_poll span.contextImg, #ctx_folder_nopoll span.contextImg {
background-image: url("graphics/mail_unseen.png");
}
-.msglist div.statusFlagged, #ctx_message_setflag span.contextImg, #ctx_draft_setflag span.contextImg, #oa_setflag span.contextImg, #flag_flagged span.contextImg {
+#ctx_message_setflag span.contextImg, #ctx_draft_setflag span.contextImg, #oa_setflag span.contextImg {
background-image: url("graphics/mail_flagged.png");
}
-#flag_clear span.contextImg {
+#ctx_message_unsetflag span.contextImg, #ctx_draft_unsetflag span.contextImg, #oa_unsetflag span.contextImg {
background-image: url("graphics/mail_clearflag.png");
}
-.msglist div.statusAnswered, #hordeAlerts div.imp-reply, #flag_answered span.contextImg {
+#hordeAlerts div.imp-reply {
background-image: url("graphics/mail_answered.png");
}
-#flag_unanswered span.contextImg {
- background-image: url("graphics/mail_notanswered.png");
-}
-.msglist div.statusDraft, #flag_draft span.contextImg, #ctx_draft_resume span.contextImg {
+#ctx_draft_resume span.contextImg {
background-image: url("graphics/mail_draft.png");
}
-#flag_notdraft span.contextImg {
- background-image: url("graphics/mail_notdraft.png");
-}
#previewtoggle span.contextImg {
background-image: url("graphics/preview.png");
}
span.spellcheckPopdownImg {
background-image: url("graphics/popdown.png");
}
+
+div.msgflags.flagPersonal {
+ background-image: url("graphics/mail_personal.png");
+}
+div.msgflags.flagHighpriority {
+ background-image: url("graphics/mail_priority_high.png");
+}
+div.msgflags.flagLowpriority {
+ background-image: url("graphics/mail_priority_low.png");
+}
+div.msgflags.flagSignedmsg {
+ background-image: url("graphics/signed.png");
+}
+div.msgflags.flagEncryptmsg {
+ background-image: url("graphics/encrypted.png");
+}
+div.msgflags.flagAttachmsg {
+ background-image: url("graphics/attachment.png");
+}
+div.msgflags.flagUnseen, span.contextImg.flagUnseen {
+ background-image: url("graphics/mail_unseen.png");
+}
+div.msgflags.flagAnswered, span.contextImg.flagAnswered {
+ background-image: url("graphics/mail_answered.png");
+}
+div.msgflags.flagDraft, span.contextImg.flagDraft {
+ background-image: url("graphics/mail_draft.png");
+}
+div.msgflags.flagFlagged, span.contextImg.flagFlagged {
+ background-image: url("graphics/mail_flagged.png");
+}
+div.msgflags.flagDeleted, span.contextImg.flagDeleted {
+ background-image: url("graphics/mail_deleted.png");
+}
+div.msgflags.flagForwarded, span.contextImg.flagForwarded {
+ background-image: url("graphics/mail_forwarded.png");
+}