react-native-bootsplash 4.0.0-alpha.1 → 4.0.0-beta.1

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.
@@ -1,52 +1,50 @@
1
1
  package com.zoontek.rnbootsplash;
2
2
 
3
+ import android.animation.Animator;
4
+ import android.animation.AnimatorListenerAdapter;
3
5
  import android.app.Activity;
4
- import android.content.Context;
5
- import android.content.DialogInterface;
6
- import android.content.res.Resources;
7
6
  import android.view.View;
8
- import android.view.ViewConfiguration;
9
- import android.view.Window;
7
+ import android.view.animation.AccelerateInterpolator;
10
8
 
11
- import androidx.annotation.ColorRes;
9
+ import androidx.annotation.NonNull;
12
10
  import androidx.annotation.Nullable;
13
- import androidx.annotation.StyleRes;
11
+ import androidx.core.splashscreen.SplashScreen;
12
+ import androidx.core.splashscreen.SplashScreenViewProvider;
14
13
 
14
+ import com.facebook.common.logging.FLog;
15
15
  import com.facebook.react.bridge.LifecycleEventListener;
16
16
  import com.facebook.react.bridge.Promise;
17
17
  import com.facebook.react.bridge.ReactApplicationContext;
18
18
  import com.facebook.react.bridge.ReactContextBaseJavaModule;
19
19
  import com.facebook.react.bridge.ReactMethod;
20
20
  import com.facebook.react.bridge.UiThreadUtil;
21
+ import com.facebook.react.common.ReactConstants;
21
22
  import com.facebook.react.module.annotations.ReactModule;
22
- import com.facebook.react.uimanager.PixelUtil;
23
23
 
24
24
  import java.util.ArrayList;
25
- import java.util.HashMap;
26
- import java.util.Map;
27
25
  import java.util.Timer;
28
26
  import java.util.TimerTask;
29
27
 
