diff options
Diffstat (limited to 'StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios')
4 files changed, 144 insertions, 51 deletions
diff --git a/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/NSString+URLEncoding.h b/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/NSString+URLEncoding.h new file mode 100644 index 00000000..d7da331d --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/NSString+URLEncoding.h @@ -0,0 +1,5 @@ +#import <Foundation/Foundation.h> + +@interface NSString (URLEncoding) +@property (readonly) NSString *URLEncodedString; +@end diff --git a/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/NSString+URLEncoding.m b/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/NSString+URLEncoding.m new file mode 100644 index 00000000..b737626c --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/NSString+URLEncoding.m @@ -0,0 +1,30 @@ +#import "NSString+URLEncoding.h" + +@implementation NSString (URLEncoding) +- (NSString*)URLEncodedString +{ + NSString* result = (NSString *)CFBridgingRelease( + CFURLCreateStringByAddingPercentEscapes( + kCFAllocatorDefault, + (CFStringRef)self, + CFSTR("#%"), // don't escape these + NULL, // allow escaping these + kCFStringEncodingUTF8 + ) + ); + + // we may have a URL with more than one '#' now - which iOS doesn't allow, so escape all but the first one + NSArray *parts = [result componentsSeparatedByString:@"#"]; + NSString *finalResult = parts[0]; + for (int i=1; i<parts.count; i++) { + NSString *part = [parts objectAtIndex:i]; + if (i==1) { + finalResult = [finalResult stringByAppendingString:@"#"]; + } else { + finalResult = [finalResult stringByAppendingString:@"%23"]; + } + finalResult = [finalResult stringByAppendingString:part]; + } + return finalResult; +} +@end
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/SocialSharing.h b/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/SocialSharing.h index b51474d3..0c731450 100755..100644 --- a/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/SocialSharing.h +++ b/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/SocialSharing.h @@ -4,13 +4,14 @@ @interface SocialSharing : CDVPlugin <UIPopoverControllerDelegate, MFMailComposeViewControllerDelegate, UIDocumentInteractionControllerDelegate> @property (nonatomic, strong) MFMailComposeViewController *globalMailComposer; -@property (retain) UIDocumentInteractionController * documentInteractionController; +@property (nonatomic, strong) UIDocumentInteractionController * documentInteractionController; @property (retain) NSString * tempStoredFile; @property (retain) CDVInvokedUrlCommand * command; - (void)available:(CDVInvokedUrlCommand*)command; - (void)setIPadPopupCoordinates:(CDVInvokedUrlCommand*)command; - (void)share:(CDVInvokedUrlCommand*)command; +- (void)shareWithOptions:(CDVInvokedUrlCommand*)command; - (void)canShareVia:(CDVInvokedUrlCommand*)command; - (void)canShareViaEmail:(CDVInvokedUrlCommand*)command; - (void)shareVia:(CDVInvokedUrlCommand*)command; diff --git a/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/SocialSharing.m b/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/SocialSharing.m index cd0913a4..014925bd 100755..100644 --- a/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/SocialSharing.m +++ b/StoneIsland/plugins/cordova-plugin-x-socialsharing/src/ios/SocialSharing.m @@ -1,4 +1,5 @@ #import "SocialSharing.h" +#import "NSString+URLEncoding.h" #import <Cordova/CDV.h> #import <Social/Social.h> #import <Foundation/NSException.h> @@ -6,6 +7,11 @@ #import <MessageUI/MFMailComposeViewController.h> #import <MobileCoreServices/MobileCoreServices.h> +static NSString *const kShareOptionMessage = @"message"; +static NSString *const kShareOptionSubject = @"subject"; +static NSString *const kShareOptionFiles = @"files"; +static NSString *const kShareOptionUrl = @"url"; + @implementation SocialSharing { UIPopoverController *_popover; NSString *_popupCoordinates; @@ -51,23 +57,46 @@ } - (void)share:(CDVInvokedUrlCommand*)command { + [self shareInternal:command + withOptions:@{ + kShareOptionMessage: [command.arguments objectAtIndex:0], + kShareOptionSubject: [command.arguments objectAtIndex:1], + kShareOptionFiles: [command.arguments objectAtIndex:2], + kShareOptionUrl: [command.arguments objectAtIndex:3] + } + isBooleanResponse:YES +]; +} + +- (void)shareWithOptions:(CDVInvokedUrlCommand*)command { + NSDictionary* options = [command.arguments objectAtIndex:0]; + [self shareInternal:command + withOptions:options + isBooleanResponse:NO + ]; +} + +- (void)shareInternal:(CDVInvokedUrlCommand*)command withOptions:(NSDictionary*)options isBooleanResponse:(BOOL)boolResponse { [self.commandDelegate runInBackground:^{ //avoid main thread block especially if sharing big files from url if (!NSClassFromString(@"UIActivityViewController")) { CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"not available"]; [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; return; } - - NSString *message = [command.arguments objectAtIndex:0]; - NSString *subject = [command.arguments objectAtIndex:1]; - NSArray *filenames = [command.arguments objectAtIndex:2]; - NSString *urlString = [command.arguments objectAtIndex:3]; - + + NSString *message = options[kShareOptionMessage]; + NSString *subject = options[kShareOptionSubject]; + NSArray *filenames = options[kShareOptionFiles]; + NSString *urlString = options[kShareOptionUrl]; + NSMutableArray *activityItems = [[NSMutableArray alloc] init]; + + if (message != (id)[NSNull null] && message != nil) { [activityItems addObject:message]; - - NSMutableArray *files = [[NSMutableArray alloc] init]; - if (filenames != (id)[NSNull null] && filenames.count > 0) { + } + + if (filenames != (id)[NSNull null] && filenames != nil && filenames.count > 0) { + NSMutableArray *files = [[NSMutableArray alloc] init]; for (NSString* filename in filenames) { NSObject *file = [self getImage:filename]; if (file == nil) { @@ -79,31 +108,47 @@ } [activityItems addObjectsFromArray:files]; } - - if (urlString != (id)[NSNull null]) { - [activityItems addObject:[NSURL URLWithString:urlString]]; + + if (urlString != (id)[NSNull null] && urlString != nil) { + [activityItems addObject:[NSURL URLWithString:[urlString URLEncodedString]]]; } - + UIActivity *activity = [[UIActivity alloc] init]; NSArray *applicationActivities = [[NSArray alloc] initWithObjects:activity, nil]; UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:applicationActivities]; - if (subject != (id)[NSNull null]) { + if (subject != (id)[NSNull null] && subject != nil) { [activityVC setValue:subject forKey:@"subject"]; } - - // TODO deprecated in iOS 8.0, change this some day - [activityVC setCompletionHandler:^(NSString *activityType, BOOL completed) { - [self cleanupStoredFiles]; - NSLog(@"SocialSharing app selected: %@", activityType); - CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:completed]; - [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; - }]; - + + if ([activityVC respondsToSelector:(@selector(setCompletionWithItemsHandler:))]) { + [activityVC setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray * returnedItems, NSError * activityError) { + [self cleanupStoredFiles]; + if (boolResponse) { + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:completed] + callbackId:command.callbackId]; + } else { + NSDictionary * result = @{@"completed":@(completed), @"app":activityType == nil ? @"" : activityType}; + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result] + callbackId:command.callbackId]; + } + }]; + } else { + // let's suppress this warning otherwise folks will start opening issues while it's not relevant +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + [activityVC setCompletionHandler:^(NSString *activityType, BOOL completed) { + [self cleanupStoredFiles]; + NSDictionary * result = @{@"completed":@(completed), @"app":activityType}; + CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:result]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +#pragma GCC diagnostic warning "-Wdeprecated-declarations" + } + NSArray * socialSharingExcludeActivities = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"SocialSharingExcludeActivities"]; if (socialSharingExcludeActivities!=nil && [socialSharingExcludeActivities count] > 0) { activityVC.excludedActivityTypes = socialSharingExcludeActivities; } - + dispatch_async(dispatch_get_main_queue(), ^(void){ // iPad on iOS >= 8 needs a different approach if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) { @@ -230,27 +275,27 @@ - (void)shareViaInternal:(CDVInvokedUrlCommand*)command type:(NSString *) type { - + NSString *message = [command.arguments objectAtIndex:0]; // subject is not supported by the SLComposeViewController NSArray *filenames = [command.arguments objectAtIndex:2]; NSString *urlString = [command.arguments objectAtIndex:3]; - + // boldly invoke the target app, because the phone will display a nice message asking to configure the app SLComposeViewController *composeViewController = [SLComposeViewController composeViewControllerForServiceType:type]; if (message != (id)[NSNull null]) { [composeViewController setInitialText:message]; } - + for (NSString* filename in filenames) { UIImage* image = [self getImage:filename]; if (image != nil) { [composeViewController addImage:image]; } } - + if (urlString != (id)[NSNull null]) { - [composeViewController addURL:[NSURL URLWithString:urlString]]; + [composeViewController addURL:[NSURL URLWithString:[urlString URLEncodedString]]]; } [composeViewController setCompletionHandler:^(SLComposeViewControllerResult result) { @@ -272,7 +317,7 @@ - (void)shareViaEmail:(CDVInvokedUrlCommand*)command { if ([self isEmailAvailable]) { - + if (TARGET_IPHONE_SIMULATOR && IsAtLeastiOSVersion(@"8.0")) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"SocialSharing plugin" message:@"Sharing via email is not supported on the iOS 8 simulator." @@ -282,38 +327,40 @@ [alert show]; return; } - + + [self cycleTheGlobalMailComposer]; + self.globalMailComposer.mailComposeDelegate = self; - + if ([command.arguments objectAtIndex:0] != (id)[NSNull null]) { NSString *message = [command.arguments objectAtIndex:0]; BOOL isHTML = [message rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch].location != NSNotFound; [self.globalMailComposer setMessageBody:message isHTML:isHTML]; } - + if ([command.arguments objectAtIndex:1] != (id)[NSNull null]) { [self.globalMailComposer setSubject: [command.arguments objectAtIndex:1]]; } - + if ([command.arguments objectAtIndex:2] != (id)[NSNull null]) { [self.globalMailComposer setToRecipients:[command.arguments objectAtIndex:2]]; } - + if ([command.arguments objectAtIndex:3] != (id)[NSNull null]) { [self.globalMailComposer setCcRecipients:[command.arguments objectAtIndex:3]]; } - + if ([command.arguments objectAtIndex:4] != (id)[NSNull null]) { [self.globalMailComposer setBccRecipients:[command.arguments objectAtIndex:4]]; } - + if ([command.arguments objectAtIndex:5] != (id)[NSNull null]) { NSArray* attachments = [command.arguments objectAtIndex:5]; NSFileManager* fileManager = [NSFileManager defaultManager]; for (NSString* path in attachments) { NSURL *file = [self getFile:path]; NSData* data = [fileManager contentsAtPath:file.path]; - + NSString* fileName; NSString* mimeType; NSString* basename = [self getBasenameFromAttachmentPath:path]; @@ -331,14 +378,14 @@ [self.globalMailComposer addAttachmentData:data mimeType:mimeType fileName:fileName]; } } - + // remember the command, because we need it in the didFinishWithResult method _command = command; [self.commandDelegate runInBackground:^{ [[self getTopMostViewController] presentViewController:self.globalMailComposer animated:YES completion:nil]; }]; - + } else { CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"not available"]; [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; @@ -358,7 +405,7 @@ NSString* pathWithoutPrefix = [path stringByReplacingOccurrencesOfString:@"base64:" withString:@""]; return [pathWithoutPrefix substringToIndex:[pathWithoutPrefix rangeOfString:@"//"].location]; } - return path; + return [path componentsSeparatedByString: @"?"][0]; } - (NSString*) getMimeTypeFromFileExtension:(NSString*)extension { @@ -406,7 +453,7 @@ NSString *message = [options objectForKey:@"message"]; NSString *subject = [options objectForKey:@"subject"]; NSString *image = [options objectForKey:@"image"]; - + MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init]; picker.messageComposeDelegate = (id) self; if (message != (id)[NSNull null]) { @@ -424,7 +471,7 @@ } } } - + if (phonenumbers != (id)[NSNull null]) { [picker setRecipients:[phonenumbers componentsSeparatedByString:@","]]; } @@ -469,7 +516,7 @@ } - (void)shareViaInstagram:(CDVInvokedUrlCommand*)command { - + // on iOS9 canShareVia('instagram'..) will only work if instagram:// is whitelisted. // If it's not, this method will ask permission to the user on iOS9 for opening the app, // which is of course better than Instagram sharing not working at all because you forgot to whitelist it. @@ -492,7 +539,7 @@ image = [self getImage:filename]; break; } - + // NSData *imageObj = [NSData dataFromBase64String:objectAtIndex0]; NSString *tmpDir = NSTemporaryDirectory(); NSString *path = [tmpDir stringByAppendingPathComponent:@"instagram.igo"]; @@ -513,11 +560,15 @@ // remember the command for the delegate method _command = command; - [_documentInteractionController presentOpenInMenuFromRect:CGRectZero inView:self.webView animated:YES]; + + // test for #513 + dispatch_async(dispatch_get_main_queue(), ^(void){ + [_documentInteractionController presentOpenInMenuFromRect:CGRectZero inView:self.webView animated:YES]; + }); } - (void)shareViaWhatsApp:(CDVInvokedUrlCommand*)command { - + // on iOS9 canShareVia('whatsapp'..) will only work if whatsapp:// is whitelisted. // If it's not, this method will ask permission to the user on iOS9 for opening the app, // which is of course better than WhatsApp sharing not working at all because you forgot to whitelist it. @@ -534,6 +585,7 @@ // subject is not supported by the SLComposeViewController NSArray *filenames = [command.arguments objectAtIndex:2]; NSString *urlString = [command.arguments objectAtIndex:3]; + NSString *abid = [command.arguments objectAtIndex:4]; // only use the first image (for now.. maybe we can share in a loop?) UIImage* image = nil; @@ -561,14 +613,18 @@ if ([shareString isEqual: @""]) { shareString = urlString; } else { - shareString = [NSString stringWithFormat:@"%@ %@", shareString, urlString]; + shareString = [NSString stringWithFormat:@"%@ %@", shareString, [urlString URLEncodedString]]; } } NSString * encodedShareString = [shareString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; // also encode the '=' character encodedShareString = [encodedShareString stringByReplacingOccurrencesOfString:@"=" withString:@"%3D"]; encodedShareString = [encodedShareString stringByReplacingOccurrencesOfString:@"&" withString:@"%26"]; - NSString * encodedShareStringForWhatsApp = [NSString stringWithFormat:@"whatsapp://send?text=%@", encodedShareString]; + NSString * abidString = @""; + if (abid != (id)[NSNull null]) { + abidString = [NSString stringWithFormat:@"abid=%@&", abid]; + } + NSString * encodedShareStringForWhatsApp = [NSString stringWithFormat:@"whatsapp://send?%@text=%@", abidString, encodedShareString]; NSURL *whatsappURL = [NSURL URLWithString:encodedShareStringForWhatsApp]; [[UIApplication sharedApplication] openURL: whatsappURL]; @@ -641,7 +697,8 @@ if ([fileName hasPrefix:@"http"]) { NSURL *url = [NSURL URLWithString:fileName]; NSData *fileData = [NSData dataWithContentsOfURL:url]; - file = [NSURL fileURLWithPath:[self storeInFile:(NSString*)[[fileName componentsSeparatedByString: @"/"] lastObject] fileData:fileData]]; + NSString *name = (NSString*)[[fileName componentsSeparatedByString: @"/"] lastObject]; + file = [NSURL fileURLWithPath:[self storeInFile:[name componentsSeparatedByString: @"?"][0] fileData:fileData]]; } else if ([fileName hasPrefix:@"www/"]) { NSString *bundlePath = [[NSBundle mainBundle] bundlePath]; NSString *fullPath = [NSString stringWithFormat:@"%@/%@", bundlePath, fileName]; |
