feat(mobile/background): use reducedUI only when app is not active and log appState (#15167)

* feat(mobile/background): use reducedUI only when app is not active and log appState changes
This commit is contained in:
Calinteodor
2024-10-22 16:19:31 +03:00
committed by GitHub
parent dd859d2a26
commit 939a9a45d3
9 changed files with 36 additions and 18 deletions

View File

@@ -48,7 +48,7 @@ import { IKeyboardShortcutsState } from '../keyboard-shortcuts/types';
import { ILargeVideoState } from '../large-video/reducer';
import { ILobbyState } from '../lobby/reducer';
import { IMobileAudioModeState } from '../mobile/audio-mode/reducer';
import { IBackgroundState } from '../mobile/background/reducer';
import { IMobileBackgroundState } from '../mobile/background/reducer';
import { ICallIntegrationState } from '../mobile/call-integration/reducer';
import { IMobileExternalApiState } from '../mobile/external-api/reducer';
import { IFullScreenState } from '../mobile/full-screen/reducer';
@@ -93,7 +93,6 @@ export interface IReduxState {
'features/analytics': IAnalyticsState;
'features/authentication': IAuthenticationState;
'features/av-moderation': IAVModerationState;
'features/background': IBackgroundState;
'features/base/app': IAppState;
'features/base/audio-only': IAudioOnlyState;
'features/base/color-scheme': any;
@@ -141,6 +140,7 @@ export interface IReduxState {
'features/large-video': ILargeVideoState;
'features/lobby': ILobbyState;
'features/mobile/audio-mode': IMobileAudioModeState;
'features/mobile/background': IMobileBackgroundState;
'features/mobile/external-api': IMobileExternalApiState;
'features/mobile/watchos': IMobileWatchOSState;
'features/no-audio-signal': INoAudioSignalState;

View File

@@ -33,7 +33,7 @@ const _updateLastN = debounce(({ dispatch, getState }: IStore) => {
}
const { enabled: audioOnly } = state['features/base/audio-only'];
const { appState } = state['features/background'] || {};
const { appState } = state['features/mobile/background'] || {};
const { enabled: filmStripEnabled } = state['features/filmstrip'];
const config = state['features/base/config'];
const { carMode } = state['features/video-layout'];
@@ -44,7 +44,9 @@ const _updateLastN = debounce(({ dispatch, getState }: IStore) => {
// 3. -1 as the default value.
let lastNSelected = config.startLastN ?? (config.channelLastN ?? -1);
if (appState === 'background' || carMode) {
// Because this is shared, on web appState is always undefined,
// meaning that it is never active
if (navigator.product === 'ReactNative' && (appState !== 'active' || carMode)) {
lastNSelected = 0;
} else if (audioOnly) {
const { remoteScreenShares, tileViewEnabled } = state['features/video-layout'];

View File

@@ -71,6 +71,5 @@ MiddlewareRegistry.register(store => next => action => {
* @returns {void}
*/
function _maybeClearAccessStatus(store: IStore, { appState }: { appState: string; }) {
appState === 'background'
&& store.dispatch(setCalendarAuthorization(undefined));
appState === 'background' && store.dispatch(setCalendarAuthorization(undefined));
}

View File

@@ -559,7 +559,7 @@ class Conference extends AbstractConference<IProps, State> {
* @returns {IProps}
*/
function _mapStateToProps(state: IReduxState, _ownProps: any) {
const { appState } = state['features/background'];
const { appState } = state['features/mobile/background'];
const { isOpen } = state['features/participants-pane'];
const { aspectRatio, reducedUI } = state['features/base/responsive-ui'];
const { backgroundColor } = state['features/dynamic-branding'];
@@ -581,7 +581,11 @@ function _mapStateToProps(state: IReduxState, _ownProps: any) {
_isParticipantsPaneOpen: isOpen,
_largeVideoParticipantId: state['features/large-video'].participantId,
_pictureInPictureEnabled: isPipEnabled(state),
_reducedUI: reducedUI || appState === 'background',
// [iOS] - Transitioning between foreground & background, appState goes from active -> inactive -> background
// and during periods of inactivity such as entering the multitasking view,
// opening the Notification Center or in the event of an incoming call.
_reducedUI: reducedUI || appState !== 'active',
_showLobby: getIsLobbyVisible(state),
_startCarMode: startCarMode,
_toolboxVisible: isToolboxVisible(state)

View File

@@ -0,0 +1,3 @@
import { getLogger } from '../../base/logging/functions';
export default getLogger('features/mobile/background');

View File

@@ -5,6 +5,7 @@ import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app/actionTypes';
import MiddlewareRegistry from '../../base/redux/MiddlewareRegistry';
import { _setAppStateSubscription, appStateChanged } from './actions';
import logger from './logger';
/**
* Middleware that captures App lifetime actions and subscribes to application
@@ -45,6 +46,8 @@ MiddlewareRegistry.register(store => next => action => {
*/
function _onAppStateChange(dispatch: IStore['dispatch'], appState: string) {
dispatch(appStateChanged(appState));
logger.debug(`appState changed to: ${appState}`);
}
/**
@@ -59,7 +62,7 @@ function _onAppStateChange(dispatch: IStore['dispatch'], appState: string) {
* @returns {Object} The value returned by {@code next(action)}.
*/
function _setAppStateListener({ dispatch, getState }: IStore, listener: any) {
const { subscription } = getState()['features/background'];
const { subscription } = getState()['features/mobile/background'];
subscription?.remove();

View File

@@ -4,7 +4,7 @@ import ReducerRegistry from '../../base/redux/ReducerRegistry';
import { APP_STATE_CHANGED, _SET_APP_STATE_SUBSCRIPTION } from './actionTypes';
export interface IBackgroundState {
export interface IMobileBackgroundState {
appState: string;
subscription?: NativeEventSubscription;
}
@@ -13,10 +13,11 @@ export interface IBackgroundState {
* The default/initial redux state of the feature background.
*/
const DEFAULT_STATE = {
appState: 'active'
appState: ''
};
ReducerRegistry.register<IBackgroundState>('features/background', (state = DEFAULT_STATE, action): IBackgroundState => {
// eslint-disable-next-line max-len
ReducerRegistry.register<IMobileBackgroundState>('features/mobile/background', (state = DEFAULT_STATE, action): IMobileBackgroundState => {
switch (action.type) {
case _SET_APP_STATE_SUBSCRIPTION:

View File

@@ -4,7 +4,7 @@ import { v4 as uuidv4 } from 'uuid';
import { createTrackMutedEvent } from '../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../analytics/functions';
import { appNavigate } from '../../app/actions';
import { appNavigate } from '../../app/actions.native';
import { IReduxState, IStore } from '../../app/types';
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app/actionTypes';
import { SET_AUDIO_ONLY } from '../../base/audio-only/actionTypes';
@@ -30,7 +30,7 @@ import {
TRACK_REMOVED,
TRACK_UPDATED
} from '../../base/tracks/actionTypes';
import { isLocalTrackMuted } from '../../base/tracks/functions.any';
import { isLocalTrackMuted } from '../../base/tracks/functions.native';
import CallKit from './CallKit';
import ConnectionService from './ConnectionService';
@@ -158,6 +158,7 @@ function _conferenceFailed({ getState }: IStore, next: Function, action: AnyActi
if (callUUID) {
delete action.conference.callUUID;
CallIntegration.reportCallFailed(callUUID);
}
}
@@ -234,6 +235,7 @@ function _conferenceLeft({ getState }: IStore, next: Function, action: AnyAction
if (callUUID) {
delete action.conference.callUUID;
CallIntegration.endCall(callUUID);
}
@@ -272,7 +274,7 @@ function _conferenceWillJoin({ dispatch, getState }: IStore, next: Function, act
return result;
}
// When assigning the call UUID, do so in upper case, since iOS will return
// When assigning the callUUID, do so in upper case, since iOS will return
// it upper-cased.
conference.callUUID = (callUUID || uuidv4()).toUpperCase();
@@ -300,6 +302,7 @@ function _conferenceWillJoin({ dispatch, getState }: IStore, next: Function, act
// We're not tracking the call anymore - it doesn't exist on
// the native side.
delete conference.callUUID;
dispatch(appNavigate(undefined));
Alert.alert(
'Call aborted',
@@ -362,11 +365,12 @@ function _onPerformEndCallAction({ callUUID }: { callUUID: string; }) {
const { dispatch, getState } = this; // eslint-disable-line @typescript-eslint/no-invalid-this
const conference = getCurrentConference(getState);
if (conference && conference.callUUID === callUUID) {
if (conference?.callUUID === callUUID) {
// We arrive here when a call is ended by the system, for example, when
// another incoming call is received and the user selects "End &
// Accept".
delete conference.callUUID;
dispatch(appNavigate(undefined));
}
}
@@ -383,10 +387,12 @@ function _onPerformSetMutedCallAction({ callUUID, muted }: { callUUID: string; m
const { dispatch, getState } = this; // eslint-disable-line @typescript-eslint/no-invalid-this
const conference = getCurrentConference(getState);
if (conference && conference.callUUID === callUUID) {
if (conference?.callUUID === callUUID) {
muted = Boolean(muted); // eslint-disable-line no-param-reassign
sendAnalytics(
createTrackMutedEvent('audio', 'call-integration', muted));
dispatch(setAudioMuted(muted, /* ensureTrack */ true));
}
}

View File

@@ -60,7 +60,7 @@ StateListenerRegistry.register(
*/
function _onImmersiveChange({ getState }: IStore) {
const state = getState();
const { appState } = state['features/background'];
const { appState } = state['features/mobile/background'];
if (appState === 'active') {
_setFullScreen(shouldUseFullScreen(state));