Update RCTNetworking, RCTNetInfo and RCTLocationManager to use new events system

Summary: Updated networking and geolocation to use the new events system.

Reviewed By: javache

Differential Revision: D3339945

fbshipit-source-id: f1332fb2aab8560e4783739e223c1f31d583cfcf
This commit is contained in:
Nick Lockwood 2016-05-24 10:26:33 -07:00 committed by Facebook Github Bot 3
parent 71bf8a3e48
commit 3f08fe4b7f
27 changed files with 229 additions and 340 deletions

View File

@ -1,4 +1,11 @@
/** /**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* The examples provided by Facebook are for non-commercial testing and * The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only. * evaluation purposes only.
* *
@ -16,9 +23,9 @@
*/ */
'use strict'; 'use strict';
var React = require('react'); const React = require('react');
var ReactNative = require('react-native'); const ReactNative = require('react-native');
var { const {
AppState, AppState,
Text, Text,
View View
@ -29,13 +36,19 @@ var AppStateSubscription = React.createClass({
return { return {
appState: AppState.currentState, appState: AppState.currentState,
previousAppStates: [], previousAppStates: [],
memoryWarnings: 0,
}; };
}, },
componentDidMount: function() { componentDidMount: function() {
AppState.addEventListener('change', this._handleAppStateChange); AppState.addEventListener('change', this._handleAppStateChange);
AppState.addEventListener('memoryWarning', this._handleMemoryWarning);
}, },
componentWillUnmount: function() { componentWillUnmount: function() {
AppState.removeEventListener('change', this._handleAppStateChange); AppState.removeEventListener('change', this._handleAppStateChange);
AppState.removeEventListener('memoryWarning', this._handleMemoryWarning);
},
_handleMemoryWarning: function() {
this.setState({memoryWarnings: this.state.memoryWarnings + 1});
}, },
_handleAppStateChange: function(appState) { _handleAppStateChange: function(appState) {
var previousAppStates = this.state.previousAppStates.slice(); var previousAppStates = this.state.previousAppStates.slice();
@ -46,6 +59,13 @@ var AppStateSubscription = React.createClass({
}); });
}, },
render() { render() {
if (this.props.showMemoryWarnings) {
return (
<View>
<Text>{this.state.memoryWarnings}</Text>
</View>
);
}
if (this.props.showCurrentOnly) { if (this.props.showCurrentOnly) {
return ( return (
<View> <View>
@ -78,4 +98,10 @@ exports.examples = [
title: 'Previous states:', title: 'Previous states:',
render(): ReactElement { return <AppStateSubscription showCurrentOnly={false} />; } render(): ReactElement { return <AppStateSubscription showCurrentOnly={false} />; }
}, },
{
platform: 'ios',
title: 'Memory Warnings',
description: 'In the IOS simulator, hit Shift+Command+M to simulate a memory warning.',
render(): ReactElement { return <AppStateSubscription showMemoryWarnings={true} />; }
},
]; ];

View File

@ -1,99 +0,0 @@
/**
* The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only.
*
* Facebook reserves all rights not expressly granted.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @providesModule AppStateIOSExample
* @flow
*/
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
AppStateIOS,
Text,
View
} = ReactNative;
var AppStateSubscription = React.createClass({
getInitialState() {
return {
appState: AppStateIOS.currentState,
previousAppStates: [],
memoryWarnings: 0,
};
},
componentDidMount: function() {
AppStateIOS.addEventListener('change', this._handleAppStateChange);
AppStateIOS.addEventListener('memoryWarning', this._handleMemoryWarning);
},
componentWillUnmount: function() {
AppStateIOS.removeEventListener('change', this._handleAppStateChange);
AppStateIOS.removeEventListener('memoryWarning', this._handleMemoryWarning);
},
_handleMemoryWarning: function() {
this.setState({memoryWarnings: this.state.memoryWarnings + 1});
},
_handleAppStateChange: function(appState) {
var previousAppStates = this.state.previousAppStates.slice();
previousAppStates.push(this.state.appState);
this.setState({
appState,
previousAppStates,
});
},
render() {
if (this.props.showMemoryWarnings) {
return (
<View>
<Text>{this.state.memoryWarnings}</Text>
</View>
);
}
if (this.props.showCurrentOnly) {
return (
<View>
<Text>{this.state.appState}</Text>
</View>
);
}
return (
<View>
<Text>{JSON.stringify(this.state.previousAppStates)}</Text>
</View>
);
}
});
exports.title = 'AppStateIOS';
exports.description = 'iOS app background status';
exports.examples = [
{
title: 'AppStateIOS.currentState',
description: 'Can be null on app initialization',
render() { return <Text>{AppStateIOS.currentState}</Text>; }
},
{
title: 'Subscribed AppStateIOS:',
description: 'This changes according to the current state, so you can only ever see it rendered as "active"',
render(): ReactElement { return <AppStateSubscription showCurrentOnly={true} />; }
},
{
title: 'Previous states:',
render(): ReactElement { return <AppStateSubscription showCurrentOnly={false} />; }
},
{
title: 'Memory Warnings',
description: 'In the simulator, hit Shift+Command+M to simulate a memory warning.',
render(): ReactElement { return <AppStateSubscription showMemoryWarnings={true} />; }
},
];

View File

@ -171,10 +171,6 @@ const APIExamples: Array<UIExplorerExample> = [
key: 'AnExApp', key: 'AnExApp',
module: require('./AnimatedGratuitousApp/AnExApp'), module: require('./AnimatedGratuitousApp/AnExApp'),
}, },
{
key: 'AppStateIOSExample',
module: require('./AppStateIOSExample'),
},
{ {
key: 'AppStateExample', key: 'AppStateExample',
module: require('./AppStateExample'), module: require('./AppStateExample'),

View File

@ -105,9 +105,7 @@
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations" #pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_eventDispatcher sendDeviceEventWithName:_eventName body:_body]; [_eventDispatcher sendDeviceEventWithName:_eventName body:_body];
#pragma clang diagnostic pop #pragma clang diagnostic pop
[_bridge verify]; [_bridge verify];

View File

@ -1,4 +1,11 @@
/** /**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* The examples provided by Facebook are for non-commercial testing and * The examples provided by Facebook are for non-commercial testing and
* evaluation purposes only. * evaluation purposes only.
* *
@ -21,7 +28,7 @@ var {
AlertIOS, AlertIOS,
CameraRoll, CameraRoll,
Image, Image,
LinkingIOS, Linking,
ProgressViewIOS, ProgressViewIOS,
StyleSheet, StyleSheet,
Text, Text,
@ -215,7 +222,7 @@ class FormUploader extends React.Component {
return; return;
} }
var url = xhr.responseText.slice(index).split('\n')[0]; var url = xhr.responseText.slice(index).split('\n')[0];
LinkingIOS.openURL(url); Linking.openURL(url);
}; };
var formdata = new FormData(); var formdata = new FormData();
if (this.state.randomPhoto) { if (this.state.randomPhoto) {

View File

@ -11,15 +11,16 @@
*/ */
'use strict'; 'use strict';
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter'); const NativeEventEmitter = require('NativeEventEmitter');
var RCTLocationObserver = require('NativeModules').LocationObserver; const RCTLocationObserver = require('NativeModules').LocationObserver;
var invariant = require('fbjs/lib/invariant'); const invariant = require('fbjs/lib/invariant');
var logError = require('logError'); const logError = require('logError');
var warning = require('fbjs/lib/warning'); const warning = require('fbjs/lib/warning');
const LocationEventEmitter = new NativeEventEmitter(RCTLocationObserver);
var subscriptions = []; var subscriptions = [];
var updatesEnabled = false; var updatesEnabled = false;
type GeoOptions = { type GeoOptions = {
@ -80,11 +81,11 @@ var Geolocation = {
} }
var watchID = subscriptions.length; var watchID = subscriptions.length;
subscriptions.push([ subscriptions.push([
RCTDeviceEventEmitter.addListener( LocationEventEmitter.addListener(
'geolocationDidChange', 'geolocationDidChange',
success success
), ),
error ? RCTDeviceEventEmitter.addListener( error ? LocationEventEmitter.addListener(
'geolocationError', 'geolocationError',
error error
) : null, ) : null,

View File

@ -7,8 +7,8 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
#import "RCTBridgeModule.h" #import "RCTEventEmitter.h"
@interface RCTLocationObserver : NSObject<RCTBridgeModule> @interface RCTLocationObserver : RCTEventEmitter
@end @end

View File

@ -113,8 +113,6 @@ static NSDictionary<NSString *, id> *RCTPositionError(RCTPositionErrorCode code,
RCT_EXPORT_MODULE() RCT_EXPORT_MODULE()
@synthesize bridge = _bridge;
#pragma mark - Lifecycle #pragma mark - Lifecycle
- (void)dealloc - (void)dealloc
@ -128,8 +126,12 @@ RCT_EXPORT_MODULE()
return dispatch_get_main_queue(); return dispatch_get_main_queue();
} }
#pragma mark - Private API - (NSArray<NSString *> *)supportedEvents
{
return @[@"geolocationDidChange", @"geolocationError"];
}
#pragma mark - Private API
- (void)beginLocationUpdatesWithDesiredAccuracy:(CLLocationAccuracy)desiredAccuracy distanceFilter:(CLLocationDistance)distanceFilter - (void)beginLocationUpdatesWithDesiredAccuracy:(CLLocationAccuracy)desiredAccuracy distanceFilter:(CLLocationDistance)distanceFilter
{ {
@ -279,11 +281,7 @@ RCT_EXPORT_METHOD(getCurrentPosition:(RCTLocationOptions)options
// Send event // Send event
if (_observingLocation) { if (_observingLocation) {
#pragma clang diagnostic push [self sendEventWithName:@"geolocationDidChange" body:_lastLocationEvent];
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"geolocationDidChange"
body:_lastLocationEvent];
#pragma clang diagnostic pop
} }
// Fire all queued callbacks // Fire all queued callbacks
@ -324,11 +322,7 @@ RCT_EXPORT_METHOD(getCurrentPosition:(RCTLocationOptions)options
// Send event // Send event
if (_observingLocation) { if (_observingLocation) {
#pragma clang diagnostic push [self sendEventWithName:@"geolocationError" body:jsError];
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"geolocationError"
body:jsError];
#pragma clang diagnostic pop
} }
// Fire all queued error callbacks // Fire all queued error callbacks

View File

@ -88,8 +88,11 @@ continueUserActivity:(NSUserActivity *)userActivity
- (void)handleOpenURLNotification:(NSNotification *)notification - (void)handleOpenURLNotification:(NSNotification *)notification
{ {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"openURL" [_bridge.eventDispatcher sendDeviceEventWithName:@"openURL"
body:notification.userInfo]; body:notification.userInfo];
#pragma clang diagnostic pop
} }
RCT_EXPORT_METHOD(openURL:(NSURL *)URL RCT_EXPORT_METHOD(openURL:(NSURL *)URL

View File

@ -12,12 +12,14 @@
'use strict'; 'use strict';
const Map = require('Map'); const Map = require('Map');
const NativeEventEmitter = require('NativeEventEmitter');
const NativeModules = require('NativeModules'); const NativeModules = require('NativeModules');
const Platform = require('Platform'); const Platform = require('Platform');
const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
const RCTNetInfo = NativeModules.NetInfo; const RCTNetInfo = NativeModules.NetInfo;
const deprecatedCallback = require('deprecatedCallback'); const deprecatedCallback = require('deprecatedCallback');
const NetInfoEventEmitter = new NativeEventEmitter(RCTNetInfo);
const DEVICE_CONNECTIVITY_EVENT = 'networkStatusDidChange'; const DEVICE_CONNECTIVITY_EVENT = 'networkStatusDidChange';
type ChangeEventName = $Enum<{ type ChangeEventName = $Enum<{
@ -176,7 +178,7 @@ const NetInfo = {
eventName: ChangeEventName, eventName: ChangeEventName,
handler: Function handler: Function
): {remove: () => void} { ): {remove: () => void} {
const listener = RCTDeviceEventEmitter.addListener( const listener = NetInfoEventEmitter.addListener(
DEVICE_CONNECTIVITY_EVENT, DEVICE_CONNECTIVITY_EVENT,
(appStateData) => { (appStateData) => {
handler(appStateData.network_info); handler(appStateData.network_info);

View File

@ -9,10 +9,10 @@
#import <SystemConfiguration/SystemConfiguration.h> #import <SystemConfiguration/SystemConfiguration.h>
#import "RCTBridgeModule.h" #import "RCTEventEmitter.h"
@interface RCTNetInfo : NSObject<RCTBridgeModule> @interface RCTNetInfo : RCTEventEmitter
- (instancetype)initWithHost:(NSString *)host NS_DESIGNATED_INITIALIZER; - (instancetype)initWithHost:(NSString *)host;
@end @end

View File

@ -22,10 +22,9 @@ static NSString *const RCTReachabilityStateCell = @"cell";
{ {
SCNetworkReachabilityRef _reachability; SCNetworkReachabilityRef _reachability;
NSString *_status; NSString *_status;
NSString *_host;
} }
@synthesize bridge = _bridge;
RCT_EXPORT_MODULE() RCT_EXPORT_MODULE()
static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
@ -51,11 +50,7 @@ static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SC
if (![status isEqualToString:self->_status]) { if (![status isEqualToString:self->_status]) {
self->_status = status; self->_status = status;
#pragma clang diagnostic push [self sendEventWithName:@"networkStatusDidChange" body:@{@"network_info": status}];
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[self->_bridge.eventDispatcher sendDeviceEventWithName:@"networkStatusDidChange"
body:@{@"network_info": status}];
#pragma clang diagnostic pop
} }
} }
@ -66,34 +61,40 @@ static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SC
RCTAssertParam(host); RCTAssertParam(host);
RCTAssert(![host hasPrefix:@"http"], @"Host value should just contain the domain, not the URL scheme."); RCTAssert(![host hasPrefix:@"http"], @"Host value should just contain the domain, not the URL scheme.");
if ((self = [super init])) { if ((self = [self init])) {
_status = RCTReachabilityStateUnknown; _host = [host copy];
_reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, host.UTF8String);
SCNetworkReachabilityContext context = { 0, ( __bridge void *)self, NULL, NULL, NULL };
SCNetworkReachabilitySetCallback(_reachability, RCTReachabilityCallback, &context);
SCNetworkReachabilityScheduleWithRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
} }
return self; return self;
} }
- (instancetype)init - (NSArray<NSString *> *)supportedEvents
{ {
return [self initWithHost:@"apple.com"]; return @[@"networkStatusDidChange"];
} }
- (void)dealloc - (void)startObserving
{ {
SCNetworkReachabilityUnscheduleFromRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); _status = RCTReachabilityStateUnknown;
CFRelease(_reachability); _reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, _host.UTF8String ?: "apple.com");
SCNetworkReachabilityContext context = { 0, ( __bridge void *)self, NULL, NULL, NULL };
SCNetworkReachabilitySetCallback(_reachability, RCTReachabilityCallback, &context);
SCNetworkReachabilityScheduleWithRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}
- (void)stopObserving
{
if (_reachability) {
SCNetworkReachabilityUnscheduleFromRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFRelease(_reachability);
}
} }
#pragma mark - Public API #pragma mark - Public API
// TODO: remove error callback - not needed except by Subscribable interface
RCT_EXPORT_METHOD(getCurrentConnectivity:(RCTPromiseResolveBlock)resolve RCT_EXPORT_METHOD(getCurrentConnectivity:(RCTPromiseResolveBlock)resolve
reject:(__unused RCTPromiseRejectBlock)reject) reject:(__unused RCTPromiseRejectBlock)reject)
{ {
resolve(@{@"network_info": _status}); resolve(@{@"network_info": _status ?: RCTReachabilityStateUnknown});
} }
@end @end

View File

@ -12,39 +12,66 @@
// Do not require the native RCTNetworking module directly! Use this wrapper module instead. // Do not require the native RCTNetworking module directly! Use this wrapper module instead.
// It will add the necessary requestId, so that you don't have to generate it yourself. // It will add the necessary requestId, so that you don't have to generate it yourself.
var RCTNetworkingNative = require('NativeModules').Networking; const FormData = require('FormData');
const NativeEventEmitter = require('NativeEventEmitter');
const RCTNetworkingNative = require('NativeModules').Networking;
var _requestId = 1; type Header = [string, string];
var generateRequestId = function() {
function convertHeadersMapToArray(headers: Object): Array<Header> {
const headerArray = [];
for (const name in headers) {
headerArray.push([name, headers[name]]);
}
return headerArray;
}
let _requestId = 1;
function generateRequestId() {
return _requestId++; return _requestId++;
}; }
/** /**
* This class is a wrapper around the native RCTNetworking module. It adds a necessary unique * This class is a wrapper around the native RCTNetworking module. It adds a necessary unique
* requestId to each network request that can be used to abort that request later on. * requestId to each network request that can be used to abort that request later on.
*/ */
class RCTNetworking { class RCTNetworking extends NativeEventEmitter {
static sendRequest(method, url, headers, data, useIncrementalUpdates, timeout) { constructor() {
var requestId = generateRequestId(); super(RCTNetworkingNative);
}
sendRequest(method, url, headers, data, incrementalUpdates, timeout, callback) {
if (typeof data === 'string') {
data = {string: data};
} else if (data instanceof FormData) {
data = {
formData: data.getParts().map((part) => {
part.headers = convertHeadersMapToArray(part.headers);
return part;
}),
};
}
const requestId = generateRequestId();
RCTNetworkingNative.sendRequest( RCTNetworkingNative.sendRequest(
method, method,
url, url,
requestId, requestId,
headers, convertHeadersMapToArray(headers),
data, data,
useIncrementalUpdates, incrementalUpdates,
timeout); timeout
return requestId; );
callback(requestId);
} }
static abortRequest(requestId) { abortRequest(requestId) {
RCTNetworkingNative.abortRequest(requestId); RCTNetworkingNative.abortRequest(requestId);
} }
static clearCookies(callback) { clearCookies(callback) {
RCTNetworkingNative.clearCookies(callback); RCTNetworkingNative.clearCookies(callback);
} }
} }
module.exports = RCTNetworking; module.exports = new RCTNetworking();

View File

@ -7,12 +7,10 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
#import <Foundation/Foundation.h> #import "RCTEventEmitter.h"
#import "RCTBridge.h"
#import "RCTNetworkTask.h" #import "RCTNetworkTask.h"
@interface RCTNetworking : NSObject <RCTBridgeModule> @interface RCTNetworking : RCTEventEmitter
/** /**
* Does a handler exist for the specified request? * Does a handler exist for the specified request?

View File

@ -10,21 +10,39 @@
*/ */
'use strict'; 'use strict';
var RCTNetworkingNative = require('NativeModules').Networking; const FormData = require('FormData');
const NativeEventEmitter = require('NativeEventEmitter');
const RCTNetworkingNative = require('NativeModules').Networking;
/** class RCTNetworking extends NativeEventEmitter {
* This class is a wrapper around the native RCTNetworking module.
*/
class RCTNetworking {
static sendRequest(query, callback) { constructor() {
RCTNetworkingNative.sendRequest(query, callback); super(RCTNetworkingNative);
} }
static abortRequest(requestId) { sendRequest(method, url, headers, data, incrementalUpdates, timeout, callback) {
RCTNetworkingNative.cancelRequest(requestId); if (typeof data === 'string') {
data = {string: data};
} else if (data instanceof FormData) {
data = {formData: data.getParts()};
}
RCTNetworkingNative.sendRequest({
method,
url,
data,
headers,
incrementalUpdates,
timeout
}, callback);
} }
abortRequest(requestId) {
RCTNetworkingNative.abortRequest(requestId);
}
clearCookies(callback) {
console.warn('RCTNetworking.clearCookies is not supported on iOS');
}
} }
module.exports = RCTNetworking; module.exports = new RCTNetworking();

View File

@ -129,11 +129,18 @@ static NSString *RCTGenerateFormBoundary()
NSArray<id<RCTURLRequestHandler>> *_handlers; NSArray<id<RCTURLRequestHandler>> *_handlers;
} }
@synthesize bridge = _bridge;
@synthesize methodQueue = _methodQueue; @synthesize methodQueue = _methodQueue;
RCT_EXPORT_MODULE() RCT_EXPORT_MODULE()
- (NSArray<NSString *> *)supportedEvents
{
return @[@"didCompleteNetworkResponse",
@"didReceiveNetworkResponse",
@"didSendNetworkData",
@"didReceiveNetworkData"];
}
- (id<RCTURLRequestHandler>)handlerForRequest:(NSURLRequest *)request - (id<RCTURLRequestHandler>)handlerForRequest:(NSURLRequest *)request
{ {
if (!request.URL) { if (!request.URL) {
@ -142,7 +149,7 @@ RCT_EXPORT_MODULE()
if (!_handlers) { if (!_handlers) {
// Get handlers, sorted in reverse priority order (highest priority first) // Get handlers, sorted in reverse priority order (highest priority first)
_handlers = [[_bridge modulesConformingToProtocol:@protocol(RCTURLRequestHandler)] sortedArrayUsingComparator:^NSComparisonResult(id<RCTURLRequestHandler> a, id<RCTURLRequestHandler> b) { _handlers = [[self.bridge modulesConformingToProtocol:@protocol(RCTURLRequestHandler)] sortedArrayUsingComparator:^NSComparisonResult(id<RCTURLRequestHandler> a, id<RCTURLRequestHandler> b) {
float priorityA = [a respondsToSelector:@selector(handlerPriority)] ? [a handlerPriority] : 0; float priorityA = [a respondsToSelector:@selector(handlerPriority)] ? [a handlerPriority] : 0;
float priorityB = [b respondsToSelector:@selector(handlerPriority)] ? [b handlerPriority] : 0; float priorityB = [b respondsToSelector:@selector(handlerPriority)] ? [b handlerPriority] : 0;
if (priorityA > priorityB) { if (priorityA > priorityB) {
@ -346,11 +353,7 @@ RCT_EXPORT_MODULE()
} }
NSArray<id> *responseJSON = @[task.requestID, responseText ?: @""]; NSArray<id> *responseJSON = @[task.requestID, responseText ?: @""];
#pragma clang diagnostic push [self sendEventWithName:@"didReceiveNetworkData" body:responseJSON];
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkData"
body:responseJSON];
#pragma clang diagnostic pop
} }
- (void)sendRequest:(NSURLRequest *)request - (void)sendRequest:(NSURLRequest *)request
@ -364,10 +367,7 @@ RCT_EXPORT_MODULE()
RCTURLRequestProgressBlock uploadProgressBlock = ^(int64_t progress, int64_t total) { RCTURLRequestProgressBlock uploadProgressBlock = ^(int64_t progress, int64_t total) {
dispatch_async(_methodQueue, ^{ dispatch_async(_methodQueue, ^{
NSArray *responseJSON = @[task.requestID, @((double)progress), @((double)total)]; NSArray *responseJSON = @[task.requestID, @((double)progress), @((double)total)];
#pragma clang diagnostic push [self sendEventWithName:@"didSendNetworkData" body:responseJSON];
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"didSendNetworkData" body:responseJSON];
#pragma clang diagnostic pop
}); });
}; };
@ -385,11 +385,7 @@ RCT_EXPORT_MODULE()
} }
id responseURL = response.URL ? response.URL.absoluteString : [NSNull null]; id responseURL = response.URL ? response.URL.absoluteString : [NSNull null];
NSArray<id> *responseJSON = @[task.requestID, @(status), headers, responseURL]; NSArray<id> *responseJSON = @[task.requestID, @(status), headers, responseURL];
#pragma clang diagnostic push [self sendEventWithName:@"didReceiveNetworkResponse" body:responseJSON];
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkResponse"
body:responseJSON];
#pragma clang diagnostic pop
}); });
}; };
@ -410,12 +406,7 @@ RCT_EXPORT_MODULE()
error.code == kCFURLErrorTimedOut ? @YES : @NO error.code == kCFURLErrorTimedOut ? @YES : @NO
]; ];
#pragma clang diagnostic push [self sendEventWithName:@"didCompleteNetworkResponse" body:responseJSON];
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"didCompleteNetworkResponse"
body:responseJSON];
#pragma clang diagnostic pop
[_tasksByRequestID removeObjectForKey:task.requestID]; [_tasksByRequestID removeObjectForKey:task.requestID];
}); });
}; };
@ -469,7 +460,7 @@ RCT_EXPORT_METHOD(sendRequest:(NSDictionary *)query
}]; }];
} }
RCT_EXPORT_METHOD(cancelRequest:(nonnull NSNumber *)requestID) RCT_EXPORT_METHOD(abortRequest:(nonnull NSNumber *)requestID)
{ {
[_tasksByRequestID[requestID] cancel]; [_tasksByRequestID[requestID] cancel];
[_tasksByRequestID removeObjectForKey:requestID]; [_tasksByRequestID removeObjectForKey:requestID];

View File

@ -1,62 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule XMLHttpRequest
* @flow
*/
'use strict';
var FormData = require('FormData');
var RCTNetworking = require('RCTNetworking');
var XMLHttpRequestBase = require('XMLHttpRequestBase');
type Header = [string, string];
function convertHeadersMapToArray(headers: Object): Array<Header> {
var headerArray = [];
for (var name in headers) {
headerArray.push([name, headers[name]]);
}
return headerArray;
}
class XMLHttpRequest extends XMLHttpRequestBase {
sendImpl(
method: ?string,
url: ?string,
headers: Object,
data: any,
useIncrementalUpdates: boolean,
timeout: number,
): void {
var body;
if (typeof data === 'string') {
body = {string: data};
} else if (data instanceof FormData) {
body = {
formData: data.getParts().map((part) => {
part.headers = convertHeadersMapToArray(part.headers);
return part;
}),
};
} else {
body = data;
}
var requestId = RCTNetworking.sendRequest(
method,
url,
convertHeadersMapToArray(headers),
body,
useIncrementalUpdates,
timeout
);
this.didCreateRequest(requestId);
}
}
module.exports = XMLHttpRequest;

View File

@ -1,47 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule XMLHttpRequest
* @flow
*/
'use strict';
var FormData = require('FormData');
var RCTNetworking = require('RCTNetworking');
var XMLHttpRequestBase = require('XMLHttpRequestBase');
class XMLHttpRequest extends XMLHttpRequestBase {
sendImpl(
method: ?string,
url: ?string,
headers: Object,
data: any,
incrementalUpdates: boolean,
timeout: number,
): void {
if (typeof data === 'string') {
data = {string: data};
} else if (data instanceof FormData) {
data = {formData: data.getParts()};
}
RCTNetworking.sendRequest(
{
method,
url,
data,
headers,
incrementalUpdates,
timeout
},
this.didCreateRequest.bind(this)
);
}
}
module.exports = XMLHttpRequest;

View File

@ -6,13 +6,12 @@
* LICENSE file in the root directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
* *
* @providesModule XMLHttpRequestBase * @providesModule XMLHttpRequest
* @flow * @flow
*/ */
'use strict'; 'use strict';
var RCTNetworking = require('RCTNetworking'); const RCTNetworking = require('RCTNetworking');
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
const EventTarget = require('event-target-shim'); const EventTarget = require('event-target-shim');
const invariant = require('fbjs/lib/invariant'); const invariant = require('fbjs/lib/invariant');
@ -212,19 +211,19 @@ class XMLHttpRequestBase extends EventTarget(...XHR_EVENTS) {
didCreateRequest(requestId: number): void { didCreateRequest(requestId: number): void {
this._requestId = requestId; this._requestId = requestId;
this._subscriptions.push(RCTDeviceEventEmitter.addListener( this._subscriptions.push(RCTNetworking.addListener(
'didSendNetworkData', 'didSendNetworkData',
(args) => this.__didUploadProgress(...args) (args) => this.__didUploadProgress(...args)
)); ));
this._subscriptions.push(RCTDeviceEventEmitter.addListener( this._subscriptions.push(RCTNetworking.addListener(
'didReceiveNetworkResponse', 'didReceiveNetworkResponse',
(args) => this._didReceiveResponse(...args) (args) => this._didReceiveResponse(...args)
)); ));
this._subscriptions.push(RCTDeviceEventEmitter.addListener( this._subscriptions.push(RCTNetworking.addListener(
'didReceiveNetworkData', 'didReceiveNetworkData',
(args) => this._didReceiveData(...args) (args) => this._didReceiveData(...args)
)); ));
this._subscriptions.push(RCTDeviceEventEmitter.addListener( this._subscriptions.push(RCTNetworking.addListener(
'didCompleteNetworkResponse', 'didCompleteNetworkResponse',
(args) => this.__didCompleteResponse(...args) (args) => this.__didCompleteResponse(...args)
)); ));
@ -337,10 +336,18 @@ class XMLHttpRequestBase extends EventTarget(...XHR_EVENTS) {
url: ?string, url: ?string,
headers: Object, headers: Object,
data: any, data: any,
incrementalEvents: boolean, useIncrementalUpdates: boolean,
timeout: number timeout: number,
): void { ): void {
throw new Error('Subclass must define sendImpl method'); RCTNetworking.sendRequest(
method,
url,
headers,
data,
useIncrementalUpdates,
timeout,
this.didCreateRequest.bind(this),
);
} }
send(data: any): void { send(data: any): void {

View File

@ -12,13 +12,11 @@
jest jest
.disableAutomock() .disableAutomock()
.dontMock('event-target-shim') .dontMock('event-target-shim')
.dontMock('XMLHttpRequestBase'); .dontMock('XMLHttpRequest');
const XMLHttpRequestBase = require('XMLHttpRequestBase'); const XMLHttpRequest = require('XMLHttpRequest');
class XMLHttpRequest extends XMLHttpRequestBase {} describe('XMLHttpRequest', function(){
describe('XMLHttpRequestBase', function(){
var xhr; var xhr;
var handleTimeout; var handleTimeout;
var handleError; var handleError;

View File

@ -137,20 +137,29 @@ RCT_EXPORT_MODULE()
- (void)handleLocalNotificationReceived:(NSNotification *)notification - (void)handleLocalNotificationReceived:(NSNotification *)notification
{ {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"localNotificationReceived" [_bridge.eventDispatcher sendDeviceEventWithName:@"localNotificationReceived"
body:notification.userInfo]; body:notification.userInfo];
#pragma clang diagnostic pop
} }
- (void)handleRemoteNotificationReceived:(NSNotification *)notification - (void)handleRemoteNotificationReceived:(NSNotification *)notification
{ {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationReceived" [_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationReceived"
body:notification.userInfo]; body:notification.userInfo];
#pragma clang diagnostic pop
} }
- (void)handleRemoteNotificationsRegistered:(NSNotification *)notification - (void)handleRemoteNotificationsRegistered:(NSNotification *)notification
{ {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationsRegistered" [_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationsRegistered"
body:notification.userInfo]; body:notification.userInfo];
#pragma clang diagnostic pop
} }
/** /**

View File

@ -10,11 +10,11 @@
*/ */
'use strict'; 'use strict';
var warning = require('fbjs/lib/warning'); const warning = require('fbjs/lib/warning');
if (__DEV__) { if (__DEV__) {
var warningDedupe = {}; const warningDedupe = {};
var addonWarn = function(prevName, newPackageName) { const addonWarn = function(prevName, newPackageName) {
warning( warning(
warningDedupe[prevName], warningDedupe[prevName],
'React.addons.' + prevName + ' is deprecated. Please import the "' + 'React.addons.' + prevName + ' is deprecated. Please import the "' +
@ -25,7 +25,7 @@ if (__DEV__) {
} }
// Export React, plus some native additions. // Export React, plus some native additions.
var ReactNative = { const ReactNative = {
// Components // Components
get ActivityIndicatorIOS() { return require('ActivityIndicatorIOS'); }, get ActivityIndicatorIOS() { return require('ActivityIndicatorIOS'); },
get ART() { return require('ReactNativeART'); }, get ART() { return require('ReactNativeART'); },
@ -87,9 +87,11 @@ var ReactNative = {
get ImagePickerIOS() { return require('ImagePickerIOS'); }, get ImagePickerIOS() { return require('ImagePickerIOS'); },
get IntentAndroid() { return require('IntentAndroid'); }, get IntentAndroid() { return require('IntentAndroid'); },
get InteractionManager() { return require('InteractionManager'); }, get InteractionManager() { return require('InteractionManager'); },
get Keyboard() { return require('Keyboard'); },
get LayoutAnimation() { return require('LayoutAnimation'); }, get LayoutAnimation() { return require('LayoutAnimation'); },
get Linking() { return require('Linking'); }, get Linking() { return require('Linking'); },
get LinkingIOS() { return require('LinkingIOS'); }, get LinkingIOS() { return require('LinkingIOS'); },
get NativeEventEmitter() { return require('NativeEventEmitter'); },
get NavigationExperimental() { return require('NavigationExperimental'); }, get NavigationExperimental() { return require('NavigationExperimental'); },
get NetInfo() { return require('NetInfo'); }, get NetInfo() { return require('NetInfo'); },
get PanResponder() { return require('PanResponder'); }, get PanResponder() { return require('PanResponder'); },
@ -171,7 +173,7 @@ var ReactNative = {
// Preserve getters with warnings on the internal ReactNative copy without // Preserve getters with warnings on the internal ReactNative copy without
// invoking them. // invoking them.
var ReactNativeInternal = require('ReactNative'); const ReactNativeInternal = require('ReactNative');
function applyForwarding(key) { function applyForwarding(key) {
if (__DEV__) { if (__DEV__) {
Object.defineProperty( Object.defineProperty(
@ -183,7 +185,7 @@ function applyForwarding(key) {
} }
ReactNative[key] = ReactNativeInternal[key]; ReactNative[key] = ReactNativeInternal[key];
} }
for (var key in ReactNativeInternal) { for (const key in ReactNativeInternal) {
applyForwarding(key); applyForwarding(key);
} }

View File

@ -85,9 +85,11 @@ var ReactNative = Object.assign(Object.create(require('ReactNative')), {
ImagePickerIOS: require('ImagePickerIOS'), ImagePickerIOS: require('ImagePickerIOS'),
IntentAndroid: require('IntentAndroid'), IntentAndroid: require('IntentAndroid'),
InteractionManager: require('InteractionManager'), InteractionManager: require('InteractionManager'),
Keyboard: require('Keyboard'),
LayoutAnimation: require('LayoutAnimation'), LayoutAnimation: require('LayoutAnimation'),
Linking: require('Linking'), Linking: require('Linking'),
LinkingIOS: require('LinkingIOS'), LinkingIOS: require('LinkingIOS'),
NativeEventEmitter: require('NativeEventEmitter'),
NavigationExperimental: require('NavigationExperimental'), NavigationExperimental: require('NavigationExperimental'),
NetInfo: require('NetInfo'), NetInfo: require('NetInfo'),
PanResponder: require('PanResponder'), PanResponder: require('PanResponder'),

View File

@ -92,8 +92,11 @@ RCT_EXPORT_MODULE()
BOOL newIsVoiceOverEnabled = UIAccessibilityIsVoiceOverRunning(); BOOL newIsVoiceOverEnabled = UIAccessibilityIsVoiceOverRunning();
if (_isVoiceOverEnabled != newIsVoiceOverEnabled) { if (_isVoiceOverEnabled != newIsVoiceOverEnabled) {
_isVoiceOverEnabled = newIsVoiceOverEnabled; _isVoiceOverEnabled = newIsVoiceOverEnabled;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"voiceOverDidChange" [_bridge.eventDispatcher sendDeviceEventWithName:@"voiceOverDidChange"
body:@(_isVoiceOverEnabled)]; body:@(_isVoiceOverEnabled)];
#pragma clang diagnostic pop
} }
} }

View File

@ -182,7 +182,10 @@ RCT_EXPORT_MODULE()
selectedTitle:@"Hide Inspector" selectedTitle:@"Hide Inspector"
handler:^(__unused BOOL enabled) handler:^(__unused BOOL enabled)
{ {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[weakSelf.bridge.eventDispatcher sendDeviceEventWithName:@"toggleElementInspector" body:nil]; [weakSelf.bridge.eventDispatcher sendDeviceEventWithName:@"toggleElementInspector" body:nil];
#pragma clang diagnostic pop
}]]; }]];
_webSocketExecutorName = [_defaults objectForKey:@"websocket-executor-name"] ?: @"JS Remotely"; _webSocketExecutorName = [_defaults objectForKey:@"websocket-executor-name"] ?: @"JS Remotely";
@ -214,8 +217,11 @@ RCT_EXPORT_MODULE()
modifierFlags:UIKeyModifierCommand modifierFlags:UIKeyModifierCommand
action:^(__unused UIKeyCommand *command) { action:^(__unused UIKeyCommand *command) {
[weakSelf.bridge.eventDispatcher [weakSelf.bridge.eventDispatcher
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
sendDeviceEventWithName:@"toggleElementInspector" sendDeviceEventWithName:@"toggleElementInspector"
body:nil]; body:nil];
#pragma clang diagnostic pop
}]; }];
// Reload in normal mode // Reload in normal mode
@ -388,7 +394,10 @@ RCT_EXPORT_MODULE()
// Inspector can only be shown after JS has loaded // Inspector can only be shown after JS has loaded
if ([_settings[@"showInspector"] boolValue]) { if ([_settings[@"showInspector"] boolValue]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[self.bridge.eventDispatcher sendDeviceEventWithName:@"toggleElementInspector" body:nil]; [self.bridge.eventDispatcher sendDeviceEventWithName:@"toggleElementInspector" body:nil];
#pragma clang diagnostic pop
} }
}); });
} }

View File

@ -37,7 +37,9 @@
- (void)sendEventWithName:(NSString *)eventName body:(id)body - (void)sendEventWithName:(NSString *)eventName body:(id)body
{ {
RCTAssert(_bridge != nil, @"bridge is not set."); RCTAssert(_bridge != nil, @"bridge is not set. This is probably because you've "
"explicitly synthesized the bridge in %@, even though it's inherited "
"from RCTEventEmitter.", [self class]);
if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) { if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
RCTLogError(@"`%@` is not a supported event type for %@. Supported events are: `%@`", RCTLogError(@"`%@` is not a supported event type for %@. Supported events are: `%@`",

View File

@ -253,8 +253,11 @@ RCT_EXPORT_MODULE()
!UIInterfaceOrientationIsPortrait(nextOrientation)) || !UIInterfaceOrientationIsPortrait(nextOrientation)) ||
(UIInterfaceOrientationIsLandscape(_currentInterfaceOrientation) && (UIInterfaceOrientationIsLandscape(_currentInterfaceOrientation) &&
!UIInterfaceOrientationIsLandscape(nextOrientation))) { !UIInterfaceOrientationIsLandscape(nextOrientation))) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions" [_bridge.eventDispatcher sendDeviceEventWithName:@"didUpdateDimensions"
body:RCTExportedDimensions(YES)]; body:RCTExportedDimensions(YES)];
#pragma clang diagnostic pop
} }
_currentInterfaceOrientation = nextOrientation; _currentInterfaceOrientation = nextOrientation;