mirror of
https://github.com/block/buzz.git
synced 2026-11-11 20:01:09 +00:00
fix(link-previews): proxy sent preview media (#5627)
## Overview **Category:** fix **User Impact:** Sent link previews now reliably display their thumbnail and favicon when the media is hosted on the relay. **Problem:** Sent preview cards loaded relay-hosted snapshot media directly, so authenticated relay requests could fail even though the snapshot itself was valid. **Solution:** Rewrite snapshot media at the shared card render boundary through Buzz's authenticated local media proxy, preserving the original display domain and rerendering when the proxy becomes ready. ## Changes <details> <summary>File changes</summary> **desktop/src/shared/ui/link-preview-attachment.tsx** Routes sent preview thumbnails and favicons through authenticated relay media handling above the Compact/Rich fork while preserving original metadata. **desktop/src/testing/e2eBridge.ts** Adds an opt-in proxy-readiness seam that deterministically re-arms the production media lookup when released. **desktop/tests/e2e/messaging.spec.ts** Covers the real send, snapshot, recipient, and card-render path for Compact and Rich previews, including fallback URLs, proxied URLs, and decoded image content. **desktop/tests/helpers/bridge.ts** Exposes the opt-in media-proxy startup state to E2E tests. </details> ## Reproduction Steps 1. Send a link whose preview snapshot includes a relay-hosted thumbnail and favicon. 2. Inspect the sent message card in Compact mode and confirm both images render after the local media proxy becomes ready. 3. Switch link previews to Rich mode and confirm the thumbnail and favicon continue to render. 4. Run the focused Playwright regression: `pnpm exec playwright test tests/e2e/messaging.spec.ts --project=smoke --grep "sent link preview media uses the authenticated proxy"` ## Before / After | Before | After | | --- | --- | | Relay-hosted preview media fails to load. | The sent preview thumbnail and favicon render through the authenticated media proxy. | |  |  | Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import type { ResolvedLinkPreview } from "@/shared/lib/useResolvedLinkPreviews";
|
||||
import { useLinkPreviewStyle } from "@/shared/lib/linkPreviewStylePreference";
|
||||
import { rewriteRelayUrl } from "@/shared/lib/mediaUrl";
|
||||
import { useMediaProxyPort } from "@/shared/lib/useMediaProxyPort";
|
||||
import { CompactLinkPreviewAttachment } from "@/shared/ui/compact-link-preview-attachment";
|
||||
import {
|
||||
type LinkPreviewImageLightboxComponent,
|
||||
@@ -21,6 +23,16 @@ export function LinkPreviewAttachment({
|
||||
preview: ResolvedLinkPreview;
|
||||
showControls?: boolean;
|
||||
}) {
|
||||
useMediaProxyPort();
|
||||
const renderedPreview = {
|
||||
...preview,
|
||||
faviconDataUrl: preview.faviconDataUrl
|
||||
? rewriteRelayUrl(preview.faviconDataUrl)
|
||||
: null,
|
||||
imageDataUrl: preview.imageDataUrl
|
||||
? rewriteRelayUrl(preview.imageDataUrl)
|
||||
: null,
|
||||
};
|
||||
const style = useLinkPreviewStyle();
|
||||
if (style === "rich") {
|
||||
return (
|
||||
@@ -29,7 +41,7 @@ export function LinkPreviewAttachment({
|
||||
ImageLightbox={ImageLightbox}
|
||||
onOpen={onOpen}
|
||||
onRemove={onRemove}
|
||||
preview={preview}
|
||||
preview={renderedPreview}
|
||||
showControls={showControls}
|
||||
/>
|
||||
);
|
||||
@@ -40,7 +52,7 @@ export function LinkPreviewAttachment({
|
||||
className={className}
|
||||
onOpen={onOpen}
|
||||
onRemove={onRemove}
|
||||
preview={preview}
|
||||
preview={renderedPreview}
|
||||
showControls={showControls}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -61,6 +61,10 @@ import type {
|
||||
RawInstallRuntimeResult,
|
||||
RuntimeFileConfigSubset,
|
||||
} from "@/shared/api/tauri";
|
||||
import {
|
||||
ensureRelayOriginFetch,
|
||||
resetMediaCaches,
|
||||
} from "@/shared/lib/mediaUrl";
|
||||
import { normalizePubkey } from "@/shared/lib/pubkey";
|
||||
import {
|
||||
isValidLinkPreviewSnapshotCanonicalUrl,
|
||||
@@ -318,6 +322,8 @@ type E2eConfig = {
|
||||
applyCommunityDelayMs?: number;
|
||||
openDmDelayMs?: number;
|
||||
sendMessageDelayMs?: number;
|
||||
/** Hold the media proxy at port 0 until the E2E release seam is invoked. */
|
||||
mediaProxyInitiallyUnavailable?: boolean;
|
||||
/** Hold mock send live echoes until the E2E release seam is invoked. */
|
||||
deferSendMessageLiveEcho?: boolean;
|
||||
/** Close the first channel-window live REQ; its retry is accepted. */
|
||||
@@ -1101,6 +1107,8 @@ declare global {
|
||||
command: string;
|
||||
payload: unknown;
|
||||
}>;
|
||||
/** Release a mock media proxy held at port 0 and return its ready port. */
|
||||
__BUZZ_E2E_RELEASE_MEDIA_PROXY__?: () => number;
|
||||
/** Release mock send events that were stored but withheld from live subscribers. */
|
||||
__BUZZ_E2E_RELEASE_SEND_MESSAGE_LIVE_ECHO__?: () => number;
|
||||
__BUZZ_E2E_EMIT_MEDIA_UPLOAD_PHASE__?: (input: {
|
||||
@@ -1391,6 +1399,7 @@ const CHANNEL_WINDOW_AUX_DELETION_KINDS = new Set([
|
||||
// in e2e (instead of the `buzz-media://` fallback). The reaction guard
|
||||
// asserts against this exact port.
|
||||
const MOCK_MEDIA_PROXY_PORT = 54321;
|
||||
let mockMediaProxyPort = MOCK_MEDIA_PROXY_PORT;
|
||||
|
||||
// A relay-hosted custom emoji used by the reaction guard. Its URL matches
|
||||
// `rewriteRelayUrl()`'s `/media/{64-hex}.{ext}` pattern on the relay origin, so
|
||||
@@ -10132,6 +10141,15 @@ export function maybeInstallE2eTauriMocks() {
|
||||
window.__BUZZ_E2E_COMMANDS__ = [];
|
||||
window.__BUZZ_E2E_COMMAND_PAYLOADS__ = [];
|
||||
window.__BUZZ_E2E_COMMAND_LOG__ = [];
|
||||
mockMediaProxyPort = config.mock?.mediaProxyInitiallyUnavailable
|
||||
? 0
|
||||
: MOCK_MEDIA_PROXY_PORT;
|
||||
window.__BUZZ_E2E_RELEASE_MEDIA_PROXY__ = () => {
|
||||
mockMediaProxyPort = MOCK_MEDIA_PROXY_PORT;
|
||||
resetMediaCaches();
|
||||
ensureRelayOriginFetch();
|
||||
return mockMediaProxyPort;
|
||||
};
|
||||
window.__BUZZ_E2E_EMIT_MOCK_HUDDLE_TTS_SPEAKER__ = (payload) =>
|
||||
emit("huddle-tts-speaker-level", payload);
|
||||
window.__BUZZ_E2E_SIGNED_EVENTS__ = [];
|
||||
@@ -12696,7 +12714,7 @@ export function maybeInstallE2eTauriMocks() {
|
||||
activeConfig,
|
||||
);
|
||||
case "get_media_proxy_port":
|
||||
return MOCK_MEDIA_PROXY_PORT;
|
||||
return mockMediaProxyPort;
|
||||
case "pick_and_upload_media":
|
||||
return await resolveMockUploadDescriptors(activeConfig);
|
||||
case "pick_and_upload_image":
|
||||
|
||||
Reference in New Issue
Block a user