diff --git a/packages/rn-tester/js/RNTesterAppShared.js b/packages/rn-tester/js/RNTesterAppShared.js index 3f93d9aa480..27260cc901a 100644 --- a/packages/rn-tester/js/RNTesterAppShared.js +++ b/packages/rn-tester/js/RNTesterAppShared.js @@ -26,7 +26,13 @@ import { initialNavigationState, } from './utils/testerStateUtils'; import * as React from 'react'; -import {BackHandler, StyleSheet, View, useColorScheme} from 'react-native'; +import { + BackHandler, + Linking, + StyleSheet, + View, + useColorScheme, +} from 'react-native'; // RNTester App currently uses in memory storage for storing navigation state @@ -113,6 +119,45 @@ const RNTesterApp = ({ [dispatch], ); + // Setup Linking event subscription + const handleOpenUrlRequest = React.useCallback( + ({url}: {url: string, ...}) => { + // Supported URL pattern(s): + // * rntester://example/ + const match = /^rntester:\/\/example\/(.+)$/.exec(url); + if (!match) { + console.warn( + `handleOpenUrlRequest: Received unsupported URL: '${url}'`, + ); + return; + } + + const key = match[1]; + const exampleModule = RNTesterList.Modules[key]; + if (exampleModule == null) { + console.warn( + `handleOpenUrlRequest: Unable to find requested module with key: '${key}'`, + ); + return; + } + + console.log(`handleOpenUrlRequest: Opening example '${key}'`); + + dispatch({ + type: RNTesterNavigationActionsType.EXAMPLE_OPEN_URL_REQUEST, + data: { + key, + title: exampleModule.title || key, + }, + }); + }, + [dispatch], + ); + React.useEffect(() => { + const subscription = Linking.addEventListener('url', handleOpenUrlRequest); + return () => subscription.remove(); + }, [handleOpenUrlRequest]); + const theme = colorScheme === 'dark' ? themes.dark : themes.light; if (examplesList === null) { diff --git a/packages/rn-tester/js/utils/RNTesterNavigationReducer.js b/packages/rn-tester/js/utils/RNTesterNavigationReducer.js index 9c2097d668c..db59ba5a7a7 100644 --- a/packages/rn-tester/js/utils/RNTesterNavigationReducer.js +++ b/packages/rn-tester/js/utils/RNTesterNavigationReducer.js @@ -18,6 +18,7 @@ export const RNTesterNavigationActionsType = { BACK_BUTTON_PRESS: 'BACK_BUTTON_PRESS', MODULE_CARD_PRESS: 'MODULE_CARD_PRESS', EXAMPLE_CARD_PRESS: 'EXAMPLE_CARD_PRESS', + EXAMPLE_OPEN_URL_REQUEST: 'EXAMPLE_OPEN_URL_REQUEST', }; const getUpdatedRecentlyUsed = ({ @@ -100,6 +101,14 @@ export const RNTesterNavigationReducer = ( state.activeModuleExampleKey != null ? state.activeModuleTitle : null, }; + case RNTesterNavigationActionsType.EXAMPLE_OPEN_URL_REQUEST: + return { + ...state, + activeModuleKey: key, + activeModuleTitle: title, + activeModuleExampleKey: null, + }; + default: throw new Error(`Invalid action type ${action.type}`); }