Skip to content

fix: dispatch image presses from iOS table cells - #959

Merged
hryhoriiK97 merged 4 commits into
software-mansion:mainfrom
pingdotgg:fix/ios-table-image-press
Oct 10, 2026
Merged

hryhoriiK97 merged 4 commits into
software-mansion:mainfrom
pingdotgg:fix/ios-table-image-press

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

What/Why?

Tapping an unlinked image in an iOS GFM table does not invoke the existing onImagePress callback. Preserve image URL/alt attributes, hit-test actual glyph bounds and forward presses through root and nested blockquote tables. Linked images retain link priority; cell padding does not activate an adjacent image.

Fixes #952. The callback lets the application open its existing viewer; this PR does not add a viewer or a media API.

Testing

  • Four registered XCTest cases executed successfully, with zero failures or skips: original URL/alt, callback dispatch, linked-image priority and padding exclusion.
  • The added iOS Maestro flow passed bare-table and nested-blockquote image callbacks, original URL/alt values and linked-image routing. The Playground uses an alert so each callback is observable.
  • Library types, Bob/module/codegen, targeted lint and normal hooks passed. Android behavior is unchanged.

Same controlled table fixture and viewport, upstream base before and PR production sources after:

Before:

Before: tapping the table image does not invoke the callback

After:

After: tapping the table image invokes the image callback with its original URL and alt text

Before interaction:

Before: table-image tap produces no image alert

After interaction:

After: table-image tap opens the example image callback alert

The captures use a local public example asset; Maestro separately uses a public image URL and verifies nested tables. Local native proof uses an isolated upstream example checkout on an iPhone 17 Pro simulator running iOS 27. Xcode used two jobs, disabled signing/index/debug symbols, and task-owned XCFrameworks retained the arm64 simulator slice to fit the host. These are host resource settings, not workflow or production changes. No Android device, VoiceOver traversal, or full Maestro-suite pass is claimed.

Base: b80be973. Current head: ae431a2d. CI is incomplete. The current Android unit-test job failed before tests while installing NDK 27.1.12297006: the downloaded archive was not a ZIP. The production Android build passed on this head. A retry needs upstream Actions write access, which this account does not have. iOS jobs remain queued.

PR Checklist

  • Code compiles and runs on iOS
  • Code compiles and runs on Android, unchanged and not run on a device
  • Updated documentation/README if applicable, existing public callback
  • Ran example app to verify changes
  • Added focused iOS E2E test is passing, full suite not run
  • Required E2E tests have been added

Model: GPT-6.1. Harness: Codex in T3 Code.

@juliusmarminge
juliusmarminge marked this pull request as ready for review October 8, 2026 18:49
- resolve the tapped grid item once and dispatch on its kind; links keep
  nearest-glyph hits, only images require the tap inside their bounds
- expose imageAtPoint: next to linkAtPoint: and test through public API
- fire onImagePress for images in blockquote paragraphs, not only tables
- wrap the image callback with weak self like the link callbacks
- drop the "not fired inside GFM tables" note from the docs
- dedupe the Maestro flow into a subflow; "Preview" headers keep the
  "Image" alert title unambiguous

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hryhoriiK97

Copy link
Copy Markdown
Collaborator

Thanks! The core fix is right: the image attributes were already registered by the render context, the table cell renderer just never applied them. I pushed a follow-up commit (1865ffa) with a few adjustments:

  • Quoted paragraph images. The blockquote's own tap handler only resolved links, so > ![img](url) stayed silent while > | ![img] | now fired. It falls through to imageAtTapLocation like the root does.
  • Link hit testing unchanged. The glyph-bounds check also applied to links, which changed how taps past the end of a short link resolve. Links keep nearest-glyph behaviour; only images require the tap inside their bounds. The grid now resolves the tapped item once and dispatches on its kind.
  • imageAtPoint: is public next to linkAtPoint:, so the tests go through public API instead of a category over private methods and a gesture stub.
  • Callback wiring uses the weak-self wrapper in the blockquote registry, matching the link callbacks.
  • Docs no longer say the callback is skipped inside GFM tables (API reference, docs-md, known-limitations).
  • Maestro: one parameterised subflow for the three cases, table headers renamed to "Preview" so the "Image" alert title is unambiguous, redundant platform wrapper removed.

Verified locally: build and XCTest suite pass on an iPhone 17 simulator (iOS 26.5), and taps on root, nested-quote, linked and quoted-paragraph images behave as expected in the example app.

Heads-up: this and #958 both add entries to the example project.pbxproj at the same spots, so whichever lands second will need a rebase.

Keep the PR to the library fix and docs: remove the XCTest cases, the
Maestro flow, the Playground alert they drove, and the test-only
imageAtPoint: accessor.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hryhoriiK97
hryhoriiK97 merged commit 2e9a838 into software-mansion:main Oct 10, 2026
20 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 table images do not emit onImagePress, including inside quotes

2 participants