Add draft flagging to DIMP.
authorMichael M Slusarz <slusarz@curecanti.org>
Wed, 11 Feb 2009 05:27:27 +0000 (22:27 -0700)
committerMichael M Slusarz <slusarz@curecanti.org>
Wed, 11 Feb 2009 05:45:05 +0000 (22:45 -0700)
imp/ajax.php
imp/docs/CHANGES
imp/js/src/DimpBase.js
imp/js/src/compose-dimp.js
imp/js/src/fullmessage-dimp.js
imp/templates/index/index-dimp.inc
imp/themes/graphics/mail_notdraft.png [new file with mode: 0644]
imp/themes/screen-dimp.css
imp/themes/silver/graphics/mail_notdraft.png [new file with mode: 0644]
imp/themes/silver/screen-dimp.css

index ac4f6c5..098d04f 100644 (file)
@@ -375,19 +375,29 @@ case 'CopyMessage':
     break;
 
 case 'MarkMessage':
-    $flag = Util::getPost('messageFlag');
-    if (!$flag || empty($indices)) {
+    $flags = Util::getPost('flags');
+    if (!$flags || empty($indices)) {
         break;
     }
-    if ($flag[0] == '-') {
-        $flag = substr($flag, 1);
-        $set = false;
-    } else {
-        $set = true;
+    $flags = Horde_Serialize::unserialize($flags, SERIALIZE_JSON);
+
+    $set = $notset = array();
+    foreach ($flags as $val) {
+        if ($val[0] == '-') {
+            $notset[] = substr($val, 1);
+        } else {
+            $set[] = $val;
+        }
     }
 
     $imp_message = IMP_Message::singleton();
-    $result = $imp_message->flag(array($flag), $indices, $set);
+    if (!empty($set)) {
+        $result = $imp_message->flag($set, $indices, true);
+    }
+    if (!empty($notset)) {
+        $result = $imp_message->flag($notset, $indices, false);
+    }
+
     if ($result) {
         $result = new stdClass;
     }
index 65a9375..309cb93 100644 (file)
@@ -2,6 +2,7 @@
 v5.0-git
 --------
 
+[mms] Add full IMAP message flagging capabilities to DIMP.
 [mms] Decode IDN (RFC 3490) names in addresses (Request #5836).
 [mms] Add ability to download attachments in MIMP (Request #2925).
 [mms] Revamp JS event handling model.
index 2d97cb6..e2c1af1 100644 (file)
@@ -1278,7 +1278,7 @@ var DimpBase = {
             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', r);
+            this.flag('deleted', { index: r });
             e.stop();
             break;
 
@@ -1504,7 +1504,7 @@ var DimpBase = {
 
             case 'ctx_folder_seen':
             case 'ctx_folder_unseen':
-                this.flag(id == 'ctx_folder_seen' ? 'allSeen' : 'allUnseen', null, DimpCore.DMenu.element().readAttribute('mbox'));
+                this.flag(id == 'ctx_folder_seen' ? 'allSeen' : 'allUnseen', { mailbox: DimpCore.DMenu.element().readAttribute('mbox') });
                 break;
 
             case 'ctx_folder_poll':
@@ -1563,6 +1563,8 @@ var DimpBase = {
             case 'flag_clear':
             case 'flag_answered':
             case 'flag_unanswered':
+            case 'flag_draft':
+            case 'flag_notdraft':
                 this.flag(id.substring(5));
                 break;
 
@@ -2021,20 +2023,22 @@ var DimpBase = {
     },
 
     /* Flag actions for message list. */
-    flag: function(action, index, folder)
+    // opts = 'index', 'mailbox', 'noserver' (only for answered/unanswered)
+    flag: function(action, opts)
     {
         var actionCall, args, vs,
             obs = [],
             unseenstatus = 1;
+        opts = opts || {};
 
-        if (index) {
-            if (Object.isUndefined(folder)) {
-                vs = this.viewport.createSelection('dataob', index);
-            } else {
-                vs = this.viewport.getViewportSelection().search({ imapuid: { equal: [ index ] }, view: { equal: [ folder ] } });
-                if (!vs.size() && folder != this.folder) {
-                    vs = this.viewport.getViewportSelection(folder).search({ imapuid: { equal: [ index ] } });
+        if (opts.index) {
+            if (opts.mailbox) {
+                vs = this.viewport.getViewportSelection().search({ imapuid: { equal: [ opts.index ] }, view: { equal: [ opts.mailbox ] } });
+                if (!vs.size() && opts.mailbox != this.folder) {
+                    vs = this.viewport.getViewportSelection(opts.mailbox).search({ imapuid: { equal: [ opts.index ] } });
                 }
+            } else {
+                vs = this.viewport.createSelection('dataob', opts.index);
             }
         } else {
             vs = this.viewport.getSelected();
@@ -2043,8 +2047,8 @@ var DimpBase = {
         switch (action) {
         case 'allUnseen':
         case 'allSeen':
-            DimpCore.doAction((action == 'allUnseen') ? 'MarkFolderUnseen' : 'MarkFolderSeen', { view: folder }, null, this.bcache.get('flagAC') || this.bcache.set('flagAC', this._flagAllCallback.bind(this)));
-            if (folder == this.folder) {
+            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');
             }
             break;
@@ -2082,7 +2086,7 @@ var DimpBase = {
                 // 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: !(index && folder) });
+                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).
@@ -2097,10 +2101,10 @@ var DimpBase = {
             if (!vs.size()) {
                 break;
             }
-            args = { view: this.folder, messageFlag: '-\\seen' };
+            args = { view: this.folder, flags: [ '-\\seen' ].toJSON() };
             if (action == 'seen') {
                 unseenstatus = 0;
-                args.messageFlag = '\\seen';
+                args.flags = [ '\\seen' ];
             }
             obs = vs.get('dataob');
             if (obs.size()) {
@@ -2118,19 +2122,52 @@ var DimpBase = {
             }
             args = {
                 view: this.folder,
-                messageFlag: ((action == 'flagged') ? '\\flagged' : '-\\flagged')
+                flags: [ ((action == 'flagged') ? '' : '-') + '\\flagged' ].toJSON()
             };
             this.viewport.updateFlag(vs, 'flagged', action == 'flagged');
             DimpCore.doAction('MarkMessage', args, vs);
             break;
 
         case 'answered':
+            if (!vs.size()) {
+                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()) {
+                break;
+            }
             this.viewport.updateFlag(vs, 'answered', false);
+            if (!opts.noserver) {
+                args = {
+                    view: this.folder,
+                    flags: [ '-\\answered' ].toJSON()
+                };
+                DimpCore.doAction('MarkMessage', args, 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;
 
         case 'forwarded':
index 7a2e0d4..866190d 100644 (file)
@@ -222,11 +222,11 @@ var DimpCompose = {
                 if (DIMP.baseWindow) {
                     switch (d.reply_type) {
                     case 'reply':
-                        DIMP.baseWindow.DimpBase.flag('answered', d.index, d.reply_folder);
+                        DIMP.baseWindow.DimpBase.flag('answered', { index: d.index, mailbox: d.reply_folder, noserver: true });
                         break;
 
                     case 'forward':
-                        DIMP.baseWindow.DimpBase.flag('forwarded', d.index, d.reply_folder);
+                        DIMP.baseWindow.DimpBase.flag('forwarded', { index: d.index, mailbox: d.reply_folder, noserver: true });
                         break;
                     }
 
index 4644079..2441ea2 100644 (file)
@@ -93,7 +93,7 @@ var DimpFullmessage = {
             case 'button_deleted':
             case 'button_ham':
             case 'button_spam':
-                DIMP.baseWindow.DimpBase.flag(id.substring(7), DIMP.conf.msg_index, DIMP.conf.msg_folder);
+                DIMP.baseWindow.DimpBase.flag(id.substring(7), { index: DIMP.conf.msg_index, mailbox: DIMP.conf.msg_folder });
                 window.close();
                 e.stop();
                 return;
index 45e937f..6b2c3c4 100644 (file)
@@ -433,6 +433,8 @@ function _simpleButton($id, $text, $image, $imagedir = null)
  <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>
 </div>
 
 <div class="context" id="ctx_contacts" style="display:none">
diff --git a/imp/themes/graphics/mail_notdraft.png b/imp/themes/graphics/mail_notdraft.png
new file mode 100644 (file)
index 0000000..b539221
Binary files /dev/null and b/imp/themes/graphics/mail_notdraft.png differ
index e878092..33e6547 100644 (file)
@@ -1080,9 +1080,12 @@ span.iconImg, span.contextImg, span.spellcheckPopdownImg {
 #flag_unanswered span.contextImg {
     background-image: url("graphics/mail_notanswered.png");
 }
-#ctx_draft_resume span.contextImg {
+#flag_draft 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");
 }
diff --git a/imp/themes/silver/graphics/mail_notdraft.png b/imp/themes/silver/graphics/mail_notdraft.png
new file mode 100644 (file)
index 0000000..03b9b91
Binary files /dev/null and b/imp/themes/silver/graphics/mail_notdraft.png differ
index 1a7f048..30362f4 100644 (file)
 #flag_unanswered span.contextImg {
     background-image: url("graphics/mail_notanswered.png");
 }
+#flag_draft span.contextImg {
+    background-image: url("graphics/mail_draft.png");
+}
+#flag_notdraft span.contextImg {
+    background-image: url("graphics/mail_notdraft.png");
+}
 #ctx_draft_resume span.contextImg {
     background-image: url("graphics/mail_draft.png");
 }