Merge pull request #5874 from matrix-org/gsouquet-room-events

This commit is contained in:
Germain 2021-04-21 09:09:01 +01:00 committed by GitHub
commit 68fb9a78c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 155 additions and 138 deletions

View file

@ -289,12 +289,11 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
// shallow-copy from the template as we need to make modifications to it
this.tagAesthetics = objectShallowClone(TAG_AESTHETICS);
this.updateDmAddRoomAction();
this.dispatcherRef = defaultDispatcher.register(this.onAction);
this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate);
}
public componentDidMount(): void {
this.dispatcherRef = defaultDispatcher.register(this.onAction);
this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate);
SpaceStore.instance.on(SUGGESTED_ROOMS, this.updateSuggestedRooms);
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.updateLists);
this.customTagStoreRef = CustomRoomTagStore.addListener(this.updateLists);
@ -502,59 +501,50 @@ export default class RoomList extends React.PureComponent<IProps, IState> {
}
private renderSublists(): React.ReactElement[] {
const components: React.ReactElement[] = [];
const tagOrder = TAG_ORDER.reduce((p, c) => {
if (c === CUSTOM_TAGS_BEFORE_TAG) {
const customTags = Object.keys(this.state.sublists)
.filter(t => isCustomTag(t));
p.push(...customTags);
}
p.push(c);
return p;
}, [] as TagID[]);
// show a skeleton UI if the user is in no rooms and they are not filtering
const showSkeleton = !this.state.isNameFiltering &&
Object.values(RoomListStore.instance.unfilteredLists).every(list => !list?.length);
for (const orderedTagId of tagOrder) {
const orderedRooms = this.state.sublists[orderedTagId] || [];
let extraTiles = null;
if (orderedTagId === DefaultTagID.Invite) {
extraTiles = this.renderCommunityInvites();
} else if (orderedTagId === DefaultTagID.Suggested) {
extraTiles = this.renderSuggestedRooms();
return TAG_ORDER.reduce((tags, tagId) => {
if (tagId === CUSTOM_TAGS_BEFORE_TAG) {
const customTags = Object.keys(this.state.sublists)
.filter(tagId => isCustomTag(tagId));
tags.push(...customTags);
}
tags.push(tagId);
return tags;
}, [] as TagID[])
.map(orderedTagId => {
let extraTiles = null;
if (orderedTagId === DefaultTagID.Invite) {
extraTiles = this.renderCommunityInvites();
} else if (orderedTagId === DefaultTagID.Suggested) {
extraTiles = this.renderSuggestedRooms();
}
const totalTiles = orderedRooms.length + (extraTiles ? extraTiles.length : 0);
if (totalTiles === 0 && !ALWAYS_VISIBLE_TAGS.includes(orderedTagId)) {
continue; // skip tag - not needed
}
const aesthetics: ITagAesthetics = isCustomTag(orderedTagId)
? customTagAesthetics(orderedTagId)
: this.tagAesthetics[orderedTagId];
if (!aesthetics) throw new Error(`Tag ${orderedTagId} does not have aesthetics`);
const aesthetics: ITagAesthetics = isCustomTag(orderedTagId)
? customTagAesthetics(orderedTagId)
: this.tagAesthetics[orderedTagId];
if (!aesthetics) throw new Error(`Tag ${orderedTagId} does not have aesthetics`);
components.push(<RoomSublist
key={`sublist-${orderedTagId}`}
tagId={orderedTagId}
forRooms={true}
startAsHidden={aesthetics.defaultHidden}
label={aesthetics.sectionLabelRaw ? aesthetics.sectionLabelRaw : _t(aesthetics.sectionLabel)}
onAddRoom={aesthetics.onAddRoom}
addRoomLabel={aesthetics.addRoomLabel ? _t(aesthetics.addRoomLabel) : aesthetics.addRoomLabel}
addRoomContextMenu={aesthetics.addRoomContextMenu}
isMinimized={this.props.isMinimized}
onResize={this.props.onResize}
showSkeleton={showSkeleton}
extraTiles={extraTiles}
/>);
}
return components;
// The cost of mounting/unmounting this component offsets the cost
// of keeping it in the DOM and hiding it when it is not required
return <RoomSublist
key={`sublist-${orderedTagId}`}
tagId={orderedTagId}
forRooms={true}
startAsHidden={aesthetics.defaultHidden}
label={aesthetics.sectionLabelRaw ? aesthetics.sectionLabelRaw : _t(aesthetics.sectionLabel)}
onAddRoom={aesthetics.onAddRoom}
addRoomLabel={aesthetics.addRoomLabel ? _t(aesthetics.addRoomLabel) : aesthetics.addRoomLabel}
addRoomContextMenu={aesthetics.addRoomContextMenu}
isMinimized={this.props.isMinimized}
onResize={this.props.onResize}
showSkeleton={showSkeleton}
extraTiles={extraTiles}
alwaysVisible={ALWAYS_VISIBLE_TAGS.includes(orderedTagId)}
/>
});
}
public render() {

View file

@ -74,6 +74,7 @@ interface IProps {
tagId: TagID;
onResize: () => void;
showSkeleton?: boolean;
alwaysVisible?: boolean;
extraTiles?: ReactComponentElement<typeof ExtraTile>[];
@ -125,8 +126,6 @@ export default class RoomSublist extends React.Component<IProps, IState> {
};
// Why Object.assign() and not this.state.height? Because TypeScript says no.
this.state = Object.assign(this.state, {height: this.calculateInitialHeight()});
this.dispatcherRef = defaultDispatcher.register(this.onAction);
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.onListsUpdated);
}
private calculateInitialHeight() {
@ -242,6 +241,11 @@ export default class RoomSublist extends React.Component<IProps, IState> {
return false;
}
public componentDidMount() {
this.dispatcherRef = defaultDispatcher.register(this.onAction);
RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.onListsUpdated);
}
public componentWillUnmount() {
defaultDispatcher.unregister(this.dispatcherRef);
RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.onListsUpdated);
@ -759,6 +763,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
'mx_RoomSublist': true,
'mx_RoomSublist_hasMenuOpen': !!this.state.contextMenuPosition,
'mx_RoomSublist_minimized': this.props.isMinimized,
'mx_RoomSublist_hidden': !this.state.rooms.length && this.props.alwaysVisible !== true,
});
let content = null;

