diff --git a/lang/main.json b/lang/main.json index f9dd01974..14643d4b4 100644 --- a/lang/main.json +++ b/lang/main.json @@ -1010,6 +1010,7 @@ "profileSection": "Profile", "serverURL": "Server URL", "showAdvanced": "Show advanced settings", + "startCarModeInLowBandwidthMode": "Start car mode in low bandwidth mode", "startWithAudioMuted": "Start with audio muted", "startWithVideoMuted": "Start with video muted", "terms": "Terms", diff --git a/react/features/base/settings/reducer.ts b/react/features/base/settings/reducer.ts index f93cd752f..c76dc373d 100644 --- a/react/features/base/settings/reducer.ts +++ b/react/features/base/settings/reducer.ts @@ -37,6 +37,7 @@ const DEFAULT_STATE: ISettingsState = { soundsTalkWhileMuted: true, soundsReactions: true, startAudioOnly: false, + startCarMode: false, startWithAudioMuted: false, startWithVideoMuted: false, userSelectedAudioOutputDeviceId: undefined, @@ -74,6 +75,7 @@ export interface ISettingsState { soundsReactions?: boolean; soundsTalkWhileMuted?: boolean; startAudioOnly?: boolean; + startCarMode?: boolean; startWithAudioMuted?: boolean; startWithVideoMuted?: boolean; userSelectedAudioOutputDeviceId?: string; diff --git a/react/features/conference/components/native/Conference.js b/react/features/conference/components/native/Conference.js index 4ed84fdf9..2b01aba3d 100644 --- a/react/features/conference/components/native/Conference.js +++ b/react/features/conference/components/native/Conference.js @@ -60,13 +60,18 @@ type Props = AbstractProps & { */ _aspectRatio: Symbol, + /** + * Whether the audio only is enabled or not. + */ + _audioOnlyEnabled: boolean, + /** * Branding styles for conference. */ _brandingStyles: Object, /** - * Wherther the calendar feature is enabled or not. + * Whether the calendar feature is enabled or not. */ _calendarEnabled: boolean, @@ -134,6 +139,11 @@ type Props = AbstractProps & { */ _showLobby: boolean, + /** + * Indicates whether the car mode is enabled. + */ + _startCarMode: boolean, + /** * The redux {@code dispatch} function. */ @@ -142,7 +152,12 @@ type Props = AbstractProps & { /** * Object containing the safe area insets. */ - insets: Object + insets: Object, + + /** + * Default prop for navigating between screen components(React Navigation). + */ + navigation: Object }; type State = { @@ -192,7 +207,17 @@ class Conference extends AbstractConference { * @returns {void} */ componentDidMount() { + const { + _audioOnlyEnabled, + _startCarMode, + navigation + } = this.props; + BackHandler.addEventListener('hardwareBackPress', this._onHardwareBackPress); + + if (_audioOnlyEnabled && _startCarMode) { + navigation.navigate(screen.conference.carmode); + } } /** @@ -536,6 +561,8 @@ function _mapStateToProps(state) { const { isOpen } = state['features/participants-pane']; const { aspectRatio, reducedUI } = state['features/base/responsive-ui']; const { backgroundColor } = state['features/dynamic-branding']; + const { startCarMode } = state['features/base/settings']; + const { enabled: audioOnlyEnabled } = state['features/base/audio-only']; const participantCount = getParticipantCount(state); const brandingStyles = backgroundColor ? { backgroundColor @@ -544,6 +571,7 @@ function _mapStateToProps(state) { return { ...abstractMapStateToProps(state), _aspectRatio: aspectRatio, + _audioOnlyEnabled: Boolean(audioOnlyEnabled), _brandingStyles: brandingStyles, _calendarEnabled: isCalendarEnabled(state), _connecting: isConnecting(state), @@ -556,6 +584,7 @@ function _mapStateToProps(state) { _reducedUI: reducedUI, _shouldEnableAutoKnock: shouldEnableAutoKnock(state), _showLobby: getIsLobbyVisible(state), + _startCarMode: startCarMode, _toolboxVisible: isToolboxVisible(state) }; } diff --git a/react/features/settings/components/native/SettingsView.tsx b/react/features/settings/components/native/SettingsView.tsx index 35f021ead..fe27ce60b 100644 --- a/react/features/settings/components/native/SettingsView.tsx +++ b/react/features/settings/components/native/SettingsView.tsx @@ -88,6 +88,11 @@ interface State { */ serverURL: string; + /** + * State variable for start car mode. + */ + startCarMode: boolean; + /** * State variable for the start with audio muted switch. */ @@ -135,6 +140,7 @@ interface Props extends WithTranslation { displayName: string; email: string; serverURL: string; + startCarMode: boolean; startWithAudioMuted: boolean; startWithVideoMuted: boolean; }; @@ -185,6 +191,7 @@ class SettingsView extends Component { displayName, email, serverURL, + startCarMode, startWithAudioMuted, startWithVideoMuted } = props._settings || {}; @@ -197,6 +204,7 @@ class SettingsView extends Component { displayName, email, serverURL, + startCarMode, startWithAudioMuted, startWithVideoMuted }; @@ -213,6 +221,8 @@ class SettingsView extends Component { this._onDisableSelfView = this._onDisableSelfView.bind(this); this._onStartAudioMutedChange = this._onStartAudioMutedChange.bind(this); + this._onStartCarmodeInLowBandwidthMode + = this._onStartCarmodeInLowBandwidthMode.bind(this); this._onStartVideoMutedChange = this._onStartVideoMutedChange.bind(this); this._setURLFieldReference = this._setURLFieldReference.bind(this); @@ -250,6 +260,7 @@ class SettingsView extends Component { displayName, email, serverURL, + startCarMode, startWithAudioMuted, startWithVideoMuted } = this.state; @@ -325,6 +336,13 @@ class SettingsView extends Component { theme = { textInputTheme } value = { serverURL } /> + + + + { }); } + /** . + * Handles car mode in low bandwidth mode. + * + * @param {boolean} startCarMode - The new value. + * @private + * @returns {void} + */ + _onStartCarmodeInLowBandwidthMode(startCarMode: boolean) { + this.setState({ + startCarMode + }); + + this._updateSettings({ + startCarMode + }); + } + /** * Handles the disable crash reporting change event. * diff --git a/react/features/toolbox/components/native/AudioOnlyButton.js b/react/features/toolbox/components/native/AudioOnlyButton.js index eb49db51f..1681e0c35 100644 --- a/react/features/toolbox/components/native/AudioOnlyButton.js +++ b/react/features/toolbox/components/native/AudioOnlyButton.js @@ -1,11 +1,15 @@ // @flow -import { toggleAudioOnly } from '../../../base/audio-only'; +import { setAudioOnly, toggleAudioOnly } from '../../../base/audio-only'; import { AUDIO_ONLY_BUTTON_ENABLED, getFeatureFlag } from '../../../base/flags'; import { translate } from '../../../base/i18n'; import { IconAudioOnly, IconAudioOnlyOff } from '../../../base/icons'; import { connect } from '../../../base/redux'; import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components'; +import { + navigate +} from '../../../mobile/navigation/components/conference/ConferenceNavigationContainerRef'; +import { screen } from '../../../mobile/navigation/routes'; /** * The type of the React {@code Component} props of {@link AudioOnlyButton}. @@ -17,6 +21,11 @@ type Props = AbstractButtonProps & { */ _audioOnly: boolean, + /** + * Indicates whether the car mode is enabled. + */ + _startCarMode: boolean, + /** * The redux {@code dispatch} function. */ @@ -41,9 +50,17 @@ class AudioOnlyButton extends AbstractButton { * @returns {void} */ _handleClick() { - this.props.dispatch(toggleAudioOnly()); + const { _audioOnly, _startCarMode, dispatch } = this.props; + + if (!_audioOnly && _startCarMode) { + dispatch(setAudioOnly(true)); + navigate(screen.conference.carmode); + } else { + dispatch(toggleAudioOnly()); + } } + /** * Indicates whether this button is in toggled state or not. * @@ -70,10 +87,12 @@ class AudioOnlyButton extends AbstractButton { function _mapStateToProps(state, ownProps): Object { const { enabled: audioOnly } = state['features/base/audio-only']; const enabledInFeatureFlags = getFeatureFlag(state, AUDIO_ONLY_BUTTON_ENABLED, true); + const { startCarMode } = state['features/base/settings']; const { visible = enabledInFeatureFlags } = ownProps; return { _audioOnly: Boolean(audioOnly), + _startCarMode: startCarMode, visible }; }