|
@@ -1,37 +1,29 @@
|
1
|
1
|
// @flow
|
2
|
2
|
|
3
|
3
|
import React from 'react';
|
4
|
|
-import { Alert, NativeModules, SafeAreaView, ScrollView, Switch, Text, TextInput, View } from 'react-native';
|
|
4
|
+import { Alert, NativeModules, ScrollView, Switch, Text, TextInput } from 'react-native';
|
5
|
5
|
|
6
|
|
-import { ColorSchemeRegistry } from '../../../base/color-scheme';
|
7
|
6
|
import { translate } from '../../../base/i18n';
|
8
|
|
-import { HeaderWithNavigation, Modal } from '../../../base/react';
|
|
7
|
+import { JitsiModal } from '../../../base/modal';
|
9
|
8
|
import { connect } from '../../../base/redux';
|
10
|
9
|
|
|
10
|
+import { SETTINGS_VIEW_ID } from '../../constants';
|
|
11
|
+import { normalizeUserInputURL } from '../../functions';
|
|
12
|
+
|
11
|
13
|
import {
|
12
|
14
|
AbstractSettingsView,
|
13
|
15
|
_mapStateToProps as _abstractMapStateToProps,
|
14
|
|
- type Props as AbstractProps
|
|
16
|
+ type Props
|
15
|
17
|
} from '../AbstractSettingsView';
|
16
|
|
-import { setSettingsViewVisible } from '../../actions';
|
|
18
|
+
|
17
|
19
|
import FormRow from './FormRow';
|
18
|
20
|
import FormSectionHeader from './FormSectionHeader';
|
19
|
|
-import { normalizeUserInputURL } from '../../functions';
|
20
|
|
-import styles from './styles';
|
21
|
21
|
|
22
|
22
|
/**
|
23
|
23
|
* Application information module.
|
24
|
24
|
*/
|
25
|
25
|
const { AppInfo } = NativeModules;
|
26
|
26
|
|
27
|
|
-type Props = AbstractProps & {
|
28
|
|
-
|
29
|
|
- /**
|
30
|
|
- * Color schemed style of the header component.
|
31
|
|
- */
|
32
|
|
- _headerStyles: Object
|
33
|
|
-}
|
34
|
|
-
|
35
|
27
|
type State = {
|
36
|
28
|
|
37
|
29
|
/**
|
|
@@ -113,9 +105,9 @@ class SettingsView extends AbstractSettingsView<Props, State> {
|
113
|
105
|
|
114
|
106
|
// Bind event handlers so they are only bound once per instance.
|
115
|
107
|
this._onBlurServerURL = this._onBlurServerURL.bind(this);
|
|
108
|
+ this._onClose = this._onClose.bind(this);
|
116
|
109
|
this._onDisableCallIntegration = this._onDisableCallIntegration.bind(this);
|
117
|
110
|
this._onDisableP2P = this._onDisableP2P.bind(this);
|
118
|
|
- this._onRequestClose = this._onRequestClose.bind(this);
|
119
|
111
|
this._onShowAdvanced = this._onShowAdvanced.bind(this);
|
120
|
112
|
this._setURLFieldReference = this._setURLFieldReference.bind(this);
|
121
|
113
|
this._showURLAlert = this._showURLAlert.bind(this);
|
|
@@ -128,16 +120,78 @@ class SettingsView extends AbstractSettingsView<Props, State> {
|
128
|
120
|
* @returns {ReactElement}
|
129
|
121
|
*/
|
130
|
122
|
render() {
|
|
123
|
+ const { displayName, email, serverURL, startWithAudioMuted, startWithVideoMuted } = this.state;
|
|
124
|
+
|
131
|
125
|
return (
|
132
|
|
- <Modal
|
133
|
|
- onRequestClose = { this._onRequestClose }
|
134
|
|
- presentationStyle = 'overFullScreen'
|
135
|
|
- visible = { this.props._visible }>
|
136
|
|
- <View style = { this.props._headerStyles.page }>
|
137
|
|
- { this._renderHeader() }
|
138
|
|
- { this._renderBody() }
|
139
|
|
- </View>
|
140
|
|
- </Modal>
|
|
126
|
+ <JitsiModal
|
|
127
|
+ headerProps = {{
|
|
128
|
+ headerLabelKey: 'settingsView.header'
|
|
129
|
+ }}
|
|
130
|
+ modalId = { SETTINGS_VIEW_ID }
|
|
131
|
+ onClose = { this._onClose }>
|
|
132
|
+ <ScrollView>
|
|
133
|
+ <FormSectionHeader
|
|
134
|
+ label = 'settingsView.profileSection' />
|
|
135
|
+ <FormRow
|
|
136
|
+ fieldSeparator = { true }
|
|
137
|
+ label = 'settingsView.displayName'
|
|
138
|
+ layout = 'column'>
|
|
139
|
+ <TextInput
|
|
140
|
+ autoCorrect = { false }
|
|
141
|
+ onChangeText = { this._onChangeDisplayName }
|
|
142
|
+ placeholder = 'John Doe'
|
|
143
|
+ value = { displayName } />
|
|
144
|
+ </FormRow>
|
|
145
|
+ <FormRow
|
|
146
|
+ label = 'settingsView.email'
|
|
147
|
+ layout = 'column'>
|
|
148
|
+ <TextInput
|
|
149
|
+ autoCapitalize = 'none'
|
|
150
|
+ autoCorrect = { false }
|
|
151
|
+ keyboardType = { 'email-address' }
|
|
152
|
+ onChangeText = { this._onChangeEmail }
|
|
153
|
+ placeholder = 'email@example.com'
|
|
154
|
+ value = { email } />
|
|
155
|
+ </FormRow>
|
|
156
|
+ <FormSectionHeader
|
|
157
|
+ label = 'settingsView.conferenceSection' />
|
|
158
|
+ <FormRow
|
|
159
|
+ fieldSeparator = { true }
|
|
160
|
+ label = 'settingsView.serverURL'
|
|
161
|
+ layout = 'column'>
|
|
162
|
+ <TextInput
|
|
163
|
+ autoCapitalize = 'none'
|
|
164
|
+ autoCorrect = { false }
|
|
165
|
+ onBlur = { this._onBlurServerURL }
|
|
166
|
+ onChangeText = { this._onChangeServerURL }
|
|
167
|
+ placeholder = { this.props._serverURL }
|
|
168
|
+ value = { serverURL } />
|
|
169
|
+ </FormRow>
|
|
170
|
+ <FormRow
|
|
171
|
+ fieldSeparator = { true }
|
|
172
|
+ label = 'settingsView.startWithAudioMuted'>
|
|
173
|
+ <Switch
|
|
174
|
+ onValueChange = { this._onStartAudioMutedChange }
|
|
175
|
+ value = { startWithAudioMuted } />
|
|
176
|
+ </FormRow>
|
|
177
|
+ <FormRow label = 'settingsView.startWithVideoMuted'>
|
|
178
|
+ <Switch
|
|
179
|
+ onValueChange = { this._onStartVideoMutedChange }
|
|
180
|
+ value = { startWithVideoMuted } />
|
|
181
|
+ </FormRow>
|
|
182
|
+ <FormSectionHeader
|
|
183
|
+ label = 'settingsView.buildInfoSection' />
|
|
184
|
+ <FormRow
|
|
185
|
+ label = 'settingsView.version'>
|
|
186
|
+ <Text>
|
|
187
|
+ { `${AppInfo.version} build ${AppInfo.buildNumber}` }
|
|
188
|
+ </Text>
|
|
189
|
+ </FormRow>
|
|
190
|
+ <FormSectionHeader
|
|
191
|
+ label = 'settingsView.advanced' />
|
|
192
|
+ { this._renderAdvancedSettings() }
|
|
193
|
+ </ScrollView>
|
|
194
|
+ </JitsiModal>
|
141
|
195
|
);
|
142
|
196
|
}
|
143
|
197
|
|
|
@@ -231,17 +285,18 @@ class SettingsView extends AbstractSettingsView<Props, State> {
|
231
|
285
|
});
|
232
|
286
|
}
|
233
|
287
|
|
234
|
|
- _onRequestClose: () => void;
|
|
288
|
+ _onClose: () => void;
|
235
|
289
|
|
236
|
290
|
/**
|
237
|
|
- * Handles the back button. Also invokes normalizeUserInputURL to validate
|
|
291
|
+ * Callback to be invoked on closing the modal. Also invokes normalizeUserInputURL to validate
|
238
|
292
|
* the URL entered by the user.
|
239
|
293
|
*
|
240
|
|
- * @returns {void}
|
|
294
|
+ * @returns {boolean} - True if the modal can be closed.
|
241
|
295
|
*/
|
242
|
|
- _onRequestClose() {
|
|
296
|
+ _onClose() {
|
243
|
297
|
this.setState({ showAdvanced: false });
|
244
|
|
- this._processServerURL(true /* hideOnSuccess */);
|
|
298
|
+
|
|
299
|
+ return this._processServerURL(true /* hideOnSuccess */);
|
245
|
300
|
}
|
246
|
301
|
|
247
|
302
|
_onShowAdvanced: () => void;
|
|
@@ -296,12 +351,13 @@ class SettingsView extends AbstractSettingsView<Props, State> {
|
296
|
351
|
|
297
|
352
|
if (normalizedURL === null) {
|
298
|
353
|
this._showURLAlert();
|
299
|
|
- } else {
|
300
|
|
- this._onChangeServerURL(normalizedURL);
|
301
|
|
- if (hideOnSuccess) {
|
302
|
|
- this.props.dispatch(setSettingsViewVisible(false));
|
303
|
|
- }
|
|
354
|
+
|
|
355
|
+ return false;
|
304
|
356
|
}
|
|
357
|
+
|
|
358
|
+ this._onChangeServerURL(normalizedURL);
|
|
359
|
+
|
|
360
|
+ return hideOnSuccess;
|
305
|
361
|
}
|
306
|
362
|
|
307
|
363
|
/**
|
|
@@ -345,97 +401,6 @@ class SettingsView extends AbstractSettingsView<Props, State> {
|
345
|
401
|
);
|
346
|
402
|
}
|
347
|
403
|
|
348
|
|
- /**
|
349
|
|
- * Renders the body (under the header) of {@code SettingsView}.
|
350
|
|
- *
|
351
|
|
- * @private
|
352
|
|
- * @returns {React$Element}
|
353
|
|
- */
|
354
|
|
- _renderBody() {
|
355
|
|
- const { displayName, email, serverURL, startWithAudioMuted, startWithVideoMuted } = this.state;
|
356
|
|
-
|
357
|
|
- return (
|
358
|
|
- <SafeAreaView style = { styles.settingsForm }>
|
359
|
|
- <ScrollView>
|
360
|
|
- <FormSectionHeader
|
361
|
|
- label = 'settingsView.profileSection' />
|
362
|
|
- <FormRow
|
363
|
|
- fieldSeparator = { true }
|
364
|
|
- label = 'settingsView.displayName'
|
365
|
|
- layout = 'column'>
|
366
|
|
- <TextInput
|
367
|
|
- autoCorrect = { false }
|
368
|
|
- onChangeText = { this._onChangeDisplayName }
|
369
|
|
- placeholder = 'John Doe'
|
370
|
|
- value = { displayName } />
|
371
|
|
- </FormRow>
|
372
|
|
- <FormRow
|
373
|
|
- label = 'settingsView.email'
|
374
|
|
- layout = 'column'>
|
375
|
|
- <TextInput
|
376
|
|
- autoCapitalize = 'none'
|
377
|
|
- autoCorrect = { false }
|
378
|
|
- keyboardType = { 'email-address' }
|
379
|
|
- onChangeText = { this._onChangeEmail }
|
380
|
|
- placeholder = 'email@example.com'
|
381
|
|
- value = { email } />
|
382
|
|
- </FormRow>
|
383
|
|
- <FormSectionHeader
|
384
|
|
- label = 'settingsView.conferenceSection' />
|
385
|
|
- <FormRow
|
386
|
|
- fieldSeparator = { true }
|
387
|
|
- label = 'settingsView.serverURL'
|
388
|
|
- layout = 'column'>
|
389
|
|
- <TextInput
|
390
|
|
- autoCapitalize = 'none'
|
391
|
|
- autoCorrect = { false }
|
392
|
|
- onBlur = { this._onBlurServerURL }
|
393
|
|
- onChangeText = { this._onChangeServerURL }
|
394
|
|
- placeholder = { this.props._serverURL }
|
395
|
|
- value = { serverURL } />
|
396
|
|
- </FormRow>
|
397
|
|
- <FormRow
|
398
|
|
- fieldSeparator = { true }
|
399
|
|
- label = 'settingsView.startWithAudioMuted'>
|
400
|
|
- <Switch
|
401
|
|
- onValueChange = { this._onStartAudioMutedChange }
|
402
|
|
- value = { startWithAudioMuted } />
|
403
|
|
- </FormRow>
|
404
|
|
- <FormRow label = 'settingsView.startWithVideoMuted'>
|
405
|
|
- <Switch
|
406
|
|
- onValueChange = { this._onStartVideoMutedChange }
|
407
|
|
- value = { startWithVideoMuted } />
|
408
|
|
- </FormRow>
|
409
|
|
- <FormSectionHeader
|
410
|
|
- label = 'settingsView.buildInfoSection' />
|
411
|
|
- <FormRow
|
412
|
|
- label = 'settingsView.version'>
|
413
|
|
- <Text>
|
414
|
|
- { `${AppInfo.version} build ${AppInfo.buildNumber}` }
|
415
|
|
- </Text>
|
416
|
|
- </FormRow>
|
417
|
|
- <FormSectionHeader
|
418
|
|
- label = 'settingsView.advanced' />
|
419
|
|
- { this._renderAdvancedSettings() }
|
420
|
|
- </ScrollView>
|
421
|
|
- </SafeAreaView>
|
422
|
|
- );
|
423
|
|
- }
|
424
|
|
-
|
425
|
|
- /**
|
426
|
|
- * Renders the header of {@code SettingsView}.
|
427
|
|
- *
|
428
|
|
- * @private
|
429
|
|
- * @returns {React$Element}
|
430
|
|
- */
|
431
|
|
- _renderHeader() {
|
432
|
|
- return (
|
433
|
|
- <HeaderWithNavigation
|
434
|
|
- headerLabelKey = 'settingsView.header'
|
435
|
|
- onPressBack = { this._onRequestClose } />
|
436
|
|
- );
|
437
|
|
- }
|
438
|
|
-
|
439
|
404
|
_setURLFieldReference: (React$ElementRef<*> | null) => void;
|
440
|
405
|
|
441
|
406
|
/**
|
|
@@ -478,14 +443,11 @@ class SettingsView extends AbstractSettingsView<Props, State> {
|
478
|
443
|
* Maps part of the Redux state to the props of this component.
|
479
|
444
|
*
|
480
|
445
|
* @param {Object} state - The Redux state.
|
481
|
|
- * @returns {{
|
482
|
|
- * _headerStyles: Object
|
483
|
|
- * }}
|
|
446
|
+ * @returns {Props}
|
484
|
447
|
*/
|
485
|
448
|
function _mapStateToProps(state) {
|
486
|
449
|
return {
|
487
|
|
- ..._abstractMapStateToProps(state),
|
488
|
|
- _headerStyles: ColorSchemeRegistry.get(state, 'Header')
|
|
450
|
+ ..._abstractMapStateToProps(state)
|
489
|
451
|
};
|
490
|
452
|
}
|
491
|
453
|
|