diff --git a/matrixgw_frontend/src/api/matrix/MatrixApiRoom.ts b/matrixgw_frontend/src/api/matrix/MatrixApiRoom.ts index 39fa989..fecbd21 100644 --- a/matrixgw_frontend/src/api/matrix/MatrixApiRoom.ts +++ b/matrixgw_frontend/src/api/matrix/MatrixApiRoom.ts @@ -1,5 +1,7 @@ import { APIClient } from "../ApiClient"; +import type { UserInfo } from "../AuthApi"; import type { MatrixEvent } from "./MatrixApiEvent"; +import type { UsersMap } from "./MatrixApiProfile"; export interface Room { id: string; @@ -12,6 +14,32 @@ export interface Room { latest_event?: MatrixEvent; } +/** + * Find main member of room + */ +export function mainRoomMember(user: UserInfo, r: Room): string | undefined { + if (r.members.length <= 1) return r.members[0]; + + if (r.members.length < 2) + return r.members[0] == user.matrix_user_id ? r.members[1] : r.members[0]; + + return undefined; +} + +/** + * Find room name + */ +export function roomName(user: UserInfo, r: Room, users: UsersMap): string { + if (r.name) return r.name; + + const name = r.members + .filter((m) => m !== user.matrix_user_id) + .map((m) => users.get(m)?.display_name ?? m) + .join(","); + + return name === "" ? "Empty room" : name; +} + export class MatrixApiRoom { /** * Get the list of joined rooms diff --git a/matrixgw_frontend/src/index.css b/matrixgw_frontend/src/index.css index b303f80..ba4562c 100644 --- a/matrixgw_frontend/src/index.css +++ b/matrixgw_frontend/src/index.css @@ -7,3 +7,12 @@ body, #root { height: 100%; } + +#root { + display: flex; + flex-direction: column; +} + +#root > div { + flex: 1; +} diff --git a/matrixgw_frontend/src/widgets/dashboard/BaseAuthenticatedPage.tsx b/matrixgw_frontend/src/widgets/dashboard/BaseAuthenticatedPage.tsx index 886b8dc..81f706e 100644 --- a/matrixgw_frontend/src/widgets/dashboard/BaseAuthenticatedPage.tsx +++ b/matrixgw_frontend/src/widgets/dashboard/BaseAuthenticatedPage.tsx @@ -114,8 +114,6 @@ export default function BaseAuthenticatedPage(): React.ReactElement { position: "relative", display: "flex", overflow: "hidden", - height: "100%", - width: "100%", }} > + (); @@ -44,10 +45,27 @@ function _MainMessageWidget(p: { users: UsersMap; }): React.ReactElement { const [space, setSpace] = React.useState(); + const [room, setRoom] = React.useState(); + + 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 (
+ + todo
); diff --git a/matrixgw_frontend/src/widgets/messages/RoomIcon.tsx b/matrixgw_frontend/src/widgets/messages/RoomIcon.tsx index 6c49338..8efafac 100644 --- a/matrixgw_frontend/src/widgets/messages/RoomIcon.tsx +++ b/matrixgw_frontend/src/widgets/messages/RoomIcon.tsx @@ -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 ; - else - return ( - - ); + return ( + + {name.slice(0, 1)} + + ); } diff --git a/matrixgw_frontend/src/widgets/messages/RoomSelector.tsx b/matrixgw_frontend/src/widgets/messages/RoomSelector.tsx new file mode 100644 index 0000000..cbdba06 --- /dev/null +++ b/matrixgw_frontend/src/widgets/messages/RoomSelector.tsx @@ -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 ( +
+ No room to display. +
+ ); + + return ( + + {p.rooms.map((r) => ( + + ) + } + disablePadding + > + p.onChange(r)} + dense + selected={p.currRoom?.id === r.id} + > + + + + + + + ))} + + ); +}