Conversation
# Why The Jetpack Compose `Icon` docs didn't mention the `@expo/material-symbols` package or its `add-material-symbols` CLI. The universal `Icon` page also linked to a non-existent repo. # How - Rewrote `jetpack-compose/icon.mdx` to import icons from `@expo/material-symbols/<icon>.xml` subpaths and added a section on the `add-material-symbols` CLI for non-default styles/axes. - Added the `@expo/material-symbols` install hint on `universal/icon.mdx` and fixed its broken repo link. - Mirrored to `unversioned` and `v56.0.0`. # Test Plan run website locally or preview at https://pr-45929.expo-docs.pages.dev/versions/v56.0.0/sdk/ui/jetpack-compose/icon/ <!-- Please describe the motivation for this PR, and link to relevant GitHub issues, forums posts, or feature requests. --> <!-- Please describe how you tested this change and how a reviewer could reproduce your test, especially if this PR does not include automated tests! If possible, please also provide terminal output and/or screenshots demonstrating your test/reproduction. --> # 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)
…mes [EXP-23] (#45847) ## Summary Stacked on #45831 Limits `REACT_NATIVE_OVERRIDE_HERMES_DIR` to local .env files only. ## 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) - [ ] 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)
…11] (#45834) ## Summary Stacked on #45831 We should use the new API in `@expo/env` to pass the original system env to all spawn calls, since we're otherwise "upgrading" the loaded environment variables with the ones already loaded during startup. ## 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) - [ ] 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)
…#45842) ## Summary Stacked on #45831 Related to #45833 Limits `EXPO_UNSTABLE_MCP_SERVER` raw URL value to the original system env. ## 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) - [ ] 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)
…1] (#45833) ## Summary Stacked on #45831 Limits `__UNSAFE_EXPO_HOME_DIRECTORY`, `EXPO_PACKAGER_PROXY_URL`, `EXPO_UNIVERSE_DIR`, and `EXPO_OVERRIDE_METRO_CONFIG` to be read from original system env only. ## 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) - [ ] 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)
…nal host redirection [EXP-37] (#45866) ## Summary In one case in `expo-router` and the redirect case in `expo-server`, it's possible for catch-all routes to generate leading `//` values, which then causes the redirect to be interpreted with an arbitrary hostname target. ## 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) - [ ] 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)
Fixes `<Host modifiers={...}>` being silently dropped on iOS.
`HostProps` (TS) already extends `CommonViewModifierProps` and
`Host/index.tsx` already forwards `modifiers` to the native view, but
`HostViewProps` (Swift) never declared the field. The prop got dropped
during deserialization and every typechecked modifier on `Host` was a
no-op no matter what you passed.
The fix is generic across the registered modifier surface. Once
`HostViewProps` accepts the field and `HostView.body` chains
`.applyModifiers(...)`, the same `ViewModifierRegistry` dispatch path
that already handles every modifier on `UIBaseView` and `TextView`
becomes available to `Host`. One field plus one chain restores the
entire registered set in a single shot. Environment propagation (`tint`,
`font`, `foregroundStyle`, `disabled`), layout (`frame`, `padding`),
chrome (`background`, `clipShape`, `border`, `shadow`), transforms
(`rotationEffect`, `scaleEffect`), filters (`blur`, `opacity`,
`grayscale`), gestures (`onTapGesture`), and iOS 26 Liquid Glass
(`glassEffect`).
```tsx
import { Host, Toggle, Slider, Button, VStack } from '@expo/ui/swift-ui';
import {
tint, font, foregroundStyle, padding, background, clipShape, shadow,
} from '@expo/ui/swift-ui/modifiers';
<Host
matchContents
modifiers={[
tint('#A78BFA'),
font({ size: 16, weight: 'semibold', design: 'rounded' }),
foregroundStyle('#0F172A'),
padding({ all: 16 }),
background('#FFF'),
clipShape('roundedRectangle', 16),
shadow({ radius: 12, y: 6, color: '#33' }),
]}>
<VStack>
<Toggle isOn={enabled} onIsOnChange={setEnabled} label="Notifications" />
<Slider value={volume} onValueChange={setVolume} min={0} max={1} />
<Button label="Save" onPress={save} />
{/* every nested control inherits the cascade */}
</VStack>
</Host>
```
# Test Plan
Test repro with screenshots here:
[`ramonclaudio/expo-ui-host-modifiers-45872-repro`](https://github.com/ramonclaudio/expo-ui-host-modifiers-45872-repro).
The README walks through all 15 cards so you can preview the demo
without rebuilding.
Smoke-tested on iPhone 17 Pro simulator (iOS 26.5, Xcode 26.5) via
`apps/native-component-list`:
- `pnpm build`, `pnpm lint --max-warnings 0`, and `pnpm test` (9 suites,
50 tests) all green in `packages/expo-ui`.
- `et generate-docs-api-data -p expo-ui` produces no diffs caused by
this PR. The TypeScript surface is unchanged so there's nothing to
regenerate. The only diffs it surfaced were unrelated drift from other
PRs, which I discarded.
- Modifiers screen in `apps/native-component-list` renders descendant
`Toggle`, `Picker`, `Slider`, and `Stepper` tinted in `#FF6B6B` and in
`font({ size: 16, weight: 'medium', design: 'rounded' })` once the outer
`Host` is wrapped in the two-modifier chain. Removing the `@Field var
modifiers` from `HostViewProps` and rebuilding makes both effects vanish
at once.
- Standalone repro renders 15 side-by-side cards covering every category
against an unmodified Host. Environment (`tint`, `font`,
`foregroundStyle`, `disabled`), chrome (`background`, `cornerRadius`,
`border`, `shadow` stacked), transforms (`rotationEffect`,
`scaleEffect`), filters (`blur`, `opacity`, `grayscale`), interaction
(`onTapGesture`), and iOS 26 Liquid Glass (`glassEffect`). With the
patch removed, every "WITH MODIFIER" column looks identical to the
default.
Force the mangle hook's xcodebuild invocation to use `SYMROOT=build` so build products are emitted under ios/Pods/build, matching the directory scanned for symbols. # Why `expo-brownfield` runs an `xcodebuild` step while generating iOS mangling definitions, then scans `ios/Pods/build` for the built products. Without an explicit build root, Xcode can emit the products somewhere else, leaving the scanner with incomplete symbols and causing generated mangling defines to be incorrect. Fixes #45801 # How Passes `SYMROOT=build` to the mangle hook’s `xcodebuild` invocation so build products are emitted under ios/Pods/build, matching the directory the mangle scanner already expects. # Test Plan - Verified in a brownfield repro that fresh pod install regenerates mangling definitions for multiple apps. - Verified `ios/Pods/build/Release-iphonesimulator` is populated after the mangle build. - Verified the host app builds and launches, and both embedded apps open successfully # 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) --------- Co-authored-by: Gabriel Donadel <donadeldev@gmail.com>
… to Expo CLI [EXP-11] (#45832) ## Summary Stacked on #45831 We should use the new API in `@expo/env` to pass the original system env to the Expo CLI, since we're otherwise "upgrading" the loaded environment variables with the ones already loaded in `expo-doctor`. Additionally, this PR adds a check to ensure that `*.local` env files aren't committed to source control, similar to the other checks for this. This is already recommended in the docs, but not captured: https://docs.expo.dev/guides/environment-variables/#using-multiple-env-files-to-define-separate-environments ## Set of changes - Pass `env` as `getOriginalEnv()` to `expo` commands - Add `EnvLocalFilesCheck` ## 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) - [ ] 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)
# Why
When we start adding more integrations it would be neat to have them
grouped under one object property, rather then top level one.
This PR changes the router integration API from
```ts
ExpoObserve.configure({
disableRouterIntegration: false
});
```
to
```ts
ExpoObserve.configure({
integrations: {
'expo-router': true,
},
});
```
Such API gives us more flexibility in the future allowing for per
integration configuration
```ts
ExpoObserve.configure({
integrations: {
'xyz': { 'a': '123' },
},
});
```
# How
1. Change the types to reflect new API
2. Pass the whole `integrations` object to native side
3. Disable expo router by default
# Test Plan
1. CI
2. Manual testing in observe-tester
# 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)
…45974) ## Why Fixes #45292. `packages/expo-notifications/android/build.gradle` ships a `proguard-rules.pro` containing `-keep class expo.modules.notifications.** {*;}`, but never declares `consumerProguardFiles 'proguard-rules.pro'`, so the rule is **never** applied to consumer apps' R8 pass. In a signed release build with R8 enabled (the typical Expo setup via `expo-build-properties.enableProguardInReleaseBuilds: true`): - `NotificationRequest`, `NotificationContent`, and `NotificationTrigger` subclasses get obfuscated (e.g. `expo.modules.notifications.notifications.model.NotificationRequest` → `V6.g`). - `SharedPreferencesNotificationsStore` serializes these classes to `SharedPreferences` via `ObjectOutputStream`, then reads them back via `ObjectInputStream.readObject()`. - `readObject()` throws `ClassNotFoundException`, which the store silently swallows and returns `null` per entry. - `Notifications.getAllScheduledNotificationsAsync()` therefore returns `[]` regardless of how many notifications were scheduled. - The `AlarmManager` broadcast also fails to deserialize on its scheduled trigger time → **no scheduled notifications ever fire**. - All of this is silent — no log, no error surfaced to JS. ## How One-line addition inside the existing `defaultConfig` block, mirroring the pattern already used by sibling packages — e.g. [`expo-modules-core/android/build.gradle`](https://github.com/expo/expo/blob/main/packages/expo-modules-core/android/build.gradle): ```diff defaultConfig { versionCode 21 versionName '56.0.9' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles 'proguard-rules.pro' } ``` The `proguard-rules.pro` file already exists in the package; only the directive that wires it up was missing. ## Test plan - [ ] Build a release AAB of an Expo app with `expo-notifications` and `expo-build-properties.enableProguardInReleaseBuilds: true` against this branch. - [ ] Schedule a notification with `Notifications.scheduleNotificationAsync({ trigger: { type: 'date', date: Date.now() + 60_000 }, content: { title: 'X', body: 'Y' } })`. - [ ] `Notifications.getAllScheduledNotificationsAsync()` returns the scheduled entry (not `[]`). - [ ] Notification fires at the scheduled time. - [ ] Reproduce the failure mode by building the same app against `main` without this patch — `getAllScheduledNotificationsAsync()` returns `[]` and nothing fires. --- cc @vonovak — you asked for a PR with a fix on the issue. cc @a-resh — original reporter; happy to defer if you already have a PR in progress, just let me know. --------- Co-authored-by: Vojtech Novak <vonovak@gmail.com>
# Why The `getFavorite()` and `setFavorite()` functions are already supported on iOS. This PR adds support for these functions on Android. # How - The `MediaStore.MediaColumns.IS_FAVORITE` column on Android tells us whether an asset is marked as a favorite. Unfortunately, it wasn't added until Android 11, which means that third-party system gallery apps developed their own workarounds. Consequently, marking an asset as a favorite using the `setFavorite` method might not be visible in them. - Extended the `AssetDelegate` interface and implemented the functions for `AssetModernDelegate` and `AssetLegacyDelegate`. # Test Plan Removed the iOS-only condition from the already existing tests in BareExpo ✅
# Why `useObserveForRouter` had an inline guard that throws if the router integration is toggled on/off during a screen's lifecycle. The pattern — snapshot the initial value in a ref, compare on every render, throw on mismatch — is reusable, and we'll want it again as more integrations land. # How 1. Extract a `useAssertValueDoesNotChange(value, error)` hook in `src/useAssertValueDoesNotChange.ts` — reference-equality check against the initial render value, throws `error` on mismatch. 2. Replace the inline ref/throw in `useObserveForRouter` with a call to the new hook. 3. Re-export `isInitialized` as `isExpoRouterInitialized` from the expo-router integration barrel for clarity at call sites. 4. In `useObserve` call `useObserveForRouter` conditionally only when router is enabled 5. Add native unit tests covering: initial render, stable rerenders, value change, reference equality on equal-shape objects, independent sibling instances, undefined → undefined, and undefined → defined transitions. # Test Plan 1. CI 2. `useAssertValueDoesNotChange.test.native.tsx` # 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)
…ons on Android via the `EXPO_ROUTER_DISABLE_NATIVE_TABS_MD` environment variable (#45857) # Why Solves: #43614 # How 1. Add the `EXPO_ROUTER_DISABLE_NATIVE_TABS_MD` env 2. When it's set to true replace `'expo-router/build/native-tabs/utils/materialIconConverter.android.js',` with `'expo-router/build/native-tabs/utils/materialIconConverter-not-implemented.js'` # Test Plan 1. CI 2. Router e2e `EXPO_ROUTER_DISABLE_NATIVE_TABS_MD=1 pnpm start:native-navigation --clear` <img height="512" alt="Screenshot_1778865586" src="https://github.com/user-attachments/assets/3c453392-35a1-4b02-95f2-09ecbcd763d3" /> `pnpm start:native-navigation` <img height="512" alt="Screenshot_1778865489" src="https://github.com/user-attachments/assets/092f138e-0d23-4e12-a998-3907ed90f7f2" /> <img width="832" height="163" alt="image" src="https://github.com/user-attachments/assets/2745ff3f-beb2-4fd9-b0a0-b4f0ab5090aa" /> # 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) - [ ] 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)
# Why `bare-expo` (via `native-component-list` and `test-suite`) is one of the apps we exercise with `expo-observe`, but the entry screens never called `markInteractive()`. That means TTI/interactive metrics for those flows were missing or inaccurate, making it harder to dogfood `expo-observe` against a real app. # How 1. Add `expo-observe` as a workspace dependency to `native-component-list` and `test-suite`. 2. Call `useObserve().markInteractive()` from the screens that act as the interactive landing surface: - `ComponentListScreen` - `Screens/index` `MainScreen` (converted from a class to a function component so it can use hooks) - `test-suite` `SelectScreen` # Test Plan 1. CI 2. Manual testing in bare-expo — verified `markInteractive` fires and shows up in `expo-observe` metrics. # 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)
…tead of `android.adaptiveIcon` (#45704) Why: - Closes #17969. - When both `android.icon` and `android.adaptiveIcon.foregroundImage` were configured, `@expo/prebuild-config` used the adaptive foreground image for all Android launcher icon outputs. That made legacy Android launcher icons use the inset adaptive foreground instead of the explicit legacy `android.icon`. How: - Keep `android.icon` as the source for legacy `ic_launcher.webp` and `ic_launcher_round.webp` when it is provided. - Keep `android.adaptiveIcon.foregroundImage` as the source for adaptive foreground assets on Android 8+. - Preserve the existing fallback for projects that only provide adaptive icon config by generating pseudo-adaptive legacy icons from the adaptive assets. - Added focused coverage that writes distinct legacy and adaptive assets and verifies the generated legacy and adaptive files use the intended sources. - Rebuilt `@expo/prebuild-config` generated output. Test Plan: - `pnpm --filter @expo/prebuild-config test -- withAndroidIcons-test` passed: 1 suite, 10 tests. - `pnpm --filter @expo/prebuild-config lint` passed. - `pnpm --filter @expo/prebuild-config build` passed. - `pnpm --filter @expo/prebuild-config test` passed: 12 suites, 69 tests, 6 snapshots. - `git diff --cached --check` passed before commit. Risk: - Source files changed: 1. - Test files changed: 1. - Changelog files changed: 1. - Generated build files changed: 3. - No native runtime or docs changes. - Behavioral scope is limited to Android launcher icon asset generation in `@expo/prebuild-config`.
## Summary Accidentally inverted check from recent change. Tests caught this ## 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) - [ ] 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: Expo Bot <34669131+expo-bot@users.noreply.github.com>
## Summary See: expo/spawn-async#55 ## 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) - [ ] 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 : )