[RN] Make full-screen more resilient on Android (Coding style: consistency)
This commit is contained in:
parent
4757c1ebca
commit
e2cf7a788d
|
@ -416,20 +416,20 @@ public class JitsiMeetView extends FrameLayout {
|
|||
}
|
||||
|
||||
/**
|
||||
* Handler for focus changes which the window where this view is attached to
|
||||
* is experiencing. Here we call into the Immersive mode plugin, so it
|
||||
* triggers an event.
|
||||
* Called when the window containing this view gains or loses focus.
|
||||
*
|
||||
* @param hasFocus - Whether the window / view has focus or not.
|
||||
* @param hasFocus If the window of this view now has focus, {@code true};
|
||||
* otherwise, {@code false}.
|
||||
*/
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
|
||||
RNImmersiveModule module = RNImmersiveModule.getInstance();
|
||||
// https://github.com/mockingbot/react-native-immersive#restore-immersive-state
|
||||
RNImmersiveModule immersive = RNImmersiveModule.getInstance();
|
||||
|
||||
if (hasFocus && module != null) {
|
||||
module.emitImmersiveStateChangeEvent();
|
||||
if (hasFocus && immersive != null) {
|
||||
immersive.emitImmersiveStateChangeEvent();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import { equals, set, ReducerRegistry } from '../redux';
|
|||
import { SET_CALLEE_INFO_VISIBLE, SET_JWT } from './actionTypes';
|
||||
|
||||
/**
|
||||
* The initial redux state of the feature jwt.
|
||||
* The default/initial redux state of the feature jwt.
|
||||
*
|
||||
* @private
|
||||
* @type {{
|
||||
|
@ -13,7 +13,7 @@ import { SET_CALLEE_INFO_VISIBLE, SET_JWT } from './actionTypes';
|
|||
* isGuest: boolean
|
||||
* }}
|
||||
*/
|
||||
const _INITIAL_STATE = {
|
||||
const DEFAULT_STATE = {
|
||||
/**
|
||||
* The indicator which determines whether (the) {@code CalleeInfo} is
|
||||
* visible.
|
||||
|
@ -42,7 +42,7 @@ const _INITIAL_STATE = {
|
|||
*/
|
||||
ReducerRegistry.register(
|
||||
'features/base/jwt',
|
||||
(state = _INITIAL_STATE, action) => {
|
||||
(state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case SET_CALLEE_INFO_VISIBLE:
|
||||
return set(state, 'calleeInfoVisible', action.calleeInfoVisible);
|
||||
|
@ -51,7 +51,7 @@ ReducerRegistry.register(
|
|||
// eslint-disable-next-line no-unused-vars
|
||||
const { type, ...payload } = action;
|
||||
const nextState = {
|
||||
..._INITIAL_STATE,
|
||||
...DEFAULT_STATE,
|
||||
...payload
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import { ReducerRegistry } from '../redux';
|
||||
|
||||
import {
|
||||
|
@ -8,18 +10,18 @@ import {
|
|||
} from './actionTypes';
|
||||
|
||||
/**
|
||||
* The initial state of the feature base/lib-jitsi-meet.
|
||||
* The default/initial redux state of the feature base/lib-jitsi-meet.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
const INITIAL_STATE = {};
|
||||
const DEFAULT_STATE = {};
|
||||
|
||||
ReducerRegistry.register(
|
||||
'features/base/lib-jitsi-meet',
|
||||
(state = INITIAL_STATE, action) => {
|
||||
(state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case LIB_DID_DISPOSE:
|
||||
return INITIAL_STATE;
|
||||
return DEFAULT_STATE;
|
||||
|
||||
case LIB_DID_INIT:
|
||||
return {
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
// @flow
|
||||
|
||||
import { equals, ReducerRegistry } from '../redux';
|
||||
|
||||
import { SET_LOGGING_CONFIG } from './actionTypes';
|
||||
|
||||
/**
|
||||
* The initial state of the feature base/logging.
|
||||
* The default/initial redux state of the feature base/logging.
|
||||
*
|
||||
* XXX When making any changes to the INITIAL_STATE make sure to also update
|
||||
* XXX When making any changes to the DEFAULT_STATE make sure to also update
|
||||
* logging_config.js file located in the root directory of this project !!!
|
||||
*
|
||||
* @type {{
|
||||
* config: Object
|
||||
* }}
|
||||
*/
|
||||
const INITIAL_STATE = {
|
||||
const DEFAULT_STATE = {
|
||||
config: {
|
||||
defaultLogLevel: 'trace',
|
||||
|
||||
|
@ -26,7 +28,7 @@ const INITIAL_STATE = {
|
|||
|
||||
ReducerRegistry.register(
|
||||
'features/base/logging',
|
||||
(state = INITIAL_STATE, action) => {
|
||||
(state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case SET_LOGGING_CONFIG:
|
||||
return _setLoggingConfig(state, action);
|
||||
|
@ -48,9 +50,9 @@ ReducerRegistry.register(
|
|||
*/
|
||||
function _setLoggingConfig(state, action) {
|
||||
const config = {
|
||||
// The config of INITIAL_STATE is the default configuration of the
|
||||
// The config of DEFAULT_STATE is the default configuration of the
|
||||
// feature base/logging.
|
||||
...INITIAL_STATE.config,
|
||||
...DEFAULT_STATE.config,
|
||||
...action.config
|
||||
};
|
||||
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
// @flow
|
||||
|
||||
import { ReducerRegistry, set } from '../redux';
|
||||
|
||||
import { SET_ASPECT_RATIO, SET_REDUCED_UI } from './actionTypes';
|
||||
import { ASPECT_RATIO_NARROW } from './constants';
|
||||
|
||||
/**
|
||||
* The initial redux state of the feature base/responsive-ui.
|
||||
* The default/initial redux state of the feature base/responsive-ui.
|
||||
*/
|
||||
const _INITIAL_STATE = {
|
||||
const DEFAULT_STATE = {
|
||||
aspectRatio: ASPECT_RATIO_NARROW,
|
||||
reducedUI: false
|
||||
};
|
||||
|
||||
ReducerRegistry.register(
|
||||
'features/base/responsive-ui',
|
||||
(state = _INITIAL_STATE, action) => {
|
||||
(state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case SET_ASPECT_RATIO:
|
||||
return set(state, 'aspectRatio', action.aspectRatio);
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
/* @flow */
|
||||
// @flow
|
||||
|
||||
import { AppState } from 'react-native';
|
||||
import type { Dispatch } from 'redux';
|
||||
|
||||
import {
|
||||
APP_WILL_MOUNT,
|
||||
APP_WILL_UNMOUNT
|
||||
} from '../../app';
|
||||
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../app';
|
||||
import { MiddlewareRegistry } from '../../base/redux';
|
||||
|
||||
import {
|
||||
_setAppStateListener,
|
||||
_setAppStateListener as _setAppStateListenerA,
|
||||
_setBackgroundVideoMuted,
|
||||
appStateChanged
|
||||
} from './actions';
|
||||
|
@ -25,39 +22,29 @@ import {
|
|||
* required to mute or unmute the local video in case the application goes to
|
||||
* the background or comes back from it.
|
||||
*
|
||||
* @param {Store} store - Redux store.
|
||||
* @param {Store} store - The 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 _SET_APP_STATE_LISTENER:
|
||||
return _setAppStateListenerF(store, next, action);
|
||||
|
||||
case APP_STATE_CHANGED:
|
||||
_appStateChanged(store.dispatch, action.appState);
|
||||
break;
|
||||
|
||||
case APP_WILL_MOUNT:
|
||||
store.dispatch(
|
||||
_setAppStateListener(
|
||||
_onAppStateChange.bind(undefined, store.dispatch)));
|
||||
case APP_WILL_MOUNT: {
|
||||
const { dispatch } = store;
|
||||
|
||||
dispatch(
|
||||
_setAppStateListenerA(_onAppStateChange.bind(undefined, dispatch)));
|
||||
break;
|
||||
}
|
||||
|
||||
case APP_WILL_UNMOUNT:
|
||||
store.dispatch(_setAppStateListener(null));
|
||||
store.dispatch(_setAppStateListenerA(undefined));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -65,11 +52,11 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
});
|
||||
|
||||
/**
|
||||
* Handles app state changes. Dispatches the necessary Redux actions for the
|
||||
* 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 {Dispatch} dispatch - The redux {@code dispatch} function.
|
||||
* @param {string} appState - The current app state.
|
||||
* @private
|
||||
* @returns {void}
|
||||
|
@ -97,9 +84,9 @@ function _appStateChanged(dispatch: Function, appState: string) {
|
|||
|
||||
/**
|
||||
* Called by React Native's AppState API to notify that the application state
|
||||
* has changed. Dispatches the change within the (associated) Redux store.
|
||||
* has changed. Dispatches the change within the (associated) redux store.
|
||||
*
|
||||
* @param {Dispatch} dispatch - Redux dispatch function.
|
||||
* @param {Dispatch} dispatch - The redux {@code dispatch} function.
|
||||
* @param {string} appState - The current application execution state.
|
||||
* @private
|
||||
* @returns {void}
|
||||
|
@ -107,3 +94,31 @@ function _appStateChanged(dispatch: Function, appState: string) {
|
|||
function _onAppStateChange(dispatch: Dispatch<*>, appState: string) {
|
||||
dispatch(appStateChanged(appState));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the feature filmstrip that the action
|
||||
* {@link _SET_IMMERSIVE_LISTENER} is being dispatched within a specific redux
|
||||
* store.
|
||||
*
|
||||
* @param {Store} store - The redux store in which the specified action is being
|
||||
* dispatched.
|
||||
* @param {Dispatch} next - The redux dispatch function to dispatch the
|
||||
* specified action to the specified store.
|
||||
* @param {Action} action - The redux action {@code _SET_IMMERSIVE_LISTENER}
|
||||
* which is being dispatched in the specified store.
|
||||
* @private
|
||||
* @returns {Object} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _setAppStateListenerF({ getState }, next, action) {
|
||||
// Remove the old AppState listener and add the new one.
|
||||
const { appStateListener: oldListener } = getState()['features/background'];
|
||||
const result = next(action);
|
||||
const { appStateListener: newListener } = getState()['features/background'];
|
||||
|
||||
if (oldListener !== newListener) {
|
||||
oldListener && AppState.removeEventListener('change', oldListener);
|
||||
newListener && AppState.addEventListener('change', newListener);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import { ReducerRegistry } from '../../base/redux';
|
||||
|
||||
import {
|
||||
|
@ -5,13 +7,16 @@ import {
|
|||
APP_STATE_CHANGED
|
||||
} from './actionTypes';
|
||||
|
||||
const INITIAL_STATE = {
|
||||
/**
|
||||
* The default/initial redux state of the feature background.
|
||||
*/
|
||||
const DEFAULT_STATE = {
|
||||
appState: 'active'
|
||||
};
|
||||
|
||||
ReducerRegistry.register(
|
||||
'features/background',
|
||||
(state = INITIAL_STATE, action) => {
|
||||
(state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case _SET_APP_STATE_LISTENER:
|
||||
return {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/**
|
||||
* The type of redux action to set the Immersive change event listener.
|
||||
* The type of (redux) action to set the react-native-immersive's change event
|
||||
* listener.
|
||||
*
|
||||
* {
|
||||
* type: _SET_IMMERSIVE_LISTENER,
|
||||
|
|
|
@ -3,13 +3,14 @@
|
|||
import { _SET_IMMERSIVE_LISTENER } from './actionTypes';
|
||||
|
||||
/**
|
||||
* Sets the listener to be used with React Native's Immersive API.
|
||||
* Sets the change event listener to be used with react-native-immersive's API.
|
||||
*
|
||||
* @param {Function} listener - Function to be set as the change event listener.
|
||||
* @param {Function} [listener] - The function to be used with
|
||||
* react-native-immersive's API as the change event listener.
|
||||
* @protected
|
||||
* @returns {{
|
||||
* type: _SET_IMMERSIVE_LISTENER,
|
||||
* listener: Function
|
||||
* listener: ?Function
|
||||
* }}
|
||||
*/
|
||||
export function _setImmersiveListener(listener: ?Function) {
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
import { Platform } from '../../base/react';
|
||||
import { MiddlewareRegistry } from '../../base/redux';
|
||||
|
||||
import { _setImmersiveListener } from './actions';
|
||||
import { _setImmersiveListener as _setImmersiveListenerA } from './actions';
|
||||
import { _SET_IMMERSIVE_LISTENER } from './actionTypes';
|
||||
|
||||
/**
|
||||
|
@ -28,59 +28,47 @@ import { _SET_IMMERSIVE_LISTENER } from './actionTypes';
|
|||
* @param {Store} store - The redux store.
|
||||
* @returns {Function}
|
||||
*/
|
||||
MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
|
||||
const result = next(action);
|
||||
|
||||
let fullScreen = null;
|
||||
|
||||
MiddlewareRegistry.register(store => next => action => {
|
||||
switch (action.type) {
|
||||
case _SET_IMMERSIVE_LISTENER:
|
||||
// XXX The React Native module Immersive is only implemented on Android
|
||||
// and throws on other platforms.
|
||||
if (Platform.OS === 'android') {
|
||||
// Remove the current/old Immersive listener.
|
||||
const { listener } = getState()['features/full-screen'];
|
||||
|
||||
listener && Immersive.removeImmersiveListener(listener);
|
||||
|
||||
// Add the new listener.
|
||||
action.listener && Immersive.addImmersiveListener(action.listener);
|
||||
}
|
||||
break;
|
||||
return _setImmersiveListenerF(store, next, action);
|
||||
|
||||
case APP_WILL_MOUNT: {
|
||||
const context = {
|
||||
dispatch,
|
||||
getState
|
||||
};
|
||||
const result = next(action);
|
||||
|
||||
dispatch(
|
||||
_setImmersiveListener(_onImmersiveChange.bind(undefined, context)));
|
||||
break;
|
||||
store.dispatch(
|
||||
_setImmersiveListenerA(_onImmersiveChange.bind(undefined, store)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
case APP_WILL_UNMOUNT:
|
||||
_setImmersiveListener(undefined);
|
||||
store.dispatch(_setImmersiveListenerA(undefined));
|
||||
break;
|
||||
|
||||
case CONFERENCE_WILL_JOIN:
|
||||
case CONFERENCE_JOINED:
|
||||
case SET_AUDIO_ONLY: {
|
||||
const result = next(action);
|
||||
const { audioOnly, conference, joining }
|
||||
= getState()['features/base/conference'];
|
||||
= store.getState()['features/base/conference'];
|
||||
|
||||
fullScreen = conference || joining ? !audioOnly : false;
|
||||
break;
|
||||
_setFullScreen(conference || joining ? !audioOnly : false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
case CONFERENCE_FAILED:
|
||||
case CONFERENCE_LEFT:
|
||||
fullScreen = false;
|
||||
break;
|
||||
case CONFERENCE_LEFT: {
|
||||
const result = next(action);
|
||||
|
||||
_setFullScreen(false);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
fullScreen !== null && _setFullScreen(fullScreen);
|
||||
|
||||
return result;
|
||||
return next(action);
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -119,11 +107,43 @@ function _setFullScreen(fullScreen: boolean) {
|
|||
// throws on other platforms.
|
||||
if (Platform.OS === 'android') {
|
||||
fullScreen ? Immersive.on() : Immersive.off();
|
||||
} else {
|
||||
// On platforms other than Android go with whatever React Native itself
|
||||
// supports.
|
||||
StatusBar.setHidden(fullScreen, 'slide');
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
/**
|
||||
* Notifies the feature filmstrip that the action
|
||||
* {@link _SET_IMMERSIVE_LISTENER} is being dispatched within a specific redux
|
||||
* store.
|
||||
*
|
||||
* @param {Store} store - The redux store in which the specified action is being
|
||||
* dispatched.
|
||||
* @param {Dispatch} next - The redux dispatch function to dispatch the
|
||||
* specified action to the specified store.
|
||||
* @param {Action} action - The redux action {@code _SET_IMMERSIVE_LISTENER}
|
||||
* which is being dispatched in the specified store.
|
||||
* @private
|
||||
* @returns {Object} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _setImmersiveListenerF({ getState }, next, action) {
|
||||
// XXX The React Native module Immersive is only implemented on Android and
|
||||
// throws on other platforms.
|
||||
if (Platform.OS === 'android') {
|
||||
// Remove the old Immersive listener and add the new one.
|
||||
const { listener: oldListener } = getState()['features/full-screen'];
|
||||
const result = next(action);
|
||||
const { listener: newListener } = getState()['features/full-screen'];
|
||||
|
||||
if (oldListener !== newListener) {
|
||||
oldListener && Immersive.removeImmersiveListener(oldListener);
|
||||
newListener && Immersive.addImmersiveListener(newListener);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// On platforms other than Android go with whatever React Native itself
|
||||
// supports.
|
||||
StatusBar.setHidden(fullScreen, 'slide');
|
||||
return next(action);
|
||||
}
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
// @flow
|
||||
|
||||
import { ReducerRegistry } from '../../base/redux';
|
||||
|
||||
import { _SET_IMMERSIVE_LISTENER } from './actionTypes';
|
||||
|
||||
const INITIAL_STATE = {
|
||||
listener: undefined
|
||||
};
|
||||
ReducerRegistry.register('features/full-screen', (state = {}, action) => {
|
||||
switch (action.type) {
|
||||
case _SET_IMMERSIVE_LISTENER:
|
||||
return {
|
||||
...state,
|
||||
listener: action.listener
|
||||
};
|
||||
}
|
||||
|
||||
ReducerRegistry.register(
|
||||
'features/full-screen',
|
||||
(state = INITIAL_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case _SET_IMMERSIVE_LISTENER:
|
||||
return {
|
||||
...state,
|
||||
listener: action.listener
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
});
|
||||
return state;
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* @flow */
|
||||
// @flow
|
||||
|
||||
import { ReducerRegistry, set } from '../../base/redux';
|
||||
|
||||
|
@ -9,13 +9,13 @@ import {
|
|||
} from './actionTypes';
|
||||
|
||||
/**
|
||||
* The initial redux state of the feature network-activity.
|
||||
* The default/initial redux state of the feature network-activity.
|
||||
*
|
||||
* @type {{
|
||||
* requests: Map
|
||||
* }}
|
||||
*/
|
||||
const _INITIAL_STATE = {
|
||||
const DEFAULT_STATE = {
|
||||
/**
|
||||
* The ongoing network requests i.e. the network request which have been
|
||||
* added to the redux store/state and have not been removed.
|
||||
|
@ -27,7 +27,7 @@ const _INITIAL_STATE = {
|
|||
|
||||
ReducerRegistry.register(
|
||||
'features/network-activity',
|
||||
(state = _INITIAL_STATE, action) => {
|
||||
(state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case _ADD_NETWORK_REQUEST: {
|
||||
const {
|
||||
|
@ -44,7 +44,7 @@ ReducerRegistry.register(
|
|||
}
|
||||
|
||||
case _REMOVE_ALL_NETWORK_REQUESTS:
|
||||
return set(state, 'requests', _INITIAL_STATE.requests);
|
||||
return set(state, 'requests', DEFAULT_STATE.requests);
|
||||
|
||||
case _REMOVE_NETWORK_REQUEST: {
|
||||
const { request: key } = action;
|
||||
|
|
Loading…
Reference in New Issue