react-native-bootsplash 5.5.3 → 6.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,13 +3,17 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.writeXml = exports.writeJson = exports.writeHtml = exports.readXml = exports.readHtml = exports.parseColor = exports.logWrite = exports.log = exports.hfs = exports.getIOSAssetFileName = exports.generate = exports.cleanIOSAssets = exports.addFileToXcodeProject = void 0;
6
+ exports.writeXml = exports.writeJson = exports.writeHtml = exports.withGenerate = exports.readXml = exports.readHtml = exports.parseColor = exports.log = exports.hfs = exports.getImageHeight = exports.generate = void 0;
7
7
  var _hash = _interopRequireDefault(require("@emotion/hash"));
8
- var _configPlugins = require("@expo/config-plugins");
8
+ var _config = require("@expo/config");
9
+ var Expo = _interopRequireWildcard(require("@expo/config-plugins"));
10
+ var _Colors = require("@expo/config-plugins/build/android/Colors");
11
+ var _codeMod = require("@expo/config-plugins/build/android/codeMod");
12
+ var _generateCode = require("@expo/config-plugins/build/utils/generateCode");
9
13
  var _plist = _interopRequireDefault(require("@expo/plist"));
10
14
  var _cliTools = require("@react-native-community/cli-tools");
11
15
  var _detectIndent = _interopRequireDefault(require("detect-indent"));
12
- var _fs = _interopRequireDefault(require("fs"));
16
+ var _fsExtra = _interopRequireDefault(require("fs-extra"));
13
17
  var _nodeHtmlParser = require("node-html-parser");
14
18
  var _path = _interopRequireDefault(require("path"));
15
19
  var _picocolors = _interopRequireDefault(require("picocolors"));
@@ -23,6 +27,21 @@ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return
23
27
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
24
28
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
29
  const workingPath = process.env.INIT_CWD ?? process.env.PWD ?? process.cwd();
