Updated AppState module to use new emitter system
Summary: AppState now subclasses NativeEventEmitter instead of using global RCTDeviceEventEmitter. Reviewed By: javache Differential Revision: D3310488 fbshipit-source-id: f0116599223f4411307385c0dab683659d8d63b6
This commit is contained in:
parent
c87b737ca1
commit
d9737571c4
|
@ -66,9 +66,13 @@ typedef void (^ControlBlock)(RCTRootView*);
|
||||||
|
|
||||||
- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView
|
- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView
|
||||||
{
|
{
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
|
||||||
[rootView.bridge.eventDispatcher sendAppEventWithName:@"rootViewDidChangeIntrinsicSize"
|
[rootView.bridge.eventDispatcher sendAppEventWithName:@"rootViewDidChangeIntrinsicSize"
|
||||||
body:@{@"width": @(rootView.intrinsicSize.width),
|
body:@{@"width": @(rootView.intrinsicSize.width),
|
||||||
@"height": @(rootView.intrinsicSize.height)}];
|
@"height": @(rootView.intrinsicSize.height)}];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -103,8 +103,13 @@
|
||||||
[[_bridge expect] enqueueJSCall:_JSMethod
|
[[_bridge expect] enqueueJSCall:_JSMethod
|
||||||
args:[_testEvent arguments]];
|
args:[_testEvent arguments]];
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
|
||||||
[_eventDispatcher sendDeviceEventWithName:_eventName body:_body];
|
[_eventDispatcher sendDeviceEventWithName:_eventName body:_body];
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
[_bridge verify];
|
[_bridge verify];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,11 +41,16 @@
|
||||||
|
|
||||||
RCT_EXPORT_MODULE()
|
RCT_EXPORT_MODULE()
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
|
||||||
|
|
||||||
- (NSArray<NSString *> *)customDirectEventTypes
|
- (NSArray<NSString *> *)customDirectEventTypes
|
||||||
{
|
{
|
||||||
return @[@"foo"];
|
return @[@"foo"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,18 +11,12 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var Map = require('Map');
|
const NativeEventEmitter = require('NativeEventEmitter');
|
||||||
var NativeModules = require('NativeModules');
|
const NativeModules = require('NativeModules');
|
||||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
const RCTAppState = NativeModules.AppState;
|
||||||
var RCTAppState = NativeModules.AppState;
|
|
||||||
|
|
||||||
var logError = require('logError');
|
const logError = require('logError');
|
||||||
var invariant = require('fbjs/lib/invariant');
|
const invariant = require('fbjs/lib/invariant');
|
||||||
|
|
||||||
var _eventHandlers = {
|
|
||||||
change: new Map(),
|
|
||||||
memoryWarning: new Map(),
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `AppState` can tell you if the app is in the foreground or background,
|
* `AppState` can tell you if the app is in the foreground or background,
|
||||||
|
@ -36,8 +30,9 @@ var _eventHandlers = {
|
||||||
* - `active` - The app is running in the foreground
|
* - `active` - The app is running in the foreground
|
||||||
* - `background` - The app is running in the background. The user is either
|
* - `background` - The app is running in the background. The user is either
|
||||||
* in another app or on the home screen
|
* in another app or on the home screen
|
||||||
* - `inactive` - This is a transition state that currently never happens for
|
* - `inactive` - This is a state that occurs when transitioning between
|
||||||
* typical React Native apps.
|
* foreground & background, and during periods of inactivity such as
|
||||||
|
* entering the Multitasking view or in the event of an incoming call
|
||||||
*
|
*
|
||||||
* For more information, see
|
* For more information, see
|
||||||
* [Apple's documentation](https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html)
|
* [Apple's documentation](https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html)
|
||||||
|
@ -75,13 +70,58 @@ var _eventHandlers = {
|
||||||
* state will happen only momentarily.
|
* state will happen only momentarily.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var AppState = {
|
class AppState extends NativeEventEmitter {
|
||||||
|
|
||||||
/**
|
_eventHandlers: Object;
|
||||||
|
currentState: ?string;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super(RCTAppState);
|
||||||
|
|
||||||
|
this._eventHandlers = {
|
||||||
|
change: new Map(),
|
||||||
|
memoryWarning: new Map(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: getCurrentAppState callback seems to be called at a really late stage
|
||||||
|
// after app launch. Trying to get currentState when mounting App component
|
||||||
|
// will likely to have the initial value here.
|
||||||
|
// Initialize to 'active' instead of null.
|
||||||
|
this.currentState = 'active';
|
||||||
|
|
||||||
|
// TODO: this is a terrible solution - in order to ensure `currentState` prop
|
||||||
|
// is up to date, we have to register an observer that updates it whenever
|
||||||
|
// the state changes, even if nobody cares. We should just deprecate the
|
||||||
|
// `currentState` property and get rid of this.
|
||||||
|
this.addListener(
|
||||||
|
'appStateDidChange',
|
||||||
|
(appStateData) => {
|
||||||
|
this.currentState = appStateData.app_state;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: see above - this request just populates the value of `currentState`
|
||||||
|
// when the module is first initialized. Would be better to get rid of the prop
|
||||||
|
// and expose `getCurrentAppState` method directly.
|
||||||
|
RCTAppState.getCurrentAppState(
|
||||||
|
(appStateData) => {
|
||||||
|
this.currentState = appStateData.app_state;
|
||||||
|
},
|
||||||
|
logError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* Add a handler to AppState changes by listening to the `change` event type
|
* Add a handler to AppState changes by listening to the `change` event type
|
||||||
* and providing the handler
|
* and providing the handler
|
||||||
|
*
|
||||||
|
* TODO: now that AppState is a subclass of NativeEventEmitter, we could deprecate
|
||||||
|
* `addEventListener` and `removeEventListener` and just use `addListener` and
|
||||||
|
* `listener.remove()` directly. That will be a breaking change though, as both
|
||||||
|
* the method and event names are different (addListener events are currently
|
||||||
|
* required to be globally unique).
|
||||||
*/
|
*/
|
||||||
addEventListener: function(
|
addEventListener(
|
||||||
type: string,
|
type: string,
|
||||||
handler: Function
|
handler: Function
|
||||||
) {
|
) {
|
||||||
|
@ -90,24 +130,24 @@ var AppState = {
|
||||||
'Trying to subscribe to unknown event: "%s"', type
|
'Trying to subscribe to unknown event: "%s"', type
|
||||||
);
|
);
|
||||||
if (type === 'change') {
|
if (type === 'change') {
|
||||||
_eventHandlers[type].set(handler, RCTDeviceEventEmitter.addListener(
|
this._eventHandlers[type].set(handler, this.addListener(
|
||||||
'appStateDidChange',
|
'appStateDidChange',
|
||||||
(appStateData) => {
|
(appStateData) => {
|
||||||
handler(appStateData.app_state);
|
handler(appStateData.app_state);
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
} else if (type === 'memoryWarning') {
|
} else if (type === 'memoryWarning') {
|
||||||
_eventHandlers[type].set(handler, RCTDeviceEventEmitter.addListener(
|
this._eventHandlers[type].set(handler, this.addListener(
|
||||||
'memoryWarning',
|
'memoryWarning',
|
||||||
handler
|
handler
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a handler by passing the `change` event type and the handler
|
* Remove a handler by passing the `change` event type and the handler
|
||||||
*/
|
*/
|
||||||
removeEventListener: function(
|
removeEventListener(
|
||||||
type: string,
|
type: string,
|
||||||
handler: Function
|
handler: Function
|
||||||
) {
|
) {
|
||||||
|
@ -115,28 +155,14 @@ var AppState = {
|
||||||
['change', 'memoryWarning'].indexOf(type) !== -1,
|
['change', 'memoryWarning'].indexOf(type) !== -1,
|
||||||
'Trying to remove listener for unknown event: "%s"', type
|
'Trying to remove listener for unknown event: "%s"', type
|
||||||
);
|
);
|
||||||
if (!_eventHandlers[type].has(handler)) {
|
if (!this._eventHandlers[type].has(handler)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_eventHandlers[type].get(handler).remove();
|
this._eventHandlers[type].get(handler).remove();
|
||||||
_eventHandlers[type].delete(handler);
|
this._eventHandlers[type].delete(handler);
|
||||||
},
|
}
|
||||||
|
|
||||||
currentState: ('active' : ?string),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RCTDeviceEventEmitter.addListener(
|
AppState = new AppState();
|
||||||
'appStateDidChange',
|
|
||||||
(appStateData) => {
|
|
||||||
AppState.currentState = appStateData.app_state;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
RCTAppState.getCurrentAppState(
|
|
||||||
(appStateData) => {
|
|
||||||
AppState.currentState = appStateData.app_state;
|
|
||||||
},
|
|
||||||
logError
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = AppState;
|
module.exports = AppState;
|
||||||
|
|
|
@ -11,20 +11,8 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var warning = require('fbjs/lib/warning');
|
const AppState = require('AppState');
|
||||||
|
|
||||||
class AppStateIOS {
|
console.warn('AppStateIOS is deprecated. Use AppState instead');
|
||||||
|
|
||||||
static addEventListener(type, handler) {
|
module.exports = AppState;
|
||||||
warning(false, 'Cannot listen to AppStateIOS events on Android.');
|
|
||||||
}
|
|
||||||
|
|
||||||
static removeEventListener(type, handler) {
|
|
||||||
warning(false, 'Cannot remove AppStateIOS listener on Android.');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AppStateIOS.currentState = null;
|
|
||||||
|
|
||||||
module.exports = AppStateIOS;
|
|
|
@ -1,147 +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 AppStateIOS
|
|
||||||
* @flow
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var NativeModules = require('NativeModules');
|
|
||||||
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
|
||||||
var RCTAppState = NativeModules.AppState;
|
|
||||||
|
|
||||||
var logError = require('logError');
|
|
||||||
var invariant = require('fbjs/lib/invariant');
|
|
||||||
|
|
||||||
var _eventHandlers = {
|
|
||||||
change: new Map(),
|
|
||||||
memoryWarning: new Map(),
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* `AppStateIOS` can tell you if the app is in the foreground or background,
|
|
||||||
* and notify you when the state changes.
|
|
||||||
*
|
|
||||||
* AppStateIOS is frequently used to determine the intent and proper behavior when
|
|
||||||
* handling push notifications.
|
|
||||||
*
|
|
||||||
* ### iOS App States
|
|
||||||
*
|
|
||||||
* - `active` - The app is running in the foreground
|
|
||||||
* - `background` - The app is running in the background. The user is either
|
|
||||||
* in another app or on the home screen
|
|
||||||
* - `inactive` - This is a state that occurs when transitioning between
|
|
||||||
* foreground & background, and during periods of inactivity such as
|
|
||||||
* entering the Multitasking view or in the event of an incoming call
|
|
||||||
*
|
|
||||||
* For more information, see
|
|
||||||
* [Apple's documentation](https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html)
|
|
||||||
*
|
|
||||||
* ### Basic Usage
|
|
||||||
*
|
|
||||||
* To see the current state, you can check `AppStateIOS.currentState`, which
|
|
||||||
* will be kept up-to-date. However, `currentState` will be null at launch
|
|
||||||
* while `AppStateIOS` retrieves it over the bridge.
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* getInitialState: function() {
|
|
||||||
* return {
|
|
||||||
* currentAppState: AppStateIOS.currentState,
|
|
||||||
* };
|
|
||||||
* },
|
|
||||||
* componentDidMount: function() {
|
|
||||||
* AppStateIOS.addEventListener('change', this._handleAppStateChange);
|
|
||||||
* },
|
|
||||||
* componentWillUnmount: function() {
|
|
||||||
* AppStateIOS.removeEventListener('change', this._handleAppStateChange);
|
|
||||||
* },
|
|
||||||
* _handleAppStateChange: function(currentAppState) {
|
|
||||||
* this.setState({ currentAppState, });
|
|
||||||
* },
|
|
||||||
* render: function() {
|
|
||||||
* return (
|
|
||||||
* <Text>Current state is: {this.state.currentAppState}</Text>
|
|
||||||
* );
|
|
||||||
* },
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* This example will only ever appear to say "Current state is: active" because
|
|
||||||
* the app is only visible to the user when in the `active` state, and the null
|
|
||||||
* state will happen only momentarily.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var AppStateIOS = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a handler to AppState changes by listening to the `change` event type
|
|
||||||
* and providing the handler
|
|
||||||
*/
|
|
||||||
addEventListener: function(
|
|
||||||
type: string,
|
|
||||||
handler: Function
|
|
||||||
) {
|
|
||||||
invariant(
|
|
||||||
['change', 'memoryWarning'].indexOf(type) !== -1,
|
|
||||||
'Trying to subscribe to unknown event: "%s"', type
|
|
||||||
);
|
|
||||||
if (type === 'change') {
|
|
||||||
_eventHandlers[type].set(handler, RCTDeviceEventEmitter.addListener(
|
|
||||||
'appStateDidChange',
|
|
||||||
(appStateData) => {
|
|
||||||
handler(appStateData.app_state);
|
|
||||||
}
|
|
||||||
));
|
|
||||||
} else if (type === 'memoryWarning') {
|
|
||||||
_eventHandlers[type].set(handler, RCTDeviceEventEmitter.addListener(
|
|
||||||
'memoryWarning',
|
|
||||||
handler
|
|
||||||
));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a handler by passing the `change` event type and the handler
|
|
||||||
*/
|
|
||||||
removeEventListener: function(
|
|
||||||
type: string,
|
|
||||||
handler: Function
|
|
||||||
) {
|
|
||||||
invariant(
|
|
||||||
['change', 'memoryWarning'].indexOf(type) !== -1,
|
|
||||||
'Trying to remove listener for unknown event: "%s"', type
|
|
||||||
);
|
|
||||||
if (!_eventHandlers[type].has(handler)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_eventHandlers[type].get(handler).remove();
|
|
||||||
_eventHandlers[type].delete(handler);
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: getCurrentAppState callback seems to be called at a really late stage
|
|
||||||
// after app launch. Trying to get currentState when mounting App component
|
|
||||||
// will likely to have the initial value here.
|
|
||||||
// Initialize to 'active' instead of null.
|
|
||||||
currentState: ('active' : ?string),
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
RCTDeviceEventEmitter.addListener(
|
|
||||||
'appStateDidChange',
|
|
||||||
(appStateData) => {
|
|
||||||
AppStateIOS.currentState = appStateData.app_state;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
RCTAppState.getCurrentAppState(
|
|
||||||
(appStateData) => {
|
|
||||||
AppStateIOS.currentState = appStateData.app_state;
|
|
||||||
},
|
|
||||||
logError
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = AppStateIOS;
|
|
|
@ -30,31 +30,35 @@ class RCTDeviceEventEmitter extends EventEmitter {
|
||||||
super(sharedSubscriber);
|
super(sharedSubscriber);
|
||||||
this.sharedSubscriber = sharedSubscriber;
|
this.sharedSubscriber = sharedSubscriber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_nativeEventModule(eventType: ?string) {
|
||||||
|
if (eventType) {
|
||||||
|
if (eventType.lastIndexOf('statusBar', 0) === 0) {
|
||||||
|
console.warn('`%s` event should be registered via the StatusBarIOS module', eventType);
|
||||||
|
return require('StatusBarIOS');
|
||||||
|
}
|
||||||
|
if (eventType.lastIndexOf('keyboard', 0) === 0) {
|
||||||
|
console.warn('`%s` event should be registered via the Keyboard module', eventType);
|
||||||
|
return require('Keyboard');
|
||||||
|
}
|
||||||
|
if (eventType === 'appStateDidChange' || eventType === 'memoryWarning') {
|
||||||
|
console.warn('`%s` event should be registered via the AppState module', eventType);
|
||||||
|
return require('AppState');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
addListener(eventType: string, listener: Function, context: ?Object): EmitterSubscription {
|
addListener(eventType: string, listener: Function, context: ?Object): EmitterSubscription {
|
||||||
if (eventType.lastIndexOf('statusBar', 0) === 0) {
|
const eventModule = this._nativeEventModule(eventType);
|
||||||
console.warn('`%s` event should be registered via the StatusBarIOS module', eventType);
|
return eventModule ? eventModule.addListener(eventType, listener, context)
|
||||||
return require('StatusBarIOS').addListener(eventType, listener, context);
|
: super.addListener(eventType, listener, context);
|
||||||
}
|
|
||||||
if (eventType.lastIndexOf('keyboard', 0) === 0) {
|
|
||||||
console.warn('`%s` event should be registered via the Keyboard module', eventType);
|
|
||||||
return require('Keyboard').addListener(eventType, listener, context);
|
|
||||||
}
|
|
||||||
return super.addListener(eventType, listener, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeAllListeners(eventType: ?string) {
|
removeAllListeners(eventType: ?string) {
|
||||||
if (eventType) {
|
const eventModule = this._nativeEventModule(eventType);
|
||||||
if (eventType.lastIndexOf('statusBar', 0) === 0) {
|
(eventModule && eventType) ? eventModule.removeAllListeners(eventType)
|
||||||
console.warn('statusBar events should be unregistered via the StatusBarIOS module');
|
: super.removeAllListeners(eventType);
|
||||||
return require('StatusBarIOS').removeAllListeners(eventType);
|
|
||||||
}
|
|
||||||
if (eventType.lastIndexOf('keyboard', 0) === 0) {
|
|
||||||
console.warn('keyboard events should be unregistered via the Keyboard module');
|
|
||||||
return require('Keyboard').removeAllListeners(eventType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.removeAllListeners(eventType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeSubscription(subscription: EmitterSubscription) {
|
removeSubscription(subscription: EmitterSubscription) {
|
||||||
|
|
|
@ -279,8 +279,11 @@ RCT_EXPORT_METHOD(getCurrentPosition:(RCTLocationOptions)options
|
||||||
|
|
||||||
// Send event
|
// Send event
|
||||||
if (_observingLocation) {
|
if (_observingLocation) {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"geolocationDidChange"
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"geolocationDidChange"
|
||||||
body:_lastLocationEvent];
|
body:_lastLocationEvent];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire all queued callbacks
|
// Fire all queued callbacks
|
||||||
|
@ -321,8 +324,11 @@ RCT_EXPORT_METHOD(getCurrentPosition:(RCTLocationOptions)options
|
||||||
|
|
||||||
// Send event
|
// Send event
|
||||||
if (_observingLocation) {
|
if (_observingLocation) {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"geolocationError"
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"geolocationError"
|
||||||
body:jsError];
|
body:jsError];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire all queued error callbacks
|
// Fire all queued error callbacks
|
||||||
|
|
|
@ -51,8 +51,11 @@ 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
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
[self->_bridge.eventDispatcher sendDeviceEventWithName:@"networkStatusDidChange"
|
[self->_bridge.eventDispatcher sendDeviceEventWithName:@"networkStatusDidChange"
|
||||||
body:@{@"network_info": status}];
|
body:@{@"network_info": status}];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -346,8 +346,11 @@ RCT_EXPORT_MODULE()
|
||||||
}
|
}
|
||||||
|
|
||||||
NSArray<id> *responseJSON = @[task.requestID, responseText ?: @""];
|
NSArray<id> *responseJSON = @[task.requestID, responseText ?: @""];
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkData"
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkData"
|
||||||
body:responseJSON];
|
body:responseJSON];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)sendRequest:(NSURLRequest *)request
|
- (void)sendRequest:(NSURLRequest *)request
|
||||||
|
@ -361,7 +364,10 @@ 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
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"didSendNetworkData" body:responseJSON];
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"didSendNetworkData" body:responseJSON];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -379,8 +385,11 @@ 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
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkResponse"
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"didReceiveNetworkResponse"
|
||||||
body:responseJSON];
|
body:responseJSON];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -401,8 +410,11 @@ RCT_EXPORT_MODULE()
|
||||||
error.code == kCFURLErrorTimedOut ? @YES : @NO
|
error.code == kCFURLErrorTimedOut ? @YES : @NO
|
||||||
];
|
];
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"didCompleteNetworkResponse"
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"didCompleteNetworkResponse"
|
||||||
body:responseJSON];
|
body:responseJSON];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
[_tasksByRequestID removeObjectForKey:task.requestID];
|
[_tasksByRequestID removeObjectForKey:task.requestID];
|
||||||
});
|
});
|
||||||
|
|
|
@ -52,7 +52,10 @@ RCT_EXPORT_METHOD(verifySnapshot:(RCTResponseSenderBlock)callback)
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(sendAppEvent:(NSString *)name body:(nullable id)body)
|
RCT_EXPORT_METHOD(sendAppEvent:(NSString *)name body:(nullable id)body)
|
||||||
{
|
{
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
[_bridge.eventDispatcher sendAppEventWithName:name body:body];
|
[_bridge.eventDispatcher sendAppEventWithName:name body:body];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_REMAP_METHOD(shouldResolve, shouldResolve_resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
RCT_REMAP_METHOD(shouldResolve, shouldResolve_resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
||||||
|
|
|
@ -62,9 +62,12 @@ RCT_EXPORT_MODULE()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
[_bridge.eventDispatcher
|
[_bridge.eventDispatcher
|
||||||
sendDeviceEventWithName:@"settingsUpdated"
|
sendDeviceEventWithName:@"settingsUpdated"
|
||||||
body:RCTJSONClean([_defaults dictionaryRepresentation])];
|
body:RCTJSONClean([_defaults dictionaryRepresentation])];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
@property (nonatomic, assign) NSInteger mostRecentEventCount;
|
@property (nonatomic, assign) NSInteger mostRecentEventCount;
|
||||||
@property (nonatomic, strong) NSNumber *maxLength;
|
@property (nonatomic, strong) NSNumber *maxLength;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) RCTDirectEventBlock onChange;
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onSelectionChange;
|
@property (nonatomic, copy) RCTDirectEventBlock onSelectionChange;
|
||||||
|
|
||||||
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithEventDispatcher:(RCTEventDispatcher *)eventDispatcher NS_DESIGNATED_INITIALIZER;
|
||||||
|
|
|
@ -472,7 +472,7 @@ static NSAttributedString *removeReactTagFromString(NSAttributedString *string)
|
||||||
[self _setPlaceholderVisibility];
|
[self _setPlaceholderVisibility];
|
||||||
_nativeEventCount++;
|
_nativeEventCount++;
|
||||||
|
|
||||||
if (!self.reactTag) {
|
if (!self.reactTag || !_onChange) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,8 +490,7 @@ static NSAttributedString *removeReactTagFromString(NSAttributedString *string)
|
||||||
}
|
}
|
||||||
_previousTextLength = textLength;
|
_previousTextLength = textLength;
|
||||||
_previousContentHeight = contentHeight;
|
_previousContentHeight = contentHeight;
|
||||||
|
_onChange(@{
|
||||||
NSDictionary *event = @{
|
|
||||||
@"text": self.text,
|
@"text": self.text,
|
||||||
@"contentSize": @{
|
@"contentSize": @{
|
||||||
@"height": @(contentHeight),
|
@"height": @(contentHeight),
|
||||||
|
@ -499,8 +498,7 @@ static NSAttributedString *removeReactTagFromString(NSAttributedString *string)
|
||||||
},
|
},
|
||||||
@"target": self.reactTag,
|
@"target": self.reactTag,
|
||||||
@"eventCount": @(_nativeEventCount),
|
@"eventCount": @(_nativeEventCount),
|
||||||
};
|
});
|
||||||
[_eventDispatcher sendInputEventWithName:@"change" body:event];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)textViewDidEndEditing:(UITextView *)textView
|
- (void)textViewDidEndEditing:(UITextView *)textView
|
||||||
|
|
|
@ -35,7 +35,6 @@ RCT_EXTERN const NSInteger RCTTextUpdateLagWarningThreshold;
|
||||||
RCT_EXTERN NSString *RCTNormalizeInputEventName(NSString *eventName);
|
RCT_EXTERN NSString *RCTNormalizeInputEventName(NSString *eventName);
|
||||||
|
|
||||||
@protocol RCTEvent <NSObject>
|
@protocol RCTEvent <NSObject>
|
||||||
|
|
||||||
@required
|
@required
|
||||||
|
|
||||||
@property (nonatomic, strong, readonly) NSNumber *viewTag;
|
@property (nonatomic, strong, readonly) NSNumber *viewTag;
|
||||||
|
@ -60,25 +59,25 @@ RCT_EXTERN NSString *RCTNormalizeInputEventName(NSString *eventName);
|
||||||
@interface RCTEventDispatcher : NSObject <RCTBridgeModule>
|
@interface RCTEventDispatcher : NSObject <RCTBridgeModule>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send an application-specific event that does not relate to a specific
|
* Deprecated, do not use.
|
||||||
* view, e.g. a navigation or data update notification.
|
|
||||||
*/
|
*/
|
||||||
- (void)sendAppEventWithName:(NSString *)name body:(id)body;
|
- (void)sendAppEventWithName:(NSString *)name body:(id)body
|
||||||
|
__deprecated_msg("Subclass RCTEventEmitter instead");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a device or iOS event that does not relate to a specific view,
|
* Deprecated, do not use.
|
||||||
* e.g.rotation, location, keyboard show/hide, background/awake, etc.
|
|
||||||
*/
|
*/
|
||||||
- (void)sendDeviceEventWithName:(NSString *)name body:(id)body;
|
- (void)sendDeviceEventWithName:(NSString *)name body:(id)body
|
||||||
|
__deprecated_msg("Subclass RCTEventEmitter instead");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a user input event. The body dictionary must contain a "target"
|
* Deprecated, do not use.
|
||||||
* parameter, representing the React tag of the view sending the event
|
|
||||||
*/
|
*/
|
||||||
- (void)sendInputEventWithName:(NSString *)name body:(NSDictionary *)body;
|
- (void)sendInputEventWithName:(NSString *)name body:(NSDictionary *)body
|
||||||
|
__deprecated_msg("Use RCTDirectEventBlock or RCTBubblingEventBlock instead");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a text input/focus event.
|
* Send a text input/focus event. For internal use only.
|
||||||
*/
|
*/
|
||||||
- (void)sendTextEventWithType:(RCTTextEventType)type
|
- (void)sendTextEventWithType:(RCTTextEventType)type
|
||||||
reactTag:(NSNumber *)reactTag
|
reactTag:(NSNumber *)reactTag
|
||||||
|
|
|
@ -126,7 +126,10 @@ RCT_EXPORT_MODULE()
|
||||||
body[@"key"] = key;
|
body[@"key"] = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
[self sendInputEventWithName:events[type] body:body];
|
[self sendInputEventWithName:events[type] body:body];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)sendEvent:(id<RCTEvent>)event
|
- (void)sendEvent:(id<RCTEvent>)event
|
||||||
|
|
|
@ -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 RCTAppState : NSObject<RCTBridgeModule>
|
@interface RCTAppState : RCTEventEmitter
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
static NSString *RCTCurrentAppBackgroundState()
|
static NSString *RCTCurrentAppBackgroundState()
|
||||||
{
|
{
|
||||||
|
RCTAssertMainThread();
|
||||||
|
|
||||||
static NSDictionary *states;
|
static NSDictionary *states;
|
||||||
static dispatch_once_t onceToken;
|
static dispatch_once_t onceToken;
|
||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
|
@ -37,26 +39,22 @@ static NSString *RCTCurrentAppBackgroundState()
|
||||||
NSString *_lastKnownState;
|
NSString *_lastKnownState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@synthesize bridge = _bridge;
|
|
||||||
|
|
||||||
RCT_EXPORT_MODULE()
|
RCT_EXPORT_MODULE()
|
||||||
|
|
||||||
|
- (dispatch_queue_t)methodQueue
|
||||||
|
{
|
||||||
|
return dispatch_get_main_queue();
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Lifecycle
|
#pragma mark - Lifecycle
|
||||||
|
|
||||||
- (instancetype)init
|
- (NSArray<NSString *> *)supportedEvents
|
||||||
{
|
{
|
||||||
if ((self = [super init])) {
|
return @[@"appStateDidChange", @"memoryWarning"];
|
||||||
|
|
||||||
// Needs to be called on the main thread, as it accesses UIApplication
|
|
||||||
_lastKnownState = RCTCurrentAppBackgroundState();
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setBridge:(RCTBridge *)bridge
|
- (void)startObserving
|
||||||
{
|
{
|
||||||
_bridge = bridge;
|
|
||||||
|
|
||||||
for (NSString *name in @[UIApplicationDidBecomeActiveNotification,
|
for (NSString *name in @[UIApplicationDidBecomeActiveNotification,
|
||||||
UIApplicationDidEnterBackgroundNotification,
|
UIApplicationDidEnterBackgroundNotification,
|
||||||
UIApplicationDidFinishLaunchingNotification,
|
UIApplicationDidFinishLaunchingNotification,
|
||||||
|
@ -75,19 +73,18 @@ RCT_EXPORT_MODULE()
|
||||||
object:nil];
|
object:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)handleMemoryWarning
|
- (void)stopObserving
|
||||||
{
|
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"memoryWarning"
|
|
||||||
body:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc
|
|
||||||
{
|
{
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - App Notification Methods
|
#pragma mark - App Notification Methods
|
||||||
|
|
||||||
|
- (void)handleMemoryWarning
|
||||||
|
{
|
||||||
|
[self sendEventWithName:@"memoryWarning" body:nil];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)handleAppStateDidChange:(NSNotification *)notification
|
- (void)handleAppStateDidChange:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
NSString *newState;
|
NSString *newState;
|
||||||
|
@ -102,8 +99,8 @@ RCT_EXPORT_MODULE()
|
||||||
|
|
||||||
if (![newState isEqualToString:_lastKnownState]) {
|
if (![newState isEqualToString:_lastKnownState]) {
|
||||||
_lastKnownState = newState;
|
_lastKnownState = newState;
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"appStateDidChange"
|
[self sendEventWithName:@"appStateDidChange"
|
||||||
body:@{@"app_state": _lastKnownState}];
|
body:@{@"app_state": _lastKnownState}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +112,7 @@ RCT_EXPORT_MODULE()
|
||||||
RCT_EXPORT_METHOD(getCurrentAppState:(RCTResponseSenderBlock)callback
|
RCT_EXPORT_METHOD(getCurrentAppState:(RCTResponseSenderBlock)callback
|
||||||
error:(__unused RCTResponseSenderBlock)error)
|
error:(__unused RCTResponseSenderBlock)error)
|
||||||
{
|
{
|
||||||
callback(@[@{@"app_state": _lastKnownState}]);
|
callback(@[@{@"app_state": RCTCurrentAppBackgroundState()}]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#import "RCTEventEmitter.h"
|
#import "RCTEventEmitter.h"
|
||||||
#import "RCTAssert.h"
|
#import "RCTAssert.h"
|
||||||
|
#import "RCTUtils.h"
|
||||||
#import "RCTLog.h"
|
#import "RCTLog.h"
|
||||||
|
|
||||||
@implementation RCTEventEmitter
|
@implementation RCTEventEmitter
|
||||||
|
@ -21,9 +22,16 @@
|
||||||
return @"";
|
return @"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
if (self != [RCTEventEmitter class]) {
|
||||||
|
RCTAssert(RCTClassOverridesInstanceMethod(self, @selector(supportedEvents)),
|
||||||
|
@"You must override the `supportedEvents` method of %@", self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray<NSString *> *)supportedEvents
|
- (NSArray<NSString *> *)supportedEvents
|
||||||
{
|
{
|
||||||
RCTAssert(NO, @"You must override the `supportedEvents` method of %@", [self class]);
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +40,8 @@
|
||||||
RCTAssert(_bridge != nil, @"bridge is not set.");
|
RCTAssert(_bridge != nil, @"bridge is not set.");
|
||||||
|
|
||||||
if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
|
if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
|
||||||
RCTLogError(@"`%@` is not a supported event type for %@", eventName, [self class]);
|
RCTLogError(@"`%@` is not a supported event type for %@. Supported events are: `%@`",
|
||||||
|
eventName, [self class], [[self supportedEvents] componentsJoinedByString:@"`, `"]);
|
||||||
}
|
}
|
||||||
if (_listenerCount > 0) {
|
if (_listenerCount > 0) {
|
||||||
[_bridge enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
[_bridge enqueueJSCall:@"RCTDeviceEventEmitter.emit"
|
||||||
|
@ -62,7 +71,8 @@
|
||||||
RCT_EXPORT_METHOD(addListener:(NSString *)eventName)
|
RCT_EXPORT_METHOD(addListener:(NSString *)eventName)
|
||||||
{
|
{
|
||||||
if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
|
if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
|
||||||
RCTLogError(@"`%@` is not a supported event type for %@", eventName, [self class]);
|
RCTLogError(@"`%@` is not a supported event type for %@. Supported events are: `%@`",
|
||||||
|
eventName, [self class], [[self supportedEvents] componentsJoinedByString:@"`, `"]);
|
||||||
}
|
}
|
||||||
if (_listenerCount == 0) {
|
if (_listenerCount == 0) {
|
||||||
[self startObserving];
|
[self startObserving];
|
||||||
|
|
|
@ -180,7 +180,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||||
((void (*)(id, SEL, id))objc_msgSend)(target, setter, [RCTConvert BOOL:json] ? ^(NSDictionary *body) {
|
((void (*)(id, SEL, id))objc_msgSend)(target, setter, [RCTConvert BOOL:json] ? ^(NSDictionary *body) {
|
||||||
body = [NSMutableDictionary dictionaryWithDictionary:body];
|
body = [NSMutableDictionary dictionaryWithDictionary:body];
|
||||||
((NSMutableDictionary *)body)[@"target"] = weakTarget.reactTag;
|
((NSMutableDictionary *)body)[@"target"] = weakTarget.reactTag;
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
[weakManager.bridge.eventDispatcher sendInputEventWithName:RCTNormalizeInputEventName(name) body:body];
|
[weakManager.bridge.eventDispatcher sendInputEventWithName:RCTNormalizeInputEventName(name) body:body];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
} : nil);
|
} : nil);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue