Skip to content

feat(attachments): drag/drop sort ordering for post media & files (create + edit) - #306

Merged
lopugit merged 3 commits into
developfrom
claude/media-files-sort-drag-drop-1f75a0
Aug 18, 2026
Merged

feat(attachments): drag/drop sort ordering for post media & files (create + edit)#306
lopugit merged 3 commits into
developfrom
claude/media-files-sort-drag-drop-1f75a0

Conversation

@lopugit

@lopugit lopugit commented Aug 18, 2026

Copy link
Copy Markdown
Owner

What

Adds sort/ordering drag & drop to the post composer's Media & Files panel — when creating posts/comments (and Messenger messages) and when editing posts — as requested. Every tile and file row with 2+ items in its section gets a ⠿ grip: drag it (pointer events, so mouse AND touch work), or focus it and use Arrow keys / Home / End. The hovered drop position shows an accent outline; the move commits on release.

How order persists (end-to-end)

  • Create: the composer's upload order (as reordered) IS the attachmentIds order sent to the server. The bind hook now stamps attachmentSortIndex on each bound attachment thing per its list position (order lives on the relational child docs, per FUNDAMENTALS §3 — the post never stores an id list).
  • Edit: the edit composer previously rendered a dead-end upload panel (uploads there were silently dropped — things.update never bound them) and hid existing attachments entirely. It now shows the post's existing attachments as a reorderable gallery instead; Save sends the ordered ids only when the order changed.
  • Server: PATCH /api/v1/things { id, attachmentIds } re-stamps a bound set. It must be a pure permutation of the currently bound ids (verified against live state; additions/removals 409). Same gates as attachment creation: full user session, same-origin, JSON. Runs before updateThing so the response projection already carries the new order; idempotent, so a failed crystal write + retry converges (observed live — see Verification).
  • Read: resolvePostAttachments (posts/comments) and Messenger's message-attachment resolve sort stamped docs by attachmentSortIndex, with legacy unstamped docs keeping their createdAt order after stamped ones.

Follow-up fixes surfaced by the preview E2E

  • c5ef265: attachment-only posts had a dead Save in edit mode — contentValid now counts the post's existing bound attachments (the upload snapshot is empty in edit mode).
  • bbab057: updateThing validated post crystals without the postAttachments context creates get, so every edit of an attachment-only post 400'd with the say-something rule. It now resolves live bound-attachment presence (server-authored state, as trusted as create-time inspection); covers PUT via upsertThing's delegation.

Notes

  • MediaGalleryTile grew optional dragging/dropTarget/containerProps; the shared gesture logic is one hook (useMediaReorder) used by both the upload composer and the new edit gallery. Grips keep React.memo effective (stable callbacks + primitives).
  • Reordering is per-section (media grid / file list), matching how PostAttachments renders them grouped; cross-section drags are inert.
  • matchesCommittedPostCreate + addComment reconciliation compare attachment sets unordered, so ambiguous-create recovery is unaffected.
  • Custom emoji picker (maxFiles=1) shows no grips; profile avatar/banner slots untouched. Adding/removing attachments during edit stays out of scope (binding is create-only today); the gallery says so honestly.

Verification

  • npm run test:unit passes (106 attachment-family tests incl. new orderAttachmentDocsByStoredSort, planAttachmentReorder, PATCH-reorder postAttachmentRequest cases); lint:files clean; Web CI + API suite green.
  • Local dev (real mouse + keyboard): grip drags both directions, ArrowLeft/Right + Home/End with focus following the moved tile, file-row drag with drop outline, cross-section drags inert, desktop + 375px mobile with no horizontal overflow.
  • Vercel preview E2E (real S3 + DB, throwaway account dragdrop-e2e-0818, private post): uploaded 3 images + 2 files, dragged to [bravo, charlie, alpha] + [doc-two, doc-one], posted → order persisted after full reload. Edited: gallery rendered saved order, dragged to [charlie, alpha, bravo] + [doc-two, doc-one], Save → 'Post updated', card + reload + /post/:id permalink all render the new order. The intermediate failed-save attempt also proved the reorder-first PATCH semantics: order stamped, crystal 400 surfaced, retry converged.
  • TESTING.md gained two permanent checklist items covering both flows.

🤖 Generated with Claude Code

