## 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>
## Overview
**Category:** fix
**User impact:** Link previews no longer disappear when a message is
sent while preview metadata or media is still settling. Fast Enter,
rapid Enter, and confirmed-draft auto-send now preserve the preview
without duplicate sends or stale tags.
**Problem:** The composer could look ready before its sender-authored
snapshot tag existed. Send paths could then race preview
resolution/upload, while debounced preview state could attach a tag for
a URL that had already been removed. The same timing also caused
confirmed-draft auto-send to be consumed without sending.
**Solution:**
- Debounce preview resolution to avoid card flicker while typing, then
disable every submit path while a supported external preview settles. A
2-second escape cap still permits a bare-link send if resolution stalls.
- Keep submit synchronous: acquire a composer-local lock before
asynchronous send work, read ready tags from the live URL set, and
reject Enter/form submits while a snapshot is pending.
- Retry confirmed-draft auto-submit until preview settling clears, then
submit exactly once.
- Upload thumbnail and favicon independently. A failed upload shows a
toast and degrades to the surviving media (or text-only) rather than
leaving the card spinning.
- Exclude message-edit mode from preview resolution, upload, and Save
gating. Edit-time preview snapshots remain follow-up #5273.
- Canonicalize fragment-bearing URLs for preview lookup/snapshot
identity while preserving the original fragment links in message text.
## Link preview state walkthrough
Captured using PR #5245's actual public Open Graph metadata and artwork.
The deterministic E2E bridge controls only upload timing so the
transient disabled state can be captured reliably.
| State | Expected behavior | Screenshot |
| --- | --- | --- |
| **1. Snapshot upload pending** | The real PR preview is visible, but
Submit remains disabled until its sendable snapshot tag is ready. Click
and Enter cannot send a bare link during the settling window. | 
|
| **2. Snapshot ready** | Once snapshot upload settles and the tag is
ready, the same preview remains and Submit becomes active. | 
|
| **3. Message sent** | The sent event carries the snapshot tag and
renders the PR title, description, and artwork inline instead of
degrading to a bare URL. | 
|
## Regression coverage
- Enter during metadata resolution or snapshot upload cannot send early.
- Paste-and-immediate-Enter sends after settling; rapid Enter submits
exactly once.
- Confirmed-draft auto-send waits for settling and fires exactly once.
- Removed/replaced URLs cannot leak stale snapshot tags or media refs.
- Thumbnail upload failure toasts and sends with the surviving favicon.
- Edit mode does not resolve/upload previews or gate Save.
- Fragment variants share a canonical preview while original fragment
links remain clickable.
- Existing ready-preview, suppression, bare-link fallback, and
multi-preview behavior remains covered.
## Reproduction steps
1. Open a channel and paste a supported external URL into the composer.
2. Press Enter immediately, before preview metadata/media finishes
settling.
3. Before this fix, the event could be sent without its preview snapshot
(or confirmed-draft auto-send could be lost). With this fix, submit
waits behind the disabled state and fires once with the matching
snapshot tag.
4. Remove or replace the URL and press Enter inside the debounce window.
The sent event contains tags only for URLs still present in the
submitted content.
## Validation
All required PR checks are green, including Desktop Core, Desktop Smoke
E2E shards, Desktop E2E Integration shards, macOS build, security
checks, and DCO.
---------
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
## Overview
**Category:** improvement
**User impact:** Link previews appear in the composer and travel as
privacy-safe sender-authored snapshots, so recipients never contact the
linked site merely by opening a conversation.
**Problem:** Cold-cache link paste could freeze the composer before the
URL painted; recipient-side unfurling leaked visits; invalid or
unresolved preview work could interfere with sending or leave dead cards
behind.
**Solution:** Paint pasted links before starting cold resolver work,
resolve only in the sender's composer, attach only complete validated
snapshots at Send, and render authored snapshots without recipient
fallback fetching.
## Behavior
- **Cold paste stays responsive:** bare and angle-bracket URL paste
paths commit the visible link before resolver work begins.
- **Sender-only fetching:** metadata is resolved while composing;
recipients render only the sender-authored snapshot.
- **Send never waits:** pending, failed, invalid, and unsendable
previews are omitted. They do not block or cancel the message.
- **Terminal misses disappear:** failed, timed-out, or 404 resolver
results remove the composer card while preserving visible link text.
- **Display-text links work:** Markdown links such as `[review the pull
request](…)` produce and send the same snapshots as bare URLs.
- **Compact and Rich presentation:** Compact remains the default; Rich
preserves source description line breaks and paragraphs.
- **Immediate draft-wide dismissal:** clicking × immediately hides all
previews for the draft, suppresses links pasted later, and emits only
`["link-preview", "none"]`. No confirmation detour. Suppression resets
after send or clearing the draft.
- **Zero recipient fallback:** missing, stale, malformed, off-relay,
unsupported, or suppressed snapshots remain ordinary visible links;
recipients never regenerate them.
## Implementation
- Resolve previews from deferred composer URL state so paste can paint
first.
- Upload finished preview media to the active community relay and
snapshot only valid, sendable media references.
- Atomically capture ready snapshots at submit time; never append a late
preview after send.
- Validate snapshot and suppression tags in desktop/native and relay
ingestion, rejecting duplicate or mixed forms.
- Render composer previews as stable 55px attachment cards at desktop
and narrow widths.
- Add deterministic E2E coverage for cold paste,
ready/pending/failed/invalid previews, display-text links, multiline
Rich descriptions, immediate dismissal, later-pasted links, and
suppression reset.
## Validation
Validated head: `9807ba8952f190e76153834abf8ab61dd40be5e2`
- Push hooks passed: `check-push-org`, branch skew, desktop check,
mobile tests, desktop tests, Rust tests, and desktop Tauri checks.
- Focused screenshot E2E at the validated head: 5/5 passed across
Compact/Rich composer and recipient states, 800px/420px geometry,
display-text links, multiline descriptions, and immediate dismissal.
- PR CI was triggered for this exact head and is currently running;
completed checks are green at the time of this update.
- Worktree is clean and both PR head and validated branch resolve to
`9807ba895…`.
## Screenshots
### Compact composer
| Loading | Ready |
|---|---|
| 
| 
|
### Rich composer
| Loading | Ready |
|---|---|
| 
| 
|
### Responsive composer
| 800px loading | 800px ready |
|---|---|
| 
| 
|
| 420px loading | 420px ready |
|---|---|
| 
| 
|
### Recipient presentation
| Compact | Rich |
|---|---|
| 
| 
|
### Display-text Markdown link
| Composer | Recipient |
|---|---|
| 
| 
|
### Rich multiline description

