diff --git a/native/profile/linked-devices-header-right-button.react.js b/native/profile/linked-devices-header-right-button.react.js index b612b34a4..70f2d8ede 100644 --- a/native/profile/linked-devices-header-right-button.react.js +++ b/native/profile/linked-devices-header-right-button.react.js @@ -1,34 +1,44 @@ // @flow import { useNavigation } from '@react-navigation/native'; import * as React from 'react'; import { Text, TouchableOpacity } from 'react-native'; import { SecondaryDeviceQRCodeScannerRouteName } from '../navigation/route-names.js'; import { useStyles } from '../themes/colors.js'; +import Alert from '../utils/alert.js'; +import { deviceIsEmulator } from '../utils/url-utils.js'; function LinkedDevicesHeaderRightButton(): React.Node { const styles = useStyles(unboundStyles); - const navigation = useNavigation(); + const { navigate } = useNavigation(); - const navigateToQRCodeScanner = React.useCallback( - () => navigation.navigate(SecondaryDeviceQRCodeScannerRouteName), - [navigation], - ); + const navigateToQRCodeScanner = React.useCallback(() => { + if (deviceIsEmulator) { + Alert.alert( + 'Unsupported device', + "You can't access the QR code scanner on a simulator.", + [{ text: 'OK' }], + { cancelable: false }, + ); + return; + } + navigate(SecondaryDeviceQRCodeScannerRouteName); + }, [navigate]); return ( Add ); } const unboundStyles = { textStyle: { color: 'headerChevron', fontSize: 16, marginRight: 10, }, }; export default LinkedDevicesHeaderRightButton; diff --git a/native/utils/url-utils.js b/native/utils/url-utils.js index 76dad957b..9c7218c33 100644 --- a/native/utils/url-utils.js +++ b/native/utils/url-utils.js @@ -1,81 +1,82 @@ // @flow import invariant from 'invariant'; import { Platform } from 'react-native'; import DeviceInfo from 'react-native-device-info'; import urlParseLax from 'url-parse-lax'; import { natDevHostname, checkForMissingNatDevHostname, } from './dev-hostname.js'; const localhostHostname = 'localhost'; const localhostHostnameFromAndroidEmulator = '10.0.2.2'; const productionNodeServerURL = 'https://squadcal.org'; const productionLandingURL = 'https://comm.app'; -const devIsEmulator: boolean = __DEV__ && DeviceInfo.isEmulatorSync(); +const deviceIsEmulator: boolean = __DEV__ && DeviceInfo.isEmulatorSync(); // ESLint doesn't recognize that invariant always throws // eslint-disable-next-line consistent-return function getDevServerHostname(): string { - if (!devIsEmulator) { + if (!deviceIsEmulator) { checkForMissingNatDevHostname(); return natDevHostname; } else if (Platform.OS === 'android') { return localhostHostnameFromAndroidEmulator; } else if (Platform.OS === 'ios') { return localhostHostname; } invariant(false, `unsupported platform: ${Platform.OS}`); } function getDevNodeServerURLFromHostname(hostname: string): string { return `http://${hostname}:3000/comm`; } function getDevLandingURLFromHostname(hostname: string): string { return `http://${hostname}:3000/commlanding`; } function getDevNodeServerURL(): string { const hostname = getDevServerHostname(); return getDevNodeServerURLFromHostname(hostname); } function getDevLandingURL(): string { const hostname = getDevServerHostname(); return getDevLandingURLFromHostname(hostname); } const nodeServerOptions: string[] = [ productionNodeServerURL, getDevNodeServerURL(), ]; const defaultURLPrefix: string = __DEV__ ? getDevNodeServerURL() : productionNodeServerURL; const defaultLandingURLPrefix: string = __DEV__ ? getDevLandingURL() : productionLandingURL; const natNodeServer: string = getDevNodeServerURLFromHostname(natDevHostname); const setCustomServer = 'SET_CUSTOM_SERVER'; function normalizeURL(url: string): string { return urlParseLax(url).href; } export { defaultURLPrefix, defaultLandingURLPrefix, getDevServerHostname, nodeServerOptions, natNodeServer, setCustomServer, normalizeURL, + deviceIsEmulator, };