Create separate ImageFile component for image attachments

This commit is contained in:
Michaili K 2021-08-15 18:53:42 +02:00
parent 1b4d1e73df
commit 88c9775e23
No known key found for this signature in database
GPG key ID: BD613494318FEBA0
3 changed files with 56 additions and 22 deletions

View file

@ -92,8 +92,10 @@
.image { .image {
cursor: pointer; cursor: pointer;
} width: 100%;
height: 100%;
.loading { &.loading {
background: var(--background); background: var(--background);
}
} }

View file

@ -11,6 +11,7 @@ import AttachmentActions from "./AttachmentActions";
import { SizedGrid } from "./Grid"; import { SizedGrid } from "./Grid";
import Spoiler from "./Spoiler"; import Spoiler from "./Spoiler";
import TextFile from "./TextFile"; import TextFile from "./TextFile";
import ImageFile from "./ImageFile";
interface Props { interface Props {
attachment: AttachmentI; attachment: AttachmentI;
@ -21,11 +22,8 @@ const MAX_ATTACHMENT_WIDTH = 480;
export default function Attachment({ attachment, hasContent }: Props) { export default function Attachment({ attachment, hasContent }: Props) {
const client = useContext(AppContext); const client = useContext(AppContext);
const { openScreen } = useIntermediate();
const { filename, metadata } = attachment; const { filename, metadata } = attachment;
const [spoiler, setSpoiler] = useState(filename.startsWith("SPOILER_")); const [spoiler, setSpoiler] = useState(filename.startsWith("SPOILER_"));
// only used in image attachments
const [loading, setLoading] = useState(true);
const url = client.generateFileURL( const url = client.generateFileURL(
attachment, attachment,
@ -41,24 +39,9 @@ export default function Attachment({ attachment, hasContent }: Props) {
height={metadata.height} height={metadata.height}
className={classNames({ className={classNames({
[styles.margin]: hasContent, [styles.margin]: hasContent,
[styles.loading]: loading,
spoiler, spoiler,
})}> })}>
<img <ImageFile attachment={attachment} />
src={url}
alt={filename}
className={styles.image}
loading="lazy"
onClick={() =>
openScreen({ id: "image_viewer", attachment })
}
onLoad={() =>
setLoading(false)
}
onMouseDown={(ev) =>
ev.button === 1 && window.open(url, "_blank")
}
/>
{spoiler && <Spoiler set={setSpoiler} />} {spoiler && <Spoiler set={setSpoiler} />}
</SizedGrid> </SizedGrid>
); );

View file

@ -0,0 +1,49 @@
import {Attachment} from "revolt-api/types/Autumn";
import styles from "./Attachment.module.scss";
import classNames from "classnames";
import {useContext, useState} from "preact/hooks";
import {useIntermediate} from "../../../../context/intermediate/Intermediate";
import {AppContext} from "../../../../context/revoltjs/RevoltClient";
enum ImageLoadingState
{
Loading,
Loaded,
Error
}
interface Props {
attachment: Attachment;
}
export default function ImageFile({ attachment }: Props)
{
const [loading, setLoading] = useState(ImageLoadingState.Loading);
const client = useContext(AppContext);
const { openScreen } = useIntermediate();
const url = client.generateFileURL(attachment)!;
return <img
src={url}
alt={attachment.filename}
loading="lazy"
className={classNames(styles.image, {
[styles.loading]: loading !== ImageLoadingState.Loaded
})}
onClick={() =>
openScreen({id: "image_viewer", attachment})
}
onMouseDown={(ev) =>
ev.button === 1 && window.open(url, "_blank")
}
onLoad={() =>
setLoading(ImageLoadingState.Loaded)
}
onError={() =>
setLoading(ImageLoadingState.Error)
}
/>
}