From b2fc189b932b97461ffba79a1973ffd02366e8b7 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Fri, 25 Jun 2010 19:58:30 +0000 Subject: [PATCH] See ChangeLog Monotone-Parent: 2b83c62317d266d5f7a2e2046fc19f68f88a385f Monotone-Revision: 763ab7e667a159d6b727544a067a085d622ab598 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2010-06-25T19:58:30 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 57 +++++ SoObjects/Mailer/SOGoDraftObject.h | 3 + SoObjects/Mailer/SOGoDraftObject.m | 49 ++++- UI/MailerUI/UIxMailEditor.m | 42 +++- UI/MailerUI/UIxMailListActions.h | 5 + UI/MailerUI/UIxMailListActions.m | 217 +++++++++++--------- UI/MailerUI/UIxMailMainFrame.m | 35 +++- UI/Templates/MailerUI/UIxMailEditor.wox | 2 + UI/Templates/MailerUI/UIxMailMainFrame.wox | 1 + UI/WebServerResources/MailerUI.js | 172 +++++++++------- UI/WebServerResources/SOGoDataTable.js | 39 +++- UI/WebServerResources/SOGoMailDataSource.js | 84 +++++--- 12 files changed, 501 insertions(+), 205 deletions(-) diff --git a/ChangeLog b/ChangeLog index 273f3d344..198596fd3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,60 @@ +2010-06-25 Francis Lachapelle + + * UI/MailerUI/UIxMailMainFrame.m (-inboxData): new method used to + avoid an AJAX call when first loading the webmail module. It + returns a dictionary with the UIDs of the inbox folder as well as + the headers of the first few messages. + + * UI/MailerUI/UIxMailListActions.m (-imap4SortOrdering): fixed an + issue that would not save the sorting state when matching the + default sort key but not the sort direction. + (-getUIDsAndHeadersInFolder:): new method that returns all UIDs of + a mail folder and the headers of the first corresponding messages. + (-getHeadersForUIDs:inFolder:): was getHeadersAction. It now + returns an array of arrays instead of an array of + dictionaries. The first array contains the previous dictionary + keys so we can easily reconstruct a dictionary in JavaScript. + + * UI/MailerUI/UIxMailEditor.m (-setSourceUID:, -sourceUID, + -setSourceFolder:, -sourceFolder): new methods to keep track of + the source folder replying or forwarding a message. + (-sendAction): now calls the JavaScript function refreshMessage + instead of refreshCurrentMailbox. + + * SoObjects/Mailer/SOGoDraftObject.m (-setSourceFolder:, + -setSourceFolderWithMailObject:, -sourceFolder): new methods to + keep track of the source folder replying or forwarding a message. + (-fetchMailForEditing:): fixed the message UID value. + + * UI/WebServerResources/SOGoMailDataSource.js (remove): new + function that was integrated to invalidate. There are now + splitted. + (init): new function to initialize the data source with + pre-fetched uids and headers. + (getData): if the source is not yet loaded, the function will now + be called by the method _loadCallback. + (_getRemoteDataCallback): headers received from the server are no + formatted as a hash but as an array with the first entry + corresponding the previous hash keys. + + * UI/WebServerResources/SOGoDataTable.js (initSource): was + setSource which was redefined to received a data source as + argument. + (invalidate): new function to refresh a single row. + + * UI/WebServerResources/MailerUI.js (openMailbox): added caching + of data sources (IMAP folders). The previous selection is now + restored when chaning folders. + (loadMessageCallback): the window is no longer reloaded if the + message doesn't exist; only the proper row is removed. + (refreshMessage): new function called after sending a message. + +2010-06-24 Francis Lachapelle + + * UI/MailerUI/UIxMailEditor.m (-sendAction): trigger the new + JavaScript function refreshMessage() instead of + refreshCurrentFolder() so we only refresh one row. + 2010-06-23 Francis Lachapelle * SoObjects/SOGo/SOGoUserDefaults.m (-language): verify that the diff --git a/SoObjects/Mailer/SOGoDraftObject.h b/SoObjects/Mailer/SOGoDraftObject.h index 39608997d..f3a7b5ebd 100644 --- a/SoObjects/Mailer/SOGoDraftObject.h +++ b/SoObjects/Mailer/SOGoDraftObject.h @@ -56,6 +56,7 @@ NSString *text; NSString *sourceURL; NSString *sourceFlag; + NSString *sourceFolder; } /* contents */ @@ -75,6 +76,8 @@ /* for replies and forwards */ - (void) setSourceURL: (NSString *) newSurceURL; - (void) setSourceFlag: (NSString *) newSourceFlag; +- (void) setSourceFolder: (NSString *) newSourceFolder; +- (NSString *) sourceFolder; - (void) setIMAP4ID: (int) newIMAPID; - (int) IMAP4ID; diff --git a/SoObjects/Mailer/SOGoDraftObject.m b/SoObjects/Mailer/SOGoDraftObject.m index 0d8156b3c..294bb431e 100644 --- a/SoObjects/Mailer/SOGoDraftObject.m +++ b/SoObjects/Mailer/SOGoDraftObject.m @@ -1,5 +1,5 @@ /* - Copyright (C) 2007-2009 Inverse inc. + Copyright (C) 2007-2010 Inverse inc. Copyright (C) 2004-2005 SKYRIX Software AG This file is part of SOGo. @@ -259,6 +259,35 @@ static NSString *userAgent = nil; ASSIGN (sourceFlag, newSourceFlag); } +- (void) setSourceFolder: (NSString *) newSourceFolder +{ + ASSIGN (sourceFolder, newSourceFolder); +} + +- (void) setSourceFolderWithMailObject: (SOGoMailObject *) sourceMail +{ + NSMutableArray *paths; + id parent; + + parent = [sourceMail container]; + paths = [NSMutableArray arrayWithCapacity: 1]; + while (parent && ![parent isKindOfClass: [SOGoMailAccount class]]) + { + [paths insertObject: [parent nameInContainer] atIndex: 0]; + parent = [parent container]; + } + if (parent) + [paths insertObject: [NSString stringWithFormat: @"/%@", [parent nameInContainer]] + atIndex: 0]; + + [self setSourceFolder: [paths componentsJoinedByString: @"/"]]; +} + +- (NSString *) sourceFolder +{ + return sourceFolder; +} + - (NSException *) storeInfo { NSMutableDictionary *infos; @@ -273,12 +302,13 @@ static NSString *userAgent = nil; if (inReplyTo) [infos setObject: inReplyTo forKey: @"inReplyTo"]; if (IMAP4ID > -1) - [infos setObject: [NSNumber numberWithInt: IMAP4ID] - forKey: @"IMAP4ID"]; - if (sourceURL && sourceFlag) + [infos setObject: [NSString stringWithFormat: @"%i", IMAP4ID] + forKey: @"IMAP4ID"]; + if (sourceURL && sourceFlag && sourceFolder) { [infos setObject: sourceURL forKey: @"sourceURL"]; [infos setObject: sourceFlag forKey: @"sourceFlag"]; + [infos setObject: sourceFolder forKey: @"sourceFolder"]; } if ([infos writeToFile: [self infoPath] atomically:YES]) @@ -324,6 +354,9 @@ static NSString *userAgent = nil; value = [infoDict objectForKey: @"sourceFlag"]; if (value) [self setSourceFlag: value]; + value = [infoDict objectForKey: @"sourceFolder"]; + if (value) + [self setSourceFolder: value]; value = [infoDict objectForKey: @"inReplyTo"]; if (value) @@ -622,7 +655,8 @@ static NSString *userAgent = nil; [self setText: [sourceMail contentForEditing]]; [self setSourceURL: [sourceMail imap4URLString]]; - IMAP4ID = [[sourceMail nameInContainer] intValue]; + [self setIMAP4ID: [[sourceMail nameInContainer] intValue]]; + [self setSourceFolderWithMailObject: sourceMail]; [self storeInfo]; } @@ -650,6 +684,9 @@ static NSString *userAgent = nil; [self setHeaders: info]; [self setSourceURL: [sourceMail imap4URLString]]; [self setSourceFlag: @"Answered"]; + [self setIMAP4ID: [[sourceMail nameInContainer] intValue]]; + [self setSourceFolderWithMailObject: sourceMail]; + [self storeInfo]; } @@ -670,6 +707,8 @@ static NSString *userAgent = nil; [self setSourceURL: [sourceMail imap4URLString]]; [self setSourceFlag: @"$Forwarded"]; + [self setIMAP4ID: [[sourceMail nameInContainer] intValue]]; + [self setSourceFolderWithMailObject: sourceMail]; /* attach message */ ud = [[context activeUser] userDefaults]; diff --git a/UI/MailerUI/UIxMailEditor.m b/UI/MailerUI/UIxMailEditor.m index 4b914af7b..5bb60bfaa 100644 --- a/UI/MailerUI/UIxMailEditor.m +++ b/UI/MailerUI/UIxMailEditor.m @@ -65,6 +65,8 @@ NSArray *cc; NSArray *bcc; NSString *subject; + NSString *sourceUID; + NSString *sourceFolder; NSString *text; NSMutableArray *fromEMails; NSString *from; @@ -116,6 +118,8 @@ static NSArray *infoKeys = nil; [to release]; [cc release]; [bcc release]; + [sourceUID release]; + [sourceFolder release]; [attachmentName release]; [attachmentNames release]; [attachedFiles release]; @@ -245,6 +249,29 @@ static NSArray *infoKeys = nil; return text; } +- (void) setSourceUID: (int) newSourceUID +{ + NSString *s; + + s = [NSString stringWithFormat: @"%i", newSourceUID]; + ASSIGN (sourceUID, s); +} + +- (NSString *) sourceUID +{ + return sourceUID; +} + +- (void) setSourceFolder: (NSString *) newSourceFolder +{ + ASSIGN (sourceFolder, newSourceFolder); +} + +- (NSString *) sourceFolder +{ + return sourceFolder; +} + - (void) setTo: (NSArray *) newTo { if ([newTo isKindOfClass: [NSNull class]]) @@ -490,6 +517,11 @@ static NSArray *infoKeys = nil; return [[self attachmentNames] count] > 0 ? YES : NO; } +- (NSString *) uid +{ + return [[self clientObject] nameInContainer]; +} + - (id) defaultAction { SOGoDraftObject *co; @@ -498,6 +530,8 @@ static NSArray *infoKeys = nil; [co fetchInfo]; [self loadInfo: [co headers]]; [self setText: [co text]]; + [self setSourceUID: [co IMAP4ID]]; + [self setSourceFolder: [co sourceFolder]]; return self; } @@ -537,6 +571,7 @@ static NSArray *infoKeys = nil; - (id ) sendAction { id result; + SOGoDraftObject *co; // TODO: need to validate whether we have a To etc @@ -548,7 +583,12 @@ static NSArray *infoKeys = nil; { result = (id ) [[self clientObject] sendMail]; if (!result) - result = [self jsCloseWithRefreshMethod: @"refreshCurrentFolder()"]; + { + co = [self clientObject]; + result = [self jsCloseWithRefreshMethod: [NSString stringWithFormat: @"refreshMessage(\"%@\", %i)", + [co sourceFolder], + [co IMAP4ID]]]; + } } else result = [self failedToSaveFormResponse]; diff --git a/UI/MailerUI/UIxMailListActions.h b/UI/MailerUI/UIxMailListActions.h index 9feab0835..4ef02591b 100644 --- a/UI/MailerUI/UIxMailListActions.h +++ b/UI/MailerUI/UIxMailListActions.h @@ -45,6 +45,11 @@ - (EOQualifier *) searchQualifier; - (NSString *) msgLabels; +- (NSArray *) getSortedUIDsInFolder: (SOGoMailFolder *) mailFolder; +- (NSArray *) getHeadersForUIDs: (NSArray *) uids + inFolder: (SOGoMailFolder *) mailFolder; +- (NSDictionary *) getUIDsAndHeadersInFolder: (SOGoMailFolder *) mailFolder; + - (id) getMailAction; - (id ) getSortedUIDsAction; - (id ) getHeadersAction; diff --git a/UI/MailerUI/UIxMailListActions.m b/UI/MailerUI/UIxMailListActions.m index b852bc2fc..ce090705a 100644 --- a/UI/MailerUI/UIxMailListActions.m +++ b/UI/MailerUI/UIxMailListActions.m @@ -64,6 +64,9 @@ #import "UIxMailListActions.h" +// The maximum number of headers to prefetch when querying the UIDs list +#define headersPrefetchMaxSize 100 + @implementation UIxMailListActions - (id) initWithRequest: (WORequest *) newRequest @@ -341,7 +344,7 @@ - (NSString *) imap4SortOrdering { NSString *sort, *ascending; - NSString *module; //*login + NSString *module; NSMutableDictionary *moduleSettings; BOOL asc; SOGoUser *activeUser; @@ -352,14 +355,23 @@ ascending = [[context request] formValueForKey: @"asc"]; asc = [ascending boolValue]; - if (![sort isEqualToString: [self defaultSortKey]]) + activeUser = [context activeUser]; + clientObject = [self clientObject]; + module = [[[clientObject container] container] nameInContainer]; + us = [activeUser userSettings]; + moduleSettings = [us objectForKey: module]; + + if ([sort isEqualToString: [self defaultSortKey]] && !asc) { + if (moduleSettings) + { + [moduleSettings removeObjectForKey: @"SortingState"]; + [us synchronize]; + } + } + else + { // Save the sorting state in the user settings - activeUser = [context activeUser]; - clientObject = [self clientObject]; - module = [[[clientObject container] container] nameInContainer]; - us = [activeUser userSettings]; - moduleSettings = [us objectForKey: module]; if (!moduleSettings) { moduleSettings = [NSMutableDictionary dictionary]; @@ -413,10 +425,9 @@ return qualifier; } -- (NSArray *) sortedUIDs +- (NSArray *) getSortedUIDsInFolder: (SOGoMailFolder *) mailFolder { EOQualifier *qualifier, *fetchQualifier, *notDeleted; - SOGoMailFolder *folder; if (!sortedUIDs) { @@ -434,10 +445,9 @@ else fetchQualifier = notDeleted; - folder = [self clientObject]; sortedUIDs - = [folder fetchUIDsMatchingQualifier: fetchQualifier - sortOrdering: [self imap4SortOrdering]]; + = [mailFolder fetchUIDsMatchingQualifier: fetchQualifier + sortOrdering: [self imap4SortOrdering]]; [sortedUIDs retain]; } @@ -449,7 +459,7 @@ NSArray *messageNbrs; int index; - messageNbrs = [self sortedUIDs]; + messageNbrs = [self getSortedUIDsInFolder: [self clientObject]]; index = [messageNbrs indexOfObject: [NSNumber numberWithInt: messageNbr]]; // if (index < 0) @@ -524,75 +534,55 @@ return [self redirectToLocation:@"view"]; } +- (NSDictionary *) getUIDsAndHeadersInFolder: (SOGoMailFolder *) mailFolder +{ + NSArray *uids, *headers; + NSDictionary *data; + NSRange r; + int count; + + uids = [self getSortedUIDsInFolder: mailFolder]; // retrieves the form parameters "sort" and "asc" + + // Also retrieve the first headers, up to 'headersPrefetchMaxSize' + count = [uids count]; + if (count > headersPrefetchMaxSize) count = headersPrefetchMaxSize; + r = NSMakeRange(0, count); + headers = [self getHeadersForUIDs: [uids subarrayWithRange: r] + inFolder: mailFolder]; + + data = [NSDictionary dictionaryWithObjectsAndKeys: uids, @"uids", + headers, @"headers", nil]; + + return data; +} + - (id ) getSortedUIDsAction { - NSArray *uids; - NSRange r; - WORequest *request; + NSDictionary *data; + SOGoMailFolder *folder; WOResponse *response; - int firstUID, firstIndex, count; - - request = [context request]; - uids = [self sortedUIDs]; // retrieves the form parameters "sort" and "asc" - if ([request formValueForKey: @"start"] != nil) - { - firstUID = [[request formValueForKey: @"start"] intValue]; - firstIndex = [self indexOfMessageUID: firstUID]; - if (firstIndex == NSNotFound) - return [NSException exceptionWithHTTPStatus: 404 - reason: @"Message not found"]; - } - else - firstIndex = -1; - - if ([request formValueForKey: @"count"] != nil) - { - count = [[request formValueForKey: @"count"] intValue]; - } - else - count = 0; - - if (firstIndex > -1) - { - if (count <= 0 || (count + firstIndex) > [uids count]) - count = [uids count] - firstIndex; - r = NSMakeRange(firstIndex, count); - uids = [uids subarrayWithRange: r]; - } - response = [context response]; + folder = [self clientObject]; + data = [self getUIDsAndHeadersInFolder: folder]; [response setHeader: @"text/plain; charset=utf-8" forKey: @"content-type"]; - [response appendContentString: [uids jsonRepresentation]]; + [response appendContentString: [data jsonRepresentation]]; return response; } -- (id ) getHeadersAction +- (NSArray *) getHeadersForUIDs: (NSArray *) uids + inFolder: (SOGoMailFolder *) mailFolder { - NSArray *uids, *to, *from; + NSArray *to, *from; NSDictionary *msgs; - NSMutableArray *headers; - NSMutableDictionary *msg; + NSMutableArray *headers, *msg; NSEnumerator *msgsList; NSString *msgIconStatus, *msgDate; - SOGoMailFolder *mailFolder; - WORequest *request; - WOResponse *response; UIxEnvelopeAddressFormatter *addressFormatter; - request = [context request]; - - if ([request formValueForKey: @"uids"] == nil) - { - return [NSException exceptionWithHTTPStatus: 404 - reason: @"No UID specified"]; - } - - uids = [[request formValueForKey: @"uids"] componentsSeparatedByString: @","]; // Should we support ranges? ie "x-y" headers = [NSMutableArray arrayWithCapacity: [uids count]]; - mailFolder = [self clientObject]; addressFormatter = [context mailEnvelopeAddressFormatter]; // Fetch headers @@ -601,78 +591,109 @@ msgsList = [[msgs objectForKey: @"fetch"] objectEnumerator]; [self setMessage: [msgsList nextObject]]; + + msg = [NSMutableArray arrayWithObjects: @"To", @"Attachment", @"Flagged", @"Subject", @"From", @"Unread", @"Priority", @"Date", @"Size", @"rowClasses", @"labels", @"rowID", @"uid", nil]; + [headers addObject: msg]; while (message) { - msg = [NSMutableDictionary dictionaryWithCapacity: 11]; + msg = [NSMutableArray arrayWithCapacity: 12]; // Columns data + // To to = [[message objectForKey: @"envelope"] to]; if ([to count] > 0) - [msg setObject: [addressFormatter stringForArray: to] - forKey: @"To"]; - - if ([self hasMessageAttachment]) - [msg setObject: [NSString stringWithFormat: @"", [self urlForResourceFilename: @"title_attachment_14x14.png"]] - forKey: @"Attachment"]; - - if ([self isMessageFlagged]) - { - [msg setObject: [NSString stringWithFormat: @"", - [self urlForResourceFilename: @"flag.png"]] - forKey: @"Flagged"]; - } + [msg addObject: [addressFormatter stringForArray: to]]; else - { - [msg setObject: [NSString stringWithFormat: @"", - [self urlForResourceFilename: @"dot.png"]] - forKey: @"Flagged"]; - } + [msg addObject: @""]; - [msg setObject: [NSString stringWithFormat: @"%@", - [self messageSubject]] - forKey: @"Subject"]; + // Attachment + if ([self hasMessageAttachment]) + [msg addObject: [NSString stringWithFormat: @"", [self urlForResourceFilename: @"title_attachment_14x14.png"]]]; + else + [msg addObject: @""]; + + // Flagged + if ([self isMessageFlagged]) + [msg addObject: [NSString stringWithFormat: @"", + [self urlForResourceFilename: @"flag.png"]]]; + else + [msg addObject: [NSString stringWithFormat: @"", + [self urlForResourceFilename: @"dot.png"]]]; + + // Subject + [msg addObject: [NSString stringWithFormat: @"%@", + [self messageSubject]]]; + // From from = [[message objectForKey: @"envelope"] from]; if ([from count] > 0) - [msg setObject: [addressFormatter stringForArray: from] forKey: @"From"]; + [msg addObject: [addressFormatter stringForArray: from]]; else - [msg setObject: @"" forKey: @"From"]; + [msg addObject: @""]; + + // Unread if ([self isMessageRead]) msgIconStatus = @"dot.png"; else msgIconStatus = @"icon_unread.gif"; - [msg setObject: [self messageRowStyleClass] forKey: @"rowClasses"]; - [msg setObject: [NSString stringWithFormat: @"", + [msg addObject: [NSString stringWithFormat: @"", [self urlForResourceFilename: msgIconStatus], [self labelForKey: @"Mark Unread"], [self labelForKey: @"Mark Read"], [self labelForKey: @"Mark Unread"], - [self msgIconReadImgID]] - forKey: @"Unread"]; + [self msgIconReadImgID]]]; - [msg setObject: [self messagePriority] forKey: @"Priority"]; + // Priority + [msg addObject: [self messagePriority]]; + // Date msgDate = [self messageDate]; if (msgDate == nil) msgDate = @""; - [msg setObject: msgDate forKey: @"Date"]; + [msg addObject: msgDate]; - [msg setObject: [self messageSize] forKey: @"Size"]; + // Size + [msg addObject: [self messageSize]]; - [msg setObject: [self msgLabels] forKey: @"labels"]; + // rowClasses + [msg addObject: [self messageRowStyleClass]]; - [msg setObject: [self msgRowID] forKey: @"rowID"]; + // labels + [msg addObject: [self msgLabels]]; - [msg setObject: [message objectForKey: @"uid"] forKey: @"uid"]; + // rowID + [msg addObject: [self msgRowID]]; + // uid + [msg addObject: [message objectForKey: @"uid"]]; + [headers addObject: msg]; [self setMessage: [msgsList nextObject]]; } + return headers; +} + +- (id ) getHeadersAction +{ + NSArray *uids, *headers; + WORequest *request; + WOResponse *response; + + request = [context request]; + if ([request formValueForKey: @"uids"] == nil) + { + return [NSException exceptionWithHTTPStatus: 404 + reason: @"No UID specified"]; + } + + uids = [[request formValueForKey: @"uids"] componentsSeparatedByString: @","]; // Should we support ranges? ie "x-y" + headers = [self getHeadersForUIDs: uids + inFolder: [self clientObject]]; response = [context response]; [response setHeader: @"text/plain; charset=utf-8" forKey: @"content-type"]; diff --git a/UI/MailerUI/UIxMailMainFrame.m b/UI/MailerUI/UIxMailMainFrame.m index 87e6bf9b3..fc8aabb59 100644 --- a/UI/MailerUI/UIxMailMainFrame.m +++ b/UI/MailerUI/UIxMailMainFrame.m @@ -23,6 +23,8 @@ #import #import +#import + #import #import #import @@ -42,6 +44,7 @@ #import #import #import +#import #import #import #import @@ -54,6 +57,7 @@ #import #import "UIxMailMainFrame.h" +#import "UIxMailListActions.h" // Avoid compilation warnings @interface SOGoUserFolder (private) @@ -173,6 +177,33 @@ return [u hasSuffix:@"/"] ? @"view" : @"#"; } +- (NSString *) inboxData +{ + SOGoMailAccounts *accounts; + SOGoMailAccount *account; + SOGoMailFolder *inbox; + + NSString *firstAccount; + NSDictionary *data; + SOGoUser *activeUser; + UIxMailListActions *actions; + + [self _setupContext]; + + actions = [[[UIxMailListActions new] initWithRequest: [context request]] autorelease]; + activeUser = [context activeUser]; + accounts = [self clientObject]; + + firstAccount = [[[accounts accountKeys] allKeys] + objectAtIndex: 0]; + account = [accounts lookupName: firstAccount inContext: context acquire: NO]; + inbox = [account inboxFolderInContext: context]; + + data = [actions getUIDsAndHeadersInFolder: inbox]; + + return [data jsonRepresentation]; +} + - (id ) composeAction { id contact; @@ -333,7 +364,7 @@ [self _setupContext]; vertical = [moduleSettings objectForKey: @"DragHandleVertical"]; - return ((vertical && [vertical intValue] > 0) ? (id)[vertical stringByAppendingFormat: @"px"] : nil); + return ((vertical && [vertical intValue] > 0) ? (id)[vertical stringByAppendingString: @"px"] : nil); } - (NSString *) horizontalDragHandleStyle @@ -343,7 +374,7 @@ [self _setupContext]; horizontal = [moduleSettings objectForKey: @"DragHandleHorizontal"]; - return ((horizontal && [horizontal intValue] > 0) ? (id)[horizontal stringByAppendingFormat: @"px"] : nil); + return ((horizontal && [horizontal intValue] > 0) ? (id)[horizontal stringByAppendingString: @"px"] : nil); } - (NSString *) mailboxContentStyle diff --git a/UI/Templates/MailerUI/UIxMailEditor.wox b/UI/Templates/MailerUI/UIxMailEditor.wox index ec91788f9..f7ad250af 100644 --- a/UI/Templates/MailerUI/UIxMailEditor.wox +++ b/UI/Templates/MailerUI/UIxMailEditor.wox @@ -13,6 +13,8 @@ const:jsFiles="UIxMailToSelection.js,ckeditor/ckeditor.js,SOGoAutoCompletion.js">
diff --git a/UI/Templates/MailerUI/UIxMailMainFrame.wox b/UI/Templates/MailerUI/UIxMailMainFrame.wox index 328dbd00f..2b0ef2f88 100644 --- a/UI/Templates/MailerUI/UIxMailMainFrame.wox +++ b/UI/Templates/MailerUI/UIxMailMainFrame.wox @@ -11,6 +11,7 @@