first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,271 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.generateUniversalIconAsync = generateUniversalIconAsync;
exports.getIcons = getIcons;
exports.setIconsAsync = setIconsAsync;
exports.withIosIcons = void 0;
function _configPlugins() {
const data = require("@expo/config-plugins");
_configPlugins = function () {
return data;
};
return data;
}
function _Target() {
const data = require("@expo/config-plugins/build/ios/Target");
_Target = function () {
return data;
};
return data;
}
function _imageUtils() {
const data = require("@expo/image-utils");
_imageUtils = function () {
return data;
};
return data;
}
function _fs() {
const data = _interopRequireDefault(require("fs"));
_fs = function () {
return data;
};
return data;
}
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _AssetContents() {
const data = require("./AssetContents");
_AssetContents = function () {
return data;
};
return data;
}
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const {
getProjectName
} = _configPlugins().IOSConfig.XcodeUtils;
const IMAGE_CACHE_NAME = 'icons';
const IMAGESET_PATH = 'Images.xcassets/AppIcon.appiconset';
const withIosIcons = config => {
config = (0, _configPlugins().withDangerousMod)(config, ['ios', async config => {
await setIconsAsync(config, config.modRequest.projectRoot);
return config;
}]);
config = (0, _configPlugins().withXcodeProject)(config, config => {
const icon = getIcons(config);
const projectName = config.modRequest.projectName;
if (icon && typeof icon === 'string' && _path().default.extname(icon) === '.icon' && projectName) {
const iconName = _path().default.basename(icon, '.icon');
setIconName(config.modResults, projectName, iconName);
addIconFileToProject(config.modResults, projectName, iconName);
}
return config;
});
return config;
};
exports.withIosIcons = withIosIcons;
function getIcons(config) {
const iosSpecificIcons = config.ios?.icon;
if (iosSpecificIcons) {
// For backwards compatibility, the icon can be a string
if (typeof iosSpecificIcons === 'string') {
return iosSpecificIcons || config.icon || null;
}
if (typeof iosSpecificIcons === 'object') {
const paths = [iosSpecificIcons.light, iosSpecificIcons.dark, iosSpecificIcons.tinted].filter(Boolean);
for (const iconPath of paths) {
if (typeof iconPath === 'string' && _path().default.extname(iconPath) === '.icon') {
_configPlugins().WarningAggregator.addWarningIOS('icon', `Liquid glass icons (.icon) should be provided as a string to the "ios.icon" property, not as an object. Found: "${iconPath}"`);
}
}
}
// in iOS 18 introduced the ability to specify dark and tinted icons, which users can specify as an object
if (!iosSpecificIcons.light && !iosSpecificIcons.dark && !iosSpecificIcons.tinted) {
return config.icon || null;
}
return iosSpecificIcons;
}
// Top level icon property should not be used to specify a `.icon` folder
if (config.icon && typeof config.icon === 'string' && _path().default.extname(config.icon) === '.icon') {
_configPlugins().WarningAggregator.addWarningIOS('icon', `Liquid glass icons (.icon) should be provided via the "ios.icon" property, not the root "icon" property. Found: "${config.icon}"`);
}
if (config.icon) {
return config.icon;
}
return null;
}
async function setIconsAsync(config, projectRoot) {
const icon = getIcons(config);
if (!icon || typeof icon === 'string' && !icon || typeof icon === 'object' && !icon?.light && !icon?.dark && !icon?.tinted) {
_configPlugins().WarningAggregator.addWarningIOS('icon', 'No icon is defined in the Expo config.');
}
// Something like projectRoot/ios/MyApp/
const iosNamedProjectRoot = getIosNamedProjectPath(projectRoot);
if (typeof icon === 'string' && _path().default.extname(icon) === '.icon') {
return await addLiquidGlassIcon(icon, projectRoot, iosNamedProjectRoot);
}
// Ensure the Images.xcassets/AppIcon.appiconset path exists
await _fs().default.promises.mkdir(_path().default.join(iosNamedProjectRoot, IMAGESET_PATH), {
recursive: true
});
const imagesJson = [];
const baseIconPath = typeof icon === 'object' ? icon?.light || icon?.dark || icon?.tinted : icon;
// Store the image JSON data for assigning via the Contents.json
const baseIcon = await generateUniversalIconAsync(projectRoot, {
icon: baseIconPath,
cacheKey: 'universal-icon',
iosNamedProjectRoot,
platform: 'ios'
});
imagesJson.push(baseIcon);
if (typeof icon === 'object') {
if (icon?.dark) {
const darkIcon = await generateUniversalIconAsync(projectRoot, {
icon: icon.dark,
cacheKey: 'universal-icon-dark',
iosNamedProjectRoot,
platform: 'ios',
appearance: 'dark'
});
imagesJson.push(darkIcon);
}
if (icon?.tinted) {
const tintedIcon = await generateUniversalIconAsync(projectRoot, {
icon: icon.tinted,
cacheKey: 'universal-icon-tinted',
iosNamedProjectRoot,
platform: 'ios',
appearance: 'tinted'
});
imagesJson.push(tintedIcon);
}
}
// Finally, write the Contents.json
await (0, _AssetContents().writeContentsJsonAsync)(_path().default.join(iosNamedProjectRoot, IMAGESET_PATH), {
images: imagesJson
});
}
/**
* Return the project's named iOS path: ios/MyProject/
*
* @param projectRoot Expo project root path.
*/
function getIosNamedProjectPath(projectRoot) {
const projectName = getProjectName(projectRoot);
return _path().default.join(projectRoot, 'ios', projectName);
}
function getAppleIconName(size, scale, appearance) {
let name = 'App-Icon';
if (appearance) {
name = `${name}-${appearance}`;
}
name = `${name}-${size}x${size}@${scale}x.png`;
return name;
}
async function generateUniversalIconAsync(projectRoot, {
icon,
cacheKey,
iosNamedProjectRoot,
platform,
appearance
}) {
const size = 1024;
const filename = getAppleIconName(size, 1, appearance);
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,
// Transparency needs to be preserved in dark variant, but can safely be removed in "light" and "tinted" variants.
removeTransparency: appearance !== 'dark',
// 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. (for "any" and "tinted" variants)
// TODO: Maybe use a more adaptive option based on the icon color?
backgroundColor: appearance !== 'dark' ? '#ffffff' : undefined
})).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 = _path().default.join(iosNamedProjectRoot, IMAGESET_PATH, filename);
await _fs().default.promises.writeFile(assetPath, source);
return {
filename,
idiom: 'universal',
platform,
size: `${size}x${size}`,
...(appearance ? {
appearances: [{
appearance: 'luminosity',
value: appearance
}]
} : {})
};
}
async function addLiquidGlassIcon(iconPath, projectRoot, iosNamedProjectRoot) {
const iconName = _path().default.basename(iconPath, '.icon');
const sourceIconPath = _path().default.join(projectRoot, iconPath);
const targetIconPath = _path().default.join(iosNamedProjectRoot, `${iconName}.icon`);
if (!_fs().default.existsSync(sourceIconPath)) {
_configPlugins().WarningAggregator.addWarningIOS('icon', `Liquid glass icon file not found at path: ${iconPath}`);
return;
}
await _fs().default.promises.cp(sourceIconPath, targetIconPath, {
recursive: true
});
}
/**
* Adds the .icons name to the project
*/
function setIconName(project, projectName, iconName) {
const [, target] = (0, _Target().findNativeTargetByName)(project, projectName);
const configurations = _configPlugins().IOSConfig.XcodeUtils.getBuildConfigurationsForListId(project, target.buildConfigurationList);
for (const [, config] of configurations) {
if (config?.buildSettings) {
config.buildSettings.ASSETCATALOG_COMPILER_APPICON_NAME = iconName;
}
}
}
/**
* Adds the .icon file to the project
*/
function addIconFileToProject(project, projectName, iconName) {
const iconPath = `${iconName}.icon`;
_configPlugins().IOSConfig.XcodeUtils.addResourceFileToGroup({
filepath: `${projectName}/${iconPath}`,
groupName: projectName,
project,
isBuildFile: true,
verbose: true
});
}
//# sourceMappingURL=withIosIcons.js.map