RoomList: improve performance (#32919)
* perf: add memo to room avatar view * perf: batch rlsV3 emit * perf: avoid to re-render the room list if the room list state and sections are same * perf: listen only message preview of the specific room * perf: avoid to re-render the room list item if the notification or the content is same * chore: replace useState and useEffect by useMemo in virtualized list * fix: listen to room name event in RoomAvatar * fix: room avatar re-render when room is low priority
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
import { EventType, JoinRule, type MatrixEvent, type Room, RoomEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { useTypedEventEmitter } from "../../../hooks/useEventEmitter";
|
||||
import { useTypedEventEmitter, useTypedEventEmitterState } from "../../../hooks/useEventEmitter";
|
||||
import { useDmMember, usePresence, type Presence } from "../../views/avatars/WithPresenceIndicator";
|
||||
import { DefaultTagID } from "../../../stores/room-list-v3/skip-list/tag";
|
||||
|
||||
@@ -41,7 +41,7 @@ export function useRoomAvatarViewModel(room: Room): RoomAvatarViewState {
|
||||
const roomMember = useDmMember(room);
|
||||
const presence = usePresence(room, roomMember);
|
||||
const isPublic = useIsPublic(room);
|
||||
const isLowPriority = !!room.tags[DefaultTagID.LowPriority];
|
||||
const isLowPriority = useTypedEventEmitterState(room, RoomEvent.Tags, () => !!room.tags[DefaultTagID.LowPriority]);
|
||||
|
||||
let badgeDecoration: AvatarBadgeDecoration | undefined;
|
||||
if (isLowPriority) {
|
||||
|
||||
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useMemo, type ComponentProps } from "react";
|
||||
import { type Room, RoomType, KnownMembership, EventType } from "matrix-js-sdk/src/matrix";
|
||||
import { type Room, RoomType, KnownMembership, EventType, RoomEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { type RoomAvatarEventContent } from "matrix-js-sdk/src/types";
|
||||
|
||||
import BaseAvatar from "./BaseAvatar";
|
||||
@@ -21,6 +21,7 @@ import { useSettingValue } from "../../../hooks/useSettings";
|
||||
import { useRoomState } from "../../../hooks/useRoomState";
|
||||
import { useRoomIdName } from "../../../hooks/room/useRoomIdName";
|
||||
import { MediaPreviewValue } from "../../../@types/media_preview";
|
||||
import { useTypedEventEmitterState } from "../../../hooks/useEventEmitter";
|
||||
|
||||
interface IProps extends Omit<ComponentProps<typeof BaseAvatar>, "name" | "idName" | "url" | "onClick" | "size"> {
|
||||
// Room may be left unset here, but if it is,
|
||||
@@ -37,7 +38,8 @@ interface IProps extends Omit<ComponentProps<typeof BaseAvatar>, "name" | "idNam
|
||||
}
|
||||
|
||||
const RoomAvatar: React.FC<IProps> = ({ room, viewAvatarOnClick, onClick, oobData, size = "36px", ...otherProps }) => {
|
||||
const roomName = room?.name ?? oobData?.name ?? "?";
|
||||
const name = useTypedEventEmitterState(room, RoomEvent.Name, () => room?.name);
|
||||
const roomName = name ?? oobData?.name ?? "?";
|
||||
const avatarEvent = useRoomState(room, (state) => state.getStateEvents(EventType.RoomAvatar, ""));
|
||||
const roomIdName = useRoomIdName(room, oobData);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { type JSX } from "react";
|
||||
import React, { memo, type JSX } from "react";
|
||||
import { type Room } from "matrix-js-sdk/src/matrix";
|
||||
import PublicIcon from "@vector-im/compound-design-tokens/assets/web/icons/public";
|
||||
import VideoIcon from "@vector-im/compound-design-tokens/assets/web/icons/video-call-solid";
|
||||
@@ -33,7 +33,7 @@ interface RoomAvatarViewProps {
|
||||
* Component to display the avatar of a room.
|
||||
* Currently only 32px size is supported.
|
||||
*/
|
||||
export function RoomAvatarView({ room }: RoomAvatarViewProps): JSX.Element {
|
||||
export const RoomAvatarView = memo(function RoomAvatarView({ room }: RoomAvatarViewProps): JSX.Element {
|
||||
const vm = useRoomAvatarViewModel(room);
|
||||
// No decoration, we just show the avatar
|
||||
if (!vm.badgeDecoration) return <RoomAvatar size="32px" room={room} />;
|
||||
@@ -54,7 +54,7 @@ export function RoomAvatarView({ room }: RoomAvatarViewProps): JSX.Element {
|
||||
{label ? <Tooltip label={label}>{icon}</Tooltip> : icon}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the decoration for the avatar based on the presence.
|
||||
|
||||
Reference in New Issue
Block a user