81 lines
2.2 KiB
TypeScript
81 lines
2.2 KiB
TypeScript
|
import type { mastodon } from "masto";
|
||
|
import { type Component, For, createSignal } from "solid-js";
|
||
|
import { css } from "solid-styled";
|
||
|
import tootStyle from "./toot.module.css";
|
||
|
import { Portal } from "solid-js/web";
|
||
|
import MediaViewer, { MEDIA_VIEWER_HEROSRC } from "./MediaViewer";
|
||
|
import { HeroSourceProvider } from "../platform/anim";
|
||
|
|
||
|
const MediaAttachmentGrid: Component<{
|
||
|
attachments: mastodon.v1.MediaAttachment[];
|
||
|
}> = (props) => {
|
||
|
let rootRef: HTMLElement;
|
||
|
const [viewerIndex, setViewerIndex] = createSignal<number>();
|
||
|
const viewerOpened = () => typeof viewerIndex() !== "undefined"
|
||
|
const gridTemplateColumns = () => {
|
||
|
const l = props.attachments.length;
|
||
|
if (l < 2) {
|
||
|
return "1fr";
|
||
|
}
|
||
|
if (l < 4) {
|
||
|
return "repeat(2, 1fr)";
|
||
|
}
|
||
|
return "repeat(3, 1fr)";
|
||
|
};
|
||
|
|
||
|
const openViewerFor = (index: number) => {
|
||
|
setViewerIndex(index);
|
||
|
};
|
||
|
|
||
|
css`
|
||
|
.attachments {
|
||
|
grid-template-columns: ${gridTemplateColumns()};
|
||
|
}
|
||
|
`;
|
||
|
return (
|
||
|
<section
|
||
|
ref={rootRef!}
|
||
|
class={[tootStyle.tootAttachmentGrp, "attachments"].join(" ")}
|
||
|
onClick={(e) => e.stopImmediatePropagation()}
|
||
|
>
|
||
|
<For each={props.attachments}>
|
||
|
{(item, index) => {
|
||
|
switch (item.type) {
|
||
|
case "image":
|
||
|
return (
|
||
|
<img
|
||
|
src={item.previewUrl}
|
||
|
alt={item.description || undefined}
|
||
|
onClick={[openViewerFor, index()]}
|
||
|
loading="lazy"
|
||
|
></img>
|
||
|
);
|
||
|
case "video":
|
||
|
case "gifv":
|
||
|
case "audio":
|
||
|
case "unknown":
|
||
|
return <div></div>;
|
||
|
}
|
||
|
}}
|
||
|
</For>
|
||
|
<HeroSourceProvider
|
||
|
value={() => ({
|
||
|
[MEDIA_VIEWER_HEROSRC]: rootRef.children.item(
|
||
|
viewerIndex() || 0,
|
||
|
) as HTMLElement,
|
||
|
})}
|
||
|
>
|
||
|
<MediaViewer
|
||
|
show={viewerOpened()}
|
||
|
index={viewerIndex() || 0}
|
||
|
onIndexUpdated={setViewerIndex}
|
||
|
media={props.attachments}
|
||
|
onClose={() => setViewerIndex(undefined)}
|
||
|
/>
|
||
|
</HeroSourceProvider>
|
||
|
</section>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
export default MediaAttachmentGrid;
|