All checks were successful
continuous-integration/drone/push Build is passing
129 lines
3.3 KiB
TypeScript
129 lines
3.3 KiB
TypeScript
import SearchIcon from "@mui/icons-material/Search";
|
|
import {
|
|
Chip,
|
|
List,
|
|
ListItem,
|
|
ListItemButton,
|
|
ListItemIcon,
|
|
ListItemText,
|
|
TextField,
|
|
} from "@mui/material";
|
|
import React from "react";
|
|
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();
|
|
|
|
const [filter, setFilter] = React.useState("");
|
|
const [unread, setUnread] = React.useState(false);
|
|
|
|
const shownRooms = React.useMemo(
|
|
() =>
|
|
p.rooms
|
|
.filter((r) => !unread || r.number_unread_messages > 0)
|
|
.filter(
|
|
(r) =>
|
|
filter === "" ||
|
|
r.name?.toLocaleLowerCase()?.includes(filter.toLocaleLowerCase())
|
|
),
|
|
[p.rooms, unread, filter]
|
|
);
|
|
|
|
if (p.rooms.length === 0)
|
|
return (
|
|
<div
|
|
style={{
|
|
width: ROOM_SELECTOR_WIDTH,
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
}}
|
|
>
|
|
No room to display.
|
|
</div>
|
|
);
|
|
|
|
return (
|
|
<div style={{ display: "flex", flexDirection: "column" }}>
|
|
{/** Filter bar */}
|
|
<TextField
|
|
placeholder="Filter rooms"
|
|
slotProps={{
|
|
input: {
|
|
startAdornment: <SearchIcon style={{ marginRight: "10px" }} />,
|
|
},
|
|
}}
|
|
style={{ margin: "5px" }}
|
|
value={filter}
|
|
onChange={(e) => setFilter(e.target.value)}
|
|
/>
|
|
|
|
{/** Chip bar */}
|
|
<div style={{ padding: "5px 10px", marginTop: "5px" }}>
|
|
<span onClick={() => setUnread(!unread)} style={{ cursor: "pointer" }}>
|
|
<Chip
|
|
label="Unread"
|
|
size="medium"
|
|
color={unread ? "success" : undefined}
|
|
variant="outlined"
|
|
/>
|
|
</span>
|
|
</div>
|
|
|
|
{/** Rooms list */}
|
|
<List
|
|
style={{
|
|
flex: 1,
|
|
width: ROOM_SELECTOR_WIDTH,
|
|
overflow: "scroll",
|
|
}}
|
|
>
|
|
{shownRooms.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={
|
|
<span
|
|
style={{
|
|
fontWeight:
|
|
r.number_unread_messages > 0 ? "bold" : undefined,
|
|
}}
|
|
>
|
|
{roomName(user.info, r, p.users)}
|
|
</span>
|
|
}
|
|
/>
|
|
</ListItemButton>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</div>
|
|
);
|
|
}
|