]> err.no Git - scalable-opengroupware.org/commitdiff
more work on mailer
authorhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Sat, 2 Oct 2004 16:41:24 +0000 (16:41 +0000)
committerhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Sat, 2 Oct 2004 16:41:24 +0000 (16:41 +0000)
git-svn-id: http://svn.opengroupware.org/SOGo/trunk@340 d1b88da0-ebda-0310-925b-ed51d893ca5b

14 files changed:
SOGo/UI/Mailer/GNUmakefile
SOGo/UI/Mailer/Images/icon_mark_flagged.gif [new file with mode: 0644]
SOGo/UI/Mailer/Images/icon_mark_read.gif [new file with mode: 0644]
SOGo/UI/Mailer/Images/icon_mark_unflagged.gif [new file with mode: 0644]
SOGo/UI/Mailer/Images/icon_mark_unread.gif [new file with mode: 0644]
SOGo/UI/Mailer/Images/icon_read.gif [new file with mode: 0644]
SOGo/UI/Mailer/Images/icon_unread.gif [new file with mode: 0644]
SOGo/UI/Mailer/UIxMailFormatter.h
SOGo/UI/Mailer/UIxMailFormatter.m
SOGo/UI/Mailer/UIxMailListView.m
SOGo/UI/Mailer/UIxMailListView.wox
SOGo/UI/Mailer/UIxSubjectFormatter.m [new file with mode: 0644]
SOGo/UI/Mailer/mailer.css
SOGo/UI/Mailer/product.plist

index 5de68bca2a7fbd8347b5909b2874b1fbffec476e..8b621200a3e937c4b7cefc32821462c8a252a414 100644 (file)
@@ -11,11 +11,13 @@ MailerUI_LANGUAGES = English French
 MailerUI_OBJC_FILES += \
        MailerUIProduct.m       \
        \
-       UIxMailMainFrame.m      \
-       UIxMailTree.m           \
        UIxMailFormatter.m      \
+       UIxSubjectFormatter.m   \
        WOContext+UIxMailer.m   \
        \
+       UIxMailMainFrame.m      \
+       UIxMailTree.m           \
+       \
        UIxMailAccountsView.m   \
        UIxMailAccountView.m    \
        UIxMailListView.m       \
