diff --git a/src/app/components/user-profile/UserChips.tsx b/src/app/components/user-profile/UserChips.tsx index ffb8dea1..3c9c215a 100644 --- a/src/app/components/user-profile/UserChips.tsx +++ b/src/app/components/user-profile/UserChips.tsx @@ -1,7 +1,8 @@ -import React, { MouseEventHandler, useState } from 'react'; +import React, { MouseEventHandler, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import FocusTrap from 'focus-trap-react'; import { isKeyHotkey } from 'is-hotkey'; +import { Room } from 'matrix-js-sdk'; import { PopOut, Menu, @@ -134,6 +135,12 @@ export function ServerChip({ server }: { server: string }) { ); } +type MutualRoomsData = { + rooms: Room[]; + spaces: Room[]; + directs: Room[]; +}; + export function MutualRoomsChip({ userId }: { userId: string }) { const mx = useMatrixClient(); const mutualRoomSupported = useMutualRoomsSupport(); @@ -154,6 +161,33 @@ export function MutualRoomsChip({ userId }: { userId: string }) { const close = () => setCords(undefined); + const mutual: MutualRoomsData = useMemo(() => { + const data: MutualRoomsData = { + rooms: [], + spaces: [], + directs: [], + }; + + if (mutualRoomsState.status === AsyncStatus.Success) { + const mutualRooms = mutualRoomsState.data + .sort(factoryRoomIdByAtoZ(mx)) + .map(getRoom) + .filter((room) => !!room); + mutualRooms.forEach((room) => { + if (room.isSpaceRoom()) { + data.spaces.push(room); + return; + } + if (directs.includes(room.roomId)) { + data.directs.push(room); + return; + } + data.rooms.push(room); + }); + } + return data; + }, [mutualRoomsState, getRoom, directs, mx]); + if ( userId === mx.getSafeUserId() || !mutualRoomSupported || @@ -162,6 +196,56 @@ export function MutualRoomsChip({ userId }: { userId: string }) { return null; } + const renderItem = (room: Room) => { + const { roomId } = room; + const dm = directs.includes(roomId); + + return ( + { + if (room.isSpaceRoom()) { + navigateSpace(roomId); + } else { + navigateRoom(roomId); + } + closeUserRoomProfile(); + }} + before={ + + {dm || room.isSpaceRoom() ? ( + ( + + {nameInitials(room.name)} + + )} + /> + ) : ( + + )} + + } + > + + {room.name} + + + ); + }; + return ( - {mutualRoomsState.data - .sort(factoryRoomIdByAtoZ(mx)) - .map((roomId) => getRoom(roomId)) - .map((room) => { - if (!room) return null; - const { roomId } = room; - const dm = directs.includes(roomId); - - return ( - { - if (room.isSpaceRoom()) { - navigateSpace(roomId); - } else { - navigateRoom(roomId); - } - closeUserRoomProfile(); - }} - before={ - - {dm || room.isSpaceRoom() ? ( - ( - - {nameInitials(room.name)} - - )} - /> - ) : ( - - )} - - } - > - - {room.name} - - - ); - })} + {mutual.spaces.length > 0 && ( + + + Spaces + + {mutual.spaces.map(renderItem)} + + )} + {mutual.rooms.length > 0 && ( + + + Rooms + + {mutual.rooms.map(renderItem)} + + )} + {mutual.directs.length > 0 && ( + + + Direct Messages + + {mutual.directs.map(renderItem)} + + )} @@ -262,7 +314,9 @@ export function MutualRoomsChip({ userId }: { userId: string }) { variant="SurfaceVariant" radii="Pill" before={mutualRoomsState.status === AsyncStatus.Loading && } - disabled={mutualRoomsState.status !== AsyncStatus.Success} + disabled={ + mutualRoomsState.status !== AsyncStatus.Success || mutualRoomsState.data.length === 0 + } onClick={open} aria-pressed={!!cords} >