mirror of
https://github.com/multica-ai/multica.git
synced 2026-08-05 17:40:11 +02:00
* feat(editor): page through an issue's / chat's images (MUL-5752)
Opening any image in an issue or a chat session now starts a sequence: the
viewer shows "3 / 7", chevrons and Left/Right walk to the neighbouring
images, and the ends disable rather than wrap.
Images only. PDFs, video, audio and text keep their single-file preview —
mixing kinds would mean defining load, keyboard and playback semantics for a
"next" that can land on a PDF page.
- packages/core/attachments/image-sequence.ts: the ordered sequence for a set
of {content, attachments} blocks, plus the image test, the URL to attachment
match and the standalone-attachment rule the renderers already applied
separately. Built from data, not the DOM, because both the issue timeline
and the chat list are virtualized. Shared with mobile.
- ImageSequenceProvider hosts one viewer per surface and freezes the sequence
on open, so arriving comments cannot shift the index under the reader. An
image the sequence does not know (a composer's in-flight upload) still
opens on its own.
- A frame that fails to load is skipped in the direction of travel with a
light toast, so a deleted attachment cannot trap the reader.
- Mobile keeps the semantics with its own interaction: the lightbox pages the
same sequence by horizontal swipe and shows the same counter.
The re-sign hook moves out of attachment.tsx into hooks/use-inline-media-url
so the modal can upgrade an auth-gated URL for an image the reader navigated
to rather than clicked — without it, paging broke on Desktop and on
proxy-mode self-hosts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
* fix(mobile): call the chat image-sequence memo unconditionally (MUL-5752)
`imageBlocks` sat below the loading and empty-state early returns, so the
useMemo only ran on renders that got past both — a rules-of-hooks violation
that mobile CI caught. Moved above both returns; an empty `messages` just
yields an empty block list.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
* fix(editor): flashless sequence navigation and preview header alignment
- Keep PreviewPanel mounted across navigation; swap the image only after
the next frame decodes (useSettledImageURL), and prefetch both
neighbours while the viewer is open
- Baseline-align filename/type in the header, keep ZoomControls mounted
(disabled until measured), move the position counter to a bottom pill
- Disabled boundary arrows keep receiving pointer events so the zoom
canvas grab cursor can't show over a dead control
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(editor): only keep zoom controls mounted for sequence previews
Standalone previews restore the original gate (hidden until measured,
hidden for content with no intrinsic size); the always-mounted variant
broke tests whose i18n mocks never expected the canvas strings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>