Skip to content

[pull] main from expo:main - #1199

Merged
pull[bot] merged 11 commits into
code:mainfrom
expo:main
Aug 31, 2026
Merged

[pull] main from expo:main#1199
pull[bot] merged 11 commits into
code:mainfrom
expo:main

Conversation

@pull

@pull pull Bot commented Aug 31, 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 : )

tsapeta and others added 11 commits August 31, 2026 12:28
)

# Why

Stacked on #49241, which turned off the React Compiler-derived rules
that oxlint 1.79 enables by default. Five of them (`react/use-memo`,
`react/void-use-memo`, `react/purity`,
`react/preserve-manual-memoization`, `react/static-components`) have few
enough findings to clean up right away. The remaining four (`refs`,
`globals`, `immutability`, `set-state-in-effect`) have around 400
findings and stay off pending triage.

# How

The real fixes are mechanical: `JSON.stringify(...)` calls moved out of
dependency arrays, render-created components hoisted to module scope, a
`useMemo` callback inlined, a reassigned prop renamed in the Slot shim,
and a fetch-on-mount effect reordered below the callback it calls.

Intentional patterns keep the rules enabled and opt out narrowly
instead: the vendored React Navigation code and the two demo apps get
config-level opt-outs, and a handful of stable-identity sites (memoized
wrappers, cached component factories, aliases of static components,
deps-forwarding generic hooks) get annotated inline disables.

# Test Plan

Full oxlint sweep over all 130 oxlint packages and the three oxlint apps
is clean. `et check-packages` passes for expo-router, `@expo/log-box`,
expo-module-scripts, expo-audio, expo-modules-core and expo. The
expo-router suites covering the touched files pass (86 tests).

<!-- disable:changelog-checks -->
# Why

`expo-blur` README.md is outdated

# Test Plan

