From 197b4d615b207e7dc3726b52151332b837201392 Mon Sep 17 00:00:00 2001 From: Evan Bacon Date: Tue, 13 Oct 2020 22:54:17 +0200 Subject: [PATCH 1/4] unify android metadata tools --- packages/config/src/android/Facebook.ts | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/packages/config/src/android/Facebook.ts b/packages/config/src/android/Facebook.ts index e5cbba8751..70bf54c5d5 100644 --- a/packages/config/src/android/Facebook.ts +++ b/packages/config/src/android/Facebook.ts @@ -1,7 +1,12 @@ import { Parser } from 'xml2js'; import { ExpoConfig } from '../Config.types'; -import { addMetaDataItemToMainApplication, Document, getMainApplication } from './Manifest'; +import { + addMetaDataItemToMainApplication, + Document, + getMainApplication, + removeMetaDataItemFromMainApplication, +} from './Manifest'; import { readResourcesXMLAsync, ResourceItemXML } from './Resources'; import { getProjectStringsXMLPathAsync, removeStringItem, setStringItem } from './Strings'; import { writeXMLAsync } from './XML'; @@ -98,7 +103,7 @@ export async function setFacebookAppIdString(config: ExpoConfig, projectDirector return true; } -export async function setFacebookConfig(config: ExpoConfig, manifestDocument: Document) { +export function setFacebookConfig(config: ExpoConfig, manifestDocument: Document) { const scheme = getFacebookScheme(config); const appId = getFacebookAppId(config); const displayName = getFacebookDisplayName(config); @@ -177,17 +182,3 @@ export async function setFacebookConfig(config: ExpoConfig, manifestDocument: Do return manifestDocument; } - -// TODO: Use Manifest version after https://github.com/expo/expo-cli/pull/2587 lands -function removeMetaDataItemFromMainApplication(mainApplication: any, itemName: string) { - if (mainApplication.hasOwnProperty('meta-data')) { - const index = mainApplication['meta-data'].findIndex( - (e: any) => e['$']['android:name'] === itemName - ); - - if (index > -1) { - mainApplication['meta-data'].splice(index, 1); - } - } - return mainApplication; -} From 67a5b86402e77128cacf00d3b18fcbbc58acee93 Mon Sep 17 00:00:00 2001 From: Evan Bacon Date: Tue, 13 Oct 2020 22:54:24 +0200 Subject: [PATCH 2/4] Update Icon.ts --- packages/config/src/android/Icon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/config/src/android/Icon.ts b/packages/config/src/android/Icon.ts index 62458f8e15..d75adf6c86 100644 --- a/packages/config/src/android/Icon.ts +++ b/packages/config/src/android/Icon.ts @@ -263,7 +263,7 @@ async function createAdaptiveIconXmlFiles(projectRoot: string, icLauncherXmlStri async function removeBackgroundImageFilesAsync(projectRoot: string) { Promise.all( - Object.values(dpiValues).map(async ({ folderName, scale }) => { + Object.values(dpiValues).map(async ({ folderName }) => { const dpiFolderPath = path.resolve(projectRoot, ANDROID_RES_PATH, folderName); await fs.remove(path.resolve(dpiFolderPath, IC_LAUNCHER_BACKGROUND_PNG)); }) From a8c39a9115de55acb0f947a82d3cad0fe0f242d8 Mon Sep 17 00:00:00 2001 From: Evan Bacon Date: Tue, 13 Oct 2020 23:09:24 +0200 Subject: [PATCH 3/4] added unified project modifier --- packages/config/src/ios/DeviceFamily.ts | 11 +++++---- packages/config/src/ios/Google.ts | 13 +++++++---- packages/config/src/ios/Locales.ts | 19 +++++++-------- .../src/ios/__tests__/DeviceFamily-test.ts | 14 ++++++++--- .../config/src/ios/__tests__/Locales-test.ts | 9 ++++++-- .../apply/configureIOSProjectAsync.ts | 23 +++++++++++++++---- 6 files changed, 59 insertions(+), 30 deletions(-) diff --git a/packages/config/src/ios/DeviceFamily.ts b/packages/config/src/ios/DeviceFamily.ts index f9ccee132e..e5b740dfe6 100644 --- a/packages/config/src/ios/DeviceFamily.ts +++ b/packages/config/src/ios/DeviceFamily.ts @@ -1,7 +1,6 @@ -import * as fs from 'fs-extra'; +import { XcodeProject } from 'xcode'; import { ExpoConfig } from '../Config.types'; -import { getPbxproj } from './utils/Xcodeproj'; export function getSupportsTablet(config: ExpoConfig): boolean { return !!config.ios?.supportsTablet; @@ -38,10 +37,12 @@ export function formatDeviceFamilies(deviceFamilies: number[]): string { /** * Add to pbxproj under TARGETED_DEVICE_FAMILY */ -export function setDeviceFamily(config: ExpoConfig, projectRoot: string) { +export function setDeviceFamily( + config: ExpoConfig, + { project }: { project: XcodeProject } +): XcodeProject { const deviceFamilies = formatDeviceFamilies(getDeviceFamilies(config)); - const project = getPbxproj(projectRoot); const configurations = project.pbxXCBuildConfigurationSection(); // @ts-ignore for (const { buildSettings } of Object.values(configurations || {})) { @@ -52,5 +53,5 @@ export function setDeviceFamily(config: ExpoConfig, projectRoot: string) { } } - fs.writeFileSync(project.filepath, project.writeSync()); + return project; } diff --git a/packages/config/src/ios/Google.ts b/packages/config/src/ios/Google.ts index b09bd6f716..a6587ec450 100644 --- a/packages/config/src/ios/Google.ts +++ b/packages/config/src/ios/Google.ts @@ -1,11 +1,12 @@ import fs from 'fs-extra'; import path from 'path'; +import { XcodeProject } from 'xcode'; import { ExpoConfig } from '../Config.types'; import { InfoPlist } from './IosConfig.types'; import { getSourceRoot } from './Paths'; import { appendScheme } from './Scheme'; -import { addFileToGroup, getPbxproj, getProjectName } from './utils/Xcodeproj'; +import { addFileToGroup, getProjectName } from './utils/Xcodeproj'; export function getGoogleMapsApiKey(config: ExpoConfig) { return config.ios?.config?.googleMapsApiKey ?? null; @@ -82,10 +83,13 @@ export function setGoogleConfig(config: ExpoConfig, infoPlist: InfoPlist): InfoP return infoPlist; } -export function setGoogleServicesFile(config: ExpoConfig, projectRoot: string) { +export function setGoogleServicesFile( + config: ExpoConfig, + { projectRoot, project }: { project: XcodeProject; projectRoot: string } +): XcodeProject { const googleServicesFileRelativePath = getGoogleServicesFile(config); if (googleServicesFileRelativePath === null) { - return; + return project; } const googleServiceFilePath = path.resolve(projectRoot, googleServicesFileRelativePath); @@ -94,8 +98,7 @@ export function setGoogleServicesFile(config: ExpoConfig, projectRoot: string) { path.join(getSourceRoot(projectRoot), 'GoogleService-Info.plist') ); - let project = getPbxproj(projectRoot); const projectName = getProjectName(projectRoot); project = addFileToGroup(`${projectName}/GoogleService-Info.plist`, projectName, project); - fs.writeFileSync(project.filepath, project.writeSync()); + return project; } diff --git a/packages/config/src/ios/Locales.ts b/packages/config/src/ios/Locales.ts index 46a1b9d530..cd3750ec22 100644 --- a/packages/config/src/ios/Locales.ts +++ b/packages/config/src/ios/Locales.ts @@ -1,15 +1,11 @@ import JsonFile from '@expo/json-file'; import * as fs from 'fs-extra'; import { join } from 'path'; +import { XcodeProject } from 'xcode'; import { ExpoConfig } from '../Config.types'; import { addWarningIOS } from '../WarningAggregator'; -import { - addFileToGroup, - ensureGroupRecursively, - getPbxproj, - getProjectName, -} from './utils/Xcodeproj'; +import { addFileToGroup, ensureGroupRecursively, getProjectName } from './utils/Xcodeproj'; type LocaleJson = Record; type ResolvedLocalesJson = Record; @@ -19,15 +15,17 @@ export function getLocales(config: ExpoConfig): Record { +export async function setLocalesAsync( + config: ExpoConfig, + { projectRoot, project }: { projectRoot: string; project: XcodeProject } +): Promise { const locales = getLocales(config); if (!locales) { - return; + return project; } // possibly validate CFBundleAllowMixedLocalizations is enabled const localesMap = await getResolvedLocalesAsync(projectRoot, locales); - let project = getPbxproj(projectRoot); const projectName = getProjectName(projectRoot); const supportingDirectory = join(projectRoot, 'ios', projectName, 'Supporting'); @@ -55,8 +53,7 @@ export async function setLocalesAsync(config: ExpoConfig, projectRoot: string): } } - // Sync the Xcode project with the changes. - fs.writeFileSync(project.filepath, project.writeSync()); + return project; } export async function getResolvedLocalesAsync( diff --git a/packages/config/src/ios/__tests__/DeviceFamily-test.ts b/packages/config/src/ios/__tests__/DeviceFamily-test.ts index 583fb3d0e9..1e77bf967f 100644 --- a/packages/config/src/ios/__tests__/DeviceFamily-test.ts +++ b/packages/config/src/ios/__tests__/DeviceFamily-test.ts @@ -1,3 +1,4 @@ +import { ExpoConfig } from '@expo/config-types'; import { fs, vol } from 'memfs'; import * as path from 'path'; @@ -8,6 +9,7 @@ import { getSupportsTablet, setDeviceFamily, } from '../DeviceFamily'; +import { getPbxproj } from '../utils/Xcodeproj'; const actualFs = jest.requireActual('fs') as typeof fs; @@ -99,8 +101,14 @@ describe(setDeviceFamily, () => { }); it('updates device families without throwing', async () => { - setDeviceFamily({ name: '', slug: '', ios: {} }, projectRoot); - setDeviceFamily({ name: '', slug: '', ios: { supportsTablet: true } }, projectRoot); - setDeviceFamily({ name: '', slug: '', ios: { isTabletOnly: true } }, projectRoot); + setDeviceFamilyForRoot({ name: '', slug: '', ios: {} }, projectRoot); + setDeviceFamilyForRoot({ name: '', slug: '', ios: { supportsTablet: true } }, projectRoot); + setDeviceFamilyForRoot({ name: '', slug: '', ios: { isTabletOnly: true } }, projectRoot); }); }); + +function setDeviceFamilyForRoot(config: ExpoConfig, projectRoot: string) { + let project = getPbxproj(projectRoot); + project = setDeviceFamily(config, { project }); + fs.writeFileSync(project.filepath, project.writeSync()); +} diff --git a/packages/config/src/ios/__tests__/Locales-test.ts b/packages/config/src/ios/__tests__/Locales-test.ts index de1cd1a1c0..42e87f8505 100644 --- a/packages/config/src/ios/__tests__/Locales-test.ts +++ b/packages/config/src/ios/__tests__/Locales-test.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import { addWarningIOS } from '../../WarningAggregator'; import { getLocales, setLocalesAsync } from '../Locales'; +import { getPbxproj } from '../utils/Xcodeproj'; const actualFs = jest.requireActual('fs') as typeof fs; jest.mock('fs'); @@ -61,7 +62,9 @@ describe('e2e: iOS locales', () => { projectRoot ); - await setLocalesAsync( + let project = getPbxproj(projectRoot); + + project = await setLocalesAsync( { slug: 'testproject', version: '1', @@ -75,8 +78,10 @@ describe('e2e: iOS locales', () => { es: { CFBundleDisplayName: 'spanish-name' }, }, }, - projectRoot + { project, projectRoot } ); + // Sync the Xcode project with the changes. + fs.writeFileSync(project.filepath, project.writeSync()); }); afterAll(() => { diff --git a/packages/expo-cli/src/commands/apply/configureIOSProjectAsync.ts b/packages/expo-cli/src/commands/apply/configureIOSProjectAsync.ts index 27bc872c59..4b0c6f5b27 100644 --- a/packages/expo-cli/src/commands/apply/configureIOSProjectAsync.ts +++ b/packages/expo-cli/src/commands/apply/configureIOSProjectAsync.ts @@ -1,7 +1,9 @@ import { getConfig, IOSConfig, WarningAggregator } from '@expo/config'; -import { getProjectName } from '@expo/config/build/ios/utils/Xcodeproj'; +import { getPbxproj, getProjectName } from '@expo/config/build/ios/utils/Xcodeproj'; import { IosPlist, UserManager } from '@expo/xdl'; +import { writeFile } from 'fs-extra'; import path from 'path'; +import { XcodeProject } from 'xcode'; import { getOrPromptForBundleIdentifier } from '../eject/ConfigValidation'; @@ -13,7 +15,13 @@ export default async function configureIOSProjectAsync(projectRoot: string) { const { exp } = getConfig(projectRoot, { skipSDKVersionRequirement: true }); const username = await UserManager.getCurrentUsernameAsync(); - IOSConfig.Google.setGoogleServicesFile(exp, projectRoot); + // Configure the Xcode project + await modifyPbxprojAsync(projectRoot, async project => { + project = await IOSConfig.Google.setGoogleServicesFile(exp, { project, projectRoot }); + project = await IOSConfig.Locales.setLocalesAsync(exp, { project, projectRoot }); + project = IOSConfig.DeviceFamily.setDeviceFamily(exp, { project }); + return project; + }); // Configure the Info.plist await modifyInfoPlistAsync(projectRoot, infoPlist => { @@ -70,8 +78,15 @@ export default async function configureIOSProjectAsync(projectRoot: string) { // Other await IOSConfig.Icons.setIconsAsync(exp, projectRoot); await IOSConfig.SplashScreen.setSplashScreenAsync(exp, projectRoot); - await IOSConfig.Locales.setLocalesAsync(exp, projectRoot); - IOSConfig.DeviceFamily.setDeviceFamily(exp, projectRoot); +} + +async function modifyPbxprojAsync( + projectRoot: string, + callbackAsync: (project: XcodeProject) => Promise +) { + const project = getPbxproj(projectRoot); + const result = await callbackAsync(project); + await writeFile(project.filepath, result.writeSync()); } async function modifyEntitlementsPlistAsync(projectRoot: string, callback: (plist: any) => any) { From b48514768a9a306e8f6a66772ae69259a5288de1 Mon Sep 17 00:00:00 2001 From: Evan Bacon Date: Wed, 14 Oct 2020 00:23:31 +0200 Subject: [PATCH 4/4] Update Facebook.ts --- packages/config/src/android/Facebook.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/config/src/android/Facebook.ts b/packages/config/src/android/Facebook.ts index 70bf54c5d5..cdf4ed603d 100644 --- a/packages/config/src/android/Facebook.ts +++ b/packages/config/src/android/Facebook.ts @@ -67,16 +67,13 @@ async function ensureFacebookActivityAsync({ }) { const facebookSchemeActivityXML = facebookSchemeActivity(scheme); const parser = new Parser(); - const facebookSchemeActivityJSON = await parser.parseStringPromise(facebookSchemeActivityXML); + const facebookSchemeActivityJSON = (await parser.parseStringPromise(facebookSchemeActivityXML)) + .activity; - //TODO: don't write if facebook scheme activity is already present - if ('activity' in mainApplication) { - mainApplication['activity'] = mainApplication['activity'].concat( - facebookSchemeActivityJSON['activity'] - ); - } else { - mainApplication['activity'] = facebookSchemeActivityJSON['activity']; + if (!Array.isArray(mainApplication.activity)) { + mainApplication.activity = []; } + mainApplication.activity.push(facebookSchemeActivityJSON); } export async function setFacebookAppIdString(config: ExpoConfig, projectDirectory: string) {