### Immediate dismissal
| Before × | Immediately after × |
|---|---|
| 
| 
|
---------
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
## Summary
- Make channel join/leave activity use the selected inline avatar-stack
treatment.
- Group related membership activity for one hour and preserve
profile/overflow-name interactions.
- Restore the virtualized day-divider handoff and align the sticky date
behavior with the message timeline.
## Validation
- `pnpm check`
- `pnpm test`
- `cargo test --manifest-path desktop/src-tauri/Cargo.toml`
- Visual desktop screenshot captured with seeded membership activity
---------
Signed-off-by: kenny lopez <klopez4212@gmail.com>
## Summary
- target the visible thread branch collapse guide in the messaging smoke
test
- avoid clicking the underlying collapse rail when the guide overlaps it
- retain the existing post-click assertions that verify the two-reply
branch collapses
## Context
`main` CI failed because Playwright repeatedly attempted to click the
lower `thread-collapse-rail` while the matching `thread-collapse-guide`
intercepted pointer events. Both controls dispatch collapse for the same
branch; the guide is the actual topmost user target and is already used
by `thread-unread.spec.ts`.
Failing run: https://github.com/block/buzz/actions/runs/30575425126
## Validation
- focused Playwright smoke test: 1 passed
- pre-push hooks: desktop check passed; 3,835 desktop tests passed
- `git diff --check`
## Review
Princess Donut reviewed the test-only approach and locator determinism
with no blockers. Mongo review is pending.
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>