Skip to content

Migrate ShareActionHandler to a code-generated, type-safe native contract #104432

Open

Description

@roryabraham

Context

Follow-up to the bridge discussion during review of #101208. Keep this architectural migration separate from that PR's Android cold-start file-sharing fix.

Problem

ShareActionHandler.processFiles has inconsistent native payloads and a handwritten TypeScript declaration that cannot enforce the native implementations:

  • Android returns a JSON string containing one object; iOS returns an array of dictionaries.
  • Android emits numeric processedAt, while iOS and the TS declaration use a string.
  • Android text results omit aspectRatio, although ShareActionContent declares it required.
  • PR Fix cold-start file sharing to open Submit expense #101208 broadens the callback type to accept arrays, objects, strings, null, and undefined, with transport-specific parsing used by ShareRootPage.

Reference implementations at the reviewed revision:

Proposed approach

Use a single code-generated contract for the JS/native boundary, preferably following the existing Nitro ContactsModule pattern, which returns typed records from Swift/Kotlin. TurboModules are an alternative, but simply transporting JSON strings through a generated method does not solve payload type safety.

  • Return one consistent typed collection, such as Promise<SharedFile[]>, on both platforms.
  • Standardize timestamp types, optional fields, and no-data/error semantics (for example, an empty array for no pending files and rejection for processing failures).
  • Cover both App standalone and Mobile-Expensify hybrid implementations; coordinate any companion changes needed there.
  • Remove legacy JSON-string parsing and platform-specific result-shape handling from consumers.

Cold-start intent persistence and initial routing remain necessary and are not replaced by codegen. Persisted data and external intent metadata still require validation when read; storage serialization should remain an internal implementation detail.

Acceptance criteria

  • One generated specification defines the shared-file payload and method contract used by native implementations and TS consumers.
  • Android and iOS return the same collection shape, field types, and documented no-data/error behavior.
  • App standalone and Mobile-Expensify hybrid implementations are covered.
  • UI consumers no longer parse native JSON strings or branch on platform-specific transport shapes.
  • Tests cover file and text payloads, optional metadata, no pending share, invalid/unavailable attachments, and processing failures.
  • Cold-start and warm-start sharing continue to work on Android and iOS in supported standalone/hybrid builds.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions