Initial commit

This commit is contained in:
Ben Alpert
2015-01-29 17:10:49 -08:00
commit a15603d8f1
382 changed files with 39183 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#import <UIKit/UIKit.h>
#import "RCTExport.h"
@interface RCTAlertManager : NSObject <RCTNativeModule>
@end

View File

@@ -0,0 +1,107 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#import "RCTAlertManager.h"
#import "RCTLog.h"
@interface RCTAlertManager() <UIAlertViewDelegate>
@end
@implementation RCTAlertManager
{
NSMutableArray *_alerts;
NSMutableArray *_alertCallbacks;
NSMutableArray *_alertButtonKeys;
}
- (instancetype)init
{
if ((self = [super init])) {
_alerts = [[NSMutableArray alloc] init];
_alertCallbacks = [[NSMutableArray alloc] init];
_alertButtonKeys = [[NSMutableArray alloc] init];
}
return self;
}
/**
* @param {NSDictionary} args Dictionary of the form
*
* @{
* @"message": @"<Alert message>",
* @"buttons": @[
* @{@"<key1>": @"<title1>"},
* @{@"<key2>": @"<cancelButtonTitle>"},
* ]
* }
* The key from the `buttons` dictionary is passed back in the callback on click.
* Buttons are displayed in the order they are specified. If "cancel" is used as
* the button key, it will be differently highlighted, according to iOS UI conventions.
*/
- (void)alertWithArgs:(NSDictionary *)args callback:(RCTResponseSenderBlock)callback
{
RCT_EXPORT();
NSString *title = args[@"title"];
NSString *message = args[@"message"];
NSArray *buttons = args[@"buttons"];
if (!title && !message) {
RCTLogMustFix(@"Must specify either an alert title, or message, or both");
return;
} else if (buttons.count == 0) {
RCTLogMustFix(@"Must have at least one button.");
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
NSMutableArray *buttonKeys = [[NSMutableArray alloc] initWithCapacity:buttons.count];
NSInteger index = 0;
for (NSDictionary *button in buttons) {
if (button.count != 1) {
RCTLogMustFix(@"Button definitions should have exactly one key.");
}
NSString *buttonKey = [button.allKeys firstObject];
NSString *buttonTitle = [button[buttonKey] description];
[alertView addButtonWithTitle:buttonTitle];
if ([buttonKey isEqualToString: @"cancel"]) {
alertView.cancelButtonIndex = index;
}
[buttonKeys addObject:buttonKey];
index ++;
}
[_alerts addObject:alertView];
[_alertCallbacks addObject:callback ?: ^(id unused) {}];
[_alertButtonKeys addObject:buttonKeys];
[alertView show];
});
}
#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSUInteger index = [_alerts indexOfObject:alertView];
RCTAssert(index != NSNotFound, @"Dismissed alert was not recognised");
RCTResponseSenderBlock callback = _alertCallbacks[index];
NSArray *buttonKeys = _alertButtonKeys[index];
callback(@[buttonKeys[buttonIndex]]);
[_alerts removeObjectAtIndex:index];
[_alertCallbacks removeObjectAtIndex:index];
[_alertButtonKeys removeObjectAtIndex:index];
}
@end

View File

@@ -0,0 +1,10 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#import <Foundation/Foundation.h>
#import "RCTExport.h"
@interface RCTDataManager : NSObject <RCTNativeModule>
@end

View File

