feat: publish native overlay hosts as an independent package - #137
huhuanming wants to merge 6 commits into
Conversation
Migrate the verified Fabric Android, iOS, C++ and Web implementation from app-monorepo with a documented Nitro-template exception and standalone build, type, test and packaging checks. Preserve the native-sheet compatibility API. Align 42 release workspaces to 3.0.162-alpha.268 for branch CI publication on next. Extend dependency synchronization to kit/playground and the temporary overlay workspace reference; keep stable tags and PR merges unchanged. Validation: 39 overlay tests, 36 release-tool tests, typecheck, lint, test integrity, immutable install, JS/declaration/tarball build, full Android arm64-v8a example build, and CocoaPods install passed. iOS runtime remains unverified on this host.
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
| const element = ref.current; | ||
| if (!element) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
P1: [Hide page entries mounted after their owner is suspended]
When a page owner is already suspended and another overlay from that owner mounts, suspendedOwners remains unchanged. This effect does not run for the new portal child, leaving that entry visible and interactive over the active page.
Apply the current suspension state when page entries are inserted, as well as when the owner list changes.
| container | ||
| .querySelectorAll<HTMLElement>(`[${ENTRY_ATTRIBUTE}]`) | ||
| .forEach((node) => { | ||
| setInert(node, Number(node.dataset.stackOrder) < seq); |
There was a problem hiding this comment.
P2: [Use level order when inerting page overlays]
If a blocking secure page overlay opens before a modal page overlay, the later modal has a higher sequence number but still renders below secure. This comparison leaves the modal focusable and accessible beneath the blocking overlay.
Compare page entries using level order first and sequence within a level when applying inert.
| private fun updateAccessibility() { | ||
| val entries = orderedEntries() | ||
| val topIndex = entries.indexOfLast { it.blocking && it.isShownForInput } | ||
| val content = parent as? ViewGroup |
There was a problem hiding this comment.
P2: [Apply Android accessibility isolation to page overlays]
When a blocking page overlay is attached, it lives in NativeOverlayPageHostView, while this accessibility pass checks only the global orderedEntries(). Page attachment also does not trigger this pass, so TalkBack can still navigate underlying page controls.
Update accessibility state when page entries attach or detach, and hide page content outside the active overlay without hiding the page host.
| * predictive back, so the dispatcher alone never runs first. | ||
| */ | ||
| fun handleBackKey(event: KeyEvent): Boolean { | ||
| val entry = topBlockingEntry() ?: return false |
There was a problem hiding this comment.
P2: [Handle Back for dismissible non-blocking overlays on Android]
When a non-blocking overlay is explicitly dismissible, topBlockingEntry() returns no entry (or a blocking entry beneath it). Back then reaches navigation or dismisses the lower overlay instead of the visible one. Please select the topmost input-ready entry that is either blocking or dismissible, then consume Back according to its dismissal setting.
| const ownerKey = props.ownerKey ?? pageScope.ownerKey; | ||
| // Without a host or owner there is nowhere to anchor a page overlay. | ||
| const scope = | ||
| props.scope === 'page' && hostKey && ownerKey ? 'page' : 'global'; |
There was a problem hiding this comment.
P2: [Keep page-scoped overlays within their page boundary]
If a caller requests page scope before hostKey or ownerKey is available, this expression changes the entry to global scope. The overlay can then appear above unrelated routes and will not suspend with its owning page. Please keep it page-scoped and withhold presentation until its required host and owner are available.
Move the overlay hosts into a publishable native-view package so app-monorepo consumes a registry version instead of an in-repo workspace copy. This migrates the Android, iOS, custom C++, TypeScript and Web implementation; the SPEC explains the Fabric/custom-shadow-node requirement. The existing native-sheet API remains available.
At
59b3f142, the three confirmed review findings are fixed: late Web page portals inherit suspended-owner isolation; blocking isolation compares overlay level before sequence, so a newer modal remains inert under an older secure entry; Android page overlays isolate the page/navigation accessibility tree and restore the caller's prior flags on dismissal, suspension, detach and blocker transitions. These corrections keep the existing public contract. The Android CI now executes the overlay unit suite along with the nine existing suites.All 42 publishable workspaces and internal exact dependencies move together to fresh
3.0.162-alpha.272. The original manual package-publish workflow is dispatched on this branch withnpm_dist_tag=nextand an emptyonly_workspace. The complete branch publication succeeded. Independent verification confirms all 42 exact versions, next tags and downloadable tarballs (HTTP200), all 42 latest tags unchanged, and package gitHead59b3f142d6e4b9d25cfdd359574c2947700dd559. App-monorepo integration waits for final native-tests completion. The previous unified alpha270 release succeeded at run #271. No already-published version is overwritten or deleted; no merge is requested.Validation for the correction:
14847dd339234a7fd85d4fa523360b777f7fcc2eupdates only that lockfile, generated with pinned CocoaPods1.16.2. The new native-tests run succeeded: package validation, all ten Android suites, Kotlin CLI, all three SwiftPM suites, lockfile verification, explicit NativeOverlay iOS Simulator compilation and all six XCTest suites passed. Package implementation and release contents are unchanged by the lockfile repair. The previous implementation's native-tests passed all nine Android suites, Kotlin CLI, three SwiftPM suites, explicit iOS Simulator overlay pod compilation and six XCTest suites.App-monorepo integration and UI verification are tracked separately. Native main startup imports are reduced while preserving the upstream Tamagui factory and development validation; the existing budget threshold is unchanged.