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