Check
https://docs.expo.dev/versions/latest/sdk/blur-view/#android-support

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [ ] 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: Vojtech Novak <vonovak@gmail.com>
…permission (#49546)

> [!WARNING]
> **Agent-authored and NOT human-reviewed.** An automated `/verify
--fix` run for #49340 wrote this change and checked it in a sandbox; the
reasoning and evidence are in the outcome comment on that issue. Review
it as you would any external contribution.

Requested by @tsapeta · [investigation
run](https://github.com/expo/expo/actions/runs/33384097692) · refs
#49340

The push message format table documents the iOS `sound` and `badge`
fields without saying that iOS applies neither one unless the user
allowed sounds and badges for the app. The usual permission check does
not show this, because `getPermissionsAsync()` keeps returning `status:
"granted"` while `ios.allowsSound` and `ios.allowsBadge` are `false`.

This adds one paragraph to
`docs/pages/push-notifications/sending-notifications.mdx`, next to the
existing notes on `contentAvailable`, `ttl`, `priority`, and
`channelId`. It names the two `ios` fields to check. No other page
changes, and no runtime behaviour changes.

Measured on a hosted iOS simulator: with **Badges** off in Settings, a
notification carrying `sound: "default"` and `badge: 5` arrived and set
no icon badge, while `status` stayed `granted`.

<details><summary>Cause</summary>

The failure is a documentation gap, not a defect in
`expo-notifications`.

For a notification that arrives while the app is in the background or
terminated, iOS decides the presentation before any app code runs.
[`NotificationCenterManager.swift#L135-L164`](https://github.com/expo/expo/blob/04de6949bbb7e830be07172304d462ccd267f76a/packages/expo-notifications/ios/ExpoNotifications/Notifications/NotificationCenterManager.swift#L135-L164)
shows the only place where the package changes presentation options, and
iOS calls it only when the app is in the foreground. The permission
request maps the JS default to `[.alert, .badge, .sound]` in
[`NotificationPermissions.ts#L60-L70`](https://github.com/expo/expo/blob/04de6949bbb7e830be07172304d462ccd267f76a/packages/expo-notifications/src/NotificationPermissions.ts#L60-L70)
and
[`PermissionsModule.swift#L29-L34`](https://github.com/expo/expo/blob/04de6949bbb7e830be07172304d462ccd267f76a/packages/expo-notifications/ios/ExpoNotifications/Permissions/PermissionsModule.swift#L29-L34),
so the package asks for all three.

The `sound` and `badge` rows of the message format table at
[sending-notifications.mdx#L274-L275](https://github.com/expo/expo/blob/04de6949bbb7e830be07172304d462ccd267f76a/docs/pages/push-notifications/sending-notifications.mdx#L274-L275)
do not mention the authorization requirement. The common registration
recipe tests only `status !== 'granted'`, so a reader following the docs
cannot see the state that drops the sound and the badge.

</details>

<details><summary>Verification</summary>

Measured on a hosted iOS simulator (iOS 26), running Expo Go against
Metro, Expo SDK 57, `expo-notifications` 57.0.15. The test app used the
registration code from the reproduction repo in
[#49340](#49340). Each arm delivered
a notification whose content set `sound: 'default'` and `badge: 5`, with
the app in the background.

| arm | `status` | `ios.allowsSound` | `ios.allowsBadge` | delivered |
icon badge |
| --- | --- | --- | --- | --- | --- |
| Sounds and Badges on | `granted` | `true` | `true` | yes | 5 |
| Sounds and Badges off in Settings | `granted` | `false` | `false` |
yes, `getPresentedNotificationsAsync()` returned 2 entries, each with
`badge: 5` | none |

A second `requestPermissionsAsync()` call in the second arm returned
`status=granted sound=false badge=false` and opened no prompt, which is
the basis for the sentence about the Settings app.

</details>

<details><summary>Checks run</summary>

From `docs/`, on a full `pnpm install` of the checkout:

- `pnpm lint-prose` — Vale: 0 errors, 0 warnings, 0 suggestions in 1600
files.
- `pnpm test` — 58 suites, 630 tests, 32 snapshots, all passing.
- `pnpm test:worker` — all tests passed.
- `NODE_ENV=production pnpm lint --max-warnings 0` — `tsc`, `eslint` and
the `oxfmt` format check passed. `oxlint` did not run: it panics with
`oxc_allocator/src/pool/fixed_size.rs:112 called Result::unwrap() on an
Err value`. The same panic happens on the unmodified tree, so it is an
environment failure, not a result for this change. `oxlint` also reports
"No files found to lint" for the changed `.mdx` file.
- Not run: the `🏗️ Build Docs website` job from `docs-pr.yml`.

</details>

<details><summary>Not covered</summary>

No remote push was delivered. The measurement used a scheduled local
notification with the same `sound` and `badge` content fields. The
hosted simulator gives no audio, so the sound half of the note rests on
the `allowsSound: false` reading and on Apple's documented behaviour,
not on a sound measurement. No Release or TestFlight build was
exercised.

</details>

<!-- expo-bot:fix-options v1 -->
<details><summary>Options considered</summary>

1. **Change `expo-notifications` so that a missing sound or badge
authorization becomes visible in code.** Rejected: the data is already
there. `getPermissionsAsync()` returns `ios.allowsSound` and
`ios.allowsBadge` today, so a code change would only add a second way to
read the same fields, and it would alter a public API to fix a reader's
expectation.
2. **Add a runtime warning when the app sends or receives a notification
while sound or badge authorization is off.** Rejected: the package
cannot know that the payload asked for a sound or a badge on the
background path, because iOS never gives it that notification. A warning
on every launch would fire for apps that deliberately ask for alerts
only.
3. **Do nothing and let the issue thread answer it.** Rejected: the
message format table is where a reader looks for what `sound` and
`badge` do, and the next reader repeats the same search.
4. **Document the behaviour in the message format notes.** Chosen: the
gap is in the prose, prose cannot regress runtime, and the note sits
next to the four notes that already qualify other fields in the same
table.

</details>
<!-- /expo-bot:fix-options -->

---------

Co-authored-by: expo-bot <expo-bot@users.noreply.github.com>
Co-authored-by: Aman Mittal <amandeepmittal@live.com>
# Why

Document the EAS Simulator REST API added in
expo/universe#30213 so integrations can manage
remote device sessions without EAS CLI.

# How

- Add a REST API reference to the EAS Simulator preview docs, following
the existing Workflows REST API patterns.
- Cover authentication, creation options, polling, controller
configuration, stopping sessions, and errors.
- Match the merged API: three lifecycle endpoints, inline
`remoteConfig`, credential caching protections, and duration limits that
exclude cleanup time.
- Link the reference from the sidebar, introduction, getting-started
guide, and CLI reference.

# Test Plan

CI + preview

# Checklist

- [x] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)

Documentation only; no package changelog or native build changes.
# Why

In order to automate the process of updating Expo Go builds on `eas go`
and sign.expo.dev automatically, we should publish the Expo Go IPA
generated during the release flow to the same GitHub releases repo.

# How

This PR extends the `et eas ios-simulator-upload` action instead of
adding a new release step. (Perhaps we should just rename it to `eas
ios-upload` ? )

After it uploads the simulator archive and updates the versions
endpoint, it now also:

- downloads the device IPA from the `release-client` EAS build (the one
produced by `ios-client-build-and-submit`), and
- uploads it as `Expo-Go-<version>.ipa` to the same GitHub release,
reusing the release object already in scope.

The versions endpoint is unchanged for now: `iosClientUrl` still points
to the simulator tarball. I'll add a dedicated field for the IPA in a
follow-up PR

# Test Plan

N / A
…iew and app modules (#49336)

# Why
Cleans up expoview's dependency block. Many declarations existed for
vendored module copies that no longer exist, SDK packages that left the
SDK years ago, or for third-party libraries the SDK packages now declare
themselves. The app module carried its own copies of the same. They
inflate the release classpath that R8 has to trace on every build.

# How
Removed every dependency with no source reference in expoview or app,
the Google Analytics receivers from the manifest template along with
their artifact, and the orphaned cropper activity entry whose library
expo-image-picker declares in its own manifest. Also removed
declarations the owning SDK packages provide, and the app module's
copies of expoview's api dependencies. The camera and review
dependencies stay: the home QR scanner and review prompt use them.

# Test Plan
Release build of Expo Go and NCL: home QR scan, image picker with
editing, notifications token, install referrer, webview, location, sign
in.
…49337)

# Why
We declared both Coil 2 and Coil 3. AccountScreen, still used Coil 2's
AsyncImage but the rest of the home UI is on Coil 3, so both libraries
shipped in the app.

# How
Switched the import

# Test Plan
Expo go. Avatars load as before
…olding (#49338)

# Why
expoview was once published as a maven AAR for ExpoKit and served as the
template for generating versioned expoview-abiXX copies. Both systems
are gone: the ABI list has been empty for a while, vendored modules no
longer exist, and the transform script was deleted. The leftover
markers, files, and maven coordinates are dead weight and actively
misleading.

# How
Deleted versioning_linking.gradle, the versioned-react-native gradle
scaffolding, the empty ABI loop in settings.gradle, the frozen SDK 45
maven coordinates, and all WHEN_VERSIONING markers plus related stale
comments and gitignore entries.

# Test Plan
Expo go
…9515)

# Why

👋 I've been really loving the direction of expo-ui and expo-router, and
in particular the newer toolbar api, but have found the Android parts
lacking in how I can style. iOS gets past this, at least imo, because
out of the box it looks better. I've added `cornerRadius` to the menu
since I think it goes a long way in making it look better without adding
a bunch of options that may or may not be accepted.

I did not see a mention of requiring an issue before contributing, but
apologies if I missed that somewhere.

# How

I started by manually editing installed versions of expo-ui and
expo-router and creating a patch from that. Once I confirmed it worked
as expected [in my app](stumpapp/stump#1355), I
just manually copied it over to my fork.

I also added small blurbs/examples in the relevant docs sections (mostly
copying existing ones and tweaking for the change).

# Test Plan

I added a new section to and ran the `native-component-list` app. If the
standard for this small of a change is different, please let me know and
I can definitely try to align with that.

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [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)
- [x] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [x] 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 Aug 31, 2026
@pull pull Bot added the ⤵️ pull label Aug 31, 2026
@pull
pull Bot merged commit 5e4b01c into code:main Aug 31, 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.

8 participants