feat(desktop): send authored link preview snapshots - #3818
Conversation
76a5892 to
85ef69d
Compare
502f8fd to
3990447
Compare
Co-authored-by: npub14vtk7pvazqrq9639qu7e560wnqtl0d53ca4gjuvq6jzf3k2el23qqlwa7f <ab176f059d100602ea25073d9a69ee9817f7b691c76a897180d48498d959faa2@buzz.block.builderlab.xyz> Signed-off-by: npub14vtk7pvazqrq9639qu7e560wnqtl0d53ca4gjuvq6jzf3k2el23qqlwa7f <ab176f059d100602ea25073d9a69ee9817f7b691c76a897180d48498d959faa2@buzz.block.builderlab.xyz>
Co-authored-by: npub14vtk7pvazqrq9639qu7e560wnqtl0d53ca4gjuvq6jzf3k2el23qqlwa7f <ab176f059d100602ea25073d9a69ee9817f7b691c76a897180d48498d959faa2@buzz.block.builderlab.xyz> Signed-off-by: npub14vtk7pvazqrq9639qu7e560wnqtl0d53ca4gjuvq6jzf3k2el23qqlwa7f <ab176f059d100602ea25073d9a69ee9817f7b691c76a897180d48498d959faa2@buzz.block.builderlab.xyz>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: npub14vtk7pvazqrq9639qu7e560wnqtl0d53ca4gjuvq6jzf3k2el23qqlwa7f <ab176f059d100602ea25073d9a69ee9817f7b691c76a897180d48498d959faa2@buzz.block.builderlab.xyz> Signed-off-by: npub14vtk7pvazqrq9639qu7e560wnqtl0d53ca4gjuvq6jzf3k2el23qqlwa7f <ab176f059d100602ea25073d9a69ee9817f7b691c76a897180d48498d959faa2@buzz.block.builderlab.xyz>
Co-authored-by: npub14vtk7pvazqrq9639qu7e560wnqtl0d53ca4gjuvq6jzf3k2el23qqlwa7f <ab176f059d100602ea25073d9a69ee9817f7b691c76a897180d48498d959faa2@buzz.block.builderlab.xyz> Signed-off-by: npub14vtk7pvazqrq9639qu7e560wnqtl0d53ca4gjuvq6jzf3k2el23qqlwa7f <ab176f059d100602ea25073d9a69ee9817f7b691c76a897180d48498d959faa2@buzz.block.builderlab.xyz>
Co-authored-by: npub14vtk7pvazqrq9639qu7e560wnqtl0d53ca4gjuvq6jzf3k2el23qqlwa7f <ab176f059d100602ea25073d9a69ee9817f7b691c76a897180d48498d959faa2@buzz.block.builderlab.xyz> Signed-off-by: npub14vtk7pvazqrq9639qu7e560wnqtl0d53ca4gjuvq6jzf3k2el23qqlwa7f <ab176f059d100602ea25073d9a69ee9817f7b691c76a897180d48498d959faa2@buzz.block.builderlab.xyz>
…eview card - link-preview-attachment.tsx: add optional onRemove prop that renders a small X button floating just outside the card's top-right corner (left-full top-0, z-20 above the link trigger), fading in on message row hover via group-hover/message and reachable by keyboard via focus-visible - link-preview-attachment.tsx: wrap the card in a relative container carrying the width classes (w-80 max-w-full shrink-0) since the card's overflow-hidden would clip a button positioned outside its bounds - link-preview-attachment.tsx: remove the AttachmentActions block with the hover-revealed ExternalLink icon, eliminating the reserved flex gap on card hover - markdown.tsx: drop the "Remove previews for everyone" text button below the preview list and its spacing wrapper; pass onRemove to each LinkPreviewAttachment instead, opening the same confirmation dialog - removal flow and AlertDialog confirmation are unchanged; X only renders when onRemoveLinkPreviewsForEveryone is available (own messages) Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
…cards
- Remove the "Automatic preview from {domain}" gradient overlay on preview
images; simplify the img alt text to "Preview from {domain}"
- Drop the "· {typeLabel}" suffix (PR/issue/repo/file/link/etc.) from the
card metadata row — the provider name and logo already convey the source,
so the row now shows just the provider
- typeLabel stays in the SupportedLinkPreview model since it still powers
the accessible aria-label ("Open GitHub PR: ...")
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Replace separate description and image controls with one Show more/Show less toggle that collapses both elements. - Expand rich preview text to the full available metadata and widen preview containers for readable 280-character tweets. - Add vertical padding beside the accent border and cap preview images at 300px while preserving responsive sizing. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Update rich preview cards with wider layouts, compact image sizing, and unified content expansion controls - Allow link titles to span two lines and preserve full expanded descriptions - Raise fetched description metadata to the standard 280-character X post limit - Preserve encoded description line breaks while normalizing intra-line whitespace - Add metadata tests covering line breaks and description length limits Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Render OG description line breaks instead of collapsing them into spaces - Group blank-line-separated paragraphs with compact spacing to avoid oversized gaps - Reuse the rich preview image component for consistent skeleton and lightbox behavior across link types Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Route rich link preview images through the markdown gallery lightbox so preview images support consistent zoom transitions and gallery navigation. - Extract link preview lightbox behavior and focusable-element discovery into focused markdown modules to keep the main renderer within its size limit. - Infer image dimensions from loaded thumbnails when explicit lightbox metadata is unavailable. - Pass the shared lightbox component through the link preview list and attachment layers. - Render compact preview cards inline with wrapping and place the remove action on the final compact card. - Preserve rich preview stacking and existing remove behavior for rich layouts. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Add a hover-only vertical ellipsis beside the first compact or rich preview. - Provide a Link display submenu for switching the global Rich or Compact appearance preference. - Show an actionable confirmation-backed Remove preview option for message authors while keeping display controls available to everyone. - Link preference-change toasts to Appearance settings and expand rich preview images to match uploaded image width. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Remove compact card borders and background surfaces while preserving transparent hover behavior. - Round thumbnail images on every corner and expand cards to the 24rem image-upload width. - Shorten the preview settings submenu label from Link display to Display. - Update compact preview geometry coverage for the wider borderless layout and await screenshot animations. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Expand compact preview thumbnails to an 88px height with slightly wider responsive dimensions. - Reduce the thumbnail-to-content inset so preview text sits closer to its image. - Allow compact titles to wrap across two lines for better readability. - De-emphasize hostnames and descriptions with a softer secondary foreground color. - Update desktop geometry coverage for the revised dimensions, spacing, and title treatment. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Remove legacy provider-specific compact preview logos and layouts in favor of hostname-driven metadata. - Present imageless compact previews with the same 84px height, description support, and left-rule treatment as image-backed cards. - Preserve fetched favicons and make favicon/hostname identity rows link directly to their source URL. - Align rich and compact hostname and description colors on the same secondary foreground treatment. - Expand messaging E2E coverage for equal-height cards, generic favicons, linked hostnames, and imageless descriptions. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Underline compact preview hostnames and titles together whenever the card is hovered. - Remove independent hostname hover styling so the interaction consistently represents the full destination URL. - Restore stronger description colors for standard rich previews and tweet content while keeping hostnames secondary. - Add E2E coverage confirming both compact identity elements receive the shared hover affordance. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
85ef69d to
a2ffdf8
Compare
|
rich previews are nice. make sure they stay opt-in or gated for private/untrusted hosts so we dont fetch surprise content |
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
…-setting * origin/main: feat(desktop): import local Pocket voices (#3259) fix(desktop): open profiles from avatars (#3751) refactor(voice): extract reusable Pocket primitives + Pocket voice settings (relands #2467 + #3208) (#3910) docs: add VISION_REMOTE_AGENTS.md (#3924) feat(desktop): auto-enable huddle transcription for agents (#3180) feat(agent): optional reply guard reminds a silent turn to publish (#3763) feat(desktop): upgrade Pocket TTS model (#3266) Signed-off-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz> Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Classify native preview image outcomes and honor bounded Retry-After cooldowns for rate-limited hosts - Extract host cooldown bookkeeping to keep the preview command within the desktop file-size guard - Fetch preview images and favicons independently so secondary failures preserve resolved metadata - Add bounded frontend concurrency, fragment deduplication, expiring negative cache entries, and cooldown-aware retries - Render deterministic Compact and Rich fallbacks for transient fetch and browser decode failures - Expand Rust, metadata-loader, mock bridge, and Playwright coverage for throttling and recovery Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Incorporate upstream desktop changes required by the pre-push overlap guard - Preserve the link preview thumbnail stabilization work on the updated base Co-authored-by: Taylor Ho <taylorkmho@gmail.com> * origin/main: (26 commits) docs: formal spec for remote agents and their management (#3748) fix(nip-oa): accept raw Nostr tag form in parse_json_array (#4203) perf(relay): serve relay-membership checks from the read replica (#4124) chore(deps): bump nostr-relay-pool for RUSTSEC-2026-0224 (#4139) docs(nostr): document #h requirement for live reaction subscriptions (#3487) docs(chart): fix ArgoCD example for native OCI sources (full artifact repoURL + path) (#3426) docs(readme): clarify which release asset to download per platform (#3481) fix(relay): allow open relays to set their NIP-11 workspace icon (kind:9033) (#3998) docs: note that addressable channel events scope by d, not h (#4103) docs: fix stale kind count, quick-start numbering, and empty Further Reading (#2613) fix(desktop): keep thread-open affordance in archived channels (#4012) docs: add one-click Railway deploy for a hosted relay (#2733) fix(desktop): point Oh My Pi preset at omp.sh (#3516) fix(mesh): stop restarting a busy or loading shared-compute node (#3909) fix(desktop): preserve first huddle speech (#3962) feat(desktop): Agent Trading Cards — mintable agent-snapshot card PNGs with optional NIP-44 lock (#3278) fix(buzz-acp): thread cache-read tokens into NIP-AM kind:44200 events (#3999) feat(relay): accept kind:30621 multi-repo projects at ingest (#3171) fix(release): preserve main in desktop PR body (#3979) chore(release): release Buzz Desktop version 0.5.3 (#3972) ... Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
- Import the retry-after bound only in the link preview test module - Keep production Tauri builds free of the unused-import warning enforced by pre-push clippy Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
wesbillman
left a comment
There was a problem hiding this comment.
Reviewing on Wes Billman's behalf. Requesting changes for a recipient privacy blocker at 60d348e526b96001acf6e57479b2fed3c6289245:
[P1 privacy] Merely viewing an unsolicited message automatically contacts sender-controlled hosts from the recipient's machine, with no off or consent control. Interactive unsuppressed messages extract preview URLs (desktop/src/shared/ui/markdown.tsx:1857-1863), the hook immediately loads each URL (desktop/src/shared/lib/useResolvedLinkPreviews.ts:223-277), and native code performs a direct GET with a Buzz Desktop user-agent (desktop/src-tauri/src/commands/link_preview.rs:191-215). The only preference is compact | rich, defaulting to compact—not off (desktop/src/shared/lib/linkPreviewStylePreference.ts:3-18). This exposes the recipient's IP and request timing to a message author without recipient action.
The SSRF hardening is strong, but it protects the machine rather than the user's network privacy. Please use a safe proxy, default-off/explicit enablement, consent before fetching, or another design that prevents unsolicited recipient-side requests. Please also add negative tests around the preview-specific URL gate (HTTP, credentials, non-443 ports, and private-IP hosts).
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
…er-snapshots * origin/main: (29 commits) feat(agents): model-tuning parity in global Agent Defaults editor (#4578) Polish Share Compute settings (#3735) fix(reactions): wrap long popover names (#3834) fix(desktop): clarify inherited agent parallelism (#4010) feat(desktop): make onboarding model defaults skippable (#3968) ci: add guarded desktop release cache prewarm (#4575) fix(mobile): recover stale relay sessions (#4372) chore(release): release Buzz Desktop version 0.5.4 (#4562) test(mobile): assert follow boundary semantics (#4559) docs(release): align desktop handoff instructions (#3988) fix: report agent usage per provider round, not once per turn (#4545) fix(desktop): harden Windows installs against Defender block and orphaned Node (#4382) feat(desktop): improve channel template discovery (#4549) fix(desktop): save key backups to authorized path (#4022) Add channel activity hover menu (#3935) feat(desktop): show saved Run on settings when editing an agent (#4539) fix(desktop): disambiguate provider API key labels and annotate mint key (#4406) fix(desktop): make OpenAI key re-enterable after first save in card mint dialog (#4140) fix(config-bridge): add harness-definition env tier and fix equal-value model override (#3580) Polish mobile composer and messaging UI (#3918) ... Signed-off-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz> Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Overview
Category: improvement
User Impact: Link previews appear in the composer attachment tray and travel as privacy-safe sender-authored snapshots, so opening a conversation never contacts the linked site.
Problem: Recipient-side unfurling leaked link visits, composer cards looked like timeline content, and preview work could interfere with sending.
Solution: Resolve previews only in the sender's composer, upload finished preview media to the active community relay, attach only complete versioned snapshots at Send, and render only strictly validated snapshots on recipients.
Privacy and delivery model
["link-preview", "none"], preserves clickable URL text, and resets after send or clearing the draft.Changes
Validation
At
11b60d88f:pnpm --dir desktop typecheck— passed.pnpm --dir desktop exec biome check src/features/messages/ui/MessageComposer.tsx src/features/messages/ui/useComposerLinkPreviews.tsx tests/e2e/messaging.spec.ts— passed.pnpm --dir desktop exec playwright test --project=smoke messaging.spec.ts— 42/42 passed.cargo test --manifest-path desktop/src-tauri/Cargo.toml link_preview_tags— 3/3 passed.cargo test -p buzz-relay link_preview_suppression— 3/3 passed.Screenshots