30
- @ReactModule(name = RNBootSplashModule.MODULE_NAME)
28
+ @ReactModule(name = RNBootSplashModule.NAME)
31
29
  public class RNBootSplashModule extends ReactContextBaseJavaModule implements LifecycleEventListener {
32
30
 
33
- public static final String MODULE_NAME = "RNBootSplash";
31
+ public static final String NAME = "RNBootSplash";
34
32
  private static final int ANIMATION_DURATION = 220;
35
33
 
36
34
  private enum Status {
37
35
  VISIBLE,
38
36
  HIDDEN,
39
- TRANSITIONING_TO_VISIBLE,
40
- TRANSITIONING_TO_HIDDEN
37
+ TRANSITIONING
41
38
  }
42
39
 
43
- private static int mBootThemeResId = -1;
40
+ @Nullable
41
+ private static SplashScreen mSplashScreen = null;
42
+
44
43
  private static final ArrayList<RNBootSplashTask> mTaskQueue = new ArrayList<>();
45
44
  private static Status mStatus = Status.HIDDEN;
46
45
  private static boolean mIsAppInBackground = false;
47
-
48
- @Nullable
49
- private static RNBootSplashDialog mDialog = null;
46
+ private static boolean mShouldFade = false;
47
+ private static boolean mShouldKeepOnScreen = true;
50
48
 
51
49
  public RNBootSplashModule(ReactApplicationContext reactContext) {
52
50
  super(reactContext);
@@ -55,73 +53,46 @@ public class RNBootSplashModule extends ReactContextBaseJavaModule implements Li
55
53
 
56
54
  @Override
57
55
  public String getName() {
58
- return MODULE_NAME;
56
+ return NAME;
59
57
  }
60
58
 
61
- @Override
62
- public @Nullable Map<String, Object> getConstants() {
63
- final HashMap<String, Object> constants = new HashMap<>();
64
- final Context context = getReactApplicationContext();
65
- final Resources resources = context.getResources();
66
- final boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
67
-
68
- final int statusBarHeightResId =
69
- resources.getIdentifier("status_bar_height", "dimen", "android");
70
- final int navigationBarHeightResId =
71
- resources.getIdentifier("navigation_bar_height", "dimen", "android");
72
-
73
- final float statusBarHeight =
74
- statusBarHeightResId > 0
75
- ? Math.round(PixelUtil.toDIPFromPixel(resources.getDimensionPixelSize(statusBarHeightResId)))
76
- : 0;
77
- final float navigationBarHeight =
78
- navigationBarHeightResId > 0 && !hasMenuKey
79
- ? Math.round(PixelUtil.toDIPFromPixel(resources.getDimensionPixelSize(navigationBarHeightResId)))
80
- : 0;
81
-
82
- constants.put("statusBarHeight", statusBarHeight);
83
- constants.put("navigationBarHeight", navigationBarHeight);
84
-
85
- return constants;
86
- }
87
-
88
- protected static void init(final Activity activity,
89
- @StyleRes final int bootThemeResId,
90
- @ColorRes final int backgroundColorResId) {
91
- UiThreadUtil.runOnUiThread(new Runnable() {
92
- @Override
93
- public void run() {
94
- if (activity == null
95
- || activity.isFinishing()
96
- || mDialog != null) {
97
- return;
98
- }
99
-
100
- final int backgroundColor = activity.getResources().getColor(backgroundColorResId);
101
- final View decorView = activity.getWindow().getDecorView();
102
-
103
- mBootThemeResId = bootThemeResId;
104
- mStatus = Status.VISIBLE;
105
- mDialog = new RNBootSplashDialog(activity, mBootThemeResId);
106
-
107
- mDialog.setOnShowListener(new DialogInterface.OnShowListener() {
108
- @Override
109
- public void onShow(DialogInterface dialog) {
110
- decorView.setBackgroundColor(backgroundColor);
111
- }
112
- });
59
+ protected static void init(@Nullable final Activity activity) {
60
+ if (activity == null) {
61
+ FLog.w(
62
+ ReactConstants.TAG,
63
+ NAME + ": Ignored initialization, current activity is null.");
64
+ return;
65
+ }
113
66
 
114
- Window window = mDialog.getWindow();
67
+ mSplashScreen = SplashScreen.installSplashScreen(activity);
68
+ mStatus = Status.VISIBLE;
115
69
 
116
- if (window != null) {
117
- window.setWindowAnimations(R.style.bootsplash_no_animation);
118
- }
70
+ mSplashScreen.setKeepVisibleCondition(new SplashScreen.KeepOnScreenCondition() {
71
+ @Override
72
+ public boolean shouldKeepOnScreen() {
73
+ return mShouldKeepOnScreen;
74
+ }
75
+ });
119
76
 
120
- if (!mDialog.isShowing()) {
121
- mDialog.show();
122
- } else {
123
- decorView.setBackgroundColor(backgroundColor);
124
- }
77
+ mSplashScreen.setOnExitAnimationListener(new SplashScreen.OnExitAnimationListener() {
78
+ @Override
79
+ public void onSplashScreenExit(@NonNull SplashScreenViewProvider splashScreenViewProvider) {
80
+ View splashScreenView = splashScreenViewProvider.getView();
81
+
82
+ splashScreenView
83
+ .animate()
84
+ // Crappy hack to avoid automatic layout transitions
85
+ .setDuration(mShouldFade ? ANIMATION_DURATION: 0)
86
+ .setStartDelay(mShouldFade ? 0 : ANIMATION_DURATION)
87
+ .alpha(0.0f)
88
+ .setInterpolator(new AccelerateInterpolator())
89
+ .setListener(new AnimatorListenerAdapter() {
90
+ @Override
91
+ public void onAnimationEnd(Animator animation) {
92
+ super.onAnimationEnd(animation);
93
+ splashScreenViewProvider.remove();
94
+ }
95
+ }).start();
125
96
  }
126
97
  });
127
98
  }
@@ -143,27 +114,17 @@ public class RNBootSplashModule extends ReactContextBaseJavaModule implements Li
143
114
  }
144
115
 
145
116
  private void shiftNextTask() {
146
- boolean shouldSkipTick = mBootThemeResId == -1
147
- || mStatus == Status.TRANSITIONING_TO_VISIBLE
148
- || mStatus == Status.TRANSITIONING_TO_HIDDEN
117
+ boolean shouldSkipTick = mStatus == Status.TRANSITIONING
149
118
  || mIsAppInBackground
150
119
  || mTaskQueue.isEmpty();
151
120
 
152
121
  if (shouldSkipTick) return;
153
122
 
154
123
  RNBootSplashTask task = mTaskQueue.remove(0);
155
-
156
- switch (task.getType()) {
157
- case SHOW:
158
- show(task);
159
- break;
160
- case HIDE:
161
- hide(task);
162
- break;
163
- }
124
+ hideWithTask(task);
164
125
  }
165
126
 
166
- private void waitAndShiftNextTask() {
127
+ private void waitAndRetry() {
167
128
  final Timer timer = new Timer();
168
129
 
169
130
  timer.schedule(new TimerTask() {
@@ -175,134 +136,55 @@ public class RNBootSplashModule extends ReactContextBaseJavaModule implements Li
175
136
  }, 250);
176
137
  }
177
138
 
178
- private void show(final RNBootSplashTask task) {
179
- UiThreadUtil.runOnUiThread(new Runnable() {
180
- @Override
181
- public void run() {
182
- final Activity activity = getReactApplicationContext().getCurrentActivity();
183
- final boolean fade = task.getFade();
184
- final Promise promise = task.getPromise();
185
-
186
- if (activity == null || activity.isFinishing()) {
187
- waitAndShiftNextTask();
188
- return;
189
- }
190
-
191
- if (mDialog != null) {
192
- promise.resolve(true); // splash screen is already visible
193
- shiftNextTask();
194
- return;
195
- }
196
-
197
- mStatus = Status.TRANSITIONING_TO_VISIBLE;
198
- mDialog = new RNBootSplashDialog(activity, mBootThemeResId);
199
-
200
- Window window = mDialog.getWindow();
201
-
202
- if (window != null) {
203
- window.setWindowAnimations(fade
204
- ? R.style.bootsplash_fade_animation
205
- : R.style.bootsplash_no_animation);
206
- }
207
-
208
- if (!mDialog.isShowing()) {
209
- mDialog.show();
210
- }
211
-
212
- if (!fade) {
213
- mStatus = Status.VISIBLE;
214
- promise.resolve(true);
215
- shiftNextTask();
216
- } else {
217
- final Timer timer = new Timer();
139
+ private void hideWithTask(final RNBootSplashTask task) {
140
+ final Activity activity = getReactApplicationContext().getCurrentActivity();
141
+ final boolean fade = task.getFade();
142
+ final Promise promise = task.getPromise();
218
143
 
219
- timer.schedule(new TimerTask() {
220
- @Override
221
- public void run() {
222
- mStatus = Status.VISIBLE;
223
- promise.resolve(true);
224
- shiftNextTask();
225
- timer.cancel();
226
- }
227
- }, ANIMATION_DURATION);
228
- }
229
- }
230
- });
231
- }
144
+ if (mSplashScreen == null || mStatus == Status.HIDDEN) {
145
+ promise.resolve(true);
146
+ shiftNextTask();
147
+ return;
148
+ }
232
149
 
233
- private void hide(final RNBootSplashTask task) {
234
150
  UiThreadUtil.runOnUiThread(new Runnable() {
235
151
  @Override
236
152
  public void run() {
237
- final Activity activity = getReactApplicationContext().getCurrentActivity();
238
- final boolean fade = task.getFade();
239
- final Promise promise = task.getPromise();
240
-
241
153
  if (activity == null || activity.isFinishing()) {
242
- waitAndShiftNextTask();
154
+ waitAndRetry(); // Wait for activity to be ready
243
155
  return;
244
156
  }
245
157
 
246
- if (mDialog == null) {
247
- promise.resolve(true); // splash screen is already hidden
248
- shiftNextTask();
249
- return;
158
+ if (fade) {
159
+ mStatus = Status.TRANSITIONING;
250
160
  }
251
161
 
252
- mStatus = Status.TRANSITIONING_TO_HIDDEN;
162
+ mShouldFade = fade;
163
+ mShouldKeepOnScreen = false;
253
164
 
254
- Window window = mDialog.getWindow();
165
+ final Timer timer = new Timer();
255
166
 
256
- mDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
167
+ // We cannot rely on setOnExitAnimationListener
168
+ // See https://issuetracker.google.com/issues/197906327
169
+ timer.schedule(new TimerTask() {
257
170
  @Override
258
- public void onDismiss(DialogInterface dialog) {
171
+ public void run() {
259
172
  mStatus = Status.HIDDEN;
260
- mDialog = null;
261
173
  promise.resolve(true);
174
+ timer.cancel();
262
175
  shiftNextTask();
263
176
  }
264
- });
265
-
266
- if (window != null) {
267
- window.setWindowAnimations(fade
268
- ? R.style.bootsplash_fade_animation
269
- : R.style.bootsplash_no_animation);
270
- }
271
-
272
- if (!fade) {
273
- mDialog.dismiss();
274
- } else {
275
- mDialog.hide();
276
- final Timer timer = new Timer();
277
-
278
- timer.schedule(new TimerTask() {
279
- @Override
280
- public void run() {
281
- mDialog.dismiss();
282
- timer.cancel();
283
- }
284
- }, ANIMATION_DURATION);
285
- }
177
+ }, ANIMATION_DURATION);
286
178
  }
287
179
  });
288
180
  }
289
181
 
290
- @ReactMethod
291
- public void show(final boolean fade, final Promise promise) {
292
- if (mBootThemeResId == -1) {
293
- promise.reject("uninitialized_module", "react-native-bootsplash has not been initialized");
294
- } else {
295
- mTaskQueue.add(new RNBootSplashTask(RNBootSplashTask.Type.SHOW, fade, promise));
296
- shiftNextTask();
297
- }
298
- }
299
-
300
182
  @ReactMethod
301
183
  public void hide(final boolean fade, final Promise promise) {
302
- if (mBootThemeResId == -1) {
303
- promise.reject("uninitialized_module", "react-native-bootsplash has not been initialized");
184
+ if (mSplashScreen == null || mStatus == Status.HIDDEN) {
185
+ promise.resolve(true);
304
186
  } else {
305
- mTaskQueue.add(new RNBootSplashTask(RNBootSplashTask.Type.HIDE, fade, promise));
187
+ mTaskQueue.add(new RNBootSplashTask(fade, promise));
306
188
  shiftNextTask();
307
189
  }
308
190
  }
@@ -316,8 +198,7 @@ public class RNBootSplashModule extends ReactContextBaseJavaModule implements Li
316
198
  case HIDDEN:
317
199
  promise.resolve("hidden");
318
200
  break;
319
- case TRANSITIONING_TO_VISIBLE:
320
- case TRANSITIONING_TO_HIDDEN:
201
+ case TRANSITIONING:
321
202
  promise.resolve("transitioning");
322
203
  break;
323
204
  }
@@ -1,5 +1,7 @@
1
1
  package com.zoontek.rnbootsplash;
2
2
 
3
+ import androidx.annotation.NonNull;
4
+
3
5
  import com.facebook.react.ReactPackage;
4
6
  import com.facebook.react.bridge.NativeModule;
5
7
  import com.facebook.react.bridge.ReactApplicationContext;
@@ -11,13 +13,15 @@ import java.util.List;
11
13
 
12
14
  public class RNBootSplashPackage implements ReactPackage {
13
15
 
16
+ @NonNull
14
17
  @Override
15
- public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
18
+ public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
16
19
  return Arrays.<NativeModule>asList(new RNBootSplashModule(reactContext));
17
20
  }
18
21
 
22
+ @NonNull
19
23
  @Override
20
- public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
24
+ public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
21
25
  return Collections.emptyList();
22
26
  }
23
27
  }
@@ -6,19 +6,10 @@ import com.facebook.react.bridge.Promise;
6
6
 
7
7
  public class RNBootSplashTask {
8
8
 
9
- public enum Type {
10
- SHOW,
11
- HIDE
12
- }
13
-
14
9
  private final boolean mFade;
15
10
  @NonNull private final Promise mPromise;
16
- @NonNull private final Type mType;
17
11
 
18
- public RNBootSplashTask(@NonNull final Type type,
19
- final boolean fade,
20
- @NonNull final Promise promise) {
21
- mType = type;
12
+ public RNBootSplashTask(final boolean fade, @NonNull final Promise promise) {
22
13
  mFade = fade;
23
14
  mPromise = promise;
24
15
  }
@@ -27,11 +18,6 @@ public class RNBootSplashTask {
27
18
  return mFade;
28
19
  }
29
20
 
30
- @NonNull
31
- public Type getType() {
32
- return mType;
33
- }
34
-
35
21
  @NonNull
36
22
  public Promise getPromise() {
37
23
  return mPromise;