Skip to content

feat(input): expose link destination in StyleState so apps can display link target - #9

Closed
hsource wants to merge 2 commits into
mainfrom
feat/link-destination-in-style-state
Closed

hsource wants to merge 2 commits into
mainfrom
feat/link-destination-in-style-state

Conversation

@hsource

@hsource hsource commented Sep 23, 2026 •

Copy link
Copy Markdown

Note: this PR has been manually reviewed and is a version of code that's been part of the Wanderlog (wanderlog.com) mobile apps for the past 3 weeks

What/Why?

Rich-text toolbars need the URL of the link at the caret, not only whether link formatting is active (for example, to prefill an "edit link" dialog). This adds destination to styleState.link in onChangeState and in the context-menu onPress event.

  • StyleState.link is now a discriminated union, { isActive: false } | { isActive: true; destination: string }, so TypeScript can narrow on isActive. Both platforms send { isActive, destination } with destination set to "" when there's no link, matching the codegen spec, and JS narrows it with a single ternary.
  • There is now one rule for "the link at the selection", shared by the style state, setLink, removeLink and the iOS link prompt, so they always agree: the link containing the first selected character, or, for a collapsed caret, the link the caret is inside or right after. Link ranges are half-open, and the caret often lands just past a link's last character after tapping it. Before, the toolbar could show a link as active at that position while removeLink found nothing. On Android, setLink now also updates an existing link's URL like iOS does, instead of requiring a selection. Backspace still deletes a link atomically based on the character before the caret.
  • iOS and Android both emit a new onChangeState event when only the destination changes, for example when moving the caret between two adjacent links.
  • The playground prints the latest onChangeState payload as JSON under the input, and a Maestro flow checks the link's destination in it.

Testing

Checks run: yarn typecheck, eslint, clang-format on the changed iOS files, ktlint, Android compileDebugKotlin, and example app builds for the iOS simulator (iPhone 17, iOS 26.4) and a Pixel 6a.

Test results for linkDestination

link_destination_test.yaml passes on both platforms: after creating a link and tapping into it, the style state reports the link as active with destination https://example.com. The recordings show the playground's style-state JSON under the input. The flow swipes the formatting toolbar first, because the link button is now off-screen at the end of it (the existing link_test.yaml on main has the same problem).

iOS Android

Manual testing for unified iOS logic

Here's some additional manual testing after the iOS link logic changes. I specifically tested:

  • Adding a link
  • Focusing start/end of link
  • Adding a link that covers same span as an existing link
Manual testing

PR Checklist

  • Code compiles and runs on iOS
  • Code compiles and runs on Android
  • Updated documentation/README if applicable
  • Ran example app to verify changes
  • E2E tests are passing
  • Required E2E tests have been added (if applicable)

@hsource
hsource force-pushed the feat/link-destination-in-style-state branch 3 times, most recently from 1a2dc79 to 8d6d19a Compare September 24, 2026 00:03
@hsource hsource changed the title feat(input): expose link destination in StyleState feat(input): expose link destination in StyleState so apps can display link target Sep 24, 2026
@hsource
hsource force-pushed the feat/link-destination-in-style-state branch from 8d6d19a to d5fedc9 Compare September 24, 2026 00:29
hsource and others added 2 commits September 23, 2026 17:48
onChangeState and context-menu styleState.link now include destination
when the caret is inside a manual link, including at the half-open range
end index where iOS often places the caret.

Co-authored-by: Cursor <cursoragent@cursor.com>
… flow

The playground prints the latest onChangeState payload as JSON, and the
flow checks that tapping into a link reports its destination.

Co-authored-by: Cursor <cursoragent@cursor.com>
@hsource
hsource force-pushed the feat/link-destination-in-style-state branch from d5fedc9 to a33aa49 Compare September 24, 2026 00:48
@hsource

hsource commented Sep 24, 2026

Copy link
Copy Markdown
Author

Moved upstream: software-mansion#883

@hsource hsource closed this Sep 24, 2026
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