Skip to content

[pull] main from expo:main#958

Merged
pull[bot] merged 4 commits into
code:mainfrom
expo:main
Jun 12, 2026
Merged

[pull] main from expo:main#958
pull[bot] merged 4 commits into
code:mainfrom
expo:main

Conversation

@pull

@pull pull Bot commented Jun 12, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

zoontek and others added 4 commits June 12, 2026 00:37
… deep link (#46796)

# Why

The `ios-test-e2e` job has been hitting the 40-minute step timeout (e.g.
[this
run](https://github.com/expo/expo/actions/runs/27332214136/job/80752810210)).
It isn't a hang — the slow Xcode 26.4.1 / iOS 26.4 / iPhone 17 Pro
simulator (boot ~135s, Maestro driver connect ~200s, flows 100–340s) is
amplified by two flows that fail and burn their retry budgets until the
clock runs out. Confirmed both via the run's debug screenshots.

# How

Two independent root causes, two commits:

**1. expo-video fullscreen exit (`[ios][video]`)** — failed all 3
attempts. The flow double-tapped the top-left corner to dismiss the
native `AVPlayerViewController`. On iOS 26 the player controls
auto-hide, so tapping the corner while they're hidden does nothing and
the app stays in fullscreen (the failure screenshot shows Big Buck Bunny
still fullscreen, no chrome). Fix: tap the center first to reliably
reveal the controls, then tap the close button. Android is unchanged.
The exact close-button coordinate may still need a CI tweak — see Test
Plan.

**2. test-suite `run?tests=` deep link (`[test-suite]`)** — failed 4×
before the timeout. `SelectScreen.handleOpenURL` only recognized
`/select/` and `/all` paths and fell through to `setModules()` (the
selection list) for `run?tests=` URLs. On a cold start it raced React
Navigation's linking and could win, leaving the app on the selection
list instead of the run screen (confirmed by the failure screenshot).
Fix: parse the `tests` query and navigate to the run screen explicitly.

The expo-image `header-Appearance` blip in the same run recovered on
retry (image comparisons passed) and is not addressed here.

# Test Plan

These only run on CI (no local iOS 26 simulator). Validating by
re-running the `ios-test-e2e` job on this branch:
- `expo-video/fullscreen-test` reaches `1 = onFullscreenExit` instead of
staying fullscreen. If the reveal-then-dismiss still misses the close
button, the top-left coordinate (`11%,10%`) will be tuned in a
follow-up.
- `maestro-generated` (native modules) shows the run screen
(`test_suite_selection_query_text` = "Basic") instead of the selection
list.
- Overall job completes under the 40-minute step timeout.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Why

The community `BottomSheet` host is absolutely positioned over the
screen at all times. After the sheet is dismissed it kept intercepting
touches in the area the sheet used to occupy, so controls behind it
stopped responding.

Closes #45810.

# How

Set `pointerEvents="none"` on the `Host` wrapper (iOS + Android). The
native sheet is presented in its own window, so it still receives
touches while open — the anchor host just no longer blocks anything
behind it.

# Test Plan

Repro from #45810: open the sheet, close via `dismiss()` / `close()` /
`snapToIndex(-1)`, then tap a control where the sheet was — it's
interactive again. Verified on iOS and Android with a bare-expo Tester
screen.
…inding (#46367)

# Why

Fixes #46302.

Opening `@expo/ui` `BottomSheet` / `BottomSheetModal` with multiple snap
points on Android throws one of two errors, both originating from the
same race in the community wrapper:

```
Error: Call to function 'ModalBottomSheetView.expand' has been rejected.
→ No handler registered for AsyncFunction 'expand' on view 'ModalBottomSheetView'
```

```
Error: Call to function 'ModalBottomSheetView.partialExpand' has been rejected.
→ Unable to find ComposeFunctionHolder view with tag N
```

`BottomSheet.android.tsx` had a `useEffect` keyed on
`[hasMultipleSnapPoints, isOpen, maxIndex]` that called
`sheetRef.current?.expand()` / `partialExpand()` right after `isOpen`
flipped true. The AsyncFunction handlers for those methods are
registered inside the native `Content { }` block via `DisposableEffect`,
which runs only on first composition. The JS `useEffect` ran between
view-attach and that first composition, so the dispatcher fired before
the handler was bound → first error. The same effect could re-fire while
a view was disposing → dispatch to a stale view tag → second error.

(Note for #46302: there's no prebuilt AAR shipped — the
`local-maven-repo/` directory that appears in `node_modules/@expo/ui/`
is Gradle's local build cache, populated from the actual `.kt` sources
on first build. The source-only fix in this PR is sufficient.)

# How

- Add a new `initialFullyExpanded: Boolean` prop to
`ModalBottomSheetViewProps` on the native `ModalBottomSheetView`, and to
the `@expo/ui/jetpack-compose` `ModalBottomSheet` primitive.
- Apply the prop inside a `LaunchedEffect(Unit)` declared **after** the
`ModalBottomSheet(…)` composable call, so it runs after Material3's
internal show effect. Material3's `animateTo(PartiallyExpanded)` starts
first, then our `animateTo(Expanded)` cancels and retargets via
`animateTo`'s `MutatorMutex`. Final state: `Expanded`.
- The partially-expanded state remains structurally present, so
`partialExpand()` and drag-down still work after opening at the max snap
point — distinct from `skipPartiallyExpanded`, which permanently removes
the partial state.
- In `BottomSheet.android.tsx`, delete the racing `useEffect` entirely
and pass the new `initialFullyExpanded` prop instead.

### Behavior note

The deleted `useEffect` was also (incidentally) re-firing when
`snapPoints` changed while the sheet was open, yanking the user back to
partial each time. With this patch, mid-open `snapPoints` mutation
preserves the current state — net improvement.

# Test Plan

Manual smoke test on Android (`apps/native-component-list` via
`apps/bare-expo`):

- `BottomSheetScreen.android.tsx` has a new **"Initial fully expanded"**
toggle. Ran all 4 combinations with **"Skip partially expanded"**:
  - OFF × OFF → opens at partial, no crash
- OFF × **ON** (the previously-crashing path) → opens at full, drag-down
to partial works, no crash
  - ON × OFF → opens at full (single-state), no crash
  - ON × ON → opens at full (skip semantic dominates), no crash
- Close → reopen at maxIndex multiple times, no second-open crash.
- Swipe-dismiss during the initial expand animation —
`CancellationException` caught, no unhandled rejection.
- Mid-session `snapToIndex(0)` after opening at maxIndex animates back
to partial.

# Checklist

- [x] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)

---------

Co-authored-by: Aman Mittal <amandeepmittal@live.com>
Co-authored-by: nishan (o^▽^o) <nishanbende@gmail.com>
…46815)

# Why

User-supplied `modifiers` had no effect on universal components when the
component derived a modifier of the same type from its props, e.g.
`buttonStyle` on `Button` always lost to the `variant` prop.

Fixes - #46804,
#45602

# How

- Added `omitUserOverridden`: a modifier passed through `modifiers`
takes ownership of its `$type`, and the component skips the same-type
modifier it derives from props.
- Applied it to style-derived modifiers in `transformToModifiers` (iOS
and Android), the `variant` `buttonStyle` in `Button`, and `textStyle`
modifiers in `Text`. Event, lifecycle, and behavior modifiers are never
dropped.
- This also makes `ListItem`'s `buttonStyle('plain')` take effect, it
was losing to the `Button` variant default.

# Test Plan

Unit tests for `omitUserOverridden`, both `transformToModifiers`,
universal `Button`, and `Text`.

# Checklist

- [x] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
@pull pull Bot locked and limited conversation to collaborators Jun 12, 2026
@pull pull Bot added the ⤵️ pull label Jun 12, 2026
@pull pull Bot merged commit aca0879 into code:main Jun 12, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants