mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-01-12 22:50:10 +08:00
Summary: This is the next step in moving RN towards standard path-based requires. All the requires in `Libraries` have been rewritten to use relative requires with a few exceptions, namely, `vendor` and `Renderer/oss` since those need to be changed upstream. This commit uses relative requires instead of `react-native/...` so that if Facebook were to stop syncing out certain folders and therefore remove code from the react-native package, internal code at Facebook would not need to change. See the umbrella issue at https://github.com/facebook/react-native/issues/24316 for more detail. [General] [Changed] - Migrate "Libraries" from Haste to standard path-based requires Pull Request resolved: https://github.com/facebook/react-native/pull/24749 Differential Revision: D15258017 Pulled By: cpojer fbshipit-source-id: a1f480ea36c05c659b6f37c8f02f6f9216d5a323
162 lines
4.8 KiB
JavaScript
162 lines
4.8 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
* @flow
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const EventEmitter = require('../vendor/emitter/EventEmitter');
|
|
const NativeEventEmitter = require('../EventEmitter/NativeEventEmitter');
|
|
const NativeModules = require('../BatchedBridge/NativeModules');
|
|
const RCTAppState = NativeModules.AppState;
|
|
|
|
const logError = require('../Utilities/logError');
|
|
const invariant = require('invariant');
|
|
|
|
/**
|
|
* `AppState` can tell you if the app is in the foreground or background,
|
|
* and notify you when the state changes.
|
|
*
|
|
* See http://facebook.github.io/react-native/docs/appstate.html
|
|
*/
|
|
class AppState extends NativeEventEmitter {
|
|
_eventHandlers: Object;
|
|
currentState: ?string;
|
|
isAvailable: boolean;
|
|
|
|
constructor() {
|
|
super(RCTAppState);
|
|
|
|
this.isAvailable = true;
|
|
this._eventHandlers = {
|
|
change: new Map(),
|
|
memoryWarning: new Map(),
|
|
};
|
|
|
|
this.currentState = RCTAppState.initialAppState;
|
|
|
|
let eventUpdated = false;
|
|
|
|
// 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 => {
|
|
eventUpdated = true;
|
|
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 => {
|
|
// It's possible that the state will have changed here & listeners need to be notified
|
|
if (!eventUpdated && this.currentState !== appStateData.app_state) {
|
|
this.currentState = appStateData.app_state;
|
|
this.emit('appStateDidChange', appStateData);
|
|
}
|
|
}, logError);
|
|
}
|
|
|
|
// 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).
|
|
/**
|
|
* Add a handler to AppState changes by listening to the `change` event type
|
|
* and providing the handler.
|
|
*
|
|
* See http://facebook.github.io/react-native/docs/appstate.html#addeventlistener
|
|
*/
|
|
addEventListener(type: string, handler: Function) {
|
|
invariant(
|
|
['change', 'memoryWarning'].indexOf(type) !== -1,
|
|
'Trying to subscribe to unknown event: "%s"',
|
|
type,
|
|
);
|
|
if (type === 'change') {
|
|
this._eventHandlers[type].set(
|
|
handler,
|
|
this.addListener('appStateDidChange', appStateData => {
|
|
handler(appStateData.app_state);
|
|
}),
|
|
);
|
|
} else if (type === 'memoryWarning') {
|
|
this._eventHandlers[type].set(
|
|
handler,
|
|
this.addListener('memoryWarning', handler),
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove a handler by passing the `change` event type and the handler.
|
|
*
|
|
* See http://facebook.github.io/react-native/docs/appstate.html#removeeventlistener
|
|
*/
|
|
removeEventListener(type: string, handler: Function) {
|
|
invariant(
|
|
['change', 'memoryWarning'].indexOf(type) !== -1,
|
|
'Trying to remove listener for unknown event: "%s"',
|
|
type,
|
|
);
|
|
if (!this._eventHandlers[type].has(handler)) {
|
|
return;
|
|
}
|
|
this._eventHandlers[type].get(handler).remove();
|
|
this._eventHandlers[type].delete(handler);
|
|
}
|
|
}
|
|
|
|
function throwMissingNativeModule() {
|
|
invariant(
|
|
false,
|
|
'Cannot use AppState module when native RCTAppState is not included in the build.\n' +
|
|
'Either include it, or check AppState.isAvailable before calling any methods.',
|
|
);
|
|
}
|
|
|
|
class MissingNativeAppStateShim extends EventEmitter {
|
|
// AppState
|
|
isAvailable: boolean = false;
|
|
currentState: ?string = null;
|
|
|
|
addEventListener() {
|
|
throwMissingNativeModule();
|
|
}
|
|
|
|
removeEventListener() {
|
|
throwMissingNativeModule();
|
|
}
|
|
|
|
// EventEmitter
|
|
addListener() {
|
|
throwMissingNativeModule();
|
|
}
|
|
|
|
removeAllListeners() {
|
|
throwMissingNativeModule();
|
|
}
|
|
|
|
removeSubscription() {
|
|
throwMissingNativeModule();
|
|
}
|
|
}
|
|
|
|
// This module depends on the native `RCTAppState` module. If you don't include it,
|
|
// `AppState.isAvailable` will return `false`, and any method calls will throw.
|
|
// We reassign the class variable to keep the autodoc generator happy.
|
|
if (RCTAppState) {
|
|
AppState = new AppState();
|
|
} else {
|
|
AppState = new MissingNativeAppStateShim();
|
|
}
|
|
|
|
module.exports = AppState;
|