Skip to content

Commit

Permalink
perf(mail(js)): various optimizations
Browse files Browse the repository at this point in the history
We now use IMAP QRESYNC to synchronize mailbox.
  • Loading branch information
cgx committed Jun 15, 2021
1 parent b4ccafd commit a9c6f09
Show file tree
Hide file tree
Showing 16 changed files with 360 additions and 170 deletions.
9 changes: 8 additions & 1 deletion SoObjects/Mailer/SOGoMailFolder.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,14 @@
matchingSyncToken: (NSString *) theSyncToken
fromDate: (NSCalendarDate *) theStartDate
initialLoad: (BOOL) initialLoadInProgress;
/* flags */
- (NSArray *) syncTokenFieldsWithProperties: (NSDictionary *) theProperties
matchingSyncToken: (NSString *) theSyncToken
fromDate: (NSCalendarDate *) theStartDate
initialLoad: (BOOL) initialLoadInProgress
sortOrdering: (id) theSortOrdering
threaded: (BOOL) isThreaded;

/* flags */

- (NSException *) addFlagsToAllMessages: (id) _f;

Expand Down
29 changes: 23 additions & 6 deletions SoObjects/Mailer/SOGoMailFolder.m
Original file line number Diff line number Diff line change
Expand Up @@ -2259,6 +2259,21 @@ - (NSArray *) syncTokenFieldsWithProperties: (NSDictionary *) theProperties
matchingSyncToken: (NSString *) theSyncToken
fromDate: (NSCalendarDate *) theStartDate
initialLoad: (BOOL) initialLoadInProgress
{
return [self syncTokenFieldsWithProperties: theProperties
matchingSyncToken: theSyncToken
fromDate: theStartDate
initialLoad: initialLoadInProgress
sortOrdering: nil
threaded: NO];
}

- (NSArray *) syncTokenFieldsWithProperties: (NSDictionary *) theProperties
matchingSyncToken: (NSString *) theSyncToken
fromDate: (NSCalendarDate *) theStartDate
initialLoad: (BOOL) initialLoadInProgress
sortOrdering: (id) theSortOrdering
threaded: (BOOL) isThreaded
{
EOQualifier *searchQualifier;
NSMutableArray *allTokens;
Expand Down Expand Up @@ -2316,17 +2331,19 @@ - (NSArray *) syncTokenFieldsWithProperties: (NSDictionary *) theProperties

// we fetch modified or added uids
uids = [self fetchUIDsMatchingQualifier: searchQualifier
sortOrdering: nil];
sortOrdering: theSortOrdering];

fetchResults = [(NSDictionary *)[self fetchUIDs: uids
parts: [NSArray arrayWithObjects: @"modseq", @"flags", nil]]
objectForKey: @"fetch"];

/* NOTE: we sort items manually because Cyrus does not properly sort
entries with a MODSEQ of 0 */
fetchResults
= [fetchResults sortedArrayUsingFunction: _compareFetchResultsByMODSEQ
context: NULL];
if (theSortOrdering == nil)
{
/* NOTE: we sort items manually because Cyrus does not properly sort
entries with a MODSEQ of 0 */
fetchResults = [fetchResults sortedArrayUsingFunction: _compareFetchResultsByMODSEQ
context: NULL];
}

for (i = 0; i < [fetchResults count]; i++)
{
Expand Down
81 changes: 79 additions & 2 deletions UI/MailerUI/UIxMailListActions.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSString+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGImap4/NGImap4Connection.h>
#import <NGImap4/NGImap4Envelope.h>

#import <EOControl/EOQualifier.h>
Expand Down Expand Up @@ -489,7 +490,7 @@ - (NSArray *) getSortedUIDsInFolder: (SOGoMailFolder *) mailFolder
}
else
fetchQualifier = notDeleted;

sortedUIDs = [mailFolder fetchUIDsMatchingQualifier: fetchQualifier
sortOrdering: [self imap4SortOrdering]
threaded: sortByThread];
Expand Down Expand Up @@ -648,7 +649,7 @@ - (NSDictionary *) getUIDsInFolder: (SOGoMailFolder *) folder
int count;

data = [NSMutableDictionary dictionary];

// TODO: we might want to flush the caches?
//[folder flushMailCaches];
[folder expungeLastMarkedFolder];
Expand All @@ -661,6 +662,16 @@ - (NSDictionary *) getUIDsInFolder: (SOGoMailFolder *) folder
return nil;
}

// We first make sure QRESYNC is enabled
if (![[folder imap4Connection] enableExtensions: [NSArray arrayWithObject: @"QRESYNC"]])
{
NSString *tag = [folder davCollectionTag];
if (![tag isEqualToString: @"-1"])
{
[data setObject: tag forKey: @"syncToken"];
}
}

