mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-23 20:01:01 +08:00
[react-packager][streamline oss] Move open sourced JS source to react-native-github
This commit is contained in:
9
ReactKit/Modules/RCTAlertManager.h
Normal file
9
ReactKit/Modules/RCTAlertManager.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
|
||||
@interface RCTAlertManager : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
||||
107
ReactKit/Modules/RCTAlertManager.m
Normal file
107
ReactKit/Modules/RCTAlertManager.m
Normal 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
|
||||
10
ReactKit/Modules/RCTDataManager.h
Normal file
10
ReactKit/Modules/RCTDataManager.h
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
|
||||
@interface RCTDataManager : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
||||
|
||||
73
ReactKit/Modules/RCTDataManager.m
Normal file
73
ReactKit/Modules/RCTDataManager.m
Normal 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
|
||||
9
ReactKit/Modules/RCTExceptionsManager.h
Normal file
9
ReactKit/Modules/RCTExceptionsManager.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
|
||||
@interface RCTExceptionsManager : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
||||
23
ReactKit/Modules/RCTExceptionsManager.m
Normal file
23
ReactKit/Modules/RCTExceptionsManager.m
Normal 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
|
||||
9
ReactKit/Modules/RCTStatusBarManager.h
Normal file
9
ReactKit/Modules/RCTStatusBarManager.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
|
||||
@interface RCTStatusBarManager : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
||||
67
ReactKit/Modules/RCTStatusBarManager.m
Normal file
67
ReactKit/Modules/RCTStatusBarManager.m
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTStatusBarManager.h"
|
||||
|
||||
#import "RCTLog.h"
|
||||
|
||||
@implementation RCTStatusBarManager
|
||||
|
||||
static BOOL RCTViewControllerBasedStatusBarAppearance()
|
||||
{
|
||||
static BOOL value;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
value = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"] boolValue];
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
- (void)setStyle:(UIStatusBarStyle)statusBarStyle animated:(BOOL)animated
|
||||
{
|
||||
RCT_EXPORT();
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
if (RCTViewControllerBasedStatusBarAppearance()) {
|
||||
RCTLogError(@"RCTStatusBarManager module requires that the \
|
||||
UIViewControllerBasedStatusBarAppearance key in the Info.plist is set to NO");
|
||||
} else {
|
||||
[[UIApplication sharedApplication] setStatusBarStyle:statusBarStyle
|
||||
animated:animated];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setHidden:(BOOL)hidden withAnimation:(UIStatusBarAnimation)animation
|
||||
{
|
||||
RCT_EXPORT();
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
if (RCTViewControllerBasedStatusBarAppearance()) {
|
||||
RCTLogError(@"RCTStatusBarManager module requires that the \
|
||||
UIViewControllerBasedStatusBarAppearance key in the Info.plist is set to NO");
|
||||
} else {
|
||||
[[UIApplication sharedApplication] setStatusBarHidden:hidden
|
||||
withAnimation:animation];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+ (NSDictionary *)constantsToExport
|
||||
{
|
||||
return @{
|
||||
@"Style": @{
|
||||
@"default": @(UIStatusBarStyleDefault),
|
||||
@"lightContent": @(UIStatusBarStyleLightContent),
|
||||
},
|
||||
@"Animation": @{
|
||||
@"none": @(UIStatusBarAnimationNone),
|
||||
@"fade": @(UIStatusBarAnimationFade),
|
||||
@"slide": @(UIStatusBarAnimationSlide),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
10
ReactKit/Modules/RCTTiming.h
Normal file
10
ReactKit/Modules/RCTTiming.h
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
#import "RCTInvalidating.h"
|
||||
|
||||
@interface RCTTiming : NSObject <RCTBridgeModule, RCTInvalidating>
|
||||
|
||||
@end
|
||||
203
ReactKit/Modules/RCTTiming.m
Normal file
203
ReactKit/Modules/RCTTiming.m
Normal file
@@ -0,0 +1,203 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import "RCTTiming.h"
|
||||
|
||||
#import "RCTBridge.h"
|
||||
#import "RCTLog.h"
|
||||
#import "RCTSparseArray.h"
|
||||
#import "RCTUtils.h"
|
||||
|
||||
@interface RCTTimer : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) NSDate *target;
|
||||
@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])) {
|
||||
_interval = interval;
|
||||
_repeats = repeats;
|
||||
_callbackID = callbackID;
|
||||
_target = [NSDate dateWithTimeIntervalSinceNow:targetTime];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `YES` if we should invoke the JS callback.
|
||||
*/
|
||||
- (BOOL)updateFoundNeedsJSUpdate
|
||||
{
|
||||
if (_target && _target.timeIntervalSinceNow <= 0) {
|
||||
// The JS Timers will do fine grained calculating of expired timeouts.
|
||||
_target = _repeats ? [NSDate dateWithTimeIntervalSinceNow:_interval] : nil;
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTTiming
|
||||
{
|
||||
RCTSparseArray *_timers;
|
||||
RCTBridge *_bridge;
|
||||
id _updateTimer;
|
||||
}
|
||||
|
||||
+ (NSArray *)JSMethods
|
||||
{
|
||||
return @[@"RCTJSTimers.callTimers"];
|
||||
}
|
||||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_bridge = bridge;
|
||||
_timers = [[RCTSparseArray alloc] init];
|
||||
[self startTimers];
|
||||
|
||||
for (NSString *name in @[UIApplicationWillResignActiveNotification,
|
||||
UIApplicationDidEnterBackgroundNotification,
|
||||
UIApplicationWillTerminateNotification]) {
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(stopTimers)
|
||||
name:name
|
||||
object:nil];
|
||||
}
|
||||
|
||||
for (NSString *name in @[UIApplicationDidBecomeActiveNotification,
|
||||
UIApplicationWillEnterForegroundNotification]) {
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(startTimers)
|
||||
name:name
|
||||
object:nil];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (BOOL)isValid
|
||||
{
|
||||
return _bridge != nil;
|
||||
}
|
||||
|
||||
- (void)invalidate
|
||||
{
|
||||
[self stopTimers];
|
||||
_bridge = nil;
|
||||
}
|
||||
|
||||
- (void)stopTimers
|
||||
{
|
||||
[_updateTimer invalidate];
|
||||
_updateTimer = nil;
|
||||
}
|
||||
|
||||
- (void)startTimers
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
|
||||
if (![self isValid] || _updateTimer != nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
_updateTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)];
|
||||
if (_updateTimer) {
|
||||
[_updateTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||
} else {
|
||||
RCTLogWarn(@"Failed to create a display link (probably on buildbot) - using an NSTimer for AppEngine instead.");
|
||||
_updateTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60)
|
||||
target:self
|
||||
selector:@selector(update)
|
||||
userInfo:nil
|
||||
repeats:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)update
|
||||
{
|
||||
RCTAssertMainThread();
|
||||
|
||||
NSMutableArray *timersToCall = [[NSMutableArray alloc] init];
|
||||
for (RCTTimer *timer in _timers.allObjects) {
|
||||
if ([timer updateFoundNeedsJSUpdate]) {
|
||||
[timersToCall addObject:timer.callbackID];
|
||||
}
|
||||
if (!timer.target) {
|
||||
_timers[timer.callbackID] = nil;
|
||||
}
|
||||
}
|
||||
|
||||
// call timers that need to be called
|
||||
if ([timersToCall count] > 0) {
|
||||
[_bridge enqueueJSCall:@"RCTJSTimers.callTimers" args:@[timersToCall]];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:(double)jsDuration
|
||||
jsSchedulingTime:(double)jsSchedulingTime
|
||||
repeats:(BOOL)repeats
|
||||
{
|
||||
RCT_EXPORT();
|
||||
|
||||
NSTimeInterval interval = jsDuration / 1000;
|
||||
NSTimeInterval jsCreationTimeSinceUnixEpoch = jsSchedulingTime / 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;
|
||||
}
|
||||
|
||||
RCTTimer *timer = [[RCTTimer alloc] initWithCallbackID:callbackID
|
||||
interval:interval
|
||||
targetTime:targetTime
|
||||
repeats:repeats];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
_timers[callbackID] = timer;
|
||||
});
|
||||
}
|
||||
|
||||
- (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
|
||||
26
ReactKit/Modules/RCTUIManager.h
Normal file
26
ReactKit/Modules/RCTUIManager.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2004-present Facebook. All Rights Reserved.
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
#import "RCTInvalidating.h"
|
||||
|
||||
@class RCTRootView;
|
||||
|
||||
@protocol RCTScrollableProtocol;
|
||||
|
||||
@interface RCTUIManager : NSObject <RCTBridgeModule, RCTInvalidating>
|
||||
|
||||
@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;
|
||||
|
||||
- (void)registerRootView:(RCTRootView *)rootView;
|
||||
|
||||
+ (UIView *)JSResponder;
|
||||
|
||||
@end
|
||||
1352
ReactKit/Modules/RCTUIManager.m
Normal file
1352
ReactKit/Modules/RCTUIManager.m
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user