react-native-bootsplash 5.5.3 → 6.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.
- package/README.md +38 -38
- package/app.plugin.js +2 -0
- package/dist/commonjs/addon/index.js +38 -30
- package/dist/commonjs/addon/index.js.map +1 -1
- package/dist/commonjs/generate.js +570 -203
- package/dist/commonjs/generate.js.map +1 -1
- package/dist/commonjs/index.js +19 -13
- package/dist/commonjs/index.js.map +1 -1
- package/dist/module/addon/index.js +38 -30
- package/dist/module/addon/index.js.map +1 -1
- package/dist/module/generate.js +559 -190
- package/dist/module/generate.js.map +1 -1
- package/dist/module/index.js +19 -13
- package/dist/module/index.js.map +1 -1
- package/dist/typescript/addon/index.d.ts +1 -1
- package/dist/typescript/addon/index.d.ts.map +1 -1
- package/dist/typescript/generate.d.ts +47 -41
- package/dist/typescript/generate.d.ts.map +1 -1
- package/dist/typescript/index.d.ts +1 -0
- package/dist/typescript/index.d.ts.map +1 -1
- package/package.json +16 -12
- package/react-native.config.js +16 -10
- package/src/generate.ts +779 -279
- package/src/index.ts +26 -16
package/dist/module/generate.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import murmurhash from "@emotion/hash";
|
|
2
|
-
import {
|
|
2
|
+
import { getConfig as getExpoConfig } from "@expo/config";
|
|
3
|
+
import * as Expo from "@expo/config-plugins";
|
|
4
|
+
import { assignColorValue } from "@expo/config-plugins/build/android/Colors";
|
|
5
|
+
import { addImports } from "@expo/config-plugins/build/android/codeMod";
|
|
6
|
+
import { mergeContents } from "@expo/config-plugins/build/utils/generateCode";
|
|
3
7
|
import plist from "@expo/plist";
|
|
4
8
|
import { findProjectRoot } from "@react-native-community/cli-tools";
|
|
5
9
|
import detectIndent from "detect-indent";
|
|
6
|
-
import fs from "fs";
|
|
10
|
+
import fs from "fs-extra";
|
|
7
11
|
import { parse as parseHtml } from "node-html-parser";
|
|
8
12
|
import path from "path";
|
|
9
13
|
import pc from "picocolors";
|
|
@@ -14,6 +18,21 @@ import sharp from "sharp";
|
|
|
14
18
|
import { dedent } from "ts-dedent";
|
|
15
19
|
import formatXml from "xml-formatter";
|
|
16
20
|
const workingPath = process.env.INIT_CWD ?? process.env.PWD ?? process.cwd();
|
|
21
|
+
const projectRoot = findProjectRoot(workingPath);
|
|
22
|
+
export const log = {
|
|
23
|
+
error: text => {
|
|
24
|
+
console.log(pc.red(`❌ ${text}`));
|
|
25
|
+
},
|
|
26
|
+
title: (emoji, text) => {
|
|
27
|
+
console.log(`\n${emoji} ${pc.underline(pc.bold(text))}`);
|
|
28
|
+
},
|
|
29
|
+
warn: text => {
|
|
30
|
+
console.log(pc.yellow(`⚠️ ${text}`));
|
|
31
|
+
},
|
|
32
|
+
write: (filePath, dimensions) => {
|
|
33
|
+
console.log(` ${path.relative(workingPath, filePath)}` + (dimensions != null ? ` (${dimensions.width}x${dimensions.height})` : ""));
|
|
34
|
+
}
|
|
35
|
+
};
|
|
17
36
|
export const parseColor = value => {
|
|
18
37
|
const up = value.toUpperCase().replace(/[^0-9A-F]/g, "");
|
|
19
38
|
if (up.length !== 3 && up.length !== 6) {
|
|
@@ -22,12 +41,12 @@ export const parseColor = value => {
|
|
|
22
41
|
}
|
|
23
42
|
const hex = up.length === 3 ? "#" + up[0] + up[0] + up[1] + up[1] + up[2] + up[2] : "#" + up;
|
|
24
43
|
const rgb = {
|
|
25
|
-
R: (parseInt("" + hex[1] + hex[2], 16) / 255).toPrecision(15),
|
|
26
|
-
G: (parseInt("" + hex[3] + hex[4], 16) / 255).toPrecision(15),
|
|
27
|
-
B: (parseInt("" + hex[5] + hex[6], 16) / 255).toPrecision(15)
|
|
44
|
+
R: (Number.parseInt("" + hex[1] + hex[2], 16) / 255).toPrecision(15),
|
|
45
|
+
G: (Number.parseInt("" + hex[3] + hex[4], 16) / 255).toPrecision(15),
|
|
46
|
+
B: (Number.parseInt("" + hex[5] + hex[6], 16) / 255).toPrecision(15)
|
|
28
47
|
};
|
|
29
48
|
return {
|
|
30
|
-
hex,
|
|
49
|
+
hex: hex.toLowerCase(),
|
|
31
50
|
rgb
|
|
32
51
|
};
|
|
33
52
|
};
|
|
@@ -38,7 +57,8 @@ const getStoryboard = ({
|
|
|
38
57
|
R,
|
|
39
58
|
G,
|
|
40
59
|
B
|
|
41
|
-
}
|
|
60
|
+
},
|
|
61
|
+
fileNameSuffix
|
|
42
62
|
}) => {
|
|
43
63
|
const frameWidth = 375;
|
|
44
64
|
const frameHeight = 667;
|
|
@@ -51,6 +71,7 @@ const getStoryboard = ({
|
|
|
51
71
|
<dependencies>
|
|
52
72
|
<deployment identifier="iOS"/>
|
|
53
73
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
|
|
74
|
+
<capability name="Named colors" minToolsVersion="9.0"/>
|
|
54
75
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
|
55
76
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
56
77
|
</dependencies>
|
|
@@ -63,7 +84,7 @@ const getStoryboard = ({
|
|
|
63
84
|
<rect key="frame" x="0.0" y="0.0" width="${frameWidth}" height="${frameHeight}"/>
|
|
64
85
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
65
86
|
<subviews>
|
|
66
|
-
<imageView autoresizesSubviews="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="BootSplashLogo" translatesAutoresizingMaskIntoConstraints="NO" id="3lX-Ut-9ad">
|
|
87
|
+
<imageView autoresizesSubviews="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="BootSplashLogo-${fileNameSuffix}" translatesAutoresizingMaskIntoConstraints="NO" id="3lX-Ut-9ad">
|
|
67
88
|
<rect key="frame" x="${logoX}" y="${logoY}" width="${logoWidth}" height="${logoHeight}"/>
|
|
68
89
|
<accessibility key="accessibilityConfiguration">
|
|
69
90
|
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
|
|
@@ -71,7 +92,7 @@ const getStoryboard = ({
|
|
|
71
92
|
</imageView>
|
|
72
93
|
</subviews>
|
|
73
94
|
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
|
|
74
|
-
<color key="backgroundColor"
|
|
95
|
+
<color key="backgroundColor" name="BootSplashBackground-${fileNameSuffix}"/>
|
|
75
96
|
<constraints>
|
|
76
97
|
<constraint firstItem="3lX-Ut-9ad" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="Fh9-Fy-1nT"/>
|
|
77
98
|
<constraint firstItem="3lX-Ut-9ad" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="nvB-Ic-PnI"/>
|
|
@@ -84,60 +105,58 @@ const getStoryboard = ({
|
|
|
84
105
|
</scene>
|
|
85
106
|
</scenes>
|
|
86
107
|
<resources>
|
|
87
|
-
<image name="BootSplashLogo" width="${logoWidth}" height="${logoHeight}"/>
|
|
108
|
+
<image name="BootSplashLogo-${fileNameSuffix}" width="${logoWidth}" height="${logoHeight}"/>
|
|
109
|
+
<namedColor name="BootSplashBackground-${fileNameSuffix}">
|
|
110
|
+
<color red="${R}" green="${G}" blue="${B}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
111
|
+
</namedColor>
|
|
88
112
|
</resources>
|
|
89
113
|
</document>
|
|
90
114
|
`;
|
|
91
115
|
};
|
|
92
|
-
export const addFileToXcodeProject = filePath => {
|
|
93
|
-
const projectRoot = findProjectRoot(workingPath);
|
|
94
|
-
const pbxprojectPath = IOSConfig.Paths.getPBXProjectPath(projectRoot);
|
|
95
|
-
const project = IOSConfig.XcodeUtils.getPbxproj(projectRoot);
|
|
96
|
-
const xcodeProjectPath = IOSConfig.Paths.getXcodeProjectPath(projectRoot);
|
|
97
|
-
IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
98
|
-
filepath: filePath,
|
|
99
|
-
groupName: path.parse(xcodeProjectPath).name,
|
|
100
|
-
project,
|
|
101
|
-
isBuildFile: true
|
|
102
|
-
});
|
|
103
|
-
hfs.write(pbxprojectPath, project.writeSync());
|
|
104
|
-
logWrite(pbxprojectPath);
|
|
105
|
-
};
|
|
106
116
|
|
|
107
117
|
// Freely inspired by https://github.com/humanwhocodes/humanfs
|
|
108
118
|
export const hfs = {
|
|
109
119
|
buffer: path => fs.readFileSync(path),
|
|
110
120
|
exists: path => fs.existsSync(path),
|
|
121
|
+
isDir: path => fs.lstatSync(path).isDirectory(),
|
|
111
122
|
json: path => JSON.parse(fs.readFileSync(path, "utf-8")),
|
|
112
123
|
readDir: path => fs.readdirSync(path, "utf-8"),
|
|
113
124
|
realPath: path => fs.realpathSync(path, "utf-8"),
|
|
114
125
|
rm: path => fs.rmSync(path, {
|
|
115
|
-
force: true
|
|
126
|
+
force: true,
|
|
127
|
+
recursive: true
|
|
116
128
|
}),
|
|
117
129
|
text: path => fs.readFileSync(path, "utf-8"),
|
|
130
|
+
copy: (src, dest) => {
|
|
131
|
+
if (hfs.isDir(src) || !hfs.exists(dest)) {
|
|
132
|
+
return fs.copySync(src, dest, {
|
|
133
|
+
overwrite: true
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const srcBuffer = fs.readFileSync(src);
|
|
137
|
+
const destBuffer = fs.readFileSync(dest);
|
|
138
|
+
if (!srcBuffer.equals(destBuffer)) {
|
|
139
|
+
return fs.copySync(src, dest, {
|
|
140
|
+
overwrite: true
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
},
|
|
118
144
|
ensureDir: dir => {
|
|
119
145
|
fs.mkdirSync(dir, {
|
|
120
146
|
recursive: true
|
|
121
147
|
});
|
|
122
148
|
},
|
|
123
|
-
write: (
|
|
124
|
-
const trimmed =
|
|
125
|
-
fs.writeFileSync(
|
|
149
|
+
write: (path, content) => {
|
|
150
|
+
const trimmed = content.trim();
|
|
151
|
+
fs.writeFileSync(path, trimmed === "" ? trimmed : trimmed + "\n", "utf-8");
|
|
126
152
|
}
|
|
127
153
|
};
|
|
128
|
-
export const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
title: (emoji, text) => console.log(`\n${emoji} ${pc.underline(pc.bold(text))}`),
|
|
132
|
-
warn: text => console.log(pc.yellow(`⚠️ ${text}`))
|
|
154
|
+
export const writeJson = (filePath, content) => {
|
|
155
|
+
hfs.write(filePath, JSON.stringify(content, null, 2));
|
|
156
|
+
log.write(filePath);
|
|
133
157
|
};
|
|
134
|
-
export const
|
|
135
|
-
|
|
136
|
-
hfs.write(file, JSON.stringify(json, null, 2));
|
|
137
|
-
logWrite(file);
|
|
138
|
-
};
|
|
139
|
-
export const readXml = file => {
|
|
140
|
-
const xml = hfs.text(file);
|
|
158
|
+
export const readXml = filePath => {
|
|
159
|
+
const xml = hfs.text(filePath);
|
|
141
160
|
const {
|
|
142
161
|
indent
|
|
143
162
|
} = detectIndent(xml);
|
|
@@ -149,8 +168,8 @@ export const readXml = file => {
|
|
|
149
168
|
formatOptions
|
|
150
169
|
};
|
|
151
170
|
};
|
|
152
|
-
export const writeXml = (
|
|
153
|
-
const formatted = formatXml(
|
|
171
|
+
export const writeXml = (filePath, content, options) => {
|
|
172
|
+
const formatted = formatXml(content, {
|
|
154
173
|
collapseContent: true,
|
|
155
174
|
forceSelfClosingEmptyTag: true,
|
|
156
175
|
indentation: " ",
|
|
@@ -158,11 +177,11 @@ export const writeXml = (file, xml, options) => {
|
|
|
158
177
|
whiteSpaceAtEndOfSelfclosingTag: true,
|
|
159
178
|
...options
|
|
160
179
|
});
|
|
161
|
-
hfs.write(
|
|
162
|
-
|
|
180
|
+
hfs.write(filePath, formatted);
|
|
181
|
+
log.write(filePath);
|
|
163
182
|
};
|
|
164
|
-
export const readHtml =
|
|
165
|
-
const html = hfs.text(
|
|
183
|
+
export const readHtml = filePath => {
|
|
184
|
+
const html = hfs.text(filePath);
|
|
166
185
|
const {
|
|
167
186
|
type,
|
|
168
187
|
amount
|
|
@@ -176,30 +195,52 @@ export const readHtml = file => {
|
|
|
176
195
|
formatOptions
|
|
177
196
|
};
|
|
178
197
|
};
|
|
179
|
-
export const writeHtml = async (
|
|
180
|
-
const formatted = await prettier.format(
|
|
198
|
+
export const writeHtml = async (filePath, content, options) => {
|
|
199
|
+
const formatted = await prettier.format(content, {
|
|
181
200
|
parser: "html",
|
|
182
201
|
plugins: [htmlPlugin, cssPlugin],
|
|
183
202
|
tabWidth: 2,
|
|
184
203
|
useTabs: false,
|
|
185
204
|
...options
|
|
186
205
|
});
|
|
187
|
-
hfs.write(
|
|
188
|
-
|
|
206
|
+
hfs.write(filePath, formatted);
|
|
207
|
+
log.write(filePath);
|
|
189
208
|
};
|
|
190
|
-
|
|
191
|
-
hfs.readDir(dir).filter(file => file.
|
|
209
|
+
const cleanIOS = dir => {
|
|
210
|
+
hfs.readDir(dir).filter(file => file === "Colors.xcassets" || file === "Images.xcassets").map(file => path.join(dir, file)).flatMap(dir => hfs.readDir(dir).filter(file => file.startsWith("BootSplash")).map(file => path.join(dir, file))).forEach(file => {
|
|
211
|
+
hfs.rm(file);
|
|
212
|
+
});
|
|
192
213
|
};
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}) => {
|
|
214
|
+
const getImageBase64 = async (image, width) => {
|
|
215
|
+
if (image == null) {
|
|
216
|
+
return "";
|
|
217
|
+
}
|
|
198
218
|
const buffer = await image.clone().resize(width).png({
|
|
199
219
|
quality: 100
|
|
200
220
|
}).toBuffer();
|
|
201
|
-
|
|
202
|
-
|
|
221
|
+
return buffer.toString("base64");
|
|
222
|
+
};
|
|
223
|
+
const getFileNameSuffix = async ({
|
|
224
|
+
background,
|
|
225
|
+
brand,
|
|
226
|
+
brandWidth,
|
|
227
|
+
darkBackground,
|
|
228
|
+
darkBrand,
|
|
229
|
+
darkLogo,
|
|
230
|
+
logo,
|
|
231
|
+
logoWidth
|
|
232
|
+
}) => {
|
|
233
|
+
const [logoHash, darkLogoHash, brandHash, darkBrandHash] = await Promise.all([getImageBase64(logo, logoWidth), getImageBase64(darkLogo, logoWidth), getImageBase64(brand, brandWidth), getImageBase64(darkBrand, brandWidth)]);
|
|
234
|
+
const record = {
|
|
235
|
+
background: background.hex,
|
|
236
|
+
darkBackground: darkBackground?.hex ?? "",
|
|
237
|
+
logo: logoHash,
|
|
238
|
+
darkLogo: darkLogoHash,
|
|
239
|
+
brand: brandHash,
|
|
240
|
+
darkBrand: darkBrandHash
|
|
241
|
+
};
|
|
242
|
+
const stableKey = Object.keys(record).sort().map(key => record[key]).join();
|
|
243
|
+
return murmurhash(stableKey);
|
|
203
244
|
};
|
|
204
245
|
const ensureSupportedFormat = async (name, image) => {
|
|
205
246
|
if (image == null) {
|
|
@@ -213,46 +254,85 @@ const ensureSupportedFormat = async (name, image) => {
|
|
|
213
254
|
process.exit(1);
|
|
214
255
|
}
|
|
215
256
|
};
|
|
216
|
-
const
|
|
257
|
+
const getAndroidOutputPath = ({
|
|
258
|
+
android,
|
|
259
|
+
assetsOutputPath,
|
|
217
260
|
brandHeight,
|
|
218
261
|
brandWidth,
|
|
219
262
|
flavor,
|
|
263
|
+
isExpo,
|
|
220
264
|
logoHeight,
|
|
221
|
-
logoWidth
|
|
265
|
+
logoWidth,
|
|
266
|
+
platforms
|
|
222
267
|
}) => {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
log.warn(`No ${path.relative(workingPath, androidResPath)} directory found. Skipping Android assets generation…`);
|
|
226
|
-
} else if (logoWidth > 288 || logoHeight > 288) {
|
|
227
|
-
log.warn("Logo size exceeding 288x288dp will be cropped by Android. Skipping Android assets generation…");
|
|
228
|
-
} else if (brandHeight > 80 || brandWidth > 200) {
|
|
229
|
-
log.warn("Brand size exceeding 200x80dp will be cropped by Android. Skipping Android assets generation…");
|
|
230
|
-
} else {
|
|
231
|
-
if (logoWidth > 192 || logoHeight > 192) {
|
|
232
|
-
log.warn(`Logo size exceeds 192x192dp. It might be cropped by Android.`);
|
|
233
|
-
}
|
|
234
|
-
return androidResPath;
|
|
268
|
+
if (!platforms.includes("android")) {
|
|
269
|
+
return;
|
|
235
270
|
}
|
|
271
|
+
if (isExpo) {
|
|
272
|
+
return path.resolve(assetsOutputPath, "android");
|
|
273
|
+
}
|
|
274
|
+
if (android == null) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const androidOutputPath = path.resolve(android.sourceDir, android.appName, "src", flavor, "res");
|
|
278
|
+
if (!hfs.exists(androidOutputPath)) {
|
|
279
|
+
return log.warn(`No ${path.relative(workingPath, androidOutputPath)} directory found. Skipping Android assets generation…`);
|
|
280
|
+
}
|
|
281
|
+
if (logoWidth > 288 || logoHeight > 288) {
|
|
282
|
+
return log.warn("Logo size exceeding 288x288dp will be cropped by Android. Skipping Android assets generation…");
|
|
283
|
+
}
|
|
284
|
+
if (brandWidth > 200 || brandHeight > 80) {
|
|
285
|
+
return log.warn("Brand size exceeding 200x80dp will be cropped by Android. Skipping Android assets generation…");
|
|
286
|
+
}
|
|
287
|
+
if (logoWidth > 192 || logoHeight > 192) {
|
|
288
|
+
log.warn("Logo size exceeds 192x192dp. It might be cropped by Android.");
|
|
289
|
+
}
|
|
290
|
+
return androidOutputPath;
|
|
236
291
|
};
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
292
|
+
const getIOSOutputPath = ({
|
|
293
|
+
assetsOutputPath,
|
|
294
|
+
ios,
|
|
295
|
+
isExpo,
|
|
296
|
+
platforms
|
|
297
|
+
}) => {
|
|
298
|
+
if (!platforms.includes("ios")) {
|
|
240
299
|
return;
|
|
241
300
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
return
|
|
301
|
+
if (isExpo) {
|
|
302
|
+
return path.resolve(assetsOutputPath, "ios");
|
|
303
|
+
}
|
|
304
|
+
if (ios == null) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (ios.xcodeProject == null) {
|
|
308
|
+
return log.warn("No Xcode project found. Skipping iOS assets generation…");
|
|
309
|
+
}
|
|
310
|
+
const iosOutputPath = path.resolve(ios.sourceDir, ios.xcodeProject.name).replace(/\.(xcodeproj|xcworkspace)$/, "");
|
|
311
|
+
if (!hfs.exists(iosOutputPath)) {
|
|
312
|
+
return log.warn(`No ${path.relative(workingPath, iosOutputPath)} directory found. Skipping iOS assets generation…`);
|
|
247
313
|
}
|
|
314
|
+
return iosOutputPath;
|
|
248
315
|
};
|
|
249
|
-
const getHtmlTemplatePath =
|
|
316
|
+
const getHtmlTemplatePath = ({
|
|
317
|
+
html,
|
|
318
|
+
platforms
|
|
319
|
+
}) => {
|
|
320
|
+
if (!platforms.includes("web")) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
250
323
|
const htmlTemplatePath = path.resolve(workingPath, html);
|
|
251
324
|
if (!hfs.exists(htmlTemplatePath)) {
|
|
252
|
-
log.warn(`No ${path.relative(workingPath, htmlTemplatePath)} file found. Skipping HTML + CSS generation…`);
|
|
253
|
-
} else {
|
|
254
|
-
return htmlTemplatePath;
|
|
325
|
+
return log.warn(`No ${path.relative(workingPath, htmlTemplatePath)} file found. Skipping HTML + CSS generation…`);
|
|
255
326
|
}
|
|
327
|
+
return htmlTemplatePath;
|
|
328
|
+
};
|
|
329
|
+
export const getImageHeight = (image, width) => {
|
|
330
|
+
if (image == null) {
|
|
331
|
+
return Promise.resolve(0);
|
|
332
|
+
}
|
|
333
|
+
return image.clone().resize(width).toBuffer().then(buffer => sharp(buffer).metadata()).then(({
|
|
334
|
+
height = 0
|
|
335
|
+
}) => Math.round(height));
|
|
256
336
|
};
|
|
257
337
|
const requireAddon = () => {
|
|
258
338
|
try {
|
|
@@ -270,9 +350,12 @@ export const generate = async ({
|
|
|
270
350
|
licenseKey,
|
|
271
351
|
...args
|
|
272
352
|
}) => {
|
|
353
|
+
const isExpo = getExpoConfig(projectRoot, {
|
|
354
|
+
skipSDKVersionRequirement: true
|
|
355
|
+
}).exp.sdkVersion != null;
|
|
273
356
|
const [nodeStringVersion = ""] = process.versions.node.split(".");
|
|
274
|
-
const nodeVersion = parseInt(nodeStringVersion, 10);
|
|
275
|
-
if (!isNaN(nodeVersion) && nodeVersion < 18) {
|
|
357
|
+
const nodeVersion = Number.parseInt(nodeStringVersion, 10);
|
|
358
|
+
if (!Number.isNaN(nodeVersion) && nodeVersion < 18) {
|
|
276
359
|
log.error("Requires Node 18 (or higher)");
|
|
277
360
|
process.exit(1);
|
|
278
361
|
}
|
|
@@ -280,7 +363,7 @@ export const generate = async ({
|
|
|
280
363
|
const darkLogoPath = args.darkLogo != null ? path.resolve(workingPath, args.darkLogo) : undefined;
|
|
281
364
|
const brandPath = args.brand != null ? path.resolve(workingPath, args.brand) : undefined;
|
|
282
365
|
const darkBrandPath = args.darkBrand != null ? path.resolve(workingPath, args.darkBrand) : undefined;
|
|
283
|
-
const assetsOutputPath =
|
|
366
|
+
const assetsOutputPath = path.resolve(workingPath, args.assetsOutput);
|
|
284
367
|
const logo = sharp(logoPath);
|
|
285
368
|
const darkLogo = darkLogoPath != null ? sharp(darkLogoPath) : undefined;
|
|
286
369
|
const brand = brandPath != null ? sharp(brandPath) : undefined;
|
|
@@ -291,7 +374,7 @@ export const generate = async ({
|
|
|
291
374
|
const darkBackground = args.darkBackground != null ? parseColor(args.darkBackground) : undefined;
|
|
292
375
|
const executeAddon = brand != null || darkBackground != null || darkLogo != null || darkBrand != null;
|
|
293
376
|
if (licenseKey != null && !executeAddon) {
|
|
294
|
-
log.warn(
|
|
377
|
+
log.warn("You specified a license key but none of the options that requires it.");
|
|
295
378
|
}
|
|
296
379
|
if (licenseKey == null && executeAddon) {
|
|
297
380
|
const options = [brand != null ? "brand" : "", darkBackground != null ? "dark-background" : "", darkLogo != null ? "dark-logo" : "", darkBrand != null ? "dark-brand" : ""].filter(option => option !== "").map(option => `--${option}`).join(", ");
|
|
@@ -306,49 +389,48 @@ export const generate = async ({
|
|
|
306
389
|
await ensureSupportedFormat("Dark logo", darkLogo);
|
|
307
390
|
await ensureSupportedFormat("Brand", brand);
|
|
308
391
|
await ensureSupportedFormat("Dark brand", darkBrand);
|
|
309
|
-
const logoHeight = await logo
|
|
310
|
-
|
|
311
|
-
}) => Math.round(height));
|
|
312
|
-
const brandHeight = (await brand?.clone().resize(brandWidth).toBuffer().then(buffer => sharp(buffer).metadata()).then(({
|
|
313
|
-
height = 0
|
|
314
|
-
}) => Math.round(height))) ?? 0;
|
|
392
|
+
const logoHeight = await getImageHeight(logo, logoWidth);
|
|
393
|
+
const brandHeight = await getImageHeight(brand, brandWidth);
|
|
315
394
|
if (logoWidth < args.logoWidth) {
|
|
316
395
|
log.warn(`Logo width must be a multiple of 2. It has been rounded to ${logoWidth}dp.`);
|
|
317
396
|
}
|
|
318
397
|
if (brandWidth < args.brandWidth) {
|
|
319
398
|
log.warn(`Brand width must be a multiple of 2. It has been rounded to ${brandWidth}dp.`);
|
|
320
399
|
}
|
|
321
|
-
const
|
|
400
|
+
const fileNameSuffix = await getFileNameSuffix({
|
|
401
|
+
background,
|
|
402
|
+
brand,
|
|
403
|
+
brandWidth,
|
|
404
|
+
darkBackground,
|
|
405
|
+
darkBrand,
|
|
406
|
+
darkLogo,
|
|
407
|
+
logo,
|
|
408
|
+
logoWidth
|
|
409
|
+
});
|
|
410
|
+
const androidOutputPath = getAndroidOutputPath({
|
|
411
|
+
android,
|
|
412
|
+
assetsOutputPath,
|
|
322
413
|
brandHeight,
|
|
323
414
|
brandWidth,
|
|
324
415
|
flavor,
|
|
416
|
+
isExpo,
|
|
325
417
|
logoHeight,
|
|
326
|
-
logoWidth
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
const
|
|
330
|
-
|
|
418
|
+
logoWidth,
|
|
419
|
+
platforms
|
|
420
|
+
});
|
|
421
|
+
const iosOutputPath = getIOSOutputPath({
|
|
422
|
+
assetsOutputPath,
|
|
423
|
+
ios,
|
|
424
|
+
isExpo,
|
|
425
|
+
platforms
|
|
426
|
+
});
|
|
427
|
+
const htmlTemplatePath = getHtmlTemplatePath({
|
|
428
|
+
html,
|
|
429
|
+
platforms
|
|
430
|
+
});
|
|
431
|
+
if (androidOutputPath != null) {
|
|
331
432
|
log.title("🤖", "Android");
|
|
332
|
-
|
|
333
|
-
hfs.ensureDir(valuesPath);
|
|
334
|
-
const colorsXmlPath = path.resolve(valuesPath, "colors.xml");
|
|
335
|
-
const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
|
|
336
|
-
if (hfs.exists(colorsXmlPath)) {
|
|
337
|
-
const {
|
|
338
|
-
root,
|
|
339
|
-
formatOptions
|
|
340
|
-
} = readXml(colorsXmlPath);
|
|
341
|
-
const nextColor = parseHtml(colorsXmlEntry);
|
|
342
|
-
const prevColor = root.querySelector('color[name="bootsplash_background"]');
|
|
343
|
-
if (prevColor != null) {
|
|
344
|
-
prevColor.replaceWith(nextColor);
|
|
345
|
-
} else {
|
|
346
|
-
root.querySelector("resources")?.appendChild(nextColor);
|
|
347
|
-
}
|
|
348
|
-
writeXml(colorsXmlPath, root.toString(), formatOptions);
|
|
349
|
-
} else {
|
|
350
|
-
writeXml(colorsXmlPath, `<resources>${colorsXmlEntry}</resources>`);
|
|
351
|
-
}
|
|
433
|
+
hfs.ensureDir(androidOutputPath);
|
|
352
434
|
await Promise.all([{
|
|
353
435
|
ratio: 1,
|
|
354
436
|
suffix: "mdpi"
|
|
@@ -368,7 +450,7 @@ export const generate = async ({
|
|
|
368
450
|
ratio,
|
|
369
451
|
suffix
|
|
370
452
|
}) => {
|
|
371
|
-
const drawableDirPath = path.resolve(
|
|
453
|
+
const drawableDirPath = path.resolve(androidOutputPath, `drawable-${suffix}`);
|
|
372
454
|
hfs.ensureDir(drawableDirPath);
|
|
373
455
|
|
|
374
456
|
// https://developer.android.com/develop/ui/views/launch/splash-screen#dimensions
|
|
@@ -394,44 +476,71 @@ export const generate = async ({
|
|
|
394
476
|
}]).png({
|
|
395
477
|
quality: 100
|
|
396
478
|
}).toFile(filePath)).then(() => {
|
|
397
|
-
|
|
479
|
+
log.write(filePath, {
|
|
398
480
|
width: canvasSize,
|
|
399
481
|
height: canvasSize
|
|
400
482
|
});
|
|
401
483
|
});
|
|
402
484
|
}));
|
|
485
|
+
if (!isExpo) {
|
|
486
|
+
const valuesPath = path.resolve(androidOutputPath, "values");
|
|
487
|
+
hfs.ensureDir(valuesPath);
|
|
488
|
+
const colorsXmlPath = path.resolve(valuesPath, "colors.xml");
|
|
489
|
+
const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
|
|
490
|
+
if (hfs.exists(colorsXmlPath)) {
|
|
491
|
+
const {
|
|
492
|
+
root,
|
|
493
|
+
formatOptions
|
|
494
|
+
} = readXml(colorsXmlPath);
|
|
495
|
+
const nextColor = parseHtml(colorsXmlEntry);
|
|
496
|
+
const prevColor = root.querySelector('color[name="bootsplash_background"]');
|
|
497
|
+
if (prevColor != null) {
|
|
498
|
+
prevColor.replaceWith(nextColor);
|
|
499
|
+
} else {
|
|
500
|
+
root.querySelector("resources")?.appendChild(nextColor);
|
|
501
|
+
}
|
|
502
|
+
writeXml(colorsXmlPath, root.toString(), formatOptions);
|
|
503
|
+
} else {
|
|
504
|
+
writeXml(colorsXmlPath, `<resources>${colorsXmlEntry}</resources>`);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
403
507
|
}
|
|
404
|
-
if (
|
|
508
|
+
if (iosOutputPath != null) {
|
|
405
509
|
log.title("🍏", "iOS");
|
|
406
|
-
|
|
510
|
+
hfs.ensureDir(iosOutputPath);
|
|
511
|
+
cleanIOS(iosOutputPath);
|
|
512
|
+
const storyboardPath = path.resolve(iosOutputPath, "BootSplash.storyboard");
|
|
513
|
+
const colorsSetPath = path.resolve(iosOutputPath, "Colors.xcassets", `BootSplashBackground-${fileNameSuffix}.colorset`);
|
|
514
|
+
const imageSetPath = path.resolve(iosOutputPath, "Images.xcassets", `BootSplashLogo-${fileNameSuffix}.imageset`);
|
|
515
|
+
hfs.ensureDir(colorsSetPath);
|
|
516
|
+
hfs.ensureDir(imageSetPath);
|
|
407
517
|
writeXml(storyboardPath, getStoryboard({
|
|
408
518
|
logoHeight,
|
|
409
519
|
logoWidth,
|
|
410
|
-
background: background.rgb
|
|
520
|
+
background: background.rgb,
|
|
521
|
+
fileNameSuffix
|
|
411
522
|
}), {
|
|
412
523
|
whiteSpaceAtEndOfSelfclosingTag: false
|
|
413
524
|
});
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
name: "bootsplash_logo",
|
|
432
|
-
image: logo,
|
|
433
|
-
width: logoWidth
|
|
525
|
+
writeJson(path.resolve(colorsSetPath, "Contents.json"), {
|
|
526
|
+
colors: [{
|
|
527
|
+
idiom: "universal",
|
|
528
|
+
color: {
|
|
529
|
+
"color-space": "srgb",
|
|
530
|
+
components: {
|
|
531
|
+
blue: background.rgb.B,
|
|
532
|
+
green: background.rgb.G,
|
|
533
|
+
red: background.rgb.R,
|
|
534
|
+
alpha: "1.000"
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}],
|
|
538
|
+
info: {
|
|
539
|
+
author: "xcode",
|
|
540
|
+
version: 1
|
|
541
|
+
}
|
|
434
542
|
});
|
|
543
|
+
const logoFileName = `logo-${fileNameSuffix}`;
|
|
435
544
|
writeJson(path.resolve(imageSetPath, "Contents.json"), {
|
|
436
545
|
images: [{
|
|
437
546
|
idiom: "universal",
|
|
@@ -471,12 +580,44 @@ export const generate = async ({
|
|
|
471
580
|
width,
|
|
472
581
|
height
|
|
473
582
|
}) => {
|
|
474
|
-
|
|
583
|
+
log.write(filePath, {
|
|
475
584
|
width,
|
|
476
585
|
height
|
|
477
586
|
});
|
|
478
587
|
});
|
|
479
588
|
}));
|
|
589
|
+
if (!isExpo) {
|
|
590
|
+
const infoPlistPath = path.resolve(iosOutputPath, "Info.plist");
|
|
591
|
+
const infoPlist = plist.parse(hfs.text(infoPlistPath));
|
|
592
|
+
infoPlist["UILaunchStoryboardName"] = "BootSplash";
|
|
593
|
+
const formatted = formatXml(plist.build(infoPlist), {
|
|
594
|
+
collapseContent: true,
|
|
595
|
+
forceSelfClosingEmptyTag: false,
|
|
596
|
+
indentation: "\t",
|
|
597
|
+
lineSeparator: "\n",
|
|
598
|
+
whiteSpaceAtEndOfSelfclosingTag: false
|
|
599
|
+
}).replace(/<string\/>/gm, "<string></string>").replace(/^\t/gm, "");
|
|
600
|
+
hfs.write(infoPlistPath, formatted);
|
|
601
|
+
log.write(infoPlistPath);
|
|
602
|
+
const pbxprojectPath = Expo.IOSConfig.Paths.getPBXProjectPath(projectRoot);
|
|
603
|
+
const xcodeProjectPath = Expo.IOSConfig.Paths.getXcodeProjectPath(projectRoot);
|
|
604
|
+
const project = Expo.IOSConfig.XcodeUtils.getPbxproj(projectRoot);
|
|
605
|
+
const projectName = path.basename(iosOutputPath);
|
|
606
|
+
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
607
|
+
filepath: path.join(projectName, "BootSplash.storyboard"),
|
|
608
|
+
groupName: path.parse(xcodeProjectPath).name,
|
|
609
|
+
project,
|
|
610
|
+
isBuildFile: true
|
|
611
|
+
});
|
|
612
|
+
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
613
|
+
filepath: path.join(projectName, "Colors.xcassets"),
|
|
614
|
+
groupName: path.parse(xcodeProjectPath).name,
|
|
615
|
+
project,
|
|
616
|
+
isBuildFile: true
|
|
617
|
+
});
|
|
618
|
+
hfs.write(pbxprojectPath, project.writeSync());
|
|
619
|
+
log.write(pbxprojectPath);
|
|
620
|
+
}
|
|
480
621
|
}
|
|
481
622
|
if (htmlTemplatePath != null) {
|
|
482
623
|
log.title("🌐", "Web");
|
|
@@ -531,55 +672,55 @@ export const generate = async ({
|
|
|
531
672
|
}
|
|
532
673
|
await writeHtml(htmlTemplatePath, root.toString(), formatOptions);
|
|
533
674
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
675
|
+
log.title("📄", "Assets");
|
|
676
|
+
hfs.ensureDir(assetsOutputPath);
|
|
677
|
+
writeJson(path.resolve(assetsOutputPath, "manifest.json"), {
|
|
678
|
+
background: background.hex,
|
|
679
|
+
logo: {
|
|
680
|
+
width: logoWidth,
|
|
681
|
+
height: logoHeight
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
await Promise.all([{
|
|
685
|
+
ratio: 1,
|
|
686
|
+
suffix: ""
|
|
687
|
+
}, {
|
|
688
|
+
ratio: 1.5,
|
|
689
|
+
suffix: "@1,5x"
|
|
690
|
+
}, {
|
|
691
|
+
ratio: 2,
|
|
692
|
+
suffix: "@2x"
|
|
693
|
+
}, {
|
|
694
|
+
ratio: 3,
|
|
695
|
+
suffix: "@3x"
|
|
696
|
+
}, {
|
|
697
|
+
ratio: 4,
|
|
698
|
+
suffix: "@4x"
|
|
699
|
+
}].map(({
|
|
700
|
+
ratio,
|
|
701
|
+
suffix
|
|
702
|
+
}) => {
|
|
703
|
+
const filePath = path.resolve(assetsOutputPath, `logo${suffix}.png`);
|
|
704
|
+
return logo.clone().resize(Math.round(logoWidth * ratio)).png({
|
|
705
|
+
quality: 100
|
|
706
|
+
}).toFile(filePath).then(({
|
|
707
|
+
width,
|
|
708
|
+
height
|
|
562
709
|
}) => {
|
|
563
|
-
|
|
564
|
-
return logo.clone().resize(Math.round(logoWidth * ratio)).png({
|
|
565
|
-
quality: 100
|
|
566
|
-
}).toFile(filePath).then(({
|
|
710
|
+
log.write(filePath, {
|
|
567
711
|
width,
|
|
568
712
|
height
|
|
569
|
-
}) => {
|
|
570
|
-
logWrite(filePath, {
|
|
571
|
-
width,
|
|
572
|
-
height
|
|
573
|
-
});
|
|
574
713
|
});
|
|
575
|
-
})
|
|
576
|
-
}
|
|
714
|
+
});
|
|
715
|
+
}));
|
|
577
716
|
if (licenseKey != null && executeAddon) {
|
|
578
717
|
const addon = requireAddon();
|
|
579
718
|
await addon?.execute({
|
|
580
719
|
licenseKey,
|
|
581
|
-
|
|
582
|
-
|
|
720
|
+
isExpo,
|
|
721
|
+
fileNameSuffix,
|
|
722
|
+
androidOutputPath,
|
|
723
|
+
iosOutputPath,
|
|
583
724
|
htmlTemplatePath,
|
|
584
725
|
assetsOutputPath,
|
|
585
726
|
logoHeight,
|
|
@@ -598,12 +739,240 @@ export const generate = async ({
|
|
|
598
739
|
darkBrand
|
|
599
740
|
});
|
|
600
741
|
} else {
|
|
601
|
-
log
|
|
742
|
+
console.log(`
|
|
602
743
|
${pc.blue("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓")}
|
|
603
744
|
${pc.blue("┃")} 🔑 ${pc.bold("Get a license key for brand image / dark mode support")} ${pc.blue("┃")}
|
|
604
745
|
${pc.blue("┃")} ${pc.underline("https://zoontek.gumroad.com/l/bootsplash-generator")} ${pc.blue("┃")}
|
|
605
746
|
${pc.blue("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛")}`);
|
|
606
747
|
}
|
|
607
|
-
log
|
|
748
|
+
console.log(`\n💖 Thanks for using ${pc.underline("react-native-bootsplash")}`);
|
|
749
|
+
};
|
|
750
|
+
const withAndroidAssets = (config, props) => Expo.withDangerousMod(config, ["android", config => {
|
|
751
|
+
const {
|
|
752
|
+
assetsDir = "assets/bootsplash"
|
|
753
|
+
} = props;
|
|
754
|
+
const {
|
|
755
|
+
platformProjectRoot
|
|
756
|
+
} = config.modRequest;
|
|
757
|
+
const srcDir = path.resolve(workingPath, assetsDir, "android");
|
|
758
|
+
const destDir = path.resolve(platformProjectRoot, "app", "src", "main", "res");
|
|
759
|
+
for (const drawableDir of hfs.readDir(srcDir)) {
|
|
760
|
+
const srcDrawableDir = path.join(srcDir, drawableDir);
|
|
761
|
+
const destDrawableDir = path.join(destDir, drawableDir);
|
|
762
|
+
hfs.ensureDir(destDrawableDir);
|
|
763
|
+
for (const file of hfs.readDir(srcDrawableDir)) {
|
|
764
|
+
hfs.copy(path.join(srcDrawableDir, file), path.join(destDrawableDir, file));
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
return config;
|
|
768
|
+
}]);
|
|
769
|
+
const withAndroidManifest = config => Expo.withAndroidManifest(config, config => {
|
|
770
|
+
config.modResults.manifest.application?.forEach(application => {
|
|
771
|
+
if (application.$["android:name"] === ".MainApplication") {
|
|
772
|
+
const {
|
|
773
|
+
activity
|
|
774
|
+
} = application;
|
|
775
|
+
activity?.forEach(activity => {
|
|
776
|
+
if (activity.$["android:name"] === ".MainActivity") {
|
|
777
|
+
activity.$["android:theme"] = "@style/BootTheme";
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
return config;
|
|
783
|
+
});
|
|
784
|
+
const withMainActivity = config => Expo.withMainActivity(config, config => {
|
|
785
|
+
const {
|
|
786
|
+
modResults
|
|
787
|
+
} = config;
|
|
788
|
+
const {
|
|
789
|
+
language
|
|
790
|
+
} = modResults;
|
|
791
|
+
const withImports = addImports(modResults.contents.replace(/(\/\/ )?setTheme\(R\.style\.AppTheme\)/, "// setTheme(R.style.AppTheme)"), ["android.os.Bundle", "com.zoontek.rnbootsplash.RNBootSplash"], language === "java");
|
|
792
|
+
|
|
793
|
+
// indented with 4 spaces
|
|
794
|
+
const withInit = mergeContents({
|
|
795
|
+
src: withImports,
|
|
796
|
+
comment: " //",
|
|
797
|
+
tag: "bootsplash-init",
|
|
798
|
+
offset: 0,
|
|
799
|
+
anchor: /super\.onCreate\(null\)/,
|
|
800
|
+
newSrc: " RNBootSplash.init(this, R.style.BootTheme)" + (language === "java" ? ";" : "")
|
|
801
|
+
});
|
|
802
|
+
return {
|
|
803
|
+
...config,
|
|
804
|
+
modResults: {
|
|
805
|
+
...modResults,
|
|
806
|
+
contents: withInit.contents
|
|
807
|
+
}
|
|
808
|
+
};
|
|
809
|
+
});
|
|
810
|
+
const withAndroidStyles = (config, props) => Expo.withAndroidStyles(config, async config => {
|
|
811
|
+
const {
|
|
812
|
+
assetsDir = "assets/bootsplash",
|
|
813
|
+
edgeToEdge = false
|
|
814
|
+
} = props;
|
|
815
|
+
const manifest = await hfs.json(path.resolve(workingPath, assetsDir, "manifest.json"));
|
|
816
|
+
const item = [{
|
|
817
|
+
$: {
|
|
818
|
+
name: "postBootSplashTheme"
|
|
819
|
+
},
|
|
820
|
+
_: "@style/AppTheme"
|
|
821
|
+
}, {
|
|
822
|
+
$: {
|
|
823
|
+
name: "bootSplashBackground"
|
|
824
|
+
},
|
|
825
|
+
_: "@color/bootsplash_background"
|
|
826
|
+
}, {
|
|
827
|
+
$: {
|
|
828
|
+
name: "bootSplashLogo"
|
|
829
|
+
},
|
|
830
|
+
_: "@drawable/bootsplash_logo"
|
|
831
|
+
}];
|
|
832
|
+
if (manifest.brand != null) {
|
|
833
|
+
item.push({
|
|
834
|
+
$: {
|
|
835
|
+
name: "bootSplashBrand"
|
|
836
|
+
},
|
|
837
|
+
_: "@drawable/bootsplash_brand"
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
config.modResults.resources.style?.filter(({
|
|
841
|
+
$
|
|
842
|
+
}) => $.name !== "BootTheme").push({
|
|
843
|
+
item,
|
|
844
|
+
$: {
|
|
845
|
+
name: "BootTheme",
|
|
846
|
+
parent: edgeToEdge ? "Theme.BootSplash" : "Theme.BootSplash.EdgeToEdge"
|
|
847
|
+
}
|
|
848
|
+
});
|
|
849
|
+
return config;
|
|
850
|
+
});
|
|
851
|
+
const withAndroidColors = (config, props) => Expo.withAndroidColors(config, async config => {
|
|
852
|
+
const {
|
|
853
|
+
assetsDir = "assets/bootsplash"
|
|
854
|
+
} = props;
|
|
855
|
+
const manifest = await hfs.json(path.resolve(workingPath, assetsDir, "manifest.json"));
|
|
856
|
+
config.modResults = assignColorValue(config.modResults, {
|
|
857
|
+
name: "bootsplash_background",
|
|
858
|
+
value: manifest.background
|
|
859
|
+
});
|
|
860
|
+
return config;
|
|
861
|
+
});
|
|
862
|
+
const withAndroidColorsNight = (config, props) => Expo.withAndroidColorsNight(config, async config => {
|
|
863
|
+
const {
|
|
864
|
+
assetsDir = "assets/bootsplash"
|
|
865
|
+
} = props;
|
|
866
|
+
const manifest = await hfs.json(path.resolve(workingPath, assetsDir, "manifest.json"));
|
|
867
|
+
if (manifest.darkBackground != null) {
|
|
868
|
+
config.modResults = assignColorValue(config.modResults, {
|
|
869
|
+
name: "bootsplash_background",
|
|
870
|
+
value: manifest.darkBackground
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
return config;
|
|
874
|
+
});
|
|
875
|
+
const withIOSAssets = (config, props) => Expo.withDangerousMod(config, ["ios", config => {
|
|
876
|
+
const {
|
|
877
|
+
assetsDir = "assets/bootsplash"
|
|
878
|
+
} = props;
|
|
879
|
+
const {
|
|
880
|
+
platformProjectRoot,
|
|
881
|
+
projectName = ""
|
|
882
|
+
} = config.modRequest;
|
|
883
|
+
const srcDir = path.resolve(workingPath, assetsDir, "ios");
|
|
884
|
+
const destDir = path.resolve(platformProjectRoot, projectName);
|
|
885
|
+
cleanIOS(destDir);
|
|
886
|
+
hfs.copy(path.join(srcDir, "BootSplash.storyboard"), path.join(destDir, "BootSplash.storyboard"));
|
|
887
|
+
for (const xcassetsDir of ["Colors.xcassets", "Images.xcassets"]) {
|
|
888
|
+
const srcXcassetsDir = path.join(srcDir, xcassetsDir);
|
|
889
|
+
const destXcassetsDir = path.join(destDir, xcassetsDir);
|
|
890
|
+
hfs.ensureDir(destXcassetsDir);
|
|
891
|
+
for (const file of hfs.readDir(srcXcassetsDir)) {
|
|
892
|
+
hfs.copy(path.join(srcXcassetsDir, file), path.join(destXcassetsDir, file));
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
return config;
|
|
896
|
+
}]);
|
|
897
|
+
const withAppDelegate = config => Expo.withAppDelegate(config, config => {
|
|
898
|
+
const [sdkStringVersion = ""] = config.sdkVersion?.split(".") ?? "";
|
|
899
|
+
const isAtLeastExpo51 = Number.parseInt(sdkStringVersion, 10) >= 51;
|
|
900
|
+
const {
|
|
901
|
+
modResults
|
|
902
|
+
} = config;
|
|
903
|
+
const {
|
|
904
|
+
language
|
|
905
|
+
} = modResults;
|
|
906
|
+
if (language !== "objc" && language !== "objcpp") {
|
|
907
|
+
throw new Error(`Cannot modify the project AppDelegate as it's not in a supported language: ${language}`);
|
|
908
|
+
}
|
|
909
|
+
const withHeader = mergeContents({
|
|
910
|
+
src: modResults.contents,
|
|
911
|
+
comment: "//",
|
|
912
|
+
tag: "bootsplash-header",
|
|
913
|
+
offset: 1,
|
|
914
|
+
anchor: /#import "AppDelegate\.h"/,
|
|
915
|
+
newSrc: '#import "RNBootSplash.h"'
|
|
916
|
+
});
|
|
917
|
+
const withRootView = mergeContents({
|
|
918
|
+
src: withHeader.contents,
|
|
919
|
+
comment: "//",
|
|
920
|
+
tag: "bootsplash-init",
|
|
921
|
+
offset: 0,
|
|
922
|
+
anchor: /@end/,
|
|
923
|
+
newSrc: isAtLeastExpo51 ? dedent`
|
|
924
|
+
- (void)customizeRootView:(RCTRootView *)rootView {
|
|
925
|
+
[RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];
|
|
926
|
+
}
|
|
927
|
+
` : dedent`
|
|
928
|
+
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initProps:(NSDictionary *)initProps {
|
|
929
|
+
UIView *rootView = [super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
|
|
930
|
+
[RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];
|
|
931
|
+
return rootView;
|
|
932
|
+
}
|
|
933
|
+
`
|
|
934
|
+
});
|
|
935
|
+
return {
|
|
936
|
+
...config,
|
|
937
|
+
modResults: {
|
|
938
|
+
...modResults,
|
|
939
|
+
contents: withRootView.contents
|
|
940
|
+
}
|
|
941
|
+
};
|
|
942
|
+
});
|
|
943
|
+
const withInfoPlist = config => Expo.withInfoPlist(config, config => {
|
|
944
|
+
config.modResults["UILaunchStoryboardName"] = "BootSplash";
|
|
945
|
+
return config;
|
|
946
|
+
});
|
|
947
|
+
const withXcodeProject = config => Expo.withXcodeProject(config, config => {
|
|
948
|
+
const {
|
|
949
|
+
projectName = ""
|
|
950
|
+
} = config.modRequest;
|
|
951
|
+
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
952
|
+
filepath: path.join(projectName, "BootSplash.storyboard"),
|
|
953
|
+
groupName: projectName,
|
|
954
|
+
project: config.modResults,
|
|
955
|
+
isBuildFile: true
|
|
956
|
+
});
|
|
957
|
+
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
958
|
+
filepath: path.join(projectName, "Colors.xcassets"),
|
|
959
|
+
groupName: projectName,
|
|
960
|
+
project: config.modResults,
|
|
961
|
+
isBuildFile: true
|
|
962
|
+
});
|
|
963
|
+
return config;
|
|
964
|
+
});
|
|
965
|
+
export const withGenerate = (config, props = {}) => {
|
|
966
|
+
const plugins = [];
|
|
967
|
+
const {
|
|
968
|
+
platforms = []
|
|
969
|
+
} = config;
|
|
970
|
+
if (platforms.includes("android")) {
|
|
971
|
+
plugins.push(withAndroidAssets, withAndroidManifest, withMainActivity, withAndroidStyles, withAndroidColors, withAndroidColorsNight);
|
|
972
|
+
}
|
|
973
|
+
if (platforms.includes("ios")) {
|
|
974
|
+
plugins.push(withIOSAssets, withAppDelegate, withInfoPlist, withXcodeProject);
|
|
975
|
+
}
|
|
976
|
+
return Expo.withPlugins(config, plugins.map(plugin => [plugin, props]));
|
|
608
977
|
};
|
|
609
978
|
//# sourceMappingURL=generate.js.map
|