From f6a51fd80b2dad812fe9678f26fa9a8f00171fc0 Mon Sep 17 00:00:00 2001 From: Kieran Date: Thu, 25 May 2023 20:20:45 +0100 Subject: [PATCH] feat: render image/video in link previews --- packages/app/src/Element/LinkPreview.tsx | 38 ++++++++++++++++++++---- packages/app/src/SnortApi.ts | 1 + 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/packages/app/src/Element/LinkPreview.tsx b/packages/app/src/Element/LinkPreview.tsx index 83512264..e6d5881f 100644 --- a/packages/app/src/Element/LinkPreview.tsx +++ b/packages/app/src/Element/LinkPreview.tsx @@ -4,6 +4,7 @@ import { CSSProperties, useEffect, useState } from "react"; import Spinner from "Icons/Spinner"; import SnortApi, { LinkPreviewData } from "SnortApi"; import useImgProxy from "Hooks/useImgProxy"; +import { MediaElement } from "Element/MediaElement"; async function fetchUrlPreviewInfo(url: string) { const api = new SnortApi(); @@ -21,8 +22,12 @@ const LinkPreview = ({ url }: { url: string }) => { useEffect(() => { (async () => { const data = await fetchUrlPreviewInfo(url); - if (data && data.image) { - setPreview(data); + if (data) { + const type = data.og_tags?.find(a => a[0].toLowerCase() === "og:type"); + const canPreviewType = type?.[1].startsWith("image") || type?.[1].startsWith("video") || false; + if (canPreviewType || data.image) { + setPreview(data); + } } else { setPreview(null); } @@ -36,14 +41,37 @@ const LinkPreview = ({ url }: { url: string }) => { ); - const backgroundImage = preview?.image ? `url(${proxy(preview?.image)})` : ""; - const style = { "--img-url": backgroundImage } as CSSProperties; + function previewElement() { + const type = preview?.og_tags?.find(a => a[0].toLowerCase() === "og:type")?.[1]; + if (type?.startsWith("video")) { + const urlTags = ["og:video:secure_url", "og:video:url", "og:video"]; + const link = preview?.og_tags?.find(a => urlTags.includes(a[0].toLowerCase()))?.[1]; + const videoType = preview?.og_tags?.find(a => a[0].toLowerCase() === "og:video:type")?.[1] ?? "video/mp4"; + if (link) { + return ; + } + } + if (type?.startsWith("image")) { + const urlTags = ["og:image:secure_url", "og:image:url", "og:image"]; + const link = preview?.og_tags?.find(a => urlTags.includes(a[0].toLowerCase()))?.[1]; + const videoType = preview?.og_tags?.find(a => a[0].toLowerCase() === "og:image:type")?.[1] ?? "image/png"; + if (link) { + return ; + } + } + if (preview?.image) { + const backgroundImage = preview?.image ? `url(${proxy(preview?.image)})` : ""; + const style = { "--img-url": backgroundImage } as CSSProperties; + return
; + } + return null; + } return (
{preview && ( e.stopPropagation()} target="_blank" rel="noreferrer" className="ext"> - {preview?.image &&
} + {previewElement()}

{preview?.title} {preview?.description && ( diff --git a/packages/app/src/SnortApi.ts b/packages/app/src/SnortApi.ts index 404e7d78..217bfcfc 100644 --- a/packages/app/src/SnortApi.ts +++ b/packages/app/src/SnortApi.ts @@ -45,6 +45,7 @@ export interface LinkPreviewData { title?: string; description?: string; image?: string; + og_tags?: Array<[name: string, value: string]>; } export default class SnortApi {