react-native-bootsplash 6.3.10 → 7.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 +16 -41
- package/android/build.gradle +10 -17
- package/android/src/main/AndroidManifest.xml +1 -1
- package/android/src/main/java/com/zoontek/rnbootsplash/RNBootSplashModuleImpl.kt +2 -2
- package/android/src/main/java/com/zoontek/rnbootsplash/RNBootSplashPackage.kt +0 -1
- package/android/src/main/java/com/zoontek/rnbootsplash/RNBootSplashQueue.kt +1 -1
- package/android/src/main/res/drawable/compat_splash_screen.xml +11 -6
- package/android/src/main/res/drawable/compat_splash_screen_oneui_4.xml +13 -6
- package/android/src/main/res/values/colors.xml +1 -3
- package/android/src/main/res/values/public.xml +0 -2
- package/android/src/main/res/values/styles.xml +13 -19
- package/android/src/main/res/values-night/styles.xml +1 -1
- package/android/src/main/res/values-v27/colors.xml +4 -0
- package/android/src/main/res/values-v27/styles.xml +1 -6
- package/android/src/main/res/values-v29/styles.xml +1 -11
- package/android/src/main/res/values-v30/styles.xml +1 -9
- package/android/src/main/res/values-v31/styles.xml +1 -1
- package/android/src/newarch/com/zoontek/rnbootsplash/RNBootSplashModule.kt +2 -2
- package/android/src/oldarch/com/zoontek/rnbootsplash/RNBootSplashModule.kt +3 -3
- package/app.plugin.js +1 -1
- package/cli.js +2 -11
- package/dist/commonjs/addon/index.js +49 -49
- package/dist/commonjs/addon/index.js.map +1 -1
- package/dist/commonjs/generate.js +811 -541
- package/dist/commonjs/generate.js.map +1 -1
- package/dist/commonjs/index.js +1 -1
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/specs/NativeRNBootSplash.js.map +1 -0
- package/dist/commonjs/{NativeRNBootSplash.web.js → specs/NativeRNBootSplash.web.js} +1 -1
- package/dist/commonjs/specs/NativeRNBootSplash.web.js.map +1 -0
- package/dist/module/addon/index.js +49 -49
- package/dist/module/addon/index.js.map +1 -1
- package/dist/module/generate.js +807 -539
- package/dist/module/generate.js.map +1 -1
- package/dist/module/index.js +1 -1
- package/dist/module/index.js.map +1 -1
- package/dist/module/specs/NativeRNBootSplash.js.map +1 -0
- package/dist/module/{NativeRNBootSplash.web.js → specs/NativeRNBootSplash.web.js} +1 -1
- package/dist/module/specs/NativeRNBootSplash.web.js.map +1 -0
- package/dist/typescript/addon/index.d.ts +8 -2
- package/dist/typescript/addon/index.d.ts.map +1 -1
- package/dist/typescript/generate.d.ts +90 -35
- package/dist/typescript/generate.d.ts.map +1 -1
- package/dist/typescript/index.d.ts +2 -2
- package/dist/typescript/index.d.ts.map +1 -1
- package/dist/typescript/{NativeRNBootSplash.d.ts → specs/NativeRNBootSplash.d.ts} +1 -1
- package/dist/typescript/specs/NativeRNBootSplash.d.ts.map +1 -0
- package/dist/typescript/{NativeRNBootSplash.web.d.ts → specs/NativeRNBootSplash.web.d.ts} +1 -1
- package/dist/typescript/specs/NativeRNBootSplash.web.d.ts.map +1 -0
- package/ios/RNBootSplash.mm +4 -10
- package/package.json +24 -29
- package/src/generate.ts +1048 -782
- package/src/index.ts +7 -7
- package/src/{NativeRNBootSplash.ts → specs/NativeRNBootSplash.ts} +1 -1
- package/src/{NativeRNBootSplash.web.ts → specs/NativeRNBootSplash.web.ts} +1 -1
- package/android/src/main/AndroidManifestNew.xml +0 -3
- package/android/src/main/res/drawable-v23/compat_splash_screen.xml +0 -19
- package/android/src/main/res/drawable-v23/compat_splash_screen_oneui_4.xml +0 -21
- package/android/src/main/res/values-v23/styles.xml +0 -13
- package/dist/commonjs/NativeRNBootSplash.js.map +0 -1
- package/dist/commonjs/NativeRNBootSplash.web.js.map +0 -1
- package/dist/commonjs/expo.js +0 -348
- package/dist/commonjs/expo.js.map +0 -1
- package/dist/module/NativeRNBootSplash.js.map +0 -1
- package/dist/module/NativeRNBootSplash.web.js.map +0 -1
- package/dist/module/expo.js +0 -341
- package/dist/module/expo.js.map +0 -1
- package/dist/typescript/NativeRNBootSplash.d.ts.map +0 -1
- package/dist/typescript/NativeRNBootSplash.web.d.ts.map +0 -1
- package/dist/typescript/expo.d.ts +0 -11
- package/dist/typescript/expo.d.ts.map +0 -1
- package/react-native.config.js +0 -101
- package/src/expo.ts +0 -439
- /package/dist/commonjs/{NativeRNBootSplash.js → specs/NativeRNBootSplash.js} +0 -0
- /package/dist/module/{NativeRNBootSplash.js → specs/NativeRNBootSplash.js} +0 -0
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.writeXmlLike = exports.writeJson = exports.
|
|
6
|
+
exports.writeXmlLike = exports.writeWebAssets = exports.writeJson = exports.writeIOSAssets = exports.writeGenericAssets = exports.writeAndroidAssets = exports.workingPath = exports.withBootSplash = exports.readXmlLike = exports.log = exports.hfs = exports.getExtras = exports.generate = void 0;
|
|
7
7
|
var Expo = _interopRequireWildcard(require("@expo/config-plugins"));
|
|
8
|
+
var _Colors = require("@expo/config-plugins/build/android/Colors");
|
|
9
|
+
var _codeMod = require("@expo/config-plugins/build/android/codeMod");
|
|
10
|
+
var _generateCode = require("@expo/config-plugins/build/utils/generateCode");
|
|
8
11
|
var _plist = _interopRequireDefault(require("@expo/plist"));
|
|
9
12
|
var _cliConfigAndroid = require("@react-native-community/cli-config-android");
|
|
10
13
|
var _cliConfigApple = require("@react-native-community/cli-config-apple");
|
|
@@ -26,13 +29,10 @@ var _util = _interopRequireDefault(require("util"));
|
|
|
26
29
|
var _xmlFormatter = _interopRequireDefault(require("xml-formatter"));
|
|
27
30
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
28
31
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
29
|
-
const
|
|
32
|
+
const PACKAGE_NAME = "react-native-bootsplash";
|
|
33
|
+
let isExpo = false;
|
|
34
|
+
const workingPath = exports.workingPath = process.env.INIT_CWD ?? process.env.PWD ?? process.cwd();
|
|
30
35
|
const projectRoot = (0, _cliTools.findProjectRoot)(workingPath);
|
|
31
|
-
const getIOSProjectConfig = (0, _cliConfigApple.getProjectConfig)({
|
|
32
|
-
platformName: "ios"
|
|
33
|
-
});
|
|
34
|
-
const ios = getIOSProjectConfig(projectRoot, {});
|
|
35
|
-
const android = (0, _cliConfigAndroid.projectConfig)(projectRoot);
|
|
36
36
|
const promisifiedExec = _util.default.promisify(_child_process.default.exec);
|
|
37
37
|
const exec = cmd => promisifiedExec(cmd).then(({
|
|
38
38
|
stdout,
|
|
@@ -40,16 +40,20 @@ const exec = cmd => promisifiedExec(cmd).then(({
|
|
|
40
40
|
}) => stdout || stderr);
|
|
41
41
|
const log = exports.log = {
|
|
42
42
|
error: text => {
|
|
43
|
-
console.log(_picocolors.default.red(`❌ ${text}`));
|
|
43
|
+
console.log(_picocolors.default.red(isExpo ? `❌ [${PACKAGE_NAME}] ${text}` : `❌ ${text}`));
|
|
44
44
|
},
|
|
45
45
|
title: (emoji, text) => {
|
|
46
|
-
|
|
46
|
+
if (!isExpo) {
|
|
47
|
+
console.log(`\n${emoji} ${_picocolors.default.underline(_picocolors.default.bold(text))}`);
|
|
48
|
+
}
|
|
47
49
|
},
|
|
48
50
|
warn: text => {
|
|
49
|
-
console.log(_picocolors.default.yellow(`⚠️
|
|
51
|
+
console.log(_picocolors.default.yellow(isExpo ? `⚠️ [${PACKAGE_NAME}] ${text}` : `⚠️ ${text}`));
|
|
50
52
|
},
|
|
51
53
|
write: (filePath, dimensions) => {
|
|
52
|
-
|
|
54
|
+
if (!isExpo) {
|
|
55
|
+
console.log(` ${_path.default.relative(workingPath, filePath)}` + (dimensions != null ? ` (${dimensions.width}x${dimensions.height})` : ""));
|
|
56
|
+
}
|
|
53
57
|
}
|
|
54
58
|
};
|
|
55
59
|
const parseColor = value => {
|
|
@@ -70,19 +74,24 @@ const parseColor = value => {
|
|
|
70
74
|
};
|
|
71
75
|
};
|
|
72
76
|
const getStoryboard = ({
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
props,
|
|
78
|
+
extras
|
|
79
|
+
}) => {
|
|
80
|
+
const {
|
|
81
|
+
background,
|
|
82
|
+
logo
|
|
83
|
+
} = props;
|
|
84
|
+
const {
|
|
85
|
+
fileNameSuffix,
|
|
86
|
+
logoHeight
|
|
87
|
+
} = extras;
|
|
88
|
+
const {
|
|
76
89
|
R,
|
|
77
90
|
G,
|
|
78
91
|
B
|
|
79
|
-
}
|
|
80
|
-
fileNameSuffix
|
|
81
|
-
}) => {
|
|
92
|
+
} = background.rgb;
|
|
82
93
|
const frameWidth = 375;
|
|
83
94
|
const frameHeight = 667;
|
|
84
|
-
const logoX = (frameWidth - logoWidth) / 2;
|
|
85
|
-
const logoY = (frameHeight - logoHeight) / 2;
|
|
86
95
|
return (0, _tsDedent.dedent)`
|
|
87
96
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
88
97
|
<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">
|
|
@@ -104,7 +113,7 @@ const getStoryboard = ({
|
|
|
104
113
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
105
114
|
<subviews>
|
|
106
115
|
<imageView autoresizesSubviews="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="BootSplashLogo-${fileNameSuffix}" translatesAutoresizingMaskIntoConstraints="NO" id="3lX-Ut-9ad">
|
|
107
|
-
<rect key="frame" x="${
|
|
116
|
+
<rect key="frame" x="${(frameWidth - logo.width) / 2}" y="${(frameHeight - logoHeight) / 2}" width="${logo.width}" height="${logoHeight}"/>
|
|
108
117
|
<accessibility key="accessibilityConfiguration">
|
|
109
118
|
<accessibilityTraits key="traits" image="YES" notEnabled="YES"/>
|
|
110
119
|
</accessibility>
|
|
@@ -124,7 +133,7 @@ const getStoryboard = ({
|
|
|
124
133
|
</scene>
|
|
125
134
|
</scenes>
|
|
126
135
|
<resources>
|
|
127
|
-
<image name="BootSplashLogo-${fileNameSuffix}" width="${
|
|
136
|
+
<image name="BootSplashLogo-${fileNameSuffix}" width="${logo.width}" height="${logoHeight}"/>
|
|
128
137
|
<namedColor name="BootSplashBackground-${fileNameSuffix}">
|
|
129
138
|
<color red="${R}" green="${G}" blue="${B}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
130
139
|
</namedColor>
|
|
@@ -146,20 +155,6 @@ const hfs = exports.hfs = {
|
|
|
146
155
|
recursive: true
|
|
147
156
|
}),
|
|
148
157
|
text: path => _fsExtra.default.readFileSync(path, "utf-8"),
|
|
149
|
-
copy: (src, dest) => {
|
|
150
|
-
if (hfs.isDir(src) || !hfs.exists(dest)) {
|
|
151
|
-
return _fsExtra.default.copySync(src, dest, {
|
|
152
|
-
overwrite: true
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
const srcBuffer = _fsExtra.default.readFileSync(src);
|
|
156
|
-
const destBuffer = _fsExtra.default.readFileSync(dest);
|
|
157
|
-
if (!srcBuffer.equals(destBuffer)) {
|
|
158
|
-
return _fsExtra.default.copySync(src, dest, {
|
|
159
|
-
overwrite: true
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
},
|
|
163
158
|
ensureDir: dir => {
|
|
164
159
|
_fsExtra.default.mkdirSync(dir, {
|
|
165
160
|
recursive: true
|
|
@@ -170,53 +165,6 @@ const hfs = exports.hfs = {
|
|
|
170
165
|
_fsExtra.default.writeFileSync(path, trimmed === "" ? trimmed : trimmed + "\n", "utf-8");
|
|
171
166
|
}
|
|
172
167
|
};
|
|
173
|
-
|
|
174
|
-
// Adapted from https://github.com/square/find-yarn-workspace-root
|
|
175
|
-
const findUp = (from, matcher) => {
|
|
176
|
-
let previous;
|
|
177
|
-
let current = _path.default.normalize(from);
|
|
178
|
-
do {
|
|
179
|
-
const found = matcher(current);
|
|
180
|
-
if (typeof found !== "undefined") {
|
|
181
|
-
return found;
|
|
182
|
-
}
|
|
183
|
-
previous = current;
|
|
184
|
-
current = _path.default.dirname(current);
|
|
185
|
-
} while (current !== previous);
|
|
186
|
-
};
|
|
187
|
-
const getExpoConfig = from => {
|
|
188
|
-
const hasDependency = findUp(from, dir => {
|
|
189
|
-
const pkgPath = _path.default.resolve(dir, "package.json");
|
|
190
|
-
if (_fsExtra.default.existsSync(pkgPath)) {
|
|
191
|
-
try {
|
|
192
|
-
const pkg = hfs.json(pkgPath);
|
|
193
|
-
return pkg.dependencies?.expo != null;
|
|
194
|
-
} catch {} // eslint-disable-line no-empty
|
|
195
|
-
}
|
|
196
|
-
}) ?? false;
|
|
197
|
-
if (!hasDependency) {
|
|
198
|
-
return {
|
|
199
|
-
isExpo: false
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
const version = findUp(from, dir => {
|
|
203
|
-
const pkgPath = _path.default.resolve(dir, "node_modules", "expo", "package.json");
|
|
204
|
-
if (_fsExtra.default.existsSync(pkgPath)) {
|
|
205
|
-
try {
|
|
206
|
-
const pkg = hfs.json(pkgPath);
|
|
207
|
-
return pkg.version;
|
|
208
|
-
} catch {} // eslint-disable-line no-empty
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
if (version == null || _semver.default.lt(version, "51.0.20")) {
|
|
212
|
-
log.error("Requires Expo 51.0.20 (or higher)");
|
|
213
|
-
process.exit(1);
|
|
214
|
-
}
|
|
215
|
-
return {
|
|
216
|
-
isExpo: true
|
|
217
|
-
};
|
|
218
|
-
};
|
|
219
|
-
exports.getExpoConfig = getExpoConfig;
|
|
220
168
|
const writeJson = (filePath, content) => {
|
|
221
169
|
hfs.write(filePath, JSON.stringify(content, null, 2));
|
|
222
170
|
log.write(filePath);
|
|
@@ -272,49 +220,14 @@ const writeXmlLike = async (filePath, content, {
|
|
|
272
220
|
}
|
|
273
221
|
};
|
|
274
222
|
exports.writeXmlLike = writeXmlLike;
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
hfs.rm(file);
|
|
278
|
-
});
|
|
279
|
-
};
|
|
280
|
-
exports.cleanIOSAssets = cleanIOSAssets;
|
|
281
|
-
const getImageBase64 = async (image, width) => {
|
|
282
|
-
if (image == null) {
|
|
223
|
+
const getAssetBase64 = async (name, asset) => {
|
|
224
|
+
if (asset == null) {
|
|
283
225
|
return "";
|
|
284
226
|
}
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
};
|
|
290
|
-
const getFileNameSuffix = async ({
|
|
291
|
-
background,
|
|
292
|
-
brand,
|
|
293
|
-
brandWidth,
|
|
294
|
-
darkBackground,
|
|
295
|
-
darkBrand,
|
|
296
|
-
darkLogo,
|
|
297
|
-
logo,
|
|
298
|
-
logoWidth
|
|
299
|
-
}) => {
|
|
300
|
-
const [logoHash, darkLogoHash, brandHash, darkBrandHash] = await Promise.all([getImageBase64(logo, logoWidth), getImageBase64(darkLogo, logoWidth), getImageBase64(brand, brandWidth), getImageBase64(darkBrand, brandWidth)]);
|
|
301
|
-
const record = {
|
|
302
|
-
background: background.hex,
|
|
303
|
-
darkBackground: darkBackground?.hex ?? "",
|
|
304
|
-
logo: logoHash,
|
|
305
|
-
darkLogo: darkLogoHash,
|
|
306
|
-
brand: brandHash,
|
|
307
|
-
darkBrand: darkBrandHash
|
|
308
|
-
};
|
|
309
|
-
const stableKey = Object.keys(record).sort().map(key => record[key]).join();
|
|
310
|
-
return _crypto.default.createHash("shake256", {
|
|
311
|
-
outputLength: 3
|
|
312
|
-
}).update(stableKey).digest("hex").toLowerCase();
|
|
313
|
-
};
|
|
314
|
-
const ensureSupportedFormat = async (name, image) => {
|
|
315
|
-
if (image == null) {
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
227
|
+
const {
|
|
228
|
+
image,
|
|
229
|
+
width
|
|
230
|
+
} = asset;
|
|
318
231
|
const {
|
|
319
232
|
format
|
|
320
233
|
} = await image.metadata();
|
|
@@ -322,56 +235,32 @@ const ensureSupportedFormat = async (name, image) => {
|
|
|
322
235
|
log.error(`${name} image file format (${format}) is not supported`);
|
|
323
236
|
process.exit(1);
|
|
324
237
|
}
|
|
238
|
+
const buffer = await image.clone().resize(width).png({
|
|
239
|
+
quality: 100
|
|
240
|
+
}).toBuffer();
|
|
241
|
+
return buffer.toString("base64");
|
|
325
242
|
};
|
|
326
243
|
const getAndroidOutputPath = ({
|
|
327
|
-
assetsOutputPath,
|
|
328
|
-
brandHeight,
|
|
329
|
-
brandWidth,
|
|
330
244
|
flavor,
|
|
331
|
-
isExpo,
|
|
332
|
-
logoHeight,
|
|
333
|
-
logoWidth,
|
|
334
245
|
platforms
|
|
335
246
|
}) => {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
const withSizeChecks = assetsOutputPath => {
|
|
340
|
-
if (logoWidth > 288 || logoHeight > 288) {
|
|
341
|
-
return log.warn("Logo size exceeding 288x288dp will be cropped by Android. Skipping Android assets generation…");
|
|
342
|
-
}
|
|
343
|
-
if (brandWidth > 200 || brandHeight > 80) {
|
|
344
|
-
return log.warn("Brand size exceeding 200x80dp will be cropped by Android. Skipping Android assets generation…");
|
|
345
|
-
}
|
|
346
|
-
if (logoWidth > 192 || logoHeight > 192) {
|
|
347
|
-
log.warn("Logo size exceeds 192x192dp. It might be cropped by Android.");
|
|
348
|
-
}
|
|
349
|
-
return assetsOutputPath;
|
|
350
|
-
};
|
|
351
|
-
if (isExpo) {
|
|
352
|
-
return withSizeChecks(_path.default.resolve(assetsOutputPath, "android"));
|
|
353
|
-
}
|
|
354
|
-
if (android == null) {
|
|
247
|
+
const android = (0, _cliConfigAndroid.projectConfig)(projectRoot);
|
|
248
|
+
if (!platforms.includes("android") || android == null) {
|
|
355
249
|
return;
|
|
356
250
|
}
|
|
357
251
|
const androidOutputPath = _path.default.resolve(android.sourceDir, android.appName, "src", flavor, "res");
|
|
358
252
|
if (!hfs.exists(androidOutputPath)) {
|
|
359
253
|
return log.warn(`No ${_path.default.relative(workingPath, androidOutputPath)} directory found. Skipping Android assets generation…`);
|
|
360
254
|
}
|
|
361
|
-
return
|
|
255
|
+
return androidOutputPath;
|
|
362
256
|
};
|
|
363
257
|
const getIOSOutputPath = ({
|
|
364
|
-
assetsOutputPath,
|
|
365
|
-
isExpo,
|
|
366
258
|
platforms
|
|
367
259
|
}) => {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
}
|
|
371
|
-
if (
|
|
372
|
-
return _path.default.resolve(assetsOutputPath, "ios");
|
|
373
|
-
}
|
|
374
|
-
if (ios == null) {
|
|
260
|
+
const ios = (0, _cliConfigApple.getProjectConfig)({
|
|
261
|
+
platformName: "ios"
|
|
262
|
+
})(projectRoot, {});
|
|
263
|
+
if (!platforms.includes("ios") || ios == null) {
|
|
375
264
|
return;
|
|
376
265
|
}
|
|
377
266
|
if (ios.xcodeProject == null) {
|
|
@@ -383,428 +272,390 @@ const getIOSOutputPath = ({
|
|
|
383
272
|
}
|
|
384
273
|
return iosOutputPath;
|
|
385
274
|
};
|
|
386
|
-
const getHtmlTemplatePath =
|
|
387
|
-
isExpo,
|
|
275
|
+
const getHtmlTemplatePath = ({
|
|
388
276
|
html,
|
|
389
277
|
platforms
|
|
390
278
|
}) => {
|
|
391
279
|
if (!platforms.includes("web")) {
|
|
392
280
|
return;
|
|
393
281
|
}
|
|
394
|
-
if (isExpo) {
|
|
395
|
-
const htmlTemplatePath = _path.default.resolve(workingPath, html);
|
|
396
|
-
const htmlTemplateRelativePath = _path.default.relative(workingPath, htmlTemplatePath);
|
|
397
|
-
if (htmlTemplateRelativePath === "public/index.html" && !hfs.exists(htmlTemplatePath)) {
|
|
398
|
-
const cmd = `npx expo customize ${htmlTemplateRelativePath}`;
|
|
399
|
-
console.log(_picocolors.default.dim(`Running ${cmd}`));
|
|
400
|
-
await exec(cmd);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
282
|
const htmlTemplatePath = _path.default.resolve(workingPath, html);
|
|
404
283
|
if (!hfs.exists(htmlTemplatePath)) {
|
|
405
|
-
return log.warn(`No ${_path.default.relative(workingPath, htmlTemplatePath)}
|
|
284
|
+
return log.warn(`No ${_path.default.relative(workingPath, htmlTemplatePath)} found. Skipping HTML + CSS generation…`);
|
|
406
285
|
}
|
|
407
286
|
return htmlTemplatePath;
|
|
408
287
|
};
|
|
409
|
-
const
|
|
410
|
-
|
|
288
|
+
const getInfoPlistPath = ({
|
|
289
|
+
iosOutputPath,
|
|
290
|
+
plist
|
|
291
|
+
}) => {
|
|
292
|
+
if (plist != null) {
|
|
293
|
+
const infoPlistPath = _path.default.resolve(workingPath, plist);
|
|
294
|
+
if (!hfs.exists(infoPlistPath)) {
|
|
295
|
+
return log.warn(`No ${_path.default.relative(workingPath, infoPlistPath)} found`);
|
|
296
|
+
}
|
|
297
|
+
return infoPlistPath;
|
|
298
|
+
}
|
|
299
|
+
return _path.default.resolve(iosOutputPath, "Info.plist");
|
|
300
|
+
};
|
|
301
|
+
const getAssetHeight = asset => {
|
|
302
|
+
if (asset == null) {
|
|
411
303
|
return Promise.resolve(0);
|
|
412
304
|
}
|
|
413
|
-
return image.clone().resize(width).toBuffer().then(buffer => (0, _sharp.default)(buffer).metadata()).then(({
|
|
305
|
+
return asset.image.clone().resize(asset.width).toBuffer().then(buffer => (0, _sharp.default)(buffer).metadata()).then(({
|
|
414
306
|
height = 0
|
|
415
307
|
}) => Math.round(height));
|
|
416
308
|
};
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
return require("./addon"); // eslint-disable-line
|
|
420
|
-
} catch {
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
};
|
|
424
|
-
const generate = async ({
|
|
425
|
-
projectType,
|
|
426
|
-
platforms,
|
|
427
|
-
html,
|
|
428
|
-
flavor,
|
|
309
|
+
const getProps = ({
|
|
310
|
+
android = {},
|
|
429
311
|
licenseKey,
|
|
430
|
-
...
|
|
312
|
+
...config
|
|
431
313
|
}) => {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
log.error("Requires Node 18 (or higher)");
|
|
314
|
+
if (_semver.default.lt(process.versions.node, "20.0.0")) {
|
|
315
|
+
log.error("Requires Node 20 (or higher)");
|
|
435
316
|
process.exit(1);
|
|
436
317
|
}
|
|
437
|
-
const
|
|
438
|
-
const
|
|
439
|
-
const
|
|
440
|
-
const
|
|
441
|
-
const
|
|
442
|
-
const
|
|
443
|
-
const
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
const
|
|
318
|
+
const assetsOutputPath = _path.default.resolve(workingPath, config.assetsOutput);
|
|
319
|
+
const logoPath = _path.default.resolve(workingPath, config.logo);
|
|
320
|
+
const darkLogoPath = config.darkLogo != null ? _path.default.resolve(workingPath, config.darkLogo) : undefined;
|
|
321
|
+
const brandPath = config.brand != null ? _path.default.resolve(workingPath, config.brand) : undefined;
|
|
322
|
+
const darkBrandPath = config.darkBrand != null ? _path.default.resolve(workingPath, config.darkBrand) : undefined;
|
|
323
|
+
const logoWidth = config.logoWidth - config.logoWidth % 2;
|
|
324
|
+
const brandWidth = config.brandWidth - config.brandWidth % 2;
|
|
325
|
+
const logo = {
|
|
326
|
+
path: logoPath,
|
|
327
|
+
image: (0, _sharp.default)(logoPath),
|
|
328
|
+
width: logoWidth
|
|
329
|
+
};
|
|
330
|
+
const darkLogo = darkLogoPath != null ? {
|
|
331
|
+
path: darkLogoPath,
|
|
332
|
+
image: (0, _sharp.default)(darkLogoPath),
|
|
333
|
+
width: logoWidth
|
|
334
|
+
} : undefined;
|
|
335
|
+
const brand = brandPath != null ? {
|
|
336
|
+
path: brandPath,
|
|
337
|
+
image: (0, _sharp.default)(brandPath),
|
|
338
|
+
width: brandWidth
|
|
339
|
+
} : undefined;
|
|
340
|
+
const darkBrand = darkBrandPath != null ? {
|
|
341
|
+
path: darkBrandPath,
|
|
342
|
+
image: (0, _sharp.default)(darkBrandPath),
|
|
343
|
+
width: brandWidth
|
|
344
|
+
} : undefined;
|
|
345
|
+
const background = parseColor(config.background);
|
|
346
|
+
const darkBackground = config.darkBackground != null ? parseColor(config.darkBackground) : undefined;
|
|
450
347
|
const executeAddon = brand != null || darkBackground != null || darkLogo != null || darkBrand != null;
|
|
451
348
|
if (licenseKey != null && !executeAddon) {
|
|
452
349
|
log.warn("You specified a license key but none of the options that requires it.");
|
|
453
350
|
}
|
|
351
|
+
const optionNames = {
|
|
352
|
+
brand: isExpo ? "brand" : "--brand",
|
|
353
|
+
darkBackground: isExpo ? "darkBackground" : "--dark-background",
|
|
354
|
+
darkLogo: isExpo ? "darkLogo" : "--dark-logo",
|
|
355
|
+
darkBrand: isExpo ? "darkBrand" : "--dark-brand"
|
|
356
|
+
};
|
|
454
357
|
if (licenseKey == null && executeAddon) {
|
|
455
|
-
const options = [brand != null ?
|
|
358
|
+
const options = [brand != null ? optionNames.brand : "", darkBackground != null ? optionNames.darkBackground : "", darkLogo != null ? optionNames.darkLogo : "", darkBrand != null ? optionNames.darkBrand : ""].filter(option => option !== "").join(", ");
|
|
456
359
|
log.error(`You need to specify a license key in order to use ${options}.`);
|
|
457
360
|
process.exit(1);
|
|
458
361
|
}
|
|
459
362
|
if (brand == null && darkBrand != null) {
|
|
460
|
-
log.error(
|
|
363
|
+
log.error(`${optionNames.darkBrand} option couldn't be used without ${optionNames.brand}.`);
|
|
461
364
|
process.exit(1);
|
|
462
365
|
}
|
|
463
|
-
|
|
464
|
-
await ensureSupportedFormat("Dark logo", darkLogo);
|
|
465
|
-
await ensureSupportedFormat("Brand", brand);
|
|
466
|
-
await ensureSupportedFormat("Dark brand", darkBrand);
|
|
467
|
-
const logoHeight = await getImageHeight(logo, logoWidth);
|
|
468
|
-
const brandHeight = await getImageHeight(brand, brandWidth);
|
|
469
|
-
if (logoWidth < args.logoWidth) {
|
|
366
|
+
if (logoWidth < config.logoWidth) {
|
|
470
367
|
log.warn(`Logo width must be a multiple of 2. It has been rounded to ${logoWidth}dp.`);
|
|
471
368
|
}
|
|
472
|
-
if (brandWidth <
|
|
369
|
+
if (brandWidth < config.brandWidth) {
|
|
473
370
|
log.warn(`Brand width must be a multiple of 2. It has been rounded to ${brandWidth}dp.`);
|
|
474
371
|
}
|
|
475
|
-
|
|
372
|
+
return {
|
|
373
|
+
android,
|
|
374
|
+
assetsOutputPath,
|
|
375
|
+
licenseKey,
|
|
376
|
+
executeAddon,
|
|
476
377
|
background,
|
|
477
|
-
brand,
|
|
478
|
-
brandWidth,
|
|
479
378
|
darkBackground,
|
|
480
|
-
darkBrand,
|
|
481
|
-
darkLogo,
|
|
482
379
|
logo,
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
380
|
+
darkLogo,
|
|
381
|
+
brand,
|
|
382
|
+
darkBrand
|
|
383
|
+
};
|
|
384
|
+
};
|
|
385
|
+
const getExtras = async ({
|
|
386
|
+
background,
|
|
387
|
+
darkBackground,
|
|
388
|
+
logo,
|
|
389
|
+
darkLogo,
|
|
390
|
+
brand,
|
|
391
|
+
darkBrand
|
|
392
|
+
}) => {
|
|
393
|
+
const [logoHash, darkLogoHash, brandHash, darkBrandHash, logoHeight, brandHeight] = await Promise.all([getAssetBase64("Logo", logo), getAssetBase64("Dark logo", darkLogo), getAssetBase64("Brand", brand), getAssetBase64("Dark brand", darkBrand), getAssetHeight(logo), getAssetHeight(brand)]);
|
|
394
|
+
const record = {
|
|
395
|
+
background: background.hex,
|
|
396
|
+
darkBackground: darkBackground?.hex ?? "",
|
|
397
|
+
logo: logoHash,
|
|
398
|
+
darkLogo: darkLogoHash,
|
|
399
|
+
brand: brandHash,
|
|
400
|
+
darkBrand: darkBrandHash
|
|
401
|
+
};
|
|
402
|
+
const stableKey = Object.keys(record).sort().map(key => record[key]).join();
|
|
403
|
+
const fileNameSuffix = _crypto.default.createHash("shake256", {
|
|
404
|
+
outputLength: 3
|
|
405
|
+
}).update(stableKey).digest("hex").toLowerCase();
|
|
406
|
+
return {
|
|
407
|
+
fileNameSuffix,
|
|
491
408
|
logoHeight,
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
}
|
|
505
|
-
if (
|
|
506
|
-
log.
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
409
|
+
brandHeight
|
|
410
|
+
};
|
|
411
|
+
};
|
|
412
|
+
exports.getExtras = getExtras;
|
|
413
|
+
const writeAndroidAssets = async ({
|
|
414
|
+
androidOutputPath,
|
|
415
|
+
props,
|
|
416
|
+
extras
|
|
417
|
+
}) => {
|
|
418
|
+
const {
|
|
419
|
+
logo,
|
|
420
|
+
brand
|
|
421
|
+
} = props;
|
|
422
|
+
if (logo.width > 192 || extras.logoHeight > 192) {
|
|
423
|
+
return log.warn("Logo size exceeding 192x192dp will be cropped by Android. Skipping Android assets generation…");
|
|
424
|
+
}
|
|
425
|
+
if (brand != null && (brand.width > 200 || extras.brandHeight > 80)) {
|
|
426
|
+
return log.warn("Brand size exceeding 200x80dp will be cropped by Android. Skipping Android assets generation…");
|
|
427
|
+
}
|
|
428
|
+
if (logo.width > 134 || extras.logoHeight > 134) {
|
|
429
|
+
log.warn("Logo size exceeds 134x134dp. It might be cropped by Android.");
|
|
430
|
+
}
|
|
431
|
+
log.title("🤖", "Android");
|
|
432
|
+
hfs.ensureDir(androidOutputPath);
|
|
433
|
+
await Promise.all([{
|
|
434
|
+
ratio: 1,
|
|
435
|
+
suffix: "mdpi"
|
|
436
|
+
}, {
|
|
437
|
+
ratio: 1.5,
|
|
438
|
+
suffix: "hdpi"
|
|
439
|
+
}, {
|
|
440
|
+
ratio: 2,
|
|
441
|
+
suffix: "xhdpi"
|
|
442
|
+
}, {
|
|
443
|
+
ratio: 3,
|
|
444
|
+
suffix: "xxhdpi"
|
|
445
|
+
}, {
|
|
446
|
+
ratio: 4,
|
|
447
|
+
suffix: "xxxhdpi"
|
|
448
|
+
}].map(({
|
|
449
|
+
ratio,
|
|
450
|
+
suffix
|
|
451
|
+
}) => {
|
|
452
|
+
const drawableDirPath = _path.default.resolve(androidOutputPath, `drawable-${suffix}`);
|
|
453
|
+
hfs.ensureDir(drawableDirPath);
|
|
529
454
|
|
|
530
|
-
|
|
531
|
-
|
|
455
|
+
// https://developer.android.com/develop/ui/views/launch/splash-screen#dimensions
|
|
456
|
+
const canvasSize = 288 * ratio;
|
|
532
457
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
});
|
|
547
|
-
const filePath = _path.default.resolve(drawableDirPath, "bootsplash_logo.png");
|
|
548
|
-
return logo.clone().resize(logoWidth * ratio).toBuffer().then(input => canvas.composite([{
|
|
549
|
-
input
|
|
550
|
-
}]).png({
|
|
551
|
-
quality: 100
|
|
552
|
-
}).toFile(filePath)).then(() => {
|
|
553
|
-
log.write(filePath, {
|
|
554
|
-
width: canvasSize,
|
|
555
|
-
height: canvasSize
|
|
556
|
-
});
|
|
557
|
-
});
|
|
558
|
-
}));
|
|
559
|
-
if (!isExpo) {
|
|
560
|
-
const manifestXmlPath = _path.default.resolve(androidOutputPath, "..", "AndroidManifest.xml");
|
|
561
|
-
if (hfs.exists(manifestXmlPath)) {
|
|
562
|
-
const manifestXml = readXmlLike(manifestXmlPath);
|
|
563
|
-
const activities = manifestXml.root.querySelectorAll("activity");
|
|
564
|
-
for (const activity of activities) {
|
|
565
|
-
if (activity.getAttribute("android:name") === ".MainActivity") {
|
|
566
|
-
activity.setAttribute("android:theme", "@style/BootTheme");
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
await writeXmlLike(manifestXmlPath, manifestXml.root.toString(), {
|
|
570
|
-
...manifestXml.formatOptions,
|
|
571
|
-
formatter: "prettier",
|
|
572
|
-
htmlWhitespaceSensitivity: "ignore",
|
|
573
|
-
selfClosingTags: true,
|
|
574
|
-
singleAttributePerLine: true
|
|
575
|
-
});
|
|
576
|
-
} else {
|
|
577
|
-
log.warn("No AndroidManifest.xml found. Skipping…");
|
|
578
|
-
}
|
|
579
|
-
const valuesPath = _path.default.resolve(androidOutputPath, "values");
|
|
580
|
-
hfs.ensureDir(valuesPath);
|
|
581
|
-
const colorsXmlPath = _path.default.resolve(valuesPath, "colors.xml");
|
|
582
|
-
const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
|
|
583
|
-
if (hfs.exists(colorsXmlPath)) {
|
|
584
|
-
const colorsXml = readXmlLike(colorsXmlPath);
|
|
585
|
-
const nextColor = (0, _nodeHtmlParser.parse)(colorsXmlEntry);
|
|
586
|
-
const prevColor = colorsXml.root.querySelector('color[name="bootsplash_background"]');
|
|
587
|
-
if (prevColor != null) {
|
|
588
|
-
prevColor.replaceWith(nextColor);
|
|
589
|
-
} else {
|
|
590
|
-
colorsXml.root.querySelector("resources")?.appendChild(nextColor);
|
|
458
|
+
// https://sharp.pixelplumbing.com/api-constructor
|
|
459
|
+
const canvas = (0, _sharp.default)({
|
|
460
|
+
create: {
|
|
461
|
+
width: canvasSize,
|
|
462
|
+
height: canvasSize,
|
|
463
|
+
channels: 4,
|
|
464
|
+
background: {
|
|
465
|
+
r: 255,
|
|
466
|
+
g: 255,
|
|
467
|
+
b: 255,
|
|
468
|
+
alpha: 0
|
|
591
469
|
}
|
|
592
|
-
await writeXmlLike(colorsXmlPath, colorsXml.root.toString(), {
|
|
593
|
-
...colorsXml.formatOptions,
|
|
594
|
-
formatter: "xmlFormatter"
|
|
595
|
-
});
|
|
596
|
-
} else {
|
|
597
|
-
await writeXmlLike(colorsXmlPath, `<resources>${colorsXmlEntry}</resources>`, {
|
|
598
|
-
formatter: "xmlFormatter"
|
|
599
|
-
});
|
|
600
470
|
}
|
|
601
|
-
const stylesXmlPath = _path.default.resolve(valuesPath, "styles.xml");
|
|
602
|
-
if (hfs.exists(stylesXmlPath)) {
|
|
603
|
-
const stylesXml = readXmlLike(stylesXmlPath);
|
|
604
|
-
const prevStyle = stylesXml.root.querySelector('style[name="BootTheme"]');
|
|
605
|
-
const parent = prevStyle?.getAttribute("parent") ?? "Theme.BootSplash";
|
|
606
|
-
const extraItems = (0, _nodeHtmlParser.parse)(prevStyle?.text.split("\n").map(line => line.trim()).join("") ?? "").childNodes.filter(node => {
|
|
607
|
-
if (!(node instanceof _nodeHtmlParser.HTMLElement)) {
|
|
608
|
-
return true;
|
|
609
|
-
}
|
|
610
|
-
const name = node.getAttribute("name");
|
|
611
|
-
return name !== "bootSplashBackground" && name !== "bootSplashLogo" && name !== "bootSplashBrand" && name !== "postBootSplashTheme";
|
|
612
|
-
}).map(node => node.toString());
|
|
613
|
-
const styleItems = [...(extraItems.length > 0 ? [...extraItems, ""] : []), '<item name="bootSplashBackground">@color/bootsplash_background</item>', '<item name="bootSplashLogo">@drawable/bootsplash_logo</item>', ...(brand != null && brandPath != null ? ['<item name="bootSplashBrand">@drawable/bootsplash_brand</item>'] : []), '<item name="postBootSplashTheme">@style/AppTheme</item>'];
|
|
614
|
-
const nextStyle = (0, _nodeHtmlParser.parse)((0, _tsDedent.dedent)`
|
|
615
|
-
<style name="BootTheme" parent="${parent}">
|
|
616
|
-
${styleItems.join("\n")}
|
|
617
|
-
</style>
|
|
618
|
-
`);
|
|
619
|
-
prevStyle?.remove(); // remove the existing style
|
|
620
|
-
stylesXml.root.querySelector("resources")?.appendChild(nextStyle);
|
|
621
|
-
await writeXmlLike(stylesXmlPath, stylesXml.root.toString(), {
|
|
622
|
-
...stylesXml.formatOptions,
|
|
623
|
-
formatter: "prettier",
|
|
624
|
-
htmlWhitespaceSensitivity: "ignore"
|
|
625
|
-
});
|
|
626
|
-
} else {
|
|
627
|
-
log.warn("No styles.xml found. Skipping…");
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
if (iosOutputPath != null) {
|
|
632
|
-
log.title("🍏", "iOS");
|
|
633
|
-
hfs.ensureDir(iosOutputPath);
|
|
634
|
-
cleanIOSAssets(iosOutputPath);
|
|
635
|
-
const storyboardPath = _path.default.resolve(iosOutputPath, "BootSplash.storyboard");
|
|
636
|
-
const colorsSetPath = _path.default.resolve(iosOutputPath, "Colors.xcassets", `BootSplashBackground-${fileNameSuffix}.colorset`);
|
|
637
|
-
const imageSetPath = _path.default.resolve(iosOutputPath, "Images.xcassets", `BootSplashLogo-${fileNameSuffix}.imageset`);
|
|
638
|
-
hfs.ensureDir(colorsSetPath);
|
|
639
|
-
hfs.ensureDir(imageSetPath);
|
|
640
|
-
await writeXmlLike(storyboardPath, getStoryboard({
|
|
641
|
-
logoHeight,
|
|
642
|
-
logoWidth,
|
|
643
|
-
background: background.rgb,
|
|
644
|
-
fileNameSuffix
|
|
645
|
-
}), {
|
|
646
|
-
formatter: "xmlFormatter",
|
|
647
|
-
whiteSpaceAtEndOfSelfclosingTag: false
|
|
648
471
|
});
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
}],
|
|
662
|
-
info: {
|
|
663
|
-
author: "xcode",
|
|
664
|
-
version: 1
|
|
665
|
-
}
|
|
472
|
+
const filePath = _path.default.resolve(drawableDirPath, "bootsplash_logo.png");
|
|
473
|
+
return logo.image.clone().resize(logo.width * ratio).toBuffer().then(input => canvas.composite([{
|
|
474
|
+
input
|
|
475
|
+
}]).png({
|
|
476
|
+
quality: 100
|
|
477
|
+
}).toFile(filePath)).then(() => {
|
|
478
|
+
log.write(filePath, {
|
|
479
|
+
width: canvasSize,
|
|
480
|
+
height: canvasSize
|
|
481
|
+
});
|
|
666
482
|
});
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
483
|
+
}));
|
|
484
|
+
};
|
|
485
|
+
exports.writeAndroidAssets = writeAndroidAssets;
|
|
486
|
+
const writeIOSAssets = async ({
|
|
487
|
+
iosOutputPath,
|
|
488
|
+
props,
|
|
489
|
+
extras
|
|
490
|
+
}) => {
|
|
491
|
+
const {
|
|
492
|
+
background,
|
|
493
|
+
logo
|
|
494
|
+
} = props;
|
|
495
|
+
log.title("🍏", "iOS");
|
|
496
|
+
hfs.ensureDir(iosOutputPath);
|
|
497
|
+
|
|
498
|
+
// clean existing assets
|
|
499
|
+
hfs.readDir(iosOutputPath).filter(file => file === "Colors.xcassets" || file === "Images.xcassets").map(file => _path.default.join(iosOutputPath, file)).flatMap(dir => hfs.readDir(dir).filter(file => file.startsWith("BootSplash")).map(file => _path.default.join(dir, file))).forEach(file => {
|
|
500
|
+
hfs.rm(file);
|
|
501
|
+
});
|
|
502
|
+
const storyboardPath = _path.default.resolve(iosOutputPath, "BootSplash.storyboard");
|
|
503
|
+
await writeXmlLike(storyboardPath, getStoryboard({
|
|
504
|
+
props,
|
|
505
|
+
extras
|
|
506
|
+
}), {
|
|
507
|
+
formatter: "xmlFormatter",
|
|
508
|
+
whiteSpaceAtEndOfSelfclosingTag: false
|
|
509
|
+
});
|
|
510
|
+
const colorsSetPath = _path.default.resolve(iosOutputPath, "Colors.xcassets", `BootSplashBackground-${extras.fileNameSuffix}.colorset`);
|
|
511
|
+
hfs.ensureDir(colorsSetPath);
|
|
512
|
+
writeJson(_path.default.resolve(colorsSetPath, "Contents.json"), {
|
|
513
|
+
colors: [{
|
|
514
|
+
idiom: "universal",
|
|
515
|
+
color: {
|
|
516
|
+
"color-space": "srgb",
|
|
517
|
+
components: {
|
|
518
|
+
blue: background.rgb.B,
|
|
519
|
+
green: background.rgb.G,
|
|
520
|
+
red: background.rgb.R,
|
|
521
|
+
alpha: "1.000"
|
|
522
|
+
}
|
|
685
523
|
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
524
|
+
}],
|
|
525
|
+
info: {
|
|
526
|
+
author: "xcode",
|
|
527
|
+
version: 1
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
const logoFileName = `logo-${extras.fileNameSuffix}`;
|
|
531
|
+
const imagesSetPath = _path.default.resolve(iosOutputPath, "Images.xcassets", `BootSplashLogo-${extras.fileNameSuffix}.imageset`);
|
|
532
|
+
hfs.ensureDir(imagesSetPath);
|
|
533
|
+
writeJson(_path.default.resolve(imagesSetPath, "Contents.json"), {
|
|
534
|
+
images: [{
|
|
535
|
+
idiom: "universal",
|
|
536
|
+
filename: `${logoFileName}.png`,
|
|
537
|
+
scale: "1x"
|
|
690
538
|
}, {
|
|
691
|
-
|
|
692
|
-
|
|
539
|
+
idiom: "universal",
|
|
540
|
+
filename: `${logoFileName}@2x.png`,
|
|
541
|
+
scale: "2x"
|
|
693
542
|
}, {
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
543
|
+
idiom: "universal",
|
|
544
|
+
filename: `${logoFileName}@3x.png`,
|
|
545
|
+
scale: "3x"
|
|
546
|
+
}],
|
|
547
|
+
info: {
|
|
548
|
+
author: "xcode",
|
|
549
|
+
version: 1
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
await Promise.all([{
|
|
553
|
+
ratio: 1,
|
|
554
|
+
suffix: ""
|
|
555
|
+
}, {
|
|
556
|
+
ratio: 2,
|
|
557
|
+
suffix: "@2x"
|
|
558
|
+
}, {
|
|
559
|
+
ratio: 3,
|
|
560
|
+
suffix: "@3x"
|
|
561
|
+
}].map(({
|
|
562
|
+
ratio,
|
|
563
|
+
suffix
|
|
564
|
+
}) => {
|
|
565
|
+
const filePath = _path.default.resolve(imagesSetPath, `${logoFileName}${suffix}.png`);
|
|
566
|
+
return logo.image.clone().resize(logo.width * ratio).png({
|
|
567
|
+
quality: 100
|
|
568
|
+
}).toFile(filePath).then(({
|
|
569
|
+
width,
|
|
570
|
+
height
|
|
699
571
|
}) => {
|
|
700
|
-
|
|
701
|
-
return logo.clone().resize(logoWidth * ratio).png({
|
|
702
|
-
quality: 100
|
|
703
|
-
}).toFile(filePath).then(({
|
|
572
|
+
log.write(filePath, {
|
|
704
573
|
width,
|
|
705
574
|
height
|
|
706
|
-
}) => {
|
|
707
|
-
log.write(filePath, {
|
|
708
|
-
width,
|
|
709
|
-
height
|
|
710
|
-
});
|
|
711
575
|
});
|
|
712
|
-
}));
|
|
713
|
-
if (!isExpo) {
|
|
714
|
-
const infoPlistPath = _path.default.resolve(iosOutputPath, "Info.plist");
|
|
715
|
-
const infoPlist = _plist.default.parse(hfs.text(infoPlistPath));
|
|
716
|
-
infoPlist["UILaunchStoryboardName"] = "BootSplash";
|
|
717
|
-
const formatted = (0, _xmlFormatter.default)(_plist.default.build(infoPlist), {
|
|
718
|
-
collapseContent: true,
|
|
719
|
-
forceSelfClosingEmptyTag: false,
|
|
720
|
-
indentation: "\t",
|
|
721
|
-
lineSeparator: "\n",
|
|
722
|
-
whiteSpaceAtEndOfSelfclosingTag: false
|
|
723
|
-
}).replace(/<string\/>/gm, "<string></string>").replace(/^\t/gm, "");
|
|
724
|
-
hfs.write(infoPlistPath, formatted);
|
|
725
|
-
log.write(infoPlistPath);
|
|
726
|
-
const pbxprojectPath = Expo.IOSConfig.Paths.getPBXProjectPath(projectRoot);
|
|
727
|
-
const xcodeProjectPath = Expo.IOSConfig.Paths.getXcodeProjectPath(projectRoot);
|
|
728
|
-
const project = Expo.IOSConfig.XcodeUtils.getPbxproj(projectRoot);
|
|
729
|
-
const projectName = _path.default.basename(iosOutputPath);
|
|
730
|
-
const groupName = _path.default.parse(xcodeProjectPath).name;
|
|
731
|
-
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
732
|
-
project,
|
|
733
|
-
filepath: _path.default.join(projectName, "BootSplash.storyboard"),
|
|
734
|
-
groupName,
|
|
735
|
-
isBuildFile: true
|
|
736
|
-
});
|
|
737
|
-
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
738
|
-
project,
|
|
739
|
-
filepath: _path.default.join(projectName, "Colors.xcassets"),
|
|
740
|
-
groupName,
|
|
741
|
-
isBuildFile: true
|
|
742
|
-
});
|
|
743
|
-
hfs.write(pbxprojectPath, project.writeSync());
|
|
744
|
-
log.write(pbxprojectPath);
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
if (htmlTemplatePath != null) {
|
|
748
|
-
log.title("🌐", "Web");
|
|
749
|
-
const htmlTemplate = readXmlLike(htmlTemplatePath);
|
|
750
|
-
const {
|
|
751
|
-
format
|
|
752
|
-
} = await logo.metadata();
|
|
753
|
-
const prevStyle = htmlTemplate.root.querySelector("#bootsplash-style");
|
|
754
|
-
const base64 = (format === "svg" ? hfs.buffer(logoPath) : await logo.clone().resize(Math.round(logoWidth * 2)).png({
|
|
755
|
-
quality: 100
|
|
756
|
-
}).toBuffer()).toString("base64");
|
|
757
|
-
const dataURI = `data:image/${format ? "svg+xml" : "png"};base64,${base64}`;
|
|
758
|
-
const nextStyle = (0, _nodeHtmlParser.parse)((0, _tsDedent.dedent)`
|
|
759
|
-
<style id="bootsplash-style">
|
|
760
|
-
#bootsplash {
|
|
761
|
-
position: absolute;
|
|
762
|
-
top: 0;
|
|
763
|
-
bottom: 0;
|
|
764
|
-
left: 0;
|
|
765
|
-
right: 0;
|
|
766
|
-
overflow: hidden;
|
|
767
|
-
display: flex;
|
|
768
|
-
justify-content: center;
|
|
769
|
-
align-items: center;
|
|
770
|
-
background-color: ${background.hex};
|
|
771
|
-
}
|
|
772
|
-
#bootsplash-logo {
|
|
773
|
-
content: url("${dataURI}");
|
|
774
|
-
width: ${logoWidth}px;
|
|
775
|
-
height: ${logoHeight}px;
|
|
776
|
-
}
|
|
777
|
-
</style>
|
|
778
|
-
`);
|
|
779
|
-
if (prevStyle != null) {
|
|
780
|
-
prevStyle.replaceWith(nextStyle);
|
|
781
|
-
} else {
|
|
782
|
-
htmlTemplate.root.querySelector("head")?.appendChild(nextStyle);
|
|
783
|
-
}
|
|
784
|
-
const prevDiv = htmlTemplate.root.querySelector("#bootsplash");
|
|
785
|
-
const nextDiv = (0, _nodeHtmlParser.parse)((0, _tsDedent.dedent)`
|
|
786
|
-
<div id="bootsplash">
|
|
787
|
-
<div id="bootsplash-logo"></div>
|
|
788
|
-
</div>
|
|
789
|
-
`);
|
|
790
|
-
if (prevDiv != null) {
|
|
791
|
-
prevDiv.replaceWith(nextDiv);
|
|
792
|
-
} else {
|
|
793
|
-
htmlTemplate.root.querySelector("body")?.appendChild(nextDiv);
|
|
794
|
-
}
|
|
795
|
-
await writeXmlLike(htmlTemplatePath, htmlTemplate.root.toString(), {
|
|
796
|
-
...htmlTemplate.formatOptions,
|
|
797
|
-
formatter: "prettier",
|
|
798
|
-
useCssPlugin: true
|
|
799
576
|
});
|
|
577
|
+
}));
|
|
578
|
+
};
|
|
579
|
+
exports.writeIOSAssets = writeIOSAssets;
|
|
580
|
+
const writeWebAssets = async ({
|
|
581
|
+
htmlTemplatePath,
|
|
582
|
+
props,
|
|
583
|
+
extras
|
|
584
|
+
}) => {
|
|
585
|
+
const {
|
|
586
|
+
background,
|
|
587
|
+
logo
|
|
588
|
+
} = props;
|
|
589
|
+
log.title("🌐", "Web");
|
|
590
|
+
const htmlTemplate = readXmlLike(htmlTemplatePath);
|
|
591
|
+
const {
|
|
592
|
+
format
|
|
593
|
+
} = await logo.image.metadata();
|
|
594
|
+
const prevStyle = htmlTemplate.root.querySelector("#bootsplash-style");
|
|
595
|
+
const base64 = (format === "svg" ? hfs.buffer(logo.path) : await logo.image.clone().resize(Math.round(logo.width * 2)).png({
|
|
596
|
+
quality: 100
|
|
597
|
+
}).toBuffer()).toString("base64");
|
|
598
|
+
const dataURI = `data:image/${format ? "svg+xml" : "png"};base64,${base64}`;
|
|
599
|
+
const nextStyle = (0, _nodeHtmlParser.parse)((0, _tsDedent.dedent)`
|
|
600
|
+
<style id="bootsplash-style">
|
|
601
|
+
#bootsplash {
|
|
602
|
+
position: absolute;
|
|
603
|
+
top: 0;
|
|
604
|
+
bottom: 0;
|
|
605
|
+
left: 0;
|
|
606
|
+
right: 0;
|
|
607
|
+
overflow: hidden;
|
|
608
|
+
display: flex;
|
|
609
|
+
justify-content: center;
|
|
610
|
+
align-items: center;
|
|
611
|
+
background-color: ${background.hex};
|
|
612
|
+
}
|
|
613
|
+
#bootsplash-logo {
|
|
614
|
+
content: url("${dataURI}");
|
|
615
|
+
width: ${logo.width}px;
|
|
616
|
+
height: ${extras.logoHeight}px;
|
|
617
|
+
}
|
|
618
|
+
</style>
|
|
619
|
+
`);
|
|
620
|
+
if (prevStyle != null) {
|
|
621
|
+
prevStyle.replaceWith(nextStyle);
|
|
622
|
+
} else {
|
|
623
|
+
htmlTemplate.root.querySelector("head")?.appendChild(nextStyle);
|
|
800
624
|
}
|
|
625
|
+
const prevDiv = htmlTemplate.root.querySelector("#bootsplash");
|
|
626
|
+
const nextDiv = (0, _nodeHtmlParser.parse)((0, _tsDedent.dedent)`
|
|
627
|
+
<div id="bootsplash">
|
|
628
|
+
<div id="bootsplash-logo"></div>
|
|
629
|
+
</div>
|
|
630
|
+
`);
|
|
631
|
+
if (prevDiv != null) {
|
|
632
|
+
prevDiv.replaceWith(nextDiv);
|
|
633
|
+
} else {
|
|
634
|
+
htmlTemplate.root.querySelector("body")?.appendChild(nextDiv);
|
|
635
|
+
}
|
|
636
|
+
await writeXmlLike(htmlTemplatePath, htmlTemplate.root.toString(), {
|
|
637
|
+
...htmlTemplate.formatOptions,
|
|
638
|
+
formatter: "prettier",
|
|
639
|
+
useCssPlugin: true
|
|
640
|
+
});
|
|
641
|
+
};
|
|
642
|
+
exports.writeWebAssets = writeWebAssets;
|
|
643
|
+
const writeGenericAssets = async ({
|
|
644
|
+
props,
|
|
645
|
+
extras
|
|
646
|
+
}) => {
|
|
647
|
+
const {
|
|
648
|
+
assetsOutputPath,
|
|
649
|
+
background,
|
|
650
|
+
logo
|
|
651
|
+
} = props;
|
|
801
652
|
log.title("📄", "Assets");
|
|
802
653
|
hfs.ensureDir(assetsOutputPath);
|
|
803
654
|
writeJson(_path.default.resolve(assetsOutputPath, "manifest.json"), {
|
|
804
655
|
background: background.hex,
|
|
805
656
|
logo: {
|
|
806
|
-
width:
|
|
807
|
-
height: logoHeight
|
|
657
|
+
width: logo.width,
|
|
658
|
+
height: extras.logoHeight
|
|
808
659
|
}
|
|
809
660
|
});
|
|
810
661
|
await Promise.all([{
|
|
@@ -827,7 +678,7 @@ const generate = async ({
|
|
|
827
678
|
suffix
|
|
828
679
|
}) => {
|
|
829
680
|
const filePath = _path.default.resolve(assetsOutputPath, `logo${suffix}.png`);
|
|
830
|
-
return logo.clone().resize(Math.round(
|
|
681
|
+
return logo.image.clone().resize(Math.round(logo.width * ratio)).png({
|
|
831
682
|
quality: 100
|
|
832
683
|
}).toFile(filePath).then(({
|
|
833
684
|
width,
|
|
@@ -839,30 +690,179 @@ const generate = async ({
|
|
|
839
690
|
});
|
|
840
691
|
});
|
|
841
692
|
}));
|
|
693
|
+
};
|
|
694
|
+
exports.writeGenericAssets = writeGenericAssets;
|
|
695
|
+
const requireAddon = () => {
|
|
696
|
+
try {
|
|
697
|
+
return require("./addon");
|
|
698
|
+
} catch {
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
const generate = async ({
|
|
703
|
+
platforms,
|
|
704
|
+
html,
|
|
705
|
+
flavor,
|
|
706
|
+
plist,
|
|
707
|
+
...config
|
|
708
|
+
}) => {
|
|
709
|
+
const props = getProps(config);
|
|
710
|
+
const {
|
|
711
|
+
background,
|
|
712
|
+
brand,
|
|
713
|
+
licenseKey,
|
|
714
|
+
executeAddon
|
|
715
|
+
} = props;
|
|
716
|
+
const extras = await getExtras(props);
|
|
717
|
+
const androidOutputPath = getAndroidOutputPath({
|
|
718
|
+
flavor,
|
|
719
|
+
platforms
|
|
720
|
+
});
|
|
721
|
+
const iosOutputPath = getIOSOutputPath({
|
|
722
|
+
platforms
|
|
723
|
+
});
|
|
724
|
+
const htmlTemplatePath = getHtmlTemplatePath({
|
|
725
|
+
html,
|
|
726
|
+
platforms
|
|
727
|
+
});
|
|
728
|
+
if (androidOutputPath != null) {
|
|
729
|
+
await writeAndroidAssets({
|
|
730
|
+
androidOutputPath,
|
|
731
|
+
props,
|
|
732
|
+
extras
|
|
733
|
+
});
|
|
734
|
+
const manifestXmlPath = _path.default.resolve(androidOutputPath, "..", "AndroidManifest.xml");
|
|
735
|
+
if (hfs.exists(manifestXmlPath)) {
|
|
736
|
+
const manifestXml = readXmlLike(manifestXmlPath);
|
|
737
|
+
const activities = manifestXml.root.querySelectorAll("activity");
|
|
738
|
+
for (const activity of activities) {
|
|
739
|
+
if (activity.getAttribute("android:name") === ".MainActivity") {
|
|
740
|
+
activity.setAttribute("android:theme", "@style/BootTheme");
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
await writeXmlLike(manifestXmlPath, manifestXml.root.toString(), {
|
|
744
|
+
...manifestXml.formatOptions,
|
|
745
|
+
formatter: "prettier",
|
|
746
|
+
htmlWhitespaceSensitivity: "ignore",
|
|
747
|
+
selfClosingTags: true,
|
|
748
|
+
singleAttributePerLine: true
|
|
749
|
+
});
|
|
750
|
+
} else {
|
|
751
|
+
log.warn("No AndroidManifest.xml found");
|
|
752
|
+
}
|
|
753
|
+
const valuesPath = _path.default.resolve(androidOutputPath, "values");
|
|
754
|
+
hfs.ensureDir(valuesPath);
|
|
755
|
+
const colorsXmlPath = _path.default.resolve(valuesPath, "colors.xml");
|
|
756
|
+
const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
|
|
757
|
+
if (hfs.exists(colorsXmlPath)) {
|
|
758
|
+
const colorsXml = readXmlLike(colorsXmlPath);
|
|
759
|
+
const nextColor = (0, _nodeHtmlParser.parse)(colorsXmlEntry);
|
|
760
|
+
const prevColor = colorsXml.root.querySelector('color[name="bootsplash_background"]');
|
|
761
|
+
if (prevColor != null) {
|
|
762
|
+
prevColor.replaceWith(nextColor);
|
|
763
|
+
} else {
|
|
764
|
+
colorsXml.root.querySelector("resources")?.appendChild(nextColor);
|
|
765
|
+
}
|
|
766
|
+
await writeXmlLike(colorsXmlPath, colorsXml.root.toString(), {
|
|
767
|
+
...colorsXml.formatOptions,
|
|
768
|
+
formatter: "xmlFormatter"
|
|
769
|
+
});
|
|
770
|
+
} else {
|
|
771
|
+
await writeXmlLike(colorsXmlPath, `<resources>${colorsXmlEntry}</resources>`, {
|
|
772
|
+
formatter: "xmlFormatter"
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
const stylesXmlPath = _path.default.resolve(valuesPath, "styles.xml");
|
|
776
|
+
if (hfs.exists(stylesXmlPath)) {
|
|
777
|
+
const stylesXml = readXmlLike(stylesXmlPath);
|
|
778
|
+
const prevStyle = stylesXml.root.querySelector('style[name="BootTheme"]');
|
|
779
|
+
const parent = prevStyle?.getAttribute("parent") ?? "Theme.BootSplash";
|
|
780
|
+
const extraItems = (0, _nodeHtmlParser.parse)(prevStyle?.text.split("\n").map(line => line.trim()).join("") ?? "").childNodes.filter(node => {
|
|
781
|
+
if (!(node instanceof _nodeHtmlParser.HTMLElement)) {
|
|
782
|
+
return true;
|
|
783
|
+
}
|
|
784
|
+
const name = node.getAttribute("name");
|
|
785
|
+
return name !== "bootSplashBackground" && name !== "bootSplashLogo" && name !== "bootSplashBrand" && name !== "postBootSplashTheme";
|
|
786
|
+
}).map(node => node.toString());
|
|
787
|
+
const styleItems = [...(extraItems.length > 0 ? [...extraItems, ""] : []), '<item name="bootSplashBackground">@color/bootsplash_background</item>', '<item name="bootSplashLogo">@drawable/bootsplash_logo</item>', ...(brand != null ? ['<item name="bootSplashBrand">@drawable/bootsplash_brand</item>'] : []), '<item name="postBootSplashTheme">@style/AppTheme</item>'];
|
|
788
|
+
const nextStyle = (0, _nodeHtmlParser.parse)((0, _tsDedent.dedent)`
|
|
789
|
+
<style name="BootTheme" parent="${parent}">
|
|
790
|
+
${styleItems.join("\n")}
|
|
791
|
+
</style>
|
|
792
|
+
`);
|
|
793
|
+
prevStyle?.remove(); // remove the existing style
|
|
794
|
+
stylesXml.root.querySelector("resources")?.appendChild(nextStyle);
|
|
795
|
+
await writeXmlLike(stylesXmlPath, stylesXml.root.toString(), {
|
|
796
|
+
...stylesXml.formatOptions,
|
|
797
|
+
formatter: "prettier",
|
|
798
|
+
htmlWhitespaceSensitivity: "ignore"
|
|
799
|
+
});
|
|
800
|
+
} else {
|
|
801
|
+
log.warn("No styles.xml found");
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
if (iosOutputPath != null) {
|
|
805
|
+
await writeIOSAssets({
|
|
806
|
+
iosOutputPath,
|
|
807
|
+
props,
|
|
808
|
+
extras
|
|
809
|
+
});
|
|
810
|
+
const infoPlistPath = getInfoPlistPath({
|
|
811
|
+
iosOutputPath,
|
|
812
|
+
plist
|
|
813
|
+
});
|
|
814
|
+
if (infoPlistPath != null) {
|
|
815
|
+
const infoPlist = _plist.default.parse(hfs.text(infoPlistPath));
|
|
816
|
+
infoPlist["UILaunchStoryboardName"] = "BootSplash";
|
|
817
|
+
const formatted = (0, _xmlFormatter.default)(_plist.default.build(infoPlist), {
|
|
818
|
+
collapseContent: true,
|
|
819
|
+
forceSelfClosingEmptyTag: false,
|
|
820
|
+
indentation: "\t",
|
|
821
|
+
lineSeparator: "\n",
|
|
822
|
+
whiteSpaceAtEndOfSelfclosingTag: false
|
|
823
|
+
}).replace(/<string\/>/gm, "<string></string>").replace(/^\t/gm, "");
|
|
824
|
+
hfs.write(infoPlistPath, formatted);
|
|
825
|
+
log.write(infoPlistPath);
|
|
826
|
+
}
|
|
827
|
+
const pbxprojectPath = Expo.IOSConfig.Paths.getPBXProjectPath(projectRoot);
|
|
828
|
+
const xcodeProjectPath = Expo.IOSConfig.Paths.getXcodeProjectPath(projectRoot);
|
|
829
|
+
const project = Expo.IOSConfig.XcodeUtils.getPbxproj(projectRoot);
|
|
830
|
+
const projectName = _path.default.basename(iosOutputPath);
|
|
831
|
+
const groupName = _path.default.parse(xcodeProjectPath).name;
|
|
832
|
+
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
833
|
+
project,
|
|
834
|
+
filepath: _path.default.join(projectName, "BootSplash.storyboard"),
|
|
835
|
+
groupName,
|
|
836
|
+
isBuildFile: true
|
|
837
|
+
});
|
|
838
|
+
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
839
|
+
project,
|
|
840
|
+
filepath: _path.default.join(projectName, "Colors.xcassets"),
|
|
841
|
+
groupName,
|
|
842
|
+
isBuildFile: true
|
|
843
|
+
});
|
|
844
|
+
hfs.write(pbxprojectPath, project.writeSync());
|
|
845
|
+
log.write(pbxprojectPath);
|
|
846
|
+
}
|
|
847
|
+
if (htmlTemplatePath != null) {
|
|
848
|
+
await writeWebAssets({
|
|
849
|
+
htmlTemplatePath,
|
|
850
|
+
props,
|
|
851
|
+
extras
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
await writeGenericAssets({
|
|
855
|
+
props,
|
|
856
|
+
extras
|
|
857
|
+
});
|
|
842
858
|
if (licenseKey != null && executeAddon) {
|
|
843
859
|
const addon = requireAddon();
|
|
844
860
|
await addon?.execute({
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
fileNameSuffix,
|
|
861
|
+
props,
|
|
862
|
+
extras,
|
|
848
863
|
androidOutputPath,
|
|
849
864
|
iosOutputPath,
|
|
850
|
-
htmlTemplatePath
|
|
851
|
-
assetsOutputPath,
|
|
852
|
-
logoHeight,
|
|
853
|
-
logoWidth,
|
|
854
|
-
brandHeight,
|
|
855
|
-
brandWidth,
|
|
856
|
-
logoPath,
|
|
857
|
-
darkLogoPath,
|
|
858
|
-
brandPath,
|
|
859
|
-
darkBrandPath,
|
|
860
|
-
background,
|
|
861
|
-
logo,
|
|
862
|
-
brand,
|
|
863
|
-
darkBackground,
|
|
864
|
-
darkLogo,
|
|
865
|
-
darkBrand
|
|
865
|
+
htmlTemplatePath
|
|
866
866
|
});
|
|
867
867
|
} else {
|
|
868
868
|
console.log(`
|
|
@@ -873,5 +873,275 @@ ${_picocolors.default.blue("┗━━━━━━━━━━━━━━━━
|
|
|
873
873
|
}
|
|
874
874
|
console.log(`\n💖 Thanks for using ${_picocolors.default.underline("react-native-bootsplash")}`);
|
|
875
875
|
};
|
|
876
|
+
|
|
877
|
+
// Expo plugin
|
|
876
878
|
exports.generate = generate;
|
|
879
|
+
const withoutExpoSplashScreen = Expo.createRunOncePlugin(config => config, "expo-splash-screen", "skip");
|
|
880
|
+
const withAndroidAssets = (config, props) => Expo.withDangerousMod(config, ["android", async config => {
|
|
881
|
+
const {
|
|
882
|
+
platformProjectRoot
|
|
883
|
+
} = config.modRequest;
|
|
884
|
+
const extras = await getExtras(props);
|
|
885
|
+
const androidOutputPath = _path.default.resolve(platformProjectRoot, "app", "src", "main", "res");
|
|
886
|
+
await writeAndroidAssets({
|
|
887
|
+
androidOutputPath,
|
|
888
|
+
props,
|
|
889
|
+
extras
|
|
890
|
+
});
|
|
891
|
+
return config;
|
|
892
|
+
}]);
|
|
893
|
+
const withAndroidManifest = config => Expo.withAndroidManifest(config, config => {
|
|
894
|
+
config.modResults.manifest.application?.forEach(application => {
|
|
895
|
+
if (application.$["android:name"] === ".MainApplication") {
|
|
896
|
+
const {
|
|
897
|
+
activity
|
|
898
|
+
} = application;
|
|
899
|
+
activity?.forEach(activity => {
|
|
900
|
+
if (activity.$["android:name"] === ".MainActivity") {
|
|
901
|
+
activity.$["android:theme"] = "@style/BootTheme";
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
return config;
|
|
907
|
+
});
|
|
908
|
+
const withMainActivity = config => Expo.withMainActivity(config, config => {
|
|
909
|
+
const {
|
|
910
|
+
modResults
|
|
911
|
+
} = config;
|
|
912
|
+
const withImports = (0, _codeMod.addImports)(modResults.contents.replace(/(\/\/ )?setTheme\(R\.style\.AppTheme\)/, "// setTheme(R.style.AppTheme)"), ["android.os.Bundle", "com.zoontek.rnbootsplash.RNBootSplash"], false);
|
|
913
|
+
|
|
914
|
+
// indented with 4 spaces
|
|
915
|
+
const withInit = (0, _generateCode.mergeContents)({
|
|
916
|
+
src: withImports,
|
|
917
|
+
comment: " //",
|
|
918
|
+
tag: "bootsplash-init",
|
|
919
|
+
offset: 0,
|
|
920
|
+
anchor: /super\.onCreate\(null\)/,
|
|
921
|
+
newSrc: " RNBootSplash.init(this, R.style.BootTheme)"
|
|
922
|
+
});
|
|
923
|
+
return {
|
|
924
|
+
...config,
|
|
925
|
+
modResults: {
|
|
926
|
+
...modResults,
|
|
927
|
+
contents: withInit.contents
|
|
928
|
+
}
|
|
929
|
+
};
|
|
930
|
+
});
|
|
931
|
+
const withAndroidStyles = (config, props) => Expo.withAndroidStyles(config, config => {
|
|
932
|
+
const {
|
|
933
|
+
android,
|
|
934
|
+
brand
|
|
935
|
+
} = props;
|
|
936
|
+
const {
|
|
937
|
+
darkContentBarsStyle
|
|
938
|
+
} = android;
|
|
939
|
+
const {
|
|
940
|
+
modResults
|
|
941
|
+
} = config;
|
|
942
|
+
const {
|
|
943
|
+
resources
|
|
944
|
+
} = modResults;
|
|
945
|
+
const {
|
|
946
|
+
style = []
|
|
947
|
+
} = resources;
|
|
948
|
+
const item = [{
|
|
949
|
+
$: {
|
|
950
|
+
name: "postBootSplashTheme"
|
|
951
|
+
},
|
|
952
|
+
_: "@style/AppTheme"
|
|
953
|
+
}, {
|
|
954
|
+
$: {
|
|
955
|
+
name: "bootSplashBackground"
|
|
956
|
+
},
|
|
957
|
+
_: "@color/bootsplash_background"
|
|
958
|
+
}, {
|
|
959
|
+
$: {
|
|
960
|
+
name: "bootSplashLogo"
|
|
961
|
+
},
|
|
962
|
+
_: "@drawable/bootsplash_logo"
|
|
963
|
+
}];
|
|
964
|
+
if (brand != null) {
|
|
965
|
+
item.push({
|
|
966
|
+
$: {
|
|
967
|
+
name: "bootSplashBrand"
|
|
968
|
+
},
|
|
969
|
+
_: "@drawable/bootsplash_brand"
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
if (darkContentBarsStyle != null) {
|
|
973
|
+
item.push({
|
|
974
|
+
$: {
|
|
975
|
+
name: "darkContentBarsStyle"
|
|
976
|
+
},
|
|
977
|
+
_: String(darkContentBarsStyle)
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
const withBootTheme = [...style.filter(({
|
|
981
|
+
$
|
|
982
|
+
}) => $.name !== "BootTheme"), {
|
|
983
|
+
$: {
|
|
984
|
+
name: "BootTheme",
|
|
985
|
+
parent: "Theme.BootSplash"
|
|
986
|
+
},
|
|
987
|
+
item
|
|
988
|
+
}];
|
|
989
|
+
return {
|
|
990
|
+
...config,
|
|
991
|
+
modResults: {
|
|
992
|
+
...modResults,
|
|
993
|
+
resources: {
|
|
994
|
+
...resources,
|
|
995
|
+
style: withBootTheme
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
};
|
|
999
|
+
});
|
|
1000
|
+
const withAndroidColors = (config, props) => Expo.withAndroidColors(config, config => {
|
|
1001
|
+
const {
|
|
1002
|
+
background
|
|
1003
|
+
} = props;
|
|
1004
|
+
config.modResults = (0, _Colors.assignColorValue)(config.modResults, {
|
|
1005
|
+
name: "bootsplash_background",
|
|
1006
|
+
value: background.hex
|
|
1007
|
+
});
|
|
1008
|
+
return config;
|
|
1009
|
+
});
|
|
1010
|
+
const withIOSAssets = (config, props) => Expo.withDangerousMod(config, ["ios", async config => {
|
|
1011
|
+
const {
|
|
1012
|
+
platformProjectRoot,
|
|
1013
|
+
projectName = ""
|
|
1014
|
+
} = config.modRequest;
|
|
1015
|
+
const extras = await getExtras(props);
|
|
1016
|
+
const iosOutputPath = _path.default.resolve(platformProjectRoot, projectName);
|
|
1017
|
+
await writeIOSAssets({
|
|
1018
|
+
iosOutputPath,
|
|
1019
|
+
props,
|
|
1020
|
+
extras
|
|
1021
|
+
});
|
|
1022
|
+
return config;
|
|
1023
|
+
}]);
|
|
1024
|
+
const withAppDelegate = config => Expo.withAppDelegate(config, config => {
|
|
1025
|
+
const {
|
|
1026
|
+
modResults
|
|
1027
|
+
} = config;
|
|
1028
|
+
const {
|
|
1029
|
+
language
|
|
1030
|
+
} = modResults;
|
|
1031
|
+
if (language !== "objc" && language !== "objcpp" && language !== "swift") {
|
|
1032
|
+
throw new Error(`Cannot modify the project AppDelegate as it's not in a supported language: ${language}`);
|
|
1033
|
+
}
|
|
1034
|
+
const withHeader = (0, _generateCode.mergeContents)({
|
|
1035
|
+
src: modResults.contents,
|
|
1036
|
+
comment: "//",
|
|
1037
|
+
tag: "bootsplash-header",
|
|
1038
|
+
offset: 1,
|
|
1039
|
+
anchor: /import Expo/,
|
|
1040
|
+
newSrc: "import RNBootSplash"
|
|
1041
|
+
});
|
|
1042
|
+
const withRootView = (0, _generateCode.mergeContents)({
|
|
1043
|
+
src: withHeader.contents,
|
|
1044
|
+
comment: "//",
|
|
1045
|
+
tag: "bootsplash-init",
|
|
1046
|
+
offset: 1,
|
|
1047
|
+
anchor: /class ReactNativeDelegate: ExpoReactNativeFactoryDelegate {/,
|
|
1048
|
+
newSrc: (0, _tsDedent.dedent)`
|
|
1049
|
+
public override func customize(_ rootView: UIView) {
|
|
1050
|
+
super.customize(rootView)
|
|
1051
|
+
RNBootSplash.initWithStoryboard("BootSplash", rootView: rootView)
|
|
1052
|
+
}
|
|
1053
|
+
`
|
|
1054
|
+
});
|
|
1055
|
+
return {
|
|
1056
|
+
...config,
|
|
1057
|
+
modResults: {
|
|
1058
|
+
...modResults,
|
|
1059
|
+
contents: withRootView.contents
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
});
|
|
1063
|
+
const withInfoPlist = config => Expo.withInfoPlist(config, config => {
|
|
1064
|
+
config.modResults["UILaunchStoryboardName"] = "BootSplash";
|
|
1065
|
+
return config;
|
|
1066
|
+
});
|
|
1067
|
+
const withXcodeProject = config => Expo.withXcodeProject(config, config => {
|
|
1068
|
+
const {
|
|
1069
|
+
projectName = ""
|
|
1070
|
+
} = config.modRequest;
|
|
1071
|
+
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
1072
|
+
filepath: _path.default.join(projectName, "BootSplash.storyboard"),
|
|
1073
|
+
groupName: projectName,
|
|
1074
|
+
project: config.modResults,
|
|
1075
|
+
isBuildFile: true
|
|
1076
|
+
});
|
|
1077
|
+
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
1078
|
+
filepath: _path.default.join(projectName, "Colors.xcassets"),
|
|
1079
|
+
groupName: projectName,
|
|
1080
|
+
project: config.modResults,
|
|
1081
|
+
isBuildFile: true
|
|
1082
|
+
});
|
|
1083
|
+
return config;
|
|
1084
|
+
});
|
|
1085
|
+
const withWebAssets = (config, props) => Expo.withDangerousMod(config, [config.platforms?.includes("ios") ? "ios" : "android", async config => {
|
|
1086
|
+
const extras = await getExtras(props);
|
|
1087
|
+
const fileName = "public/index.html";
|
|
1088
|
+
const htmlTemplatePath = _path.default.resolve(workingPath, fileName);
|
|
1089
|
+
if (!hfs.exists(htmlTemplatePath)) {
|
|
1090
|
+
await exec(`npx expo customize ${fileName}`);
|
|
1091
|
+
}
|
|
1092
|
+
await writeWebAssets({
|
|
1093
|
+
htmlTemplatePath,
|
|
1094
|
+
props,
|
|
1095
|
+
extras
|
|
1096
|
+
});
|
|
1097
|
+
return config;
|
|
1098
|
+
}]);
|
|
1099
|
+
const withGenericAssets = (config, props) => Expo.withDangerousMod(config, [config.platforms?.includes("ios") ? "ios" : "android", async config => {
|
|
1100
|
+
const extras = await getExtras(props);
|
|
1101
|
+
await writeGenericAssets({
|
|
1102
|
+
props,
|
|
1103
|
+
extras
|
|
1104
|
+
});
|
|
1105
|
+
return config;
|
|
1106
|
+
}]);
|
|
1107
|
+
const withBootSplash = exports.withBootSplash = Expo.createRunOncePlugin((config, baseProps) => {
|
|
1108
|
+
const {
|
|
1109
|
+
platforms = [],
|
|
1110
|
+
sdkVersion = "0.1.0"
|
|
1111
|
+
} = config;
|
|
1112
|
+
isExpo = true;
|
|
1113
|
+
if (_semver.default.lt(sdkVersion, "53.0.0")) {
|
|
1114
|
+
log.error("Requires Expo 53.0.0 (or higher)");
|
|
1115
|
+
process.exit(1);
|
|
1116
|
+
}
|
|
1117
|
+
if (!baseProps?.logo) {
|
|
1118
|
+
log.error("Missing required parameter 'logo'");
|
|
1119
|
+
process.exit(1);
|
|
1120
|
+
}
|
|
1121
|
+
const props = getProps({
|
|
1122
|
+
assetsOutput: "assets/bootsplash",
|
|
1123
|
+
background: "#fff",
|
|
1124
|
+
brandWidth: 80,
|
|
1125
|
+
logoWidth: 100,
|
|
1126
|
+
...baseProps
|
|
1127
|
+
});
|
|
1128
|
+
const {
|
|
1129
|
+
executeAddon
|
|
1130
|
+
} = props;
|
|
1131
|
+
const addon = executeAddon ? requireAddon() : undefined;
|
|
1132
|
+
const plugins = [withoutExpoSplashScreen, addon?.withGenericAssets ?? withGenericAssets];
|
|
1133
|
+
if (platforms.includes("android")) {
|
|
1134
|
+
plugins.push(addon?.withAndroidAssets ?? withAndroidAssets, withAndroidManifest, withMainActivity, withAndroidStyles, withAndroidColors);
|
|
1135
|
+
if (addon != null) {
|
|
1136
|
+
plugins.push(addon.withAndroidColorsNight);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
if (platforms.includes("ios")) {
|
|
1140
|
+
plugins.push(addon?.withIOSAssets ?? withIOSAssets, withAppDelegate, withInfoPlist, withXcodeProject);
|
|
1141
|
+
}
|
|
1142
|
+
if (platforms.includes("web")) {
|
|
1143
|
+
plugins.push(addon?.withWebAssets ?? withWebAssets);
|
|
1144
|
+
}
|
|
1145
|
+
return Expo.withPlugins(config, plugins.map(plugin => [plugin, props]));
|
|
1146
|
+
}, PACKAGE_NAME);
|
|
877
1147
|
//# sourceMappingURL=generate.js.map
|