@@ -43,6 +45,7 @@ MailerUI_RESOURCE_FILES += \
 MailerUI_RESOURCE_FILES += \
        screenshots/*.png       \
        Images/tbtv_*.gif       \
+       Images/icon_*.gif       \
        Images/tbtb_*.png       \
 
 MailerUI_LOCALIZED_RESOURCE_FILES += \
diff --git a/SOGo/UI/Mailer/Images/icon_mark_flagged.gif b/SOGo/UI/Mailer/Images/icon_mark_flagged.gif
new file mode 100644 (file)
index 0000000..c7bbd75
Binary files /dev/null and b/SOGo/UI/Mailer/Images/icon_mark_flagged.gif differ
diff --git a/SOGo/UI/Mailer/Images/icon_mark_read.gif b/SOGo/UI/Mailer/Images/icon_mark_read.gif
new file mode 100644 (file)
index 0000000..2b0a47d
Binary files /dev/null and b/SOGo/UI/Mailer/Images/icon_mark_read.gif differ
diff --git a/SOGo/UI/Mailer/Images/icon_mark_unflagged.gif b/SOGo/UI/Mailer/Images/icon_mark_unflagged.gif
new file mode 100644 (file)
index 0000000..31c74b3
Binary files /dev/null and b/SOGo/UI/Mailer/Images/icon_mark_unflagged.gif differ
diff --git a/SOGo/UI/Mailer/Images/icon_mark_unread.gif b/SOGo/UI/Mailer/Images/icon_mark_unread.gif
new file mode 100644 (file)
index 0000000..c522a9e
Binary files /dev/null and b/SOGo/UI/Mailer/Images/icon_mark_unread.gif differ
diff --git a/SOGo/UI/Mailer/Images/icon_read.gif b/SOGo/UI/Mailer/Images/icon_read.gif
new file mode 100644 (file)
index 0000000..3644686
Binary files /dev/null and b/SOGo/UI/Mailer/Images/icon_read.gif differ
diff --git a/SOGo/UI/Mailer/Images/icon_unread.gif b/SOGo/UI/Mailer/Images/icon_unread.gif
new file mode 100644 (file)
index 0000000..f7009d5
Binary files /dev/null and b/SOGo/UI/Mailer/Images/icon_unread.gif differ
index c7501327f7281f2e3b5102e6fa1e3d8acc4e7458..8507c21b1d4bfe034c9d675c82f30fd3b667bfd1 100644 (file)
 
 #import <Foundation/NSFormatter.h>
 
-@class NSString, NSCalendarDate, NSTimeZone;
+/*
+  UIxMailFormatter
+  
+  Formatters which render various mail related fields.
+*/
+
+@class NSData, NSString, NSCalendarDate, NSTimeZone;
 
 @interface UIxMailFormatter : NSFormatter
 {
 
 - (NSString *)missingSubjectLabel;
 
+/* specific formatters */
+
+- (NSString *)stringForStringValue:(NSString *)_subject;
+- (NSString *)stringForDataValue:(NSData *)_subject;
+
 @end
 
 @interface UIxEnvelopeAddressFormatter : UIxMailFormatter
index 79e77e2d1e402edf1f623a905b02adeaf9312fb2..c5a13819c4b66294bf6936f4c81f79f50e0c8e7b 100644 (file)
@@ -148,85 +148,6 @@ static BOOL debugOn = YES;
 
 @end /* UIxMailDateFormatter */
 
-@implementation UIxSubjectFormatter
-
-- (id)init {
-  if ((self = [super init])) {
-    self->maxLength = 64;
-  }
-  return self;
-}
-
-/* configuration */
-
-- (unsigned int)maxLength {
-  return self->maxLength;
-}
-
-/* labels */
-
-- (NSString *)missingSubjectLabel {
-  return [self labelForKey:@"no_subject"];
-}
-
-/* specific formatters */
-
-- (NSString *)stringForStringValue:(NSString *)_subject {
-  NSString *s;
-  
-  if ([_subject hasPrefix:@"=?"]) { /* quoted printable */
-#warning TODO: work on QP decoding
-    /*  =?iso-8859-1?q?Yannick=20DAmboise?= */
-    if ((s = [_subject stringByDecodingQuotedPrintable]))
-      _subject = s;
-  }
-  
-  if ([_subject length] == 0)
-    return [self missingSubjectLabel];
-  
-  if ([_subject length] <= [self maxLength])
-    return _subject;
-  
-  s = [_subject substringToIndex:([self maxLength] - 3)];
-  return [s stringByAppendingString:@"..."];
-}
-
-- (NSString *)stringForDataValue:(NSData *)_subject {
-  NSString *s, *r;
-  
-  if ([_subject length] == 0)
-    return [self missingSubjectLabel];
-  
-  [self debugWithFormat:@"WARNING: NSData subject! (using UTF-8 to decode!)"];
-
-  // TODO: exception handler?
-  s = [[NSString alloc] initWithData:_subject encoding:NSUTF8StringEncoding];
-  if (s == nil) {
-    [self logWithFormat:@"ERROR: could do not decode NSData subject!"];
-    return [self labelForKey:@"Error_CouldNotDecodeSubject"];
-  }
-  
-  r = [[self stringForStringValue:s] copy];
-  [s release];
-  return [r autorelease];
-}
-
-/* formatter entry function */
-
-- (NSString *)stringForObjectValue:(id)_subject {
-  if (![_subject isNotNull])
-    return [self missingSubjectLabel];
-  
-  if ([_subject isKindOfClass:StrClass])
-    return [self stringForStringValue:_subject];
-  if ([_subject isKindOfClass:[NSData class]])
-    return [self stringForDataValue:_subject];
-  
-  return [self stringForStringValue:[_subject stringValue]];
-}
-
-@end /* UIxSubjectFormatter */
-
 #include <NGImap4/NGImap4EnvelopeAddress.h>
 
 @implementation UIxEnvelopeAddressFormatter
index 11da482f39ced117434ee9ced684855ec36205a5..cc86c77775e5eeb46b0f4eac7855f62ca7a4b0c3 100644 (file)
   return self->message;
 }
 
+- (BOOL)showToAddress {
+  // TODO: switch for Sent folder
+  return NO;
+}
+
 /* derived accessors */
 
 - (BOOL)isMessageRead {
@@ -65,6 +70,9 @@
   flags = [[self message] valueForKey:@"flags"];
   return [flags containsObject:@"seen"];
 }
+- (NSString *)messageUidString {
+  return [[[self message] valueForKey:@"uid"] stringValue];
+}
 
 - (NSArray *)messages {
   NSArray *uids;
   return [msgs valueForKey:@"fetch"];
 }
 
