diff --git a/src/timelines/MediaAttachmentGrid.css b/src/timelines/MediaAttachmentGrid.css index 55bb30d..378b091 100644 --- a/src/timelines/MediaAttachmentGrid.css +++ b/src/timelines/MediaAttachmentGrid.css @@ -6,18 +6,27 @@ gap: 4px; contain: layout style; - > :where(img, video) { + &.sensitive>.cell> :where(img, video) { + filter: blur(20px) saturate(0.2); + } + + >.cell> :where(img, video) { + object-fit: contain; + width: 100%; + height: 100%; + } + + >.cell { max-height: 35vh; min-height: 40px; min-width: 40px; - object-fit: contain; max-width: 100%; + contain: strict; + content-visibility: auto; background-color: var(--media-color-accent, var(--tutu-color-surface-d)); border-radius: 2px; border: 1px solid var(--tutu-color-surface-d); transition: outline-width 60ms var(--tutu-anim-curve-std), border-color 60ms var(--tutu-anim-curve-std); - contain: strict; - content-visibility: auto; &:hover, &:focus-visible { diff --git a/src/timelines/MediaAttachmentGrid.tsx b/src/timelines/MediaAttachmentGrid.tsx index 2b9db57..8fec903 100644 --- a/src/timelines/MediaAttachmentGrid.tsx +++ b/src/timelines/MediaAttachmentGrid.tsx @@ -1,7 +1,6 @@ import type { mastodon } from "masto"; import { type Component, - For, Index, Match, Switch, @@ -44,8 +43,15 @@ function constraintedSize( }; } +function isolateCallback(event: Event) { + if (event.target !== event.currentTarget) { + event.stopPropagation(); + } +} + const MediaAttachmentGrid: Component<{ attachments: mastodon.v1.MediaAttachment[]; + sensitive?: boolean; }> = (props) => { const [rootRef, setRootRef] = createSignal(); const [viewerIndex, setViewerIndex] = createSignal(); @@ -53,14 +59,13 @@ const MediaAttachmentGrid: Component<{ const settings = useStore($settings); const windowSize = useWindowSize(); - createRenderEffect((lastDispose?: () => void) => { - lastDispose?.(); + createRenderEffect(() => { const vidx = viewerIndex(); if (typeof vidx === "undefined") return; const container = document.createElement("div"); container.setAttribute("role", "presentation"); document.body.appendChild(container); - return render(() => { + const dispose = render(() => { onCleanup(() => { document.body.removeChild(container); }); @@ -75,6 +80,8 @@ const MediaAttachmentGrid: Component<{ /> ); }, container); + + onCleanup(dispose); }); const openViewerFor = (index: number) => { @@ -131,69 +138,62 @@ const MediaAttachmentGrid: Component<{
{ - if (e.target !== e.currentTarget) { - e.stopImmediatePropagation(); - } + classList={{ + sensitive: props.sensitive, }} + style={{ "column-count": columnCount() }} + onClick={isolateCallback} > {(item, index) => { const itemType = () => item().type; return ( - - - {item().description - - - - - - - - - + ); }} diff --git a/src/timelines/RegularToot.tsx b/src/timelines/RegularToot.tsx index 6861258..d98de09 100644 --- a/src/timelines/RegularToot.tsx +++ b/src/timelines/RegularToot.tsx @@ -47,7 +47,7 @@ type TootActionGroupProps = { ) => void; }; -type TootCardProps = { +type RegularTootProps = { status: mastodon.v1.Status; actionable?: boolean; evaluated?: boolean; @@ -235,7 +235,7 @@ function onToggleReveal(setValue: Setter, event: Event) { * You can extract the intent from the attributes of the "actionable" element. * The action type is the dataset's `action`. */ -const RegularToot: Component = (props) => { +const RegularToot: Component = (props) => { let rootRef: HTMLElement; const [managed, managedActionGroup, rest] = splitProps( props, @@ -293,7 +293,7 @@ const RegularToot: Component = (props) => { return ( <> -
= (props) => { 0}> - + = (props) => { /> -
+ ); };