feat(composer): add per-link preview controls - #4258
Draft
tellaho wants to merge 39 commits into
Draft
Conversation
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>
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>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
tellaho
force-pushed
the
tho/per-link-preview-controls
branch
from
August 2, 2026 05:34
62e051f to
3f21a71
Compare
Contributor
|
Re-validated the branch end-to-end against current
Every gate listed in the PR's own validation block passes on this checkout. No further changes needed from my side — ready for review. Attempted to flip the PR from draft → ready-for-review but |
tellaho
force-pushed
the
tho/link-preview-rich-setting
branch
5 times, most recently
from
August 6, 2026 01:57
5c2ba22 to
33b754a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Category: new-feature
User Impact: Authors can review and remove individual link previews before sending while keeping the links in their message.
Problem: Link previews only appeared after send, and authors could only remove every preview at once. Solution: Resolve previews inside new and edit composers, persist canonical per-URL suppression through drafts and events, and apply the same controls across optimistic, timeline, and forum rendering without blocking Send.
File changes
desktop/src-tauri/src/commands/messages.rs
Accept and validate per-link suppression on sends and edits.
desktop/src-tauri/src/events.rs, desktop/src-tauri/src/link_preview_tags.rs
Build canonical suppression tags into message and edit events behind a strict HTTPS-only validator.
desktop/src-tauri/src/egress_guard_tests.rs, desktop/src-tauri/src/huddle/pipeline.rs, desktop/src-tauri/src/lib.rs
Wire the new builder argument through existing Rust callers and register the validator module.
desktop/src/features/channels/ui/ChannelPane.types.ts, desktop/src/features/channels/ui/ChannelScreen.tsx, desktop/src/features/channels/useChannelPaneHandlers.ts
Seed edit composers from effective event suppression and pass controls through send/edit handlers.
desktop/src/features/messages/hooks.ts, desktop/src/features/messages/ui/useMentionSendFlow.ts
Carry suppression through normal, mention-confirmed, optimistic, REST, and edit paths.
desktop/src/features/messages/lib/applyEditTagOverlay.mjs, desktop/src/features/messages/lib/applyEditTagOverlay.test.mjs, desktop/src/features/messages/lib/formatTimelineMessages.ts
Overlay URL-specific edit controls deterministically while preserving blanket suppression compatibility.
desktop/src/features/messages/lib/imetaMediaMarkdown.ts, desktop/src/features/messages/lib/imetaMediaMarkdown.test.mjs
Split preview-control tags from media, emoji, and mention tags for validated relay submission.
desktop/src/features/messages/lib/useDrafts.ts, desktop/src/features/messages/ui/useDraftPersistSnapshot.ts
Persist and restore per-draft suppression with backward-compatible migration.
desktop/src/features/messages/ui/MessageComposer.tsx, desktop/src/features/messages/ui/MessageComposer.types.ts, desktop/src/features/messages/ui/useComposerLinkPreviews.tsx
Render non-blocking previews before send and restore suppression correctly across draft and edit transitions.
desktop/src/features/messages/ui/MessageRow.tsx, desktop/src/shared/ui/link-preview-list.tsx, desktop/src/shared/ui/markdown.tsx, desktop/src/shared/ui/markdown/types.ts, desktop/src/shared/ui/markdownUtils.ts
Reuse existing preview cards for per-item removal and filter suppressed canonical URLs on rendered messages.
desktop/src/shared/api/editMessage.ts, desktop/src/shared/api/tauri.ts
Expose suppression fields through the desktop bridge.
desktop/src/shared/lib/linkPreviewSuppression.mjs, desktop/src/shared/lib/linkPreviewSuppression.d.mts, desktop/src/shared/lib/linkPreviewSuppression.test.mjs
Normalize fragments, deduplicate URLs, parse legacy controls, and build deterministic tags.
desktop/tests/e2e/messaging.spec.ts
Cover composer preview deduplication, canonical removal, retained text, and Compact/Rich display.
Reproduction steps
Validation
pnpm checkcargo test --workspace: 2,105 passed, 14 ignoredcargo clippy --all-targets -- -D warningsmessaging.spec.ts: 41 passedScreenshots
Compact
Rich after removing one preview