const { withAppBuildGradle, withDangerousMod, } = require('@expo/config-plugins'); const fs = require('fs'); const path = require('path'); const BUILD_TYPES_MARKER = '// @generated by with-android-customizations'; const BUILD_TYPES_APPLY = `${BUILD_TYPES_MARKER} apply from: new File( rootDir, "../plugins/android/android-build-types.gradle", ) `; const ANDROID_ASSET_VARIANTS = [ { source: 'release', target: 'main' }, { source: 'preview', target: 'preRelease' }, ]; const LAUNCHER_RESOURCE_NAMES = [ 'ic_launcher', 'ic_launcher_background', 'ic_launcher_foreground', 'ic_launcher_monochrome', 'ic_launcher_round', ]; const DRAWABLE_RESOURCE_NAMES = [ 'notification_icon', 'splash_icon', 'splashscreen_logo', ]; const ANDROID_DENSITIES = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi', 'xxxhdpi']; const withBuildGradleCustomizations = config => withAppBuildGradle(config, config => { const { contents } = config.modResults; if (!contents.includes(BUILD_TYPES_MARKER)) { config.modResults.contents = `${contents.trimEnd()} ${BUILD_TYPES_APPLY}`; } return config; }); const removeGeneratedIconResources = resDir => { if (!fs.existsSync(resDir)) { return; } for (const resourceDirName of fs.readdirSync(resDir)) { const resourceDir = path.join(resDir, resourceDirName); if (!fs.statSync(resourceDir).isDirectory()) { continue; } if (resourceDirName.startsWith('mipmap-')) { for (const resourceName of LAUNCHER_RESOURCE_NAMES) { for (const extension of ['png', 'webp', 'xml']) { fs.rmSync(path.join(resourceDir, `${resourceName}.${extension}`), { force: true, }); } } } if (resourceDirName.startsWith('drawable-')) { for (const resourceName of DRAWABLE_RESOURCE_NAMES) { for (const extension of ['png', 'webp', 'xml']) { fs.rmSync(path.join(resourceDir, `${resourceName}.${extension}`), { force: true, }); } } } } }; const installVariantSplashIcons = resDir => { for (const density of ANDROID_DENSITIES) { const drawableDir = path.join(resDir, `drawable-${density}`); const sourcePath = path.join(drawableDir, 'splash_icon.png'); const splashPath = path.join(drawableDir, 'splashscreen_logo.png'); const nightDrawableDir = path.join(resDir, `drawable-night-${density}`); const nightSplashPath = path.join( nightDrawableDir, 'splashscreen_logo.png', ); fs.renameSync(sourcePath, splashPath); fs.mkdirSync(nightDrawableDir, { recursive: true }); fs.copyFileSync(splashPath, nightSplashPath); } }; const withAndroidVariantAssets = config => withDangerousMod(config, [ 'android', config => { const { projectRoot, platformProjectRoot } = config.modRequest; for (const variant of ANDROID_ASSET_VARIANTS) { const sourceResDir = path.join( projectRoot, 'assets', 'android-icons', variant.source, 'res', ); const targetResDir = path.join( platformProjectRoot, 'app', 'src', variant.target, 'res', ); removeGeneratedIconResources(targetResDir); fs.mkdirSync(targetResDir, { recursive: true }); fs.cpSync(sourceResDir, targetResDir, { recursive: true }); installVariantSplashIcons(targetResDir); } return config; }, ]); module.exports = config => { config = withBuildGradleCustomizations(config); return withAndroidVariantAssets(config); };