react-native-custom-splash 2.2.0 → 3.0.1
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/package.json +2 -2
- package/plugin/src/index.js +2 -2
- package/plugin/src/withCustomSplash.js +164 -109
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-custom-splash",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "A custom splash screen module for React Native with native iOS and Android support, fully compatible with Expo",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"android",
|
|
18
18
|
"native-module"
|
|
19
19
|
],
|
|
20
|
-
"author": "
|
|
20
|
+
"author": "Vijay Kishan",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"repository": {
|
|
23
23
|
"type": "git",
|
package/plugin/src/index.js
CHANGED
|
@@ -8,7 +8,7 @@ const {
|
|
|
8
8
|
} = require('@expo/config-plugins');
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const fs = require('fs');
|
|
11
|
-
const
|
|
11
|
+
const withForcediOSSplash = require('./withCustomSplash');
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Validate and normalize plugin configuration
|
|
@@ -531,6 +531,6 @@ module.exports = (config, props = {}) => {
|
|
|
531
531
|
|
|
532
532
|
return withPlugins(config, [
|
|
533
533
|
[withSplashScreenAndroid, pluginConfig],
|
|
534
|
-
[
|
|
534
|
+
[withForcediOSSplash, pluginConfig],
|
|
535
535
|
]);
|
|
536
536
|
};
|
|
@@ -3,10 +3,19 @@ const path = require('path');
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
* This runs AFTER Expo's default splash and overwrites everything
|
|
6
|
+
* FINAL WORKING iOS Splash - Xcode Compatible
|
|
8
7
|
*/
|
|
9
|
-
function
|
|
8
|
+
function withForcediOSSplash(config, pluginConfig) {
|
|
9
|
+
// Disable Expo's splash
|
|
10
|
+
config = {
|
|
11
|
+
...config,
|
|
12
|
+
splash: undefined,
|
|
13
|
+
ios: {
|
|
14
|
+
...config.ios,
|
|
15
|
+
splash: undefined
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
10
19
|
return withDangerousMod(config, [
|
|
11
20
|
'ios',
|
|
12
21
|
async (config) => {
|
|
@@ -14,129 +23,164 @@ function withCustomiOSSplash(config, pluginConfig) {
|
|
|
14
23
|
const iosPath = config.modRequest.platformProjectRoot;
|
|
15
24
|
const projectName = config.modRequest.projectName;
|
|
16
25
|
|
|
17
|
-
console.log('\n
|
|
26
|
+
console.log('\n🔥 SETTING UP CUSTOM SPLASH...\n');
|
|
27
|
+
|
|
28
|
+
// Delete ALL old splash files
|
|
29
|
+
const filesToDelete = [
|
|
30
|
+
path.join(iosPath, projectName, 'SplashScreen.storyboard'),
|
|
31
|
+
path.join(iosPath, projectName, 'LaunchScreen.storyboard'),
|
|
32
|
+
path.join(iosPath, projectName, 'Images.xcassets', 'SplashScreenLegacy.imageset'),
|
|
33
|
+
path.join(iosPath, projectName, 'Images.xcassets', 'SplashScreen.imageset'),
|
|
34
|
+
path.join(iosPath, projectName, 'Images.xcassets', 'SplashScreenBackground.imageset'),
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
filesToDelete.forEach(filePath => {
|
|
38
|
+
try {
|
|
39
|
+
if (fs.existsSync(filePath)) {
|
|
40
|
+
if (fs.lstatSync(filePath).isDirectory()) {
|
|
41
|
+
fs.rmSync(filePath, { recursive: true, force: true });
|
|
42
|
+
} else {
|
|
43
|
+
fs.unlinkSync(filePath);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
} catch (e) {
|
|
47
|
+
// Ignore
|
|
48
|
+
}
|
|
49
|
+
});
|
|
18
50
|
|
|
19
|
-
//
|
|
51
|
+
// Update Info.plist
|
|
20
52
|
const plistPath = path.join(iosPath, projectName, 'Info.plist');
|
|
21
53
|
if (fs.existsSync(plistPath)) {
|
|
22
54
|
let plist = fs.readFileSync(plistPath, 'utf8');
|
|
55
|
+
plist = plist.replace(/<key>UILaunchStoryboardName<\/key>\s*<string>.*?<\/string>/g, '');
|
|
56
|
+
plist = plist.replace(/<key>UILaunchScreen<\/key>[\s\S]*?<\/dict>/g, '');
|
|
23
57
|
|
|
24
|
-
|
|
25
|
-
if (!plist.includes('<key>UILaunchStoryboardName</key>')) {
|
|
58
|
+
if (!plist.includes('UILaunchStoryboardName')) {
|
|
26
59
|
plist = plist.replace(
|
|
27
60
|
'</dict>\n</plist>',
|
|
28
61
|
'\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n</dict>\n</plist>'
|
|
29
62
|
);
|
|
30
|
-
} else {
|
|
31
|
-
plist = plist.replace(
|
|
32
|
-
/<key>UILaunchStoryboardName<\/key>\s*<string>.*?<\/string>/,
|
|
33
|
-
'<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>'
|
|
34
|
-
);
|
|
35
63
|
}
|
|
36
64
|
|
|
37
|
-
// Remove UILaunchScreen dictionary
|
|
38
|
-
plist = plist.replace(/<key>UILaunchScreen<\/key>[\s\S]*?<\/dict>/g, '');
|
|
39
|
-
|
|
40
65
|
fs.writeFileSync(plistPath, plist);
|
|
41
66
|
console.log('✅ Info.plist updated');
|
|
42
67
|
}
|
|
43
68
|
|
|
44
|
-
// 2. Delete ALL old storyboards
|
|
45
|
-
const storyboards = [
|
|
46
|
-
path.join(iosPath, projectName, 'SplashScreen.storyboard'),
|
|
47
|
-
path.join(iosPath, projectName, 'LaunchScreen.storyboard'),
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
storyboards.forEach(sb => {
|
|
51
|
-
if (fs.existsSync(sb)) {
|
|
52
|
-
fs.unlinkSync(sb);
|
|
53
|
-
console.log(`🗑️ Deleted: ${path.basename(sb)}`);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// 3. Delete SplashScreenLegacy
|
|
58
|
-
const legacyPath = path.join(iosPath, projectName, 'Images.xcassets', 'SplashScreenLegacy.imageset');
|
|
59
|
-
if (fs.existsSync(legacyPath)) {
|
|
60
|
-
fs.rmSync(legacyPath, { recursive: true });
|
|
61
|
-
console.log('🗑️ Deleted: SplashScreenLegacy');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// 4. Delete SplashScreen imageset (from Expo)
|
|
65
|
-
const splashImagePath = path.join(iosPath, projectName, 'Images.xcassets', 'SplashScreen.imageset');
|
|
66
|
-
if (fs.existsSync(splashImagePath)) {
|
|
67
|
-
fs.rmSync(splashImagePath, { recursive: true });
|
|
68
|
-
console.log('🗑️ Deleted: SplashScreen');
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// 5. Copy user images
|
|
72
69
|
const assetsPath = path.join(iosPath, projectName, 'Images.xcassets');
|
|
73
70
|
let hasImage = false;
|
|
74
71
|
let hasLogo = false;
|
|
75
72
|
|
|
73
|
+
// Copy splash_image
|
|
76
74
|
if (pluginConfig.image) {
|
|
77
75
|
const srcImage = path.join(projectRoot, pluginConfig.image);
|
|
78
76
|
if (fs.existsSync(srcImage)) {
|
|
79
|
-
const destDir = path.join(assetsPath, '
|
|
77
|
+
const destDir = path.join(assetsPath, 'SplashImage.imageset');
|
|
78
|
+
|
|
79
|
+
if (fs.existsSync(destDir)) {
|
|
80
|
+
fs.rmSync(destDir, { recursive: true, force: true });
|
|
81
|
+
}
|
|
80
82
|
fs.mkdirSync(destDir, { recursive: true });
|
|
81
83
|
|
|
82
|
-
// Copy
|
|
83
|
-
|
|
84
|
-
const destFile = path.join(destDir, `splash_image${scale}.png`);
|
|
85
|
-
fs.copyFileSync(srcImage, destFile);
|
|
86
|
-
});
|
|
84
|
+
// Copy image
|
|
85
|
+
fs.copyFileSync(srcImage, path.join(destDir, 'splash.png'));
|
|
87
86
|
|
|
88
87
|
// Create Contents.json
|
|
89
88
|
const contents = {
|
|
90
89
|
images: [
|
|
91
|
-
{
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
{
|
|
91
|
+
filename: 'splash.png',
|
|
92
|
+
idiom: 'universal',
|
|
93
|
+
scale: '1x'
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
filename: 'splash.png',
|
|
97
|
+
idiom: 'universal',
|
|
98
|
+
scale: '2x'
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
filename: 'splash.png',
|
|
102
|
+
idiom: 'universal',
|
|
103
|
+
scale: '3x'
|
|
104
|
+
}
|
|
94
105
|
],
|
|
95
|
-
info: {
|
|
106
|
+
info: {
|
|
107
|
+
author: 'xcode',
|
|
108
|
+
version: 1
|
|
109
|
+
}
|
|
96
110
|
};
|
|
97
|
-
|
|
111
|
+
|
|
112
|
+
fs.writeFileSync(
|
|
113
|
+
path.join(destDir, 'Contents.json'),
|
|
114
|
+
JSON.stringify(contents, null, 2)
|
|
115
|
+
);
|
|
98
116
|
|
|
99
117
|
hasImage = true;
|
|
100
|
-
console.log('✅
|
|
118
|
+
console.log('✅ Background image copied: SplashImage');
|
|
101
119
|
}
|
|
102
120
|
}
|
|
103
121
|
|
|
122
|
+
// Copy splash_logo
|
|
104
123
|
if (pluginConfig.logo) {
|
|
105
124
|
const srcLogo = path.join(projectRoot, pluginConfig.logo);
|
|
106
125
|
if (fs.existsSync(srcLogo)) {
|
|
107
|
-
const destDir = path.join(assetsPath, '
|
|
126
|
+
const destDir = path.join(assetsPath, 'SplashLogo.imageset');
|
|
127
|
+
|
|
128
|
+
if (fs.existsSync(destDir)) {
|
|
129
|
+
fs.rmSync(destDir, { recursive: true, force: true });
|
|
130
|
+
}
|
|
108
131
|
fs.mkdirSync(destDir, { recursive: true });
|
|
109
132
|
|
|
110
|
-
// Copy
|
|
111
|
-
|
|
112
|
-
const destFile = path.join(destDir, `splash_logo${scale}.png`);
|
|
113
|
-
fs.copyFileSync(srcLogo, destFile);
|
|
114
|
-
});
|
|
133
|
+
// Copy logo
|
|
134
|
+
fs.copyFileSync(srcLogo, path.join(destDir, 'logo.png'));
|
|
115
135
|
|
|
116
136
|
// Create Contents.json
|
|
117
137
|
const contents = {
|
|
118
138
|
images: [
|
|
119
|
-
{
|
|
120
|
-
|
|
121
|
-
|
|
139
|
+
{
|
|
140
|
+
filename: 'logo.png',
|
|
141
|
+
idiom: 'universal',
|
|
142
|
+
scale: '1x'
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
filename: 'logo.png',
|
|
146
|
+
idiom: 'universal',
|
|
147
|
+
scale: '2x'
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
filename: 'logo.png',
|
|
151
|
+
idiom: 'universal',
|
|
152
|
+
scale: '3x'
|
|
153
|
+
}
|
|
122
154
|
],
|
|
123
|
-
info: {
|
|
155
|
+
info: {
|
|
156
|
+
author: 'xcode',
|
|
157
|
+
version: 1
|
|
158
|
+
}
|
|
124
159
|
};
|
|
125
|
-
|
|
160
|
+
|
|
161
|
+
fs.writeFileSync(
|
|
162
|
+
path.join(destDir, 'Contents.json'),
|
|
163
|
+
JSON.stringify(contents, null, 2)
|
|
164
|
+
);
|
|
126
165
|
|
|
127
166
|
hasLogo = true;
|
|
128
|
-
console.log('✅
|
|
167
|
+
console.log('✅ Logo image copied: SplashLogo');
|
|
129
168
|
}
|
|
130
169
|
}
|
|
131
170
|
|
|
132
|
-
//
|
|
133
|
-
const storyboard =
|
|
171
|
+
// Create LaunchScreen.storyboard
|
|
172
|
+
const storyboard = createXcodeStoryboard(hasImage, hasLogo, pluginConfig.backgroundColor);
|
|
134
173
|
const storyboardPath = path.join(iosPath, projectName, 'LaunchScreen.storyboard');
|
|
174
|
+
|
|
175
|
+
if (fs.existsSync(storyboardPath)) {
|
|
176
|
+
fs.unlinkSync(storyboardPath);
|
|
177
|
+
}
|
|
178
|
+
|
|
135
179
|
fs.writeFileSync(storyboardPath, storyboard);
|
|
136
180
|
|
|
137
|
-
console.log('✅
|
|
138
|
-
console.log(` Background: ${hasImage ? '
|
|
139
|
-
console.log(` Logo: ${hasLogo ? '
|
|
181
|
+
console.log('✅ LaunchScreen.storyboard created!');
|
|
182
|
+
console.log(` Background: ${hasImage ? 'SplashImage ✓' : 'Color only'}`);
|
|
183
|
+
console.log(` Logo: ${hasLogo ? 'SplashLogo ✓' : 'None'}`);
|
|
140
184
|
console.log(` Color: ${pluginConfig.backgroundColor}\n`);
|
|
141
185
|
|
|
142
186
|
return config;
|
|
@@ -144,61 +188,73 @@ function withCustomiOSSplash(config, pluginConfig) {
|
|
|
144
188
|
]);
|
|
145
189
|
}
|
|
146
190
|
|
|
147
|
-
function
|
|
191
|
+
function createXcodeStoryboard(hasImage, hasLogo, bgColor) {
|
|
148
192
|
const color = bgColor.replace('#', '');
|
|
149
193
|
const r = parseInt(color.substr(0, 2), 16) / 255;
|
|
150
194
|
const g = parseInt(color.substr(2, 2), 16) / 255;
|
|
151
195
|
const b = parseInt(color.substr(4, 2), 16) / 255;
|
|
152
196
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
197
|
+
// Build subviews
|
|
198
|
+
let subviews = '';
|
|
199
|
+
let constraints = '';
|
|
200
|
+
let resources = '';
|
|
201
|
+
|
|
202
|
+
if (hasImage) {
|
|
203
|
+
subviews += `
|
|
204
|
+
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SplashImage" translatesAutoresizingMaskIntoConstraints="NO" id="splash-bg">
|
|
205
|
+
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
|
206
|
+
</imageView>`;
|
|
207
|
+
|
|
208
|
+
constraints += `
|
|
209
|
+
<constraint firstItem="splash-bg" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="bg-top"/>
|
|
210
|
+
<constraint firstItem="splash-bg" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="bg-leading"/>
|
|
211
|
+
<constraint firstItem="splash-bg" firstAttribute="trailing" secondItem="Ze5-6b-2t3" secondAttribute="trailing" id="bg-trailing"/>
|
|
212
|
+
<constraint firstItem="splash-bg" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="bg-bottom"/>`;
|
|
213
|
+
|
|
214
|
+
resources += `
|
|
215
|
+
<image name="SplashImage" width="1242" height="2688"/>`;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (hasLogo) {
|
|
219
|
+
subviews += `
|
|
220
|
+
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SplashLogo" translatesAutoresizingMaskIntoConstraints="NO" id="splash-logo">
|
|
221
|
+
<rect key="frame" x="132" y="373" width="150" height="150"/>
|
|
222
|
+
<constraints>
|
|
223
|
+
<constraint firstAttribute="width" constant="150" id="logo-width"/>
|
|
224
|
+
<constraint firstAttribute="height" constant="150" id="logo-height"/>
|
|
225
|
+
</constraints>
|
|
226
|
+
</imageView>`;
|
|
227
|
+
|
|
228
|
+
constraints += `
|
|
229
|
+
<constraint firstItem="splash-logo" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="logo-centerx"/>
|
|
230
|
+
<constraint firstItem="splash-logo" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="logo-centery"/>`;
|
|
231
|
+
|
|
232
|
+
resources += `
|
|
233
|
+
<image name="SplashLogo" width="512" height="512"/>`;
|
|
234
|
+
}
|
|
180
235
|
|
|
181
236
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
182
|
-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="
|
|
237
|
+
<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">
|
|
183
238
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
|
184
239
|
<dependencies>
|
|
185
240
|
<deployment identifier="iOS"/>
|
|
186
|
-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="
|
|
241
|
+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
|
|
187
242
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
|
188
243
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
189
244
|
</dependencies>
|
|
190
245
|
<scenes>
|
|
246
|
+
<!--View Controller-->
|
|
191
247
|
<scene sceneID="EHf-IW-A2E">
|
|
192
248
|
<objects>
|
|
193
249
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
|
194
|
-
<view key="view" contentMode="scaleToFill" id="
|
|
250
|
+
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
|
195
251
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
|
196
252
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
197
|
-
<subviews>${
|
|
253
|
+
<subviews>${subviews}
|
|
198
254
|
</subviews>
|
|
199
|
-
<viewLayoutGuide key="safeArea" id="
|
|
255
|
+
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
|
200
256
|
<color key="backgroundColor" red="${r}" green="${g}" blue="${b}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
201
|
-
<constraints>${
|
|
257
|
+
<constraints>${constraints}
|
|
202
258
|
</constraints>
|
|
203
259
|
</view>
|
|
204
260
|
</viewController>
|
|
@@ -207,10 +263,9 @@ function createStoryboard(hasImage, hasLogo, bgColor) {
|
|
|
207
263
|
<point key="canvasLocation" x="53" y="375"/>
|
|
208
264
|
</scene>
|
|
209
265
|
</scenes>
|
|
210
|
-
<resources
|
|
211
|
-
${resources.join('\n')}
|
|
266
|
+
<resources>${resources}
|
|
212
267
|
</resources>
|
|
213
268
|
</document>`;
|
|
214
269
|
}
|
|
215
270
|
|
|
216
|
-
module.exports =
|
|
271
|
+
module.exports = withForcediOSSplash;
|