ref: Settings to JitsiModal

This commit is contained in:
Bettenbuk Zoltan 2020-04-06 17:21:50 +02:00 committed by Zoltan Bettenbuk
parent 678ed605d7
commit 2f817b6633
9 changed files with 100 additions and 210 deletions

View File

@ -3,17 +3,6 @@
*/ */
export const SET_AUDIO_SETTINGS_VISIBILITY = 'SET_AUDIO_SETTINGS_VISIBILITY'; export const SET_AUDIO_SETTINGS_VISIBILITY = 'SET_AUDIO_SETTINGS_VISIBILITY';
/**
* The type of (redux) action which sets the visibility of the view/UI rendering
* the app's settings.
*
* {
* type: SET_SETTINGS_VIEW_VISIBLE
* visible: boolean
* }
*/
export const SET_SETTINGS_VIEW_VISIBLE = 'SET_SETTINGS_VIEW_VISIBLE';
/** /**
* The type of (redux) action which sets the visibility of the video settings popup. * The type of (redux) action which sets the visibility of the video settings popup.
*/ */

View File

@ -6,7 +6,6 @@ import { i18next } from '../base/i18n';
import { import {
SET_AUDIO_SETTINGS_VISIBILITY, SET_AUDIO_SETTINGS_VISIBILITY,
SET_SETTINGS_VIEW_VISIBLE,
SET_VIDEO_SETTINGS_VISIBILITY SET_VIDEO_SETTINGS_VISIBILITY
} from './actionTypes'; } from './actionTypes';
import { SettingsDialog } from './components'; import { SettingsDialog } from './components';
@ -14,23 +13,6 @@ import { getMoreTabProps, getProfileTabProps } from './functions';
declare var APP: Object; declare var APP: Object;
/**
* Sets the visibility of the view/UI which renders the app's settings.
*
* @param {boolean} visible - If the view/UI which renders the app's settings is
* to be made visible, {@code true}; otherwise, {@code false}.
* @returns {{
* type: SET_SETTINGS_VIEW_VISIBLE,
* visible: boolean
* }}
*/
export function setSettingsViewVisible(visible: boolean) {
return {
type: SET_SETTINGS_VIEW_VISIBLE,
visible
};
}
/** /**
* Opens {@code SettingsDialog}. * Opens {@code SettingsDialog}.
* *

View File

@ -1,37 +1,29 @@
// @flow // @flow
import React from 'react'; import React from 'react';
import { Alert, NativeModules, SafeAreaView, ScrollView, Switch, Text, TextInput, View } from 'react-native'; import { Alert, NativeModules, ScrollView, Switch, Text, TextInput } from 'react-native';
import { ColorSchemeRegistry } from '../../../base/color-scheme';
import { translate } from '../../../base/i18n'; import { translate } from '../../../base/i18n';
import { HeaderWithNavigation, Modal } from '../../../base/react'; import { JitsiModal } from '../../../base/modal';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
import { SETTINGS_VIEW_ID } from '../../constants';
import { normalizeUserInputURL } from '../../functions';
import { import {
AbstractSettingsView, AbstractSettingsView,
_mapStateToProps as _abstractMapStateToProps, _mapStateToProps as _abstractMapStateToProps,
type Props as AbstractProps type Props
} from '../AbstractSettingsView'; } from '../AbstractSettingsView';
import { setSettingsViewVisible } from '../../actions';
import FormRow from './FormRow'; import FormRow from './FormRow';
import FormSectionHeader from './FormSectionHeader'; import FormSectionHeader from './FormSectionHeader';
import { normalizeUserInputURL } from '../../functions';
import styles from './styles';
/** /**
* Application information module. * Application information module.
*/ */
const { AppInfo } = NativeModules; const { AppInfo } = NativeModules;
type Props = AbstractProps & {
/**
* Color schemed style of the header component.
*/
_headerStyles: Object
}
type State = { type State = {
/** /**
@ -113,9 +105,9 @@ class SettingsView extends AbstractSettingsView<Props, State> {
// Bind event handlers so they are only bound once per instance. // Bind event handlers so they are only bound once per instance.
this._onBlurServerURL = this._onBlurServerURL.bind(this); this._onBlurServerURL = this._onBlurServerURL.bind(this);
this._onClose = this._onClose.bind(this);
this._onDisableCallIntegration = this._onDisableCallIntegration.bind(this); this._onDisableCallIntegration = this._onDisableCallIntegration.bind(this);
this._onDisableP2P = this._onDisableP2P.bind(this); this._onDisableP2P = this._onDisableP2P.bind(this);
this._onRequestClose = this._onRequestClose.bind(this);
this._onShowAdvanced = this._onShowAdvanced.bind(this); this._onShowAdvanced = this._onShowAdvanced.bind(this);
this._setURLFieldReference = this._setURLFieldReference.bind(this); this._setURLFieldReference = this._setURLFieldReference.bind(this);
this._showURLAlert = this._showURLAlert.bind(this); this._showURLAlert = this._showURLAlert.bind(this);
@ -128,16 +120,78 @@ class SettingsView extends AbstractSettingsView<Props, State> {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
const { displayName, email, serverURL, startWithAudioMuted, startWithVideoMuted } = this.state;
return ( return (
<Modal <JitsiModal
onRequestClose = { this._onRequestClose } headerProps = {{
presentationStyle = 'overFullScreen' headerLabelKey: 'settingsView.header'
visible = { this.props._visible }> }}
<View style = { this.props._headerStyles.page }> modalId = { SETTINGS_VIEW_ID }
{ this._renderHeader() } onClose = { this._onClose }>
{ this._renderBody() } <ScrollView>
</View> <FormSectionHeader
</Modal> label = 'settingsView.profileSection' />
<FormRow
fieldSeparator = { true }
label = 'settingsView.displayName'
layout = 'column'>
<TextInput
autoCorrect = { false }
onChangeText = { this._onChangeDisplayName }
placeholder = 'John Doe'
value = { displayName } />
</FormRow>
<FormRow
label = 'settingsView.email'
layout = 'column'>
<TextInput
autoCapitalize = 'none'
autoCorrect = { false }
keyboardType = { 'email-address' }
onChangeText = { this._onChangeEmail }
placeholder = 'email@example.com'
value = { email } />
</FormRow>
<FormSectionHeader
label = 'settingsView.conferenceSection' />
<FormRow
fieldSeparator = { true }
label = 'settingsView.serverURL'
layout = 'column'>
<TextInput
autoCapitalize = 'none'
autoCorrect = { false }
onBlur = { this._onBlurServerURL }
onChangeText = { this._onChangeServerURL }
placeholder = { this.props._serverURL }
value = { serverURL } />
</FormRow>
<FormRow
fieldSeparator = { true }
label = 'settingsView.startWithAudioMuted'>
<Switch
onValueChange = { this._onStartAudioMutedChange }
value = { startWithAudioMuted } />
</FormRow>
<FormRow label = 'settingsView.startWithVideoMuted'>
<Switch
onValueChange = { this._onStartVideoMutedChange }
value = { startWithVideoMuted } />
</FormRow>
<FormSectionHeader
label = 'settingsView.buildInfoSection' />
<FormRow
label = 'settingsView.version'>
<Text>
{ `${AppInfo.version} build ${AppInfo.buildNumber}` }
</Text>
</FormRow>
<FormSectionHeader
label = 'settingsView.advanced' />
{ this._renderAdvancedSettings() }
</ScrollView>
</JitsiModal>
); );
} }
@ -231,17 +285,18 @@ class SettingsView extends AbstractSettingsView<Props, State> {
}); });
} }
_onRequestClose: () => void; _onClose: () => void;
/** /**
* Handles the back button. Also invokes normalizeUserInputURL to validate * Callback to be invoked on closing the modal. Also invokes normalizeUserInputURL to validate
* the URL entered by the user. * the URL entered by the user.
* *
* @returns {void} * @returns {boolean} - True if the modal can be closed.
*/ */
_onRequestClose() { _onClose() {
this.setState({ showAdvanced: false }); this.setState({ showAdvanced: false });
this._processServerURL(true /* hideOnSuccess */);
return this._processServerURL(true /* hideOnSuccess */);
} }
_onShowAdvanced: () => void; _onShowAdvanced: () => void;
@ -296,12 +351,13 @@ class SettingsView extends AbstractSettingsView<Props, State> {
if (normalizedURL === null) { if (normalizedURL === null) {
this._showURLAlert(); this._showURLAlert();
} else {
this._onChangeServerURL(normalizedURL); return false;
if (hideOnSuccess) {
this.props.dispatch(setSettingsViewVisible(false));
}
} }
this._onChangeServerURL(normalizedURL);
return hideOnSuccess;
} }
/** /**
@ -345,97 +401,6 @@ class SettingsView extends AbstractSettingsView<Props, State> {
); );
} }
/**
* Renders the body (under the header) of {@code SettingsView}.
*
* @private
* @returns {React$Element}
*/
_renderBody() {
const { displayName, email, serverURL, startWithAudioMuted, startWithVideoMuted } = this.state;
return (
<SafeAreaView style = { styles.settingsForm }>
<ScrollView>
<FormSectionHeader
label = 'settingsView.profileSection' />
<FormRow
fieldSeparator = { true }
label = 'settingsView.displayName'
layout = 'column'>
<TextInput
autoCorrect = { false }
onChangeText = { this._onChangeDisplayName }
placeholder = 'John Doe'
value = { displayName } />
</FormRow>
<FormRow
label = 'settingsView.email'
layout = 'column'>
<TextInput
autoCapitalize = 'none'
autoCorrect = { false }
keyboardType = { 'email-address' }
onChangeText = { this._onChangeEmail }
placeholder = 'email@example.com'
value = { email } />
</FormRow>
<FormSectionHeader
label = 'settingsView.conferenceSection' />
<FormRow
fieldSeparator = { true }
label = 'settingsView.serverURL'
layout = 'column'>
<TextInput
autoCapitalize = 'none'
autoCorrect = { false }
onBlur = { this._onBlurServerURL }
onChangeText = { this._onChangeServerURL }
placeholder = { this.props._serverURL }
value = { serverURL } />
</FormRow>
<FormRow
fieldSeparator = { true }
label = 'settingsView.startWithAudioMuted'>
<Switch
onValueChange = { this._onStartAudioMutedChange }
value = { startWithAudioMuted } />
</FormRow>
<FormRow label = 'settingsView.startWithVideoMuted'>
<Switch
onValueChange = { this._onStartVideoMutedChange }
value = { startWithVideoMuted } />
</FormRow>
<FormSectionHeader
label = 'settingsView.buildInfoSection' />
<FormRow
label = 'settingsView.version'>
<Text>
{ `${AppInfo.version} build ${AppInfo.buildNumber}` }
</Text>
</FormRow>
<FormSectionHeader
label = 'settingsView.advanced' />
{ this._renderAdvancedSettings() }
</ScrollView>
</SafeAreaView>
);
}
/**
* Renders the header of {@code SettingsView}.
*
* @private
* @returns {React$Element}
*/
_renderHeader() {
return (
<HeaderWithNavigation
headerLabelKey = 'settingsView.header'
onPressBack = { this._onRequestClose } />
);
}
_setURLFieldReference: (React$ElementRef<*> | null) => void; _setURLFieldReference: (React$ElementRef<*> | null) => void;
/** /**
@ -478,14 +443,11 @@ class SettingsView extends AbstractSettingsView<Props, State> {
* Maps part of the Redux state to the props of this component. * Maps part of the Redux state to the props of this component.
* *
* @param {Object} state - The Redux state. * @param {Object} state - The Redux state.
* @returns {{ * @returns {Props}
* _headerStyles: Object
* }}
*/ */
function _mapStateToProps(state) { function _mapStateToProps(state) {
return { return {
..._abstractMapStateToProps(state), ..._abstractMapStateToProps(state)
_headerStyles: ColorSchemeRegistry.get(state, 'Header')
}; };
} }

View File

@ -78,11 +78,6 @@ export default {
padding: 5 padding: 5
}, },
settingsForm: {
backgroundColor: ColorPalette.white,
flex: 1
},
/** /**
* Global {@code Text} color for the components. * Global {@code Text} color for the components.
*/ */

