From bb44e391007561476fdcf9cfaedc7942d841f602 Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 11 Aug 2026 02:15:33 +0200 Subject: [PATCH 1/4] working rendering of encrypted bundled linkpreviews i think --- .../components/url-preview/UrlPreviewCard.tsx | 76 +++++++++++++------ 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/src/app/components/url-preview/UrlPreviewCard.tsx b/src/app/components/url-preview/UrlPreviewCard.tsx index 1302536054..efae98e288 100644 --- a/src/app/components/url-preview/UrlPreviewCard.tsx +++ b/src/app/components/url-preview/UrlPreviewCard.tsx @@ -17,7 +17,11 @@ import { ImageViewer } from '../image-viewer'; import { useSetting } from '$state/hooks/settings'; import { settingsAtom } from '$state/settings'; import type { IImageInfo } from '$types/matrix/common'; -import { MATRIX_UNSTABLE_BLUR_HASH_PROPERTY_NAME } from '$unstable/prefixes'; +import { + MATRIX_BUNDLED_EMBEDS_ENCRYPTED_PROPERTY_NAME, + MATRIX_UNSTABLE_BLUR_HASH_PROPERTY_NAME, +} from '$unstable/prefixes'; +import type { EncryptedAttachmentInfo } from 'browser-encrypt-attachment'; const linkStyles = { color: color.Success.Main }; @@ -99,21 +103,43 @@ export const UrlPreviewCard = as< const [linkPreviewImageMaxHeight] = useSetting(settingsAtom, 'linkPreviewImageMaxHeight'); const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad'); + type PreviewRenderProps = { + bundle: IPreviewUrlResponse; + encdata?: EncryptedAttachmentInfo & { + url: string; + }; + }; + const [previewStatus, loadPreview] = useAsyncCallback( - useCallback(() => { - if (!ts && !bundle) return Promise.resolve(null); + useCallback(async (): Promise => { + if (!ts && !bundle) return null; if (urlPreview && ts) { const clientCache = getClientCache(mx); const cached = clientCache.get(url); - if (cached !== undefined) return cached; + if (cached !== undefined) return { bundle: await cached }; const previewResult = mx?.getUrlPreview(url, ts); - if (!previewResult) return Promise.resolve(null); + if (!previewResult) return null; clientCache.set(url, previewResult); previewResult.finally(() => clientCache.delete(url)).catch(() => {}); - return previewResult; + return { bundle: await previewResult }; } - return Promise.resolve(bundle); - }, [ts, bundle, urlPreview, mx, url]) + if (bundle && bundle[MATRIX_BUNDLED_EMBEDS_ENCRYPTED_PROPERTY_NAME]) { + let encinfo = bundle[ + MATRIX_BUNDLED_EMBEDS_ENCRYPTED_PROPERTY_NAME + ] as unknown as EncryptedAttachmentInfo & { + url: string; + }; + const encryptedUrl = mxcUrlToHttp(mx, encinfo['url'] || '', useAuthentication); + if (!encryptedUrl) return { bundle: bundle }; + try { + return { bundle: bundle, encdata: encinfo }; + } catch (e) { + console.error(e); + return bundle ? { bundle: bundle } : null; + } + } + return bundle ? { bundle: bundle } : null; + }, [ts, bundle, urlPreview, mx, url, useAuthentication]) ); useEffect(() => { @@ -124,11 +150,13 @@ export const UrlPreviewCard = as< if (previewStatus.status === AsyncStatus.Error) return null; - const renderContent = (prev: IPreviewUrlResponse) => { + const renderContent = (renderProps: PreviewRenderProps) => { + let prev = renderProps.bundle; const siteName = prev['og:site_name']; const title = prev['og:title']; const description = prev['og:description']; - const imgUrl = mxcUrlToHttp( + + let imgUrl = mxcUrlToHttp( mx, prev['og:image'] || '', useAuthentication, @@ -137,6 +165,7 @@ export const UrlPreviewCard = as< 'scale', false ); + const handleAuxClick = (ev: React.MouseEvent) => { if (!prev['og:image']) { console.warn('No image'); @@ -273,7 +302,7 @@ export const UrlPreviewCard = as< /> )} - {!showOgVideo && prev['og:image'] && ( + {!showOgVideo && (prev['og:image:type'] || prev['og:image'] || prev["matrix:image:size"] ) && ( } @@ -321,16 +351,18 @@ export const UrlPreviewCard = as< /> )} - {!showOgVideo && !prev['og:image'] && prev['og:audio'] && ( - - } - /> - - )} + {!showOgVideo && + !(prev['og:image:type'] || prev['og:image'] || prev["matrix:image:size"]) && + (prev['og:audio:type'] || prev['og:audio']) && ( + + } + /> + + )} ); }; From 91f5d92d693bd40339eee0c8beced6c8953365c5 Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 11 Aug 2026 02:51:27 +0200 Subject: [PATCH 2/4] yoink misc.ts from the other branch --- src/unstable/prefixes/misc.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/unstable/prefixes/misc.ts b/src/unstable/prefixes/misc.ts index 09fc536d83..db6d15d412 100644 --- a/src/unstable/prefixes/misc.ts +++ b/src/unstable/prefixes/misc.ts @@ -4,6 +4,9 @@ export const MATRIX_UNSTABLE_PROFILE_BANNER_PROPERTY_NAME = 'chat.commet.profile_banner'; export const MATRIX_COMMET_UNSTABLE_PROFILE_COLOR_SCHEME_PROPERTY_NAME = 'chat.commet.profile_color_scheme'; +///opengraph field for encrypted embeds +export const MATRIX_BUNDLED_EMBEDS_ENCRYPTED_PROPERTY_NAME = 'beeper:image:encryption'; + /** * @deprecated */ From 9a6cf9cab618c9a70a1bb7ad5a9c4741be2743a1 Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 11 Aug 2026 03:08:29 +0200 Subject: [PATCH 3/4] document-change --- .../render_encrypted_media_in_bundled_link_previews_.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/render_encrypted_media_in_bundled_link_previews_.md diff --git a/.changeset/render_encrypted_media_in_bundled_link_previews_.md b/.changeset/render_encrypted_media_in_bundled_link_previews_.md new file mode 100644 index 0000000000..a99505afe4 --- /dev/null +++ b/.changeset/render_encrypted_media_in_bundled_link_previews_.md @@ -0,0 +1,5 @@ +--- +default: minor +--- + +# render encrypted media in bundled link previews From 973175da569932c862addb4e09e0c7d74b19aa4e Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 11 Aug 2026 03:12:26 +0200 Subject: [PATCH 4/4] format --- ...crypted_media_in_bundled_link_previews_.md | 2 +- .../components/url-preview/UrlPreviewCard.tsx | 95 ++++++++++--------- 2 files changed, 49 insertions(+), 48 deletions(-) diff --git a/.changeset/render_encrypted_media_in_bundled_link_previews_.md b/.changeset/render_encrypted_media_in_bundled_link_previews_.md index a99505afe4..ae38269894 100644 --- a/.changeset/render_encrypted_media_in_bundled_link_previews_.md +++ b/.changeset/render_encrypted_media_in_bundled_link_previews_.md @@ -2,4 +2,4 @@ default: minor --- -# render encrypted media in bundled link previews +# render encrypted media in bundled link previews diff --git a/src/app/components/url-preview/UrlPreviewCard.tsx b/src/app/components/url-preview/UrlPreviewCard.tsx index efae98e288..7f71ce7e1e 100644 --- a/src/app/components/url-preview/UrlPreviewCard.tsx +++ b/src/app/components/url-preview/UrlPreviewCard.tsx @@ -302,57 +302,58 @@ export const UrlPreviewCard = as< /> )} - {!showOgVideo && (prev['og:image:type'] || prev['og:image'] || prev["matrix:image:size"] ) && ( - - } - renderImage={(p) => ( - - )} - /> - - )} + > + } + renderImage={(p) => ( + + )} + /> + + )} {!showOgVideo && - !(prev['og:image:type'] || prev['og:image'] || prev["matrix:image:size"]) && + !(prev['og:image:type'] || prev['og:image'] || prev['matrix:image:size']) && (prev['og:audio:type'] || prev['og:audio']) && (