aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/ui
diff options
context:
space:
mode:
authorGravatar Hoa V. DINH <dinh.viet.hoa@gmail.com>2013-07-25 11:07:10 -0700
committerGravatar Hoa V. DINH <dinh.viet.hoa@gmail.com>2013-07-25 11:07:10 -0700
commitd90d68c7ba923fea3d805a9ebf872f84b6947e57 (patch)
tree371c404b10cc3efa791176e83c2c9a66154f32d7 /src/ui
parent9c4ab2641e8cd3ffbb208770ca38a429d198539c (diff)
Moved iOS MCOMessageView to src/ui/ios
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/common/MCOCIDURLProtocol.h (renamed from src/ui/mac/MCOCIDURLProtocol.h)0
-rw-r--r--src/ui/common/MCOCIDURLProtocol.mm (renamed from src/ui/mac/MCOCIDURLProtocol.mm)6
-rwxr-xr-xsrc/ui/ios/MCOMessageView.h50
-rwxr-xr-xsrc/ui/ios/MCOMessageView.mm416
4 files changed, 466 insertions, 6 deletions
diff --git a/src/ui/mac/MCOCIDURLProtocol.h b/src/ui/common/MCOCIDURLProtocol.h
index ac4b0f2b..ac4b0f2b 100644
--- a/src/ui/mac/MCOCIDURLProtocol.h
+++ b/src/ui/common/MCOCIDURLProtocol.h
diff --git a/src/ui/mac/MCOCIDURLProtocol.mm b/src/ui/common/MCOCIDURLProtocol.mm
index 83730c9d..ad529f54 100644
--- a/src/ui/mac/MCOCIDURLProtocol.mm
+++ b/src/ui/common/MCOCIDURLProtocol.mm
@@ -8,8 +8,6 @@
#import "MCOCIDURLProtocol.h"
-#import "MCOMessageView.h"
-
#define MCOCIDURLProtocolDownloadedNotification @"MCOCIDURLProtocolDownloadedNotification"
@implementation MCOCIDURLProtocol
@@ -92,7 +90,6 @@
{
NSDictionary * userInfo = [notification userInfo];
- //NSLog(@"downloaded?");
NSString * notifPartID = [userInfo objectForKey:@"PartUniqueID"];
MCOAbstractMessage * notifMessage = [userInfo objectForKey:@"Message"];
if (notifMessage != [self _message]) {
@@ -102,8 +99,6 @@
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];
@@ -142,7 +137,6 @@
}
[[NSNotificationCenter defaultCenter] postNotificationName:MCOCIDURLProtocolDownloadedNotification object:nil userInfo:userInfo];
[userInfo release];
- //NSLog(@"downloaded %p %@", self, partUniqueID);
}
@end
diff --git a/src/ui/ios/MCOMessageView.h b/src/ui/ios/MCOMessageView.h
new file mode 100755
index 00000000..3c4ce50d
--- /dev/null
+++ b/src/ui/ios/MCOMessageView.h
@@ -0,0 +1,50 @@
+//
+// MCOMessageView.h
+// testUI
+//
+// Created by DINH Viêt Hoà on 1/19/13.
+// Copyright (c) 2013 MailCore. All rights reserved.
+//
+
+#include <MailCore/MailCore.h>
+
+#import <UIKit/UIKit.h>
+
+@protocol MCOMessageViewDelegate;
+
+@interface MCOMessageView : UIView <UIWebViewDelegate>
+
+@property (nonatomic, copy) NSString * folder;
+@property (nonatomic, strong) MCOAbstractMessage * message;
+
+@property (nonatomic, assign) id <MCOMessageViewDelegate> delegate;
+
+@property (nonatomic, assign) BOOL prefetchIMAPImagesEnabled;
+@property (nonatomic, assign) BOOL prefetchIMAPAttachmentsEnabled;
+
+@end
+
+@protocol MCOMessageViewDelegate <NSObject>
+
+@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/src/ui/ios/MCOMessageView.mm b/src/ui/ios/MCOMessageView.mm
new file mode 100755
index 00000000..e3786bb5
--- /dev/null
+++ b/src/ui/ios/MCOMessageView.mm
@@ -0,0 +1,416 @@
+//
+// 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"
+
+static NSString * mainJavascript = @"\
+var imageElements = function() {\
+ var imageNodes = document.getElementsByTagName('img');\
+ return [].slice.call(imageNodes);\
+};\
+\
+var findCIDImageURL = function() {\
+ var images = imageElements();\
+ \
+ var imgLinks = [];\
+ for (var i = 0; i < images.length; i++) {\
+ var url = images[i].getAttribute('src');\
+ if (url.indexOf('cid:') == 0 || url.indexOf('x-mailcore-image:') == 0)\
+ imgLinks.push(url);\
+ }\
+ return JSON.stringify(imgLinks);\
+};\
+\
+var replaceImageSrc = function(info) {\
+ var images = imageElements();\
+ \
+ for (var i = 0; i < images.length; i++) {\
+ var url = images[i].getAttribute('src');\
+ if (url.indexOf(info.URLKey) == 0) {\
+ images[i].setAttribute('src', info.LocalPathKey);\
+ break;\
+ }\
+ }\
+};\
+";
+
+static NSString * mainStyle = @"\
+body {\
+ font-family: Helvetica;\
+ font-size: 14px;\
+ word-wrap: break-word;\
+ -webkit-text-size-adjust:none;\
+ -webkit-nbsp-mode: space;\
+}\
+\
+pre {\
+ white-space: pre-wrap;\
+}\
+";
+
+@interface MCOMessageView () <MCOHTMLRendererIMAPDelegate>
+
+@end
+
+@implementation MCOMessageView {
+ UIWebView * _webView;
+ NSString * _folder;
+ MCOAbstractMessage * _message;
+ id <MCOMessageViewDelegate> _delegate;
+ BOOL _prefetchIMAPImagesEnabled;
+ BOOL _prefetchIMAPAttachmentsEnabled;
+}
+
+@synthesize folder = _folder;
+@synthesize delegate = _delegate;
+@synthesize prefetchIMAPImagesEnabled = _prefetchIMAPImagesEnabled;
+@synthesize prefetchIMAPAttachmentsEnabled = _prefetchIMAPAttachmentsEnabled;
+
+- (id)initWithFrame:(CGRect)frame
+{
+ self = [super initWithFrame:frame];
+
+ _webView = [[UIWebView alloc] initWithFrame:[self bounds]];
+ [_webView setAutoresizingMask:(UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth)];
+ [_webView setDelegate:self];
+ [self addSubview:_webView];
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [_message release];
+ [_folder release];
+ [_webView release];
+
+ [super dealloc];
+}
+
+- (void) setMessage:(MCOAbstractMessage *)message
+{
+ [_message release];
+ _message = [message retain];
+
+ [_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);
+ }
+ }
+ if (content == nil) {
+ [_webView loadHTMLString:@"" baseURL:nil];
+ return;
+ }
+
+ NSMutableString * html = [NSMutableString string];
+ [html appendFormat:@"<html><head><script>%@</script><style>%@</style></head>"
+ @"<body>%@</body><iframe src='x-mailcore-msgviewloaded:' style='width: 0px; height: 0px; border: none;'>"
+ @"</iframe></html>", mainJavascript, mainStyle, content];
+ [_webView loadHTMLString:html baseURL:nil];
+}
+
+- (void) _loadImages
+{
+ NSString * result = [_webView stringByEvaluatingJavaScriptFromString:@"findCIDImageURL()"];
+ NSLog(@"----------");
+ NSLog(@"%@", result);
+ NSData * data = [result dataUsingEncoding:NSUTF8StringEncoding];
+ NSError *error = nil;
+ NSArray * imagesURLStrings = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
+
+ for(NSString * urlString in imagesURLStrings) {
+ MCOAbstractPart * part = nil;
+ NSURL * url;
+
+ url = [NSURL URLWithString:urlString];
+ if ([MCOCIDURLProtocol isCID:url]) {
+ part = [self _partForCIDURL:url];
+ }
+ else if ([MCOCIDURLProtocol isXMailcoreImage:url]) {
+ NSString * specifier = [url resourceSpecifier];
+ NSString * partUniqueID = specifier;
+ part = [self _partForUniqueID:partUniqueID];
+ }
+
+ if (part == nil)
+ continue;
+
+ NSString * partUniqueID = [part uniqueID];
+ NSData * data = [[self delegate] MCOMessageView:self dataForPartWithUniqueID:partUniqueID];
+
+ void (^replaceImages)(NSError *error) = ^(NSError *error) {
+ NSData * downloadedData = [[self delegate] MCOMessageView:self dataForPartWithUniqueID:partUniqueID];
+ NSData * previewData = [[self delegate] MCOMessageView:self previewForData:downloadedData isHTMLInlineImage:[MCOCIDURLProtocol isCID:url]];
+ NSString * filename = [NSString stringWithFormat:@"%lu", (unsigned long)urlString.hash];
+ NSURL * cacheURL = [self _cacheJPEGImageData:previewData withFilename:filename];
+
+ NSDictionary * args = @{ @"URLKey": urlString, @"LocalPathKey": cacheURL.absoluteString };
+ NSString * jsonString = [self _jsonEscapedStringFromDictionary:args];
+
+ NSString * replaceScript = [NSString stringWithFormat:@"replaceImageSrc(%@)", jsonString];
+ [_webView stringByEvaluatingJavaScriptFromString:replaceScript];
+ };
+
+ if (data == nil) {
+ [[self delegate] MCOMessageView:self fetchDataForPartWithUniqueID:partUniqueID downloadedFinished:^(NSError * error) {
+ replaceImages(error);
+ }];
+ } else {
+ replaceImages(nil);
+ }
+ }
+}
+
+- (NSString *) _jsonEscapedStringFromDictionary:(NSDictionary *)dictionary
+{
+ NSData * json = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil];
+ NSString * jsonString = [[NSString alloc] initWithData:json encoding:NSUTF8StringEncoding];
+ return jsonString;
+}
+
+- (NSURL *) _cacheJPEGImageData:(NSData *)imageData withFilename:(NSString *)filename
+{
+ NSString * path = [[NSTemporaryDirectory() stringByAppendingPathComponent:filename] stringByAppendingPathExtension:@"jpg"];
+ [imageData writeToFile:path atomically:YES];
+ return [NSURL fileURLWithPath:path];
+}
+
+- (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];
+
+ 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
+{
+ if ([[[request URL] scheme] isEqualToString:@"x-mailcore-msgviewloaded"]) {
+ [self _loadImages];
+ }
+
+ 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 NO;
+ }
+ 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:(MCOAbstractMessage *)msg templateForMainHeader:(MCOMessageHeader *)header
+{
+ if (![[self delegate] respondsToSelector:@selector(MCOMessageView_templateForMainHeader:)]) {
+ return nil;
+ }
+ return [[self delegate] MCOMessageView_templateForMainHeader:self];
+}
+
+- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateForImage:(MCOAbstractPart *)header
+{
+ NSString * templateString;
+ if ([[self delegate] respondsToSelector:@selector(MCOMessageView_templateForImage:)]) {
+ templateString = [[self delegate] MCOMessageView_templateForImage:self];
+ }
+ else {
+ templateString = @"<img src=\"{{URL}}\"/>";
+ }
+ templateString = [NSString stringWithFormat:@"<div id=\"{{CONTENTID}}\">%@</div>", templateString];
+ return templateString;
+}
+
+- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateForAttachment:(MCOAbstractPart *)part
+{
+ if (![[self delegate] respondsToSelector:@selector(MCOMessageView_templateForAttachment:)]) {
+ return NULL;
+ }
+ NSString * templateString = [[self delegate] MCOMessageView_templateForAttachment:self];
+ templateString = [NSString stringWithFormat:@"<div id=\"{{CONTENTID}}\">%@</div>", 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:(MCOAbstractMessage *)msg templateForEmbeddedMessage:(MCOAbstractMessagePart *)part
+{
+ if (![[self delegate] respondsToSelector:@selector(MCOMessageView_templateForEmbeddedMessage:)]) {
+ return NULL;
+ }
+ return [[self delegate] MCOMessageView_templateForEmbeddedMessage:self];
+}
+
+- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateForEmbeddedMessageHeader:(MCOMessageHeader *)header
+{
+ 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