mirror of
https://github.com/spacebarchat/client.git
synced 2024-11-25 11:42:30 +01:00
avatar status dots
This commit is contained in:
parent
95279954b0
commit
bcf173563d
@ -1,9 +1,11 @@
|
||||
import { PresenceUpdateStatus } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { PopoutContext } from "../contexts/PopoutContext";
|
||||
import AccountStore from "../stores/AccountStore";
|
||||
import { useAppStore } from "../stores/AppStore";
|
||||
import Presence from "../stores/objects/Presence";
|
||||
import User from "../stores/objects/User";
|
||||
import Container from "./Container";
|
||||
import UserProfilePopout from "./UserProfilePopout";
|
||||
@ -11,8 +13,8 @@ import UserProfilePopout from "./UserProfilePopout";
|
||||
const Wrapper = styled(Container)<{ size: number }>`
|
||||
width: ${(props) => props.size}px;
|
||||
height: ${(props) => props.size}px;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
@ -20,12 +22,28 @@ const Wrapper = styled(Container)<{ size: number }>`
|
||||
}
|
||||
`;
|
||||
|
||||
const StatusDot = styled.span<{ color: string; width?: number; height?: number }>`
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background-color: ${(props) => props.color};
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--background-primary);
|
||||
width: ${(props) => props.width ?? 10}px;
|
||||
height: ${(props) => props.height ?? 10}px;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
user?: User | AccountStore;
|
||||
size?: number;
|
||||
style?: React.CSSProperties;
|
||||
onClick?: (() => void) | null;
|
||||
popoutPlacement?: "left" | "right" | "top" | "bottom";
|
||||
presence?: Presence;
|
||||
statusDotStyle?: {
|
||||
width?: number;
|
||||
height?: number;
|
||||
};
|
||||
}
|
||||
|
||||
function Avatar(props: Props) {
|
||||
@ -47,7 +65,7 @@ function Avatar(props: Props) {
|
||||
if (!rect) return;
|
||||
|
||||
popoutContext.open({
|
||||
element: <UserProfilePopout user={user} />,
|
||||
element: <UserProfilePopout user={user} presence={props.presence} />,
|
||||
position: rect,
|
||||
placement: props.popoutPlacement,
|
||||
});
|
||||
@ -57,7 +75,18 @@ function Avatar(props: Props) {
|
||||
|
||||
return (
|
||||
<Wrapper size={props.size ?? 32} style={props.style} ref={ref} {...clickProp}>
|
||||
<img src={user.avatarUrl} width={props.size ?? 32} height={props.size ?? 32} loading="eager" />
|
||||
<img
|
||||
style={{
|
||||
borderRadius: "50%",
|
||||
}}
|
||||
src={user.avatarUrl}
|
||||
width={props.size ?? 32}
|
||||
height={props.size ?? 32}
|
||||
loading="eager"
|
||||
/>
|
||||
{props.presence && props.presence.status !== PresenceUpdateStatus.Offline && (
|
||||
<StatusDot color={app.theme.getStatusColor(props.presence.status)} {...props.statusDotStyle} />
|
||||
)}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ function MemberListItem({ item }: Props) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
popoutContext.open({
|
||||
element: <UserProfilePopout user={item.user!} />,
|
||||
element: <UserProfilePopout user={item.user!} presence={presence} member={item} />,
|
||||
position: e.currentTarget.getBoundingClientRect(),
|
||||
placement: "right",
|
||||
});
|
||||
@ -91,7 +91,7 @@ function MemberListItem({ item }: Props) {
|
||||
<Container>
|
||||
<Wrapper offline={presence?.status === PresenceUpdateStatus.Offline}>
|
||||
<AvatarWrapper>
|
||||
<Avatar user={item.user!} size={32} />
|
||||
<Avatar user={item.user!} size={32} presence={presence} />
|
||||
</AvatarWrapper>
|
||||
<TextWrapper>
|
||||
<Text color={item.roleColor}>{item.nick ?? item.user?.username}</Text>
|
||||
|
@ -3,6 +3,8 @@ import styled from "styled-components";
|
||||
import { ReactComponent as SpacebarLogoBlue } from "../assets/images/logo/Spacebar_Icon.svg";
|
||||
import useLogger from "../hooks/useLogger";
|
||||
import AccountStore from "../stores/AccountStore";
|
||||
import GuildMember from "../stores/objects/GuildMember";
|
||||
import Presence from "../stores/objects/Presence";
|
||||
import User from "../stores/objects/User";
|
||||
import Snowflake from "../utils/Snowflake";
|
||||
import Avatar from "./Avatar";
|
||||
@ -80,7 +82,13 @@ const MemberSinceText = styled.span`
|
||||
font-weight: var(--font-weight-regular);
|
||||
`;
|
||||
|
||||
function UserProfilePopout({ user }: { user: User | AccountStore }) {
|
||||
interface Props {
|
||||
user: User | AccountStore;
|
||||
presence?: Presence;
|
||||
member?: GuildMember;
|
||||
}
|
||||
|
||||
function UserProfilePopout({ user, presence, member }: Props) {
|
||||
const logger = useLogger("UserProfilePopout");
|
||||
// if (!member.user) {
|
||||
// logger.error("member.user is undefined");
|
||||
@ -103,6 +111,11 @@ function UserProfilePopout({ user }: { user: User | AccountStore }) {
|
||||
// TODO: open profile modal
|
||||
}}
|
||||
user={user}
|
||||
presence={presence}
|
||||
statusDotStyle={{
|
||||
width: 16,
|
||||
height: 16,
|
||||
}}
|
||||
/>
|
||||
</Top>
|
||||
<Bottom>
|
||||
|
@ -56,7 +56,9 @@ export type ThemeVariables =
|
||||
| "warningContrastText"
|
||||
| "interactive"
|
||||
| "scrollbarTrack"
|
||||
| "scrollbarThumb";
|
||||
| "scrollbarThumb"
|
||||
| "statusIdle"
|
||||
| "statusOffline";
|
||||
|
||||
export type Overrides = {
|
||||
[variable in ThemeVariables]: string;
|
||||
@ -102,13 +104,13 @@ export const ThemePresets: Record<string, Theme> = {
|
||||
inputBackground: "#757575",
|
||||
error: "#e83f36",
|
||||
divider: "#3c3c3c",
|
||||
primary: "",
|
||||
primaryLight: "",
|
||||
primaryDark: "",
|
||||
primaryContrastText: "",
|
||||
secondary: "",
|
||||
secondaryLight: "",
|
||||
secondaryDark: "",
|
||||
primary: "#0185ff",
|
||||
primaryLight: "#339dff",
|
||||
primaryDark: "#005db2",
|
||||
primaryContrastText: "#ffffff",
|
||||
secondary: "#000115",
|
||||
secondaryLight: "#000677",
|
||||
secondaryDark: "#000111",
|
||||
secondaryContrastText: "",
|
||||
danger: "",
|
||||
dangerLight: "",
|
||||
@ -125,6 +127,8 @@ export const ThemePresets: Record<string, Theme> = {
|
||||
scrollbarTrack: "",
|
||||
scrollbarThumb: "",
|
||||
interactive: "",
|
||||
statusIdle: "#ff7c01",
|
||||
statusOffline: "#5d5d5d",
|
||||
font: font,
|
||||
},
|
||||
dark: {
|
||||
@ -149,9 +153,11 @@ export const ThemePresets: Record<string, Theme> = {
|
||||
primaryLight: "#339dff",
|
||||
primaryDark: "#005db2",
|
||||
primaryContrastText: "#ffffff",
|
||||
secondary: "#ff7c01",
|
||||
secondaryLight: "#ff9633",
|
||||
secondaryDark: "#b25600",
|
||||
secondary: "#000115",
|
||||
secondaryLight: "#000677",
|
||||
secondaryDark: "#000111",
|
||||
// secondary: "#ff7c01",
|
||||
// secondaryLight: "#ff9633",
|
||||
secondaryContrastText: "#040404",
|
||||
danger: "#ff3a3b",
|
||||
dangerLight: "#ff6162",
|
||||
@ -168,6 +174,8 @@ export const ThemePresets: Record<string, Theme> = {
|
||||
scrollbarTrack: "#232323",
|
||||
scrollbarThumb: "#171717",
|
||||
interactive: "#424242",
|
||||
statusIdle: "#ff7c01",
|
||||
statusOffline: "#5d5d5d",
|
||||
font: font,
|
||||
},
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { PresenceUpdateStatus } from "@spacebarchat/spacebar-api-types/v9";
|
||||
import { computed, makeAutoObservable } from "mobx";
|
||||
import type { Theme } from "../contexts/Theme";
|
||||
import { ThemePresets } from "../contexts/Theme";
|
||||
@ -21,4 +22,19 @@ export default class ThemeStore {
|
||||
|
||||
return variables as unknown as Theme;
|
||||
}
|
||||
|
||||
@computed
|
||||
getStatusColor(status?: PresenceUpdateStatus) {
|
||||
switch (status) {
|
||||
case PresenceUpdateStatus.Online:
|
||||
return ThemePresets["dark"].successLight;
|
||||
case PresenceUpdateStatus.Idle:
|
||||
return ThemePresets["dark"].statusIdle;
|
||||
case PresenceUpdateStatus.DoNotDisturb:
|
||||
return ThemePresets["dark"].dangerLight;
|
||||
case PresenceUpdateStatus.Offline:
|
||||
default:
|
||||
return ThemePresets["dark"].statusOffline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user