Skip to content

Commit

Permalink
Add callback with results of ActivityView completion handler
Browse files Browse the repository at this point in the history
  • Loading branch information
cmcewen committed Dec 22, 2015
1 parent 8f37c1b commit d949c8f
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 14 deletions.
23 changes: 21 additions & 2 deletions ActivityView.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,30 @@ var {
var NativeActivityView = NativeModules.ActivityView;

/**
* High-level docs for the ActivityView iOS API can be written here.
* ActivityView has two function calls - `show`, and `showWithCallback`
* Both require a shareObject
*
* The shareObject has the following properties:
*
* text: "Text you want to share" (string),
* url: "URL you want to share" (string),
* imageUrl: "Url of the image you want to share/action" (string),
* image: "Name of the image in the app bundle" (string),
* exclude: ["array", "of", "activities", "to", "exclude"] (array of strings)
* anchor: React.findNodeHandle(this.refs.share) (number),
*
* The callback is of the form
* function(activityType (string),
* completed (boolean),
* returnedItems (array),
* activityError (string)
* )
*
*/

var ActivityView = {
show: NativeActivityView.show
show: NativeActivityView.show,
showWithCallback: NativeActivityView.showWithCallback
};

module.exports = ActivityView;
56 changes: 44 additions & 12 deletions ActivityView.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#import "RCTLog.h"
#import "RCTBridge.h"
#import "RCTUIManager.h"
#import "RCTUtils.h"

@implementation ActivityView

Expand All @@ -16,6 +17,10 @@ - (dispatch_queue_t)methodQueue

// Map user passed array of strings to UIActivities
- (NSArray*)excludedActivitiesForKeys:(NSArray*)passedKeys {
if (!passedKeys) {
return nil;
}

NSDictionary *activities = @{
@"postToFacebook": UIActivityTypePostToFacebook,
@"postToTwitter": UIActivityTypePostToTwitter,
Expand Down Expand Up @@ -47,13 +52,11 @@ - (NSArray*)excludedActivitiesForKeys:(NSArray*)passedKeys {
return excludedActivities;
}

RCT_EXPORT_METHOD(show:(NSDictionary *)args)
{
- (UIActivityViewController *)activityViewFromDictionary:(NSDictionary *)args {
NSMutableArray *shareObject = [NSMutableArray array];
NSString *text = args[@"text"];
NSURL *url = args[@"url"];
NSString *imageUrl = args[@"imageUrl"];
NSArray *activitiesToExclude = args[@"exclude"];
NSString *image = args[@"image"];
NSData * imageData;

Expand All @@ -66,13 +69,11 @@ - (NSArray*)excludedActivitiesForKeys:(NSArray*)passedKeys {
}
}


// Return if no args were passed
if (!text && !url && !image && !imageData) {
RCTLogError(@"[ActivityView] You must specify a text, url, image and/or imageUrl.");
return;
return nil;
}


if (text) {
[shareObject addObject:text];
Expand All @@ -89,14 +90,16 @@ - (NSArray*)excludedActivitiesForKeys:(NSArray*)passedKeys {
}

UIActivityViewController *activityView = [[UIActivityViewController alloc] initWithActivityItems:shareObject applicationActivities:nil];

activityView.excludedActivityTypes = [self excludedActivitiesForKeys:args[@"exclude"]];

activityView.excludedActivityTypes = activitiesToExclude
? [self excludedActivitiesForKeys:activitiesToExclude]
: nil;
return activityView;
}

- (void) displayActivityViewController:(UIActivityViewController *)activityView withAnchor:(NSNumber *)anchorViewTag {
// Display the Activity View
UIViewController *ctrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController];

/*
* The `anchor` option takes a view to set as the anchor for the share
* popup to point to, on iPads running iOS 8. If it is not passed, it
Expand All @@ -105,7 +108,6 @@ - (NSArray*)excludedActivitiesForKeys:(NSArray*)passedKeys {
*/
if ([activityView respondsToSelector:@selector(popoverPresentationController)]) {
activityView.popoverPresentationController.sourceView = ctrl.view;
NSNumber *anchorViewTag = [RCTConvert NSNumber:args[@"anchor"]];
if (anchorViewTag) {
UIView *anchorView = [self.bridge.uiManager viewForReactTag:anchorViewTag];
activityView.popoverPresentationController.sourceRect = [anchorView convertRect:anchorView.bounds toView:ctrl.view];
Expand All @@ -118,4 +120,34 @@ - (NSArray*)excludedActivitiesForKeys:(NSArray*)passedKeys {
[ctrl presentViewController:activityView animated:YES completion:nil];
}

RCT_EXPORT_METHOD(show:(NSDictionary *)args)
{
UIActivityViewController* activityView = [self activityViewFromDictionary:args];

if (activityView) {
[self displayActivityViewController:activityView withAnchor:[RCTConvert NSNumber:args[@"anchor"]]];
} else {
return;
}
}

RCT_EXPORT_METHOD(showWithCallback:(NSDictionary *)args callback:(RCTResponseSenderBlock)callback)
{
UIActivityViewController* activityView = [self activityViewFromDictionary:args];

if (activityView) {
[activityView setCompletionWithItemsHandler:
^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
callback(@[RCTNullIfNil(activityType),
@(completed),
RCTNullIfNil(returnedItems),
RCTNullIfNil(activityError.localizedDescription)]);
}
];
[self displayActivityViewController:activityView withAnchor:[RCTConvert NSNumber:args[@"anchor"]]];
} else {
return;
}
}

@end
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,30 @@ ActivityView.show({
});
```

### showWithCallback(shareObject, callback)
Same as the above, but with an optional callback called after the ActivityView is either completed or cancelled

__Arguments__
- `shareObject` - An _Object_ containing one or more of the following keys `text`, `url`, `anchor`, `exclude`, `imageUrl` or `image`.
- `callback` - A function with 4 arguments: `activityType`, `completed`, `returnedItems`, and `activityError`

__Examples__
```js
ActivityView.show({
text: 'ActivityView for React Native',
url: 'https://github.com/naoufal/react-native-activity-view',
imageUrl: 'https://facebook.github.io/react/img/logo_og.png',
exclude: ['postToFlickr', 'airDrop'],
anchor: React.findNodeHandle(this.refs.share),
}, function(activityType, completed, returnedItems, activityError) {
if (completed) {
console.log('success!')
else {
console.log('cancelled')
}
});
```
## License
Copyright (c) 2015, [Naoufal Kadhom](http://naoufal.com/)
Expand Down

0 comments on commit d949c8f

Please sign in to comment.