diff --git a/src/dispatcher/iOSDevice.tsx b/src/dispatcher/iOSDevice.tsx index 9f5f16a37..9dc0b37bf 100644 --- a/src/dispatcher/iOSDevice.tsx +++ b/src/dispatcher/iOSDevice.tsx @@ -7,6 +7,7 @@ import {ChildProcess} from 'child_process'; import {Store} from '../reducers/index'; +import {setXcodeDetected} from '../reducers/application'; import {Logger} from '../fb-interfaces/Logger'; import {DeviceType} from '../devices/BaseDevice'; import {promisify} from 'util'; @@ -150,7 +151,7 @@ function getActiveDevices(): Promise> { } function queryDevicesForever(store: Store, logger: Logger) { - queryDevices(store, logger) + return queryDevices(store, logger) .then(() => { // It's important to schedule the next check AFTER the current one has completed // to avoid simultaneous queries which can cause multiple user input prompts. @@ -189,6 +190,12 @@ async function checkXcodeVersionMismatch() { } } +async function isXcodeDetected(): Promise { + return promisify(child_process.exec)('xcode-select -p') + .then(_ => true) + .catch(_ => false); +} + export async function getActiveDevicesAndSimulators(): Promise< Array > { @@ -208,5 +215,12 @@ export default (store: Store, logger: Logger) => { if (process.platform !== 'darwin') { return; } - queryDevicesForever(store, logger); + isXcodeDetected() + .then(isDetected => { + store.dispatch(setXcodeDetected(isDetected)); + return isDetected; + }) + .then(isDetected => + isDetected ? queryDevicesForever(store, logger) : Promise.resolve(), + ); }; diff --git a/src/reducers/application.tsx b/src/reducers/application.tsx index 99c81465c..141eab865 100644 --- a/src/reducers/application.tsx +++ b/src/reducers/application.tsx @@ -76,6 +76,7 @@ export type State = { launcherMsg: LauncherMsg; flipperRating: number | null; statusMessages: Array; + xcodeCommandLineToolsDetected: boolean; }; type BooleanActionType = @@ -140,6 +141,12 @@ export type Action = | { type: 'REMOVE_STATUS_MSG'; payload: {msg: string; sender: string}; + } + | { + type: 'SET_XCODE_DETECTED'; + payload: { + isDetected: boolean; + }; }; export const initialState: () => State = () => ({ @@ -161,6 +168,7 @@ export const initialState: () => State = () => ({ }, flipperRating: null, statusMessages: [], + xcodeCommandLineToolsDetected: false, }); function statusMessage(sender: string, msg: string): string { @@ -268,6 +276,8 @@ export default function reducer( return {...state, statusMessages}; } return state; + } else if (action.type === 'SET_XCODE_DETECTED') { + return {...state, xcodeCommandLineToolsDetected: action.payload.isDetected}; } else { return state; } @@ -345,3 +355,8 @@ export const removeStatusMessage = (payload: StatusMessageType): Action => ({ type: 'REMOVE_STATUS_MSG', payload, }); + +export const setXcodeDetected = (isDetected: boolean): Action => ({ + type: 'SET_XCODE_DETECTED', + payload: {isDetected}, +}); diff --git a/src/utils/listDevices.tsx b/src/utils/listDevices.tsx index 66d94e704..03e8dbed4 100644 --- a/src/utils/listDevices.tsx +++ b/src/utils/listDevices.tsx @@ -10,7 +10,13 @@ import BaseDevice from '../devices/BaseDevice'; import {Store} from '../reducers/index'; export async function listDevices(store: Store): Promise> { - const androidDevices = await getActiveAndroidDevices(store); - const iOSDevices: BaseDevice[] = await getActiveDevicesAndSimulators(); - return iOSDevices.concat(androidDevices); + const state = store.getState(); + const androidDevices = state.settingsState.enableAndroid + ? await getActiveAndroidDevices(store) + : []; + const iOSDevices: BaseDevice[] = state.application + .xcodeCommandLineToolsDetected + ? await getActiveDevicesAndSimulators() + : []; + return [...androidDevices, ...iOSDevices]; }