Skip to content

Add composer attachments and compatible media preparation - #183

Merged
wesbillman merged 9 commits into
mainfrom
brain/composer-attachments
Sep 24, 2026
Merged

wesbillman merged 9 commits into
mainfrom
brain/composer-attachments

Conversation

@wesbillman

@wesbillman wesbillman commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Prepared by Brain on Wes's behalf.

Outcome

Add picker, clipboard and pane-owned drag/drop attachments to existing channel/thread composers, using the existing session upload and outbox contracts. Uploaded files can be sent without text. Drafts retain files across in-tab navigation, expose retry/removal, and fence cancelled/late results.

Match old Buzz's supported file-preparation paths and final-byte defaults without adding another delivery subsystem:

  • JPEG/PNG/WebP cleanup; GIF/APNG/WebP structural cleanup that preserves animation containers and snapshot PNG manifests.
  • Lazy, cancellable lossless WebP worker for still images requiring pixel transforms, including WebKit. Animated ICC/orientation transforms fail explicitly rather than silently changing appearance.
  • Byte-sniffed, fixed-demuxer ffmpeg preparation for video, HEIC/HEIF and the existing voice-note-*.wav exception. Unsupported codecs/missing host tools fail visibly; no generic audio upload conversion.
  • Private request-owned source spooling, streaming hash/sign/upload and backpressured media downloads. Cancellation/deadlines include response drain; cleanup precedes upload-slot release.
  • Canonical uploaded type and authenticated URL govern previews. Documents/HTML remain inert downloads, with nosniff and range headers preserved.

Limits and scope

Final-byte defaults: GIF 10 MiB; other supported images 50 MiB; generic files 100 MiB; videos 500 MiB. Relay policy remains authoritative. Separate client safety budgets: 500 MiB source ceiling, 128 MiB voice-note input, ten files/draft, 1,000 MiB retained source files/session. Browser Blobs still retain whole prepared payloads: streaming bounds broker transfer memory, not total browser memory.

Uses the development broker; this does not implement packaged native upload transport. No FOUNDATION/session/outbox edits. Background-send, attachment-first new sessions and UX polish were explicitly deferred. Reload discards unsent files, and navigation pauses unfinished uploads for explicit Retry.

Conflict and review repair — 2026-09-23

  • Merged main through 28265118d54144258bb8a23d2db9ef38e760e979; current head is 2627b3b34813018cb43c4024a69c1be380a5f03f. Preserved both broker import sets and main's remembered-agent behavior with the attachment-aware recipient assertions.
  • Addressed both findings in Carl's review: pane ownership and polite per-file status. Fix commit: 2326c3ea.
  • Sessions remains only a consumer of shared composer/drop behavior: the small pane-boundary fix can disappear with that screen. No Sessions-specific upload subsystem or new abstraction.
  • Repaired the standalone relay-composer fixture to supply main's new template-provider input.

Validation

  • At pushed head 2627b3b3, mandatory pre-push hooks passed TypeScript, 241 Vitest files / 2,506 tests, design typecheck and all design guards. Required hooks remained enabled; PR commits have DCO trailers. git diff --check passed and the worktree is clean.
  • Five new integration regressions in attachment-panes.test.tsx passed at that head: actual Sessions timeline drops (active/archived), actual portaled media-comment drops (composer available/absent), competing-composer isolation, and preparation/upload/readiness live semantics while editor focus stays put. These are DOM/semantic checks, not native drag/drop or assistive-technology speech-output evidence.
  • composer-attachments.spec.mjs: 6/6 passed across Chromium/WebKit during review-fix validation, before the final profiling-only main merge. Browser-only justification: actual File/DataTransfer/clipboard delivery and attachment-only send/download; decoder/canvas/worker/Wasm output; toolbar geometry and Tab order. Three scenarios total, none removed; no isolated browser mutation evidence claimed. The final merge changed only profiling scripts/fixtures/tests and contribution docs.
  • Fresh frontend/design builds and broad browser/native checks are left to CI, not duplicated locally. Earlier production frontend/design builds and 15 design-test files / 84 cases passed at aabd077e, not the current head.
  • Earlier implementation evidence remains bounded: generated HEIC/MOV/WMV/MPEG/voice-note conversions through real ffmpeg and an isolated signed-upload fixture; synthetic 500 MiB video and 100 MiB document streaming checks; ten generated outputs accepted by the deployed relay under Brain's identity. Tiny fixtures and synthetic envelopes do not certify valid maximum-size media or browser memory behavior.
  • Hosted status at delivery: DCO Check passed; CI run 35933653923 is in progress; Windows native validation is skipped. GitHub reports MERGEABLE (no conflicts), but BLOCKED / REVIEW_REQUIRED. No new-head hosted CI success is claimed.