@@ -0,0 +1,73 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#import "RCTDataManager.h"
#import "RCTAssert.h"
#import "RCTLog.h"
#import "RCTUtils.h"
@implementation RCTDataManager
/**
* Executes a network request.
* The responseSender block won't be called on same thread as called.
*/
- (void)executeQuery:(NSString *)queryType
query:(id)query
queryHash:(__unused NSString *)queryHash
responseSender:(RCTResponseSenderBlock)responseSender
{
RCT_EXPORT(queryData);
if ([queryType isEqualToString:@"http"]) {
// Parse query
NSDictionary *queryDict = query;
if ([query isKindOfClass:[NSString class]]) {
// TODO: it would be more efficient just to send a dictionary
queryDict = RCTJSONParse(query, NULL);
}
// Build request
NSURL *url = [NSURL URLWithString:queryDict[@"url"]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = queryDict[@"method"] ?: @"GET";
request.allHTTPHeaderFields = queryDict[@"headers"];
if ([queryDict[@"data"] isKindOfClass:[NSString class]]) {
request.HTTPBody = [queryDict[@"data"] dataUsingEncoding:NSUTF8StringEncoding];
}
// Build data task
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *connectionError) {
// Build response
NSDictionary *responseJSON;
if (connectionError == nil) {
NSStringEncoding encoding;
if (response.textEncodingName) {
CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
} else {
encoding = NSUTF8StringEncoding;
}
NSString *returnData = [[NSString alloc] initWithData:data encoding:encoding];
responseJSON = @{@"status": @200, @"responseText": returnData};
} else {
responseJSON = @{@"status": @0, @"responseText": [connectionError localizedDescription]};
}
// Send response (won't be sent on same thread as caller)
responseSender(@[RCTJSONStringify(responseJSON, NULL)]);
}];
[task resume];
} else {
RCTLogMustFix(@"unsupported query type %@", queryType);
return;
}
}
@end

View File

@@ -0,0 +1,9 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#import <Foundation/Foundation.h>
#import "RCTExport.h"
@interface RCTExceptionsManager : NSObject <RCTNativeModule>
@end

View File

@@ -0,0 +1,23 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#import "RCTExceptionsManager.h"
#import "RCTRedBox.h"
@implementation RCTExceptionsManager
- (void)reportUnhandledExceptionWithMessage:(NSString *)message stack:(NSArray *)stack
{
RCT_EXPORT(reportUnhandledException);
[[RCTRedBox sharedInstance] showErrorMessage:message withStack:stack];
}
- (void)updateExceptionMessage:(NSString *)message stack:(NSArray *)stack
{
RCT_EXPORT(updateExceptionMessage);
[[RCTRedBox sharedInstance] updateErrorMessage:message withStack:stack];
}
@end

View File

@@ -0,0 +1,14 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#import <Foundation/Foundation.h>
#import "RCTExport.h"
@class RCTBridge;
@interface RCTTiming : NSObject <RCTNativeModule>
- (instancetype)initWithBridge:(RCTBridge *)bridge;
- (void)enqueueUpdateTimers;
@end

View File

