diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index dd8b567c26..0ff6d8d222 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -266,12 +266,11 @@ export default class RoomList extends React.Component { } }; - private renderCommunityInvites(): React.ReactElement[] { + private renderCommunityInvites(): TemporaryTile[] { // TODO: Put community invites in a more sensible place (not in the room list) // See https://github.com/vector-im/riot-web/issues/14456 return MatrixClientPeg.get().getGroups().filter(g => { - if (g.myMembership !== 'invite') return false; - return !this.searchFilter || this.searchFilter.matches(g.name || ""); + return g.myMembership === 'invite'; }).map(g => { const avatar = ( { @@ -146,8 +148,18 @@ export default class RoomSublist extends React.Component { return padding; } + private get extraTiles(): TemporaryTile[] | null { + if (this.state.filteredExtraTiles) { + return this.state.filteredExtraTiles; + } + if (this.props.extraBadTilesThatShouldntExist) { + return this.props.extraBadTilesThatShouldntExist; + } + return null; + } + private get numTiles(): number { - return RoomSublist.calcNumTiles(this.state.rooms, this.props.extraBadTilesThatShouldntExist); + return RoomSublist.calcNumTiles(this.state.rooms, this.extraTiles); } private static calcNumTiles(rooms: Room[], extraTiles: any[]) { @@ -168,9 +180,10 @@ export default class RoomSublist extends React.Component { this.setState({isExpanded: !this.layout.isCollapsed}); } } + const prevExtraTiles = prevState.filteredExtraTiles || prevProps.extraBadTilesThatShouldntExist; // as the rooms can come in one by one we need to reevaluate // the amount of available rooms to cap the amount of requested visible rooms by the layout - if (RoomSublist.calcNumTiles(prevState.rooms, prevProps.extraBadTilesThatShouldntExist) !== this.numTiles) { + if (RoomSublist.calcNumTiles(prevState.rooms, prevExtraTiles) !== this.numTiles) { this.setState({height: this.calculateInitialHeight()}); } } @@ -191,14 +204,14 @@ export default class RoomSublist extends React.Component { // If we're supposed to handle extra tiles, take the performance hit and re-render all the // time so we don't have to consider them as part of the visible room optimization. const prevExtraTiles = this.props.extraBadTilesThatShouldntExist || []; - const nextExtraTiles = nextProps.extraBadTilesThatShouldntExist || []; + const nextExtraTiles = (nextState.filteredExtraTiles || nextProps.extraBadTilesThatShouldntExist) || []; if (prevExtraTiles.length > 0 || nextExtraTiles.length > 0) { return true; } // If we're about to update the height of the list, we don't really care about which rooms // are visible or not for no-op purposes, so ensure that the height calculation runs through. - if (RoomSublist.calcNumTiles(nextState.rooms, nextProps.extraBadTilesThatShouldntExist) !== this.numTiles) { + if (RoomSublist.calcNumTiles(nextState.rooms, nextExtraTiles) !== this.numTiles) { return true; } @@ -238,10 +251,26 @@ export default class RoomSublist extends React.Component { } private onListsUpdated = () => { + const stateUpdates: IState & any = {}; // &any is to avoid a cast on the initializer + + if (this.props.extraBadTilesThatShouldntExist) { + const nameCondition = RoomListStore.instance.getFirstNameFilterCondition(); + if (nameCondition) { + stateUpdates.filteredExtraTiles = this.props.extraBadTilesThatShouldntExist + .filter(t => nameCondition.matches(t.props.displayName || "")); + } else if (this.state.filteredExtraTiles) { + stateUpdates.filteredExtraTiles = null; + } + } + const currentRooms = this.state.rooms; const newRooms = RoomListStore.instance.orderedLists[this.props.tagId] || []; if (arrayHasOrderChange(currentRooms, newRooms)) { - this.setState({rooms: newRooms}); + stateUpdates.rooms = newRooms; + } + + if (Object.keys(stateUpdates).length > 0) { + this.setState(stateUpdates); } }; @@ -484,8 +513,9 @@ export default class RoomSublist extends React.Component { } } - if (this.props.extraBadTilesThatShouldntExist) { - tiles.push(...this.props.extraBadTilesThatShouldntExist); + if (this.extraTiles) { + // HACK: We break typing here, but this 'extra tiles' property shouldn't exist. + (tiles as any[]).push(...this.extraTiles); } // We only have to do this because of the extra tiles. We do it conditionally diff --git a/src/stores/room-list/RoomListStore.ts b/src/stores/room-list/RoomListStore.ts index 1f6c14ba2f..7049381c75 100644 --- a/src/stores/room-list/RoomListStore.ts +++ b/src/stores/room-list/RoomListStore.ts @@ -32,6 +32,7 @@ import { isNullOrUndefined } from "matrix-js-sdk/src/utils"; import RoomListLayoutStore from "./RoomListLayoutStore"; import { MarkedExecution } from "../../utils/MarkedExecution"; import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; +import { NameFilterCondition } from "./filters/NameFilterCondition"; interface IState { tagsEnabled?: boolean; @@ -588,6 +589,20 @@ export class RoomListStoreClass extends AsyncStoreWithClient { this.updateFn.trigger(); } + /** + * Gets the first (and ideally only) name filter condition. If one isn't present, + * this returns null. + * @returns The first name filter condition, or null if none. + */ + public getFirstNameFilterCondition(): NameFilterCondition | null { + for (const filter of this.filterConditions) { + if (filter instanceof NameFilterCondition) { + return filter; + } + } + return null; + } + /** * Gets the tags for a room identified by the store. The returned set * should never be empty, and will contain DefaultTagID.Untagged if