30
+ const projectRoot = (0, _cliTools.findProjectRoot)(workingPath);
31
+ const log = exports.log = {
32
+ error: text => {
33
+ console.log(_picocolors.default.red(`❌ ${text}`));
34
+ },
35
+ title: (emoji, text) => {
36
+ console.log(`\n${emoji} ${_picocolors.default.underline(_picocolors.default.bold(text))}`);
37
+ },
38
+ warn: text => {
39
+ console.log(_picocolors.default.yellow(`⚠️ ${text}`));
40
+ },
41
+ write: (filePath, dimensions) => {
42
+ console.log(` ${_path.default.relative(workingPath, filePath)}` + (dimensions != null ? ` (${dimensions.width}x${dimensions.height})` : ""));
43
+ }
44
+ };
26
45
  const parseColor = value => {
27
46
  const up = value.toUpperCase().replace(/[^0-9A-F]/g, "");
28
47
  if (up.length !== 3 && up.length !== 6) {
@@ -31,12 +50,12 @@ const parseColor = value => {
31
50
  }
32
51
  const hex = up.length === 3 ? "#" + up[0] + up[0] + up[1] + up[1] + up[2] + up[2] : "#" + up;
33
52
  const rgb = {
34
- R: (parseInt("" + hex[1] + hex[2], 16) / 255).toPrecision(15),
35
- G: (parseInt("" + hex[3] + hex[4], 16) / 255).toPrecision(15),
36
- B: (parseInt("" + hex[5] + hex[6], 16) / 255).toPrecision(15)
53
+ R: (Number.parseInt("" + hex[1] + hex[2], 16) / 255).toPrecision(15),
54
+ G: (Number.parseInt("" + hex[3] + hex[4], 16) / 255).toPrecision(15),
55
+ B: (Number.parseInt("" + hex[5] + hex[6], 16) / 255).toPrecision(15)
37
56
  };
38
57
  return {
39
- hex,
58
+ hex: hex.toLowerCase(),
40
59
  rgb
41
60
  };
42
61
  };
@@ -48,7 +67,8 @@ const getStoryboard = ({
48
67
  R,
49
68
  G,
50
69
  B
51
- }
70
+ },
71
+ fileNameSuffix
52
72
  }) => {
53
73
  const frameWidth = 375;
54
74
  const frameHeight = 667;
@@ -61,6 +81,7 @@ const getStoryboard = ({
61
81
  <dependencies>
62
82
  <deployment identifier="iOS"/>
63
83
  <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
84
+ <capability name="Named colors" minToolsVersion="9.0"/>
64
85
  <capability name="Safe area layout guides" minToolsVersion="9.0"/>
65
86
  <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
66
87
  </dependencies>
@@ -73,7 +94,7 @@ const getStoryboard = ({
73
94
  <rect key="frame" x="0.0" y="0.0" width="${frameWidth}" height="${frameHeight}"/>
74
95
  <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
75
96
  <subviews>
76
- <imageView autoresizesSubviews="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="BootSplashLogo" translatesAutoresizingMaskIntoConstraints="NO" id="3lX-Ut-9ad">
97
+ <imageView autoresizesSubviews="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="BootSplashLogo-${fileNameSuffix}" translatesAutoresizingMaskIntoConstraints="NO" id="3lX-Ut-9ad">
77
98
  <rect key="frame" x="${logoX}" y="${logoY}" width="${logoWidth}" height="${logoHeight}"/>
78
99
  <accessibility key="accessibilityConfiguration">
79
100
  <accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
@@ -81,7 +102,7 @@ const getStoryboard = ({
81
102
  </imageView>
82
103
  </subviews>
83
104
  <viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
84
- <color key="backgroundColor" red="${R}" green="${G}" blue="${B}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
105
+ <color key="backgroundColor" name="BootSplashBackground-${fileNameSuffix}"/>
85
106
  <constraints>
86
107
  <constraint firstItem="3lX-Ut-9ad" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="Fh9-Fy-1nT"/>
87
108
  <constraint firstItem="3lX-Ut-9ad" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="nvB-Ic-PnI"/>
@@ -94,63 +115,59 @@ const getStoryboard = ({
94
115
  </scene>
95
116
  </scenes>
96
117
  <resources>
97
- <image name="BootSplashLogo" width="${logoWidth}" height="${logoHeight}"/>
118
+ <image name="BootSplashLogo-${fileNameSuffix}" width="${logoWidth}" height="${logoHeight}"/>
119
+ <namedColor name="BootSplashBackground-${fileNameSuffix}">
120
+ <color red="${R}" green="${G}" blue="${B}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
121
+ </namedColor>
98
122
  </resources>
99
123
  </document>
100
124
  `;
101
125
  };
102
- const addFileToXcodeProject = filePath => {
103
- const projectRoot = (0, _cliTools.findProjectRoot)(workingPath);
104
- const pbxprojectPath = _configPlugins.IOSConfig.Paths.getPBXProjectPath(projectRoot);
105
- const project = _configPlugins.IOSConfig.XcodeUtils.getPbxproj(projectRoot);
106
- const xcodeProjectPath = _configPlugins.IOSConfig.Paths.getXcodeProjectPath(projectRoot);
107
- _configPlugins.IOSConfig.XcodeUtils.addResourceFileToGroup({
108
- filepath: filePath,
109
- groupName: _path.default.parse(xcodeProjectPath).name,
110
- project,
111
- isBuildFile: true
112
- });
113
- hfs.write(pbxprojectPath, project.writeSync());
114
- logWrite(pbxprojectPath);
115
- };
116
126
 
117
127
  // Freely inspired by https://github.com/humanwhocodes/humanfs
118
- exports.addFileToXcodeProject = addFileToXcodeProject;
119
128
  const hfs = exports.hfs = {
120
- buffer: path => _fs.default.readFileSync(path),
121
- exists: path => _fs.default.existsSync(path),
122
- json: path => JSON.parse(_fs.default.readFileSync(path, "utf-8")),
123
- readDir: path => _fs.default.readdirSync(path, "utf-8"),
124
- realPath: path => _fs.default.realpathSync(path, "utf-8"),
125
- rm: path => _fs.default.rmSync(path, {
126
- force: true
129
+ buffer: path => _fsExtra.default.readFileSync(path),
130
+ exists: path => _fsExtra.default.existsSync(path),
131
+ isDir: path => _fsExtra.default.lstatSync(path).isDirectory(),
132
+ json: path => JSON.parse(_fsExtra.default.readFileSync(path, "utf-8")),
133
+ readDir: path => _fsExtra.default.readdirSync(path, "utf-8"),
134
+ realPath: path => _fsExtra.default.realpathSync(path, "utf-8"),
135
+ rm: path => _fsExtra.default.rmSync(path, {
136
+ force: true,
137
+ recursive: true
127
138
  }),
128
- text: path => _fs.default.readFileSync(path, "utf-8"),
139
+ text: path => _fsExtra.default.readFileSync(path, "utf-8"),
140
+ copy: (src, dest) => {
141
+ if (hfs.isDir(src) || !hfs.exists(dest)) {
142
+ return _fsExtra.default.copySync(src, dest, {
143
+ overwrite: true
144
+ });
145
+ }
146
+ const srcBuffer = _fsExtra.default.readFileSync(src);
147
+ const destBuffer = _fsExtra.default.readFileSync(dest);
148
+ if (!srcBuffer.equals(destBuffer)) {
149
+ return _fsExtra.default.copySync(src, dest, {
150
+ overwrite: true
151
+ });
152
+ }
153
+ },
129
154
  ensureDir: dir => {
130
- _fs.default.mkdirSync(dir, {
155
+ _fsExtra.default.mkdirSync(dir, {
131
156
  recursive: true
132
157
  });
133
158
  },
134
- write: (file, data) => {
135
- const trimmed = data.trim();
136
- _fs.default.writeFileSync(file, trimmed === "" ? trimmed : trimmed + "\n", "utf-8");
159
+ write: (path, content) => {
160
+ const trimmed = content.trim();
161
+ _fsExtra.default.writeFileSync(path, trimmed === "" ? trimmed : trimmed + "\n", "utf-8");
137
162
  }
138
163
  };
139
- const log = exports.log = {
140
- error: text => console.log(_picocolors.default.red(`❌ ${text}`)),
141
- text: text => console.log(text),
142
- title: (emoji, text) => console.log(`\n${emoji} ${_picocolors.default.underline(_picocolors.default.bold(text))}`),
143
- warn: text => console.log(_picocolors.default.yellow(`⚠️ ${text}`))
144
- };
145
- const logWrite = (filePath, dimensions) => console.log(` ${_path.default.relative(workingPath, filePath)}` + (dimensions != null ? ` (${dimensions.width}x${dimensions.height})` : ""));
146
- exports.logWrite = logWrite;
147
- const writeJson = (file, json) => {
148
- hfs.write(file, JSON.stringify(json, null, 2));
149
- logWrite(file);
164
+ const writeJson = (filePath, content) => {
165
+ hfs.write(filePath, JSON.stringify(content, null, 2));
166
+ log.write(filePath);
150
167
  };
151
168
  exports.writeJson = writeJson;
152
- const readXml = file => {
153
- const xml = hfs.text(file);
169
+ const readXml = filePath => {
170
+ const xml = hfs.text(filePath);
154
171
  const {
155
172
  indent
156
173
  } = (0, _detectIndent.default)(xml);
@@ -163,8 +180,8 @@ const readXml = file => {
163
180
  };
164
181
  };
165
182
  exports.readXml = readXml;
166
- const writeXml = (file, xml, options) => {
167
- const formatted = (0, _xmlFormatter.default)(xml, {
183
+ const writeXml = (filePath, content, options) => {
184
+ const formatted = (0, _xmlFormatter.default)(content, {
168
185
  collapseContent: true,
169
186
  forceSelfClosingEmptyTag: true,
170
187
  indentation: " ",
@@ -172,12 +189,12 @@ const writeXml = (file, xml, options) => {
172
189
  whiteSpaceAtEndOfSelfclosingTag: true,
173
190
  ...options
174
191
  });
175
- hfs.write(file, formatted);
176
- logWrite(file);
192
+ hfs.write(filePath, formatted);
193
+ log.write(filePath);
177
194
  };
178
195
  exports.writeXml = writeXml;
179
- const readHtml = file => {
180
- const html = hfs.text(file);
196
+ const readHtml = filePath => {
197
+ const html = hfs.text(filePath);
181
198
  const {
182
199
  type,
183
200
  amount
@@ -192,34 +209,54 @@ const readHtml = file => {
192
209
  };
193
210
  };
194
211
  exports.readHtml = readHtml;
195
- const writeHtml = async (file, html, options) => {
196
- const formatted = await prettier.format(html, {
212
+ const writeHtml = async (filePath, content, options) => {
213
+ const formatted = await prettier.format(content, {
197
214
  parser: "html",
198
215
  plugins: [htmlPlugin, cssPlugin],
199
216
  tabWidth: 2,
200
217
  useTabs: false,
201
218
  ...options
202
219
  });
203
- hfs.write(file, formatted);
204
- logWrite(file);
220
+ hfs.write(filePath, formatted);
221
+ log.write(filePath);
205
222
  };
206
223
  exports.writeHtml = writeHtml;
207
- const cleanIOSAssets = (dir, prefix) => {
208
- hfs.readDir(dir).filter(file => file.startsWith(prefix) && file.endsWith(".png")).map(file => _path.default.join(dir, file)).forEach(file => hfs.rm(file));
224
+ const cleanIOS = dir => {
225
+ hfs.readDir(dir).filter(file => file === "Colors.xcassets" || file === "Images.xcassets").map(file => _path.default.join(dir, file)).flatMap(dir => hfs.readDir(dir).filter(file => file.startsWith("BootSplash")).map(file => _path.default.join(dir, file))).forEach(file => {
226
+ hfs.rm(file);
227
+ });
209
228
  };
210
- exports.cleanIOSAssets = cleanIOSAssets;
211
- const getIOSAssetFileName = async ({
212
- name,
213
- image,
214
- width
215
- }) => {
229
+ const getImageBase64 = async (image, width) => {
230
+ if (image == null) {
231
+ return "";
232
+ }
216
233
  const buffer = await image.clone().resize(width).png({
217
234
  quality: 100
218
235
  }).toBuffer();
219
- const hash = (0, _hash.default)(buffer.toString("base64"));
220
- return `${name}-${hash}`;
236
+ return buffer.toString("base64");
237
+ };
238
+ const getFileNameSuffix = async ({
239
+ background,
240
+ brand,
241
+ brandWidth,
242
+ darkBackground,
243
+ darkBrand,
244
+ darkLogo,
245
+ logo,
246
+ logoWidth
247
+ }) => {
248
+ const [logoHash, darkLogoHash, brandHash, darkBrandHash] = await Promise.all([getImageBase64(logo, logoWidth), getImageBase64(darkLogo, logoWidth), getImageBase64(brand, brandWidth), getImageBase64(darkBrand, brandWidth)]);
249
+ const record = {
250
+ background: background.hex,
251
+ darkBackground: darkBackground?.hex ?? "",
252
+ logo: logoHash,
253
+ darkLogo: darkLogoHash,
254
+ brand: brandHash,
255
+ darkBrand: darkBrandHash
256
+ };
257
+ const stableKey = Object.keys(record).sort().map(key => record[key]).join();
258
+ return (0, _hash.default)(stableKey);
221
259
  };
222
- exports.getIOSAssetFileName = getIOSAssetFileName;
223
260
  const ensureSupportedFormat = async (name, image) => {
224
261
  if (image == null) {
225
262
  return;
@@ -232,47 +269,87 @@ const ensureSupportedFormat = async (name, image) => {
232
269
  process.exit(1);
233
270
  }
234
271
  };
235
- const getAndroidResPath = (android, {
272
+ const getAndroidOutputPath = ({
273
+ android,
274
+ assetsOutputPath,
236
275
  brandHeight,
237
276
  brandWidth,
238
277
  flavor,
278
+ isExpo,
239
279
  logoHeight,
240
- logoWidth
280
+ logoWidth,
281
+ platforms
241
282
  }) => {
242
- const androidResPath = _path.default.resolve(android.sourceDir, android.appName, "src", flavor, "res");
243
- if (!hfs.exists(androidResPath)) {
244
- log.warn(`No ${_path.default.relative(workingPath, androidResPath)} directory found. Skipping Android assets generation…`);
245
- } else if (logoWidth > 288 || logoHeight > 288) {
246
- log.warn("Logo size exceeding 288x288dp will be cropped by Android. Skipping Android assets generation…");
247
- } else if (brandHeight > 80 || brandWidth > 200) {
248
- log.warn("Brand size exceeding 200x80dp will be cropped by Android. Skipping Android assets generation…");
249
- } else {
250
- if (logoWidth > 192 || logoHeight > 192) {
251
- log.warn(`Logo size exceeds 192x192dp. It might be cropped by Android.`);
252
- }
253
- return androidResPath;
283
+ if (!platforms.includes("android")) {
284
+ return;
285
+ }
286
+ if (isExpo) {
287
+ return _path.default.resolve(assetsOutputPath, "android");
254
288
  }
289
+ if (android == null) {
290
+ return;
291
+ }
292
+ const androidOutputPath = _path.default.resolve(android.sourceDir, android.appName, "src", flavor, "res");
293
+ if (!hfs.exists(androidOutputPath)) {
294
+ return log.warn(`No ${_path.default.relative(workingPath, androidOutputPath)} directory found. Skipping Android assets generation…`);
295
+ }
296
+ if (logoWidth > 288 || logoHeight > 288) {
297
+ return log.warn("Logo size exceeding 288x288dp will be cropped by Android. Skipping Android assets generation…");
298
+ }
299
+ if (brandWidth > 200 || brandHeight > 80) {
300
+ return log.warn("Brand size exceeding 200x80dp will be cropped by Android. Skipping Android assets generation…");
301
+ }
302
+ if (logoWidth > 192 || logoHeight > 192) {
303
+ log.warn("Logo size exceeds 192x192dp. It might be cropped by Android.");
304
+ }
305
+ return androidOutputPath;
255
306
  };
256
- const getIOSProjectPath = ios => {
257
- if (ios.xcodeProject == null) {
258
- log.warn("No Xcode project found. Skipping iOS assets generation…");
307
+ const getIOSOutputPath = ({
308
+ assetsOutputPath,
309
+ ios,
310
+ isExpo,
311
+ platforms
312
+ }) => {
313
+ if (!platforms.includes("ios")) {
259
314
  return;
260
315
  }
261
- const iosProjectPath = _path.default.resolve(ios.sourceDir, ios.xcodeProject.name).replace(/\.(xcodeproj|xcworkspace)$/, "");
262
- if (!hfs.exists(iosProjectPath)) {
263
- log.warn(`No ${_path.default.relative(workingPath, iosProjectPath)} directory found. Skipping iOS assets generation…`);
264
- } else {
265
- return iosProjectPath;
316
+ if (isExpo) {
317
+ return _path.default.resolve(assetsOutputPath, "ios");
318
+ }
319
+ if (ios == null) {
320
+ return;
321
+ }
322
+ if (ios.xcodeProject == null) {
323
+ return log.warn("No Xcode project found. Skipping iOS assets generation…");
266
324
  }
325
+ const iosOutputPath = _path.default.resolve(ios.sourceDir, ios.xcodeProject.name).replace(/\.(xcodeproj|xcworkspace)$/, "");
326
+ if (!hfs.exists(iosOutputPath)) {
327
+ return log.warn(`No ${_path.default.relative(workingPath, iosOutputPath)} directory found. Skipping iOS assets generation…`);
328
+ }
329
+ return iosOutputPath;
267
330
  };
268
- const getHtmlTemplatePath = html => {
331
+ const getHtmlTemplatePath = ({
332
+ html,
333
+ platforms
334
+ }) => {
335
+ if (!platforms.includes("web")) {
336
+ return;
337
+ }
269
338
  const htmlTemplatePath = _path.default.resolve(workingPath, html);
270
339
  if (!hfs.exists(htmlTemplatePath)) {
271
- log.warn(`No ${_path.default.relative(workingPath, htmlTemplatePath)} file found. Skipping HTML + CSS generation…`);
272
- } else {
273
- return htmlTemplatePath;
340
+ return log.warn(`No ${_path.default.relative(workingPath, htmlTemplatePath)} file found. Skipping HTML + CSS generation…`);
274
341
  }
342
+ return htmlTemplatePath;
275
343
  };
344
+ const getImageHeight = (image, width) => {
345
+ if (image == null) {
346
+ return Promise.resolve(0);
347
+ }
348
+ return image.clone().resize(width).toBuffer().then(buffer => (0, _sharp.default)(buffer).metadata()).then(({
349
+ height = 0
350
+ }) => Math.round(height));
351
+ };
352
+ exports.getImageHeight = getImageHeight;
276
353
  const requireAddon = () => {
277
354
  try {
278
355
  return require("./addon"); // eslint-disable-line
@@ -289,9 +366,12 @@ const generate = async ({
289
366
  licenseKey,
290
367
  ...args
291
368
  }) => {
369
+ const isExpo = (0, _config.getConfig)(projectRoot, {
370
+ skipSDKVersionRequirement: true
371
+ }).exp.sdkVersion != null;
292
372
  const [nodeStringVersion = ""] = process.versions.node.split(".");
293
- const nodeVersion = parseInt(nodeStringVersion, 10);
294
- if (!isNaN(nodeVersion) && nodeVersion < 18) {
373
+ const nodeVersion = Number.parseInt(nodeStringVersion, 10);
374
+ if (!Number.isNaN(nodeVersion) && nodeVersion < 18) {
295
375
  log.error("Requires Node 18 (or higher)");
296
376
  process.exit(1);
297
377
  }
@@ -299,7 +379,7 @@ const generate = async ({
299
379
  const darkLogoPath = args.darkLogo != null ? _path.default.resolve(workingPath, args.darkLogo) : undefined;
300
380
  const brandPath = args.brand != null ? _path.default.resolve(workingPath, args.brand) : undefined;
301
381
  const darkBrandPath = args.darkBrand != null ? _path.default.resolve(workingPath, args.darkBrand) : undefined;
302
- const assetsOutputPath = args.assetsOutput != null ? _path.default.resolve(workingPath, args.assetsOutput) : undefined;
382
+ const assetsOutputPath = _path.default.resolve(workingPath, args.assetsOutput);
303
383
  const logo = (0, _sharp.default)(logoPath);
304
384
  const darkLogo = darkLogoPath != null ? (0, _sharp.default)(darkLogoPath) : undefined;
305
385
  const brand = brandPath != null ? (0, _sharp.default)(brandPath) : undefined;
@@ -310,7 +390,7 @@ const generate = async ({
310
390
  const darkBackground = args.darkBackground != null ? parseColor(args.darkBackground) : undefined;
311
391
  const executeAddon = brand != null || darkBackground != null || darkLogo != null || darkBrand != null;
312
392
  if (licenseKey != null && !executeAddon) {
313
- log.warn(`You specified a license key but none of the options that requires it.`);
393
+ log.warn("You specified a license key but none of the options that requires it.");
314
394
  }
315
395
  if (licenseKey == null && executeAddon) {
316
396
  const options = [brand != null ? "brand" : "", darkBackground != null ? "dark-background" : "", darkLogo != null ? "dark-logo" : "", darkBrand != null ? "dark-brand" : ""].filter(option => option !== "").map(option => `--${option}`).join(", ");
@@ -325,49 +405,48 @@ const generate = async ({
325
405
  await ensureSupportedFormat("Dark logo", darkLogo);
326
406
  await ensureSupportedFormat("Brand", brand);
327
407
  await ensureSupportedFormat("Dark brand", darkBrand);
328
- const logoHeight = await logo.clone().resize(logoWidth).toBuffer().then(buffer => (0, _sharp.default)(buffer).metadata()).then(({
329
- height = 0
330
- }) => Math.round(height));
331
- const brandHeight = (await brand?.clone().resize(brandWidth).toBuffer().then(buffer => (0, _sharp.default)(buffer).metadata()).then(({
332
- height = 0
333
- }) => Math.round(height))) ?? 0;
408
+ const logoHeight = await getImageHeight(logo, logoWidth);
409
+ const brandHeight = await getImageHeight(brand, brandWidth);
334
410
  if (logoWidth < args.logoWidth) {
335
411
  log.warn(`Logo width must be a multiple of 2. It has been rounded to ${logoWidth}dp.`);
336
412
  }
337
413
  if (brandWidth < args.brandWidth) {
338
414
  log.warn(`Brand width must be a multiple of 2. It has been rounded to ${brandWidth}dp.`);
339
415
  }
340
- const androidResPath = platforms.includes("android") && android != null ? getAndroidResPath(android, {
416
+ const fileNameSuffix = await getFileNameSuffix({
417
+ background,
418
+ brand,
419
+ brandWidth,
420
+ darkBackground,
421
+ darkBrand,
422
+ darkLogo,
423
+ logo,
424
+ logoWidth
425
+ });
426
+ const androidOutputPath = getAndroidOutputPath({
427
+ android,
428
+ assetsOutputPath,
341
429
  brandHeight,
342
430
  brandWidth,
343
431
  flavor,
432
+ isExpo,
344
433
  logoHeight,
345
- logoWidth
346
- }) : undefined;
347
- const iosProjectPath = platforms.includes("ios") && ios != null ? getIOSProjectPath(ios) : undefined;
348
- const htmlTemplatePath = platforms.includes("web") ? getHtmlTemplatePath(html) : undefined;
349
- if (androidResPath != null) {
434
+ logoWidth,
435
+ platforms
436
+ });
437
+ const iosOutputPath = getIOSOutputPath({
438
+ assetsOutputPath,
439
+ ios,
440
+ isExpo,
441
+ platforms
442
+ });
443
+ const htmlTemplatePath = getHtmlTemplatePath({
444
+ html,
445
+ platforms
446
+ });
447
+ if (androidOutputPath != null) {
350
448
  log.title("🤖", "Android");
351
- const valuesPath = _path.default.resolve(androidResPath, "values");
352
- hfs.ensureDir(valuesPath);
353
- const colorsXmlPath = _path.default.resolve(valuesPath, "colors.xml");
354
- const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
355
- if (hfs.exists(colorsXmlPath)) {
356
- const {
357
- root,
358
- formatOptions
359
- } = readXml(colorsXmlPath);
360
- const nextColor = (0, _nodeHtmlParser.parse)(colorsXmlEntry);
361
- const prevColor = root.querySelector('color[name="bootsplash_background"]');
362
- if (prevColor != null) {
363
- prevColor.replaceWith(nextColor);
364
- } else {
365
- root.querySelector("resources")?.appendChild(nextColor);
366
- }
367
- writeXml(colorsXmlPath, root.toString(), formatOptions);
368
- } else {
369
- writeXml(colorsXmlPath, `<resources>${colorsXmlEntry}</resources>`);
370
- }
449
+ hfs.ensureDir(androidOutputPath);
371
450
  await Promise.all([{
372
451
  ratio: 1,
373
452
  suffix: "mdpi"
@@ -387,7 +466,7 @@ const generate = async ({
387
466
  ratio,
388
467
  suffix
389
468
  }) => {
390
- const drawableDirPath = _path.default.resolve(androidResPath, `drawable-${suffix}`);
469
+ const drawableDirPath = _path.default.resolve(androidOutputPath, `drawable-${suffix}`);
391
470
  hfs.ensureDir(drawableDirPath);
392
471
 
393
472
  // https://developer.android.com/develop/ui/views/launch/splash-screen#dimensions
@@ -413,44 +492,71 @@ const generate = async ({
413
492
  }]).png({
414
493
  quality: 100
415
494
  }).toFile(filePath)).then(() => {
416
- logWrite(filePath, {
495
+ log.write(filePath, {
417
496
  width: canvasSize,
418
497
  height: canvasSize
419
498
  });
420
499
  });
421
500
  }));
501
+ if (!isExpo) {
502
+ const valuesPath = _path.default.resolve(androidOutputPath, "values");
503
+ hfs.ensureDir(valuesPath);
504
+ const colorsXmlPath = _path.default.resolve(valuesPath, "colors.xml");
505
+ const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
506
+ if (hfs.exists(colorsXmlPath)) {
507
+ const {
508
+ root,
509
+ formatOptions
510
+ } = readXml(colorsXmlPath);
511
+ const nextColor = (0, _nodeHtmlParser.parse)(colorsXmlEntry);
512
+ const prevColor = root.querySelector('color[name="bootsplash_background"]');
513
+ if (prevColor != null) {
514
+ prevColor.replaceWith(nextColor);
515
+ } else {
516
+ root.querySelector("resources")?.appendChild(nextColor);
517
+ }
518
+ writeXml(colorsXmlPath, root.toString(), formatOptions);
519
+ } else {
520
+ writeXml(colorsXmlPath, `<resources>${colorsXmlEntry}</resources>`);
521
+ }
522
+ }
422
523
  }
423
- if (iosProjectPath != null) {
524
+ if (iosOutputPath != null) {
424
525
  log.title("🍏", "iOS");
425
- const storyboardPath = _path.default.resolve(iosProjectPath, "BootSplash.storyboard");
526
+ hfs.ensureDir(iosOutputPath);
527
+ cleanIOS(iosOutputPath);
528
+ const storyboardPath = _path.default.resolve(iosOutputPath, "BootSplash.storyboard");
529
+ const colorsSetPath = _path.default.resolve(iosOutputPath, "Colors.xcassets", `BootSplashBackground-${fileNameSuffix}.colorset`);
530
+ const imageSetPath = _path.default.resolve(iosOutputPath, "Images.xcassets", `BootSplashLogo-${fileNameSuffix}.imageset`);
531
+ hfs.ensureDir(colorsSetPath);
532
+ hfs.ensureDir(imageSetPath);
426
533
  writeXml(storyboardPath, getStoryboard({
427
534
  logoHeight,
428
535
  logoWidth,
429
- background: background.rgb
536
+ background: background.rgb,
537
+ fileNameSuffix
430
538
  }), {
431
539
  whiteSpaceAtEndOfSelfclosingTag: false
432
540
  });
433
- addFileToXcodeProject(_path.default.join(_path.default.basename(iosProjectPath), "BootSplash.storyboard"));
434
- const infoPlistPath = _path.default.join(iosProjectPath, "Info.plist");
435
- const infoPlist = _plist.default.parse(hfs.text(infoPlistPath));
436
- infoPlist["UILaunchStoryboardName"] = "BootSplash";
437
- const formatted = (0, _xmlFormatter.default)(_plist.default.build(infoPlist), {
438
- collapseContent: true,
439
- forceSelfClosingEmptyTag: false,
440
- indentation: "\t",
441
- lineSeparator: "\n",
442
- whiteSpaceAtEndOfSelfclosingTag: false
443
- }).replace(/<string\/>/gm, "<string></string>").replace(/^\t/gm, "");
444
- hfs.write(infoPlistPath, formatted);
445
- logWrite(infoPlistPath);
446
- const imageSetPath = _path.default.resolve(iosProjectPath, "Images.xcassets", "BootSplashLogo.imageset");
447
- hfs.ensureDir(imageSetPath);
448
- cleanIOSAssets(imageSetPath, "bootsplash_logo");
449
- const logoFileName = await getIOSAssetFileName({
450
- name: "bootsplash_logo",
451
- image: logo,
452
- width: logoWidth
541
+ writeJson(_path.default.resolve(colorsSetPath, "Contents.json"), {
542
+ colors: [{
543
+ idiom: "universal",
544
+ color: {
545
+ "color-space": "srgb",
546
+ components: {
547
+ blue: background.rgb.B,
548
+ green: background.rgb.G,
549
+ red: background.rgb.R,
550
+ alpha: "1.000"
551
+ }
552
+ }
553
+ }],
554
+ info: {
555
+ author: "xcode",
556
+ version: 1
557
+ }
453
558
  });
559
+ const logoFileName = `logo-${fileNameSuffix}`;
454
560
  writeJson(_path.default.resolve(imageSetPath, "Contents.json"), {
455
561
  images: [{
456
562
  idiom: "universal",
@@ -490,12 +596,44 @@ const generate = async ({
490
596
  width,
491
597
  height
492
598
  }) => {
493
- logWrite(filePath, {
599
+ log.write(filePath, {
494
600
  width,
495
601
  height
496
602
  });
497
603
  });
498
604
  }));
605
+ if (!isExpo) {
606
+ const infoPlistPath = _path.default.resolve(iosOutputPath, "Info.plist");
607
+ const infoPlist = _plist.default.parse(hfs.text(infoPlistPath));
608
+ infoPlist["UILaunchStoryboardName"] = "BootSplash";
609
+ const formatted = (0, _xmlFormatter.default)(_plist.default.build(infoPlist), {
610
+ collapseContent: true,
611
+ forceSelfClosingEmptyTag: false,
612
+ indentation: "\t",
613
+ lineSeparator: "\n",
614
+ whiteSpaceAtEndOfSelfclosingTag: false
615
+ }).replace(/<string\/>/gm, "<string></string>").replace(/^\t/gm, "");
616
+ hfs.write(infoPlistPath, formatted);
617
+ log.write(infoPlistPath);
618
+ const pbxprojectPath = Expo.IOSConfig.Paths.getPBXProjectPath(projectRoot);
619
+ const xcodeProjectPath = Expo.IOSConfig.Paths.getXcodeProjectPath(projectRoot);
620
+ const project = Expo.IOSConfig.XcodeUtils.getPbxproj(projectRoot);
621
+ const projectName = _path.default.basename(iosOutputPath);
622
+ Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
623
+ filepath: _path.default.join(projectName, "BootSplash.storyboard"),
624
+ groupName: _path.default.parse(xcodeProjectPath).name,
625
+ project,
626
+ isBuildFile: true
627
+ });
628
+ Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
629
+ filepath: _path.default.join(projectName, "Colors.xcassets"),
630
+ groupName: _path.default.parse(xcodeProjectPath).name,
631
+ project,
632
+ isBuildFile: true
633
+ });
634
+ hfs.write(pbxprojectPath, project.writeSync());
635
+ log.write(pbxprojectPath);
636
+ }
499
637
  }
500
638
  if (htmlTemplatePath != null) {
501
639
  log.title("🌐", "Web");
@@ -550,55 +688,55 @@ const generate = async ({
550
688
  }
551
689
  await writeHtml(htmlTemplatePath, root.toString(), formatOptions);
552
690
  }
553
- if (assetsOutputPath != null) {
554
- log.title("📄", "Assets");
555
- hfs.ensureDir(assetsOutputPath);
556
- writeJson(_path.default.resolve(assetsOutputPath, "bootsplash_manifest.json"), {
557
- background: background.hex,
558
- logo: {
559
- width: logoWidth,
560
- height: logoHeight
561
- }
562
- });
563
- await Promise.all([{
564
- ratio: 1,
565
- suffix: ""
566
- }, {
567
- ratio: 1.5,
568
- suffix: "@1,5x"
569
- }, {
570
- ratio: 2,
571
- suffix: "@2x"
572
- }, {
573
- ratio: 3,
574
- suffix: "@3x"
575
- }, {
576
- ratio: 4,
577
- suffix: "@4x"
578
- }].map(({
579
- ratio,
580
- suffix
691
+ log.title("📄", "Assets");
692
+ hfs.ensureDir(assetsOutputPath);
693
+ writeJson(_path.default.resolve(assetsOutputPath, "manifest.json"), {
694
+ background: background.hex,
695
+ logo: {
696
+ width: logoWidth,
697
+ height: logoHeight
698
+ }
699
+ });
700
+ await Promise.all([{
701
+ ratio: 1,
702
+ suffix: ""
703
+ }, {
704
+ ratio: 1.5,
705
+ suffix: "@1,5x"
706
+ }, {
707
+ ratio: 2,
708
+ suffix: "@2x"
709
+ }, {
710
+ ratio: 3,
711
+ suffix: "@3x"
712
+ }, {
713
+ ratio: 4,
714
+ suffix: "@4x"
715
+ }].map(({
716
+ ratio,
717
+ suffix
718
+ }) => {
719
+ const filePath = _path.default.resolve(assetsOutputPath, `logo${suffix}.png`);
720
+ return logo.clone().resize(Math.round(logoWidth * ratio)).png({
721
+ quality: 100
722
+ }).toFile(filePath).then(({
723
+ width,
724
+ height
581
725
  }) => {
582
- const filePath = _path.default.resolve(assetsOutputPath, `bootsplash_logo${suffix}.png`);
583
- return logo.clone().resize(Math.round(logoWidth * ratio)).png({
584
- quality: 100
585
- }).toFile(filePath).then(({
726
+ log.write(filePath, {
586
727
  width,
587
728
  height
588
- }) => {
589
- logWrite(filePath, {
590
- width,
591
- height
592
- });
593
729
  });
594
- }));
595
- }
730
+ });
731
+ }));
596
732
  if (licenseKey != null && executeAddon) {
597
733
  const addon = requireAddon();
598
734
  await addon?.execute({
599
735
  licenseKey,
600
- androidResPath,
601
- iosProjectPath,
736
+ isExpo,
737
+ fileNameSuffix,
738
+ androidOutputPath,
739
+ iosOutputPath,
602
740
  htmlTemplatePath,
603
741
  assetsOutputPath,
604
742
  logoHeight,
@@ -617,13 +755,242 @@ const generate = async ({
617
755
  darkBrand
618
756
  });
619
757
  } else {
620
- log.text(`
758
+ console.log(`
621
759
  ${_picocolors.default.blue("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓")}
622
760
  ${_picocolors.default.blue("┃")} 🔑 ${_picocolors.default.bold("Get a license key for brand image / dark mode support")} ${_picocolors.default.blue("┃")}
623
761
  ${_picocolors.default.blue("┃")} ${_picocolors.default.underline("https://zoontek.gumroad.com/l/bootsplash-generator")} ${_picocolors.default.blue("┃")}
624
762
  ${_picocolors.default.blue("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛")}`);
625
763
  }
626
- log.text(`\n💖 Thanks for using ${_picocolors.default.underline("react-native-bootsplash")}`);
764
+ console.log(`\n💖 Thanks for using ${_picocolors.default.underline("react-native-bootsplash")}`);
627
765
  };
628
766
  exports.generate = generate;
767
+ const withAndroidAssets = (config, props) => Expo.withDangerousMod(config, ["android", config => {
768
+ const {
769
+ assetsDir = "assets/bootsplash"
770
+ } = props;
771
+ const {
772
+ platformProjectRoot
773
+ } = config.modRequest;
774
+ const srcDir = _path.default.resolve(workingPath, assetsDir, "android");
775
+ const destDir = _path.default.resolve(platformProjectRoot, "app", "src", "main", "res");
776
+ for (const drawableDir of hfs.readDir(srcDir)) {
777
+ const srcDrawableDir = _path.default.join(srcDir, drawableDir);
778
+ const destDrawableDir = _path.default.join(destDir, drawableDir);
779
+ hfs.ensureDir(destDrawableDir);
780
+ for (const file of hfs.readDir(srcDrawableDir)) {
781
+ hfs.copy(_path.default.join(srcDrawableDir, file), _path.default.join(destDrawableDir, file));
782
+ }
783
+ }
784
+ return config;
785
+ }]);
786
+ const withAndroidManifest = config => Expo.withAndroidManifest(config, config => {
787
+ config.modResults.manifest.application?.forEach(application => {
788
+ if (application.$["android:name"] === ".MainApplication") {
789
+ const {
790
+ activity
791
+ } = application;
792
+ activity?.forEach(activity => {
793
+ if (activity.$["android:name"] === ".MainActivity") {
794
+ activity.$["android:theme"] = "@style/BootTheme";
795
+ }
796
+ });
797
+ }
798
+ });
799
+ return config;
800
+ });
801
+ const withMainActivity = config => Expo.withMainActivity(config, config => {
802
+ const {
803
+ modResults
804
+ } = config;
805
+ const {
806
+ language
807
+ } = modResults;
808
+ const withImports = (0, _codeMod.addImports)(modResults.contents.replace(/(\/\/ )?setTheme\(R\.style\.AppTheme\)/, "// setTheme(R.style.AppTheme)"), ["android.os.Bundle", "com.zoontek.rnbootsplash.RNBootSplash"], language === "java");
809
+
810
+ // indented with 4 spaces
811
+ const withInit = (0, _generateCode.mergeContents)({
812
+ src: withImports,
813
+ comment: " //",
814
+ tag: "bootsplash-init",
815
+ offset: 0,
816
+ anchor: /super\.onCreate\(null\)/,
817
+ newSrc: " RNBootSplash.init(this, R.style.BootTheme)" + (language === "java" ? ";" : "")
818
+ });
819
+ return {
820
+ ...config,
821
+ modResults: {
822
+ ...modResults,
823
+ contents: withInit.contents
824
+ }
825
+ };
826
+ });
827
+ const withAndroidStyles = (config, props) => Expo.withAndroidStyles(config, async config => {
828
+ const {
829
+ assetsDir = "assets/bootsplash",
830
+ edgeToEdge = false
831
+ } = props;
832
+ const manifest = await hfs.json(_path.default.resolve(workingPath, assetsDir, "manifest.json"));
833
+ const item = [{
834
+ $: {
835
+ name: "postBootSplashTheme"
836
+ },
837
+ _: "@style/AppTheme"
838
+ }, {
839
+ $: {
840
+ name: "bootSplashBackground"
841
+ },
842
+ _: "@color/bootsplash_background"
843
+ }, {
844
+ $: {
845
+ name: "bootSplashLogo"
846
+ },
847
+ _: "@drawable/bootsplash_logo"
848
+ }];
849
+ if (manifest.brand != null) {
850
+ item.push({
851
+ $: {
852
+ name: "bootSplashBrand"
853
+ },
854
+ _: "@drawable/bootsplash_brand"
855
+ });
856
+ }
857
+ config.modResults.resources.style?.filter(({
858
+ $
859
+ }) => $.name !== "BootTheme").push({
860
+ item,
861
+ $: {
862
+ name: "BootTheme",
863
+ parent: edgeToEdge ? "Theme.BootSplash" : "Theme.BootSplash.EdgeToEdge"
864
+ }
865
+ });
866
+ return config;
867
+ });
868
+ const withAndroidColors = (config, props) => Expo.withAndroidColors(config, async config => {
869
+ const {
870
+ assetsDir = "assets/bootsplash"
871
+ } = props;
872
+ const manifest = await hfs.json(_path.default.resolve(workingPath, assetsDir, "manifest.json"));
873
+ config.modResults = (0, _Colors.assignColorValue)(config.modResults, {
874
+ name: "bootsplash_background",
875
+ value: manifest.background
876
+ });
877
+ return config;
878
+ });
879
+ const withAndroidColorsNight = (config, props) => Expo.withAndroidColorsNight(config, async config => {
880
+ const {
881
+ assetsDir = "assets/bootsplash"
882
+ } = props;
883
+ const manifest = await hfs.json(_path.default.resolve(workingPath, assetsDir, "manifest.json"));
884
+ if (manifest.darkBackground != null) {
885
+ config.modResults = (0, _Colors.assignColorValue)(config.modResults, {
886
+ name: "bootsplash_background",
887
+ value: manifest.darkBackground
888
+ });
889
+ }
890
+ return config;
891
+ });
892
+ const withIOSAssets = (config, props) => Expo.withDangerousMod(config, ["ios", config => {
893
+ const {
894
+ assetsDir = "assets/bootsplash"
895
+ } = props;
896
+ const {
897
+ platformProjectRoot,
898
+ projectName = ""
899
+ } = config.modRequest;
900
+ const srcDir = _path.default.resolve(workingPath, assetsDir, "ios");
901
+ const destDir = _path.default.resolve(platformProjectRoot, projectName);
902
+ cleanIOS(destDir);
903
+ hfs.copy(_path.default.join(srcDir, "BootSplash.storyboard"), _path.default.join(destDir, "BootSplash.storyboard"));
904
+ for (const xcassetsDir of ["Colors.xcassets", "Images.xcassets"]) {
905
+ const srcXcassetsDir = _path.default.join(srcDir, xcassetsDir);
906
+ const destXcassetsDir = _path.default.join(destDir, xcassetsDir);
907
+ hfs.ensureDir(destXcassetsDir);
908
+ for (const file of hfs.readDir(srcXcassetsDir)) {
909
+ hfs.copy(_path.default.join(srcXcassetsDir, file), _path.default.join(destXcassetsDir, file));
910
+ }
911
+ }
912
+ return config;
913
+ }]);
914
+ const withAppDelegate = config => Expo.withAppDelegate(config, config => {
915
+ const [sdkStringVersion = ""] = config.sdkVersion?.split(".") ?? "";
916
+ const isAtLeastExpo51 = Number.parseInt(sdkStringVersion, 10) >= 51;
917
+ const {
918
+ modResults
919
+ } = config;
920
+ const {
921
+ language
922
+ } = modResults;
923
+ if (language !== "objc" && language !== "objcpp") {
924
+ throw new Error(`Cannot modify the project AppDelegate as it's not in a supported language: ${language}`);
925
+ }
926
+ const withHeader = (0, _generateCode.mergeContents)({
927
+ src: modResults.contents,
928
+ comment: "//",
929
+ tag: "bootsplash-header",
930
+ offset: 1,
931
+ anchor: /#import "AppDelegate\.h"/,
932
+ newSrc: '#import "RNBootSplash.h"'
933
+ });
934
+ const withRootView = (0, _generateCode.mergeContents)({
935
+ src: withHeader.contents,
936
+ comment: "//",
937
+ tag: "bootsplash-init",
938
+ offset: 0,
939
+ anchor: /@end/,
940
+ newSrc: isAtLeastExpo51 ? (0, _tsDedent.dedent)`
941
+ - (void)customizeRootView:(RCTRootView *)rootView {
942
+ [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];
943
+ }
944
+ ` : (0, _tsDedent.dedent)`
945
+ - (UIView *)createRootViewWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initProps:(NSDictionary *)initProps {
946
+ UIView *rootView = [super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
947
+ [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];
948
+ return rootView;
949
+ }
950
+ `
951
+ });
952
+ return {
953
+ ...config,
954
+ modResults: {
955
+ ...modResults,
956
+ contents: withRootView.contents
957
+ }
958
+ };
959
+ });
960
+ const withInfoPlist = config => Expo.withInfoPlist(config, config => {
961
+ config.modResults["UILaunchStoryboardName"] = "BootSplash";
962
+ return config;
963
+ });
964
+ const withXcodeProject = config => Expo.withXcodeProject(config, config => {
965
+ const {
966
+ projectName = ""
967
+ } = config.modRequest;
968
+ Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
969
+ filepath: _path.default.join(projectName, "BootSplash.storyboard"),
970
+ groupName: projectName,
971
+ project: config.modResults,
972
+ isBuildFile: true
973
+ });
974
+ Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
975
+ filepath: _path.default.join(projectName, "Colors.xcassets"),
976
+ groupName: projectName,
977
+ project: config.modResults,
978
+ isBuildFile: true
979
+ });
980
+ return config;
981
+ });
982
+ const withGenerate = (config, props = {}) => {
983
+ const plugins = [];
984
+ const {
985
+ platforms = []
986
+ } = config;
987
+ if (platforms.includes("android")) {
988
+ plugins.push(withAndroidAssets, withAndroidManifest, withMainActivity, withAndroidStyles, withAndroidColors, withAndroidColorsNight);
989
+ }
990
+ if (platforms.includes("ios")) {
991
+ plugins.push(withIOSAssets, withAppDelegate, withInfoPlist, withXcodeProject);
992
+ }
993
+ return Expo.withPlugins(config, plugins.map(plugin => [plugin, props]));
994
+ };
995
+ exports.withGenerate = withGenerate;
629
996
  //# sourceMappingURL=generate.js.map