Media & Files tiles and file rows in the post/comment/message composer
now carry a grip handle: drag (pointer events - mouse and touch), or
use arrow keys / Home / End on the focused grip, to set the order.
Editing a post swaps the dead-end upload panel for a reorderable
gallery of the post's existing attachments.

Order persists end-to-end: binds stamp attachmentSortIndex per doc in
client list order, PATCH /api/v1/things { id, attachmentIds } re-stamps
a bound set as a pure permutation (same-origin full-session only), and
the post + messenger read paths sort stamped docs first with legacy
docs keeping createdAt order.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
thingtime Ready Ready Preview Aug 18, 2026 7:53am
thingtime (develop) Ready Ready Preview Aug 18, 2026 7:53am

Request Review

@github-actions
github-actions Bot temporarily deployed to develop-pr-306 August 18, 2026 06:20 Destroyed
@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

🧹 Develop S3 preview removed

The PR-specific alias and every workflow-created develop deployment were removed when this PR closed.

The ordinary generated Vercel Preview remains available on the shared development runtime.

The edit composer replaced the upload panel with the reorder gallery,
so contentValid must count the post's existing bound attachments - an
attachment-only post's Save was dead, making its reorder unsaveable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ator

updateThing validated post crystals without the postAttachments context
creates get from route inspection, so every edit of an attachment-only
post failed with the say-something rule. Bound ready attachments are
server-authored state; resolving their presence at update time is as
trusted as the create-time inspection. Covers PUT too via upsertThing's
delegation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to develop-pr-306 August 18, 2026 07:51 Destroyed
@github-actions
github-actions Bot temporarily deployed to develop-pr-306 August 18, 2026 08:28 Destroyed
@lopugit
lopugit merged commit 08f2e9a into develop Aug 18, 2026
26 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Promoted to main in #311.

An earlier run stood aside on this PR; that verdict no longer applies.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Promotion #311 has verified source lineage at current develop tip 08f2e9aec28437b3e44995abe3119cc389958bf8.

@lopugit

lopugit commented Aug 18, 2026

Copy link
Copy Markdown
Owner Author

🚀 Promotion PR for main opened: #311

@github-actions github-actions Bot mentioned this pull request Aug 18, 2026
lopugit added a commit that referenced this pull request Aug 18, 2026
… branch

Union resolutions keep both the protected moderation stamp and #306's
attachmentSortIndex on the attachment doc type and in the feed/messenger
aggregation projections. attachments 111/111, moderation 10/10, full nitro
build green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lopugit added a commit that referenced this pull request Aug 18, 2026
…g/drop sort ordering for post media & files (create + edit) (#306)
lopugit added a commit that referenced this pull request Aug 18, 2026
lopugit added a commit that referenced this pull request Aug 18, 2026
…g/drop sort ordering for post media & files (create + edit) (#306)
lopugit added a commit that referenced this pull request Aug 18, 2026
github-actions Bot added a commit that referenced this pull request Aug 18, 2026
…g/drop sort ordering for post media & files (create + edit) (#306)
github-actions Bot added a commit that referenced this pull request Aug 18, 2026
github-actions Bot added a commit that referenced this pull request Aug 19, 2026
…g/drop sort ordering for post media & files (create + edit) (#306)
github-actions Bot added a commit that referenced this pull request Aug 19, 2026
github-actions Bot added a commit that referenced this pull request Aug 21, 2026
…g/drop sort ordering for post media & files (create + edit) (#306)
github-actions Bot added a commit that referenced this pull request Aug 21, 2026
github-actions Bot added a commit that referenced this pull request Aug 21, 2026
…g/drop sort ordering for post media & files (create + edit) (#306)
github-actions Bot added a commit that referenced this pull request Aug 21, 2026
github-actions Bot added a commit that referenced this pull request Aug 21, 2026
…g/drop sort ordering for post media & files (create + edit) (#306)
github-actions Bot added a commit that referenced this pull request Aug 21, 2026
lopugit added a commit that referenced this pull request Aug 21, 2026
feat(media): masonry gallery, lightbox, media Thing pages + title/description (stacked on #306)
lopugit added a commit that referenced this pull request Aug 21, 2026
…drag-drop-1f75a0--to-main

[Promote][attachments #1] feat(attachments): drag/drop sort ordering for post media & files (create + edit) (#306)
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