react-native-bootsplash 4.7.4 → 5.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +214 -107
  2. package/RNBootSplash.podspec +11 -11
  3. package/android/.npmignore +11 -0
  4. package/android/build.gradle +0 -1
  5. package/android/src/main/java/com/zoontek/rnbootsplash/RNBootSplash.java +3 -2
  6. package/android/src/main/java/com/zoontek/rnbootsplash/RNBootSplashDialog.java +49 -0
  7. package/android/src/main/java/com/zoontek/rnbootsplash/RNBootSplashModuleImpl.java +157 -87
  8. package/android/src/main/res/anim/bootsplash_fade_in.xml +7 -0
  9. package/android/src/main/res/anim/bootsplash_fade_out.xml +7 -0
  10. package/android/src/main/res/drawable/compat_splash_screen.xml +19 -0
  11. package/android/src/main/res/values/attrs.xml +8 -0
  12. package/android/src/main/res/values/public.xml +7 -0
  13. package/android/src/main/res/values/styles.xml +29 -0
  14. package/android/src/main/res/values-v31/styles.xml +7 -0
  15. package/android/src/newarch/com/zoontek/rnbootsplash/RNBootSplashModule.java +11 -4
  16. package/android/src/oldarch/com/zoontek/rnbootsplash/RNBootSplashModule.java +13 -4
  17. package/dist/commonjs/NativeRNBootSplash.js.map +1 -1
  18. package/dist/commonjs/addon/index.js +3 -0
  19. package/dist/commonjs/addon/index.js.map +1 -0
  20. package/dist/commonjs/generate.js +289 -194
  21. package/dist/commonjs/generate.js.map +1 -1
  22. package/dist/commonjs/index.js +115 -7
  23. package/dist/commonjs/index.js.map +1 -1
  24. package/dist/module/NativeRNBootSplash.js.map +1 -1
  25. package/dist/module/addon/index.js +3 -0
  26. package/dist/module/addon/index.js.map +1 -0
  27. package/dist/module/generate.js +287 -195
  28. package/dist/module/generate.js.map +1 -1
  29. package/dist/module/index.js +113 -6
  30. package/dist/module/index.js.map +1 -1
  31. package/dist/typescript/NativeRNBootSplash.d.ts +6 -3
  32. package/dist/typescript/NativeRNBootSplash.d.ts.map +1 -1
  33. package/dist/typescript/addon/index.d.ts +3 -0
  34. package/dist/typescript/addon/index.d.ts.map +1 -0
  35. package/dist/typescript/generate.d.ts +47 -14
  36. package/dist/typescript/generate.d.ts.map +1 -1
  37. package/dist/typescript/index.d.ts +33 -5
  38. package/dist/typescript/index.d.ts.map +1 -1
  39. package/example/android/app/debug.keystore +0 -0
  40. package/example/vendor/bundle/ruby/2.7.0/gems/ffi-1.15.5/ext/ffi_c/libffi/.travis/compile +351 -0
  41. package/example/vendor/bundle/ruby/2.7.0/gems/ffi-1.15.5/ext/ffi_c/libffi/testsuite/libffi.bhaible/Makefile +28 -0
  42. package/ios/.DS_Store +0 -0
  43. package/ios/.npmignore +8 -0
  44. package/ios/RNBootSplash.mm +101 -95
  45. package/package.json +22 -15
  46. package/react-native.config.js +74 -76
  47. package/src/.DS_Store +0 -0
  48. package/src/.npmignore +1 -0
  49. package/src/NativeRNBootSplash.ts +3 -4
  50. package/src/addon/index.ts +788 -0
  51. package/src/generate.ts +457 -232
  52. package/src/index.ts +205 -8
  53. package/RNBootSplash.res +0 -29
  54. package/bsconfig.json +0 -14
