react-native-bootsplash 4.1.2 → 4.1.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/README.md
CHANGED
|
@@ -132,6 +132,17 @@ yarn react-native generate-bootsplash assets/bootsplash_logo_original.png \
|
|
|
132
132
|
--flavor=main
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
+
#### Using an SVG
|
|
136
|
+
|
|
137
|
+
You might want to use SVG as input file. For that, you can install a CLI tool to convert your logo first:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
$ brew install librsvg # available on macOS
|
|
141
|
+
$ rsvg-convert -w 3000 bootsplash_logo.svg bootsplash_logo.png # create a large PNG with generous leeway for 4x Android xxxhdpi devices
|
|
142
|
+
$ react-native generate-bootsplash bootsplash_logo.png
|
|
143
|
+
$ rm bootsplash_logo.png # optionally, clean up the PNG
|
|
144
|
+
```
|
|
145
|
+
|
|
135
146
|

|
|
136
147
|
|
|
137
148
|
This tool relies on the naming conventions that are used in the `/example` project and will therefore create the following files:
|
|
@@ -316,8 +327,6 @@ RNBootSplash.hide(); // immediate
|
|
|
316
327
|
RNBootSplash.hide({ fade: true }); // fade
|
|
317
328
|
```
|
|
318
329
|
|
|
319
|
-
---
|
|
320
|
-
|
|
321
330
|
### getVisibilityStatus()
|
|
322
331
|
|
|
323
332
|
#### Method type
|
|
@@ -360,7 +369,25 @@ function App() {
|
|
|
360
369
|
|
|
361
370
|
**🤙 A more complex example is available in the [`/example` folder](example).**
|
|
362
371
|
|
|
363
|
-
|
|
372
|
+
## Using React Navigation
|
|
373
|
+
|
|
374
|
+
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.
|
|
375
|
+
|
|
376
|
+
```js
|
|
377
|
+
import React from "react";
|
|
378
|
+
import { NavigationContainer } from "@react-navigation/native";
|
|
379
|
+
import RNBootSplash from "react-native-bootsplash";
|
|
380
|
+
|
|
381
|
+
function App() {
|
|
382
|
+
return (
|
|
383
|
+
<NavigationContainer onReady={() => RNBootSplash.hide()}>
|
|
384
|
+
{/* content */}
|
|
385
|
+
</NavigationContainer>
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## Testing with Jest
|
|
364
391
|
|
|
365
392
|
Testing code which uses this library requires some setup since we need to mock the native methods.
|
|
366
393
|
|
|
@@ -383,24 +410,6 @@ After that, we need to add the setup file in the jest config. You can add it und
|
|
|
383
410
|
}
|
|
384
411
|
```
|
|
385
412
|
|
|
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
413
|
## 🕵️♂️ Comparison with [react-native-splash-screen](https://github.com/crazycodeboy/react-native-splash-screen)
|
|
405
414
|
|
|
406
415
|
- 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.
|
|
@@ -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,16 +1,6 @@
|
|
|
1
1
|
#import <React/RCTBridgeModule.h>
|
|
2
2
|
#import <React/RCTRootView.h>
|
|
3
3
|
|
|
4
|
-
@interface RNBootSplashTask : NSObject
|
|
5
|
-
|
|
6
|
-
@property (nonatomic, readonly) BOOL fade;
|
|
7
|
-
@property (nonatomic, readonly, strong) RCTPromiseResolveBlock _Nonnull resolve;
|
|
8
|
-
|
|
9
|
-
- (instancetype _Nonnull)initWithFade:(BOOL)fade
|
|
10
|
-
resolver:(RCTPromiseResolveBlock _Nonnull)resolve;
|
|
11
|
-
|
|
12
|
-
@end
|
|
13
|
-
|
|
14
4
|
@interface RNBootSplash : NSObject <RCTBridgeModule>
|
|
15
5
|
|
|
16
6
|
+ (void)initWithStoryboard:(NSString * _Nonnull)storyboardName
|
package/ios/RNBootSplash.m
CHANGED
|
@@ -3,24 +3,9 @@
|
|
|
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
8
|
static bool _isTransitioning = false;
|
|
9
|
-
static bool _shouldPreventInit = false;
|
|
10
|
-
|
|
11
|
-
@implementation RNBootSplashTask
|
|
12
|
-
|
|
13
|
-
- (instancetype)initWithFade:(BOOL)fade
|
|
14
|
-
resolver:(RCTPromiseResolveBlock _Nonnull)resolve {
|
|
15
|
-
if (self = [super init]) {
|
|
16
|
-
_fade = fade;
|
|
17
|
-
_resolve = resolve;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return self;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
@end
|
|
24
9
|
|
|
25
10
|
@implementation RNBootSplash
|
|
26
11
|
|
|
@@ -48,13 +33,13 @@ RCT_EXPORT_MODULE();
|
|
|
48
33
|
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
|
|
49
34
|
UIView *loadingView = [[storyboard instantiateInitialViewController] view];
|
|
50
35
|
|
|
51
|
-
if (
|
|
52
|
-
return;
|
|
36
|
+
if (_resolverQueue != nil)
|
|
37
|
+
return; // hide has already been called, abort init
|
|
53
38
|
|
|
54
39
|
[_rootView setLoadingView:loadingView];
|
|
55
40
|
|
|
56
41
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
57
|
-
selector:@selector(onJavaScriptDidLoad
|
|
42
|
+
selector:@selector(onJavaScriptDidLoad)
|
|
58
43
|
name:RCTJavaScriptDidLoadNotification
|
|
59
44
|
object:nil];
|
|
60
45
|
|
|
@@ -62,21 +47,10 @@ RCT_EXPORT_MODULE();
|
|
|
62
47
|
selector:@selector(onJavaScriptDidFailToLoad)
|
|
63
48
|
name:RCTJavaScriptDidFailToLoadNotification
|
|
64
49
|
object:nil];
|
|
65
|
-
|
|
66
|
-
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
67
|
-
selector:@selector(shiftNextTask)
|
|
68
|
-
name:UIApplicationDidBecomeActiveNotification
|
|
69
|
-
object:nil];
|
|
70
50
|
}
|
|
71
51
|
|
|
72
|
-
+ (void)onJavaScriptDidLoad
|
|
73
|
-
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
74
|
-
name:RCTJavaScriptDidLoadNotification
|
|
75
|
-
object:nil];
|
|
76
|
-
|
|
77
|
-
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
78
|
-
name:RCTJavaScriptDidFailToLoadNotification
|
|
79
|
-
object:nil];
|
|
52
|
+
+ (void)onJavaScriptDidLoad {
|
|
53
|
+
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
80
54
|
}
|
|
81
55
|
|
|
82
56
|
+ (void)onJavaScriptDidFailToLoad {
|
|
@@ -91,39 +65,36 @@ RCT_EXPORT_MODULE();
|
|
|
91
65
|
+ (void)removeLoadingView {
|
|
92
66
|
if (![self isHidden]) {
|
|
93
67
|
_rootView.loadingView.hidden = YES;
|
|
68
|
+
|
|
94
69
|
[_rootView.loadingView removeFromSuperview];
|
|
95
70
|
_rootView.loadingView = nil;
|
|
96
71
|
}
|
|
97
72
|
}
|
|
98
73
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
+ (void)shiftNextTask {
|
|
105
|
-
[self ensureTaskQueue];
|
|
74
|
+
- (void)clearResolverQueue {
|
|
75
|
+
while ([_resolverQueue count] > 0) {
|
|
76
|
+
RCTPromiseResolveBlock resolve = [_resolverQueue objectAtIndex:0];
|
|
77
|
+
[_resolverQueue removeObjectAtIndex:0];
|
|
106
78
|
|
|
107
|
-
|
|
108
|
-
!_isTransitioning &&
|
|
109
|
-
[[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground) {
|
|
110
|
-
RNBootSplashTask *task = [_taskQueue objectAtIndex:0];
|
|
111
|
-
[_taskQueue removeObjectAtIndex:0];
|
|
112
|
-
|
|
113
|
-
[self hideWithTask:task];
|
|
79
|
+
resolve(@(true));
|
|
114
80
|
}
|
|
115
81
|
}
|
|
116
82
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
83
|
+
RCT_REMAP_METHOD(hide,
|
|
84
|
+
hideWithFade:(BOOL)fade
|
|
85
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
86
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
87
|
+
if (_resolverQueue == nil)
|
|
88
|
+
_resolverQueue = [[NSMutableArray alloc] init];
|
|
89
|
+
|
|
90
|
+
[_resolverQueue addObject:resolve];
|
|
122
91
|
|
|
123
|
-
if (
|
|
124
|
-
[self
|
|
125
|
-
|
|
126
|
-
|
|
92
|
+
if ([RNBootSplash isHidden] || RCTRunningInAppExtension())
|
|
93
|
+
return [self clearResolverQueue];
|
|
94
|
+
|
|
95
|
+
if (!fade) {
|
|
96
|
+
[RNBootSplash removeLoadingView];
|
|
97
|
+
return [self clearResolverQueue];
|
|
127
98
|
}
|
|
128
99
|
|
|
129
100
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
@@ -139,31 +110,13 @@ RCT_EXPORT_MODULE();
|
|
|
139
110
|
[_rootView.loadingView removeFromSuperview];
|
|
140
111
|
_rootView.loadingView = nil;
|
|
141
112
|
|
|
142
|
-
task.resolve(@(true));
|
|
143
113
|
_isTransitioning = false;
|
|
144
114
|
|
|
145
|
-
return [self
|
|
115
|
+
return [self clearResolverQueue];
|
|
146
116
|
}];
|
|
147
117
|
});
|
|
148
118
|
}
|
|
149
119
|
|
|
150
|
-
RCT_REMAP_METHOD(hide,
|
|
151
|
-
hideWithFade:(BOOL)fade
|
|
152
|
-
resolver:(RCTPromiseResolveBlock)resolve
|
|
153
|
-
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
154
|
-
_shouldPreventInit = true;
|
|
155
|
-
|
|
156
|
-
if ([RNBootSplash isHidden] || RCTRunningInAppExtension())
|
|
157
|
-
return resolve(@(true));
|
|
158
|
-
|
|
159
|
-
RNBootSplashTask *task = [[RNBootSplashTask alloc] initWithFade:fade
|
|
160
|
-
resolver:resolve];
|
|
161
|
-
|
|
162
|
-
[RNBootSplash ensureTaskQueue];
|
|
163
|
-
[_taskQueue addObject:task];
|
|
164
|
-
[RNBootSplash shiftNextTask];
|
|
165
|
-
}
|
|
166
|
-
|
|
167
120
|
RCT_REMAP_METHOD(getVisibilityStatus,
|
|
168
121
|
getVisibilityStatusWithResolver:(RCTPromiseResolveBlock)resolve
|
|
169
122
|
rejecter:(RCTPromiseRejectBlock)reject) {
|
package/package.json
CHANGED
|
@@ -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
|
-
}
|