From 56a134c85c0a23816829185322ac8ab2e89ea1bc Mon Sep 17 00:00:00 2001 From: Ajay Bura <32841439+ajbura@users.noreply.github.com> Date: Tue, 27 Dec 2022 20:15:17 +0530 Subject: [PATCH] Add room utils --- src/app/utils/room.ts | 118 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/app/utils/room.ts diff --git a/src/app/utils/room.ts b/src/app/utils/room.ts new file mode 100644 index 00000000..541ae2b7 --- /dev/null +++ b/src/app/utils/room.ts @@ -0,0 +1,118 @@ +import { MatrixClient, MatrixEvent, Room } from 'matrix-js-sdk'; +import { AccountDataEvent } from '../../types/matrix/accountData'; +import { RoomToParents, RoomType, StateEvent } from '../../types/matrix/room'; + +export const getStateEvent = ( + room: Room, + eventType: StateEvent, + stateKey = '' +): MatrixEvent | null => room.currentState.getStateEvents(eventType, stateKey); + +export const getStateEvents = (room: Room, eventType: StateEvent): MatrixEvent[] => + room.currentState.getStateEvents(eventType); + +export const getAccountData = ( + mx: MatrixClient, + eventType: AccountDataEvent +): MatrixEvent | undefined => mx.getAccountData(eventType); + +export const getMDirects = (mDirectEvent: MatrixEvent): Set => { + const roomIds = new Set(); + const userIdToDirects = mDirectEvent?.getContent(); + + if (userIdToDirects === undefined) return roomIds; + + Object.keys(userIdToDirects).forEach((userId) => { + const directs = userIdToDirects[userId]; + if (Array.isArray(directs)) { + directs.forEach((id) => { + if (typeof id === 'string') roomIds.add(id); + }); + } + }); + + return roomIds; +}; + +export const isDirectInvite = (room: Room | null, myUserId: string | null): boolean => { + if (!room || !myUserId) return false; + const me = room.getMember(myUserId); + const memberEvent = me?.events?.member; + const content = memberEvent?.getContent(); + return content?.is_direct === true; +}; + +export const isSpace = (room: Room | null): boolean => { + if (!room) return false; + const event = getStateEvent(room, StateEvent.RoomCreate); + if (!event) return false; + return event.getContent().type === RoomType.Space; +}; + +export const isRoom = (room: Room | null): boolean => { + if (!room) return false; + const event = getStateEvent(room, StateEvent.RoomCreate); + if (!event) return false; + return event.getContent().type === undefined; +}; + +export const isUnsupportedRoom = (room: Room | null): boolean => { + if (!room) return false; + const event = getStateEvent(room, StateEvent.RoomCreate); + if (!event) return true; // Consider room unsupported if m.room.create event doesn't exist + return event.getContent().type !== undefined && event.getContent().type !== RoomType.Space; +}; + +export function isValidChild(mEvent: MatrixEvent): boolean { + return mEvent.getType() === StateEvent.SpaceChild && Object.keys(mEvent.getContent()).length > 0; +} + +export const getAllParents = (roomToParents: RoomToParents, roomId: string): Set => { + const allParents = new Set(); + + const addAllParentIds = (rId: string) => { + if (allParents.has(rId)) return; + allParents.add(rId); + + const parents = roomToParents.get(rId); + parents?.forEach((id) => addAllParentIds(id)); + }; + addAllParentIds(roomId); + allParents.delete(roomId); + return allParents; +}; + +export const getSpaceChildren = (room: Room) => + getStateEvents(room, StateEvent.SpaceChild).reduce((filtered, mEvent) => { + const stateKey = mEvent.getStateKey(); + if (isValidChild(mEvent) && stateKey) { + filtered.push(stateKey); + } + return filtered; + }, []); + +export const mapParentWithChildren = ( + roomToParents: RoomToParents, + roomId: string, + children: string[] +) => { + const allParents = getAllParents(roomToParents, roomId); + children.forEach((childId) => { + if (allParents.has(childId)) { + // Space cycle detected. + return; + } + const parents = roomToParents.get(childId) ?? new Set(); + parents.add(roomId); + roomToParents.set(childId, parents); + }); +}; + +export const getRoomToParents = (mx: MatrixClient): RoomToParents => { + const map: RoomToParents = new Map(); + mx.getRooms() + .filter((room) => isSpace(room)) + .forEach((room) => mapParentWithChildren(map, room.roomId, getSpaceChildren(room))); + + return map; +};