[MM-25349] centre failed network action component and improve responsiveness to device orientation (#4834)

This commit is contained in:
Ashish Bhate 2020-10-26 08:02:14 +00:00 committed by GitHub
parent 0db46f2003
commit 1f6cd323f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 167 additions and 108 deletions

View file

@ -16,7 +16,10 @@ export default class CloudSvg extends PureComponent {
render() {
const {color, height, width} = this.props;
return (
<View style={{height, width, alignItems: 'flex-start'}}>
<View
style={{height, width, alignItems: 'flex-start'}}
testID='failed_network_action.cloud_icon'
>
<Svg
width={width}
height={height}

View file

@ -0,0 +1,115 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {Text, View} from 'react-native';
import {intlShape} from 'react-intl';
import Button from 'react-native-button';
import {INDICATOR_BAR_HEIGHT} from '@constants/view';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import Cloud from './cloud';
export default class FailedNetworkAction extends PureComponent {
static propTypes = {
actionText: PropTypes.string,
errorMessage: PropTypes.string,
errorTitle: PropTypes.string,
isLandscape: PropTypes.bool.isRequired,
onRetry: PropTypes.func.isRequired,
theme: PropTypes.object.isRequired,
};
static contextTypes = {
intl: intlShape.isRequired,
};
render() {
const {formatMessage} = this.context.intl;
const {onRetry, theme} = this.props;
const style = getStyleFromTheme(theme);
const actionText = this.props.actionText || formatMessage({
id: 'mobile.failed_network_action.retry',
defaultMessage: 'Try again',
});
const errorTitle = this.props.errorTitle || formatMessage({
id: 'mobile.failed_network_action.title',
defaultMessage: 'No internet connection',
});
const errorMessage = this.props.errorMessage || formatMessage({
id: 'mobile.failed_network_action.shortDescription',
defaultMessage: 'Messages will load when you have an internet connection.',
});
return (
<View style={style.container}>
{ !this.props.isLandscape &&
<Cloud
color={changeOpacity(theme.centerChannelColor, 0.15)}
height={76}
width={76}
/>
}
<Text
style={style.title}
testID='error_title'
>
{errorTitle}
</Text>
<Text
style={style.description}
testID='error_text'
>
{errorMessage}
</Text>
<Button
onPress={onRetry}
containerStyle={style.buttonContainer}
>
<Text style={style.link}>{actionText}</Text>
</Button>
</View>
);
}
}
const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
return {
container: {
alignItems: 'center',
flex: 1,
justifyContent: 'center',
paddingHorizontal: 15,
paddingVertical: INDICATOR_BAR_HEIGHT,
paddingBottom: 15,
},
title: {
color: changeOpacity(theme.centerChannelColor, 0.8),
fontSize: 20,
fontWeight: '600',
marginBottom: 15,
marginTop: 10,
},
description: {
color: changeOpacity(theme.centerChannelColor, 0.4),
fontSize: 17,
lineHeight: 25,
textAlign: 'center',
},
link: {
color: theme.buttonColor,
fontSize: 15,
},
buttonContainer: {
backgroundColor: theme.buttonBg,
borderRadius: 5,
height: 42,
justifyContent: 'center',
marginTop: 20,
paddingHorizontal: 12,
},
};
});

View file

@ -0,0 +1,35 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import FailedNetworkAction from './failed_network_action';
import {renderWithReduxIntl} from 'test/testing_library';
import Preferences from '@mm-redux/constants/preferences';
import {waitFor} from '@testing-library/react-native';
describe('FailedNetworkAction', () => {
const baseProps = {
onRetry: jest.fn(),
theme: Preferences.THEMES.default,
isLandscape: false,
errorMessage: 'Error Message',
errorTitle: 'Error Title',
};
test('Cloud in portrait', async () => {
const {getByTestId} = renderWithReduxIntl(
<FailedNetworkAction {...baseProps}/>,
);
await waitFor(() => expect(getByTestId('failed_network_action.cloud_icon')).toBeTruthy());
});
test('Cloud NOT in landscape', async () => {
const props = {...baseProps, isLandscape: true};
const {queryByTestId} = renderWithReduxIntl(
<FailedNetworkAction {...props}/>,
);
await waitFor(() => expect(queryByTestId('failed_network_action.cloud_icon')).toBeNull());
});
});

View file

@ -1,104 +1,16 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {Text, View} from 'react-native';
import {intlShape} from 'react-intl';
import Button from 'react-native-button';
import {connect} from 'react-redux';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {isLandscape} from 'app/selectors/device';
import Cloud from './cloud';
import FailedNetworkAction from './failed_network_action';
export default class FailedNetworkAction extends PureComponent {
static propTypes = {
onRetry: PropTypes.func.isRequired,
actionText: PropTypes.string,
errorMessage: PropTypes.string,
errorTitle: PropTypes.string,
theme: PropTypes.object.isRequired,
function mapStateToProps(state) {
return {
isLandscape: isLandscape(state),
};
static contextTypes = {
intl: intlShape.isRequired,
};
static defaultProps = {
showAction: true,
};
render() {
const {formatMessage} = this.context.intl;
const {onRetry, theme} = this.props;
const style = getStyleFromTheme(theme);
const actionText = this.props.actionText || formatMessage({
id: 'mobile.failed_network_action.retry',
defaultMessage: 'Try again',
});
const errorTitle = this.props.errorTitle || formatMessage({
id: 'mobile.failed_network_action.title',
defaultMessage: 'No internet connection',
});
const errorMessage = this.props.errorMessage || formatMessage({
id: 'mobile.failed_network_action.shortDescription',
defaultMessage: 'Messages will load when you have an internet connection.',
});
return (
<View style={style.container}>
<Cloud
color={changeOpacity(theme.centerChannelColor, 0.15)}
height={76}
width={76}
/>
<Text style={style.title}>{errorTitle}</Text>
<Text style={style.description}>{errorMessage}</Text>
<Button
onPress={onRetry}
containerStyle={style.buttonContainer}
>
<Text style={style.link}>{actionText}</Text>
</Button>
</View>
);
}
}
const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
return {
container: {
alignItems: 'center',
flex: 1,
justifyContent: 'center',
paddingHorizontal: 15,
paddingBottom: 100,
},
title: {
color: changeOpacity(theme.centerChannelColor, 0.8),
fontSize: 20,
fontWeight: '600',
marginBottom: 15,
marginTop: 10,
},
description: {
color: changeOpacity(theme.centerChannelColor, 0.4),
fontSize: 17,
lineHeight: 25,
textAlign: 'center',
},
link: {
color: theme.buttonColor,
fontSize: 15,
},
buttonContainer: {
backgroundColor: theme.buttonBg,
borderRadius: 5,
height: 42,
justifyContent: 'center',
marginTop: 20,
paddingHorizontal: 12,
},
};
});
export default connect(mapStateToProps)(FailedNetworkAction);

View file

@ -9,11 +9,10 @@ exports[`ErrorTeamsList should match snapshot 1`] = `
}
>
<Connect(StatusBar) />
<FailedNetworkAction
<Connect(FailedNetworkAction)
errorMessage="Teams could not be loaded."
errorTitle="Something went wrong"
onRetry={[Function]}
showAction={true}
theme={
Object {
"awayIndicator": "#ffbc42",

View file

@ -39,9 +39,8 @@ exports[`FlaggedPosts should match snapshot when getFlaggedPosts failed 1`] = `
}
>
<Connect(StatusBar) />
<FailedNetworkAction
<Connect(FailedNetworkAction)
onRetry={[Function]}
showAction={true}
theme={
Object {
"awayIndicator": "#ffbc42",

View file

@ -39,9 +39,8 @@ exports[`PinnedPosts should match snapshot when getPinnedPosts failed 1`] = `
}
>
<Connect(StatusBar) />
<FailedNetworkAction
<Connect(FailedNetworkAction)
onRetry={[Function]}
showAction={true}
theme={
Object {
"awayIndicator": "#ffbc42",

View file

@ -39,9 +39,8 @@ exports[`RecentMentions should match snapshot when getRecentMentions failed 1`]
}
>
<Connect(StatusBar) />
<FailedNetworkAction
<Connect(FailedNetworkAction)
onRetry={[Function]}
showAction={true}
theme={
Object {
"awayIndicator": "#ffbc42",

View file

@ -1,9 +1,8 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SelectTeam should match snapshot for fail of teams 1`] = `
<FailedNetworkAction
<Connect(FailedNetworkAction)
onRetry={[Function]}
showAction={true}
theme={
Object {
"awayIndicator": "#ffbc42",

View file

@ -285,9 +285,8 @@ exports[`TermsOfService should match snapshot for fail of get terms 1`] = `
}
>
<Connect(StatusBar) />
<FailedNetworkAction
<Connect(FailedNetworkAction)
onRetry={[Function]}
showAction={true}
theme={
Object {
"awayIndicator": "#ffbc42",