Bulk media drop renders as one gallery (client-side grouping, standard events) #137

Closed
opened 2026-09-17 16:26:17 -04:00 by jared · 1 comment
Owner

Jared: "could be really useful if implemented with care and done properly."

The careful way

Matrix has no merged spec for multi-file events (the multi-attachment MSCs are unmerged), so sending one custom event would break every other client. Instead keep sending one standard m.image/m.video per file and do the grouping at render time: consecutive media events from the same sender within ~60 s and with no text in between render as one grid tile ("gallery") in Lotus; Element and others still see N normal images. Nothing on the wire changes.

Scope

  • Grouping rule (pure, unit-tested): same sender, media msgtypes only, contiguous, ≤ 60 s apart, cap at 10 per group; a reply/thread/edit relation breaks the group.
  • Render: 2–4 column grid with the existing image sizing/blurhash/click-to-view; the viewer swipes/arrows through the group; captions show under each item on open; read receipts/reactions attach to the last event of the group with the others still individually reachable (hover → "open as separate messages"? — decide).
  • Sending: the upload board already sends in order; add a "send as gallery" hint only if ordering/timing needs tightening (send sequentially so the 60 s rule holds).
  • Verify with 5 screenshots dropped at once on desktop and phone before/after.
Jared: "could be really useful if implemented with care and done properly." ### The careful way Matrix has no merged spec for multi-file events (the multi-attachment MSCs are unmerged), so sending one custom event would break every other client. Instead keep sending **one standard `m.image`/`m.video` per file** and do the grouping **at render time**: consecutive media events from the same sender within ~60 s and with no text in between render as one grid tile ("gallery") in Lotus; Element and others still see N normal images. Nothing on the wire changes. ### Scope - Grouping rule (pure, unit-tested): same sender, media msgtypes only, contiguous, ≤ 60 s apart, cap at 10 per group; a reply/thread/edit relation breaks the group. - Render: 2–4 column grid with the existing image sizing/blurhash/click-to-view; the viewer swipes/arrows through the group; captions show under each item on open; read receipts/reactions attach to the *last* event of the group with the others still individually reachable (hover → "open as separate messages"? — decide). - Sending: the upload board already sends in order; add a "send as gallery" hint only if ordering/timing needs tightening (send sequentially so the 60 s rule holds). - Verify with 5 screenshots dropped at once on desktop and phone before/after.
jared added this to the Features 2026-Q4 milestone 2026-09-17 16:26:17 -04:00
jared added the enhancementpriority: mediumuxarea: media labels 2026-09-17 16:26:17 -04:00
jared self-assigned this 2026-09-17 16:26:17 -04:00
Author
Owner

Done in bd8c79e0 — render-time grouping only; nothing changes on the wire (verified: the events are plain m.image per file, the recipient's other clients would see 5 images).

Rule (utils/mediaGroups.ts, 9 unit tests): same sender · m.image/m.video with a thumbnail · contiguous (reactions/edits/redactions in between are ignored, anything else breaks) · ≤ 60 s between consecutive members · no reply/thread/edit relation · not redacted · cap 10. A member with reactions or a thread closes its group so they stay visible under the rendered event. Runs of one render as today.

Render: the group renders once at its last event (so read receipts land where people actually read up to) as a 2–4 column grid of square thumbs (blurhash placeholder, play badge for video, "tap to load" when media auto-load is off). Tapping a tile opens the lightbox on that group in send order (←/→, zoom, download, jump to message). Footer: "5 photos · Show separately" → splits for the session; the last image then carries "Show as gallery" to regroup. Reply/forward/pin on the gallery act on the last event.

Sending: the upload board already queues sendMessage in order via the SDK scheduler, so no "send as gallery" hint was needed — 5 files dropped at once arrived within ~2 s.

Verified headless

  • desktop + phone: 5 images → members rendered 00001, one grid "5 photos", 5 cells
  • lightbox from tile 3: 3 / 5, → 4 / 5, ←← 2 / 5
  • Show separately → 11111 + regroup chip; Show as gallery → 00001
  • 👍 on photo 3 → grids [1–3] (with the reaction under it) and [4–5]
  • E2EE room, real UI drop of 5 files: sender and recipient both get one 5-tile grid with decrypted thumbnails

desktop
split by reaction, phone
e2ee recipient
lightbox

Done in bd8c79e0 — render-time grouping only; nothing changes on the wire (verified: the events are plain `m.image` per file, the recipient's *other* clients would see 5 images). **Rule** (`utils/mediaGroups.ts`, 9 unit tests): same sender · `m.image`/`m.video` with a thumbnail · contiguous (reactions/edits/redactions in between are ignored, anything else breaks) · ≤ 60 s between consecutive members · no reply/thread/edit relation · not redacted · cap 10. A member with reactions or a thread closes its group so they stay visible under the rendered event. Runs of one render as today. **Render:** the group renders once at its *last* event (so read receipts land where people actually read up to) as a 2–4 column grid of square thumbs (blurhash placeholder, play badge for video, "tap to load" when media auto-load is off). Tapping a tile opens the lightbox on *that group in send order* (←/→, zoom, download, jump to message). Footer: "5 photos · Show separately" → splits for the session; the last image then carries "Show as gallery" to regroup. Reply/forward/pin on the gallery act on the last event. **Sending:** the upload board already queues `sendMessage` in order via the SDK scheduler, so no "send as gallery" hint was needed — 5 files dropped at once arrived within ~2 s. **Verified headless** - desktop + phone: 5 images → members rendered `00001`, one grid "5 photos", 5 cells - lightbox from tile 3: `3 / 5`, → `4 / 5`, ←← `2 / 5` - Show separately → `11111` + regroup chip; Show as gallery → `00001` - 👍 on photo 3 → grids [1–3] (with the reaction under it) and [4–5] - **E2EE room, real UI drop of 5 files**: sender and recipient both get one 5-tile grid with decrypted thumbnails ![desktop](https://code.lotusguild.org/attachments/90519e4b-ad2a-4698-af3d-28c5abb6aca9) ![split by reaction, phone](https://code.lotusguild.org/attachments/49022c5b-cc18-40af-939a-6dba6f19e3fc) ![e2ee recipient](https://code.lotusguild.org/attachments/be0ff9f2-7844-43c5-ae73-f9ff09c497fd) ![lightbox](https://code.lotusguild.org/attachments/ce9cfd93-2640-432e-818e-fa2148008861)
jared closed this issue 2026-09-20 00:48:36 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#137