diff --git a/packages/cli-platform-ios/src/commands/runIOS/index.ts b/packages/cli-platform-ios/src/commands/runIOS/index.ts index cff9905c7..bd31639b9 100644 --- a/packages/cli-platform-ios/src/commands/runIOS/index.ts +++ b/packages/cli-platform-ios/src/commands/runIOS/index.ts @@ -19,6 +19,7 @@ import { getDefaultUserTerminal, startServerInNewWindow, findDevServerPort, + cacheManager, } from '@react-native-community/cli-tools'; import {buildProject} from '../buildIOS/buildProject'; import {BuildFlags, buildOptions} from '../buildIOS/buildOptions'; @@ -28,7 +29,7 @@ import listIOSDevices from '../../tools/listIOSDevices'; import {promptForDeviceSelection} from '../../tools/prompts'; import getSimulators from '../../tools/getSimulators'; import {getXcodeProjectAndDir} from '../buildIOS/getXcodeProjectAndDir'; -import resolvePods from '../../tools/pods'; +import resolvePods, {getPackageJson} from '../../tools/pods'; import getArchitecture from '../../tools/getArchitecture'; import findXcodeProject from '../../config/findXcodeProject'; @@ -129,14 +130,34 @@ async function runIOS(_: Array, ctx: Config, args: FlagsT) { } and "list-devices" parameters were passed to "run" command. We will list available devices and let you choose from one.`, ); } - const selectedDevice = await promptForDeviceSelection(availableDevices); + + const packageJson = getPackageJson(ctx.root); + const preferredDevice = cacheManager.get( + packageJson.name, + 'lastUsedIOSDeviceId', + ); + + const selectedDevice = await promptForDeviceSelection( + availableDevices, + preferredDevice, + ); + if (!selectedDevice) { throw new CLIError( `Failed to select device, please try to run app without ${ args.listDevices ? 'list-devices' : 'interactive' } command.`, ); + } else { + if (selectedDevice.udid !== preferredDevice) { + cacheManager.set( + packageJson.name, + 'lastUsedIOSDeviceId', + selectedDevice.udid, + ); + } } + if (selectedDevice.type === 'simulator') { return runOnSimulator(xcodeProject, mode, scheme, args, selectedDevice); } else { diff --git a/packages/cli-platform-ios/src/tools/prompts.ts b/packages/cli-platform-ios/src/tools/prompts.ts index 0f69317a6..2aa343b5c 100644 --- a/packages/cli-platform-ios/src/tools/prompts.ts +++ b/packages/cli-platform-ios/src/tools/prompts.ts @@ -35,14 +35,27 @@ export async function promptForConfigurationSelection( } export async function promptForDeviceSelection( - availableDevices: Device[], + devices: Device[], + lastUsedIOSDeviceId?: string, ): Promise { + const sortedDevices = [...devices]; + const devicesIds = sortedDevices.map(({udid}) => udid); + + if (lastUsedIOSDeviceId) { + const preferredDeviceIndex = devicesIds.indexOf(lastUsedIOSDeviceId); + + if (preferredDeviceIndex > -1) { + const [preferredDevice] = sortedDevices.splice(preferredDeviceIndex, 1); + sortedDevices.unshift(preferredDevice); + } + } + const {device} = await prompt({ type: 'select', name: 'device', message: 'Select the device you want to use', - choices: availableDevices - .filter((d) => d.type === 'device' || d.type === 'simulator') + choices: sortedDevices + .filter(({type}) => type === 'device' || type === 'simulator') .map((d) => { const version = d.version ? ` (${d.version.match(/^(\d+\.\d+)/)?.[1]})` diff --git a/packages/cli-tools/src/cacheManager.ts b/packages/cli-tools/src/cacheManager.ts index 06f21d25e..227eb674a 100644 --- a/packages/cli-tools/src/cacheManager.ts +++ b/packages/cli-tools/src/cacheManager.ts @@ -5,7 +5,12 @@ import appDirs from 'appdirsjs'; import chalk from 'chalk'; import logger from './logger'; -type CacheKey = 'eTag' | 'lastChecked' | 'latestVersion' | 'dependencies'; +type CacheKey = + | 'eTag' + | 'lastChecked' + | 'latestVersion' + | 'dependencies' + | 'lastUsedIOSDeviceId'; type Cache = {[key in CacheKey]?: string}; function loadCache(name: string): Cache | undefined {