react-native-bootsplash 7.0.2 → 7.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app.plugin.js +1 -1
- package/cli.js +1 -1
- package/dist/commonjs/extras/addon/index.js +97 -0
- package/dist/commonjs/extras/addon/index.js.map +1 -0
- package/dist/commonjs/{expo.js → extras/expo.js} +27 -23
- package/dist/commonjs/extras/expo.js.map +1 -0
- package/dist/commonjs/extras/generate.js +274 -0
- package/dist/commonjs/extras/generate.js.map +1 -0
- package/dist/commonjs/{generate.js → extras/utils.js} +109 -344
- package/dist/commonjs/extras/utils.js.map +1 -0
- package/dist/commonjs/package.json +1 -0
- package/dist/module/extras/addon/index.js +97 -0
- package/dist/module/extras/addon/index.js.map +1 -0
- package/dist/module/{expo.js → extras/expo.js} +5 -2
- package/dist/module/extras/expo.js.map +1 -0
- package/dist/module/extras/generate.js +267 -0
- package/dist/module/extras/generate.js.map +1 -0
- package/dist/module/{generate.js → extras/utils.js} +97 -331
- package/dist/module/extras/utils.js.map +1 -0
- package/dist/module/package.json +1 -0
- package/dist/typescript/{addon → commonjs/extras/addon}/index.d.ts +1 -1
- package/dist/typescript/commonjs/extras/addon/index.d.ts.map +1 -0
- package/dist/typescript/commonjs/extras/expo.d.ts +8 -0
- package/dist/typescript/commonjs/extras/expo.d.ts.map +1 -0
- package/dist/typescript/commonjs/extras/generate.d.ts +17 -0
- package/dist/typescript/commonjs/extras/generate.d.ts.map +1 -0
- package/dist/typescript/{generate.d.ts → commonjs/extras/utils.d.ts} +67 -36
- package/dist/typescript/commonjs/extras/utils.d.ts.map +1 -0
- package/dist/typescript/commonjs/index.d.ts.map +1 -0
- package/dist/typescript/commonjs/package.json +1 -0
- package/dist/typescript/commonjs/specs/NativeRNBootSplash.d.ts.map +1 -0
- package/dist/typescript/commonjs/specs/NativeRNBootSplash.web.d.ts.map +1 -0
- package/dist/typescript/module/extras/addon/index.d.ts +26 -0
- package/dist/typescript/module/extras/addon/index.d.ts.map +1 -0
- package/dist/typescript/module/extras/expo.d.ts +8 -0
- package/dist/typescript/module/extras/expo.d.ts.map +1 -0
- package/dist/typescript/module/extras/generate.d.ts +17 -0
- package/dist/typescript/module/extras/generate.d.ts.map +1 -0
- package/dist/typescript/module/extras/utils.d.ts +193 -0
- package/dist/typescript/module/extras/utils.d.ts.map +1 -0
- package/dist/typescript/module/index.d.ts +61 -0
- package/dist/typescript/module/index.d.ts.map +1 -0
- package/dist/typescript/module/package.json +1 -0
- package/dist/typescript/module/specs/NativeRNBootSplash.d.ts +14 -0
- package/dist/typescript/module/specs/NativeRNBootSplash.d.ts.map +1 -0
- package/dist/typescript/module/specs/NativeRNBootSplash.web.d.ts +9 -0
- package/dist/typescript/module/specs/NativeRNBootSplash.web.d.ts.map +1 -0
- package/package.json +49 -19
- package/src/{expo.ts → extras/expo.ts} +30 -31
- package/src/extras/generate.ts +410 -0
- package/src/{generate.ts → extras/utils.ts} +156 -479
- package/dist/commonjs/addon/index.js +0 -97
- package/dist/commonjs/addon/index.js.map +0 -1
- package/dist/commonjs/expo.js.map +0 -1
- package/dist/commonjs/generate.js.map +0 -1
- package/dist/module/addon/index.js +0 -97
- package/dist/module/addon/index.js.map +0 -1
- package/dist/module/expo.js.map +0 -1
- package/dist/module/generate.js.map +0 -1
- package/dist/typescript/addon/index.d.ts.map +0 -1
- package/dist/typescript/expo.d.ts +0 -6
- package/dist/typescript/expo.d.ts.map +0 -1
- package/dist/typescript/generate.d.ts.map +0 -1
- package/dist/typescript/index.d.ts.map +0 -1
- package/dist/typescript/specs/NativeRNBootSplash.d.ts.map +0 -1
- package/dist/typescript/specs/NativeRNBootSplash.web.d.ts.map +0 -1
- /package/dist/typescript/{index.d.ts → commonjs/index.d.ts} +0 -0
- /package/dist/typescript/{specs → commonjs/specs}/NativeRNBootSplash.d.ts +0 -0
- /package/dist/typescript/{specs → commonjs/specs}/NativeRNBootSplash.web.d.ts +0 -0
|
@@ -8,32 +8,33 @@ import semver from "semver";
|
|
|
8
8
|
import { dedent } from "ts-dedent";
|
|
9
9
|
import util from "util";
|
|
10
10
|
import {
|
|
11
|
-
type
|
|
11
|
+
type BootSplashPluginConfig,
|
|
12
12
|
hfs,
|
|
13
13
|
log,
|
|
14
14
|
PACKAGE_NAME,
|
|
15
15
|
requireAddon,
|
|
16
|
-
|
|
16
|
+
setLoggerMode,
|
|
17
17
|
transformProps,
|
|
18
18
|
writeAndroidAssets,
|
|
19
19
|
writeGenericAssets,
|
|
20
20
|
writeIOSAssets,
|
|
21
21
|
writeWebAssets,
|
|
22
|
-
} from "./
|
|
22
|
+
} from "./utils";
|
|
23
23
|
|
|
24
24
|
const promisifiedExec = util.promisify(childProcess.exec);
|
|
25
25
|
|
|
26
26
|
const exec = (cmd: string) =>
|
|
27
27
|
promisifiedExec(cmd).then(({ stdout, stderr }) => stdout || stderr);
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
type ConfigPlugin = Expo.ConfigPlugin<BootSplashPluginConfig>;
|
|
30
|
+
|
|
31
|
+
const withoutExpoSplashScreen: ConfigPlugin = Expo.createRunOncePlugin(
|
|
32
|
+
(expoConfig) => expoConfig,
|
|
33
|
+
"expo-splash-screen",
|
|
34
|
+
"skip",
|
|
35
|
+
);
|
|
35
36
|
|
|
36
|
-
const withAndroidAssets:
|
|
37
|
+
const withAndroidAssets: ConfigPlugin = (expoConfig, rawProps) =>
|
|
37
38
|
Expo.withDangerousMod(expoConfig, [
|
|
38
39
|
"android",
|
|
39
40
|
async (config) => {
|
|
@@ -56,7 +57,7 @@ const withAndroidAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
|
|
|
56
57
|
},
|
|
57
58
|
]);
|
|
58
59
|
|
|
59
|
-
const withAndroidManifest:
|
|
60
|
+
const withAndroidManifest: ConfigPlugin = (expoConfig) =>
|
|
60
61
|
Expo.withAndroidManifest(expoConfig, (config) => {
|
|
61
62
|
config.modResults.manifest.application?.forEach((application) => {
|
|
62
63
|
if (application.$["android:name"] === ".MainApplication") {
|
|
@@ -73,7 +74,7 @@ const withAndroidManifest: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
|
|
|
73
74
|
return config;
|
|
74
75
|
});
|
|
75
76
|
|
|
76
|
-
const withMainActivity:
|
|
77
|
+
const withMainActivity: ConfigPlugin = (expoConfig) =>
|
|
77
78
|
Expo.withMainActivity(expoConfig, (config) => {
|
|
78
79
|
const { modResults } = config;
|
|
79
80
|
|
|
@@ -105,7 +106,7 @@ const withMainActivity: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
|
|
|
105
106
|
};
|
|
106
107
|
});
|
|
107
108
|
|
|
108
|
-
const withAndroidStyles:
|
|
109
|
+
const withAndroidStyles: ConfigPlugin = (expoConfig, rawProps) =>
|
|
109
110
|
Expo.withAndroidStyles(expoConfig, async (config) => {
|
|
110
111
|
const { projectRoot } = config.modRequest;
|
|
111
112
|
const { android, brand } = await transformProps(projectRoot, rawProps);
|
|
@@ -166,7 +167,7 @@ const withAndroidStyles: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
|
|
|
166
167
|
};
|
|
167
168
|
});
|
|
168
169
|
|
|
169
|
-
const withAndroidColors:
|
|
170
|
+
const withAndroidColors: ConfigPlugin = (expoConfig, rawProps) =>
|
|
170
171
|
Expo.withAndroidColors(expoConfig, async (config) => {
|
|
171
172
|
const { projectRoot } = config.modRequest;
|
|
172
173
|
const { background } = await transformProps(projectRoot, rawProps);
|
|
@@ -179,10 +180,7 @@ const withAndroidColors: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
|
|
|
179
180
|
return config;
|
|
180
181
|
});
|
|
181
182
|
|
|
182
|
-
const withAndroidColorsNight:
|
|
183
|
-
expoConfig,
|
|
184
|
-
rawProps,
|
|
185
|
-
) =>
|
|
183
|
+
const withAndroidColorsNight: ConfigPlugin = (expoConfig, rawProps) =>
|
|
186
184
|
Expo.withAndroidColorsNight(expoConfig, async (config) => {
|
|
187
185
|
const { projectRoot } = config.modRequest;
|
|
188
186
|
const props = await transformProps(projectRoot, rawProps);
|
|
@@ -193,7 +191,7 @@ const withAndroidColorsNight: Expo.ConfigPlugin<RawProps> = (
|
|
|
193
191
|
: config;
|
|
194
192
|
});
|
|
195
193
|
|
|
196
|
-
const withIOSAssets:
|
|
194
|
+
const withIOSAssets: ConfigPlugin = (expoConfig, rawProps) =>
|
|
197
195
|
Expo.withDangerousMod(expoConfig, [
|
|
198
196
|
"ios",
|
|
199
197
|
async (config) => {
|
|
@@ -214,7 +212,7 @@ const withIOSAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
|
|
|
214
212
|
},
|
|
215
213
|
]);
|
|
216
214
|
|
|
217
|
-
const withAppDelegate:
|
|
215
|
+
const withAppDelegate: ConfigPlugin = (expoConfig) =>
|
|
218
216
|
Expo.withAppDelegate(expoConfig, (config) => {
|
|
219
217
|
const { modResults } = config;
|
|
220
218
|
const { language } = modResults;
|
|
@@ -257,13 +255,13 @@ const withAppDelegate: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
|
|
|
257
255
|
};
|
|
258
256
|
});
|
|
259
257
|
|
|
260
|
-
const withInfoPlist:
|
|
258
|
+
const withInfoPlist: ConfigPlugin = (expoConfig) =>
|
|
261
259
|
Expo.withInfoPlist(expoConfig, (config) => {
|
|
262
260
|
config.modResults["UILaunchStoryboardName"] = "BootSplash";
|
|
263
261
|
return config;
|
|
264
262
|
});
|
|
265
263
|
|
|
266
|
-
const withXcodeProject:
|
|
264
|
+
const withXcodeProject: ConfigPlugin = (expoConfig) =>
|
|
267
265
|
Expo.withXcodeProject(expoConfig, (config) => {
|
|
268
266
|
const { projectName = "" } = config.modRequest;
|
|
269
267
|
|
|
@@ -284,7 +282,7 @@ const withXcodeProject: Expo.ConfigPlugin<RawProps> = (expoConfig) =>
|
|
|
284
282
|
return config;
|
|
285
283
|
});
|
|
286
284
|
|
|
287
|
-
const withWebAssets:
|
|
285
|
+
const withWebAssets: ConfigPlugin = (expoConfig, rawProps) =>
|
|
288
286
|
Expo.withDangerousMod(expoConfig, [
|
|
289
287
|
expoConfig.platforms?.includes("ios") ? "ios" : "android",
|
|
290
288
|
async (config) => {
|
|
@@ -306,7 +304,7 @@ const withWebAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
|
|
|
306
304
|
},
|
|
307
305
|
]);
|
|
308
306
|
|
|
309
|
-
const withGenericAssets:
|
|
307
|
+
const withGenericAssets: ConfigPlugin = (expoConfig, rawProps) =>
|
|
310
308
|
Expo.withDangerousMod(expoConfig, [
|
|
311
309
|
expoConfig.platforms?.includes("ios") ? "ios" : "android",
|
|
312
310
|
async (config) => {
|
|
@@ -322,11 +320,11 @@ const withGenericAssets: Expo.ConfigPlugin<RawProps> = (expoConfig, rawProps) =>
|
|
|
322
320
|
]);
|
|
323
321
|
|
|
324
322
|
export const withBootSplash = Expo.createRunOncePlugin<
|
|
325
|
-
(Partial<
|
|
323
|
+
(Partial<BootSplashPluginConfig> & { logo: string }) | undefined
|
|
326
324
|
>((expoConfig, baseProps) => {
|
|
327
325
|
const { platforms = [], sdkVersion = "0.1.0" } = expoConfig;
|
|
328
326
|
|
|
329
|
-
|
|
327
|
+
setLoggerMode({ type: "plugin" });
|
|
330
328
|
|
|
331
329
|
if (semver.lt(sdkVersion, "54.0.0")) {
|
|
332
330
|
log.error("Requires Expo 54.0.0 (or higher)");
|
|
@@ -338,7 +336,7 @@ export const withBootSplash = Expo.createRunOncePlugin<
|
|
|
338
336
|
process.exit(1);
|
|
339
337
|
}
|
|
340
338
|
|
|
341
|
-
const rawProps:
|
|
339
|
+
const rawProps: BootSplashPluginConfig = {
|
|
342
340
|
assetsOutput: "assets/bootsplash",
|
|
343
341
|
background: "#fff",
|
|
344
342
|
brandWidth: 80,
|
|
@@ -346,10 +344,7 @@ export const withBootSplash = Expo.createRunOncePlugin<
|
|
|
346
344
|
...baseProps,
|
|
347
345
|
};
|
|
348
346
|
|
|
349
|
-
const plugins:
|
|
350
|
-
withoutExpoSplashScreen,
|
|
351
|
-
withGenericAssets,
|
|
352
|
-
];
|
|
347
|
+
const plugins: ConfigPlugin[] = [withoutExpoSplashScreen, withGenericAssets];
|
|
353
348
|
|
|
354
349
|
if (platforms.includes("android")) {
|
|
355
350
|
plugins.push(
|
|
@@ -380,3 +375,7 @@ export const withBootSplash = Expo.createRunOncePlugin<
|
|
|
380
375
|
plugins.map((plugin) => [plugin, rawProps]),
|
|
381
376
|
);
|
|
382
377
|
}, PACKAGE_NAME);
|
|
378
|
+
|
|
379
|
+
export default (
|
|
380
|
+
config: BootSplashPluginConfig,
|
|
381
|
+
): [typeof PACKAGE_NAME, BootSplashPluginConfig] => [PACKAGE_NAME, config];
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
import * as Expo from "@expo/config-plugins";
|
|
2
|
+
import ExpoPlist from "@expo/plist";
|
|
3
|
+
import glob from "fast-glob";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import { HTMLElement, parse as parseHtml } from "node-html-parser";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import pc from "picocolors";
|
|
8
|
+
import { dedent } from "ts-dedent";
|
|
9
|
+
import formatXml from "xml-formatter";
|
|
10
|
+
import {
|
|
11
|
+
hfs,
|
|
12
|
+
log,
|
|
13
|
+
readXmlLike,
|
|
14
|
+
requireAddon,
|
|
15
|
+
setLoggerMode,
|
|
16
|
+
transformProps,
|
|
17
|
+
writeAndroidAssets,
|
|
18
|
+
writeGenericAssets,
|
|
19
|
+
writeIOSAssets,
|
|
20
|
+
writeWebAssets,
|
|
21
|
+
writeXmlLike,
|
|
22
|
+
} from "./utils";
|
|
23
|
+
|
|
24
|
+
const cwd = process.env.INIT_CWD ?? process.env.PWD ?? process.cwd();
|
|
25
|
+
setLoggerMode({ type: "cli", cwd });
|
|
26
|
+
|
|
27
|
+
const projectRoot = (() => {
|
|
28
|
+
let directory = path.resolve(cwd);
|
|
29
|
+
|
|
30
|
+
const { root } = path.parse(directory);
|
|
31
|
+
const ends = new Set([root, path.resolve(directory, root)]);
|
|
32
|
+
|
|
33
|
+
while (directory) {
|
|
34
|
+
const pkgPath = path.join(directory, "package.json");
|
|
35
|
+
const stats = fs.statSync(pkgPath, { throwIfNoEntry: false });
|
|
36
|
+
|
|
37
|
+
if (stats != null && stats.isFile()) {
|
|
38
|
+
return path.dirname(pkgPath);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (ends.has(directory)) {
|
|
42
|
+
break;
|
|
43
|
+
} else {
|
|
44
|
+
directory = path.dirname(directory);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
})();
|
|
48
|
+
|
|
49
|
+
if (!projectRoot) {
|
|
50
|
+
log.error("We couldn't find a package.json in your project.");
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const getAndroidOutputPath = ({ flavor }: { flavor: string }) => {
|
|
55
|
+
const sourceDir = path.join(projectRoot, "android");
|
|
56
|
+
|
|
57
|
+
if (!fs.existsSync(sourceDir)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const appDir = path.join(sourceDir, "app");
|
|
62
|
+
|
|
63
|
+
const androidOutputPath = path.resolve(
|
|
64
|
+
sourceDir,
|
|
65
|
+
fs.existsSync(appDir) ? "app" : "",
|
|
66
|
+
"src",
|
|
67
|
+
flavor,
|
|
68
|
+
"res",
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (hfs.exists(androidOutputPath)) {
|
|
72
|
+
return androidOutputPath;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
log.warn(
|
|
76
|
+
`No ${path.relative(
|
|
77
|
+
cwd,
|
|
78
|
+
androidOutputPath,
|
|
79
|
+
)} directory found. Skipping Android assets generation…`,
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const getIOSOutputPath = () => {
|
|
84
|
+
const podfile = glob
|
|
85
|
+
.sync("**/Podfile", {
|
|
86
|
+
cwd: projectRoot.replace(/^([a-zA-Z]+:|\.\/)/, ""),
|
|
87
|
+
deep: 10,
|
|
88
|
+
ignore: ["**/@(Pods|node_modules|Carthage|vendor|android)/**"],
|
|
89
|
+
})
|
|
90
|
+
.find((project) => {
|
|
91
|
+
return path.dirname(project) === "ios";
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
if (!podfile) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const sourceDir = path.dirname(path.join(projectRoot, podfile));
|
|
99
|
+
|
|
100
|
+
const xcodeProjectName = fs
|
|
101
|
+
.readdirSync(sourceDir)
|
|
102
|
+
.sort()
|
|
103
|
+
.reverse()
|
|
104
|
+
.find((fileName) => {
|
|
105
|
+
const ext = path.extname(fileName);
|
|
106
|
+
return ext === ".xcodeproj" || ext === ".xcworkspace";
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (xcodeProjectName == null) {
|
|
110
|
+
log.warn("No Xcode project found. Skipping iOS assets generation…");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const iosOutputPath = path
|
|
115
|
+
.resolve(sourceDir, xcodeProjectName)
|
|
116
|
+
.replace(/\.(xcodeproj|xcworkspace)$/, "");
|
|
117
|
+
|
|
118
|
+
if (hfs.exists(iosOutputPath)) {
|
|
119
|
+
return iosOutputPath;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
log.warn(
|
|
123
|
+
`No ${path.relative(
|
|
124
|
+
cwd,
|
|
125
|
+
iosOutputPath,
|
|
126
|
+
)} directory found. Skipping iOS assets generation…`,
|
|
127
|
+
);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const getHtmlTemplatePath = ({ html }: { html: string }) => {
|
|
131
|
+
const htmlTemplatePath = path.resolve(cwd, html);
|
|
132
|
+
|
|
133
|
+
if (hfs.exists(htmlTemplatePath)) {
|
|
134
|
+
return htmlTemplatePath;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
log.warn(
|
|
138
|
+
`No ${path.relative(
|
|
139
|
+
cwd,
|
|
140
|
+
htmlTemplatePath,
|
|
141
|
+
)} found. Skipping HTML + CSS generation…`,
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const getInfoPlistPath = ({
|
|
146
|
+
iosOutputPath,
|
|
147
|
+
plist,
|
|
148
|
+
}: {
|
|
149
|
+
iosOutputPath: string;
|
|
150
|
+
plist: string | undefined;
|
|
151
|
+
}) => {
|
|
152
|
+
if (plist != null) {
|
|
153
|
+
const infoPlistPath = path.resolve(cwd, plist);
|
|
154
|
+
|
|
155
|
+
if (!hfs.exists(infoPlistPath)) {
|
|
156
|
+
return log.warn(`No ${path.relative(cwd, infoPlistPath)} found`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return infoPlistPath;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return path.resolve(iosOutputPath, "Info.plist");
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export const generate = async ({
|
|
166
|
+
platforms,
|
|
167
|
+
html,
|
|
168
|
+
flavor,
|
|
169
|
+
plist,
|
|
170
|
+
...rawProps
|
|
171
|
+
}: {
|
|
172
|
+
platforms: Array<"android" | "ios" | "web">;
|
|
173
|
+
html: string;
|
|
174
|
+
flavor: string;
|
|
175
|
+
plist?: string;
|
|
176
|
+
|
|
177
|
+
logo: string;
|
|
178
|
+
background: string;
|
|
179
|
+
logoWidth: number;
|
|
180
|
+
assetsOutput: string;
|
|
181
|
+
licenseKey?: string;
|
|
182
|
+
brand?: string;
|
|
183
|
+
brandWidth: number;
|
|
184
|
+
darkBackground?: string;
|
|
185
|
+
darkLogo?: string;
|
|
186
|
+
darkBrand?: string;
|
|
187
|
+
}) => {
|
|
188
|
+
const props = await transformProps(cwd, rawProps);
|
|
189
|
+
const addon = requireAddon(props);
|
|
190
|
+
|
|
191
|
+
const { background, brand } = props;
|
|
192
|
+
|
|
193
|
+
const androidOutputPath = platforms.includes("android")
|
|
194
|
+
? getAndroidOutputPath({ flavor })
|
|
195
|
+
: undefined;
|
|
196
|
+
|
|
197
|
+
const iosOutputPath = platforms.includes("ios")
|
|
198
|
+
? getIOSOutputPath()
|
|
199
|
+
: undefined;
|
|
200
|
+
|
|
201
|
+
const htmlTemplatePath = platforms.includes("web")
|
|
202
|
+
? getHtmlTemplatePath({ html })
|
|
203
|
+
: undefined;
|
|
204
|
+
|
|
205
|
+
if (androidOutputPath != null) {
|
|
206
|
+
await writeAndroidAssets({ androidOutputPath, props });
|
|
207
|
+
|
|
208
|
+
const manifestXmlPath = path.resolve(
|
|
209
|
+
androidOutputPath,
|
|
210
|
+
"..",
|
|
211
|
+
"AndroidManifest.xml",
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
if (hfs.exists(manifestXmlPath)) {
|
|
215
|
+
const manifestXml = readXmlLike(manifestXmlPath);
|
|
216
|
+
const activities = manifestXml.root.querySelectorAll("activity");
|
|
217
|
+
|
|
218
|
+
for (const activity of activities) {
|
|
219
|
+
if (activity.getAttribute("android:name") === ".MainActivity") {
|
|
220
|
+
activity.setAttribute("android:theme", "@style/BootTheme");
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
await writeXmlLike(manifestXmlPath, manifestXml.root.toString(), {
|
|
225
|
+
...manifestXml.formatOptions,
|
|
226
|
+
formatter: "prettier",
|
|
227
|
+
htmlWhitespaceSensitivity: "ignore",
|
|
228
|
+
selfClosingTags: true,
|
|
229
|
+
singleAttributePerLine: true,
|
|
230
|
+
});
|
|
231
|
+
} else {
|
|
232
|
+
log.warn("No AndroidManifest.xml found");
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const valuesPath = path.resolve(androidOutputPath, "values");
|
|
236
|
+
hfs.ensureDir(valuesPath);
|
|
237
|
+
|
|
238
|
+
const colorsXmlPath = path.resolve(valuesPath, "colors.xml");
|
|
239
|
+
const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
|
|
240
|
+
|
|
241
|
+
if (hfs.exists(colorsXmlPath)) {
|
|
242
|
+
const colorsXml = readXmlLike(colorsXmlPath);
|
|
243
|
+
const nextColor = parseHtml(colorsXmlEntry);
|
|
244
|
+
|
|
245
|
+
const prevColor = colorsXml.root.querySelector(
|
|
246
|
+
'color[name="bootsplash_background"]',
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
if (prevColor != null) {
|
|
250
|
+
prevColor.replaceWith(nextColor);
|
|
251
|
+
} else {
|
|
252
|
+
colorsXml.root.querySelector("resources")?.appendChild(nextColor);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
await writeXmlLike(colorsXmlPath, colorsXml.root.toString(), {
|
|
256
|
+
...colorsXml.formatOptions,
|
|
257
|
+
formatter: "xmlFormatter",
|
|
258
|
+
});
|
|
259
|
+
} else {
|
|
260
|
+
await writeXmlLike(
|
|
261
|
+
colorsXmlPath,
|
|
262
|
+
`<resources>${colorsXmlEntry}</resources>`,
|
|
263
|
+
{ formatter: "xmlFormatter" },
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const stylesXmlPath = path.resolve(valuesPath, "styles.xml");
|
|
268
|
+
|
|
269
|
+
if (hfs.exists(stylesXmlPath)) {
|
|
270
|
+
const stylesXml = readXmlLike(stylesXmlPath);
|
|
271
|
+
const prevStyle = stylesXml.root.querySelector('style[name="BootTheme"]');
|
|
272
|
+
const parent = prevStyle?.getAttribute("parent") ?? "Theme.BootSplash";
|
|
273
|
+
|
|
274
|
+
const extraItems = parseHtml(
|
|
275
|
+
prevStyle?.text
|
|
276
|
+
.split("\n")
|
|
277
|
+
.map((line) => line.trim())
|
|
278
|
+
.join("") ?? "",
|
|
279
|
+
)
|
|
280
|
+
.childNodes.filter((node) => {
|
|
281
|
+
if (!(node instanceof HTMLElement)) {
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const name = node.getAttribute("name");
|
|
286
|
+
|
|
287
|
+
return (
|
|
288
|
+
name !== "bootSplashBackground" &&
|
|
289
|
+
name !== "bootSplashLogo" &&
|
|
290
|
+
name !== "bootSplashBrand" &&
|
|
291
|
+
name !== "postBootSplashTheme"
|
|
292
|
+
);
|
|
293
|
+
})
|
|
294
|
+
.map((node) => node.toString());
|
|
295
|
+
|
|
296
|
+
const styleItems: string[] = [
|
|
297
|
+
...(extraItems.length > 0 ? [...extraItems, ""] : []),
|
|
298
|
+
|
|
299
|
+
'<item name="bootSplashBackground">@color/bootsplash_background</item>',
|
|
300
|
+
'<item name="bootSplashLogo">@drawable/bootsplash_logo</item>',
|
|
301
|
+
|
|
302
|
+
...(brand != null
|
|
303
|
+
? ['<item name="bootSplashBrand">@drawable/bootsplash_brand</item>']
|
|
304
|
+
: []),
|
|
305
|
+
|
|
306
|
+
'<item name="postBootSplashTheme">@style/AppTheme</item>',
|
|
307
|
+
];
|
|
308
|
+
|
|
309
|
+
const nextStyle = parseHtml(dedent`
|
|
310
|
+
<style name="BootTheme" parent="${parent}">
|
|
311
|
+
${styleItems.join("\n")}
|
|
312
|
+
</style>
|
|
313
|
+
`);
|
|
314
|
+
|
|
315
|
+
prevStyle?.remove(); // remove the existing style
|
|
316
|
+
stylesXml.root.querySelector("resources")?.appendChild(nextStyle);
|
|
317
|
+
|
|
318
|
+
await writeXmlLike(stylesXmlPath, stylesXml.root.toString(), {
|
|
319
|
+
...stylesXml.formatOptions,
|
|
320
|
+
formatter: "prettier",
|
|
321
|
+
htmlWhitespaceSensitivity: "ignore",
|
|
322
|
+
});
|
|
323
|
+
} else {
|
|
324
|
+
log.warn("No styles.xml found");
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (iosOutputPath != null) {
|
|
329
|
+
await writeIOSAssets({ iosOutputPath, props });
|
|
330
|
+
|
|
331
|
+
const pbxprojectPath = Expo.IOSConfig.Paths.getPBXProjectPath(projectRoot);
|
|
332
|
+
|
|
333
|
+
const xcodeProjectPath =
|
|
334
|
+
Expo.IOSConfig.Paths.getXcodeProjectPath(projectRoot);
|
|
335
|
+
|
|
336
|
+
const project = Expo.IOSConfig.XcodeUtils.getPbxproj(projectRoot);
|
|
337
|
+
const projectName = path.basename(iosOutputPath);
|
|
338
|
+
const groupName = path.parse(xcodeProjectPath).name;
|
|
339
|
+
|
|
340
|
+
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
341
|
+
project,
|
|
342
|
+
filepath: path.join(projectName, "BootSplash.storyboard"),
|
|
343
|
+
groupName,
|
|
344
|
+
isBuildFile: true,
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
348
|
+
project,
|
|
349
|
+
filepath: path.join(projectName, "Colors.xcassets"),
|
|
350
|
+
groupName,
|
|
351
|
+
isBuildFile: true,
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
hfs.write(pbxprojectPath, project.writeSync());
|
|
355
|
+
log.write(pbxprojectPath);
|
|
356
|
+
|
|
357
|
+
const infoPlistPath = getInfoPlistPath({ iosOutputPath, plist });
|
|
358
|
+
|
|
359
|
+
if (infoPlistPath != null) {
|
|
360
|
+
const infoPlist = ExpoPlist.parse(hfs.text(infoPlistPath)) as Record<
|
|
361
|
+
string,
|
|
362
|
+
unknown
|
|
363
|
+
>;
|
|
364
|
+
|
|
365
|
+
infoPlist["UILaunchStoryboardName"] = "BootSplash";
|
|
366
|
+
|
|
367
|
+
const formatted = formatXml(ExpoPlist.build(infoPlist), {
|
|
368
|
+
collapseContent: true,
|
|
369
|
+
forceSelfClosingEmptyTag: false,
|
|
370
|
+
indentation: "\t",
|
|
371
|
+
lineSeparator: "\n",
|
|
372
|
+
whiteSpaceAtEndOfSelfclosingTag: false,
|
|
373
|
+
})
|
|
374
|
+
.replace(/<string\/>/gm, "<string></string>")
|
|
375
|
+
.replace(/^\t/gm, "");
|
|
376
|
+
|
|
377
|
+
hfs.write(infoPlistPath, formatted);
|
|
378
|
+
log.write(infoPlistPath);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (htmlTemplatePath != null) {
|
|
383
|
+
await writeWebAssets({ htmlTemplatePath, props });
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
await writeGenericAssets({ props });
|
|
387
|
+
|
|
388
|
+
if (addon != null) {
|
|
389
|
+
await addon.execute({
|
|
390
|
+
props,
|
|
391
|
+
androidOutputPath,
|
|
392
|
+
iosOutputPath,
|
|
393
|
+
htmlTemplatePath,
|
|
394
|
+
});
|
|
395
|
+
} else {
|
|
396
|
+
console.log(`
|
|
397
|
+
${pc.blue("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓")}
|
|
398
|
+
${pc.blue("┃")} 🔑 ${pc.bold(
|
|
399
|
+
"Get a license key for brand image / dark mode support",
|
|
400
|
+
)} ${pc.blue("┃")}
|
|
401
|
+
${pc.blue("┃")} ${pc.underline(
|
|
402
|
+
"https://zoontek.gumroad.com/l/bootsplash-generator",
|
|
403
|
+
)} ${pc.blue("┃")}
|
|
404
|
+
${pc.blue("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛")}`);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
console.log(
|
|
408
|
+
`\n💖 Thanks for using ${pc.underline("react-native-bootsplash")}`,
|
|
409
|
+
);
|
|
410
|
+
};
|