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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-custom-splash",
3
- "version": "2.2.0",
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": "Your Name",
20
+ "author": "Vijay Kishan",
21
21
  "license": "MIT",
22
22
  "repository": {
23
23
  "type": "git",
@@ -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 withCustomiOSSplash = require('./withCustomSplash');
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
- [withCustomiOSSplash, pluginConfig],
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
- * COMPLETE iOS Splash Screen Setup
7
- * This runs AFTER Expo's default splash and overwrites everything
6
+ * ULTIMATE iOS Splash Fix - Forceful & Complete
7
+ * This DISABLES Expo's splash and FORCES user images
8
8
  */
9
- function withCustomiOSSplash(config, pluginConfig) {
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šŸš€ Setting up custom iOS splash screen...\n');
28
+ console.log('\nļæ½ FORCING CUSTOM SPLASH SCREEN (FINAL FIX)...\n');
18
29
 
19
- // 1. Update Info.plist
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
- // Force LaunchScreen
25
- if (!plist.includes('<key>UILaunchStoryboardName</key>')) {
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 updated');
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
- // 5. Copy user images
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
- const destFile = path.join(destDir, `splash_image${scale}.png`);
85
- fs.copyFileSync(srcImage, destFile);
96
+ fs.copyFileSync(srcImage, path.join(destDir, `splash_image${scale}.png`));
86
97
  });
87
98
 
88
- // Create Contents.json
89
- const contents = {
90
- images: [
91
- { idiom: 'universal', filename: 'splash_image.png', scale: '1x' },
92
- { idiom: 'universal', filename: 'splash_image@2x.png', scale: '2x' },
93
- { idiom: 'universal', filename: 'splash_image@3x.png', scale: '3x' }
94
- ],
95
- info: { author: 'xcode', version: 1 }
96
- };
97
- fs.writeFileSync(path.join(destDir, 'Contents.json'), JSON.stringify(contents, null, 2));
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('āœ… Copied: splash_image');
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
- const destFile = path.join(destDir, `splash_logo${scale}.png`);
113
- fs.copyFileSync(srcLogo, destFile);
130
+ fs.copyFileSync(srcLogo, path.join(destDir, `splash_logo${scale}.png`));
114
131
  });
115
132
 
116
- // Create Contents.json
117
- const contents = {
118
- images: [
119
- { idiom: 'universal', filename: 'splash_logo.png', scale: '1x' },
120
- { idiom: 'universal', filename: 'splash_logo@2x.png', scale: '2x' },
121
- { idiom: 'universal', filename: 'splash_logo@3x.png', scale: '3x' }
122
- ],
123
- info: { author: 'xcode', version: 1 }
124
- };
125
- fs.writeFileSync(path.join(destDir, 'Contents.json'), JSON.stringify(contents, null, 2));
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('āœ… Copied: splash_logo');
147
+ console.log('āœ… FORCED: splash_logo');
129
148
  }
130
149
  }
131
150
 
132
- // 6. Create NEW LaunchScreen.storyboard
133
- const storyboard = createStoryboard(hasImage, hasLogo, pluginConfig.backgroundColor);
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
- console.log('āœ… Created: LaunchScreen.storyboard');
138
- console.log(` Background: ${hasImage ? 'splash_image āœ“' : 'color only'}`);
139
- console.log(` Logo: ${hasLogo ? 'splash_logo āœ“' : 'none'}`);
140
- console.log(` Color: ${pluginConfig.backgroundColor}\n`);
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 createStoryboard(hasImage, hasLogo, bgColor) {
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 bgImageView = hasImage ? `
154
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="splash_image" translatesAutoresizingMaskIntoConstraints="NO" id="bgImg">
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 logoImageView = hasLogo ? `
159
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="splash_logo" translatesAutoresizingMaskIntoConstraints="NO" id="logoImg">
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="logoW"/>
163
- <constraint firstAttribute="height" constant="150" id="logoH"/>
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="bgImg" firstAttribute="top" secondItem="view" secondAttribute="top"/>
169
- <constraint firstItem="bgImg" firstAttribute="leading" secondItem="view" secondAttribute="leading"/>
170
- <constraint firstItem="bgImg" firstAttribute="trailing" secondItem="view" secondAttribute="trailing"/>
171
- <constraint firstItem="bgImg" firstAttribute="bottom" secondItem="view" secondAttribute="bottom"/>` : '';
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="logoImg" firstAttribute="centerX" secondItem="view" secondAttribute="centerX"/>
175
- <constraint firstItem="logoImg" firstAttribute="centerY" secondItem="view" secondAttribute="centerY"/>` : '';
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="01J-lp-oVM">
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="EHf-IW-A2E">
218
+ <scene sceneID="SC">
192
219
  <objects>
193
- <viewController id="01J-lp-oVM" sceneMemberID="viewController">
194
- <view key="view" contentMode="scaleToFill" id="view">
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>${bgImageView}${logoImageView}
224
+ <subviews>${bgImage}${logoImage}
198
225
  </subviews>
199
- <viewLayoutGuide key="safeArea" id="safeArea"/>
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="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
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 = withCustomiOSSplash;
242
+ module.exports = withForcediOSSplash;