Display rooms list
This commit is contained in:
@@ -8,6 +8,7 @@ import { MatrixSyncApi } from "../../api/MatrixSyncApi";
|
||||
import { AsyncWidget } from "../AsyncWidget";
|
||||
import { SpaceSelector } from "./SpaceSelector";
|
||||
import { Divider } from "@mui/material";
|
||||
import { RoomSelector } from "./RoomSelector";
|
||||
|
||||
export function MainMessageWidget(): React.ReactElement {
|
||||
const [rooms, setRooms] = React.useState<Room[] | undefined>();
|
||||
@@ -44,10 +45,27 @@ function _MainMessageWidget(p: {
|
||||
users: UsersMap;
|
||||
}): React.ReactElement {
|
||||
const [space, setSpace] = React.useState<string | undefined>();
|
||||
const [room, setRoom] = React.useState<Room | undefined>();
|
||||
|
||||
const spaceRooms = React.useMemo(() => {
|
||||
return p.rooms
|
||||
.filter((r) => !r.is_space && (!space || r.parents.includes(space)))
|
||||
.sort(
|
||||
(a, b) => (b.latest_event?.time ?? 0) - (a.latest_event?.time ?? 0)
|
||||
);
|
||||
}, [space, p.rooms]);
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", height: "100%" }}>
|
||||
<SpaceSelector {...p} selectedSpace={space} onChange={setSpace} />
|
||||
<Divider orientation="vertical" />
|
||||
<RoomSelector
|
||||
{...p}
|
||||
rooms={spaceRooms}
|
||||
currRoom={room}
|
||||
onChange={setRoom}
|
||||
/>
|
||||
<Divider orientation="vertical" />
|
||||
<span style={{ flex: 1 }}>todo</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { Icon } from "@mui/material";
|
||||
import { Avatar } from "@mui/material";
|
||||
import { MatrixApiMedia } from "../../api/matrix/MatrixApiMedia";
|
||||
import type { UsersMap } from "../../api/matrix/MatrixApiProfile";
|
||||
import type { Room } from "../../api/matrix/MatrixApiRoom";
|
||||
import {
|
||||
mainRoomMember,
|
||||
roomName,
|
||||
type Room,
|
||||
} from "../../api/matrix/MatrixApiRoom";
|
||||
import { useUserInfo } from "../dashboard/BaseAuthenticatedPage";
|
||||
import GroupIcon from "@mui/icons-material/Group";
|
||||
|
||||
export function RoomIcon(p: {
|
||||
room: Room;
|
||||
@@ -13,20 +16,18 @@ export function RoomIcon(p: {
|
||||
|
||||
let url = p.room.avatar;
|
||||
|
||||
if (!url && p.room.members.length <= 1) url = p.room.members[0];
|
||||
if (!url) {
|
||||
const member = mainRoomMember(user.info, p.room);
|
||||
if (member) url = p.users.get(member)?.avatar;
|
||||
}
|
||||
const name = roomName(user.info, p.room, p.users);
|
||||
|
||||
if (!url && p.room.members.length < 2)
|
||||
url =
|
||||
p.room.members[0] == user.info.matrix_user_id
|
||||
? p.room.members[1]
|
||||
: p.room.members[0];
|
||||
|
||||
if (!url) return <GroupIcon />;
|
||||
else
|
||||
return (
|
||||
<img
|
||||
src={MatrixApiMedia.MediaURL(url, true)}
|
||||
style={{ maxWidth: "1em", maxHeight: "1em" }}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<Avatar
|
||||
variant={p.room.is_space ? "square" : undefined}
|
||||
src={url ? MatrixApiMedia.MediaURL(url, true) : undefined}
|
||||
>
|
||||
{name.slice(0, 1)}
|
||||
</Avatar>
|
||||
);
|
||||
}
|
||||
|
||||
69
matrixgw_frontend/src/widgets/messages/RoomSelector.tsx
Normal file
69
matrixgw_frontend/src/widgets/messages/RoomSelector.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import {
|
||||
Chip,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
} from "@mui/material";
|
||||
import type { UsersMap } from "../../api/matrix/MatrixApiProfile";
|
||||
import { roomName, type Room } from "../../api/matrix/MatrixApiRoom";
|
||||
import { useUserInfo } from "../dashboard/BaseAuthenticatedPage";
|
||||
import { RoomIcon } from "./RoomIcon";
|
||||
|
||||
const ROOM_SELECTOR_WIDTH = "300px";
|
||||
|
||||
export function RoomSelector(p: {
|
||||
users: UsersMap;
|
||||
rooms: Room[];
|
||||
currRoom?: Room;
|
||||
onChange: (r: Room) => void;
|
||||
}): React.ReactElement {
|
||||
const user = useUserInfo();
|
||||
|
||||
if (p.rooms.length === 0)
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: ROOM_SELECTOR_WIDTH,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
No room to display.
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<List
|
||||
style={{
|
||||
width: ROOM_SELECTOR_WIDTH,
|
||||
}}
|
||||
>
|
||||
{p.rooms.map((r) => (
|
||||
<ListItem
|
||||
key={r.id}
|
||||
secondaryAction={
|
||||
r.number_unread_messages === 0 ? undefined : (
|
||||
<Chip color="error" label={r.number_unread_messages} />
|
||||
)
|
||||
}
|
||||
disablePadding
|
||||
>
|
||||
<ListItemButton
|
||||
role={undefined}
|
||||
onClick={() => p.onChange(r)}
|
||||
dense
|
||||
selected={p.currRoom?.id === r.id}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<RoomIcon room={r} {...p} />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={roomName(user.info, r, p.users)} />
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user