@@ -0,0 +1,154 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#import "RCTTiming.h"
#import "RCTBridge.h"
#import "RCTLog.h"
#import "RCTModuleIDs.h"
#import "RCTSparseArray.h"
#import "RCTUtils.h"
@interface RCTTimer : NSObject
@property (nonatomic, strong, readonly) NSDate *target;
@property (nonatomic, assign, readonly, getter=isActive) BOOL active;
@property (nonatomic, assign, readonly) BOOL repeats;
@property (nonatomic, strong, readonly) NSNumber *callbackID;
@property (nonatomic, assign, readonly) NSTimeInterval interval;
@end
@implementation RCTTimer
- (instancetype)initWithCallbackID:(NSNumber *)callbackID
interval:(NSTimeInterval)interval
targetTime:(NSTimeInterval)targetTime
repeats:(BOOL)repeats
{
if (self = [super init]) {
_active = YES;
_interval = interval;
_repeats = repeats;
_callbackID = callbackID;
_target = [NSDate dateWithTimeIntervalSinceNow:targetTime];
}
return self;
}
/**
* Returns `YES` if we should invoke the JS callback.
*/
- (BOOL)updateFoundNeedsJSUpdate
{
if (_active && _target.timeIntervalSinceNow <= 0) {
// The JS Timers will do fine grained calculating of expired timeouts.
if (_repeats) {
_target = [NSDate dateWithTimeIntervalSinceNow:_interval];
} else {
_active = NO;
}
return YES;
}
return NO;
}
@end
@implementation RCTTiming
{
RCTSparseArray *_timers;
RCTBridge *_bridge;
}
- (instancetype)initWithBridge:(RCTBridge *)bridge
{
if (self = [super init]) {
_bridge = bridge;
_timers = [[RCTSparseArray alloc] init];
}
return self;
}
/**
* TODO (#5906496): Wait until operations on `javaScriptQueue` are complete to complete the
* `dealloc`.
*/
/* - (void)dealloc
{
} */
- (void)enqueueUpdateTimers
{
RCTAssertMainThread();
NSMutableArray *timersToCall = [[NSMutableArray alloc] init];
for (RCTTimer *timer in _timers.allObjects) {
if ([timer updateFoundNeedsJSUpdate]) {
[timersToCall addObject:timer.callbackID];
}
if (!timer.active) {
_timers[timer.callbackID] = nil;
}
}
// call timers that need to be called
if ([timersToCall count] > 0) {
[_bridge enqueueJSCall:RCTModuleIDJSTimers methodID:RCTJSTimersCallTimers args:@[timersToCall]];
}
}
- (void)scheduleCallbackID:(NSNumber *)callbackID interval:(NSTimeInterval)interval targetTime:(NSTimeInterval)targetTime repeats:(BOOL)repeats
{
dispatch_async(dispatch_get_main_queue(), ^{
RCTTimer *timer = [[RCTTimer alloc] initWithCallbackID:callbackID interval:interval targetTime:targetTime repeats:repeats];
_timers[callbackID] = timer;
});
}
/**
* There's a small difference between the time when we call
* setTimeout/setInterval/requestAnimation frame and the time it actually makes
* it here. This is important and needs to be taken into account when
* calculating the timer's target time. We calculate this by passing in
* Date.now() from JS and then subtracting that from the current time here.
*/
- (void)createTimer:(NSNumber *)callbackID
duration:(NSNumber *)jsDuration
jsSchedulingTime:(NSNumber *)jsSchedulingTime
repeats:(NSNumber *)repeats
{
RCT_EXPORT();
NSTimeInterval interval = jsDuration.doubleValue / 1000;
NSTimeInterval jsCreationTimeSinceUnixEpoch = jsSchedulingTime.doubleValue / 1000;
NSTimeInterval currentTimeSinceUnixEpoch = [[NSDate date] timeIntervalSince1970];
NSTimeInterval jsSchedulingOverhead = currentTimeSinceUnixEpoch - jsCreationTimeSinceUnixEpoch;
if (jsSchedulingOverhead < 0) {
RCTLogWarn(@"jsSchedulingOverhead (%ims) should be positive", (int)(jsSchedulingOverhead * 1000));
}
NSTimeInterval targetTime = interval - jsSchedulingOverhead;
if (interval < 0.018) { // Make sure short intervals run each frame
interval = 0;
}
[self scheduleCallbackID:callbackID
interval:interval
targetTime:targetTime
repeats:repeats.boolValue];
}
- (void)deleteTimer:(NSNumber *)timerID
{
RCT_EXPORT();
if (timerID) {
dispatch_async(dispatch_get_main_queue(), ^{
_timers[timerID] = nil;
});
} else {
RCTLogWarn(@"Called deleteTimer: with a nil timerID");
}
}
@end

View File

@@ -0,0 +1,40 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#import <UIKit/UIKit.h>
#import "RCTExport.h"
#import "RCTInvalidating.h"
@protocol RCTScrollableProtocol;
@protocol RCTViewNodeProtocol;
@class RCTRootView;
@class RCTJavaScriptEventDispatcher;
@class RCTShadowView;
@class RCTAnimationRegistry;
@interface RCTUIManager : NSObject <RCTInvalidating, RCTNativeModule>
- (instancetype)initWithShadowQueue:(dispatch_queue_t)shadowQueue
viewManagers:(NSDictionary *)viewManagers;
@property (nonatomic, strong) RCTJavaScriptEventDispatcher *eventDispatcher;
@property (nonatomic, strong) RCTSparseArray *shadowViewRegistry;
@property (nonatomic, strong) RCTSparseArray *viewRegistry;
@property (nonatomic, strong) RCTAnimationRegistry *animationRegistry;
@property (nonatomic, weak) id<RCTScrollableProtocol> mainScrollView;
/**
* Allows native environment code to respond to "the main scroll view" events.
* see `RCTUIManager`'s `setMainScrollViewTag`.
*/
@property (nonatomic, readwrite, weak) id<UIScrollViewDelegate> nativeMainScrollDelegate;
+ (UIView <RCTViewNodeProtocol> *)closestReactAncestor:(UIView *)view;
+ (UIView <RCTViewNodeProtocol> *)closestReactAncestorThatRespondsToTouch:(UITouch *)touch;
- (void)registerRootView:(RCTRootView *)rootView;
+ (UIView *)JSResponder;
@end

File diff suppressed because it is too large Load Diff