This commit is contained in:
watrabi
2025-09-18 17:55:52 -04:00
commit 977f1ff4b8
15030 changed files with 17324420 additions and 0 deletions
@@ -0,0 +1,14 @@
//
// RBHybridModuleDialogs.h
// RobloxMobile
//
// Created by Ariel Lichtin on 2/5/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "RBHybridModule.h"
@interface RBHybridModuleAnalytics : RBHybridModule
@end
@@ -0,0 +1,43 @@
//
// RBHybridModuleDialogs.m
// RobloxMobile
//
// Created by Ariel Lichtin on 2/5/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import "RBHybridModuleAnalytics.h"
#import "RBHybridCommand.h"
#import "NSDictionary+Parsing.h"
#import "Flurry.h"
#define MODULE_ID @"Analytics"
@implementation RBHybridModuleAnalytics
-(instancetype) init
{
self = [super initWithModuleID:MODULE_ID];
if(self)
{
[self registerFunction:@"trackEvent" withSelector:@selector(trackEvent:)];
}
return self;
}
/**
* Present a single button dialog
*
* @param {string} eventName - Event name
* @param {Object} params - Dictionary with the event parameters. Only the first level will be saved. (i.e. no nested objects).
*
*/
-(void)trackEvent:(RBHybridCommand*)command
{
NSString* event = [command.params stringForKey:@"eventName" withDefault:@"Roblox"];
NSDictionary* params = [command.params dictionaryForKey:@"params" withDefault:@{}];
[Flurry logEvent:event withParameters:params];
}
@end
@@ -0,0 +1,14 @@
//
// RBHybridModuleDialogs.h
// RobloxMobile
//
// Created by Ariel Lichtin on 2/5/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "RBHybridModule.h"
@interface RBHybridModuleDialogs : RBHybridModule
@end
@@ -0,0 +1,109 @@
//
// RBHybridModuleDialogs.m
// RobloxMobile
//
// Created by Ariel Lichtin on 2/5/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import "RBHybridModuleDialogs.h"
#import "RBHybridCommand.h"
#import "NSDictionary+Parsing.h"
#import "UIAlertView+Blocks.h"
#define MODULE_ID @"Dialogs"
@implementation RBHybridModuleDialogs
-(instancetype) init
{
self = [super initWithModuleID:MODULE_ID];
if(self)
{
[self registerFunction:@"alert" withSelector:@selector(alert:)];
[self registerFunction:@"confirm" withSelector:@selector(confirm:)];
[self registerFunction:@"prompt" withSelector:@selector(prompt:)];
}
return self;
}
/**
* Present a single button dialog
*
* @param {string} text - Content text
* @param {Function} callback - Callback
* @param {string} title - Window title
* @param {string} buttonName - Button name
* @instance
*/
-(void)alert:(RBHybridCommand*)command
{
NSString* text = [command.params stringForKey:@"text"];
NSString* title = [command.params stringForKey:@"title" withDefault:@"Roblox"];
NSString* buttonName = [command.params stringForKey:@"buttonName" withDefault:NSLocalizedString(@"OkWord", nil)];
UIAlertView* alert = [[UIAlertView alloc]
initWithTitle:title
message:text
delegate:nil
cancelButtonTitle:buttonName
otherButtonTitles:nil];
[alert showWithCompletion:^(UIAlertView *alertView, NSInteger buttonIndex)
{
[command executeCallback:YES];
}];
}
/**
* Present a dialog with multiple options
*
* @param {string} text - Content text
* @param {Function} callback - Callback
* @param {string} title - Window title
* @param {string[]} buttonName - Button labels
* @instance
*/
-(void)confirm:(RBHybridCommand*)command
{
NSString* text = [command.params stringForKey:@"text"];
NSString* title = [command.params stringForKey:@"title" withDefault:@"Roblox"];
NSArray* buttons = [command.params arrayForKey:@"buttonName"];
// Validate button
NSString* firstButton;
if(buttons.count > 0 && [buttons[0] isKindOfClass:[NSString class]])
{
firstButton = buttons[0];
buttons = [buttons subarrayWithRange:NSMakeRange(1, buttons.count - 1)];
}
else
{
firstButton = NSLocalizedString(@"OkWord", nil);
}
UIAlertView* alert = [[UIAlertView alloc]
initWithTitle:title
message:text
delegate:nil
cancelButtonTitle:firstButton
otherButtonTitles:nil];
for(NSString* buttonName in buttons)
{
[alert addButtonWithTitle:buttonName];
}
[alert showWithCompletion:^(UIAlertView *alertView, NSInteger buttonIndex)
{
[command executeCallback:YES];
}];
}
-(void)prompt:(RBHybridCommand*)command
{
// [command executeCallback:@[]];
}
@end
@@ -0,0 +1,13 @@
//
// RBHybridModuleSocial.h
// RobloxMobile
//
// Created by Ariel Lichtin on 2/5/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import "RBHybridModule.h"
@interface RBHybridModuleGame : RBHybridModule
@end
@@ -0,0 +1,64 @@
//
// RBHybridModuleGame.mm
// RobloxMobile
//
// Created by Ariel Lichtin on 2/5/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import "RBHybridModuleGame.h"
#import "RBGameViewController.h"
#import "NSDictionary+Parsing.h"
#define MODULE_ID @"Game"
@implementation RBHybridModuleGame
{
RBHybridCommand* _command;
}
-(instancetype) init
{
self = [super initWithModuleID:MODULE_ID];
if(self)
{
[self registerFunction:@"startWithPlaceID" withSelector:@selector(startGameWithPlaceID:)];
}
return self;
}
/**
* Start a game session
*
* @param {string} placeID - ID of the place to start
* @param {Function} callback
* @instance
*/
-(void)startGameWithPlaceID:(RBHybridCommand*)command
{
_command = command;
NSString* placeID = [command.params stringForKey:@"placeID" withDefault:nil];
if(placeID != nil)
{
RBGameViewController* gameController = [[RBGameViewController alloc] initWithLaunchParams:[RBXGameLaunchParams InitParamsForJoinPlace:placeID.integerValue]];
gameController.completionHandler = ^
{
dispatch_async(dispatch_get_main_queue(), ^
{
if(_command)
{
[_command executeCallback:YES];
}
});
};
[command.originWebView.controller presentViewController:gameController animated:NO completion:nil];
}
else
{
[command executeCallback:NO];
}
}
@end
@@ -0,0 +1,13 @@
//
// RBHybridModuleSocial.h
// RobloxMobile
//
// Created by Ariel Lichtin on 2/5/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import "RBHybridModule.h"
@interface RBHybridModuleSocial : RBHybridModule
@end
@@ -0,0 +1,139 @@
//
// RBHybridModuleSocial.m
// RobloxMobile
//
// Created by Ariel Lichtin on 2/5/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import "RBHybridModuleSocial.h"
#import "RBHybridCommand.h"
#import "RBHybridWebView.h"
#import "NSDictionary+Parsing.h"
#import "UIViewController+Helpers.h"
#import "RBHybridModuleSocial_FBActivity.h"
#import "RBHybridModuleSocial_TwitterActivity.h"
#import "RBHybridModuleSocial_GooglePlusActivity.h"
#import <Social/Social.h>
#define MODULE_ID @"Social"
@implementation RBHybridModuleSocial
-(instancetype) init
{
self = [super initWithModuleID:MODULE_ID];
if(self)
{
[self registerFunction:@"presentShareDialog" withSelector:@selector(presentShareDialog:)];
}
return self;
}
/**
* Present a share dialog
* @param {string} text - Text to share
* @param {string} link - Link to embed
* @param {string} [imageURL=null] - link
* @param {Function} [callback] - Callback
* @instance
*/
-(void)presentShareDialog:(RBHybridCommand*)command
{
NSMutableArray* items = [NSMutableArray array];
// Collect arguments
NSString* text = [command.params stringForKey:@"text" withDefault:@""];
[items addObject:text];
NSString* link = [command.params stringForKey:@"link"];
NSURL* linkURL = nil;
if(link != nil)
{
linkURL = [NSURL URLWithString:link];
[items addObject:linkURL];
}
NSString* imageURLStr = [command.params stringForKey:@"imageURL" withDefault:nil];
NSURL* imageURL = nil;
UIImage* image = nil;
if(imageURL != nil)
{
imageURL = [NSURL URLWithString:imageURLStr];
NSData* imgData = [NSData dataWithContentsOfURL:imageURL];
image = [UIImage imageWithData:imgData];
[items addObject:image];
}
// Do the action
dispatch_async(dispatch_get_main_queue(), ^
{
RBHybridModuleSocial_FBActivity* facebookActivity = [[RBHybridModuleSocial_FBActivity alloc] init];
facebookActivity.parentController = command.originWebView.controller;
facebookActivity.text = text;
facebookActivity.link = linkURL;
facebookActivity.imageURL = imageURL;
facebookActivity.image = image;
RBHybridModuleSocial_TwitterActivity* twitterActivity = [[RBHybridModuleSocial_TwitterActivity alloc] init];
twitterActivity.parentController = command.originWebView.controller;
twitterActivity.text = text;
twitterActivity.link = linkURL;
twitterActivity.imageURL = imageURL;
twitterActivity.image = image;
// For Apple submission problems, I am disbaling GP until they fix the library.
RBHybridModuleSocial_GooglePlusActivity* googlePlusActivity = [[RBHybridModuleSocial_GooglePlusActivity alloc] init];
googlePlusActivity.text = text;
googlePlusActivity.link = linkURL;
googlePlusActivity.imageURL = imageURL;
googlePlusActivity.image = image;
NSArray* activities = @[facebookActivity, twitterActivity, googlePlusActivity];
UIViewController* parentController = command.originWebView.controller;
UIActivityViewController* activityController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:activities];
activityController.excludedActivityTypes = @[
UIActivityTypePostToFacebook,
UIActivityTypePostToTwitter,
UIActivityTypePostToWeibo,
UIActivityTypePostToFlickr,
UIActivityTypePostToVimeo
];
if( [activityController respondsToSelector:@selector(popoverPresentationController:)] )
{
activityController.popoverPresentationController.sourceView = parentController.view;
activityController.popoverPresentationController.permittedArrowDirections = 0;
activityController.popoverPresentationController.sourceRect = CGRectInset(parentController.view.bounds, 200, 200);
}
// Setup callbacks
// setCompletionWithItemsHandler is avaialble only in iOS8
if( [activityController respondsToSelector:@selector(setCompletionWithItemsHandler:)] )
{
activityController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError)
{
[self onActionCompletedForCommand:command withStatus:completed];
};
}
else
{
activityController.completionHandler = ^(NSString *activityType, BOOL completed)
{
[self onActionCompletedForCommand:command withStatus:completed];
};
}
[parentController presentViewController:activityController animated:YES completion:nil];
});
}
-(void)onActionCompletedForCommand:(RBHybridCommand*)command withStatus:(BOOL)completed
{
[command executeCallback:completed];
}
@end
@@ -0,0 +1,19 @@
//
// RBHybridModuleSocial_FBActivity.h
// RobloxMobile
//
// Created by Ariel Lichtin on 2/19/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RBHybridModuleSocial_FBActivity : UIActivity
@property(weak, nonatomic) UIViewController* parentController;
@property(strong, nonatomic) NSString* text;
@property(strong, nonatomic) NSURL* link;
@property(strong, nonatomic) NSURL* imageURL;
@property(strong, nonatomic) UIImage* image;
@end
@@ -0,0 +1,106 @@
//
// RBHybridModuleSocial_FBActivity.m
// RobloxMobile
//
// Created by Ariel Lichtin on 2/19/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import "RBHybridModuleSocial_FBActivity.h"
#import <FacebookSDK/FacebookSDK.h>
#import <Social/Social.h>
@implementation RBHybridModuleSocial_FBActivity
{
FBLinkShareParams* _shareParams;
BOOL _shareWithFBApp;
}
+ (UIActivityCategory)activityCategory
{
return UIActivityCategoryShare;
}
- (NSString *)activityType
{
return @"wtf.watrbx.activity.facebook";
}
- (NSString *)activityTitle
{
return @"Facebook";
}
- (UIImage *)activityImage
{
UIImage* image = [UIImage imageNamed:@"Social-FB-Icon"];
return image;
}
// For some reason on iOS7 without this function the icon is completely gray
- (UIImage *)_activityImage
{
UIImage* image = [UIImage imageNamed:@"Social-FB-Icon"];
return image;
}
- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems
{
return YES;
}
- (void)prepareWithActivityItems:(NSArray *)activityItems
{
_shareParams = [[FBLinkShareParams alloc] init];
_shareParams.name = _text;
_shareParams.link = _link;
_shareParams.picture = _imageURL;
_shareWithFBApp = ![FBDialogs canPresentOSIntegratedShareDialog] && [FBDialogs canPresentShareDialogWithParams:_shareParams];
}
- (UIViewController *)activityViewController
{
if(!_shareWithFBApp)
{
SLComposeViewController *composeViewController = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[composeViewController setInitialText:_text];
if(_link)
{
[composeViewController addURL:_link];
}
if(_image)
{
[composeViewController addImage:_image];
}
[composeViewController setCompletionHandler:^(SLComposeViewControllerResult result)
{
[self activityDidFinish:(result == SLComposeViewControllerResultDone)];
}];
return composeViewController;
}
return nil;
}
- (void)performActivity
{
if(_shareWithFBApp)
{
// FBDialogs call to open Share dialog within the Facebook app
[FBDialogs
presentShareDialogWithParams:_shareParams
clientState:nil
handler:^(FBAppCall *call, NSDictionary *results, NSError *error)
{
BOOL success = !error && !(results[@"completionGesture"] && [results[@"completionGesture"] isEqualToString:@"cancel"]);
[self activityDidFinish:success];
}];
}
}
@end
@@ -0,0 +1,18 @@
//
// RBHybridModuleSocial_GooglePlusActivity.h
// RobloxMobile
//
// Created by Ariel Lichtin on 2/19/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RBHybridModuleSocial_GooglePlusActivity : UIActivity
@property(strong, nonatomic) NSString* text;
@property(strong, nonatomic) NSURL* link;
@property(strong, nonatomic) NSURL* imageURL;
@property(strong, nonatomic) UIImage* image;
@end
@@ -0,0 +1,124 @@
//
// RBHybridModuleSocial_GooglePlusActivity.m
// RobloxMobile
//
// Created by Ariel Lichtin on 2/19/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import "RBHybridModuleSocial_GooglePlusActivity.h"
#import <GooglePlus/GooglePlus.h>
#import <GoogleOpenSource/GoogleOpenSource.h>
//
// As defined in https://console.developers.google.com/project/roblox-mobile
//
static NSString * const kClientId = @"757902889875-mdpibqck9096ap3gt0minfg85d27kavm.apps.googleusercontent.com";
@interface RBHybridModuleSocial_GooglePlusActivity() <GPPSignInDelegate, GPPShareDelegate>
@end
@implementation RBHybridModuleSocial_GooglePlusActivity
+ (UIActivityCategory)activityCategory
{
return UIActivityCategoryShare;
}
- (NSString *)activityType
{
return @"wtf.watrbx.activity.googleplus";
}
- (NSString *)activityTitle
{
return @"Google+";
}
- (UIImage *)activityImage
{
UIImage* image = [UIImage imageNamed:@"Social-Google-Icon"];
return image;
}
// For some reason on iOS7 without this function the icon is completely gray
- (UIImage *)_activityImage
{
UIImage* image = [UIImage imageNamed:@"Social-Google-Icon"];
return image;
}
- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems
{
return YES;
}
- (void)prepareWithActivityItems:(NSArray *)activityItems
{
[GPPSignIn sharedInstance].clientID = kClientId;
}
- (UIViewController *)activityViewController
{
return nil;
}
- (void)performActivity
{
[self signIn];
}
- (void)signIn
{
GPPSignIn *signIn = [GPPSignIn sharedInstance];
signIn.shouldFetchGooglePlusUser = YES;
//signIn.shouldFetchGoogleUserEmail = YES;
signIn.delegate = self;
signIn.clientID = kClientId;
signIn.scopes = @[ kGTLAuthScopePlusLogin ]; // "https://www.googleapis.com/auth/plus.login" scope
//signIn.scopes = @[ @"profile" ]; // "profile" scope
BOOL userLoggedIn = [signIn trySilentAuthentication];
if(!userLoggedIn)
{
[signIn authenticate];
}
}
// The authorization has finished and is successful if |error| is |nil|.
- (void)finishedWithAuth:(GTMOAuth2Authentication *)auth error:(NSError *)error
{
if(error == nil)
{
[self shareLink];
}
else
{
[self activityDidFinish:NO];
}
}
- (void)shareLink
{
[GPPShare sharedInstance].delegate = self;
id<GPPNativeShareBuilder> shareBuilder = [[GPPShare sharedInstance] nativeShareDialog];
[shareBuilder setPrefillText:_text];
[shareBuilder setURLToShare:_link];
[shareBuilder attachImage:_image];
[shareBuilder setContentDeepLinkID:[_link query]];
[shareBuilder open];
}
- (void)finishedSharing:(BOOL)shared
{
[self activityDidFinish:shared];
}
@end
@@ -0,0 +1,19 @@
//
// RBHybridModuleSocial_TwitterActivity.h
// RobloxMobile
//
// Created by Ariel Lichtin on 2/19/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RBHybridModuleSocial_TwitterActivity : UIActivity
@property(weak, nonatomic) UIViewController* parentController;
@property(strong, nonatomic) NSString* text;
@property(strong, nonatomic) NSURL* link;
@property(strong, nonatomic) NSURL* imageURL;
@property(strong, nonatomic) UIImage* image;
@end
@@ -0,0 +1,74 @@
//
// RBHybridModuleSocial_TwitterActivity.m
// RobloxMobile
//
// Created by Ariel Lichtin on 2/19/15.
// Copyright (c) 2015 ROBLOX. All rights reserved.
//
#import "RBHybridModuleSocial_TwitterActivity.h"
#import <Social/Social.h>
@implementation RBHybridModuleSocial_TwitterActivity
+ (UIActivityCategory)activityCategory
{
return UIActivityCategoryShare;
}
- (NSString *)activityType
{
return @"wtf.watrbx.activity.twitter";
}
- (NSString *)activityTitle
{
return @"Twitter";
}
- (UIImage *)activityImage
{
UIImage* image = [UIImage imageNamed:@"Social-Twitter-Icon"];
return image;
}
// For some reason on iOS7 without this function the icon is completely gray
- (UIImage *)_activityImage
{
UIImage* image = [UIImage imageNamed:@"Social-Twitter-Icon"];
return image;
}
- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems
{
return YES;
}
- (void)prepareWithActivityItems:(NSArray *)activityItems
{
}
- (UIViewController *)activityViewController
{
NSString *message = _text;
NSString *urlString = [_link absoluteString];
// Boldly invoke the target app, because the phone will display a nice message asking to configure the app
SLComposeViewController *composeViewController = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[composeViewController setInitialText:message];
[composeViewController addURL:[NSURL URLWithString:urlString]];
[composeViewController setCompletionHandler:^(SLComposeViewControllerResult result)
{
[self activityDidFinish:(result == SLComposeViewControllerResultDone)];
}];
return composeViewController;
}
- (void)performActivity
{
}
@end