Remaining merge gates

  • Passing required CI required check and reviewer/code-owner approval (repository rules require one approval and code-owner review).
  • Native Finder → Tauri drop routing and worker/Wasm/local-preview loading under Tauri's effective policy remain unverified.
  • Maximum-size valid media upload, playback/seek and memory behavior against deployed relay policy remain unverified.
  • The conflict/review repair does not clear those pre-existing acceptance gaps or authorize merging. This update leaves the PR's existing ready-for-review state unchanged.

Source conversation: Buzz channel ccfeb72c-9a27-4165-b6b5-01b800837604, conflict/review-fix thread 65f04b7aa131aa0c56301549e7514f0799794ffdbbabb90a0fd81f1960afe2b0.

Brain added 5 commits September 23, 2026 16:31
Signed-off-by: Brain <1a02c72794dcd0f07058a353bc3a81f4028b8c77c92c87fce6d5c8b85970a20b@buzz.block.builderlab.xyz>
Signed-off-by: Brain <1a02c72794dcd0f07058a353bc3a81f4028b8c77c92c87fce6d5c8b85970a20b@buzz.block.builderlab.xyz>
Signed-off-by: Brain <1a02c72794dcd0f07058a353bc3a81f4028b8c77c92c87fce6d5c8b85970a20b@buzz.block.builderlab.xyz>
Signed-off-by: Brain <1a02c72794dcd0f07058a353bc3a81f4028b8c77c92c87fce6d5c8b85970a20b@buzz.block.builderlab.xyz>
Signed-off-by: Brain <1a02c72794dcd0f07058a353bc3a81f4028b8c77c92c87fce6d5c8b85970a20b@buzz.block.builderlab.xyz>
@wesbillman
wesbillman marked this pull request as ready for review September 23, 2026 23:02
@wesbillman
wesbillman requested review from a team and comp615 as code owners September 23, 2026 23:02
@wesbillman

Copy link
Copy Markdown
Collaborator Author
Screen.Recording.2026-09-23.at.5.05.23.PM.mov

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Changes required at a20cc33ef4fb7b46145be207212b3669c0a3ce83: two P2 integration/accessibility findings inline. Fix both and add focused regression coverage before merge. GitHub prohibits a formal changes-requested review from the PR author’s account, so these findings are recorded as a comment review.

Read-only review covered composer surfaces and draft lifecycle through preparation, upload, outbox metadata and rendering, with independent UI, image-preparation and host/broker lanes. No local test runs, app launches or live uploads were performed for this review. Hosted checks passed, including both Chromium/WebKit shards and CI required; Windows native validation was skipped.

The PR’s disclosed native Finder/Tauri/policy and maximum-size valid-media/memory acceptance gates remain unverified. These are separate from the two code findings; this review does not require implementing the explicitly deferred packaged native upload transport.

setDragging(false);
const form = composer.current;
const zone =
form?.closest<HTMLElement>("[data-attachment-drop-zone]") ?? form;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

[P2] Wire pane ownership for the other production composers

This fallback installs the listeners only on the composer form. The existing-session conversation in src/bundled/sessions/SessionsPage.tsx:206-250 and the fullscreen media-review comments pane in src/features/messages/MediaReviewViewer.tsx:266-301 both render the newly attachment-enabled MessageComposer, but neither supplies a data-attachment-drop-zone ancestor. Consequently, dropping a file over their timeline/comments area does not reach attachFiles, although dropping on the form or using picker/paste works. The media-review UI is portaled to document.body, so it cannot inherit Channels’ native DOM drop listener either.

Give these existing panes explicit drop ownership and unclaimed-drop rejection, preserving isolation from other open composers. Cover an outside-form drop into the existing Sessions timeline and the portaled comments pane, plus rejection when the owning composer is unavailable. This is source-established missing routing, not a claim that browser navigation/data loss was reproduced.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brain, an automated agent, replying on Wes's behalf.

Fixed in 2326c3e (now included in pushed head 2627b3b). Both existing-session and portaled media-comments panes now declare drop ownership and reuse the existing unhandled-drop rejection. No Sessions-specific upload logic or new ownership abstraction was added.

The four pane cases in src/features/messages/attachment-panes.test.tsx mount the actual production components under StrictMode, exercise outside-form drops with a competing outer composer, and cover active/archived Sessions plus available/absent media-review composers. All passed again in the mandatory pre-push run at 2627b3b. This is DOM event-routing evidence, not native Finder/Tauri validation.

Comment on lines +138 to +140
<span className={styles.hint}>
{size} · {status}
</span>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

[P2] Announce upload progress and readiness without moving focus

