MM-18464 Interactive dialog renders out of safe area view on landscape orientation (#3335)

* MM-18464

Updated Dialog Items to support isLandscape for SafeArea View

* MM-18464 Updated SafeAreaView

Updated Autoselector Component

* MM-18464 Resolved Issues

Resolved issues for MM-18464

* MM-18464 Resolved Snapshot

Resolved snapshots
This commit is contained in:
CJ 2019-09-27 17:44:48 -04:00 committed by Miguel Alatzar
parent 3b3a696a55
commit 2009999090
15 changed files with 93 additions and 38 deletions

View file

@ -10,6 +10,7 @@ import Icon from 'react-native-vector-icons/FontAwesome';
import {displayUsername} from 'mattermost-redux/utils/user_utils';
import FormattedText from 'app/components/formatted_text';
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
import TouchableWithFeedback from 'app/components/touchable_with_feedback';
import {preventDoubleTap} from 'app/utils/tap';
import {makeStyleSheetFromTheme, changeOpacity} from 'app/utils/theme';
@ -34,6 +35,7 @@ export default class AutocompleteSelector extends PureComponent {
helpText: PropTypes.node,
errorText: PropTypes.node,
roundedBorders: PropTypes.bool,
isLandscape: PropTypes.bool.isRequired,
};
static contextTypes = {
@ -116,6 +118,7 @@ export default class AutocompleteSelector extends PureComponent {
optional,
showRequiredAsterisk,
roundedBorders,
isLandscape,
} = this.props;
const {selectedText} = this.state;
const style = getStyleSheet(theme);
@ -181,7 +184,9 @@ export default class AutocompleteSelector extends PureComponent {
return (
<View style={style.container}>
{labelContent}
<View style={padding(isLandscape)}>
{labelContent}
</View>
<TouchableWithFeedback
style={style.flex}
onPress={this.goToSelectorScreen}
@ -189,7 +194,7 @@ export default class AutocompleteSelector extends PureComponent {
>
<View style={inputStyle}>
<Text
style={selectedStyle}
style={[selectedStyle, padding(isLandscape)]}
numberOfLines={1}
>
{text}
@ -197,12 +202,14 @@ export default class AutocompleteSelector extends PureComponent {
<Icon
name='chevron-down'
color={changeOpacity(theme.centerChannelColor, 0.5)}
style={style.icon}
style={[style.icon, padding(isLandscape)]}
/>
</View>
</TouchableWithFeedback>
{helpTextContent}
{errorTextContent}
<View style={padding(isLandscape)}>
{helpTextContent}
{errorTextContent}
</View>
</View>
);
}

View file

@ -9,11 +9,13 @@ import {getTeammateNameDisplaySetting, getTheme} from 'mattermost-redux/selector
import {setAutocompleteSelector} from 'app/actions/views/post';
import AutocompleteSelector from './autocomplete_selector';
import {isLandscape} from 'app/selectors/device';
function mapStateToProps(state) {
return {
teammateNameDisplay: getTeammateNameDisplaySetting(state),
theme: getTheme(state),
isLandscape: isLandscape(state),
};
}

View file

@ -4,12 +4,13 @@
import {connect} from 'react-redux';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {isLandscape} from 'app/selectors/device';
import OptionListRow from './option_list_row';
function mapStateToProps(state) {
return {
theme: getTheme(state),
isLandscape: isLandscape(state),
};
}

View file

@ -17,12 +17,17 @@ export default class OptionListRow extends React.PureComponent {
id: PropTypes.string,
theme: PropTypes.object.isRequired,
...CustomListRow.propTypes,
isLandscape: PropTypes.bool.isRequired,
};
static contextTypes = {
intl: intlShape,
};
static defaultProps = {
isLandscape: false,
};
onPress = () => {
if (this.props.onPress) {
this.props.onPress(this.props.id, this.props.item);
@ -36,6 +41,7 @@ export default class OptionListRow extends React.PureComponent {
selected,
theme,
item,
isLandscape,
} = this.props;
const {text, value} = item;
@ -48,6 +54,7 @@ export default class OptionListRow extends React.PureComponent {
enabled={enabled}
selectable={selectable}
selected={selected}
isLandscape={isLandscape}
>
<View style={style.textContainer}>
<View>

View file

@ -104,25 +104,27 @@ export default class BoolSetting extends PureComponent {
}
return (
<View style={padding(isLandscape)}>
{labelContent}
<React.Fragment>
<View style={padding(isLandscape)}>
{labelContent}
</View>
<View style={style.separator}/>
<View style={[style.inputContainer]}>
<Text style={style.placeholderText}>
<View style={style.inputContainer}>
<Text style={[style.placeholderText, padding(isLandscape)]}>
{placeholder}
</Text>
<Switch
onValueChange={this.handleChange}
value={value}
style={style.inputSwitch}
style={[style.inputSwitch, padding(isLandscape)]}
/>
</View>
<View style={style.separator}/>
<View>
<View style={padding(isLandscape)}>
{helpTextContent}
{errorTextContent}
</View>
</View>
</React.Fragment>
);
}
}

View file

@ -5,9 +5,12 @@ exports[`DialogIntroductionText should not render the component with an empty va
exports[`DialogIntroductionText should render the introduction text correctly 1`] = `
<View
style={
Object {
"marginHorizontal": 15,
}
Array [
Object {
"marginHorizontal": 15,
},
null,
]
}
>
<Connect(Markdown)

View file

@ -18,6 +18,7 @@ exports[`InteractiveDialog should display introduction text if present 1`] = `
>
<Connect(StatusBar) />
<DialogIntroductionText
isLandscape={false}
theme={
Object {
"awayIndicator": "#ffbc42",

View file

@ -118,6 +118,7 @@ export default class DialogElement extends PureComponent {
multiline={multiline}
keyboardType={keyboardType}
secureTextEntry={secureTextEntry}
isLandscape={isLandscape}
/>
);
} else if (type === 'select') {
@ -135,6 +136,7 @@ export default class DialogElement extends PureComponent {
showRequiredAsterisk={true}
selected={this.state.selected}
roundedBorders={false}
isLandscape={isLandscape}
/>
);
} else if (type === 'radio') {
@ -148,6 +150,7 @@ export default class DialogElement extends PureComponent {
theme={theme}
default={value}
onChange={this.onChange}
isLandscape={isLandscape}
/>
);
} else if (type === 'bool') {

View file

@ -9,17 +9,20 @@ import Markdown from 'app/components/markdown';
import {getMarkdownTextStyles, getMarkdownBlockStyles} from 'app/utils/markdown';
import {makeStyleSheetFromTheme} from 'app/utils/theme';
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
export default class DialogIntroductionText extends PureComponent {
static propTypes = {
value: PropTypes.string.isRequired,
theme: PropTypes.object.isRequired,
isLandscape: PropTypes.bool.isRequired,
};
render() {
const {
value,
theme,
isLandscape,
} = this.props;
if (value) {
@ -28,7 +31,7 @@ export default class DialogIntroductionText extends PureComponent {
const textStyles = getMarkdownTextStyles(theme);
return (
<View style={style.introductionTextView}>
<View style={[style.introductionTextView, padding(isLandscape)]}>
<Markdown
baseTextStyle={style.introductionText}
textStyles={textStyles}

View file

@ -12,6 +12,7 @@ describe('DialogIntroductionText', () => {
const baseProps = {
theme: Preferences.THEMES.default,
value: '**bold** *italic* [link](https://mattermost.com/) <br/> [link target blank](!https://mattermost.com/)',
isLandscape: false,
};
test('should render the introduction text correctly', () => {

View file

@ -179,6 +179,7 @@ export default class InteractiveDialog extends PureComponent {
<DialogIntroductionText
value={introductionText}
theme={theme}
isLandscape={isLandscape}
/>
}
{elements && elements.map((e) => {

View file

@ -12,9 +12,12 @@ exports[`SelectorScreen should match snapshot for channels 1`] = `
<Connect(StatusBar) />
<View
style={
Object {
"marginVertical": 5,
}
Array [
Object {
"marginVertical": 5,
},
null,
]
}
>
<SearchBarIos
@ -104,9 +107,12 @@ exports[`SelectorScreen should match snapshot for channels 2`] = `
<Connect(StatusBar) />
<View
style={
Object {
"marginVertical": 5,
}
Array [
Object {
"marginVertical": 5,
},
null,
]
}
>
<SearchBarIos
@ -196,9 +202,12 @@ exports[`SelectorScreen should match snapshot for explicit options 1`] = `
<Connect(StatusBar) />
<View
style={
Object {
"marginVertical": 5,
}
Array [
Object {
"marginVertical": 5,
},
null,
]
}
>
<SearchBarIos
@ -295,9 +304,12 @@ exports[`SelectorScreen should match snapshot for searching 1`] = `
<Connect(StatusBar) />
<View
style={
Object {
"marginVertical": 5,
}
Array [
Object {
"marginVertical": 5,
},
null,
]
}
>
<SearchBarIos
@ -387,9 +399,12 @@ exports[`SelectorScreen should match snapshot for users 1`] = `
<Connect(StatusBar) />
<View
style={
Object {
"marginVertical": 5,
}
Array [
Object {
"marginVertical": 5,
},
null,
]
}
>
<SearchBarIos
@ -479,9 +494,12 @@ exports[`SelectorScreen should match snapshot for users 2`] = `
<Connect(StatusBar) />
<View
style={
Object {
"marginVertical": 5,
}
Array [
Object {
"marginVertical": 5,
},
null,
]
}
>
<SearchBarIos

View file

@ -8,7 +8,7 @@ import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {getProfiles, searchProfiles} from 'mattermost-redux/actions/users';
import {getChannels, searchChannels} from 'mattermost-redux/actions/channels';
import {isLandscape} from 'app/selectors/device';
import SelectorScreen from './selector_screen';
function mapStateToProps(state) {
@ -22,6 +22,7 @@ function mapStateToProps(state) {
dataSource: menuAction.dataSource,
onSelect: menuAction.onSelect,
theme: getTheme(state),
isLandscape: isLandscape(state),
};
}

View file

@ -33,6 +33,8 @@ import {
import {t} from 'app/utils/i18n';
import {popTopScreen} from 'app/actions/navigation';
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
export default class SelectorScreen extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
@ -47,6 +49,7 @@ export default class SelectorScreen extends PureComponent {
dataSource: PropTypes.string,
onSelect: PropTypes.func.isRequired,
theme: PropTypes.object.isRequired,
isLandscape: PropTypes.bool.isRequired,
};
static contextTypes = {
@ -293,7 +296,7 @@ export default class SelectorScreen extends PureComponent {
render() {
const {formatMessage} = this.context.intl;
const {theme, dataSource} = this.props;
const {theme, dataSource, isLandscape} = this.props;
const {loading, term} = this.state;
const style = getStyleFromTheme(theme);
@ -322,7 +325,7 @@ export default class SelectorScreen extends PureComponent {
return (
<View style={style.container}>
<StatusBar/>
<View style={style.searchBar}>
<View style={[style.searchBar, padding(isLandscape)]}>
<SearchBar
ref='search_bar'
placeholder={formatMessage({id: 'search_bar.search', defaultMessage: 'Search'})}
@ -353,6 +356,7 @@ export default class SelectorScreen extends PureComponent {
onRowPress={this.handleSelectItem}
renderItem={rowComponent}
theme={theme}
isLandscape={isLandscape}
/>
</View>
);

View file

@ -76,6 +76,7 @@ describe('SelectorScreen', () => {
data: [{text: 'text', value: 'value'}],
dataSource: null,
theme: Preferences.THEMES.default,
isLandscape: false,
};
test('should match snapshot for explicit options', async () => {