Skip to content

feat(a11y): image alt text via NIP-92 imeta - #92

Open
dmnyc wants to merge 3 commits into
barrydeen:mainfrom
dmnyc:feat/alt-text-imeta
Open

dmnyc wants to merge 3 commits into
barrydeen:mainfrom
dmnyc:feat/alt-text-imeta

Conversation

@dmnyc

@dmnyc dmnyc commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Port of wisp-ios #472 — see that PR for functionality reference. Matches wisp #661.

Author-supplied image descriptions ride the event in the NIP-92 imeta alt slot, and every render surface displays and reads them back.

Read: MediaMeta.alt plus kind-agnostic imeta parsing extracted to a JVM-testable Imeta.kt; ALT badge opening a Description sheet on inline images, carousel tiles and gallery thumbs, always a sibling of the image's tap target so screen readers get two clean focus stops; fullscreen viewers get tap-to-toggle chrome with an alt caption.

Compose: +ALT / ✓ALT chips on gallery pages and attached images, with a 2000-char editor. Publish emits one imeta per described image; undescribed images emit no tag. Alt round-trips through NIP-37 drafts.

No AI component, matching iOS.

Second commit ports the iOS linebreak fix: multi-paragraph descriptions survive the round trip, while runaway break runs are capped on both publish and parse. Third commit is on-device composer polish — thumbnails gained a remove (X), moved under the attach row, and the chip label tightened.

Testing: 88 unit tests, 0 failures (ImetaTest 12, Nip68Test 5). Builds clean.

Port of wisp-ios #472 — see that PR for functionality reference.
Author-supplied image descriptions ride the event in the NIP-92 imeta
`alt` slot, and every render surface displays and reads them back.

Read: MediaMeta.alt plus kind-agnostic imeta parsing extracted to a
JVM-testable Imeta.kt; ALT badge opening a Description sheet on inline
images, carousel tiles and gallery thumbs, always a sibling of the
image's tap target so screen readers get two clean focus stops;
fullscreen viewers get tap-to-toggle chrome with an alt caption.

Compose: + ALT / checked ALT chips on gallery pages and attached images,
with a 2000-char editor. Publish emits one imeta per described image;
undescribed images emit no tag. Alt round-trips through NIP-37 drafts.

No AI component, matching iOS.
The alt editor is multiline and the imeta `alt` slot carries real
newlines inside its tag string, but normalization only trimmed the ends:
authored CRLF or 3+ break runs published as-is, and third-party alt with
runaway break runs rendered as-is.

normalizeAltBreaks ports the iOS reference: CRLF/CR to LF, each line
trimmed, runs of 3+ newlines capped at one paragraph gap, ends trimmed.
Applied when publishing (sanitizeAltText feeds every emission path, plus
the Nip68 builder and the NIP-37 draft tags) and when parsing, so
multi-paragraph descriptions survive the round trip while bloat can't
balloon the layout. Slot parsing still splits on the first space only, so
interior breaks belong to the value and reach every render surface.
On-device review of the alt-text composer:

- attachment thumbnails had no remove control; an (X) now calls
  removeMediaUrl, which drops the URL from the note text and forgets that
  image's description with it
- that button rendered far too large as an IconButton, which applies its
  own 40dp state-layer size after the caller's modifier; a plain sized Box
  gives the 20dp circle the layout actually asked for
- the strip sat above the text field, and below the live preview it got
  lost; it now sits directly under the attach row that produced it
- thumbnails 56dp to 88dp so both controls fit, and the row scrolls
  horizontally once several images are attached
- the chip reads "+ALT" / "✓ALT", no space
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