react-native-bootsplash 7.0.2 → 7.1.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.
Files changed (69) hide show
  1. package/app.plugin.js +1 -1
  2. package/cli.js +1 -1
  3. package/dist/commonjs/extras/addon/index.js +97 -0
  4. package/dist/commonjs/extras/addon/index.js.map +1 -0
  5. package/dist/commonjs/{expo.js → extras/expo.js} +27 -23
  6. package/dist/commonjs/extras/expo.js.map +1 -0
  7. package/dist/commonjs/extras/generate.js +274 -0
  8. package/dist/commonjs/extras/generate.js.map +1 -0
  9. package/dist/commonjs/{generate.js → extras/utils.js} +109 -344
  10. package/dist/commonjs/extras/utils.js.map +1 -0
  11. package/dist/commonjs/package.json +1 -0
  12. package/dist/module/extras/addon/index.js +97 -0
  13. package/dist/module/extras/addon/index.js.map +1 -0
  14. package/dist/module/{expo.js → extras/expo.js} +5 -2
  15. package/dist/module/extras/expo.js.map +1 -0
  16. package/dist/module/extras/generate.js +267 -0
  17. package/dist/module/extras/generate.js.map +1 -0
  18. package/dist/module/{generate.js → extras/utils.js} +97 -331
  19. package/dist/module/extras/utils.js.map +1 -0
  20. package/dist/module/package.json +1 -0
  21. package/dist/typescript/{addon → commonjs/extras/addon}/index.d.ts +1 -1
  22. package/dist/typescript/commonjs/extras/addon/index.d.ts.map +1 -0
  23. package/dist/typescript/commonjs/extras/expo.d.ts +8 -0
  24. package/dist/typescript/commonjs/extras/expo.d.ts.map +1 -0
  25. package/dist/typescript/commonjs/extras/generate.d.ts +17 -0
  26. package/dist/typescript/commonjs/extras/generate.d.ts.map +1 -0
  27. package/dist/typescript/{generate.d.ts → commonjs/extras/utils.d.ts} +67 -36
  28. package/dist/typescript/commonjs/extras/utils.d.ts.map +1 -0
  29. package/dist/typescript/commonjs/index.d.ts.map +1 -0
  30. package/dist/typescript/commonjs/package.json +1 -0
  31. package/dist/typescript/commonjs/specs/NativeRNBootSplash.d.ts.map +1 -0
  32. package/dist/typescript/commonjs/specs/NativeRNBootSplash.web.d.ts.map +1 -0
  33. package/dist/typescript/module/extras/addon/index.d.ts +26 -0
  34. package/dist/typescript/module/extras/addon/index.d.ts.map +1 -0
  35. package/dist/typescript/module/extras/expo.d.ts +8 -0
  36. package/dist/typescript/module/extras/expo.d.ts.map +1 -0
  37. package/dist/typescript/module/extras/generate.d.ts +17 -0
  38. package/dist/typescript/module/extras/generate.d.ts.map +1 -0
  39. package/dist/typescript/module/extras/utils.d.ts +193 -0
  40. package/dist/typescript/module/extras/utils.d.ts.map +1 -0
  41. package/dist/typescript/module/index.d.ts +61 -0
  42. package/dist/typescript/module/index.d.ts.map +1 -0
  43. package/dist/typescript/module/package.json +1 -0
  44. package/dist/typescript/module/specs/NativeRNBootSplash.d.ts +14 -0
  45. package/dist/typescript/module/specs/NativeRNBootSplash.d.ts.map +1 -0
  46. package/dist/typescript/module/specs/NativeRNBootSplash.web.d.ts +9 -0
  47. package/dist/typescript/module/specs/NativeRNBootSplash.web.d.ts.map +1 -0
  48. package/package.json +49 -19
  49. package/src/{expo.ts → extras/expo.ts} +30 -31
  50. package/src/extras/generate.ts +410 -0
  51. package/src/{generate.ts → extras/utils.ts} +156 -479
  52. package/dist/commonjs/addon/index.js +0 -97
  53. package/dist/commonjs/addon/index.js.map +0 -1
  54. package/dist/commonjs/expo.js.map +0 -1
  55. package/dist/commonjs/generate.js.map +0 -1
  56. package/dist/module/addon/index.js +0 -97
  57. package/dist/module/addon/index.js.map +0 -1
  58. package/dist/module/expo.js.map +0 -1
  59. package/dist/module/generate.js.map +0 -1
  60. package/dist/typescript/addon/index.d.ts.map +0 -1
  61. package/dist/typescript/expo.d.ts +0 -6
  62. package/dist/typescript/expo.d.ts.map +0 -1
  63. package/dist/typescript/generate.d.ts.map +0 -1
  64. package/dist/typescript/index.d.ts.map +0 -1
  65. package/dist/typescript/specs/NativeRNBootSplash.d.ts.map +0 -1
  66. package/dist/typescript/specs/NativeRNBootSplash.web.d.ts.map +0 -1
  67. /package/dist/typescript/{index.d.ts → commonjs/index.d.ts} +0 -0
  68. /package/dist/typescript/{specs → commonjs/specs}/NativeRNBootSplash.d.ts +0 -0
  69. /package/dist/typescript/{specs → commonjs/specs}/NativeRNBootSplash.web.d.ts +0 -0
