1import { ExpoConfig } from '@expo/config-types'; 2import { XcodeProject } from 'xcode'; 3 4import { ConfigPlugin } from '../Plugin.types'; 5import { withXcodeProject } from '../plugins/ios-plugins'; 6import { addWarningIOS } from '../utils/warnings'; 7 8export const withDeviceFamily: ConfigPlugin = (config) => { 9 return withXcodeProject(config, async (config) => { 10 config.modResults = await setDeviceFamily(config, { 11 project: config.modResults, 12 }); 13 return config; 14 }); 15}; 16 17export function getSupportsTablet(config: Pick<ExpoConfig, 'ios'>): boolean { 18 return !!config.ios?.supportsTablet; 19} 20 21export function getIsTabletOnly(config: Pick<ExpoConfig, 'ios'>): boolean { 22 return !!config?.ios?.isTabletOnly; 23} 24 25export function getDeviceFamilies(config: Pick<ExpoConfig, 'ios'>): number[] { 26 const supportsTablet = getSupportsTablet(config); 27 const isTabletOnly = getIsTabletOnly(config); 28 29 if (isTabletOnly && config.ios?.supportsTablet === false) { 30 addWarningIOS( 31 'ios.supportsTablet', 32 `Found contradictory values: \`{ ios: { isTabletOnly: true, supportsTablet: false } }\`. Using \`{ isTabletOnly: true }\`.` 33 ); 34 } 35 36 // 1 is iPhone, 2 is iPad 37 if (isTabletOnly) { 38 return [2]; 39 } else if (supportsTablet) { 40 return [1, 2]; 41 } else { 42 // is iPhone only 43 return [1]; 44 } 45} 46 47/** 48 * Wrapping the families in double quotes is the only way to set a value with a comma in it. 49 * 50 * @param deviceFamilies 51 */ 52export function formatDeviceFamilies(deviceFamilies: number[]): string { 53 return `"${deviceFamilies.join(',')}"`; 54} 55 56/** 57 * Add to pbxproj under TARGETED_DEVICE_FAMILY 58 */ 59export function setDeviceFamily( 60 config: Pick<ExpoConfig, 'ios'>, 61 { project }: { project: XcodeProject } 62): XcodeProject { 63 const deviceFamilies = formatDeviceFamilies(getDeviceFamilies(config)); 64 65 const configurations = project.pbxXCBuildConfigurationSection(); 66 // @ts-ignore 67 for (const { buildSettings } of Object.values(configurations || {})) { 68 // Guessing that this is the best way to emulate Xcode. 69 // Using `project.addToBuildSettings` modifies too many targets. 70 if (typeof buildSettings?.PRODUCT_NAME !== 'undefined') { 71 if (typeof buildSettings?.TVOS_DEPLOYMENT_TARGET !== 'undefined') { 72 buildSettings.TARGETED_DEVICE_FAMILY = '3'; 73 } else { 74 buildSettings.TARGETED_DEVICE_FAMILY = deviceFamilies; 75 } 76 } 77 } 78 79 return project; 80} 81