Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Showing
with 1762 additions and 885 deletions
import dayjs from "dayjs"; import { observer } from "mobx-react-lite";
import Tooltip from "../Tooltip"; import { Message } from "revolt.js/dist/maps/Messages";
import styled, { css, keyframes } from "styled-components";
import { decodeTime } from "ulid"; import { decodeTime } from "ulid";
import { Text } from "preact-i18n"; import { Text } from "preact-i18n";
import styled, { css } from "styled-components";
import { MessageObject } from "../../../context/revoltjs/util"; import { useDictionary } from "../../../lib/i18n";
import { dayjs } from "../../../context/Locale";
import Tooltip from "../Tooltip";
export interface BaseMessageProps { export interface BaseMessageProps {
head?: boolean, head?: boolean;
failed?: boolean, failed?: boolean;
mention?: boolean, mention?: boolean;
blocked?: boolean, blocked?: boolean;
sending?: boolean, sending?: boolean;
contrast?: boolean contrast?: boolean;
highlight?: boolean;
} }
const highlight = keyframes`
0% { background: var(--mention); }
66% { background: var(--mention); }
100% { background: transparent; }
`;
export default styled.div<BaseMessageProps>` export default styled.div<BaseMessageProps>`
display: flex; display: flex;
overflow-x: none; overflow: none;
padding: .125rem; padding: 0.125rem;
flex-direction: row; flex-direction: row;
padding-right: 16px; padding-inline-end: 16px;
${ props => props.contrast && css` @media (pointer: coarse) {
padding: .3rem; user-select: none;
border-radius: 4px; }
background: var(--hover);
` }
${ props => props.head && css` ${(props) =>
margin-top: 12px; props.contrast &&
` } css`
padding: 0.3rem;
background: var(--hover);
border-radius: var(--border-radius);
`}
${ props => props.mention && css` ${(props) =>
background: var(--mention); props.head &&
` } css`
margin-top: 12px;
`}
${ props => props.blocked && css` ${(props) =>
filter: blur(4px); props.mention &&
transition: 0.2s ease filter; css`
background: var(--mention);
`}
&:hover { ${(props) =>
filter: none; props.blocked &&
} css`
` } filter: blur(4px);
transition: 0.2s ease filter;
${ props => props.sending && css` &:hover {
opacity: 0.8; filter: none;
color: var(--tertiary-foreground); }
` } `}
${ props => props.failed && css` ${(props) =>
color: var(--error); props.sending &&
` } css`
opacity: 0.8;
color: var(--tertiary-foreground);
`}
.author { ${(props) =>
props.failed &&
css`
color: var(--error);
`}
${(props) =>
props.highlight &&
css`
animation-name: ${highlight};
animation-timing-function: ease;
animation-duration: 3s;
`}
.detail {
gap: 8px; gap: 8px;
display: flex; display: flex;
align-items: center; align-items: center;
flex-shrink: 0;
} }
.author {
overflow: hidden;
cursor: pointer;
font-weight: 600 !important;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
white-space: normal;
&:hover {
text-decoration: underline;
}
}
.copy { .copy {
width: 0;
height: 0;
opacity: 0;
display: block; display: block;
overflow: hidden; overflow: hidden;
} }
...@@ -84,76 +135,125 @@ export const MessageInfo = styled.div` ...@@ -84,76 +135,125 @@ export const MessageInfo = styled.div`
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
::selection { .copyBracket {
background-color: transparent; opacity: 0;
color: var(--tertiary-foreground); position: absolute;
}
.copyTime {
opacity: 0;
position: absolute;
}
svg {
user-select: none;
cursor: pointer;
&:active {
transform: translateY(1px);
}
} }
time { time {
opacity: 0; opacity: 0;
} }
time, .edited { time,
.edited {
margin-top: 1px;
cursor: default; cursor: default;
display: inline; display: inline;
font-size: 10px; font-size: 10px;
color: var(--tertiary-foreground); color: var(--tertiary-foreground);
} }
time,
.edited > div {
&::selection {
background-color: transparent;
color: var(--tertiary-foreground);
}
}
.header {
cursor: pointer;
}
`; `;
export const MessageContent = styled.div` export const MessageContent = styled.div`
min-width: 0; min-width: 0;
flex-grow: 1; flex-grow: 1;
display: flex; display: flex;
overflow: hidden; // overflow: hidden;
font-size: 0.875rem;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
font-size: var(--text-size);
`; `;
export const DetailBase = styled.div` export const DetailBase = styled.div`
flex-shrink: 0;
gap: 4px; gap: 4px;
font-size: 10px; font-size: 10px;
display: inline-flex; display: inline-flex;
color: var(--tertiary-foreground); color: var(--tertiary-foreground);
.edited {
cursor: default;
&::selection {
background-color: transparent;
color: var(--tertiary-foreground);
}
}
`; `;
export function MessageDetail({ message, position }: { message: MessageObject, position: 'left' | 'top' }) { export const MessageDetail = observer(
if (position === 'left') { ({ message, position }: { message: Message; position: "left" | "top" }) => {
if (message.edited) { const dict = useDictionary();
return (
<> if (position === "left") {
<span className="copy"> if (message.edited) {
[<time>{dayjs(decodeTime(message._id)).format("H:mm")}</time>] return (
</span> <>
<span className="edited"> <time className="copyTime">
<Tooltip content={dayjs(message.edited).format("LLLL")}> <i className="copyBracket">[</i>
<Text id="app.main.channel.edited" /> {dayjs(decodeTime(message._id)).format(
</Tooltip> dict.dayjs?.timeFormat,
</span> )}
</> <i className="copyBracket">]</i>
) </time>
} else { <span className="edited">
<Tooltip
content={dayjs(message.edited).format("LLLL")}>
<Text id="app.main.channel.edited" />
</Tooltip>
</span>
</>
);
}
return ( return (
<> <>
<time> <time>
<i className="copy">[</i> <i className="copyBracket">[</i>
{ dayjs(decodeTime(message._id)).format("H:mm") } {dayjs(decodeTime(message._id)).format(
<i className="copy">]</i> dict.dayjs?.timeFormat,
)}
<i className="copyBracket">]</i>
</time> </time>
</> </>
) );
} }
}
return ( return (
<DetailBase> <DetailBase>
<time> <time>{dayjs(decodeTime(message._id)).calendar()}</time>
{dayjs(decodeTime(message._id)).calendar()} {message.edited && (
</time> <Tooltip content={dayjs(message.edited).format("LLLL")}>
{ message.edited && <Tooltip content={dayjs(message.edited).format("LLLL")}> <span className="edited">
<Text id="app.main.channel.edited" /> <Text id="app.main.channel.edited" />
</Tooltip> } </span>
</DetailBase> </Tooltip>
) )}
} </DetailBase>
);
},
);
.attachment { .attachment {
border-radius: 6px; display: grid;
margin: .125rem 0 .125rem; grid-auto-flow: row dense;
grid-auto-columns: min(100%, var(--attachment-max-width));
margin: 0.125rem 0 0.125rem;
width: max-content;
max-width: 100%;
&[data-spoiler="true"] { &[data-spoiler="true"] {
filter: blur(30px); filter: blur(30px);
pointer-events: none; pointer-events: none;
} }
&[data-has-content="true"] {
margin-top: 4px;
}
&.image {
cursor: pointer;
}
&.video {
.actions {
padding: 10px 12px;
border-radius: 6px 6px 0 0;
}
video {
width: 100%;
border-radius: 0 0 6px 6px;
}
}
&.audio { &.audio {
gap: 4px; gap: 4px;
padding: 6px; padding: 6px;
display: flex; display: flex;
border-radius: 6px; max-width: 100%;
flex-direction: column; flex-direction: column;
width: var(--attachment-default-width);
background: var(--secondary-background); background: var(--secondary-background);
max-width: 400px;
> audio { > audio {
width: 100%; width: 100%;
...@@ -43,20 +28,20 @@ ...@@ -43,20 +28,20 @@
&.file { &.file {
> div { > div {
width: 400px;
padding: 12px; padding: 12px;
max-width: 100%;
user-select: none; user-select: none;
width: fit-content; width: fit-content;
border-radius: 6px; border-radius: var(--border-radius);
width: var(--attachment-default-width);
} }
} }
&.text { &.text {
display: flex; width: 100%;
overflow: hidden; overflow: hidden;
max-width: 800px; grid-auto-columns: unset;
border-radius: 6px; max-width: var(--attachment-max-text-width);
flex-direction: column;
.textContent { .textContent {
height: 140px; height: 140px;
...@@ -65,18 +50,18 @@ ...@@ -65,18 +50,18 @@
overflow-y: auto; overflow-y: auto;
border-radius: 0 !important; border-radius: 0 !important;
background: var(--secondary-header); background: var(--secondary-header);
pre { pre {
margin: 0; margin: 0;
} }
pre code { pre code {
font-family: "Fira Mono", sans-serif; font-family: var(--monospace-font), sans-serif;
} }
&[data-loading="true"] { &[data-loading="true"] {
display: flex; display: flex;
> * { > * {
flex-grow: 1; flex-grow: 1;
} }
...@@ -85,35 +70,22 @@ ...@@ -85,35 +70,22 @@
} }
} }
.actions { .margin {
gap: 8px; margin-top: 4px;
padding: 8px; }
display: flex;
overflow: none; .container {
max-width: 100%; max-width: 100%;
align-items: center; overflow: hidden;
flex-direction: row; width: fit-content;
color: var(--foreground);
background: var(--secondary-background);
> svg { > :first-child {
flex-shrink: 0; width: min(var(--attachment-max-width), 100%, var(--width));
} }
}
.info {
display: flex;
flex-direction: column;
flex-grow: 1;
> span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.filesize { .container,
font-size: 10px; .attachment,
color: var(--secondary-foreground); .image {
} border-radius: var(--border-radius);
}
} }
This diff is collapsed.
This diff is collapsed.
import { User } from "revolt.js"; import { User } from "revolt.js/dist/maps/Users";
import UserIcon from "./UserIcon";
import Checkbox, { CheckboxProps } from "../../ui/Checkbox"; import Checkbox, { CheckboxProps } from "../../ui/Checkbox";
import UserIcon from "./UserIcon";
import { Username } from "./UserShort";
type UserProps = Omit<CheckboxProps, "children"> & { user: User }; type UserProps = Omit<CheckboxProps, "children"> & { user: User };
export default function UserCheckbox({ user, ...props }: UserProps) { export default function UserCheckbox({ user, ...props }: UserProps) {
return ( return (
<Checkbox {...props}> <Checkbox {...props}>
<UserIcon target={user} size={32} /> <UserIcon target={user} size={32} />
{user.username} <Username user={user} />
</Checkbox> </Checkbox>
); );
} }