1import chalk from 'chalk';
2
3import { getBestSimulatorAsync } from './getBestSimulator';
4import { Device } from './simctl';
5import { createSelectionFilter, promptAsync } from '../../../utils/prompts';
6
7/**
8 * Sort the devices so the last simulator that was opened (user's default) is the first suggested.
9 *
10 * @param devices list of devices to sort.
11 * @param osType optional sort by operating system.
12 */
13export async function sortDefaultDeviceToBeginningAsync(
14  devices: Device[],
15  osType?: Device['osType']
16): Promise<Device[]> {
17  const defaultId = await getBestSimulatorAsync({ osType });
18  if (defaultId) {
19    let iterations = 0;
20    while (devices[0].udid !== defaultId && iterations < devices.length) {
21      devices.push(devices.shift()!);
22      iterations++;
23    }
24  }
25  return devices;
26}
27
28/** Prompt the user to select an Apple device, sorting the most likely option to the beginning. */
29export async function promptAppleDeviceAsync(
30  devices: Device[],
31  osType?: Device['osType']
32): Promise<Device> {
33  devices = await sortDefaultDeviceToBeginningAsync(devices, osType);
34  const results = await promptAppleDeviceInternalAsync(devices);
35  return devices.find(({ udid }) => results === udid)!;
36}
37
38async function promptAppleDeviceInternalAsync(devices: Device[]): Promise<string> {
39  // TODO: provide an option to add or download more simulators
40  // TODO: Add support for physical devices too.
41
42  const { value } = await promptAsync({
43    type: 'autocomplete',
44    name: 'value',
45    limit: 11,
46    message: 'Select a simulator',
47    choices: devices.map((item) => {
48      const isActive = item.state === 'Booted';
49      const format = isActive ? chalk.bold : (text: string) => text;
50      return {
51        title: `${format(item.name)} ${chalk.dim(`(${item.osVersion})`)}`,
52        value: item.udid,
53      };
54    }),
55    suggest: createSelectionFilter(),
56  });
57
58  return value;
59}
60