View File

@ -4,3 +4,8 @@ export const SETTINGS_TABS = {
MORE: 'more_tab', MORE: 'more_tab',
PROFILE: 'profile_tab' PROFILE: 'profile_tab'
}; };
/**
* View ID for the Settings modal.
*/
export const SETTINGS_VIEW_ID = 'SETTINGS_VIEW_ID';

View File

@ -4,5 +4,4 @@ export * from './components';
export * from './constants'; export * from './constants';
export * from './functions'; export * from './functions';
import './middleware';
import './reducer'; import './reducer';

View File

@ -1,36 +0,0 @@
// @flow
import { SET_ROOM } from '../base/conference';
import { MiddlewareRegistry } from '../base/redux';
import { setSettingsViewVisible } from './actions';
/**
* The redux middleware to set the visibility of {@link SettingsView}.
*
* @param {Store} store - The redux store.
* @returns {Function}
*/
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case SET_ROOM:
return _hideSettingsView(store, next, action);
}
return next(action);
});
/**
* Hides {@link SettingsView}.
*
* @param {Store} store - The redux store.
* @param {Dispatch} next - The redux {@code dispatch} function.
* @param {Action} action - The redux action.
* @private
* @returns {Object} The new state.
*/
function _hideSettingsView({ dispatch }, next, action) {
dispatch(setSettingsViewVisible(false));
return next(action);
}

