Context for phoenix_kit_annotations — drawn-on-image shapes created
via the Etcher overlay layer in the MediaBrowser modal.
Most callers won't use this directly — they go through
PhoenixKit.Modules.Storage.EtcherAdapter which implements the
Etcher.Storage behaviour and dispatches to this context. The module
is exposed so admin tooling, audits, or background workers can do
CRUD without reaching for the adapter.
Summary
Functions
Create an annotation for a file.
Delete an annotation by UUID.
Fetch a single annotation by UUID, or nil.
List annotations for a file, ordered by position then insertion time.
List annotations for a file together with a tooltip-friendly preview of their comment thread. Each element is a map
Update an annotation's geometry / style / metadata / position.
Types
Functions
@spec create(attrs()) :: {:ok, PhoenixKit.Annotations.Annotation.t()} | {:error, Ecto.Changeset.t()}
Create an annotation for a file.
attrs accepts both atom- and string-keyed maps (the latter is what
flows in from LiveView events). Keys: :file_uuid, :kind,
:geometry, optional :creator_uuid, :style, :metadata,
:position.
@spec delete(uuid()) :: :ok | {:error, :not_found | Ecto.Changeset.t()}
Delete an annotation by UUID.
Cascades to any linked comments — i.e. comments on the annotation's
file that carry metadata.annotation_uuid pointing at this row. The
cascade is a hard delete: annotation comments are conceptually owned
by their annotation, so they go with it instead of lingering as
[removed] placeholders in the file's thread. phoenix_kit_comment_media
rows fall away via their ON DELETE CASCADE; the underlying media
files (referenced via comment_media.file_uuid) stay untouched —
they're library assets, not comment-owned. No-ops cleanly when
PhoenixKitComments isn't installed.
@spec get(uuid()) :: PhoenixKit.Annotations.Annotation.t() | nil
Fetch a single annotation by UUID, or nil.
@spec list_for_file(uuid()) :: [PhoenixKit.Annotations.Annotation.t()]
List annotations for a file, ordered by position then insertion time.
List annotations for a file together with a tooltip-friendly preview of their comment thread. Each element is a map:
%{
annotation: %Annotation{},
first_comment: %{content, author, thumbnail_url} | nil,
comment_count: integer()
}Annotation comments are stored against the file (resource_type: "file",
resource_uuid: file_uuid) with metadata.annotation_uuid pointing at
the annotation, so they show up in the file's main comments thread
alongside non-annotated discussion. This loader pulls every file
comment in one query and groups by that metadata key.
If the comments package isn't installed, returns the same shape with
first_comment: nil and comment_count: 0 so callers always handle
one schema.
@spec update(uuid(), attrs()) :: {:ok, PhoenixKit.Annotations.Annotation.t()} | {:error, :not_found | Ecto.Changeset.t()}
Update an annotation's geometry / style / metadata / position.