2015-03-12 19:51:44 +00:00
|
|
|
/**
|
2015-03-23 22:07:33 +00:00
|
|
|
* 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.
|
2015-03-12 19:51:44 +00:00
|
|
|
*
|
|
|
|
* @providesModule AppStateIOS
|
2015-03-25 02:34:12 +00:00
|
|
|
* @flow
|
2015-03-12 19:51:44 +00:00
|
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
|
2015-05-26 22:06:20 +00:00
|
|
|
var Map = require('Map');
|
2015-03-12 19:51:44 +00:00
|
|
|
var NativeModules = require('NativeModules');
|
|
|
|
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
2015-03-18 22:57:49 +00:00
|
|
|
var RCTAppState = NativeModules.AppState;
|
2015-03-12 19:51:44 +00:00
|
|
|
|
|
|
|
var logError = require('logError');
|
2015-05-22 19:57:08 +00:00
|
|
|
var invariant = require('invariant');
|
2015-03-12 19:51:44 +00:00
|
|
|
|
2015-05-22 19:57:08 +00:00
|
|
|
var _eventHandlers = {
|
|
|
|
change: new Map(),
|
|
|
|
memoryWarning: new Map(),
|
|
|
|
};
|
2015-03-12 19:51:44 +00:00
|
|
|
|
2015-03-26 01:19:28 +00:00
|
|
|
/**
|
|
|
|
* `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 transition state that currently never happens for
|
|
|
|
* typical React Native apps.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2015-03-12 19:51:44 +00:00
|
|
|
|
2015-03-26 01:19:28 +00:00
|
|
|
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
|
|
|
|
) {
|
2015-05-22 19:57:08 +00:00
|
|
|
invariant(
|
|
|
|
['change', 'memoryWarning'].indexOf(type) !== -1,
|
|
|
|
'Trying to subscribe to unknown event: "%s"', type
|
2015-03-12 19:51:44 +00:00
|
|
|
);
|
2015-05-22 19:57:08 +00:00
|
|
|
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
|
|
|
|
));
|
|
|
|
}
|
2015-03-26 01:19:28 +00:00
|
|
|
},
|
2015-03-12 19:51:44 +00:00
|
|
|
|
2015-03-26 01:19:28 +00:00
|
|
|
/**
|
|
|
|
* Remove a handler by passing the `change` event type and the handler
|
|
|
|
*/
|
|
|
|
removeEventListener: function(
|
|
|
|
type: string,
|
|
|
|
handler: Function
|
|
|
|
) {
|
2015-05-22 19:57:08 +00:00
|
|
|
invariant(
|
|
|
|
['change', 'memoryWarning'].indexOf(type) !== -1,
|
|
|
|
'Trying to remove listener for unknown event: "%s"', type
|
|
|
|
);
|
|
|
|
if (!_eventHandlers[type].has(handler)) {
|
2015-03-12 19:51:44 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-05-22 19:57:08 +00:00
|
|
|
_eventHandlers[type].get(handler).remove();
|
|
|
|
_eventHandlers[type].delete(handler);
|
2015-03-26 01:19:28 +00:00
|
|
|
},
|
2015-03-12 19:51:44 +00:00
|
|
|
|
2015-09-25 20:22:25 +00:00
|
|
|
// 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),
|
2015-03-12 19:51:44 +00:00
|
|
|
|
2015-03-26 01:19:28 +00:00
|
|
|
};
|
2015-03-12 19:51:44 +00:00
|
|
|
|
|
|
|
RCTDeviceEventEmitter.addListener(
|
2015-05-22 19:57:08 +00:00
|
|
|
'appStateDidChange',
|
2015-03-12 19:51:44 +00:00
|
|
|
(appStateData) => {
|
|
|
|
AppStateIOS.currentState = appStateData.app_state;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2015-03-17 20:42:44 +00:00
|
|
|
RCTAppState.getCurrentAppState(
|
2015-03-12 19:51:44 +00:00
|
|
|
(appStateData) => {
|
|
|
|
AppStateIOS.currentState = appStateData.app_state;
|
|
|
|
},
|
|
|
|
logError
|
|
|
|
);
|
|
|
|
|
|
|
|
module.exports = AppStateIOS;
|