mirror of https://github.com/jitsi/jitsi-meet
pull/2451/head
jitsi-meet_2817
parent
e23d4317eb
commit
9f69c4d730
@ -1,19 +0,0 @@ |
|||||||
/** |
|
||||||
* The type of (redux) action which signals the request |
|
||||||
* to hide the app settings screen. |
|
||||||
* |
|
||||||
* { |
|
||||||
* type: HIDE_APP_SETTINGS |
|
||||||
* } |
|
||||||
*/ |
|
||||||
export const HIDE_APP_SETTINGS = Symbol('HIDE_APP_SETTINGS'); |
|
||||||
|
|
||||||
/** |
|
||||||
* The type of (redux) action which signals the request |
|
||||||
* to show the app settings screen where available. |
|
||||||
* |
|
||||||
* { |
|
||||||
* type: SHOW_APP_SETTINGS |
|
||||||
* } |
|
||||||
*/ |
|
||||||
export const SHOW_APP_SETTINGS = Symbol('SHOW_APP_SETTINGS'); |
|
@ -1,29 +0,0 @@ |
|||||||
// @flow
|
|
||||||
|
|
||||||
import { HIDE_APP_SETTINGS, SHOW_APP_SETTINGS } from './actionTypes'; |
|
||||||
|
|
||||||
/** |
|
||||||
* Redux-signals the request to hide the app settings screen. |
|
||||||
* |
|
||||||
* @returns {{ |
|
||||||
* type: HIDE_APP_SETTINGS |
|
||||||
* }} |
|
||||||
*/ |
|
||||||
export function hideAppSettings() { |
|
||||||
return { |
|
||||||
type: HIDE_APP_SETTINGS |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Redux-signals the request to open the app settings screen. |
|
||||||
* |
|
||||||
* @returns {{ |
|
||||||
* type: SHOW_APP_SETTINGS |
|
||||||
* }} |
|
||||||
*/ |
|
||||||
export function showAppSettings() { |
|
||||||
return { |
|
||||||
type: SHOW_APP_SETTINGS |
|
||||||
}; |
|
||||||
} |
|
@ -1,238 +0,0 @@ |
|||||||
// @flow
|
|
||||||
|
|
||||||
import React from 'react'; |
|
||||||
import { |
|
||||||
Alert, |
|
||||||
Modal, |
|
||||||
SafeAreaView, |
|
||||||
ScrollView, |
|
||||||
Switch, |
|
||||||
Text, |
|
||||||
TextInput, |
|
||||||
View |
|
||||||
} from 'react-native'; |
|
||||||
import { connect } from 'react-redux'; |
|
||||||
|
|
||||||
import { translate } from '../../base/i18n'; |
|
||||||
import { Header } from '../../base/react'; |
|
||||||
import { PlatformElements } from '../../base/styles'; |
|
||||||
|
|
||||||
import { hideAppSettings } from '../actions'; |
|
||||||
import { normalizeUserInputURL } from '../functions'; |
|
||||||
|
|
||||||
import { BackButton, FormRow, FormSectionHeader } from './_'; |
|
||||||
import { _mapStateToProps, AbstractAppSettings } from './AbstractAppSettings'; |
|
||||||
import styles from './styles'; |
|
||||||
|
|
||||||
/** |
|
||||||
* The native container rendering the app settings page. |
|
||||||
* |
|
||||||
* @extends AbstractAppSettings |
|
||||||
*/ |
|
||||||
class AppSettings extends AbstractAppSettings { |
|
||||||
_urlField: Object; |
|
||||||
|
|
||||||
/** |
|
||||||
* Instantiates a new {@code AppSettings} instance. |
|
||||||
* |
|
||||||
* @inheritdoc |
|
||||||
*/ |
|
||||||
constructor(props) { |
|
||||||
super(props); |
|
||||||
|
|
||||||
this._onBlurServerURL = this._onBlurServerURL.bind(this); |
|
||||||
this._onRequestClose = this._onRequestClose.bind(this); |
|
||||||
this._setURLFieldReference = this._setURLFieldReference.bind(this); |
|
||||||
this._showURLAlert = this._showURLAlert.bind(this); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Implements React's {@link Component#render()}, renders the settings page. |
|
||||||
* |
|
||||||
* @inheritdoc |
|
||||||
* @returns {ReactElement} |
|
||||||
*/ |
|
||||||
render() { |
|
||||||
const { _profile, t } = this.props; |
|
||||||
|
|
||||||
return ( |
|
||||||
<Modal |
|
||||||
animationType = 'slide' |
|
||||||
onRequestClose = { this._onRequestClose } |
|
||||||
presentationStyle = 'fullScreen' |
|
||||||
supportedOrientations = { [ |
|
||||||
'landscape', |
|
||||||
'portrait' |
|
||||||
] } |
|
||||||
visible = { this.props._visible }> |
|
||||||
<View style = { PlatformElements.page }> |
|
||||||
<Header> |
|
||||||
<BackButton |
|
||||||
onPress = { this._onRequestClose } /> |
|
||||||
<Text |
|
||||||
style = { [ |
|
||||||
styles.text, |
|
||||||
PlatformElements.headerText |
|
||||||
] } > |
|
||||||
{ t('settingsScreen.header') } |
|
||||||
</Text> |
|
||||||
</Header> |
|
||||||
<SafeAreaView style = { styles.settingsForm }> |
|
||||||
<ScrollView> |
|
||||||
<FormSectionHeader |
|
||||||
i18nLabel = 'settingsScreen.profileSection' /> |
|
||||||
<FormRow |
|
||||||
fieldSeparator = { true } |
|
||||||
i18nLabel = 'settingsScreen.displayName' > |
|
||||||
<TextInput |
|
||||||
onChangeText = { this._onChangeDisplayName } |
|
||||||
placeholder = 'John Doe' |
|
||||||
value = { _profile.displayName } /> |
|
||||||
</FormRow> |
|
||||||
<FormRow |
|
||||||
i18nLabel = 'settingsScreen.email' > |
|
||||||
<TextInput |
|
||||||
keyboardType = { 'email-address' } |
|
||||||
onChangeText = { this._onChangeEmail } |
|
||||||
placeholder = 'email@example.com' |
|
||||||
value = { _profile.email } /> |
|
||||||
</FormRow> |
|
||||||
<FormSectionHeader |
|
||||||
i18nLabel |
|
||||||
= 'settingsScreen.conferenceSection' /> |
|
||||||
<FormRow |
|
||||||
fieldSeparator = { true } |
|
||||||
i18nLabel = 'settingsScreen.serverURL' > |
|
||||||
<TextInput |
|
||||||
autoCapitalize = 'none' |
|
||||||
onBlur = { this._onBlurServerURL } |
|
||||||
onChangeText = { this._onChangeServerURL } |
|
||||||
placeholder = { this.props._serverURL } |
|
||||||
value = { _profile.serverURL } /> |
|
||||||
</FormRow> |
|
||||||
<FormRow |
|
||||||
fieldSeparator = { true } |
|
||||||
i18nLabel |
|
||||||
= 'settingsScreen.startWithAudioMuted' > |
|
||||||
<Switch |
|
||||||
onValueChange = { |
|
||||||
this._onStartAudioMutedChange |
|
||||||
} |
|
||||||
value = { |
|
||||||
_profile.startWithAudioMuted |
|
||||||
} /> |
|
||||||
</FormRow> |
|
||||||
<FormRow |
|
||||||
i18nLabel |
|
||||||
= 'settingsScreen.startWithVideoMuted' > |
|
||||||
<Switch |
|
||||||
onValueChange = { |
|
||||||
this._onStartVideoMutedChange |
|
||||||
} |
|
||||||
value = { |
|
||||||
_profile.startWithVideoMuted |
|
||||||
} /> |
|
||||||
</FormRow> |
|
||||||
</ScrollView> |
|
||||||
</SafeAreaView> |
|
||||||
</View> |
|
||||||
</Modal> |
|
||||||
); |
|
||||||
} |
|
||||||
|
|
||||||
_onBlurServerURL: () => void; |
|
||||||
|
|
||||||
/** |
|
||||||
* Handler the server URL lose focus event. Here we validate the server URL |
|
||||||
* and update it to the normalized version, or show an error if incorrect. |
|
||||||
* |
|
||||||
* @private |
|
||||||
* @returns {void} |
|
||||||
*/ |
|
||||||
_onBlurServerURL() { |
|
||||||
this._processServerURL(false /* hideOnSuccess */); |
|
||||||
} |
|
||||||
|
|
||||||
_onChangeDisplayName: (string) => void; |
|
||||||
|
|
||||||
_onChangeEmail: (string) => void; |
|
||||||
|
|
||||||
_onChangeServerURL: (string) => void; |
|
||||||
|
|
||||||
_onStartAudioMutedChange: (boolean) => void; |
|
||||||
|
|
||||||
_onStartVideoMutedChange: (boolean) => void; |
|
||||||
|
|
||||||
/** |
|
||||||
* Processes the server URL. It normalizes it and an error alert is |
|
||||||
* displayed in case it's incorrect. |
|
||||||
* |
|
||||||
* @param {boolean} hideOnSuccess - True if the dialog should be hidden if |
|
||||||
* normalization / validation succeeds, false otherwise. |
|
||||||
* @private |
|
||||||
* @returns {void} |
|
||||||
*/ |
|
||||||
_processServerURL(hideOnSuccess: boolean) { |
|
||||||
const { serverURL } = this.props._profile; |
|
||||||
const normalizedURL = normalizeUserInputURL(serverURL); |
|
||||||
|
|
||||||
if (normalizedURL === null) { |
|
||||||
this._showURLAlert(); |
|
||||||
} else { |
|
||||||
this._onChangeServerURL(normalizedURL); |
|
||||||
if (hideOnSuccess) { |
|
||||||
this.props.dispatch(hideAppSettings()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
_onRequestClose: () => void; |
|
||||||
|
|
||||||
/** |
|
||||||
* Handles the back button. |
|
||||||
* Also invokes normalizeUserInputURL to validate the URL entered |
|
||||||
* by the user. |
|
||||||
* |
|
||||||
* @returns {void} |
|
||||||
*/ |
|
||||||
_onRequestClose() { |
|
||||||
this._processServerURL(true /* hideOnSuccess */); |
|
||||||
} |
|
||||||
|
|
||||||
_setURLFieldReference: (React$ElementRef<*> | null) => void; |
|
||||||
|
|
||||||
/** |
|
||||||
* Stores a reference to the URL field for later use. |
|
||||||
* |
|
||||||
* @protected |
|
||||||
* @param {Object} component - The field component. |
|
||||||
* @returns {void} |
|
||||||
*/ |
|
||||||
_setURLFieldReference(component) { |
|
||||||
this._urlField = component; |
|
||||||
} |
|
||||||
|
|
||||||
_showURLAlert: () => void; |
|
||||||
|
|
||||||
/** |
|
||||||
* Shows an alert telling the user that the URL he/she entered was invalid. |
|
||||||
* |
|
||||||
* @returns {void} |
|
||||||
*/ |
|
||||||
_showURLAlert() { |
|
||||||
const { t } = this.props; |
|
||||||
|
|
||||||
Alert.alert( |
|
||||||
t('settingsScreen.alertTitle'), |
|
||||||
t('settingsScreen.alertURLText'), |
|
||||||
[ |
|
||||||
{ |
|
||||||
onPress: () => this._urlField.focus(), |
|
||||||
text: t('settingsScreen.alertOk') |
|
||||||
} |
|
||||||
] |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export default translate(connect(_mapStateToProps)(AppSettings)); |
|
@ -1 +0,0 @@ |
|||||||
export { default as AppSettings } from './AppSettings'; |
|
@ -1,3 +0,0 @@ |
|||||||
export { default as BackButton } from './BackButton'; |
|
||||||
export { default as FormRow } from './FormRow'; |
|
||||||
export { default as FormSectionHeader } from './FormSectionHeader'; |
|
@ -1,33 +0,0 @@ |
|||||||
import { |
|
||||||
BoxModel, |
|
||||||
ColorPalette, |
|
||||||
createStyleSheet |
|
||||||
} from '../../base/styles'; |
|
||||||
|
|
||||||
/** |
|
||||||
* The styles of the React {@code Components} of the feature |
|
||||||
* {@code app-settings}. |
|
||||||
*/ |
|
||||||
export default createStyleSheet({ |
|
||||||
/** |
|
||||||
* Style of the ScrollView to be able to scroll the content. |
|
||||||
*/ |
|
||||||
scrollView: { |
|
||||||
flex: 1 |
|
||||||
}, |
|
||||||
|
|
||||||
/** |
|
||||||
* Style of the settings screen content (form). |
|
||||||
*/ |
|
||||||
settingsForm: { |
|
||||||
flex: 1, |
|
||||||
margin: BoxModel.margin |
|
||||||
}, |
|
||||||
|
|
||||||
/** |
|
||||||
* Global {@code Text} color for the page. |
|
||||||
*/ |
|
||||||
text: { |
|
||||||
color: ColorPalette.black |
|
||||||
} |
|
||||||
}); |
|
@ -1,31 +0,0 @@ |
|||||||
// @flow
|
|
||||||
|
|
||||||
import { |
|
||||||
HIDE_APP_SETTINGS, |
|
||||||
SHOW_APP_SETTINGS |
|
||||||
} from './actionTypes'; |
|
||||||
|
|
||||||
import { ReducerRegistry } from '../base/redux'; |
|
||||||
|
|
||||||
const DEFAULT_STATE = { |
|
||||||
visible: false |
|
||||||
}; |
|
||||||
|
|
||||||
ReducerRegistry.register( |
|
||||||
'features/app-settings', (state = DEFAULT_STATE, action) => { |
|
||||||
switch (action.type) { |
|
||||||
case HIDE_APP_SETTINGS: |
|
||||||
return { |
|
||||||
...state, |
|
||||||
visible: false |
|
||||||
}; |
|
||||||
|
|
||||||
case SHOW_APP_SETTINGS: |
|
||||||
return { |
|
||||||
...state, |
|
||||||
visible: true |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
return state; |
|
||||||
}); |
|
@ -1,8 +1,7 @@ |
|||||||
export { default as Container } from './Container'; |
export { default as Container } from './Container'; |
||||||
|
export { default as Header } from './Header'; |
||||||
export { default as Link } from './Link'; |
export { default as Link } from './Link'; |
||||||
export { default as LoadingIndicator } from './LoadingIndicator'; |
export { default as LoadingIndicator } from './LoadingIndicator'; |
||||||
export { default as Header } from './Header'; |
|
||||||
export { default as SideBar } from './SideBar'; |
export { default as SideBar } from './SideBar'; |
||||||
export * from './styles'; |
|
||||||
export { default as TintedView } from './TintedView'; |
|
||||||
export { default as Text } from './Text'; |
export { default as Text } from './Text'; |
||||||
|
export { default as TintedView } from './TintedView'; |
||||||
|
@ -1,41 +0,0 @@ |
|||||||
import { ColorPalette } from './ColorPalette'; |
|
||||||
|
|
||||||
import { |
|
||||||
createStyleSheet |
|
||||||
} from '../../functions'; |
|
||||||
|
|
||||||
export const PlatformElements = createStyleSheet({ |
|
||||||
|
|
||||||
/** |
|
||||||
* Platform specific header button (e.g. back, menu...etc). |
|
||||||
*/ |
|
||||||
headerButton: { |
|
||||||
alignSelf: 'center', |
|
||||||
color: ColorPalette.white, |
|
||||||
fontSize: 26, |
|
||||||
paddingRight: 22 |
|
||||||
}, |
|
||||||
|
|
||||||
/** |
|
||||||
* Generic style for a label placed in the header. |
|
||||||
*/ |
|
||||||
headerText: { |
|
||||||
color: ColorPalette.white, |
|
||||||
fontSize: 20 |
|
||||||
}, |
|
||||||
|
|
||||||
/** |
|
||||||
* The topmost level element of a page. |
|
||||||
*/ |
|
||||||
page: { |
|
||||||
alignItems: 'stretch', |
|
||||||
bottom: 0, |
|
||||||
flex: 1, |
|
||||||
flexDirection: 'column', |
|
||||||
left: 0, |
|
||||||
overflow: 'hidden', |
|
||||||
position: 'absolute', |
|
||||||
right: 0, |
|
||||||
top: 0 |
|
||||||
} |
|
||||||
}); |
|
@ -1 +0,0 @@ |
|||||||
export * from './components'; |
|
@ -0,0 +1,10 @@ |
|||||||
|
/** |
||||||
|
* 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 = Symbol('SET_SETTINGS_VIEW_VISIBLE'); |
@ -0,0 +1,20 @@ |
|||||||
|
// @flow
|
||||||
|
|
||||||
|
import { SET_SETTINGS_VIEW_VISIBLE } from './actionTypes'; |
||||||
|
|
||||||
|
/** |
||||||
|
* 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 |
||||||
|
}; |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
export * from './web'; |
@ -0,0 +1 @@ |
|||||||
|
export * from './_'; |
@ -0,0 +1,251 @@ |
|||||||
|
// @flow
|
||||||
|
|
||||||
|
import React from 'react'; |
||||||
|
import { |
||||||
|
Alert, |
||||||
|
Modal, |
||||||
|
SafeAreaView, |
||||||
|
ScrollView, |
||||||
|
Switch, |
||||||
|
Text, |
||||||
|
TextInput, |
||||||
|
View |
||||||
|
} from 'react-native'; |
||||||
|
import { connect } from 'react-redux'; |
||||||
|
|
||||||
|
import { translate } from '../../../base/i18n'; |
||||||
|
import { Header } from '../../../base/react'; |
||||||
|
|
||||||
|
import { |
||||||
|
AbstractSettingsView, |
||||||
|
_mapStateToProps |
||||||
|
} from '../AbstractSettingsView'; |
||||||
|
import { setSettingsViewVisible } from '../../actions'; |
||||||
|
import BackButton from './BackButton'; |
||||||
|
import FormRow from './FormRow'; |
||||||
|
import FormSectionHeader from './FormSectionHeader'; |
||||||
|
import { normalizeUserInputURL } from '../../functions'; |
||||||
|
import styles from './styles'; |
||||||
|
|
||||||
|
/** |
||||||
|
* The native container rendering the app settings page. |
||||||
|
* |
||||||
|
* @extends AbstractSettingsView |
||||||
|
*/ |
||||||
|
class SettingsView extends AbstractSettingsView { |
||||||
|
_urlField: Object; |
||||||
|
|
||||||
|
/** |
||||||
|
* Initializes a new {@code SettingsView} instance. |
||||||
|
* |
||||||
|
* @inheritdoc |
||||||
|
*/ |
||||||
|
constructor(props) { |
||||||
|
super(props); |
||||||
|
|
||||||
|
// Bind event handlers so they are only bound once per instance.
|
||||||
|
this._onBlurServerURL = this._onBlurServerURL.bind(this); |
||||||
|
this._onRequestClose = this._onRequestClose.bind(this); |
||||||
|
this._setURLFieldReference = this._setURLFieldReference.bind(this); |
||||||
|
this._showURLAlert = this._showURLAlert.bind(this); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Implements React's {@link Component#render()}, renders the settings page. |
||||||
|
* |
||||||
|
* @inheritdoc |
||||||
|
* @returns {ReactElement} |
||||||
|
*/ |
||||||
|
render() { |
||||||
|
return ( |
||||||
|
<Modal |
||||||
|
animationType = 'slide' |
||||||
|
onRequestClose = { this._onRequestClose } |
||||||
|
presentationStyle = 'fullScreen' |
||||||
|
supportedOrientations = { [ |
||||||
|
'landscape', |
||||||
|
'portrait' |
||||||
|
] } |
||||||
|
visible = { this.props._visible }> |
||||||
|
<View style = { Header.pageStyle }> |
||||||
|
{ this._renderHeader() } |
||||||
|
{ this._renderBody() } |
||||||
|
</View> |
||||||
|
</Modal> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
_onBlurServerURL: () => void; |
||||||
|
|
||||||
|
/** |
||||||
|
* Handler the server URL lose focus event. Here we validate the server URL |
||||||
|
* and update it to the normalized version, or show an error if incorrect. |
||||||
|
* |
||||||
|
* @private |
||||||
|
* @returns {void} |
||||||
|
*/ |
||||||
|
_onBlurServerURL() { |
||||||
|
this._processServerURL(false /* hideOnSuccess */); |
||||||
|
} |
||||||
|
|
||||||
|
_onChangeDisplayName: (string) => void; |
||||||
|
|
||||||
|
_onChangeEmail: (string) => void; |
||||||
|
|
||||||
|
_onChangeServerURL: (string) => void; |
||||||
|
|
||||||
|
_onRequestClose: () => void; |
||||||
|
|
||||||
|
/** |
||||||
|
* Handles the back button. Also invokes normalizeUserInputURL to validate |
||||||
|
* the URL entered by the user. |
||||||
|
* |
||||||
|
* @returns {void} |
||||||
|
*/ |
||||||
|
_onRequestClose() { |
||||||
|
this._processServerURL(true /* hideOnSuccess */); |
||||||
|
} |
||||||
|
|
||||||
|
_onStartAudioMutedChange: (boolean) => void; |
||||||
|
|
||||||
|
_onStartVideoMutedChange: (boolean) => void; |
||||||
|
|
||||||
|
/** |
||||||
|
* Processes the server URL. It normalizes it and an error alert is |
||||||
|
* displayed in case it's incorrect. |
||||||
|
* |
||||||
|
* @param {boolean} hideOnSuccess - True if the dialog should be hidden if |
||||||
|
* normalization / validation succeeds, false otherwise. |
||||||
|
* @private |
||||||
|
* @returns {void} |
||||||
|
*/ |
||||||
|
_processServerURL(hideOnSuccess: boolean) { |
||||||
|
const { serverURL } = this.props._profile; |
||||||
|
const normalizedURL = normalizeUserInputURL(serverURL); |
||||||
|
|
||||||
|
if (normalizedURL === null) { |
||||||
|
this._showURLAlert(); |
||||||
|
} else { |
||||||
|
this._onChangeServerURL(normalizedURL); |
||||||
|
if (hideOnSuccess) { |
||||||
|
this.props.dispatch(setSettingsViewVisible(false)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Renders the body (under the header) of {@code SettingsView}. |
||||||
|
* |
||||||
|
* @private |
||||||
|
* @returns {React$Element} |
||||||
|
*/ |
||||||
|
_renderBody() { |
||||||
|
const { _profile } = this.props; |
||||||
|
|
||||||
|
return ( |
||||||
|
<SafeAreaView style = { styles.settingsForm }> |
||||||
|
<ScrollView> |
||||||
|
<FormSectionHeader |
||||||
|
i18nLabel = 'settingsView.profileSection' /> |
||||||
|
<FormRow |
||||||
|
fieldSeparator = { true } |
||||||
|
i18nLabel = 'settingsView.displayName'> |
||||||
|
<TextInput |
||||||
|
onChangeText = { this._onChangeDisplayName } |
||||||
|
placeholder = 'John Doe' |
||||||
|
value = { _profile.displayName } /> |
||||||
|
</FormRow> |
||||||
|
<FormRow i18nLabel = 'settingsView.email'> |
||||||
|
<TextInput |
||||||
|
keyboardType = { 'email-address' } |
||||||
|
onChangeText = { this._onChangeEmail } |
||||||
|
placeholder = 'email@example.com' |
||||||
|
value = { _profile.email } /> |
||||||
|
</FormRow> |
||||||
|
<FormSectionHeader |
||||||
|
i18nLabel = 'settingsView.conferenceSection' /> |
||||||
|
<FormRow |
||||||
|
fieldSeparator = { true } |
||||||
|
i18nLabel = 'settingsView.serverURL'> |
||||||
|
<TextInput |
||||||
|
autoCapitalize = 'none' |
||||||
|
onBlur = { this._onBlurServerURL } |
||||||
|
onChangeText = { this._onChangeServerURL } |
||||||
|
placeholder = { this.props._serverURL } |
||||||
|
value = { _profile.serverURL } /> |
||||||
|
</FormRow> |
||||||
|
<FormRow |
||||||
|
fieldSeparator = { true } |
||||||
|
i18nLabel = 'settingsView.startWithAudioMuted'> |
||||||
|
<Switch |
||||||
|
onValueChange = { this._onStartAudioMutedChange } |
||||||
|
value = { _profile.startWithAudioMuted } /> |
||||||
|
</FormRow> |
||||||
|
<FormRow i18nLabel = 'settingsView.startWithVideoMuted'> |
||||||
|
<Switch |
||||||
|
onValueChange = { this._onStartVideoMutedChange } |
||||||
|
value = { _profile.startWithVideoMuted } /> |
||||||
|
</FormRow> |
||||||
|
</ScrollView> |
||||||
|
</SafeAreaView> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Renders the header of {@code SettingsView}. |
||||||
|
* |
||||||
|
* @private |
||||||
|
* @returns {React$Element} |
||||||
|
*/ |
||||||
|
_renderHeader() { |
||||||
|
return ( |
||||||
|
<Header> |
||||||
|
<BackButton onPress = { this._onRequestClose } /> |
||||||
|
<Text |
||||||
|
style = { [ |
||||||
|
styles.text, |
||||||
|
Header.textStyle |
||||||
|
] }> |
||||||
|
{ this.props.t('settingsView.header') } |
||||||
|
</Text> |
||||||
|
</Header> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
_setURLFieldReference: (React$ElementRef<*> | null) => void; |
||||||
|
|
||||||
|
/** |
||||||
|
* Stores a reference to the URL field for later use. |
||||||
|
* |
||||||
|
* @param {Object} component - The field component. |
||||||
|
* @protected |
||||||
|
* @returns {void} |
||||||
|
*/ |
||||||
|
_setURLFieldReference(component) { |
||||||
|
this._urlField = component; |
||||||
|
} |
||||||
|
|
||||||
|
_showURLAlert: () => void; |
||||||
|
|
||||||
|
/** |
||||||
|
* Shows an alert telling the user that the URL he/she entered was invalid. |
||||||
|
* |
||||||
|
* @returns {void} |
||||||
|
*/ |
||||||
|
_showURLAlert() { |
||||||
|
const { t } = this.props; |
||||||
|
|
||||||
|
Alert.alert( |
||||||
|
t('settingsView.alertTitle'), |
||||||
|
t('settingsView.alertURLText'), |
||||||
|
[ |
||||||
|
{ |
||||||
|
onPress: () => this._urlField.focus(), |
||||||
|
text: t('settingsView.alertOk') |
||||||
|
} |
||||||
|
] |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default translate(connect(_mapStateToProps)(SettingsView)); |
@ -0,0 +1 @@ |
|||||||
|
export { default as SettingsView } from './SettingsView'; |
@ -1,4 +1,6 @@ |
|||||||
export * from './actions'; |
export * from './actions'; |
||||||
|
export * from './actionTypes'; |
||||||
export * from './components'; |
export * from './components'; |
||||||
|
|
||||||
|
import './middleware'; |
||||||
import './reducer'; |
import './reducer'; |
@ -0,0 +1,17 @@ |
|||||||
|
// @flow
|
||||||
|
|
||||||
|
import { ReducerRegistry } from '../base/redux'; |
||||||
|
|
||||||
|
import { SET_SETTINGS_VIEW_VISIBLE } from './actionTypes'; |
||||||
|
|
||||||
|
ReducerRegistry.register('features/settings', (state = {}, action) => { |
||||||
|
switch (action.type) { |
||||||
|
case SET_SETTINGS_VIEW_VISIBLE: |
||||||
|
return { |
||||||
|
...state, |
||||||
|
visible: action.visible |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
return state; |
||||||
|
}); |
@ -1,4 +1,10 @@ |
|||||||
/** |
/** |
||||||
* Action type to signal the need to hide or show the side bar. |
* The type of the (redux) action which sets the visibility of |
||||||
|
* {@link WelcomePageSideBar}. |
||||||
|
* |
||||||
|
* { |
||||||
|
* type: SET_SIDEBAR_VISIBLE, |
||||||
|
* visible: boolean |
||||||
|
* } |
||||||
*/ |
*/ |
||||||
export const SET_SIDEBAR_VISIBILITY = Symbol('SET_SIDEBAR_VISIBILITY'); |
export const SET_SIDEBAR_VISIBLE = Symbol('SET_SIDEBAR_VISIBLE'); |
||||||
|
@ -1,19 +1,20 @@ |
|||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import { SET_SIDEBAR_VISIBILITY } from './actionTypes'; |
import { SET_SIDEBAR_VISIBLE } from './actionTypes'; |
||||||
|
|
||||||
/** |
/** |
||||||
* Redux action to hide or show the status bar. |
* Sets the visibility of {@link WelcomePageSideBar}. |
||||||
* |
* |
||||||
* @param {boolean} visible - The new value of the visibility. |
* @param {boolean} visible - If the {@code WelcomePageSideBar} is to be made |
||||||
|
* visible, {@code true}; otherwise, {@code false}. |
||||||
* @returns {{ |
* @returns {{ |
||||||
* type: SET_SIDEBAR_VISIBILITY, |
* type: SET_SIDEBAR_VISIBLE, |
||||||
* sideBarVisible: boolean |
* visible: boolean |
||||||
* }} |
* }} |
||||||
*/ |
*/ |
||||||
export function setSideBarVisibility(visible: boolean) { |
export function setSideBarVisible(visible: boolean) { |
||||||
return { |
return { |
||||||
type: SET_SIDEBAR_VISIBILITY, |
type: SET_SIDEBAR_VISIBLE, |
||||||
sideBarVisible: visible |
visible |
||||||
}; |
}; |
||||||
} |
} |
||||||
|
@ -1,5 +1,5 @@ |
|||||||
import './reducer'; |
|
||||||
import './route'; |
|
||||||
|
|
||||||
export * from './components'; |
export * from './components'; |
||||||
export * from './functions'; |
export * from './functions'; |
||||||
|
|
||||||
|
import './reducer'; |
||||||
|
import './route'; |
||||||
|
@ -1,23 +1,20 @@ |
|||||||
import { ReducerRegistry } from '../base/redux'; |
// @flow
|
||||||
import { SET_SIDEBAR_VISIBILITY } from './actionTypes'; |
|
||||||
|
|
||||||
const DEFAULT_STATE = { |
import { ReducerRegistry } from '../base/redux'; |
||||||
sideBarVisible: false |
import { SET_SIDEBAR_VISIBLE } from './actionTypes'; |
||||||
}; |
|
||||||
|
|
||||||
/** |
/** |
||||||
* Reduces the Redux actions of the feature features/recording. |
* Reduces redux actions for the purposes of {@code features/welcome}. |
||||||
*/ |
*/ |
||||||
ReducerRegistry.register('features/welcome', |
ReducerRegistry.register('features/welcome', (state = {}, action) => { |
||||||
(state = DEFAULT_STATE, action) => { |
switch (action.type) { |
||||||
switch (action.type) { |
case SET_SIDEBAR_VISIBLE: |
||||||
case SET_SIDEBAR_VISIBILITY: |
return { |
||||||
return { |
...state, |
||||||
...state, |
sideBarVisible: action.visible |
||||||
sideBarVisible: action.sideBarVisible |
}; |
||||||
}; |
|
||||||
|
|
||||||
default: |
default: |
||||||
return state; |
return state; |
||||||
} |
} |
||||||
}); |
}); |
||||||
|
Loading…
Reference in new issue