diff --git a/app/components/markdown/markdown_table/__snapshots__/markdown_table.test.js.snap b/app/components/markdown/markdown_table/__snapshots__/markdown_table.test.js.snap index cc1ce4c58..25a75b2e2 100644 --- a/app/components/markdown/markdown_table/__snapshots__/markdown_table.test.js.snap +++ b/app/components/markdown/markdown_table/__snapshots__/markdown_table.test.js.snap @@ -30,13 +30,14 @@ exports[`MarkdownTable should match snapshot 1`] = ` "width": "100%", }, Object { - "width": 480, + "width": 672, }, ] } > < className="row" + isFirstRow={true} > < className="col" @@ -53,6 +54,12 @@ exports[`MarkdownTable should match snapshot 1`] = ` < className="col" /> + < + className="col" + /> + < + className="col" + /> < className="row" @@ -72,6 +79,12 @@ exports[`MarkdownTable should match snapshot 1`] = ` < className="col" /> + < + className="col" + /> + < + className="col" + /> < className="row" @@ -91,6 +104,12 @@ exports[`MarkdownTable should match snapshot 1`] = ` < className="col" /> + < + className="col" + /> + < + className="col" + /> < className="row" @@ -110,6 +129,62 @@ exports[`MarkdownTable should match snapshot 1`] = ` < className="col" /> + < + className="col" + /> + < + className="col" + /> + + < + className="row" + > + < + className="col" + /> + < + className="col" + /> + < + className="col" + /> + < + className="col" + /> + < + className="col" + /> + < + className="col" + /> + < + className="col" + /> + + < + className="row" + > + < + className="col" + /> + < + className="col" + /> + < + className="col" + /> + < + className="col" + /> + < + className="col" + /> + < + className="col" + /> + < + className="col" + /> < className="row" @@ -130,6 +205,12 @@ exports[`MarkdownTable should match snapshot 1`] = ` < className="col" /> + < + className="col" + /> + < + className="col" + /> @@ -195,7 +276,7 @@ exports[`MarkdownTable should match snapshot 1`] = ` "paddingTop": 8, }, Object { - "width": 480, + "width": 672, }, ] } diff --git a/app/components/markdown/markdown_table/markdown_table.js b/app/components/markdown/markdown_table/markdown_table.js index edef740b7..fcd404617 100644 --- a/app/components/markdown/markdown_table/markdown_table.js +++ b/app/components/markdown/markdown_table/markdown_table.js @@ -40,14 +40,16 @@ export default class MarkdownTable extends React.PureComponent { this.state = { containerWidth: 0, contentHeight: 0, - contentWidth: 0, - maxPreviewColumns: MAX_PREVIEW_COLUMNS, cellWidth: 0, + rowsSliced: false, }; } componentDidMount() { Dimensions.addEventListener('change', this.setMaxPreviewColumns); + + const window = Dimensions.get('window'); + this.setMaxPreviewColumns({window}); } componentWillUnmount() { @@ -60,13 +62,10 @@ export default class MarkdownTable extends React.PureComponent { } getTableWidth = (isFullView = false) => { - let columns = this.props.numColumns; + const maxPreviewColumns = this.state.maxPreviewColumns || MAX_PREVIEW_COLUMNS; + const columns = Math.min(this.props.numColumns, maxPreviewColumns); - if (columns > MAX_PREVIEW_COLUMNS) { - columns = MAX_PREVIEW_COLUMNS; - } - - return isFullView || columns === 1 ? columns * CELL_MAX_WIDTH : columns * CELL_MIN_WIDTH; + return (isFullView || columns === 1) ? columns * CELL_MAX_WIDTH : columns * CELL_MIN_WIDTH; }; handlePress = preventDoubleTap(() => { @@ -98,30 +97,7 @@ export default class MarkdownTable extends React.PureComponent { }; renderPreviewRows = (isFullView = false) => { - const {maxPreviewColumns} = this.state; - const tableStyle = this.getTableStyle(isFullView); - - // 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 ( - - {rows} - - ); + return this.renderRows(isFullView, true); } shouldRenderAsFlex = (isFullView = false) => { @@ -165,12 +141,33 @@ export default class MarkdownTable extends React.PureComponent { return tableStyle; } - renderRows = (isFullView = false) => { + renderRows = (isFullView = false, isPreview = false) => { const tableStyle = this.getTableStyle(isFullView); + let rows = React.Children.toArray(this.props.children); + if (isPreview) { + const {maxPreviewColumns} = this.state; + const prevRowLength = rows.length; + const prevColLength = React.Children.toArray(rows[0].props.children).length; + + rows = rows.slice(0, maxPreviewColumns).map((row) => { + const children = React.Children.toArray(row.props.children).slice(0, maxPreviewColumns); + return { + ...row, + props: { + ...row.props, + children, + }, + }; + }); + + const rowsSliced = prevRowLength > rows.length; + const colsSliced = prevColLength > React.Children.toArray(rows[0].props.children).length; + this.setState({rowsSliced, colsSliced}); + } + // 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); rows[rows.length - 1] = React.cloneElement(rows[rows.length - 1], { isLastRow: true, }); @@ -188,43 +185,53 @@ export default class MarkdownTable extends React.PureComponent { } render() { - const style = getStyleSheet(this.props.theme); - let moreRight = null; + const {containerWidth, contentHeight} = this.state; + const {theme} = this.props; + const style = getStyleSheet(theme); const tableWidth = this.getTableWidth(); const renderAsFlex = this.shouldRenderAsFlex(); let leftOffset; - if (renderAsFlex || tableWidth > this.state.containerWidth) { - leftOffset = this.state.containerWidth - 20; + if (renderAsFlex || tableWidth > containerWidth) { + leftOffset = containerWidth - 20; } else { leftOffset = tableWidth - 20; } + let expandButtonOffset = leftOffset; + if (Platform.OS === 'android') { + expandButtonOffset -= 10; + } - // Renders when table width exceeds the container, or if the columns exceed maximum allowed for previews - if ((this.state.containerWidth && tableWidth > this.state.containerWidth && !renderAsFlex) || + // Renders when the columns were sliced, or the table width exceeds the container, + // or if the columns exceed maximum allowed for previews + let moreRight = null; + if (this.state.colsSliced || + (containerWidth && tableWidth > containerWidth && !renderAsFlex) || (this.props.numColumns > MAX_PREVIEW_COLUMNS)) { moreRight = ( ); } let moreBelow = null; - if (this.state.contentHeight > MAX_HEIGHT) { + if (this.state.rowsSliced) { + const width = renderAsFlex ? '100%' : Math.min(tableWidth, containerWidth); + moreBelow = ( ); } @@ -233,7 +240,7 @@ export default class MarkdownTable extends React.PureComponent { @@ -314,9 +321,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => { displayFlex: { flex: 1, }, - fullWidth: { - width: '100%', - }, table: { width: '100%', borderColor: changeOpacity(theme.centerChannelColor, 0.2), @@ -326,12 +330,11 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => { paddingRight: 10, }, moreBelow: { - bottom: 30, + bottom: 34, height: 20, position: 'absolute', left: 0, borderColor: changeOpacity(theme.centerChannelColor, 0.2), - borderBottomWidth: 1, }, moreRight: { maxHeight: MAX_HEIGHT, diff --git a/app/components/markdown/markdown_table/markdown_table.test.js b/app/components/markdown/markdown_table/markdown_table.test.js index 1d2fee805..6406c8266 100644 --- a/app/components/markdown/markdown_table/markdown_table.test.js +++ b/app/components/markdown/markdown_table/markdown_table.test.js @@ -38,6 +38,18 @@ describe('MarkdownTable', () => { expect(wrapper.getElement()).toMatchSnapshot(); }); + test('should call setMaxPreviewColumns on mount', () => { + const wrapper = shallowWithIntl( + , + ); + const instance = wrapper.instance(); + const setMaxPreviewColumns = jest.spyOn(instance, 'setMaxPreviewColumns'); + + instance.componentDidMount(); + expect(setMaxPreviewColumns).toHaveBeenCalled(); + expect(instance.state.maxPreviewColumns).toBeDefined(); + }); + test('should slice rows and columns', () => { const wrapper = shallowWithIntl( , @@ -52,4 +64,34 @@ describe('MarkdownTable', () => { expect(wrapper.find('.row')).toHaveLength(newMaxPreviewColumns); expect(wrapper.find('.col')).toHaveLength(Math.pow(newMaxPreviewColumns, 2)); }); + + test('should add the isFirstRow prop to the first row', () => { + const wrapper = shallowWithIntl( + , + ); + const instance = wrapper.instance(); + const fullRows = instance.renderRows(); + const previewRows = instance.renderPreviewRows(); + + [fullRows, previewRows].forEach((rows) => { + const firstRows = rows.props.children.filter((child) => child.props.isFirstRow); + expect(firstRows.length).toEqual(1); + expect(firstRows[0]).toEqual(rows.props.children[0]); + }); + }); + + test('should add the isLastRow prop to the last row', () => { + const wrapper = shallowWithIntl( + , + ); + const instance = wrapper.instance(); + const fullRows = instance.renderRows(); + const previewRows = instance.renderPreviewRows(); + + [fullRows, previewRows].forEach((rows) => { + const lastRows = rows.props.children.filter((child) => child.props.isLastRow); + expect(lastRows.length).toEqual(1); + expect(lastRows[0]).toEqual(rows.props.children[rows.props.children.length - 1]); + }); + }); });