161 lines
5.9 KiB
JavaScript
161 lines
5.9 KiB
JavaScript
"use strict";
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
result["default"] = mod;
|
|
return result;
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const image_utils_1 = require("@expo/image-utils");
|
|
const fs = __importStar(require("fs-extra"));
|
|
const path_1 = require("path");
|
|
const core_plugins_1 = require("../plugins/core-plugins");
|
|
const WarningAggregator = __importStar(require("../utils/warnings"));
|
|
const AssetContents_1 = require("./AssetContents");
|
|
const Xcodeproj_1 = require("./utils/Xcodeproj");
|
|
exports.withIcons = config => {
|
|
return core_plugins_1.withDangerousMod(config, [
|
|
'ios',
|
|
async (config) => {
|
|
await setIconsAsync(config, config.modRequest.projectRoot);
|
|
return config;
|
|
},
|
|
]);
|
|
};
|
|
const IMAGE_CACHE_NAME = 'icons';
|
|
const IMAGESET_PATH = 'Images.xcassets/AppIcon.appiconset';
|
|
// Hard-coding seemed like the clearest and safest way to implement the sizes.
|
|
exports.ICON_CONTENTS = [
|
|
{
|
|
idiom: 'iphone',
|
|
sizes: [
|
|
{
|
|
size: 20,
|
|
scales: [2, 3],
|
|
},
|
|
{
|
|
size: 29,
|
|
scales: [1, 2, 3],
|
|
},
|
|
{
|
|
size: 40,
|
|
scales: [2, 3],
|
|
},
|
|
{
|
|
size: 60,
|
|
scales: [2, 3],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
idiom: 'ipad',
|
|
sizes: [
|
|
{
|
|
size: 20,
|
|
scales: [1, 2],
|
|
},
|
|
{
|
|
size: 29,
|
|
scales: [1, 2],
|
|
},
|
|
{
|
|
size: 40,
|
|
scales: [1, 2],
|
|
},
|
|
{
|
|
size: 76,
|
|
scales: [1, 2],
|
|
},
|
|
{
|
|
size: 83.5,
|
|
scales: [2],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
idiom: 'ios-marketing',
|
|
sizes: [
|
|
{
|
|
size: 1024,
|
|
scales: [1],
|
|
},
|
|
],
|
|
},
|
|
];
|
|
function getIcons(config) {
|
|
var _a;
|
|
// No support for empty strings.
|
|
return ((_a = config.ios) === null || _a === void 0 ? void 0 : _a.icon) || config.icon || null;
|
|
}
|
|
exports.getIcons = getIcons;
|
|
async function setIconsAsync(config, projectRoot) {
|
|
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;
|
|
}
|
|
// Something like projectRoot/ios/MyApp/
|
|
const iosNamedProjectRoot = getIosNamedProjectPath(projectRoot);
|
|
// Ensure the Images.xcassets/AppIcon.appiconset path exists
|
|
await fs.ensureDir(path_1.join(iosNamedProjectRoot, IMAGESET_PATH));
|
|
// Store the image JSON data for assigning via the Contents.json
|
|
const imagesJson = [];
|
|
// keep track of icons that have been generated so we can reuse them in the Contents.json
|
|
const generatedIcons = {};
|
|
for (const platform of exports.ICON_CONTENTS) {
|
|
const isMarketing = platform.idiom === 'ios-marketing';
|
|
for (const { size, scales } of platform.sizes) {
|
|
for (const scale of scales) {
|
|
// The marketing icon is special because it makes no sense.
|
|
const filename = isMarketing ? 'ItunesArtwork@2x.png' : getAppleIconName(size, scale);
|
|
// Only create an image that hasn't already been generated.
|
|
if (!(filename in generatedIcons)) {
|
|
const iconSizePx = size * scale;
|
|
// 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 image_utils_1.generateImageAsync({ projectRoot, cacheType: IMAGE_CACHE_NAME }, {
|
|
src: icon,
|
|
name: filename,
|
|
width: iconSizePx,
|
|
height: iconSizePx,
|
|
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',
|
|
});
|
|
// Write image buffer to the file system.
|
|
const assetPath = path_1.join(iosNamedProjectRoot, IMAGESET_PATH, filename);
|
|
await fs.writeFile(assetPath, source);
|
|
// Save a reference to the generated image so we don't create a duplicate.
|
|
generatedIcons[filename] = true;
|
|
}
|
|
imagesJson.push({
|
|
idiom: platform.idiom,
|
|
size: `${size}x${size}`,
|
|
// @ts-ignore: template types not supported in TS yet
|
|
scale: `${scale}x`,
|
|
filename,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
// Finally, write the Config.json
|
|
await AssetContents_1.writeContentsJsonAsync(path_1.join(iosNamedProjectRoot, IMAGESET_PATH), { images: imagesJson });
|
|
}
|
|
exports.setIconsAsync = setIconsAsync;
|
|
/**
|
|
* Return the project's named iOS path: ios/MyProject/
|
|
*
|
|
* @param projectRoot Expo project root path.
|
|
*/
|
|
function getIosNamedProjectPath(projectRoot) {
|
|
const projectName = Xcodeproj_1.getProjectName(projectRoot);
|
|
return path_1.join(projectRoot, 'ios', projectName);
|
|
}
|
|
function getAppleIconName(size, scale) {
|
|
return `App-Icon-${size}x${size}@${scale}x.png`;
|
|
}
|
|
//# sourceMappingURL=Icons.js.map
|