Merge pull request #5048 from matrix-org/travis/perf4

Improve RoomTile performance
pull/21833/head
Travis Ralston 2020-07-24 14:02:29 -06:00 committed by GitHub
commit fbdbbce529
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 21 additions and 28 deletions

View File

@ -61,18 +61,16 @@ interface IProps {
showMessagePreview: boolean; showMessagePreview: boolean;
isMinimized: boolean; isMinimized: boolean;
tag: TagID; tag: TagID;
// TODO: Incoming call boxes: https://github.com/vector-im/riot-web/issues/14177
} }
type PartialDOMRect = Pick<DOMRect, "left" | "bottom">; type PartialDOMRect = Pick<DOMRect, "left" | "bottom">;
interface IState { interface IState {
hover: boolean;
notificationState: NotificationState; notificationState: NotificationState;
selected: boolean; selected: boolean;
notificationsMenuPosition: PartialDOMRect; notificationsMenuPosition: PartialDOMRect;
generalMenuPosition: PartialDOMRect; generalMenuPosition: PartialDOMRect;
messagePreview?: string;
} }
const messagePreviewId = (roomId: string) => `mx_RoomTile_messagePreview_${roomId}`; const messagePreviewId = (roomId: string) => `mx_RoomTile_messagePreview_${roomId}`;
@ -111,7 +109,7 @@ const NotifOption: React.FC<INotifOptionProps> = ({active, onClick, iconClassNam
); );
}; };
export default class RoomTile extends React.Component<IProps, IState> { export default class RoomTile extends React.PureComponent<IProps, IState> {
private dispatcherRef: string; private dispatcherRef: string;
private roomTileRef = createRef<HTMLDivElement>(); private roomTileRef = createRef<HTMLDivElement>();
@ -119,11 +117,13 @@ export default class RoomTile extends React.Component<IProps, IState> {
super(props); super(props);
this.state = { this.state = {
hover: false,
notificationState: RoomNotificationStateStore.instance.getRoomState(this.props.room), notificationState: RoomNotificationStateStore.instance.getRoomState(this.props.room),
selected: ActiveRoomObserver.activeRoomId === this.props.room.roomId, selected: ActiveRoomObserver.activeRoomId === this.props.room.roomId,
notificationsMenuPosition: null, notificationsMenuPosition: null,
generalMenuPosition: null, generalMenuPosition: null,
// generatePreview() will return nothing if the user has previews disabled
messagePreview: this.generatePreview(),
}; };
ActiveRoomObserver.addListener(this.props.room.roomId, this.onActiveRoomUpdate); ActiveRoomObserver.addListener(this.props.room.roomId, this.onActiveRoomUpdate);
@ -164,10 +164,19 @@ export default class RoomTile extends React.Component<IProps, IState> {
private onRoomPreviewChanged = (room: Room) => { private onRoomPreviewChanged = (room: Room) => {
if (this.props.room && room.roomId === this.props.room.roomId) { if (this.props.room && room.roomId === this.props.room.roomId) {
this.forceUpdate(); // we don't have any state to set, so just complain that we need an update // generatePreview() will return nothing if the user has previews disabled
this.setState({messagePreview: this.generatePreview()});
} }
}; };
private generatePreview(): string | null {
if (!this.showMessagePreview) {
return null;
}
return MessagePreviewStore.instance.getPreviewForRoom(this.props.room, this.props.tag);
}
private scrollIntoView = () => { private scrollIntoView = () => {
if (!this.roomTileRef.current) return; if (!this.roomTileRef.current) return;
this.roomTileRef.current.scrollIntoView({ this.roomTileRef.current.scrollIntoView({
@ -176,14 +185,6 @@ export default class RoomTile extends React.Component<IProps, IState> {
}); });
}; };
private onTileMouseEnter = () => {
this.setState({hover: true});
};
private onTileMouseLeave = () => {
this.setState({hover: false});
};
private onTileClick = (ev: React.KeyboardEvent) => { private onTileClick = (ev: React.KeyboardEvent) => {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
@ -503,18 +504,12 @@ export default class RoomTile extends React.Component<IProps, IState> {
name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon name = name.replace(":", ":\u200b"); // add a zero-width space to allow linewrapping after the colon
let messagePreview = null; let messagePreview = null;
if (this.showMessagePreview) { if (this.showMessagePreview && this.state.messagePreview) {
// The preview store heavily caches this info, so should be safe to hammer. messagePreview = (
const text = MessagePreviewStore.instance.getPreviewForRoom(this.props.room, this.props.tag); <div className="mx_RoomTile_messagePreview" id={messagePreviewId(this.props.room.roomId)}>
{this.state.messagePreview}
// Only show the preview if there is one to show. </div>
if (text) { );
messagePreview = (
<div className="mx_RoomTile_messagePreview" id={messagePreviewId(this.props.room.roomId)}>
{text}
</div>
);
}
} }
const nameClasses = classNames({ const nameClasses = classNames({
@ -568,8 +563,6 @@ export default class RoomTile extends React.Component<IProps, IState> {
tabIndex={isActive ? 0 : -1} tabIndex={isActive ? 0 : -1}
inputRef={ref} inputRef={ref}
className={classes} className={classes}
onMouseEnter={this.onTileMouseEnter}
onMouseLeave={this.onTileMouseLeave}
onClick={this.onTileClick} onClick={this.onTileClick}
onContextMenu={this.onContextMenu} onContextMenu={this.onContextMenu}
role="treeitem" role="treeitem"