use LazyRenderList in emoji picker Category

This commit is contained in:
Bruno Windels 2019-10-24 16:01:34 +02:00
parent 3e360c156a
commit 00b1816986

View file

@ -16,9 +16,11 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { CATEGORY_HEADER_HEIGHT, EMOJI_HEIGHT, EMOJIS_PER_ROW } from "./EmojiPicker";
import sdk from '../../../index'; import sdk from '../../../index';
const OVERFLOW_ROWS = 3;
class Category extends React.PureComponent { class Category extends React.PureComponent {
static propTypes = { static propTypes = {
emojis: PropTypes.arrayOf(PropTypes.object).isRequired, emojis: PropTypes.arrayOf(PropTypes.object).isRequired,
@ -30,22 +32,54 @@ class Category extends React.PureComponent {
selectedEmojis: PropTypes.instanceOf(Set), selectedEmojis: PropTypes.instanceOf(Set),
}; };
_renderEmojiRow = (rowIndex) => {
const { onClick, onMouseEnter, onMouseLeave, selectedEmojis, emojis } = this.props;
const emojisForRow = emojis.slice(rowIndex * 8, (rowIndex + 1) * 8);
const Emoji = sdk.getComponent("emojipicker.Emoji");
return (<div key={rowIndex}>{
emojisForRow.map(emoji =>
<Emoji key={emoji.hexcode} emoji={emoji} selectedEmojis={selectedEmojis}
onClick={onClick} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />)
}</div>);
};
render() { render() {
const { onClick, onMouseEnter, onMouseLeave, emojis, name, selectedEmojis } = this.props; const { emojis, name, heightBefore, viewportHeight, scrollTop } = this.props;
if (!emojis || emojis.length === 0) { if (!emojis || emojis.length === 0) {
return null; return null;
} }
const rows = new Array(Math.ceil(emojis.length / EMOJIS_PER_ROW));
for (let counter = 0; counter < rows.length; ++counter) {
rows[counter] = counter;
}
const LazyRenderList = sdk.getComponent('elements.LazyRenderList');
const viewportTop = scrollTop;
const viewportBottom = viewportTop + viewportHeight;
const listTop = heightBefore + CATEGORY_HEADER_HEIGHT;
const listBottom = listTop + (rows.length * EMOJI_HEIGHT);
const top = Math.max(viewportTop, listTop);
const bottom = Math.min(viewportBottom, listBottom);
// the viewport height and scrollTop passed to the LazyRenderList
// is capped at the intersection with the real viewport, so lists
// out of view are passed height 0, so they won't render any items.
const localHeight = Math.max(0, bottom - top);
const localScrollTop = Math.max(0, scrollTop - listTop);
const Emoji = sdk.getComponent("emojipicker.Emoji");
return ( return (
<section className="mx_EmojiPicker_category" data-category-id={this.props.id}> <section className="mx_EmojiPicker_category" data-category-id={this.props.id}>
<h2 className="mx_EmojiPicker_category_label"> <h2 className="mx_EmojiPicker_category_label">
{name} {name}
</h2> </h2>
<ul className="mx_EmojiPicker_list"> <LazyRenderList
{emojis.map(emoji => <Emoji key={emoji.hexcode} emoji={emoji} selectedEmojis={selectedEmojis} element="ul" className="mx_EmojiPicker_list"
onClick={onClick} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />)} itemHeight={EMOJI_HEIGHT} items={rows}
</ul> scrollTop={localScrollTop}
height={localHeight}
overflowItems={OVERFLOW_ROWS}
overflowMargin={0}
renderItem={this._renderEmojiRow}>
</LazyRenderList>
</section> </section>
); );
} }