From 78ff578ba6e3db00e336185c76ff122eadb17e46 Mon Sep 17 00:00:00 2001 From: Oliver Rickard Date: Wed, 1 May 2013 21:49:35 -0700 Subject: Modified the mac project web view to run on iOS. Not fully tested. --- .../iOS UI Test.xcodeproj/project.pbxproj | 24 +- .../iOS UI Test/iOS UI Test/DetailViewController.h | 16 - .../iOS UI Test/iOS UI Test/DetailViewController.m | 51 --- .../iOS UI Test/iOS UI Test/MCOCIDURLProtocol.h | 31 ++ .../iOS UI Test/iOS UI Test/MCOCIDURLProtocol.mm | 145 +++++++++ .../ios/iOS UI Test/iOS UI Test/MCOMessageView.h | 48 +++ .../ios/iOS UI Test/iOS UI Test/MCOMessageView.mm | 348 +++++++++++++++++++++ .../iOS UI Test/iOS UI Test/MCTMsgViewController.h | 31 ++ .../iOS UI Test/iOS UI Test/MCTMsgViewController.m | 271 ++++++++++++++++ .../iOS UI Test/iOS UI Test/MasterViewController.m | 14 +- .../iOS UI Test/en.lproj/MainStoryboard.storyboard | 44 +-- 11 files changed, 908 insertions(+), 115 deletions(-) delete mode 100644 example/ios/iOS UI Test/iOS UI Test/DetailViewController.h delete mode 100644 example/ios/iOS UI Test/iOS UI Test/DetailViewController.m create mode 100755 example/ios/iOS UI Test/iOS UI Test/MCOCIDURLProtocol.h create mode 100755 example/ios/iOS UI Test/iOS UI Test/MCOCIDURLProtocol.mm create mode 100755 example/ios/iOS UI Test/iOS UI Test/MCOMessageView.h create mode 100755 example/ios/iOS UI Test/iOS UI Test/MCOMessageView.mm create mode 100755 example/ios/iOS UI Test/iOS UI Test/MCTMsgViewController.h create mode 100755 example/ios/iOS UI Test/iOS UI Test/MCTMsgViewController.m (limited to 'example') diff --git a/example/ios/iOS UI Test/iOS UI Test.xcodeproj/project.pbxproj b/example/ios/iOS UI Test/iOS UI Test.xcodeproj/project.pbxproj index bb9124a9..cc5a6ae7 100644 --- a/example/ios/iOS UI Test/iOS UI Test.xcodeproj/project.pbxproj +++ b/example/ios/iOS UI Test/iOS UI Test.xcodeproj/project.pbxproj @@ -22,10 +22,12 @@ AB9EAE1C170368F000D750C7 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AB9EAE1B170368F000D750C7 /* Default-568h@2x.png */; }; AB9EAE1F170368F000D750C7 /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AB9EAE1D170368F000D750C7 /* MainStoryboard.storyboard */; }; AB9EAE22170368F000D750C7 /* MasterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AB9EAE21170368F000D750C7 /* MasterViewController.m */; }; - AB9EAE25170368F000D750C7 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AB9EAE24170368F000D750C7 /* DetailViewController.m */; }; AB9EAE3617036FD700D750C7 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = AB9EAE3417036FD600D750C7 /* SettingsViewController.m */; }; AB9EAE3717036FD700D750C7 /* SettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB9EAE3517036FD700D750C7 /* SettingsViewController.xib */; }; AB9EAE40170374D900D750C7 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB9EAE3F170374D900D750C7 /* Security.framework */; }; + B12AAA3317322654003551C7 /* MCOCIDURLProtocol.mm in Sources */ = {isa = PBXBuildFile; fileRef = B12AAA2E17322654003551C7 /* MCOCIDURLProtocol.mm */; }; + B12AAA3417322654003551C7 /* MCOMessageView.mm in Sources */ = {isa = PBXBuildFile; fileRef = B12AAA3017322654003551C7 /* MCOMessageView.mm */; }; + B12AAA3517322654003551C7 /* MCTMsgViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B12AAA3217322654003551C7 /* MCTMsgViewController.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -97,12 +99,16 @@ AB9EAE1E170368F000D750C7 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard.storyboard; sourceTree = ""; }; AB9EAE20170368F000D750C7 /* MasterViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MasterViewController.h; sourceTree = ""; }; AB9EAE21170368F000D750C7 /* MasterViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MasterViewController.m; sourceTree = ""; }; - AB9EAE23170368F000D750C7 /* DetailViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; - AB9EAE24170368F000D750C7 /* DetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; AB9EAE3317036FD600D750C7 /* SettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsViewController.h; sourceTree = ""; }; AB9EAE3417036FD600D750C7 /* SettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsViewController.m; sourceTree = ""; }; AB9EAE3517036FD700D750C7 /* SettingsViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SettingsViewController.xib; sourceTree = ""; }; AB9EAE3F170374D900D750C7 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + B12AAA2D17322654003551C7 /* MCOCIDURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOCIDURLProtocol.h; sourceTree = ""; }; + B12AAA2E17322654003551C7 /* MCOCIDURLProtocol.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOCIDURLProtocol.mm; sourceTree = ""; }; + B12AAA2F17322654003551C7 /* MCOMessageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCOMessageView.h; sourceTree = ""; }; + B12AAA3017322654003551C7 /* MCOMessageView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MCOMessageView.mm; sourceTree = ""; }; + B12AAA3117322654003551C7 /* MCTMsgViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MCTMsgViewController.h; sourceTree = ""; }; + B12AAA3217322654003551C7 /* MCTMsgViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCTMsgViewController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -186,8 +192,12 @@ AB9EAE1D170368F000D750C7 /* MainStoryboard.storyboard */, AB9EAE20170368F000D750C7 /* MasterViewController.h */, AB9EAE21170368F000D750C7 /* MasterViewController.m */, - AB9EAE23170368F000D750C7 /* DetailViewController.h */, - AB9EAE24170368F000D750C7 /* DetailViewController.m */, + B12AAA2D17322654003551C7 /* MCOCIDURLProtocol.h */, + B12AAA2E17322654003551C7 /* MCOCIDURLProtocol.mm */, + B12AAA2F17322654003551C7 /* MCOMessageView.h */, + B12AAA3017322654003551C7 /* MCOMessageView.mm */, + B12AAA3117322654003551C7 /* MCTMsgViewController.h */, + B12AAA3217322654003551C7 /* MCTMsgViewController.m */, AB9EAE0C170368F000D750C7 /* Supporting Files */, AB9EAE3317036FD600D750C7 /* SettingsViewController.h */, AB9EAE3417036FD600D750C7 /* SettingsViewController.m */, @@ -325,10 +335,12 @@ AB9EAE12170368F000D750C7 /* main.mm in Sources */, AB9EAE16170368F000D750C7 /* AppDelegate.m in Sources */, AB9EAE22170368F000D750C7 /* MasterViewController.m in Sources */, - AB9EAE25170368F000D750C7 /* DetailViewController.m in Sources */, AB9EAE3617036FD700D750C7 /* SettingsViewController.m in Sources */, AB665BCD17134336007F2151 /* FXKeychain.m in Sources */, AB7BA4511713CE3300104953 /* Application.mm in Sources */, + B12AAA3317322654003551C7 /* MCOCIDURLProtocol.mm in Sources */, + B12AAA3417322654003551C7 /* MCOMessageView.mm in Sources */, + B12AAA3517322654003551C7 /* MCTMsgViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/example/ios/iOS UI Test/iOS UI Test/DetailViewController.h b/example/ios/iOS UI Test/iOS UI Test/DetailViewController.h deleted file mode 100644 index fe50ad58..00000000 --- a/example/ios/iOS UI Test/iOS UI Test/DetailViewController.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// DetailViewController.h -// iOS UI Test -// -// Created by Jonathan Willing on 4/8/13. -// Copyright (c) 2013 AppJon. All rights reserved. -// - -#import - -@interface DetailViewController : UIViewController - -@property (strong, nonatomic) id detailItem; - -@property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel; -@end diff --git a/example/ios/iOS UI Test/iOS UI Test/DetailViewController.m b/example/ios/iOS UI Test/iOS UI Test/DetailViewController.m deleted file mode 100644 index 16100698..00000000 --- a/example/ios/iOS UI Test/iOS UI Test/DetailViewController.m +++ /dev/null @@ -1,51 +0,0 @@ -// -// DetailViewController.m -// iOS UI Test -// -// Created by Jonathan Willing on 4/8/13. -// Copyright (c) 2013 AppJon. All rights reserved. -// - -#import "DetailViewController.h" - -@interface DetailViewController () -- (void)configureView; -@end - -@implementation DetailViewController - -#pragma mark - Managing the detail item - -- (void)setDetailItem:(id)newDetailItem -{ - if (_detailItem != newDetailItem) { - _detailItem = newDetailItem; - - // Update the view. - [self configureView]; - } -} - -- (void)configureView -{ - // Update the user interface for the detail item. - - if (self.detailItem) { - self.detailDescriptionLabel.text = [self.detailItem description]; - } -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - // Do any additional setup after loading the view, typically from a nib. - [self configureView]; -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -@end diff --git a/example/ios/iOS UI Test/iOS UI Test/MCOCIDURLProtocol.h b/example/ios/iOS UI Test/iOS UI Test/MCOCIDURLProtocol.h new file mode 100755 index 00000000..ac4b0f2b --- /dev/null +++ b/example/ios/iOS UI Test/iOS UI Test/MCOCIDURLProtocol.h @@ -0,0 +1,31 @@ +// +// MCTCIDURLProtocol.h +// testUI +// +// Created by DINH Viêt Hoà on 1/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import + +#include + +@interface MCOCIDURLProtocol : NSURLProtocol + ++ (void) registerProtocol; + ++ (BOOL) isCID:(NSURL *)url; ++ (BOOL) isXMailcoreImage:(NSURL *)url; + +#ifdef __cplusplus ++ (void) startLoadingWithMessage:(MCOAbstractMessage *)message + partUniqueID:(NSString *)partUniqueID + data:(NSData *)data + request:(NSMutableURLRequest *)request; + ++ (void) partDownloadedMessage:(MCOAbstractMessage *)message + partUniqueID:(NSString *)partUniqueID + data:(NSData *)data; +#endif + +@end diff --git a/example/ios/iOS UI Test/iOS UI Test/MCOCIDURLProtocol.mm b/example/ios/iOS UI Test/iOS UI Test/MCOCIDURLProtocol.mm new file mode 100755 index 00000000..6a6d0a03 --- /dev/null +++ b/example/ios/iOS UI Test/iOS UI Test/MCOCIDURLProtocol.mm @@ -0,0 +1,145 @@ +// +// MCTCIDURLProtocol.m +// testUI +// +// Created by DINH Viêt Hoà on 1/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import "MCOCIDURLProtocol.h" + +#import "MCOMessageView.h" + +#define MCOCIDURLProtocolDownloadedNotification @"MCOCIDURLProtocolDownloadedNotification" + +@implementation MCOCIDURLProtocol + ++ (void) registerProtocol +{ + static dispatch_once_t onceToken = 0; + dispatch_once(&onceToken, ^{ + [NSURLProtocol registerClass:[MCOCIDURLProtocol class]]; + }); +} + ++ (BOOL) canInitWithRequest:(NSURLRequest *)theRequest +{ + if ([self isCID:[theRequest URL]]) + return YES; + if ([self isXMailcoreImage:[theRequest URL]]) + return YES; + return NO; +} + ++ (BOOL) isCID:(NSURL *)url +{ + NSString *theScheme = [url scheme]; + if ([theScheme caseInsensitiveCompare:@"cid"] == NSOrderedSame) + return YES; + return NO; +} + ++ (BOOL) isXMailcoreImage:(NSURL *)url +{ + NSString *theScheme = [url scheme]; + if ([theScheme caseInsensitiveCompare:@"x-mailcore-image"] == NSOrderedSame) + return YES; + return NO; +} + ++ (NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request +{ + return request; +} + +- (id) initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id < NSURLProtocolClient >)client +{ + self = [super initWithRequest:request cachedResponse:cachedResponse client:client]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_downloaded:) name:MCOCIDURLProtocolDownloadedNotification object:nil]; + return self; +} + +- (void) dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (NSString *) _partUniqueID +{ + return [NSURLProtocol propertyForKey:@"PartUniqueID" inRequest:[self request]]; +} + +- (NSData *) _data +{ + return [NSURLProtocol propertyForKey:@"Data" inRequest:[self request]]; +} + +- (MCOAbstractMessage *) _message +{ + return (MCOAbstractMessage *) [NSURLProtocol propertyForKey:@"Message" inRequest:[self request]]; +} + +- (void) startLoading +{ + //NSLog(@"waiting for %p %@", self, [self _partUniqueID]); + if ([self _data] != NULL) { + [[self class] partDownloadedMessage:[self _message] partUniqueID:[self _partUniqueID] data:[self _data]]; + } +} + +- (void) _downloaded:(NSNotification *)notification +{ + NSDictionary * userInfo = [notification userInfo]; + + //NSLog(@"downloaded?"); + NSString * notifPartID = [userInfo objectForKey:@"PartUniqueID"]; + MCOAbstractMessage * notifMessage = [userInfo objectForKey:@"Message"]; + if (notifMessage != [self _message]) { + return; + } + if (![[self _partUniqueID] isEqualToString:notifPartID]) { + return; + } + + //NSLog(@"downloaded2 %p %@", self, notifPartID); + + NSData * data = [userInfo objectForKey:@"Data"]; + NSURLResponse * response = [[NSURLResponse alloc] initWithURL:[[self request] URL] MIMEType:@"application/data" + expectedContentLength:[data length] textEncodingName:nil]; + [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; + [[self client] URLProtocol:self didLoadData:data]; + [[self client] URLProtocolDidFinishLoading:self]; +} + +- (void) stopLoading +{ +} + ++ (void) startLoadingWithMessage:(MCOAbstractMessage *)message + partUniqueID:(NSString *)partUniqueID + data:(NSData *)data + request:(NSMutableURLRequest *)request +{ + [NSURLProtocol setProperty:message + forKey:@"Message" inRequest:request]; + if (data != NULL) { + [NSURLProtocol setProperty:data forKey:@"Data" inRequest:request]; + } + [NSURLProtocol setProperty:partUniqueID forKey:@"PartUniqueID" inRequest:request]; +} + ++ (void) partDownloadedMessage:(MCOAbstractMessage *)message + partUniqueID:(NSString *)partUniqueID + data:(NSData *)data +{ + NSMutableDictionary * userInfo = [[NSMutableDictionary alloc] init]; + [userInfo setObject:message forKey:@"Message"]; + [userInfo setObject:partUniqueID forKey:@"PartUniqueID"]; + if (data != NULL) { + [userInfo setObject:data forKey:@"Data"]; + } + [[NSNotificationCenter defaultCenter] postNotificationName:MCOCIDURLProtocolDownloadedNotification object:nil userInfo:userInfo]; + //NSLog(@"downloaded %p %@", self, partUniqueID); +} + +@end diff --git a/example/ios/iOS UI Test/iOS UI Test/MCOMessageView.h b/example/ios/iOS UI Test/iOS UI Test/MCOMessageView.h new file mode 100755 index 00000000..5c458079 --- /dev/null +++ b/example/ios/iOS UI Test/iOS UI Test/MCOMessageView.h @@ -0,0 +1,48 @@ +// +// MCOMessageView.h +// testUI +// +// Created by DINH Viêt Hoà on 1/19/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include + +@protocol MCOMessageViewDelegate; + +@interface MCOMessageView : UIView + +@property (nonatomic, copy) NSString * folder; +@property (nonatomic, strong) MCOAbstractMessage * message; + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, assign) BOOL prefetchIMAPImagesEnabled; +@property (nonatomic, assign) BOOL prefetchIMAPAttachmentsEnabled; + +@end + +@protocol MCOMessageViewDelegate + +@optional +- (NSData *) MCOMessageView:(MCOMessageView *)view dataForPartWithUniqueID:(NSString *)partUniqueID; +- (void) MCOMessageView:(MCOMessageView *)view fetchDataForPartWithUniqueID:(NSString *)partUniqueID + downloadedFinished:(void (^)(NSError * error))downloadFinished; + +- (NSString *) MCOMessageView_templateForMainHeader:(MCOMessageView *)view; +- (NSString *) MCOMessageView_templateForImage:(MCOMessageView *)view; +- (NSString *) MCOMessageView_templateForAttachment:(MCOMessageView *)view; +- (NSString *) MCOMessageView_templateForMessage:(MCOMessageView *)view; +- (NSString *) MCOMessageView_templateForEmbeddedMessage:(MCOMessageView *)view; +- (NSString *) MCOMessageView_templateForEmbeddedMessageHeader:(MCOMessageView *)view; +- (NSString *) MCOMessageView_templateForAttachmentSeparator:(MCOMessageView *)view; + +- (NSDictionary *) MCOMessageView:(MCOMessageView *)view templateValuesForPartWithUniqueID:(NSString *)uniqueID; +- (NSDictionary *) MCOMessageView:(MCOMessageView *)view templateValuesForHeader:(MCOMessageHeader *)header; +- (BOOL) MCOMessageView:(MCOMessageView *)view canPreviewPart:(MCOAbstractPart *)part; + +- (NSString *) MCOMessageView:(MCOMessageView *)view filteredHTMLForPart:(NSString *)html; +- (NSString *) MCOMessageView:(MCOMessageView *)view filteredHTMLForMessage:(NSString *)html; +- (NSData *) MCOMessageView:(MCOMessageView *)view previewForData:(NSData *)data isHTMLInlineImage:(BOOL)isHTMLInlineImage; + +@end diff --git a/example/ios/iOS UI Test/iOS UI Test/MCOMessageView.mm b/example/ios/iOS UI Test/iOS UI Test/MCOMessageView.mm new file mode 100755 index 00000000..87e07b57 --- /dev/null +++ b/example/ios/iOS UI Test/iOS UI Test/MCOMessageView.mm @@ -0,0 +1,348 @@ +// +// MCOMessageView.m +// testUI +// +// Created by DINH Viêt Hoà on 1/19/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import "MCOMessageView.h" + +#import "MCOCIDURLProtocol.h" + +@interface MCOMessageView () + +@end + +@implementation MCOMessageView { + UIWebView * _webView; + NSString * _folder; + MCOAbstractMessage * _message; + __weak id _delegate; + BOOL _prefetchIMAPImagesEnabled; + BOOL _prefetchIMAPAttachmentsEnabled; +} + +@synthesize folder = _folder; +@synthesize delegate = _delegate; +@synthesize prefetchIMAPImagesEnabled = _prefetchIMAPImagesEnabled; +@synthesize prefetchIMAPAttachmentsEnabled = _prefetchIMAPAttachmentsEnabled; + ++ (void) initialize +{ + [MCOCIDURLProtocol registerProtocol]; +} + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + + if(self) { + _webView = [[UIWebView alloc] initWithFrame:[self bounds]]; + [_webView setAutoresizingMask:(UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth)]; + [_webView setDelegate:self]; + + [self addSubview:_webView]; + } + + return self; +} + +- (void) dealloc +{ + _message = nil; + _folder = nil; + _webView = nil; +} + +- (void) setMessage:(MCOAbstractMessage *)message +{ + _message = message; + + [_webView stopLoading]; + [self _refresh]; +} + +- (MCOAbstractMessage *) message +{ + return _message; +} + +- (void) _refresh +{ + NSString * content; + + if (_message == nil) { + content = nil; + } + else { + if ([_message isKindOfClass:[MCOIMAPMessage class]]) { + content = [(MCOIMAPMessage *) _message htmlRenderingWithFolder:_folder delegate:self]; + } + else if ([_message isKindOfClass:[MCOMessageBuilder class]]) { + content = [(MCOMessageBuilder *) _message htmlRenderingWithDelegate:self]; + } + else if ([_message isKindOfClass:[MCOMessageParser class]]) { + content = [(MCOMessageParser *) _message htmlRenderingWithDelegate:self]; + } + else { + content = nil; + MCAssert(0); + } + } + [_webView loadHTMLString:content baseURL:nil]; +} + +- (MCOAbstractPart *) _partForCIDURL:(NSURL *)url +{ + return [_message partForContentID:[url resourceSpecifier]]; +} + +- (MCOAbstractPart *) _partForUniqueID:(NSString *)partUniqueID +{ + return [_message partForUniqueID:partUniqueID]; +} + +- (NSData *) _dataForIMAPPart:(MCOIMAPPart *)part folder:(NSString *)folder +{ + NSData * data; + NSString * partUniqueID = [part uniqueID]; + data = [[self delegate] MCOMessageView:self dataForPartWithUniqueID:partUniqueID]; + if (data == NULL) { + [[self delegate] MCOMessageView:self fetchDataForPartWithUniqueID:partUniqueID downloadedFinished:^(NSError * error) { + [self _refresh]; + }]; + } + return data; +} + +- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { + + NSURLRequest *responseRequest = [self webView:webView resource:nil willSendRequest:request redirectResponse:nil fromDataSource:nil]; + + //NSLog(@"responseRequest:%@", responseRequest); + + if(responseRequest == request) { + return YES; + } else { + [webView loadRequest:responseRequest]; + return NO; + } + +} + +- (NSURLRequest *)webView:(UIWebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(id)dataSource +{ + MCOAbstractPart * part = NULL; + + if ([MCOCIDURLProtocol isCID:[request URL]]) { + part = [self _partForCIDURL:[request URL]]; + } + else if ([MCOCIDURLProtocol isXMailcoreImage:[ request URL]]) { + NSString * specifier = [[request URL] resourceSpecifier]; + NSString * partUniqueID = specifier; + part = [self _partForUniqueID:partUniqueID]; + } + + if (part != NULL) { + if ([_message isKindOfClass:[MCOIMAPMessage class]]) { + NSMutableURLRequest * mutableRequest = [request mutableCopy]; + NSString * partUniqueID = [part uniqueID]; + NSData * data = [[self delegate] MCOMessageView:self dataForPartWithUniqueID:partUniqueID]; + if (data == NULL) { + [[self delegate] MCOMessageView:self fetchDataForPartWithUniqueID:partUniqueID downloadedFinished:^(NSError * error) { + NSData * downloadedData = [[self delegate] MCOMessageView:self dataForPartWithUniqueID:partUniqueID]; + NSData * previewData = [[self delegate] MCOMessageView:self previewForData:downloadedData isHTMLInlineImage:[MCOCIDURLProtocol isCID:[request URL]]]; + [MCOCIDURLProtocol partDownloadedMessage:_message partUniqueID:partUniqueID data:previewData]; + }]; + } + [MCOCIDURLProtocol startLoadingWithMessage:_message + partUniqueID:partUniqueID + data:data + request:mutableRequest]; + + return mutableRequest; + } + else if ([_message isKindOfClass:[MCOMessageParser class]]) { + NSMutableURLRequest * mutableRequest = [request mutableCopy]; + NSString * partUniqueID = [part uniqueID]; + NSData * data = [(MCOAttachment *) part data]; + NSData * previewData = [[self delegate] MCOMessageView:self previewForData:data isHTMLInlineImage:[MCOCIDURLProtocol isCID:[request URL]]]; + [MCOCIDURLProtocol startLoadingWithMessage:_message + partUniqueID:partUniqueID + data:previewData + request:mutableRequest]; + + return mutableRequest; + } + else { + return request; + } + } + else { + return request; + } +} + +- (BOOL) MCOAbstractMessage:(MCOAbstractMessage *)msg canPreviewPart:(MCOAbstractPart *)part +{ + static NSMutableSet * supportedImageMimeTypes = NULL; + if (supportedImageMimeTypes == NULL) { + supportedImageMimeTypes = [[NSMutableSet alloc] init]; + [supportedImageMimeTypes addObject:@"image/png"]; + [supportedImageMimeTypes addObject:@"image/gif"]; + [supportedImageMimeTypes addObject:@"image/jpg"]; + [supportedImageMimeTypes addObject:@"image/jpeg"]; + } + static NSMutableSet * supportedImageExtension = NULL; + if (supportedImageExtension == NULL) { + supportedImageExtension = [[NSMutableSet alloc] init]; + [supportedImageExtension addObject:@"png"]; + [supportedImageExtension addObject:@"gif"]; + [supportedImageExtension addObject:@"jpg"]; + [supportedImageExtension addObject:@"jpeg"]; + } + + if ([supportedImageMimeTypes containsObject:[[part mimeType] lowercaseString]]) + return YES; + + NSString * ext = nil; + if ([part filename] != nil) { + if ([[part filename] pathExtension] != nil) { + ext = [[[part filename] pathExtension] lowercaseString]; + } + } + if (ext != nil) { + if ([supportedImageExtension containsObject:ext]) + return YES; + } + + if (![[self delegate] respondsToSelector:@selector(MCOMessageView:canPreviewPart:)]) { + return false; + } + return [[self delegate] MCOMessageView:self canPreviewPart:part]; +} + +- (NSDictionary *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateValuesForHeader:(MCOMessageHeader *)header +{ + if (![[self delegate] respondsToSelector:@selector(MCOMessageView:templateValuesForHeader:)]) { + return nil; + } + return [[self delegate] MCOMessageView:self templateValuesForHeader:header]; +} + +- (NSDictionary *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateValuesForPart:(MCOAbstractPart *)part +{ + if (![[self delegate] respondsToSelector:@selector(MCOMessageView:templateValuesForPartWithUniqueID:)]) { + return nil; + } + return [[self delegate] MCOMessageView:self templateValuesForPartWithUniqueID:[part uniqueID]]; +} + +- (NSString *) MCOAbstractMessage_templateForMainHeader:(MCOAbstractMessage *)msg +{ + if (![[self delegate] respondsToSelector:@selector(MCOMessageView_templateForMainHeader:)]) { + return nil; + } + return [[self delegate] MCOMessageView_templateForMainHeader:self]; +} + +- (NSString *) MCOAbstractMessage_templateForImage:(MCOAbstractMessage *)msg +{ + NSString * templateString; + if ([[self delegate] respondsToSelector:@selector(MCOMessageView_templateForImage:)]) { + templateString = [[self delegate] MCOMessageView_templateForImage:self]; + } + else { + templateString = @""; + } + templateString = [NSString stringWithFormat:@"
%@
", templateString]; + return templateString; +} + +- (NSString *) MCOAbstractMessage_templateForAttachment:(MCOAbstractMessage *)msg +{ + if (![[self delegate] respondsToSelector:@selector(MCOMessageView_templateForAttachment:)]) { + return NULL; + } + NSString * templateString = [[self delegate] MCOMessageView_templateForAttachment:self]; + templateString = [NSString stringWithFormat:@"
%@
", templateString]; + return templateString; +} + +- (NSString *) MCOAbstractMessage_templateForMessage:(MCOAbstractMessage *)msg +{ + if (![[self delegate] respondsToSelector:@selector(MCOMessageView_templateForMessage:)]) { + return NULL; + } + return [[self delegate] MCOMessageView_templateForMessage:self]; +} + +- (NSString *) MCOAbstractMessage_templateForEmbeddedMessage:(MCOAbstractMessage *)msg +{ + if (![[self delegate] respondsToSelector:@selector(MCOMessageView_templateForEmbeddedMessage:)]) { + return NULL; + } + return [[self delegate] MCOMessageView_templateForEmbeddedMessage:self]; +} + +- (NSString *) MCOAbstractMessage_templateForEmbeddedMessageHeader:(MCOAbstractMessage *)msg +{ + if (![[self delegate] respondsToSelector:@selector(MCOMessageView_templateForEmbeddedMessageHeader:)]) { + return NULL; + } + return [[self delegate] MCOMessageView_templateForEmbeddedMessageHeader:self]; +} + +- (NSString *) MCOAbstractMessage_templateForAttachmentSeparator:(MCOAbstractMessage *)msg +{ + if (![[self delegate] respondsToSelector:@selector(MCOMessageView_templateForAttachmentSeparator:)]) { + return NULL; + } + return [[self delegate] MCOMessageView_templateForAttachmentSeparator:self]; +} + +- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg filterHTMLForPart:(NSString *)html +{ + if (![[self delegate] respondsToSelector:@selector(MCOMessageView:filteredHTMLForPart:)]) { + return html; + } + return [[self delegate] MCOMessageView:self filteredHTMLForPart:html]; +} + +- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg filterHTMLForMessage:(NSString *)html +{ + if (![[self delegate] respondsToSelector:@selector(MCOMessageView:filteredHTMLForMessage:)]) { + return html; + } + return [[self delegate] MCOMessageView:self filteredHTMLForMessage:html]; +} + +- (NSData *) MCOAbstractMessage:(MCOAbstractMessage *)msg dataForIMAPPart:(MCOIMAPPart *)part folder:(NSString *)folder +{ + return [self _dataForIMAPPart:part folder:folder]; +} + +- (void) MCOAbstractMessage:(MCOAbstractMessage *)msg prefetchAttachmentIMAPPart:(MCOIMAPPart *)part folder:(NSString *)folder +{ + if (!_prefetchIMAPAttachmentsEnabled) + return; + + NSString * partUniqueID = [part uniqueID]; + [[self delegate] MCOMessageView:self fetchDataForPartWithUniqueID:partUniqueID downloadedFinished:^(NSError * error) { + // do nothing + }]; +} + +- (void) MCOAbstractMessage:(MCOAbstractMessage *)msg prefetchImageIMAPPart:(MCOIMAPPart *)part folder:(NSString *)folder +{ + if (!_prefetchIMAPImagesEnabled) + return; + + NSString * partUniqueID = [part uniqueID]; + [[self delegate] MCOMessageView:self fetchDataForPartWithUniqueID:partUniqueID downloadedFinished:^(NSError * error) { + // do nothing + }]; +} + +@end diff --git a/example/ios/iOS UI Test/iOS UI Test/MCTMsgViewController.h b/example/ios/iOS UI Test/iOS UI Test/MCTMsgViewController.h new file mode 100755 index 00000000..2de70a55 --- /dev/null +++ b/example/ios/iOS UI Test/iOS UI Test/MCTMsgViewController.h @@ -0,0 +1,31 @@ +// +// MCTMsgViewController.h +// testUI +// +// Created by DINH Viêt Hoà on 1/20/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#include + +@class MCOMessageView; +@class MCOIMAPAsyncSession; +@class MCOMAPMessage; + +@interface MCTMsgViewController : UIViewController { + IBOutlet MCOMessageView * _messageView; + NSMutableDictionary * _storage; + NSMutableSet * _pending; + NSMutableArray * _ops; + MCOIMAPSession * _session; + MCOIMAPMessage * _message; + NSMutableDictionary * _callbacks; + NSString * _folder; +} + +@property (nonatomic, copy) NSString * folder; + +@property (nonatomic, strong) MCOIMAPSession * session; +@property (nonatomic, strong) MCOIMAPMessage * message; + +@end diff --git a/example/ios/iOS UI Test/iOS UI Test/MCTMsgViewController.m b/example/ios/iOS UI Test/iOS UI Test/MCTMsgViewController.m new file mode 100755 index 00000000..6e3e8d52 --- /dev/null +++ b/example/ios/iOS UI Test/iOS UI Test/MCTMsgViewController.m @@ -0,0 +1,271 @@ +// +// MCTMsgViewController.m +// testUI +// +// Created by DINH Viêt Hoà on 1/20/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import "MCTMsgViewController.h" + +#import "MCOMessageView.h" + +@interface MCTMsgViewController () + +@end + +@implementation MCTMsgViewController + +@synthesize folder = _folder; +@synthesize session = _session; + +- (void) awakeFromNib +{ + _storage = [[NSMutableDictionary alloc] init]; + _ops = [[NSMutableArray alloc] init]; + _pending = [[NSMutableSet alloc] init]; + _callbacks = [[NSMutableDictionary alloc] init]; +} + +- (id)init { + self = [super init]; + + if(self) { + [self awakeFromNib]; + } + + return self; +} + +- (void)viewDidLoad { + _messageView = [[MCOMessageView alloc] initWithFrame:self.view.bounds]; + _messageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.view addSubview:_messageView]; + + if (![[NSUserDefaults standardUserDefaults] boolForKey:@"FetchFullMessageEnabled"]) { + [_messageView setDelegate:self]; + [_messageView setFolder:_folder]; + [_messageView setMessage:_message]; + } + else { + [_messageView setMessage:NULL]; + MCOIMAPFetchContentOperation * op = [_session fetchMessageByUIDOperationWithFolder:_folder uid:[_message uid]]; + [_ops addObject:op]; + [op start:^(NSError * error, NSData * data) { + if ([error code] != MCOErrorNone) { + return; + } + + NSAssert(data != nil, @"data != nil"); + + MCOMessageParser * msg = [MCOMessageParser messageParserWithData:data]; + [_messageView setDelegate:self]; + [_messageView setFolder:_folder]; + [_messageView setMessage:msg]; + }]; + } +} + +- (void) setMessage:(MCOIMAPMessage *)message +{ + NSLog(@"set message : %@", message); + for(MCOOperation * op in _ops) { + [op cancel]; + } + [_ops removeAllObjects]; + + [_callbacks removeAllObjects]; + [_pending removeAllObjects]; + [_storage removeAllObjects]; + _message = message; +} + +- (MCOIMAPMessage *) message +{ + return _message; +} + +- (MCOIMAPFetchContentOperation *) _fetchIMAPPartWithUniqueID:(NSString *)partUniqueID folder:(NSString *)folder +{ + NSLog(@"%@ is missing, fetching", partUniqueID); + + if ([_pending containsObject:partUniqueID]) { + return NULL; + } + + MCOIMAPPart * part = (MCOIMAPPart *) [_message partForUniqueID:partUniqueID]; + NSAssert(part != nil, @"part != nil"); + + [_pending addObject:partUniqueID]; + + MCOIMAPFetchContentOperation * op = [_session fetchMessageAttachmentByUIDOperationWithFolder:folder uid:[_message uid] partID:[part partID] encoding:[part encoding]]; + [_ops addObject:op]; + [op start:^(NSError * error, NSData * data) { + if ([error code] != MCOErrorNone) { + [self _callbackForPartUniqueID:partUniqueID error:error]; + return; + } + + NSAssert(data != NULL, @"data != nil"); + [_ops removeObject:op]; + [_storage setObject:data forKey:partUniqueID]; + [_pending removeObject:partUniqueID]; + NSLog(@"downloaded %@", partUniqueID); + + [self _callbackForPartUniqueID:partUniqueID error:nil]; + }]; + + return op; +} + +typedef void (^DownloadCallback)(NSError * error); + +- (void) _callbackForPartUniqueID:(NSString *)partUniqueID error:(NSError *)error +{ + NSArray * blocks; + blocks = [_callbacks objectForKey:partUniqueID]; + NSLog(@"%@", blocks); + for(DownloadCallback block in blocks) { + block(error); + } + NSLog(@"done: %@", blocks); +} + +- (NSString *) MCOMessageView_templateForAttachment:(MCOMessageView *)view +{ + return @"
\ +{{#HASSIZE}}\ +
- {{FILENAME}}, {{SIZE}}
\ +{{/HASSIZE}}\ +{{#NOSIZE}}\ +
- {{FILENAME}}
\ +{{/NOSIZE}}"; +} + +- (NSString *) MCOMessageView_templateForMessage:(MCOMessageView *)view +{ + return @"
{{HEADER}}
{{BODY}}
"; +} + +- (BOOL) MCOMessageView:(MCOMessageView *)view canPreviewPart:(MCOAbstractPart *)part +{ + // tiff, tif, pdf + NSString * mimeType = [[part mimeType] lowercaseString]; + if ([mimeType isEqualToString:@"image/tiff"]) { + return YES; + } + else if ([mimeType isEqualToString:@"image/tif"]) { + return YES; + } + else if ([mimeType isEqualToString:@"application/pdf"]) { + return YES; + } + + NSString * ext = nil; + if ([part filename] != nil) { + if ([[part filename] pathExtension] != nil) { + ext = [[[part filename] pathExtension] lowercaseString]; + } + } + if (ext != nil) { + if ([ext isEqualToString:@"tiff"]) { + return YES; + } + else if ([ext isEqualToString:@"tif"]) { + return YES; + } + else if ([ext isEqualToString:@"pdf"]) { + return YES; + } + } + + return NO; +} + +- (NSString *) MCOMessageView:(MCOMessageView *)view filteredHTML:(NSString *)html +{ + return html; +} + +- (NSData *) MCOMessageView:(MCOMessageView *)view dataForPartWithUniqueID:(NSString *)partUniqueID +{ + NSData * data = [_storage objectForKey:partUniqueID]; + return data; +} + +- (void) MCOMessageView:(MCOMessageView *)view fetchDataForPartWithUniqueID:(NSString *)partUniqueID + downloadedFinished:(void (^)(NSError * error))downloadFinished +{ + MCOIMAPFetchContentOperation * op = [self _fetchIMAPPartWithUniqueID:partUniqueID folder:_folder]; + [op setProgress:^(unsigned int current, unsigned int maximum) { + NSLog(@"progress content: %u/%u", current, maximum); + }]; + [_ops addObject:op]; + if (downloadFinished != NULL) { + NSMutableArray * blocks; + blocks = [_callbacks objectForKey:partUniqueID]; + if (blocks == nil) { + blocks = [NSMutableArray array]; + [_callbacks setObject:blocks forKey:partUniqueID]; + } + [blocks addObject:[downloadFinished copy]]; + } +} + +- (NSData *) MCOMessageView:(MCOMessageView *)view previewForData:(NSData *)data isHTMLInlineImage:(BOOL)isHTMLInlineImage +{ + if (isHTMLInlineImage) { + return data; + } + else { + return [self _convertToJPEGData:data]; + } +} + +#define IMAGE_PREVIEW_HEIGHT 300 +#define IMAGE_PREVIEW_WIDTH 500 + +- (NSData *) _convertToJPEGData:(NSData *)data +{ +// CGImageRef imageSource; +// CGImageRef thumbnail; +// NSMutableDictionary * info; +// int width; +// int height; +// float quality; +// +// width = IMAGE_PREVIEW_WIDTH; +// height = IMAGE_PREVIEW_HEIGHT; +// quality = 1.0; +// +// imageSource = CGImageSourceCreateWithData((__bridge CFDataRef) data, NULL); +// if (imageSource == NULL) +// return nil; +// +// info = [[NSMutableDictionary alloc] init]; +// [info setObject:(id) kCFBooleanTrue forKey:(id) kCGImageSourceCreateThumbnailWithTransform]; +// [info setObject:(id) kCFBooleanTrue forKey:(id) kCGImageSourceCreateThumbnailFromImageAlways]; +// [info setObject:(id) [NSNumber numberWithFloat:(float) IMAGE_PREVIEW_WIDTH] forKey:(id) kCGImageSourceThumbnailMaxPixelSize]; +// thumbnail = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, (CFDictionaryRef) info); +// [info release]; +// +// CGImageDestinationRef destination; +// NSMutableData * destData = [NSMutableData data]; +// +// destination = CGImageDestinationCreateWithData((CFMutableDataRef) destData, +// (CFStringRef) @"public.jpeg", +// 1, NULL); +// +// CGImageDestinationAddImage(destination, thumbnail, NULL); +// CGImageDestinationFinalize(destination); +// +// CFRelease(destination); +// +// CFRelease(thumbnail); +// CFRelease(imageSource); +// +// return destData; + return nil; +} + +@end 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 c244f611..0e4c848b 100644 --- a/example/ios/iOS UI Test/iOS UI Test/MasterViewController.m +++ b/example/ios/iOS UI Test/iOS UI Test/MasterViewController.m @@ -7,9 +7,9 @@ // #import "MasterViewController.h" -#import "DetailViewController.h" #import #import "FXKeychain.h" +#import "MCTMsgViewController.h" @interface MasterViewController () @property (nonatomic, strong) NSArray *messages; @@ -123,12 +123,12 @@ } } -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - if ([[segue identifier] isEqualToString:@"showDetail"]) { - NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; - NSDate *object = self.messages[indexPath.row]; - [[segue destinationViewController] setDetailItem:object]; - } +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + MCOIMAPMessage *msg = self.messages[indexPath.row]; + MCTMsgViewController *vc = [[MCTMsgViewController alloc] init]; + vc.message = msg; + vc.session = self.imapSession; + [self.navigationController pushViewController:vc animated:YES]; } @end diff --git a/example/ios/iOS UI Test/iOS UI Test/en.lproj/MainStoryboard.storyboard b/example/ios/iOS UI Test/iOS UI Test/en.lproj/MainStoryboard.storyboard index 70f1848a..63190886 100644 --- a/example/ios/iOS UI Test/iOS UI Test/en.lproj/MainStoryboard.storyboard +++ b/example/ios/iOS UI Test/iOS UI Test/en.lproj/MainStoryboard.storyboard @@ -1,5 +1,5 @@ - + @@ -46,9 +46,6 @@ - - - @@ -69,38 +66,15 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + -- cgit v1.2.3