Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
4420224
[core][android] Fix crash flushing a shadow node size update to a des…
intergalacticspacehighway Jun 11, 2026
910e35f
[docs] Add multi-pm (package managers)Terminal blocks in multiple sec…
amandeepmittal Jun 11, 2026
dff07d8
[docs] Clarify `faceIDPermission` false option in LocalAuthenticatio…
amandeepmittal Jun 11, 2026
efb38b2
[docs] Add info on building app variants locally with `expo run` (#46…
amandeepmittal Jun 11, 2026
3f898e1
[docs] Update SDK package versions for all SDK references (#46709)
amandeepmittal Jun 11, 2026
407a25d
[gha][docs] Sync bundled native module versions on deploy (#46710)
amandeepmittal Jun 11, 2026
a35f14c
[docs] Convert screenshots to WebP in multiple docs (#46742)
amandeepmittal Jun 11, 2026
c72156d
[docs] Add AI agent quick start guides and migrate MCP page to /mcp (…
amandeepmittal Jun 11, 2026
900a2e5
[expo-type-information] Emit events declared in the native module (#4…
HubertBer Jun 11, 2026
cdb7a33
[expo-video][e2e] Gate player output viewshot on first frame render (…
zoontek Jun 11, 2026
7e1e669
[ci] Attempt to fix React Native nightly and Publish Canaries workflo…
zoontek Jun 11, 2026
5c72d53
[media-library] Add `Query.exeForMetadata()` for bulk fetch (#46485)
Wenszel Jun 11, 2026
1e7289f
[core][Android] Ignore already-settled promises (#46770)
jakex7 Jun 11, 2026
461bc92
[ui][iOS] Added the SwiftUI `activityBackgroundTint` modifier (#46756)
jakex7 Jun 11, 2026
a9e782d
[ci] Update setup-java action (#46793)
zoontek Jun 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/android-instrumentation-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
- name: 🧹 Cleanup GitHub Linux runner disk space
uses: ./.github/actions/cleanup-linux-disk-space
- name: 🔨 Use JDK 17
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '17'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/android-unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
- name: 🧹 Cleanup GitHub Linux runner disk space
uses: ./.github/actions/cleanup-linux-disk-space
- name: 🔨 Use JDK 17
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '17'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/development-client-latest-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- name: 💎 Install cocoapods
run: sudo gem install cocoapods
- name: 🔨 Use JDK 11
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '11'
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ jobs:
fail_on_error: true
# Override vale-action's older bundled reviewdog to avoid large-diff limits.
reviewdog_url: https://github.com/reviewdog/reviewdog/releases/download/v0.21.0/reviewdog_0.21.0_Linux_x86_64.tar.gz
- name: 🔄 Sync bundled native module versions
working-directory: docs
run: pnpm versions-schema-sync
continue-on-error: true
timeout-minutes: 1
- name: 🏗️ Build Docs website for deploy
working-directory: docs
run: pnpm export
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/expo-go-android-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
- name: 🧹 Cleanup GitHub Linux runner disk space
uses: ./.github/actions/cleanup-linux-disk-space
- name: 🔨 Use JDK 17
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '17'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-canaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
cache: 'pnpm'
registry-url: https://registry.npmjs.org/
- name: 🔨 Use JDK 17
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '17'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-react-native-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ jobs:
node-version: 20
cache: 'pnpm'
- name: 🔨 Use JDK 17
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '17'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-suite-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ jobs:
with:
bun-version: 1.x
- name: 🔨 Use JDK 17
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '17'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ jobs:
with:
bun-version: 1.x
- name: 🔨 Use JDK 17
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'temurin'
java-version: '17'
Expand Down
16 changes: 16 additions & 0 deletions apps/bare-expo/e2e/expo-video/player-output-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ jsEngine: graaljs
visible: 'Players ready'
timeout: 30000
- tapOn: 'Move player 1 to the next video view'
- extendedWaitUntil:
visible:
id: 'viewshot-ready'
timeout: 10000
- runFlow:
file: ../_nested-flows/viewshot-comparison.yaml
env:
Expand All @@ -18,6 +22,10 @@ jsEngine: graaljs
text: 'Move player 2 to the next video view'
repeat: 2
- tapOn: 'Move player 1 to the next video view'
- extendedWaitUntil:
visible:
id: 'viewshot-ready'
timeout: 10000
- runFlow:
file: ../_nested-flows/viewshot-comparison.yaml
env:
Expand All @@ -26,6 +34,10 @@ jsEngine: graaljs
mode: 'keep-originals'
- tapOn: 'Move player 1 to first video view'
- tapOn: 'Move player 2 to first video view'
- extendedWaitUntil:
visible:
id: 'viewshot-ready'
timeout: 10000
- runFlow:
file: ../_nested-flows/viewshot-comparison.yaml
env:
Expand All @@ -40,6 +52,10 @@ jsEngine: graaljs
- tapOn:
text: 'Move player 1 to the next video view'
repeat: 2
- extendedWaitUntil:
visible:
id: 'viewshot-ready'
timeout: 10000
- runFlow:
file: ../_nested-flows/viewshot-comparison.yaml
env:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEvent } from 'expo';
import { useVideoPlayer, VideoPlayer, VideoView } from 'expo-video';
import React, { useCallback, useRef, useState } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import { Platform, View, StyleSheet, Text } from 'react-native';

import { bigBuckBunnySource, elephantsDreamSource } from './videoSources';
import { styles } from './videoStyles';
Expand Down Expand Up @@ -39,6 +39,27 @@ export default function VideoChangePlayerOutputScreen() {

const [viewPlayers, setViewPlayers] = useState([player, player2, null, null]);

// Per-view "frame painted" state to gate e2e screenshots: a swapped iOS VideoView stays blank until
// ready, so we mark it not-ready on swap and flip it back from `onFirstFrameRender`. Optimistic so
// other platforms don't gate.
const [readyViews, setReadyViews] = useState([true, true, true, true]);

const framesSettled = viewPlayers.every(
(viewPlayer, index) => viewPlayer == null || readyViews[index]
);

const markViewRendered = useCallback((viewIndex: number) => {
setReadyViews((prev) => {
if (prev[viewIndex]) {
return prev;
}

const next = [...prev];
next[viewIndex] = true;
return next;
});
}, []);

const advancePlayer = useCallback(
(playerIndex: number) => {
const currentIndex = players.current[playerIndex].viewIndex;
Expand All @@ -59,6 +80,15 @@ export default function VideoChangePlayerOutputScreen() {
newViewPlayers[newViewIndex] = players.current[playerIndex].ref;
setViewPlayers(newViewPlayers);

// The view receiving the player must repaint; mark it not-ready until `onFirstFrameRender` fires.
if (Platform.OS === 'ios') {
setReadyViews((prev) => {
const next = [...prev];
next[newViewIndex] = false;
return next;
});
}

players.current[playerIndex].viewIndex = newViewIndex;
},
[viewPlayers, useIncorrectReplace]
Expand All @@ -79,6 +109,7 @@ export default function VideoChangePlayerOutputScreen() {
player={viewPlayers[i]}
nativeControls={nativeControls}
allowsVideoFrameAnalysis={false}
onFirstFrameRender={() => markViewRendered(i)}
/>
))}
</E2EViewShotContainer>
Expand Down Expand Up @@ -112,6 +143,7 @@ export default function VideoChangePlayerOutputScreen() {
}}
/>
{e2eSetupDone && bothReady && <Text>Players ready</Text>}
{framesSettled && <Text testID="viewshot-ready">Viewshot ready</Text>}
</View>
);
}
Expand Down
48 changes: 48 additions & 0 deletions apps/test-suite/tests/MediaLibraryNext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,54 @@ export async function test(t) {
t.expect(secondAsset.id).toBe(shorterAsset.id);
t.expect(thirdAsset.id).toBe(tallerAsset.id);
});

t.it('exeForMetadata works correctly for images', async () => {
// given
const asset = await Asset.create(pngFile.localUri);
assetsContainer.push(asset);
const albumName = createAlbumName('exeForMetadata works correctly for images');
const album = await Album.create(albumName, [asset]);
albumsContainer.push(album);
// when
const results = await new Query().album(album).exeForMetadata();
// then
t.expect(results.length).toBe(1);
const result = results[0];
t.expect(result.id).toBeDefined();
t.expect(result.creationTime).toBeDefined();
t.expect(result.duration).toBe(null);
t.expect(result.filename.toLowerCase()).toMatch(/\.png/);
t.expect(result.height).toBeGreaterThan(0);
t.expect(result.mediaType).toBeDefined();
t.expect(new Date(result.modificationTime).getFullYear()).toBeGreaterThan(1970);
t.expect(result.modificationTime).toBeGreaterThan(0);
t.expect(result.width).toBeGreaterThan(0);
t.expect(result.isFavorite).toBe(false);
});

t.it('exeForMetadata works correctly for videos', async () => {
// given
const asset = await Asset.create(mp4File.localUri);
assetsContainer.push(asset);
const albumName = createAlbumName('exeForMetadata works correctly for videos');
const album = await Album.create(albumName, [asset]);
albumsContainer.push(album);
// when
const results = await new Query().album(album).exeForMetadata();
// then
t.expect(results.length).toBe(1);
const result = results[0];
t.expect(result.id).toBeDefined();
t.expect(result.creationTime).toBeDefined();
t.expect(result.duration).toBeGreaterThan(0);
t.expect(result.filename.toLowerCase()).toMatch(/\.mp4/);
t.expect(result.height).toBeGreaterThan(0);
t.expect(result.mediaType).toBeDefined();
t.expect(new Date(result.modificationTime).getFullYear()).toBeGreaterThan(1970);
t.expect(result.modificationTime).toBeGreaterThan(0);
t.expect(result.width).toBeGreaterThan(0);
t.expect(result.isFavorite).toBe(false);
});
});

t.describe('asset.getAlbums()', () => {
Expand Down
3 changes: 3 additions & 0 deletions docs/.vale/writing-styles/expo-docs/HeadingCase.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,19 @@ exceptions:
- '.*CLI.*'
- '.*TTI.*'
- '.*Classic Updates.*'
- '.*Claude Code.*'
- '.*Clerk.*'
- '.*CNG.*'
- '.*CocoaPods.*'
- '.*CodePush.*'
- '.*Codex.*'
- '.*Convex.*'
- '.*Command Line Tools.*'
- '.*Config Plugin.*'
- '.*CORS.*'
- '.*CRUD.*'
- '.*credentials\.json.*'
- '.*Cursor.*'
- '.*DevTools.*'
- '.*Developer Console.*'
- '.*Developer Mode.*'
Expand Down
3 changes: 3 additions & 0 deletions docs/common/client-redirects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ const RENAMED_PAGES: Record<string, string> = {
'/develop/development-builds/installation/': '/develop/development-builds/create-a-build/',
'/develop/development-builds/parallel-installation': '/build-reference/variants/',

// MCP server moved out of the EAS section to the top-level /mcp route
'/eas/ai/mcp/': '/mcp/',

// Picker replaced by SegmentedButton
'/versions/latest/sdk/ui/jetpack-compose/picker/':
'/versions/latest/sdk/ui/jetpack-compose/segmentedbutton/',
Expand Down
16 changes: 14 additions & 2 deletions docs/constants/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const homeDirectories = [
'deploy',
'review',
'monitoring',
'agents',
];
/** Manual list of directories to categorize as "Learn" */
const learnDirectories = ['tutorial', 'additional-resources'];
Expand Down Expand Up @@ -73,7 +74,19 @@ export const home = [
makePage('get-started/start-developing.mdx'),
makePage('get-started/next-steps.mdx'),
]),
makeSection('AI', [makePage('skills.mdx'), makePage('llms.mdx')]),
makeSection('AI', [
makePage('agents/index.mdx'),
makePage('skills.mdx'),
makePage('mcp.mdx'),
makeGroup(
'AI agents',
[makePage('agents/claude.mdx'), makePage('agents/codex.mdx'), makePage('agents/cursor.mdx')],
{
expanded: false,
}
),
makePage('llms.mdx'),
]),
makeSection('Develop', [
makePage('develop/tools.mdx'),
makePage('develop/app-navigation.mdx'),
Expand Down Expand Up @@ -445,7 +458,6 @@ export const eas = [
expanded: true,
}
),
makeSection('AI', [makePage('eas/ai/mcp.mdx')]),
makeSection('EAS Workflows', [
makePage('eas/workflows/introduction.mdx'),
makePage('eas/workflows/get-started.mdx'),
Expand Down
1 change: 0 additions & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
"prismjs": "^1.30.0",
"prop-types": "^15.8.1",
"react": "^19.2.6",
"react-confetti-explosion": "^3.0.3",
"react-diff-view": "^3.3.3",
"react-dom": "^19.2.6",
"react-markdown": "^10.1.0",
Expand Down
Loading
Loading