diff --git a/js/conversation_controller.js b/js/conversation_controller.js index e3eb312b8..6f0c8f1a1 100644 --- a/js/conversation_controller.js +++ b/js/conversation_controller.js @@ -11,8 +11,6 @@ const conversations = new Whisper.ConversationCollection(); const inboxCollection = new (Backbone.Collection.extend({ initialize() { - this.on('change:timestamp change:name change:number', this.sort); - this.listenTo(conversations, 'add change:active_at', this.addActive); this.listenTo(conversations, 'reset', () => this.reset([])); diff --git a/package.json b/package.json index 9766c6d88..f574233a4 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "dependencies": { "@journeyapps/sqlcipher": "https://github.com/scottnonnenberg-signal/node-sqlcipher.git#36149a4b03ccf11ec18b9205e1bfd9056015cf07", "@sindresorhus/is": "0.8.0", + "@types/react-virtualized": "9.18.12", "backbone": "1.3.3", "blob-util": "1.3.0", "blueimp-canvas-to-blob": "3.14.0", diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index 3e097a78c..048fb1c59 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -2989,8 +2989,10 @@ .module-left-pane__list { flex-grow: 1; flex-shrink: 1; +} - overflow-y: scroll; +.module-left-pane__virtual-list { + outline: none; } // Module: Start New Conversation diff --git a/ts/components/ConversationListItem.tsx b/ts/components/ConversationListItem.tsx index d9d6acd7e..2e5ba3795 100644 --- a/ts/components/ConversationListItem.tsx +++ b/ts/components/ConversationListItem.tsx @@ -32,6 +32,7 @@ export type PropsData = { type PropsHousekeeping = { i18n: LocalizerType; + style?: Object; onClick?: (id: string) => void; }; @@ -176,7 +177,7 @@ export class ConversationListItem extends React.PureComponent { } public render() { - const { unreadCount, onClick, id, isSelected } = this.props; + const { unreadCount, onClick, id, isSelected, style } = this.props; return (
{ onClick(id); } }} + style={style} className={classNames( 'module-conversation-list-item', unreadCount > 0 ? 'module-conversation-list-item--has-unread' : null, diff --git a/ts/components/LeftPane.tsx b/ts/components/LeftPane.tsx index 8175f288b..427ca107d 100644 --- a/ts/components/LeftPane.tsx +++ b/ts/components/LeftPane.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { AutoSizer, List } from 'react-virtualized'; import { ConversationListItem, @@ -23,11 +24,39 @@ export interface Props { renderMainHeader: () => JSX.Element; } +// from https://github.com/bvaughn/react-virtualized/blob/fb3484ed5dcc41bffae8eab029126c0fb8f7abc0/source/List/types.js#L5 +type RowRendererParams = { + index: number; + isScrolling: boolean; + isVisible: boolean; + key: string; + parent: Object; + style: Object; +}; + export class LeftPane extends React.Component { + public renderRow = ({ index, key, style }: RowRendererParams) => { + const { conversations, i18n, openConversationInternal } = this.props; + if (!conversations) { + return null; + } + const conversation = conversations[index]; + + return ( + + ); + }; + public renderList() { const { - conversations, i18n, + conversations, openConversationInternal, startNewConversation, searchResults, @@ -44,16 +73,28 @@ export class LeftPane extends React.Component { ); } + if (!conversations || !conversations.length) { + return null; + } + + // 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. return (
- {(conversations || []).map(conversation => ( - - ))} + + {({ height, width }) => ( + + )} +
); } diff --git a/yarn.lock b/yarn.lock index 30bf7e9a4..b89af707d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -176,6 +176,14 @@ "@types/react" "*" redux "^4.0.0" +"@types/react-virtualized@9.18.12": + version "9.18.12" + resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.18.12.tgz#541e65c5e0b4629d6a1c6f339171c7943e016ecb" + integrity sha512-Msdpt9zvYlb5Ul4PA339QUkJ0/z2O+gaFxed1rG+2rZjbe6XdYo7jWfJe206KBnjj84DwPPIbPFQCtoGuNwNTQ== + dependencies: + "@types/prop-types" "*" + "@types/react" "*" + "@types/react@*", "@types/react@16.8.5": version "16.8.5" resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.5.tgz#03b9a6597bc20f6eaaed43f377a160f7e41c2b90"