mirror of
https://github.com/spacebarchat/client.git
synced 2024-11-22 10:22:30 +01:00
member list item colors, and user popouts
This commit is contained in:
parent
5da4bccdab
commit
4779e1134a
@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, { ReactNode } from "react";
|
||||
import styled from "styled-components";
|
||||
import Icon from "./Icon";
|
||||
|
||||
@ -35,7 +35,7 @@ const Item = styled.span`
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
items: string[];
|
||||
items: ReactNode[];
|
||||
}
|
||||
|
||||
function ListSection(props: Props) {
|
||||
@ -49,9 +49,10 @@ function ListSection(props: Props) {
|
||||
{props.name}
|
||||
</Title>
|
||||
<Wrapper open={open}>
|
||||
{props.items.map((item, i) => (
|
||||
{/* {props.items.map((item, i) => (
|
||||
<Item key={i}>{item}</Item>
|
||||
))}
|
||||
))} */}
|
||||
{...props.items}
|
||||
</Wrapper>
|
||||
</Container>
|
||||
);
|
||||
|
@ -5,6 +5,7 @@ import styled from "styled-components";
|
||||
import { useAppStore } from "../../stores/AppStore";
|
||||
import GuildMemberListStore from "../../stores/GuildMemberListStore";
|
||||
import ListSection from "../ListSection";
|
||||
import MemberListItem from "./MemberListItem";
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
@ -61,9 +62,12 @@ function MemberList() {
|
||||
<ListSection
|
||||
key={i}
|
||||
name={category.name}
|
||||
items={
|
||||
category.items.map((x) => x.nick ?? x.user?.username).filter((x) => x) as string[]
|
||||
}
|
||||
// items={
|
||||
// category.items.map((x) => x.nick ?? x.user?.username).filter((x) => x) as string[]
|
||||
// }
|
||||
items={category.items.map((x) => (
|
||||
<MemberListItem item={x} />
|
||||
))}
|
||||
/>
|
||||
))
|
||||
: null}
|
||||
|
@ -1,19 +1,17 @@
|
||||
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 { PopoutContext } from "../../contexts/PopoutContext";
|
||||
import GuildMember from "../../stores/objects/GuildMember";
|
||||
import { IContextMenuItem } from "../ContextMenuItem";
|
||||
import UserProfilePopout from "../UserProfilePopout";
|
||||
|
||||
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")};
|
||||
const Wrapper = styled.div`
|
||||
margin-left: 8px;
|
||||
height: 33px;
|
||||
border-radius: 4px;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
@ -25,41 +23,39 @@ const Wrapper = styled.div<{ isCategory?: boolean }>`
|
||||
}
|
||||
`;
|
||||
|
||||
const Text = styled.span<{ isCategory?: boolean }>`
|
||||
const Text = styled.span<{ color?: string }>`
|
||||
font-size: 16px;
|
||||
font-weight: var(--font-weight-regular);
|
||||
white-space: nowrap;
|
||||
color: var(--text-secondary);
|
||||
color: ${(props) => props.color ?? "var(--text-secondary)"};
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
item: string | GuildMember;
|
||||
item: GuildMember;
|
||||
}
|
||||
|
||||
function MemberListItem({ item }: Props) {
|
||||
const navigate = useNavigate();
|
||||
const popoutContext = React.useContext(PopoutContext);
|
||||
|
||||
const { openModal } = useModals();
|
||||
|
||||
const contextMenu = React.useContext(ContextMenuContext);
|
||||
const [contextMenuItems, setContextMenuItems] = React.useState<IContextMenuItem[]>([]);
|
||||
// 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)}
|
||||
key={item.user?.id}
|
||||
// onContextMenu={(e) => contextMenu.open2(e, contextMenuItems)}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
popoutContext.open({
|
||||
element: <UserProfilePopout user={item.user!} />,
|
||||
position: e.currentTarget.getBoundingClientRect(),
|
||||
placement: "right",
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Wrapper isCategory={typeof item === "string"}>
|
||||
<Text isCategory={typeof item === "string"}>
|
||||
{typeof item === "string" ? item : item.nick ?? item.user?.username}
|
||||
</Text>
|
||||
<Wrapper>
|
||||
<Text color={item.roleColor}>{item.nick ?? item.user?.username}</Text>
|
||||
</Wrapper>
|
||||
</ListItem>
|
||||
);
|
||||
|
@ -36,12 +36,7 @@ function MessageAuthor({ message }: Props) {
|
||||
if (!guild) return;
|
||||
const member = guild.members.get(message.author.id);
|
||||
if (!member) return;
|
||||
const highestRole = member.roles.reduce((prev, role) => {
|
||||
if (role.position > prev.position) return role;
|
||||
return prev;
|
||||
}, member.roles[0]);
|
||||
if (highestRole?.color === "#000000") return; // TODO: why the fk do we use black as the default color???
|
||||
setColor(highestRole?.color);
|
||||
setColor(member.roleColor);
|
||||
}
|
||||
}, [message]);
|
||||
|
||||
|
@ -3,7 +3,7 @@ import {
|
||||
GatewayGuildMemberListUpdateMember,
|
||||
GuildMemberFlags,
|
||||
} from "@spacebarchat/spacebar-api-types/v9";
|
||||
import { action, observable } from "mobx";
|
||||
import { action, computed, observable } from "mobx";
|
||||
import AppStore from "../AppStore";
|
||||
import Guild from "./Guild";
|
||||
import Role from "./Role";
|
||||
@ -49,6 +49,16 @@ export default class GuildMember {
|
||||
}
|
||||
}
|
||||
|
||||
@computed
|
||||
get roleColor() {
|
||||
const highestRole = this.roles.reduce((prev, role) => {
|
||||
if (role.position > prev.position) return role;
|
||||
return prev;
|
||||
}, this.roles[0]);
|
||||
if (highestRole?.color === "#000000") return; // TODO: why the fk do we use black as the default color???
|
||||
return highestRole?.color;
|
||||
}
|
||||
|
||||
@action
|
||||
update(member: APIGuildMember | GatewayGuildMemberListUpdateMember) {
|
||||
Object.assign(this, member);
|
||||
|
Loading…
Reference in New Issue
Block a user