Fire @press on nested text runs - #52
Open
gwleuverink wants to merge 2 commits into
Open
Conversation
gwleuverink
force-pushed
the
fix/nested-text-press
branch
from
August 15, 2026 23:36
1aed0fe to
0a5f00d
Compare
gwleuverink
marked this pull request as ready for review
August 15, 2026 23:45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes NativePHP/mobile-air#339. A
<text @press>inside another<text>rendered fine but taps did nothing. A standalone<text @press>worked.The PHP side turned out to be innocent. The nested run crosses the wire with a live
on_presscallback id, and firing that callback from the test suite runs the handler. Press handling on native is attached per node view byNodeGestureModifier, and the text renderers never create views for their text children. They fold them into one attributed string, so theonPresssitting on the run node was never read. Same on both platforms.The fix uses each platform's inline link mechanism, which already hit-tests taps inside a wrapped paragraph, and calls the same
sendPressEventevery other renderer here calls. PHP receives an ordinary press. No core changes, no wire changes.On Android every span emitted under a pressable run gets its own
LinkAnnotation.Clickable, so annotation ranges stay flat instead of nesting when a pressable sits inside a pressable. I carry the run's own text decoration into the link styles, because withstyles = nullCompose underlined the range like a hyperlink.On iOS the innermost
@presstravels down throughRunContext, pressable runs get a custom schemerun.link, andcomposedBodyintercepts it with anOpenURLAction. Real URLs still fall through to the system. The run's explicitforegroundColorkeeps the authored color instead of the link tint.Both platforms resolve the press target the same way, down through the run context: a styled sub-run inside a pressable run stays tappable, and the innermost
@presswins. Long-press and the other gesture callbacks stay out of scope here, link annotations are tap-only primitives, and wiring those needs a different mechanism. Today they silently do nothing on runs, same as@pressdid before this.Verified with a counter screen on both:
Styling checked too: authored color and weight survive, no underline, no accent tint.
Press inside press is verified as well, on both platforms: a tap on the inner pressable fires only the inner handler, the outer one fires on its own words, innermost wins. On Android that was outer=2 inner=2 from exactly two taps on each region, on iOS the same by hand.
No automated test in here, and that's deliberate.
Native::test()passes on the broken build, it dispatches by callback id against the PHP tree and never touches a renderer, so it can't see this class of bug. A real regression test needs to drive the native side.Jump ships these renderers precompiled, so the fix reaches the reporter with the next Jump release, not with a composer update.