/** * Copyright (c) Nicolas Gallagher. * 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. * * @noflow */ import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment'; import findIndex from 'array-find-index'; import invariant from 'fbjs/lib/invariant'; // Android 4.4 browser const isPrefixed = canUseDOM && !document.hasOwnProperty('hidden') && document.hasOwnProperty('webkitHidden'); const EVENT_TYPES = ['change', 'memoryWarning']; const VISIBILITY_CHANGE_EVENT = isPrefixed ? 'webkitvisibilitychange' : 'visibilitychange'; const VISIBILITY_STATE_PROPERTY = isPrefixed ? 'webkitVisibilityState' : 'visibilityState'; const AppStates = { BACKGROUND: 'background', ACTIVE: 'active' }; const listeners = []; export default class AppState { static isAvailable = canUseDOM && document[VISIBILITY_STATE_PROPERTY]; static get currentState() { if (!AppState.isAvailable) { return AppStates.ACTIVE; } switch (document[VISIBILITY_STATE_PROPERTY]) { case 'hidden': case 'prerender': case 'unloaded': return AppStates.BACKGROUND; default: return AppStates.ACTIVE; } } static addEventListener(type: string, handler: Function) { if (AppState.isAvailable) { invariant( EVENT_TYPES.indexOf(type) !== -1, 'Trying to subscribe to unknown event: "%s"', type ); if (type === 'change') { const callback = () => handler(AppState.currentState); listeners.push([handler, callback]); document.addEventListener(VISIBILITY_CHANGE_EVENT, callback, false); } } } static removeEventListener(type: string, handler: Function) { if (AppState.isAvailable) { invariant( EVENT_TYPES.indexOf(type) !== -1, 'Trying to remove listener for unknown event: "%s"', type ); if (type === 'change') { const listenerIndex = findIndex(listeners, pair => pair[0] === handler); invariant( listenerIndex !== -1, 'Trying to remove AppState listener for unregistered handler' ); const callback = listeners[listenerIndex][1]; document.removeEventListener(VISIBILITY_CHANGE_EVENT, callback, false); listeners.splice(listenerIndex, 1); } } } }