+/* URL processing */
+
+- (NSString *)messageViewTarget {
+  return [@"SOGo_msg_" stringByAppendingString:[self messageUidString]];
+}
+- (NSString *)messageViewURL {
+  // TODO: noframe only when view-target is empty
+  // TODO: markread only if the message is unread
+  NSString *s;
+  
+  s = [[self messageUidString] stringByAppendingString:@"/view?noframe=1"];
+  if (![self isMessageRead]) s = [s stringByAppendingString:@"&markread=1"];
+  return s;
+}
+- (NSString *)markReadURL {
+  return [@"markMessageRead?uid=" stringByAppendingString:
+            [self messageUidString]];
+}
+- (NSString *)markUnreadURL {
+  return [@"markMessageUnread?uid=" stringByAppendingString:
+            [self messageUidString]];
+}
+
 /* actions */
 
 - (id)defaultAction {
   return self;
 }
 
+- (id)markMessageUnreadAction {
+  [self logWithFormat:@"TODO: mark message unread!"];
+  return [self redirectToLocation:@"view"];
+}
+- (id)markMessageReadAction {
+  [self logWithFormat:@"TODO: mark message read!"];
+  return [self redirectToLocation:@"view"];
+}
+
 @end /* UIxMailListView */
index ab2195fe99251a2aee47b72d23caadec0301096c..53e2aa5fe65bdca5bd2ffbcf699721ab6cf15fab 100644 (file)
   title="name"
 >
   <div class="titlediv">
-    View:
-    <select name="viewfilter">
+    <a rsrc:href="tbird_073_mailwelcome.png">View:</a>, <!-- TODO ;-) -->
+    <select name="viewfilter">    <!-- var:popup? -->
      <option value="all"   >All</option>
      <option value="unread">Unread</option>
     </select>
-    <!-- var:popup -->
+
     Subject or Sender contains:
     <input name="searchtext" type="text" />
     <input name="clear" type="submit" value="Clear" />
 
   <div class="embedwhite_out">
     <div class="embedwhite_in">
-      <a rsrc:href="tbird_073_mailwelcome.png">screenshot</a>
-
-      <table border="0" width="100%">
+      <table border="0" width="100%" cellspacing="0" cellpadding="1">
         <tr class="tableview">
-          <td>Date</td>
-          <td>Subject</td>
-          <td>From</td>
-          <td>To</td>
-          <td>Flags</td>
+         <!-- TODO: see AB for sorting -->
+          
+          <td class="tbtv_headercell" width="50%">
+           <a href="?sort=subject"><var:string label:value="Subject" /></a>
+          </td>
+          <td class="tbtv_headercell">
+            <var:if condition="showToAddress" const:negate="YES">
+              <a href="?sort=from"><var:string label:value="From" /></a>
+            </var:if>
+            <var:if condition="showToAddress">
+              <a href="?sort=to"><var:string label:value="To" /></a>
+            </var:if>
+          </td>
+          <td class="tbtv_headercell">
+            <!-- TODO: fix me, use the proper Thunderbird Icon -->
+            <img rsrc:src="icon_read.gif" />
+          </td>
+          <td class="tbtv_headercell">
+            <a href="?sort=date"><var:string label:value="Date" /></a>
+          </td>
         </tr>
 
         <var:foreach list="messages" item="message">
           <tr class="tableview">
-            <td>
-              <var:string value="message.envelope.date" 
-                          formatter="context.mailDateFormatter"/>
-            </td>
             <td>
               <var:if condition="isMessageRead">
-                <span class="readmailsubject">
-                  <var:string value="message.envelope.subject"
-                              formatter="context.mailSubjectFormatter"/>
-                </span>
+                <div class="mailer_readmailsubject">
+                  <a var:href="messageViewURL" var:target="messageViewTarget">
+                    <var:string value="message.envelope.subject"
+                                formatter="context.mailSubjectFormatter"/>
+                  </a>
+                </div>
               </var:if>
               <var:if condition="isMessageRead" const:negate="YES">
-                <span class="unreadmailsubject">
-                  <var:string value="message.envelope.subject"
-                              formatter="context.mailSubjectFormatter"/>
-                </span>
+                <div class="mailer_unreadmailsubject">
+                  <a var:href="messageViewURL" var:target="messageViewTarget">
+                    <var:string value="message.envelope.subject"
+                                formatter="context.mailSubjectFormatter"/>
+                  </a>
+                </div>
+              </var:if>
+            </td>
+            <td>
+              <!-- TODO: show compose links -->
+              <var:if condition="showToAddress" const:negate="YES">
+                <var:string value="message.envelope.from"
+                            formatter="context.mailEnvelopeAddressFormatter" />
+              </var:if>
+              <var:if condition="showToAddress">
+                <var:string value="message.envelope.to"
+                            formatter="context.mailEnvelopeAddressFormatter" />
               </var:if>
             </td>
