react-native-custom-splash 3.0.2 → 3.0.3

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": "3.0.2",
3
+ "version": "3.0.3",
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",
@@ -2,12 +2,14 @@ const { withDangerousMod } = require('@expo/config-plugins');
2
2
  const path = require('path');
3
3
  const fs = require('fs');
4
4
 
5
+ /**
6
+ * BULLET-PROOF iOS Splash Screen
7
+ * This completely replaces Expo's splash with user's custom splash
8
+ */
5
9
  function withForcediOSSplash(config, pluginConfig) {
6
- config = {
7
- ...config,
8
- splash: undefined,
9
- ios: { ...config.ios, splash: undefined }
10
- };
10
+ // COMPLETELY DISABLE Expo's splash
11
+ if (config.splash) delete config.splash;
12
+ if (config.ios && config.ios.splash) delete config.ios.splash;
11
13
 
12
14
  return withDangerousMod(config, [
13
15
  'ios',
@@ -15,111 +17,122 @@ function withForcediOSSplash(config, pluginConfig) {
15
17
  const projectRoot = config.modRequest.projectRoot;
16
18
  const iosPath = config.modRequest.platformProjectRoot;
17
19
  const projectName = config.modRequest.projectName;
20
+ const projectDir = path.join(iosPath, projectName);
21
+ const assetsPath = path.join(projectDir, 'Images.xcassets');
18
22
 
19
- console.log('\nšŸ”„ Setting up splash screen...\n');
23
+ console.log('\nšŸ”„ CUSTOM SPLASH SCREEN SETUP...\n');
20
24
 
21
- // Delete old files
22
- const toDelete = [
25
+ // STEP 1: DELETE ALL EXPO SPLASH FILES
26
+ const filesToDelete = [
23
27
  'SplashScreen.storyboard',
24
28
  'LaunchScreen.storyboard',
25
- 'Images.xcassets/SplashScreenLegacy.imageset',
29
+ ];
30
+
31
+ const foldersToDelete = [
26
32
  'Images.xcassets/SplashScreen.imageset',
27
33
  'Images.xcassets/SplashScreenBackground.imageset',
34
+ 'Images.xcassets/SplashScreenLegacy.imageset',
28
35
  ];
29
36
 
30
- toDelete.forEach(file => {
31
- const fullPath = path.join(iosPath, projectName, file);
32
- try {
33
- if (fs.existsSync(fullPath)) {
34
- if (fs.lstatSync(fullPath).isDirectory()) {
35
- fs.rmSync(fullPath, { recursive: true, force: true });
36
- } else {
37
- fs.unlinkSync(fullPath);
38
- }
39
- }
40
- } catch (e) { }
37
+ filesToDelete.forEach(file => {
38
+ const fullPath = path.join(projectDir, file);
39
+ if (fs.existsSync(fullPath)) {
40
+ fs.unlinkSync(fullPath);
41
+ console.log('šŸ—‘ļø Deleted:', file);
42
+ }
41
43
  });
42
44
 
43
- // Update Info.plist
44
- const plistPath = path.join(iosPath, projectName, 'Info.plist');
45
+ foldersToDelete.forEach(folder => {
46
+ const fullPath = path.join(projectDir, folder);
47
+ if (fs.existsSync(fullPath)) {
48
+ fs.rmSync(fullPath, { recursive: true, force: true });
49
+ console.log('šŸ—‘ļø Deleted:', folder);
50
+ }
51
+ });
52
+
53
+ // STEP 2: UPDATE INFO.PLIST
54
+ const plistPath = path.join(projectDir, 'Info.plist');
45
55
  if (fs.existsSync(plistPath)) {
46
56
  let plist = fs.readFileSync(plistPath, 'utf8');
47
- plist = plist.replace(/<key>UILaunchStoryboardName<\/key>\s*<string>.*?<\/string>/g, '');
57
+
58
+ // Remove old references
59
+ plist = plist.replace(/<key>UILaunchStoryboardName<\/key>\s*<string>.*?<\/string>/gs, '');
48
60
  plist = plist.replace(/<key>UILaunchScreen<\/key>[\s\S]*?<\/dict>/g, '');
49
61
 
50
- if (!plist.includes('UILaunchStoryboardName')) {
51
- plist = plist.replace('</dict>\n</plist>', '\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n</dict>\n</plist>');
52
- }
62
+ // Add LaunchScreen reference
63
+ plist = plist.replace(
64
+ '</dict>\n</plist>',
65
+ '\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n</dict>\n</plist>'
66
+ );
53
67
 
54
68
  fs.writeFileSync(plistPath, plist);
69
+ console.log('āœ… Info.plist updated');
55
70
  }
56
71
 
57
- const assetsPath = path.join(iosPath, projectName, 'Images.xcassets');
58
- let hasImage = false;
72
+ // STEP 3: COPY USER IMAGES
73
+ let hasBackground = false;
59
74
  let hasLogo = false;
60
75
 
61
- // Copy background image
62
76
  if (pluginConfig.image) {
63
77
  const srcPath = path.join(projectRoot, pluginConfig.image);
64
78
  if (fs.existsSync(srcPath)) {
65
- const imagesetDir = path.join(assetsPath, 'SplashBg.imageset');
66
-
67
- if (fs.existsSync(imagesetDir)) fs.rmSync(imagesetDir, { recursive: true, force: true });
79
+ const imagesetDir = path.join(assetsPath, 'SplashBackground.imageset');
80
+ if (fs.existsSync(imagesetDir)) {
81
+ fs.rmSync(imagesetDir, { recursive: true, force: true });
82
+ }
68
83
  fs.mkdirSync(imagesetDir, { recursive: true });
69
84
 
70
- fs.copyFileSync(srcPath, path.join(imagesetDir, 'image.png'));
71
-
85
+ fs.copyFileSync(srcPath, path.join(imagesetDir, 'background.png'));
72
86
  fs.writeFileSync(path.join(imagesetDir, 'Contents.json'), JSON.stringify({
73
87
  images: [
74
- { filename: 'image.png', idiom: 'universal', scale: '1x' },
75
- { filename: 'image.png', idiom: 'universal', scale: '2x' },
76
- { filename: 'image.png', idiom: 'universal', scale: '3x' }
88
+ { idiom: 'universal', filename: 'background.png', scale: '1x' },
89
+ { idiom: 'universal', filename: 'background.png', scale: '2x' },
90
+ { idiom: 'universal', filename: 'background.png', scale: '3x' }
77
91
  ],
78
92
  info: { author: 'xcode', version: 1 }
79
93
  }, null, 2));
80
94
 
81
- hasImage = true;
82
- console.log('āœ… Background copied');
95
+ hasBackground = true;
96
+ console.log('āœ… Background image: SplashBackground');
83
97
  }
84
98
  }
85
99
 
86
- // Copy logo
87
100
  if (pluginConfig.logo) {
88
101
  const srcPath = path.join(projectRoot, pluginConfig.logo);
89
102
  if (fs.existsSync(srcPath)) {
90
- const imagesetDir = path.join(assetsPath, 'SplashIcon.imageset');
91
-
92
- if (fs.existsSync(imagesetDir)) fs.rmSync(imagesetDir, { recursive: true, force: true });
103
+ const imagesetDir = path.join(assetsPath, 'SplashLogo.imageset');
104
+ if (fs.existsSync(imagesetDir)) {
105
+ fs.rmSync(imagesetDir, { recursive: true, force: true });
106
+ }
93
107
  fs.mkdirSync(imagesetDir, { recursive: true });
94
108
 
95
- fs.copyFileSync(srcPath, path.join(imagesetDir, 'icon.png'));
96
-
109
+ fs.copyFileSync(srcPath, path.join(imagesetDir, 'logo.png'));
97
110
  fs.writeFileSync(path.join(imagesetDir, 'Contents.json'), JSON.stringify({
98
111
  images: [
99
- { filename: 'icon.png', idiom: 'universal', scale: '1x' },
100
- { filename: 'icon.png', idiom: 'universal', scale: '2x' },
101
- { filename: 'icon.png', idiom: 'universal', scale: '3x' }
112
+ { idiom: 'universal', filename: 'logo.png', scale: '1x' },
113
+ { idiom: 'universal', filename: 'logo.png', scale: '2x' },
114
+ { idiom: 'universal', filename: 'logo.png', scale: '3x' }
102
115
  ],
103
116
  info: { author: 'xcode', version: 1 }
104
117
  }, null, 2));
105
118
 
106
119
  hasLogo = true;
107
- console.log('āœ… Logo copied');
120
+ console.log('āœ… Logo image: SplashLogo');
108
121
  }
109
122
  }
110
123
 
111
- // Create storyboard
112
- const color = pluginConfig.backgroundColor.replace('#', '');
113
- const r = parseInt(color.substr(0, 2), 16) / 255;
114
- const g = parseInt(color.substr(2, 2), 16) / 255;
115
- const b = parseInt(color.substr(4, 2), 16) / 255;
124
+ // STEP 4: CREATE CLEAN LAUNCHSCREEN.STORYBOARD
125
+ const bgColor = pluginConfig.backgroundColor || '#FFFFFF';
126
+ const color = bgColor.replace('#', '');
127
+ const r = (parseInt(color.substr(0, 2), 16) / 255).toFixed(6);
128
+ const g = (parseInt(color.substr(2, 2), 16) / 255).toFixed(6);
129
+ const b = (parseInt(color.substr(4, 2), 16) / 255).toFixed(6);
116
130
 
117
- const storyboard = `<?xml version="1.0" encoding="UTF-8"?>
118
- <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">
119
- <device id="retina6_1" orientation="portrait" appearance="light"/>
131
+ let storyboard = `<?xml version="1.0" encoding="UTF-8"?>
132
+ <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="22505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
133
+ <device id="retina6_12" orientation="portrait" appearance="light"/>
120
134
  <dependencies>
121
- <deployment identifier="iOS"/>
122
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
135
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22504"/>
123
136
  <capability name="Safe area layout guides" minToolsVersion="9.0"/>
124
137
  <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
125
138
  </dependencies>
@@ -127,51 +140,85 @@ function withForcediOSSplash(config, pluginConfig) {
127
140
  <scene sceneID="EHf-IW-A2E">
128
141
  <objects>
129
142
  <viewController id="01J-lp-oVM" sceneMemberID="viewController">
130
- <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
131
- <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
143
+ <view key="view" contentMode="scaleToFill" id="mainView">
144
+ <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
132
145
  <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
133
- <subviews>${hasImage ? `
134
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SplashBg" translatesAutoresizingMaskIntoConstraints="NO" id="bg-img">
135
- <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
136
- </imageView>` : ''}${hasLogo ? `
137
- <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SplashIcon" translatesAutoresizingMaskIntoConstraints="NO" id="logo-img">
138
- <rect key="frame" x="132" y="373" width="150" height="150"/>
146
+ <subviews>`;
147
+
148
+ // Add background image if exists
149
+ if (hasBackground) {
150
+ storyboard += `
151
+ <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SplashBackground" translatesAutoresizingMaskIntoConstraints="NO" id="backgroundImageView">
152
+ <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
153
+ </imageView>`;
154
+ }
155
+
156
+ // Add logo if exists
157
+ if (hasLogo) {
158
+ storyboard += `
159
+ <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="SplashLogo" translatesAutoresizingMaskIntoConstraints="NO" id="logoImageView">
160
+ <rect key="frame" x="121.5" y="376" width="150" height="100"/>
139
161
  <constraints>
140
- <constraint firstAttribute="width" constant="150" id="w"/>
141
- <constraint firstAttribute="height" constant="150" id="h"/>
162
+ <constraint firstAttribute="width" constant="150" id="logoWidth"/>
163
+ <constraint firstAttribute="height" constant="100" id="logoHeight"/>
142
164
  </constraints>
143
- </imageView>` : ''}
165
+ </imageView>`;
166
+ }
167
+
168
+ storyboard += `
144
169
  </subviews>
145
- <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
170
+ <viewLayoutGuide key="safeArea" id="safeAreaGuide"/>
146
171
  <color key="backgroundColor" red="${r}" green="${g}" blue="${b}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
147
- <constraints>${hasImage ? `
148
- <constraint firstItem="bg-img" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top"/>
149
- <constraint firstItem="bg-img" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading"/>
150
- <constraint firstItem="bg-img" firstAttribute="trailing" secondItem="Ze5-6b-2t3" secondAttribute="trailing"/>
151
- <constraint firstItem="bg-img" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom"/>` : ''}${hasLogo ? `
152
- <constraint firstItem="logo-img" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX"/>
153
- <constraint firstItem="logo-img" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY"/>` : ''}
172
+ <constraints>`;
173
+
174
+ // Add background constraints
175
+ if (hasBackground) {
176
+ storyboard += `
177
+ <constraint firstItem="backgroundImageView" firstAttribute="top" secondItem="mainView" secondAttribute="top" id="bgTop"/>
178
+ <constraint firstItem="backgroundImageView" firstAttribute="leading" secondItem="mainView" secondAttribute="leading" id="bgLeading"/>
179
+ <constraint firstItem="backgroundImageView" firstAttribute="trailing" secondItem="mainView" secondAttribute="trailing" id="bgTrailing"/>
180
+ <constraint firstItem="backgroundImageView" firstAttribute="bottom" secondItem="mainView" secondAttribute="bottom" id="bgBottom"/>`;
181
+ }
182
+
183
+ // Add logo constraints
184
+ if (hasLogo) {
185
+ storyboard += `
186
+ <constraint firstItem="logoImageView" firstAttribute="centerX" secondItem="mainView" secondAttribute="centerX" id="logoCenterX"/>
187
+ <constraint firstItem="logoImageView" firstAttribute="centerY" secondItem="mainView" secondAttribute="centerY" id="logoCenterY"/>`;
188
+ }
189
+
190
+ storyboard += `
154
191
  </constraints>
155
192
  </view>
156
193
  </viewController>
157
- <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
194
+ <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
158
195
  </objects>
159
- <point key="canvasLocation" x="53" y="375"/>
196
+ <point key="canvasLocation" x="0" y="0"/>
160
197
  </scene>
161
198
  </scenes>
162
- <resources>${hasImage ? `
163
- <image name="SplashBg" width="1242" height="2688"/>` : ''}${hasLogo ? `
164
- <image name="SplashIcon" width="512" height="512"/>` : ''}
199
+ <resources>`;
200
+
201
+ if (hasBackground) {
202
+ storyboard += `
203
+ <image name="SplashBackground" width="1242" height="2688"/>`;
204
+ }
205
+ if (hasLogo) {
206
+ storyboard += `
207
+ <image name="SplashLogo" width="512" height="512"/>`;
208
+ }
209
+
210
+ storyboard += `
165
211
  </resources>
166
212
  </document>`;
167
213
 
168
- const storyboardPath = path.join(iosPath, projectName, 'LaunchScreen.storyboard');
169
- if (fs.existsSync(storyboardPath)) fs.unlinkSync(storyboardPath);
214
+ // Write storyboard
215
+ const storyboardPath = path.join(projectDir, 'LaunchScreen.storyboard');
170
216
  fs.writeFileSync(storyboardPath, storyboard);
171
217
 
172
- console.log('āœ… LaunchScreen.storyboard created!');
173
- console.log(` Background: ${hasImage ? 'YES' : 'NO'}`);
174
- console.log(` Logo: ${hasLogo ? 'YES' : 'NO'}\n`);
218
+ console.log('āœ… LaunchScreen.storyboard created');
219
+ console.log(` šŸ“ø Background: ${hasBackground ? 'YES' : 'NO'}`);
220
+ console.log(` šŸŽØ Logo: ${hasLogo ? 'YES' : 'NO'}`);
221
+ console.log(` 🌈 Color: ${bgColor}\n`);
175
222
 
176
223
  return config;
177
224
  },