From 178be32c0aafde16d2c93b927f7465e515faf0d4 Mon Sep 17 00:00:00 2001 From: LimitedDelusions <88751373+LimitedDelusions@users.noreply.github.com> Date: Sun, 17 May 2026 10:25:48 -0400 Subject: [PATCH] Normalize Loom share links for embeds --- src/people/utils/LoomViewerRecorder.tsx | 43 +++++++++++++++---- .../__tests__/LoomViewerRecorder.test.tsx | 19 ++++++++ 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/people/utils/LoomViewerRecorder.tsx b/src/people/utils/LoomViewerRecorder.tsx index 61dc76bfc..856fbc93f 100644 --- a/src/people/utils/LoomViewerRecorder.tsx +++ b/src/people/utils/LoomViewerRecorder.tsx @@ -7,6 +7,23 @@ const PUBLIC_APP_ID = 'ded90c8e-92ed-496d-bfe3-f742d7fa9785'; const BUTTON_ID = 'loom-record-sdk-button'; +const normalizeLoomEmbedUrl = (url: string) => { + try { + const parsedUrl = new URL(url); + const isLoomUrl = parsedUrl.hostname === 'loom.com' || parsedUrl.hostname.endsWith('.loom.com'); + const [urlType, videoId] = parsedUrl.pathname.split('/').filter(Boolean); + + if (isLoomUrl && urlType === 'share' && videoId) { + parsedUrl.pathname = `/embed/${videoId}`; + return parsedUrl.toString(); + } + } catch { + return url; + } + + return url; +}; + export default function LoomViewerRecorder(props: LoomViewProps) { const { loomEmbedUrl, onChange, readOnly, style } = props; const [videoUrl, setVideoUrl] = useState(loomEmbedUrl || ''); @@ -45,15 +62,23 @@ export default function LoomViewerRecorder(props: LoomViewProps) { return null; } - const loomViewer = videoUrl && ( -
-
` - }} - /> + const normalizedVideoUrl = videoUrl ? normalizeLoomEmbedUrl(videoUrl) : ''; + const loomViewer = normalizedVideoUrl && ( +
+