From 4c497313c52e7d402f25f93856c4079cbb6fd07d Mon Sep 17 00:00:00 2001 From: thislight Date: Mon, 23 Sep 2024 15:43:49 +0800 Subject: [PATCH] MediaAttachmentGrid: major layout revised * Now the media preview use masonry layout * Supports preview video media --- src/timelines/MediaAttachmentGrid.tsx | 38 ++++++++++++++++++--------- src/timelines/toot.module.css | 4 +-- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/timelines/MediaAttachmentGrid.tsx b/src/timelines/MediaAttachmentGrid.tsx index 76d9f96..546340a 100644 --- a/src/timelines/MediaAttachmentGrid.tsx +++ b/src/timelines/MediaAttachmentGrid.tsx @@ -12,24 +12,16 @@ import { css } from "solid-styled"; import tootStyle from "./toot.module.css"; import MediaViewer from "./MediaViewer"; import { render } from "solid-js/web"; +import { useWindowSize } from "@solid-primitives/resize-observer"; const MediaAttachmentGrid: Component<{ attachments: mastodon.v1.MediaAttachment[]; }> = (props) => { let rootRef: HTMLElement; - const [dispose, setDispose] = createSignal<() => void>(); const [viewerIndex, setViewerIndex] = createSignal(); const viewerOpened = () => typeof viewerIndex() !== "undefined"; - const gridTemplateColumns = () => { - const l = props.attachments.length; - if (l < 2) { - return "minmax(40px, auto)"; - } - if (l < 4) { - return "repeat(2, minmax(40px, auto))"; - } - return "repeat(3, minmax(40px, auto))"; - }; + const windowSize = useWindowSize(); + const vh35 = () => Math.floor(windowSize.height * 0.35); createRenderEffect((lastDispose?: () => void) => { lastDispose?.(); @@ -61,7 +53,7 @@ const MediaAttachmentGrid: Component<{ css` .attachments { - grid-template-columns: ${gridTemplateColumns()}; + column-count: ${(props.attachments.length === 1 ? 1 : 3).toString()}; } `; return ( @@ -72,17 +64,39 @@ const MediaAttachmentGrid: Component<{ > {(item, index) => { + const width = item.meta?.small?.width; + const height = item.meta?.small?.height; + const aspectRatio = item.meta?.small?.aspect; + const maxHeight = vh35(); + const realHeight = height && height > maxHeight ? maxHeight : height; + const realWidth = + height && height > maxHeight + ? maxHeight * (aspectRatio ?? 1) + : width; + const style = { + width: realWidth ? `${realWidth}px` : undefined, + height: realHeight ? `${realHeight}px` : undefined, + "aspect-ratio": aspectRatio?.toString(), + }; switch (item.type) { case "image": return ( {item.description ); case "video": + return ( +