Conversation
… 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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 : )