1import chalk from 'chalk';
2
3import { Device, logUnauthorized } from './adb';
4import { AbortCommandError } from '../../../utils/errors';
5import { createSelectionFilter, promptAsync } from '../../../utils/prompts';
6
7function nameStyleForDevice(device: Device): (name: string) => string {
8  const isActive = device.isBooted;
9  if (!isActive) {
10    // Use no style changes for a disconnected device that is available to be opened.
11    return (text: string) => text;
12  }
13  // A device that is connected and ready to be used should be bolded to match iOS.
14  if (device.isAuthorized) {
15    return chalk.bold;
16  }
17  // Devices that are unauthorized and connected cannot be used, but they are connected so gray them out.
18  return (text: string) => chalk.bold(chalk.gray(text));
19}
20
21export async function promptForDeviceAsync(devices: Device[]): Promise<Device> {
22  // TODO: provide an option to add or download more simulators
23
24  const { value } = await promptAsync({
25    type: 'autocomplete',
26    name: 'value',
27    limit: 11,
28    message: 'Select a device/emulator',
29    choices: devices.map((item) => {
30      const format = nameStyleForDevice(item);
31      const type = item.isAuthorized ? item.type : 'unauthorized';
32      return {
33        title: `${format(item.name)} ${chalk.dim(`(${type})`)}`,
34        value: item.name,
35      };
36    }),
37    suggest: createSelectionFilter(),
38  });
39
40  const device = devices.find(({ name }) => name === value);
41
42  if (device?.isAuthorized === false) {
43    logUnauthorized(device);
44    throw new AbortCommandError();
45  }
46
47  return device!;
48}
49