message: use TruncatedList to prevent rendering hundreds/thousands of DOM nodes
diff: @@ -242,6 +242,8 @@ class SendAccountData extends GenericEditor {
  }
  }
  +const INITIAL_LOAD_TILES = 20;
  +
  class FilteredList extends React.Component {
  static propTypes = {
  children: PropTypes.any,
  @@ -249,31 +251,65 @@ class FilteredList extends React.Component {
  onChange: PropTypes.func,
  };
  + static filterChildren(children, query) {
  + if (!query) return children;
  + const lcQuery = query.toLowerCase();
  + return children.filter((child) => child.key.toLowerCase().includes(lcQuery));
  + }
  +
  constructor(props, context) {
  super(props, context);
  - this.onQuery = this.onQuery.bind(this);
  - }
  - onQuery(ev) {
  - if (this.props.onChange) this.props.onChange(ev.target.value);
  + this.state = {
  + filteredChildren: FilteredList.filterChildren(this.props.children, this.props.query),
  + truncateAt: INITIAL_LOAD_TILES,
  + };
  }
  - filterChildren() {
  - if (this.props.query) {
  - const lowerQuery = this.props.query.toLowerCase();
  - return this.props.children.filter((child) => child.key.toLowerCase().includes(lowerQuery));
  - }
  - return this.props.children;
  + componentWillReceiveProps(nextProps) {
  + if (this.props.children === nextProps.children && this.props.query === nextProps.query) return;
  + this.setState({
  + filteredChildren: FilteredList.filterChildren(nextProps.children, nextProps.query),
  + truncateAt: INITIAL_LOAD_TILES,
  + });
  }
  + showAll = () => {
  + this.setState({
  + truncateAt: -1,
  + });
  + };
  +
  + createOverflowElement = (overflowCount: number, totalCount: number) => {
  + return <button className="mx_DevTools_RoomStateExplorer_button" onClick={this.showAll}>
  + { _t("and %(count)s others...", { count: overflowCount }) }
  + </button>;
  + };
  +
  + onQuery = (ev) => {
  + if (this.props.onChange) this.props.onChange(ev.target.value);
  + };
  +
  + getChildren = (start: number, end: number) => {
  + return this.state.filteredChildren.slice(start, end);
  + };
  +
  + getChildCount = (): number => {
  + return this.state.filteredChildren.length;
  + };
  +
  render() {
  + const TruncatedList = sdk.getComponent("elements.TruncatedList");
  return <div>
  <input size="64"
  onChange={this.onQuery}
  value={this.props.query}
  placeholder={_t('Filter results')}
  className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query" />
  - { this.filterChildren() }
  + <TruncatedList getChildren={this.getChildren}
  + getChildCount={this.getChildCount}
  + truncateAt={this.state.truncateAt}
  + createOverflowElement={this.createOverflowElement} />
  </div>;
  }
  }
  