forked from abner/for-legacy-web
Run prettier on all files.
This commit is contained in:
@@ -1,14 +1,16 @@
|
||||
import { User } from "revolt.js";
|
||||
import UserIcon from "./UserIcon";
|
||||
|
||||
import Checkbox, { CheckboxProps } from "../../ui/Checkbox";
|
||||
|
||||
import UserIcon from "./UserIcon";
|
||||
|
||||
type UserProps = Omit<CheckboxProps, "children"> & { user: User };
|
||||
|
||||
export default function UserCheckbox({ user, ...props }: UserProps) {
|
||||
return (
|
||||
<Checkbox {...props}>
|
||||
<UserIcon target={user} size={32} />
|
||||
{user.username}
|
||||
</Checkbox>
|
||||
);
|
||||
return (
|
||||
<Checkbox {...props}>
|
||||
<UserIcon target={user} size={32} />
|
||||
{user.username}
|
||||
</Checkbox>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,75 +1,84 @@
|
||||
import Tooltip from "../Tooltip";
|
||||
import { User } from "revolt.js";
|
||||
import UserIcon from "./UserIcon";
|
||||
import { Text } from "preact-i18n";
|
||||
import Header from "../../ui/Header";
|
||||
import UserStatus from './UserStatus';
|
||||
import styled from "styled-components";
|
||||
import { Localizer } from 'preact-i18n';
|
||||
import { Link } from "react-router-dom";
|
||||
import IconButton from "../../ui/IconButton";
|
||||
import { Cog } from "@styled-icons/boxicons-solid";
|
||||
import { Link } from "react-router-dom";
|
||||
import { User } from "revolt.js";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { openContextMenu } from "preact-context-menu";
|
||||
import { Text } from "preact-i18n";
|
||||
import { Localizer } from "preact-i18n";
|
||||
|
||||
import { isTouchscreenDevice } from "../../../lib/isTouchscreenDevice";
|
||||
|
||||
import { useIntermediate } from "../../../context/intermediate/Intermediate";
|
||||
|
||||
import Header from "../../ui/Header";
|
||||
import IconButton from "../../ui/IconButton";
|
||||
|
||||
import Tooltip from "../Tooltip";
|
||||
import UserIcon from "./UserIcon";
|
||||
import UserStatus from "./UserStatus";
|
||||
|
||||
const HeaderBase = styled.div`
|
||||
gap: 0;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
* {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
gap: 0;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.username {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
* {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.status {
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
.username {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.status {
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
user: User
|
||||
user: User;
|
||||
}
|
||||
|
||||
export default function UserHeader({ user }: Props) {
|
||||
const { writeClipboard } = useIntermediate();
|
||||
const { writeClipboard } = useIntermediate();
|
||||
|
||||
return (
|
||||
<Header borders placement="secondary">
|
||||
<HeaderBase>
|
||||
<Localizer>
|
||||
<Tooltip content={<Text id="app.special.copy_username" />}>
|
||||
<span className="username"
|
||||
onClick={() => writeClipboard(user.username)}>
|
||||
@{user.username}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Localizer>
|
||||
<span className="status"
|
||||
onClick={() => openContextMenu("Status")}>
|
||||
<UserStatus user={user} />
|
||||
</span>
|
||||
</HeaderBase>
|
||||
{ !isTouchscreenDevice && <div className="actions">
|
||||
<Link to="/settings">
|
||||
<IconButton>
|
||||
<Cog size={24} />
|
||||
</IconButton>
|
||||
</Link>
|
||||
</div> }
|
||||
</Header>
|
||||
)
|
||||
return (
|
||||
<Header borders placement="secondary">
|
||||
<HeaderBase>
|
||||
<Localizer>
|
||||
<Tooltip content={<Text id="app.special.copy_username" />}>
|
||||
<span
|
||||
className="username"
|
||||
onClick={() => writeClipboard(user.username)}>
|
||||
@{user.username}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Localizer>
|
||||
<span
|
||||
className="status"
|
||||
onClick={() => openContextMenu("Status")}>
|
||||
<UserStatus user={user} />
|
||||
</span>
|
||||
</HeaderBase>
|
||||
{!isTouchscreenDevice && (
|
||||
<div className="actions">
|
||||
<Link to="/settings">
|
||||
<IconButton>
|
||||
<Cog size={24} />
|
||||
</IconButton>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</Header>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,93 +1,104 @@
|
||||
import { User } from "revolt.js";
|
||||
import { useContext } from "preact/hooks";
|
||||
import { MicrophoneOff } from "@styled-icons/boxicons-regular";
|
||||
import styled, { css } from "styled-components";
|
||||
import { User } from "revolt.js";
|
||||
import { Users } from "revolt.js/dist/api/objects";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import { useContext } from "preact/hooks";
|
||||
|
||||
import { ThemeContext } from "../../../context/Theme";
|
||||
import IconBase, { IconBaseProps } from "../IconBase";
|
||||
import { AppContext } from "../../../context/revoltjs/RevoltClient";
|
||||
|
||||
import IconBase, { IconBaseProps } from "../IconBase";
|
||||
import fallback from "../assets/user.png";
|
||||
|
||||
type VoiceStatus = "muted";
|
||||
interface Props extends IconBaseProps<User> {
|
||||
mask?: string;
|
||||
status?: boolean;
|
||||
voice?: VoiceStatus;
|
||||
mask?: string;
|
||||
status?: boolean;
|
||||
voice?: VoiceStatus;
|
||||
}
|
||||
|
||||
export function useStatusColour(user?: User) {
|
||||
const theme = useContext(ThemeContext);
|
||||
const theme = useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
user?.online &&
|
||||
user?.status?.presence !== Users.Presence.Invisible
|
||||
? user?.status?.presence === Users.Presence.Idle
|
||||
? theme["status-away"]
|
||||
: user?.status?.presence ===
|
||||
Users.Presence.Busy
|
||||
? theme["status-busy"]
|
||||
: theme["status-online"]
|
||||
: theme["status-invisible"]
|
||||
);
|
||||
return user?.online && user?.status?.presence !== Users.Presence.Invisible
|
||||
? user?.status?.presence === Users.Presence.Idle
|
||||
? theme["status-away"]
|
||||
: user?.status?.presence === Users.Presence.Busy
|
||||
? theme["status-busy"]
|
||||
: theme["status-online"]
|
||||
: theme["status-invisible"];
|
||||
}
|
||||
|
||||
const VoiceIndicator = styled.div<{ status: VoiceStatus }>`
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
svg {
|
||||
stroke: white;
|
||||
}
|
||||
svg {
|
||||
stroke: white;
|
||||
}
|
||||
|
||||
${ props => props.status === 'muted' && css`
|
||||
background: var(--error);
|
||||
` }
|
||||
${(props) =>
|
||||
props.status === "muted" &&
|
||||
css`
|
||||
background: var(--error);
|
||||
`}
|
||||
`;
|
||||
|
||||
import fallback from '../assets/user.png';
|
||||
export default function UserIcon(
|
||||
props: Props & Omit<JSX.SVGAttributes<SVGSVGElement>, keyof Props>,
|
||||
) {
|
||||
const client = useContext(AppContext);
|
||||
|
||||
export default function UserIcon(props: Props & Omit<JSX.SVGAttributes<SVGSVGElement>, keyof Props>) {
|
||||
const client = useContext(AppContext);
|
||||
const {
|
||||
target,
|
||||
attachment,
|
||||
size,
|
||||
voice,
|
||||
status,
|
||||
animate,
|
||||
mask,
|
||||
children,
|
||||
as,
|
||||
...svgProps
|
||||
} = props;
|
||||
const iconURL =
|
||||
client.generateFileURL(
|
||||
target?.avatar ?? attachment,
|
||||
{ max_side: 256 },
|
||||
animate,
|
||||
) ?? (target ? client.users.getDefaultAvatarURL(target._id) : fallback);
|
||||
|
||||
const { target, attachment, size, voice, status, animate, mask, children, as, ...svgProps } = props;
|
||||
const iconURL = client.generateFileURL(target?.avatar ?? attachment, { max_side: 256 }, animate)
|
||||
?? (target ? client.users.getDefaultAvatarURL(target._id) : fallback);
|
||||
|
||||
return (
|
||||
<IconBase {...svgProps}
|
||||
width={size}
|
||||
height={size}
|
||||
aria-hidden="true"
|
||||
viewBox="0 0 32 32">
|
||||
<foreignObject x="0" y="0" width="32" height="32" mask={mask ?? (status ? "url(#user)" : undefined)}>
|
||||
{
|
||||
<img src={iconURL}
|
||||
draggable={false} />
|
||||
}
|
||||
</foreignObject>
|
||||
{props.status && (
|
||||
<circle
|
||||
cx="27"
|
||||
cy="27"
|
||||
r="5"
|
||||
fill={useStatusColour(target)}
|
||||
/>
|
||||
)}
|
||||
{props.voice && (
|
||||
<foreignObject
|
||||
x="22"
|
||||
y="22"
|
||||
width="10"
|
||||
height="10">
|
||||
<VoiceIndicator status={props.voice}>
|
||||
{props.voice === "muted" && <MicrophoneOff size={6} />}
|
||||
</VoiceIndicator>
|
||||
</foreignObject>
|
||||
)}
|
||||
</IconBase>
|
||||
);
|
||||
return (
|
||||
<IconBase
|
||||
{...svgProps}
|
||||
width={size}
|
||||
height={size}
|
||||
aria-hidden="true"
|
||||
viewBox="0 0 32 32">
|
||||
<foreignObject
|
||||
x="0"
|
||||
y="0"
|
||||
width="32"
|
||||
height="32"
|
||||
mask={mask ?? (status ? "url(#user)" : undefined)}>
|
||||
{<img src={iconURL} draggable={false} />}
|
||||
</foreignObject>
|
||||
{props.status && (
|
||||
<circle cx="27" cy="27" r="5" fill={useStatusColour(target)} />
|
||||
)}
|
||||
{props.voice && (
|
||||
<foreignObject x="22" y="22" width="10" height="10">
|
||||
<VoiceIndicator status={props.voice}>
|
||||
{props.voice === "muted" && <MicrophoneOff size={6} />}
|
||||
</VoiceIndicator>
|
||||
</foreignObject>
|
||||
)}
|
||||
</IconBase>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,31 @@
|
||||
import { User } from "revolt.js";
|
||||
import UserIcon from "./UserIcon";
|
||||
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
export function Username({ user, ...otherProps }: { user?: User } & JSX.HTMLAttributes<HTMLElement>) {
|
||||
return <span {...otherProps}>{ user?.username ?? <Text id="app.main.channel.unknown_user" /> }</span>;
|
||||
import UserIcon from "./UserIcon";
|
||||
|
||||
export function Username({
|
||||
user,
|
||||
...otherProps
|
||||
}: { user?: User } & JSX.HTMLAttributes<HTMLElement>) {
|
||||
return (
|
||||
<span {...otherProps}>
|
||||
{user?.username ?? <Text id="app.main.channel.unknown_user" />}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export default function UserShort({ user, size }: { user?: User, size?: number }) {
|
||||
return <>
|
||||
<UserIcon size={size ?? 24} target={user} />
|
||||
<Username user={user} />
|
||||
</>;
|
||||
}
|
||||
export default function UserShort({
|
||||
user,
|
||||
size,
|
||||
}: {
|
||||
user?: User;
|
||||
size?: number;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<UserIcon size={size ?? 24} target={user} />
|
||||
<Username user={user} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,31 +1,32 @@
|
||||
import { User } from "revolt.js";
|
||||
import { Text } from "preact-i18n";
|
||||
import { Users } from "revolt.js/dist/api/objects";
|
||||
|
||||
import { Text } from "preact-i18n";
|
||||
|
||||
interface Props {
|
||||
user: User;
|
||||
user: User;
|
||||
}
|
||||
|
||||
export default function UserStatus({ user }: Props) {
|
||||
if (user.online) {
|
||||
if (user.status?.text) {
|
||||
return <>{user.status?.text}</>;
|
||||
}
|
||||
if (user.online) {
|
||||
if (user.status?.text) {
|
||||
return <>{user.status?.text}</>;
|
||||
}
|
||||
|
||||
if (user.status?.presence === Users.Presence.Busy) {
|
||||
return <Text id="app.status.busy" />;
|
||||
}
|
||||
if (user.status?.presence === Users.Presence.Busy) {
|
||||
return <Text id="app.status.busy" />;
|
||||
}
|
||||
|
||||
if (user.status?.presence === Users.Presence.Idle) {
|
||||
return <Text id="app.status.idle" />;
|
||||
}
|
||||
if (user.status?.presence === Users.Presence.Idle) {
|
||||
return <Text id="app.status.idle" />;
|
||||
}
|
||||
|
||||
if (user.status?.presence === Users.Presence.Invisible) {
|
||||
return <Text id="app.status.offline" />;
|
||||
}
|
||||
if (user.status?.presence === Users.Presence.Invisible) {
|
||||
return <Text id="app.status.offline" />;
|
||||
}
|
||||
|
||||
return <Text id="app.status.online" />;
|
||||
}
|
||||
return <Text id="app.status.online" />;
|
||||
}
|
||||
|
||||
return <Text id="app.status.offline" />;
|
||||
return <Text id="app.status.offline" />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user