From d5925ac9d58e5e0694c0222b81706020106a42c6 Mon Sep 17 00:00:00 2001 From: Josh Perez <60019601+josh-signal@users.noreply.github.com> Date: Thu, 23 Apr 2020 15:20:47 -0400 Subject: [PATCH] LeftPane: Measure content above list to calculate list size --- stylesheets/_modules.scss | 13 +++-- ts/components/LeftPane.tsx | 68 ++++++++++++------------- ts/components/SearchResults.stories.tsx | 2 + ts/components/SearchResults.tsx | 56 ++++++++------------ ts/util/lint/exceptions.json | 2 +- 5 files changed, 67 insertions(+), 74 deletions(-) diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index 12a78ac93d..38699475c5 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -5206,8 +5206,8 @@ button.module-image__border-overlay:focus { } .module-left-pane__header { - flex-shrink: 0; flex-grow: 0; + flex-shrink: 0; } .module-left-pane__archive-header { @@ -5295,13 +5295,20 @@ button.module-image__border-overlay:focus { } } -.module-left-pane__list { +.module-left-pane__list--measure { flex-grow: 1; flex-shrink: 1; - outline: none; } +.module-left-pane__list--wrapper { + position: relative; +} + +.module-left-pane__list { + position: absolute; +} + .module-left-pane__virtual-list { outline: none; } diff --git a/ts/components/LeftPane.tsx b/ts/components/LeftPane.tsx index ab7f124aed..f14c01f904 100644 --- a/ts/components/LeftPane.tsx +++ b/ts/components/LeftPane.tsx @@ -56,12 +56,6 @@ export class LeftPane extends React.Component { public containerRef = React.createRef(); public setFocusToFirstNeeded = false; public setFocusToLastNeeded = false; - public state = { - dimensions: { - height: 0, - width: 0, - }, - }; public renderRow = ({ index, @@ -165,10 +159,6 @@ export class LeftPane extends React.Component { } }; - public handleResize = ({ bounds }: { bounds: BoundingRect }) => { - this.setState({ dimensions: bounds }); - }; - public handleFocus = () => { const { selectedConversationId } = this.props; const { current: container } = this.containerRef; @@ -295,7 +285,10 @@ export class LeftPane extends React.Component { : conversations.length + (archivedConversations.length ? 1 : 0); }; - public renderList = (): JSX.Element | Array => { + public renderList = ({ + height, + width, + }: BoundingRect): JSX.Element | Array => { const { archivedConversations, i18n, @@ -311,6 +304,8 @@ export class LeftPane extends React.Component { return ( { const length = this.getLength(); - const archived = showArchived ? ( -
- {i18n('archiveHelperText')} -
- ) : null; - // We ensure that the listKey differs between inbox and archive views, which ensures // that AutoSizer properly detects the new size of its slot in the flexbox. The // archive explainer text at the top of the archive view causes problems otherwise. // It also ensures that we scroll to the top when switching views. const listKey = showArchived ? 1 : 0; - const { height, width } = this.state.dimensions; - // Note: conversations is not a known prop for List, but it is required to ensure that // it re-renders when our conversation data changes. Otherwise it would just render // on startup and scroll. - const list = ( + return (
{
); - - return [archived, list]; }; public renderArchivedHeader = (): JSX.Element => { @@ -392,6 +377,7 @@ export class LeftPane extends React.Component { public render(): JSX.Element { const { + i18n, renderExpiredBuildDialog, renderMainHeader, renderNetworkStatus, @@ -400,21 +386,31 @@ export class LeftPane extends React.Component { showArchived, } = this.props; + /* tslint:disable no-non-null-assertion */ return ( - - {({ measureRef }: MeasuredComponentProps) => ( -
-
- {showArchived ? this.renderArchivedHeader() : renderMainHeader()} -
- {renderExpiredBuildDialog()} - {renderNetworkStatus()} - {renderUpdateDialog()} - {renderRelinkDialog()} - {this.renderList()} +
+
+ {showArchived ? this.renderArchivedHeader() : renderMainHeader()} +
+ {renderExpiredBuildDialog()} + {renderNetworkStatus()} + {renderUpdateDialog()} + {renderRelinkDialog()} + {showArchived && ( +
+ {i18n('archiveHelperText')}
)} - + + {({ contentRect, measureRef }: MeasuredComponentProps) => ( +
+
+ {this.renderList(contentRect.bounds!)} +
+
+ )} +
+
); } } diff --git a/ts/components/SearchResults.stories.tsx b/ts/components/SearchResults.stories.tsx index 0188d43b11..0829c882a4 100644 --- a/ts/components/SearchResults.stories.tsx +++ b/ts/components/SearchResults.stories.tsx @@ -111,6 +111,7 @@ messageLookup.set('4-guid-guid-guid-guid-guid', { const defaultProps = { discussionsLoading: false, + height: 700, items: [], i18n, messagesLoading: false, @@ -135,6 +136,7 @@ const defaultProps = { selectedConversationId: undefined, selectedMessageId: undefined, startNewConversation: action('start-new-conversation'), + width: 320, }; const conversations = [ diff --git a/ts/components/SearchResults.tsx b/ts/components/SearchResults.tsx index 46bf15d4ce..03630aa170 100644 --- a/ts/components/SearchResults.tsx +++ b/ts/components/SearchResults.tsx @@ -1,10 +1,5 @@ import React from 'react'; -import { - AutoSizer, - CellMeasurer, - CellMeasurerCache, - List, -} from 'react-virtualized'; +import { CellMeasurer, CellMeasurerCache, List } from 'react-virtualized'; import { debounce, get, isNumber } from 'lodash'; import { Intl } from './Intl'; @@ -86,6 +81,8 @@ type PropsHousekeepingType = { query: string, options: { regionCode: string } ) => void; + height: number; + width: number; renderMessageSearchResult: (id: string) => JSX.Element; }; @@ -121,8 +118,6 @@ type OnScrollParamsType = { export class SearchResults extends React.Component { public setFocusToFirstNeeded = false; public setFocusToLastNeeded = false; - public mostRecentWidth = 0; - public mostRecentHeight = 0; public cellSizeCache = new CellMeasurerCache({ defaultHeight: 80, fixedWidth: true, @@ -454,7 +449,7 @@ export class SearchResults extends React.Component { parent, style, }: RowRendererParamsType): JSX.Element => { - const { items } = this.props; + const { items, width } = this.props; const row = items[index]; @@ -466,7 +461,7 @@ export class SearchResults extends React.Component { key={key} parent={parent} rowIndex={index} - width={this.mostRecentWidth} + width={width} > {this.renderRowContents(row)} @@ -530,11 +525,13 @@ export class SearchResults extends React.Component { public render() { const { + height, i18n, items, noResults, searchConversationName, searchTerm, + width, } = this.props; const { scrollToIndex } = this.state; @@ -581,30 +578,21 @@ export class SearchResults extends React.Component { onKeyDown={this.handleKeyDown} onFocus={this.handleFocus} > - - {({ height, width }) => { - this.mostRecentWidth = width; - this.mostRecentHeight = height; - - return ( - - ); - }} - +
); } diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json index 14c5304a64..c495509c3b 100644 --- a/ts/util/lint/exceptions.json +++ b/ts/util/lint/exceptions.json @@ -11522,7 +11522,7 @@ "rule": "React-createRef", "path": "ts/components/SearchResults.js", "line": " this.listRef = react_1.default.createRef();", - "lineNumber": 26, + "lineNumber": 24, "reasonCategory": "usageTrusted", "updated": "2019-08-09T00:44:31.008Z", "reasonDetail": "SearchResults needs to interact with its child List directly"