import { API } from "revolt.js"; import styles from "./Embed.module.scss"; import classNames from "classnames"; import { useContext } from "preact/hooks"; import { useClient } from "../../../../controllers/client/ClientController"; import { modalController } from "../../../../controllers/modals/ModalController"; import { MessageAreaWidthContext } from "../../../../pages/channels/messaging/MessageArea"; import Markdown from "../../../markdown/Markdown"; import Attachment from "../attachments/Attachment"; import EmbedMedia from "./EmbedMedia"; interface Props { embed: API.Embed; } const MAX_EMBED_WIDTH = 480; const MAX_EMBED_HEIGHT = 640; const CONTAINER_PADDING = 24; const MAX_PREVIEW_SIZE = 150; export default function Embed({ embed }: Props) { const client = useClient(); const maxWidth = Math.min( useContext(MessageAreaWidthContext) - CONTAINER_PADDING, MAX_EMBED_WIDTH, ); function calculateSize( w: number, h: number, ): { width: number; height: number } { const limitingWidth = Math.min(maxWidth, w); const limitingHeight = Math.min(MAX_EMBED_HEIGHT, h); // Calculate smallest possible WxH. const width = Math.min(limitingWidth, limitingHeight * (w / h)); const height = Math.min(limitingHeight, limitingWidth * (h / w)); return { width, height }; } switch (embed.type) { case "Text": case "Website": { // Determine special embed size. let mw, mh; const largeMedia = embed.type === "Text" ? typeof embed.media !== "undefined" : (embed.special && embed.special.type !== "None") || embed.image?.size === "Large"; if (embed.type === "Text") { mw = MAX_EMBED_WIDTH; mh = 1; } else { switch (embed.special?.type) { case "YouTube": case "Bandcamp": { mw = embed.video?.width ?? 1280; mh = embed.video?.height ?? 720; break; } case "Twitch": case "Lightspeed": case "Streamable": { mw = 1280; mh = 720; break; } default: { if (embed.image?.size === "Preview") { mw = MAX_EMBED_WIDTH; mh = Math.min( embed.image.height ?? 0, MAX_PREVIEW_SIZE, ); } else { mw = embed.image?.width ?? MAX_EMBED_WIDTH; mh = embed.image?.height ?? 0; } } } } const { width, height } = calculateSize(mw, mh); if (embed.type === "Website" && embed.special?.type === "GIF") { return ( ); } return (
{(embed.type === "Text" ? embed.title : embed.site_name) && (
{embed.icon_url && ( (e.currentTarget.style.display = "none") } /> )}
{embed.type === "Text" ? embed.title : embed.site_name}{" "}
)} {/*Author*/} {embed.type === "Website" && embed.title && ( (ev.button === 0 || ev.button === 1) && modalController.openLink(embed.url!) } className={styles.title}> {embed.title} )} {embed.description && (embed.type === "Text" ? ( ) : (
{embed.description}
))} {largeMedia && (embed.type === "Text" ? ( ) : ( ))}
{!largeMedia && embed.type === "Website" && (
)}
); } case "Image": { return ( modalController.push({ type: "image_viewer", embed }) } onMouseDown={(ev) => ev.button === 1 && modalController.openLink(embed.url) } /> ); } case "Video": { return (