2021-07-24 18:46:33 +01:00
|
|
|
import { ChevronDown } from "@styled-icons/boxicons-regular";
|
|
|
|
import { isEqual } from "lodash";
|
2021-07-29 15:11:21 +01:00
|
|
|
import { observer } from "mobx-react-lite";
|
2021-09-25 14:43:28 +01:00
|
|
|
import { Virtuoso } from "react-virtuoso";
|
2022-04-22 21:06:12 +01:00
|
|
|
import { Member } from "revolt.js/esm/maps/Members";
|
|
|
|
import { Server } from "revolt.js/esm/maps/Servers";
|
2021-07-05 11:23:23 +01:00
|
|
|
|
|
|
|
import styles from "./Panes.module.scss";
|
2021-07-24 18:46:33 +01:00
|
|
|
import { Text } from "preact-i18n";
|
2021-09-25 14:43:28 +01:00
|
|
|
import { useEffect, useMemo, useState } from "preact/hooks";
|
2021-07-05 11:23:23 +01:00
|
|
|
|
2021-07-24 18:46:33 +01:00
|
|
|
import UserIcon from "../../../components/common/user/UserIcon";
|
2021-09-25 14:43:28 +01:00
|
|
|
import { Username } from "../../../components/common/user/UserShort";
|
2021-07-24 18:46:33 +01:00
|
|
|
import Button from "../../../components/ui/Button";
|
|
|
|
import Checkbox from "../../../components/ui/Checkbox";
|
|
|
|
import IconButton from "../../../components/ui/IconButton";
|
2021-09-25 14:43:28 +01:00
|
|
|
import InputBox from "../../../components/ui/InputBox";
|
2021-07-24 18:46:33 +01:00
|
|
|
import Overline from "../../../components/ui/Overline";
|
|
|
|
|
2021-09-25 14:43:28 +01:00
|
|
|
interface InnerProps {
|
|
|
|
member: Member;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Inner = observer(({ member }: InnerProps) => {
|
|
|
|
const [open, setOpen] = useState(false);
|
|
|
|
const [roles, setRoles] = useState<string[]>(member.roles ?? []);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
setRoles(member.roles ?? []);
|
|
|
|
}, [member.roles]);
|
|
|
|
|
|
|
|
const server_roles = member.server?.roles ?? {};
|
|
|
|
const user = member.user;
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<div
|
|
|
|
className={styles.member}
|
|
|
|
data-open={open}
|
|
|
|
onClick={() => setOpen(!open)}>
|
|
|
|
<span>
|
|
|
|
<UserIcon target={user} size={24} />{" "}
|
|
|
|
<Username user={member.user} showServerIdentity="both" />
|
|
|
|
</span>
|
|
|
|
<IconButton className={styles.chevron}>
|
|
|
|
<ChevronDown size={24} />
|
|
|
|
</IconButton>
|
|
|
|
</div>
|
|
|
|
{open && (
|
|
|
|
<div className={styles.memberView}>
|
|
|
|
<Overline type="subtle">Roles</Overline>
|
|
|
|
{Object.keys(server_roles).map((key) => {
|
|
|
|
const role = server_roles[key];
|
|
|
|
return (
|
|
|
|
<Checkbox
|
|
|
|
key={key}
|
|
|
|
checked={roles.includes(key) ?? false}
|
|
|
|
onChange={(v) => {
|
|
|
|
if (v) {
|
|
|
|
setRoles([...roles, key]);
|
|
|
|
} else {
|
|
|
|
setRoles(
|
|
|
|
roles.filter((x) => x !== key),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}}>
|
|
|
|
<span
|
|
|
|
style={{
|
|
|
|
color: role.colour,
|
|
|
|
}}>
|
|
|
|
{role.name}
|
|
|
|
</span>
|
|
|
|
</Checkbox>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
<Button
|
|
|
|
compact
|
|
|
|
disabled={isEqual(member.roles ?? [], roles)}
|
|
|
|
onClick={() =>
|
|
|
|
member.edit({
|
|
|
|
roles,
|
|
|
|
})
|
|
|
|
}>
|
|
|
|
<Text id="app.special.modals.actions.save" />
|
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2021-06-19 22:37:12 +01:00
|
|
|
interface Props {
|
2021-07-29 19:01:40 +01:00
|
|
|
server: Server;
|
2021-06-19 22:37:12 +01:00
|
|
|
}
|
|
|
|
|
2021-09-25 14:43:28 +01:00
|
|
|
export const Members = ({ server }: Props) => {
|
|
|
|
const [data, setData] = useState<Member[] | undefined>(undefined);
|
|
|
|
const [query, setQuery] = useState("");
|
2021-07-01 17:36:34 +01:00
|
|
|
|
2021-07-05 11:25:20 +01:00
|
|
|
useEffect(() => {
|
2021-09-25 14:43:28 +01:00
|
|
|
server
|
|
|
|
.fetchMembers()
|
|
|
|
.then((data) => data.members)
|
|
|
|
.then(setData);
|
2021-08-05 14:47:00 +01:00
|
|
|
}, [server, setData]);
|
2021-06-19 22:37:12 +01:00
|
|
|
|
2021-09-25 14:43:28 +01:00
|
|
|
const members = useMemo(
|
|
|
|
() =>
|
|
|
|
query
|
2022-01-14 17:54:34 +01:00
|
|
|
? data?.filter((x) =>
|
|
|
|
x.user?.username
|
|
|
|
.toLowerCase()
|
|
|
|
.includes(query.toLowerCase()),
|
|
|
|
)
|
2021-09-25 14:43:28 +01:00
|
|
|
: data,
|
|
|
|
[data, query],
|
|
|
|
);
|
2021-07-24 18:46:33 +01:00
|
|
|
|
2021-07-05 11:25:20 +01:00
|
|
|
return (
|
2021-07-24 18:46:33 +01:00
|
|
|
<div className={styles.userList}>
|
2021-09-25 14:43:28 +01:00
|
|
|
<InputBox
|
|
|
|
placeholder="Search for a specific user..."
|
|
|
|
value={query}
|
|
|
|
onChange={(e) => setQuery(e.currentTarget.value)}
|
|
|
|
contrast
|
|
|
|
/>
|
|
|
|
<div className={styles.subtitle}>{data?.length ?? 0} Members</div>
|
|
|
|
{members && (
|
|
|
|
<div className={styles.virtual}>
|
|
|
|
<Virtuoso
|
|
|
|
totalCount={members.length}
|
|
|
|
itemContent={(index) => (
|
|
|
|
<Inner member={members[index]} />
|
|
|
|
)}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
)}
|
2021-07-05 11:25:20 +01:00
|
|
|
</div>
|
|
|
|
);
|
2021-09-25 14:43:28 +01:00
|
|
|
};
|