From 1ef3423c67086601246053c2a3a5e639ac3596e8 Mon Sep 17 00:00:00 2001 From: Lin Junjie Date: Thu, 25 Jul 2013 20:14:55 +0800 Subject: Load last 10 emails in iOS example app --- .../iOS UI Test/iOS UI Test/MasterViewController.m | 46 +++++++++++++++------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'example') diff --git a/example/ios/iOS UI Test/iOS UI Test/MasterViewController.m b/example/ios/iOS UI Test/iOS UI Test/MasterViewController.m index 7540eee8..89173dbd 100644 --- a/example/ios/iOS UI Test/iOS UI Test/MasterViewController.m +++ b/example/ios/iOS UI Test/iOS UI Test/MasterViewController.m @@ -17,6 +17,8 @@ #define CLIENT_SECRET @"the-client-secret" #define KEYCHAIN_ITEM_NAME @"MailCore OAuth 2.0 Token" +#define NUMBER_OF_MESSAGES_TO_LOAD 10 + @interface MasterViewController () @property (nonatomic, strong) NSArray *messages; @@ -109,7 +111,7 @@ finishedRefreshWithFetcher:(GTMHTTPFetcher *)fetcher self.imapSession.connectionLogger = ^(void * connectionID, MCOConnectionLogType type, NSData * data) { @synchronized(weakSelf) { if (type != MCOConnectionLogTypeSentPrivate) { - NSLog(@"event logged:%p %i withData: %@", connectionID, type, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); +// NSLog(@"event logged:%p %i withData: %@", connectionID, type, [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); } } }; @@ -134,21 +136,37 @@ finishedRefreshWithFetcher:(GTMHTTPFetcher *)fetcher (MCOIMAPMessagesRequestKindHeaders | MCOIMAPMessagesRequestKindStructure | MCOIMAPMessagesRequestKindInternalDate | MCOIMAPMessagesRequestKindHeaderSubject | MCOIMAPMessagesRequestKindFlags); - self.imapMessagesFetchOp = [self.imapSession fetchMessagesByUIDOperationWithFolder:@"INBOX" - requestKind:requestKind - uids:[MCOIndexSet indexSetWithRange:MCORangeMake(1, UINT64_MAX)]]; - [self.imapMessagesFetchOp setProgress:^(unsigned int progress) { - //NSLog(@"progress: %u", progress); - }]; - __weak MasterViewController *weakSelf = self; - [self.imapMessagesFetchOp start:^(NSError *error, NSArray *messages, MCOIndexSet *vanishedMessages) { - MasterViewController *strongSelf = weakSelf; - NSLog(@"fetched all messages."); + NSString *inboxFolder = @"INBOX"; + MCOIMAPFolderInfoOperation *inboxFolderInfo = [self.imapSession folderInfoOperation:inboxFolder]; + + [inboxFolderInfo start:^(NSError *error, MCOIMAPFolderInfo *info) + { + NSUInteger numberOfMessagesToLoad = + MIN([info messageCount], NUMBER_OF_MESSAGES_TO_LOAD); + + if (numberOfMessagesToLoad == 0) + return; + + self.imapMessagesFetchOp = + [self.imapSession fetchMessagesByNumberOperationWithFolder:inboxFolder + requestKind:requestKind + numbers: + [MCOIndexSet indexSetWithRange:MCORangeMake([info messageCount] - (numberOfMessagesToLoad - 1), (numberOfMessagesToLoad - 1))]]; + + [self.imapMessagesFetchOp setProgress:^(unsigned int progress) { + NSLog(@"Progress: %u of %u", progress, numberOfMessagesToLoad); + }]; - NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"header.date" ascending:NO]; - strongSelf.messages = [messages sortedArrayUsingDescriptors:@[sort]]; - [strongSelf.tableView reloadData]; + __weak MasterViewController *weakSelf = self; + [self.imapMessagesFetchOp start:^(NSError *error, NSArray *messages, MCOIndexSet *vanishedMessages) { + MasterViewController *strongSelf = weakSelf; + NSLog(@"fetched all messages."); + + NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"header.date" ascending:NO]; + strongSelf.messages = [messages sortedArrayUsingDescriptors:@[sort]]; + [strongSelf.tableView reloadData]; + }]; }]; } -- cgit v1.2.3 From 61053a2c137056992c2393eb9471495ac1b25487 Mon Sep 17 00:00:00 2001 From: Lin Junjie Date: Thu, 25 Jul 2013 21:38:57 +0800 Subject: iOS example app: Add 'Load more' when there are more mails to fetch. Adds caching of preview so we don't have to fetch them again on load more. --- .../iOS UI Test/iOS UI Test/MasterViewController.m | 234 ++++++++++++++++++--- 1 file changed, 203 insertions(+), 31 deletions(-) (limited to 'example') diff --git a/example/ios/iOS UI Test/iOS UI Test/MasterViewController.m b/example/ios/iOS UI Test/iOS UI Test/MasterViewController.m index 89173dbd..0ed66e70 100644 --- a/example/ios/iOS UI Test/iOS UI Test/MasterViewController.m +++ b/example/ios/iOS UI Test/iOS UI Test/MasterViewController.m @@ -19,12 +19,21 @@ #define NUMBER_OF_MESSAGES_TO_LOAD 10 +static NSString *mailCellIdentifier = @"MailCell"; +static NSString *inboxInfoIdentifier = @"InboxStatusCell"; + @interface MasterViewController () @property (nonatomic, strong) NSArray *messages; @property (nonatomic, strong) MCOIMAPOperation *imapCheckOp; @property (nonatomic, strong) MCOIMAPSession *imapSession; @property (nonatomic, strong) MCOIMAPFetchMessagesOperation *imapMessagesFetchOp; + + +@property (nonatomic) NSInteger totalNumberOfInboxMessages; +@property (nonatomic) BOOL isLoading; +@property (nonatomic, strong) UIActivityIndicatorView *loadMoreActivityView; +@property (nonatomic, strong) NSMutableDictionary *messagePreviews; @end @implementation MasterViewController @@ -32,6 +41,13 @@ - (void)viewDidLoad { [super viewDidLoad]; + [self.tableView registerClass:[MCTTableViewCell class] + forCellReuseIdentifier:mailCellIdentifier]; + + self.loadMoreActivityView = + [[UIActivityIndicatorView alloc] + initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + [[NSUserDefaults standardUserDefaults] registerDefaults:@{ HostnameKey: @"imap.gmail.com" }]; if ([[NSUserDefaults standardUserDefaults] boolForKey:@"OAuth2Enabled"]) { @@ -115,6 +131,13 @@ finishedRefreshWithFetcher:(GTMHTTPFetcher *)fetcher } } }; + + // Reset the inbox + self.messages = nil; + self.totalNumberOfInboxMessages = -1; + self.isLoading = NO; + self.messagePreviews = [NSMutableDictionary dictionary]; + [self.tableView reloadData]; NSLog(@"checking account"); self.imapCheckOp = [self.imapSession checkAccountOperation]; @@ -122,7 +145,7 @@ finishedRefreshWithFetcher:(GTMHTTPFetcher *)fetcher MasterViewController *strongSelf = weakSelf; NSLog(@"finished checking account."); if (error == nil) { - [strongSelf loadEmails]; + [strongSelf loadLastNMessages:NUMBER_OF_MESSAGES_TO_LOAD]; } else { NSLog(@"error loading account: %@", error); } @@ -131,7 +154,10 @@ finishedRefreshWithFetcher:(GTMHTTPFetcher *)fetcher }]; } -- (void)loadEmails { +- (void)loadLastNMessages:(NSUInteger)nMessages +{ + self.isLoading = YES; + MCOIMAPMessagesRequestKind requestKind = (MCOIMAPMessagesRequestKind) (MCOIMAPMessagesRequestKindHeaders | MCOIMAPMessagesRequestKindStructure | MCOIMAPMessagesRequestKindInternalDate | MCOIMAPMessagesRequestKindHeaderSubject | @@ -142,29 +168,73 @@ finishedRefreshWithFetcher:(GTMHTTPFetcher *)fetcher [inboxFolderInfo start:^(NSError *error, MCOIMAPFolderInfo *info) { + BOOL totalNumberOfMessagesDidChange = + self.totalNumberOfInboxMessages != [info messageCount]; + + self.totalNumberOfInboxMessages = [info messageCount]; + NSUInteger numberOfMessagesToLoad = - MIN([info messageCount], NUMBER_OF_MESSAGES_TO_LOAD); + MIN(self.totalNumberOfInboxMessages, nMessages); if (numberOfMessagesToLoad == 0) + { + self.isLoading = NO; return; - + } + + MCORange fetchRange; + + // If total number of messages did not change since last fetch, + // assume nothing was deleted since our last fetch and just + // fetch what we don't have + if (!totalNumberOfMessagesDidChange && self.messages.count) + { + numberOfMessagesToLoad -= self.messages.count; + + fetchRange = + MCORangeMake(self.totalNumberOfInboxMessages - + self.messages.count - + (numberOfMessagesToLoad - 1), + (numberOfMessagesToLoad - 1)); + } + + // Else just fetch the last N messages + else + { + fetchRange = + MCORangeMake(self.totalNumberOfInboxMessages - + (numberOfMessagesToLoad - 1), + (numberOfMessagesToLoad - 1)); + } + self.imapMessagesFetchOp = [self.imapSession fetchMessagesByNumberOperationWithFolder:inboxFolder requestKind:requestKind numbers: - [MCOIndexSet indexSetWithRange:MCORangeMake([info messageCount] - (numberOfMessagesToLoad - 1), (numberOfMessagesToLoad - 1))]]; + [MCOIndexSet indexSetWithRange:fetchRange]]; [self.imapMessagesFetchOp setProgress:^(unsigned int progress) { NSLog(@"Progress: %u of %u", progress, numberOfMessagesToLoad); }]; __weak MasterViewController *weakSelf = self; - [self.imapMessagesFetchOp start:^(NSError *error, NSArray *messages, MCOIndexSet *vanishedMessages) { + [self.imapMessagesFetchOp start: + ^(NSError *error, NSArray *messages, MCOIndexSet *vanishedMessages) + { MasterViewController *strongSelf = weakSelf; NSLog(@"fetched all messages."); - NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"header.date" ascending:NO]; - strongSelf.messages = [messages sortedArrayUsingDescriptors:@[sort]]; + self.isLoading = NO; + + NSSortDescriptor *sort = + [NSSortDescriptor sortDescriptorWithKey:@"header.date" ascending:NO]; + + NSMutableArray *combinedMessages = + [NSMutableArray arrayWithArray:messages]; + [combinedMessages addObjectsFromArray:strongSelf.messages]; + + strongSelf.messages = + [combinedMessages sortedArrayUsingDescriptors:@[sort]]; [strongSelf.tableView reloadData]; }]; }]; @@ -178,30 +248,103 @@ finishedRefreshWithFetcher:(GTMHTTPFetcher *)fetcher #pragma mark - Table View - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; + return 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + if (section == 1) + { + if (self.totalNumberOfInboxMessages >= 0) + return 1; + + return 0; + } + return self.messages.count; } -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - NSString * cellIdentifier = @"Cell"; - [tableView registerClass:[MCTTableViewCell class] forCellReuseIdentifier:cellIdentifier]; - - MCTTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath]; - MCOIMAPMessage *message = self.messages[indexPath.row]; - - cell.textLabel.text = message.header.subject; - cell.messageRenderingOperation = [self.imapSession plainTextBodyRenderingOperationWithMessage:message - folder:@"INBOX"]; - - [cell.messageRenderingOperation start:^(NSString * plainTextBodyString, NSError * error) { - cell.detailTextLabel.text = plainTextBodyString; - cell.messageRenderingOperation = nil; - }]; +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + switch (indexPath.section) + { + case 0: + { + MCTTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:mailCellIdentifier forIndexPath:indexPath]; + MCOIMAPMessage *message = self.messages[indexPath.row]; + + cell.textLabel.text = message.header.subject; + + NSString *uidKey = [NSString stringWithFormat:@"%d", message.uid]; + NSString *cachedPreview = self.messagePreviews[uidKey]; + + if (cachedPreview) + { + cell.detailTextLabel.text = cachedPreview; + } + else + { + cell.messageRenderingOperation = [self.imapSession plainTextBodyRenderingOperationWithMessage:message + folder:@"INBOX"]; + + [cell.messageRenderingOperation start:^(NSString * plainTextBodyString, NSError * error) { + cell.detailTextLabel.text = plainTextBodyString; + cell.messageRenderingOperation = nil; + self.messagePreviews[uidKey] = plainTextBodyString; + }]; + } + + return cell; + break; + } + + case 1: + { + UITableViewCell *cell = + [tableView dequeueReusableCellWithIdentifier:inboxInfoIdentifier]; + + if (!cell) + { + cell = + [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle + reuseIdentifier:inboxInfoIdentifier]; + + cell.textLabel.font = [UIFont boldSystemFontOfSize:14]; + cell.textLabel.textAlignment = NSTextAlignmentCenter; + cell.detailTextLabel.textAlignment = NSTextAlignmentCenter; + } + + if (self.messages.count < self.totalNumberOfInboxMessages) + { + cell.textLabel.text = + [NSString stringWithFormat:@"Load %d more", + MIN(self.totalNumberOfInboxMessages - self.messages.count, + NUMBER_OF_MESSAGES_TO_LOAD)]; + } + else + { + cell.textLabel.text = nil; + } + + cell.detailTextLabel.text = + [NSString stringWithFormat:@"%d message(s)", + self.totalNumberOfInboxMessages]; + + cell.accessoryView = self.loadMoreActivityView; + + if (self.isLoading) + [self.loadMoreActivityView startAnimating]; + else + [self.loadMoreActivityView stopAnimating]; + + return cell; + break; + } + + default: + return nil; + break; + } - return cell; } - (void)showSettingsViewController:(id)sender { @@ -228,12 +371,41 @@ finishedRefreshWithFetcher:(GTMHTTPFetcher *)fetcher } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - MCOIMAPMessage *msg = self.messages[indexPath.row]; - MCTMsgViewController *vc = [[MCTMsgViewController alloc] init]; - vc.folder = @"INBOX"; - vc.message = msg; - vc.session = self.imapSession; - [self.navigationController pushViewController:vc animated:YES]; + + switch (indexPath.section) + { + case 0: + { + MCOIMAPMessage *msg = self.messages[indexPath.row]; + MCTMsgViewController *vc = [[MCTMsgViewController alloc] init]; + vc.folder = @"INBOX"; + vc.message = msg; + vc.session = self.imapSession; + [self.navigationController pushViewController:vc animated:YES]; + + break; + } + + case 1: + { + UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; + + if (!self.isLoading && + self.messages.count < self.totalNumberOfInboxMessages) + { + [self loadLastNMessages:self.messages.count + NUMBER_OF_MESSAGES_TO_LOAD]; + cell.accessoryView = self.loadMoreActivityView; + [self.loadMoreActivityView startAnimating]; + } + + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + break; + } + + default: + break; + } + } @end -- cgit v1.2.3