Commit 2abeaa3
authored
fix(Android, Tabs): propagate actionOrigin into navigation state progression (#3996)
## Description
`TabsContainer` (Android, gamma) was deciding several things off
`isInExternalOperationContext` even though the real intent was to gate
on the action's `actionOrigin`. The two were aligned only by accident —
`isInExternalOperationContext == true` ⇔ `actionOrigin ∈ {
PROGRAMMATIC_JS, PROGRAMMATIC_NATIVE }` — which made
`PROGRAMMATIC_NATIVE` updates behave incorrectly on Android compared to
iOS:
1. `progressNavigationState` did not have `actionOrigin` available, so
consumers observing the progression could not distinguish user-driven
from external/programmatic transitions.
2. `lastUINavState` was not updated for `PROGRAMMATIC_NATIVE`, even
though that origin represents a native-authoritative state change
(downstream library calling `submitSelectionOfTabsScreenWithKey`). This
caused subsequent JS requests with stale `baseProvenance` to slip
through `isNavigationStateStale` checks instead of being rejected.
3. The "prevent native selection" gate fired on
`!isInExternalOperationContext`, which incidentally also rejected
`PROGRAMMATIC_NATIVE` updates. Per intent (and matching iOS), this gate
should reject only `USER` actions.
This PR threads the resolved `actionOrigin` through the relevant code
paths and switches each gate to test the origin directly. iOS and
Android now agree on semantics.
Side note: `isPreventNativeSelectionEnabled` is misnamed — it really
means "prevent user selection". Renaming it deferred until a future
major release.
## Changes
- Compute `actionOrigin` once in `onMenuItemSelected`, before any gate
that depends on it.
- Thread `actionOrigin` through `updateSelectedFragment` and
`progressNavigationState`.
- `lastUINavState` now updates whenever `actionOrigin !=
PROGRAMMATIC_JS` (was: whenever `!isInExternalOperationContext`).
- Prevent-native-selection gate now checks `actionOrigin == USER` (was:
`!isInExternalOperationContext`).
## Test plan
Manual reproduction on Android via `FabricExample`:
1. **`PROGRAMMATIC_NATIVE` no longer rejected by prevent-selection.**
From a downstream-library code path (or a temporary call site) invoke
`tabsContainer.submitSelectionOfTabsScreenWithKey(key)` on a
`TabsScreen` whose `isPreventNativeSelectionEnabled = true`. Before:
selection blocked, `onNavigationStateUpdatePrevented` emitted. After:
selection applied, no prevention emitted.
2. **`lastUINavState` advances for `PROGRAMMATIC_NATIVE`.** After the
above selection, dispatch a JS `navStateRequest` with the
pre-native-update `baseProvenance`. Before: request applied (stale not
detected). After: request rejected as stale via
`isNavigationStateStale`.
3. **`actionOrigin` reaches observers during progression.** Register a
`TabsNavigationStateObserver` and verify `actionOrigin` on
`dispatchOnNativeStateChange` for each of: native tab tap (`USER`),
`navStateRequest` from JS (`PROGRAMMATIC_JS`),
`submitSelectionOfTabsScreenWithKey` (`PROGRAMMATIC_NATIVE`).
4. **Regression check.** Standard tab tap on a tab with
`isPreventNativeSelectionEnabled = true` is still prevented and emits
`onNavigationStateUpdatePrevented`.
No automated tests exist for this path yet; recommend adding one matrix
test in a follow-up.
## Checklist
- [ ] Included code example that can be used to test this change.
- [ ] For visual changes, included screenshots / GIFs / recordings
documenting the change.
- [ ] For API changes, updated relevant public types.
- [ ] Ensured that CI passes1 parent 46036b3 commit 2abeaa3
1 file changed
Lines changed: 21 additions & 13 deletions
Lines changed: 21 additions & 13 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
474 | 474 | | |
475 | 475 | | |
476 | 476 | | |
477 | | - | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
478 | 481 | | |
479 | 482 | | |
480 | 483 | | |
| |||
488 | 491 | | |
489 | 492 | | |
490 | 493 | | |
491 | | - | |
| 494 | + | |
492 | 495 | | |
493 | 496 | | |
494 | 497 | | |
495 | | - | |
| 498 | + | |
496 | 499 | | |
497 | 500 | | |
498 | 501 | | |
| |||
503 | 506 | | |
504 | 507 | | |
505 | 508 | | |
506 | | - | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
507 | 513 | | |
508 | | - | |
| 514 | + | |
509 | 515 | | |
510 | 516 | | |
511 | 517 | | |
| |||
521 | 527 | | |
522 | 528 | | |
523 | 529 | | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
524 | 537 | | |
525 | | - | |
| 538 | + | |
526 | 539 | | |
527 | 540 | | |
528 | 541 | | |
529 | 542 | | |
530 | | - | |
| 543 | + | |
531 | 544 | | |
532 | 545 | | |
533 | 546 | | |
| |||
537 | 550 | | |
538 | 551 | | |
539 | 552 | | |
540 | | - | |
541 | | - | |
542 | | - | |
543 | | - | |
544 | | - | |
545 | | - | |
| 553 | + | |
546 | 554 | | |
547 | 555 | | |
548 | 556 | | |
| |||
0 commit comments