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
@@ -8,32 +8,33 @@ import semver from "semver";
8
8
  import { dedent } from "ts-dedent";
9
9
  import util from "util";
10
10
  import {
11
- type RawProps,
11
+ type BootSplashPluginConfig,
12
12
  hfs,
13
13
  log,
14
14
  PACKAGE_NAME,
15
15
  requireAddon,
16
- setIsExpo,
16
+ setLoggerMode,
17
17
  transformProps,
18
18
  writeAndroidAssets,
19
19
  writeGenericAssets,
20
20
  writeIOSAssets,
21
21
  writeWebAssets,
22
- } from "./generate";
22
+ } from "./utils";
23
23
 
24
24
  const promisifiedExec = util.promisify(childProcess.exec);
25
25
 
26
26
  const exec = (cmd: string) =>
27
27
  promisifiedExec(cmd).then(({ stdout, stderr }) => stdout || stderr);
28
28
 
29
- const withoutExpoSplashScreen: Expo.ConfigPlugin<RawProps> =
30
- Expo.createRunOncePlugin(
31
- (expoConfig) => expoConfig,
32
- "expo-splash-screen",
33
- "skip",
34
- );
29
+ type ConfigPlugin = Expo.ConfigPlugin<BootSplashPluginConfig>;
30
+
31
+ const withoutExpoSplashScreen: ConfigPlugin = Expo.createRunOncePlugin(
32
+ (expoConfig) => expoConfig,
33
+ "expo-splash-screen",
34
+ "skip",
35
+ );
35
36
 
36
- const withAndroidAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
37
+ const withAndroidAssets: ConfigPlugin = (expoConfig, rawProps) =>
37
38
  Expo.withDangerousMod(expoConfig, [
38
39
  "android",
39
40
  async (config) => {
@@ -56,7 +57,7 @@ const withAndroidAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
56
57
  },
57
58
  ]);
58
59
 
