react-native-custom-splash 2.2.0 ā 3.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/package.json +2 -2
- package/plugin/src/index.js +2 -2
- package/plugin/src/withCustomSplash.js +127 -101
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-custom-splash",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
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
|
};
|
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-
const { withDangerousMod } = require('@expo/config-plugins');
|
|
1
|
+
const { withDangerousMod, withPlugins } = require('@expo/config-plugins');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
* This
|
|
6
|
+
* ULTIMATE iOS Splash Fix - Forceful & Complete
|
|
7
|
+
* This DISABLES Expo's splash and FORCES user images
|
|
8
8
|
*/
|
|
9
|
-
function
|
|
9
|
+
function withForcediOSSplash(config, pluginConfig) {
|
|
10
|
+
// STEP 1: Disable Expo's default splash completely
|
|
11
|
+
config = {
|
|
12
|
+
...config,
|
|
13
|
+
splash: undefined, // Remove Expo splash config
|
|
14
|
+
ios: {
|
|
15
|
+
...config.ios,
|
|
16
|
+
splash: undefined // Remove iOS splash config
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// STEP 2: Use dangerousMod to forcefully set everything
|
|
10
21
|
return withDangerousMod(config, [
|
|
11
22
|
'ios',
|
|
12
23
|
async (config) => {
|
|
@@ -14,61 +25,57 @@ function withCustomiOSSplash(config, pluginConfig) {
|
|
|
14
25
|
const iosPath = config.modRequest.platformProjectRoot;
|
|
15
26
|
const projectName = config.modRequest.projectName;
|
|
16
27
|
|
|
17
|
-
console.log('\n
|
|
28
|
+
console.log('\nļæ½ FORCING CUSTOM SPLASH SCREEN (FINAL FIX)...\n');
|
|
18
29
|
|
|
19
|
-
//
|
|
30
|
+
// Wait a bit to ensure Expo is done
|
|
31
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
32
|
+
|
|
33
|
+
// NUCLEAR OPTION: Delete EVERYTHING splash-related
|
|
34
|
+
const filesToDelete = [
|
|
35
|
+
path.join(iosPath, projectName, 'SplashScreen.storyboard'),
|
|
36
|
+
path.join(iosPath, projectName, 'LaunchScreen.storyboard'),
|
|
37
|
+
path.join(iosPath, projectName, 'Images.xcassets', 'SplashScreenLegacy.imageset'),
|
|
38
|
+
path.join(iosPath, projectName, 'Images.xcassets', 'SplashScreen.imageset'),
|
|
39
|
+
path.join(iosPath, projectName, 'Images.xcassets', 'SplashScreenBackground.imageset'),
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
filesToDelete.forEach(filePath => {
|
|
43
|
+
try {
|
|
44
|
+
if (fs.existsSync(filePath)) {
|
|
45
|
+
if (fs.lstatSync(filePath).isDirectory()) {
|
|
46
|
+
fs.rmSync(filePath, { recursive: true, force: true });
|
|
47
|
+
} else {
|
|
48
|
+
fs.unlinkSync(filePath);
|
|
49
|
+
}
|
|
50
|
+
console.log('šļø Deleted:', path.basename(filePath));
|
|
51
|
+
}
|
|
52
|
+
} catch (e) {
|
|
53
|
+
// Ignore errors
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Force update Info.plist
|
|
20
58
|
const plistPath = path.join(iosPath, projectName, 'Info.plist');
|
|
21
59
|
if (fs.existsSync(plistPath)) {
|
|
22
60
|
let plist = fs.readFileSync(plistPath, 'utf8');
|
|
23
61
|
|
|
24
|
-
//
|
|
25
|
-
|
|
62
|
+
// Remove ALL launch screen configurations
|
|
63
|
+
plist = plist.replace(/<key>UILaunchStoryboardName<\/key>\s*<string>.*?<\/string>/g, '');
|
|
64
|
+
plist = plist.replace(/<key>UILaunchScreen<\/key>[\s\S]*?<\/dict>/g, '');
|
|
65
|
+
|
|
66
|
+
// Add our LaunchScreen BEFORE closing dict
|
|
67
|
+
if (!plist.includes('UILaunchStoryboardName')) {
|
|
26
68
|
plist = plist.replace(
|
|
27
69
|
'</dict>\n</plist>',
|
|
28
70
|
'\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n</dict>\n</plist>'
|
|
29
71
|
);
|
|
30
|
-
} else {
|
|
31
|
-
plist = plist.replace(
|
|
32
|
-
/<key>UILaunchStoryboardName<\/key>\s*<string>.*?<\/string>/,
|
|
33
|
-
'<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>'
|
|
34
|
-
);
|
|
35
72
|
}
|
|
36
73
|
|
|
37
|
-
// Remove UILaunchScreen dictionary
|
|
38
|
-
plist = plist.replace(/<key>UILaunchScreen<\/key>[\s\S]*?<\/dict>/g, '');
|
|
39
|
-
|
|
40
74
|
fs.writeFileSync(plistPath, plist);
|
|
41
|
-
console.log('ā
Info.plist
|
|
42
|
-
}
|
|
43
|
-
|
|
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');
|
|
75
|
+
console.log('ā
Info.plist FORCED');
|
|
69
76
|
}
|
|
70
77
|
|
|
71
|
-
//
|
|
78
|
+
// Copy user images with FORCE
|
|
72
79
|
const assetsPath = path.join(iosPath, projectName, 'Images.xcassets');
|
|
73
80
|
let hasImage = false;
|
|
74
81
|
let hasLogo = false;
|
|
@@ -77,27 +84,33 @@ function withCustomiOSSplash(config, pluginConfig) {
|
|
|
77
84
|
const srcImage = path.join(projectRoot, pluginConfig.image);
|
|
78
85
|
if (fs.existsSync(srcImage)) {
|
|
79
86
|
const destDir = path.join(assetsPath, 'splash_image.imageset');
|
|
87
|
+
|
|
88
|
+
// Force delete and recreate
|
|
89
|
+
if (fs.existsSync(destDir)) {
|
|
90
|
+
fs.rmSync(destDir, { recursive: true, force: true });
|
|
91
|
+
}
|
|
80
92
|
fs.mkdirSync(destDir, { recursive: true });
|
|
81
93
|
|
|
82
94
|
// Copy for all scales
|
|
83
95
|
['', '@2x', '@3x'].forEach(scale => {
|
|
84
|
-
|
|
85
|
-
fs.copyFileSync(srcImage, destFile);
|
|
96
|
+
fs.copyFileSync(srcImage, path.join(destDir, `splash_image${scale}.png`));
|
|
86
97
|
});
|
|
87
98
|
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
// Force Contents.json
|
|
100
|
+
fs.writeFileSync(
|
|
101
|
+
path.join(destDir, 'Contents.json'),
|
|
102
|
+
JSON.stringify({
|
|
103
|
+
images: [
|
|
104
|
+
{ idiom: 'universal', filename: 'splash_image.png', scale: '1x' },
|
|
105
|
+
{ idiom: 'universal', filename: 'splash_image@2x.png', scale: '2x' },
|
|
106
|
+
{ idiom: 'universal', filename: 'splash_image@3x.png', scale: '3x' }
|
|
107
|
+
],
|
|
108
|
+
info: { author: 'xcode', version: 1 }
|
|
109
|
+
}, null, 2)
|
|
110
|
+
);
|
|
98
111
|
|
|
99
112
|
hasImage = true;
|
|
100
|
-
console.log('ā
|
|
113
|
+
console.log('ā
FORCED: splash_image');
|
|
101
114
|
}
|
|
102
115
|
}
|
|
103
116
|
|
|
@@ -105,81 +118,95 @@ function withCustomiOSSplash(config, pluginConfig) {
|
|
|
105
118
|
const srcLogo = path.join(projectRoot, pluginConfig.logo);
|
|
106
119
|
if (fs.existsSync(srcLogo)) {
|
|
107
120
|
const destDir = path.join(assetsPath, 'splash_logo.imageset');
|
|
121
|
+
|
|
122
|
+
// Force delete and recreate
|
|
123
|
+
if (fs.existsSync(destDir)) {
|
|
124
|
+
fs.rmSync(destDir, { recursive: true, force: true });
|
|
125
|
+
}
|
|
108
126
|
fs.mkdirSync(destDir, { recursive: true });
|
|
109
127
|
|
|
110
128
|
// Copy for all scales
|
|
111
129
|
['', '@2x', '@3x'].forEach(scale => {
|
|
112
|
-
|
|
113
|
-
fs.copyFileSync(srcLogo, destFile);
|
|
130
|
+
fs.copyFileSync(srcLogo, path.join(destDir, `splash_logo${scale}.png`));
|
|
114
131
|
});
|
|
115
132
|
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
133
|
+
// Force Contents.json
|
|
134
|
+
fs.writeFileSync(
|
|
135
|
+
path.join(destDir, 'Contents.json'),
|
|
136
|
+
JSON.stringify({
|
|
137
|
+
images: [
|
|
138
|
+
{ idiom: 'universal', filename: 'splash_logo.png', scale: '1x' },
|
|
139
|
+
{ idiom: 'universal', filename: 'splash_logo@2x.png', scale: '2x' },
|
|
140
|
+
{ idiom: 'universal', filename: 'splash_logo@3x.png', scale: '3x' }
|
|
141
|
+
],
|
|
142
|
+
info: { author: 'xcode', version: 1 }
|
|
143
|
+
}, null, 2)
|
|
144
|
+
);
|
|
126
145
|
|
|
127
146
|
hasLogo = true;
|
|
128
|
-
console.log('ā
|
|
147
|
+
console.log('ā
FORCED: splash_logo');
|
|
129
148
|
}
|
|
130
149
|
}
|
|
131
150
|
|
|
132
|
-
//
|
|
133
|
-
const storyboard =
|
|
151
|
+
// FORCE create LaunchScreen.storyboard
|
|
152
|
+
const storyboard = createForcedStoryboard(hasImage, hasLogo, pluginConfig.backgroundColor);
|
|
134
153
|
const storyboardPath = path.join(iosPath, projectName, 'LaunchScreen.storyboard');
|
|
135
|
-
fs.writeFileSync(storyboardPath, storyboard);
|
|
136
154
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
155
|
+
// Delete if exists
|
|
156
|
+
if (fs.existsSync(storyboardPath)) {
|
|
157
|
+
fs.unlinkSync(storyboardPath);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Write with force
|
|
161
|
+
fs.writeFileSync(storyboardPath, storyboard, { flag: 'w' });
|
|
162
|
+
|
|
163
|
+
console.log('ā
FORCED: LaunchScreen.storyboard');
|
|
164
|
+
console.log(` š¼ļø Background: ${hasImage ? 'splash_image' : 'color'}`);
|
|
165
|
+
console.log(` šØ Logo: ${hasLogo ? 'splash_logo' : 'none'}`);
|
|
166
|
+
console.log(` š Color: ${pluginConfig.backgroundColor}`);
|
|
167
|
+
console.log('\nā
CUSTOM SPLASH FORCED SUCCESSFULLY!\n');
|
|
141
168
|
|
|
142
169
|
return config;
|
|
143
170
|
},
|
|
144
171
|
]);
|
|
145
172
|
}
|
|
146
173
|
|
|
147
|
-
function
|
|
174
|
+
function createForcedStoryboard(hasImage, hasLogo, bgColor) {
|
|
148
175
|
const color = bgColor.replace('#', '');
|
|
149
176
|
const r = parseInt(color.substr(0, 2), 16) / 255;
|
|
150
177
|
const g = parseInt(color.substr(2, 2), 16) / 255;
|
|
151
178
|
const b = parseInt(color.substr(4, 2), 16) / 255;
|
|
152
179
|
|
|
153
|
-
const
|
|
154
|
-
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="splash_image" translatesAutoresizingMaskIntoConstraints="NO" id="
|
|
180
|
+
const bgImage = hasImage ? `
|
|
181
|
+
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="splash_image" translatesAutoresizingMaskIntoConstraints="NO" id="BG">
|
|
155
182
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
|
156
183
|
</imageView>` : '';
|
|
157
184
|
|
|
158
|
-
const
|
|
159
|
-
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="splash_logo" translatesAutoresizingMaskIntoConstraints="NO" id="
|
|
185
|
+
const logoImage = hasLogo ? `
|
|
186
|
+
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="splash_logo" translatesAutoresizingMaskIntoConstraints="NO" id="LOGO">
|
|
160
187
|
<rect key="frame" x="132" y="348" width="150" height="150"/>
|
|
161
188
|
<constraints>
|
|
162
|
-
<constraint firstAttribute="width" constant="150" id="
|
|
163
|
-
<constraint firstAttribute="height" constant="150" id="
|
|
189
|
+
<constraint firstAttribute="width" constant="150" id="LW"/>
|
|
190
|
+
<constraint firstAttribute="height" constant="150" id="LH"/>
|
|
164
191
|
</constraints>
|
|
165
192
|
</imageView>` : '';
|
|
166
193
|
|
|
167
194
|
const bgConstraints = hasImage ? `
|
|
168
|
-
<constraint firstItem="
|
|
169
|
-
<constraint firstItem="
|
|
170
|
-
<constraint firstItem="
|
|
171
|
-
<constraint firstItem="
|
|
195
|
+
<constraint firstItem="BG" firstAttribute="top" secondItem="V" secondAttribute="top" id="BT"/>
|
|
196
|
+
<constraint firstItem="BG" firstAttribute="leading" secondItem="V" secondAttribute="leading" id="BL"/>
|
|
197
|
+
<constraint firstItem="BG" firstAttribute="trailing" secondItem="V" secondAttribute="trailing" id="BR"/>
|
|
198
|
+
<constraint firstItem="BG" firstAttribute="bottom" secondItem="V" secondAttribute="bottom" id="BB"/>` : '';
|
|
172
199
|
|
|
173
200
|
const logoConstraints = hasLogo ? `
|
|
174
|
-
<constraint firstItem="
|
|
175
|
-
<constraint firstItem="
|
|
201
|
+
<constraint firstItem="LOGO" firstAttribute="centerX" secondItem="V" secondAttribute="centerX" id="LX"/>
|
|
202
|
+
<constraint firstItem="LOGO" firstAttribute="centerY" secondItem="V" secondAttribute="centerY" id="LY"/>` : '';
|
|
176
203
|
|
|
177
204
|
const resources = [];
|
|
178
205
|
if (hasImage) resources.push(' <image name="splash_image" width="1242" height="2688"/>');
|
|
179
206
|
if (hasLogo) resources.push(' <image name="splash_logo" width="512" height="512"/>');
|
|
180
207
|
|
|
181
208
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
182
|
-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="
|
|
209
|
+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="VC">
|
|
183
210
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
|
184
211
|
<dependencies>
|
|
185
212
|
<deployment identifier="iOS"/>
|
|
@@ -188,29 +215,28 @@ function createStoryboard(hasImage, hasLogo, bgColor) {
|
|
|
188
215
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
189
216
|
</dependencies>
|
|
190
217
|
<scenes>
|
|
191
|
-
<scene sceneID="
|
|
218
|
+
<scene sceneID="SC">
|
|
192
219
|
<objects>
|
|
193
|
-
<viewController id="
|
|
194
|
-
<view key="view" contentMode="scaleToFill" id="
|
|
220
|
+
<viewController id="VC" sceneMemberID="viewController">
|
|
221
|
+
<view key="view" contentMode="scaleToFill" id="V">
|
|
195
222
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
|
196
223
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
197
|
-
<subviews>${
|
|
224
|
+
<subviews>${bgImage}${logoImage}
|
|
198
225
|
</subviews>
|
|
199
|
-
<viewLayoutGuide key="safeArea" id="
|
|
226
|
+
<viewLayoutGuide key="safeArea" id="SA"/>
|
|
200
227
|
<color key="backgroundColor" red="${r}" green="${g}" blue="${b}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
201
228
|
<constraints>${bgConstraints}${logoConstraints}
|
|
202
229
|
</constraints>
|
|
203
230
|
</view>
|
|
204
231
|
</viewController>
|
|
205
|
-
<placeholder placeholderIdentifier="IBFirstResponder" id="
|
|
232
|
+
<placeholder placeholderIdentifier="IBFirstResponder" id="FR" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
|
206
233
|
</objects>
|
|
207
234
|
<point key="canvasLocation" x="53" y="375"/>
|
|
208
235
|
</scene>
|
|
209
236
|
</scenes>
|
|
210
|
-
<resources
|
|
211
|
-
${resources.join('\n')}
|
|
237
|
+
<resources>${resources.join('\n')}
|
|
212
238
|
</resources>
|
|
213
239
|
</document>`;
|
|
214
240
|
}
|
|
215
241
|
|
|
216
|
-
module.exports =
|
|
242
|
+
module.exports = withForcediOSSplash;
|