Skip to content

feat(ocr): entity chips under the recognized text - #150

Merged
johnny4young merged 2 commits into
mainfrom
feat/ocr-entity-chips
Sep 17, 2026
Merged

johnny4young merged 2 commits into
mainfrom
feat/ocr-entity-chips

Conversation

@johnny4young

Copy link
Copy Markdown
Owner

What

Entity chips under the text recognized from an image, in the panel's peek (follow-up to #140).

  • Open for each http(s) link found in the text (up to three), Send email for addresses, and Translate when the text is in another language and an on-device engine can run now (an installed native pair or the language model). The translation renders beside the original with Copy and Paste.
  • No chip for a recognized secret; only http, https and mailto ever open, re-checked at the call site.
  • Chips wrap instead of truncating; 11 pt medium labels.

How it was verified

  • make lint: 0 violations. make test: 1,143 tests in 170 suites.
  • Mutation: admitting file: and javascript: schemes fails unsafeSchemesAreDropped.
  • ManualOCRUITests (3 tests) green locally; the link chip is asserted by host and clicking it never leaves the app under the paste sink. Hosted UI run dispatched on this head.
  • macOS and iOS builds succeed.

Out of scope

iOS parity, and chips for phone numbers or dates (copying the line covers them).

Recognized image text now shows what it can do. Under the lines, a chip
row offers:

- Open <host> for each http(s) link found anywhere in the text (bare
  domains the detector recognizes get their scheme), up to three;
- Send email for mailto: addresses;
- Translate when the text reads in a language other than the interface
  language AND an on-device engine can run now — an installed native pair
  or the language model. The translation renders beside the original, at
  the same body size, with Copy and Paste.

Chips never appear for a recognized secret: a flagged text is not sent
anywhere, not even to the on-device model. Only http, https and mailto
ever open, re-checked at the call site because OCR output is untrusted.
Chips wrap into rows instead of truncating, at 11 pt medium — the macOS
floor for an interactive label, one step above the metadata around them.

Tests: the detector (dedup, cap, unsafe schemes, mailto with a query),
the translation offer with injected engines, and the OCR UI test asserts
the link chip by host and that clicking it never leaves the app. The UI
fixture gains a link line.
…ow layout

Review of the entity chips found ten defects; this lands the fixes.

- Copy translation and Paste translation now go through the same
  revalidation as every other copy from the section (private mode,
  deletion, expiry), and Translate itself revalidates before the text
  reaches the model. Copy translation confirms with the section's
  "Copied to clipboard" status.
- The translation lifecycle is one enum (none, offered, running, done,
  failed): a finished translation keeps its target and survives an
  offer refresh; the task is keyed to the request and cancelled on a
  new request or when the section disappears, so a stale result can
  neither re-enable the chip nor land.
- The translation block is capped like the peek's other long outputs
  (scrolling, 140 pt), so it never pushes the action list off the panel.
- The email chip shows its address; two recipients can no longer read as
  the same chip, to the eye or to VoiceOver.
- One FlowLayout in GanchoDesign replaces the private copies in both
  Intelligence screens and the chip-only ChipFlow. It measures and
  places against the same row width and offers each subview the row
  width, so a long host wraps inside its chip instead of running past
  the panel edge as a trusted-looking prefix.
- The Translate offer asks SmartPasteService.route, the same decision on
  the same sanitized, clipped text translate sends, instead of re-deriving
  the routing matrix on the raw text.
- openRecognizedEntity takes an ImageTextEntity: the detector is the one
  allowlist, and a launch the system refuses shows a toast.
- LanguageName in GanchoDesign replaces three private copies of the
  language-name lookup. The paste-sink flag's doc names its side effects.
- Tests: the offer is asserted to read the sanitized text; the UI test
  counts link chips instead of probing a fixed index.
@johnny4young
johnny4young merged commit 107ccdc into main Sep 17, 2026
5 of 6 checks passed
@johnny4young
johnny4young deleted the feat/ocr-entity-chips branch September 17, 2026 00:05
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