From fefae0d76ae003fe4aa112b6eb16b0c849d43b7f Mon Sep 17 00:00:00 2001 From: Kadi Kraman Date: Tue, 26 May 2026 16:57:07 +0100 Subject: [PATCH 1/8] [docs] Reverse the tabs in observe (#46305) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Why We currently show 55 instructions first in tabs, but should be the opposite # How Reverse the tabs # Test Plan 👀 # Checklist - [ ] 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) --- docs/pages/eas/observe/get-started.mdx | 34 ++++++++-------- docs/pages/eas/observe/reference/metrics.mdx | 40 +++++++++---------- .../eas/observe/reference/troubleshooting.mdx | 32 +++++++-------- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/docs/pages/eas/observe/get-started.mdx b/docs/pages/eas/observe/get-started.mdx index 7e8ab8898ab307..35c2962b7f0d6d 100644 --- a/docs/pages/eas/observe/get-started.mdx +++ b/docs/pages/eas/observe/get-started.mdx @@ -51,32 +51,32 @@ Wrap your root layout with `AppMetricsRoot` (SDK 55) or `ObserveRoot` (SDK 56 an - + ```tsx app/_layout.tsx import { Stack } from 'expo-router'; -import { AppMetricsRoot } from 'expo-observe'; +import { ObserveRoot } from 'expo-observe'; function RootLayout() { return ; } -export default AppMetricsRoot.wrap(RootLayout); +export default ObserveRoot.wrap(RootLayout); ``` - + ```tsx app/_layout.tsx import { Stack } from 'expo-router'; -import { ObserveRoot } from 'expo-observe'; +import { AppMetricsRoot } from 'expo-observe'; function RootLayout() { return ; } -export default ObserveRoot.wrap(RootLayout); +export default AppMetricsRoot.wrap(RootLayout); ``` @@ -98,12 +98,12 @@ Call `markInteractive()` when your app is fully ready for user interaction. This - + ```tsx app/_layout.tsx import { Stack } from 'expo-router'; import * as SplashScreen from 'expo-splash-screen'; -import { AppMetrics, AppMetricsRoot } from 'expo-observe'; +import { ObserveRoot, useObserve } from 'expo-observe'; import { useEffect, useState } from 'react'; // Keep the splash screen visible while we fetch resources @@ -111,6 +111,7 @@ SplashScreen.preventAutoHideAsync(); function RootLayout() { const [isReady, setIsReady] = useState(false); + const { markInteractive } = useObserve(); useEffect(() => { async function prepare() { @@ -130,9 +131,9 @@ function RootLayout() { useEffect(() => { if (isReady) { SplashScreen.hide(); - AppMetrics.markInteractive(); + markInteractive(); } - }, [isReady]); + }, [isReady, markInteractive]); if (!isReady) { return null; @@ -141,17 +142,17 @@ function RootLayout() { return ; } -export default AppMetricsRoot.wrap(RootLayout); +export default ObserveRoot.wrap(RootLayout); ``` - + ```tsx app/_layout.tsx import { Stack } from 'expo-router'; import * as SplashScreen from 'expo-splash-screen'; -import { ObserveRoot, useObserve } from 'expo-observe'; +import { AppMetrics, AppMetricsRoot } from 'expo-observe'; import { useEffect, useState } from 'react'; // Keep the splash screen visible while we fetch resources @@ -159,7 +160,6 @@ SplashScreen.preventAutoHideAsync(); function RootLayout() { const [isReady, setIsReady] = useState(false); - const { markInteractive } = useObserve(); useEffect(() => { async function prepare() { @@ -179,9 +179,9 @@ function RootLayout() { useEffect(() => { if (isReady) { SplashScreen.hide(); - markInteractive(); + AppMetrics.markInteractive(); } - }, [isReady, markInteractive]); + }, [isReady]); if (!isReady) { return null; @@ -190,7 +190,7 @@ function RootLayout() { return ; } -export default ObserveRoot.wrap(RootLayout); +export default AppMetricsRoot.wrap(RootLayout); ``` diff --git a/docs/pages/eas/observe/reference/metrics.mdx b/docs/pages/eas/observe/reference/metrics.mdx index 5433e06d3d0f7f..c9c6856ec323f4 100644 --- a/docs/pages/eas/observe/reference/metrics.mdx +++ b/docs/pages/eas/observe/reference/metrics.mdx @@ -102,15 +102,15 @@ This metric is not reported automatically. To start measuring it, call `markInte - + -Call `AppMetrics.markInteractive()` from anywhere in your app. +Call `markInteractive()` from the `useObserve()` hook inside a component. - + -Call `markInteractive()` from the `useObserve()` hook inside a component. +Call `AppMetrics.markInteractive()` from anywhere in your app. @@ -163,12 +163,14 @@ You can attach your own params to the TTI event by passing them to `markInteract - + ```tsx -import { AppMetrics } from 'expo-observe'; +import { useObserve } from 'expo-observe'; -AppMetrics.markInteractive({ +const { markInteractive } = useObserve(); + +markInteractive({ params: { tenant: 'acme', cohort: 'beta', @@ -179,14 +181,12 @@ AppMetrics.markInteractive({ - + ```tsx -import { useObserve } from 'expo-observe'; - -const { markInteractive } = useObserve(); +import { AppMetrics } from 'expo-observe'; -markInteractive({ +AppMetrics.markInteractive({ params: { tenant: 'acme', cohort: 'beta', @@ -203,12 +203,14 @@ You can also override the route name attached to the event, which is otherwise p - + ```tsx -import { AppMetrics } from 'expo-observe'; +import { useObserve } from 'expo-observe'; -AppMetrics.markInteractive({ +const { markInteractive } = useObserve(); + +markInteractive({ routeName: '/feed', params: { cacheHit: true }, }); @@ -216,14 +218,12 @@ AppMetrics.markInteractive({ - + ```tsx -import { useObserve } from 'expo-observe'; - -const { markInteractive } = useObserve(); +import { AppMetrics } from 'expo-observe'; -markInteractive({ +AppMetrics.markInteractive({ routeName: '/feed', params: { cacheHit: true }, }); diff --git a/docs/pages/eas/observe/reference/troubleshooting.mdx b/docs/pages/eas/observe/reference/troubleshooting.mdx index a82fcbd428b4ef..a28658ff0b9089 100644 --- a/docs/pages/eas/observe/reference/troubleshooting.mdx +++ b/docs/pages/eas/observe/reference/troubleshooting.mdx @@ -23,30 +23,30 @@ Verify that your root layout is wrapped with the root HOC: - + ```jsx -import { AppMetricsRoot } from 'expo-observe'; +import { ObserveRoot } from 'expo-observe'; function RootLayout() { return (/* your layout */); } -export default AppMetricsRoot.wrap(RootLayout); +export default ObserveRoot.wrap(RootLayout); ``` - + ```jsx -import { ObserveRoot } from 'expo-observe'; +import { AppMetricsRoot } from 'expo-observe'; function RootLayout() { return (/* your layout */); } -export default ObserveRoot.wrap(RootLayout); +export default AppMetricsRoot.wrap(RootLayout); ``` @@ -59,16 +59,16 @@ This metric requires manual instrumentation. Verify that: - + -1. You are calling `AppMetrics.markInteractive()` after your splash screen is hidden. +1. You are calling `markInteractive()` (from `useObserve()`) after your splash screen is hidden. 2. The call is actually being executed (add a `console.log` to verify). - + -1. You are calling `markInteractive()` (from `useObserve()`) after your splash screen is hidden. +1. You are calling `AppMetrics.markInteractive()` after your splash screen is hidden. 2. The call is actually being executed (add a `console.log` to verify). @@ -127,30 +127,30 @@ After: - + ```jsx -import { AppMetricsRoot } from 'expo-observe'; +import { ObserveRoot } from 'expo-observe'; function RootLayout() { return (/* your layout */); } -export default AppMetricsRoot.wrap(RootLayout); +export default ObserveRoot.wrap(RootLayout); ``` - + ```jsx -import { ObserveRoot } from 'expo-observe'; +import { AppMetricsRoot } from 'expo-observe'; function RootLayout() { return (/* your layout */); } -export default ObserveRoot.wrap(RootLayout); +export default AppMetricsRoot.wrap(RootLayout); ``` From 48c1a22dc757bedb6921ce48838e8ffe35690454 Mon Sep 17 00:00:00 2001 From: Mathieu Acthernoene Date: Tue, 26 May 2026 18:41:37 +0200 Subject: [PATCH 2/8] [expo-splash-screen] Remove applyImageToSplashScreenXML arg defaults (#46307) --- .../expo-splash-screen/plugin/build/InterfaceBuilder.d.ts | 4 ++-- .../expo-splash-screen/plugin/build/InterfaceBuilder.js | 2 +- .../expo-splash-screen/plugin/src/InterfaceBuilder.ts | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/expo-splash-screen/plugin/build/InterfaceBuilder.d.ts b/packages/expo-splash-screen/plugin/build/InterfaceBuilder.d.ts index 54aeddaa99e8a8..3d39940197aada 100644 --- a/packages/expo-splash-screen/plugin/build/InterfaceBuilder.d.ts +++ b/packages/expo-splash-screen/plugin/build/InterfaceBuilder.d.ts @@ -224,9 +224,9 @@ export declare function removeImageFromSplashScreen(xml: IBSplashScreenDocument, export declare function applyImageToSplashScreenXML(xml: IBSplashScreenDocument, { imageName, contentMode, backgroundColor, enableFullScreenImage, imageWidth, }: { imageName: string; contentMode: ImageContentMode; - backgroundColor?: string; + backgroundColor: string; enableFullScreenImage: boolean; - imageWidth?: number; + imageWidth: number; }): IBSplashScreenDocument; /** * IB does not allow two items to have the same ID. diff --git a/packages/expo-splash-screen/plugin/build/InterfaceBuilder.js b/packages/expo-splash-screen/plugin/build/InterfaceBuilder.js index 5d1be2c115d701..914e7a7d92cfa1 100644 --- a/packages/expo-splash-screen/plugin/build/InterfaceBuilder.js +++ b/packages/expo-splash-screen/plugin/build/InterfaceBuilder.js @@ -71,7 +71,7 @@ function getAbsoluteConstraints(childId, parentId, legacy = false) { createConstraint([childId, 'centerY'], [parentId, 'centerY']), ]; } -function applyImageToSplashScreenXML(xml, { imageName, contentMode, backgroundColor = '#ffffff', enableFullScreenImage, imageWidth = 100, }) { +function applyImageToSplashScreenXML(xml, { imageName, contentMode, backgroundColor, enableFullScreenImage, imageWidth, }) { const mainView = xml.document.scenes[0]?.scene[0]?.objects[0]?.viewController[0]?.view[0]; const rect = mainView?.rect[0]; const width = enableFullScreenImage ? 414 : imageWidth; diff --git a/packages/expo-splash-screen/plugin/src/InterfaceBuilder.ts b/packages/expo-splash-screen/plugin/src/InterfaceBuilder.ts index ff6c7029a94934..eb82f542d040a8 100644 --- a/packages/expo-splash-screen/plugin/src/InterfaceBuilder.ts +++ b/packages/expo-splash-screen/plugin/src/InterfaceBuilder.ts @@ -352,15 +352,15 @@ export function applyImageToSplashScreenXML( { imageName, contentMode, - backgroundColor = '#ffffff', + backgroundColor, enableFullScreenImage, - imageWidth = 100, + imageWidth, }: { imageName: string; contentMode: ImageContentMode; - backgroundColor?: string; + backgroundColor: string; enableFullScreenImage: boolean; - imageWidth?: number; + imageWidth: number; } ): IBSplashScreenDocument { const mainView = xml.document.scenes[0]?.scene[0]?.objects[0]?.viewController[0]?.view[0]; From 86a7539d956829bc4f5961e0838db9cb54a6e9cd Mon Sep 17 00:00:00 2001 From: Mathieu Acthernoene Date: Tue, 26 May 2026 19:13:50 +0200 Subject: [PATCH 3/8] Bump react-native-pager-view to 8.0.2 (#46309) # Why Bump `react-native-pager-view` to `8.0.2`, delete obsolete patch. # How Currently, deps are not aligned. # Test Plan # Checklist - [ ] 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) --- apps/bare-expo/ios/Podfile.lock | 12 +++-- apps/bare-expo/package.json | 2 +- apps/expo-go/ios/Podfile.lock | 8 ++-- apps/expo-go/package.json | 2 +- apps/native-component-list/package.json | 2 +- packages/expo/bundledNativeModules.json | 2 +- pnpm-lock.yaml | 47 +++---------------- .../patches/react-native-pager-view.patch | 13 ----- 8 files changed, 23 insertions(+), 65 deletions(-) delete mode 100644 tools/src/react-native-nightlies/patches/react-native-pager-view.patch diff --git a/apps/bare-expo/ios/Podfile.lock b/apps/bare-expo/ios/Podfile.lock index 2093311df47ce0..a87a2435f462b8 100644 --- a/apps/bare-expo/ios/Podfile.lock +++ b/apps/bare-expo/ios/Podfile.lock @@ -2319,7 +2319,7 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - react-native-pager-view (6.9.1): + - react-native-pager-view (8.0.2): - hermes-engine - RCTRequired - RCTTypeSafety @@ -2340,6 +2340,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - ReactNativeDependencies + - SwiftUIIntrospect (~> 1.0) - Yoga - react-native-safe-area-context (5.7.0): - hermes-engine @@ -3286,6 +3287,7 @@ PODS: - SDWebImageWebPCoder (0.14.6): - libwebp (~> 1.0) - SDWebImage/Core (~> 5.17) + - SwiftUIIntrospect (1.3.0) - TestExpoUi (1.0.0): - ExpoModulesCore - ExpoUI @@ -3472,7 +3474,7 @@ DEPENDENCIES: - "React-mutationobservernativemodule (from `../../../node_modules/.pnpm/react-native@0.86.0-rc.2_@babel+core@7.29.0_@react-native+jest-preset@0.86.0-rc.2_@babe_15430a234b5f1224b01b5b0cfcd0d009/node_modules/react-native/ReactCommon/react/nativemodule/mutationobserver`)" - "react-native-keyboard-controller (from `../../../node_modules/.pnpm/react-native-keyboard-controller@1.21.8_patch_hash=0a01a06c301b2ef0c02744515b2380fa632b_5d540240147b1e6a809a2e5dfc7f63ae/node_modules/react-native-keyboard-controller`)" - "react-native-netinfo (from `../../../node_modules/.pnpm/@react-native-community+netinfo@11.5.2_patch_hash=ced0cb79848978ecc3e780a4d812d94868434_1fde534caf42d9334de0b3d49ccd9bc7/node_modules/@react-native-community/netinfo`)" - - "react-native-pager-view (from `../../../node_modules/.pnpm/react-native-pager-view@6.9.1_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react-native_14432c7732db1b714e78f47c9f489141/node_modules/react-native-pager-view`)" + - "react-native-pager-view (from `../../../node_modules/.pnpm/react-native-pager-view@8.0.2_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react-native_6b4b0fdd3eb0bf5714ad508f011817e1/node_modules/react-native-pager-view`)" - "react-native-safe-area-context (from `../../../node_modules/.pnpm/react-native-safe-area-context@5.7.0_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react_6cf9b087dcc8c4e0435d8137de00cfae/node_modules/react-native-safe-area-context`)" - "react-native-segmented-control (from `../../../node_modules/.pnpm/@react-native-segmented-control+segmented-control@2.5.7_react-native@0.86.0-rc.2_@babel_413547125b3ab0390f55e29d9f9caef9/node_modules/@react-native-segmented-control/segmented-control`)" - "react-native-skia (from `../../../node_modules/.pnpm/@shopify+react-native-skia@2.4.18_react-native-reanimated@4.3.1_patch_hash=1e34e4238541_ebf101251c5227b8ebfcfaf0e464ed4b/node_modules/@shopify/react-native-skia`)" @@ -3543,6 +3545,7 @@ SPEC REPOS: - SDWebImageAVIFCoder - SDWebImageSVGCoder - SDWebImageWebPCoder + - SwiftUIIntrospect - ZXingObjC EXTERNAL SOURCES: @@ -3886,7 +3889,7 @@ EXTERNAL SOURCES: react-native-netinfo: :path: "../../../node_modules/.pnpm/@react-native-community+netinfo@11.5.2_patch_hash=ced0cb79848978ecc3e780a4d812d94868434_1fde534caf42d9334de0b3d49ccd9bc7/node_modules/@react-native-community/netinfo" react-native-pager-view: - :path: "../../../node_modules/.pnpm/react-native-pager-view@6.9.1_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react-native_14432c7732db1b714e78f47c9f489141/node_modules/react-native-pager-view" + :path: "../../../node_modules/.pnpm/react-native-pager-view@8.0.2_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react-native_6b4b0fdd3eb0bf5714ad508f011817e1/node_modules/react-native-pager-view" react-native-safe-area-context: :path: "../../../node_modules/.pnpm/react-native-safe-area-context@5.7.0_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react_6cf9b087dcc8c4e0435d8137de00cfae/node_modules/react-native-safe-area-context" react-native-segmented-control: @@ -4136,7 +4139,7 @@ SPEC CHECKSUMS: React-mutationobservernativemodule: f8d819437fb342b8ffe815acbb8eadd099eb22c6 react-native-keyboard-controller: b54dc0d54c67c3c62b7463a5600c1acadaff997a react-native-netinfo: 4319d381f35bc11b53dafebd5cd99c04c66a9fb4 - react-native-pager-view: a3cb9627d41fa2f31ad2b312af6e3f10f831f26d + react-native-pager-view: c9f0c94cc64041ac70f28f79527ea2ac664cf25c react-native-safe-area-context: 6b4966397ada0f7dd481e4486a2ef936834861a1 react-native-segmented-control: bf6e0032726727498e18dd437ae88afcdbc18e99 react-native-skia: 93613a9428b7f33530e5e085e95a89f023548320 @@ -4191,6 +4194,7 @@ SPEC CHECKSUMS: SDWebImageAVIFCoder: afe194a084e851f70228e4be35ef651df0fc5c57 SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380 + SwiftUIIntrospect: fee9aa07293ee280373a591e1824e8ddc869ba5d TestExpoUi: e376582270047f880c7e44afc7f912c97b14da54 UMAppLoader: b7d22886a244871c20b5a8f2fcea13c18534e677 WorkletsTester: 15a12097d67f73fd107ab7dc8236cab805e472b0 diff --git a/apps/bare-expo/package.json b/apps/bare-expo/package.json index 2cb89e914008bd..65dc999a94016a 100644 --- a/apps/bare-expo/package.json +++ b/apps/bare-expo/package.json @@ -86,7 +86,7 @@ "react-native": "0.86.0-rc.2", "react-native-gesture-handler": "~2.31.2", "react-native-keyboard-controller": "^1.21.8", - "react-native-pager-view": "6.9.1", + "react-native-pager-view": "8.0.2", "react-native-reanimated": "4.3.1", "react-native-safe-area-context": "5.7.0", "react-native-screens": "4.25.2", diff --git a/apps/expo-go/ios/Podfile.lock b/apps/expo-go/ios/Podfile.lock index 8d4292e53fb11e..3726ab2c0ff551 100644 --- a/apps/expo-go/ios/Podfile.lock +++ b/apps/expo-go/ios/Podfile.lock @@ -2668,7 +2668,7 @@ PODS: - ReactCommon/turbomodule/core - SocketRocket - Yoga - - react-native-pager-view (8.0.1): + - react-native-pager-view (8.0.2): - boost - DoubleConversion - fast_float @@ -4242,7 +4242,7 @@ DEPENDENCIES: - "react-native-keyboard-controller (from `../../../node_modules/.pnpm/react-native-keyboard-controller@1.21.8_patch_hash=0a01a06c301b2ef0c02744515b2380fa632b_5d540240147b1e6a809a2e5dfc7f63ae/node_modules/react-native-keyboard-controller`)" - "react-native-maps/Maps (from `../../../node_modules/.pnpm/react-native-maps@1.27.2_react-native-web@0.21.2_encoding@0.1.13_react-dom@19.2.3_react_5667e236c2c50f6a54d303a871dda30a/node_modules/react-native-maps`)" - "react-native-netinfo (from `../../../node_modules/.pnpm/@react-native-community+netinfo@12.0.1_patch_hash=ced0cb79848978ecc3e780a4d812d94868434_cc13d8903dabe0c21fe8763c1ffd52a0/node_modules/@react-native-community/netinfo`)" - - "react-native-pager-view (from `../../../node_modules/.pnpm/react-native-pager-view@8.0.1_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react-native_b05071ae89ad750c1f450711bb192a72/node_modules/react-native-pager-view`)" + - "react-native-pager-view (from `../../../node_modules/.pnpm/react-native-pager-view@8.0.2_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react-native_6b4b0fdd3eb0bf5714ad508f011817e1/node_modules/react-native-pager-view`)" - "react-native-safe-area-context (from `../../../node_modules/.pnpm/react-native-safe-area-context@5.7.0_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react_6cf9b087dcc8c4e0435d8137de00cfae/node_modules/react-native-safe-area-context`)" - "react-native-segmented-control (from `../../../node_modules/.pnpm/@react-native-segmented-control+segmented-control@2.5.7_react-native@0.86.0-rc.2_@babel_413547125b3ab0390f55e29d9f9caef9/node_modules/@react-native-segmented-control/segmented-control`)" - "react-native-skia (from `../../../node_modules/.pnpm/@shopify+react-native-skia@2.6.2_patch_hash=ba884424a75156115606f768b005e5af9a39e9836f1_17eda521ffc25cf5b86744e3438118bc/node_modules/@shopify/react-native-skia`)" @@ -4579,7 +4579,7 @@ EXTERNAL SOURCES: react-native-netinfo: :path: "../../../node_modules/.pnpm/@react-native-community+netinfo@12.0.1_patch_hash=ced0cb79848978ecc3e780a4d812d94868434_cc13d8903dabe0c21fe8763c1ffd52a0/node_modules/@react-native-community/netinfo" react-native-pager-view: - :path: "../../../node_modules/.pnpm/react-native-pager-view@8.0.1_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react-native_b05071ae89ad750c1f450711bb192a72/node_modules/react-native-pager-view" + :path: "../../../node_modules/.pnpm/react-native-pager-view@8.0.2_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react-native_6b4b0fdd3eb0bf5714ad508f011817e1/node_modules/react-native-pager-view" react-native-safe-area-context: :path: "../../../node_modules/.pnpm/react-native-safe-area-context@5.7.0_react-native@0.86.0-rc.2_@babel+core@7.29.0_@react_6cf9b087dcc8c4e0435d8137de00cfae/node_modules/react-native-safe-area-context" react-native-segmented-control: @@ -4827,7 +4827,7 @@ SPEC CHECKSUMS: react-native-keyboard-controller: d543b2ca3fd062e794b4087a3fe0340159545503 react-native-maps: b5af575a371e57847c6d8490e726c08036f7c80f react-native-netinfo: a0be8c77f8420a60ddf07eb87be1a36f02a1bd65 - react-native-pager-view: 899d0774fc9602b6a46eb2ac08febc09f470534d + react-native-pager-view: 2694b7efa49588b1cc3aecb5f513871135f499cc react-native-safe-area-context: befb5404eb8a16fdc07fa2bebab3568ecabcbb8a react-native-segmented-control: bf6e0032726727498e18dd437ae88afcdbc18e99 react-native-skia: fc73e9bdc46ebb420a98c9c2be29fee80f565e79 diff --git a/apps/expo-go/package.json b/apps/expo-go/package.json index 9f132325307240..94607593d6b8ea 100644 --- a/apps/expo-go/package.json +++ b/apps/expo-go/package.json @@ -86,7 +86,7 @@ "react-native-gesture-handler": "~2.31.2", "react-native-keyboard-controller": "^1.21.8", "react-native-maps": "1.27.2", - "react-native-pager-view": "8.0.1", + "react-native-pager-view": "8.0.2", "react-native-reanimated": "4.3.1", "react-native-safe-area-context": "5.7.0", "react-native-screens": "4.25.2", diff --git a/apps/native-component-list/package.json b/apps/native-component-list/package.json index 113f3985a5361a..c369d8ec118f90 100644 --- a/apps/native-component-list/package.json +++ b/apps/native-component-list/package.json @@ -150,7 +150,7 @@ "react-native-gesture-handler": "~2.31.2", "react-native-keyboard-controller": "^1.21.8", "react-native-maps": "1.27.2", - "react-native-pager-view": "8.0.0", + "react-native-pager-view": "8.0.2", "react-native-paper": "^5.12.5", "react-native-reanimated": "4.3.1", "react-native-safe-area-context": "5.7.0", diff --git a/packages/expo/bundledNativeModules.json b/packages/expo/bundledNativeModules.json index b860f2e6876ba5..b580a20b3b3f1f 100644 --- a/packages/expo/bundledNativeModules.json +++ b/packages/expo/bundledNativeModules.json @@ -104,7 +104,7 @@ "react-native-get-random-values": "~1.11.0", "react-native-keyboard-controller": "1.21.8", "react-native-maps": "1.27.2", - "react-native-pager-view": "8.0.1", + "react-native-pager-view": "8.0.2", "react-native-worklets": "0.8.3", "react-native-reanimated": "4.3.1", "react-native-screens": "4.25.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f107df927c717d..2e4833ca24775e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -233,8 +233,8 @@ importers: specifier: ^1.21.8 version: 1.21.8(patch_hash=0a01a06c301b2ef0c02744515b2380fa632b826ada5886db9eea481db01ce6a2)(react-native-reanimated@4.3.1(patch_hash=1e34e4238541638db96b94d5a2e974e73f3b801788a3d8f5c3f4b237a0559138)(react-native-worklets@0.8.3(patch_hash=3f49a21b44ba558989a3366eeff9c92ee331e18b736dbe89c5962ecc6f2802f1)(@babel/core@7.29.0)(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3))(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3))(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) react-native-pager-view: - specifier: 6.9.1 - version: 6.9.1(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) + specifier: 8.0.2 + version: 8.0.2(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) react-native-reanimated: specifier: 4.3.1 version: 4.3.1(patch_hash=1e34e4238541638db96b94d5a2e974e73f3b801788a3d8f5c3f4b237a0559138)(react-native-worklets@0.8.3(patch_hash=3f49a21b44ba558989a3366eeff9c92ee331e18b736dbe89c5962ecc6f2802f1)(@babel/core@7.29.0)(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3))(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) @@ -669,8 +669,8 @@ importers: specifier: 1.27.2 version: 1.27.2(react-native-web@0.21.2(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) react-native-pager-view: - specifier: 8.0.1 - version: 8.0.1(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) + specifier: 8.0.2 + version: 8.0.2(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) react-native-reanimated: specifier: 4.3.1 version: 4.3.1(patch_hash=1e34e4238541638db96b94d5a2e974e73f3b801788a3d8f5c3f4b237a0559138)(react-native-worklets@0.8.3(patch_hash=3f49a21b44ba558989a3366eeff9c92ee331e18b736dbe89c5962ecc6f2802f1)(@babel/core@7.29.0)(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3))(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) @@ -1128,8 +1128,8 @@ importers: specifier: 1.27.2 version: 1.27.2(react-native-web@0.21.2(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) react-native-pager-view: - specifier: 8.0.0 - version: 8.0.0(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) + specifier: 8.0.2 + version: 8.0.2(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) react-native-paper: specifier: ^5.12.5 version: 5.15.0(react-native-safe-area-context@5.7.0(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3))(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3) @@ -7551,7 +7551,7 @@ packages: '@expo/bunyan@4.0.1': resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==} - engines: {'0': node >=0.10.0} + engines: {node: '>=0.10.0'} '@expo/code-signing-certificates@0.0.6': resolution: {integrity: sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w==} @@ -14272,24 +14272,6 @@ packages: react-native-web: optional: true - react-native-pager-view@6.9.1: - resolution: {integrity: sha512-uUT0MMMbNtoSbxe9pRvdJJKEi9snjuJ3fXlZhG8F2vVMOBJVt/AFtqMPUHu9yMflmqOr08PewKzj9EPl/Yj+Gw==} - peerDependencies: - react: 19.2.3 - react-native: 0.86.0-rc.2 - - react-native-pager-view@8.0.0: - resolution: {integrity: sha512-oAwlWT1lhTkIs9HhODnjNNl/owxzn9DP1MbP+az6OTUdgbmzA16Up83sBH8NRKwrH8rNm7iuWnX1qMqiiWOLhg==} - peerDependencies: - react: 19.2.3 - react-native: 0.86.0-rc.2 - - react-native-pager-view@8.0.1: - resolution: {integrity: sha512-pGOne2o0y0HOQLrlTLcGgOE48uJlqSZHRRwdW8nL6JJozMkPGJYi/G9e0EsJoWFpXYONjiDgr8IwxC4F6/r7Lg==} - peerDependencies: - react: 19.2.3 - react-native: 0.86.0-rc.2 - react-native-pager-view@8.0.2: resolution: {integrity: sha512-Y8All2BbjidI4ZIF9kBOIIoldkqrY/2FXapHZMdjwD+ByXhiOWTFenPs5rq9KRN5uAH/gOXtQCqHLxQDNBQRiQ==} peerDependencies: @@ -25302,21 +25284,6 @@ snapshots: optionalDependencies: react-native-web: 0.21.2(encoding@0.1.13)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - react-native-pager-view@6.9.1(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3): - dependencies: - react: 19.2.3 - react-native: 0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3) - - react-native-pager-view@8.0.0(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3): - dependencies: - react: 19.2.3 - react-native: 0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3) - - react-native-pager-view@8.0.1(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3): - dependencies: - react: 19.2.3 - react-native: 0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3) - react-native-pager-view@8.0.2(react-native@0.86.0-rc.2(@babel/core@7.29.0)(@react-native/jest-preset@0.86.0-rc.2(@babel/core@7.29.0)(react@19.2.3))(@react-native/metro-config@0.86.0-rc.2(@babel/core@7.29.0))(@types/react@19.2.14)(react@19.2.3))(react@19.2.3): dependencies: react: 19.2.3 diff --git a/tools/src/react-native-nightlies/patches/react-native-pager-view.patch b/tools/src/react-native-nightlies/patches/react-native-pager-view.patch deleted file mode 100644 index 75b491fea25f6d..00000000000000 --- a/tools/src/react-native-nightlies/patches/react-native-pager-view.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/node_modules/react-native-pager-view/android/src/paper/java/com/reactnativepagerview/PagerViewViewManager.kt b/node_modules/react-native-pager-view/android/src/paper/java/com/reactnativepagerview/PagerViewViewManager.kt -index 4d0adff..959362c 100644 ---- a/node_modules/react-native-pager-view/android/src/paper/java/com/reactnativepagerview/PagerViewViewManager.kt -+++ b/node_modules/react-native-pager-view/android/src/paper/java/com/reactnativepagerview/PagerViewViewManager.kt -@@ -69,7 +69,7 @@ class PagerViewViewManager : ViewGroupManager() { - return host - } - -- override fun addView(host: NestedScrollableHost, child: View?, index: Int) { -+ override fun addView(host: NestedScrollableHost, child: View, index: Int) { - PagerViewViewManagerImpl.addView(host, child, index) - } - From 43370a02f00e7756af82a349d5111af683843c7c Mon Sep 17 00:00:00 2001 From: Aman Mittal Date: Wed, 27 May 2026 00:05:33 +0530 Subject: [PATCH 4/8] [docs] Improve TabButton component (#46310) --- docs/ui/components/Tabs/TabButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ui/components/Tabs/TabButton.tsx b/docs/ui/components/Tabs/TabButton.tsx index 4bdcbfd5ac7167..4df7c7bc48e0f6 100644 --- a/docs/ui/components/Tabs/TabButton.tsx +++ b/docs/ui/components/Tabs/TabButton.tsx @@ -46,7 +46,7 @@ export function TabButton({ className={mergeClasses( 'absolute inset-0 rounded-md border', theme === 'default' && 'border-secondary bg-screen dark:bg-hover dark:drop-shadow-none', - theme === 'secondary' && 'border-button-secondary bg-default shadow-xs dark:bg-subtle' + theme === 'secondary' && 'border-default bg-default shadow-sm dark:bg-subtle' )} /> )} From 68aff76ee3cba5366fcbd3c3a9b1be5ca2822f87 Mon Sep 17 00:00:00 2001 From: Aman Mittal Date: Wed, 27 May 2026 00:05:45 +0530 Subject: [PATCH 5/8] [docs] Update Xcode value in SDK compatibility table for SDK 56 (#46308) --- docs/ui/components/SDKTables/sdk-versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ui/components/SDKTables/sdk-versions.json b/docs/ui/components/SDKTables/sdk-versions.json index 1c7d8a04438cbb..6b3cec9b1df4f0 100644 --- a/docs/ui/components/SDKTables/sdk-versions.json +++ b/docs/ui/components/SDKTables/sdk-versions.json @@ -7,7 +7,7 @@ "targetSdkVersion": "36", "buildToolsVersion": "36.0.0", "ios": "16.4+", - "xcode": "26.2+", + "xcode": "26.4+", "react-native": "0.85", "react-native-web": "0.21.0", "react-native-tvos": "0.85-stable", From 739c71170e4e3eb4c9d0f067d54d74f026099f6e Mon Sep 17 00:00:00 2001 From: Alan Hughes <30924086+alanjhughes@users.noreply.github.com> Date: Tue, 26 May 2026 19:48:20 +0100 Subject: [PATCH 6/8] [docs][dev-client] Update config plugin options (#46303) --- .../versions/unversioned/sdk/dev-client.mdx | 45 ++++++------------- .../pages/versions/v56.0.0/sdk/dev-client.mdx | 45 ++++++------------- 2 files changed, 28 insertions(+), 62 deletions(-) diff --git a/docs/pages/versions/unversioned/sdk/dev-client.mdx b/docs/pages/versions/unversioned/sdk/dev-client.mdx index 5052394183c8fc..23ffdccf04a1ae 100644 --- a/docs/pages/versions/unversioned/sdk/dev-client.mdx +++ b/docs/pages/versions/unversioned/sdk/dev-client.mdx @@ -42,7 +42,10 @@ You can configure development client launcher using its built-in [config plugin] "defaultLaunchURL": "http://localhost:8081", "android": { "defaultLaunchURL": "http://10.0.0.2:8081" - } + }, + "toolsButton": "true", + "skipOnboarding": "false", + "showMenuAtLaunch": "true" } ] ] @@ -78,40 +81,20 @@ You can configure development client launcher using its built-in [config plugin] ].join('\n'), }, { - name: 'android.launchMode', - description: [ - 'Determines whether to launch the most recently opened project or navigate to the launcher screen on Android. Overrides the top-level `launchMode` setting for Android only.', - '* `most-recent` - Attempt to launch directly into a previously opened project and if unable to connect, fall back to the launcher screen.', - '* `launcher` - Opens the launcher screen.', - ].join('\n'), - default: '"most-recent"', - platform: 'android', - }, - { - name: 'ios.launchMode', - description: [ - 'Determines whether to launch the most recently opened project or navigate to the launcher screen on iOS. Overrides the top-level `launchMode` setting for iOS only.', - '* `most-recent` - Attempt to launch directly into a previously opened project and if unable to connect, fall back to the launcher screen.', - '* `launcher` - Opens the launcher screen.', - ].join('\n'), - default: '"most-recent"', - platform: 'ios', + name: 'toolsButton', + description: 'Whether to show the floating tools button.', + default: 'true', }, { - name: 'android.defaultLaunchURL', - description: [ - 'Instead of navigating to launcher screen launch directly into this URL.', - 'If `launchMode` is set to `most-recent`, then launcher will use the `defaultLaunchURL` as a fallback.', - ].join('\n'), - platform: 'android', + name: 'skipOnboarding', + description: + 'Skip the onboarding screen that shows in the dev menu on the first launch of the app.', + default: 'false', }, { - name: 'ios.defaultLaunchURL', - description: [ - 'Instead of navigating to launcher screen launch directly into this URL.', - 'If `launchMode` is set to `most-recent`, then launcher will use the `defaultLaunchURL` as a fallback.', - ].join('\n'), - platform: 'ios', + name: 'showMenuAtLaunch', + description: 'Show the developer menu immediately after launching the app.', + default: 'true', }, ]} /> diff --git a/docs/pages/versions/v56.0.0/sdk/dev-client.mdx b/docs/pages/versions/v56.0.0/sdk/dev-client.mdx index 4ffb003549701f..708365bf5498f6 100644 --- a/docs/pages/versions/v56.0.0/sdk/dev-client.mdx +++ b/docs/pages/versions/v56.0.0/sdk/dev-client.mdx @@ -42,7 +42,10 @@ You can configure development client launcher using its built-in [config plugin] "defaultLaunchURL": "http://localhost:8081", "android": { "defaultLaunchURL": "http://10.0.0.2:8081" - } + }, + "toolsButton": "true", + "skipOnboarding": "false", + "showMenuAtLaunch": "true" } ] ] @@ -78,40 +81,20 @@ You can configure development client launcher using its built-in [config plugin] ].join('\n'), }, { - name: 'android.launchMode', - description: [ - 'Determines whether to launch the most recently opened project or navigate to the launcher screen on Android. Overrides the top-level `launchMode` setting for Android only.', - '* `most-recent` - Attempt to launch directly into a previously opened project and if unable to connect, fall back to the launcher screen.', - '* `launcher` - Opens the launcher screen.', - ].join('\n'), - default: '"most-recent"', - platform: 'android', - }, - { - name: 'ios.launchMode', - description: [ - 'Determines whether to launch the most recently opened project or navigate to the launcher screen on iOS. Overrides the top-level `launchMode` setting for iOS only.', - '* `most-recent` - Attempt to launch directly into a previously opened project and if unable to connect, fall back to the launcher screen.', - '* `launcher` - Opens the launcher screen.', - ].join('\n'), - default: '"most-recent"', - platform: 'ios', + name: 'toolsButton', + description: 'Whether to show the floating tools button.', + default: 'true', }, { - name: 'android.defaultLaunchURL', - description: [ - 'Instead of navigating to launcher screen launch directly into this URL.', - 'If `launchMode` is set to `most-recent`, then launcher will use the `defaultLaunchURL` as a fallback.', - ].join('\n'), - platform: 'android', + name: 'skipOnboarding', + description: + 'Skip the onboarding screen that shows in the dev menu on the first launch of the app.', + default: 'false', }, { - name: 'ios.defaultLaunchURL', - description: [ - 'Instead of navigating to launcher screen launch directly into this URL.', - 'If `launchMode` is set to `most-recent`, then launcher will use the `defaultLaunchURL` as a fallback.', - ].join('\n'), - platform: 'ios', + name: 'showMenuAtLaunch', + description: 'Show the developer menu immediately after launching the app.', + default: 'true', }, ]} /> From 7860a98e0b0a00acc3f6142abaa051b4490fd371 Mon Sep 17 00:00:00 2001 From: Kudo Chien Date: Wed, 27 May 2026 03:01:27 +0800 Subject: [PATCH 7/8] [docs] update mcp for GA (#46315) --- docs/pages/eas/ai/mcp.mdx | 8 +++----- .../ExpoMCPToolsTable/data/expo-mcp-tools.json | 3 ++- .../components/ExpoMCPToolsTable/sync-expo-mcp-tools.js | 9 +++++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/pages/eas/ai/mcp.mdx b/docs/pages/eas/ai/mcp.mdx index c39f99a2891d8f..e1bd248d71d9d7 100644 --- a/docs/pages/eas/ai/mcp.mdx +++ b/docs/pages/eas/ai/mcp.mdx @@ -14,8 +14,6 @@ import { Terminal } from '~/ui/components/Snippet'; import { Step } from '~/ui/components/Step'; import { VideoBoxLink } from '~/ui/components/VideoBoxLink'; -> **info** Expo MCP Server requires an [EAS paid plan](https://expo.dev/pricing). - [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) is a standard protocol that allows AI models to integrate with external data sources, providing enhanced context for more precise responses. It enables AI-assisted tools like agents to understand your development environment more deeply, allowing them to provide better assistance with your codebase. Expo MCP Server is a remote MCP server hosted by Expo that integrates with popular AI-assisted tools such as Claude Code, Cursor, VS Code, and others, enabling them to interact directly with your Expo projects. @@ -62,8 +60,8 @@ Your AI-assisted tools can autonomously write the code, capture screenshots to v The complete table of [MCP capabilities](#available-mcp-capabilities) documents the tools and prompts Expo MCP Server provides to AI-assisted tools. - - An [EAS paid plan](https://expo.dev/pricing) is required to use Expo MCP Server. + + An Expo account is required to use Expo MCP Server. Create a project with `npx create-expo-app@latest --template default@sdk-56`, or ensure your @@ -187,7 +185,7 @@ Expo MCP Server provides two types of capabilities depending on your setup: ### Server capabilities -Server capabilities are available with just the remote MCP server connection, without needing to set up a local development server. The **search_documentation** tool is an example of a server capability. +Server capabilities are available with just the remote MCP server connection, without needing to set up a local development server. ### Local capabilities diff --git a/docs/ui/components/ExpoMCPToolsTable/data/expo-mcp-tools.json b/docs/ui/components/ExpoMCPToolsTable/data/expo-mcp-tools.json index ea5c230ff2ad77..1762913e7a1bda 100644 --- a/docs/ui/components/ExpoMCPToolsTable/data/expo-mcp-tools.json +++ b/docs/ui/components/ExpoMCPToolsTable/data/expo-mcp-tools.json @@ -17,7 +17,8 @@ "name": "search_documentation", "description": "Search the official Expo documentation and return page URLs ranked by relevance for a user query. Use read_documentation to fetch the full content of specific pages, starting from the top.", "examplePrompt": "search documentation for CNG", - "availability": "Server" + "availability": "Server", + "requirements": "requires an EAS paid plan" }, { "name": "read_documentation", diff --git a/docs/ui/components/ExpoMCPToolsTable/sync-expo-mcp-tools.js b/docs/ui/components/ExpoMCPToolsTable/sync-expo-mcp-tools.js index 1f84f1a5b749e9..6bd02b111ec324 100644 --- a/docs/ui/components/ExpoMCPToolsTable/sync-expo-mcp-tools.js +++ b/docs/ui/components/ExpoMCPToolsTable/sync-expo-mcp-tools.js @@ -28,6 +28,14 @@ const LOCAL_REQUIREMENTS = { expo_router_sitemap: 'requires `expo-router` library', }; +/** + * Requirements for server tools that have plan-specific availability. + * Keyed by tool name. + */ +const SERVER_REQUIREMENTS = { + search_documentation: 'requires an EAS paid plan', +}; + /** * Example prompts for server tools (docs-only, not from MCP server). * Keyed by tool name. @@ -125,6 +133,7 @@ async function fetchServerTools() { description: ensureTrailingPeriod(tool.description), examplePrompt: SERVER_EXAMPLE_PROMPTS[tool.name] ?? '', availability: 'Server', + ...(SERVER_REQUIREMENTS[tool.name] && { requirements: SERVER_REQUIREMENTS[tool.name] }), })); } From d0e2f477a11e880cc10113f041a014015857994d Mon Sep 17 00:00:00 2001 From: Gabriel Donadel Dall'Agnol Date: Tue, 26 May 2026 16:59:18 -0300 Subject: [PATCH 8/8] [linking] Add clearInitialURL function (#46265) # Why When using `expo-dev-client` on iOS, a deep link captured at app launch persists in `expo-linking`'s process-lifetime singleton for the entire OS process. Currently, there is no public API to clear it, and the dev-launcher silently re-applies it on every subsequent React Native instance it creates. After the user connected to a bundler and then returned to the dev launcher, the next app load would re-fire the original deep link as if the user had just opened it. # How - Add `clearInitialURL()` API to `expo-linking` and an internal notification (`ExpoLinkingClearInitialURL`) that the registry observes to reset itself. - In `expo-dev-launcher` stops re-injecting `UIApplicationLaunchOptionsURLKey` once `pendingDeepLinkRegistry` has been consumed, and posts `ExpoLinkingClearInitialURL` from `navigateToLauncher` so `expo-linking`'s registry is wiped at the same moment the user's React host is torn down. # Test Plan Manual repro on `apps/minimal-tester` --- packages/expo-dev-launcher/CHANGELOG.md | 2 ++ .../ios/EXDevLauncherController.m | 10 ++++++--- packages/expo-linking/CHANGELOG.md | 2 ++ .../expo/modules/linking/ExpoLinkingModule.kt | 4 ++++ packages/expo-linking/build/ExpoLinking.d.ts | 1 + .../expo-linking/build/ExpoLinking.d.ts.map | 2 +- .../expo-linking/build/ExpoLinking.js.map | 2 +- .../expo-linking/build/ExpoLinking.web.d.ts | 1 + .../build/ExpoLinking.web.d.ts.map | 2 +- .../expo-linking/build/ExpoLinking.web.js | 1 + .../expo-linking/build/ExpoLinking.web.js.map | 2 +- packages/expo-linking/build/Linking.d.ts | 9 ++++++++ packages/expo-linking/build/Linking.d.ts.map | 2 +- packages/expo-linking/build/Linking.js | 11 ++++++++++ packages/expo-linking/build/Linking.js.map | 2 +- .../expo-linking/build/Linking.server.d.ts | 1 + .../build/Linking.server.d.ts.map | 2 +- packages/expo-linking/build/Linking.server.js | 1 + .../expo-linking/build/Linking.server.js.map | 2 +- .../expo-linking/ios/ExpoLinkingModule.swift | 4 ++++ .../ios/ExpoLinkingRegistry.swift | 21 +++++++++++++++++-- packages/expo-linking/src/ExpoLinking.ts | 1 + packages/expo-linking/src/ExpoLinking.web.ts | 2 ++ packages/expo-linking/src/Linking.server.ts | 2 ++ packages/expo-linking/src/Linking.ts | 12 +++++++++++ 25 files changed, 88 insertions(+), 13 deletions(-) diff --git a/packages/expo-dev-launcher/CHANGELOG.md b/packages/expo-dev-launcher/CHANGELOG.md index a8a96a175fd155..a1df921e1e2f37 100644 --- a/packages/expo-dev-launcher/CHANGELOG.md +++ b/packages/expo-dev-launcher/CHANGELOG.md @@ -8,6 +8,8 @@ ### 🐛 Bug fixes +- [iOS] Cleared the deep-link URL from cached `launchOptions` after it is consumed ([#46265](https://github.com/expo/expo/pull/46265) by [@gabrieldonadel](https://github.com/gabrieldonadel)) + ### 💡 Others ## 56.0.16 — 2026-05-26 diff --git a/packages/expo-dev-launcher/ios/EXDevLauncherController.m b/packages/expo-dev-launcher/ios/EXDevLauncherController.m index e5317fea751025..372d0210c54a36 100644 --- a/packages/expo-dev-launcher/ios/EXDevLauncherController.m +++ b/packages/expo-dev-launcher/ios/EXDevLauncherController.m @@ -116,9 +116,9 @@ - (void)clearRecentlyOpenedApps if (deepLink) { // Passes pending deep link to initialURL if any launchOptions[UIApplicationLaunchOptionsURLKey] = deepLink; - } else if (launchOptions[UIApplicationLaunchOptionsURLKey] && [EXDevLauncherURLHelper isDevLauncherURL:launchOptions[UIApplicationLaunchOptionsURLKey]]) { - // Strips initialURL if it is from myapp://expo-development-client/?url=... - // That would make dev-launcher acts like a normal app. + } else { + // The pending deep link has already been consumed by an earlier React host. Strip the URL + // from the cached launchOptions so a subsequent React host launchOptions[UIApplicationLaunchOptionsURLKey] = nil; } @@ -294,6 +294,10 @@ - (void)navigateToLauncher // Reset app react host [self.delegate destroyReactInstance]; + // Tell expo-linking to clear its cached initial URL so the next React host doesn't pick up + // the deep link that originally launched the previous app. + [[NSNotificationCenter defaultCenter] postNotificationName:@"ExpoLinkingClearInitialURL" object:self]; + if (_devLauncherViewController != nil) { [_devLauncherViewController resetHostingController]; } diff --git a/packages/expo-linking/CHANGELOG.md b/packages/expo-linking/CHANGELOG.md index ad1b910ef49218..e775f3542fe70d 100644 --- a/packages/expo-linking/CHANGELOG.md +++ b/packages/expo-linking/CHANGELOG.md @@ -6,6 +6,8 @@ ### 🎉 New features +- Added `Linking.clearInitialURL()` to reset the cached deep-link URL. ([#46265](https://github.com/expo/expo/pull/46265) by @gabrieldonadel) + ### 🐛 Bug fixes ### 💡 Others diff --git a/packages/expo-linking/android/src/main/java/expo/modules/linking/ExpoLinkingModule.kt b/packages/expo-linking/android/src/main/java/expo/modules/linking/ExpoLinkingModule.kt index 044c936f517684..07b06b8cc73437 100644 --- a/packages/expo-linking/android/src/main/java/expo/modules/linking/ExpoLinkingModule.kt +++ b/packages/expo-linking/android/src/main/java/expo/modules/linking/ExpoLinkingModule.kt @@ -23,6 +23,10 @@ class ExpoLinkingModule : Module() { initialURL?.toString() } + Function("clearInitialURL") { + initialURL = null + } + OnStartObserving("onURLReceived") { val weakModule = WeakReference(this@ExpoLinkingModule) val observer: (Uri?) -> Unit = { uri: Uri? -> diff --git a/packages/expo-linking/build/ExpoLinking.d.ts b/packages/expo-linking/build/ExpoLinking.d.ts index 526e196afd4853..61e8d49ef82904 100644 --- a/packages/expo-linking/build/ExpoLinking.d.ts +++ b/packages/expo-linking/build/ExpoLinking.d.ts @@ -4,6 +4,7 @@ type ExpoLinkingModuleEvents = { }; declare class ExpoLinkingNativeModule extends NativeModule { getLinkingURL(): string | null; + clearInitialURL(): void; } declare const ExpoLinking: ExpoLinkingNativeModule; export default ExpoLinking; diff --git a/packages/expo-linking/build/ExpoLinking.d.ts.map b/packages/expo-linking/build/ExpoLinking.d.ts.map index 743335dad10930..841d7c0e0e0b90 100644 --- a/packages/expo-linking/build/ExpoLinking.d.ts.map +++ b/packages/expo-linking/build/ExpoLinking.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"ExpoLinking.d.ts","sourceRoot":"","sources":["../src/ExpoLinking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtE,KAAK,uBAAuB,GAAG;IAC7B,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,OAAO,OAAO,uBAAwB,SAAQ,YAAY,CAAC,uBAAuB,CAAC;IACjF,aAAa,IAAI,MAAM,GAAG,IAAI;CAC/B;AAED,QAAA,MAAM,WAAW,yBAA8D,CAAC;AAChF,eAAe,WAAW,CAAC"} \ No newline at end of file +{"version":3,"file":"ExpoLinking.d.ts","sourceRoot":"","sources":["../src/ExpoLinking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtE,KAAK,uBAAuB,GAAG;IAC7B,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF,OAAO,OAAO,uBAAwB,SAAQ,YAAY,CAAC,uBAAuB,CAAC;IACjF,aAAa,IAAI,MAAM,GAAG,IAAI;IAC9B,eAAe,IAAI,IAAI;CACxB;AAED,QAAA,MAAM,WAAW,yBAA8D,CAAC;AAChF,eAAe,WAAW,CAAC"} \ No newline at end of file diff --git a/packages/expo-linking/build/ExpoLinking.js.map b/packages/expo-linking/build/ExpoLinking.js.map index 5f7abc814aebfc..21f65d709c9ada 100644 --- a/packages/expo-linking/build/ExpoLinking.js.map +++ b/packages/expo-linking/build/ExpoLinking.js.map @@ -1 +1 @@ -{"version":3,"file":"ExpoLinking.js","sourceRoot":"","sources":["../src/ExpoLinking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAUtE,MAAM,WAAW,GAAG,mBAAmB,CAA0B,aAAa,CAAC,CAAC;AAChF,eAAe,WAAW,CAAC","sourcesContent":["import { requireNativeModule, NativeModule } from 'expo-modules-core';\n\ntype ExpoLinkingModuleEvents = {\n onURLReceived(url: string): void;\n};\n\ndeclare class ExpoLinkingNativeModule extends NativeModule {\n getLinkingURL(): string | null;\n}\n\nconst ExpoLinking = requireNativeModule('ExpoLinking');\nexport default ExpoLinking;\n"]} \ No newline at end of file +{"version":3,"file":"ExpoLinking.js","sourceRoot":"","sources":["../src/ExpoLinking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAWtE,MAAM,WAAW,GAAG,mBAAmB,CAA0B,aAAa,CAAC,CAAC;AAChF,eAAe,WAAW,CAAC","sourcesContent":["import { requireNativeModule, NativeModule } from 'expo-modules-core';\n\ntype ExpoLinkingModuleEvents = {\n onURLReceived(url: string): void;\n};\n\ndeclare class ExpoLinkingNativeModule extends NativeModule {\n getLinkingURL(): string | null;\n clearInitialURL(): void;\n}\n\nconst ExpoLinking = requireNativeModule('ExpoLinking');\nexport default ExpoLinking;\n"]} \ No newline at end of file diff --git a/packages/expo-linking/build/ExpoLinking.web.d.ts b/packages/expo-linking/build/ExpoLinking.web.d.ts index 1742c78ab319c7..e055c07a42a82b 100644 --- a/packages/expo-linking/build/ExpoLinking.web.d.ts +++ b/packages/expo-linking/build/ExpoLinking.web.d.ts @@ -4,6 +4,7 @@ declare const _default: { remove(): void; }; getLinkingURL(): string; + clearInitialURL(): void; }; export default _default; //# sourceMappingURL=ExpoLinking.web.d.ts.map \ No newline at end of file diff --git a/packages/expo-linking/build/ExpoLinking.web.d.ts.map b/packages/expo-linking/build/ExpoLinking.web.d.ts.map index 21ba73284f46cb..bc5e1b9596eb67 100644 --- a/packages/expo-linking/build/ExpoLinking.web.d.ts.map +++ b/packages/expo-linking/build/ExpoLinking.web.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"ExpoLinking.web.d.ts","sourceRoot":"","sources":["../src/ExpoLinking.web.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;;2BAG1B,eAAe,GAAG,MAAM,YAAY,WAAW,GAAG;QAAE,MAAM,IAAI,IAAI,CAAA;KAAE;qBAoB1E,MAAM;;AArBzB,wBAyBE"} \ No newline at end of file +{"version":3,"file":"ExpoLinking.web.d.ts","sourceRoot":"","sources":["../src/ExpoLinking.web.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;;2BAG1B,eAAe,GAAG,MAAM,YAAY,WAAW,GAAG;QAAE,MAAM,IAAI,IAAI,CAAA;KAAE;qBAoB1E,MAAM;uBAKJ,IAAI;;AA1BzB,wBA2BE"} \ No newline at end of file diff --git a/packages/expo-linking/build/ExpoLinking.web.js b/packages/expo-linking/build/ExpoLinking.web.js index 2fc8ff3a0e15a9..4351dd8d173fdd 100644 --- a/packages/expo-linking/build/ExpoLinking.web.js +++ b/packages/expo-linking/build/ExpoLinking.web.js @@ -19,5 +19,6 @@ export default { return ''; return window.location.href; }, + clearInitialURL() { }, }; //# sourceMappingURL=ExpoLinking.web.js.map \ No newline at end of file diff --git a/packages/expo-linking/build/ExpoLinking.web.js.map b/packages/expo-linking/build/ExpoLinking.web.js.map index b6a10afbc141a6..47c47ae5912d6b 100644 --- a/packages/expo-linking/build/ExpoLinking.web.js.map +++ b/packages/expo-linking/build/ExpoLinking.web.js.map @@ -1 +1 @@ -{"version":3,"file":"ExpoLinking.web.js","sourceRoot":"","sources":["../src/ExpoLinking.web.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAC;AAIlC,eAAe;IACb,WAAW,CAAC,SAAmC,EAAE,QAAqB;QACpE,SAAS,CACP,SAAS,KAAK,eAAe,EAC7B,0BAA0B,SAAS,uBAAuB,CAC3D,CAAC;QACF,qCAAqC;QACrC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,OAAO,EAAE,MAAM,KAAI,CAAC,EAAE,CAAC;QACzB,CAAC;QAED,MAAM,cAAc,GAAG,CAAC,WAAyB,EAAE,EAAE,CACnD,QAAQ,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;QACvD,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;QAC1D,OAAO;YACL,MAAM,EAAE,GAAG,EAAE;gBACX,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;YACxD,CAAC;SACF,CAAC;IACJ,CAAC;IAED,aAAa;QACX,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,EAAE,CAAC;QAC7C,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC9B,CAAC;CACF,CAAC","sourcesContent":["import invariant from 'invariant';\n\nimport type { URLListener } from './Linking.types';\n\nexport default {\n addListener(eventName: 'onURLReceived' | string, listener: URLListener): { remove(): void } {\n invariant(\n eventName === 'onURLReceived',\n `Linking.addListener(): ${eventName} is not a valid event`\n );\n // Do nothing in Node.js environments\n if (typeof window === 'undefined') {\n return { remove() {} };\n }\n\n const nativeListener = (nativeEvent: MessageEvent) =>\n listener({ url: window.location.href, nativeEvent });\n window.addEventListener('message', nativeListener, false);\n return {\n remove: () => {\n window.removeEventListener('message', nativeListener);\n },\n };\n },\n\n getLinkingURL(): string {\n if (typeof window === 'undefined') return '';\n return window.location.href;\n },\n};\n"]} \ No newline at end of file +{"version":3,"file":"ExpoLinking.web.js","sourceRoot":"","sources":["../src/ExpoLinking.web.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,WAAW,CAAC;AAIlC,eAAe;IACb,WAAW,CAAC,SAAmC,EAAE,QAAqB;QACpE,SAAS,CACP,SAAS,KAAK,eAAe,EAC7B,0BAA0B,SAAS,uBAAuB,CAC3D,CAAC;QACF,qCAAqC;QACrC,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,OAAO,EAAE,MAAM,KAAI,CAAC,EAAE,CAAC;QACzB,CAAC;QAED,MAAM,cAAc,GAAG,CAAC,WAAyB,EAAE,EAAE,CACnD,QAAQ,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;QACvD,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;QAC1D,OAAO;YACL,MAAM,EAAE,GAAG,EAAE;gBACX,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;YACxD,CAAC;SACF,CAAC;IACJ,CAAC;IAED,aAAa;QACX,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,EAAE,CAAC;QAC7C,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC9B,CAAC;IAED,eAAe,KAAU,CAAC;CAC3B,CAAC","sourcesContent":["import invariant from 'invariant';\n\nimport type { URLListener } from './Linking.types';\n\nexport default {\n addListener(eventName: 'onURLReceived' | string, listener: URLListener): { remove(): void } {\n invariant(\n eventName === 'onURLReceived',\n `Linking.addListener(): ${eventName} is not a valid event`\n );\n // Do nothing in Node.js environments\n if (typeof window === 'undefined') {\n return { remove() {} };\n }\n\n const nativeListener = (nativeEvent: MessageEvent) =>\n listener({ url: window.location.href, nativeEvent });\n window.addEventListener('message', nativeListener, false);\n return {\n remove: () => {\n window.removeEventListener('message', nativeListener);\n },\n };\n },\n\n getLinkingURL(): string {\n if (typeof window === 'undefined') return '';\n return window.location.href;\n },\n\n clearInitialURL(): void {},\n};\n"]} \ No newline at end of file diff --git a/packages/expo-linking/build/Linking.d.ts b/packages/expo-linking/build/Linking.d.ts index 2606e5e58ac436..039983c43cd4e0 100644 --- a/packages/expo-linking/build/Linking.d.ts +++ b/packages/expo-linking/build/Linking.d.ts @@ -39,6 +39,15 @@ export declare function getInitialURL(): Promise; * @return The URL string that launched your app, or `null`. */ export declare function getLinkingURL(): string | null; +/** + * Clears the cached initial URL used to launch the app, subsequent + * calls to [`getLinkingURL()`] return `null` until a new deep link is received. + * + * On web this is a no-op. + * @platform android + * @platform ios + */ +export declare function clearInitialURL(): void; /** * Attempt to open the given URL with an installed app. See the [Linking guide](/guides/linking) * for more information. diff --git a/packages/expo-linking/build/Linking.d.ts.map b/packages/expo-linking/build/Linking.d.ts.map index 5cfd6ee2214615..806b0240445e13 100644 --- a/packages/expo-linking/build/Linking.d.ts.map +++ b/packages/expo-linking/build/Linking.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"Linking.d.ts","sourceRoot":"","sources":["../src/Linking.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAIxD,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAMhF;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,GAAG,mBAAmB,CAEvF;AAGD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,SAAS,CAAC,CAY/D;AAGD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAK3F;AAGD;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAQlD;AAGD;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE5D;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAE7C;AAGD;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGxD;AAGD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG9D;AAGD;;;;GAIG;AACH,wBAAgB,MAAM,IAAI,MAAM,GAAG,IAAI,CActC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAa7C;AAED,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file +{"version":3,"file":"Linking.d.ts","sourceRoot":"","sources":["../src/Linking.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAIxD,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAMhF;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,GAAG,mBAAmB,CAEvF;AAGD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,SAAS,CAAC,CAY/D;AAGD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAK3F;AAGD;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAQlD;AAGD;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE5D;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAE7C;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC;AAGD;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGxD;AAGD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG9D;AAGD;;;;GAIG;AACH,wBAAgB,MAAM,IAAI,MAAM,GAAG,IAAI,CActC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAa7C;AAED,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file diff --git a/packages/expo-linking/build/Linking.js b/packages/expo-linking/build/Linking.js index f736226583b142..68426589d9b44a 100644 --- a/packages/expo-linking/build/Linking.js +++ b/packages/expo-linking/build/Linking.js @@ -79,6 +79,17 @@ export async function getInitialURL() { export function getLinkingURL() { return ExpoLinking.getLinkingURL(); } +/** + * Clears the cached initial URL used to launch the app, subsequent + * calls to [`getLinkingURL()`] return `null` until a new deep link is received. + * + * On web this is a no-op. + * @platform android + * @platform ios + */ +export function clearInitialURL() { + ExpoLinking.clearInitialURL?.(); +} // @needsAudit /** * Attempt to open the given URL with an installed app. See the [Linking guide](/guides/linking) diff --git a/packages/expo-linking/build/Linking.js.map b/packages/expo-linking/build/Linking.js.map index a415aa331ced13..eb775d7768bf1a 100644 --- a/packages/expo-linking/build/Linking.js.map +++ b/packages/expo-linking/build/Linking.js.map @@ -1 +1 @@ -{"version":3,"file":"Linking.js","sourceRoot":"","sources":["../src/Linking.ts"],"names":[],"mappings":"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","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\nimport { useEffect, useState } from 'react';\nimport type { EmitterSubscription } from 'react-native';\nimport { Platform } from 'react-native';\n\nimport ExpoLinking from './ExpoLinking';\nimport type { ParsedURL, SendIntentExtras, URLListener } from './Linking.types';\nimport RNLinking from './RNLinking';\nimport { parse } from './createURL';\nimport { validateURL } from './validateURL';\n\n// @needsAudit\n/**\n * Add a handler to `Linking` changes by listening to the `url` event type and providing the handler.\n * It is recommended to use the [`useLinkingURL()`](#uselinkingurl) hook instead.\n * @param type The only valid type is `'url'`.\n * @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type\n * [`EventType`](#eventtype).\n * @return An EmitterSubscription that has the remove method from EventSubscription\n * @see [React Native documentation on Linking](https://reactnative.dev/docs/linking#addeventlistener).\n */\nexport function addEventListener(type: 'url', handler: URLListener): EmitterSubscription {\n return RNLinking.addEventListener(type, handler);\n}\n\n// @needsAudit\n/**\n * Helper method which wraps React Native's `Linking.getInitialURL()` in `Linking.parse()`.\n * Parses the deep link information out of the URL used to open the experience initially.\n * If no link opened the app, all the fields will be `null`.\n * > On the web it parses the current window URL.\n * @return A promise that resolves with `ParsedURL` object.\n */\nexport async function parseInitialURLAsync(): Promise {\n const initialUrl = await RNLinking.getInitialURL();\n if (!initialUrl) {\n return {\n scheme: null,\n hostname: null,\n path: null,\n queryParams: null,\n };\n }\n\n return parse(initialUrl);\n}\n\n// @needsAudit\n/**\n * Launch an Android intent with extras.\n * > Use [`expo-intent-launcher`](./intent-launcher) instead. `sendIntent` is only included in\n * > `Linking` for API compatibility with React Native's Linking API.\n * @platform android\n */\nexport async function sendIntent(action: string, extras?: SendIntentExtras[]): Promise {\n if (Platform.OS === 'android') {\n return await RNLinking.sendIntent(action, extras);\n }\n throw new UnavailabilityError('Linking', 'sendIntent');\n}\n\n// @needsAudit\n/**\n * Open the operating system settings app and displays the app’s custom settings, if it has any.\n */\nexport async function openSettings(): Promise {\n if (Platform.OS === 'web') {\n throw new UnavailabilityError('Linking', 'openSettings');\n }\n if (RNLinking.openSettings) {\n return await RNLinking.openSettings();\n }\n await openURL('app-settings:');\n}\n\n// @needsAudit\n/**\n * Get the URL that was used to launch the app if it was launched by a link.\n * @return The URL string that launched your app, or `null`.\n */\nexport async function getInitialURL(): Promise {\n return (await RNLinking.getInitialURL()) ?? null;\n}\n\n/**\n * Get the URL that was used to launch the app if it was launched by a link.\n * @return The URL string that launched your app, or `null`.\n */\nexport function getLinkingURL(): string | null {\n return ExpoLinking.getLinkingURL();\n}\n\n// @needsAudit\n/**\n * Attempt to open the given URL with an installed app. See the [Linking guide](/guides/linking)\n * for more information.\n * @param url A URL for the operating system to open. For example: `tel:5555555`, `exp://`.\n * @return A `Promise` that is fulfilled with `true` if the link is opened operating system\n * automatically or the user confirms the prompt to open the link. The `Promise` rejects if there\n * are no applications registered for the URL or the user cancels the dialog.\n */\nexport async function openURL(url: string): Promise {\n validateURL(url);\n return await RNLinking.openURL(url);\n}\n\n// @needsAudit\n/**\n * Determine whether or not an installed app can handle a given URL.\n * On web this always returns `true` because there is no API for detecting what URLs can be opened.\n * @param url The URL that you want to test can be opened.\n * @return A `Promise` object that is fulfilled with `true` if the URL can be handled, otherwise it\n * `false` if not.\n * The `Promise` will reject on Android if it was impossible to check if the URL can be opened, and\n * on iOS if you didn't [add the specific scheme in the `LSApplicationQueriesSchemes` key inside **Info.plist**](/guides/linking#linking-from-your-app).\n */\nexport async function canOpenURL(url: string): Promise {\n validateURL(url);\n return await RNLinking.canOpenURL(url);\n}\n\n// @needsAudit\n/**\n * Returns the initial URL followed by any subsequent changes to the URL.\n * @deprecated Use `useLinkingURL` hook instead.\n * @return Returns the initial URL or `null`.\n */\nexport function useURL(): string | null {\n const [url, setLink] = useState(null);\n\n function onChange(event: { url: string }) {\n setLink(event.url);\n }\n\n useEffect(() => {\n getInitialURL().then((url) => setLink(url));\n const subscription = addEventListener('url', onChange);\n return () => subscription.remove();\n }, []);\n\n return url;\n}\n\n/**\n * Returns the linking URL followed by any subsequent changes to the URL.\n * Always returns the initial URL immediately on reload.\n * @return Returns the initial URL or `null`.\n */\nexport function useLinkingURL(): string | null {\n const [url, setLink] = useState(ExpoLinking.getLinkingURL);\n\n function onChange(event: { url: string }) {\n setLink(event.url);\n }\n\n useEffect(() => {\n const subscription = ExpoLinking.addListener('onURLReceived', onChange as any);\n return () => subscription.remove();\n }, []);\n\n return url ?? null;\n}\n\nexport * from './Linking.types';\nexport * from './Schemes';\nexport { parse, createURL } from './createURL';\n"]} \ No newline at end of file +{"version":3,"file":"Linking.js","sourceRoot":"","sources":["../src/Linking.ts"],"names":[],"mappings":"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","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\nimport { useEffect, useState } from 'react';\nimport type { EmitterSubscription } from 'react-native';\nimport { Platform } from 'react-native';\n\nimport ExpoLinking from './ExpoLinking';\nimport type { ParsedURL, SendIntentExtras, URLListener } from './Linking.types';\nimport RNLinking from './RNLinking';\nimport { parse } from './createURL';\nimport { validateURL } from './validateURL';\n\n// @needsAudit\n/**\n * Add a handler to `Linking` changes by listening to the `url` event type and providing the handler.\n * It is recommended to use the [`useLinkingURL()`](#uselinkingurl) hook instead.\n * @param type The only valid type is `'url'`.\n * @param handler An [`URLListener`](#urllistener) function that takes an `event` object of the type\n * [`EventType`](#eventtype).\n * @return An EmitterSubscription that has the remove method from EventSubscription\n * @see [React Native documentation on Linking](https://reactnative.dev/docs/linking#addeventlistener).\n */\nexport function addEventListener(type: 'url', handler: URLListener): EmitterSubscription {\n return RNLinking.addEventListener(type, handler);\n}\n\n// @needsAudit\n/**\n * Helper method which wraps React Native's `Linking.getInitialURL()` in `Linking.parse()`.\n * Parses the deep link information out of the URL used to open the experience initially.\n * If no link opened the app, all the fields will be `null`.\n * > On the web it parses the current window URL.\n * @return A promise that resolves with `ParsedURL` object.\n */\nexport async function parseInitialURLAsync(): Promise {\n const initialUrl = await RNLinking.getInitialURL();\n if (!initialUrl) {\n return {\n scheme: null,\n hostname: null,\n path: null,\n queryParams: null,\n };\n }\n\n return parse(initialUrl);\n}\n\n// @needsAudit\n/**\n * Launch an Android intent with extras.\n * > Use [`expo-intent-launcher`](./intent-launcher) instead. `sendIntent` is only included in\n * > `Linking` for API compatibility with React Native's Linking API.\n * @platform android\n */\nexport async function sendIntent(action: string, extras?: SendIntentExtras[]): Promise {\n if (Platform.OS === 'android') {\n return await RNLinking.sendIntent(action, extras);\n }\n throw new UnavailabilityError('Linking', 'sendIntent');\n}\n\n// @needsAudit\n/**\n * Open the operating system settings app and displays the app’s custom settings, if it has any.\n */\nexport async function openSettings(): Promise {\n if (Platform.OS === 'web') {\n throw new UnavailabilityError('Linking', 'openSettings');\n }\n if (RNLinking.openSettings) {\n return await RNLinking.openSettings();\n }\n await openURL('app-settings:');\n}\n\n// @needsAudit\n/**\n * Get the URL that was used to launch the app if it was launched by a link.\n * @return The URL string that launched your app, or `null`.\n */\nexport async function getInitialURL(): Promise {\n return (await RNLinking.getInitialURL()) ?? null;\n}\n\n/**\n * Get the URL that was used to launch the app if it was launched by a link.\n * @return The URL string that launched your app, or `null`.\n */\nexport function getLinkingURL(): string | null {\n return ExpoLinking.getLinkingURL();\n}\n\n/**\n * Clears the cached initial URL used to launch the app, subsequent\n * calls to [`getLinkingURL()`] return `null` until a new deep link is received.\n *\n * On web this is a no-op.\n * @platform android\n * @platform ios\n */\nexport function clearInitialURL(): void {\n ExpoLinking.clearInitialURL?.();\n}\n\n// @needsAudit\n/**\n * Attempt to open the given URL with an installed app. See the [Linking guide](/guides/linking)\n * for more information.\n * @param url A URL for the operating system to open. For example: `tel:5555555`, `exp://`.\n * @return A `Promise` that is fulfilled with `true` if the link is opened operating system\n * automatically or the user confirms the prompt to open the link. The `Promise` rejects if there\n * are no applications registered for the URL or the user cancels the dialog.\n */\nexport async function openURL(url: string): Promise {\n validateURL(url);\n return await RNLinking.openURL(url);\n}\n\n// @needsAudit\n/**\n * Determine whether or not an installed app can handle a given URL.\n * On web this always returns `true` because there is no API for detecting what URLs can be opened.\n * @param url The URL that you want to test can be opened.\n * @return A `Promise` object that is fulfilled with `true` if the URL can be handled, otherwise it\n * `false` if not.\n * The `Promise` will reject on Android if it was impossible to check if the URL can be opened, and\n * on iOS if you didn't [add the specific scheme in the `LSApplicationQueriesSchemes` key inside **Info.plist**](/guides/linking#linking-from-your-app).\n */\nexport async function canOpenURL(url: string): Promise {\n validateURL(url);\n return await RNLinking.canOpenURL(url);\n}\n\n// @needsAudit\n/**\n * Returns the initial URL followed by any subsequent changes to the URL.\n * @deprecated Use `useLinkingURL` hook instead.\n * @return Returns the initial URL or `null`.\n */\nexport function useURL(): string | null {\n const [url, setLink] = useState(null);\n\n function onChange(event: { url: string }) {\n setLink(event.url);\n }\n\n useEffect(() => {\n getInitialURL().then((url) => setLink(url));\n const subscription = addEventListener('url', onChange);\n return () => subscription.remove();\n }, []);\n\n return url;\n}\n\n/**\n * Returns the linking URL followed by any subsequent changes to the URL.\n * Always returns the initial URL immediately on reload.\n * @return Returns the initial URL or `null`.\n */\nexport function useLinkingURL(): string | null {\n const [url, setLink] = useState(ExpoLinking.getLinkingURL);\n\n function onChange(event: { url: string }) {\n setLink(event.url);\n }\n\n useEffect(() => {\n const subscription = ExpoLinking.addListener('onURLReceived', onChange as any);\n return () => subscription.remove();\n }, []);\n\n return url ?? null;\n}\n\nexport * from './Linking.types';\nexport * from './Schemes';\nexport { parse, createURL } from './createURL';\n"]} \ No newline at end of file diff --git a/packages/expo-linking/build/Linking.server.d.ts b/packages/expo-linking/build/Linking.server.d.ts index 4b12638656eb24..7b8085f26b987a 100644 --- a/packages/expo-linking/build/Linking.server.d.ts +++ b/packages/expo-linking/build/Linking.server.d.ts @@ -7,6 +7,7 @@ export declare function sendIntent(action: string, extras?: SendIntentExtras[]): export declare function openSettings(): Promise; export declare function getInitialURL(): Promise; export declare function getLinkingURL(): string; +export declare function clearInitialURL(): void; export declare function openURL(url: string): Promise; export declare function canOpenURL(): Promise; export declare function useURL(): string | null; diff --git a/packages/expo-linking/build/Linking.server.d.ts.map b/packages/expo-linking/build/Linking.server.d.ts.map index 189ce957855c18..586a6e87d3355e 100644 --- a/packages/expo-linking/build/Linking.server.d.ts.map +++ b/packages/expo-linking/build/Linking.server.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"Linking.server.d.ts","sourceRoot":"","sources":["../src/Linking.server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEhF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW;;EAEjE;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,SAAS,CAAC,CAO/D;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3F;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE5D;AAED,wBAAgB,aAAa,WAE5B;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExD;AAED,wBAAsB,UAAU,qBAE/B;AAED,wBAAgB,MAAM,IAAI,MAAM,GAAG,IAAI,CAEtC;AAED,wBAAgB,aAAa,SAE5B;AAED,cAAc,iBAAiB,CAAC;AAEhC,wBAAgB,sBAAsB,YAErC;AAED,wBAAgB,oBAAoB,YAEnC;AAED,wBAAgB,eAAe,YAE9B;AAED,wBAAgB,aAAa,WAE5B;AAED,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file +{"version":3,"file":"Linking.server.d.ts","sourceRoot":"","sources":["../src/Linking.server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEhF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW;;EAEjE;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,SAAS,CAAC,CAO/D;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3F;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE5D;AAED,wBAAgB,aAAa,WAE5B;AAED,wBAAgB,eAAe,IAAI,IAAI,CAAG;AAE1C,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExD;AAED,wBAAsB,UAAU,qBAE/B;AAED,wBAAgB,MAAM,IAAI,MAAM,GAAG,IAAI,CAEtC;AAED,wBAAgB,aAAa,SAE5B;AAED,cAAc,iBAAiB,CAAC;AAEhC,wBAAgB,sBAAsB,YAErC;AAED,wBAAgB,oBAAoB,YAEnC;AAED,wBAAgB,eAAe,YAE9B;AAED,wBAAgB,aAAa,WAE5B;AAED,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file diff --git a/packages/expo-linking/build/Linking.server.js b/packages/expo-linking/build/Linking.server.js index 97bcc0d69a4302..47c59c260c929c 100644 --- a/packages/expo-linking/build/Linking.server.js +++ b/packages/expo-linking/build/Linking.server.js @@ -22,6 +22,7 @@ export async function getInitialURL() { export function getLinkingURL() { return ''; } +export function clearInitialURL() { } export async function openURL(url) { return true; } diff --git a/packages/expo-linking/build/Linking.server.js.map b/packages/expo-linking/build/Linking.server.js.map index afe78424c7d1d4..793496ca146b8a 100644 --- a/packages/expo-linking/build/Linking.server.js.map +++ b/packages/expo-linking/build/Linking.server.js.map @@ -1 +1 @@ -{"version":3,"file":"Linking.server.js","sourceRoot":"","sources":["../src/Linking.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAIxD,MAAM,UAAU,gBAAgB,CAAC,IAAW,EAAE,OAAoB;IAChE,OAAO,EAAE,MAAM,KAAI,CAAC,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,IAAI;KAClB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc,EAAE,MAA2B;IAC1E,MAAM,IAAI,mBAAmB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,IAAI,mBAAmB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW;IACvC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,cAAc,iBAAiB,CAAC;AAEhC,MAAM,UAAU,sBAAsB;IACpC,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\n\nimport type { ParsedURL, SendIntentExtras, URLListener } from './Linking.types';\n\nexport function addEventListener(type: 'url', handler: URLListener) {\n return { remove() {} };\n}\n\nexport async function parseInitialURLAsync(): Promise {\n return {\n scheme: null,\n hostname: null,\n path: null,\n queryParams: null,\n };\n}\n\nexport async function sendIntent(action: string, extras?: SendIntentExtras[]): Promise {\n throw new UnavailabilityError('Linking', 'sendIntent');\n}\n\nexport async function openSettings(): Promise {\n throw new UnavailabilityError('Linking', 'openSettings');\n}\n\nexport async function getInitialURL(): Promise {\n return '';\n}\n\nexport function getLinkingURL() {\n return '';\n}\n\nexport async function openURL(url: string): Promise {\n return true;\n}\n\nexport async function canOpenURL() {\n return true;\n}\n\nexport function useURL(): string | null {\n return null;\n}\n\nexport function useLinkingURL() {\n return null;\n}\n\nexport * from './Linking.types';\n\nexport function collectManifestSchemes() {\n return [];\n}\n\nexport function hasConstantsManifest() {\n return false;\n}\n\nexport function hasCustomScheme() {\n return false;\n}\n\nexport function resolveScheme() {\n return '';\n}\n\nexport { parse, createURL } from './createURL';\n"]} \ No newline at end of file +{"version":3,"file":"Linking.server.js","sourceRoot":"","sources":["../src/Linking.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAIxD,MAAM,UAAU,gBAAgB,CAAC,IAAW,EAAE,OAAoB;IAChE,OAAO,EAAE,MAAM,KAAI,CAAC,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,IAAI;KAClB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc,EAAE,MAA2B;IAC1E,MAAM,IAAI,mBAAmB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,IAAI,mBAAmB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,eAAe,KAAU,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAW;IACvC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,cAAc,iBAAiB,CAAC;AAEhC,MAAM,UAAU,sBAAsB;IACpC,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\n\nimport type { ParsedURL, SendIntentExtras, URLListener } from './Linking.types';\n\nexport function addEventListener(type: 'url', handler: URLListener) {\n return { remove() {} };\n}\n\nexport async function parseInitialURLAsync(): Promise {\n return {\n scheme: null,\n hostname: null,\n path: null,\n queryParams: null,\n };\n}\n\nexport async function sendIntent(action: string, extras?: SendIntentExtras[]): Promise {\n throw new UnavailabilityError('Linking', 'sendIntent');\n}\n\nexport async function openSettings(): Promise {\n throw new UnavailabilityError('Linking', 'openSettings');\n}\n\nexport async function getInitialURL(): Promise {\n return '';\n}\n\nexport function getLinkingURL() {\n return '';\n}\n\nexport function clearInitialURL(): void {}\n\nexport async function openURL(url: string): Promise {\n return true;\n}\n\nexport async function canOpenURL() {\n return true;\n}\n\nexport function useURL(): string | null {\n return null;\n}\n\nexport function useLinkingURL() {\n return null;\n}\n\nexport * from './Linking.types';\n\nexport function collectManifestSchemes() {\n return [];\n}\n\nexport function hasConstantsManifest() {\n return false;\n}\n\nexport function hasCustomScheme() {\n return false;\n}\n\nexport function resolveScheme() {\n return '';\n}\n\nexport { parse, createURL } from './createURL';\n"]} \ No newline at end of file diff --git a/packages/expo-linking/ios/ExpoLinkingModule.swift b/packages/expo-linking/ios/ExpoLinkingModule.swift index 5c958f6281d2b8..97aa9187dfb142 100644 --- a/packages/expo-linking/ios/ExpoLinkingModule.swift +++ b/packages/expo-linking/ios/ExpoLinkingModule.swift @@ -21,6 +21,10 @@ public class ExpoLinkingModule: Module { Function("getLinkingURL") { return ExpoLinkingRegistry.shared.initialURL?.absoluteString } + + Function("clearInitialURL") { + ExpoLinkingRegistry.shared.initialURL = nil + } } @objc func handleURLReceivedNotification(_ notification: Notification) { diff --git a/packages/expo-linking/ios/ExpoLinkingRegistry.swift b/packages/expo-linking/ios/ExpoLinkingRegistry.swift index ad64e68426cd0f..1583dc4a191c69 100644 --- a/packages/expo-linking/ios/ExpoLinkingRegistry.swift +++ b/packages/expo-linking/ios/ExpoLinkingRegistry.swift @@ -1,8 +1,25 @@ +import Foundation + typealias OnURLReceivedCallback = (URL) -> Void -class ExpoLinkingRegistry { +public let clearInitialURLNotification = Notification.Name("ExpoLinkingClearInitialURL") + +class ExpoLinkingRegistry: NSObject { static let shared = ExpoLinkingRegistry() var initialURL: URL? - private init() { } + private override init() { + super.init() + NotificationCenter.default.addObserver( + self, + selector: #selector(handleClearInitialURL), + name: clearInitialURLNotification, + object: nil + ) + } + + @objc + private func handleClearInitialURL() { + initialURL = nil + } } diff --git a/packages/expo-linking/src/ExpoLinking.ts b/packages/expo-linking/src/ExpoLinking.ts index 0b2adf17d9295c..3c77c40d7c2fce 100644 --- a/packages/expo-linking/src/ExpoLinking.ts +++ b/packages/expo-linking/src/ExpoLinking.ts @@ -6,6 +6,7 @@ type ExpoLinkingModuleEvents = { declare class ExpoLinkingNativeModule extends NativeModule { getLinkingURL(): string | null; + clearInitialURL(): void; } const ExpoLinking = requireNativeModule('ExpoLinking'); diff --git a/packages/expo-linking/src/ExpoLinking.web.ts b/packages/expo-linking/src/ExpoLinking.web.ts index 7500fbc87a5b1c..948e9461e8d51e 100644 --- a/packages/expo-linking/src/ExpoLinking.web.ts +++ b/packages/expo-linking/src/ExpoLinking.web.ts @@ -27,4 +27,6 @@ export default { if (typeof window === 'undefined') return ''; return window.location.href; }, + + clearInitialURL(): void {}, }; diff --git a/packages/expo-linking/src/Linking.server.ts b/packages/expo-linking/src/Linking.server.ts index f83ef8f47e89b2..f2a2d435191bc4 100644 --- a/packages/expo-linking/src/Linking.server.ts +++ b/packages/expo-linking/src/Linking.server.ts @@ -31,6 +31,8 @@ export function getLinkingURL() { return ''; } +export function clearInitialURL(): void {} + export async function openURL(url: string): Promise { return true; } diff --git a/packages/expo-linking/src/Linking.ts b/packages/expo-linking/src/Linking.ts index 500630d978364d..ce20056b95f927 100644 --- a/packages/expo-linking/src/Linking.ts +++ b/packages/expo-linking/src/Linking.ts @@ -90,6 +90,18 @@ export function getLinkingURL(): string | null { return ExpoLinking.getLinkingURL(); } +/** + * Clears the cached initial URL used to launch the app, subsequent + * calls to [`getLinkingURL()`] return `null` until a new deep link is received. + * + * On web this is a no-op. + * @platform android + * @platform ios + */ +export function clearInitialURL(): void { + ExpoLinking.clearInitialURL?.(); +} + // @needsAudit /** * Attempt to open the given URL with an installed app. See the [Linking guide](/guides/linking)