// Get rid of the extra parenthesis
// uids = [[[[uids stringValue] stringByReplacingOccurrencesOfString:@"(" withString:@""] stringByReplacingOccurrencesOfString:@")" withString:@""] componentsSeparatedByString:@","];

Expand Down Expand Up @@ -786,6 +797,72 @@ - (NSDictionary *) getUIDsInFolder: (SOGoMailFolder *) folder
return response;
}

- (id <WOActionResults>) getChangesAction
{
NSArray *changedMessages, *headers;
NSDictionary *requestContent, *data, *changedMessage;
NSMutableArray *changedUids, *deletedUids;
NSString *syncToken, *newSyncToken, *uid;
SOGoMailFolder *folder;
WORequest *request;
WOResponse *response;
int i, max;

request = [context request];
requestContent = [[request contentAsString] objectFromJSONString];
response = nil;
folder = [self clientObject];
syncToken = [requestContent objectForKey: @"syncToken"];
newSyncToken = [folder davCollectionTag];

if ([syncToken length] && ![syncToken isEqual: newSyncToken])
{
// Fetch list of changed uids
changedMessages = [folder syncTokenFieldsWithProperties: nil
matchingSyncToken: syncToken
fromDate: nil
initialLoad: NO
sortOrdering: [self imap4SortOrdering]
threaded: sortByThread];
if ((max = [changedMessages count]))
{
// Split new or modified uids from deleted uids
changedUids = [NSMutableArray array];
deletedUids = [NSMutableArray array];
for (i = 0; i < max; i++)
{
changedMessage = [changedMessages objectAtIndex: i];
uid = [[changedMessage allKeys] lastObject];
if ([[changedMessage objectForKey: uid] isEqual: [NSNull null]])
[deletedUids addObject: uid];
else
[changedUids addObject: uid];
}

// Fetch headers for new or modified messages
headers = [self getHeadersForUIDs: changedUids
inFolder: folder];

data = [NSDictionary dictionaryWithObjectsAndKeys:
changedUids, @"changed",
deletedUids, @"deleted",
headers, @"headers",
newSyncToken, @"syncToken",
nil];
response = [self responseWithStatus: 200 andJSONRepresentation: data];
}
}
if (!response)
{
data = [NSDictionary dictionaryWithObjectsAndKeys:
newSyncToken, @"syncToken",
nil];
response = [self responseWithStatus: 200 andJSONRepresentation: data];
}

return response;
}

- (NSArray *) getHeadersForUIDs: (NSArray *) uids
inFolder: (SOGoMailFolder *) mailFolder
{
Expand Down
5 changes: 5 additions & 0 deletions UI/MailerUI/product.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
actionClass = "UIxMailListActions";
actionName = "getUIDs";
};
changes = {
protectedBy = "View";
actionClass = "UIxMailListActions";
actionName = "getChanges";
};
headers = {
protectedBy = "View";
actionClass = "UIxMailListActions";
Expand Down
6 changes: 3 additions & 3 deletions UI/Templates/MailerUI/UIxMailFolderTemplate.wox
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
<md-button class="sg-icon-button" ng-click="mailbox.unselectMessages()">
<md-icon>arrow_back</md-icon>
</md-button>
<label class="md-truncate"><span ng-bind="mailbox.service.selectedFolder.$selectedCount()"><!-- count --></span> <var:string label:value="selected"/></label>
<label class="md-truncate"><span ng-bind="mailbox.service.selectedFolder.selectedCount()"><!-- count --></span> <var:string label:value="selected"/></label>
<div class="md-flex"><!-- spacer --></div>
<md-button class="sg-icon-button" ng-click="mailbox.selectAll()">
<md-tooltip md-direction="bottom"><var:string label:value="Select All"/></md-tooltip>
Expand Down Expand Up @@ -286,8 +286,8 @@
<md-list class="sg-section-list"
ng-class="{ 'sg-list-selectable': mailbox.mode.multiple }"
sg-draggable="mailbox.selectedFolder"
sg-drag-start="mailbox.selectedFolder.hasSelectedMessage() || mailbox.selectedFolder.$selectedCount()"
sg-drag-count="mailbox.selectedFolder.$selectedCount()">
sg-drag-start="mailbox.selectedFolder.hasSelectedMessage() || mailbox.selectedFolder.selectedCount()"
sg-drag-count="mailbox.selectedFolder.selectedCount()">
<md-list-item
aria-label="{{currentMessage.subject}}"
class="sg-message-list-item"
Expand Down
Loading

0 comments on commit a9c6f09

Please sign in to comment.