Skip to content

Commit

Permalink
Adds frictionless apprequest support
Browse files Browse the repository at this point in the history
Summary:
Here are the mods to the sdk:
1. adds four methods to the Facebook class, for use by applications
  * enableFrictionlessRequests
  * reloadFrictionlessRecipientCache
  * isFrictionlessEnabledForRecipient
  * isFrictionlessEnabledForRecipients
2. extends dialog method and support class to support frictionless behavior for “apprequest” dialogs
3. extends Hacbook sample to add frictionless app-request support

Notes:
* enableFrictionlessRequests method of FBFrictionless turns on frictionless apprequest behavior in the SDK
* frictionless apprequest behavior means
  a.) a cache of allowed frictionless recipients is maintained
  b.) cache checked by dialog, and dialog is invisible for frictionless recipients
  c.) send responses are checked and recipient list is updated
  d.) logout and login cause clear and refetch of cache respectively
  • Loading branch information
onebit committed Feb 25, 2012
1 parent 9acf743 commit 4e3567c
Show file tree
Hide file tree
Showing 17 changed files with 1,123 additions and 688 deletions.
5 changes: 5 additions & 0 deletions .arcconfig
@@ -0,0 +1,5 @@
{
"project_id" : "facebook-ios-sdk",
"conduit_uri" : "https://phabricator.fb.com/api/",
"copyright_holder" : "Facebook"
}
1 change: 0 additions & 1 deletion .gitignore
Expand Up @@ -21,7 +21,6 @@ test/UnitTest/UnitTest.xcodeproj/*.mode*
test/UnitTest/build/
*~
*#
.arcconfig
.DS_Store
project.xcworkspace
xcuserdata
6 changes: 6 additions & 0 deletions sample/Hackbook/Hackbook.xcodeproj/project.pbxproj
Expand Up @@ -38,6 +38,7 @@
30EA73FC13F5D590003DC0D2 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30EA73FB13F5D590003DC0D2 /* CoreLocation.framework */; };
30ED588C14358F8A00A226C3 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30ED588B14358F8A00A226C3 /* Default@2x.png */; };
30ED588F14358F9400A226C3 /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30ED588E14358F9400A226C3 /* Icon@2x.png */; };
84E7D99614D9CC13006A6299 /* FBFrictionlessRequestSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 84E7D99514D9CC13006A6299 /* FBFrictionlessRequestSettings.m */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand Down Expand Up @@ -92,6 +93,8 @@
30EA73FB13F5D590003DC0D2 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
30ED588B14358F8A00A226C3 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = "<group>"; };
30ED588E14358F9400A226C3 /* Icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon@2x.png"; sourceTree = "<group>"; };
84E7D99414D9CC13006A6299 /* FBFrictionlessRequestSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FBFrictionlessRequestSettings.h; path = ../../src/FBFrictionlessRequestSettings.h; sourceTree = "<group>"; };
84E7D99514D9CC13006A6299 /* FBFrictionlessRequestSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FBFrictionlessRequestSettings.m; path = ../../src/FBFrictionlessRequestSettings.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -197,6 +200,8 @@
30EA73D613F5D523003DC0D2 /* FBLoginDialog.m */,
30EA73D713F5D523003DC0D2 /* FBRequest.h */,
30EA73D813F5D523003DC0D2 /* FBRequest.m */,
84E7D99414D9CC13006A6299 /* FBFrictionlessRequestSettings.h */,
84E7D99514D9CC13006A6299 /* FBFrictionlessRequestSettings.m */,
30EA73D913F5D523003DC0D2 /* JSON */,
);
name = FBConnect;
Expand Down Expand Up @@ -310,6 +315,7 @@
30EA73F013F5D523003DC0D2 /* SBJsonBase.m in Sources */,
30EA73F113F5D523003DC0D2 /* SBJsonParser.m in Sources */,
30EA73F213F5D523003DC0D2 /* SBJsonWriter.m in Sources */,
84E7D99614D9CC13006A6299 /* FBFrictionlessRequestSettings.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
46 changes: 38 additions & 8 deletions sample/Hackbook/Hackbook/APICallsViewController.m
Expand Up @@ -539,6 +539,28 @@ - (void)getUserFriendTargetDialogRequest {
[self apiGraphFriends];
}

/*
* API: Enable frictionless in the SDK, retrieve friends enabled for frictionless send
*/
- (void)enableFrictionlessAppRequests {
HackbookAppDelegate *delegate =
(HackbookAppDelegate *)[[UIApplication sharedApplication] delegate];

// Enable frictionless app requests
[[delegate facebook] enableFrictionlessRequests];

UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:@"Enabled Frictionless Requests"
message:@"Request actions such as\n"
@"Send Request and Send Invite\n"
@"now support frictionless behavior."
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil,
nil];
[alertView show];
}

