import React, { forwardRef, MouseEventHandler, useEffect, useMemo } from 'react'; import { MatrixError, Room } from 'matrix-js-sdk'; import { IHierarchyRoom } from 'matrix-js-sdk/lib/@types/spaces'; import { Box, config, Text } from 'folds'; import { HierarchyItem, HierarchyItemRoom, HierarchyItemSpace, useFetchSpaceHierarchyLevel, } from '../../hooks/useSpaceHierarchy'; import { IPowerLevels, powerLevelAPI } from '../../hooks/usePowerLevels'; import { useMatrixClient } from '../../hooks/useMatrixClient'; import { SpaceItemCard } from './SpaceItem'; import { AfterItemDropTarget, CanDropCallback } from './DnD'; import { HierarchyItemMenu } from './HierarchyItemMenu'; import { RoomItemCard } from './RoomItem'; import { RoomType } from '../../../types/matrix/room'; import { SequenceCard } from '../../components/sequence-card'; type SpaceHierarchyProps = { summary: IHierarchyRoom | undefined; spaceItem: HierarchyItemSpace; roomItems?: HierarchyItemRoom[]; allJoinedRooms: Set; mDirects: Set; roomsPowerLevels: Map; canEditSpaceChild: (powerLevels: IPowerLevels) => boolean; categoryId: string; closed: boolean; handleClose: MouseEventHandler; draggingItem?: HierarchyItem; onDragging: (item?: HierarchyItem) => void; canDrop: CanDropCallback; disabledReorder?: boolean; nextSpaceId?: string; getRoom: (roomId: string) => Room | undefined; pinned: boolean; togglePinToSidebar: (roomId: string) => void; onSpacesFound: (spaceItems: IHierarchyRoom[]) => void; onOpenRoom: MouseEventHandler; }; export const SpaceHierarchy = forwardRef( ( { summary, spaceItem, roomItems, allJoinedRooms, mDirects, roomsPowerLevels, canEditSpaceChild, categoryId, closed, handleClose, draggingItem, onDragging, canDrop, disabledReorder, nextSpaceId, getRoom, pinned, togglePinToSidebar, onOpenRoom, onSpacesFound, }, ref ) => { const mx = useMatrixClient(); const { fetching, error, rooms } = useFetchSpaceHierarchyLevel(spaceItem.roomId, true); const subspaces = useMemo(() => { const s: Map = new Map(); rooms.forEach((r) => { if (r.room_type === RoomType.Space) { s.set(r.room_id, r); } }); return s; }, [rooms]); const spacePowerLevels = roomsPowerLevels.get(spaceItem.roomId) ?? {}; const userPLInSpace = powerLevelAPI.getPowerLevel( spacePowerLevels, mx.getUserId() ?? undefined ); const canInviteInSpace = powerLevelAPI.canDoAction(spacePowerLevels, 'invite', userPLInSpace); const draggingSpace = draggingItem?.roomId === spaceItem.roomId && draggingItem.parentId === spaceItem.parentId; const { parentId } = spaceItem; const parentPowerLevels = parentId ? roomsPowerLevels.get(parentId) ?? {} : undefined; useEffect(() => { onSpacesFound(Array.from(subspaces.values())); }, [subspaces, onSpacesFound]); let childItems = roomItems?.filter((i) => !subspaces.has(i.roomId)); if (!canEditSpaceChild(spacePowerLevels)) { // hide unknown rooms for normal user childItems = childItems?.filter((i) => { const forbidden = error instanceof MatrixError ? error.errcode === 'M_FORBIDDEN' : false; const inaccessibleRoom = !rooms.get(i.roomId) && !fetching && (error ? forbidden : true); return !inaccessibleRoom; }); } return ( ) } after={ } onDragging={onDragging} data-dragging={draggingSpace} /> {childItems && childItems.length > 0 ? ( {childItems.map((roomItem, index) => { const roomSummary = rooms.get(roomItem.roomId); const roomPowerLevels = roomsPowerLevels.get(roomItem.roomId) ?? {}; const userPLInRoom = powerLevelAPI.getPowerLevel( roomPowerLevels, mx.getUserId() ?? undefined ); const canInviteInRoom = powerLevelAPI.canDoAction( roomPowerLevels, 'invite', userPLInRoom ); const lastItem = index === childItems.length; const nextRoomId = lastItem ? nextSpaceId : childItems[index + 1]?.roomId; const roomDragging = draggingItem?.roomId === roomItem.roomId && draggingItem.parentId === roomItem.parentId; return ( } after={ } data-dragging={roomDragging} onDragging={onDragging} /> ); })} ) : ( childItems && ( No Rooms This space does not contains rooms yet. ) )} ); } );