mattermost-mobile/ios/MattermostShare/ShareViewController.m
2018-06-27 18:17:44 -04:00

285 lines
11 KiB
Objective-C

#import "ShareViewController.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import "PerformRequests.h"
#import "SessionManager.h"
NSExtensionContext* extensionContext;
@implementation ShareViewController
+ (BOOL)requiresMainQueueSetup
{
return YES;
}
@synthesize bridge = _bridge;
- (UIView*) shareView {
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"share.ios" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"MattermostShare"
initialProperties:nil
launchOptions:nil];
rootView.backgroundColor = nil;
return rootView;
}
RCT_EXPORT_MODULE(MattermostShare);
- (void)viewDidLoad {
[super viewDidLoad];
extensionContext = self.extensionContext;
UIView *rootView = [self shareView];
if (rootView.backgroundColor == nil) {
rootView.backgroundColor = [[UIColor alloc] initWithRed:1 green:1 blue:1 alpha:0.1];
}
self.view = rootView;
}
RCT_REMAP_METHOD(getOrientation,
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
if([UIScreen mainScreen].bounds.size.width < [UIScreen mainScreen].bounds.size.height) {
resolve(@"PORTRAIT");
} else {
resolve(@"LANDSCAPE");
}
}
RCT_EXPORT_METHOD(close:(NSDictionary *)data appGroupId:(NSString *)appGroupId) {
if (data != nil) {
NSString *requestId = [data objectForKey:@"requestId"];
NSString *useBackgroundUpload = [data objectForKey:@"useBackgroundUpload"];
NSString *certificateName = [data objectForKey:@"certificate"];
BOOL tryToUploadInTheBackgound = useBackgroundUpload ? [useBackgroundUpload boolValue] : NO;
if (tryToUploadInTheBackgound) {
NSString *requestWithGroup = [NSString stringWithFormat:@"%@|%@", requestId, appGroupId];
[SessionManager sharedSession].closeExtension = ^{
[extensionContext completeRequestReturningItems:nil
completionHandler:nil];
NSLog(@"Extension closed");
};
[SessionManager sharedSession].sendShareEvent = ^(NSString* eventName) {
NSLog(@"Send Share Extension Event to JS");
[_bridge enqueueJSCall:@"RCTDeviceEventEmitter"
method:@"emit"
args:@[eventName]
completion:nil];
};
[[SessionManager sharedSession] setRequestWithGroup:requestWithGroup certificateName:certificateName];
[[SessionManager sharedSession] setDataForRequest:data forRequestWithGroup:requestWithGroup];
[[SessionManager sharedSession] createPostForRequest:requestWithGroup];
} else {
NSDictionary *post = [data objectForKey:@"post"];
NSArray *files = [data objectForKey:@"files"];
PerformRequests *request = [[PerformRequests alloc] initWithPost:post withFiles:files forRequestId:requestId inAppGroupId:appGroupId inContext:extensionContext];
[request createPost];
}
} else {
[extensionContext completeRequestReturningItems:nil
completionHandler:nil];
NSLog(@"Extension closed");
}
}
RCT_REMAP_METHOD(data,
appGroupId: (NSString *)appGroupId
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
[self extractDataFromContext: extensionContext withAppGroup: appGroupId andCallback:^(NSArray* items ,NSError* err) {
if (err) {
reject(@"data", @"Failed to extract attachment content", err);
return;
}
resolve(items);
}];
}
typedef void (^ProviderCallback)(NSString *content, NSString *contentType, BOOL owner, NSError *err);
- (void)extractDataFromContext:(NSExtensionContext *)context withAppGroup:(NSString *) appGroupId andCallback:(void(^)(NSArray *items ,NSError *err))callback {
@try {
NSExtensionItem *item = [context.inputItems firstObject];
NSArray *attachments = item.attachments;
NSMutableArray *items = [[NSMutableArray alloc] init];
__block int attachmentIdx = 0;
__block ProviderCallback providerCb = nil;
__block __weak ProviderCallback weakProviderCb = nil;
providerCb = ^ void (NSString *content, NSString *contentType, BOOL owner, NSError *err) {
if (err) {
callback(nil, err);
return;
}
if (content != nil) {
[items addObject:@{
@"type": contentType,
@"value": content,
@"owner": [NSNumber numberWithBool:owner],
}];
}
++attachmentIdx;
if (attachmentIdx == [attachments count]) {
callback(items, nil);
} else {
[self extractDataFromProvider:attachments[attachmentIdx] withAppGroup:appGroupId andCallback: weakProviderCb];
}
};
weakProviderCb = providerCb;
[self extractDataFromProvider:attachments[0] withAppGroup:appGroupId andCallback: providerCb];
}
@catch (NSException *exc) {
NSError *error = [NSError errorWithDomain:@"fiftythree.paste" code:1 userInfo:@{
@"reason": [exc description]
}];
callback(nil, error);
}
}
- (void)extractDataFromProvider:(NSItemProvider *)provider withAppGroup:(NSString *) appGroupId andCallback:(void(^)(NSString* content, NSString* contentType, BOOL owner, NSError *err))callback {
if([provider hasItemConformingToTypeIdentifier:@"public.movie"]) {
[provider loadItemForTypeIdentifier:@"public.movie" options:nil completionHandler:^(id<NSSecureCoding, NSObject> item, NSError *error) {
@try {
if ([item isKindOfClass: NSURL.class]) {
NSURL *url = (NSURL *)item;
return callback([url absoluteString], @"public.movie", NO, nil);
}
return callback(nil, nil, NO, nil);
}
@catch(NSException *exc) {
NSError *error = [NSError errorWithDomain:@"fiftythree.paste" code:2 userInfo:@{
@"reason": [exc description]
}];
callback(nil, nil, NO, error);
}
}];
return;
}
if([provider hasItemConformingToTypeIdentifier:@"public.image"]) {
[provider loadItemForTypeIdentifier:@"public.image" options:nil completionHandler:^(id<NSSecureCoding, NSObject> item, NSError *error) {
if (error) {
callback(nil, nil, NO, error);
return;
}
@try {
if ([item isKindOfClass: NSURL.class]) {
NSURL *url = (NSURL *)item;
return callback([url absoluteString], @"public.image", NO, nil);
} else if ([item isKindOfClass: UIImage.class]) {
UIImage *image = (UIImage *)item;
NSString *fileName = [NSString stringWithFormat:@"%@.jpg", [[NSUUID UUID] UUIDString]];
NSURL *tempContainerURL = [[SessionManager sharedSession] tempContainerURL:appGroupId];
if (tempContainerURL == nil){
return callback(nil, nil, NO, nil);
}
NSURL *tempFileURL = [tempContainerURL URLByAppendingPathComponent: fileName];
BOOL created = [UIImageJPEGRepresentation(image, 1) writeToFile:[tempFileURL path] atomically:YES];
if (created) {
return callback([tempFileURL absoluteString], @"public.image", YES, nil);
} else {
return callback(nil, nil, NO, nil);
}
} else if ([item isKindOfClass: NSData.class]) {
NSString *fileName = [NSString stringWithFormat:@"%@.jpg", [[NSUUID UUID] UUIDString]];
NSData *data = (NSData *)item;
UIImage *image = [UIImage imageWithData:data];
NSURL *tempContainerURL = [[SessionManager sharedSession] tempContainerURL:appGroupId];
if (tempContainerURL == nil){
return callback(nil, nil, NO, nil);
}
NSURL *tempFileURL = [tempContainerURL URLByAppendingPathComponent: fileName];
BOOL created = [UIImageJPEGRepresentation(image, 0.95) writeToFile:[tempFileURL path] atomically:YES];
if (created) {
return callback([tempFileURL absoluteString], @"public.image", YES, nil);
} else {
return callback(nil, nil, NO, nil);
}
} else {
// Do nothing, some type we don't support.
return callback(nil, nil, NO, nil);
}
}
@catch(NSException *exc) {
NSError *error = [NSError errorWithDomain:@"fiftythree.paste" code:2 userInfo:@{
@"reason": [exc description]
}];
callback(nil, nil, NO, error);
}
}];
return;
}
if([provider hasItemConformingToTypeIdentifier:@"public.file-url"]) {
[provider loadItemForTypeIdentifier:@"public.file-url" options:nil completionHandler:^(id<NSSecureCoding, NSObject> item, NSError *error) {
if (error) {
callback(nil, nil, NO, error);
return;
}
if ([item isKindOfClass:NSURL.class]) {
return callback([(NSURL *)item absoluteString], @"public.file-url", NO, nil);
} else if ([item isKindOfClass:NSString.class]) {
return callback((NSString *)item, @"public.file-url", NO, nil);
}
callback(nil, nil, NO, nil);
}];
return;
}
if([provider hasItemConformingToTypeIdentifier:@"public.url"]) {
[provider loadItemForTypeIdentifier:@"public.url" options:nil completionHandler:^(id<NSSecureCoding, NSObject> item, NSError *error) {
if (error) {
callback(nil, nil, NO, error);
return;
}
if ([item isKindOfClass:NSURL.class]) {
return callback([(NSURL *)item absoluteString], @"public.url", NO, nil);
} else if ([item isKindOfClass:NSString.class]) {
return callback((NSString *)item, @"public.url", NO, nil);
}
}];
return;
}
if([provider hasItemConformingToTypeIdentifier:@"public.plain-text"]) {
[provider loadItemForTypeIdentifier:@"public.plain-text" options:nil completionHandler:^(id<NSSecureCoding, NSObject> item, NSError *error) {
if (error) {
callback(nil, nil, NO, error);
return;
}
if ([item isKindOfClass:NSString.class]) {
return callback((NSString *)item, @"public.plain-text", NO, nil);
} else if ([item isKindOfClass:NSAttributedString.class]) {
NSAttributedString *str = (NSAttributedString *)item;
return callback([str string], @"public.plain-text", NO, nil);
} else if ([item isKindOfClass:NSData.class]) {
NSString *str = [[NSString alloc] initWithData:(NSData *)item encoding:NSUTF8StringEncoding];
if (str) {
return callback(str, @"public.plain-text", NO, nil);
} else {
return callback(nil, nil, NO, nil);
}
} else {
return callback(nil, nil, NO, nil);
}
}];
return;
}
callback(nil, nil, NO, nil);
}
@end