react-native-bootsplash 7.0.0-beta.1 → 7.0.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/src/generate.ts CHANGED
@@ -1,12 +1,8 @@
1
1
  import * as Expo from "@expo/config-plugins";
2
- import { assignColorValue } from "@expo/config-plugins/build/android/Colors";
3
- import { addImports } from "@expo/config-plugins/build/android/codeMod";
4
- import { mergeContents } from "@expo/config-plugins/build/utils/generateCode";
5
2
  import ExpoPlist from "@expo/plist";
6
3
  import { projectConfig as getAndroidProjectConfig } from "@react-native-community/cli-config-android";
7
4
  import { getProjectConfig as getAppleProjectConfig } from "@react-native-community/cli-config-apple";
8
5
  import { findProjectRoot } from "@react-native-community/cli-tools";
9
- import childProcess from "child_process";
10
6
  import crypto from "crypto";
11
7
  import detectIndent, { type Indent } from "detect-indent";
12
8
  import fs from "fs-extra";
@@ -20,20 +16,12 @@ import * as prettier from "prettier/standalone";
20
16
  import semver from "semver";
21
17
  import sharp, { type Sharp } from "sharp";
22
18
  import { dedent } from "ts-dedent";
23
- import util from "util";
24
19
  import formatXml, { type XMLFormatterOptions } from "xml-formatter";
25
20
  import type { Manifest } from ".";
26
21
 
27
- const PACKAGE_NAME = "react-native-bootsplash";
22
+ type Platforms = ("android" | "ios" | "web")[];
28
23
 
