Automated cherry pick of #3571 (#3577)

* Preview markdown table as 5x5 max

* Make linter happy

* Determine max columns from device width

* Add snapshot test

* Use Dimensions and update unit tests

* Remove async
This commit is contained in:
Mattermost Build 2019-11-19 20:32:12 +01:00 committed by Miguel Alatzar
parent 1111818d9f
commit b7d4d592cc
3 changed files with 281 additions and 1 deletions

View file

@ -0,0 +1,177 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`MarkdownTable should match snapshot 1`] = `
<TouchableWithFeedbackIOS
onPress={[Function]}
style={
Object {
"paddingRight": 10,
}
}
type="opacity"
>
<ScrollViewMock
contentContainerStyle={
Object {
"width": 1000,
}
}
onContentSizeChange={[Function]}
onLayout={[Function]}
scrollEnabled={false}
showsVerticalScrollIndicator={false}
style={
Array [
Object {
"borderBottomWidth": 1,
"borderColor": "rgba(61,60,64,0.2)",
"borderRightWidth": 1,
"maxHeight": 300,
},
Object {
"maxWidth": 1000,
},
]
}
>
<View
style={
Array [
Object {
"borderColor": "rgba(61,60,64,0.2)",
"borderLeftWidth": 1,
"borderTopWidth": 1,
},
]
}
>
<
className="row"
>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
</>
<
className="row"
>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
</>
<
className="row"
>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
</>
<
className="row"
>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
</>
<
className="row"
isLastRow={true}
>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
<
className="col"
/>
</>
</View>
</ScrollViewMock>
<TouchableWithFeedbackIOS
onPress={[Function]}
style={
Object {
"backgroundColor": "#ffffff",
"borderColor": "rgba(61,60,64,0.2)",
"borderRadius": 15,
"borderWidth": 1,
"bottom": 20,
"height": 30,
"left": -20,
"paddingLeft": 7,
"paddingTop": 6,
"width": 30,
}
}
type="native"
>
<Icon
allowFontScaling={false}
name="expand"
size={12}
style={
Object {
"color": "#2389d7",
"fontSize": 15,
}
}
/>
</TouchableWithFeedbackIOS>
</TouchableWithFeedbackIOS>
`;

View file

@ -7,6 +7,7 @@ import {intlShape} from 'react-intl';
import {
ScrollView,
View,
Dimensions,
} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import Icon from 'react-native-vector-icons/FontAwesome';
@ -19,6 +20,7 @@ import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import {goToScreen} from 'app/actions/navigation';
const MAX_HEIGHT = 300;
const MAX_PREVIEW_COLUMNS = 5;
export default class MarkdownTable extends React.PureComponent {
static propTypes = {
@ -38,9 +40,23 @@ export default class MarkdownTable extends React.PureComponent {
containerWidth: 0,
contentHeight: 0,
contentWidth: 0,
maxPreviewColumns: MAX_PREVIEW_COLUMNS,
};
}
componentDidMount() {
Dimensions.addEventListener('change', this.setMaxPreviewColumns);
}
componentWillUnmount() {
Dimensions.removeEventListener('change', this.setMaxPreviewColumns);
}
setMaxPreviewColumns = ({window}) => {
const maxPreviewColumns = Math.floor(window.width / CELL_WIDTH);
this.setState({maxPreviewColumns});
}
getTableWidth = () => {
return this.props.numColumns * CELL_WIDTH;
};
@ -73,6 +89,38 @@ export default class MarkdownTable extends React.PureComponent {
});
};
renderPreviewRows = (drawExtraBorders = true) => {
const {maxPreviewColumns} = this.state;
const style = getStyleSheet(this.props.theme);
const tableStyle = [style.table];
if (drawExtraBorders) {
tableStyle.push(style.tableExtraBorders);
}
// Add an extra prop to the last row of the table so that it knows not to render a bottom border
// since the container should be rendering that
const rows = React.Children.toArray(this.props.children).slice(0, maxPreviewColumns).map((row) => {
const children = React.Children.toArray(row.props.children).slice(0, maxPreviewColumns);
return {
...row,
props: {
...row.props,
children,
},
};
});
rows[rows.length - 1] = React.cloneElement(rows[rows.length - 1], {
isLastRow: true,
});
return (
<View style={tableStyle}>
{rows}
</View>
);
}
renderRows = (drawExtraBorders = true) => {
const style = getStyleSheet(this.props.theme);
@ -152,7 +200,7 @@ export default class MarkdownTable extends React.PureComponent {
showsVerticalScrollIndicator={false}
style={[style.container, {maxWidth: this.getTableWidth()}]}
>
{this.renderRows(false)}
{this.renderPreviewRows(false)}
</ScrollView>
{moreRight}
{moreBelow}

View file

@ -0,0 +1,55 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {shallowWithIntl} from 'test/intl-test-helper';
import Preferences from 'mattermost-redux/constants/preferences';
import MarkdownTable from './markdown_table';
describe('MarkdownTable', () => {
const createCell = (type, children = null) => {
return React.createElement('', {key: Date.now(), className: type}, children);
};
const numColumns = 10;
const children = [];
for (let i = 0; i <= numColumns; i++) {
const cols = [];
for (let j = 0; j <= numColumns; j++) {
cols.push(createCell('col'));
}
children.push(createCell('row', cols));
}
const baseProps = {
children,
numColumns,
theme: Preferences.THEMES.default,
};
test('should match snapshot', () => {
const wrapper = shallowWithIntl(
<MarkdownTable {...baseProps}/>
);
expect(wrapper.getElement()).toMatchSnapshot();
});
test('should slice rows and columns', () => {
const wrapper = shallowWithIntl(
<MarkdownTable {...baseProps}/>
);
const {maxPreviewColumns} = wrapper.state();
expect(wrapper.find('.row')).toHaveLength(maxPreviewColumns);
expect(wrapper.find('.col')).toHaveLength(Math.pow(maxPreviewColumns, 2));
const newMaxPreviewColumns = maxPreviewColumns - 1;
wrapper.setState({maxPreviewColumns: newMaxPreviewColumns});
expect(wrapper.find('.row')).toHaveLength(newMaxPreviewColumns);
expect(wrapper.find('.col')).toHaveLength(Math.pow(newMaxPreviewColumns, 2));
});
});