diff --git a/flow-typed/npm/which_v1.x.x.js b/flow-typed/npm/which_v1.x.x.js new file mode 100644 index 000000000..661a731aa --- /dev/null +++ b/flow-typed/npm/which_v1.x.x.js @@ -0,0 +1,13 @@ +declare module "which" { + declare type Options = {|path?: string, pathExt?: string, all?: boolean|}; + declare function whichAsync(cmd: string, cb: (err: ?Error, path: string) => void): void; + declare function whichAsync(cmd: string, options: Options, cb: (err: ?Error, path: string) => void): void; + + declare function whichSync(cmd: string, options?: Options): string; + declare function whichSync(cmd: string, options: {|...Options, noThrow?: false|}): string; + declare function whichSync(cmd: string, options: {|...Options, noThrow: true|}): ?string; + declare module.exports: { + [[call]]: typeof whichAsync, + sync: typeof whichSync + } +} diff --git a/package.json b/package.json index 61be1888d..2db2593f3 100644 --- a/package.json +++ b/package.json @@ -92,6 +92,7 @@ "string-natural-compare": "^2.0.2", "tmp": "^0.0.33", "websocket": "^1.0.24", + "which": "^1.3.1", "xml2js": "^0.4.19", "yargs": "^11.0.0" }, diff --git a/src/chrome/DevicesButton.js b/src/chrome/DevicesButton.js index 5edde314e..35f6fea15 100644 --- a/src/chrome/DevicesButton.js +++ b/src/chrome/DevicesButton.js @@ -8,9 +8,14 @@ import {Component, Button, styled} from 'flipper'; import {connect} from 'react-redux'; import {spawn} from 'child_process'; +import {dirname} from 'path'; import {selectDevice, preferDevice} from '../reducers/connections.js'; +import {default as which} from 'which'; +import {promisify} from 'util'; import type BaseDevice from '../devices/BaseDevice.js'; +const whichPromise = promisify(which); + type Props = { selectedDevice: ?BaseDevice, androidEmulators: Array, @@ -27,13 +32,18 @@ const DropdownButton = styled(Button)({ /* eslint-disable prettier/prettier */ class DevicesButton extends Component { launchEmulator = (name: string) => { - const child = spawn('emulator', [`@${name}`], { - detached: true, - }); - child.stderr.on('data', data => { - console.error(`Android emulator error: ${data}`); - }); - child.on('error', console.error); + // On Linux, you must run the emulator from the directory it's in because + // reasons ... + whichPromise('emulator').then(emulatorPath => { + const child = spawn(emulatorPath, [`@${name}`], { + detached: true, + cwd: dirname(emulatorPath), + }); + child.stderr.on('data', data => { + console.error(`Android emulator error: ${data}`); + }); + child.on('error', console.error); + }).catch(console.error); this.props.preferDevice(name); }; diff --git a/yarn.lock b/yarn.lock index 6dad39c8e..391207309 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6696,7 +6696,7 @@ which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" -which@^1.2.12, which@^1.2.9, which@^1.3.0: +which@^1.2.12, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" dependencies: