From cb9348fbd692bcd737672dfb8ab96b5af831e5d1 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 25 Nov 2025 00:34:31 -0500 Subject: [PATCH] use iframely for urls in embed block editor --- components/Blocks/EmbedBlock.tsx | 81 +++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 16 deletions(-) diff --git a/components/Blocks/EmbedBlock.tsx b/components/Blocks/EmbedBlock.tsx index 3c0eaef9..919479b0 100644 --- a/components/Blocks/EmbedBlock.tsx +++ b/components/Blocks/EmbedBlock.tsx @@ -10,11 +10,15 @@ import { Separator } from "components/Layout"; import { Input } from "components/Input"; import { isUrl } from "src/utils/isURL"; import { elementId } from "src/utils/elementId"; -import { deleteBlock } from "./DeleteBlock"; import { focusBlock } from "src/utils/focusBlock"; import { useDrag } from "src/hooks/useDrag"; import { BlockEmbedSmall } from "components/Icons/BlockEmbedSmall"; import { CheckTiny } from "components/Icons/CheckTiny"; +import { DotLoader } from "components/utils/DotLoader"; +import { + LinkPreviewBody, + LinkPreviewMetadataResult, +} from "app/api/link_previews/route"; export const EmbedBlock = (props: BlockProps & { preview?: boolean }) => { let { permissions } = useEntitySetContext(); @@ -132,6 +136,7 @@ const BlockLinkInput = (props: BlockProps) => { let entity_set = useEntitySetContext(); let [linkValue, setLinkValue] = useState(""); + let [loading, setLoading] = useState(false); let { rep } = useReplicache(); let submit = async () => { let entity = props.entityID; @@ -149,21 +154,62 @@ const BlockLinkInput = (props: BlockProps) => { } let link = linkValue; if (!linkValue.startsWith("http")) link = `https://${linkValue}`; - // these mutations = simpler subset of addLinkBlock if (!rep) return; - await rep.mutate.assertFact({ - entity: entity, - attribute: "block/type", - data: { type: "block-type-union", value: "embed" }, - }); - await rep?.mutate.assertFact({ - entity: entity, - attribute: "embed/url", - data: { - type: "string", - value: link, - }, - }); + + // Try to get embed URL from iframely, fallback to direct URL + setLoading(true); + try { + let res = await fetch("/api/link_previews", { + headers: { "Content-Type": "application/json" }, + method: "POST", + body: JSON.stringify({ url: link, type: "meta" } as LinkPreviewBody), + }); + + let embedUrl = link; + let embedHeight = 360; + + if (res.status === 200) { + let data = await (res.json() as LinkPreviewMetadataResult); + if (data.success && data.data.links?.player?.[0]) { + let embed = data.data.links.player[0]; + embedUrl = embed.href; + embedHeight = embed.media?.height || 300; + } + } + + await rep.mutate.assertFact([ + { + entity: entity, + attribute: "embed/url", + data: { + type: "string", + value: embedUrl, + }, + }, + { + entity: entity, + attribute: "embed/height", + data: { + type: "number", + value: embedHeight, + }, + }, + ]); + } catch { + // On any error, fallback to using the URL directly + await rep.mutate.assertFact([ + { + entity: entity, + attribute: "embed/url", + data: { + type: "string", + value: link, + }, + }, + ]); + } finally { + setLoading(false); + } }; let smoker = useSmoker(); @@ -171,6 +217,7 @@ const BlockLinkInput = (props: BlockProps) => {
{ e.preventDefault(); + if (loading) return; let rect = document .getElementById("embed-block-submit") ?.getBoundingClientRect(); @@ -212,9 +259,11 @@ const BlockLinkInput = (props: BlockProps) => {
-- 2.51.2