expo-splash-screen 0.28.5 → 0.29.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +2 -2
  3. package/android/build.gradle +5 -5
  4. package/android/src/main/java/expo/modules/splashscreen/SplashScreenManager.kt +72 -0
  5. package/android/src/main/java/expo/modules/splashscreen/SplashScreenModule.kt +29 -27
  6. package/build/SplashScreen.types.d.ts +21 -0
  7. package/build/SplashScreen.types.d.ts.map +1 -0
  8. package/build/SplashScreen.types.js +2 -0
  9. package/build/SplashScreen.types.js.map +1 -0
  10. package/build/index.d.ts +4 -1
  11. package/build/index.d.ts.map +1 -1
  12. package/build/index.js +3 -3
  13. package/build/index.js.map +1 -1
  14. package/build/index.native.d.ts +4 -1
  15. package/build/index.native.d.ts.map +1 -1
  16. package/build/index.native.js +14 -14
  17. package/build/index.native.js.map +1 -1
  18. package/expo-module.config.json +4 -0
  19. package/ios/ExpoSplashScreen.podspec +35 -0
  20. package/ios/SplashScreenAppDelegateSubscriber.swift +7 -0
  21. package/ios/SplashScreenManager.swift +92 -0
  22. package/ios/SplashScreenModule.swift +27 -0
  23. package/ios/SplashScreenOptions.swift +6 -0
  24. package/package.json +3 -3
  25. package/plugin/build/withSplashScreen.d.ts +10 -1
  26. package/plugin/build/withSplashScreen.js +15 -5
  27. package/plugin/src/withSplashScreen.ts +26 -5
  28. package/plugin/tsconfig.tsbuildinfo +1 -0
  29. package/src/SplashScreen.types.ts +22 -0
  30. package/src/index.native.ts +20 -19
  31. package/src/index.ts +8 -3
  32. package/android/src/main/java/expo/modules/splashscreen/NativeResourcesBasedSplashScreenViewProvider.kt +0 -35
  33. package/android/src/main/java/expo/modules/splashscreen/SplashScreenImageResizeMode.kt +0 -24
  34. package/android/src/main/java/expo/modules/splashscreen/SplashScreenPackage.kt +0 -22
  35. package/android/src/main/java/expo/modules/splashscreen/SplashScreenReactActivityLifecycleListener.kt +0 -45
  36. package/android/src/main/java/expo/modules/splashscreen/SplashScreenView.kt +0 -40
  37. package/android/src/main/java/expo/modules/splashscreen/SplashScreenViewController.kt +0 -126
  38. package/android/src/main/java/expo/modules/splashscreen/SplashScreenViewProvider.kt +0 -11
  39. package/android/src/main/java/expo/modules/splashscreen/exceptions/SplashScreenExceptions.kt +0 -12
  40. package/android/src/main/java/expo/modules/splashscreen/singletons/SplashScreen.kt +0 -169
  41. package/android/src/main/java/expo/modules/splashscreen/singletons/SplashScreenStatusBar.kt +0 -30
  42. package/android/src/main/res/drawable/splashscreen.xml +0 -13
  43. package/android/src/main/res/drawable/splashscreen_image.png +0 -0
  44. package/android/src/main/res/values/strings.xml +0 -5
  45. package/android/src/main/res/values/styles_splashscreen.xml +0 -10
  46. package/ios/EXSplashScreen/EXSplashScreenModule.h +0 -9
  47. package/ios/EXSplashScreen/EXSplashScreenModule.m +0 -178
  48. package/ios/EXSplashScreen/EXSplashScreenService.h +0 -84
  49. package/ios/EXSplashScreen/EXSplashScreenService.m +0 -210
  50. package/ios/EXSplashScreen/EXSplashScreenViewController.h +0 -24
  51. package/ios/EXSplashScreen/EXSplashScreenViewController.m +0 -104
  52. package/ios/EXSplashScreen/EXSplashScreenViewNativeProvider.h +0 -12
  53. package/ios/EXSplashScreen/EXSplashScreenViewNativeProvider.m +0 -51
  54. package/ios/EXSplashScreen/EXSplashScreenViewProvider.h +0 -14
  55. package/ios/EXSplashScreen.podspec +0 -36
package/CHANGELOG.md CHANGED
@@ -10,6 +10,10 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.29.0 — 2024-10-31
14
+
15
+ _This version does not introduce any user-facing changes._
16
+
13
17
  ## 0.28.5 — 2024-10-30
14
18
 
15
19
  _This version does not introduce any user-facing changes._
package/README.md CHANGED
@@ -765,8 +765,8 @@ We try to keep changes backward compatible, the code for `expo-splash-screen` wi
765
765
  import com.facebook.react.ReactRootView;
766
766
  import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
767
767
 
768
- -import expo.modules.splashscreen.singletons.SplashScreen;
769
- -import expo.modules.splashscreen.SplashScreenImageResizeMode;
768
+ -import host.exp.exponent.experience.splashscreen.legacy.singletons.SplashScreen;
769
+ -import host.exp.exponent.experience.splashscreen.legacy.SplashScreenImageResizeMode;
770
770
  -
