Skip to content

Add form field read-only control and signature interception bridge#3

Draft
mutumbakato wants to merge 4 commits into
masterfrom
feature/form-readonly-signature-interception
Draft

Add form field read-only control and signature interception bridge#3
mutumbakato wants to merge 4 commits into
masterfrom
feature/form-readonly-signature-interception

Conversation

@mutumbakato

@mutumbakato mutumbakato commented Jul 17, 2026

Copy link
Copy Markdown

Note

Demo / proof-of-concept for the customization approach — not production-ready and not meant to merge as-is. Use it (and the guide) as a reference for customizing an SDK fork.

Summary

Exposes two native PDF form capabilities through NutrientView, on both the Legacy (Paper) and New (Fabric + TurboModule) architectures, following the BRIDGING.md recipe:

  • setFormFieldReadOnly(fullyQualifiedName, readOnly, persist?) — locks/unlocks a single form field. iOS maps persist: true to PSPDFFormField.isReadOnly (persisted PDF flag) and persist: false to isEditable (session-only). Android updates AnnotationFlags.LOCKEDCONTENTS on the field's widget annotations, preserving existing flags (READONLY is ignored for widgets, and Android's FormField has no read-only setter).
  • interceptSignatureFields prop + onSignatureFieldTapped event — consumes taps on signature form fields (iOS didTapOnAnnotation: delegate, Android FormManager.OnFormElementClickedListener) and emits {fullyQualifiedName, pageIndex} to JS instead of presenting the native signature UI.
  • dismissSignaturePad() — dismisses the presented native signature UI, resolving false otherwise (idempotent). Recognizes both the signature creation UI and the saved-signature picker: iOS type-checks the presented navigation stack against PSPDFSignatureCreationViewController, legacy PSPDFSignatureViewController, and PSPDFSignatureSelectorViewController; Android scans candidate fragment managers for ElectronicSignatureFragment and SignaturePickerFragment instances.

Also included:

  • A Signature Interception Catalog example used as the runtime test harness.
  • An implementation guide for customers customizing an SDK fork.

Verification

  • npm test (32/32), npm run lint, npm run build-and-generate-types — all pass.
  • Catalog Android assembleDebug (compiles legacy + newarch source sets + codegen) and iOS xcodebuild — both succeed.
  • Runtime (Maestro-driven, New Architecture) on a Pixel 9 Pro emulator and iPhone 17 Pro simulator:
Test Android iOS
Intercept ON: event fires with correct field/page, native UI suppressed
Intercept OFF: default "Add Signature" UI opens unchanged
dismissSignaturePad() with creation UI open → true, UI closed
dismissSignaturePad() with saved-signature picker open → true, closed
dismissSignaturePad() with nothing open → false
Lock blocks editor on the target field only; unlock restores

Known caveat surfaced during testing: form interaction (and therefore interception) requires a writable document — Android file:///android_asset/ documents open read-only. Documented in the guide.

Open items

  • Save-and-reopen persistence assertions; multi-widget fields; rotation during signature UI; same runtime matrix on Paper builds and physical devices.
  • Decide whether persist: false should reject on Android instead of behaving persistently.

mutumbakato and others added 4 commits July 17, 2026 15:39
Exposes two native form capabilities through NutrientView on both the
Legacy (Paper) and New (Fabric + TurboModule) architectures:

- setFormFieldReadOnly(fullyQualifiedName, readOnly, persist): locks or
  unlocks a single form field. iOS maps persist=true to
  PSPDFFormField.isReadOnly (persisted PDF flag) and persist=false to
  isEditable (session-only). Android updates the LOCKEDCONTENTS flag on
  the field's widget annotations, preserving existing flags.
- dismissSignaturePad(): dismisses the native signature creation UI when
  presented, resolving false otherwise. Type-checks the presented
  controller/fragment so unrelated UI is never dismissed.
- interceptSignatureFields prop + onSignatureFieldTapped event: consumes
  taps on signature form fields (iOS PSPDFViewControllerDelegate tap
  handling, Android FormManager.OnFormElementClickedListener) and emits
  the field's fully qualified name and page index to JS instead of
  presenting the native signature UI.

Verified with Catalog builds on both platforms (gradlew assembleDebug,
xcodebuild), npm test, npm run lint, and regenerated types.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a SignatureInterception example screen used to verify the new
bridge at runtime on the Android emulator and iOS simulator via
Maestro: signature tap interception (on/off), setFormFieldReadOnly
lock/unlock, and dismissSignaturePad on an open and closed signature UI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Standalone guide for customizing an SDK fork with the new APIs: public
API semantics and platform differences, per-layer implementation
walkthrough for both architectures, build/test instructions, runtime
verification results, and packaging options.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
dismissSignaturePad only targeted the signature creation UI, so it
worked on the first tap of a signature field but failed on later tries
once a saved signature existed (or under the legacy signature flow),
when the SDK presents the saved-signature picker instead.

Android now scans candidate fragment managers for instances of both
ElectronicSignatureFragment and SignaturePickerFragment (instanceof
instead of tag lookup, since the picker's tag is private) and dismisses
via the matching static helper. iOS now checks the entire presented
navigation stack against the creation controller, the legacy signature
controller, and PSPDFSignatureSelectorViewController.

Verified on the Android emulator: after saving a signature, tapping the
field opens the "Signatures" picker and dismissSignaturePad now closes
it (previously returned false). Creation-UI cycles re-verified on both
platforms; a signed field's annotation context menu is still correctly
left alone (resolves false).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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