Repository navigation
Migrate ShareActionHandler to a code-generated, type-safe native contract #104432
Description
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, althoughShareActionContentdeclares it required. - PR Fix cold-start file sharing to open Submit expense #101208 broadens the callback type to accept arrays, objects, strings,
null, andundefined, with transport-specific parsing used byShareRootPage.
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.
Activity