MediaAttachmentGrid: use new ~platform/Masonry
All checks were successful
/ depoly (push) Successful in 1m30s

* Masonry is a component provides limited masonry
  layout support
This commit is contained in:
thislight 2024-11-23 00:01:45 +08:00
parent 3a3fa40437
commit 18fa2810c4
No known key found for this signature in database
GPG key ID: FCFE5192241CCD4E
8 changed files with 266 additions and 78 deletions

View file

@ -3,10 +3,10 @@
margin-top: 1em;
margin-left: var(--card-pad, 0);
margin-right: var(--card-pad, 0);
gap: 4px;
contain: layout style;
gap: 4px;
> :where(img, video, .sensitive-placeholder) {
> * {
max-height: 35vh;
min-height: 40px;
min-width: 40px;
@ -22,12 +22,20 @@
&:focus-visible {
outline: 8px solid var(--media-color-accent, var(--tutu-color-surface-d));
border-color: var(--media-color-accent, var(--tutu-color-surface-d));
z-index: calc(var(--tutu-zidx-nav) - 1);
}
}
> * > * {
width: 100%;
height: 100%;
}
> * > :where(img, video) {
object-fit: contain;
}
>.sensitive-placeholder {
> * >.sensitive-placeholder {
display: inline-flex;
display: inline flex;
align-items: center;
@ -35,6 +43,6 @@
}
}
:where(.thread-top, .thread-mid) > .MediaAttachmentGrid {
:where(.thread-top, .thread-mid)>.MediaAttachmentGrid {
margin-left: calc(var(--card-pad, 0) + var(--toot-avatar-size, 0) + 8px);
}

View file

@ -23,6 +23,7 @@ import "./MediaAttachmentGrid.css";
import cardStyle from "~material/cards.module.css";
import { Preview } from "@suid/icons-material";
import { IconButton } from "@suid/material";
import Masonry from "~platform/Masonry";
type ElementSize = { width: number; height: number };
@ -149,13 +150,13 @@ const MediaAttachmentGrid: Component<{
}
};
return (
<section
<Masonry
component="section"
ref={setRootRef}
class={`MediaAttachmentGrid ${cardStyle.cardNoPad}`}
classList={{
sensitive: props.sensitive,
}}
style={{ "column-count": columnCount() }}
onClick={isolateCallback}
>
<Index each={props.attachments}>
@ -164,81 +165,79 @@ const MediaAttachmentGrid: Component<{
const style = createMemo(() => itemStyle(item()));
return (
<Switch>
<Match when={props.sensitive && !isReveal(index)}>
<div
class="sensitive-placeholder"
style={style()}
data-sort={index}
data-media-type={item().type}
>
<IconButton
color="inherit"
size="large"
onClick={[addReveal, index]}
aria-label="Reveal this media"
<div style={style()} role="presentation">
<Switch>
<Match when={props.sensitive && !isReveal(index)}>
<div
class="sensitive-placeholder"
data-sort={index}
data-media-type={item().type}
>
<Preview />
</IconButton>
</div>
</Match>
<Match when={itemType() === "image"}>
<img
src={item().previewUrl}
width={item().meta?.small?.width}
height={item().meta?.small?.height}
alt={item().description || undefined}
onClick={[openViewerFor, index]}
loading="lazy"
style={style()}
data-sort={index}
data-media-type={item().type}
></img>
</Match>
<Match when={itemType() === "video"}>
<video
src={item().url || undefined}
autoplay={!props.sensitive && settings().autoPlayVideos}
playsinline={settings().autoPlayVideos ? true : undefined}
controls
poster={item().previewUrl}
width={item().meta?.small?.width}
height={item().meta?.small?.height}
style={style()}
data-sort={index}
data-media-type={item().type}
preload="metadata"
/>
</Match>
<Match when={itemType() === "gifv"}>
<video
src={item().url || undefined}
autoplay={!props.sensitive && settings().autoPlayGIFs}
controls
playsinline /* or safari on iOS will play in full-screen */
loop
poster={item().previewUrl}
width={item().meta?.small?.width}
height={item().meta?.small?.height}
style={style()}
data-sort={index}
data-media-type={item().type}
preload="metadata"
/>
</Match>
<Match when={itemType() === "audio"}>
<audio
src={item().url || undefined}
controls
data-sort={index}
data-media-type={item().type}
></audio>
</Match>
</Switch>
<IconButton
color="inherit"
size="large"
onClick={[addReveal, index]}
aria-label="Reveal this media"
>
<Preview />
</IconButton>
</div>
</Match>
<Match when={itemType() === "image"}>
<img
src={item().previewUrl}
width={item().meta?.small?.width}
height={item().meta?.small?.height}
alt={item().description || undefined}
onClick={[openViewerFor, index]}
loading="lazy"
data-sort={index}
data-media-type={item().type}
></img>
</Match>
<Match when={itemType() === "video"}>
<video
src={item().url || undefined}
autoplay={!props.sensitive && settings().autoPlayVideos}
playsinline={settings().autoPlayVideos ? true : undefined}
controls
poster={item().previewUrl}
width={item().meta?.small?.width}
height={item().meta?.small?.height}
data-sort={index}
data-media-type={item().type}
preload="metadata"
/>
</Match>
<Match when={itemType() === "gifv"}>
<video
src={item().url || undefined}
autoplay={!props.sensitive && settings().autoPlayGIFs}
controls
playsinline /* or safari on iOS will play in full-screen */
loop
poster={item().previewUrl}
width={item().meta?.small?.width}
height={item().meta?.small?.height}
data-sort={index}
data-media-type={item().type}
preload="metadata"
/>
</Match>
<Match when={itemType() === "audio"}>
<audio
src={item().url || undefined}
controls
data-sort={index}
data-media-type={item().type}
></audio>
</Match>
</Switch>
</div>
);
}}
</Index>
</section>
</Masonry>
);
};