From 9846262e8b5e50d455eeb76814efc220aed96146 Mon Sep 17 00:00:00 2001
From: Paul <paulmakles@gmail.com>
Date: Sat, 10 Jul 2021 15:21:35 +0100
Subject: [PATCH] Fix attachment scaling.

---
 src/components/common/ChannelIcon.tsx         |   1 +
 src/components/common/ServerIcon.tsx          |   3 +-
 .../attachments/Attachment.module.scss        | 108 ++----------------
 .../messaging/attachments/Attachment.tsx      |  50 +++++++-
 .../attachments/AttachmentActions.module.scss |  49 ++++++++
 .../attachments/AttachmentActions.tsx         |   2 +-
 .../common/messaging/attachments/Grid.tsx     |  47 ++++++++
 src/components/common/user/UserIcon.tsx       |   2 +-
 .../navigation/left/ServerListSidebar.tsx     |  11 +-
 9 files changed, 163 insertions(+), 110 deletions(-)
 create mode 100644 src/components/common/messaging/attachments/AttachmentActions.module.scss
 create mode 100644 src/components/common/messaging/attachments/Grid.tsx

diff --git a/src/components/common/ChannelIcon.tsx b/src/components/common/ChannelIcon.tsx
index 9145d5f..01c48bf 100644
--- a/src/components/common/ChannelIcon.tsx
+++ b/src/components/common/ChannelIcon.tsx
@@ -57,6 +57,7 @@ export default function ChannelIcon(
             {...imgProps}
             width={size}
             height={size}
+            loading="lazy"
             aria-hidden="true"
             square={isServerChannel}
             src={iconURL ?? fallback}
diff --git a/src/components/common/ServerIcon.tsx b/src/components/common/ServerIcon.tsx
index 5b9dad8..168af8a 100644
--- a/src/components/common/ServerIcon.tsx
+++ b/src/components/common/ServerIcon.tsx
@@ -61,8 +61,9 @@ export default function ServerIcon(
             {...imgProps}
             width={size}
             height={size}
-            aria-hidden="true"
             src={iconURL}
+            loading="lazy"
+            aria-hidden="true"
         />
     );
 }
diff --git a/src/components/common/messaging/attachments/Attachment.module.scss b/src/components/common/messaging/attachments/Attachment.module.scss
index 111be64..0088878 100644
--- a/src/components/common/messaging/attachments/Attachment.module.scss
+++ b/src/components/common/messaging/attachments/Attachment.module.scss
@@ -3,67 +3,15 @@
     grid-auto-columns: min(100%, 480px);
     grid-auto-flow: row dense;
     
+    margin: .125rem 0 .125rem;
     width: max-content;
     max-width: 100%;
-
-    border-radius: 6px;
-    margin: .125rem 0 .125rem;
     
     &[data-spoiler="true"] {
         filter: blur(30px);
         pointer-events: none;
     }
 
-    &[data-has-content="true"] {
-        margin-top: 4px;
-    }
-
-    &.image, &.video > video {
-        cursor: pointer;   
-        
-        aspect-ratio: var(--width) / var(--height);
-        max-height: min(640px, var(--height-px));
-        max-width: min(480px, 100%, var(--width-px));
-        
-        object-fit: contain;
-        object-position: top left;
-    }
-
-    &.image {
-        &.long {
-            width: min(100%, var(--width-px));
-            height: auto;
-        }
-
-        &.tall {
-            height: min(100%, var(--height-px));
-            width: 100%;
-
-            &.loaded {
-                width: auto;
-            }
-        }
-    }
-
-    &.video {
-        .actions {
-            padding: 10px 12px;
-            border-radius: 6px 6px 0 0;
-        }
-
-        video {
-            border-radius: 0 0 6px 6px;
-
-            &.long {
-                height: auto;
-            }
-    
-            &.tall {
-                width: auto;
-            }
-        }
-    }
-
     &.audio {
         gap: 4px;
         padding: 6px;
@@ -125,52 +73,20 @@
     }
 }
 