29
- let isExpo = false;
30
-
31
- const workingPath = process.env.INIT_CWD ?? process.env.PWD ?? process.cwd();
32
- const projectRoot = findProjectRoot(workingPath);
33
-
34
- export type Platforms = ("android" | "ios" | "web")[];
35
-
36
- export type RGBColor = {
24
+ type RGBColor = {
37
25
  R: string;
38
26
  G: string;
39
27
  B: string;
@@ -44,16 +32,19 @@ type Color = {
44
32
  rgb: RGBColor;
45
33
  };
46
34
 
47
- const promisifiedExec = util.promisify(childProcess.exec);
35
+ export const packageName = "react-native-bootsplash";
36
+ const workingPath = process.env.INIT_CWD ?? process.env.PWD ?? process.cwd();
37
+ const projectRoot = findProjectRoot(workingPath);
38
+
39
+ let isExpo = false;
48
40
 
49
- const exec = (cmd: string) =>
50
- promisifiedExec(cmd).then(({ stdout, stderr }) => stdout || stderr);
41
+ export const setIsExpo = (value: boolean) => {
42
+ isExpo = value;
43
+ };
51
44
 
52
45
  export const log = {
53
46
  error: (text: string) => {
54
- console.log(
55
- pc.red(isExpo ? `❌ [${PACKAGE_NAME}] ${text}` : `❌ ${text}`),
56
- );
47
+ console.log(pc.red(isExpo ? `❌ [${packageName}] ${text}` : `❌ ${text}`));
57
48
  },
58
49
  title: (emoji: string, text: string) => {
59
50
  if (!isExpo) {
@@ -62,7 +53,7 @@ export const log = {
62
53
  },
63
54
  warn: (text: string) => {
64
55
  console.log(
65
- pc.yellow(isExpo ? `⚠️ [${PACKAGE_NAME}] ${text}` : `⚠️ ${text}`),
56
+ pc.yellow(isExpo ? `⚠️ [${packageName}] ${text}` : `⚠️ ${text}`),
66
57
  );
67
58
  },
68
59
  write: (filePath: string, dimensions?: { width: number; height: number }) => {
@@ -356,24 +347,6 @@ const getInfoPlistPath = ({
356
347
  return path.resolve(iosOutputPath, "Info.plist");
357
348
  };
358
349
 
359
- type RawProps = {
360
- logo: string;
361
- background: string;
362
- logoWidth: number;
363
- assetsOutput: string;
364
-
365
- licenseKey?: string;
366
- brand?: string;
367
- brandWidth: number;
368
- darkBackground?: string;
369
- darkLogo?: string;
370
- darkBrand?: string;
371
-
372
- android?: {
373
- darkContentBarsStyle?: boolean;
374
- };
375
- };
376
-
377
350
  export type Asset = {
378
351
  path: string;
379
352
  image: Sharp;
@@ -418,7 +391,25 @@ const toAsset = async (filePath: string, width: number): Promise<Asset> => {
418
391
  };
419
392
  };
420
393
 
421
- const transformProps = async (
394
+ export type RawProps = {
395
+ logo: string;
396
+ background: string;
397
+ logoWidth: number;
398
+ assetsOutput: string;
399
+
400
+ licenseKey?: string;
401
+ brand?: string;
402
+ brandWidth: number;
403
+ darkBackground?: string;
404
+ darkLogo?: string;
405
+ darkBrand?: string;
406
+
407
+ android?: {
408
+ darkContentBarsStyle?: boolean;
409
+ };
410
+ };
411
+
412
+ export const transformProps = async (
422
413
  rootPath: string,
423
414
  { android = {}, licenseKey, ...rawProps }: RawProps,
424
415
  ) => {
@@ -549,7 +540,7 @@ const transformProps = async (
549
540
 
550
541
  export type Props = Awaited<ReturnType<typeof transformProps>>;
551
542
 
552
- const writeAndroidAssets = async ({
543
+ export const writeAndroidAssets = async ({
553
544
  androidOutputPath,
554
545
  props,
555
546
  }: {
@@ -629,7 +620,7 @@ const writeAndroidAssets = async ({
629
620
  );
630
621
  };
631
622
 
632
- const writeIOSAssets = async ({
623
+ export const writeIOSAssets = async ({
633
624
  iosOutputPath,
634
625
  props,
635
626
  }: {
@@ -749,7 +740,7 @@ const writeIOSAssets = async ({
749
740
  );
750
741
  };
751
742
 
752
- const writeWebAssets = async ({
743
+ export const writeWebAssets = async ({
753
744
  htmlTemplatePath,
754
745
  props,
755
746
  }: {
@@ -825,7 +816,7 @@ const writeWebAssets = async ({
825
816
  });
826
817
  };
827
818
 
828
- const writeGenericAssets = async ({ props }: { props: Props }) => {
819
+ export const writeGenericAssets = async ({ props }: { props: Props }) => {
829
820
  const { assetsOutputPath, background, logo } = props;
830
821
 
831
822
  log.title("📄", "Assets");
@@ -868,7 +859,7 @@ export type AddonConfig = {
868
859
  htmlTemplatePath: string | void;
869
860
  };
870
861
 
871
- const requireAddon = ({
862
+ export const requireAddon = ({
872
863
  executeAddon,
873
864
  licenseKey,
874
865
  }: Props):
@@ -900,7 +891,8 @@ const requireAddon = ({
900
891
  | undefined => {
901
892
  if (licenseKey != null && executeAddon) {
902
893
  try {
903
- return require("./addon");
894
+ const addon = require("./dist/commonjs/addon");
895
+ return "default" in addon ? addon.default : addon;
904
896
  } catch {
905
897
  return;
906
898
  }
@@ -1065,30 +1057,6 @@ export const generate = async ({
1065
1057
  if (iosOutputPath != null) {
1066
1058
  await writeIOSAssets({ iosOutputPath, props });
1067
1059
 
1068
- const infoPlistPath = getInfoPlistPath({ iosOutputPath, plist });
1069
-
1070
- if (infoPlistPath != null) {
1071
- const infoPlist = ExpoPlist.parse(hfs.text(infoPlistPath)) as Record<
1072
- string,
1073
- unknown
1074
- >;
1075
-
1076
- infoPlist["UILaunchStoryboardName"] = "BootSplash";
1077
-
1078
- const formatted = formatXml(ExpoPlist.build(infoPlist), {
1079
- collapseContent: true,
1080
- forceSelfClosingEmptyTag: false,
1081
- indentation: "\t",
1082
- lineSeparator: "\n",
1083
- whiteSpaceAtEndOfSelfclosingTag: false,
1084
- })
1085
- .replace(/<string\/>/gm, "<string></string>")
1086
- .replace(/^\t/gm, "");
1087
-
1088
- hfs.write(infoPlistPath, formatted);
1089
- log.write(infoPlistPath);
1090
- }
1091
-
1092
1060
  const pbxprojectPath = Expo.IOSConfig.Paths.getPBXProjectPath(projectRoot);
1093
1061
 
1094
1062
  const xcodeProjectPath =
@@ -1114,6 +1082,30 @@ export const generate = async ({
1114
1082
 
1115
1083
  hfs.write(pbxprojectPath, project.writeSync());
1116
1084
  log.write(pbxprojectPath);
1085
+
1086
+ const infoPlistPath = getInfoPlistPath({ iosOutputPath, plist });
1087
+
1088
+ if (infoPlistPath != null) {
1089
+ const infoPlist = ExpoPlist.parse(hfs.text(infoPlistPath)) as Record<
1090
+ string,
1091
+ unknown
1092
+ >;
1093
+
1094
+ infoPlist["UILaunchStoryboardName"] = "BootSplash";
1095
+
1096
+ const formatted = formatXml(ExpoPlist.build(infoPlist), {
1097
+ collapseContent: true,
1098
+ forceSelfClosingEmptyTag: false,
1099
+ indentation: "\t",
1100
+ lineSeparator: "\n",
1101
+ whiteSpaceAtEndOfSelfclosingTag: false,
1102
+ })
1103
+ .replace(/<string\/>/gm, "<string></string>")
1104
+ .replace(/^\t/gm, "");
1105
+
1106
+ hfs.write(infoPlistPath, formatted);
1107
+ log.write(infoPlistPath);
1108
+ }
1117
1109
  }
1118
1110
 
1119
1111
  if (htmlTemplatePath != null) {
@@ -1145,360 +1137,3 @@ ${pc.blue("┗━━━━━━━━━━━━━━━━━━━━━━
1145
1137
  `\n💖 Thanks for using ${pc.underline("react-native-bootsplash")}`,
1146
1138
  );
1147
1139
  };
1148
-
1149
- // Expo plugin
1150
-
1151
- const withoutExpoSplashScreen: Expo.ConfigPlugin<RawProps> =
1152
- Expo.createRunOncePlugin(
1153
- (expoConfig) => expoConfig,
1154
- "expo-splash-screen",
1155
- "skip",
1156
- );
1157
-
1158
- const withAndroidAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
1159
- Expo.withDangerousMod(expoConfig, [
1160
- "android",
1161
- async (config) => {
1162
- const { platformProjectRoot, projectRoot } = config.modRequest;
1163
- const props = await transformProps(projectRoot, rawProps);
1164
- const addon = requireAddon(props);
1165
-
1166
- const androidOutputPath = path.resolve(
1167
- platformProjectRoot,
1168
- "app",
1169
- "src",
1170
- "main",
1171
- "res",
1172
- );
1173
-
1174
- await writeAndroidAssets({ androidOutputPath, props });
1175
- await addon?.writeAndroidAssets({ androidOutputPath, props });
1176
-
1177
- return config;
1178
- },
1179
- ]);
1180
-
1181
- const withAndroidManifest: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
1182
- Expo.withAndroidManifest(expoConfig, (config) => {
1183
- config.modResults.manifest.application?.forEach((application) => {
1184
- if (application.$["android:name"] === ".MainApplication") {
1185
- const { activity } = application;
1186
-
1187
- activity?.forEach((activity) => {
1188
- if (activity.$["android:name"] === ".MainActivity") {
1189
- activity.$["android:theme"] = "@style/BootTheme";
1190
- }
1191
- });
1192
- }
1193
- });
1194
-
1195
- return config;
1196
- });
1197
-
1198
- const withMainActivity: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
1199
- Expo.withMainActivity(expoConfig, (config) => {
1200
- const { modResults } = config;
1201
-
1202
- const withImports = addImports(
1203
- modResults.contents.replace(
1204
- /(\/\/ )?setTheme\(R\.style\.AppTheme\)/,
1205
- "// setTheme(R.style.AppTheme)",
1206
- ),
1207
- ["android.os.Bundle", "com.zoontek.rnbootsplash.RNBootSplash"],
1208
- false,
1209
- );
1210
-
1211
- // indented with 4 spaces
1212
- const withInit = mergeContents({
1213
- src: withImports,
1214
- comment: " //",
1215
- tag: "bootsplash-init",
1216
- offset: 0,
1217
- anchor: /super\.onCreate\(null\)/,
1218
- newSrc: " RNBootSplash.init(this, R.style.BootTheme)",
1219
- });
1220
-
1221
- return {
1222
- ...config,
1223
- modResults: {
1224
- ...modResults,
1225
- contents: withInit.contents,
1226
- },
1227
- };
1228
- });
1229
-
1230
- const withAndroidStyles: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
1231
- Expo.withAndroidStyles(expoConfig, async (config) => {
1232
- const { projectRoot } = config.modRequest;
1233
- const { android, brand } = await transformProps(projectRoot, rawProps);
1234
- const { darkContentBarsStyle } = android;
1235
-
1236
- const { modResults } = config;
1237
- const { resources } = modResults;
1238
- const { style = [] } = resources;
1239
-
1240
- const item = [
1241
- {
1242
- $: { name: "postBootSplashTheme" },
1243
- _: "@style/AppTheme",
1244
- },
1245
- {
1246
- $: { name: "bootSplashBackground" },
1247
- _: "@color/bootsplash_background",
1248
- },
1249
- {
1250
- $: { name: "bootSplashLogo" },
1251
- _: "@drawable/bootsplash_logo",
1252
- },
1253
- ];
1254
-
1255
- if (brand != null) {
1256
- item.push({
1257
- $: { name: "bootSplashBrand" },
1258
- _: "@drawable/bootsplash_brand",
1259
- });
1260
- }
1261
- if (darkContentBarsStyle != null) {
1262
- item.push({
1263
- $: { name: "darkContentBarsStyle" },
1264
- _: String(darkContentBarsStyle),
1265
- });
1266
- }
1267
-
1268
- const withBootTheme = [
1269
- ...style.filter(({ $ }) => $.name !== "BootTheme"),
1270
- {
1271
- $: {
1272
- name: "BootTheme",
1273
- parent: "Theme.BootSplash",
1274
- },
1275
- item,
1276
- },
1277
- ];
1278
-
1279
- return {
1280
- ...config,
1281
- modResults: {
1282
- ...modResults,
1283
- resources: {
1284
- ...resources,
1285
- style: withBootTheme,
1286
- },
1287
- },
1288
- };
1289
- });
1290
-
1291
- const withAndroidColors: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
1292
- Expo.withAndroidColors(expoConfig, async (config) => {
1293
- const { projectRoot } = config.modRequest;
1294
- const { background } = await transformProps(projectRoot, rawProps);
1295
-
1296
- config.modResults = assignColorValue(config.modResults, {
1297
- name: "bootsplash_background",
1298
- value: background.hex,
1299
- });
1300
-
1301
- return config;
1302
- });
1303
-
1304
- const withAndroidColorsNight: Expo.ConfigPlugin<RawProps> = (
1305
- expoConfig,
1306
- rawProps,
1307
- ) =>
1308
- Expo.withAndroidColorsNight(expoConfig, async (config) => {
1309
- const { projectRoot } = config.modRequest;
1310
- const props = await transformProps(projectRoot, rawProps);
1311
- const addon = requireAddon(props);
1312
-
1313
- return addon != null
1314
- ? await addon.withAndroidColorsNight({ config, props })
1315
- : config;
1316
- });
1317
-
1318
- const withIOSAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
1319
- Expo.withDangerousMod(expoConfig, [
1320
- "ios",
1321
- async (config) => {
1322
- const {
1323
- platformProjectRoot,
1324
- projectName = "",
1325
- projectRoot,
1326
- } = config.modRequest;
1327
-
1328
- const props = await transformProps(projectRoot, rawProps);
1329
- const addon = requireAddon(props);
1330
- const iosOutputPath = path.resolve(platformProjectRoot, projectName);
1331
-
1332
- await writeIOSAssets({ iosOutputPath, props });
1333
- await addon?.writeIOSAssets({ iosOutputPath, props });
1334
-
1335
- return config;
1336
- },
1337
- ]);
1338
-
1339
- const withAppDelegate: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
1340
- Expo.withAppDelegate(expoConfig, (config) => {
1341
- const { modResults } = config;
1342
- const { language } = modResults;
1343
-
1344
- if (language !== "swift") {
1345
- throw new Error(
1346
- `Cannot modify the project AppDelegate as it's not in a supported language: ${language}`,
1347
- );
1348
- }
1349
-
1350
- const withHeader = mergeContents({
1351
- src: modResults.contents,
1352
- comment: "//",
1353
- tag: "bootsplash-header",
1354
- offset: 1,
1355
- anchor: /import Expo/,
1356
- newSrc: "import RNBootSplash",
1357
- });
1358
-
1359
- const withRootView = mergeContents({
1360
- src: withHeader.contents,
1361
- comment: "//",
1362
- tag: "bootsplash-init",
1363
- offset: 1,
1364
- anchor: /class ReactNativeDelegate: ExpoReactNativeFactoryDelegate {/,
1365
- newSrc: dedent`
1366
- public override func customize(_ rootView: UIView) {
1367
- super.customize(rootView)
1368
- RNBootSplash.initWithStoryboard("BootSplash", rootView: rootView)
1369
- }
1370
- `,
1371
- });
1372
-
1373
- return {
1374
- ...config,
1375
- modResults: {
1376
- ...modResults,
1377
- contents: withRootView.contents,
1378
- },
1379
- };
1380
- });
1381
-
1382
- const withInfoPlist: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
1383
- Expo.withInfoPlist(expoConfig, (config) => {
1384
- config.modResults["UILaunchStoryboardName"] = "BootSplash";
1385
- return config;
1386
- });
1387
-
1388
- const withXcodeProject: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
1389
- Expo.withXcodeProject(expoConfig, (config) => {
1390
- const { projectName = "" } = config.modRequest;
1391
-
1392
- Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
1393
- filepath: path.join(projectName, "BootSplash.storyboard"),
1394
- groupName: projectName,
1395
- project: config.modResults,
1396
- isBuildFile: true,
1397
- });
1398
-
1399
- Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
1400
- filepath: path.join(projectName, "Colors.xcassets"),
1401
- groupName: projectName,
1402
- project: config.modResults,
1403
- isBuildFile: true,
1404
- });
1405
-
1406
- return config;
1407
- });
1408
-
1409
- const withWebAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
1410
- Expo.withDangerousMod(expoConfig, [
1411
- expoConfig.platforms?.includes("ios") ? "ios" : "android",
1412
- async (config) => {
1413
- const { projectRoot } = config.modRequest;
1414
- const props = await transformProps(projectRoot, rawProps);
1415
- const addon = requireAddon(props);
1416
-
1417
- const fileName = "public/index.html";
1418
- const htmlTemplatePath = path.resolve(projectRoot, fileName);
1419
-
1420
- if (!hfs.exists(htmlTemplatePath)) {
1421
- await exec(`npx expo customize ${fileName}`);
1422
- }
1423
-
1424
- await writeWebAssets({ htmlTemplatePath, props });
1425
- await addon?.writeWebAssets({ htmlTemplatePath, props });
1426
-
1427
- return config;
1428
- },
1429
- ]);
1430
-
1431
- const withGenericAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
1432
- Expo.withDangerousMod(expoConfig, [
1433
- expoConfig.platforms?.includes("ios") ? "ios" : "android",
1434
- async (config) => {
1435
- const { projectRoot } = config.modRequest;
1436
- const props = await transformProps(projectRoot, rawProps);
1437
- const addon = requireAddon(props);
1438
-
1439
- await writeGenericAssets({ props });
1440
- await addon?.writeGenericAssets({ props });
1441
-
1442
- return config;
1443
- },
1444
- ]);
1445
-
1446
- export const withBootSplash = Expo.createRunOncePlugin<
1447
- (Partial<RawProps> & { logo: string }) | undefined
1448
- >((config, baseProps) => {
1449
- const { platforms = [], sdkVersion = "0.1.0" } = config;
1450
-
1451
- isExpo = true;
1452
-
1453
- if (semver.lt(sdkVersion, "54.0.0")) {
1454
- log.error("Requires Expo 54.0.0 (or higher)");
1455
- process.exit(1);
1456
- }
1457
-
1458
- if (!baseProps?.logo) {
1459
- log.error("Missing required parameter 'logo'");
1460
- process.exit(1);
1461
- }
1462
-
1463
- const rawProps: RawProps = {
1464
- assetsOutput: "assets/bootsplash",
1465
- background: "#fff",
1466
- brandWidth: 80,
1467
- logoWidth: 100,
1468
- ...baseProps,
1469
- };
1470
-
1471
- const plugins: Expo.ConfigPlugin<RawProps>[] = [
1472
- withoutExpoSplashScreen,
1473
- withGenericAssets,
1474
- ];
1475
-
1476
- if (platforms.includes("android")) {
1477
- plugins.push(
1478
- withAndroidAssets,
1479
- withAndroidManifest,
1480
- withMainActivity,
1481
- withAndroidStyles,
1482
- withAndroidColors,
1483
- withAndroidColorsNight,
1484
- );
1485
- }
1486
-
1487
- if (platforms.includes("ios")) {
1488
- plugins.push(
1489
- withIOSAssets,
1490
- withAppDelegate,
1491
- withInfoPlist,
1492
- withXcodeProject,
1493
- );
1494
- }
1495
-
1496
- if (platforms.includes("web")) {
1497
- plugins.push(withWebAssets);
1498
- }
1499
-
1500
- return Expo.withPlugins(
1501
- config,
1502
- plugins.map((plugin) => [plugin, rawProps]),
1503
- );
1504
- }, PACKAGE_NAME);