+            
             <td>
-              <var:string value="message.envelope.from"
-                          formatter="context.mailEnvelopeAddressFormatter" />
+              <var:if condition="isMessageRead">
+                <div class="mailer_readicon">
+                  <a href="markMessageUnread" var:_uid="message.uid"
+                     label:title="Mark Unread"> </a>
+                </div>
+              </var:if>
+              <var:if condition="isMessageRead" const:negate="YES">
+                <div class="mailer_unreadicon">
+                  <a href="markMessageRead" var:_uid="message.uid"
+                     label:title="Mark Read"> </a>
+                </div>
+              </var:if>
             </td>
+           
             <td>
-              <var:string value="message.envelope.to"
-                          formatter="context.mailEnvelopeAddressFormatter" />
+              <span class="mailer_datefield">
+                <var:string value="message.envelope.date" 
+                            formatter="context.mailDateFormatter"/>
+              </span>
             </td>
-            <td><var:string value="message.flags"/></td>
           </tr>
         </var:foreach>
       </table>
-      Folder List
     </div>
   </div>
 </var:component>
diff --git a/SOGo/UI/Mailer/UIxSubjectFormatter.m b/SOGo/UI/Mailer/UIxSubjectFormatter.m
new file mode 100644 (file)
index 0000000..396d8b2
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+  Copyright (C) 2004 SKYRIX Software AG
+
+  This file is part of OpenGroupware.org.
+
+  OGo is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  OGo is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with OGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
+*/
+
+#include "UIxMailFormatter.h"
+#include "common.h"
+
+#include <NGMail/NGMimeMessageParser.h>
+
+@implementation UIxSubjectFormatter
+
+static Class StrClass  = Nil;
+static Class DataClass = Nil;
+
++ (void)initialize {
+  StrClass  = [NSString class];
+  DataClass = [NSData   class];
+}
+
+- (id)init {
+  if ((self = [super init])) {
+    self->maxLength = 64;
+  }
+  return self;
+}
+
+/* configuration */
+
+- (unsigned int)maxLength {
+  return self->maxLength;
+}
+
+- (BOOL)shouldDecodeQP {
+  return YES;
+}
+
+/* labels */
+
+- (NSString *)missingSubjectLabel {
+  return [self labelForKey:@"no_subject"];
+}
+
+/* specific formatters */
+
+- (NSString *)stringForStringValue:(NSString *)_subject {
+  NSString *s;
+  
+  /* quoted printable */
+  if ([self shouldDecodeQP] && [_subject hasPrefix:@"=?"]) {
+    /* 
+       Now this is interesting. An NSString should not contain QP markers since
+       it is already 'charset decoded'. This is also why the NGMime parser
+       expects an NSData.
+       
+       Sample:
+         =?iso-8859-1?q?Yannick=20DAmboise?=
+
+       Note: -stringByDecodingQuotedPrintable only expands =D0 like charcodes!
+    */
+    NSData *data;
+    
+    /* header field data should always be ASCII */
+    data = [_subject dataUsingEncoding:NSUTF8StringEncoding];
+    return [self stringForDataValue:data];
+  }
+  
+  if ([_subject length] == 0)
+    return [self missingSubjectLabel];
+  
+  if ([_subject length] <= [self maxLength])
+    return _subject;
+  
+  s = [_subject substringToIndex:([self maxLength] - 3)];
+  return [s stringByAppendingString:@"..."];
+}
+
+- (NSString *)stringForDataValue:(NSData *)_subject {
+  NSString *s, *r;
+  unsigned len;
+  
+  if ((len = [_subject length] == 0))
+    return [self missingSubjectLabel];
+
+  /* check for quoted printable */
+  
+  if (len > 6 && [self shouldDecodeQP]) {
+    const unsigned char *b;
+    
+    b = [_subject bytes];
+    if (b[0] == '=' && b[1] == '?') {
+      /* eg: '=?iso-8859-1?q?Yannick=20DAmboise?=' */
+      id t;
+      
+      t = [_subject decodeQuotedPrintableValueOfMIMEHeaderField:@"subject"];
+      if ([t isNotNull])
+       return [self stringForObjectValue:t];
+    }
+  }
+  
+  /* continue NSData processing */
+  
+  [self debugWithFormat:@"WARNING: NSData subject! (using UTF-8 to decode!)"];
+
+  // TODO: exception handler?
+  s = [[NSString alloc] initWithData:_subject encoding:NSUTF8StringEncoding];
+  if (s == nil) {
+    [self logWithFormat:@"ERROR: could do not decode NSData subject!"];
+    return [self labelForKey:@"Error_CouldNotDecodeSubject"];
+  }
+  
+  r = [[self stringForStringValue:s] copy];
+  [s release];
+  return [r autorelease];
+}
+
+/* formatter entry function */
+
+- (NSString *)stringForObjectValue:(id)_subject {
+  if (![_subject isNotNull])
+    return [self missingSubjectLabel];
+  
+  if ([_subject isKindOfClass:StrClass])
+    return [self stringForStringValue:_subject];
+  if ([_subject isKindOfClass:DataClass])
+    return [self stringForDataValue:_subject];
+  
+  return [self stringForStringValue:[_subject stringValue]];
+}
+
+@end /* UIxSubjectFormatter */
index 90646d7c5ec99062121bf17a9d452c0aecb2cc9b..1275fb3e1008638b9db8653481a577ab96736521 100644 (file)
@@ -139,10 +139,88 @@ td.tb_icon a {
 .tableview { 
   font-size:   9pt;
   font-family: Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
+  vertical-align: top;
 }
 
-span.readmailsubject { 
+td.tbtv_headercell { 
+  border-width:        1;
+  border-style:        solid;
+  border-top-color:    white;
+  border-left-color:   white;
+  border-bottom-color: #808080;
+  border-right-color:  #808080;
+  padding-top:         4px;
+  padding-bottom:      3px;
+  padding-left:        4px;
+  padding-right:       4px;
+  
+  background-color:    #D4D0C8;
+}
+
+td.tbtv_headercell a {
+  margin:  0px auto;
+  display: block;
+  color:   black;
 }
-span.unreadmailsubject { 
-  font-weight: bold;
+td.tbtv_headercell a:hover {
+  margin:  0px auto;
+  display: block;
+  color:   black;
+  text-decoration: none;
+  /* background-color: #C4C0B8; */
+}
+
+span.mailer_datefield { 
+  white-space: nowrap;
+}
+
+div.mailer_readmailsubject { 
+  /* TODO: use proper read icon */
+  background-image:    url(tbtv_leaf_corner_17x17.gif);
+  background-repeat:   no-repeat;
+  background-position: 0px 0px;
+  padding-top:         1px;
+  padding-left:        20px;
+}
+div.mailer_unreadmailsubject { 
+  /* TODO: use proper unread icon */
+  background-image:    url(tbtv_leaf_corner_17x17.gif);
+  background-repeat:   no-repeat;
+  background-position: 0px 0px;
+  padding-left:        20px;
+  padding-top:         1px;
+  font-weight:         bold;
+}
+div.mailer_readmailsubject a { 
+  color:           black;
+  text-decoration: none;
+}
+div.mailer_unreadmailsubject a { 
+  color:           black;
+  text-decoration: none;
+}
+
+div.mailer_readicon { 
+  /* TODO: use Thunderbird icon */
+  background-image:    url(icon_read.gif);
+  background-repeat:   no-repeat;
+  background-position: 0px 4px;
+}
+div.mailer_readicon a {
+  width:   17px;
+  height:  17px;
+  margin:  0px auto;
+  display: block;
+}
+div.mailer_unreadicon { 
+  /* TODO: use Thunderbird icon */
+  background-image:    url(icon_unread.gif);
+  background-repeat:   no-repeat;
+  background-position: 0px 4px;
+}
+div.mailer_unreadicon a {
+  width:   17px;
+  height:  17px;
+  margin:  0px auto;
+  display: block;
 }
index 68a4b7ec09641c4335bd20bdd917b95e80657e55..492458f98549bc23660dee98d29b06ebec169060 100644 (file)
     "tbtb_replyall.png",
     "tbtb_search.png",
     "tbtb_trash.png",
+
+    "icon_mark_flagged.gif",
+    "icon_mark_read.gif",
+    "icon_mark_unflagged.gif",
+    "icon_mark_unread.gif",
+    "icon_read.gif",
+    "icon_unread.gif",
     
     "tbird_073_accountview.png",
     "tbird_073_compose.png",
           protectedBy = "View";
           pageName    = "UIxMailListView"; 
         };
+        
+        markMessageUnread = {
+          protectedBy = "View";
+          pageName    = "UIxMailListView"; 
+          actionName  = "markMessageUnread";
+        };
+        markMessageRead = {
+          protectedBy = "View";
+          pageName    = "UIxMailListView"; 
+          actionName  = "markMessageRead";
+        };
       };
     };