59
- const withAndroidManifest: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
60
+ const withAndroidManifest: ConfigPlugin = (expoConfig) =>
60
61
  Expo.withAndroidManifest(expoConfig, (config) => {
61
62
  config.modResults.manifest.application?.forEach((application) => {
62
63
  if (application.$["android:name"] === ".MainApplication") {
@@ -73,7 +74,7 @@ const withAndroidManifest: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
73
74
  return config;
74
75
  });
75
76
 
76
- const withMainActivity: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
77
+ const withMainActivity: ConfigPlugin = (expoConfig) =>
77
78
  Expo.withMainActivity(expoConfig, (config) => {
78
79
  const { modResults } = config;
79
80
 
@@ -105,7 +106,7 @@ const withMainActivity: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
105
106
  };
106
107
  });
107
108
 
108
- const withAndroidStyles: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
109
+ const withAndroidStyles: ConfigPlugin = (expoConfig, rawProps) =>
109
110
  Expo.withAndroidStyles(expoConfig, async (config) => {
110
111
  const { projectRoot } = config.modRequest;
111
112
  const { android, brand } = await transformProps(projectRoot, rawProps);
@@ -166,7 +167,7 @@ const withAndroidStyles: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
166
167
  };
167
168
  });
168
169
 
169
- const withAndroidColors: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
170
+ const withAndroidColors: ConfigPlugin = (expoConfig, rawProps) =>
170
171
  Expo.withAndroidColors(expoConfig, async (config) => {
171
172
  const { projectRoot } = config.modRequest;
172
173
  const { background } = await transformProps(projectRoot, rawProps);
@@ -179,10 +180,7 @@ const withAndroidColors: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
179
180
  return config;
180
181
  });
181
182
 
182
- const withAndroidColorsNight: Expo.ConfigPlugin<RawProps> = (
183
- expoConfig,
184
- rawProps,
185
- ) =>
183
+ const withAndroidColorsNight: ConfigPlugin = (expoConfig, rawProps) =>
186
184
  Expo.withAndroidColorsNight(expoConfig, async (config) => {
187
185
  const { projectRoot } = config.modRequest;
188
186
  const props = await transformProps(projectRoot, rawProps);
@@ -193,7 +191,7 @@ const withAndroidColorsNight: Expo.ConfigPlugin<RawProps> = (
193
191
  : config;
194
192
  });
195
193
 
196
- const withIOSAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
194
+ const withIOSAssets: ConfigPlugin = (expoConfig, rawProps) =>
197
195
  Expo.withDangerousMod(expoConfig, [
198
196
  "ios",
199
197
  async (config) => {
@@ -214,7 +212,7 @@ const withIOSAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
214
212
  },
215
213
  ]);
216
214
 
217
- const withAppDelegate: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
215
+ const withAppDelegate: ConfigPlugin = (expoConfig) =>
218
216
  Expo.withAppDelegate(expoConfig, (config) => {
219
217
  const { modResults } = config;
220
218
  const { language } = modResults;
@@ -257,13 +255,13 @@ const withAppDelegate: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
257
255
  };
258
256
  });
259
257
 
260
- const withInfoPlist: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
258
+ const withInfoPlist: ConfigPlugin = (expoConfig) =>
261
259
  Expo.withInfoPlist(expoConfig, (config) => {
262
260
  config.modResults["UILaunchStoryboardName"] = "BootSplash";
263
261
  return config;
264
262
  });
265
263
 
266
- const withXcodeProject: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
264
+ const withXcodeProject: ConfigPlugin = (expoConfig) =>
267
265
  Expo.withXcodeProject(expoConfig, (config) => {
268
266
  const { projectName = "" } = config.modRequest;
269
267
 
@@ -284,7 +282,7 @@ const withXcodeProject: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
284
282
  return config;
285
283
  });
286
284
 
287
- const withWebAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
285
+ const withWebAssets: ConfigPlugin = (expoConfig, rawProps) =>
288
286
  Expo.withDangerousMod(expoConfig, [
289
287
  expoConfig.platforms?.includes("ios") ? "ios" : "android",
290
288
  async (config) => {
@@ -306,7 +304,7 @@ const withWebAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
306
304
  },
307
305
  ]);
308
306
 
309
- const withGenericAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
307
+ const withGenericAssets: ConfigPlugin = (expoConfig, rawProps) =>
310
308
  Expo.withDangerousMod(expoConfig, [
311
309
  expoConfig.platforms?.includes("ios") ? "ios" : "android",
312
310
  async (config) => {
@@ -322,11 +320,11 @@ const withGenericAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
322
320
  ]);
323
321
 
324
322
  export const withBootSplash = Expo.createRunOncePlugin<
325
- (Partial<RawProps> & { logo: string }) | undefined
323
+ (Partial<BootSplashPluginConfig> & { logo: string }) | undefined
326
324
  >((expoConfig, baseProps) => {
327
325
  const { platforms = [], sdkVersion = "0.1.0" } = expoConfig;
328
326
 
329
- setIsExpo(true);
327
+ setLoggerMode({ type: "plugin" });
330
328
 
331
329
  if (semver.lt(sdkVersion, "54.0.0")) {
332
330
  log.error("Requires Expo 54.0.0 (or higher)");
@@ -338,7 +336,7 @@ export const withBootSplash = Expo.createRunOncePlugin<
338
336
  process.exit(1);
339
337
  }
340
338
 
341
- const rawProps: RawProps = {
339
+ const rawProps: BootSplashPluginConfig = {
342
340
  assetsOutput: "assets/bootsplash",
343
341
  background: "#fff",
344
342
  brandWidth: 80,
@@ -346,10 +344,7 @@ export const withBootSplash = Expo.createRunOncePlugin<
346
344
  ...baseProps,
347
345
  };
348
346
 
349
- const plugins: Expo.ConfigPlugin<RawProps>[] = [
350
- withoutExpoSplashScreen,
351
- withGenericAssets,
352
- ];
347
+ const plugins: ConfigPlugin[] = [withoutExpoSplashScreen, withGenericAssets];
353
348
 
354
349
  if (platforms.includes("android")) {
355
350
  plugins.push(
@@ -380,3 +375,7 @@ export const withBootSplash = Expo.createRunOncePlugin<
380
375
  plugins.map((plugin) => [plugin, rawProps]),
381
376
  );
382
377
  }, PACKAGE_NAME);
378
+
379
+ export default (
380
+ config: BootSplashPluginConfig,
381
+ ): [typeof PACKAGE_NAME, BootSplashPluginConfig] => [PACKAGE_NAME, config];
@@ -0,0 +1,410 @@
1
+ import * as Expo from "@expo/config-plugins";
2
+ import ExpoPlist from "@expo/plist";
3
+ import glob from "fast-glob";
4
+ import fs from "fs";
5
+ import { HTMLElement, parse as parseHtml } from "node-html-parser";
6
+ import path from "path";
7
+ import pc from "picocolors";
8
+ import { dedent } from "ts-dedent";
9
+ import formatXml from "xml-formatter";
10
+ import {
11
+ hfs,
12
+ log,
13
+ readXmlLike,
14
+ requireAddon,
15
+ setLoggerMode,
16
+ transformProps,
17
+ writeAndroidAssets,
18
+ writeGenericAssets,
19
+ writeIOSAssets,
20
+ writeWebAssets,
21
+ writeXmlLike,
22
+ } from "./utils";
23
+
24
+ const cwd = process.env.INIT_CWD ?? process.env.PWD ?? process.cwd();
25
+ setLoggerMode({ type: "cli", cwd });
26
+
27
+ const projectRoot = (() => {
28
+ let directory = path.resolve(cwd);
29
+
30
+ const { root } = path.parse(directory);
31
+ const ends = new Set([root, path.resolve(directory, root)]);
32
+
33
+ while (directory) {
34
+ const pkgPath = path.join(directory, "package.json");
35
+ const stats = fs.statSync(pkgPath, { throwIfNoEntry: false });
36
+
37
+ if (stats != null && stats.isFile()) {
38
+ return path.dirname(pkgPath);
39
+ }
40
+
41
+ if (ends.has(directory)) {
42
+ break;
43
+ } else {
44
+ directory = path.dirname(directory);
45
+ }
46
+ }
47
+ })();
48
+
49
+ if (!projectRoot) {
50
+ log.error("We couldn't find a package.json in your project.");
51
+ process.exit(1);
52
+ }
53
+
54
+ const getAndroidOutputPath = ({ flavor }: { flavor: string }) => {
55
+ const sourceDir = path.join(projectRoot, "android");
56
+
57
+ if (!fs.existsSync(sourceDir)) {
58
+ return;
59
+ }
60
+
61
+ const appDir = path.join(sourceDir, "app");
62
+
63
+ const androidOutputPath = path.resolve(
64
+ sourceDir,
65
+ fs.existsSync(appDir) ? "app" : "",
66
+ "src",
67
+ flavor,
68
+ "res",
69
+ );
70
+
71
+ if (hfs.exists(androidOutputPath)) {
72
+ return androidOutputPath;
73
+ }
74
+
75
+ log.warn(
76
+ `No ${path.relative(
77
+ cwd,
78
+ androidOutputPath,
79
+ )} directory found. Skipping Android assets generation…`,
80
+ );
81
+ };
82
+
83
+ const getIOSOutputPath = () => {
84
+ const podfile = glob
85
+ .sync("**/Podfile", {
86
+ cwd: projectRoot.replace(/^([a-zA-Z]+:|\.\/)/, ""),
87
+ deep: 10,
88
+ ignore: ["**/@(Pods|node_modules|Carthage|vendor|android)/**"],
89
+ })
90
+ .find((project) => {
91
+ return path.dirname(project) === "ios";
92
+ });
93
+
94
+ if (!podfile) {
95
+ return;
96
+ }
97
+
98
+ const sourceDir = path.dirname(path.join(projectRoot, podfile));
99
+
100
+ const xcodeProjectName = fs
101
+ .readdirSync(sourceDir)
102
+ .sort()
103
+ .reverse()
104
+ .find((fileName) => {
105
+ const ext = path.extname(fileName);
106
+ return ext === ".xcodeproj" || ext === ".xcworkspace";
107
+ });
108
+
109
+ if (xcodeProjectName == null) {
110
+ log.warn("No Xcode project found. Skipping iOS assets generation…");
111
+ return;
112
+ }
113
+
114
+ const iosOutputPath = path
115
+ .resolve(sourceDir, xcodeProjectName)
116
+ .replace(/\.(xcodeproj|xcworkspace)$/, "");
117
+
118
+ if (hfs.exists(iosOutputPath)) {
119
+ return iosOutputPath;
120
+ }
121
+
122
+ log.warn(
123
+ `No ${path.relative(
124
+ cwd,
125
+ iosOutputPath,
126
+ )} directory found. Skipping iOS assets generation…`,
127
+ );
128
+ };
129
+
130
+ const getHtmlTemplatePath = ({ html }: { html: string }) => {
131
+ const htmlTemplatePath = path.resolve(cwd, html);
132
+
133
+ if (hfs.exists(htmlTemplatePath)) {
134
+ return htmlTemplatePath;
135
+ }
136
+
137
+ log.warn(
138
+ `No ${path.relative(
139
+ cwd,
140
+ htmlTemplatePath,
141
+ )} found. Skipping HTML + CSS generation…`,
142
+ );
143
+ };
144
+
145
+ const getInfoPlistPath = ({
146
+ iosOutputPath,
147
+ plist,
148
+ }: {
149
+ iosOutputPath: string;
150
+ plist: string | undefined;
151
+ }) => {
152
+ if (plist != null) {
153
+ const infoPlistPath = path.resolve(cwd, plist);
154
+
155
+ if (!hfs.exists(infoPlistPath)) {
156
+ return log.warn(`No ${path.relative(cwd, infoPlistPath)} found`);
157
+ }
158
+
159
+ return infoPlistPath;
160
+ }
161
+
162
+ return path.resolve(iosOutputPath, "Info.plist");
163
+ };
164
+
165
+ export const generate = async ({
166
+ platforms,
167
+ html,
168
+ flavor,
169
+ plist,
170
+ ...rawProps
171
+ }: {
172
+ platforms: Array<"android" | "ios" | "web">;
173
+ html: string;
174
+ flavor: string;
175
+ plist?: string;
176
+
177
+ logo: string;
178
+ background: string;
179
+ logoWidth: number;
180
+ assetsOutput: string;
181
+ licenseKey?: string;
182
+ brand?: string;
183
+ brandWidth: number;
184
+ darkBackground?: string;
185
+ darkLogo?: string;
186
+ darkBrand?: string;
187
+ }) => {
188
+ const props = await transformProps(cwd, rawProps);
189
+ const addon = requireAddon(props);
190
+
191
+ const { background, brand } = props;
192
+
193
+ const androidOutputPath = platforms.includes("android")
194
+ ? getAndroidOutputPath({ flavor })
195
+ : undefined;
196
+
197
+ const iosOutputPath = platforms.includes("ios")
198
+ ? getIOSOutputPath()
199
+ : undefined;
200
+
201
+ const htmlTemplatePath = platforms.includes("web")
202
+ ? getHtmlTemplatePath({ html })
203
+ : undefined;
204
+
205
+ if (androidOutputPath != null) {
206
+ await writeAndroidAssets({ androidOutputPath, props });
207
+
208
+ const manifestXmlPath = path.resolve(
209
+ androidOutputPath,
210
+ "..",
211
+ "AndroidManifest.xml",
212
+ );
213
+
214
+ if (hfs.exists(manifestXmlPath)) {
215
+ const manifestXml = readXmlLike(manifestXmlPath);
216
+ const activities = manifestXml.root.querySelectorAll("activity");
217
+
218
+ for (const activity of activities) {
219
+ if (activity.getAttribute("android:name") === ".MainActivity") {
220
+ activity.setAttribute("android:theme", "@style/BootTheme");
221
+ }
222
+ }
223
+
224
+ await writeXmlLike(manifestXmlPath, manifestXml.root.toString(), {
225
+ ...manifestXml.formatOptions,
226
+ formatter: "prettier",
227
+ htmlWhitespaceSensitivity: "ignore",
228
+ selfClosingTags: true,
229
+ singleAttributePerLine: true,
230
+ });
231
+ } else {
232
+ log.warn("No AndroidManifest.xml found");
233
+ }
234
+
235
+ const valuesPath = path.resolve(androidOutputPath, "values");
236
+ hfs.ensureDir(valuesPath);
237
+
238
+ const colorsXmlPath = path.resolve(valuesPath, "colors.xml");
239
+ const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
240
+
241
+ if (hfs.exists(colorsXmlPath)) {
242
+ const colorsXml = readXmlLike(colorsXmlPath);
243
+ const nextColor = parseHtml(colorsXmlEntry);
244
+
245
+ const prevColor = colorsXml.root.querySelector(
246
+ 'color[name="bootsplash_background"]',
247
+ );
248
+
249
+ if (prevColor != null) {
250
+ prevColor.replaceWith(nextColor);
251
+ } else {
252
+ colorsXml.root.querySelector("resources")?.appendChild(nextColor);
253
+ }
254
+
255
+ await writeXmlLike(colorsXmlPath, colorsXml.root.toString(), {
256
+ ...colorsXml.formatOptions,
257
+ formatter: "xmlFormatter",
258
+ });
259
+ } else {
260
+ await writeXmlLike(
261
+ colorsXmlPath,
262
+ `<resources>${colorsXmlEntry}</resources>`,
263
+ { formatter: "xmlFormatter" },
264
+ );
265
+ }
266
+
267
+ const stylesXmlPath = path.resolve(valuesPath, "styles.xml");
268
+
269
+ if (hfs.exists(stylesXmlPath)) {
270
+ const stylesXml = readXmlLike(stylesXmlPath);
271
+ const prevStyle = stylesXml.root.querySelector('style[name="BootTheme"]');
272
+ const parent = prevStyle?.getAttribute("parent") ?? "Theme.BootSplash";
273
+
274
+ const extraItems = parseHtml(
275
+ prevStyle?.text
276
+ .split("\n")
277
+ .map((line) => line.trim())
278
+ .join("") ?? "",
279
+ )
280
+ .childNodes.filter((node) => {
281
+ if (!(node instanceof HTMLElement)) {
282
+ return true;
283
+ }
284
+
285
+ const name = node.getAttribute("name");
286
+
287
+ return (
288
+ name !== "bootSplashBackground" &&
289
+ name !== "bootSplashLogo" &&
290
+ name !== "bootSplashBrand" &&
291
+ name !== "postBootSplashTheme"
292
+ );
293
+ })
294
+ .map((node) => node.toString());
295
+
296
+ const styleItems: string[] = [
297
+ ...(extraItems.length > 0 ? [...extraItems, ""] : []),
298
+
299
+ '<item name="bootSplashBackground">@color/bootsplash_background</item>',
300
+ '<item name="bootSplashLogo">@drawable/bootsplash_logo</item>',
301
+
302
+ ...(brand != null
303
+ ? ['<item name="bootSplashBrand">@drawable/bootsplash_brand</item>']
304
+ : []),
305
+
306
+ '<item name="postBootSplashTheme">@style/AppTheme</item>',
307
+ ];
308
+
309
+ const nextStyle = parseHtml(dedent`
310
+ <style name="BootTheme" parent="${parent}">
311
+ ${styleItems.join("\n")}
312
+ </style>
313
+ `);
314
+
315
+ prevStyle?.remove(); // remove the existing style
316
+ stylesXml.root.querySelector("resources")?.appendChild(nextStyle);
317
+
318
+ await writeXmlLike(stylesXmlPath, stylesXml.root.toString(), {
319
+ ...stylesXml.formatOptions,
320
+ formatter: "prettier",
321
+ htmlWhitespaceSensitivity: "ignore",
322
+ });
323
+ } else {
324
+ log.warn("No styles.xml found");
325
+ }
326
+ }
327
+
328
+ if (iosOutputPath != null) {
329
+ await writeIOSAssets({ iosOutputPath, props });
330
+
331
+ const pbxprojectPath = Expo.IOSConfig.Paths.getPBXProjectPath(projectRoot);
332
+
333
+ const xcodeProjectPath =
334
+ Expo.IOSConfig.Paths.getXcodeProjectPath(projectRoot);
335
+
336
+ const project = Expo.IOSConfig.XcodeUtils.getPbxproj(projectRoot);
337
+ const projectName = path.basename(iosOutputPath);
338
+ const groupName = path.parse(xcodeProjectPath).name;
339
+
340
+ Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
341
+ project,
342
+ filepath: path.join(projectName, "BootSplash.storyboard"),
343
+ groupName,
344
+ isBuildFile: true,
345
+ });
346
+
347
+ Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
348
+ project,
349
+ filepath: path.join(projectName, "Colors.xcassets"),
350
+ groupName,
351
+ isBuildFile: true,
352
+ });
353
+
354
+ hfs.write(pbxprojectPath, project.writeSync());
355
+ log.write(pbxprojectPath);
356
+
357
+ const infoPlistPath = getInfoPlistPath({ iosOutputPath, plist });
358
+
359
+ if (infoPlistPath != null) {
360
+ const infoPlist = ExpoPlist.parse(hfs.text(infoPlistPath)) as Record<
361
+ string,
362
+ unknown
363
+ >;
364
+
365
+ infoPlist["UILaunchStoryboardName"] = "BootSplash";
366
+
367
+ const formatted = formatXml(ExpoPlist.build(infoPlist), {
368
+ collapseContent: true,
369
+ forceSelfClosingEmptyTag: false,
370
+ indentation: "\t",
371
+ lineSeparator: "\n",
372
+ whiteSpaceAtEndOfSelfclosingTag: false,
373
+ })
374
+ .replace(/<string\/>/gm, "<string></string>")
375
+ .replace(/^\t/gm, "");
376
+
377
+ hfs.write(infoPlistPath, formatted);
378
+ log.write(infoPlistPath);
379
+ }
380
+ }
381
+
382
+ if (htmlTemplatePath != null) {
383
+ await writeWebAssets({ htmlTemplatePath, props });
384
+ }
385
+
386
+ await writeGenericAssets({ props });
387
+
388
+ if (addon != null) {
389
+ await addon.execute({
390
+ props,
391
+ androidOutputPath,
392
+ iosOutputPath,
393
+ htmlTemplatePath,
394
+ });
395
+ } else {
396
+ console.log(`
397
+ ${pc.blue("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓")}
398
+ ${pc.blue("┃")} 🔑 ${pc.bold(
399
+ "Get a license key for brand image / dark mode support",
400
+ )} ${pc.blue("┃")}
401
+ ${pc.blue("┃")} ${pc.underline(
402
+ "https://zoontek.gumroad.com/l/bootsplash-generator",
403
+ )} ${pc.blue("┃")}
404
+ ${pc.blue("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛")}`);
405
+ }
406
+
407
+ console.log(
408
+ `\n💖 Thanks for using ${pc.underline("react-native-bootsplash")}`,
409
+ );
410
+ };