Refactor Space Hierarchy stuff in preparation for pagination

pull/21833/head
Michael Telatynski 2021-07-29 17:35:15 +01:00
parent 56cd0e1c4f
commit d459dbe700
4 changed files with 122 additions and 132 deletions

View File

@ -833,6 +833,6 @@ export default class RoomDirectory extends React.Component<IProps, IState> {
// Similar to matrix-react-sdk's MatrixTools.getDisplayAliasForRoom // Similar to matrix-react-sdk's MatrixTools.getDisplayAliasForRoom
// but works with the objects we get from the public room list // but works with the objects we get from the public room list
function getDisplayAliasForRoom(room: IPublicRoomsChunkRoom) { export function getDisplayAliasForRoom(room: IPublicRoomsChunkRoom) {
return getDisplayAliasForAliasSet(room.canonical_alias, room.aliases); return getDisplayAliasForAliasSet(room.canonical_alias, room.aliases);
} }

View File

@ -14,15 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React, { ReactNode, useMemo, useState } from "react"; import React, { ReactNode, useCallback, useEffect, useMemo, useState } from "react";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy";
import { EventType, RoomType } from "matrix-js-sdk/src/@types/event"; import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
import { IRoomChild, IRoomChildState } from "matrix-js-sdk/src/@types/spaces"; import { IHierarchyRelation, IHierarchyRoom } from "matrix-js-sdk/src/@types/spaces";
import classNames from "classnames"; import classNames from "classnames";
import { sortBy } from "lodash"; import { sortBy } from "lodash";
import { MatrixClientPeg } from "../../MatrixClientPeg"; import { MatrixClientPeg } from "../../MatrixClientPeg";
import dis from "../../dispatcher/dispatcher"; import dis from "../../dispatcher/dispatcher";
import defaultDispatcher from "../../dispatcher/dispatcher";
import { _t } from "../../languageHandler"; import { _t } from "../../languageHandler";
import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton"; import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButton";
import BaseDialog from "../views/dialogs/BaseDialog"; import BaseDialog from "../views/dialogs/BaseDialog";
@ -30,8 +32,6 @@ import Spinner from "../views/elements/Spinner";
import SearchBox from "./SearchBox"; import SearchBox from "./SearchBox";
import RoomAvatar from "../views/avatars/RoomAvatar"; import RoomAvatar from "../views/avatars/RoomAvatar";
import RoomName from "../views/elements/RoomName"; import RoomName from "../views/elements/RoomName";
import { useAsyncMemo } from "../../hooks/useAsyncMemo";
import { EnhancedMap } from "../../utils/maps";
import StyledCheckbox from "../views/elements/StyledCheckbox"; import StyledCheckbox from "../views/elements/StyledCheckbox";
import AutoHideScrollbar from "./AutoHideScrollbar"; import AutoHideScrollbar from "./AutoHideScrollbar";
import BaseAvatar from "../views/avatars/BaseAvatar"; import BaseAvatar from "../views/avatars/BaseAvatar";
@ -42,20 +42,19 @@ import { useStateToggle } from "../../hooks/useStateToggle";
import { getChildOrder } from "../../stores/SpaceStore"; import { getChildOrder } from "../../stores/SpaceStore";
import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton";
import { linkifyElement } from "../../HtmlUtils"; import { linkifyElement } from "../../HtmlUtils";
import { getDisplayAliasForAliasSet } from "../../Rooms";
import { useDispatcher } from "../../hooks/useDispatcher"; import { useDispatcher } from "../../hooks/useDispatcher";
import defaultDispatcher from "../../dispatcher/dispatcher";
import { Action } from "../../dispatcher/actions"; import { Action } from "../../dispatcher/actions";
import { getDisplayAliasForRoom } from "./RoomDirectory";
interface IHierarchyProps { interface IHierarchyProps {
space: Room; space: Room;
initialText?: string; initialText?: string;
additionalButtons?: ReactNode; additionalButtons?: ReactNode;
showRoom(room: IRoomChild, viaServers?: string[], autoJoin?: boolean): void; showRoom(hierarchy: RoomHierarchy, roomId: string, autoJoin?: boolean): void;
} }
interface ITileProps { interface ITileProps {
room: IRoomChild; room: IHierarchyRoom;
suggested?: boolean; suggested?: boolean;
selected?: boolean; selected?: boolean;
numChildRooms?: number; numChildRooms?: number;
@ -206,7 +205,9 @@ const Tile: React.FC<ITileProps> = ({
</>; </>;
}; };
export const showRoom = (room: IRoomChild, viaServers?: string[], autoJoin = false) => { export const showRoom = (hierarchy: RoomHierarchy, roomId: string, autoJoin = false) => {
const room = hierarchy.roomMap.get(roomId);
// Don't let the user view a room they won't be able to either peek or join: // Don't let the user view a room they won't be able to either peek or join:
// fail earlier so they don't have to click back to the directory. // fail earlier so they don't have to click back to the directory.
if (MatrixClientPeg.get().isGuest()) { if (MatrixClientPeg.get().isGuest()) {
@ -224,7 +225,7 @@ export const showRoom = (room: IRoomChild, viaServers?: string[], autoJoin = fal
_type: "room_directory", // instrumentation _type: "room_directory", // instrumentation
room_alias: roomAlias, room_alias: roomAlias,
room_id: room.room_id, room_id: room.room_id,
via_servers: viaServers, via_servers: Array.from(hierarchy.viaMap.get(roomId) || []),
oob_data: { oob_data: {
avatarUrl: room.avatar_url, avatarUrl: room.avatar_url,
// XXX: This logic is duplicated from the JS SDK which would normally decide what the name is. // XXX: This logic is duplicated from the JS SDK which would normally decide what the name is.
@ -234,9 +235,9 @@ export const showRoom = (room: IRoomChild, viaServers?: string[], autoJoin = fal
}; };
interface IHierarchyLevelProps { interface IHierarchyLevelProps {
spaceId: string; root: IHierarchyRoom;
rooms: Map<string, IRoomChild>; roomSet: Set<IHierarchyRoom>;
relations: Map<string, Map<string, IRoomChildState>>; hierarchy: RoomHierarchy;
parents: Set<string>; parents: Set<string>;
selectedMap?: Map<string, Set<string>>; selectedMap?: Map<string, Set<string>>;
onViewRoomClick(roomId: string, autoJoin: boolean): void; onViewRoomClick(roomId: string, autoJoin: boolean): void;
@ -244,67 +245,69 @@ interface IHierarchyLevelProps {
} }
export const HierarchyLevel = ({ export const HierarchyLevel = ({
spaceId, root,
rooms, roomSet,
relations, hierarchy,
parents, parents,
selectedMap, selectedMap,
onViewRoomClick, onViewRoomClick,
onToggleClick, onToggleClick,
}: IHierarchyLevelProps) => { }: IHierarchyLevelProps) => {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const space = cli.getRoom(spaceId); const space = cli.getRoom(root.room_id);
const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId()); const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId());
const children = Array.from(relations.get(spaceId)?.values() || []); const sortedChildren = sortBy(root.children_state, ev => {
const sortedChildren = sortBy(children, ev => { return getChildOrder(ev.content.order, ev.origin_server_ts, ev.state_key);
// XXX: Space Summary API doesn't give the child origin_server_ts but once it does we should use it for sorting
return getChildOrder(ev.content.order, null, ev.state_key);
}); });
const [subspaces, childRooms] = sortedChildren.reduce((result, ev: IRoomChildState) => {
const roomId = ev.state_key;
if (!rooms.has(roomId)) return result;
result[rooms.get(roomId).room_type === RoomType.Space ? 0 : 1].push(roomId);
return result;
}, [[], []]) || [[], []];
const newParents = new Set(parents).add(spaceId); const [subspaces, childRooms] = sortedChildren.reduce((result, ev: IHierarchyRelation) => {
const room = hierarchy.roomMap.get(ev.state_key);
if (room && roomSet.has(room)) {
result[room.room_type === RoomType.Space ? 0 : 1].push(room);
}
return result;
}, [[] as IHierarchyRoom[], [] as IHierarchyRoom[]]);
const newParents = new Set(parents).add(root.room_id);
return <React.Fragment> return <React.Fragment>
{ {
childRooms.map(roomId => ( childRooms.map(room => (
<Tile <Tile
key={roomId} key={room.room_id}
room={rooms.get(roomId)} room={room}
suggested={relations.get(spaceId)?.get(roomId)?.content.suggested} suggested={hierarchy.isSuggested(root.room_id, room.room_id)}
selected={selectedMap?.get(spaceId)?.has(roomId)} selected={selectedMap?.get(root.room_id)?.has(room.room_id)}
onViewRoomClick={(autoJoin) => { onViewRoomClick={(autoJoin) => {
onViewRoomClick(roomId, autoJoin); onViewRoomClick(room.room_id, autoJoin);
}} }}
hasPermissions={hasPermissions} hasPermissions={hasPermissions}
onToggleClick={onToggleClick ? () => onToggleClick(spaceId, roomId) : undefined} onToggleClick={onToggleClick ? () => onToggleClick(root.room_id, room.room_id) : undefined}
/> />
)) ))
} }
{ {
subspaces.filter(roomId => !newParents.has(roomId)).map(roomId => ( subspaces.filter(room => !newParents.has(room.room_id)).map(space => (
<Tile <Tile
key={roomId} key={space.room_id}
room={rooms.get(roomId)} room={space}
numChildRooms={Array.from(relations.get(roomId)?.values() || []) numChildRooms={space.children_state.filter(ev => {
.filter(ev => rooms.has(ev.state_key) && !rooms.get(ev.state_key).room_type).length} const room = hierarchy.roomMap.get(ev.state_key);
suggested={relations.get(spaceId)?.get(roomId)?.content.suggested} return room && roomSet.has(room) && !room.room_type;
selected={selectedMap?.get(spaceId)?.has(roomId)} }).length}
suggested={hierarchy.isSuggested(root.room_id, space.room_id)}
selected={selectedMap?.get(root.room_id)?.has(space.room_id)}
onViewRoomClick={(autoJoin) => { onViewRoomClick={(autoJoin) => {
onViewRoomClick(roomId, autoJoin); onViewRoomClick(space.room_id, autoJoin);
}} }}
hasPermissions={hasPermissions} hasPermissions={hasPermissions}
onToggleClick={onToggleClick ? () => onToggleClick(spaceId, roomId) : undefined} onToggleClick={onToggleClick ? () => onToggleClick(root.room_id, space.room_id) : undefined}
> >
<HierarchyLevel <HierarchyLevel
spaceId={roomId} root={space}
rooms={rooms} roomSet={roomSet}
relations={relations} hierarchy={hierarchy}
parents={newParents} parents={newParents}
selectedMap={selectedMap} selectedMap={selectedMap}
onViewRoomClick={onViewRoomClick} onViewRoomClick={onViewRoomClick}
@ -316,49 +319,53 @@ export const HierarchyLevel = ({
</React.Fragment>; </React.Fragment>;
}; };
export const useSpaceSummary = (space: Room): [ export const useSpaceSummary = (space: Room): {
null, loading: boolean;
IRoomChild[], rooms: IHierarchyRoom[];
Map<string, Map<string, IRoomChildState>>?, hierarchy: RoomHierarchy;
Map<string, Set<string>>?, loadMore(pageSize?: number): Promise <void>;
Map<string, Set<string>>?, } => {
] | [Error] => { const [rooms, setRooms] = useState<IHierarchyRoom[]>([]);
// crude temporary refresh token approach until we have pagination and rework the data flow here const [loading, setLoading] = useState(true);
const [refreshToken, setRefreshToken] = useState(0);
const INITIAL_PAGE_SIZE = 20;
const [hierarchy, setHierarchy] = useState<RoomHierarchy>();
const resetHierarchy = useCallback(() => {
const hierarchy = new RoomHierarchy(space, INITIAL_PAGE_SIZE);
setHierarchy(hierarchy);
let discard = false;
hierarchy.load().then(() => {
if (discard) return;
setRooms(hierarchy.rooms);
setLoading(false);
});
return () => {
discard = true;
};
}, [space]);
useEffect(resetHierarchy, [resetHierarchy]);
useDispatcher(defaultDispatcher, (payload => { useDispatcher(defaultDispatcher, (payload => {
if (payload.action === Action.UpdateSpaceHierarchy) { if (payload.action === Action.UpdateSpaceHierarchy) {
setRefreshToken(t => t + 1); setLoading(true);
setRooms([]); // TODO
resetHierarchy();
} }
})); }));
// TODO pagination const loadMore = useCallback(async (pageSize?: number) => {
return useAsyncMemo(async () => { if (!hierarchy.canLoadMore || hierarchy.noSupport) return;
try {
const { rooms } = await space.client.getRoomChildren(space.roomId);
const parentChildRelations = new EnhancedMap<string, Map<string, IRoomChildState>>(); setLoading(true);
const childParentRelations = new EnhancedMap<string, Set<string>>(); await hierarchy.load(pageSize);
const viaMap = new EnhancedMap<string, Set<string>>(); setRooms(hierarchy.rooms);
setLoading(false);
}, [hierarchy]);
rooms.forEach(room => { return { loading, rooms, hierarchy, loadMore };
room.children_state.forEach((ev: IRoomChildState) => {
if (ev.type === EventType.SpaceChild) {
parentChildRelations.getOrCreate(ev.room_id, new Map()).set(ev.state_key, ev);
childParentRelations.getOrCreate(ev.state_key, new Set()).add(ev.room_id);
}
if (Array.isArray(ev.content.via)) {
const set = viaMap.getOrCreate(ev.state_key, new Set());
ev.content.via.forEach(via => set.add(via));
}
});
});
return [null, rooms, parentChildRelations, viaMap, childParentRelations];
} catch (e) {
console.error(e); // TODO
return [e];
}
}, [space, refreshToken], [undefined]);
}; };
export const SpaceHierarchy: React.FC<IHierarchyProps> = ({ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
@ -374,14 +381,12 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
const [selected, setSelected] = useState(new Map<string, Set<string>>()); // Map<parentId, Set<childId>> const [selected, setSelected] = useState(new Map<string, Set<string>>()); // Map<parentId, Set<childId>>
const [summaryError, rooms, parentChildMap, viaMap, childParentMap] = useSpaceSummary(space); const { loading, rooms, hierarchy } = useSpaceSummary(space);
const roomsMap = useMemo(() => { const filteredRoomSet = useMemo<Set<IHierarchyRoom>>(() => {
if (!rooms) return null; if (!rooms.length) return new Set();
const lcQuery = query.toLowerCase().trim(); const lcQuery = query.toLowerCase().trim();
if (!lcQuery) return new Set(rooms);
const roomsMap = new Map<string, IRoomChild>(rooms.map(r => [r.room_id, r]));
if (!lcQuery) return roomsMap;
const directMatches = rooms.filter(r => { const directMatches = rooms.filter(r => {
return r.name?.toLowerCase().includes(lcQuery) || r.topic?.toLowerCase().includes(lcQuery); return r.name?.toLowerCase().includes(lcQuery) || r.topic?.toLowerCase().includes(lcQuery);
@ -393,34 +398,30 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
while (queue.length) { while (queue.length) {
const roomId = queue.pop(); const roomId = queue.pop();
visited.add(roomId); visited.add(roomId);
childParentMap.get(roomId)?.forEach(parentId => { hierarchy.backRefs.get(roomId)?.forEach(parentId => {
if (!visited.has(parentId)) { if (!visited.has(parentId)) {
queue.push(parentId); queue.push(parentId);
} }
}); });
} }
// Remove any mappings for rooms which were not visited in the walk return new Set(rooms.filter(r => visited.has(r.room_id)));
Array.from(roomsMap.keys()).forEach(roomId => { }, [rooms, hierarchy, query]);
if (!visited.has(roomId)) {
roomsMap.delete(roomId);
}
});
return roomsMap;
}, [rooms, childParentMap, query]);
const [error, setError] = useState(""); const [error, setError] = useState("");
const [removing, setRemoving] = useState(false); const [removing, setRemoving] = useState(false);
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
if (summaryError) { if (!loading && hierarchy.noSupport) {
return <p>{ _t("Your server does not support showing space hierarchies.") }</p>; return <p>{ _t("Your server does not support showing space hierarchies.") }</p>;
} }
let content; let content;
if (roomsMap) { if (loading) {
const numRooms = Array.from(roomsMap.values()).filter(r => !r.room_type).length; content = <Spinner />;
const numSpaces = roomsMap.size - numRooms - 1; // -1 at the end to exclude the space we are looking at } else {
const numRooms = Array.from(filteredRoomSet).filter(r => !r.room_type).length;
const numSpaces = filteredRoomSet.size - numRooms - 1; // -1 at the end to exclude the space we are looking at
let countsStr; let countsStr;
if (numSpaces > 1) { if (numSpaces > 1) {
@ -438,7 +439,7 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
}); });
const selectionAllSuggested = selectedRelations.every(([parentId, childId]) => { const selectionAllSuggested = selectedRelations.every(([parentId, childId]) => {
return parentChildMap.get(parentId)?.get(childId)?.content.suggested; return hierarchy.isSuggested(parentId, childId);
}); });
const disabled = !selectedRelations.length || removing || saving; const disabled = !selectedRelations.length || removing || saving;
@ -461,17 +462,14 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
try { try {
for (const [parentId, childId] of selectedRelations) { for (const [parentId, childId] of selectedRelations) {
await cli.sendStateEvent(parentId, EventType.SpaceChild, {}, childId); await cli.sendStateEvent(parentId, EventType.SpaceChild, {}, childId);
parentChildMap.get(parentId).delete(childId);
if (parentChildMap.get(parentId).size > 0) { hierarchy.removeRelation(parentId, childId);
parentChildMap.set(parentId, new Map(parentChildMap.get(parentId)));
} else {
parentChildMap.delete(parentId);
}
} }
} catch (e) { } catch (e) {
setError(_t("Failed to remove some rooms. Try again later")); setError(_t("Failed to remove some rooms. Try again later"));
} }
setRemoving(false); setRemoving(false);
setSelected(new Map());
}} }}
kind="danger_outline" kind="danger_outline"
disabled={disabled} disabled={disabled}
@ -485,7 +483,7 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
try { try {
for (const [parentId, childId] of selectedRelations) { for (const [parentId, childId] of selectedRelations) {
const suggested = !selectionAllSuggested; const suggested = !selectionAllSuggested;
const existingContent = parentChildMap.get(parentId)?.get(childId)?.content; const existingContent = hierarchy.getRelation(parentId, childId)?.content;
if (!existingContent || existingContent.suggested === suggested) continue; if (!existingContent || existingContent.suggested === suggested) continue;
const content = { const content = {
@ -495,8 +493,8 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
await cli.sendStateEvent(parentId, EventType.SpaceChild, content, childId); await cli.sendStateEvent(parentId, EventType.SpaceChild, content, childId);
parentChildMap.get(parentId).get(childId).content = content; // mutate the local state to save us having to refetch the world
parentChildMap.set(parentId, new Map(parentChildMap.get(parentId))); existingContent.suggested = content.suggested;
} }
} catch (e) { } catch (e) {
setError("Failed to update some suggestions. Try again later"); setError("Failed to update some suggestions. Try again later");
@ -516,14 +514,14 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
} }
let results; let results;
if (roomsMap.size) { if (filteredRoomSet.size) {
const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId()); const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId());
results = <> results = <>
<HierarchyLevel <HierarchyLevel
spaceId={space.roomId} root={hierarchy.roomMap.get(space.roomId)}
rooms={roomsMap} roomSet={filteredRoomSet}
relations={parentChildMap} hierarchy={hierarchy}
parents={new Set()} parents={new Set()}
selectedMap={selected} selectedMap={selected}
onToggleClick={hasPermissions ? (parentId, childId) => { onToggleClick={hasPermissions ? (parentId, childId) => {
@ -543,7 +541,7 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
setSelected(new Map(selected.set(parentId, new Set(parentSet)))); setSelected(new Map(selected.set(parentId, new Set(parentSet))));
} : undefined} } : undefined}
onViewRoomClick={(roomId, autoJoin) => { onViewRoomClick={(roomId, autoJoin) => {
showRoom(roomsMap.get(roomId), Array.from(viaMap.get(roomId) || []), autoJoin); showRoom(hierarchy, roomId, autoJoin);
}} }}
/> />
{ children && <hr /> } { children && <hr /> }
@ -571,8 +569,6 @@ export const SpaceHierarchy: React.FC<IHierarchyProps> = ({
{ children } { children }
</AutoHideScrollbar> </AutoHideScrollbar>
</>; </>;
} else {
content = <Spinner />;
} }
// TODO loading state/error state // TODO loading state/error state
@ -624,8 +620,8 @@ const SpaceRoomDirectory: React.FC<IProps> = ({ space, onFinished, initialText }
<SpaceHierarchy <SpaceHierarchy
space={space} space={space}
showRoom={(room: IRoomChild, viaServers?: string[], autoJoin = false) => { showRoom={(hierarchy: RoomHierarchy, roomId: string, autoJoin = false) => {
showRoom(room, viaServers, autoJoin); showRoom(hierarchy, roomId, autoJoin);
onFinished(); onFinished();
}} }}
initialText={initialText} initialText={initialText}
@ -644,9 +640,3 @@ const SpaceRoomDirectory: React.FC<IProps> = ({ space, onFinished, initialText }
}; };
export default SpaceRoomDirectory; export default SpaceRoomDirectory;
// Similar to matrix-react-sdk's MatrixTools.getDisplayAliasForRoom
// but works with the objects we get from the public room list
function getDisplayAliasForRoom(room: IRoomChild) {
return getDisplayAliasForAliasSet(room.canonical_alias, room.aliases);
}

View File

@ -19,7 +19,7 @@ import { ListIteratee, Many, sortBy, throttle } from "lodash";
import { EventType, RoomType } from "matrix-js-sdk/src/@types/event"; import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import { IRoomChild } from "matrix-js-sdk/src/@types/spaces"; import { IHierarchyRoom } from "matrix-js-sdk/src/@types/spaces";
import { JoinRule } from "matrix-js-sdk/src/@types/partials"; import { JoinRule } from "matrix-js-sdk/src/@types/partials";
import { IRoomCapability } from "matrix-js-sdk/src/client"; import { IRoomCapability } from "matrix-js-sdk/src/client";
@ -63,7 +63,7 @@ export const UPDATE_INVITED_SPACES = Symbol("invited-spaces");
export const UPDATE_SELECTED_SPACE = Symbol("selected-space"); export const UPDATE_SELECTED_SPACE = Symbol("selected-space");
// Space Room ID/HOME_SPACE will be emitted when a Space's children change // Space Room ID/HOME_SPACE will be emitted when a Space's children change
export interface ISuggestedRoom extends IRoomChild { export interface ISuggestedRoom extends IHierarchyRoom {
viaServers: string[]; viaServers: string[];
} }
@ -297,7 +297,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient<IState> {
public fetchSuggestedRooms = async (space: Room, limit = MAX_SUGGESTED_ROOMS): Promise<ISuggestedRoom[]> => { public fetchSuggestedRooms = async (space: Room, limit = MAX_SUGGESTED_ROOMS): Promise<ISuggestedRoom[]> => {
try { try {
const { rooms } = await this.matrixClient.getRoomChildren(space.roomId, limit, 1, true); const { rooms } = await this.matrixClient.getRoomHierarchy(space.roomId, limit, 1, true);
const viaMap = new EnhancedMap<string, Set<string>>(); const viaMap = new EnhancedMap<string, Set<string>>();
rooms.forEach(room => { rooms.forEach(room => {

View File

@ -87,7 +87,7 @@ export function createTestClient() {
getSpaceSummary: jest.fn().mockReturnValue({ getSpaceSummary: jest.fn().mockReturnValue({
rooms: [], rooms: [],
}), }),
getRoomChildren: jest.fn().mockReturnValue({ getRoomHierarchy: jest.fn().mockReturnValue({
rooms: [], rooms: [],
}), }),