/*
* --------------------------------------------------------------------------
* Graph API
Expand Down Expand Up @@ -939,12 +961,13 @@ - (void)request:(FBRequest *)request didLoad:(id)result {
}
case kAPIFriendsForDialogFeed:
{
NSArray *resultData = [result objectForKey:@"data"];
NSArray *resultData = [result objectForKey: @"data"];
// Check that the user has friends
if ([resultData count] > 0) {
// Pick a random friend to post the feed to
int randomNumber = arc4random() % [resultData count];
[self apiDialogFeedFriend:[[resultData objectAtIndex:randomNumber] objectForKey:@"id"]];
[self apiDialogFeedFriend:
[[resultData objectAtIndex: randomNumber] objectForKey: @"id"]];
} else {
[self showMessage:@"You do not have any friends to post to."];
}
Expand Down Expand Up @@ -1015,17 +1038,24 @@ - (void)request:(FBRequest *)request didLoad:(id)result {
}
case kAPIFriendsForTargetDialogRequests:
{
NSArray *resultData = [result objectForKey:@"data"];
if ([resultData count] > 0) {
[self apiDialogRequestsSendTarget:[[resultData objectAtIndex:0] objectForKey:@"id"]];
NSArray *resultData = [result objectForKey: @"data"];
// got friends?
if ([resultData count] > 0) {
// pick a random one to send a request to
int randomIndex = arc4random() % [resultData count];
NSString* randomFriend =
[[resultData objectAtIndex: randomIndex] objectForKey: @"id"];
[self apiDialogRequestsSendTarget:randomFriend];
} else {
[self showMessage:@"You have no friends to select."];
[self showMessage: @"You have no friends to select."];
}
break;
}
case kAPIGraphMe:
{
NSString *nameID = [[NSString alloc] initWithFormat:@"%@ (%@)", [result objectForKey:@"name"], [result objectForKey:@"id"]];
NSString *nameID = [[NSString alloc] initWithFormat: @"%@ (%@)",
[result objectForKey:@"name"],
[result objectForKey:@"id"]];
NSMutableArray *userData = [[NSMutableArray alloc] initWithObjects:
[NSDictionary dictionaryWithObjectsAndKeys:
[result objectForKey:@"id"], @"id",
Expand Down Expand Up @@ -1162,7 +1192,7 @@ - (void)dialogCompleteWithUrl:(NSURL *)url {
// Successful requests return one or more request_ids.
// Get any request IDs, will be in the URL in the form
// request_ids[0]=1001316103543&request_ids[1]=10100303657380180
NSMutableArray *requestIDs = [[NSMutableArray alloc] init];
NSMutableArray *requestIDs = [[[NSMutableArray alloc] init] autorelease];
for (NSString *paramKey in params) {
if ([paramKey hasPrefix:@"request_ids"]) {
[requestIDs addObject:[params objectForKey:paramKey]];
Expand Down
10 changes: 9 additions & 1 deletion sample/Hackbook/Hackbook/DataSet.m
Expand Up @@ -101,13 +101,20 @@ - (id)init {
@"Send request", @"button",
@"getUserFriendTargetDialogRequest", @"method",
nil];
NSDictionary *requestMenu5 = [[NSDictionary alloc] initWithObjectsAndKeys:
@"Enable frictionless requests", @"title",
@"To enable a no-prompt request and invite experience, enable frictionless requests.", @"description",
@"Enable frictionless", @"button",
@"enableFrictionlessAppRequests", @"method",
nil];

NSArray *requestMenuItems = [[NSArray alloc] initWithObjects:
requestMenu1,
requestMenu2,
requestMenu3,
requestMenu4,
nil];
requestMenu5,
nil];

NSDictionary *requestConfigData = [[NSDictionary alloc] initWithObjectsAndKeys:
@"Requests", @"title",
Expand All @@ -122,6 +129,7 @@ - (id)init {
[requestMenu2 release];
[requestMenu3 release];
[requestMenu4 release];
[requestMenu5 release];
[requestMenuItems release];
[requestConfigData release];

Expand Down
14 changes: 7 additions & 7 deletions sample/Hackbook/Hackbook/HackbookAppDelegate.m
Expand Up @@ -49,28 +49,28 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
self.navigationController = navController;
[rootViewController release];
[navController release];

// Initialize Facebook
facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:rootViewController];

// Check and retrieve authorization information
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) {
facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
}

// Initialize API data (for views, etc.)
apiData = [[DataSet alloc] init];

// Initialize user permissions
userPermissions = [[NSMutableDictionary alloc] initWithCapacity:1];

// Override point for customization after application launch.
// Add the navigation controller's view to the window and display.
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];

// Check App ID:
// This is really a warning for the developer, this should not
// happen in a completed app
Expand Down Expand Up @@ -119,7 +119,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
[alertView release];
}
}

return YES;
}

Expand Down

0 comments on commit 4e3567c

Please sign in to comment.