From 93f307cd639cc92159aef5bd20ae0b931d7af138 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Mon, 6 Jul 2026 19:48:12 -0400 Subject: [PATCH] feat(embeds): inline YouTube/Vimeo players + media-forward video tiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Video link tiles (YouTube, Shorts, Vimeo) now play in place instead of only opening a browser tab. Adds a media-forward 16:9 (9:16 for Shorts) tile with a privacy-friendly click-to-play facade: the homeserver's cached og:image thumbnail + a play button, and only on click does it swap in the cookie-less youtube-nocookie / player.vimeo iframe — so nothing loads from Google/Vimeo until the user presses play. Gated by a new 'Inline Media Players' setting (default on); when off it falls back to a link that opens the video in a new tab. Also sources YouTube thumbnails from the homeserver og:image instead of img.youtube.com, which fixes the existing broken YouTube thumbnails on the web build (nginx img-src has no YouTube host) and removes the pre-click Google request. Pure URL parsing + embed-URL building moved to utils/videoEmbed.ts (unit-tested). Note: the desktop app's Tauri CSP frame-src must allow the video hosts (separate commit in cinny-desktop). Co-Authored-By: Claude Opus 4.8 --- .../components/url-preview/UrlPreview.css.tsx | 74 ++++ .../components/url-preview/UrlPreviewCard.tsx | 358 ++++++++---------- src/app/features/settings/general/General.tsx | 10 + src/app/state/settings.ts | 2 + src/app/utils/videoEmbed.test.ts | 69 ++++ src/app/utils/videoEmbed.ts | 90 +++++ 6 files changed, 393 insertions(+), 210 deletions(-) create mode 100644 src/app/utils/videoEmbed.test.ts create mode 100644 src/app/utils/videoEmbed.ts diff --git a/src/app/components/url-preview/UrlPreview.css.tsx b/src/app/components/url-preview/UrlPreview.css.tsx index 9f39cc82b..480a4eb96 100644 --- a/src/app/components/url-preview/UrlPreview.css.tsx +++ b/src/app/components/url-preview/UrlPreview.css.tsx @@ -197,6 +197,80 @@ export const MediaPlayButton = style([ }, ]); +// --------------------------------------------------------------------------- +// Inline video embed (YouTube / Vimeo) — media-forward click-to-play facade +// --------------------------------------------------------------------------- + +export const EmbedMediaLandscape = style([ + DefaultReset, + { + position: 'relative', + width: '100%', + aspectRatio: '16 / 9', + overflow: 'hidden', + backgroundColor: color.Surface.Container, + }, +]); + +export const EmbedMediaPortrait = style([ + DefaultReset, + { + position: 'relative', + width: toRem(220), + maxWidth: '100%', + aspectRatio: '9 / 16', + margin: '0 auto', + overflow: 'hidden', + backgroundColor: color.Surface.Container, + }, +]); + +// Fills the aspect box; used for both the