This commit is contained in:
Yamozha
2021-04-02 02:24:13 +03:00
parent c23950b545
commit 7256d79e2c
31493 changed files with 3036630 additions and 0 deletions

View File

@ -0,0 +1,4 @@
/**
* @param androidMainPath Path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.
*/
export default function configureAndroidManifestXml(androidMainPath: string): Promise<void>;

View File

@ -0,0 +1,48 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const xml_manipulation_1 = require("../xml-manipulation");
const ANDROID_MANIFEST_XML_FILE_PATH = './AndroidManifest.xml';
function configureAndroidManifest(xml) {
const result = xml_manipulation_1.mergeXmlElements(xml, {
elements: [
{
name: 'manifest',
elements: [
{
name: 'application',
attributes: {
'android:name': '.MainApplication',
},
elements: [
{
name: 'activity',
attributes: {
'android:name': '.MainActivity',
'android:theme': {
newValue: '@style/Theme.App.SplashScreen',
},
},
},
],
},
],
},
],
});
return result;
}
/**
* @param androidMainPath Path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.
*/
async function configureAndroidManifestXml(androidMainPath) {
const filePath = path_1.default.resolve(androidMainPath, ANDROID_MANIFEST_XML_FILE_PATH);
const xmlContent = await xml_manipulation_1.readXmlFile(filePath);
const configuredXmlContent = configureAndroidManifest(xmlContent);
await xml_manipulation_1.writeXmlFile(filePath, configuredXmlContent);
}
exports.default = configureAndroidManifestXml;
//# sourceMappingURL=AndroidManifest.xml.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"AndroidManifest.xml.js","sourceRoot":"","sources":["../../src/android/AndroidManifest.xml.ts"],"names":[],"mappings":";;;;;AAAA,gDAAwB;AAGxB,0DAAkF;AAElF,MAAM,8BAA8B,GAAG,uBAAuB,CAAC;AAE/D,SAAS,wBAAwB,CAAC,GAAY;IAC5C,MAAM,MAAM,GAAG,mCAAgB,CAAC,GAAG,EAAE;QACnC,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE;oBACR;wBACE,IAAI,EAAE,aAAa;wBACnB,UAAU,EAAE;4BACV,cAAc,EAAE,kBAAkB;yBACnC;wBACD,QAAQ,EAAE;4BACR;gCACE,IAAI,EAAE,UAAU;gCAChB,UAAU,EAAE;oCACV,cAAc,EAAE,eAAe;oCAC/B,eAAe,EAAE;wCACf,QAAQ,EAAE,+BAA+B;qCAC1C;iCACF;6BACF;yBACF;qBACF;iBACF;aACF;SACF;KACF,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACY,KAAK,UAAU,2BAA2B,CAAC,eAAuB;IAC/E,MAAM,QAAQ,GAAG,cAAI,CAAC,OAAO,CAAC,eAAe,EAAE,8BAA8B,CAAC,CAAC;IAC/E,MAAM,UAAU,GAAG,MAAM,8BAAW,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,oBAAoB,GAAG,wBAAwB,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,+BAAY,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;AACrD,CAAC;AALD,8CAKC","sourcesContent":["import path from 'path';\nimport { Element } from 'xml-js';\n\nimport { readXmlFile, writeXmlFile, mergeXmlElements } from '../xml-manipulation';\n\nconst ANDROID_MANIFEST_XML_FILE_PATH = './AndroidManifest.xml';\n\nfunction configureAndroidManifest(xml: Element): Element {\n const result = mergeXmlElements(xml, {\n elements: [\n {\n name: 'manifest',\n elements: [\n {\n name: 'application',\n attributes: {\n 'android:name': '.MainApplication',\n },\n elements: [\n {\n name: 'activity',\n attributes: {\n 'android:name': '.MainActivity',\n 'android:theme': {\n newValue: '@style/Theme.App.SplashScreen',\n },\n },\n },\n ],\n },\n ],\n },\n ],\n });\n return result;\n}\n\n/**\n * @param androidMainPath Path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.\n */\nexport default async function configureAndroidManifestXml(androidMainPath: string) {\n const filePath = path.resolve(androidMainPath, ANDROID_MANIFEST_XML_FILE_PATH);\n const xmlContent = await readXmlFile(filePath);\n const configuredXmlContent = configureAndroidManifest(xmlContent);\n await writeXmlFile(filePath, configuredXmlContent);\n}\n"]}

View File

@ -0,0 +1,16 @@
import { Color } from '../SplashScreenConfig';
/**
* @param androidMainPath Path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.
*/
export default function configureColorsXml(androidMainPath: string, config: {
backgroundColor: Color;
statusBar?: {
backgroundColor?: Color;
};
darkMode?: {
backgroundColor?: Color;
statusBar?: {
backgroundColor?: Color;
};
};
}): Promise<void>;

View File

