react-native-custom-splash 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,278 @@
1
+ # react-native-custom-splash
2
+
3
+ A custom splash screen module for React Native with native iOS and Android support, fully compatible with Expo.
4
+
5
+ ## Features
6
+
7
+ - ✅ **Native iOS & Android** splash screens
8
+ - ✅ **Expo compatible** with config plugin
9
+ - ✅ **Customizable** splash images
10
+ - ✅ **Animated transitions** for smooth hiding
11
+ - ✅ **TypeScript** support
12
+ - ✅ **Auto-show** on app launch
13
+ - ✅ **Manual control** with show/hide methods
14
+
15
+ ## Installation
16
+
17
+ ### For Expo Projects
18
+
19
+ ```bash
20
+ npm install react-native-custom-splash
21
+ # or
22
+ yarn add react-native-custom-splash
23
+ ```
24
+
25
+ Add the plugin to your `app.json` or `app.config.js`:
26
+
27
+ ```json
28
+ {
29
+ "expo": {
30
+ "plugins": [
31
+ "react-native-custom-splash"
32
+ ]
33
+ }
34
+ }
35
+ ```
36
+
37
+ Then run prebuild:
38
+
39
+ ```bash
40
+ npx expo prebuild
41
+ ```
42
+
43
+ ### For Bare React Native Projects
44
+
45
+ ```bash
46
+ npm install react-native-custom-splash
47
+ # or
48
+ yarn add react-native-custom-splash
49
+ ```
50
+
51
+ #### iOS Setup
52
+
53
+ 1. Install pods:
54
+ ```bash
55
+ cd ios && pod install && cd ..
56
+ ```
57
+
58
+ 2. The module will be automatically linked.
59
+
60
+ #### Android Setup
61
+
62
+ 1. Add the package to your `MainApplication.kt`:
63
+
64
+ ```kotlin
65
+ import com.rncustomsplash.SplashScreenPackage
66
+
67
+ // In getPackages() method:
68
+ packages.add(SplashScreenPackage())
69
+ ```
70
+
71
+ 2. Show splash in `MainActivity.kt`:
72
+
73
+ ```kotlin
74
+ import com.rncustomsplash.SplashScreenModule
75
+
76
+ override fun onCreate(savedInstanceState: Bundle?) {
77
+ SplashScreenModule.show(this)
78
+ super.onCreate(savedInstanceState)
79
+ }
80
+ ```
81
+
82
+ ## Adding Custom Splash Images
83
+
84
+ ### iOS
85
+
86
+ Add your splash image to your Xcode project:
87
+ 1. Open your project in Xcode
88
+ 2. Add an image asset named `splash` to your Assets catalog
89
+ 3. Or add a `splash.png` file to your project
90
+
91
+ ### Android
92
+
93
+ Add your splash image to Android resources:
94
+ 1. Add `splash.png` (or `splash.jpg`) to `android/app/src/main/res/drawable/`
95
+ 2. Or create a drawable resource named `splash`
96
+
97
+ You can also customize the background color in `android/app/src/main/res/values/colors.xml`:
98
+
99
+ ```xml
100
+ <color name="splash_background">#FFFFFF</color>
101
+ ```
102
+
103
+ ## Usage
104
+
105
+ ```typescript
106
+ import SplashScreen from 'react-native-custom-splash';
107
+ import { useEffect } from 'react';
108
+
109
+ function App() {
110
+ useEffect(() => {
111
+ // Hide splash screen after app is ready
112
+ // The splash screen shows automatically on launch
113
+
114
+ // Simple hide (instant)
115
+ SplashScreen.hide(false);
116
+
117
+ // Or with animation
118
+ SplashScreen.hide(true);
119
+
120
+ // You can also show it again
121
+ // SplashScreen.show();
122
+ }, []);
123
+
124
+ return (
125
+ // Your app content
126
+ );
127
+ }
128
+ ```
129
+
130
+ ## Example Project
131
+
132
+ A complete working example is included in the `example/` directory. It demonstrates:
133
+
134
+ - ✅ Automatic splash screen on launch
135
+ - ✅ Loading progress simulation
136
+ - ✅ Animated hide transitions
137
+ - ✅ Manual show/hide controls
138
+ - ✅ Full TypeScript integration
139
+
140
+ ### Run the Example
141
+
142
+ ```bash
143
+ cd example
144
+ npm install
145
+ npx expo prebuild
146
+ npm run ios # or npm run android
147
+ ```
148
+
149
+ See [example/README.md](./example/README.md) for detailed instructions.
150
+
151
+ ## API Reference
152
+
153
+ ### `SplashScreen.show()`
154
+
155
+ Shows the splash screen.
156
+
157
+ ```typescript
158
+ SplashScreen.show();
159
+ ```
160
+
161
+ ### `SplashScreen.hide(animated?)`
162
+
163
+ Hides the splash screen.
164
+
165
+ **Parameters:**
166
+ - `animated` (boolean, optional): Whether to animate the hide transition. Default: `false`
167
+
168
+ **Returns:** `Promise<boolean>` - Resolves to `true` if successful
169
+
170
+ ```typescript
171
+ // Hide instantly
172
+ await SplashScreen.hide();
173
+
174
+ // Hide with fade animation
175
+ await SplashScreen.hide(true);
176
+ ```
177
+
178
+ ## Example
179
+
180
+ ```typescript
181
+ import React, { useEffect, useState } from 'react';
182
+ import { View, Text, ActivityIndicator } from 'react-native';
183
+ import SplashScreen from 'react-native-custom-splash';
184
+
185
+ export default function App() {
186
+ const [appIsReady, setAppIsReady] = useState(false);
187
+
188
+ useEffect(() => {
189
+ async function prepare() {
190
+ try {
191
+ // Load your resources here
192
+ await loadFonts();
193
+ await loadData();
194
+
195
+ // Artificially delay for demo
196
+ await new Promise(resolve => setTimeout(resolve, 2000));
197
+ } catch (e) {
198
+ console.warn(e);
199
+ } finally {
200
+ setAppIsReady(true);
201
+ }
202
+ }
203
+
204
+ prepare();
205
+ }, []);
206
+
207
+ useEffect(() => {
208
+ if (appIsReady) {
209
+ // Hide splash screen with animation when app is ready
210
+ SplashScreen.hide(true);
211
+ }
212
+ }, [appIsReady]);
213
+
214
+ if (!appIsReady) {
215
+ return null; // Splash screen is visible
216
+ }
217
+
218
+ return (
219
+ <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
220
+ <Text>App is ready!</Text>
221
+ </View>
222
+ );
223
+ }
224
+ ```
225
+
226
+ ## Troubleshooting
227
+
228
+ ### iOS
229
+
230
+ **Module not found:**
231
+ - Make sure you ran `pod install` in the `ios/` directory
232
+ - Clean build folder: `cd ios && rm -rf build && cd ..`
233
+ - Rebuild the app
234
+
235
+ **Splash image not showing:**
236
+ - Verify the image is named `splash` in your Assets catalog
237
+ - Check that the image is added to the target
238
+
239
+ ### Android
240
+
241
+ **Module not found:**
242
+ - Verify `SplashScreenPackage()` is added to `MainApplication.kt`
243
+ - Clean build: `cd android && ./gradlew clean && cd ..`
244
+ - Rebuild the app
245
+
246
+ **Splash image not showing:**
247
+ - Check that `splash.png` exists in `res/drawable/`
248
+ - Verify the resource name matches in `splash_screen.xml`
249
+
250
+ ### Expo
251
+
252
+ **Plugin not working:**
253
+ - Make sure you added the plugin to `app.json`
254
+ - Run `npx expo prebuild --clean`
255
+ - Rebuild the app
256
+
257
+ ## TypeScript
258
+
259
+ This package includes TypeScript definitions. The module exports the following interface:
260
+
261
+ ```typescript
262
+ interface SplashScreenInterface {
263
+ show(): void;
264
+ hide(animated?: boolean): Promise<boolean>;
265
+ }
266
+ ```
267
+
268
+ ## License
269
+
270
+ MIT
271
+
272
+ ## Contributing
273
+
274
+ Contributions are welcome! Please feel free to submit a Pull Request.
275
+
276
+ ## Issues
277
+
278
+ If you encounter any issues, please file them on the GitHub repository.
@@ -0,0 +1,52 @@
1
+ buildscript {
2
+ ext.kotlin_version = '1.8.0'
3
+
4
+ repositories {
5
+ google()
6
+ mavenCentral()
7
+ }
8
+
9
+ dependencies {
10
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11
+ }
12
+ }
13
+
14
+ apply plugin: 'com.android.library'
15
+ apply plugin: 'kotlin-android'
16
+
17
+ android {
18
+ compileSdkVersion 33
19
+
20
+ defaultConfig {
21
+ minSdkVersion 21
22
+ targetSdkVersion 33
23
+ versionCode 1
24
+ versionName "1.0.0"
25
+ }
26
+
27
+ buildTypes {
28
+ release {
29
+ minifyEnabled false
30
+ }
31
+ }
32
+
33
+ compileOptions {
34
+ sourceCompatibility JavaVersion.VERSION_11
35
+ targetCompatibility JavaVersion.VERSION_11
36
+ }
37
+
38
+ kotlinOptions {
39
+ jvmTarget = '11'
40
+ }
41
+ }
42
+
43
+ repositories {
44
+ google()
45
+ mavenCentral()
46
+ }
47
+
48
+ dependencies {
49
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
50
+ implementation 'com.facebook.react:react-native:+'
51
+ implementation 'androidx.appcompat:appcompat:1.6.1'
52
+ }
@@ -0,0 +1,3 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.rncustomsplash">
3
+ </manifest>
@@ -0,0 +1,111 @@
1
+ package com.rncustomsplash
2
+
3
+ import android.app.Dialog
4
+ import android.graphics.Color
5
+ import android.graphics.drawable.ColorDrawable
6
+ import android.os.Build
7
+ import android.view.View
8
+ import android.view.WindowManager
9
+ import androidx.appcompat.app.AppCompatActivity
10
+ import com.facebook.react.bridge.Promise
11
+ import com.facebook.react.bridge.ReactApplicationContext
12
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
13
+ import com.facebook.react.bridge.ReactMethod
14
+ import com.facebook.react.bridge.UiThreadUtil
15
+
16
+ class SplashScreenModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
17
+
18
+ companion object {
19
+ private var splashDialog: Dialog? = null
20
+ private var isVisible = false
21
+
22
+ @JvmStatic
23
+ fun show(activity: AppCompatActivity) {
24
+ if (isVisible) return
25
+
26
+ UiThreadUtil.runOnUiThread {
27
+ try {
28
+ splashDialog = Dialog(activity, android.R.style.Theme_NoTitleBar_Fullscreen).apply {
29
+ setContentView(R.layout.splash_screen)
30
+ setCancelable(false)
31
+ window?.apply {
32
+ setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
33
+
34
+ // Make splash screen full screen
35
+ setFlags(
36
+ WindowManager.LayoutParams.FLAG_FULLSCREEN,
37
+ WindowManager.LayoutParams.FLAG_FULLSCREEN
38
+ )
39
+
40
+ // For API 30+, use WindowInsetsController
41
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
42
+ setDecorFitsSystemWindows(false)
43
+ } else {
44
+ @Suppress("DEPRECATION")
45
+ decorView.systemUiVisibility = (
46
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE
47
+ or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
48
+ or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
49
+ or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
50
+ or View.SYSTEM_UI_FLAG_FULLSCREEN
51
+ or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
52
+ )
53
+ }
54
+ }
55
+ show()
56
+ }
57
+ isVisible = true
58
+ } catch (e: Exception) {
59
+ e.printStackTrace()
60
+ }
61
+ }
62
+ }
63
+ }
64
+
65
+ override fun getName(): String {
66
+ return "SplashScreen"
67
+ }
68
+
69
+ @ReactMethod
70
+ fun show() {
71
+ reactApplicationContext.currentActivity?.let { activity ->
72
+ if (activity is AppCompatActivity) {
73
+ show(activity)
74
+ }
75
+ }
76
+ }
77
+
78
+ @ReactMethod
79
+ fun hide(animated: Boolean, promise: Promise) {
80
+ if (!isVisible) {
81
+ promise.resolve(false)
82
+ return
83
+ }
84
+
85
+ UiThreadUtil.runOnUiThread {
86
+ try {
87
+ splashDialog?.let { dialog ->
88
+ if (animated) {
89
+ // Add fade out animation
90
+ dialog.window?.decorView?.animate()
91
+ ?.alpha(0f)
92
+ ?.setDuration(300)
93
+ ?.withEndAction {
94
+ dialog.dismiss()
95
+ splashDialog = null
96
+ isVisible = false
97
+ }
98
+ ?.start()
99
+ } else {
100
+ dialog.dismiss()
101
+ splashDialog = null
102
+ isVisible = false
103
+ }
104
+ }
105
+ promise.resolve(true)
106
+ } catch (e: Exception) {
107
+ promise.reject("ERROR", e.message)
108
+ }
109
+ }
110
+ }
111
+ }
@@ -0,0 +1,16 @@
1
+ package com.rncustomsplash
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+ class SplashScreenPackage : ReactPackage {
9
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
10
+ return listOf(SplashScreenModule(reactContext))
11
+ }
12
+
13
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
14
+ return emptyList()
15
+ }
16
+ }
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <item android:drawable="@color/splash_background"/>
4
+ <item>
5
+ <!-- This is a placeholder. Users will replace with their own splash image -->
6
+ <shape android:shape="rectangle">
7
+ <solid android:color="@color/splash_background"/>
8
+ </shape>
9
+ </item>
10
+ </layer-list>
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
+ android:layout_width="match_parent"
4
+ android:layout_height="match_parent"
5
+ android:background="@color/splash_background"
6
+ android:gravity="center"
7
+ android:orientation="vertical">
8
+
9
+ <ImageView
10
+ android:id="@+id/splash_image"
11
+ android:layout_width="match_parent"
12
+ android:layout_height="match_parent"
13
+ android:scaleType="centerCrop"
14
+ android:src="@drawable/splash" />
15
+
16
+ </LinearLayout>
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <color name="splash_background">#FFFFFF</color>
4
+ </resources>
@@ -0,0 +1,23 @@
1
+ //
2
+ // SplashScreenModule.m
3
+ // RNCustomSplash
4
+ //
5
+ // Bridge for SplashScreenModule
6
+ //
7
+
8
+ #import <React/RCTBridgeModule.h>
9
+
10
+ @interface RCT_EXTERN_MODULE(SplashScreen, NSObject)
11
+
12
+ RCT_EXTERN_METHOD(show)
13
+
14
+ RCT_EXTERN_METHOD(hide:(BOOL)animated
15
+ resolve:(RCTPromiseResolveBlock)resolve
16
+ reject:(RCTPromiseRejectBlock)reject)
17
+
18
+ + (BOOL)requiresMainQueueSetup
19
+ {
20
+ return YES;
21
+ }
22
+
23
+ @end
@@ -0,0 +1,114 @@
1
+ //
2
+ // SplashScreenModule.swift
3
+ // RNCustomSplash
4
+ //
5
+ // Custom Native Splash Screen Module for iOS
6
+ //
7
+
8
+ import Foundation
9
+ import UIKit
10
+ import React
11
+
12
+ @objc(SplashScreen)
13
+ class SplashScreenModule: NSObject {
14
+
15
+ private static var splashWindow: UIWindow?
16
+ private static var isVisible = false
17
+
18
+ @objc
19
+ static func requiresMainQueueSetup() -> Bool {
20
+ return true
21
+ }
22
+
23
+ override init() {
24
+ super.init()
25
+ // Show splash automatically when module initializes
26
+ DispatchQueue.main.async {
27
+ SplashScreenModule.showSplashScreen()
28
+ }
29
+ }
30
+
31
+ private static func showSplashScreen() {
32
+ guard !isVisible else { return }
33
+
34
+ if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
35
+ let window = UIWindow(windowScene: scene)
36
+ window.windowLevel = .alert + 1
37
+ window.backgroundColor = .white
38
+
39
+ // Create splash view controller
40
+ let splashVC = UIViewController()
41
+ splashVC.view.backgroundColor = .white
42
+
43
+ // Try to load splash image from the main bundle
44
+ // Users should add their splash image to their app's assets
45
+ if let splashImage = UIImage(named: "splash") {
46
+ let imageView = UIImageView(image: splashImage)
47
+ imageView.contentMode = .scaleAspectFill
48
+ imageView.frame = splashVC.view.bounds
49
+ imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
50
+ splashVC.view.addSubview(imageView)
51
+ } else {
52
+ // Fallback: show white screen if no splash image is provided
53
+ if #available(iOS 13.0, *) {
54
+ splashVC.view.backgroundColor = .systemBackground
55
+ } else {
56
+ splashVC.view.backgroundColor = .white
57
+ }
58
+ }
59
+
60
+ window.rootViewController = splashVC
61
+ window.makeKeyAndVisible()
62
+
63
+ splashWindow = window
64
+ isVisible = true
65
+ }
66
+ }
67
+
68
+ @objc
69
+ func show() {
70
+ DispatchQueue.main.async {
71
+ SplashScreenModule.showSplashScreen()
72
+ }
73
+ }
74
+
75
+ @objc
76
+ func hide(_ animated: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
77
+ DispatchQueue.main.async {
78
+ guard SplashScreenModule.isVisible, let window = SplashScreenModule.splashWindow else {
79
+ resolve(false)
80
+ return
81
+ }
82
+
83
+ if animated {
84
+ UIView.animate(withDuration: 0.3, animations: {
85
+ window.alpha = 0
86
+ }) { _ in
87
+ window.isHidden = true
88
+ window.rootViewController = nil
89
+ SplashScreenModule.splashWindow = nil
90
+ SplashScreenModule.isVisible = false
91
+
92
+ // Ensure the main window becomes key again
93
+ if let mainWindow = UIApplication.shared.windows.first(where: { $0.rootViewController != nil && $0 != window }) {
94
+ mainWindow.makeKeyAndVisible()
95
+ }
96
+
97
+ resolve(true)
98
+ }
99
+ } else {
100
+ window.isHidden = true
101
+ window.rootViewController = nil
102
+ SplashScreenModule.splashWindow = nil
103
+ SplashScreenModule.isVisible = false
104
+
105
+ // Ensure the main window becomes key again
106
+ if let mainWindow = UIApplication.shared.windows.first(where: { $0.rootViewController != nil && $0 != window }) {
107
+ mainWindow.makeKeyAndVisible()
108
+ }
109
+
110
+ resolve(true)
111
+ }
112
+ }
113
+ }
114
+ }
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "react-native-custom-splash",
3
+ "version": "1.0.0",
4
+ "description": "A custom splash screen module for React Native with native iOS and Android support, fully compatible with Expo",
5
+ "main": "src/index.js",
6
+ "types": "src/index.d.ts",
7
+ "scripts": {
8
+ "test": "echo \"No tests yet\"",
9
+ "prepare": "echo \"Package prepared\""
10
+ },
11
+ "keywords": [
12
+ "react-native",
13
+ "expo",
14
+ "splash-screen",
15
+ "splash",
16
+ "ios",
17
+ "android",
18
+ "native-module"
19
+ ],
20
+ "author": "Your Name",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/vijaykishan312/react-native-custom-splash.git"
25
+ },
26
+ "peerDependencies": {
27
+ "react": "*",
28
+ "react-native": "*",
29
+ "expo": "*"
30
+ },
31
+ "devDependencies": {
32
+ "@types/react": "^18.0.0",
33
+ "@types/react-native": "^0.72.0",
34
+ "typescript": "^5.0.0"
35
+ },
36
+ "files": [
37
+ "src/",
38
+ "ios/",
39
+ "android/",
40
+ "plugin/",
41
+ "react-native-custom-splash.podspec",
42
+ "README.md",
43
+ "LICENSE"
44
+ ]
45
+ }
@@ -0,0 +1,89 @@
1
+ const {
2
+ withDangerousMod,
3
+ withPlugins,
4
+ withMainActivity,
5
+ withMainApplication,
6
+ } = require('@expo/config-plugins');
7
+ const path = require('path');
8
+ const fs = require('fs');
9
+
10
+ /**
11
+ * Plugin to add SplashScreenModule to Android
12
+ */
13
+ const withSplashScreenAndroid = (config) => {
14
+ // Add package to MainApplication
15
+ config = withMainApplication(config, async (config) => {
16
+ const { modResults } = config;
17
+ let contents = modResults.contents;
18
+
19
+ // Add import if not already present
20
+ if (!contents.includes('import com.rncustomsplash.SplashScreenPackage')) {
21
+ contents = contents.replace(
22
+ /(package\s+[\w.]+)/,
23
+ '$1\nimport com.rncustomsplash.SplashScreenPackage'
24
+ );
25
+ }
26
+
27
+ // Add package to packages list
28
+ if (!contents.includes('SplashScreenPackage()')) {
29
+ contents = contents.replace(
30
+ /(packages\.apply\s*{[^}]*)/,
31
+ '$1\n add(SplashScreenPackage())'
32
+ );
33
+ }
34
+
35
+ modResults.contents = contents;
36
+ return config;
37
+ });
38
+
39
+ // Add splash initialization to MainActivity
40
+ config = withMainActivity(config, async (config) => {
41
+ const { modResults } = config;
42
+ let contents = modResults.contents;
43
+
44
+ // Add import if not already present
45
+ if (!contents.includes('import com.rncustomsplash.SplashScreenModule')) {
46
+ contents = contents.replace(
47
+ /(package\s+[\w.]+)/,
48
+ '$1\nimport com.rncustomsplash.SplashScreenModule'
49
+ );
50
+ }
51
+
52
+ // Add splash show in onCreate
53
+ if (!contents.includes('SplashScreenModule.show(this)')) {
54
+ contents = contents.replace(
55
+ /(override\s+fun\s+onCreate\([^)]*\)\s*{)/,
56
+ '$1\n // Show splash screen\n SplashScreenModule.show(this)\n'
57
+ );
58
+ }
59
+
60
+ modResults.contents = contents;
61
+ return config;
62
+ });
63
+
64
+ return config;
65
+ };
66
+
67
+ /**
68
+ * Plugin to add SplashScreenModule to iOS
69
+ */
70
+ const withSplashScreenIOS = (config) => {
71
+ return withDangerousMod(config, [
72
+ 'ios',
73
+ async (config) => {
74
+ // The native files will be linked via CocoaPods
75
+ // No additional configuration needed here
76
+ return config;
77
+ },
78
+ ]);
79
+ };
80
+
81
+ /**
82
+ * Main plugin export
83
+ */
84
+ module.exports = (config) => {
85
+ return withPlugins(config, [
86
+ withSplashScreenAndroid,
87
+ withSplashScreenIOS,
88
+ ]);
89
+ };
@@ -0,0 +1,18 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "../package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "RNCustomSplash"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["repository"]["url"]
10
+ s.license = package["license"]
11
+ s.authors = { package["author"] => "" }
12
+ s.platforms = { :ios => "13.0" }
13
+ s.source = { :git => package["repository"]["url"], :tag => "#{s.version}" }
14
+
15
+ s.source_files = "*.{h,m,mm,swift}"
16
+
17
+ s.dependency "React-Core"
18
+ end
package/src/index.js ADDED
@@ -0,0 +1,3 @@
1
+ // JavaScript entry point (transpiled from TypeScript)
2
+ export { default } from './index.tsx';
3
+ export type { SplashScreenInterface } from './index.tsx';
package/src/index.tsx ADDED
@@ -0,0 +1,69 @@
1
+ import { NativeModules, Platform } from 'react-native';
2
+
3
+ const LINKING_ERROR =
4
+ `The package 'react-native-custom-splash' doesn't seem to be linked. Make sure: \n\n` +
5
+ Platform.select({ ios: "- Run 'pod install' in the ios/ directory\n", default: '' }) +
6
+ '- Rebuild the app after installing the package\n' +
7
+ '- If you are using Expo, run npx expo prebuild\n';
8
+
9
+ // Try both module names for compatibility
10
+ const SplashScreenModule =
11
+ NativeModules.SplashScreen || NativeModules.SplashScreenModule;
12
+
13
+ if (!SplashScreenModule) {
14
+ throw new Error(LINKING_ERROR);
15
+ }
16
+
17
+ if (__DEV__ && !SplashScreenModule) {
18
+ console.error(
19
+ '❌ SplashScreen native module not found!',
20
+ '\nAvailable modules:',
21
+ Object.keys(NativeModules).filter((m) => m.includes('Splash'))
22
+ );
23
+ }
24
+
25
+ export interface SplashScreenInterface {
26
+ /**
27
+ * Show the splash screen
28
+ */
29
+ show(): void;
30
+
31
+ /**
32
+ * Hide the splash screen
33
+ * @param animated - Whether to animate the hide transition (default: false)
34
+ * @returns Promise that resolves to true if successful
35
+ */
36
+ hide(animated?: boolean): Promise<boolean>;
37
+ }
38
+
39
+ const SplashScreen: SplashScreenInterface = {
40
+ show: () => {
41
+ if (SplashScreenModule?.show) {
42
+ if (__DEV__) {
43
+ console.log('📱 Calling SplashScreen.show()');
44
+ }
45
+ SplashScreenModule.show();
46
+ } else {
47
+ console.warn('⚠️ SplashScreen.show() not available');
48
+ }
49
+ },
50
+
51
+ hide: async (animated: boolean = false): Promise<boolean> => {
52
+ if (SplashScreenModule?.hide) {
53
+ if (__DEV__) {
54
+ console.log('📱 Calling SplashScreen.hide(animated:', animated, ')');
55
+ }
56
+ try {
57
+ return await SplashScreenModule.hide(animated);
58
+ } catch (error) {
59
+ console.error('❌ Error hiding splash screen:', error);
60
+ return false;
61
+ }
62
+ } else {
63
+ console.warn('⚠️ SplashScreen.hide() not available');
64
+ return false;
65
+ }
66
+ },
67
+ };
68
+
69
+ export default SplashScreen;