@@ -1,11 +1,8 @@
1
1
  import * as Expo from "@expo/config-plugins";
2
- import ExpoPlist from "@expo/plist";
3
2
  import crypto from "crypto";
4
3
  import detectIndent, { type Indent } from "detect-indent";
5
- import glob from "fast-glob";
6
- import findUp from "find-up";
7
- import fs from "fs-extra";
8
- import { HTMLElement, parse as parseHtml } from "node-html-parser";
4
+ import fs from "fs";
5
+ import { parse as parseHtml } from "node-html-parser";
9
6
  import path from "path";
10
7
  import pc from "picocolors";
11
8
  import type { Options as PrettierOptions } from "prettier";
@@ -16,36 +13,100 @@ import semver from "semver";
16
13
  import sharp, { type Sharp } from "sharp";
17
14
  import { dedent } from "ts-dedent";
18
15
  import formatXml, { type XMLFormatterOptions } from "xml-formatter";
19
- import type { Manifest } from ".";
16
+ import type { Manifest } from "..";
20
17
 
21
18
  export const PACKAGE_NAME = "react-native-bootsplash";
22
19
 
23
- let isExpo = false;
20
+ export type BootSplashPluginConfig = {
21
+ /**
22
+ * Logo file path (PNG or SVG)
23
+ */
24
+ logo: string;
25
+ /**
26
+ * Background color (in hexadecimal format)
27
+ * @default #fff
28
+ */
29
+ background: string;
30
+ /**
31
+ * Logo width at @1x (in dp - we recommend approximately ~100)
32
+ * @default 100
33
+ */
34
+ logoWidth: number;
35
+ /**
36
+ * Assets output directory path
37
+ * @default assets/bootsplash
38
+ */
39
+ assetsOutput: string;
40
+ /**
41
+ * License key to enable brand and dark mode assets generation
42
+ */
43
+ licenseKey?: string;
44
+ /**
45
+ * Brand file path (PNG or SVG)
46
+ */
47
+ brand?: string;
48
+ /**
49
+ * Brand width at @1x (in dp - we recommend approximately ~80)
50
+ * @default 80
51
+ */
52
+ brandWidth: number;
53
+ /**
54
+ * [dark mode] Background color (in hexadecimal format)
55
+ */
56
+ darkBackground?: string;
57
+ /**
58
+ * [dark mode] Logo file path (PNG or SVG)
59
+ */
60
+ darkLogo?: string;
61
+ /**
62
+ * [dark mode] Brand file path (PNG or SVG)
63
+ */
64
+ darkBrand?: string;
24
65
 
25
- export const setIsExpo = (value: boolean) => {
26
- isExpo = value;
66
+ android?: {
67
+ /**
68
+ * Enforce system bars style
69
+ * @default `undefined`
70
+ */
71
+ darkContentBarsStyle?: boolean;
72
+ };
73
+ };
74
+
75
+ type LoggerMode = { type: "plugin" } | { type: "cli"; cwd: string };
76
+ let loggerMode: LoggerMode = { type: "plugin" };
77
+
78
+ export const setLoggerMode = (value: LoggerMode) => {
79
+ loggerMode = value;
27
80
  };
28
81
 
29
82
  export const log = {
30
83
  error: (text: string) => {
31
84
  console.log(
32
- pc.red(isExpo ? `❌ [${PACKAGE_NAME}] ${text}` : `❌ ${text}`),
85
+ pc.red(
86
+ loggerMode.type === "plugin"
87
+ ? `❌ [${PACKAGE_NAME}] ${text}`
88
+ : `❌ ${text}`,
89
+ ),
33
90
  );
34
91
  },
35
92
  title: (emoji: string, text: string) => {
36
- if (!isExpo) {
93
+ if (loggerMode.type === "cli") {
37
94
  console.log(`\n${emoji} ${pc.underline(pc.bold(text))}`);
38
95
  }
39
96
  },
40
97
  warn: (text: string) => {
41
98
  console.log(
42
- pc.yellow(isExpo ? `⚠️ [${PACKAGE_NAME}] ${text}` : `⚠️ ${text}`),
99
+ pc.yellow(
100
+ loggerMode.type === "plugin"
101
+ ? `⚠️ [${PACKAGE_NAME}] ${text}`
102
+ : `⚠️ ${text}`,
103
+ ),
43
104
  );
44
105
  },
45
106
  write: (filePath: string, dimensions?: { width: number; height: number }) => {
46
- if (!isExpo) {
107
+ if (loggerMode.type === "cli") {
47
108
  console.log(
48
- ` ${path.relative(workingPath, filePath)}` +
109
+ ` ${path.relative(loggerMode.cwd, filePath)}` +
49
110
  (dimensions != null
50
111
  ? ` (${dimensions.width}x${dimensions.height})`
51
112
  : ""),
@@ -54,95 +115,6 @@ export const log = {
54
115
  },
55
116
  };
56
117
 
57
- const workingPath = process.env.INIT_CWD ?? process.env.PWD ?? process.cwd();
58
- const packagePath = findUp.sync("package.json", { cwd: workingPath });
59
-
60
- if (!packagePath) {
61
- log.error("We couldn't find a package.json in your project.");
62
- process.exit(1);
63
- }
64
-
65
- const projectRoot = path.dirname(packagePath);
66
-
67
- const parseColor = (value: string) => {
68
- const up = value.toUpperCase().replace(/[^0-9A-F]/g, "");
69
-
70
- if (up.length !== 3 && up.length !== 6) {
71
- log.error(`"${value}" value is not a valid hexadecimal color.`);
72
- process.exit(1);
73
- }
74
-
75
- const hex =
76
- up.length === 3
77
- ? "#" + up[0] + up[0] + up[1] + up[1] + up[2] + up[2]
78
- : "#" + up;
79
-
80
- const rgb = {
81
- R: (Number.parseInt("" + hex[1] + hex[2], 16) / 255).toPrecision(15),
82
- G: (Number.parseInt("" + hex[3] + hex[4], 16) / 255).toPrecision(15),
83
- B: (Number.parseInt("" + hex[5] + hex[6], 16) / 255).toPrecision(15),
84
- };
85
-
86
- return { hex: hex.toLowerCase(), rgb };
87
- };
88
-
89
- const getStoryboard = (props: Props) => {
90
- const { background, logo, fileNameSuffix } = props;
91
-
92
- const { R, G, B } = background.rgb;
93
- const frameWidth = 375;
94
- const frameHeight = 667;
95
-
96
- return dedent`
97
- <?xml version="1.0" encoding="UTF-8"?>
98
- <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
99
- <device id="retina4_7" orientation="portrait" appearance="light"/>
100
- <dependencies>
101
- <deployment identifier="iOS"/>
102
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
103
- <capability name="Named colors" minToolsVersion="9.0"/>
104
- <capability name="Safe area layout guides" minToolsVersion="9.0"/>
105
- <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
106
- </dependencies>
107
- <scenes>
108
- <!--View Controller-->
109
- <scene sceneID="EHf-IW-A2E">
110
- <objects>
111
- <viewController modalTransitionStyle="crossDissolve" id="01J-lp-oVM" sceneMemberID="viewController">
112
- <view key="view" autoresizesSubviews="NO" contentMode="scaleToFill" id="Ze5-6b-2t3">
113
- <rect key="frame" x="0.0" y="0.0" width="${frameWidth}" height="${frameHeight}"/>
114
- <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
115
- <subviews>
116
- <imageView autoresizesSubviews="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="BootSplashLogo-${fileNameSuffix}" translatesAutoresizingMaskIntoConstraints="NO" id="3lX-Ut-9ad">
117
- <rect key="frame" x="${(frameWidth - logo.width) / 2}" y="${(frameHeight - logo.height) / 2}" width="${logo.width}" height="${logo.height}"/>
118
- <accessibility key="accessibilityConfiguration">
119
- <accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
120
- </accessibility>
121
- </imageView>
122
- </subviews>
123
- <viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
124
- <color key="backgroundColor" name="BootSplashBackground-${fileNameSuffix}"/>
125
- <constraints>
126
- <constraint firstItem="3lX-Ut-9ad" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="Fh9-Fy-1nT"/>
127
- <constraint firstItem="3lX-Ut-9ad" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="nvB-Ic-PnI"/>
128
- </constraints>
129
- </view>
130
- </viewController>
131
- <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
132
- </objects>
133
- <point key="canvasLocation" x="0.0" y="0.0"/>
134
- </scene>
135
- </scenes>
136
- <resources>
137
- <image name="BootSplashLogo-${fileNameSuffix}" width="${logo.width}" height="${logo.height}"/>
138
- <namedColor name="BootSplashBackground-${fileNameSuffix}">
139
- <color red="${R}" green="${G}" blue="${B}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
140
- </namedColor>
141
- </resources>
142
- </document>
143
- `;
144
- };
145
-
146
118
  // Freely inspired by https://github.com/humanwhocodes/humanfs
147
119
  export const hfs = {
148
120
  buffer: (path: string) => fs.readFileSync(path),
@@ -239,117 +211,6 @@ export const writeXmlLike = async (
239
211
  }
240
212
  };
241
213
 
242
- const getAndroidOutputPath = ({ flavor }: { flavor: string }) => {
243
- const sourceDir = path.join(projectRoot, "android");
244
-
245
- if (!fs.existsSync(sourceDir)) {
246
- return;
247
- }
248
-
249
- const appDir = path.join(sourceDir, "app");
250
-
251
- const androidOutputPath = path.resolve(
252
- sourceDir,
253
- fs.existsSync(appDir) ? "app" : "",
254
- "src",
255
- flavor,
256
- "res",
257
- );
258
-
259
- if (hfs.exists(androidOutputPath)) {
260
- return androidOutputPath;
261
- }
262
-
263
- log.warn(
264
- `No ${path.relative(
265
- workingPath,
266
- androidOutputPath,
267
- )} directory found. Skipping Android assets generation…`,
268
- );
269
- };
270
-
271
- const getIOSOutputPath = () => {
272
- const podfile = glob
273
- .sync("**/Podfile", {
274
- cwd: projectRoot.replace(/^([a-zA-Z]+:|\.\/)/, ""),
275
- deep: 10,
276
- ignore: ["**/@(Pods|node_modules|Carthage|vendor|android)/**"],
277
- })
278
- .find((project) => {
279
- return path.dirname(project) === "ios";
280
- });
281
-
282
- if (!podfile) {
283
- return;
284
- }
285
-
286
- const sourceDir = path.dirname(path.join(projectRoot, podfile));
287
-
288
- const xcodeProjectName = fs
289
- .readdirSync(sourceDir)
290
- .sort()
291
- .reverse()
292
- .find((fileName) => {
293
- const ext = path.extname(fileName);
294
- return ext === ".xcworkspace" || ext === ".xcodeproj";
295
- });
296
-
297
- if (xcodeProjectName == null) {
298
- log.warn("No Xcode project found. Skipping iOS assets generation…");
299
- return;
300
- }
301
-
302
- const iosOutputPath = path
303
- .resolve(sourceDir, xcodeProjectName)
304
- .replace(/\.(xcodeproj|xcworkspace)$/, "");
305
-
306
- if (hfs.exists(iosOutputPath)) {
307
- return iosOutputPath;
308
- }
309
-
310
- log.warn(
311
- `No ${path.relative(
312
- workingPath,
313
- iosOutputPath,
314
- )} directory found. Skipping iOS assets generation…`,
315
- );
316
- };
317
-
318
- const getHtmlTemplatePath = ({ html }: { html: string }) => {
319
- const htmlTemplatePath = path.resolve(workingPath, html);
320
-
321
- if (hfs.exists(htmlTemplatePath)) {
322
- return htmlTemplatePath;
323
- }
324
-
325
- log.warn(
326
- `No ${path.relative(
327
- workingPath,
328
- htmlTemplatePath,
329
- )} found. Skipping HTML + CSS generation…`,
330
- );
331
- };
332
-
333
- const getInfoPlistPath = ({
334
- iosOutputPath,
335
- plist,
336
- }: {
337
- iosOutputPath: string;
338
- plist: string | undefined;
339
- }) => {
340
- if (plist != null) {
341
- const infoPlistPath = path.resolve(workingPath, plist);
342
-
343
- if (!hfs.exists(infoPlistPath)) {
344
- return log.warn(`No ${path.relative(workingPath, infoPlistPath)} found`);
345
- }
346
-
347
- return infoPlistPath;
348
- }
349
-
350
- return path.resolve(iosOutputPath, "Info.plist");
351
- };
352
-
353
214
  export type Asset = {
354
215
  path: string;
355
216
  image: Sharp;
@@ -394,27 +255,31 @@ const toAsset = async (filePath: string, width: number): Promise<Asset> => {
394
255
  };
395
256
  };
396
257
 
397
- export type RawProps = {
398
- logo: string;
399
- background: string;
400
- logoWidth: number;
401
- assetsOutput: string;
258
+ const parseColor = (value: string) => {
259
+ const up = value.toUpperCase().replace(/[^0-9A-F]/g, "");
402
260
 
403
- licenseKey?: string;
404
- brand?: string;
405
- brandWidth: number;
406
- darkBackground?: string;
407
- darkLogo?: string;
408
- darkBrand?: string;
261
+ if (up.length !== 3 && up.length !== 6) {
262
+ log.error(`"${value}" value is not a valid hexadecimal color.`);
263
+ process.exit(1);
264
+ }
409
265
 
410
- android?: {
411
- darkContentBarsStyle?: boolean;
266
+ const hex =
267
+ up.length === 3
268
+ ? "#" + up[0] + up[0] + up[1] + up[1] + up[2] + up[2]
269
+ : "#" + up;
270
+
271
+ const rgb = {
272
+ R: (Number.parseInt("" + hex[1] + hex[2], 16) / 255).toPrecision(15),
273
+ G: (Number.parseInt("" + hex[3] + hex[4], 16) / 255).toPrecision(15),
274
+ B: (Number.parseInt("" + hex[5] + hex[6], 16) / 255).toPrecision(15),
412
275
  };
276
+
277
+ return { hex: hex.toLowerCase(), rgb };
413
278
  };
414
279
 
415
280
  export const transformProps = async (
416
281
  rootPath: string,
417
- { android = {}, licenseKey, ...rawProps }: RawProps,
282
+ { android = {}, licenseKey, ...rawProps }: BootSplashPluginConfig,
418
283
  ) => {
419
284
  if (semver.lt(process.versions.node, "20.0.0")) {
420
285
  log.error("Requires Node 20 (or higher)");
@@ -466,11 +331,13 @@ export const transformProps = async (
466
331
  );
467
332
  }
468
333
 
334
+ const isPluginLoggerMode = loggerMode.type === "plugin";
335
+
469
336
  const optionNames = {
470
- brand: isExpo ? "brand" : "--brand",
471
- darkBackground: isExpo ? "darkBackground" : "--dark-background",
472
- darkLogo: isExpo ? "darkLogo" : "--dark-logo",
473
- darkBrand: isExpo ? "darkBrand" : "--dark-brand",
337
+ brand: isPluginLoggerMode ? "brand" : "--brand",
338
+ darkBackground: isPluginLoggerMode ? "darkBackground" : "--dark-background",
339
+ darkLogo: isPluginLoggerMode ? "darkLogo" : "--dark-logo",
340
+ darkBrand: isPluginLoggerMode ? "darkBrand" : "--dark-brand",
474
341
  };
475
342
 
476
343
  if (licenseKey == null && executeAddon) {
@@ -623,6 +490,63 @@ export const writeAndroidAssets = async ({
623
490
  );
624
491
  };
625
492
 
493
+ const getStoryboard = (props: Props) => {
494
+ const { background, logo, fileNameSuffix } = props;
495
+
496
+ const { R, G, B } = background.rgb;
497
+ const frameWidth = 375;
498
+ const frameHeight = 667;
499
+
500
+ return dedent`
501
+ <?xml version="1.0" encoding="UTF-8"?>
502
+ <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
503
+ <device id="retina4_7" orientation="portrait" appearance="light"/>
504
+ <dependencies>
505
+ <deployment identifier="iOS"/>
506
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
507
+ <capability name="Named colors" minToolsVersion="9.0"/>
508
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
509
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
510
+ </dependencies>
511
+ <scenes>
512
+ <!--View Controller-->
513
+ <scene sceneID="EHf-IW-A2E">
514
+ <objects>
515
+ <viewController modalTransitionStyle="crossDissolve" id="01J-lp-oVM" sceneMemberID="viewController">
516
+ <view key="view" autoresizesSubviews="NO" contentMode="scaleToFill" id="Ze5-6b-2t3">
517
+ <rect key="frame" x="0.0" y="0.0" width="${frameWidth}" height="${frameHeight}"/>
518
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
519
+ <subviews>
520
+ <imageView autoresizesSubviews="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="BootSplashLogo-${fileNameSuffix}" translatesAutoresizingMaskIntoConstraints="NO" id="3lX-Ut-9ad">
521
+ <rect key="frame" x="${(frameWidth - logo.width) / 2}" y="${(frameHeight - logo.height) / 2}" width="${logo.width}" height="${logo.height}"/>
522
+ <accessibility key="accessibilityConfiguration">
523
+ <accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
524
+ </accessibility>
525
+ </imageView>
526
+ </subviews>
527
+ <viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
528
+ <color key="backgroundColor" name="BootSplashBackground-${fileNameSuffix}"/>
529
+ <constraints>
530
+ <constraint firstItem="3lX-Ut-9ad" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="Fh9-Fy-1nT"/>
531
+ <constraint firstItem="3lX-Ut-9ad" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="nvB-Ic-PnI"/>
532
+ </constraints>
533
+ </view>
534
+ </viewController>
535
+ <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
536
+ </objects>
537
+ <point key="canvasLocation" x="0.0" y="0.0"/>
538
+ </scene>
539
+ </scenes>
540
+ <resources>
541
+ <image name="BootSplashLogo-${fileNameSuffix}" width="${logo.width}" height="${logo.height}"/>
542
+ <namedColor name="BootSplashBackground-${fileNameSuffix}">
543
+ <color red="${R}" green="${G}" blue="${B}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
544
+ </namedColor>
545
+ </resources>
546
+ </document>
547
+ `;
548
+ };
549
+
626
550
  export const writeIOSAssets = async ({
627
551
  iosOutputPath,
628
552
  props,
@@ -901,250 +825,3 @@ export const requireAddon = ({
901
825
  }
902
826
  }
903
827
  };
904
-
905
- export const generate = async ({
906
- platforms,
907
- html,
908
- flavor,
909
- plist,
910
- ...rawProps
911
- }: {
912
- platforms: Array<"android" | "ios" | "web">;
913
- html: string;
914
- flavor: string;
915
- plist?: string;
916
-
917
- logo: string;
918
- background: string;
919
- logoWidth: number;
920
- assetsOutput: string;
921
- licenseKey?: string;
922
- brand?: string;
923
- brandWidth: number;
924
- darkBackground?: string;
925
- darkLogo?: string;
926
- darkBrand?: string;
927
- }) => {
928
- const props = await transformProps(workingPath, rawProps);
929
- const addon = requireAddon(props);
930
-
931
- const { background, brand } = props;
932
-
933
- const androidOutputPath = platforms.includes("android")
934
- ? getAndroidOutputPath({ flavor })
935
- : undefined;
936
-
937
- const iosOutputPath = platforms.includes("ios")
938
- ? getIOSOutputPath()
939
- : undefined;
940
-
941
- const htmlTemplatePath = platforms.includes("web")
942
- ? getHtmlTemplatePath({ html })
943
- : undefined;
944
-
945
- if (androidOutputPath != null) {
946
- await writeAndroidAssets({ androidOutputPath, props });
947
-
948
- const manifestXmlPath = path.resolve(
949
- androidOutputPath,
950
- "..",
951
- "AndroidManifest.xml",
952
- );
953
-
954
- if (hfs.exists(manifestXmlPath)) {
955
- const manifestXml = readXmlLike(manifestXmlPath);
956
- const activities = manifestXml.root.querySelectorAll("activity");
957
-
958
- for (const activity of activities) {
959
- if (activity.getAttribute("android:name") === ".MainActivity") {
960
- activity.setAttribute("android:theme", "@style/BootTheme");
961
- }
962
- }
963
-
964
- await writeXmlLike(manifestXmlPath, manifestXml.root.toString(), {
965
- ...manifestXml.formatOptions,
966
- formatter: "prettier",
967
- htmlWhitespaceSensitivity: "ignore",
968
- selfClosingTags: true,
969
- singleAttributePerLine: true,
970
- });
971
- } else {
972
- log.warn("No AndroidManifest.xml found");
973
- }
974
-
975
- const valuesPath = path.resolve(androidOutputPath, "values");
976
- hfs.ensureDir(valuesPath);
977
-
978
- const colorsXmlPath = path.resolve(valuesPath, "colors.xml");
979
- const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
980
-
981
- if (hfs.exists(colorsXmlPath)) {
982
- const colorsXml = readXmlLike(colorsXmlPath);
983
- const nextColor = parseHtml(colorsXmlEntry);
984
-
985
- const prevColor = colorsXml.root.querySelector(
986
- 'color[name="bootsplash_background"]',
987
- );
988
-
989
- if (prevColor != null) {
990
- prevColor.replaceWith(nextColor);
991
- } else {
992
- colorsXml.root.querySelector("resources")?.appendChild(nextColor);
993
- }
994
-
995
- await writeXmlLike(colorsXmlPath, colorsXml.root.toString(), {
996
- ...colorsXml.formatOptions,
997
- formatter: "xmlFormatter",
998
- });
999
- } else {
1000
- await writeXmlLike(
1001
- colorsXmlPath,
1002
- `<resources>${colorsXmlEntry}</resources>`,
1003
- { formatter: "xmlFormatter" },
1004
- );
1005
- }
1006
-
1007
- const stylesXmlPath = path.resolve(valuesPath, "styles.xml");
1008
-
1009
- if (hfs.exists(stylesXmlPath)) {
1010
- const stylesXml = readXmlLike(stylesXmlPath);
1011
- const prevStyle = stylesXml.root.querySelector('style[name="BootTheme"]');
1012
- const parent = prevStyle?.getAttribute("parent") ?? "Theme.BootSplash";
1013
-
1014
- const extraItems = parseHtml(
1015
- prevStyle?.text
1016
- .split("\n")
1017
- .map((line) => line.trim())
1018
- .join("") ?? "",
1019
- )
1020
- .childNodes.filter((node) => {
1021
- if (!(node instanceof HTMLElement)) {
1022
- return true;
1023
- }
1024
-
1025
- const name = node.getAttribute("name");
1026
-
1027
- return (
1028
- name !== "bootSplashBackground" &&
1029
- name !== "bootSplashLogo" &&
1030
- name !== "bootSplashBrand" &&
1031
- name !== "postBootSplashTheme"
1032
- );
1033
- })
1034
- .map((node) => node.toString());
1035
-
1036
- const styleItems: string[] = [
1037
- ...(extraItems.length > 0 ? [...extraItems, ""] : []),
1038
-
1039
- '<item name="bootSplashBackground">@color/bootsplash_background</item>',
1040
- '<item name="bootSplashLogo">@drawable/bootsplash_logo</item>',
1041
-
1042
- ...(brand != null
1043
- ? ['<item name="bootSplashBrand">@drawable/bootsplash_brand</item>']
1044
- : []),
1045
-
1046
- '<item name="postBootSplashTheme">@style/AppTheme</item>',
1047
- ];
1048
-
1049
- const nextStyle = parseHtml(dedent`
1050
- <style name="BootTheme" parent="${parent}">
1051
- ${styleItems.join("\n")}
1052
- </style>
1053
- `);
1054
-
1055
- prevStyle?.remove(); // remove the existing style
1056
- stylesXml.root.querySelector("resources")?.appendChild(nextStyle);
1057
-
1058
- await writeXmlLike(stylesXmlPath, stylesXml.root.toString(), {
1059
- ...stylesXml.formatOptions,
1060
- formatter: "prettier",
1061
- htmlWhitespaceSensitivity: "ignore",
1062
- });
1063
- } else {
1064
- log.warn("No styles.xml found");
1065
- }
1066
- }
1067
-
1068
- if (iosOutputPath != null) {
1069
- await writeIOSAssets({ iosOutputPath, props });
1070
-
1071
- const pbxprojectPath = Expo.IOSConfig.Paths.getPBXProjectPath(projectRoot);
1072
-
1073
- const xcodeProjectPath =
1074
- Expo.IOSConfig.Paths.getXcodeProjectPath(projectRoot);
1075
-
1076
- const project = Expo.IOSConfig.XcodeUtils.getPbxproj(projectRoot);
1077
- const projectName = path.basename(iosOutputPath);
1078
- const groupName = path.parse(xcodeProjectPath).name;
1079
-
1080
- Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
1081
- project,
1082
- filepath: path.join(projectName, "BootSplash.storyboard"),
1083
- groupName,
1084
- isBuildFile: true,
1085
- });
1086
-
1087
- Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
1088
- project,
1089
- filepath: path.join(projectName, "Colors.xcassets"),
1090
- groupName,
1091
- isBuildFile: true,
1092
- });
1093
-
1094
- hfs.write(pbxprojectPath, project.writeSync());
1095
- log.write(pbxprojectPath);
1096
-
1097
- const infoPlistPath = getInfoPlistPath({ iosOutputPath, plist });
1098
-
1099
- if (infoPlistPath != null) {
1100
- const infoPlist = ExpoPlist.parse(hfs.text(infoPlistPath)) as Record<
1101
- string,
1102
- unknown
1103
- >;
1104
-
1105
- infoPlist["UILaunchStoryboardName"] = "BootSplash";
1106
-
1107
- const formatted = formatXml(ExpoPlist.build(infoPlist), {
1108
- collapseContent: true,
1109
- forceSelfClosingEmptyTag: false,
1110
- indentation: "\t",
1111
- lineSeparator: "\n",
1112
- whiteSpaceAtEndOfSelfclosingTag: false,
1113
- })
1114
- .replace(/<string\/>/gm, "<string></string>")
1115
- .replace(/^\t/gm, "");
1116
-
1117
- hfs.write(infoPlistPath, formatted);
1118
- log.write(infoPlistPath);
1119
- }
1120
- }
1121
-
1122
- if (htmlTemplatePath != null) {
1123
- await writeWebAssets({ htmlTemplatePath, props });
1124
- }
1125
-
1126
- await writeGenericAssets({ props });
1127
-
1128
- if (addon != null) {
1129
- await addon.execute({
1130
- props,
1131
- androidOutputPath,
1132
- iosOutputPath,
1133
- htmlTemplatePath,
1134
- });
1135
- } else {
1136
- console.log(`
1137
- ${pc.blue("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓")}
1138
- ${pc.blue("┃")} 🔑 ${pc.bold(
1139
- "Get a license key for brand image / dark mode support",
1140
- )} ${pc.blue("┃")}
1141
- ${pc.blue("┃")} ${pc.underline(
1142
- "https://zoontek.gumroad.com/l/bootsplash-generator",
1143
- )} ${pc.blue("┃")}
1144
- ${pc.blue("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛")}`);
1145
- }
1146
-
1147
- console.log(
1148
- `\n💖 Thanks for using ${pc.underline("react-native-bootsplash")}`,
1149
- );
1150
- };