View file

@ -97,22 +97,8 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
// generatePreview() will return nothing if the user has previews disabled
messagePreview: this.generatePreview(),
};
ActiveRoomObserver.addListener(this.props.room.roomId, this.onActiveRoomUpdate);
this.dispatcherRef = defaultDispatcher.register(this.onAction);
MessagePreviewStore.instance.on(
MessagePreviewStore.getPreviewChangedEventName(this.props.room),
this.onRoomPreviewChanged,
);
this.notificationState = RoomNotificationStateStore.instance.getRoomState(this.props.room);
this.notificationState.on(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate);
this.roomProps = EchoChamber.forRoom(this.props.room);
this.roomProps.on(PROPERTY_UPDATED, this.onRoomPropertyUpdate);
CommunityPrototypeStore.instance.on(
CommunityPrototypeStore.getUpdateEventName(this.props.room.roomId),
this.onCommunityUpdate,
);
this.props.room.on("Room.name", this.onRoomNameUpdate);
}
private onRoomNameUpdate = (room) => {
@ -167,6 +153,20 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
if (this.state.selected) {
this.scrollIntoView();
}
ActiveRoomObserver.addListener(this.props.room.roomId, this.onActiveRoomUpdate);
this.dispatcherRef = defaultDispatcher.register(this.onAction);
MessagePreviewStore.instance.on(
MessagePreviewStore.getPreviewChangedEventName(this.props.room),
this.onRoomPreviewChanged,
);
this.notificationState.on(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate);
this.roomProps.on(PROPERTY_UPDATED, this.onRoomPropertyUpdate);
this.roomProps.on("Room.name", this.onRoomNameUpdate);
CommunityPrototypeStore.instance.on(
CommunityPrototypeStore.getUpdateEventName(this.props.room.roomId),
this.onCommunityUpdate,
);
}
public componentWillUnmount() {
@ -182,8 +182,15 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
);
this.props.room.off("Room.name", this.onRoomNameUpdate);
}
ActiveRoomObserver.removeListener(this.props.room.roomId, this.onActiveRoomUpdate);
defaultDispatcher.unregister(this.dispatcherRef);
this.notificationState.off(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate);
this.roomProps.off(PROPERTY_UPDATED, this.onRoomPropertyUpdate);
this.roomProps.off("Room.name", this.onRoomNameUpdate);
CommunityPrototypeStore.instance.off(
CommunityPrototypeStore.getUpdateEventName(this.props.room.roomId),
this.onCommunityUpdate,
);
}
private onAction = (payload: ActionPayload) => {
@ -547,7 +554,7 @@ export default class RoomTile extends React.PureComponent<IProps, IState> {
/>;
let badge: React.ReactNode;
if (!this.props.isMinimized) {
if (!this.props.isMinimized && this.notificationState) {
// aria-hidden because we summarise the unread count/highlight status in a manual aria-label below
badge = (
<div className="mx_RoomTile_badgeContainer" aria-hidden="true">