Files
pad/internal
xarmian e179c595e4 feat(comments): paste/drop image attachments in comments + inline render (IDEA-1650) (#663)
* feat(comments): paste/drop image attachments in comments + inline render (IDEA-1650)

Comment composers were plain textareas with no upload path, and comment
bodies rendered markdown without an attachment resolver — so a
`pad-attachment:UUID` reference would never display. This wires both
halves end to end:

- Compose: paste or drop files into the comment composer (ItemTimeline)
  and the reply box (TimelineCommentCard). A shared helper
  (commentAttachments.ts) splices an "Uploading…" placeholder at the
  caret, uploads concurrently via the existing attachment API, and swaps
  each placeholder for its `pad-attachment:UUID` markdown ref (image
  syntax for image MIMEs, link/chip syntax otherwise — mirrors the
  editor's split). Submit is gated while uploads are in flight.
- Display: ItemTimeline lazily HEAD-probes each referenced UUID (reusing
  the editor's fetchAttachmentMetadata cache), builds a reactive
  resolver, and threads it into renderMarkdown for comments and replies
  so refs render as inline images / file chips.
- Orphan GC: comment uploads leave attachments.item_id NULL (like the
  editor), but the GC reference scan only checked items.content/fields.
  Renamed AttachmentReferencedInItems -> AttachmentReferenced and
  extended it to scan comments.body, so a screenshot referenced only
  from a comment isn't reclaimed after the grace period. Added
  TestOrphanGC_KeepsAttachmentReferencedFromComment.

Follow-up refinement (thumbnails + click-to-expand lightbox) captured as
IDEA-1660.

* fix(comments): escape markdown-significant chars in attachment filenames per Codex review (round 1)

Filenames containing [ ] or backslash could break the generated
![name](pad-attachment:...) markdown. P2 (grant-aware upload auth) is a
pre-existing endpoint-wide gap shared with the rich editor — tracked as
BUG-1661, not fixed here to keep the PR focused.

* fix(comments): preventDefault on dragover for file drops per Codex review (round 2)

Browsers only deliver a file drop to a custom target if its dragover
cancels the default; without it the page navigates to the file. Gated
on isFileDrag so in-textarea text drag-drop is unaffected.
2026-05-30 10:57:31 -04:00
..
2026-03-26 01:52:36 +00:00