2023-11-23 00:45:06 +01:00
|
|
|
import classNames from "classnames";
|
2023-11-25 17:09:01 +01:00
|
|
|
import { useMemo } from "react";
|
2023-11-23 00:45:06 +01:00
|
|
|
|
2023-11-25 17:09:01 +01:00
|
|
|
import { base64ToBuffer, decryptData } from "@/backend/accounts/crypto";
|
2023-11-24 17:11:00 +01:00
|
|
|
import { Icon, Icons } from "@/components/Icon";
|
2023-11-18 15:12:31 +01:00
|
|
|
import { UserIcon } from "@/components/UserIcon";
|
2023-11-05 17:56:56 +01:00
|
|
|
import { AccountProfile } from "@/pages/parts/auth/AccountCreatePart";
|
|
|
|
import { useAuthStore } from "@/stores/auth";
|
|
|
|
|
|
|
|
export interface AvatarProps {
|
|
|
|
profile: AccountProfile["profile"];
|
2023-11-23 00:45:06 +01:00
|
|
|
sizeClass?: string;
|
|
|
|
iconClass?: string;
|
2023-11-24 21:54:44 +01:00
|
|
|
bottom?: React.ReactNode;
|
2023-11-05 17:56:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export function Avatar(props: AvatarProps) {
|
|
|
|
return (
|
2023-11-24 21:54:44 +01:00
|
|
|
<div className="relative inline-block">
|
|
|
|
<div
|
|
|
|
className={classNames(
|
|
|
|
props.sizeClass,
|
|
|
|
"rounded-full overflow-hidden flex items-center justify-center text-white"
|
|
|
|
)}
|
|
|
|
style={{
|
|
|
|
background: `linear-gradient(to bottom right, ${props.profile.colorA}, ${props.profile.colorB})`,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<UserIcon
|
|
|
|
className={props.iconClass}
|
|
|
|
icon={props.profile.icon as any}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
{props.bottom ? (
|
|
|
|
<div className="absolute bottom-0 left-1/2 transform translate-y-1/2 -translate-x-1/2">
|
|
|
|
{props.bottom}
|
|
|
|
</div>
|
|
|
|
) : null}
|
2023-11-05 17:56:56 +01:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-11-23 00:45:06 +01:00
|
|
|
export function UserAvatar(props: {
|
|
|
|
sizeClass?: string;
|
|
|
|
iconClass?: string;
|
|
|
|
bottom?: React.ReactNode;
|
2023-11-25 17:09:01 +01:00
|
|
|
withName?: boolean;
|
2023-11-23 00:45:06 +01:00
|
|
|
}) {
|
2023-11-05 17:56:56 +01:00
|
|
|
const auth = useAuthStore();
|
2023-11-25 17:09:01 +01:00
|
|
|
|
|
|
|
const bufferSeed = useMemo(
|
|
|
|
() =>
|
|
|
|
auth.account && auth.account.seed
|
|
|
|
? base64ToBuffer(auth.account.seed)
|
|
|
|
: null,
|
|
|
|
[auth]
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!auth.account || auth.account === null) return null;
|
|
|
|
|
|
|
|
const deviceName = bufferSeed
|
|
|
|
? decryptData(auth.account.deviceName, bufferSeed)
|
|
|
|
: "...";
|
|
|
|
|
2023-11-23 00:45:06 +01:00
|
|
|
return (
|
2023-11-25 17:09:01 +01:00
|
|
|
<>
|
|
|
|
<Avatar
|
|
|
|
profile={auth.account.profile}
|
|
|
|
sizeClass={props.sizeClass ?? "w-[2rem] h-[2rem]"}
|
|
|
|
iconClass={props.iconClass}
|
|
|
|
bottom={props.bottom}
|
|
|
|
/>
|
|
|
|
{props.withName && bufferSeed ? (
|
2023-11-26 14:40:35 +01:00
|
|
|
<span className="hidden md:inline-block">
|
2023-11-25 17:09:01 +01:00
|
|
|
{deviceName.length >= 20
|
|
|
|
? `${deviceName.slice(0, 20 - 1)}…`
|
|
|
|
: deviceName}
|
|
|
|
</span>
|
|
|
|
) : null}
|
|
|
|
</>
|
2023-11-23 00:45:06 +01:00
|
|
|
);
|
2023-11-05 17:56:56 +01:00
|
|
|
}
|
2023-11-24 17:11:00 +01:00
|
|
|
|
2023-11-30 21:25:28 +01:00
|
|
|
export function NoUserAvatar(props: { iconClass?: string }) {
|
2023-11-24 17:11:00 +01:00
|
|
|
return (
|
2023-11-30 21:25:28 +01:00
|
|
|
<div className="relative inline-block p-1 text-type-dimmed">
|
|
|
|
<Icon className={props.iconClass ?? "text-xl"} icon={Icons.MENU} />
|
2023-11-24 17:11:00 +01:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|