diff --git a/packages/@expo/cli/e2e/__tests__/prebuild-test.ts b/packages/@expo/cli/e2e/__tests__/prebuild-test.ts index 89405dc52a415..3e4ffbc08aece 100644 --- a/packages/@expo/cli/e2e/__tests__/prebuild-test.ts +++ b/packages/@expo/cli/e2e/__tests__/prebuild-test.ts @@ -183,6 +183,7 @@ it( "ios/Podfile.properties.json", "ios/basicprebuild/AppDelegate.h", "ios/basicprebuild/AppDelegate.mm", + "ios/basicprebuild/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png", "ios/basicprebuild/Images.xcassets/AppIcon.appiconset/Contents.json", "ios/basicprebuild/Images.xcassets/Contents.json", "ios/basicprebuild/Images.xcassets/SplashScreenBackground.imageset/Contents.json", @@ -296,6 +297,7 @@ it( "ios/Podfile.properties.json", "ios/githubtemplateprebuild/AppDelegate.h", "ios/githubtemplateprebuild/AppDelegate.mm", + "ios/githubtemplateprebuild/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png", "ios/githubtemplateprebuild/Images.xcassets/AppIcon.appiconset/Contents.json", "ios/githubtemplateprebuild/Images.xcassets/Contents.json", "ios/githubtemplateprebuild/Images.xcassets/SplashScreenBackground.imageset/Contents.json", diff --git a/packages/@expo/image-utils/CHANGELOG.md b/packages/@expo/image-utils/CHANGELOG.md index 936df67934fe0..5a694545c36c4 100644 --- a/packages/@expo/image-utils/CHANGELOG.md +++ b/packages/@expo/image-utils/CHANGELOG.md @@ -6,7 +6,10 @@ ### 🎉 New features +- Expose `createSquareAsync` to generate a square image from a color. ([#27774](https://github.com/expo/expo/pull/27774) by [@EvanBacon](https://github.com/EvanBacon)) + ### 🐛 Bug fixes + - Fixed vulnerability with update semver from 7.5.3 to 7.5.4. ([#26876](https://github.com/expo/expo/pull/26876) by [@GaelCO](https://github.com/GaelCO)) ### 💡 Others diff --git a/packages/@expo/image-utils/build/index.d.ts b/packages/@expo/image-utils/build/index.d.ts index 13936d2298074..3a24de6cfc65d 100644 --- a/packages/@expo/image-utils/build/index.d.ts +++ b/packages/@expo/image-utils/build/index.d.ts @@ -2,9 +2,9 @@ import * as Cache from './Cache'; import { compositeImagesAsync, generateFaviconAsync, generateImageAsync, getPngInfo } from './Image'; import { ImageFormat, ImageOptions, ResizeMode } from './Image.types'; -import { jimpAsync } from './jimp'; +import { jimpAsync, createSquareAsync } from './jimp'; import { findSharpInstanceAsync, isAvailableAsync, sharpAsync } from './sharp'; import { SharpCommandOptions, SharpGlobalOptions } from './sharp.types'; export declare function imageAsync(options: SharpGlobalOptions, commands?: SharpCommandOptions[]): Promise; -export { jimpAsync, findSharpInstanceAsync, isAvailableAsync, sharpAsync, generateImageAsync, generateFaviconAsync, Cache, compositeImagesAsync, getPngInfo, }; +export { jimpAsync, createSquareAsync, findSharpInstanceAsync, isAvailableAsync, sharpAsync, generateImageAsync, generateFaviconAsync, Cache, compositeImagesAsync, getPngInfo, }; export { SharpGlobalOptions, SharpCommandOptions, ResizeMode, ImageFormat, ImageOptions }; diff --git a/packages/@expo/image-utils/build/index.js b/packages/@expo/image-utils/build/index.js index 493d8f8dc15e9..788d59c3cc9ec 100644 --- a/packages/@expo/image-utils/build/index.js +++ b/packages/@expo/image-utils/build/index.js @@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.getPngInfo = exports.compositeImagesAsync = exports.Cache = exports.generateFaviconAsync = exports.generateImageAsync = exports.sharpAsync = exports.isAvailableAsync = exports.findSharpInstanceAsync = exports.jimpAsync = exports.imageAsync = void 0; +exports.getPngInfo = exports.compositeImagesAsync = exports.Cache = exports.generateFaviconAsync = exports.generateImageAsync = exports.sharpAsync = exports.isAvailableAsync = exports.findSharpInstanceAsync = exports.createSquareAsync = exports.jimpAsync = exports.imageAsync = void 0; const Cache = __importStar(require("./Cache")); exports.Cache = Cache; const Image_1 = require("./Image"); @@ -33,6 +33,7 @@ Object.defineProperty(exports, "generateImageAsync", { enumerable: true, get: fu Object.defineProperty(exports, "getPngInfo", { enumerable: true, get: function () { return Image_1.getPngInfo; } }); const jimp_1 = require("./jimp"); Object.defineProperty(exports, "jimpAsync", { enumerable: true, get: function () { return jimp_1.jimpAsync; } }); +Object.defineProperty(exports, "createSquareAsync", { enumerable: true, get: function () { return jimp_1.createSquareAsync; } }); const sharp_1 = require("./sharp"); Object.defineProperty(exports, "findSharpInstanceAsync", { enumerable: true, get: function () { return sharp_1.findSharpInstanceAsync; } }); Object.defineProperty(exports, "isAvailableAsync", { enumerable: true, get: function () { return sharp_1.isAvailableAsync; } }); diff --git a/packages/@expo/image-utils/build/index.js.map b/packages/@expo/image-utils/build/index.js.map index 0e9aaee9eb4c1..2de850cd1e7de 100644 --- a/packages/@expo/image-utils/build/index.js.map +++ b/packages/@expo/image-utils/build/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiC;AAgC/B,sBAAK;AA/BP,mCAKiB;AA2Bf,qGA/BA,4BAAoB,OA+BA;AAFpB,qGA5BA,4BAAoB,OA4BA;AADpB,mGA1BA,0BAAkB,OA0BA;AAIlB,2FA7BA,kBAAU,OA6BA;AA1BZ,iCAAkD;AAkBhD,0FAlBsB,gBAAS,OAkBtB;AAjBX,mCAA+E;AAkB7E,uGAlBO,8BAAsB,OAkBP;AACtB,iGAnB+B,wBAAgB,OAmB/B;AAChB,2FApBiD,kBAAU,OAoBjD;AAjBL,KAAK,UAAU,UAAU,CAC9B,OAA2B,EAC3B,WAAkC,EAAE;IAEpC,IAAI,MAAM,IAAA,wBAAgB,GAAE,EAAE;QAC5B,OAAO,IAAA,kBAAU,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;KACtC;IACD,OAAO,IAAA,gBAAS,EACd,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,IAAA,oBAAa,EAAC,OAAO,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,KAAK,EAAE,EACnF,QAAQ,CACT,CAAC;AACJ,CAAC;AAXD,gCAWC"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiC;AAiC/B,sBAAK;AAhCP,mCAKiB;AA4Bf,qGAhCA,4BAAoB,OAgCA;AAFpB,qGA7BA,4BAAoB,OA6BA;AADpB,mGA3BA,0BAAkB,OA2BA;AAIlB,2FA9BA,kBAAU,OA8BA;AA3BZ,iCAAqE;AAkBnE,0FAlBsB,gBAAS,OAkBtB;AACT,kGAnBiC,wBAAiB,OAmBjC;AAlBnB,mCAA+E;AAmB7E,uGAnBO,8BAAsB,OAmBP;AACtB,iGApB+B,wBAAgB,OAoB/B;AAChB,2FArBiD,kBAAU,OAqBjD;AAlBL,KAAK,UAAU,UAAU,CAC9B,OAA2B,EAC3B,WAAkC,EAAE;IAEpC,IAAI,MAAM,IAAA,wBAAgB,GAAE,EAAE;QAC5B,OAAO,IAAA,kBAAU,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;KACtC;IACD,OAAO,IAAA,gBAAS,EACd,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,IAAA,oBAAa,EAAC,OAAO,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,KAAK,EAAE,EACnF,QAAQ,CACT,CAAC;AACJ,CAAC;AAXD,gCAWC"} \ No newline at end of file diff --git a/packages/@expo/image-utils/build/jimp.d.ts b/packages/@expo/image-utils/build/jimp.d.ts index ca2d16cbcca29..a98a1c9f902ac 100644 --- a/packages/@expo/image-utils/build/jimp.d.ts +++ b/packages/@expo/image-utils/build/jimp.d.ts @@ -10,6 +10,14 @@ export declare function convertFormat(format?: string): string | undefined; export declare function jimpAsync(options: JimpGlobalOptions, commands?: SharpCommandOptions[]): Promise; export declare function isFolderAsync(path: string): Promise; export declare function circleAsync(jimp: Jimp): Promise; +/** + * Create a square image of a given size and color. Defaults to a white PNG. + */ +export declare function createSquareAsync({ size, color, mime, }: { + size: number; + color?: string; + mime?: any; +}): Promise; export declare function getJimpImageAsync(input: string | Buffer | Jimp): Promise; export declare function resize({ input, quality }: JimpGlobalOptions, { background, position, fit, width, height }: Omit): Promise; export {}; diff --git a/packages/@expo/image-utils/build/jimp.js b/packages/@expo/image-utils/build/jimp.js index db8265e2fde1e..a13bb10d97eac 100644 --- a/packages/@expo/image-utils/build/jimp.js +++ b/packages/@expo/image-utils/build/jimp.js @@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.resize = exports.getJimpImageAsync = exports.circleAsync = exports.isFolderAsync = exports.jimpAsync = exports.convertFormat = exports.resizeBufferAsync = void 0; +exports.resize = exports.getJimpImageAsync = exports.createSquareAsync = exports.circleAsync = exports.isFolderAsync = exports.jimpAsync = exports.convertFormat = exports.resizeBufferAsync = void 0; const fs_extra_1 = __importDefault(require("fs-extra")); // @ts-ignore const jimp_compact_1 = __importDefault(require("jimp-compact")); @@ -117,6 +117,15 @@ function circleAsync(jimp) { }); } exports.circleAsync = circleAsync; +/** + * Create a square image of a given size and color. Defaults to a white PNG. + */ +async function createSquareAsync({ size, color = '#FFFFFF', mime = jimp_compact_1.default.MIME_PNG, }) { + const image = await new jimp_compact_1.default(size, size, color); + // Convert Jimp image to a Buffer + return await image.getBufferAsync(mime); +} +exports.createSquareAsync = createSquareAsync; async function getJimpImageAsync(input) { // @ts-ignore: Jimp types are broken if (typeof input === 'string' || input instanceof Buffer) diff --git a/packages/@expo/image-utils/build/jimp.js.map b/packages/@expo/image-utils/build/jimp.js.map index 0c24737f5e4b2..475945dfff543 100644 --- a/packages/@expo/image-utils/build/jimp.js.map +++ b/packages/@expo/image-utils/build/jimp.js.map @@ -1 +1 @@ -{"version":3,"file":"jimp.js","sourceRoot":"","sources":["../src/jimp.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"jimp.js","sourceRoot":"","sources":["../src/jimp.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/@expo/image-utils/src/index.ts b/packages/@expo/image-utils/src/index.ts index 85653d3a32467..cec4cd5855b32 100644 --- a/packages/@expo/image-utils/src/index.ts +++ b/packages/@expo/image-utils/src/index.ts @@ -6,7 +6,7 @@ import { getPngInfo, } from './Image'; import { ImageFormat, ImageOptions, ResizeMode } from './Image.types'; -import { convertFormat, jimpAsync } from './jimp'; +import { convertFormat, jimpAsync, createSquareAsync } from './jimp'; import { findSharpInstanceAsync, isAvailableAsync, sharpAsync } from './sharp'; import { SharpCommandOptions, SharpGlobalOptions } from './sharp.types'; @@ -25,6 +25,7 @@ export async function imageAsync( export { jimpAsync, + createSquareAsync, findSharpInstanceAsync, isAvailableAsync, sharpAsync, diff --git a/packages/@expo/image-utils/src/jimp.ts b/packages/@expo/image-utils/src/jimp.ts index 792dd4f8939c1..f716561c1a506 100644 --- a/packages/@expo/image-utils/src/jimp.ts +++ b/packages/@expo/image-utils/src/jimp.ts @@ -117,6 +117,24 @@ export function circleAsync(jimp: Jimp): Promise { }); } +/** + * Create a square image of a given size and color. Defaults to a white PNG. + */ +export async function createSquareAsync({ + size, + color = '#FFFFFF', + mime = Jimp.MIME_PNG, +}: { + size: number; + color?: string; + mime?: any; +}): Promise { + const image = await new Jimp(size, size, color); + + // Convert Jimp image to a Buffer + return await image.getBufferAsync(mime); +} + export async function getJimpImageAsync(input: string | Buffer | Jimp): Promise { // @ts-ignore: Jimp types are broken if (typeof input === 'string' || input instanceof Buffer) return await Jimp.read(input); diff --git a/packages/@expo/prebuild-config/CHANGELOG.md b/packages/@expo/prebuild-config/CHANGELOG.md index dd893d06515d0..5f139846eb5a8 100644 --- a/packages/@expo/prebuild-config/CHANGELOG.md +++ b/packages/@expo/prebuild-config/CHANGELOG.md @@ -6,6 +6,8 @@ ### 🎉 New features +- Add default icon on iOS to prevent submission failure when no `icon` is defined. ([#27774](https://github.com/expo/expo/pull/27774) by [@EvanBacon](https://github.com/EvanBacon)) + ### 🐛 Bug fixes ### 💡 Others diff --git a/packages/@expo/prebuild-config/__mocks__/@expo/image-utils.ts b/packages/@expo/prebuild-config/__mocks__/@expo/image-utils.ts index 8427446202ed0..f7f0c2fa4750c 100644 --- a/packages/@expo/prebuild-config/__mocks__/@expo/image-utils.ts +++ b/packages/@expo/prebuild-config/__mocks__/@expo/image-utils.ts @@ -1,3 +1,7 @@ +export async function createSquareAsync() { + return Buffer.from(''); +} + export async function generateImageAsync(input: any, { src }) { const fs = require('fs'); return { source: fs.readFileSync(src) }; diff --git a/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.d.ts b/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.d.ts index bdc93e825fc0b..605395639468b 100644 --- a/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.d.ts +++ b/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.d.ts @@ -6,7 +6,7 @@ export declare function getIcons(config: Pick): stri export declare function setIconsAsync(config: ExpoConfig, projectRoot: string): Promise; export declare function generateUniversalIconAsync(projectRoot: string, { icon, cacheKey, iosNamedProjectRoot, platform, }: { platform: 'watchos' | 'ios'; - icon: string; + icon?: string | null; iosNamedProjectRoot: string; cacheKey: string; }): Promise; diff --git a/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.js b/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.js index 9ca0b6517b1de..5d831bf32d25b 100644 --- a/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.js +++ b/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.js @@ -63,10 +63,8 @@ function getIcons(config) { async function setIconsAsync(config, projectRoot) { const icon = getIcons(config); if (!icon) { - _configPlugins().WarningAggregator.addWarningIOS('icon', 'This is the image that your app uses on your home screen, you will need to configure it manually.'); - return; + _configPlugins().WarningAggregator.addWarningIOS('icon', 'No icon is defined in the Expo config.'); } - // Something like projectRoot/ios/MyApp/ const iosNamedProjectRoot = getIosNamedProjectPath(projectRoot); @@ -107,25 +105,31 @@ async function generateUniversalIconAsync(projectRoot, { }) { const size = 1024; const filename = getAppleIconName(size, 1); - // Using this method will cache the images in `.expo` based on the properties used to generate them. - // this method also supports remote URLs and using the global sharp instance. - const { - source - } = await (0, _imageUtils().generateImageAsync)({ - projectRoot, - cacheType: IMAGE_CACHE_NAME + cacheKey - }, { - src: icon, - name: filename, - width: size, - height: size, - removeTransparency: true, - // The icon should be square, but if it's not then it will be cropped. - resizeMode: 'cover', - // Force the background color to solid white to prevent any transparency. - // TODO: Maybe use a more adaptive option based on the icon color? - backgroundColor: '#ffffff' - }); + let source; + if (icon) { + // Using this method will cache the images in `.expo` based on the properties used to generate them. + // this method also supports remote URLs and using the global sharp instance. + source = (await (0, _imageUtils().generateImageAsync)({ + projectRoot, + cacheType: IMAGE_CACHE_NAME + cacheKey + }, { + src: icon, + name: filename, + width: size, + height: size, + removeTransparency: true, + // The icon should be square, but if it's not then it will be cropped. + resizeMode: 'cover', + // Force the background color to solid white to prevent any transparency. + // TODO: Maybe use a more adaptive option based on the icon color? + backgroundColor: '#ffffff' + })).source; + } else { + // Create a white square image if no icon exists to mitigate the chance of a submission failure to the app store. + source = await (0, _imageUtils().createSquareAsync)({ + size + }); + } // Write image buffer to the file system. const assetPath = (0, _path().join)(iosNamedProjectRoot, IMAGESET_PATH, filename); await fs().writeFile(assetPath, source); diff --git a/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.js.map b/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.js.map index 331e762ac0ae4..03fb60d66f118 100644 --- a/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.js.map +++ b/packages/@expo/prebuild-config/build/plugins/icons/withIosIcons.js.map @@ -1 +1 @@ -{"version":3,"file":"withIosIcons.js","names":["_configPlugins","data","require","_imageUtils","fs","_interopRequireWildcard","_path","_AssetContents","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","getProjectName","IOSConfig","XcodeUtils","IMAGE_CACHE_NAME","IMAGESET_PATH","withIosIcons","config","withDangerousMod","setIconsAsync","modRequest","projectRoot","exports","getIcons","ios","icon","WarningAggregator","addWarningIOS","iosNamedProjectRoot","getIosNamedProjectPath","ensureDir","join","imagesJson","generateUniversalIconAsync","cacheKey","platform","writeContentsJsonAsync","images","projectName","getAppleIconName","size","scale","filename","source","generateImageAsync","cacheType","src","name","width","height","removeTransparency","resizeMode","backgroundColor","assetPath","writeFile","idiom"],"sources":["../../../src/plugins/icons/withIosIcons.ts"],"sourcesContent":["import { ConfigPlugin, IOSConfig, WarningAggregator, withDangerousMod } from '@expo/config-plugins';\nimport { ExpoConfig } from '@expo/config-types';\nimport { generateImageAsync } from '@expo/image-utils';\nimport * as fs from 'fs-extra';\nimport { join } from 'path';\n\nimport { ContentsJson, writeContentsJsonAsync } from './AssetContents';\n\nconst { getProjectName } = IOSConfig.XcodeUtils;\n\nconst IMAGE_CACHE_NAME = 'icons';\nconst IMAGESET_PATH = 'Images.xcassets/AppIcon.appiconset';\n\nexport const withIosIcons: ConfigPlugin = (config) => {\n return withDangerousMod(config, [\n 'ios',\n async (config) => {\n await setIconsAsync(config, config.modRequest.projectRoot);\n return config;\n },\n ]);\n};\n\nexport function getIcons(config: Pick): string | null {\n // No support for empty strings.\n return config.ios?.icon || config.icon || null;\n}\n\nexport async function setIconsAsync(config: ExpoConfig, projectRoot: string) {\n const icon = getIcons(config);\n if (!icon) {\n WarningAggregator.addWarningIOS(\n 'icon',\n 'This is the image that your app uses on your home screen, you will need to configure it manually.'\n );\n return;\n }\n\n // Something like projectRoot/ios/MyApp/\n const iosNamedProjectRoot = getIosNamedProjectPath(projectRoot);\n\n // Ensure the Images.xcassets/AppIcon.appiconset path exists\n await fs.ensureDir(join(iosNamedProjectRoot, IMAGESET_PATH));\n\n // Store the image JSON data for assigning via the Contents.json\n const imagesJson: ContentsJson['images'] = await generateUniversalIconAsync(projectRoot, {\n icon,\n cacheKey: 'universal-icon',\n iosNamedProjectRoot,\n platform: 'ios',\n });\n\n // Finally, write the Config.json\n await writeContentsJsonAsync(join(iosNamedProjectRoot, IMAGESET_PATH), { images: imagesJson });\n}\n\n/**\n * Return the project's named iOS path: ios/MyProject/\n *\n * @param projectRoot Expo project root path.\n */\nfunction getIosNamedProjectPath(projectRoot: string): string {\n const projectName = getProjectName(projectRoot);\n return join(projectRoot, 'ios', projectName);\n}\n\nfunction getAppleIconName(size: number, scale: number): string {\n return `App-Icon-${size}x${size}@${scale}x.png`;\n}\n\nexport async function generateUniversalIconAsync(\n projectRoot: string,\n {\n icon,\n cacheKey,\n iosNamedProjectRoot,\n platform,\n }: { platform: 'watchos' | 'ios'; icon: string; iosNamedProjectRoot: string; cacheKey: string }\n): Promise {\n const size = 1024;\n const filename = getAppleIconName(size, 1);\n // Using this method will cache the images in `.expo` based on the properties used to generate them.\n // this method also supports remote URLs and using the global sharp instance.\n const { source } = await generateImageAsync(\n { projectRoot, cacheType: IMAGE_CACHE_NAME + cacheKey },\n {\n src: icon,\n name: filename,\n width: size,\n height: size,\n removeTransparency: true,\n // The icon should be square, but if it's not then it will be cropped.\n resizeMode: 'cover',\n // Force the background color to solid white to prevent any transparency.\n // TODO: Maybe use a more adaptive option based on the icon color?\n backgroundColor: '#ffffff',\n }\n );\n // Write image buffer to the file system.\n const assetPath = join(iosNamedProjectRoot, IMAGESET_PATH, filename);\n await fs.writeFile(assetPath, source);\n\n return [\n {\n filename: getAppleIconName(size, 1),\n idiom: 'universal',\n platform,\n size: `${size}x${size}`,\n },\n ];\n}\n"],"mappings":";;;;;;;;;AAAA,SAAAA,eAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,cAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEA,SAAAE,YAAA;EAAA,MAAAF,IAAA,GAAAC,OAAA;EAAAC,WAAA,YAAAA,CAAA;IAAA,OAAAF,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAG,GAAA;EAAA,MAAAH,IAAA,GAAAI,uBAAA,CAAAH,OAAA;EAAAE,EAAA,YAAAA,CAAA;IAAA,OAAAH,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAK,MAAA;EAAA,MAAAL,IAAA,GAAAC,OAAA;EAAAI,KAAA,YAAAA,CAAA;IAAA,OAAAL,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEA,SAAAM,eAAA;EAAA,MAAAN,IAAA,GAAAC,OAAA;EAAAK,cAAA,YAAAA,CAAA;IAAA,OAAAN,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAAuE,SAAAO,yBAAAC,CAAA,6BAAAC,OAAA,mBAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAF,wBAAA,YAAAA,CAAAC,CAAA,WAAAA,CAAA,GAAAG,CAAA,GAAAD,CAAA,KAAAF,CAAA;AAAA,SAAAJ,wBAAAI,CAAA,EAAAE,CAAA,SAAAA,CAAA,IAAAF,CAAA,IAAAA,CAAA,CAAAI,UAAA,SAAAJ,CAAA,eAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,WAAAK,OAAA,EAAAL,CAAA,QAAAG,CAAA,GAAAJ,wBAAA,CAAAG,CAAA,OAAAC,CAAA,IAAAA,CAAA,CAAAG,GAAA,CAAAN,CAAA,UAAAG,CAAA,CAAAI,GAAA,CAAAP,CAAA,OAAAQ,CAAA,KAAAC,SAAA,UAAAC,CAAA,GAAAC,MAAA,CAAAC,cAAA,IAAAD,MAAA,CAAAE,wBAAA,WAAAC,CAAA,IAAAd,CAAA,oBAAAc,CAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAjB,CAAA,EAAAc,CAAA,SAAAI,CAAA,GAAAR,CAAA,GAAAC,MAAA,CAAAE,wBAAA,CAAAb,CAAA,EAAAc,CAAA,UAAAI,CAAA,KAAAA,CAAA,CAAAX,GAAA,IAAAW,CAAA,CAAAC,GAAA,IAAAR,MAAA,CAAAC,cAAA,CAAAJ,CAAA,EAAAM,CAAA,EAAAI,CAAA,IAAAV,CAAA,CAAAM,CAAA,IAAAd,CAAA,CAAAc,CAAA,YAAAN,CAAA,CAAAH,OAAA,GAAAL,CAAA,EAAAG,CAAA,IAAAA,CAAA,CAAAgB,GAAA,CAAAnB,CAAA,EAAAQ,CAAA,GAAAA,CAAA;AAEvE,MAAM;EAAEY;AAAe,CAAC,GAAGC,0BAAS,CAACC,UAAU;AAE/C,MAAMC,gBAAgB,GAAG,OAAO;AAChC,MAAMC,aAAa,GAAG,oCAAoC;AAEnD,MAAMC,YAA0B,GAAIC,MAAM,IAAK;EACpD,OAAO,IAAAC,iCAAgB,EAACD,MAAM,EAAE,CAC9B,KAAK,EACL,MAAOA,MAAM,IAAK;IAChB,MAAME,aAAa,CAACF,MAAM,EAAEA,MAAM,CAACG,UAAU,CAACC,WAAW,CAAC;IAC1D,OAAOJ,MAAM;EACf,CAAC,CACF,CAAC;AACJ,CAAC;AAACK,OAAA,CAAAN,YAAA,GAAAA,YAAA;AAEK,SAASO,QAAQA,CAACN,MAAwC,EAAiB;EAChF;EACA,OAAOA,MAAM,CAACO,GAAG,EAAEC,IAAI,IAAIR,MAAM,CAACQ,IAAI,IAAI,IAAI;AAChD;AAEO,eAAeN,aAAaA,CAACF,MAAkB,EAAEI,WAAmB,EAAE;EAC3E,MAAMI,IAAI,GAAGF,QAAQ,CAACN,MAAM,CAAC;EAC7B,IAAI,CAACQ,IAAI,EAAE;IACTC,kCAAiB,CAACC,aAAa,CAC7B,MAAM,EACN,mGACF,CAAC;IACD;EACF;;EAEA;EACA,MAAMC,mBAAmB,GAAGC,sBAAsB,CAACR,WAAW,CAAC;;EAE/D;EACA,MAAMnC,EAAE,CAAD,CAAC,CAAC4C,SAAS,CAAC,IAAAC,YAAI,EAACH,mBAAmB,EAAEb,aAAa,CAAC,CAAC;;EAE5D;EACA,MAAMiB,UAAkC,GAAG,MAAMC,0BAA0B,CAACZ,WAAW,EAAE;IACvFI,IAAI;IACJS,QAAQ,EAAE,gBAAgB;IAC1BN,mBAAmB;IACnBO,QAAQ,EAAE;EACZ,CAAC,CAAC;;EAEF;EACA,MAAM,IAAAC,uCAAsB,EAAC,IAAAL,YAAI,EAACH,mBAAmB,EAAEb,aAAa,CAAC,EAAE;IAAEsB,MAAM,EAAEL;EAAW,CAAC,CAAC;AAChG;;AAEA;AACA;AACA;AACA;AACA;AACA,SAASH,sBAAsBA,CAACR,WAAmB,EAAU;EAC3D,MAAMiB,WAAW,GAAG3B,cAAc,CAACU,WAAW,CAAC;EAC/C,OAAO,IAAAU,YAAI,EAACV,WAAW,EAAE,KAAK,EAAEiB,WAAW,CAAC;AAC9C;AAEA,SAASC,gBAAgBA,CAACC,IAAY,EAAEC,KAAa,EAAU;EAC7D,OAAQ,YAAWD,IAAK,IAAGA,IAAK,IAAGC,KAAM,OAAM;AACjD;AAEO,eAAeR,0BAA0BA,CAC9CZ,WAAmB,EACnB;EACEI,IAAI;EACJS,QAAQ;EACRN,mBAAmB;EACnBO;AAC4F,CAAC,EAC9D;EACjC,MAAMK,IAAI,GAAG,IAAI;EACjB,MAAME,QAAQ,GAAGH,gBAAgB,CAACC,IAAI,EAAE,CAAC,CAAC;EAC1C;EACA;EACA,MAAM;IAAEG;EAAO,CAAC,GAAG,MAAM,IAAAC,gCAAkB,EACzC;IAAEvB,WAAW;IAAEwB,SAAS,EAAE/B,gBAAgB,GAAGoB;EAAS,CAAC,EACvD;IACEY,GAAG,EAAErB,IAAI;IACTsB,IAAI,EAAEL,QAAQ;IACdM,KAAK,EAAER,IAAI;IACXS,MAAM,EAAET,IAAI;IACZU,kBAAkB,EAAE,IAAI;IACxB;IACAC,UAAU,EAAE,OAAO;IACnB;IACA;IACAC,eAAe,EAAE;EACnB,CACF,CAAC;EACD;EACA,MAAMC,SAAS,GAAG,IAAAtB,YAAI,EAACH,mBAAmB,EAAEb,aAAa,EAAE2B,QAAQ,CAAC;EACpE,MAAMxD,EAAE,CAAD,CAAC,CAACoE,SAAS,CAACD,SAAS,EAAEV,MAAM,CAAC;EAErC,OAAO,CACL;IACED,QAAQ,EAAEH,gBAAgB,CAACC,IAAI,EAAE,CAAC,CAAC;IACnCe,KAAK,EAAE,WAAW;IAClBpB,QAAQ;IACRK,IAAI,EAAG,GAAEA,IAAK,IAAGA,IAAK;EACxB,CAAC,CACF;AACH"} \ No newline at end of file +{"version":3,"file":"withIosIcons.js","names":["_configPlugins","data","require","_imageUtils","fs","_interopRequireWildcard","_path","_AssetContents","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","getProjectName","IOSConfig","XcodeUtils","IMAGE_CACHE_NAME","IMAGESET_PATH","withIosIcons","config","withDangerousMod","setIconsAsync","modRequest","projectRoot","exports","getIcons","ios","icon","WarningAggregator","addWarningIOS","iosNamedProjectRoot","getIosNamedProjectPath","ensureDir","join","imagesJson","generateUniversalIconAsync","cacheKey","platform","writeContentsJsonAsync","images","projectName","getAppleIconName","size","scale","filename","source","generateImageAsync","cacheType","src","name","width","height","removeTransparency","resizeMode","backgroundColor","createSquareAsync","assetPath","writeFile","idiom"],"sources":["../../../src/plugins/icons/withIosIcons.ts"],"sourcesContent":["import { ConfigPlugin, IOSConfig, WarningAggregator, withDangerousMod } from '@expo/config-plugins';\nimport { ExpoConfig } from '@expo/config-types';\nimport { createSquareAsync, generateImageAsync } from '@expo/image-utils';\nimport * as fs from 'fs-extra';\nimport { join } from 'path';\n\nimport { ContentsJson, writeContentsJsonAsync } from './AssetContents';\n\nconst { getProjectName } = IOSConfig.XcodeUtils;\n\nconst IMAGE_CACHE_NAME = 'icons';\nconst IMAGESET_PATH = 'Images.xcassets/AppIcon.appiconset';\n\nexport const withIosIcons: ConfigPlugin = (config) => {\n return withDangerousMod(config, [\n 'ios',\n async (config) => {\n await setIconsAsync(config, config.modRequest.projectRoot);\n return config;\n },\n ]);\n};\n\nexport function getIcons(config: Pick): string | null {\n // No support for empty strings.\n return config.ios?.icon || config.icon || null;\n}\n\nexport async function setIconsAsync(config: ExpoConfig, projectRoot: string) {\n const icon = getIcons(config);\n if (!icon) {\n WarningAggregator.addWarningIOS('icon', 'No icon is defined in the Expo config.');\n }\n // Something like projectRoot/ios/MyApp/\n const iosNamedProjectRoot = getIosNamedProjectPath(projectRoot);\n\n // Ensure the Images.xcassets/AppIcon.appiconset path exists\n await fs.ensureDir(join(iosNamedProjectRoot, IMAGESET_PATH));\n\n // Store the image JSON data for assigning via the Contents.json\n const imagesJson: ContentsJson['images'] = await generateUniversalIconAsync(projectRoot, {\n icon,\n cacheKey: 'universal-icon',\n iosNamedProjectRoot,\n platform: 'ios',\n });\n\n // Finally, write the Config.json\n await writeContentsJsonAsync(join(iosNamedProjectRoot, IMAGESET_PATH), { images: imagesJson });\n}\n\n/**\n * Return the project's named iOS path: ios/MyProject/\n *\n * @param projectRoot Expo project root path.\n */\nfunction getIosNamedProjectPath(projectRoot: string): string {\n const projectName = getProjectName(projectRoot);\n return join(projectRoot, 'ios', projectName);\n}\n\nfunction getAppleIconName(size: number, scale: number): string {\n return `App-Icon-${size}x${size}@${scale}x.png`;\n}\n\nexport async function generateUniversalIconAsync(\n projectRoot: string,\n {\n icon,\n cacheKey,\n iosNamedProjectRoot,\n platform,\n }: {\n platform: 'watchos' | 'ios';\n icon?: string | null;\n iosNamedProjectRoot: string;\n cacheKey: string;\n }\n): Promise {\n const size = 1024;\n const filename = getAppleIconName(size, 1);\n\n let source: Buffer;\n\n if (icon) {\n // Using this method will cache the images in `.expo` based on the properties used to generate them.\n // this method also supports remote URLs and using the global sharp instance.\n source = (\n await generateImageAsync(\n { projectRoot, cacheType: IMAGE_CACHE_NAME + cacheKey },\n {\n src: icon,\n name: filename,\n width: size,\n height: size,\n removeTransparency: true,\n // The icon should be square, but if it's not then it will be cropped.\n resizeMode: 'cover',\n // Force the background color to solid white to prevent any transparency.\n // TODO: Maybe use a more adaptive option based on the icon color?\n backgroundColor: '#ffffff',\n }\n )\n ).source;\n } else {\n // Create a white square image if no icon exists to mitigate the chance of a submission failure to the app store.\n source = await createSquareAsync({ size });\n }\n // Write image buffer to the file system.\n const assetPath = join(iosNamedProjectRoot, IMAGESET_PATH, filename);\n await fs.writeFile(assetPath, source);\n\n return [\n {\n filename: getAppleIconName(size, 1),\n idiom: 'universal',\n platform,\n size: `${size}x${size}`,\n },\n ];\n}\n"],"mappings":"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"} \ No newline at end of file diff --git a/packages/@expo/prebuild-config/src/plugins/__tests__/withDefaultPlugins-test.ts b/packages/@expo/prebuild-config/src/plugins/__tests__/withDefaultPlugins-test.ts index 075988e4ca8b9..7503350b619fc 100644 --- a/packages/@expo/prebuild-config/src/plugins/__tests__/withDefaultPlugins-test.ts +++ b/packages/@expo/prebuild-config/src/plugins/__tests__/withDefaultPlugins-test.ts @@ -345,6 +345,7 @@ describe('built-in plugins', () => { 'ios/HelloWorld/AppDelegate.h', 'ios/HelloWorld/AppDelegate.mm', 'ios/HelloWorld/Images.xcassets/AppIcon.appiconset/Contents.json', + 'ios/HelloWorld/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png', 'ios/HelloWorld/Images.xcassets/Contents.json', 'ios/HelloWorld/Images.xcassets/SplashScreenBackground.imageset/image.png', 'ios/HelloWorld/Images.xcassets/SplashScreenBackground.imageset/Contents.json', diff --git a/packages/@expo/prebuild-config/src/plugins/icons/__tests__/__snapshots__/withIosIcons-test.ts.snap b/packages/@expo/prebuild-config/src/plugins/icons/__tests__/__snapshots__/withIosIcons-test.ts.snap index 150379de5e3fc..6e47f8e80bdd8 100644 --- a/packages/@expo/prebuild-config/src/plugins/icons/__tests__/__snapshots__/withIosIcons-test.ts.snap +++ b/packages/@expo/prebuild-config/src/plugins/icons/__tests__/__snapshots__/withIosIcons-test.ts.snap @@ -1,5 +1,16 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`e2e: iOS icons with fallback image writes all the image files expected 1`] = ` +[ + { + "filename": "App-Icon-1024x1024@1x.png", + "idiom": "universal", + "platform": "ios", + "size": "1024x1024", + }, +] +`; + exports[`e2e: iOS icons writes all the image files expected 1`] = ` [ { diff --git a/packages/@expo/prebuild-config/src/plugins/icons/__tests__/withIosIcons-test.ts b/packages/@expo/prebuild-config/src/plugins/icons/__tests__/withIosIcons-test.ts index 1792e55145f04..65dadc3eef3a0 100644 --- a/packages/@expo/prebuild-config/src/plugins/icons/__tests__/withIosIcons-test.ts +++ b/packages/@expo/prebuild-config/src/plugins/icons/__tests__/withIosIcons-test.ts @@ -1,3 +1,4 @@ +import { WarningAggregator } from '@expo/config-plugins'; import * as fs from 'fs'; import { vol } from 'memfs'; import * as path from 'path'; @@ -8,6 +9,13 @@ import { getIcons, setIconsAsync } from '../withIosIcons'; const fsReal = jest.requireActual('fs') as typeof fs; +jest.mock('@expo/config-plugins', () => ({ + ...jest.requireActual('@expo/config-plugins'), + WarningAggregator: { + addWarningIOS: jest.fn(), + }, +})); + jest.mock('fs'); describe('iOS Icons', () => { @@ -87,6 +95,52 @@ describe('e2e: iOS icons', () => { value.startsWith('ios/HelloWorld/Images.xcassets/AppIcon.appiconset/App-Icon') ); + expect(WarningAggregator.addWarningIOS).toHaveBeenCalledTimes(0); + + expect(icons.length).toBe(1); + + // Test the Contents.json file + const contents = JSON.parse( + after['ios/HelloWorld/Images.xcassets/AppIcon.appiconset/Contents.json'] + ); + expect(contents.images).toMatchSnapshot(); + + // Ensure all icons are assigned as expected. + expect(contents.images.length).toBe(1); + }); +}); +describe('e2e: iOS icons with fallback image', () => { + const projectRoot = '/app'; + beforeAll(async () => { + vol.fromJSON(rnFixture, projectRoot); + }); + + afterAll(() => { + vol.reset(); + }); + + it('writes all the image files expected', async () => { + await setIconsAsync( + { + slug: 'HelloWorld', + version: '1', + name: 'HelloWorld', + platforms: ['ios', 'android'], + // No icon should be set + }, + projectRoot + ); + + const after = getDirFromFS(vol.toJSON(), projectRoot); + const icons = Object.keys(after).filter((value) => + value.startsWith('ios/HelloWorld/Images.xcassets/AppIcon.appiconset/App-Icon') + ); + + expect(WarningAggregator.addWarningIOS).toHaveBeenCalledTimes(1); + expect(WarningAggregator.addWarningIOS).toHaveBeenCalledWith( + 'icon', + 'No icon is defined in the Expo config.' + ); expect(icons.length).toBe(1); // Test the Contents.json file diff --git a/packages/@expo/prebuild-config/src/plugins/icons/withIosIcons.ts b/packages/@expo/prebuild-config/src/plugins/icons/withIosIcons.ts index 4aa63077dc1e4..1e01654c33748 100644 --- a/packages/@expo/prebuild-config/src/plugins/icons/withIosIcons.ts +++ b/packages/@expo/prebuild-config/src/plugins/icons/withIosIcons.ts @@ -1,6 +1,6 @@ import { ConfigPlugin, IOSConfig, WarningAggregator, withDangerousMod } from '@expo/config-plugins'; import { ExpoConfig } from '@expo/config-types'; -import { generateImageAsync } from '@expo/image-utils'; +import { createSquareAsync, generateImageAsync } from '@expo/image-utils'; import * as fs from 'fs-extra'; import { join } from 'path'; @@ -29,13 +29,8 @@ export function getIcons(config: Pick): string | nul export async function setIconsAsync(config: ExpoConfig, projectRoot: string) { const icon = getIcons(config); if (!icon) { - WarningAggregator.addWarningIOS( - 'icon', - 'This is the image that your app uses on your home screen, you will need to configure it manually.' - ); - return; + WarningAggregator.addWarningIOS('icon', 'No icon is defined in the Expo config.'); } - // Something like projectRoot/ios/MyApp/ const iosNamedProjectRoot = getIosNamedProjectPath(projectRoot); @@ -75,27 +70,42 @@ export async function generateUniversalIconAsync( cacheKey, iosNamedProjectRoot, platform, - }: { platform: 'watchos' | 'ios'; icon: string; iosNamedProjectRoot: string; cacheKey: string } + }: { + platform: 'watchos' | 'ios'; + icon?: string | null; + iosNamedProjectRoot: string; + cacheKey: string; + } ): Promise { const size = 1024; const filename = getAppleIconName(size, 1); - // Using this method will cache the images in `.expo` based on the properties used to generate them. - // this method also supports remote URLs and using the global sharp instance. - const { source } = await generateImageAsync( - { projectRoot, cacheType: IMAGE_CACHE_NAME + cacheKey }, - { - src: icon, - name: filename, - width: size, - height: size, - removeTransparency: true, - // The icon should be square, but if it's not then it will be cropped. - resizeMode: 'cover', - // Force the background color to solid white to prevent any transparency. - // TODO: Maybe use a more adaptive option based on the icon color? - backgroundColor: '#ffffff', - } - ); + + let source: Buffer; + + if (icon) { + // Using this method will cache the images in `.expo` based on the properties used to generate them. + // this method also supports remote URLs and using the global sharp instance. + source = ( + await generateImageAsync( + { projectRoot, cacheType: IMAGE_CACHE_NAME + cacheKey }, + { + src: icon, + name: filename, + width: size, + height: size, + removeTransparency: true, + // The icon should be square, but if it's not then it will be cropped. + resizeMode: 'cover', + // Force the background color to solid white to prevent any transparency. + // TODO: Maybe use a more adaptive option based on the icon color? + backgroundColor: '#ffffff', + } + ) + ).source; + } else { + // Create a white square image if no icon exists to mitigate the chance of a submission failure to the app store. + source = await createSquareAsync({ size }); + } // Write image buffer to the file system. const assetPath = join(iosNamedProjectRoot, IMAGESET_PATH, filename); await fs.writeFile(assetPath, source);