Per-file viewer LiveComponent: <Fresco.canvas> + <Etcher.layer> for
images, video / PDF / icon fallback for other types, plus a sidebar
with filename + Download + metadata + comments thread. Owns the
annotation lifecycle (composer popover, persistence sync via
EtcherAdapter, the patch-shape / delete-shape JS bridges).
Shared between MediaBrowser (admin file grid → click image → modal)
and MediaViewer (lightbox embedded by MediaGallery and other
consumers). Both parents own their own modal shell + prev/next
navigation; this component is just the per-file content.
Required assigns
:id— DOM id, must include the file uuid so the parent's prev/next navigation remounts the component on file change (and Fresco'sphx-update="ignore"canvas DOM is replaced wholesale with the new file's image).:file— curated file map (%{file_uuid, mime_type, urls, filename, file_type, size, inserted_at, ...}). Same shapeMediaBrowser'suploaded_filescarries.:current_user— logged-in user; nil-tolerant. When nil the composer + comments thread don't render (no user to attribute a comment to).:parent_id— DOM id of the outer LiveComponent (the modal host). Currently unused by this component, but kept on the assigns map so future cross-component send_updates have a target without re-plumbing the API.
Summary
Functions
Callback implementation for Phoenix.LiveComponent.render/1.
Functions
Callback implementation for Phoenix.LiveComponent.render/1.