Skip to content

fix(ios): keep checkbox states after inline images - #820

Merged
hejsztynx merged 2 commits into
software-mansion:mainfrom
henrikra:fix/ios-checkbox-states-after-image
Oct 21, 2026
Merged

hejsztynx merged 2 commits into
software-mansion:mainfrom
henrikra:fix/ios-checkbox-states-after-image

Conversation

@henrikra

@henrikra henrikra commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #819.

On iOS, when HTML has an inline image (<img>) before checkbox lists, the checked state of every checkbox item after the image is applied to the wrong position. The first item of each list after the image loses its state, and the others shift onto the item before them. The editor then emits HTML from this wrong state, so the next edit saves the lost states.

Cause: in HtmlParser.mm, an opening <li> inside a checkbox list stored its state at checkboxStates[@(plainText.length)]. plainText doesn't contain image placeholders yet. But the <ul> tag range is shifted by the preceding image count in finalizeTagEntry: to match the final NSTextStorage, and prepareCheckboxListStyleValue: filters the states by that shifted range. InputHtmlParser and TextHtmlParser then apply each key as an absolute NSTextStorage position. With N preceding images, every key was N positions too low.

Fix: key the state by plainText.length + precedingImageCount, the same image-shifted space the tag ranges and alignments already use. Links compensate for the same offset in the other direction, since they read back from plainText.

Impact: iOS HTML parsing only (EnrichedTextInput and EnrichedText). Documents without images are unchanged, because precedingImageCount is 0.

Test Plan

  1. On iOS, render an EnrichedTextInput with this defaultValue (all five items checked):
    <html>
    <ul data-type="checkbox">
    <li checked>A</li>
    </ul>
    <p><img src="https://placehold.co/200x120.png" width="200" height="120"/></p>
    <ul data-type="checkbox">
    <li checked>B</li>
    </ul>
    <p>text</p>
    <ul data-type="checkbox">
    <li checked>C</li>
    </ul>
    <ul data-type="checkbox">
    <li checked>D</li>
    <li checked>E</li>
    </ul>
    </html>
  2. Before: A and D are checked; B, C and E are unchecked. After: A–E are all checked.
  3. Tap A's checkbox. Before: onChangeHtml keeps only D checked. After: A is unchecked and B–E keep checked.
  4. The same HTML without the image renders all five checked, both before and after.

I verified this on the iOS 18.6 simulator (iPhone 16 Pro) in our app (react-native 0.86.2, Expo 57, new architecture). I applied this exact change to 1.1.1 with patch-package, and checked the loaded states and the emitted HTML after a checkbox toggle and after a text edit.

Not covered here: adjacent <ul data-type="checkbox"> lists with nothing between them render as one list (C joins D/E). That happens without images too, so it is separate from this bug.

Screenshots / Videos

Before: A and D checked, B, C and E unchecked. After: A–E all checked. I can attach the simulator screenshots if useful.

Compatibility

OS Implemented
iOS ✅
Android ✅ (not affected)
Web ✅ (not affected)

Checklist

  • E2E tests are passing. I haven't run the Maestro suite locally.
  • Required E2E tests have been added (if applicable). Not added: the native flows are screenshot baselines, which I can't generate without your simulator setup. I'm happy to add a parsing flow with this HTML if you'd like one.

🤖 Generated with Claude Code

Checkbox states were keyed by their position in plainText, which has no
image placeholders, but filtered by list ranges shifted by the number of
preceding images. Every checkbox after an image lost or shifted its
checked state. Key the states by the image-shifted position instead.

Fixes software-mansion#819

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 17, 2026 02:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The localized correction matches existing position handling, leaves image-free documents unchanged, and has no identified blocking issues.

No open issues 🎉

What changed in this PR

Fixes #819 by preserving iOS checkbox states when inline images precede checkbox lists.

Changes:

  • Includes preceding image placeholders when calculating checkbox-state positions.
  • Documents why those positions must match image-shifted list ranges.
File Description
ios/​htmlParser/​HtmlParser.mm Corrects checkbox-state offsets and explains the coordinate adjustment.

Review effort: Balanced

@hejsztynx hejsztynx left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ran the e2e ios tests and all pass. Added one e2e regression test targeting that case. Looks good, works great - nice fix!

@hejsztynx
hejsztynx merged commit f35eb41 into software-mansion:main Oct 21, 2026
8 checks passed
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.

[iOS] Checkbox checked state lost/misplaced after an inline image

4 participants