View File

@ -4,17 +4,11 @@ import { ReducerRegistry } from '../base/redux';
import { import {
SET_AUDIO_SETTINGS_VISIBILITY, SET_AUDIO_SETTINGS_VISIBILITY,
SET_SETTINGS_VIEW_VISIBLE,
SET_VIDEO_SETTINGS_VISIBILITY SET_VIDEO_SETTINGS_VISIBILITY
} from './actionTypes'; } from './actionTypes';
ReducerRegistry.register('features/settings', (state = {}, action) => { ReducerRegistry.register('features/settings', (state = {}, action) => {
switch (action.type) { switch (action.type) {
case SET_SETTINGS_VIEW_VISIBLE:
return {
...state,
visible: action.visible
};
case SET_AUDIO_SETTINGS_VISIBILITY: case SET_AUDIO_SETTINGS_VISIBILITY:
return { return {
...state, ...state,

View File

@ -16,7 +16,7 @@ import {
} from '../../base/react'; } from '../../base/react';
import { connect } from '../../base/redux'; import { connect } from '../../base/redux';
import { HELP_VIEW_MODAL_ID } from '../../help'; import { HELP_VIEW_MODAL_ID } from '../../help';
import { setSettingsViewVisible } from '../../settings'; import { SETTINGS_VIEW_ID } from '../../settings';
import { setSideBarVisible } from '../actions'; import { setSideBarVisible } from '../actions';
import SideBarItem from './SideBarItem'; import SideBarItem from './SideBarItem';
@ -157,7 +157,7 @@ class WelcomePageSideBar extends Component<Props> {
const { dispatch } = this.props; const { dispatch } = this.props;
dispatch(setSideBarVisible(false)); dispatch(setSideBarVisible(false));
dispatch(setSettingsViewVisible(true)); dispatch(setActiveModalId(SETTINGS_VIEW_ID));
} }
} }