771
771
  public class MainActivity extends ReactActivity {
772
772
  @Override
@@ -1,7 +1,7 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
3
  group = 'host.exp.exponent'
4
- version = '0.28.5'
4
+ version = '0.29.0'
5
5
 
6
6
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
7
7
  apply from: expoModulesCorePlugin
@@ -14,12 +14,12 @@ android {
14
14
  namespace "expo.modules.splashscreen"
15
15
  defaultConfig {
16
16
  versionCode 17
17
- versionName '0.28.5'
17
+ versionName '0.29.0'
18
18
  }
19
19
  }
20
20
 
21
21
  dependencies {
22
- implementation 'com.facebook.react:react-android'
23
- implementation 'androidx.appcompat:appcompat:1.2.0'
24
- implementation "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion()}"
22
+ implementation 'androidx.appcompat:appcompat:1.7.0'
23
+ implementation "androidx.core:core-splashscreen:1.2.0-alpha02"
24
+ implementation "com.facebook.react:react-android"
25
25
  }
@@ -0,0 +1,72 @@
1
+ package expo.modules.splashscreen
2
+
3
+ import android.app.Activity
4
+ import android.view.View
5
+ import android.view.ViewTreeObserver.OnPreDrawListener
6
+ import android.view.animation.AccelerateInterpolator
7
+ import androidx.core.splashscreen.SplashScreen
8
+ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
9
+ import com.facebook.react.bridge.ReactMarker
10
+ import com.facebook.react.bridge.ReactMarkerConstants
11
+
12
+ object SplashScreenManager {
13
+ private var keepSplashScreenOnScreen = true
14
+ var preventAutoHideCalled: Boolean = false
15
+ private lateinit var splashScreen: SplashScreen
16
+
17
+ private val contentAppearedListener = ReactMarker.MarkerListener { name, _, _ ->
18
+ if (name == ReactMarkerConstants.CONTENT_APPEARED) {
19
+ if (!preventAutoHideCalled) {
20
+ hide()
21
+ }
22
+ }
23
+ }
24
+
25
+ private fun configureSplashScreen(options: SplashScreenOptions = SplashScreenOptions()) {
26
+ val duration = options.duration
27
+
28
+ splashScreen.setOnExitAnimationListener { splashScreenViewProvider ->
29
+ splashScreenViewProvider.view
30
+ .animate()
31
+ .setDuration(duration)
32
+ .alpha(0.0f)
33
+ .setInterpolator(AccelerateInterpolator())
34
+ .withEndAction {
35
+ splashScreenViewProvider.remove()
36
+ }.start()
37
+ }
38
+ }
39
+
40
+ fun registerOnActivity(activity: Activity) {
41
+ splashScreen = activity.installSplashScreen()
42
+ ReactMarker.addListener(contentAppearedListener)
43
+
44
+ // Using `splashScreen.setKeepOnScreenCondition()` does not work on apis below 33
45
+ // so we need to implement this ourselves.
46
+ val contentView = activity.findViewById<View>(android.R.id.content)
47
+ val observer = contentView.viewTreeObserver
48
+ observer.addOnPreDrawListener(object : OnPreDrawListener {
49
+ override fun onPreDraw(): Boolean {
50
+ if (keepSplashScreenOnScreen) {
51
+ return false
52
+ }
53
+ contentView.viewTreeObserver.removeOnPreDrawListener(this)
54
+ return true
55
+ }
56
+ })
57
+
58
+ configureSplashScreen()
59
+ }
60
+
61
+ fun hide() {
62
+ keepSplashScreenOnScreen = false
63
+ }
64
+
65
+ fun setSplashScreenOptions(options: SplashScreenOptions) {
66
+ configureSplashScreen(options)
67
+ }
68
+
69
+ fun unregisterContentAppearedListener() {
70
+ ReactMarker.removeListener(contentAppearedListener)
71
+ }
72
+ }
@@ -1,43 +1,45 @@
1
1
  package expo.modules.splashscreen
2
2
 
3
- import expo.modules.kotlin.Promise
4
3
  import expo.modules.kotlin.modules.Module
5
4
  import expo.modules.kotlin.modules.ModuleDefinition
6
- import expo.modules.splashscreen.exceptions.HideAsyncException
7
- import expo.modules.splashscreen.exceptions.PreventAutoHideException
5
+ import expo.modules.kotlin.records.Field
6
+ import expo.modules.kotlin.records.Record
7
+ import kotlinx.coroutines.launch
8
8
 
9
- // Below import must be kept unversioned even in versioned code to provide a redirection from
10
- // versioned code realm to unversioned code realm.
11
- // Without this import any `SplashScreen.anyMethodName(...)` invocation on JS side ends up
12
- // in versioned SplashScreen kotlin object that stores no information about the ExperienceActivity.
13
- import expo.modules.splashscreen.singletons.SplashScreen
9
+ class SplashScreenOptions : Record {
10
+ @Field
11
+ val duration: Long = 400L
12
+
13
+ @Field
14
+ var fade: Boolean = true
15
+ }
14
16
 
15
17
  class SplashScreenModule : Module() {
16
18
  override fun definition() = ModuleDefinition {
17
19
  Name("ExpoSplashScreen")
18
20
 
19
- AsyncFunction("preventAutoHideAsync") { promise: Promise ->
20
- appContext.currentActivity?.let {
21
- SplashScreen.preventAutoHide(
22
- it,
23
- { hasEffect -> promise.resolve(hasEffect) },
24
- { m -> promise.reject(PreventAutoHideException(m)) }
25
- )
26
- } ?: run {
27
- promise.resolve(false)
28
- }
21
+ AsyncFunction<Unit>("preventAutoHideAsync") {
22
+ SplashScreenManager.preventAutoHideCalled = true
29
23
  }
30
24
 
31
- AsyncFunction("hideAsync") { promise: Promise ->
32
- appContext.currentActivity?.let {
33
- SplashScreen.hide(
34
- it,
35
- { hasEffect -> promise.resolve(hasEffect) },
36
- { m -> promise.reject(HideAsyncException(m)) }
37
- )
38
- } ?: run {
39
- promise.resolve(false)
25
+ Function("setOptions") { options: SplashScreenOptions ->
26
+ // Needs to run on the main thread on apis below 33
27
+ appContext.mainQueue.launch {
28
+ SplashScreenManager.setSplashScreenOptions(options)
40
29
  }
41
30
  }
31
+
32
+ Function("hide") {
33
+ SplashScreenManager.hide()
34
+ }
35
+
36
+ // For backwards compatibility
37
+ AsyncFunction("hideAsync") {
38
+ SplashScreenManager.hide()
39
+ }
40
+
41
+ OnDestroy {
42
+ SplashScreenManager.unregisterContentAppearedListener()
43
+ }
42
44
  }
43
45
  }
@@ -0,0 +1,21 @@
1
+ import { NativeModule } from 'expo-modules-core/types';
2
+ export type SplashScreenOptions = {
3
+ /**
4
+ * The duration of the fade out animation in milliseconds.
5
+ * @default 400
6
+ */
7
+ duration?: number;
8
+ /**
9
+ * Whether to hide the splash screen with a fade out animation.
10
+ * @ios
11
+ * @default false
12
+ */
13
+ fade?: boolean;
14
+ };
15
+ export interface SplashScreenNativeModule extends NativeModule {
16
+ setOptions: (options: SplashScreenOptions) => void;
17
+ preventAutoHideAsync: () => Promise<boolean>;
18
+ hide: () => void;
19
+ hideAsync: () => Promise<void>;
20
+ }
21
+ //# sourceMappingURL=SplashScreen.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SplashScreen.types.d.ts","sourceRoot":"","sources":["../src/SplashScreen.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,WAAW,wBAAyB,SAAQ,YAAY;IAC5D,UAAU,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACnD,oBAAoB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SplashScreen.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SplashScreen.types.js","sourceRoot":"","sources":["../src/SplashScreen.types.ts"],"names":[],"mappings":"","sourcesContent":["import { NativeModule } from 'expo-modules-core/types';\n\nexport type SplashScreenOptions = {\n /**\n * The duration of the fade out animation in milliseconds.\n * @default 400\n */\n duration?: number;\n /**\n * Whether to hide the splash screen with a fade out animation.\n * @ios\n * @default false\n */\n fade?: boolean;\n};\n\nexport interface SplashScreenNativeModule extends NativeModule {\n setOptions: (options: SplashScreenOptions) => void;\n preventAutoHideAsync: () => Promise<boolean>;\n hide: () => void;\n hideAsync: () => Promise<void>;\n}\n"]}
package/build/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { SplashScreenOptions } from './SplashScreen.types';
1
2
  /**
2
3
  * Makes the native splash screen (configured in `app.json`) remain visible until `hideAsync` is called.
3
4
  *
@@ -17,10 +18,12 @@
17
18
  * ```
18
19
  */
19
20
  export declare function preventAutoHideAsync(): Promise<boolean>;
21
+ export declare function setOptions(options: SplashScreenOptions): void;
20
22
  /**
21
23
  * Hides the native splash screen immediately. Be careful to ensure that your app has content ready
22
24
  * to display when you hide the splash screen, or you may see a blank screen briefly. See the
23
25
  * ["Usage"](#usage) section for an example.
24
26
  */
25
- export declare function hideAsync(): Promise<boolean>;
27
+ export declare function hide(): void;
28
+ export declare function hideAsync(): Promise<void>;
26
29
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE7D;AAGD;;;;GAIG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAElD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE7D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAG;AAGjE;;;;GAIG;AACH,wBAAgB,IAAI,IAAI,IAAI,CAAG;AAE/B,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAG"}
package/build/index.js CHANGED
@@ -20,13 +20,13 @@
20
20
  export async function preventAutoHideAsync() {
21
21
  return false;
22
22
  }
23
+ export function setOptions(options) { }
23
24
  // @needsAudit
24
25
  /**
25
26
  * Hides the native splash screen immediately. Be careful to ensure that your app has content ready
26
27
  * to display when you hide the splash screen, or you may see a blank screen briefly. See the
27
28
  * ["Usage"](#usage) section for an example.
28
29
  */
29
- export async function hideAsync() {
30
- return false;
31
- }
30
+ export function hide() { }
31
+ export async function hideAsync() { }
32
32
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,cAAc;AACd;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["// @needsAudit\n/**\n * Makes the native splash screen (configured in `app.json`) remain visible until `hideAsync` is called.\n *\n * > **Important note**: It is recommended to call this in global scope without awaiting, rather than\n * > inside React components or hooks, because otherwise this might be called too late,\n * > when the splash screen is already hidden.\n *\n * @example\n * ```ts\n * import * as SplashScreen from 'expo-splash-screen';\n *\n * SplashScreen.preventAutoHideAsync();\n *\n * export default function App() {\n * // ...\n * }\n * ```\n */\nexport async function preventAutoHideAsync(): Promise<boolean> {\n return false;\n}\n\n// @needsAudit\n/**\n * Hides the native splash screen immediately. Be careful to ensure that your app has content ready\n * to display when you hide the splash screen, or you may see a blank screen briefly. See the\n * [\"Usage\"](#usage) section for an example.\n */\nexport async function hideAsync(): Promise<boolean> {\n return false;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc;AAId;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAA4B,IAAS,CAAC;AAEjE,cAAc;AACd;;;;GAIG;AACH,MAAM,UAAU,IAAI,KAAU,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,SAAS,KAAmB,CAAC","sourcesContent":["// @needsAudit\n\nimport { SplashScreenOptions } from './SplashScreen.types';\n\n/**\n * Makes the native splash screen (configured in `app.json`) remain visible until `hideAsync` is called.\n *\n * > **Important note**: It is recommended to call this in global scope without awaiting, rather than\n * > inside React components or hooks, because otherwise this might be called too late,\n * > when the splash screen is already hidden.\n *\n * @example\n * ```ts\n * import * as SplashScreen from 'expo-splash-screen';\n *\n * SplashScreen.preventAutoHideAsync();\n *\n * export default function App() {\n * // ...\n * }\n * ```\n */\nexport async function preventAutoHideAsync(): Promise<boolean> {\n return false;\n}\n\nexport function setOptions(options: SplashScreenOptions): void {}\n\n// @needsAudit\n/**\n * Hides the native splash screen immediately. Be careful to ensure that your app has content ready\n * to display when you hide the splash screen, or you may see a blank screen briefly. See the\n * [\"Usage\"](#usage) section for an example.\n */\nexport function hide(): void {}\n\nexport async function hideAsync(): Promise<void> {}\n"]}
@@ -1,3 +1,4 @@
1
+ import { SplashScreenOptions } from './SplashScreen.types';
1
2
  /**
2
3
  * Expo Router uses this internal method to ensure that we can detect if the user
3
4
  * has explicitly opted into preventing the splash screen from hiding. This means
@@ -15,6 +16,8 @@ export declare function _internal_preventAutoHideAsync(): Promise<boolean>;
15
16
  * @private
16
17
  */
17
18
  export declare const _internal_maybeHideAsync: () => void;
18
- export declare function hideAsync(): Promise<boolean | void>;
19
+ export declare function setOptions(options: SplashScreenOptions): void;
20
+ export declare function hide(): void;
21
+ export declare function hideAsync(): Promise<void>;
19
22
  export declare const preventAutoHideAsync: () => Promise<boolean>;
20
23
  //# sourceMappingURL=index.native.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.native.d.ts","sourceRoot":"","sources":["../src/index.native.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,OAAO,CAAC,CAsBvE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,YAOpC,CAAC;AAEF,wBAAgB,SAAS,4BAgBxB;AAED,eAAO,MAAM,oBAAoB,wBAKhC,CAAC"}
1
+ {"version":3,"file":"index.native.d.ts","sourceRoot":"","sources":["../src/index.native.ts"],"names":[],"mappings":"AAEA,OAAO,EAA4B,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAOrF;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,OAAO,CAAC,CAsBvE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,YAOpC,CAAC;AAEF,wBAAgB,UAAU,CAAC,OAAO,EAAE,mBAAmB,QAMtD;AAED,wBAAgB,IAAI,SAMnB;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,eAAO,MAAM,oBAAoB,wBAKhC,CAAC"}
@@ -24,7 +24,7 @@ export async function _internal_preventAutoHideAsync() {
24
24
  if (ErrorUtils?.getGlobalHandler) {
25
25
  const originalHandler = ErrorUtils.getGlobalHandler();
26
26
  ErrorUtils.setGlobalHandler((error, isFatal) => {
27
- hideAsync();
27
+ hide();
28
28
  originalHandler(error, isFatal);
29
29
  });
30
30
  }
@@ -43,22 +43,22 @@ export const _internal_maybeHideAsync = () => {
43
43
  if (_userControlledAutoHideEnabled) {
44
44
  return;
45
45
  }
46
- hideAsync();
46
+ hide();
47
47
  };
48
- export function hideAsync() {
48
+ export function setOptions(options) {
49
49
  if (!SplashModule) {
50
- return Promise.resolve(false);
50
+ return;
51
+ }
52
+ SplashModule.setOptions(options);
53
+ }
54
+ export function hide() {
55
+ if (!SplashModule) {
56
+ return;
51
57
  }
52
- return SplashModule.hideAsync().catch((error) => {
53
- // Hide this very unfortunate error.
54
- if (
55
- // Only throw the error is something unexpected happened.
56
- _preventAutoHideAsyncInvoked &&
57
- error.message.includes('No native splash screen registered for ')) {
58
- return;
59
- }
60
- throw error;
61
- });
58
+ SplashModule.hide();
59
+ }
60
+ export async function hideAsync() {
61
+ hide();
62
62
  }
63
63
  export const preventAutoHideAsync = () => {
64
64
  // Indicate that the user is controlling the auto hide behavior.
@@ -1 +1 @@
1
- {"version":3,"file":"index.native.js","sourceRoot":"","sources":["../src/index.native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAEhE,MAAM,YAAY,GAAG,2BAA2B,CAAC,kBAAkB,CAG3D,CAAC;AAET,IAAI,8BAA8B,GAAG,KAAK,CAAC;AAC3C,IAAI,4BAA4B,GAAG,KAAK,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B;IAClD,IAAI,CAAC,YAAY,EAAE;QACjB,OAAO,KAAK,CAAC;KACd;IAED,4CAA4C;IAC5C,IAAI,4BAA4B,EAAE;QAChC,OAAO,KAAK,CAAC;KACd;IACD,4BAA4B,GAAG,IAAI,CAAC;IAEpC,oGAAoG;IACpG,oEAAoE;IACpE,IAAI,UAAU,EAAE,gBAAgB,EAAE;QAChC,MAAM,eAAe,GAAG,UAAU,CAAC,gBAAgB,EAAE,CAAC;QACtD,UAAU,CAAC,gBAAgB,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC7C,SAAS,EAAE,CAAC;YACZ,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;KACJ;IAED,OAAO,YAAY,CAAC,oBAAoB,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,EAAE;IAC3C,kFAAkF;IAClF,kFAAkF;IAClF,IAAI,8BAA8B,EAAE;QAClC,OAAO;KACR;IACD,SAAS,EAAE,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,YAAY,EAAE;QACjB,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;KAC/B;IAED,OAAO,YAAY,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAU,EAAE,EAAE;QACnD,oCAAoC;QACpC;QACE,yDAAyD;QACzD,4BAA4B;YAC5B,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,yCAAyC,CAAC,EACjE;YACA,OAAO;SACR;QACD,MAAM,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,EAAE;IACvC,gEAAgE;IAChE,8BAA8B,GAAG,IAAI,CAAC;IACtC,sBAAsB;IACtB,OAAO,8BAA8B,EAAE,CAAC;AAC1C,CAAC,CAAC","sourcesContent":["import { requireOptionalNativeModule } from 'expo-modules-core';\n\nconst SplashModule = requireOptionalNativeModule('ExpoSplashScreen') as {\n preventAutoHideAsync: () => Promise<boolean>;\n hideAsync: () => Promise<boolean>;\n} | null;\n\nlet _userControlledAutoHideEnabled = false;\nlet _preventAutoHideAsyncInvoked = false;\n\n/**\n * Expo Router uses this internal method to ensure that we can detect if the user\n * has explicitly opted into preventing the splash screen from hiding. This means\n * they will also explicitly hide it. If they don't, we will hide it for them after\n * the navigation render completes.\n *\n * @private\n */\nexport async function _internal_preventAutoHideAsync(): Promise<boolean> {\n if (!SplashModule) {\n return false;\n }\n\n // Memoize, this should only be called once.\n if (_preventAutoHideAsyncInvoked) {\n return false;\n }\n _preventAutoHideAsyncInvoked = true;\n\n // Append error handling to ensure any uncaught exceptions result in the splash screen being hidden.\n // This prevents the splash screen from floating over error screens.\n if (ErrorUtils?.getGlobalHandler) {\n const originalHandler = ErrorUtils.getGlobalHandler();\n ErrorUtils.setGlobalHandler((error, isFatal) => {\n hideAsync();\n originalHandler(error, isFatal);\n });\n }\n\n return SplashModule.preventAutoHideAsync();\n}\n\n/**\n * Used for Expo libraries to attempt hiding the splash screen after they've completed their work.\n * If the user has explicitly opted into preventing the splash screen from hiding, we should not\n * hide it for them. This is often used for animated splash screens.\n *\n * @private\n */\nexport const _internal_maybeHideAsync = () => {\n // If the user has explicitly opted into preventing the splash screen from hiding,\n // we should not hide it for them. This is often used for animated splash screens.\n if (_userControlledAutoHideEnabled) {\n return;\n }\n hideAsync();\n};\n\nexport function hideAsync() {\n if (!SplashModule) {\n return Promise.resolve(false);\n }\n\n return SplashModule.hideAsync().catch((error: any) => {\n // Hide this very unfortunate error.\n if (\n // Only throw the error is something unexpected happened.\n _preventAutoHideAsyncInvoked &&\n error.message.includes('No native splash screen registered for ')\n ) {\n return;\n }\n throw error;\n });\n}\n\nexport const preventAutoHideAsync = () => {\n // Indicate that the user is controlling the auto hide behavior.\n _userControlledAutoHideEnabled = true;\n // Prevent as usual...\n return _internal_preventAutoHideAsync();\n};\n"]}
1
+ {"version":3,"file":"index.native.js","sourceRoot":"","sources":["../src/index.native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAIhE,MAAM,YAAY,GAAG,2BAA2B,CAA2B,kBAAkB,CAAC,CAAC;AAE/F,IAAI,8BAA8B,GAAG,KAAK,CAAC;AAC3C,IAAI,4BAA4B,GAAG,KAAK,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B;IAClD,IAAI,CAAC,YAAY,EAAE;QACjB,OAAO,KAAK,CAAC;KACd;IAED,4CAA4C;IAC5C,IAAI,4BAA4B,EAAE;QAChC,OAAO,KAAK,CAAC;KACd;IACD,4BAA4B,GAAG,IAAI,CAAC;IAEpC,oGAAoG;IACpG,oEAAoE;IACpE,IAAI,UAAU,EAAE,gBAAgB,EAAE;QAChC,MAAM,eAAe,GAAG,UAAU,CAAC,gBAAgB,EAAE,CAAC;QACtD,UAAU,CAAC,gBAAgB,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC7C,IAAI,EAAE,CAAC;YACP,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;KACJ;IAED,OAAO,YAAY,CAAC,oBAAoB,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,EAAE;IAC3C,kFAAkF;IAClF,kFAAkF;IAClF,IAAI,8BAA8B,EAAE;QAClC,OAAO;KACR;IACD,IAAI,EAAE,CAAC;AACT,CAAC,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,OAA4B;IACrD,IAAI,CAAC,YAAY,EAAE;QACjB,OAAO;KACR;IAED,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,IAAI,CAAC,YAAY,EAAE;QACjB,OAAO;KACR;IAED,YAAY,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,EAAE,CAAC;AACT,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,EAAE;IACvC,gEAAgE;IAChE,8BAA8B,GAAG,IAAI,CAAC;IACtC,sBAAsB;IACtB,OAAO,8BAA8B,EAAE,CAAC;AAC1C,CAAC,CAAC","sourcesContent":["import { requireOptionalNativeModule } from 'expo-modules-core';\n\nimport { SplashScreenNativeModule, SplashScreenOptions } from './SplashScreen.types';\n\nconst SplashModule = requireOptionalNativeModule<SplashScreenNativeModule>('ExpoSplashScreen');\n\nlet _userControlledAutoHideEnabled = false;\nlet _preventAutoHideAsyncInvoked = false;\n\n/**\n * Expo Router uses this internal method to ensure that we can detect if the user\n * has explicitly opted into preventing the splash screen from hiding. This means\n * they will also explicitly hide it. If they don't, we will hide it for them after\n * the navigation render completes.\n *\n * @private\n */\nexport async function _internal_preventAutoHideAsync(): Promise<boolean> {\n if (!SplashModule) {\n return false;\n }\n\n // Memoize, this should only be called once.\n if (_preventAutoHideAsyncInvoked) {\n return false;\n }\n _preventAutoHideAsyncInvoked = true;\n\n // Append error handling to ensure any uncaught exceptions result in the splash screen being hidden.\n // This prevents the splash screen from floating over error screens.\n if (ErrorUtils?.getGlobalHandler) {\n const originalHandler = ErrorUtils.getGlobalHandler();\n ErrorUtils.setGlobalHandler((error, isFatal) => {\n hide();\n originalHandler(error, isFatal);\n });\n }\n\n return SplashModule.preventAutoHideAsync();\n}\n\n/**\n * Used for Expo libraries to attempt hiding the splash screen after they've completed their work.\n * If the user has explicitly opted into preventing the splash screen from hiding, we should not\n * hide it for them. This is often used for animated splash screens.\n *\n * @private\n */\nexport const _internal_maybeHideAsync = () => {\n // If the user has explicitly opted into preventing the splash screen from hiding,\n // we should not hide it for them. This is often used for animated splash screens.\n if (_userControlledAutoHideEnabled) {\n return;\n }\n hide();\n};\n\nexport function setOptions(options: SplashScreenOptions) {\n if (!SplashModule) {\n return;\n }\n\n SplashModule.setOptions(options);\n}\n\nexport function hide() {\n if (!SplashModule) {\n return;\n }\n\n SplashModule.hide();\n}\n\nexport async function hideAsync(): Promise<void> {\n hide();\n}\n\nexport const preventAutoHideAsync = () => {\n // Indicate that the user is controlling the auto hide behavior.\n _userControlledAutoHideEnabled = true;\n // Prevent as usual...\n return _internal_preventAutoHideAsync();\n};\n"]}
@@ -1,5 +1,9 @@
1
1
  {
2
2
  "platforms": ["apple", "android"],
3
+ "apple": {
4
+ "modules": ["SplashScreenModule"],
5
+ "appDelegateSubscribers": ["SplashScreenAppDelegateSubscriber"]
6
+ },
3
7
  "android": {
4
8
  "modules": ["expo.modules.splashscreen.SplashScreenModule"]
5
9
  }
@@ -0,0 +1,35 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
4
+
5
+ new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'
6
+ new_arch_compiler_flags = '-DRCT_NEW_ARCH_ENABLED'
7
+ compiler_flags = ''
8
+
9
+ if new_arch_enabled
10
+ compiler_flags << ' ' << new_arch_compiler_flags
11
+ end
12
+
13
+ Pod::Spec.new do |s|
14
+ s.name = 'ExpoSplashScreen'
15
+ s.version = package['version']
16
+ s.summary = package['description']
17
+ s.description = package['description']
18
+ s.license = package['license']
19
+ s.author = package['author']
20
+ s.homepage = package['homepage']
21
+ s.platforms = { :ios => '15.1', :tvos => '15.1' }
22
+ s.source = { git: 'https://github.com/expo/expo.git' }
23
+ s.static_framework = true
24
+
25
+ s.dependency 'ExpoModulesCore'
26
+
27
+ # Swift/Objective-C compatibility
28
+ s.pod_target_xcconfig = {
29
+ 'DEFINES_MODULE' => 'YES',
30
+ 'SWIFT_COMPILATION_MODE' => 'wholemodule',
31
+ 'OTHER_SWIFT_FLAGS' => "$(inherited) #{new_arch_enabled ? new_arch_compiler_flags : ''}",
32
+ }
33
+
34
+ s.source_files = "**/*.{h,m,swift}"
35
+ end
@@ -0,0 +1,7 @@
1
+ import ExpoModulesCore
2
+
3
+ public class SplashScreenAppDelegateSubscriber: ExpoAppDelegateSubscriber {
4
+ public func customizeRootView(_ rootView: UIView) {
5
+ SplashScreenManager.shared.initWith(rootView)
6
+ }
7
+ }
@@ -0,0 +1,92 @@
1
+ import React
2
+ import UIKit
3
+ import ExpoModulesCore
4
+
5
+ public class SplashScreenManager: NSObject {
6
+ @objc public static let shared = SplashScreenManager()
7
+ private var loadingView: UIView?
8
+ private var rootView: UIView?
9
+ private var options = SplashScreenOptions()
10
+ public var preventAutoHideCalled = false
11
+
12
+ private override init() {}
13
+
14
+ public func initWith(_ rootView: UIView) {
15
+ if RCTRunningInAppExtension() {
16
+ return
17
+ }
18
+
19
+ self.rootView = rootView
20
+ if let vc = UIStoryboard(name: "SplashScreen", bundle: nil).instantiateInitialViewController() {
21
+ loadingView = vc.view
22
+ loadingView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
23
+
24
+ if let bounds = self.rootView?.bounds {
25
+ loadingView?.frame = bounds
26
+ loadingView?.center = CGPoint(x: bounds.midX, y: bounds.midY)
27
+ }
28
+ loadingView?.isHidden = false
29
+ #if RCT_NEW_ARCH_ENABLED
30
+ if let hostView = rootView as? RCTSurfaceHostingProxyRootView, let loadingView {
31
+ hostView.disableActivityIndicatorAutoHide(true)
32
+ hostView.loadingView = loadingView
33
+ }
34
+ #else
35
+ if let loadingView {
36
+ self.rootView?.addSubview(loadingView)
37
+ }
38
+ #endif
39
+ }
40
+
41
+ NotificationCenter.default.addObserver(self, selector: #selector(onAppReady), name: Notification.Name("RCTContentDidAppearNotification"), object: nil)
42
+ NotificationCenter.default.addObserver(self, selector: #selector(onAppReady), name: Notification.Name.RCTJavaScriptDidLoad, object: nil)
43
+ }
44
+
45
+ @objc private func onAppReady() {
46
+ if !preventAutoHideCalled {
47
+ hide()
48
+ }
49
+ }
50
+
51
+ func hide() {
52
+ if RCTRunningInAppExtension() {
53
+ return
54
+ }
55
+
56
+ DispatchQueue.main.async { [weak self] in
57
+ guard let self, let rootView, isLoadingViewVisible() else {
58
+ return
59
+ }
60
+ let duration = options.duration / 1000
61
+ if options.fade {
62
+ UIView.transition(with: rootView, duration: duration, options: .transitionCrossDissolve) {
63
+ self.loadingView?.isHidden = true
64
+ } completion: { _ in
65
+ self.loadingView?.removeFromSuperview()
66
+ self.loadingView = nil
67
+ }
68
+ } else {
69
+ loadingView?.isHidden = true
70
+ loadingView?.removeFromSuperview()
71
+ loadingView = nil
72
+ }
73
+ }
74
+ }
75
+
76
+ func setOptions(options: SplashScreenOptions) {
77
+ self.options = options
78
+ }
79
+
80
+ private func isLoadingViewVisible() -> Bool {
81
+ guard let loadingView else {
82
+ return false
83
+ }
84
+
85
+ return !loadingView.isHidden
86
+ }
87
+
88
+ func removeObservers() {
89
+ NotificationCenter.default.removeObserver(self, name: Notification.Name("RCTContentDidAppearNotification"), object: nil)
90
+ NotificationCenter.default.removeObserver(self, name: Notification.Name.RCTJavaScriptDidLoad, object: nil)
91
+ }
92
+ }
@@ -0,0 +1,27 @@
1
+ import ExpoModulesCore
2
+
3
+ public class SplashScreenModule: Module {
4
+ public func definition() -> ModuleDefinition {
5
+ Name("ExpoSplashScreen")
6
+
7
+ AsyncFunction("preventAutoHideAsync") {
8
+ SplashScreenManager.shared.preventAutoHideCalled = true
9
+ }
10
+
11
+ Function("setOptions") { (options: SplashScreenOptions) in
12
+ SplashScreenManager.shared.setOptions(options: options)
13
+ }
14
+
15
+ Function("hide") {
16
+ SplashScreenManager.shared.hide()
17
+ }
18
+
19
+ AsyncFunction("hideAsync") {
20
+ SplashScreenManager.shared.hide()
21
+ }
22
+
23
+ OnDestroy {
24
+ SplashScreenManager.shared.removeObservers()
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,6 @@
1
+ import ExpoModulesCore
2
+
3
+ internal struct SplashScreenOptions: Record {
4
+ @Field var fade: Bool = false
5
+ @Field var duration: Double = 400
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-splash-screen",
3
- "version": "0.28.5",
3
+ "version": "0.29.0",
4
4
  "description": "Provides a module to allow keeping the native Splash Screen visible until you choose to hide it.",
5
5
  "main": "build",
6
6
  "types": "build",
@@ -34,7 +34,7 @@
34
34
  "license": "MIT",
35
35
  "homepage": "https://docs.expo.dev/versions/latest/sdk/splash-screen/",
36
36
  "dependencies": {
37
- "@expo/prebuild-config": "8.0.5"
37
+ "@expo/prebuild-config": "8.0.6"
38
38
  },
39
39
  "devDependencies": {
40
40
  "expo-module-scripts": "^4.0.0"
@@ -42,5 +42,5 @@
42
42
  "peerDependencies": {
43
43
  "expo": "*"
44
44
  },
45
- "gitHead": "d5b7ec4949eb461634b2f02a1a0ff1df2a0e2a21"
45
+ "gitHead": "1f7a56b5a5bcef23ac6e55b16db53077f6a4065c"
46
46
  }
@@ -1,3 +1,12 @@
1
+ import { AndroidSplashConfig } from '@expo/prebuild-config/build/plugins/unversioned/expo-splash-screen/getAndroidSplashConfig';
2
+ import { IOSSplashConfig } from '@expo/prebuild-config/build/plugins/unversioned/expo-splash-screen/getIosSplashConfig';
1
3
  import { ConfigPlugin } from 'expo/config-plugins';
2
- declare const _default: ConfigPlugin<void>;
4
+ type PluginConfig = {
5
+ backgroundColor: string;
6
+ logoWidth: number;
7
+ image?: string | null;
8
+ android: AndroidSplashConfig;
9
+ ios: IOSSplashConfig;
10
+ };
11
+ declare const _default: ConfigPlugin<PluginConfig>;
3
12
  export default _default;
@@ -4,11 +4,21 @@ const withAndroidSplashScreen_1 = require("@expo/prebuild-config/build/plugins/u
4
4
  const withIosSplashScreen_1 = require("@expo/prebuild-config/build/plugins/unversioned/expo-splash-screen/withIosSplashScreen");
5
5
  const config_plugins_1 = require("expo/config-plugins");
6
6
  const pkg = require('expo-splash-screen/package.json');
7
- const withSplashScreen = (config) => {
8
- // For simplicity, we'll version the unversioned code in expo-splash-screen.
9
- // This adds more JS to the package overall, but the trade-off is less copying between expo-cli/expo.
10
- config = (0, withAndroidSplashScreen_1.withAndroidSplashScreen)(config);
11
- config = (0, withIosSplashScreen_1.withIosSplashScreen)(config);
7
+ const withSplashScreen = (config, props) => {
8
+ const android = {
9
+ ...config.splash,
10
+ ...config.android?.splash,
11
+ ...props,
12
+ ...props?.android,
13
+ };
14
+ const ios = {
15
+ ...config.splash,
16
+ ...config.ios?.splash,
17
+ ...props,
18
+ ...props?.ios,
19
+ };
20
+ config = (0, withAndroidSplashScreen_1.withAndroidSplashScreen)(config, android);
21
+ config = (0, withIosSplashScreen_1.withIosSplashScreen)(config, ios);
12
22
  return config;
13
23
  };
14
24
  exports.default = (0, config_plugins_1.createRunOncePlugin)(withSplashScreen, pkg.name, pkg.version);