react-native-bootsplash 4.1.1 → 4.1.4
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/README.md +52 -55
- package/android/build.gradle +2 -2
- package/android/src/main/java/com/zoontek/rnbootsplash/RNBootSplashModule.java +40 -72
- package/ios/RNBootSplash.h +1 -17
- package/ios/RNBootSplash.m +69 -96
- package/package.json +10 -7
- package/android/src/main/java/com/zoontek/rnbootsplash/RNBootSplashTask.java +0 -25
package/README.md
CHANGED
|
@@ -97,6 +97,8 @@ public class MainApplication extends Application implements ReactApplication {
|
|
|
97
97
|
|
|
98
98
|
## Setup
|
|
99
99
|
|
|
100
|
+
ℹ️ For `react-native` < `0.68` documentation, check the [`v4.1.3 README.md`](https://github.com/zoontek/react-native-bootsplash/blob/4.1.3/README.md)
|
|
101
|
+
|
|
100
102
|
### Assets generation
|
|
101
103
|
|
|
102
104
|
In order to speed up the setup, we provide a **CLI** to generate assets, create the Android Drawable XML file and the iOS Storyboard file automatically ✨.
|
|
@@ -132,6 +134,17 @@ yarn react-native generate-bootsplash assets/bootsplash_logo_original.png \
|
|
|
132
134
|
--flavor=main
|
|
133
135
|
```
|
|
134
136
|
|
|
137
|
+
#### Using an SVG
|
|
138
|
+
|
|
139
|
+
You might want to use SVG as input file. For that, you can install a CLI tool to convert your logo first:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
$ brew install librsvg # available on macOS
|
|
143
|
+
$ rsvg-convert -w 3000 bootsplash_logo.svg -o bootsplash_logo.png # create a large PNG with generous leeway for 4x Android xxxhdpi devices
|
|
144
|
+
$ react-native generate-bootsplash bootsplash_logo.png
|
|
145
|
+
$ rm bootsplash_logo.png # optionally, clean up the PNG
|
|
146
|
+
```
|
|
147
|
+
|
|
135
148
|

|
|
136
149
|
|
|
137
150
|
This tool relies on the naming conventions that are used in the `/example` project and will therefore create the following files:
|
|
@@ -161,22 +174,20 @@ ios/YourProjectName/Images.xcassets/BootSplashLogo.imageset/bootsplash_logo@3x.p
|
|
|
161
174
|
|
|
162
175
|
_⚠️ Only `.storyboard` files are supported ([Apple has deprecated other methods in April 2020](https://developer.apple.com/news/?id=01132020b))._
|
|
163
176
|
|
|
164
|
-
Edit the `ios/YourProjectName/AppDelegate.
|
|
177
|
+
Edit the `ios/YourProjectName/AppDelegate.mm` file:
|
|
165
178
|
|
|
166
179
|
```obj-c
|
|
167
180
|
#import "AppDelegate.h"
|
|
168
|
-
|
|
169
|
-
#import <React/RCTBridge.h>
|
|
170
|
-
#import <React/RCTBundleURLProvider.h>
|
|
171
|
-
#import <React/RCTRootView.h>
|
|
172
|
-
|
|
173
181
|
#import "RNBootSplash.h" // <- add the header import
|
|
174
182
|
|
|
183
|
+
// …
|
|
184
|
+
|
|
175
185
|
@implementation AppDelegate
|
|
176
186
|
|
|
177
187
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
|
178
188
|
{
|
|
179
189
|
// …
|
|
190
|
+
|
|
180
191
|
rootViewController.view = rootView;
|
|
181
192
|
self.window.rootViewController = rootViewController;
|
|
182
193
|
[self.window makeKeyAndVisible];
|
|
@@ -200,7 +211,7 @@ Set the `BootSplash.storyboard` as launch screen file:
|
|
|
200
211
|
```gradle
|
|
201
212
|
buildscript {
|
|
202
213
|
ext {
|
|
203
|
-
buildToolsVersion = "
|
|
214
|
+
buildToolsVersion = "31.0.0"
|
|
204
215
|
minSdkVersion = 23 // <- AndroidX splashscreen has basic support for 21 (only the background color), so 23 is best
|
|
205
216
|
compileSdkVersion = 31 // <- set at least 31
|
|
206
217
|
targetSdkVersion = 31 // <- set at least 31
|
|
@@ -212,10 +223,9 @@ buildscript {
|
|
|
212
223
|
|
|
213
224
|
```gradle
|
|
214
225
|
dependencies {
|
|
215
|
-
|
|
216
|
-
//noinspection GradleDynamicVersion
|
|
217
|
-
implementation "com.facebook.react:react-native:+" // From node_modules
|
|
226
|
+
// …
|
|
218
227
|
|
|
228
|
+
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
|
|
219
229
|
implementation "androidx.core:core-splashscreen:1.0.0-beta01" // Add this line
|
|
220
230
|
|
|
221
231
|
// …
|
|
@@ -255,18 +265,7 @@ dependencies {
|
|
|
255
265
|
android:roundIcon="@mipmap/ic_launcher_round"
|
|
256
266
|
android:allowBackup="false"
|
|
257
267
|
android:theme="@style/BootTheme"> <!-- Replace @style/AppTheme with @style/BootTheme -->
|
|
258
|
-
|
|
259
|
-
android:name=".MainActivity"
|
|
260
|
-
android:label="@string/app_name"
|
|
261
|
-
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
|
262
|
-
android:launchMode="singleTask"
|
|
263
|
-
android:windowSoftInputMode="adjustResize"
|
|
264
|
-
android:exported="true"> <!-- Add android:exported="true" -->
|
|
265
|
-
<intent-filter>
|
|
266
|
-
<action android:name="android.intent.action.MAIN" />
|
|
267
|
-
<category android:name="android.intent.category.LAUNCHER" />
|
|
268
|
-
</intent-filter>
|
|
269
|
-
</activity>
|
|
268
|
+
<!-- … -->
|
|
270
269
|
</application>
|
|
271
270
|
</manifest>
|
|
272
271
|
|
|
@@ -276,23 +275,23 @@ dependencies {
|
|
|
276
275
|
|
|
277
276
|
```java
|
|
278
277
|
import com.facebook.react.ReactActivity;
|
|
279
|
-
import com.facebook.react.ReactActivityDelegate;
|
|
278
|
+
import com.facebook.react.ReactActivityDelegate;
|
|
279
|
+
import com.facebook.react.ReactRootView;
|
|
280
280
|
import com.zoontek.rnbootsplash.RNBootSplash; // <- add this necessary import
|
|
281
281
|
|
|
282
282
|
public class MainActivity extends ReactActivity {
|
|
283
283
|
|
|
284
284
|
// …
|
|
285
285
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
};
|
|
286
|
+
public static class MainActivityDelegate extends ReactActivityDelegate {
|
|
287
|
+
|
|
288
|
+
// …
|
|
289
|
+
|
|
290
|
+
@Override
|
|
291
|
+
protected void loadApp(String appKey) {
|
|
292
|
+
RNBootSplash.init(getPlainActivity()); // <- initialize the splash screen
|
|
293
|
+
super.loadApp(appKey);
|
|
294
|
+
}
|
|
296
295
|
}
|
|
297
296
|
}
|
|
298
297
|
```
|
|
@@ -316,8 +315,6 @@ RNBootSplash.hide(); // immediate
|
|
|
316
315
|
RNBootSplash.hide({ fade: true }); // fade
|
|
317
316
|
```
|
|
318
317
|
|
|
319
|
-
---
|
|
320
|
-
|
|
321
318
|
### getVisibilityStatus()
|
|
322
319
|
|
|
323
320
|
#### Method type
|
|
@@ -360,7 +357,25 @@ function App() {
|
|
|
360
357
|
|
|
361
358
|
**🤙 A more complex example is available in the [`/example` folder](example).**
|
|
362
359
|
|
|
363
|
-
|
|
360
|
+
## Using React Navigation
|
|
361
|
+
|
|
362
|
+
If you are using React Navigation, you can hide the splash screen once the navigation container and all children have finished mounting by using the `onReady` function.
|
|
363
|
+
|
|
364
|
+
```js
|
|
365
|
+
import React from "react";
|
|
366
|
+
import { NavigationContainer } from "@react-navigation/native";
|
|
367
|
+
import RNBootSplash from "react-native-bootsplash";
|
|
368
|
+
|
|
369
|
+
function App() {
|
|
370
|
+
return (
|
|
371
|
+
<NavigationContainer onReady={() => RNBootSplash.hide()}>
|
|
372
|
+
{/* content */}
|
|
373
|
+
</NavigationContainer>
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Testing with Jest
|
|
364
379
|
|
|
365
380
|
Testing code which uses this library requires some setup since we need to mock the native methods.
|
|
366
381
|
|
|
@@ -369,7 +384,7 @@ To add the mocks, create a file _jest/setup.js_ (or any other file name) contain
|
|
|
369
384
|
```js
|
|
370
385
|
jest.mock("react-native-bootsplash", () => {
|
|
371
386
|
return {
|
|
372
|
-
|
|
387
|
+
hide: jest.fn().mockResolvedValueOnce(),
|
|
373
388
|
getVisibilityStatus: jest.fn().mockResolvedValue("hidden"),
|
|
374
389
|
};
|
|
375
390
|
});
|
|
@@ -383,24 +398,6 @@ After that, we need to add the setup file in the jest config. You can add it und
|
|
|
383
398
|
}
|
|
384
399
|
```
|
|
385
400
|
|
|
386
|
-
### Using React Navigation
|
|
387
|
-
|
|
388
|
-
If you are using React Navigation, you can hide the splash screen once the navigation container and all children have finished mounting by using the `onReady` function.
|
|
389
|
-
|
|
390
|
-
```js
|
|
391
|
-
import React from "react";
|
|
392
|
-
import { NavigationContainer } from "@react-navigation/native";
|
|
393
|
-
import RNBootSplash from "react-native-bootsplash";
|
|
394
|
-
|
|
395
|
-
function App() {
|
|
396
|
-
return (
|
|
397
|
-
<NavigationContainer onReady={() => RNBootSplash.hide()}>
|
|
398
|
-
{/* content */}
|
|
399
|
-
</NavigationContainer>
|
|
400
|
-
);
|
|
401
|
-
}
|
|
402
|
-
```
|
|
403
|
-
|
|
404
401
|
## 🕵️♂️ Comparison with [react-native-splash-screen](https://github.com/crazycodeboy/react-native-splash-screen)
|
|
405
402
|
|
|
406
403
|
- If `react-native-splash-screen` encourages you to display an image over your application, `react-native-bootsplash` way-to-go is to design your launch screen using platforms tools.
|
package/android/build.gradle
CHANGED
|
@@ -12,7 +12,7 @@ buildscript {
|
|
|
12
12
|
mavenCentral()
|
|
13
13
|
}
|
|
14
14
|
dependencies {
|
|
15
|
-
classpath("com.android.tools.build:gradle:
|
|
15
|
+
classpath("com.android.tools.build:gradle:7.0.4")
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -21,7 +21,7 @@ apply plugin: "com.android.library"
|
|
|
21
21
|
|
|
22
22
|
android {
|
|
23
23
|
compileSdkVersion safeExtGet("compileSdkVersion", 31)
|
|
24
|
-
buildToolsVersion safeExtGet("buildToolsVersion", "
|
|
24
|
+
buildToolsVersion safeExtGet("buildToolsVersion", "31.0.0")
|
|
25
25
|
defaultConfig {
|
|
26
26
|
minSdkVersion safeExtGet("minSdkVersion", 23)
|
|
27
27
|
targetSdkVersion safeExtGet("targetSdkVersion", 31)
|
|
@@ -12,7 +12,6 @@ import androidx.core.splashscreen.SplashScreen;
|
|
|
12
12
|
import androidx.core.splashscreen.SplashScreenViewProvider;
|
|
13
13
|
|
|
14
14
|
import com.facebook.common.logging.FLog;
|
|
15
|
-
import com.facebook.react.bridge.LifecycleEventListener;
|
|
16
15
|
import com.facebook.react.bridge.Promise;
|
|
17
16
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
18
17
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
@@ -25,7 +24,7 @@ import java.util.Timer;
|
|
|
25
24
|
import java.util.TimerTask;
|
|
26
25
|
|
|
27
26
|
@ReactModule(name = RNBootSplashModule.NAME)
|
|
28
|
-
public class RNBootSplashModule extends ReactContextBaseJavaModule
|
|
27
|
+
public class RNBootSplashModule extends ReactContextBaseJavaModule {
|
|
29
28
|
|
|
30
29
|
public static final String NAME = "RNBootSplash";
|
|
31
30
|
private static final int ANIMATION_DURATION = 220;
|
|
@@ -39,15 +38,13 @@ public class RNBootSplashModule extends ReactContextBaseJavaModule implements Li
|
|
|
39
38
|
@Nullable
|
|
40
39
|
private static SplashScreen mSplashScreen = null;
|
|
41
40
|
|
|
42
|
-
private static final RNBootSplashQueue<
|
|
41
|
+
private static final RNBootSplashQueue<Promise> mPromiseQueue = new RNBootSplashQueue<>();
|
|
43
42
|
private static Status mStatus = Status.HIDDEN;
|
|
44
|
-
private static boolean mIsAppInForeground = true;
|
|
45
43
|
private static boolean mShouldFade = false;
|
|
46
44
|
private static boolean mShouldKeepOnScreen = true;
|
|
47
45
|
|
|
48
46
|
public RNBootSplashModule(ReactApplicationContext reactContext) {
|
|
49
47
|
super(reactContext);
|
|
50
|
-
reactContext.addLifecycleEventListener(this);
|
|
51
48
|
}
|
|
52
49
|
|
|
53
50
|
@Override
|
|
@@ -96,95 +93,66 @@ public class RNBootSplashModule extends ReactContextBaseJavaModule implements Li
|
|
|
96
93
|
});
|
|
97
94
|
}
|
|
98
95
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
@Override
|
|
105
|
-
public void onHostPause() {
|
|
106
|
-
mIsAppInForeground = false;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
@Override
|
|
110
|
-
public void onHostResume() {
|
|
111
|
-
mIsAppInForeground = true;
|
|
112
|
-
shiftNextTask();
|
|
113
|
-
}
|
|
96
|
+
private void clearPromiseQueue() {
|
|
97
|
+
while (!mPromiseQueue.isEmpty()) {
|
|
98
|
+
Promise promise = mPromiseQueue.shift();
|
|
114
99
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
RNBootSplashTask task = mTaskQueue.shift();
|
|
118
|
-
|
|
119
|
-
if (task != null) {
|
|
120
|
-
hideWithTask(task);
|
|
121
|
-
}
|
|
100
|
+
if (promise != null)
|
|
101
|
+
promise.resolve(true);
|
|
122
102
|
}
|
|
123
103
|
}
|
|
124
104
|
|
|
125
|
-
private void
|
|
126
|
-
final Timer timer = new Timer();
|
|
127
|
-
|
|
128
|
-
timer.schedule(new TimerTask() {
|
|
129
|
-
@Override
|
|
130
|
-
public void run() {
|
|
131
|
-
shiftNextTask();
|
|
132
|
-
timer.cancel();
|
|
133
|
-
}
|
|
134
|
-
}, 250);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private void hideWithTask(final RNBootSplashTask task) {
|
|
138
|
-
final Activity activity = getReactApplicationContext().getCurrentActivity();
|
|
139
|
-
final boolean fade = task.getFade();
|
|
140
|
-
final Promise promise = task.getPromise();
|
|
141
|
-
|
|
105
|
+
private void hideAndResolveAll(final boolean fade) {
|
|
142
106
|
if (mSplashScreen == null || mStatus == Status.HIDDEN) {
|
|
143
|
-
|
|
144
|
-
shiftNextTask();
|
|
107
|
+
clearPromiseQueue();
|
|
145
108
|
return;
|
|
146
109
|
}
|
|
147
110
|
|
|
148
111
|
UiThreadUtil.runOnUiThread(new Runnable() {
|
|
149
112
|
@Override
|
|
150
113
|
public void run() {
|
|
114
|
+
final Activity activity = getReactApplicationContext().getCurrentActivity();
|
|
115
|
+
|
|
151
116
|
if (activity == null || activity.isFinishing()) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
117
|
+
// Wait for activity to be ready
|
|
118
|
+
final Timer timer = new Timer();
|
|
155
119
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
120
|
+
timer.schedule(new TimerTask() {
|
|
121
|
+
@Override
|
|
122
|
+
public void run() {
|
|
123
|
+
hideAndResolveAll(fade);
|
|
124
|
+
timer.cancel();
|
|
125
|
+
}
|
|
126
|
+
}, 250);
|
|
127
|
+
} else {
|
|
128
|
+
if (fade) {
|
|
129
|
+
mStatus = Status.TRANSITIONING;
|
|
130
|
+
}
|
|
159
131
|
|
|
160
|
-
|
|
161
|
-
|
|
132
|
+
mShouldFade = fade;
|
|
133
|
+
mShouldKeepOnScreen = false;
|
|
162
134
|
|
|
163
|
-
|
|
135
|
+
final Timer timer = new Timer();
|
|
164
136
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
}
|
|
137
|
+
// We cannot rely on setOnExitAnimationListener
|
|
138
|
+
// See https://issuetracker.google.com/issues/197906327
|
|
139
|
+
timer.schedule(new TimerTask() {
|
|
140
|
+
@Override
|
|
141
|
+
public void run() {
|
|
142
|
+
mStatus = Status.HIDDEN;
|
|
143
|
+
timer.cancel();
|
|
144
|
+
clearPromiseQueue();
|
|
145
|
+
}
|
|
146
|
+
}, ANIMATION_DURATION);
|
|
147
|
+
}
|
|
176
148
|
}
|
|
177
149
|
});
|
|
178
150
|
}
|
|
179
151
|
|
|
180
152
|
@ReactMethod
|
|
181
153
|
public void hide(final boolean fade, final Promise promise) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
} else {
|
|
185
|
-
mTaskQueue.push(new RNBootSplashTask(fade, promise));
|
|
186
|
-
shiftNextTask();
|
|
187
|
-
}
|
|
154
|
+
mPromiseQueue.push(promise);
|
|
155
|
+
hideAndResolveAll(fade);
|
|
188
156
|
}
|
|
189
157
|
|
|
190
158
|
@ReactMethod
|
package/ios/RNBootSplash.h
CHANGED
|
@@ -1,25 +1,9 @@
|
|
|
1
1
|
#import <React/RCTBridgeModule.h>
|
|
2
2
|
#import <React/RCTRootView.h>
|
|
3
3
|
|
|
4
|
-
typedef enum {
|
|
5
|
-
RNBootSplashStatusVisible = 0,
|
|
6
|
-
RNBootSplashStatusHidden = 1,
|
|
7
|
-
RNBootSplashStatusTransitioning = 2
|
|
8
|
-
} RNBootSplashStatus;
|
|
9
|
-
|
|
10
|
-
@interface RNBootSplashTask : NSObject
|
|
11
|
-
|
|
12
|
-
@property (nonatomic, readonly) BOOL fade;
|
|
13
|
-
@property (nonatomic, readonly, strong) RCTPromiseResolveBlock _Nonnull resolve;
|
|
14
|
-
|
|
15
|
-
- (instancetype _Nonnull)initWithFade:(BOOL)fade
|
|
16
|
-
resolver:(RCTPromiseResolveBlock _Nonnull)resolve;
|
|
17
|
-
|
|
18
|
-
@end
|
|
19
|
-
|
|
20
4
|
@interface RNBootSplash : NSObject <RCTBridgeModule>
|
|
21
5
|
|
|
22
6
|
+ (void)initWithStoryboard:(NSString * _Nonnull)storyboardName
|
|
23
|
-
rootView:(
|
|
7
|
+
rootView:(UIView * _Nullable)rootView;
|
|
24
8
|
|
|
25
9
|
@end
|
package/ios/RNBootSplash.m
CHANGED
|
@@ -3,30 +3,16 @@
|
|
|
3
3
|
#import <React/RCTBridge.h>
|
|
4
4
|
#import <React/RCTUtils.h>
|
|
5
5
|
|
|
6
|
-
static NSMutableArray<
|
|
6
|
+
static NSMutableArray<RCTPromiseResolveBlock> *_resolverQueue = nil;
|
|
7
7
|
static RCTRootView *_rootView = nil;
|
|
8
|
-
static
|
|
9
|
-
|
|
10
|
-
@implementation RNBootSplashTask
|
|
11
|
-
|
|
12
|
-
- (instancetype)initWithFade:(BOOL)fade
|
|
13
|
-
resolver:(RCTPromiseResolveBlock _Nonnull)resolve {
|
|
14
|
-
if (self = [super init]) {
|
|
15
|
-
_fade = fade;
|
|
16
|
-
_resolve = resolve;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return self;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
@end
|
|
8
|
+
static bool _isTransitioning = false;
|
|
23
9
|
|
|
24
10
|
@implementation RNBootSplash
|
|
25
11
|
|
|
26
12
|
RCT_EXPORT_MODULE();
|
|
27
13
|
|
|
28
14
|
+ (BOOL)requiresMainQueueSetup {
|
|
29
|
-
return
|
|
15
|
+
return NO;
|
|
30
16
|
}
|
|
31
17
|
|
|
32
18
|
- (dispatch_queue_t)methodQueue {
|
|
@@ -34,20 +20,29 @@ RCT_EXPORT_MODULE();
|
|
|
34
20
|
}
|
|
35
21
|
|
|
36
22
|
+ (void)initWithStoryboard:(NSString * _Nonnull)storyboardName
|
|
37
|
-
rootView:(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
23
|
+
rootView:(UIView * _Nullable)rootView {
|
|
24
|
+
if (rootView == nil ||
|
|
25
|
+
![rootView isKindOfClass:[RCTRootView class]] ||
|
|
26
|
+
_rootView != nil ||
|
|
27
|
+
RCTRunningInAppExtension())
|
|
28
|
+
return;
|
|
41
29
|
|
|
42
|
-
|
|
43
|
-
[_rootView setLoadingView:[[storyboard instantiateInitialViewController] view]];
|
|
30
|
+
_rootView = (RCTRootView *)rootView;
|
|
44
31
|
|
|
45
32
|
[[NSNotificationCenter defaultCenter] removeObserver:rootView
|
|
46
33
|
name:RCTContentDidAppearNotification
|
|
47
34
|
object:rootView];
|
|
48
35
|
|
|
36
|
+
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
|
|
37
|
+
UIView *loadingView = [[storyboard instantiateInitialViewController] view];
|
|
38
|
+
|
|
39
|
+
if (_resolverQueue != nil)
|
|
40
|
+
return; // hide has already been called, abort init
|
|
41
|
+
|
|
42
|
+
[_rootView setLoadingView:loadingView];
|
|
43
|
+
|
|
49
44
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
50
|
-
selector:@selector(onJavaScriptDidLoad
|
|
45
|
+
selector:@selector(onJavaScriptDidLoad)
|
|
51
46
|
name:RCTJavaScriptDidLoadNotification
|
|
52
47
|
object:nil];
|
|
53
48
|
|
|
@@ -55,107 +50,85 @@ RCT_EXPORT_MODULE();
|
|
|
55
50
|
selector:@selector(onJavaScriptDidFailToLoad)
|
|
56
51
|
name:RCTJavaScriptDidFailToLoadNotification
|
|
57
52
|
object:nil];
|
|
58
|
-
|
|
59
|
-
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
60
|
-
selector:@selector(shiftNextTask)
|
|
61
|
-
name:UIApplicationDidBecomeActiveNotification
|
|
62
|
-
object:nil];
|
|
63
53
|
}
|
|
64
54
|
|
|
65
|
-
+ (void)onJavaScriptDidLoad
|
|
66
|
-
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
67
|
-
name:RCTJavaScriptDidLoadNotification
|
|
68
|
-
object:nil];
|
|
69
|
-
|
|
70
|
-
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
71
|
-
name:RCTJavaScriptDidFailToLoadNotification
|
|
72
|
-
object:nil];
|
|
55
|
+
+ (void)onJavaScriptDidLoad {
|
|
56
|
+
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
73
57
|
}
|
|
74
58
|
|
|
75
59
|
+ (void)onJavaScriptDidFailToLoad {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (_rootView != nil) {
|
|
79
|
-
_rootView.loadingView.hidden = YES;
|
|
80
|
-
[_rootView.loadingView removeFromSuperview];
|
|
81
|
-
_rootView.loadingView = nil;
|
|
82
|
-
}
|
|
83
|
-
|
|
60
|
+
[self removeLoadingView];
|
|
84
61
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
85
62
|
}
|
|
86
63
|
|
|
87
|
-
+ (
|
|
88
|
-
|
|
89
|
-
[_taskQueue count] > 0 &&
|
|
90
|
-
[[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground) {
|
|
91
|
-
RNBootSplashTask *task = [_taskQueue objectAtIndex:0];
|
|
92
|
-
[_taskQueue removeObjectAtIndex:0];
|
|
93
|
-
|
|
94
|
-
[self hideWithTask:task];
|
|
95
|
-
}
|
|
64
|
+
+ (bool)isHidden {
|
|
65
|
+
return _rootView == nil || _rootView.loadingView == nil || [_rootView.loadingView isHidden];
|
|
96
66
|
}
|
|
97
67
|
|
|
98
|
-
+ (void)
|
|
99
|
-
if (
|
|
100
|
-
task.resolve(@(true));
|
|
101
|
-
return [self shiftNextTask];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (!task.fade) {
|
|
105
|
-
_status = RNBootSplashStatusHidden;
|
|
106
|
-
|
|
68
|
+
+ (void)removeLoadingView {
|
|
69
|
+
if (![self isHidden]) {
|
|
107
70
|
_rootView.loadingView.hidden = YES;
|
|
71
|
+
|
|
108
72
|
[_rootView.loadingView removeFromSuperview];
|
|
109
73
|
_rootView.loadingView = nil;
|
|
110
|
-
|
|
111
|
-
task.resolve(@(true));
|
|
112
|
-
return [self shiftNextTask];
|
|
113
74
|
}
|
|
75
|
+
}
|
|
114
76
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
options:UIViewAnimationOptionTransitionCrossDissolve
|
|
120
|
-
animations:^{
|
|
121
|
-
_rootView.loadingView.hidden = YES;
|
|
122
|
-
}
|
|
123
|
-
completion:^(__unused BOOL finished) {
|
|
124
|
-
_status = RNBootSplashStatusHidden;
|
|
125
|
-
|
|
126
|
-
[_rootView.loadingView removeFromSuperview];
|
|
127
|
-
_rootView.loadingView = nil;
|
|
77
|
+
- (void)clearResolverQueue {
|
|
78
|
+
while ([_resolverQueue count] > 0) {
|
|
79
|
+
RCTPromiseResolveBlock resolve = [_resolverQueue objectAtIndex:0];
|
|
80
|
+
[_resolverQueue removeObjectAtIndex:0];
|
|
128
81
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}];
|
|
82
|
+
resolve(@(true));
|
|
83
|
+
}
|
|
132
84
|
}
|
|
133
85
|
|
|
134
86
|
RCT_REMAP_METHOD(hide,
|
|
135
87
|
hideWithFade:(BOOL)fade
|
|
136
88
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
137
89
|
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
138
|
-
if (
|
|
139
|
-
|
|
90
|
+
if (_resolverQueue == nil)
|
|
91
|
+
_resolverQueue = [[NSMutableArray alloc] init];
|
|
92
|
+
|
|
93
|
+
[_resolverQueue addObject:resolve];
|
|
94
|
+
|
|
95
|
+
if ([RNBootSplash isHidden] || RCTRunningInAppExtension())
|
|
96
|
+
return [self clearResolverQueue];
|
|
140
97
|
|
|
141
|
-
|
|
142
|
-
|
|
98
|
+
if (!fade) {
|
|
99
|
+
[RNBootSplash removeLoadingView];
|
|
100
|
+
return [self clearResolverQueue];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
104
|
+
_isTransitioning = true;
|
|
105
|
+
|
|
106
|
+
[UIView transitionWithView:_rootView
|
|
107
|
+
duration:0.220
|
|
108
|
+
options:UIViewAnimationOptionTransitionCrossDissolve
|
|
109
|
+
animations:^{
|
|
110
|
+
_rootView.loadingView.hidden = YES;
|
|
111
|
+
}
|
|
112
|
+
completion:^(__unused BOOL finished) {
|
|
113
|
+
[_rootView.loadingView removeFromSuperview];
|
|
114
|
+
_rootView.loadingView = nil;
|
|
143
115
|
|
|
144
|
-
|
|
145
|
-
|
|
116
|
+
_isTransitioning = false;
|
|
117
|
+
|
|
118
|
+
return [self clearResolverQueue];
|
|
119
|
+
}];
|
|
120
|
+
});
|
|
146
121
|
}
|
|
147
122
|
|
|
148
123
|
RCT_REMAP_METHOD(getVisibilityStatus,
|
|
149
124
|
getVisibilityStatusWithResolver:(RCTPromiseResolveBlock)resolve
|
|
150
125
|
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return resolve(@"transitioning");
|
|
158
|
-
}
|
|
126
|
+
if ([RNBootSplash isHidden])
|
|
127
|
+
return resolve(@"hidden");
|
|
128
|
+
else if (_isTransitioning)
|
|
129
|
+
return resolve(@"transitioning");
|
|
130
|
+
else
|
|
131
|
+
return resolve(@"visible");
|
|
159
132
|
}
|
|
160
133
|
|
|
161
134
|
@end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-bootsplash",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Display a bootsplash on your app starts. Hide it when you want.",
|
|
6
6
|
"author": "Mathieu Acthernoene <zoontek@gmail.com>",
|
|
@@ -60,19 +60,22 @@
|
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"chalk": "^4.1.2",
|
|
63
|
-
"fs-extra": "^10.0.
|
|
63
|
+
"fs-extra": "^10.0.1",
|
|
64
64
|
"jimp": "^0.16.1"
|
|
65
65
|
},
|
|
66
|
+
"resolutions": {
|
|
67
|
+
"@types/react": "^17"
|
|
68
|
+
},
|
|
66
69
|
"devDependencies": {
|
|
67
70
|
"@types/fs-extra": "^9.0.13",
|
|
68
|
-
"@types/react-native": "^0.
|
|
69
|
-
"lint-staged": "^12.
|
|
70
|
-
"prettier": "^2.
|
|
71
|
+
"@types/react-native": "^0.67.3",
|
|
72
|
+
"lint-staged": "^12.3.7",
|
|
73
|
+
"prettier": "^2.6.1",
|
|
71
74
|
"prettier-plugin-organize-imports": "^2.3.4",
|
|
72
75
|
"react": "^17.0.2",
|
|
73
|
-
"react-native": "^0.
|
|
76
|
+
"react-native": "^0.68.0",
|
|
74
77
|
"react-native-builder-bob": "^0.18.2",
|
|
75
78
|
"rescript": "^9.1.4",
|
|
76
|
-
"typescript": "^4.
|
|
79
|
+
"typescript": "^4.6.3"
|
|
77
80
|
}
|
|
78
81
|
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
package com.zoontek.rnbootsplash;
|
|
2
|
-
|
|
3
|
-
import androidx.annotation.NonNull;
|
|
4
|
-
|
|
5
|
-
import com.facebook.react.bridge.Promise;
|
|
6
|
-
|
|
7
|
-
public class RNBootSplashTask {
|
|
8
|
-
|
|
9
|
-
private final boolean mFade;
|
|
10
|
-
@NonNull private final Promise mPromise;
|
|
11
|
-
|
|
12
|
-
public RNBootSplashTask(final boolean fade, @NonNull final Promise promise) {
|
|
13
|
-
mFade = fade;
|
|
14
|
-
mPromise = promise;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
public boolean getFade() {
|
|
18
|
-
return mFade;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
@NonNull
|
|
22
|
-
public Promise getPromise() {
|
|
23
|
-
return mPromise;
|
|
24
|
-
}
|
|
25
|
-
}
|