The queued/preparing/uploading/ready text changes only inside this ordinary span; neither this component nor its enclosing composer provides live semantics for those transitions. Meanwhile MessageComposer.tsx:844-851 disables Send on attachments.blocked, and the Enter handler also silently returns while blocked (:460-471). For a screen-reader user who pastes a file and keeps focus in the editor, successful uploads provide no announcement explaining the wait or indicating when sending becomes available. Only failure is an alert.

Provide a polite, filename-qualified status announcement for preparation/upload and readiness, without making the whole attachment list noisy. Add a semantic regression that changes the attachment status while focus remains in the editor; the current tests cover visible status but not announcement semantics.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brain, an automated agent, replying on Wes's behalf.

Fixed in 2326c3e (now included in pushed head 2627b3b). Each file's status now has role=status, polite live semantics, atomic updates and screen-reader filename context; the attachment list itself is not live.

The semantic regression in src/features/messages/attachment-panes.test.tsx drives the real composer through held preparation/upload operations and Ready, verifies filename-qualified status, retained editor focus and Send gating. It passed again in the mandatory pre-push run at 2627b3b. Actual assistive-technology speech output was not exercised.

Brain added 4 commits September 23, 2026 17:16
Signed-off-by: Brain <1a02c72794dcd0f07058a353bc3a81f4028b8c77c92c87fce6d5c8b85970a20b@buzz.block.builderlab.xyz>
Signed-off-by: Brain <1a02c72794dcd0f07058a353bc3a81f4028b8c77c92c87fce6d5c8b85970a20b@buzz.block.builderlab.xyz>
Signed-off-by: Brain <1a02c72794dcd0f07058a353bc3a81f4028b8c77c92c87fce6d5c8b85970a20b@buzz.block.builderlab.xyz>
…ents

Signed-off-by: Brain <1a02c72794dcd0f07058a353bc3a81f4028b8c77c92c87fce6d5c8b85970a20b@buzz.block.builderlab.xyz>
@wesbillman
wesbillman merged commit fe897a1 into main Sep 24, 2026
12 checks passed
@wesbillman
wesbillman deleted the brain/composer-attachments branch September 24, 2026 00:13
zrmarley added a commit that referenced this pull request Sep 24, 2026
…o-player-polish

* origin/main: (38 commits)
  Fix diff content fallback, keyboard scrolling and edit selection (#205)
  Standardize form controls and field feedback across Buzz (#174)
  Keep image review downloads and external opens distinct (#144)
  Verify media review comments (#166)
  Follow system appearance (#210)
  Add rich composer formatting and spoiler rendering (#203)
  feat: show roster-backed channels and managed instances in profiles (#188)
  Add new direct message flow (#156)
  Remove Home, start in Messages, and keep Channels enabled (#194)
  fix: restore avatar presence controls and active-input sensing (#198)
  Add legacy diff messages with inline and expanded viewing (#202)
  Edit the latest own message with Up in the existing composer (#192)
  Add complete reaction toggles to the message menu (#185)
  feat: add persistent community navigation rail (#191)
  test: add margin to warm-switch performance gate (#195)
  Add composer attachments and compatible media preparation (#183)
  Add reply and copying to the shared message menu (#182)
  fix: avoid idle workspace re-renders from activity and label churn (#186)
  feat: add devtools trace capture to web profiling (#180)
  Add optional channel templates, teams and personal group defaults (#181)
  ...

Signed-off-by: Zach Marley <zmarley@squareup.com>
zrmarley added a commit that referenced this pull request Sep 24, 2026
…-content-compat

* origin/main: (38 commits)
  Fix diff content fallback, keyboard scrolling and edit selection (#205)
  Standardize form controls and field feedback across Buzz (#174)
  Keep image review downloads and external opens distinct (#144)
  Verify media review comments (#166)
  Follow system appearance (#210)
  Add rich composer formatting and spoiler rendering (#203)
  feat: show roster-backed channels and managed instances in profiles (#188)
  Add new direct message flow (#156)
  Remove Home, start in Messages, and keep Channels enabled (#194)
  fix: restore avatar presence controls and active-input sensing (#198)
  Add legacy diff messages with inline and expanded viewing (#202)
  Edit the latest own message with Up in the existing composer (#192)
  Add complete reaction toggles to the message menu (#185)
  feat: add persistent community navigation rail (#191)
  test: add margin to warm-switch performance gate (#195)
  Add composer attachments and compatible media preparation (#183)
  Add reply and copying to the shared message menu (#182)
  fix: avoid idle workspace re-renders from activity and label churn (#186)
  feat: add devtools trace capture to web profiling (#180)
  Add optional channel templates, teams and personal group defaults (#181)
  ...

Signed-off-by: Zach Marley <zmarley@squareup.com>

# Conflicts:
#	docs/channels.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant