diff --git a/react/features/app/components/App.native.js b/react/features/app/components/App.native.js index 3447b3578..43cbf6017 100644 --- a/react/features/app/components/App.native.js +++ b/react/features/app/components/App.native.js @@ -2,9 +2,9 @@ import { Linking } from 'react-native'; -import { Platform } from '../../base/react'; import '../../audio-mode'; import '../../background'; +import { Platform } from '../../base/react'; import '../../full-screen'; import '../../wake-lock'; diff --git a/react/features/background/actionTypes.js b/react/features/background/actionTypes.js index b0abe9458..f126ace50 100644 --- a/react/features/background/actionTypes.js +++ b/react/features/background/actionTypes.js @@ -1,38 +1,36 @@ import { Symbol } from '../base/react'; /** - * Action to set the AppState API change event listener. + * The type of redux action to set the AppState API change event listener. * * { * type: _SET_APP_STATE_LISTENER, * listener: Function * } * - * @private + * @protected */ export const _SET_APP_STATE_LISTENER = Symbol('_SET_APP_STATE_LISTENER'); /** - * Action to signal video will be muted because the app is going to the - * background. + * The type of redux action which signals that video will be muted because the + * app is going to the background. * * { * type: _SET_BACKGROUND_VIDEO_MUTED, * muted: boolean * } * - * @private + * @protected */ export const _SET_BACKGROUND_VIDEO_MUTED = Symbol('_SET_BACKGROUND_VIDEO_MUTED'); /** - * Action which signals that the App state has changed (in terms - * of execution mode). - * - * The application state can be one of 'active', 'inactive' or 'background', - * see: https://facebook.github.io/react-native/docs/appstate.html + * The type of redux action which signals that the app state has changed (in + * terms of execution mode). The app state can be one of 'active', 'inactive', + * or 'background'. * * { * type: APP_STATE_CHANGED, @@ -40,5 +38,6 @@ export const _SET_BACKGROUND_VIDEO_MUTED * } * * @public + * @see {@link https://facebook.github.io/react-native/docs/appstate.html} */ export const APP_STATE_CHANGED = Symbol('APP_STATE_CHANGED'); diff --git a/react/features/background/actions.js b/react/features/background/actions.js index 1fc07422a..92fbffed1 100644 --- a/react/features/background/actions.js +++ b/react/features/background/actions.js @@ -1,22 +1,24 @@ +import { setVideoMuted } from '../base/media'; + import { _SET_APP_STATE_LISTENER, _SET_BACKGROUND_VIDEO_MUTED, APP_STATE_CHANGED } from './actionTypes'; -import { setVideoMuted } from '../base/media'; - +import './middleware'; +import './reducer'; /** - * Signals that the App state has changed (in terms of execution mode). The + * Signals that the App state has changed (in terms of execution state). The * application can be in 3 states: 'active', 'inactive' and 'background'. * - * @see https://facebook.github.io/react-native/docs/appstate.html - * - * @param {string} appState - The new App state. + * @param {string} appState - The new App state. + * @public * @returns {{ * type: APP_STATE_CHANGED, * appState: string * }} + * @see {@link https://facebook.github.io/react-native/docs/appstate.html} */ export function appStateChanged(appState: string) { return { @@ -25,20 +27,34 @@ export function appStateChanged(appState: string) { }; } +/** + * Sets the listener to be used with React Native's AppState API. + * + * @param {Function} listener - Function to be set as the change event listener. + * @protected + * @returns {{ + * type: _SET_APP_STATE_LISTENER, + * listener: Function + * }} + */ +export function _setAppStateListener(listener: ?Function) { + return { + type: _SET_APP_STATE_LISTENER, + listener + }; +} /** - * Signals that the app should mute video because it's now running in - * the background, or unmute it, if it came back from the background. + * Signals that the app should mute video because it's now running in the + * background, or unmute it because it came back from the background. If video + * was already muted nothing will happen; otherwise, it will be muted. When + * coming back from the background the previous state will be restored. * - * If video was already muted nothing will happen, otherwise it will be - * muted. When coming back from the background the previous state will - * be restored. - * - * @param {boolean} muted - Set to true if video should be muted, false - * otherwise. + * @param {boolean} muted - True if video should be muted; false, otherwise. + * @protected * @returns {Function} */ -export function setBackgroundVideoMuted(muted: boolean) { +export function _setBackgroundVideoMuted(muted: boolean) { return (dispatch, getState) => { if (muted) { const mediaState = getState()['features/base/media']; @@ -56,46 +72,12 @@ export function setBackgroundVideoMuted(muted: boolean) { } } - dispatch(_setBackgroundVideoMuted(muted)); + // Remember that video was muted due to the app going to the background + // vs user's choice. + dispatch({ + type: _SET_BACKGROUND_VIDEO_MUTED, + muted + }); dispatch(setVideoMuted(muted)); }; } - - -/** - * Internal action which sets the listener to be used with React Native's - * AppState API. - * - * @param {Function} listener - Function to be set as the change event - * listener. - * @returns {{ - * type: _SET_APP_STATE_LISTENER, - * listener: Function - * }} - */ -export function _setAppStateListener(listener: ?Function) { - return { - type: _SET_APP_STATE_LISTENER, - listener - }; -} - - -/** - * Internal action which signals that video is going to be muted because the - * application is going to the background. This action is used to remember if - * video was muted due to the app going to the background vs user's choice. - * - * @param {type} muted - Set to true if video will be muted, false otherwise. - * @private - * @returns {{ - * type: _SET_BACKGROUND_VIDEO_MUTED, - * muted: boolean - * }} - */ -function _setBackgroundVideoMuted(muted: boolean) { - return { - type: _SET_BACKGROUND_VIDEO_MUTED, - muted - }; -} diff --git a/react/features/background/index.js b/react/features/background/index.js index 4cdf36b5e..e40f04336 100644 --- a/react/features/background/index.js +++ b/react/features/background/index.js @@ -1,3 +1,2 @@ +export * from './actions'; export * from './actionTypes'; -import './middleware'; -import './reducer'; diff --git a/react/features/background/middleware.js b/react/features/background/middleware.js index debdbd09a..2a1735fc2 100644 --- a/react/features/background/middleware.js +++ b/react/features/background/middleware.js @@ -3,56 +3,59 @@ import { AppState } from 'react-native'; import type { Dispatch } from 'redux'; -import { - _setAppStateListener, - appStateChanged, - setBackgroundVideoMuted -} from './actions'; -import { - _SET_APP_STATE_LISTENER, - APP_STATE_CHANGED -} from './actionTypes'; - import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app'; import { MiddlewareRegistry } from '../base/redux'; +import { + _setAppStateListener, + _setBackgroundVideoMuted, + appStateChanged +} from './actions'; +import { + _SET_APP_STATE_LISTENER, + APP_STATE_CHANGED +} from './actionTypes'; /** * Middleware that captures App lifetime actions and subscribes to application * state changes. When the application state changes it will fire the action - * requred to mute or unmute the local video in case the application goes to - * the backgound or comes back from it. + * required to mute or unmute the local video in case the application goes to + * the background or comes back from it. * - * @see https://facebook.github.io/react-native/docs/appstate.html * @param {Store} store - Redux store. * @returns {Function} + * @see {@link https://facebook.github.io/react-native/docs/appstate.html} */ MiddlewareRegistry.register(store => next => action => { switch (action.type) { case _SET_APP_STATE_LISTENER: { + // Remove the current/old AppState listener. const { appStateListener } = store.getState()['features/background']; if (appStateListener) { AppState.removeEventListener('change', appStateListener); } + + // Add the new AppState listener. if (action.listener) { AppState.addEventListener('change', action.listener); } break; } - case APP_STATE_CHANGED: - _handleAppStateChange(store.dispatch, action.appState); - break; - case APP_WILL_MOUNT: { - const listener - = __onAppStateChanged.bind(undefined, store.dispatch); - store.dispatch(_setAppStateListener(listener)); + case APP_STATE_CHANGED: + _appStateChanged(store.dispatch, action.appState); break; - } + + case APP_WILL_MOUNT: + store.dispatch( + _setAppStateListener( + _onAppStateChange.bind(undefined, store.dispatch))); + break; + case APP_WILL_UNMOUNT: store.dispatch(_setAppStateListener(null)); break; @@ -61,36 +64,46 @@ MiddlewareRegistry.register(store => next => action => { return next(action); }); - /** - * Handler for app state changes. If will fire the necessary actions for - * local video to be muted when the app goes to the background, and to - * unmute it when it comes back. + * Handles app state changes. Dispatches the necessary Redux actions for the + * local video to be muted when the app goes to the background, and to be + * unmuted when the app comes back. * - * @param {Dispatch} dispatch - Redux dispatch function. - * @param {string} appState - Current app state. + * @param {Dispatch} dispatch - Redux dispatch function. + * @param {string} appState - The current app state. * @private * @returns {void} */ -function _handleAppStateChange(dispatch: Dispatch<*>, appState: string) { - // XXX: we purposely don't handle the 'inactive' state. - if (appState === 'background') { - dispatch(setBackgroundVideoMuted(true)); - } else if (appState === 'active') { - dispatch(setBackgroundVideoMuted(false)); +function _appStateChanged(dispatch: Dispatch<*>, appState: string) { + let muted; + + switch (appState) { + case 'active': + muted = false; + break; + + case 'background': + muted = true; + break; + + case 'inactive': + default: + // XXX: We purposely don't handle the 'inactive' app state. + return; } + + dispatch(_setBackgroundVideoMuted(muted)); } - /** - * Handler called by React's AppState API indicating that the application state - * has changed. + * Called by React Native's AppState API to notify that the application state + * has changed. Dispatches the change within the (associated) Redux store. * - * @param {Dispatch} dispatch - Redux dispatch function. - * @param {string} appState - The current application execution state. + * @param {Dispatch} dispatch - Redux dispatch function. + * @param {string} appState - The current application execution state. * @private * @returns {void} */ -function __onAppStateChanged(dispatch: Dispatch<*>, appState: string) { +function _onAppStateChange(dispatch: Dispatch<*>, appState: string) { dispatch(appStateChanged(appState)); } diff --git a/react/features/background/reducer.js b/react/features/background/reducer.js index feacad531..c99ce87fc 100644 --- a/react/features/background/reducer.js +++ b/react/features/background/reducer.js @@ -1,10 +1,10 @@ +import { ReducerRegistry } from '../base/redux'; + import { _SET_APP_STATE_LISTENER, _SET_BACKGROUND_VIDEO_MUTED, APP_STATE_CHANGED } from './actionTypes'; -import { ReducerRegistry } from '../base/redux'; - ReducerRegistry.register('features/background', (state = {}, action) => { switch (action.type) {