show mutual rooms in spaces, rooms and direct messages categories

This commit is contained in:
Ajay Bura 2025-08-05 09:15:07 +05:30
parent 1b63b59fdc
commit 65600b2a1c

View file

@ -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,46 +196,7 @@ export function MutualRoomsChip({ userId }: { userId: string }) {
return null;
}
return (
<PopOut
anchor={cords}
position="Bottom"
align="Start"
offset={4}
content={
mutualRoomsState.status === AsyncStatus.Success ? (
<FocusTrap
focusTrapOptions={{
initialFocus: false,
onDeactivate: close,
clickOutsideDeactivates: true,
escapeDeactivates: stopPropagation,
isKeyForward: (evt: KeyboardEvent) => isKeyHotkey('arrowdown', evt),
isKeyBackward: (evt: KeyboardEvent) => isKeyHotkey('arrowup', evt),
}}
>
<Menu
style={{
display: 'flex',
maxWidth: toRem(200),
maxHeight: '80vh',
}}
>
<Box grow="Yes">
<Scroll size="300" hideTrack>
<Box
direction="Column"
gap="100"
style={{
padding: config.space.S200,
paddingRight: 0,
}}
>
{mutualRoomsState.data
.sort(factoryRoomIdByAtoZ(mx))
.map((roomId) => getRoom(roomId))
.map((room) => {
if (!room) return null;
const renderItem = (room: Room) => {
const { roomId } = room;
const dm = directs.includes(roomId);
@ -249,7 +244,64 @@ export function MutualRoomsChip({ userId }: { userId: string }) {
</Text>
</MenuItem>
);
})}
};
return (
<PopOut
anchor={cords}
position="Bottom"
align="Start"
offset={4}
content={
mutualRoomsState.status === AsyncStatus.Success ? (
<FocusTrap
focusTrapOptions={{
initialFocus: false,
onDeactivate: close,
clickOutsideDeactivates: true,
escapeDeactivates: stopPropagation,
isKeyForward: (evt: KeyboardEvent) => isKeyHotkey('arrowdown', evt),
isKeyBackward: (evt: KeyboardEvent) => isKeyHotkey('arrowup', evt),
}}
>
<Menu
style={{
display: 'flex',
maxWidth: toRem(200),
maxHeight: '80vh',
}}
>
<Box grow="Yes">
<Scroll size="300" hideTrack>
<Box
direction="Column"
gap="400"
style={{ padding: config.space.S200, paddingRight: 0 }}
>
{mutual.spaces.length > 0 && (
<Box direction="Column" gap="100">
<Text style={{ paddingLeft: config.space.S100 }} size="L400">
Spaces
</Text>
{mutual.spaces.map(renderItem)}
</Box>
)}
{mutual.rooms.length > 0 && (
<Box direction="Column" gap="100">
<Text style={{ paddingLeft: config.space.S100 }} size="L400">
Rooms
</Text>
{mutual.rooms.map(renderItem)}
</Box>
)}
{mutual.directs.length > 0 && (
<Box direction="Column" gap="100">
<Text style={{ paddingLeft: config.space.S100 }} size="L400">
Direct Messages
</Text>
{mutual.directs.map(renderItem)}
</Box>
)}
</Box>
</Scroll>
</Box>
@ -262,7 +314,9 @@ export function MutualRoomsChip({ userId }: { userId: string }) {
variant="SurfaceVariant"
radii="Pill"
before={mutualRoomsState.status === AsyncStatus.Loading && <Spinner size="50" />}
disabled={mutualRoomsState.status !== AsyncStatus.Success}
disabled={
mutualRoomsState.status !== AsyncStatus.Success || mutualRoomsState.data.length === 0
}
onClick={open}
aria-pressed={!!cords}
>