react-native-bootsplash 6.0.0-beta.0 → 6.0.0-beta.10
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.
- package/README.md +33 -88
- package/android/src/main/res/values/public.xml +1 -0
- package/android/src/main/res/values/styles.xml +9 -6
- package/android/src/main/res/values-night/styles.xml +1 -1
- package/android/src/main/res/values-v23/styles.xml +6 -1
- package/android/src/main/res/values-v27/styles.xml +1 -1
- package/android/src/main/res/values-v29/styles.xml +1 -1
- package/android/src/main/res/values-v30/styles.xml +1 -1
- package/app.plugin.js +2 -2
- package/dist/commonjs/addon/index.js +43 -38
- package/dist/commonjs/addon/index.js.map +1 -1
- package/dist/commonjs/expo.js +283 -0
- package/dist/commonjs/expo.js.map +1 -0
- package/dist/commonjs/generate.js +165 -323
- package/dist/commonjs/generate.js.map +1 -1
- package/dist/commonjs/index.js +3 -3
- package/dist/commonjs/index.js.map +1 -1
- package/dist/module/addon/index.js +43 -38
- package/dist/module/addon/index.js.map +1 -1
- package/dist/module/expo.js +273 -0
- package/dist/module/expo.js.map +1 -0
- package/dist/module/generate.js +162 -317
- package/dist/module/generate.js.map +1 -1
- package/dist/module/index.js +2 -2
- package/dist/module/index.js.map +1 -1
- package/dist/typescript/addon/index.d.ts.map +1 -1
- package/dist/typescript/expo.d.ts +11 -0
- package/dist/typescript/expo.d.ts.map +1 -0
- package/dist/typescript/generate.d.ts +27 -21
- package/dist/typescript/generate.d.ts.map +1 -1
- package/dist/typescript/index.d.ts +22 -4
- package/dist/typescript/index.d.ts.map +1 -1
- package/ios/RNBootSplash.mm +33 -37
- package/package.json +8 -8
- package/src/expo.ts +368 -0
- package/src/generate.ts +235 -403
- package/src/index.ts +32 -10
package/dist/module/generate.js
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
|
-
import murmurhash from "@emotion/hash";
|
|
2
|
-
import { getConfig as getExpoConfig } from "@expo/config";
|
|
3
1
|
import * as Expo from "@expo/config-plugins";
|
|
4
|
-
import { assignColorValue } from "@expo/config-plugins/build/android/Colors";
|
|
5
|
-
import { addImports } from "@expo/config-plugins/build/android/codeMod";
|
|
6
|
-
import { mergeContents } from "@expo/config-plugins/build/utils/generateCode";
|
|
7
2
|
import plist from "@expo/plist";
|
|
8
3
|
import { findProjectRoot } from "@react-native-community/cli-tools";
|
|
4
|
+
import childProcess from "child_process";
|
|
5
|
+
import crypto from "crypto";
|
|
9
6
|
import detectIndent from "detect-indent";
|
|
10
7
|
import fs from "fs-extra";
|
|
11
|
-
import { parse as parseHtml } from "node-html-parser";
|
|
8
|
+
import { HTMLElement, parse as parseHtml } from "node-html-parser";
|
|
12
9
|
import path from "path";
|
|
13
10
|
import pc from "picocolors";
|
|
14
11
|
import * as htmlPlugin from "prettier/plugins/html";
|
|
15
12
|
import * as cssPlugin from "prettier/plugins/postcss";
|
|
16
13
|
import * as prettier from "prettier/standalone";
|
|
14
|
+
import semver from "semver";
|
|
17
15
|
import sharp from "sharp";
|
|
18
16
|
import { dedent } from "ts-dedent";
|
|
17
|
+
import util from "util";
|
|
19
18
|
import formatXml from "xml-formatter";
|
|
20
19
|
const workingPath = process.env.INIT_CWD ?? process.env.PWD ?? process.cwd();
|
|
21
20
|
const projectRoot = findProjectRoot(workingPath);
|
|
21
|
+
const promisifiedExec = util.promisify(childProcess.exec);
|
|
22
|
+
const exec = cmd => promisifiedExec(cmd).then(({
|
|
23
|
+
stdout,
|
|
24
|
+
stderr
|
|
25
|
+
}) => stdout || stderr);
|
|
22
26
|
export const log = {
|
|
23
27
|
error: text => {
|
|
24
28
|
console.log(pc.red(`❌ ${text}`));
|
|
@@ -33,7 +37,7 @@ export const log = {
|
|
|
33
37
|
console.log(` ${path.relative(workingPath, filePath)}` + (dimensions != null ? ` (${dimensions.width}x${dimensions.height})` : ""));
|
|
34
38
|
}
|
|
35
39
|
};
|
|
36
|
-
|
|
40
|
+
const parseColor = value => {
|
|
37
41
|
const up = value.toUpperCase().replace(/[^0-9A-F]/g, "");
|
|
38
42
|
if (up.length !== 3 && up.length !== 6) {
|
|
39
43
|
log.error(`"${value}" value is not a valid hexadecimal color.`);
|
|
@@ -151,62 +155,76 @@ export const hfs = {
|
|
|
151
155
|
fs.writeFileSync(path, trimmed === "" ? trimmed : trimmed + "\n", "utf-8");
|
|
152
156
|
}
|
|
153
157
|
};
|
|
158
|
+
export const getExpoConfig = projectRoot => {
|
|
159
|
+
try {
|
|
160
|
+
const pkg = hfs.json(path.resolve(projectRoot, "node_modules", "expo", "package.json"));
|
|
161
|
+
const version = pkg.version;
|
|
162
|
+
if (version == null || semver.lt(version, "51.0.20")) {
|
|
163
|
+
log.error("Requires Expo 51.0.20 (or higher)");
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
isExpo: true
|
|
168
|
+
};
|
|
169
|
+
} catch {
|
|
170
|
+
return {
|
|
171
|
+
isExpo: false
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
};
|
|
154
175
|
export const writeJson = (filePath, content) => {
|
|
155
176
|
hfs.write(filePath, JSON.stringify(content, null, 2));
|
|
156
177
|
log.write(filePath);
|
|
157
178
|
};
|
|
158
|
-
export const
|
|
159
|
-
const
|
|
160
|
-
const {
|
|
161
|
-
indent
|
|
162
|
-
} = detectIndent(xml);
|
|
163
|
-
const formatOptions = {
|
|
164
|
-
indentation: indent || " "
|
|
165
|
-
};
|
|
166
|
-
return {
|
|
167
|
-
root: parseHtml(xml),
|
|
168
|
-
formatOptions
|
|
169
|
-
};
|
|
170
|
-
};
|
|
171
|
-
export const writeXml = (filePath, content, options) => {
|
|
172
|
-
const formatted = formatXml(content, {
|
|
173
|
-
collapseContent: true,
|
|
174
|
-
forceSelfClosingEmptyTag: true,
|
|
175
|
-
indentation: " ",
|
|
176
|
-
lineSeparator: "\n",
|
|
177
|
-
whiteSpaceAtEndOfSelfclosingTag: true,
|
|
178
|
-
...options
|
|
179
|
-
});
|
|
180
|
-
hfs.write(filePath, formatted);
|
|
181
|
-
log.write(filePath);
|
|
182
|
-
};
|
|
183
|
-
export const readHtml = filePath => {
|
|
184
|
-
const html = hfs.text(filePath);
|
|
185
|
-
const {
|
|
186
|
-
type,
|
|
187
|
-
amount
|
|
188
|
-
} = detectIndent(html);
|
|
189
|
-
const formatOptions = {
|
|
190
|
-
useTabs: type === "tab",
|
|
191
|
-
tabWidth: amount || 2
|
|
192
|
-
};
|
|
179
|
+
export const readXmlLike = filePath => {
|
|
180
|
+
const content = hfs.text(filePath);
|
|
193
181
|
return {
|
|
194
|
-
root: parseHtml(
|
|
195
|
-
formatOptions
|
|
182
|
+
root: parseHtml(content),
|
|
183
|
+
formatOptions: {
|
|
184
|
+
indent: detectIndent(content)
|
|
185
|
+
}
|
|
196
186
|
};
|
|
197
187
|
};
|
|
198
|
-
export const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
188
|
+
export const writeXmlLike = async (filePath, content, {
|
|
189
|
+
indent,
|
|
190
|
+
...formatOptions
|
|
191
|
+
}) => {
|
|
192
|
+
if (formatOptions.formatter === "prettier") {
|
|
193
|
+
const {
|
|
194
|
+
formatter,
|
|
195
|
+
useCssPlugin = false,
|
|
196
|
+
selfClosingTags = false,
|
|
197
|
+
...options
|
|
198
|
+
} = formatOptions;
|
|
199
|
+
const formatted = await prettier.format(content, {
|
|
200
|
+
parser: "html",
|
|
201
|
+
bracketSameLine: true,
|
|
202
|
+
printWidth: 10000,
|
|
203
|
+
plugins: [htmlPlugin, ...(useCssPlugin ? [cssPlugin] : [])],
|
|
204
|
+
useTabs: indent?.type === "tab",
|
|
205
|
+
tabWidth: (indent?.amount ?? 0) || 2,
|
|
206
|
+
...options
|
|
207
|
+
});
|
|
208
|
+
hfs.write(filePath, selfClosingTags ? formatted.replace(/><\/[a-z-0-9]+>/gi, " />") : formatted);
|
|
209
|
+
log.write(filePath);
|
|
210
|
+
} else {
|
|
211
|
+
const {
|
|
212
|
+
formatter,
|
|
213
|
+
...options
|
|
214
|
+
} = formatOptions;
|
|
215
|
+
const formatted = formatXml(content, {
|
|
216
|
+
collapseContent: true,
|
|
217
|
+
forceSelfClosingEmptyTag: true,
|
|
218
|
+
lineSeparator: "\n",
|
|
219
|
+
whiteSpaceAtEndOfSelfclosingTag: true,
|
|
220
|
+
indentation: (indent?.indent ?? "") || " ",
|
|
221
|
+
...options
|
|
222
|
+
});
|
|
223
|
+
hfs.write(filePath, formatted);
|
|
224
|
+
log.write(filePath);
|
|
225
|
+
}
|
|
208
226
|
};
|
|
209
|
-
const
|
|
227
|
+
export const cleanIOSAssets = dir => {
|
|
210
228
|
hfs.readDir(dir).filter(file => file === "Colors.xcassets" || file === "Images.xcassets").map(file => path.join(dir, file)).flatMap(dir => hfs.readDir(dir).filter(file => file.startsWith("BootSplash")).map(file => path.join(dir, file))).forEach(file => {
|
|
211
229
|
hfs.rm(file);
|
|
212
230
|
});
|
|
@@ -240,7 +258,9 @@ const getFileNameSuffix = async ({
|
|
|
240
258
|
darkBrand: darkBrandHash
|
|
241
259
|
};
|
|
242
260
|
const stableKey = Object.keys(record).sort().map(key => record[key]).join();
|
|
243
|
-
return
|
|
261
|
+
return crypto.createHash("shake256", {
|
|
262
|
+
outputLength: 3
|
|
263
|
+
}).update(stableKey).digest("hex").toLowerCase();
|
|
244
264
|
};
|
|
245
265
|
const ensureSupportedFormat = async (name, image) => {
|
|
246
266
|
if (image == null) {
|
|
@@ -290,8 +310,8 @@ const getAndroidOutputPath = ({
|
|
|
290
310
|
return androidOutputPath;
|
|
291
311
|
};
|
|
292
312
|
const getIOSOutputPath = ({
|
|
293
|
-
assetsOutputPath,
|
|
294
313
|
ios,
|
|
314
|
+
assetsOutputPath,
|
|
295
315
|
isExpo,
|
|
296
316
|
platforms
|
|
297
317
|
}) => {
|
|
@@ -313,20 +333,30 @@ const getIOSOutputPath = ({
|
|
|
313
333
|
}
|
|
314
334
|
return iosOutputPath;
|
|
315
335
|
};
|
|
316
|
-
const getHtmlTemplatePath = ({
|
|
336
|
+
const getHtmlTemplatePath = async ({
|
|
337
|
+
isExpo,
|
|
317
338
|
html,
|
|
318
339
|
platforms
|
|
319
340
|
}) => {
|
|
320
341
|
if (!platforms.includes("web")) {
|
|
321
342
|
return;
|
|
322
343
|
}
|
|
344
|
+
if (isExpo) {
|
|
345
|
+
const htmlTemplatePath = path.resolve(workingPath, html);
|
|
346
|
+
const htmlTemplateRelativePath = path.relative(workingPath, htmlTemplatePath);
|
|
347
|
+
if (htmlTemplateRelativePath === "public/index.html" && !hfs.exists(htmlTemplatePath)) {
|
|
348
|
+
const cmd = `npx expo customize ${htmlTemplateRelativePath}`;
|
|
349
|
+
console.log(pc.dim(`Running ${cmd}`));
|
|
350
|
+
await exec(cmd);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
323
353
|
const htmlTemplatePath = path.resolve(workingPath, html);
|
|
324
354
|
if (!hfs.exists(htmlTemplatePath)) {
|
|
325
355
|
return log.warn(`No ${path.relative(workingPath, htmlTemplatePath)} file found. Skipping HTML + CSS generation…`);
|
|
326
356
|
}
|
|
327
357
|
return htmlTemplatePath;
|
|
328
358
|
};
|
|
329
|
-
|
|
359
|
+
const getImageHeight = (image, width) => {
|
|
330
360
|
if (image == null) {
|
|
331
361
|
return Promise.resolve(0);
|
|
332
362
|
}
|
|
@@ -350,12 +380,10 @@ export const generate = async ({
|
|
|
350
380
|
licenseKey,
|
|
351
381
|
...args
|
|
352
382
|
}) => {
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const nodeVersion = Number.parseInt(nodeStringVersion, 10);
|
|
358
|
-
if (!Number.isNaN(nodeVersion) && nodeVersion < 18) {
|
|
383
|
+
const {
|
|
384
|
+
isExpo
|
|
385
|
+
} = getExpoConfig(workingPath);
|
|
386
|
+
if (semver.lt(process.versions.node, "18.0.0")) {
|
|
359
387
|
log.error("Requires Node 18 (or higher)");
|
|
360
388
|
process.exit(1);
|
|
361
389
|
}
|
|
@@ -424,7 +452,8 @@ export const generate = async ({
|
|
|
424
452
|
isExpo,
|
|
425
453
|
platforms
|
|
426
454
|
});
|
|
427
|
-
const htmlTemplatePath = getHtmlTemplatePath({
|
|
455
|
+
const htmlTemplatePath = await getHtmlTemplatePath({
|
|
456
|
+
isExpo,
|
|
428
457
|
html,
|
|
429
458
|
platforms
|
|
430
459
|
});
|
|
@@ -483,43 +512,85 @@ export const generate = async ({
|
|
|
483
512
|
});
|
|
484
513
|
}));
|
|
485
514
|
if (!isExpo) {
|
|
515
|
+
const manifestXmlPath = path.resolve(androidOutputPath, "..", "AndroidManifest.xml");
|
|
516
|
+
const manifestXml = readXmlLike(manifestXmlPath);
|
|
517
|
+
const activities = manifestXml.root.querySelectorAll("activity");
|
|
518
|
+
for (const activity of activities) {
|
|
519
|
+
if (activity.getAttribute("android:name") === ".MainActivity") {
|
|
520
|
+
activity.setAttribute("android:theme", "@style/BootTheme");
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
await writeXmlLike(manifestXmlPath, manifestXml.root.toString(), {
|
|
524
|
+
...manifestXml.formatOptions,
|
|
525
|
+
formatter: "prettier",
|
|
526
|
+
htmlWhitespaceSensitivity: "ignore",
|
|
527
|
+
selfClosingTags: true,
|
|
528
|
+
singleAttributePerLine: true
|
|
529
|
+
});
|
|
486
530
|
const valuesPath = path.resolve(androidOutputPath, "values");
|
|
487
531
|
hfs.ensureDir(valuesPath);
|
|
488
532
|
const colorsXmlPath = path.resolve(valuesPath, "colors.xml");
|
|
489
533
|
const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
|
|
490
534
|
if (hfs.exists(colorsXmlPath)) {
|
|
491
|
-
const
|
|
492
|
-
root,
|
|
493
|
-
formatOptions
|
|
494
|
-
} = readXml(colorsXmlPath);
|
|
535
|
+
const colorsXml = readXmlLike(colorsXmlPath);
|
|
495
536
|
const nextColor = parseHtml(colorsXmlEntry);
|
|
496
|
-
const prevColor = root.querySelector('color[name="bootsplash_background"]');
|
|
537
|
+
const prevColor = colorsXml.root.querySelector('color[name="bootsplash_background"]');
|
|
497
538
|
if (prevColor != null) {
|
|
498
539
|
prevColor.replaceWith(nextColor);
|
|
499
540
|
} else {
|
|
500
|
-
root.querySelector("resources")?.appendChild(nextColor);
|
|
541
|
+
colorsXml.root.querySelector("resources")?.appendChild(nextColor);
|
|
501
542
|
}
|
|
502
|
-
|
|
543
|
+
await writeXmlLike(colorsXmlPath, colorsXml.root.toString(), {
|
|
544
|
+
...colorsXml.formatOptions,
|
|
545
|
+
formatter: "xmlFormatter"
|
|
546
|
+
});
|
|
503
547
|
} else {
|
|
504
|
-
|
|
548
|
+
await writeXmlLike(colorsXmlPath, `<resources>${colorsXmlEntry}</resources>`, {
|
|
549
|
+
formatter: "xmlFormatter"
|
|
550
|
+
});
|
|
505
551
|
}
|
|
552
|
+
const stylesXmlPath = path.resolve(valuesPath, "styles.xml");
|
|
553
|
+
const stylesXml = readXmlLike(stylesXmlPath);
|
|
554
|
+
const prevStyle = stylesXml.root.querySelector('style[name="BootTheme"]');
|
|
555
|
+
const parent = prevStyle?.getAttribute("parent") ?? "Theme.BootSplash";
|
|
556
|
+
const extraItems = parseHtml(prevStyle?.text.split("\n").map(line => line.trim()).join("") ?? "").childNodes.filter(node => {
|
|
557
|
+
if (!(node instanceof HTMLElement)) {
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
const name = node.getAttribute("name");
|
|
561
|
+
return name !== "bootSplashBackground" && name !== "bootSplashLogo" && name !== "bootSplashBrand" && name !== "postBootSplashTheme";
|
|
562
|
+
}).map(node => node.toString());
|
|
563
|
+
const styleItems = [...(extraItems.length > 0 ? [...extraItems, ""] : []), '<item name="bootSplashBackground">@color/bootsplash_background</item>', '<item name="bootSplashLogo">@drawable/bootsplash_logo</item>', ...(brand != null && brandPath != null ? ['<item name="bootSplashBrand">@drawable/bootsplash_brand</item>'] : []), '<item name="postBootSplashTheme">@style/AppTheme</item>'];
|
|
564
|
+
const nextStyle = parseHtml(dedent`
|
|
565
|
+
<style name="BootTheme" parent="${parent}">
|
|
566
|
+
${styleItems.join("\n")}
|
|
567
|
+
</style>
|
|
568
|
+
`);
|
|
569
|
+
prevStyle?.remove(); // remove the existing style
|
|
570
|
+
stylesXml.root.querySelector("resources")?.appendChild(nextStyle);
|
|
571
|
+
await writeXmlLike(stylesXmlPath, stylesXml.root.toString(), {
|
|
572
|
+
...stylesXml.formatOptions,
|
|
573
|
+
formatter: "prettier",
|
|
574
|
+
htmlWhitespaceSensitivity: "ignore"
|
|
575
|
+
});
|
|
506
576
|
}
|
|
507
577
|
}
|
|
508
578
|
if (iosOutputPath != null) {
|
|
509
579
|
log.title("🍏", "iOS");
|
|
510
580
|
hfs.ensureDir(iosOutputPath);
|
|
511
|
-
|
|
581
|
+
cleanIOSAssets(iosOutputPath);
|
|
512
582
|
const storyboardPath = path.resolve(iosOutputPath, "BootSplash.storyboard");
|
|
513
583
|
const colorsSetPath = path.resolve(iosOutputPath, "Colors.xcassets", `BootSplashBackground-${fileNameSuffix}.colorset`);
|
|
514
584
|
const imageSetPath = path.resolve(iosOutputPath, "Images.xcassets", `BootSplashLogo-${fileNameSuffix}.imageset`);
|
|
515
585
|
hfs.ensureDir(colorsSetPath);
|
|
516
586
|
hfs.ensureDir(imageSetPath);
|
|
517
|
-
|
|
587
|
+
await writeXmlLike(storyboardPath, getStoryboard({
|
|
518
588
|
logoHeight,
|
|
519
589
|
logoWidth,
|
|
520
590
|
background: background.rgb,
|
|
521
591
|
fileNameSuffix
|
|
522
592
|
}), {
|
|
593
|
+
formatter: "xmlFormatter",
|
|
523
594
|
whiteSpaceAtEndOfSelfclosingTag: false
|
|
524
595
|
});
|
|
525
596
|
writeJson(path.resolve(colorsSetPath, "Contents.json"), {
|
|
@@ -603,16 +674,17 @@ export const generate = async ({
|
|
|
603
674
|
const xcodeProjectPath = Expo.IOSConfig.Paths.getXcodeProjectPath(projectRoot);
|
|
604
675
|
const project = Expo.IOSConfig.XcodeUtils.getPbxproj(projectRoot);
|
|
605
676
|
const projectName = path.basename(iosOutputPath);
|
|
677
|
+
const groupName = path.parse(xcodeProjectPath).name;
|
|
606
678
|
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
607
|
-
filepath: path.join(projectName, "BootSplash.storyboard"),
|
|
608
|
-
groupName: path.parse(xcodeProjectPath).name,
|
|
609
679
|
project,
|
|
680
|
+
filepath: path.join(projectName, "BootSplash.storyboard"),
|
|
681
|
+
groupName,
|
|
610
682
|
isBuildFile: true
|
|
611
683
|
});
|
|
612
684
|
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
613
|
-
filepath: path.join(projectName, "Colors.xcassets"),
|
|
614
|
-
groupName: path.parse(xcodeProjectPath).name,
|
|
615
685
|
project,
|
|
686
|
+
filepath: path.join(projectName, "Colors.xcassets"),
|
|
687
|
+
groupName,
|
|
616
688
|
isBuildFile: true
|
|
617
689
|
});
|
|
618
690
|
hfs.write(pbxprojectPath, project.writeSync());
|
|
@@ -621,14 +693,11 @@ export const generate = async ({
|
|
|
621
693
|
}
|
|
622
694
|
if (htmlTemplatePath != null) {
|
|
623
695
|
log.title("🌐", "Web");
|
|
624
|
-
const
|
|
625
|
-
root,
|
|
626
|
-
formatOptions
|
|
627
|
-
} = readHtml(htmlTemplatePath);
|
|
696
|
+
const htmlTemplate = readXmlLike(htmlTemplatePath);
|
|
628
697
|
const {
|
|
629
698
|
format
|
|
630
699
|
} = await logo.metadata();
|
|
631
|
-
const prevStyle = root.querySelector("#bootsplash-style");
|
|
700
|
+
const prevStyle = htmlTemplate.root.querySelector("#bootsplash-style");
|
|
632
701
|
const base64 = (format === "svg" ? hfs.buffer(logoPath) : await logo.clone().resize(Math.round(logoWidth * 2)).png({
|
|
633
702
|
quality: 100
|
|
634
703
|
}).toBuffer()).toString("base64");
|
|
@@ -657,9 +726,9 @@ export const generate = async ({
|
|
|
657
726
|
if (prevStyle != null) {
|
|
658
727
|
prevStyle.replaceWith(nextStyle);
|
|
659
728
|
} else {
|
|
660
|
-
root.querySelector("head")?.appendChild(nextStyle);
|
|
729
|
+
htmlTemplate.root.querySelector("head")?.appendChild(nextStyle);
|
|
661
730
|
}
|
|
662
|
-
const prevDiv = root.querySelector("#bootsplash");
|
|
731
|
+
const prevDiv = htmlTemplate.root.querySelector("#bootsplash");
|
|
663
732
|
const nextDiv = parseHtml(dedent`
|
|
664
733
|
<div id="bootsplash">
|
|
665
734
|
<div id="bootsplash-logo"></div>
|
|
@@ -668,9 +737,13 @@ export const generate = async ({
|
|
|
668
737
|
if (prevDiv != null) {
|
|
669
738
|
prevDiv.replaceWith(nextDiv);
|
|
670
739
|
} else {
|
|
671
|
-
root.querySelector("body")?.appendChild(nextDiv);
|
|
740
|
+
htmlTemplate.root.querySelector("body")?.appendChild(nextDiv);
|
|
672
741
|
}
|
|
673
|
-
await
|
|
742
|
+
await writeXmlLike(htmlTemplatePath, htmlTemplate.root.toString(), {
|
|
743
|
+
...htmlTemplate.formatOptions,
|
|
744
|
+
formatter: "prettier",
|
|
745
|
+
useCssPlugin: true
|
|
746
|
+
});
|
|
674
747
|
}
|
|
675
748
|
log.title("📄", "Assets");
|
|
676
749
|
hfs.ensureDir(assetsOutputPath);
|
|
@@ -747,232 +820,4 @@ ${pc.blue("┗━━━━━━━━━━━━━━━━━━━━━━
|
|
|
747
820
|
}
|
|
748
821
|
console.log(`\n💖 Thanks for using ${pc.underline("react-native-bootsplash")}`);
|
|
749
822
|
};
|
|
750
|
-
const withAndroidAssets = (config, props) => Expo.withDangerousMod(config, ["android", config => {
|
|
751
|
-
const {
|
|
752
|
-
assetsDir = "assets/bootsplash"
|
|
753
|
-
} = props;
|
|
754
|
-
const {
|
|
755
|
-
platformProjectRoot
|
|
756
|
-
} = config.modRequest;
|
|
757
|
-
const srcDir = path.resolve(workingPath, assetsDir, "android");
|
|
758
|
-
const destDir = path.resolve(platformProjectRoot, "app", "src", "main", "res");
|
|
759
|
-
for (const drawableDir of hfs.readDir(srcDir)) {
|
|
760
|
-
const srcDrawableDir = path.join(srcDir, drawableDir);
|
|
761
|
-
const destDrawableDir = path.join(destDir, drawableDir);
|
|
762
|
-
hfs.ensureDir(destDrawableDir);
|
|
763
|
-
for (const file of hfs.readDir(srcDrawableDir)) {
|
|
764
|
-
hfs.copy(path.join(srcDrawableDir, file), path.join(destDrawableDir, file));
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
return config;
|
|
768
|
-
}]);
|
|
769
|
-
const withAndroidManifest = config => Expo.withAndroidManifest(config, config => {
|
|
770
|
-
config.modResults.manifest.application?.forEach(application => {
|
|
771
|
-
if (application.$["android:name"] === ".MainApplication") {
|
|
772
|
-
const {
|
|
773
|
-
activity
|
|
774
|
-
} = application;
|
|
775
|
-
activity?.forEach(activity => {
|
|
776
|
-
if (activity.$["android:name"] === ".MainActivity") {
|
|
777
|
-
activity.$["android:theme"] = "@style/BootTheme";
|
|
778
|
-
}
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
});
|
|
782
|
-
return config;
|
|
783
|
-
});
|
|
784
|
-
const withMainActivity = config => Expo.withMainActivity(config, config => {
|
|
785
|
-
const {
|
|
786
|
-
modResults
|
|
787
|
-
} = config;
|
|
788
|
-
const {
|
|
789
|
-
language
|
|
790
|
-
} = modResults;
|
|
791
|
-
const withImports = addImports(modResults.contents.replace(/(\/\/ )?setTheme\(R\.style\.AppTheme\)/, "// setTheme(R.style.AppTheme)"), ["android.os.Bundle", "com.zoontek.rnbootsplash.RNBootSplash"], language === "java");
|
|
792
|
-
|
|
793
|
-
// indented with 4 spaces
|
|
794
|
-
const withInit = mergeContents({
|
|
795
|
-
src: withImports,
|
|
796
|
-
comment: " //",
|
|
797
|
-
tag: "bootsplash-init",
|
|
798
|
-
offset: 0,
|
|
799
|
-
anchor: /super\.onCreate\(null\)/,
|
|
800
|
-
newSrc: " RNBootSplash.init(this, R.style.BootTheme)" + (language === "java" ? ";" : "")
|
|
801
|
-
});
|
|
802
|
-
return {
|
|
803
|
-
...config,
|
|
804
|
-
modResults: {
|
|
805
|
-
...modResults,
|
|
806
|
-
contents: withInit.contents
|
|
807
|
-
}
|
|
808
|
-
};
|
|
809
|
-
});
|
|
810
|
-
const withAndroidStyles = (config, props) => Expo.withAndroidStyles(config, async config => {
|
|
811
|
-
const {
|
|
812
|
-
assetsDir = "assets/bootsplash",
|
|
813
|
-
edgeToEdge = false
|
|
814
|
-
} = props;
|
|
815
|
-
const manifest = await hfs.json(path.resolve(workingPath, assetsDir, "manifest.json"));
|
|
816
|
-
const item = [{
|
|
817
|
-
$: {
|
|
818
|
-
name: "postBootSplashTheme"
|
|
819
|
-
},
|
|
820
|
-
_: "@style/AppTheme"
|
|
821
|
-
}, {
|
|
822
|
-
$: {
|
|
823
|
-
name: "bootSplashBackground"
|
|
824
|
-
},
|
|
825
|
-
_: "@color/bootsplash_background"
|
|
826
|
-
}, {
|
|
827
|
-
$: {
|
|
828
|
-
name: "bootSplashLogo"
|
|
829
|
-
},
|
|
830
|
-
_: "@drawable/bootsplash_logo"
|
|
831
|
-
}];
|
|
832
|
-
if (manifest.brand != null) {
|
|
833
|
-
item.push({
|
|
834
|
-
$: {
|
|
835
|
-
name: "bootSplashBrand"
|
|
836
|
-
},
|
|
837
|
-
_: "@drawable/bootsplash_brand"
|
|
838
|
-
});
|
|
839
|
-
}
|
|
840
|
-
config.modResults.resources.style?.filter(({
|
|
841
|
-
$
|
|
842
|
-
}) => $.name !== "BootTheme").push({
|
|
843
|
-
item,
|
|
844
|
-
$: {
|
|
845
|
-
name: "BootTheme",
|
|
846
|
-
parent: edgeToEdge ? "Theme.BootSplash" : "Theme.BootSplash.EdgeToEdge"
|
|
847
|
-
}
|
|
848
|
-
});
|
|
849
|
-
return config;
|
|
850
|
-
});
|
|
851
|
-
const withAndroidColors = (config, props) => Expo.withAndroidColors(config, async config => {
|
|
852
|
-
const {
|
|
853
|
-
assetsDir = "assets/bootsplash"
|
|
854
|
-
} = props;
|
|
855
|
-
const manifest = await hfs.json(path.resolve(workingPath, assetsDir, "manifest.json"));
|
|
856
|
-
config.modResults = assignColorValue(config.modResults, {
|
|
857
|
-
name: "bootsplash_background",
|
|
858
|
-
value: manifest.background
|
|
859
|
-
});
|
|
860
|
-
return config;
|
|
861
|
-
});
|
|
862
|
-
const withAndroidColorsNight = (config, props) => Expo.withAndroidColorsNight(config, async config => {
|
|
863
|
-
const {
|
|
864
|
-
assetsDir = "assets/bootsplash"
|
|
865
|
-
} = props;
|
|
866
|
-
const manifest = await hfs.json(path.resolve(workingPath, assetsDir, "manifest.json"));
|
|
867
|
-
if (manifest.darkBackground != null) {
|
|
868
|
-
config.modResults = assignColorValue(config.modResults, {
|
|
869
|
-
name: "bootsplash_background",
|
|
870
|
-
value: manifest.darkBackground
|
|
871
|
-
});
|
|
872
|
-
}
|
|
873
|
-
return config;
|
|
874
|
-
});
|
|
875
|
-
const withIOSAssets = (config, props) => Expo.withDangerousMod(config, ["ios", config => {
|
|
876
|
-
const {
|
|
877
|
-
assetsDir = "assets/bootsplash"
|
|
878
|
-
} = props;
|
|
879
|
-
const {
|
|
880
|
-
platformProjectRoot,
|
|
881
|
-
projectName = ""
|
|
882
|
-
} = config.modRequest;
|
|
883
|
-
const srcDir = path.resolve(workingPath, assetsDir, "ios");
|
|
884
|
-
const destDir = path.resolve(platformProjectRoot, projectName);
|
|
885
|
-
cleanIOS(destDir);
|
|
886
|
-
hfs.copy(path.join(srcDir, "BootSplash.storyboard"), path.join(destDir, "BootSplash.storyboard"));
|
|
887
|
-
for (const xcassetsDir of ["Colors.xcassets", "Images.xcassets"]) {
|
|
888
|
-
const srcXcassetsDir = path.join(srcDir, xcassetsDir);
|
|
889
|
-
const destXcassetsDir = path.join(destDir, xcassetsDir);
|
|
890
|
-
hfs.ensureDir(destXcassetsDir);
|
|
891
|
-
for (const file of hfs.readDir(srcXcassetsDir)) {
|
|
892
|
-
hfs.copy(path.join(srcXcassetsDir, file), path.join(destXcassetsDir, file));
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
return config;
|
|
896
|
-
}]);
|
|
897
|
-
const withAppDelegate = config => Expo.withAppDelegate(config, config => {
|
|
898
|
-
const [sdkStringVersion = ""] = config.sdkVersion?.split(".") ?? "";
|
|
899
|
-
const isAtLeastExpo51 = Number.parseInt(sdkStringVersion, 10) >= 51;
|
|
900
|
-
const {
|
|
901
|
-
modResults
|
|
902
|
-
} = config;
|
|
903
|
-
const {
|
|
904
|
-
language
|
|
905
|
-
} = modResults;
|
|
906
|
-
if (language !== "objc" && language !== "objcpp") {
|
|
907
|
-
throw new Error(`Cannot modify the project AppDelegate as it's not in a supported language: ${language}`);
|
|
908
|
-
}
|
|
909
|
-
const withHeader = mergeContents({
|
|
910
|
-
src: modResults.contents,
|
|
911
|
-
comment: "//",
|
|
912
|
-
tag: "bootsplash-header",
|
|
913
|
-
offset: 1,
|
|
914
|
-
anchor: /#import "AppDelegate\.h"/,
|
|
915
|
-
newSrc: '#import "RNBootSplash.h"'
|
|
916
|
-
});
|
|
917
|
-
const withRootView = mergeContents({
|
|
918
|
-
src: withHeader.contents,
|
|
919
|
-
comment: "//",
|
|
920
|
-
tag: "bootsplash-init",
|
|
921
|
-
offset: 0,
|
|
922
|
-
anchor: /@end/,
|
|
923
|
-
newSrc: isAtLeastExpo51 ? dedent`
|
|
924
|
-
- (void)customizeRootView:(RCTRootView *)rootView {
|
|
925
|
-
[RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];
|
|
926
|
-
}
|
|
927
|
-
` : dedent`
|
|
928
|
-
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initProps:(NSDictionary *)initProps {
|
|
929
|
-
UIView *rootView = [super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
|
|
930
|
-
[RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];
|
|
931
|
-
return rootView;
|
|
932
|
-
}
|
|
933
|
-
`
|
|
934
|
-
});
|
|
935
|
-
return {
|
|
936
|
-
...config,
|
|
937
|
-
modResults: {
|
|
938
|
-
...modResults,
|
|
939
|
-
contents: withRootView.contents
|
|
940
|
-
}
|
|
941
|
-
};
|
|
942
|
-
});
|
|
943
|
-
const withInfoPlist = config => Expo.withInfoPlist(config, config => {
|
|
944
|
-
config.modResults["UILaunchStoryboardName"] = "BootSplash";
|
|
945
|
-
return config;
|
|
946
|
-
});
|
|
947
|
-
const withXcodeProject = config => Expo.withXcodeProject(config, config => {
|
|
948
|
-
const {
|
|
949
|
-
projectName = ""
|
|
950
|
-
} = config.modRequest;
|
|
951
|
-
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
952
|
-
filepath: path.join(projectName, "BootSplash.storyboard"),
|
|
953
|
-
groupName: projectName,
|
|
954
|
-
project: config.modResults,
|
|
955
|
-
isBuildFile: true
|
|
956
|
-
});
|
|
957
|
-
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
958
|
-
filepath: path.join(projectName, "Colors.xcassets"),
|
|
959
|
-
groupName: projectName,
|
|
960
|
-
project: config.modResults,
|
|
961
|
-
isBuildFile: true
|
|
962
|
-
});
|
|
963
|
-
return config;
|
|
964
|
-
});
|
|
965
|
-
export const withGenerate = (config, props = {}) => {
|
|
966
|
-
const plugins = [];
|
|
967
|
-
const {
|
|
968
|
-
platforms = []
|
|
969
|
-
} = config;
|
|
970
|
-
if (platforms.includes("android")) {
|
|
971
|
-
plugins.push(withAndroidAssets, withAndroidManifest, withMainActivity, withAndroidStyles, withAndroidColors, withAndroidColorsNight);
|
|
972
|
-
}
|
|
973
|
-
if (platforms.includes("ios")) {
|
|
974
|
-
plugins.push(withIOSAssets, withAppDelegate, withInfoPlist, withXcodeProject);
|
|
975
|
-
}
|
|
976
|
-
return Expo.withPlugins(config, plugins.map(plugin => [plugin, props]));
|
|
977
|
-
};
|
|
978
823
|
//# sourceMappingURL=generate.js.map
|