Skip to content

feat: text layer — search, selection, copy control (1.5.0-beta.13) - #362

Open
endigo wants to merge 3 commits into
migrate/kotlin-swiftfrom
feat/text-layer
Open

feat: text layer — search, selection, copy control (1.5.0-beta.13)#362
endigo wants to merge 3 commits into
migrate/kotlin-swiftfrom
feat/text-layer

Conversation

@endigo

@endigo endigo commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary

Adds the text layer on top of the federated 1.5.0 stack (migrate/kotlin-swift / #345):

  • Find-in-document (#137)
  • Text selection (#285)
  • Control over copy (#108)

Versions (not published yet — publish interface first):

  • flutter_pdfview_platform_interface 1.1.0
  • flutter_pdfview 1.5.0-beta.13
dependencies:
  flutter_pdfview: 1.5.0-beta.13

API

Controller

  • isTextLayerSupported()
  • searchText(query, {caseSensitive})List<PdfTextMatch>
  • nextMatch / previousMatch / setCurrentMatch / clearSearch
  • getSelectedText / clearSelection

Widget

  • enableTextSelection / enableCopy (default true, live update without remount)
  • onTextSelectionChanged / onSearchResultChanged

Platform support

Capability iOS (PDFKit) Android
Search + highlights ❌ throws UnsupportedError
Selection
Suppress copy menu
isTextLayerSupported true false

Android has no text layer today: AndroidPdfViewer's PdfiumCore does not bind Pdfium's FPDFText_* API in Java (even though libpdfium exports the symbols). Returning empty results would look like “no matches”, so query methods throw and apps should branch on isTextLayerSupported(). A future JNI shim can implement the same interface without Dart API changes.

Base

Rebased onto migrate/kotlin-swift (includes beta.12: spacing + setPage(withAnimation:)). Text-layer changelog is beta.13 so it does not collide with the already-published beta.12.

Test plan

  • flutter analyze clean (both packages)
  • Dart unit tests (interface + app package, including text_layer tests)
  • Android unit tests (FlutterPDFViewTextLayerTest + full suite)
  • example/integration_test/text_layer_test.dart on iOS simulator (real PDFKit)
  • Manual: search, next/prev match, selection, enableCopy: false
  • Publish interface 1.1.0, then app 1.5.0-beta.13

Related

Ports the text-layer work from the wt/text-layer branch onto the federated
architecture, fixes the iOS implementation so it compiles, and adds the
end-to-end coverage that would have caught it.

The iOS code did not build. Three Swift errors, all in the new code:
a second `deinit` on FlutterPDFView (the class already had one that removes
the same observers); `String? ?? NSNull()`, which is not a valid `??`; and an
`if let` on `PDFDocument.index(for:)`, which returns a non-optional Int. That
last one also ignored NSNotFound, so a match on a page the document could not
resolve would have reported page 0 — now it keeps the default explicitly.
None of it was detectable in the original worktree: SwiftPM derives package
identity from the directory name, so `flutter build ios` failed at dependency
resolution before ever reaching the compiler.

Silent failure, fixed. Android returned an empty list from searchText and null
from getSelectedText, which is indistinguishable from "this document contains
no matches" and "nothing is selected". An app would have shipped broken search
without a single error. Now the natives report
`kPdfTextLayerUnsupportedCode` and Dart raises UnsupportedError, while
`isTextLayerSupported()` lets apps branch before calling. clearSearch and
clearSelection stay no-ops, because clearing nothing is truthful.

Android is not blocked on upstream, contrary to the original note. PdfiumCore
binds none of Pdfium's text API in Java — but the libpdfium inside the same
AAR exports 36 FPDFText_* symbols (nm -D, type T, every ABI), including
FindStart/FindNext/CountChars/GetText/GetCharBox. Reaching them needs a JNI
shim, which is real work but is an option that exists today rather than a wait
for a new AndroidPdfViewer. Recorded in the README so the next attempt starts
from the right premise.

Federated placement: the shared types, settings, callbacks and controller
methods live in flutter_pdfview_platform_interface (1.1.0), so a future web or
desktop implementation inherits the contract — including the requirement to
fail rather than return empty.

Verified: 14 new integration tests drive real PDFKit on a simulator (25 total
across both suites), against a deterministic fixture with known text on known
pages (scripts/make_text_pdf.py). 188 Dart unit tests and 127 Android unit
tests pass, iOS and Android example builds succeed, analyze and format clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XKmmG2v9eJSWFDLy6mRe8F
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1936c06c-ced6-4bef-ad72-eb0b36e06ca2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Update package and platform-interface docs, replace the generic example
README with a demo map, polish the example home screen and TextSearchScreen
entry, and extend widget tests. Remove "add search" from future plans.
@endigo

endigo commented Aug 8, 2026

Copy link
Copy Markdown
Owner Author

Follow-up commit: docs + example polish for the text layer.

  • Package README: text-layer in Example, controller table (already present), future plans no longer say “add search”, iOS 13.0+
  • Platform-interface README: text-layer contract (isTextLayerSupported, throw vs empty)
  • Claude.md: key features, iOS/Android notes, testing + example scenarios
  • Example README.md demo map + integration-test instructions
  • Example app: clearer home chrome, Search Text in PDF (text layer) button, library doc
  • Example widget tests updated for the new title and TextSearchScreen chrome

Cover search/selection/copy, isTextLayerSupported, platform notes, and
example/integration test pointers for agents working in this repo.
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