"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