@ -0,0 +1,96 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const color_string_1 = __importDefault(require("color-string"));
const path_1 = __importDefault(require("path"));
const xml_manipulation_1 = require("../xml-manipulation");
const COLORS_XML_FILE_PATH = './res/values/colors.xml';
const COLORS_NIGHT_XML_FILE_PATH = './res/values-night/colors.xml';
function ensureDesiredXmlContent(xml, { backgroundColor, statusBarBackgroundColor, }) {
let idx = 0;
const result = xml_manipulation_1.mergeXmlElements(xml, {
elements: [
{
name: 'resources',
elements: [
{
idx: idx++,
comment: ` Below line is handled by '@expo/configure-splash-screen' command and it's discouraged to modify it manually `,
},
{
deletionFlag: !backgroundColor,
idx: !backgroundColor ? undefined : idx++,
name: 'color',
attributes: {
name: 'splashscreen_background',
},
elements: [
{
text: backgroundColor ? getAndroidStyleHex(backgroundColor) : '',
},
],
},
{
deletionFlag: !statusBarBackgroundColor,
idx: !statusBarBackgroundColor ? undefined : idx++,
name: 'color',
attributes: {
name: 'splashscreen_statusbar_color',
},
elements: [
{
text: statusBarBackgroundColor ? getAndroidStyleHex(statusBarBackgroundColor) : '',
},
],
},
],
},
],
});
return result;
}
/**
* css-recognized hex is of format `#RRGGBB(AA)` or `#RGB(A)`, while Android accepts `#(AA)RRGGBB` or `#(A)RGB` (https://developer.android.com/guide/topics/resources/color-list-resource)
* This function converts following formats:
* - `#RRGGBBAA` ➡️ `#AARRGGBB`,
* - `#RGBA` ➡️ `#ARGB`.
*/
function getAndroidStyleHex(color) {
return color_string_1.default.to
.hex(color)
.replace(/^(#)([0-F]{2})([0-F]{4})([0-F]{2}$)/i, '$1$4$2$3')
.replace(/^(#)([0-F])([0-F]{2})([0-F])$/i, '$1$4$2$3');
}
/**
* @param androidMainPath Path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.
*/
async function configureColorsXml(androidMainPath, config) {
var _a, _b, _c, _d;
const backgroundColor = config.backgroundColor;
const darkModeBackgroundColor = (_a = config.darkMode) === null || _a === void 0 ? void 0 : _a.backgroundColor;
const statusBarBackgroundColor = (_b = config.statusBar) === null || _b === void 0 ? void 0 : _b.backgroundColor;
const darkModeStatusBarBackgroundColor = (_d = (_c = config.darkMode) === null || _c === void 0 ? void 0 : _c.statusBar) === null || _d === void 0 ? void 0 : _d.backgroundColor;
if (darkModeStatusBarBackgroundColor && !statusBarBackgroundColor) {
throw new Error(`'darkModeStatusBarBackgroundColor' is available only if 'statusBarBackgroundColor' is provided as well.`);
}
const filePath = path_1.default.resolve(androidMainPath, COLORS_XML_FILE_PATH);
const darkFilePath = path_1.default.resolve(androidMainPath, COLORS_NIGHT_XML_FILE_PATH);
const xmlContent = await xml_manipulation_1.readXmlFile(filePath);
const darkFileContent = await xml_manipulation_1.readXmlFile(darkFilePath);
const configuredXmlContent = ensureDesiredXmlContent(xmlContent, {
backgroundColor,
statusBarBackgroundColor,
});
const configuredDarkXmlContent = ensureDesiredXmlContent(darkFileContent, {
backgroundColor: darkModeBackgroundColor,
statusBarBackgroundColor: darkModeStatusBarBackgroundColor,
});
await xml_manipulation_1.writeXmlFileOrRemoveFileUponNoResources(darkFilePath, configuredDarkXmlContent, {
disregardComments: true,
});
await xml_manipulation_1.writeXmlFile(filePath, configuredXmlContent);
}
exports.default = configureColorsXml;
//# sourceMappingURL=Colors.xml.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
import { SplashScreenImageResizeModeType } from '../constants';
/**
* @param androidMainPath Path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.
*/
export default function configureDrawableXml(androidMainPath: string, config?: {
imageResizeMode?: SplashScreenImageResizeModeType;
}): Promise<void>;

View File

@ -0,0 +1,63 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const constants_1 = require("../constants");
const xml_manipulation_1 = require("../xml-manipulation");
const DRAWABLE_XML_FILE_PATH = './res/drawable/splashscreen.xml';
function configureDrawable(xml, resizeMode) {
const expected = {
elements: [
{
idx: 0,
comment: `\n This file was created by '@expo/configure-splash-screen' and some of it's content shouldn't be modified by hand\n`,
},
{
name: 'layer-list',
attributes: {
'xmlns:android': 'http://schemas.android.com/apk/res/android',
},
elements: {
newValue: [
{
name: 'item',
attributes: {
'android:drawable': '@color/splashscreen_background',
},
},
].concat(resizeMode !== constants_1.SplashScreenImageResizeMode.NATIVE
? []
: [
{
name: 'item',
elements: [
{
name: 'bitmap',
attributes: {
'android:gravity': 'center',
'android:src': '@drawable/splashscreen_image',
},
},
],
},
]),
},
},
],
};
const result = xml_manipulation_1.mergeXmlElements(xml, expected);
return result;
}
/**
* @param androidMainPath Path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.
*/
async function configureDrawableXml(androidMainPath, config = {}) {
const filePath = path_1.default.resolve(androidMainPath, DRAWABLE_XML_FILE_PATH);
const xmlContent = await xml_manipulation_1.readXmlFile(filePath);
const configuredXmlContent = configureDrawable(xmlContent, config.imageResizeMode);
await xml_manipulation_1.writeXmlFile(filePath, configuredXmlContent);
}
exports.default = configureDrawableXml;
//# sourceMappingURL=Drawable.xml.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Drawable.xml.js","sourceRoot":"","sources":["../../src/android/Drawable.xml.ts"],"names":[],"mappings":";;;;;AAAA,gDAAwB;AAGxB,4CAA4F;AAC5F,0DAM6B;AAE7B,MAAM,sBAAsB,GAAG,iCAAiC,CAAC;AAEjE,SAAS,iBAAiB,CAAC,GAAY,EAAE,UAA4C;IACnF,MAAM,QAAQ,GAAyB;QACrC,QAAQ,EAAE;YACR;gBACE,GAAG,EAAE,CAAC;gBACN,OAAO,EAAE,uHAAuH;aACjI;YACD;gBACE,IAAI,EAAE,YAAY;gBAClB,UAAU,EAAE;oBACV,eAAe,EAAE,4CAA4C;iBAC9D;gBACD,QAAQ,EAAE;oBACR,QAAQ,EAAG;wBACT;4BACE,IAAI,EAAE,MAAM;4BACZ,UAAU,EAAE;gCACV,kBAAkB,EAAE,gCAAgC;6BACrD;yBACF;qBACwB,CAAC,MAAM,CAChC,UAAU,KAAK,uCAA2B,CAAC,MAAM;wBAC/C,CAAC,CAAC,EAAE;wBACJ,CAAC,CAAC;4BACE;gCACE,IAAI,EAAE,MAAM;gCACZ,QAAQ,EAAE;oCACR;wCACE,IAAI,EAAE,QAAQ;wCACd,UAAU,EAAE;4CACV,iBAAiB,EAAE,QAAQ;4CAC3B,aAAa,EAAE,8BAA8B;yCAC9C;qCACF;iCACF;6BACF;yBACF,CACN;iBACF;aACF;SACF;KACF,CAAC;IACF,MAAM,MAAM,GAAG,mCAAgB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACY,KAAK,UAAU,oBAAoB,CAChD,eAAuB,EACvB,SAEI,EAAE;IAEN,MAAM,QAAQ,GAAG,cAAI,CAAC,OAAO,CAAC,eAAe,EAAE,sBAAsB,CAAC,CAAC;IACvE,MAAM,UAAU,GAAG,MAAM,8BAAW,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,oBAAoB,GAAG,iBAAiB,CAAC,UAAU,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IACnF,MAAM,+BAAY,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC;AACrD,CAAC;AAVD,uCAUC","sourcesContent":["import path from 'path';\nimport { Element } from 'xml-js';\n\nimport { SplashScreenImageResizeMode, SplashScreenImageResizeModeType } from '../constants';\nimport {\n mergeXmlElements,\n readXmlFile,\n writeXmlFile,\n ExpectedElementsType,\n ExpectedElementType,\n} from '../xml-manipulation';\n\nconst DRAWABLE_XML_FILE_PATH = './res/drawable/splashscreen.xml';\n\nfunction configureDrawable(xml: Element, resizeMode?: SplashScreenImageResizeModeType): Element {\n const expected: ExpectedElementsType = {\n elements: [\n {\n idx: 0,\n comment: `\\n This file was created by '@expo/configure-splash-screen' and some of it's content shouldn't be modified by hand\\n`,\n },\n {\n name: 'layer-list',\n attributes: {\n 'xmlns:android': 'http://schemas.android.com/apk/res/android',\n },\n elements: {\n newValue: ([\n {\n name: 'item',\n attributes: {\n 'android:drawable': '@color/splashscreen_background',\n },\n },\n ] as ExpectedElementType[]).concat(\n resizeMode !== SplashScreenImageResizeMode.NATIVE\n ? []\n : [\n {\n name: 'item',\n elements: [\n {\n name: 'bitmap',\n attributes: {\n 'android:gravity': 'center',\n 'android:src': '@drawable/splashscreen_image',\n },\n },\n ],\n },\n ]\n ),\n },\n },\n ],\n };\n const result = mergeXmlElements(xml, expected);\n return result;\n}\n\n/**\n * @param androidMainPath Path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.\n */\nexport default async function configureDrawableXml(\n androidMainPath: string,\n config: {\n imageResizeMode?: SplashScreenImageResizeModeType;\n } = {}\n) {\n const filePath = path.resolve(androidMainPath, DRAWABLE_XML_FILE_PATH);\n const xmlContent = await readXmlFile(filePath);\n const configuredXmlContent = configureDrawable(xmlContent, config.imageResizeMode);\n await writeXmlFile(filePath, configuredXmlContent);\n}\n"]}

View File

@ -0,0 +1,13 @@
/**
* Deletes all previous splash_screen_images and copies new one to desired drawable directory.
* If path isn't provided then no new image is placed in drawable directories.
* @see https://developer.android.com/training/multiscreen/screendensities
*
* @param androidMainPath Absolute path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.
*/
export default function configureDrawables(androidMainPath: string, config?: {
image?: string;
darkMode?: {
image?: string;
};
}): Promise<void>;

View File

@ -0,0 +1,112 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const SPLASH_SCREEN_FILENAME = 'splashscreen_image.png';
const DRAWABLES_CONFIGS = {
default: {
modes: {
light: {
path: `./res/drawable/${SPLASH_SCREEN_FILENAME}`,
},
dark: {
path: `./res/drawable-night/${SPLASH_SCREEN_FILENAME}`,
},
},
dimensionsMultiplier: 1,
},
mdpi: {
modes: {
light: {
path: `./res/drawable-mdpi/${SPLASH_SCREEN_FILENAME}`,
},
dark: {
path: `./res/drawable-night-mdpi/${SPLASH_SCREEN_FILENAME}`,
},
},
dimensionsMultiplier: 1,
},
hdpi: {
modes: {
light: {
path: `./res/drawable-hdpi/${SPLASH_SCREEN_FILENAME}`,
},
dark: {
path: `./res/drawable-night-hdpi/${SPLASH_SCREEN_FILENAME}`,
},
},
dimensionsMultiplier: 1.5,
},
xhdpi: {
modes: {
light: {
path: `./res/drawable-xhdpi/${SPLASH_SCREEN_FILENAME}`,
},
dark: {
path: `./res/drawable-night-xhdpi/${SPLASH_SCREEN_FILENAME}`,
},
},
dimensionsMultiplier: 2,
},
xxhdpi: {
modes: {
light: {
path: `./res/drawable-xxhdpi/${SPLASH_SCREEN_FILENAME}`,
},
dark: {
path: `./res/drawable-night-xxhdpi/${SPLASH_SCREEN_FILENAME}`,
},
},
dimensionsMultiplier: 3,
},
xxxhdpi: {
modes: {
light: {
path: `./res/drawable-xxxhdpi/${SPLASH_SCREEN_FILENAME}`,
},
dark: {
path: `./res/drawable-night-xxxhdpi/${SPLASH_SCREEN_FILENAME}`,
},
},
dimensionsMultiplier: 4,
},
};
/**
* @param srcPath Absolute path
* @param dstPath Absolute path
*/
async function copyDrawableFile(srcPath, dstPath) {
if (!srcPath) {
return;
}
if (!(await fs_extra_1.default.pathExists(path_1.default.dirname(dstPath)))) {
await fs_extra_1.default.mkdir(path_1.default.dirname(dstPath));
}
await fs_extra_1.default.copyFile(srcPath, path_1.default.resolve(dstPath));
}
/**
* Deletes all previous splash_screen_images and copies new one to desired drawable directory.
* If path isn't provided then no new image is placed in drawable directories.
* @see https://developer.android.com/training/multiscreen/screendensities
*
* @param androidMainPath Absolute path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.
*/
async function configureDrawables(androidMainPath, config = {}) {
var _a;
await Promise.all(Object.values(DRAWABLES_CONFIGS).map(async ({ modes }) => {
await Promise.all(Object.values(modes).map(async ({ path: filePath }) => {
if (await fs_extra_1.default.pathExists(path_1.default.resolve(androidMainPath, filePath))) {
await fs_extra_1.default.remove(path_1.default.resolve(androidMainPath, filePath));
}
}));
}));
await Promise.all([
copyDrawableFile(config.image, path_1.default.resolve(androidMainPath, DRAWABLES_CONFIGS.default.modes.light.path)),
copyDrawableFile((_a = config.darkMode) === null || _a === void 0 ? void 0 : _a.image, path_1.default.resolve(androidMainPath, DRAWABLES_CONFIGS.default.modes.dark.path)),
]);
}
exports.default = configureDrawables;
//# sourceMappingURL=Drawables.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
import { SplashScreenImageResizeModeType } from '../constants';
/**
* Injects specific code to MainActivity that would trigger SplashScreen mounting process.
*/
export default function configureMainActivity(projectRootPath: string, config?: {
imageResizeMode?: SplashScreenImageResizeModeType;
statusBar?: {
translucent?: boolean;
};
}): Promise<void>;

View File

@ -0,0 +1,137 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const constants_1 = require("../constants");
const StateManager_1 = __importDefault(require("../utils/StateManager"));
const string_utils_1 = require("../utils/string-utils");
const Paths_1 = require("./Paths");
/**
* Injects specific code to MainActivity that would trigger SplashScreen mounting process.
*/
async function configureMainActivity(projectRootPath, config = {}) {
var _a, _b, _c;
const resizeMode = (_a = config.imageResizeMode) !== null && _a !== void 0 ? _a : constants_1.SplashScreenImageResizeMode.CONTAIN;
const statusBarTranslucent = (_c = (_b = config.statusBar) === null || _b === void 0 ? void 0 : _b.translucent) !== null && _c !== void 0 ? _c : false;
// eslint-disable-next-line
const mainActivity = await Paths_1.getMainActivityAsync(projectRootPath);
if (!mainActivity) {
throw new Error(`Failed to configure 'MainActivity'.`);
}
const isJava = mainActivity.language === 'java';
const isKotlin = mainActivity.language === 'kt';
const LE = isJava ? ';' : '';
const { state: newFileContent } = new StateManager_1.default(mainActivity.contents)
// importing ReactRootView
.applyAction(content => {
const [succeeded, newContent] = string_utils_1.replace(content, {
replacePattern: /^import com\.facebook\.react\.ReactRootView.*?$/m,
replaceContent: `import com.facebook.react.ReactRootView${LE}`,
});
return [newContent, 'replacedReactRootViewImports', succeeded];
})
.applyAction((content, { replacedReactRootViewImports }) => {
if (replacedReactRootViewImports) {
return [content, 'insertedReactRootViewImports', false];
}
const [succeeded, newContent] = string_utils_1.insert(content, {
insertPattern: isJava ? /(?=public class .* extends .* {.*$)/m : /(?=class .* : .* {.*$)/m,
insertContent: `import com.facebook.react.ReactRootView${LE}
`,
});
return [newContent, 'insertedReactRootViewImports', succeeded];
})
// importing SplashScreen
.applyAction(content => {
const [succeeded, newContent] = string_utils_1.replace(content, {
replacePattern: /^import expo\.modules\.splashscreen\..*?SplashScreen.*?\nimport expo\.modules\.splashscreen\.SplashScreenImageResizeMode.*?$/m,
replaceContent: `import expo.modules.splashscreen.singletons.SplashScreen${LE}
import expo.modules.splashscreen.SplashScreenImageResizeMode${LE}`,
});
return [newContent, 'replacedSplashImports', succeeded];
})
.applyAction((content, { replacedSplashImports }) => {
if (replacedSplashImports) {
return [content, 'insertedSplashImports', false];
}
const [succeeded, newContent] = string_utils_1.insert(content, {
insertPattern: isJava ? /(?=public class .* extends .* {.*$)/m : /(?=class .* : .* {.*$)/m,
insertContent: `import expo.modules.splashscreen.singletons.SplashScreen${LE}
import expo.modules.splashscreen.SplashScreenImageResizeMode${LE}
`,
});
return [newContent, 'insertedSplashImports', succeeded];
})
// registering SplashScreen in onCreate()
.applyAction(content => {
const [succeeded, newContent] = string_utils_1.replace(content, {
replacePattern: /(?<=super\.onCreate(.|\n)*?)SplashScreen\.show\(this, SplashScreenImageResizeMode\..*\).*$/m,
replaceContent: `SplashScreen.show(this, SplashScreenImageResizeMode.${resizeMode.toUpperCase()}, ReactRootView${isKotlin ? '::class.java' : '.class'}, ${statusBarTranslucent})${LE}`,
});
return [newContent, 'replacedInOnCreate', succeeded];
})
.applyAction((content, { replacedInOnCreate }) => {
if (replacedInOnCreate) {
return [content, 'insertedInOnCreate', false];
}
const [succeeded, newContent] = string_utils_1.insert(content, {
insertPattern: /(?<=^.*super\.onCreate.*$)/m,
insertContent: `
// SplashScreen.show(...) has to be called after super.onCreate(...)
// Below line is handled by '@expo/configure-splash-screen' command and it's discouraged to modify it manually
SplashScreen.show(this, SplashScreenImageResizeMode.${resizeMode.toUpperCase()}, ReactRootView${isKotlin ? '::class.java' : '.class'}, ${statusBarTranslucent})${LE}`,
});
return [newContent, 'insertedInOnCreate', succeeded];
})
// inserting basic onCreate()
.applyAction((content, { replacedInOnCreate, insertedInOnCreate }) => {
if (replacedInOnCreate || insertedInOnCreate) {
return [content, 'insertedOnCreate', false];
}
const [succeeded, newContent] = string_utils_1.insert(content, {
insertPattern: isJava
? /(?<=public class .* extends .* {.*$)/m
: /(?<=class .* : .* {.*$)/m,
insertContent: `
${isJava
? `@Override
protected void onCreate(Bundle savedInstanceState`
: 'override fun onCreate(savedInstanceState: Bundle?'}) {
super.onCreate(savedInstanceState)${LE}
// SplashScreen.show(...) has to be called after super.onCreate(...)
// Below line is handled by '@expo/configure-splash-screen' command and it's discouraged to modify it manually
SplashScreen.show(this, SplashScreenImageResizeMode.${resizeMode.toUpperCase()}, ReactRootView${isKotlin ? '::class.java' : '.class'}, ${statusBarTranslucent})${LE}
}
`,
});
return [newContent, 'insertedOnCreate', succeeded];
})
// importing Bundle
.applyAction((content, { replacedInOnCreate, insertedInOnCreate }) => {
if (replacedInOnCreate || insertedInOnCreate) {
return [content, 'replacedBundleImport', false];
}
const [succeeded, newContent] = string_utils_1.replace(content, {
replacePattern: /import android\.os\.Bundle/m,
replaceContent: 'import android.os.Bundle',
});
return [newContent, 'replacedBundleImport', succeeded];
})
.applyAction((content, { replacedInOnCreate, insertedInOnCreate }) => {
if (replacedInOnCreate || insertedInOnCreate) {
return [content, 'insertedBundleImport', false];
}
const [succeeded, newContent] = string_utils_1.insert(content, {
insertPattern: /(?<=(^.*?package .*?$))/m,
insertContent: `\n\nimport android.os.Bundle${LE}`,
});
return [newContent, 'insertedBundleImport', succeeded];
});
await fs_extra_1.default.writeFile(mainActivity.path, newFileContent);
}
exports.default = configureMainActivity;
//# sourceMappingURL=MainActivity.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
export interface ProjectFile<L extends string = string> {
path: string;
language: L;
contents: string;
}
export declare function assert(value: any, message?: string | Error): asserts value;
export declare type ApplicationProjectFile = ProjectFile<'java' | 'kt'>;
export declare function getMainActivityAsync(projectRoot: string): Promise<ApplicationProjectFile>;

View File

@ -0,0 +1,56 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getMainActivityAsync = exports.assert = void 0;
const assert_1 = __importDefault(require("assert"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const glob_1 = require("glob");
const path = __importStar(require("path"));
function assert(value, message) {
// TODO: Upgrade node? TypeScript isn't properly asserting values without this wrapper.
return assert_1.default(value, message);
}
exports.assert = assert;
async function getProjectFileAsync(projectRoot, name) {
const mainActivityJavaPath = glob_1.sync(path.join(projectRoot, `android/app/src/main/java/**/${name}.{java,kt}`))[0];
assert(mainActivityJavaPath, `Project file "${name}" does not exist in android project for root "${projectRoot}"`);
const mainActivityPathJava = path.resolve(mainActivityJavaPath, `../${name}.java`);
const mainActivityPathKotlin = path.resolve(mainActivityJavaPath, `../${name}.kt`);
const isJava = await fs_extra_1.default.pathExists(mainActivityPathJava);
const isKotlin = !isJava && (await fs_extra_1.default.pathExists(mainActivityPathKotlin));
if (!isJava && !isKotlin) {
throw new Error(`Failed to find '${name}' file for project: ${projectRoot}.`);
}
const filePath = isJava ? mainActivityPathJava : mainActivityPathKotlin;
return {
path: path.normalize(filePath),
contents: fs_extra_1.default.readFileSync(filePath, 'utf8'),
language: isJava ? 'java' : 'kt',
};
}
async function getMainActivityAsync(projectRoot) {
return getProjectFileAsync(projectRoot, 'MainActivity');
}
exports.getMainActivityAsync = getMainActivityAsync;
//# sourceMappingURL=Paths.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"Paths.js","sourceRoot":"","sources":["../../src/android/Paths.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oDAAgC;AAChC,wDAA0B;AAC1B,+BAAwC;AACxC,2CAA6B;AAQ7B,SAAgB,MAAM,CAAC,KAAU,EAAE,OAAwB;IACzD,uFAAuF;IACvF,OAAO,gBAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AACpC,CAAC;AAHD,wBAGC;AAID,KAAK,UAAU,mBAAmB,CAChC,WAAmB,EACnB,IAAY;IAEZ,MAAM,oBAAoB,GAAG,WAAQ,CACnC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gCAAgC,IAAI,YAAY,CAAC,CACzE,CAAC,CAAC,CAAC,CAAC;IACL,MAAM,CACJ,oBAAoB,EACpB,iBAAiB,IAAI,iDAAiD,WAAW,GAAG,CACrF,CAAC;IAEF,MAAM,oBAAoB,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,MAAM,IAAI,OAAO,CAAC,CAAC;IACnF,MAAM,sBAAsB,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,MAAM,IAAI,KAAK,CAAC,CAAC;IAEnF,MAAM,MAAM,GAAG,MAAM,kBAAE,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAE1E,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE;QACxB,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,uBAAuB,WAAW,GAAG,CAAC,CAAC;KAC/E;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,sBAAsB,CAAC;IACxE,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;QAC9B,QAAQ,EAAE,kBAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC3C,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;KACjC,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,oBAAoB,CAAC,WAAmB;IAC5D,OAAO,mBAAmB,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;AAC1D,CAAC;AAFD,oDAEC","sourcesContent":["import nodeAssert from 'assert';\nimport fs from 'fs-extra';\nimport { sync as globSync } from 'glob';\nimport * as path from 'path';\n\nexport interface ProjectFile<L extends string = string> {\n path: string;\n language: L;\n contents: string;\n}\n\nexport function assert(value: any, message?: string | Error): asserts value {\n // TODO: Upgrade node? TypeScript isn't properly asserting values without this wrapper.\n return nodeAssert(value, message);\n}\n\nexport type ApplicationProjectFile = ProjectFile<'java' | 'kt'>;\n\nasync function getProjectFileAsync(\n projectRoot: string,\n name: string\n): Promise<ApplicationProjectFile> {\n const mainActivityJavaPath = globSync(\n path.join(projectRoot, `android/app/src/main/java/**/${name}.{java,kt}`)\n )[0];\n assert(\n mainActivityJavaPath,\n `Project file \"${name}\" does not exist in android project for root \"${projectRoot}\"`\n );\n\n const mainActivityPathJava = path.resolve(mainActivityJavaPath, `../${name}.java`);\n const mainActivityPathKotlin = path.resolve(mainActivityJavaPath, `../${name}.kt`);\n\n const isJava = await fs.pathExists(mainActivityPathJava);\n const isKotlin = !isJava && (await fs.pathExists(mainActivityPathKotlin));\n\n if (!isJava && !isKotlin) {\n throw new Error(`Failed to find '${name}' file for project: ${projectRoot}.`);\n }\n const filePath = isJava ? mainActivityPathJava : mainActivityPathKotlin;\n return {\n path: path.normalize(filePath),\n contents: fs.readFileSync(filePath, 'utf8'),\n language: isJava ? 'java' : 'kt',\n };\n}\n\nexport async function getMainActivityAsync(projectRoot: string): Promise<ApplicationProjectFile> {\n return getProjectFileAsync(projectRoot, 'MainActivity');\n}\n"]}

View File

@ -0,0 +1,17 @@
import { Color } from '../SplashScreenConfig';
import { SplashScreenStatusBarStyleType } from '../constants';
/**
* @param androidMainPath Path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.
*/
export default function configureStylesXml(androidMainPath: string, config?: {
statusBar?: {
style?: SplashScreenStatusBarStyleType;
hidden?: boolean;
backgroundColor?: Color;
};
darkMode?: {
statusBar?: {
style?: SplashScreenStatusBarStyleType;
};
};
}): Promise<void>;

View File

@ -0,0 +1,183 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const constants_1 = require("../constants");
const xml_manipulation_1 = require("../xml-manipulation");
const STYLES_XML_FILE_PATH = './res/values/styles.xml';
const STYLES_V23_XML_FILE_PATH = './res/values-v23/styles.xml';
const STYLES_DARK_V23_XML_FILE_PATH = './res/values-night-v23/styles.xml';
const STYLE_NAME = 'Theme.App.SplashScreen';
function configureStyle(xml, { statusBarHidden, statusBarStyle, addStatusBarBackgroundColor, }) {
let idx = 0;
const result = xml_manipulation_1.mergeXmlElements(xml, {
elements: [
{
name: 'resources',
elements: [
{
name: 'style',
attributes: {
name: STYLE_NAME,
parent: 'Theme.AppCompat.Light.NoActionBar',
},
elements: [
{
idx: idx++,
comment: ` Below line is handled by '@expo/configure-splash-screen' command and it's discouraged to modify it manually `,
},
{
idx: idx++,
name: 'item',
attributes: {
name: 'android:windowBackground',
},
elements: [
{
text: '@drawable/splashscreen',
},
],
},
{
idx: statusBarHidden === undefined ? undefined : idx++,
deletionFlag: statusBarHidden === undefined,
name: 'item',
attributes: {
name: 'android:windowFullscreen',
},
elements: [{ text: String(statusBarHidden) }],
},
{
idx: statusBarStyle === undefined ||
statusBarStyle === constants_1.SplashScreenStatusBarStyle.DEFAULT
? undefined
: idx++,
deletionFlag: statusBarStyle === undefined ||
statusBarStyle === constants_1.SplashScreenStatusBarStyle.DEFAULT,
name: 'item',
attributes: {
name: 'android:windowLightStatusBar',
},
elements: [
{
text: statusBarStyle === constants_1.SplashScreenStatusBarStyle.LIGHT_CONTENT
? 'false'
: statusBarStyle === constants_1.SplashScreenStatusBarStyle.DARK_CONTENT
? 'true'
: '',
},
],
},
{
idx: addStatusBarBackgroundColor ? idx++ : undefined,
deletionFlag: !addStatusBarBackgroundColor,
name: 'item',
attributes: {
name: 'android:statusBarColor',
},
elements: [{ text: '@color/splashscreen_statusbar_color' }],
},
{
comment: ` Customize your splash screen theme here `,
},
],
},
],
},
],
});
return result;
}
/**
* Compares two subparts (`style` elements with STYLE_NAME name attribute) of given elements disregarding comments
*/
function areStyleElementsEqual(a, b) {
var _a, _b, _c, _d;
const styleA = (_b = (_a = a.elements) === null || _a === void 0 ? void 0 : _a[0].elements) === null || _b === void 0 ? void 0 : _b.find(({ name, attributes }) => name === 'style' && (attributes === null || attributes === void 0 ? void 0 : attributes.name) === STYLE_NAME);
const styleB = (_d = (_c = b.elements) === null || _c === void 0 ? void 0 : _c[0].elements) === null || _d === void 0 ? void 0 : _d.find(({ name, attributes }) => name === 'style' && (attributes === null || attributes === void 0 ? void 0 : attributes.name) === STYLE_NAME);
return !!styleA && !!styleB && xml_manipulation_1.xmlElementsEqual(styleA, styleB, { disregardComments: true });
}
/**
* Removes `style` element with STYLE_NAME name attribute from given element.
* Function assumes that the structure of the input `element` is correct (`element.elements[name = resources].elements[name = style, attributes.name = STYLE_NAME]`).
*/
function removeStyleElement(element) {
var _a, _b, _c, _d;
const resources = (_a = element.elements) === null || _a === void 0 ? void 0 : _a.find(el => el.name === 'resources');
const idxToBeRemoved = (_c = (_b = resources === null || resources === void 0 ? void 0 : resources.elements) === null || _b === void 0 ? void 0 : _b.findIndex(el => { var _a; return el.name === 'style' && ((_a = el.attributes) === null || _a === void 0 ? void 0 : _a.name) === STYLE_NAME; })) !== null && _c !== void 0 ? _c : -1;
if (idxToBeRemoved !== -1) {
// eslint-disable-next-line no-unused-expressions
(_d = resources === null || resources === void 0 ? void 0 : resources.elements) === null || _d === void 0 ? void 0 : _d.splice(idxToBeRemoved, 1);
}
return element;
}
/**
* Creates proper element structure with single `style` element disregarding all other styles.
* Use to create more specific configuration file, but preserving previous attributes.
* Function assumes that the structure of the input `element` is correct (`element.elements[name = resources].elements[name = style, attributes.name = STYLE_NAME]`).
*/
function elementWithStyleElement(element) {
var _a, _b;
const result = { ...element };
const resources = (_a = element.elements) === null || _a === void 0 ? void 0 : _a.find(el => el.name === 'resources');
if (!resources) {
return;
}
const styleElement = (_b = resources === null || resources === void 0 ? void 0 : resources.elements) === null || _b === void 0 ? void 0 : _b.find(el => { var _a; return el.name === 'style' && ((_a = el.attributes) === null || _a === void 0 ? void 0 : _a.name) === STYLE_NAME; });
if (!styleElement) {
return;
}
result.elements = [{ ...resources, elements: [styleElement] }];
return result;
}
/**
* @param androidMainPath Path to the main directory containing code and resources in Android project. In general that would be `android/app/src/main`.
*/
async function configureStylesXml(androidMainPath, config = {}) {
var _a, _b, _c, _d, _e, _f;
const statusBarStyle = (_b = (_a = config.statusBar) === null || _a === void 0 ? void 0 : _a.style) !== null && _b !== void 0 ? _b : constants_1.SplashScreenStatusBarStyle.DEFAULT;
const statusBarHidden = (_c = config.statusBar) === null || _c === void 0 ? void 0 : _c.hidden;
const darkModeStatusBarStyle = (_e = (_d = config.darkMode) === null || _d === void 0 ? void 0 : _d.statusBar) === null || _e === void 0 ? void 0 : _e.style;
const addStatusBarBackgroundColor = Boolean((_f = config.statusBar) === null || _f === void 0 ? void 0 : _f.backgroundColor);
if (darkModeStatusBarStyle && !statusBarStyle) {
throw new Error(`'darkModeStatusBarStyle' is available only if 'statusBarStyle' is provided as well.`);
}
const filePath = path_1.default.resolve(androidMainPath, STYLES_XML_FILE_PATH);
const v23FilePath = path_1.default.resolve(androidMainPath, STYLES_V23_XML_FILE_PATH);
const v23DarkFilePath = path_1.default.resolve(androidMainPath, STYLES_DARK_V23_XML_FILE_PATH);
const xmlContent = await xml_manipulation_1.readXmlFile(filePath);
const contentWithSingleStyle = elementWithStyleElement(xmlContent);
const v23XmlContent = await xml_manipulation_1.readXmlFile(v23FilePath, contentWithSingleStyle);
const v23DarkXmlContent = await xml_manipulation_1.readXmlFile(v23DarkFilePath, contentWithSingleStyle);
const configuredXmlContent = configureStyle(xmlContent, {
statusBarHidden,
addStatusBarBackgroundColor,
});
const configuredV23XmlContent = configureStyle(v23XmlContent, {
statusBarHidden,
statusBarStyle,
addStatusBarBackgroundColor,
});
const configuredV23DarkXmlContent = configureStyle(v23DarkXmlContent, {
statusBarHidden,
statusBarStyle: darkModeStatusBarStyle !== null && darkModeStatusBarStyle !== void 0 ? darkModeStatusBarStyle : statusBarStyle,
addStatusBarBackgroundColor,
});
if (areStyleElementsEqual(configuredV23DarkXmlContent, configuredV23XmlContent)) {
await xml_manipulation_1.writeXmlFileOrRemoveFileUponNoResources(v23DarkFilePath, removeStyleElement(configuredV23DarkXmlContent));
}
else {
await xml_manipulation_1.writeXmlFile(v23DarkFilePath, configuredV23DarkXmlContent);
}
if (areStyleElementsEqual(configuredV23XmlContent, configuredXmlContent)) {
await xml_manipulation_1.writeXmlFileOrRemoveFileUponNoResources(v23FilePath, removeStyleElement(configuredV23XmlContent));
}
else {
await xml_manipulation_1.writeXmlFile(v23FilePath, configuredV23XmlContent);
}
await xml_manipulation_1.writeXmlFile(filePath, configuredXmlContent);
}
exports.default = configureStylesXml;
//# sourceMappingURL=Styles.xml.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
import { AndroidSplashScreenConfigJSON } from '../SplashScreenConfig';
export default function configureAndroid(projectRootPath: string, configJSON: AndroidSplashScreenConfigJSON): Promise<void>;

View File

@ -0,0 +1,27 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const validators_1 = require("../validators");
const AndroidManifest_xml_1 = __importDefault(require("./AndroidManifest.xml"));
const Colors_xml_1 = __importDefault(require("./Colors.xml"));
const Drawable_xml_1 = __importDefault(require("./Drawable.xml"));
const Drawables_1 = __importDefault(require("./Drawables"));
const MainActivity_1 = __importDefault(require("./MainActivity"));
const Styles_xml_1 = __importDefault(require("./Styles.xml"));
async function configureAndroid(projectRootPath, configJSON) {
const validatedConfig = await validators_1.validateAndroidConfig(configJSON);
const androidMainPath = path_1.default.resolve(projectRootPath, 'android/app/src/main');
await Promise.all([
Drawables_1.default(androidMainPath, validatedConfig),
Colors_xml_1.default(androidMainPath, validatedConfig),
Drawable_xml_1.default(androidMainPath, validatedConfig),
Styles_xml_1.default(androidMainPath, validatedConfig),
AndroidManifest_xml_1.default(androidMainPath),
MainActivity_1.default(projectRootPath, validatedConfig),
]);
}
exports.default = configureAndroid;
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/android/index.ts"],"names":[],"mappings":";;;;;AAAA,gDAAwB;AAGxB,8CAAsD;AACtD,gFAAgE;AAChE,8DAA8C;AAC9C,kEAAkD;AAClD,4DAA6C;AAC7C,kEAAmD;AACnD,8DAA8C;AAE/B,KAAK,UAAU,gBAAgB,CAC5C,eAAuB,EACvB,UAAyC;IAEzC,MAAM,eAAe,GAAG,MAAM,kCAAqB,CAAC,UAAU,CAAC,CAAC;IAEhE,MAAM,eAAe,GAAG,cAAI,CAAC,OAAO,CAAC,eAAe,EAAE,sBAAsB,CAAC,CAAC;IAE9E,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,mBAAkB,CAAC,eAAe,EAAE,eAAe,CAAC;QACpD,oBAAkB,CAAC,eAAe,EAAE,eAAe,CAAC;QACpD,sBAAoB,CAAC,eAAe,EAAE,eAAe,CAAC;QACtD,oBAAkB,CAAC,eAAe,EAAE,eAAe,CAAC;QACpD,6BAA2B,CAAC,eAAe,CAAC;QAC5C,sBAAqB,CAAC,eAAe,EAAE,eAAe,CAAC;KACxD,CAAC,CAAC;AACL,CAAC;AAhBD,mCAgBC","sourcesContent":["import path from 'path';\n\nimport { AndroidSplashScreenConfigJSON } from '../SplashScreenConfig';\nimport { validateAndroidConfig } from '../validators';\nimport configureAndroidManifestXml from './AndroidManifest.xml';\nimport configureColorsXml from './Colors.xml';\nimport configureDrawableXml from './Drawable.xml';\nimport configureDrawables from './Drawables';\nimport configureMainActivity from './MainActivity';\nimport configureStylesXml from './Styles.xml';\n\nexport default async function configureAndroid(\n projectRootPath: string,\n configJSON: AndroidSplashScreenConfigJSON\n) {\n const validatedConfig = await validateAndroidConfig(configJSON);\n\n const androidMainPath = path.resolve(projectRootPath, 'android/app/src/main');\n\n await Promise.all([\n configureDrawables(androidMainPath, validatedConfig),\n configureColorsXml(androidMainPath, validatedConfig),\n configureDrawableXml(androidMainPath, validatedConfig),\n configureStylesXml(androidMainPath, validatedConfig),\n configureAndroidManifestXml(androidMainPath),\n configureMainActivity(projectRootPath, validatedConfig),\n ]);\n}\n"]}