feat(settings/native): fixed scroll inside screen (#12395)
* feat(settings): fixed scroll, bottom insets and bounce
This commit is contained in:
parent
a082a3fb0f
commit
4d817af060
|
@ -1,7 +1,6 @@
|
|||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import { ScrollView, View } from 'react-native';
|
||||
import { View } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
|
||||
import { StyleType } from '../../styles';
|
||||
|
@ -20,7 +19,7 @@ type Props = {
|
|||
/**
|
||||
* The children component(s) of the Modal, to be rendered.
|
||||
*/
|
||||
children: React$Node,
|
||||
children: React.ReactNode,
|
||||
|
||||
/**
|
||||
* Disabled forced keyboard dismiss?
|
||||
|
@ -47,11 +46,6 @@ type Props = {
|
|||
*/
|
||||
safeAreaInsets?: Array,
|
||||
|
||||
/**
|
||||
* Enable scroll for JitsiScreen.
|
||||
*/
|
||||
scrollEnabled?: boolean,
|
||||
|
||||
/**
|
||||
* Additional style to be appended to the KeyboardAvoidingView containing the content of the modal.
|
||||
*/
|
||||
|
@ -66,7 +60,6 @@ const JitsiScreen = ({
|
|||
hasBottomTextInput = false,
|
||||
disableForcedKeyboardDismiss = false,
|
||||
safeAreaInsets = [ 'left', 'right' ],
|
||||
scrollEnabled = false,
|
||||
style
|
||||
}: Props) => {
|
||||
const renderContent = () => (
|
||||
|
@ -85,16 +78,6 @@ const JitsiScreen = ({
|
|||
</JitsiKeyboardAvoidingView>
|
||||
);
|
||||
|
||||
if (scrollEnabled) {
|
||||
return (
|
||||
<ScrollView
|
||||
bounces = { false }
|
||||
style = { styles.jitsiScreenContainer }>
|
||||
{ renderContent() }
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style = { styles.jitsiScreenContainer }>
|
||||
{ renderContent() }
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
// @flow
|
||||
|
||||
import { ColorSchemeRegistry, schemeColor } from '../../color-scheme';
|
||||
|
||||
export default {
|
||||
|
||||
|
@ -12,10 +9,3 @@ export default {
|
|||
flex: 1
|
||||
}
|
||||
};
|
||||
|
||||
ColorSchemeRegistry.register('Modal', {
|
||||
page: {
|
||||
alignItems: 'stretch',
|
||||
backgroundColor: schemeColor('background')
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { NavigationContainer } from '@react-navigation/native';
|
||||
import { createStackNavigator } from '@react-navigation/stack';
|
||||
import React from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import HelpView from '../../../../../settings/components/native/HelpView';
|
||||
|
@ -38,6 +38,14 @@ const SettingsNavigationContainer = ({ isInWelcomePage }: Props) => {
|
|||
const baseSettingsScreenOptions = isInWelcomePage ? welcomeScreenOptions : settingsScreenOptions;
|
||||
const { t } = useTranslation();
|
||||
|
||||
const SettingsScreen = useCallback(() =>
|
||||
(
|
||||
<SettingsView
|
||||
addBottomInset = { !isInWelcomePage }
|
||||
scrollBounces = { isInWelcomePage } />
|
||||
)
|
||||
);
|
||||
|
||||
return (
|
||||
<NavigationContainer
|
||||
independent = { true }
|
||||
|
@ -46,12 +54,13 @@ const SettingsNavigationContainer = ({ isInWelcomePage }: Props) => {
|
|||
<SettingsStack.Navigator
|
||||
initialRouteName = { screen.settings.main }>
|
||||
<SettingsStack.Screen
|
||||
component = { SettingsView }
|
||||
name = { screen.settings.main }
|
||||
options = {{
|
||||
...baseSettingsScreenOptions,
|
||||
title: t('settings.title')
|
||||
}} />
|
||||
}}>
|
||||
{ SettingsScreen }
|
||||
</SettingsStack.Screen>
|
||||
<SettingsStack.Screen
|
||||
component = { HelpView }
|
||||
name = { screen.settings.links.help }
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
Alert,
|
||||
NativeModules,
|
||||
Platform,
|
||||
ScrollView,
|
||||
Text,
|
||||
View
|
||||
} from 'react-native';
|
||||
|
@ -150,6 +151,11 @@ interface Props extends WithTranslation {
|
|||
*/
|
||||
_visible: boolean;
|
||||
|
||||
/**
|
||||
* Add bottom padding to the screen.
|
||||
*/
|
||||
addBottomInset?: boolean;
|
||||
|
||||
/**
|
||||
* Redux store dispatch function.
|
||||
*/
|
||||
|
@ -159,6 +165,11 @@ interface Props extends WithTranslation {
|
|||
* Default prop for navigating between screen components(React Navigation).
|
||||
*/
|
||||
navigation: Object;
|
||||
|
||||
/**
|
||||
* Bounce when scrolling.
|
||||
*/
|
||||
scrollBounces?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -258,7 +269,11 @@ class SettingsView extends Component<Props, State> {
|
|||
startWithVideoMuted
|
||||
} = this.state;
|
||||
|
||||
const { t } = this.props;
|
||||
const {
|
||||
addBottomInset = false,
|
||||
scrollBounces = false,
|
||||
t
|
||||
} = this.props;
|
||||
|
||||
const textInputTheme = {
|
||||
colors: {
|
||||
|
@ -272,157 +287,159 @@ class SettingsView extends Component<Props, State> {
|
|||
|
||||
return (
|
||||
<JitsiScreen
|
||||
safeAreaInsets = { [ 'bottom', 'left', 'right' ] }
|
||||
scrollEnabled = { true }
|
||||
disableForcedKeyboardDismiss = { true }
|
||||
safeAreaInsets = { [ addBottomInset && 'bottom', 'left', 'right' ].filter(Boolean) }
|
||||
style = { styles.settingsViewContainer }>
|
||||
<View style = { styles.avatarContainer }>
|
||||
<Avatar
|
||||
participantId = { this.props._localParticipantId }
|
||||
size = { AVATAR_SIZE } />
|
||||
</View>
|
||||
<FormSectionAccordion
|
||||
label = 'settingsView.profileSection'>
|
||||
<TextInput
|
||||
autoCorrect = { false }
|
||||
label = { t('settingsView.displayName') }
|
||||
mode = 'outlined'
|
||||
onChangeText = { this._onChangeDisplayName }
|
||||
placeholder = { t('settingsView.displayNamePlaceholderText') }
|
||||
placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
|
||||
spellCheck = { false }
|
||||
style = { styles.textInputContainer }
|
||||
textContentType = { 'name' } // iOS only
|
||||
theme = { textInputTheme }
|
||||
value = { displayName } />
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<TextInput
|
||||
autoCapitalize = 'none'
|
||||
autoCorrect = { false }
|
||||
keyboardType = { 'email-address' }
|
||||
label = { t('settingsView.email') }
|
||||
mode = 'outlined'
|
||||
onChangeText = { this._onChangeEmail }
|
||||
placeholder = 'email@example.com'
|
||||
placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
|
||||
spellCheck = { false }
|
||||
style = { styles.textInputContainer }
|
||||
textContentType = { 'emailAddress' } // iOS only
|
||||
theme = { textInputTheme }
|
||||
value = { email } />
|
||||
</FormSectionAccordion>
|
||||
<FormSectionAccordion
|
||||
label = 'settingsView.conferenceSection'>
|
||||
<TextInput
|
||||
autoCapitalize = 'none'
|
||||
autoCorrect = { false }
|
||||
editable = { this.props._serverURLChangeEnabled }
|
||||
keyboardType = { 'url' }
|
||||
label = { t('settingsView.serverURL') }
|
||||
mode = 'outlined'
|
||||
onBlur = { this._onBlurServerURL }
|
||||
onChangeText = { this._onChangeServerURL }
|
||||
placeholder = { this.props._serverURL }
|
||||
placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
|
||||
spellCheck = { false }
|
||||
style = { styles.textInputContainer }
|
||||
textContentType = { 'URL' } // iOS only
|
||||
theme = { textInputTheme }
|
||||
value = { serverURL } />
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<FormRow label = 'settingsView.startCarModeInLowBandwidthMode'>
|
||||
<Switch
|
||||
checked = { startCarMode }
|
||||
// @ts-ignore
|
||||
onChange = { this._onStartCarmodeInLowBandwidthMode } />
|
||||
</FormRow>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<FormRow
|
||||
label = 'settingsView.startWithAudioMuted'>
|
||||
<Switch
|
||||
checked = { startWithAudioMuted }
|
||||
// @ts-ignore
|
||||
onChange = { this._onStartAudioMutedChange } />
|
||||
</FormRow>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<FormRow label = 'settingsView.startWithVideoMuted'>
|
||||
<Switch
|
||||
checked = { startWithVideoMuted }
|
||||
// @ts-ignore
|
||||
onChange = { this._onStartVideoMutedChange } />
|
||||
</FormRow>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<FormRow label = 'videothumbnail.hideSelfView'>
|
||||
<Switch
|
||||
checked = { disableSelfView }
|
||||
// @ts-ignore
|
||||
onChange = { this._onDisableSelfView } />
|
||||
</FormRow>
|
||||
</FormSectionAccordion>
|
||||
<FormSectionAccordion
|
||||
label = 'settingsView.links'>
|
||||
<Link
|
||||
style = { styles.sectionLink }
|
||||
// @ts-ignore
|
||||
to = {{ screen: screen.settings.links.help }}>
|
||||
{ t('settingsView.help') }
|
||||
</Link>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<Link
|
||||
style = { styles.sectionLink }
|
||||
// @ts-ignore
|
||||
to = {{ screen: screen.settings.links.terms }}>
|
||||
{ t('settingsView.terms') }
|
||||
</Link>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<Link
|
||||
style = { styles.sectionLink }
|
||||
// @ts-ignore
|
||||
to = {{ screen: screen.settings.links.privacy }}>
|
||||
{ t('settingsView.privacy') }
|
||||
</Link>
|
||||
</FormSectionAccordion>
|
||||
<FormSectionAccordion
|
||||
label = 'settingsView.buildInfoSection'>
|
||||
<FormRow
|
||||
label = 'settingsView.version'>
|
||||
<Text style = { styles.text }>
|
||||
{`${AppInfo.version} build ${AppInfo.buildNumber}`}
|
||||
</Text>
|
||||
</FormRow>
|
||||
</FormSectionAccordion>
|
||||
<FormSectionAccordion
|
||||
label = 'settingsView.advanced'>
|
||||
{ Platform.OS === 'android' && (
|
||||
<>
|
||||
<FormRow
|
||||
label = 'settingsView.disableCallIntegration'>
|
||||
<Switch
|
||||
checked = { disableCallIntegration }
|
||||
// @ts-ignore
|
||||
onChange = { this._onDisableCallIntegration } />
|
||||
</FormRow>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
</>
|
||||
)}
|
||||
<FormRow
|
||||
label = 'settingsView.disableP2P'>
|
||||
<Switch
|
||||
checked = { disableP2P }
|
||||
// @ts-ignore
|
||||
onChange = { this._onDisableP2P } />
|
||||
</FormRow>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
{AppInfo.GOOGLE_SERVICES_ENABLED && (
|
||||
<FormRow
|
||||
fieldSeparator = { true }
|
||||
label = 'settingsView.disableCrashReporting'>
|
||||
<ScrollView bounces = { scrollBounces }>
|
||||
<View style = { styles.avatarContainer }>
|
||||
<Avatar
|
||||
participantId = { this.props._localParticipantId }
|
||||
size = { AVATAR_SIZE } />
|
||||
</View>
|
||||
<FormSectionAccordion
|
||||
label = 'settingsView.profileSection'>
|
||||
<TextInput
|
||||
autoCorrect = { false }
|
||||
label = { t('settingsView.displayName') }
|
||||
mode = 'outlined'
|
||||
onChangeText = { this._onChangeDisplayName }
|
||||
placeholder = { t('settingsView.displayNamePlaceholderText') }
|
||||
placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
|
||||
spellCheck = { false }
|
||||
style = { styles.textInputContainer }
|
||||
textContentType = { 'name' } // iOS only
|
||||
theme = { textInputTheme }
|
||||
value = { displayName } />
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<TextInput
|
||||
autoCapitalize = 'none'
|
||||
autoCorrect = { false }
|
||||
keyboardType = { 'email-address' }
|
||||
label = { t('settingsView.email') }
|
||||
mode = 'outlined'
|
||||
onChangeText = { this._onChangeEmail }
|
||||
placeholder = 'email@example.com'
|
||||
placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
|
||||
spellCheck = { false }
|
||||
style = { styles.textInputContainer }
|
||||
textContentType = { 'emailAddress' } // iOS only
|
||||
theme = { textInputTheme }
|
||||
value = { email } />
|
||||
</FormSectionAccordion>
|
||||
<FormSectionAccordion
|
||||
label = 'settingsView.conferenceSection'>
|
||||
<TextInput
|
||||
autoCapitalize = 'none'
|
||||
autoCorrect = { false }
|
||||
editable = { this.props._serverURLChangeEnabled }
|
||||
keyboardType = { 'url' }
|
||||
label = { t('settingsView.serverURL') }
|
||||
mode = 'outlined'
|
||||
onBlur = { this._onBlurServerURL }
|
||||
onChangeText = { this._onChangeServerURL }
|
||||
placeholder = { this.props._serverURL }
|
||||
placeholderTextColor = { PLACEHOLDER_TEXT_COLOR }
|
||||
spellCheck = { false }
|
||||
style = { styles.textInputContainer }
|
||||
textContentType = { 'URL' } // iOS only
|
||||
theme = { textInputTheme }
|
||||
value = { serverURL } />
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<FormRow label = 'settingsView.startCarModeInLowBandwidthMode'>
|
||||
<Switch
|
||||
checked = { disableCrashReporting }
|
||||
checked = { startCarMode }
|
||||
// @ts-ignore
|
||||
onChange = { this._onDisableCrashReporting } />
|
||||
onChange = { this._onStartCarmodeInLowBandwidthMode } />
|
||||
</FormRow>
|
||||
)}
|
||||
</FormSectionAccordion>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<FormRow
|
||||
label = 'settingsView.startWithAudioMuted'>
|
||||
<Switch
|
||||
checked = { startWithAudioMuted }
|
||||
// @ts-ignore
|
||||
onChange = { this._onStartAudioMutedChange } />
|
||||
</FormRow>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<FormRow label = 'settingsView.startWithVideoMuted'>
|
||||
<Switch
|
||||
checked = { startWithVideoMuted }
|
||||
// @ts-ignore
|
||||
onChange = { this._onStartVideoMutedChange } />
|
||||
</FormRow>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<FormRow label = 'videothumbnail.hideSelfView'>
|
||||
<Switch
|
||||
checked = { disableSelfView }
|
||||
// @ts-ignore
|
||||
onChange = { this._onDisableSelfView } />
|
||||
</FormRow>
|
||||
</FormSectionAccordion>
|
||||
<FormSectionAccordion
|
||||
label = 'settingsView.links'>
|
||||
<Link
|
||||
style = { styles.sectionLink }
|
||||
// @ts-ignore
|
||||
to = {{ screen: screen.settings.links.help }}>
|
||||
{ t('settingsView.help') }
|
||||
</Link>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<Link
|
||||
style = { styles.sectionLink }
|
||||
// @ts-ignore
|
||||
to = {{ screen: screen.settings.links.terms }}>
|
||||
{ t('settingsView.terms') }
|
||||
</Link>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
<Link
|
||||
style = { styles.sectionLink }
|
||||
// @ts-ignore
|
||||
to = {{ screen: screen.settings.links.privacy }}>
|
||||
{ t('settingsView.privacy') }
|
||||
</Link>
|
||||
</FormSectionAccordion>
|
||||
<FormSectionAccordion
|
||||
label = 'settingsView.buildInfoSection'>
|
||||
<FormRow
|
||||
label = 'settingsView.version'>
|
||||
<Text style = { styles.text }>
|
||||
{`${AppInfo.version} build ${AppInfo.buildNumber}`}
|
||||
</Text>
|
||||
</FormRow>
|
||||
</FormSectionAccordion>
|
||||
<FormSectionAccordion
|
||||
label = 'settingsView.advanced'>
|
||||
{ Platform.OS === 'android' && (
|
||||
<>
|
||||
<FormRow
|
||||
label = 'settingsView.disableCallIntegration'>
|
||||
<Switch
|
||||
checked = { disableCallIntegration }
|
||||
// @ts-ignore
|
||||
onChange = { this._onDisableCallIntegration } />
|
||||
</FormRow>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
</>
|
||||
)}
|
||||
<FormRow
|
||||
label = 'settingsView.disableP2P'>
|
||||
<Switch
|
||||
checked = { disableP2P }
|
||||
// @ts-ignore
|
||||
onChange = { this._onDisableP2P } />
|
||||
</FormRow>
|
||||
<Divider style = { styles.fieldSeparator } />
|
||||
{AppInfo.GOOGLE_SERVICES_ENABLED && (
|
||||
<FormRow
|
||||
fieldSeparator = { true }
|
||||
label = 'settingsView.disableCrashReporting'>
|
||||
<Switch
|
||||
checked = { disableCrashReporting }
|
||||
// @ts-ignore
|
||||
onChange = { this._onDisableCrashReporting } />
|
||||
</FormRow>
|
||||
)}
|
||||
</FormSectionAccordion>
|
||||
</ScrollView>
|
||||
</JitsiScreen>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue