feat(uploads): redesign file-attachment composer UI (LC-500) #463

Merged
longjacksonle merged 4 commits from feat/LC-500-file-composer-ui into main 2026-06-27 21:22:38 +02:00

What

Bring the file-upload/attachment composer UI up to the quality of the redesigned voice composer (LC-499). Frontend + a small backend thread; no new routes/data.

Changes

  • Bounded attachment chip (replaces the bare "Attached: name (size) x" strip): image thumbnail or a file-type icon, truncated name + human size, and a labeled Remove (trash), matching the .lc-recpreview voice card.
  • Per-type previews: images get a rounded thumbnail; non-image (server allowlist is images + PDF) gets a document icon - no broken thumbnail. Names truncate and are HTML-escaped.
  • Validation + feedback (point 5): client-side pre-validation mirroring the server (type allowlist + size vs the configured cap, shown as "X MB over the Y MB limit") with inline errors; upload-in-progress spinner overlay that disables Send (via the existing __lcUploadBusy); upload error with a Retry that re-sends the same file. max_upload_bytes is threaded to the composer (shared db::settings::max_upload_bytes) so the client check matches the operator's cap.
  • Timeline (point 7): non-image attachments now render as a clean download card (icon + truncated name + human size) instead of a plain bordered link; images keep the inline thumbnail + lightbox. New Attachment::human_size.

Flags (not built)

  • Drag-and-drop + paste-to-attach already existed (document-level drop overlay + textarea paste). Point 6 needed no work.
  • Multiple attachments (point 4): not cheap - the message form carries a single file_id and a message maps to one upload; multi-attach needs a schema/handler change. Left as a separate larger task.

Tests

just check, just test, just test-saas all green (ran check last). Allowed types confirmed against uploads::allowed_ext_for_mime (JPEG/PNG/GIF/WebP/PDF). Frontend behavior (the composer JS) can't be exercised headlessly here (SSO-only login), so it was verified by build/check/tests + code review against the voice-composer quality bar.

Verify

just verify builds the release binary clean; boot fails only on the missing SSO env (environmental, as in prior PRs).

## What Bring the file-upload/attachment composer UI up to the quality of the redesigned voice composer (LC-499). Frontend + a small backend thread; no new routes/data. ## Changes - **Bounded attachment chip** (replaces the bare "Attached: name (size) x" strip): image thumbnail or a file-type icon, truncated name + human size, and a labeled **Remove** (trash), matching the `.lc-recpreview` voice card. - **Per-type previews**: images get a rounded thumbnail; non-image (server allowlist is images + PDF) gets a document icon - no broken thumbnail. Names truncate and are HTML-escaped. - **Validation + feedback (point 5)**: client-side pre-validation mirroring the server (type allowlist + size vs the configured cap, shown as "X MB over the Y MB limit") with inline errors; upload-in-progress spinner overlay that disables Send (via the existing `__lcUploadBusy`); upload error with a **Retry** that re-sends the same file. `max_upload_bytes` is threaded to the composer (shared `db::settings::max_upload_bytes`) so the client check matches the operator's cap. - **Timeline (point 7)**: non-image attachments now render as a clean download card (icon + truncated name + human size) instead of a plain bordered link; images keep the inline thumbnail + lightbox. New `Attachment::human_size`. ## Flags (not built) - **Drag-and-drop + paste-to-attach already existed** (document-level drop overlay + textarea paste). Point 6 needed no work. - **Multiple attachments (point 4): not cheap** - the message form carries a single `file_id` and a message maps to one upload; multi-attach needs a schema/handler change. Left as a separate larger task. ## Tests `just check`, `just test`, `just test-saas` all green (ran check last). Allowed types confirmed against `uploads::allowed_ext_for_mime` (JPEG/PNG/GIF/WebP/PDF). Frontend behavior (the composer JS) can't be exercised headlessly here (SSO-only login), so it was verified by build/check/tests + code review against the voice-composer quality bar. ## Verify `just verify` builds the release binary clean; boot fails only on the missing SSO env (environmental, as in prior PRs).
Add a shared db::settings::max_upload_bytes helper and surface the configured cap to RoomPage / DmPage / ComposerFragment, so the composer's client-side validation matches the server-enforced limit instead of guessing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the bare "Attached: name (size) x" strip with a bounded attachment card matching the voice preview: image thumbnail or file-type icon, truncated name + human size, and a labeled Remove (trash). Add client-side pre-validation (size vs the configured cap, type allowlist mirroring the server) with inline errors, an upload-in-progress spinner that disables Send via __lcUploadBusy, and a styled upload error with Retry that re-sends the same file. Filenames are HTML-escaped. New js i18n strings (en + es).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Upgrade the timeline generic-file attachment from a plain bordered link to a clean download card (type icon + truncated name + human size), consistent with the composer chip. Add Attachment::human_size. Image attachments (inline thumbnail + lightbox) are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
style(uploads): attachment chip + timeline file-card CSS (LC-500)
Some checks failed
check-secrets / Kingfisher (pull_request) Failing after 4s
check-secrets / TruffleHog (push) Failing after 2m14s
check-secrets / TruffleHog (pull_request) Successful in 2m17s
Create release / Create release from merged PR (pull_request) Has been skipped
check-secrets / Nosey parker (pull_request) Failing after 2m17s
Check / clippy + fmt + tests (pull_request) Successful in 3m9s
check-secrets / Kingfisher (push) Failing after 4m29s
check-secrets / Nosey parker (push) Successful in 4m31s
0f6eac309a
Token-driven (light/dark) styles for the composer attachment chip (thumbnail/icon, truncating name, upload spinner overlay) and the timeline download card.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-06-27 21:20:51 +02:00
longjacksonle deleted branch feat/LC-500-file-composer-ui 2026-06-27 21:22:38 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!463
No description provided.