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.
- package/app.plugin.js +1 -1
- package/cli.js +1 -1
- package/dist/commonjs/extras/addon/index.js +97 -0
- package/dist/commonjs/extras/addon/index.js.map +1 -0
- package/dist/commonjs/{expo.js → extras/expo.js} +27 -23
- package/dist/commonjs/extras/expo.js.map +1 -0
- package/dist/commonjs/extras/generate.js +274 -0
- package/dist/commonjs/extras/generate.js.map +1 -0
- package/dist/commonjs/{generate.js → extras/utils.js} +110 -339
- package/dist/commonjs/extras/utils.js.map +1 -0
- package/dist/commonjs/package.json +1 -0
- package/dist/module/extras/addon/index.js +97 -0
- package/dist/module/extras/addon/index.js.map +1 -0
- package/dist/module/{expo.js → extras/expo.js} +6 -3
- package/dist/module/extras/expo.js.map +1 -0
- package/dist/module/extras/generate.js +267 -0
- package/dist/module/extras/generate.js.map +1 -0
- package/dist/module/{generate.js → extras/utils.js} +98 -326
- package/dist/module/extras/utils.js.map +1 -0
- package/dist/module/package.json +1 -0
- package/dist/typescript/{addon → commonjs/extras/addon}/index.d.ts +1 -1
- package/dist/typescript/commonjs/extras/addon/index.d.ts.map +1 -0
- package/dist/typescript/commonjs/extras/expo.d.ts +8 -0
- package/dist/typescript/commonjs/extras/expo.d.ts.map +1 -0
- package/dist/typescript/commonjs/extras/generate.d.ts +17 -0
- package/dist/typescript/commonjs/extras/generate.d.ts.map +1 -0
- package/dist/typescript/{generate.d.ts → commonjs/extras/utils.d.ts} +85 -50
- package/dist/typescript/commonjs/extras/utils.d.ts.map +1 -0
- package/dist/typescript/commonjs/index.d.ts.map +1 -0
- package/dist/typescript/commonjs/package.json +1 -0
- package/dist/typescript/commonjs/specs/NativeRNBootSplash.d.ts.map +1 -0
- package/dist/typescript/commonjs/specs/NativeRNBootSplash.web.d.ts.map +1 -0
- package/dist/typescript/module/extras/addon/index.d.ts +26 -0
- package/dist/typescript/module/extras/addon/index.d.ts.map +1 -0
- package/dist/typescript/module/extras/expo.d.ts +8 -0
- package/dist/typescript/module/extras/expo.d.ts.map +1 -0
- package/dist/typescript/module/extras/generate.d.ts +17 -0
- package/dist/typescript/module/extras/generate.d.ts.map +1 -0
- package/dist/typescript/module/extras/utils.d.ts +193 -0
- package/dist/typescript/module/extras/utils.d.ts.map +1 -0
- package/dist/typescript/module/index.d.ts +61 -0
- package/dist/typescript/module/index.d.ts.map +1 -0
- package/dist/typescript/module/package.json +1 -0
- package/dist/typescript/module/specs/NativeRNBootSplash.d.ts +14 -0
- package/dist/typescript/module/specs/NativeRNBootSplash.d.ts.map +1 -0
- package/dist/typescript/module/specs/NativeRNBootSplash.web.d.ts +9 -0
- package/dist/typescript/module/specs/NativeRNBootSplash.web.d.ts.map +1 -0
- package/package.json +52 -24
- package/src/{expo.ts → extras/expo.ts} +32 -33
- package/src/extras/generate.ts +410 -0
- package/src/{generate.ts → extras/utils.ts} +159 -471
- package/dist/commonjs/addon/index.js +0 -97
- package/dist/commonjs/addon/index.js.map +0 -1
- package/dist/commonjs/expo.js.map +0 -1
- package/dist/commonjs/generate.js.map +0 -1
- package/dist/module/addon/index.js +0 -97
- package/dist/module/addon/index.js.map +0 -1
- package/dist/module/expo.js.map +0 -1
- package/dist/module/generate.js.map +0 -1
- package/dist/typescript/addon/index.d.ts.map +0 -1
- package/dist/typescript/expo.d.ts +0 -6
- package/dist/typescript/expo.d.ts.map +0 -1
- package/dist/typescript/generate.d.ts.map +0 -1
- package/dist/typescript/index.d.ts.map +0 -1
- package/dist/typescript/specs/NativeRNBootSplash.d.ts.map +0 -1
- package/dist/typescript/specs/NativeRNBootSplash.web.d.ts.map +0 -1
- /package/dist/typescript/{index.d.ts → commonjs/index.d.ts} +0 -0
- /package/dist/typescript/{specs → commonjs/specs}/NativeRNBootSplash.d.ts +0 -0
- /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
|
|
9
|
-
import {
|
|
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
|
-
|
|
18
|
+
export const PACKAGE_NAME = "react-native-bootsplash";
|
|
23
19
|
|
|
24
|
-
type
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
66
|
+
android?: {
|
|
67
|
+
/**
|
|
68
|
+
* Enforce system bars style
|
|
69
|
+
* @default `undefined`
|
|
70
|
+
*/
|
|
71
|
+
darkContentBarsStyle?: boolean;
|
|
72
|
+
};
|
|
33
73
|
};
|
|
34
74
|
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
42
|
-
|
|
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(
|
|
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 (
|
|
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(
|
|
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 (
|
|
107
|
+
if (loggerMode.type === "cli") {
|
|
61
108
|
console.log(
|
|
62
|
-
` ${path.relative(
|
|
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
|
-
|
|
395
|
-
|
|
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
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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
|
-
|
|
408
|
-
|
|
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 }:
|
|
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:
|
|
468
|
-
darkBackground:
|
|
469
|
-
darkLogo:
|
|
470
|
-
darkBrand:
|
|
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 |
|
|
858
|
-
iosOutputPath: string |
|
|
859
|
-
htmlTemplatePath: string |
|
|
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
|
-
};
|