-.actions.imageAction {
-    grid-template: 
-        "name icon external download" auto
-        "size icon external download" auto
-        / minmax(20px, 1fr) min-content min-content;
+.margin {
+    margin-top: 4px;
 }
 
-.actions {
-    display: grid;
-    grid-template: 
-        "icon name external download" auto
-        "icon size external download" auto
-        / min-content minmax(20px, 1fr) min-content;
-
-    align-items: center;
-    column-gap: 12px;
-    
-    width: 100%;
-    padding: 8px;
-    overflow: none;
-
-    color: var(--foreground);
-    background: var(--secondary-background);
-
-    span {
-        text-overflow: ellipsis;
-        white-space: nowrap;
-        overflow: hidden;
-    }
-    
-    .filesize {
-        grid-area: size;
-
-        font-size: 10px;
-        color: var(--secondary-foreground);
-    }
-
-    .downloadIcon {
-        grid-area: download;
-    }
+.container {
+    max-width: 100%;
+    overflow: hidden;
+    width: fit-content;
 
-    .externalType {
-        grid-area: external;
+    > :first-child {
+        width: min(480px, 100%, var(--width));
     }
+}
 
-    .iconType {
-        grid-area: icon;
-    }
+.container, .attachment, .image {
+    border-radius: 6px;
 }
diff --git a/src/components/common/messaging/attachments/Attachment.tsx b/src/components/common/messaging/attachments/Attachment.tsx
index 1b56382..d3a9980 100644
--- a/src/components/common/messaging/attachments/Attachment.tsx
+++ b/src/components/common/messaging/attachments/Attachment.tsx
@@ -8,9 +8,9 @@ import { useContext, useState } from "preact/hooks";
 import { useIntermediate } from "../../../../context/intermediate/Intermediate";
 import { AppContext } from "../../../../context/revoltjs/RevoltClient";
 
-import { MessageAreaWidthContext } from "../../../../pages/channels/messaging/MessageArea";
 import AttachmentActions from "./AttachmentActions";
 import TextFile from "./TextFile";
+import { SizedGrid } from "./Grid";
 
 interface Props {
     attachment: AttachmentRJS;
@@ -35,6 +35,44 @@ export default function Attachment({ attachment, hasContent }: Props) {
     switch (metadata.type) {
         case "Image": {
             return (
+                <SizedGrid width={metadata.width} height={metadata.height}
+                    className={classNames({ [styles.margin]: hasContent })}>
+                    <img src={url} alt={filename}
+                        className={styles.image}
+                        loading="lazy"
+                        onClick={() =>
+                            openScreen({ id: "image_viewer", attachment })
+                        }
+                        onMouseDown={(ev) =>
+                            ev.button === 1 && window.open(url, "_blank")
+                        } />
+                </SizedGrid>
+            )
+        }
+        case "Video": {
+            return (
+                <div className={classNames(styles.container, { [styles.margin]: hasContent })}
+                    style={{ '--width': metadata.width + 'px' }}>
+                    <AttachmentActions attachment={attachment} />
+                    <SizedGrid width={metadata.width} height={metadata.height}>
+                        <video src={url} alt={filename}
+                            controls
+                            loading="lazy"
+                            width={metadata.width}
+                            height={metadata.height}
+                            onMouseDown={(ev) =>
+                                ev.button === 1 && window.open(url, "_blank")
+                            }
+                        />
+                    </SizedGrid>
+                </div>
+            )
+        }
+
+
+
+
+            /*return (
                 <div
                     className={styles.container}
                     onClick={() => spoiler && setSpoiler(false)}>
@@ -51,8 +89,8 @@ export default function Attachment({ attachment, hasContent }: Props) {
                         width={metadata.width}
                         height={metadata.height}
                         loading="lazy"
-                        data-spoiler={spoiler}
                         data-has-content={hasContent}
+                        data-spoiler={spoiler}
                         className={classNames(
                             styles.attachment,
                             styles.image,
@@ -70,14 +108,14 @@ export default function Attachment({ attachment, hasContent }: Props) {
                         onClick={() =>
                             openScreen({ id: "image_viewer", attachment })
                         }
-                        onLoad={() => setLoaded(true)}
                         onMouseDown={(ev) =>
                             ev.button === 1 && window.open(url, "_blank")
                         }
+                        onLoad={() => setLoaded(true)}
                     />
                 </div>
             );
-        }
+        }*/
         case "Audio": {
             return (
                 <div
@@ -88,7 +126,7 @@ export default function Attachment({ attachment, hasContent }: Props) {
                 </div>
             );
         }
-        case "Video": {
+        /*case "Video": {
             return (
                 <div
                     className={styles.container}
@@ -129,7 +167,7 @@ export default function Attachment({ attachment, hasContent }: Props) {
                     </div>
                 </div>
             );
-        }
+        }*/
         case "Text": {
             return (
                 <div
diff --git a/src/components/common/messaging/attachments/AttachmentActions.module.scss b/src/components/common/messaging/attachments/AttachmentActions.module.scss
new file mode 100644
index 0000000..5eeb9a4
--- /dev/null
+++ b/src/components/common/messaging/attachments/AttachmentActions.module.scss
@@ -0,0 +1,49 @@
+.actions.imageAction {
+    grid-template: 
+        "name icon external download" auto
+        "size icon external download" auto
+        / minmax(20px, 1fr) min-content min-content;
+}
+
+.actions {
+    display: grid;
+    grid-template: 
+        "icon name external download" auto
+        "icon size external download" auto
+        / min-content minmax(20px, 1fr) min-content;
+
+    align-items: center;
+    column-gap: 12px;
+    
+    width: 100%;
+    padding: 8px;
+    overflow: none;
+
+    color: var(--foreground);
+    background: var(--secondary-background);
+
+    span {
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        overflow: hidden;
+    }
+    
+    .filesize {
+        grid-area: size;
+
+        font-size: 10px;
+        color: var(--secondary-foreground);
+    }
+
+    .downloadIcon {
+        grid-area: download;
+    }
+
+    .externalType {
+        grid-area: external;
+    }
+
+    .iconType {
+        grid-area: icon;
+    }
+}
diff --git a/src/components/common/messaging/attachments/AttachmentActions.tsx b/src/components/common/messaging/attachments/AttachmentActions.tsx
index 591494b..0f18b31 100644
--- a/src/components/common/messaging/attachments/AttachmentActions.tsx
+++ b/src/components/common/messaging/attachments/AttachmentActions.tsx
@@ -7,7 +7,7 @@ import {
 } from "@styled-icons/boxicons-regular";
 import { Attachment } from "revolt.js/dist/api/objects";
 
-import styles from "./Attachment.module.scss";
+import styles from "./AttachmentActions.module.scss";
 import classNames from "classnames";
 import { useContext } from "preact/hooks";
 
diff --git a/src/components/common/messaging/attachments/Grid.tsx b/src/components/common/messaging/attachments/Grid.tsx
new file mode 100644
index 0000000..abdfde3
--- /dev/null
+++ b/src/components/common/messaging/attachments/Grid.tsx
@@ -0,0 +1,47 @@
+import styled from "styled-components";
+import { Children } from "../../../../types/Preact";
+
+const Grid = styled.div`
+    display: grid;
+    max-width: min(480px, 100%, var(--width));
+    max-height: min(640px, var(--height));
+    aspect-ratio: var(--aspect-ratio);
+
+    img, video {
+        min-width: 100%;
+        min-height: 100%;
+
+        width: auto;
+        height: auto;
+
+        max-width: 100%;
+        max-height: 100%;
+
+        grid-area: 1 / 1;
+    }
+`;
+
+export default Grid;
+
+type Props = Omit<JSX.HTMLAttributes<HTMLDivElement>, 'children' | 'as' | 'style'> & {
+    style?: JSX.CSSProperties,
+    children?: Children,
+    width: number,
+    height: number,
+};
+
+export function SizedGrid(props: Props) {
+    const { width, height, children, style, ...divProps } = props;
+
+    return (
+        <Grid {...divProps}
+            style={{
+                ...style,
+                "--width": width + 'px',
+                "--height": height + 'px',
+                "--aspect-ratio": width / height,
+            }}>
+            { children }
+        </Grid>
+    )
+}
diff --git a/src/components/common/user/UserIcon.tsx b/src/components/common/user/UserIcon.tsx
index e5cd3dc..15e1a00 100644
--- a/src/components/common/user/UserIcon.tsx
+++ b/src/components/common/user/UserIcon.tsx
@@ -87,7 +87,7 @@ export default function UserIcon(
                 width="32"
                 height="32"
                 mask={mask ?? (status ? "url(#user)" : undefined)}>
-                {<img src={iconURL} draggable={false} />}
+                {<img src={iconURL} draggable={false} loading="lazy" />}
             </foreignObject>
             {props.status && (
                 <circle cx="27" cy="27" r="5" fill={useStatusColour(target)} />
diff --git a/src/components/navigation/left/ServerListSidebar.tsx b/src/components/navigation/left/ServerListSidebar.tsx
index c4f76f3..e10a730 100644
--- a/src/components/navigation/left/ServerListSidebar.tsx
+++ b/src/components/navigation/left/ServerListSidebar.tsx
@@ -132,7 +132,8 @@ const ServerEntry = styled.div<{ active: boolean; home?: boolean }>`
             ` }
 
         svg {
-            width: 56.5px;
+            width: 57px;
+            height: 117px;
             margin-top: 4px;
             display: relative;
 
@@ -151,10 +152,10 @@ const ServerEntry = styled.div<{ active: boolean; home?: boolean }>`
 function Swoosh() {
     return (
         <span>
-            <svg width="56" height="118" viewBox="0 0 56 118" fill="none" xmlns="http://www.w3.org/2000/svg">
-                <path d="M55.9957 0C55.6241 18.5052 31.292 28.1152 19.2904 32.1029L56 68.8124L55.9957 0Z" fill="var(--sidebar-active)"/>
-                <path d="M55.9963 117.633C55.8689 98.6899 31.3298 87.9423 19.2144 84.8847L55.9968 47.5654L55.9963 117.633Z" fill="var(--sidebar-active)"/>
-                <path d="M55.5682 58.4474C55.5682 73.7921 43.1288 86.2315 27.7841 86.2315C12.4394 86.2315 0 73.7921 0 58.4474C0 43.1026 12.4394 30.6633 27.7841 30.6633C43.1288 30.6633 55.5682 43.1026 55.5682 58.4474Z" fill="var(--sidebar-active)"/>
+            <svg xmlns="http://www.w3.org/2000/svg" width="57" height="117" fill="var(--sidebar-active)">
+                <path d="M27.746 86.465c14 0 28 11.407 28 28s.256-56 .256-56-42.256 28-28.256 28z"/>
+                <path d="M56 58.465c0 15.464-12.536 28-28 28s-28-12.536-28-28 12.536-28 28-28 28 12.536 28 28z"/>
+                <path d="M28.002 30.465c14 0 28-11.407 28-28s0 56 0 56-42-28-28-28z"/>
             </svg>
         </span>
     )
-- 
GitLab