revite/src/components/common/messaging/attachments/Attachment.tsx

119 lines
3.9 KiB
TypeScript
Raw Normal View History

2021-07-30 22:40:49 +01:00
import { Attachment as AttachmentI } from "revolt-api/types/Autumn";
2021-07-05 11:23:23 +01:00
2021-06-20 22:09:18 +01:00
import styles from "./Attachment.module.scss";
2021-07-05 11:23:23 +01:00
import classNames from "classnames";
import { attachContextMenu } from "preact-context-menu";
2021-06-20 22:09:18 +01:00
import { useContext, useState } from "preact/hooks";
2021-07-05 11:23:23 +01:00
import { AppContext } from "../../../../context/revoltjs/RevoltClient";
import AttachmentActions from "./AttachmentActions";
2021-07-10 15:21:35 +01:00
import { SizedGrid } from "./Grid";
import ImageFile from "./ImageFile";
2021-07-10 15:55:21 +01:00
import Spoiler from "./Spoiler";
import TextFile from "./TextFile";
2021-06-20 22:09:18 +01:00
interface Props {
2021-07-30 22:40:49 +01:00
attachment: AttachmentI;
2021-07-05 11:25:20 +01:00
hasContent: boolean;
2021-06-20 22:09:18 +01:00
}
const MAX_ATTACHMENT_WIDTH = 480;
export default function Attachment({ attachment, hasContent }: Props) {
2021-07-05 11:25:20 +01:00
const client = useContext(AppContext);
const { filename, metadata } = attachment;
const [spoiler, setSpoiler] = useState(filename.startsWith("SPOILER_"));
2021-06-20 22:09:18 +01:00
2021-07-05 11:25:20 +01:00
const url = client.generateFileURL(
attachment,
{ width: MAX_ATTACHMENT_WIDTH * 1.5 },
true,
);
2021-06-20 22:09:18 +01:00
2021-07-05 11:25:20 +01:00
switch (metadata.type) {
case "Image": {
return (
<SizedGrid
width={metadata.width}
height={metadata.height}
onContextMenu={attachContextMenu("Menu", {
2021-12-23 13:16:43 +00:00
attachment,
})}
className={classNames({
[styles.margin]: hasContent,
spoiler,
})}>
<ImageFile
attachment={attachment}
width={metadata.width}
height={metadata.height}
/>
{spoiler && <Spoiler set={setSpoiler} />}
2021-07-10 15:21:35 +01:00
</SizedGrid>
);
2021-07-10 15:21:35 +01:00
}
2021-07-10 15:55:21 +01:00
2021-07-10 15:21:35 +01:00
case "Video": {
return (
<div
className={classNames(styles.container, {
[styles.margin]: hasContent,
})}
style={{ "--width": `${metadata.width}px` }}>
2021-07-10 15:21:35 +01:00
<AttachmentActions attachment={attachment} />
<SizedGrid
width={metadata.width}
height={metadata.height}
2021-07-10 15:55:21 +01:00
className={classNames({ spoiler })}>
<video
src={url}
alt={filename}
2021-07-10 15:21:35 +01:00
controls
loading="lazy"
width={metadata.width}
height={metadata.height}
onMouseDown={(ev) =>
ev.button === 1 && window.open(url, "_blank")
}
/>
{spoiler && <Spoiler set={setSpoiler} />}
2021-07-10 15:21:35 +01:00
</SizedGrid>
</div>
);
2021-07-10 15:21:35 +01:00
}
2021-07-05 11:25:20 +01:00
case "Audio": {
return (
<div
className={classNames(styles.attachment, styles.audio)}
data-has-content={hasContent}>
<AttachmentActions attachment={attachment} />
<audio src={url} controls />
</div>
);
}
2021-07-05 11:25:20 +01:00
case "Text": {
return (
<div
className={classNames(styles.attachment, styles.text)}
data-has-content={hasContent}>
<TextFile attachment={attachment} />
<AttachmentActions attachment={attachment} />
</div>
);
}
2021-07-10 15:55:21 +01:00
2021-07-05 11:25:20 +01:00
default: {
return (
<div
className={classNames(styles.attachment, styles.file)}
data-has-content={hasContent}>
<AttachmentActions attachment={attachment} />
</div>
);
}
}
2021-06-20 22:09:18 +01:00
}