@@ -0,0 +1,788 @@
1
+ import crypto from "crypto";
2
+ import fs from "fs-extra";
3
+ import os from "os";
4
+ import path from "path";
5
+ import type { Sharp } from "sharp";
6
+ import sharp from "sharp";
7
+ import { Manifest } from "..";
8
+ import {
9
+ AddonConfig,
10
+ Color,
11
+ androidColorRegex,
12
+ log,
13
+ logWrite,
14
+ } from "../generate";
15
+
16
+ const BrandContentsJson = `{
17
+ "images": [
18
+ {
19
+ "idiom": "universal",
20
+ "filename": "bootsplash_brand.png",
21
+ "scale": "1x"
22
+ },
23
+ {
24
+ "idiom": "universal",
25
+ "filename": "bootsplash_brand@2x.png",
26
+ "scale": "2x"
27
+ },
28
+ {
29
+ "idiom": "universal",
30
+ "filename": "bootsplash_brand@3x.png",
31
+ "scale": "3x"
32
+ }
33
+ ],
34
+ "info": {
35
+ "author": "xcode",
36
+ "version": 1
37
+ }
38
+ }
39
+ `;
40
+
41
+ const DarkLogoContentsJson = `{
42
+ "images": [
43
+ {
44
+ "idiom": "universal",
45
+ "filename": "bootsplash_logo.png",
46
+ "scale": "1x"
47
+ },
48
+ {
49
+ "idiom": "universal",
50
+ "filename": "bootsplash_logo@2x.png",
51
+ "scale": "2x"
52
+ },
53
+ {
54
+ "idiom": "universal",
55
+ "filename": "bootsplash_logo@3x.png",
56
+ "scale": "3x"
57
+ },
58
+ {
59
+ "appearances": [
60
+ {
61
+ "appearance": "luminosity",
62
+ "value": "dark"
63
+ }
64
+ ],
65
+ "idiom": "universal",
66
+ "filename": "bootsplash_dark_logo.png",
67
+ "scale": "1x"
68
+ },
69
+ {
70
+ "appearances": [
71
+ {
72
+ "appearance": "luminosity",
73
+ "value": "dark"
74
+ }
75
+ ],
76
+ "idiom": "universal",
77
+ "filename": "bootsplash_dark_logo@2x.png",
78
+ "scale": "2x"
79
+ },
80
+ {
81
+ "appearances": [
82
+ {
83
+ "appearance": "luminosity",
84
+ "value": "dark"
85
+ }
86
+ ],
87
+ "idiom": "universal",
88
+ "filename": "bootsplash_dark_logo@3x.png",
89
+ "scale": "3x"
90
+ }
91
+ ],
92
+ "info": {
93
+ "author": "xcode",
94
+ "version": 1
95
+ }
96
+ }
97
+ `;
98
+
99
+ const DarkBrandContentsJson = `{
100
+ "images": [
101
+ {
102
+ "idiom": "universal",
103
+ "filename": "bootsplash_brand.png",
104
+ "scale": "1x"
105
+ },
106
+ {
107
+ "idiom": "universal",
108
+ "filename": "bootsplash_brand@2x.png",
109
+ "scale": "2x"
110
+ },
111
+ {
112
+ "idiom": "universal",
113
+ "filename": "bootsplash_brand@3x.png",
114
+ "scale": "3x"
115
+ },
116
+ {
117
+ "appearances": [
118
+ {
119
+ "appearance": "luminosity",
120
+ "value": "dark"
121
+ }
122
+ ],
123
+ "idiom": "universal",
124
+ "filename": "bootsplash_dark_brand.png",
125
+ "scale": "1x"
126
+ },
127
+ {
128
+ "appearances": [
129
+ {
130
+ "appearance": "luminosity",
131
+ "value": "dark"
132
+ }
133
+ ],
134
+ "idiom": "universal",
135
+ "filename": "bootsplash_dark_brand@2x.png",
136
+ "scale": "2x"
137
+ },
138
+ {
139
+ "appearances": [
140
+ {
141
+ "appearance": "luminosity",
142
+ "value": "dark"
143
+ }
144
+ ],
145
+ "idiom": "universal",
146
+ "filename": "bootsplash_dark_brand@3x.png",
147
+ "scale": "3x"
148
+ }
149
+ ],
150
+ "info": {
151
+ "author": "xcode",
152
+ "version": 1
153
+ }
154
+ }
155
+ `;
156
+
157
+ const getStoryboard = ({
158
+ logoHeight,
159
+ logoWidth,
160
+ hasBrand,
161
+ brandHeight,
162
+ brandWidth,
163
+ brandBottom,
164
+ background: { R, G, B },
165
+ hasDarkBackground,
166
+ }: {
167
+ logoHeight: number;
168
+ logoWidth: number;
169
+ hasBrand: boolean;
170
+ brandHeight: number;
171
+ brandWidth: number;
172
+ brandBottom: number;
173
+ background: Color["rgb"];
174
+ hasDarkBackground: boolean;
175
+ }) => {
176
+ const frameWidth = 375;
177
+ const frameHeight = 667;
178
+ const logoX = (frameWidth - logoWidth) / 2;
179
+ const logoY = (frameHeight - logoHeight) / 2;
180
+ const brandX = (frameWidth - brandWidth) / 2;
181
+ const brandY = frameHeight - brandBottom - brandHeight;
182
+
183
+ const content = `<?xml version="1.0" encoding="UTF-8"?>
184
+ <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">
185
+ <device id="retina4_7" orientation="portrait" appearance="light"/>
186
+ <dependencies>
187
+ <deployment identifier="iOS"/>
188
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
189
+ ${
190
+ hasDarkBackground
191
+ ? `<capability name="Named colors" minToolsVersion="9.0"/>`
192
+ : ""
193
+ }
194
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
195
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
196
+ </dependencies>
197
+ <scenes>
198
+ <!--View Controller-->
199
+ <scene sceneID="EHf-IW-A2E">
200
+ <objects>
201
+ <viewController modalTransitionStyle="crossDissolve" id="01J-lp-oVM" sceneMemberID="viewController">
202
+ <view key="view" autoresizesSubviews="NO" contentMode="scaleToFill" id="Ze5-6b-2t3">
203
+ <rect key="frame" x="0.0" y="0.0" width="${frameWidth}" height="${frameHeight}"/>
204
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
205
+ <subviews>
206
+ <imageView autoresizesSubviews="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="BootSplashLogo" translatesAutoresizingMaskIntoConstraints="NO" id="3lX-Ut-9ad">
207
+ <rect key="frame" x="${logoX}" y="${logoY}" width="${logoWidth}" height="${logoHeight}"/>
208
+ <accessibility key="accessibilityConfiguration">
209
+ <accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
210
+ </accessibility>
211
+ </imageView>
212
+ ${
213
+ hasBrand
214
+ ? `<imageView autoresizesSubviews="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="BootSplashBrand" translatesAutoresizingMaskIntoConstraints="NO" id="nNG-Iv-fRa">
215
+ <rect key="frame" x="${brandX}" y="${brandY}" width="${brandWidth}" height="${brandHeight}"/>
216
+ <accessibility key="accessibilityConfiguration">
217
+ <accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
218
+ </accessibility>
219
+ </imageView>`
220
+ : ""
221
+ }
222
+ </subviews>
223
+ <viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
224
+ ${
225
+ hasDarkBackground
226
+ ? `<color key="backgroundColor" name="BootSplashBackground"/>`
227
+ : `<color key="backgroundColor" red="${R}" green="${G}" blue="${B}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>`
228
+ }
229
+ <constraints>
230
+ <constraint firstItem="3lX-Ut-9ad" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="Fh9-Fy-1nT"/>
231
+ <constraint firstItem="3lX-Ut-9ad" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="nvB-Ic-PnI"/>
232
+ ${
233
+ hasBrand
234
+ ? `<constraint firstItem="nNG-Iv-fRa" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="y3c-De-dBE"/>
235
+ <constraint firstAttribute="bottom" secondItem="nNG-Iv-fRa" secondAttribute="bottom" constant="${brandBottom}" id="5IH-OY-8WF"/>`
236
+ : ""
237
+ }
238
+ </constraints>
239
+ </view>
240
+ </viewController>
241
+ <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
242
+ </objects>
243
+ <point key="canvasLocation" x="0.0" y="0.0"/>
244
+ </scene>
245
+ </scenes>
246
+ <resources>
247
+ ${
248
+ hasBrand
249
+ ? `<image name="BootSplashBrand" width="${brandWidth}" height="${brandHeight}"/>`
250
+ : ""
251
+ }
252
+ <image name="BootSplashLogo" width="${logoWidth}" height="${logoHeight}"/>
253
+ ${
254
+ hasDarkBackground
255
+ ? `<namedColor name="BootSplashBackground">
256
+ <color red="${R}" green="${G}" blue="${B}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
257
+ </namedColor>`
258
+ : ""
259
+ }
260
+ </resources>
261
+ </document>
262
+ `;
263
+
264
+ // Remove empty lines
265
+ return `${content
266
+ .split("\n")
267
+ .filter((line) => line.trim() !== "")
268
+ .join("\n")}\n`;
269
+ };
270
+
271
+ type AcceptedFileName = `bootsplash_${
272
+ | "logo"
273
+ | "dark_logo"
274
+ | "brand"
275
+ | "dark_brand"}`;
276
+
277
+ const generateAndroidAsset = ({
278
+ androidResPath,
279
+ fileName,
280
+ image,
281
+ imageWidth,
282
+ night,
283
+ maxWidth,
284
+ maxHeight,
285
+ }: {
286
+ androidResPath: string;
287
+ fileName: AcceptedFileName;
288
+ image: Sharp;
289
+ imageWidth: number;
290
+ night: boolean;
291
+ maxWidth: number;
292
+ maxHeight: number;
293
+ }) => {
294
+ return Promise.all(
295
+ [
296
+ { ratio: 1, suffix: "mdpi" },
297
+ { ratio: 1.5, suffix: "hdpi" },
298
+ { ratio: 2, suffix: "xhdpi" },
299
+ { ratio: 3, suffix: "xxhdpi" },
300
+ { ratio: 4, suffix: "xxxhdpi" },
301
+ ].map(({ ratio, suffix }) => {
302
+ const dirName = "drawable-" + (night ? "night-" : "") + suffix;
303
+
304
+ const drawableDirPath = path.resolve(androidResPath, dirName);
305
+ fs.ensureDirSync(drawableDirPath);
306
+
307
+ const canvasWidth = maxWidth * ratio;
308
+ const canvasHeight = maxHeight * ratio;
309
+
310
+ // https://sharp.pixelplumbing.com/api-constructor
311
+ const canvas = sharp({
312
+ create: {
313
+ width: canvasWidth,
314
+ height: canvasHeight,
315
+ channels: 4,
316
+ background: {
317
+ r: 255,
318
+ g: 255,
319
+ b: 255,
320
+ alpha: 0,
321
+ },
322
+ },
323
+ });
324
+
325
+ const filePath = path.resolve(drawableDirPath, `${fileName}.png`);
326
+
327
+ return image
328
+ .clone()
329
+ .resize(imageWidth * ratio)
330
+ .toBuffer()
331
+ .then((input) =>
332
+ canvas.composite([{ input }]).png({ quality: 100 }).toFile(filePath),
333
+ )
334
+ .then(() => {
335
+ logWrite(filePath, { width: canvasWidth, height: canvasHeight });
336
+ });
337
+ }),
338
+ );
339
+ };
340
+
341
+ const generateIOSAsset = ({
342
+ fileName,
343
+ imageSetPath,
344
+ image,
345
+ imageWidth,
346
+ }: {
347
+ fileName: AcceptedFileName;
348
+ imageSetPath: string;
349
+ image: Sharp;
350
+ imageWidth: number;
351
+ }) => {
352
+ return Promise.all(
353
+ [
354
+ { ratio: 1, suffix: "" },
355
+ { ratio: 2, suffix: "@2x" },
356
+ { ratio: 3, suffix: "@3x" },
357
+ ].map(({ ratio, suffix }) => {
358
+ const filePath = path.resolve(imageSetPath, `${fileName}${suffix}.png`);
359
+
360
+ return image
361
+ .clone()
362
+ .resize(imageWidth * ratio)
363
+ .png({ quality: 100 })
364
+ .toFile(filePath)
365
+ .then(({ width, height }) => {
366
+ logWrite(filePath, { width, height });
367
+ });
368
+ }),
369
+ );
370
+ };
371
+
372
+ const generateGenericAsset = ({
373
+ assetsOutputPath,
374
+ fileName,
375
+ image,
376
+ imageWidth,
377
+ }: {
378
+ assetsOutputPath: string;
379
+ fileName: AcceptedFileName;
380
+ image: Sharp;
381
+ imageWidth: number;
382
+ }) => {
383
+ fs.ensureDirSync(assetsOutputPath);
384
+
385
+ return Promise.all(
386
+ [
387
+ { ratio: 1, suffix: "" },
388
+ { ratio: 1.5, suffix: "@1,5x" },
389
+ { ratio: 2, suffix: "@2x" },
390
+ { ratio: 3, suffix: "@3x" },
391
+ { ratio: 4, suffix: "@4x" },
392
+ ].map(({ ratio, suffix }) => {
393
+ const filePath = path.resolve(
394
+ assetsOutputPath,
395
+ `${fileName}${suffix}.png`,
396
+ );
397
+
398
+ return image
399
+ .clone()
400
+ .resize(imageWidth * ratio)
401
+ .png({ quality: 100 })
402
+ .toFile(filePath)
403
+ .then(({ width, height }) => {
404
+ logWrite(filePath, { width, height });
405
+ });
406
+ }),
407
+ );
408
+ };
409
+
410
+ const verifyLicenseKey = (licenseKey: string) => {
411
+ const formData = new FormData();
412
+
413
+ formData.append("product_id", "T97IouVltWJ3RDe0FA_9yQ==");
414
+ formData.append("license_key", licenseKey);
415
+
416
+ return fetch("https://api.gumroad.com/v2/licenses/verify", {
417
+ method: "POST",
418
+ body: formData,
419
+ })
420
+ .then((response) => response.json())
421
+ .then((data?: { success: boolean }) => {
422
+ if (data?.success === false) {
423
+ log.error("Invalid license key");
424
+ process.exit(1);
425
+ }
426
+
427
+ if (data?.success === true) {
428
+ return;
429
+ }
430
+
431
+ throw new Error("Unknown response");
432
+ })
433
+ .catch(() => {
434
+ log.error("Cannot verify license key");
435
+ process.exit(1);
436
+ });
437
+ };
438
+
439
+ export const execute = async ({
440
+ licenseKey,
441
+
442
+ androidResPath,
443
+ iosProjectPath,
444
+ assetsOutputPath,
445
+
446
+ logoHeight,
447
+ logoWidth,
448
+ brandHeight,
449
+ brandWidth,
450
+
451
+ background,
452
+ brand,
453
+
454
+ darkBackground,
455
+ darkLogo,
456
+ darkBrand,
457
+ }: AddonConfig) => {
458
+ if (
459
+ androidResPath == null &&
460
+ iosProjectPath == null &&
461
+ assetsOutputPath == null
462
+ ) {
463
+ return;
464
+ }
465
+
466
+ const hasBrand = brand != null;
467
+ const hasDarkBackground = darkBackground != null;
468
+ const hasDarkLogo = darkLogo != null;
469
+ const hasDarkBrand = darkBrand != null;
470
+
471
+ log.title("🔑", "With licence key");
472
+
473
+ const packageJsonPath = path.resolve(
474
+ __dirname,
475
+ "..",
476
+ "..",
477
+ "..",
478
+ "package.json",
479
+ );
480
+
481
+ const { version } = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")) as {
482
+ version: string;
483
+ };
484
+
485
+ const licenseKeyHash = crypto
486
+ .createHash("sha256")
487
+ .update(licenseKey)
488
+ .digest("hex");
489
+
490
+ const libVersionHash = crypto
491
+ .createHash("sha256")
492
+ .update(version)
493
+ .digest("hex");
494
+
495
+ const licenseKeyFileName =
496
+ licenseKeyHash.substring(0, licenseKeyHash.length / 2) +
497
+ libVersionHash.substring(libVersionHash.length / 2);
498
+
499
+ const licenseKeyFilePath = path.join(
500
+ fs.realpathSync(os.tmpdir()),
501
+ `.${licenseKeyFileName}`,
502
+ );
503
+
504
+ if (!fs.existsSync(licenseKeyFilePath)) {
505
+ await verifyLicenseKey(licenseKey);
506
+ fs.writeFileSync(licenseKeyFilePath, "", "utf-8");
507
+ }
508
+
509
+ // If we want to respect Android positionning, we have to add empty pixels to bottom padding
510
+ const brandBottom = 60 + (80 - brandHeight) / 2;
511
+
512
+ if (androidResPath != null) {
513
+ if (hasDarkBackground) {
514
+ const valuesNightPath = path.resolve(androidResPath, "values-night");
515
+ fs.ensureDirSync(valuesNightPath);
516
+
517
+ const colorsXmlPath = path.resolve(valuesNightPath, "colors.xml");
518
+ const colorsXmlEntry = `<color name="bootsplash_background">${darkBackground.hex}</color>`;
519
+
520
+ if (fs.existsSync(colorsXmlPath)) {
521
+ const colorsXml = fs.readFileSync(colorsXmlPath, "utf-8");
522
+
523
+ if (colorsXml.match(androidColorRegex)) {
524
+ fs.writeFileSync(
525
+ colorsXmlPath,
526
+ colorsXml.replace(androidColorRegex, colorsXmlEntry),
527
+ "utf-8",
528
+ );
529
+ } else {
530
+ fs.writeFileSync(
531
+ colorsXmlPath,
532
+ colorsXml.replace(
533
+ /<\/resources>/g,
534
+ ` ${colorsXmlEntry}\n</resources>`,
535
+ ),
536
+ "utf-8",
537
+ );
538
+ }
539
+ } else {
540
+ fs.writeFileSync(
541
+ colorsXmlPath,
542
+ `<resources>\n ${colorsXmlEntry}\n</resources>\n`,
543
+ "utf-8",
544
+ );
545
+ }
546
+
547
+ logWrite(colorsXmlPath);
548
+ }
549
+
550
+ if (hasDarkLogo) {
551
+ await generateAndroidAsset({
552
+ androidResPath,
553
+ fileName: "bootsplash_logo",
554
+ image: darkLogo,
555
+ imageWidth: logoWidth,
556
+ night: true,
557
+ // https://developer.android.com/develop/ui/views/launch/splash-screen#dimensions
558
+ maxWidth: 288,
559
+ maxHeight: 288,
560
+ });
561
+ }
562
+
563
+ if (hasBrand) {
564
+ await generateAndroidAsset({
565
+ androidResPath,
566
+ fileName: "bootsplash_brand",
567
+ image: brand,
568
+ imageWidth: brandWidth,
569
+ night: false,
570
+ // https://developer.android.com/develop/ui/views/launch/splash-screen#dimensions
571
+ maxWidth: 200,
572
+ maxHeight: 80,
573
+ });
574
+ }
575
+
576
+ if (hasDarkBrand) {
577
+ await generateAndroidAsset({
578
+ androidResPath,
579
+ fileName: "bootsplash_brand",
580
+ image: darkBrand,
581
+ imageWidth: brandWidth,
582
+ night: true,
583
+ // https://developer.android.com/develop/ui/views/launch/splash-screen#dimensions
584
+ maxWidth: 200,
585
+ maxHeight: 80,
586
+ });
587
+ }
588
+ }
589
+
590
+ if (iosProjectPath != null) {
591
+ const storyboardPath = path.resolve(
592
+ iosProjectPath,
593
+ "BootSplash.storyboard",
594
+ );
595
+
596
+ fs.writeFileSync(
597
+ storyboardPath,
598
+ getStoryboard({
599
+ logoHeight,
600
+ logoWidth,
601
+ hasBrand,
602
+ brandHeight,
603
+ brandWidth,
604
+ brandBottom,
605
+ background: background.rgb,
606
+ hasDarkBackground,
607
+ }),
608
+ "utf-8",
609
+ );
610
+
611
+ logWrite(storyboardPath);
612
+
613
+ if (hasDarkBackground) {
614
+ const colorsSetPath = path.resolve(
615
+ iosProjectPath,
616
+ "Colors.xcassets",
617
+ "BootSplashBackground.colorset",
618
+ );
619
+
620
+ fs.ensureDirSync(colorsSetPath);
621
+
622
+ fs.writeFileSync(
623
+ path.resolve(colorsSetPath, "Contents.json"),
624
+ `{
625
+ "colors": [
626
+ {
627
+ "idiom": "universal",
628
+ "color": {
629
+ "color-space": "srgb",
630
+ "components": {
631
+ "blue": "${background.rgb.B}",
632
+ "green": "${background.rgb.G}",
633
+ "red": "${background.rgb.R}",
634
+ "alpha": "1.000"
635
+ }
636
+ }
637
+ },
638
+ {
639
+ "appearances": [
640
+ {
641
+ "appearance": "luminosity",
642
+ "value": "dark"
643
+ }
644
+ ],
645
+ "idiom": "universal",
646
+ "color": {
647
+ "color-space": "srgb",
648
+ "components": {
649
+ "red": "${darkBackground.rgb.R}",
650
+ "green": "${darkBackground.rgb.G}",
651
+ "blue": "${darkBackground.rgb.B}",
652
+ "alpha": "1.000"
653
+ }
654
+ }
655
+ }
656
+ ],
657
+ "info": {
658
+ "author": "xcode",
659
+ "version": 1
660
+ }
661
+ }
662
+ `,
663
+ "utf-8",
664
+ );
665
+
666
+ logWrite(colorsSetPath);
667
+ }
668
+
669
+ if (hasDarkLogo) {
670
+ const imageSetPath = path.resolve(
671
+ iosProjectPath,
672
+ "Images.xcassets",
673
+ "BootSplashLogo.imageset",
674
+ );
675
+
676
+ fs.ensureDirSync(imageSetPath);
677
+
678
+ fs.writeFileSync(
679
+ path.resolve(imageSetPath, "Contents.json"),
680
+ DarkLogoContentsJson,
681
+ "utf-8",
682
+ );
683
+
684
+ await generateIOSAsset({
685
+ imageSetPath,
686
+ fileName: "bootsplash_dark_logo",
687
+ image: darkLogo,
688
+ imageWidth: logoWidth,
689
+ });
690
+ }
691
+
692
+ if (hasBrand) {
693
+ const imageSetPath = path.resolve(
694
+ iosProjectPath,
695
+ "Images.xcassets",
696
+ "BootSplashBrand.imageset",
697
+ );
698
+
699
+ fs.ensureDirSync(imageSetPath);
700
+
701
+ fs.writeFileSync(
702
+ path.resolve(imageSetPath, "Contents.json"),
703
+ hasDarkBrand ? DarkBrandContentsJson : BrandContentsJson,
704
+ "utf-8",
705
+ );
706
+
707
+ await generateIOSAsset({
708
+ imageSetPath,
709
+ fileName: "bootsplash_brand",
710
+ image: brand,
711
+ imageWidth: brandWidth,
712
+ });
713
+
714
+ if (hasDarkBrand) {
715
+ await generateIOSAsset({
716
+ imageSetPath,
717
+ fileName: "bootsplash_dark_brand",
718
+ image: darkBrand,
719
+ imageWidth: brandWidth,
720
+ });
721
+ }
722
+ }
723
+ }
724
+
725
+ if (assetsOutputPath != null) {
726
+ if (hasDarkBackground || hasBrand) {
727
+ fs.ensureDirSync(assetsOutputPath);
728
+
729
+ const manifest: Manifest = {
730
+ background: background.hex,
731
+ ...(hasDarkBackground && {
732
+ darkBackground: darkBackground.hex,
733
+ }),
734
+ logo: {
735
+ width: logoWidth,
736
+ height: logoHeight,
737
+ },
738
+ ...(hasBrand && {
739
+ brand: {
740
+ bottom: brandBottom,
741
+ width: brandWidth,
742
+ height: brandHeight,
743
+ },
744
+ }),
745
+ };
746
+
747
+ const manifestPath = path.resolve(
748
+ assetsOutputPath,
749
+ "bootsplash_manifest.json",
750
+ );
751
+
752
+ fs.writeFileSync(
753
+ manifestPath,
754
+ JSON.stringify(manifest, null, 2) + "\n",
755
+ "utf-8",
756
+ );
757
+
758
+ logWrite(manifestPath);
759
+ }
760
+
761
+ if (hasDarkLogo) {
762
+ await generateGenericAsset({
763
+ assetsOutputPath,
764
+ fileName: "bootsplash_dark_logo",
765
+ image: darkLogo,
766
+ imageWidth: logoWidth,
767
+ });
768
+ }
769
+
770
+ if (hasBrand) {
771
+ await generateGenericAsset({
772
+ assetsOutputPath,
773
+ fileName: "bootsplash_brand",
774
+ image: brand,
775
+ imageWidth: brandWidth,
776
+ });
777
+ }
778
+
779
+ if (hasDarkBrand) {
780
+ await generateGenericAsset({
781
+ assetsOutputPath,
782
+ fileName: "bootsplash_dark_brand",
783
+ image: darkBrand,
784
+ imageWidth: brandWidth,
785
+ });
786
+ }
787
+ }
788
+ };