1082815dcSEvan Baconimport { ExpoConfig } from '@expo/config-types'; 2082815dcSEvan Baconimport { XcodeProject } from 'xcode'; 3082815dcSEvan Bacon 4082815dcSEvan Baconimport { ConfigPlugin } from '../Plugin.types'; 5082815dcSEvan Baconimport { withXcodeProject } from '../plugins/ios-plugins'; 6082815dcSEvan Baconimport { addWarningIOS } from '../utils/warnings'; 7082815dcSEvan Bacon 8082815dcSEvan Baconexport const withDeviceFamily: ConfigPlugin = (config) => { 9082815dcSEvan Bacon return withXcodeProject(config, async (config) => { 10082815dcSEvan Bacon config.modResults = await setDeviceFamily(config, { 11082815dcSEvan Bacon project: config.modResults, 12082815dcSEvan Bacon }); 13082815dcSEvan Bacon return config; 14082815dcSEvan Bacon }); 15082815dcSEvan Bacon}; 16082815dcSEvan Bacon 17082815dcSEvan Baconexport function getSupportsTablet(config: Pick<ExpoConfig, 'ios'>): boolean { 18082815dcSEvan Bacon return !!config.ios?.supportsTablet; 19082815dcSEvan Bacon} 20082815dcSEvan Bacon 21082815dcSEvan Baconexport function getIsTabletOnly(config: Pick<ExpoConfig, 'ios'>): boolean { 22082815dcSEvan Bacon return !!config?.ios?.isTabletOnly; 23082815dcSEvan Bacon} 24082815dcSEvan Bacon 25082815dcSEvan Baconexport function getDeviceFamilies(config: Pick<ExpoConfig, 'ios'>): number[] { 26082815dcSEvan Bacon const supportsTablet = getSupportsTablet(config); 27082815dcSEvan Bacon const isTabletOnly = getIsTabletOnly(config); 28082815dcSEvan Bacon 29082815dcSEvan Bacon if (isTabletOnly && config.ios?.supportsTablet === false) { 30082815dcSEvan Bacon addWarningIOS( 31082815dcSEvan Bacon 'ios.supportsTablet', 32082815dcSEvan Bacon `Found contradictory values: \`{ ios: { isTabletOnly: true, supportsTablet: false } }\`. Using \`{ isTabletOnly: true }\`.` 33082815dcSEvan Bacon ); 34082815dcSEvan Bacon } 35082815dcSEvan Bacon 36082815dcSEvan Bacon // 1 is iPhone, 2 is iPad 37082815dcSEvan Bacon if (isTabletOnly) { 38082815dcSEvan Bacon return [2]; 39082815dcSEvan Bacon } else if (supportsTablet) { 40082815dcSEvan Bacon return [1, 2]; 41082815dcSEvan Bacon } else { 42082815dcSEvan Bacon // is iPhone only 43082815dcSEvan Bacon return [1]; 44082815dcSEvan Bacon } 45082815dcSEvan Bacon} 46082815dcSEvan Bacon 47082815dcSEvan Bacon/** 48082815dcSEvan Bacon * Wrapping the families in double quotes is the only way to set a value with a comma in it. 49082815dcSEvan Bacon * 50082815dcSEvan Bacon * @param deviceFamilies 51082815dcSEvan Bacon */ 52082815dcSEvan Baconexport function formatDeviceFamilies(deviceFamilies: number[]): string { 53082815dcSEvan Bacon return `"${deviceFamilies.join(',')}"`; 54082815dcSEvan Bacon} 55082815dcSEvan Bacon 56082815dcSEvan Bacon/** 57082815dcSEvan Bacon * Add to pbxproj under TARGETED_DEVICE_FAMILY 58082815dcSEvan Bacon */ 59082815dcSEvan Baconexport function setDeviceFamily( 60082815dcSEvan Bacon config: Pick<ExpoConfig, 'ios'>, 61082815dcSEvan Bacon { project }: { project: XcodeProject } 62082815dcSEvan Bacon): XcodeProject { 63082815dcSEvan Bacon const deviceFamilies = formatDeviceFamilies(getDeviceFamilies(config)); 64082815dcSEvan Bacon 65082815dcSEvan Bacon const configurations = project.pbxXCBuildConfigurationSection(); 66082815dcSEvan Bacon // @ts-ignore 67082815dcSEvan Bacon for (const { buildSettings } of Object.values(configurations || {})) { 68082815dcSEvan Bacon // Guessing that this is the best way to emulate Xcode. 69082815dcSEvan Bacon // Using `project.addToBuildSettings` modifies too many targets. 70082815dcSEvan Bacon if (typeof buildSettings?.PRODUCT_NAME !== 'undefined') { 71*76d98731SDouglas Lowder if (typeof buildSettings?.TVOS_DEPLOYMENT_TARGET !== 'undefined') { 72*76d98731SDouglas Lowder buildSettings.TARGETED_DEVICE_FAMILY = '3'; 73*76d98731SDouglas Lowder } else { 74082815dcSEvan Bacon buildSettings.TARGETED_DEVICE_FAMILY = deviceFamilies; 75082815dcSEvan Bacon } 76082815dcSEvan Bacon } 77*76d98731SDouglas Lowder } 78082815dcSEvan Bacon 79082815dcSEvan Bacon return project; 80082815dcSEvan Bacon} 81