1
0
mirror of https://github.com/spacebarchat/client.git synced 2024-11-22 10:22:30 +01:00

Start implementing member list

This commit is contained in:
Puyodead1 2023-11-08 11:02:58 -05:00
parent c13dd8aaef
commit e3b438d0cb
No known key found for this signature in database
GPG Key ID: BA5F91AAEF68E5CE
4 changed files with 184 additions and 6 deletions

View File

@ -0,0 +1,53 @@
import React from "react";
import styled from "styled-components";
const Container = styled.div`
padding: 24px 8px 0 16px;
`;
const Title = styled.span`
font-size: 12px;
font-weight: var(--font-weight-bold);
color: var(--text-secondary);
user-select: none;
cursor: pointer;
`;
const Wrapper = styled.div<{ open?: boolean }>`
margin-top: 4px;
display: flex;
flex-direction: column;
display: ${(props) => (props.open === false ? "flex" : "none")};
`;
const Item = styled.span`
font-size: 16px;
font-weight: var(--font-weight-medium);
color: var(--text-normal);
user-select: none;
margin-left: 8px;
padding: 4px 0;
`;
interface Props {
name: string;
items: string[];
}
function ListSection(props: Props) {
const [open, setOpen] = React.useState(false);
const toggle = () => setOpen((prev) => !prev);
return (
<Container>
<Title onClick={toggle}>{props.name}</Title>
<Wrapper open={open}>
{props.items.map((item) => (
<Item>{item}</Item>
))}
</Wrapper>
</Container>
);
}
export default ListSection;

View File

@ -1,5 +1,7 @@
import { observer } from "mobx-react-lite";
import styled from "styled-components";
import { useAppStore } from "../../stores/AppStore";
import ListSection from "../ListSection";
const Container = styled.div`
display: flex;
@ -20,10 +22,50 @@ const Wrapper = styled.aside`
display: flex;
`;
const List = styled.ul`
padding: 0;
margin: 0;
list-style: none;
overflow-y: auto;
height: 100%;
width: 100%;
`;
function MemberList() {
const app = useAppStore();
if (!app.activeGuild || !app.activeChannel) return null;
const { memberList } = app.activeGuild;
return (
<Container>
<Wrapper>MemberList</Wrapper>
{/* <AutoSizer>
{({ width, height }) => (
<List
height={height}
overscanRowCount={2}
rowCount={memberList.length}
rowHeight={({ index }) => {
// const item = channels[index];
// if (item.type === ChannelType.GuildCategory) {
// return 44;
// }
return 33;
}}
rowRenderer={rowRenderer}
width={width}
/>
)}
</AutoSizer> */}
<List>
{memberList.map((category) => (
<ListSection
name={category.name}
items={category.items.map((x) => x.nick ?? x.user?.username).filter((x) => x) as string[]}
/>
))}
</List>
</Container>
);
}

View File

@ -0,0 +1,68 @@
import { useModals } from "@mattjennings/react-modal-stack";
import React from "react";
import { useNavigate } from "react-router-dom";
import styled from "styled-components";
import { ContextMenuContext } from "../../contexts/ContextMenuContext";
import GuildMember from "../../stores/objects/GuildMember";
import { IContextMenuItem } from "../ContextMenuItem";
const ListItem = styled.div<{ isCategory?: boolean }>`
padding: ${(props) => (props.isCategory ? "16px 8px 0 0" : "1px 8px 0 0")};
cursor: pointer;
`;
const Wrapper = styled.div<{ isCategory?: boolean }>`
margin-left: ${(props) => (props.isCategory ? "0" : "8px")};
height: ${(props) => (props.isCategory ? "28px" : "33px")};
border-radius: 4px;
align-items: center;
display: flex;
padding: 0 8px;
background-color: transparent;
&:hover {
background-color: var(--background-primary-alt);
}
`;
const Text = styled.span<{ isCategory?: boolean }>`
font-size: 16px;
font-weight: var(--font-weight-regular);
white-space: nowrap;
color: var(--text-secondary);
`;
interface Props {
item: string | GuildMember;
}
function MemberListItem({ item }: Props) {
const navigate = useNavigate();
const { openModal } = useModals();
const contextMenu = React.useContext(ContextMenuContext);
const [contextMenuItems, setContextMenuItems] = React.useState<IContextMenuItem[]>([]);
return (
<ListItem
key={typeof item === "string" ? item : item.user?.id}
isCategory={typeof item === "string"}
// onClick={() => {
// // prevent navigating to non-text channels
// if (!channel.isTextChannel) return;
// navigate(`/channels/${channel.guildId}/${channel.id}`);
// }}
onContextMenu={(e) => contextMenu.open2(e, contextMenuItems)}
>
<Wrapper isCategory={typeof item === "string"}>
<Text isCategory={typeof item === "string"}>
{typeof item === "string" ? item : item.nick ?? item.user?.username}
</Text>
</Wrapper>
</ListItem>
);
}
export default MemberListItem;

View File

@ -18,7 +18,7 @@ export default class GuildMemberListStore {
@observable groups: GatewayGuildMemberListUpdateGroup[] = [];
@observable member_count: number;
@observable online_count: number;
@observable list: (string | GuildMember)[] = [];
@observable list: { name: string; items: GuildMember[] }[] = [];
constructor(app: AppStore, guild: Guild, data: GatewayGuildMemberListUpdateDispatchData) {
this.app = app;
@ -98,9 +98,24 @@ export default class GuildMemberListStore {
// ...i.data.sort((a, b) => a.index - b.index).map(i => i.member),
// ]);
this.list = listData.flatMap((i) => [
i.title,
...i.data
// this.list = listData.flatMap((i) => [
// i.title,
// ...i.data
// .sort((a, b) => {
// const ua = a.member.user?.username;
// const ub = b.member.user?.username;
// if (ua && ub) {
// return ua.toLowerCase() > ub.toLowerCase() ? 1 : -1;
// }
// return 0;
// })
// .map((i) => i.member),
// ]);
this.list = listData.map((i) => ({
name: i.title,
items: i.data
.sort((a, b) => {
const ua = a.member.user?.username;
const ub = b.member.user?.username;
@ -111,7 +126,7 @@ export default class GuildMemberListStore {
return 0;
})
.map((i) => i.member),
]);
}));
break;
}