2005-01-28 Helge Hess <helge.hess@skyrix.com>
-
+
+ * v0.9.58
+
+ * SOGoMailObject.m: implemented a simple delete by setting the IMAP4
+ delete flag
+
+ * SOGoMailManager.m: added method to mark a message deleted
+
+ * SOGoMailFolder.m: just override -delete instead of implementing
+ -DELETAction: directrly
+
+ * SOGoMailAccount.m: added ability to retrieve Sent/Trash and INBOX
+ special mail folders
+
* v0.9.57
* SOGoMailBodyPart.m: enhanced lookup to allow for arbitary filenames
*/
@class NSArray;
+@class SOGoMailFolder;
@interface SOGoMailAccount : SOGoMailBaseObject
{
+ SOGoMailFolder *inboxFolder;
+ SOGoMailFolder *sentFolder;
+ SOGoMailFolder *trashFolder;
}
- (NSArray *)allFolderPathes;
+/* special folders */
+
+- (SOGoMailFolder *)inboxFolderInContext:(id)_ctx;
+- (SOGoMailFolder *)sentFolderInContext:(id)_ctx;
+- (SOGoMailFolder *)trashFolderInContext:(id)_ctx;
+
@end
#endif /* __Mailer_SOGoMailAccount_H__ */
return [NSException exceptionWithHTTPStatus:404 /* Not Found */];
}
+/* special folders */
+
+- (SOGoMailFolder *)inboxFolderInContext:(id)_ctx {
+ // TODO: use some profile to determine real location
+ SOGoMailFolder *folder;
+
+ if (self->inboxFolder != nil)
+ return self->inboxFolder;
+
+ folder = [self lookupName:@"INBOX" inContext:_ctx acquire:NO];
+ if ([folder isKindOfClass:[NSException class]]) return folder;
+
+ return ((self->inboxFolder = [folder retain]));
+}
+
+- (SOGoMailFolder *)sentFolderInContext:(id)_ctx {
+ // TODO: use some profile to determine real location
+ SOGoMailFolder *folder;
+
+ if (self->sentFolder != nil)
+ return self->sentFolder;
+
+ folder = [self inboxFolderInContext:_ctx];
+ if ([folder isKindOfClass:[NSException class]]) return folder;
+
+ folder = [folder lookupName:@"Sent" inContext:_ctx acquire:NO];
+ if ([folder isKindOfClass:[NSException class]]) return folder;
+
+ if (![folder isNotNull]) {
+ return [NSException exceptionWithHTTPStatus:404 /* not found */
+ reason:@"did not find Sent folder!"];
+ }
+
+ return ((self->sentFolder = [folder retain]));
+}
+
+- (SOGoMailFolder *)trashFolderInContext:(id)_ctx {
+ // TODO: use some profile to determine real location
+ SOGoMailFolder *folder;
+
+ if (self->trashFolder != nil)
+ return self->trashFolder;
+
+ folder = [self inboxFolderInContext:_ctx];
+ if ([folder isKindOfClass:[NSException class]]) return folder;
+
+ folder = [folder lookupName:@"Trash" inContext:_ctx acquire:NO];
+ if ([folder isKindOfClass:[NSException class]]) return folder;
+
+ if (![folder isNotNull]) {
+ return [NSException exceptionWithHTTPStatus:404 /* not found */
+ reason:@"did not find Trash folder!"];
+ }
+
+ return ((self->trashFolder = [folder retain]));
+}
+
/* WebDAV */
- (BOOL)davIsCollection {
password:[self imap4Password]];
}
-- (id)DELETEAction:(id)_ctx {
- id result;
-
- result = [[self mailManager] deleteMailboxAtURL:[self imap4URL]
- password:[self imap4Password]];
- if (result != nil)
- return result;
-
- return [NSNumber numberWithBool:YES];
+/* operations */
+
+- (NSException *)delete {
+ /* Note: overrides SOGoObject -delete */
+ return [[self mailManager] deleteMailboxAtURL:[self imap4URL]
+ password:[self imap4Password]];
}
@end /* SOGoMailFolder */
- (NSException *)addFlags:(id)_f toURL:(NSURL *)_u password:(NSString *)_p;
- (NSException *)removeFlags:(id)_f toURL:(NSURL *)_u password:(NSString *)_p;
+- (NSException *)markURLDeleted:(NSURL *)_u password:(NSString *)_p;
- (NSException *)postData:(NSData *)_data flags:(id)_flags
toFolderURL:(NSURL *)_url password:(NSString *)_p;
#include "SOGoMailConnectionEntry.h"
#include "common.h"
-// TODO: need a way to refresh caches on get mail!
+/*
+ Could check read-write state:
+ dict = [[self->context client] select:[self absoluteName]];
+ self->isReadOnly =
+ [[dict objectForKey:@"access"] isEqualToString:@"READ-WRITE"]
+ ? NoNumber : YesNumber;
+*/
@implementation SOGoMailManager
return [self addOrRemove:NO flags:_f toURL:_u password:_p];
}
+- (NSException *)markURLDeleted:(NSURL *)_url password:(NSString *)_p {
+ return [self addOrRemove:YES flags:@"Deleted" toURL:_url password:_p];
+}
+
- (NSException *)postData:(NSData *)_data flags:(id)_f
toFolderURL:(NSURL *)_url password:(NSString *)_p
{
return r;
}
+/* operations */
+
+- (NSException *)delete {
+ // TODO: copy to Trash folder
+ return [[self mailManager] markURLDeleted:[self imap4URL]
+ password:[self imap4Password]];
+}
+
@end /* SOGoMailObject */
# Version file
-SUBMINOR_VERSION:=57
+SUBMINOR_VERSION:=58
# v0.9.55 requires NGExtensions v4.5.136
# v0.9.44 requires libNGMime v4.3.194
/*
- Copyright (C) 2004 SKYRIX Software AG
+ Copyright (C) 2004-2005 SKYRIX Software AG
This file is part of OpenGroupware.org.
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
-// $Id$
#include "SOGoObject.h"
#include "SOGoUserFolder.h"
2005-01-28 Helge Hess <helge.hess@skyrix.com>
+ * v0.9.78
+
+ * UIxMailListView.m: properly mark deleted mails using line-through
+
+ * UIxMailView.m: close mail viewer if mail delete was successful
+
+ * mailer.css: added style classes for deleted cells
+
+ * UIxMailEditor.m: moved some Sent folder lookup to SOGoMailAccount
+
* v0.9.77
* added UIxMailSizeFormatter to render big file size numbers with some
}
- (id)lookupSentFolder {
- /*
- Lookup INBOX/Sent folder. This must be in the UI layer, because the Sent
- folder could be a user defined folder (so we cannot have a simple
- -saveToSent action on the SOGoDraftObject).
- */
SOGoMailAccount *account;
SOGoMailFolder *folder;
account = [[self clientObject] mailAccountFolder];
if ([account isKindOfClass:[NSException class]]) return account;
- folder = [account lookupName:@"INBOX" inContext:[self context] acquire:NO];
- if ([folder isKindOfClass:[NSException class]]) return folder;
-
- folder = [folder lookupName:@"Sent" inContext:[self context] acquire:NO];
+ folder = [account sentFolderInContext:[self context]];
if ([folder isKindOfClass:[NSException class]]) return folder;
-
- if (![folder isNotNull]) {
- return [NSException exceptionWithHTTPStatus:500 /* server error */
- reason:@"did not find Sent folder!"];
- }
-
- self->sentFolder = [folder retain];
- return self->sentFolder;
+ return ((self->sentFolder = [folder retain]));
}
- (NSException *)storeMailInSentFolder:(NSString *)_path {
if (![self _saveFormInfo])
return [self failedToSaveFormResponse];
- /* save mail to file (so that we can upload the mail to Cyrus */
+ /* save mail to file (so that we can upload the mail to Cyrus) */
+ // TODO: all this could be handled by the SOGoDraftObject?
mailPath = [[self clientObject] saveMimeMessageToTemporaryFile];
/* derived accessors */
+- (BOOL)isMessageDeleted {
+ NSArray *flags;
+
+ flags = [[self message] valueForKey:@"flags"];
+ return [flags containsObject:@"deleted"];
+}
+
- (BOOL)isMessageRead {
NSArray *flags;
return [[[self message] valueForKey:@"uid"] stringValue];
}
+- (NSString *)messageSubjectStyleClass {
+ return [self isMessageRead]
+ ? @"mailer_readmailsubject"
+ : @"mailer_unreadmailsubject";
+}
+- (NSString *)messageCellStyleClass {
+ return [self isMessageDeleted]
+ ? @"mailer_listcell_deleted"
+ : @"mailer_listcell_regular";
+}
+
- (BOOL)hasMessageAttachment {
/* we detect attachments by size ... */
unsigned size;
/>
-->
</td>
- <td>
- <var:if condition="isMessageRead">
- <div class="mailer_readmailsubject" var:id="msgDivID"
- >
- <!-- Note: var:href="messageViewURL" (done by JS),
- var:target="messageViewTarget" -->
- <a href="#" var:onclick="clickedMsgJS">
- <var:string value="message.envelope.subject"
- formatter="context.mailSubjectFormatter"/>
- </a>
- </div>
- </var:if>
- <var:if condition="isMessageRead" const:negate="YES">
- <div class="mailer_unreadmailsubject" var:id="msgDivID">
- <!-- Note: var:href="messageViewURL" (done by JS) -->
- <a href="#" var:onclick="clickedMsgJS">
- <var:string value="message.envelope.subject"
- formatter="context.mailSubjectFormatter"/>
- </a>
- </div>
- </var:if>
+ <td var:class="messageCellStyleClass">
+ <div var:class="messageSubjectStyleClass" var:id="msgDivID">
+ <!-- Note: var:href="messageViewURL" (done by JS),
+ var:target="messageViewTarget" -->
+ <a href="#" var:onclick="clickedMsgJS">
+ <var:string value="message.envelope.subject"
+ formatter="context.mailSubjectFormatter"/>
+ </a>
+ </div>
</td>
- <td>
+ <td var:class="messageCellStyleClass">
<!-- TODO: show compose links -->
<!-- TODO: different color for internal vs external addrs -->
<var:if condition="showToAddress" const:negate="YES">
</var:if>
</td>
- <td>
+ <td var:class="messageCellStyleClass">
<span class="mailer_datefield">
<var:string value="message.envelope.date"
formatter="context.mailDateFormatter"/>
- (BOOL)isDeletableClientObject {
return [[self clientObject] respondsToSelector:@selector(delete)];
}
+- (BOOL)isInlineViewer {
+ return NO;
+}
- (id)deleteAction {
NSException *ex;
- id url;
-
+
if (![self isDeletableClientObject]) {
return [NSException exceptionWithHTTPStatus:400 /* Bad Request */
reason:@"method cannot be invoked on "
@"the specified object"];
}
-
+
if ((ex = [[self clientObject] delete]) != nil) {
// TODO: improve error handling
[self debugWithFormat:@"failed to delete: %@", ex];
return ex;
}
+
+ if (![self isInlineViewer]) {
+ // if everything is ok, close the window (send a JS closing the Window)
+ return [self pageWithName:@"UIxMailWindowCloser"];
+ }
+ else {
+ id url;
- url = [[[self clientObject] container] baseURLInContext:[self context]];
- return [self redirectToLocation:url];
+ url = [[[self clientObject] container] baseURLInContext:[self context]];
+ return [self redirectToLocation:url];
+ }
}
- (id)getMailAction {
const:hideFolderTree="1"
>
<!--
- todo: we cannot make this static because the CC list has a dynamic height?
+ Note: We cannot make this section static (like the toolbar) because the CC
+ list has a dynamic height (would require some tricky JavaScript).
-->
<table class="mailer_fieldtable">
<tr class="mailer_fieldrow">
SUBMINOR_VERSION:=77
+# v0.9.78 requires SoObjects/Mailer v0.9.58
# v0.9.77 requires SoObjects/Mailer v0.9.57
# v0.9.74 requires SoObjects/Mailer v0.9.56
# v0.9.70 requires NGExtensions v4.5.136
}
div.mailer_readmailsubject {
- /* TODO: use proper read icon */
- /* background-image: url(tbtv_leaf_corner_17x17.gif); */
background-image: url(message-mail-read.png);
background-repeat: no-repeat;
background-position: 0px 0px;
padding-left: 20px;
}
div.mailer_unreadmailsubject {
- /* TODO: use proper unread icon */
- /* background-image: url(tbtv_leaf_corner_17x17.gif); */
background-image: url(message-mail.png);
background-repeat: no-repeat;
background-position: 0px 0px;
text-decoration: none;
}
+td.mailer_listcell_deleted {
+ text-decoration: line-through;
+}
+td.mailer_listcell_regular {
+}
+
div.mailer_readicon {
/* TODO: use Thunderbird icon */
background-image: url(icon_read.gif);
div.linked_attachment_body {
font-family: Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
- font-size: 10pt;
+ font-size: 10pt;
padding: 4px;
border-width: 1;
cssClass = "tbicon_forward"; label = "Forward"; },
),
*/
+ ( // third group
+ { link = "delete";
+ cssClass = "tbicon_delete"; label = "Delete"; },
+ ),
/* TODO: enable when implemented
( // third group
// TODO: enable when delete works (#1212)