MediaAttachmentGrid: major layout revised
* Now the media preview use masonry layout * Supports preview video media
This commit is contained in:
		
							parent
							
								
									1a0a9d7e77
								
							
						
					
					
						commit
						de03e62783
					
				
					 2 changed files with 28 additions and 14 deletions
				
			
		| 
						 | 
				
			
			@ -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<number>();
 | 
			
		||||
  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<{
 | 
			
		|||
    >
 | 
			
		||||
      <For each={props.attachments}>
 | 
			
		||||
        {(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 (
 | 
			
		||||
                <img
 | 
			
		||||
                  src={item.previewUrl}
 | 
			
		||||
                  style={style}
 | 
			
		||||
                  alt={item.description || undefined}
 | 
			
		||||
                  onClick={[openViewerFor, index()]}
 | 
			
		||||
                  loading="lazy"
 | 
			
		||||
                ></img>
 | 
			
		||||
              );
 | 
			
		||||
            case "video":
 | 
			
		||||
              return (
 | 
			
		||||
                <video
 | 
			
		||||
                  src={item.url || undefined}
 | 
			
		||||
                  style={style}
 | 
			
		||||
                  autoplay={false}
 | 
			
		||||
                />
 | 
			
		||||
              );
 | 
			
		||||
            case "gifv":
 | 
			
		||||
            case "audio":
 | 
			
		||||
            case "unknown":
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -222,12 +222,12 @@
 | 
			
		|||
  margin-top: 1em;
 | 
			
		||||
  margin-left: calc(var(--card-pad, 0) + var(--toot-avatar-size, 0) + 8px);
 | 
			
		||||
  margin-right: var(--card-pad, 0);
 | 
			
		||||
  display: grid;
 | 
			
		||||
  gap: 4px;
 | 
			
		||||
 | 
			
		||||
  > :where(img) {
 | 
			
		||||
  > :where(img, video) {
 | 
			
		||||
    max-height: 35vh;
 | 
			
		||||
    min-height: 40px;
 | 
			
		||||
    min-width: 40px;
 | 
			
		||||
    object-fit: contain;
 | 
			
		||||
    max-width: 100%;
 | 
			
		||||
    background-color: var(--tutu-color-surface-d);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue