@lodev09/react-native-true-sheet 3.7.1 → 3.7.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.
@@ -3,7 +3,6 @@ package com.lodev09.truesheet
3
3
  import android.annotation.SuppressLint
4
4
  import android.view.View
5
5
  import android.view.ViewGroup
6
- import android.view.ViewStructure
7
6
  import android.view.accessibility.AccessibilityEvent
8
7
  import androidx.annotation.UiThread
9
8
  import com.facebook.react.bridge.LifecycleEventListener
@@ -32,10 +31,6 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
32
31
  TrueSheetViewControllerDelegate,
33
32
  TrueSheetContainerViewDelegate {
34
33
 
35
- companion object {
36
- const val TAG_NAME = "TrueSheet"
37
- }
38
-
39
34
  // ==================== Properties ====================
40
35
 
41
36
  internal val viewController: TrueSheetViewController = TrueSheetViewController(reactContext)
@@ -200,7 +195,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
200
195
  if (viewController.dimmed == dimmed) return
201
196
  viewController.dimmed = dimmed
202
197
  if (viewController.isPresented) {
203
- viewController.setupDimmedBackground(viewController.currentDetentIndex)
198
+ viewController.setupDimmedBackground()
204
199
  viewController.updateDimAmount()
205
200
  }
206
201
  }
@@ -209,7 +204,7 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
209
204
  if (viewController.dimmedDetentIndex == index) return
210
205
  viewController.dimmedDetentIndex = index
211
206
  if (viewController.isPresented) {
212
- viewController.setupDimmedBackground(viewController.currentDetentIndex)
207
+ viewController.setupDimmedBackground()
213
208
  viewController.updateDimAmount()
214
209
  }
215
210
  }
@@ -492,6 +487,10 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
492
487
  dismissAll(animated = true) {}
493
488
  }
494
489
 
490
+ override fun viewControllerDidDetectScreenDismiss() {
491
+ resetTranslation()
492
+ }
493
+
495
494
  // ==================== TrueSheetContainerViewDelegate ====================
496
495
 
497
496
  override fun containerViewContentDidChangeSize(width: Int, height: Int) {
@@ -1,7 +1,6 @@
1
1
  package com.lodev09.truesheet
2
2
 
3
3
  import android.annotation.SuppressLint
4
- import android.graphics.Bitmap
5
4
  import android.graphics.Canvas
6
5
  import android.os.Build
7
6
  import android.view.MotionEvent
@@ -11,10 +10,8 @@ import android.view.accessibility.AccessibilityNodeInfo
11
10
  import android.widget.ImageView
12
11
  import androidx.activity.OnBackPressedCallback
13
12
  import androidx.appcompat.app.AppCompatActivity
14
- import androidx.coordinatorlayout.widget.CoordinatorLayout
15
13
  import androidx.core.graphics.createBitmap
16
14
  import androidx.core.view.isNotEmpty
17
- import androidx.core.view.isVisible
18
15
  import com.facebook.react.R
19
16
  import com.facebook.react.uimanager.JSPointerDispatcher
20
17
  import com.facebook.react.uimanager.JSTouchDispatcher
@@ -67,6 +64,7 @@ interface TrueSheetViewControllerDelegate {
67
64
  fun viewControllerDidBlur()
68
65
  fun viewControllerDidBackPress()
69
66
  fun viewControllerDidDetectScreenDisappear()
67
+ fun viewControllerDidDetectScreenDismiss()
70
68
  }
71
69
 
72
70
  // =============================================================================
@@ -90,8 +88,6 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
90
88
  TrueSheetBottomSheetViewDelegate {
91
89
 
92
90
  companion object {
93
- const val TAG_NAME = "TrueSheet"
94
-
95
91
  private const val DEFAULT_MAX_WIDTH = 640 // dp
96
92
  private const val DEFAULT_CORNER_RADIUS = 16 // dp
97
93
  private const val TRANSLATE_ANIMATION_DURATION = 200L
@@ -234,11 +230,15 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
234
230
  get() = ScreenUtils.getRealScreenHeight(reactContext)
235
231
 
236
232
  // Content Measurements
233
+ // Cached values used during dismiss when container is unmounted
234
+ private var cachedContentHeight: Int = 0
235
+ private var cachedHeaderHeight: Int = 0
236
+
237
237
  override val contentHeight: Int
238
- get() = containerView?.contentHeight ?: 0
238
+ get() = containerView?.contentHeight ?: cachedContentHeight
239
239
 
240
240
  override val headerHeight: Int
241
- get() = containerView?.headerHeight ?: 0
241
+ get() = containerView?.headerHeight ?: cachedHeaderHeight
242
242
 
243
243
  // Insets
244
244
  // Target keyboard height used for detent calculations
@@ -266,9 +266,10 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
266
266
  override val contentBottomInset: Int
267
267
  get() = if (insetAdjustment == "automatic") bottomInset else 0
268
268
 
269
+ @Suppress("KotlinConstantConditions", "SimplifyBooleanWithConstants")
269
270
  private val edgeToEdgeEnabled: Boolean
270
271
  get() {
271
- val defaultEnabled = android.os.Build.VERSION.SDK_INT >= 36
272
+ val defaultEnabled = Build.VERSION.SDK_INT >= 36
272
273
  return BuildConfig.EDGE_TO_EDGE_ENABLED || defaultEnabled
273
274
  }
274
275
 
@@ -340,6 +341,8 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
340
341
  isPresented = false
341
342
  isSheetVisible = false
342
343
  wasHiddenByModal = false
344
+ cachedContentHeight = 0
345
+ cachedHeaderHeight = 0
343
346
  isPresentAnimating = false
344
347
  lastEmittedPositionPx = -1
345
348
  detentIndexBeforeKeyboard = -1
@@ -539,7 +542,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
539
542
 
540
543
  if (detentInfo.index != currentDetentIndex) {
541
544
  currentDetentIndex = detentInfo.index
542
- setupDimmedBackground(detentInfo.index)
545
+ setupDimmedBackground()
543
546
  delegate?.viewControllerDidChangeDetent(detentInfo.index, detentInfo.position, detent)
544
547
  }
545
548
 
@@ -574,6 +577,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
574
577
  onModalWillDismiss = {
575
578
  if (isPresented && wasHiddenByModal && isTopmostSheet) {
576
579
  showAfterModal()
580
+ delegate?.viewControllerDidDetectScreenDismiss()
577
581
  }
578
582
  },
579
583
  onModalDidDismiss = {
@@ -659,7 +663,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
659
663
  }
660
664
 
661
665
  if (isPresented) {
662
- setupDimmedBackground(detentIndex)
666
+ setupDimmedBackground()
663
667
  setStateForDetentIndex(detentIndex)
664
668
  } else {
665
669
  shouldAnimatePresent = animated
@@ -672,7 +676,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
672
676
  emitWillPresentEvents()
673
677
 
674
678
  setupSheetDetents()
675
- setupDimmedBackground(currentDetentIndex)
679
+ setupDimmedBackground()
676
680
  setupKeyboardObserver()
677
681
  setupModalObserver()
678
682
  setupBackCallback()
@@ -703,6 +707,8 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
703
707
 
704
708
  // Create layout params with behavior
705
709
  val params = sheet.createLayoutParams()
710
+
711
+ @Suppress("UNCHECKED_CAST")
706
712
  val behavior = params.behavior as BottomSheetBehavior<TrueSheetBottomSheetView>
707
713
 
708
714
  // Configure behavior
@@ -786,6 +792,11 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
786
792
  return
787
793
  }
788
794
 
795
+ containerView?.let {
796
+ cachedContentHeight = it.contentHeight
797
+ cachedHeaderHeight = it.headerHeight
798
+ }
799
+
789
800
  interactionState = InteractionState.Reconfiguring
790
801
 
791
802
  behavior.isFitToContents = false
@@ -857,7 +868,7 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
857
868
  // MARK: - Dimmed Background
858
869
  // =============================================================================
859
870
 
860
- fun setupDimmedBackground(detentIndex: Int) {
871
+ fun setupDimmedBackground() {
861
872
  val coordinator = this.coordinatorLayout ?: run {
862
873
  RNLog.e(reactContext, "TrueSheet: coordinatorLayout is null in setupDimmedBackground")
863
874
  return
@@ -896,6 +907,8 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
896
907
 
897
908
  fun updateDimAmount(sheetTop: Int? = null, animated: Boolean = false) {
898
909
  if (!dimmed) return
910
+ if (contentHeight == 0) return
911
+
899
912
  val keyboardOffset = if (isDismissing) 0 else currentKeyboardInset
900
913
  val top = (sheetTop ?: sheetView?.top ?: return) + keyboardOffset
901
914
 
@@ -26,6 +26,7 @@ class RNScreensFragmentObserver(
26
26
  private val activeModalFragments: MutableSet<Fragment> = mutableSetOf()
27
27
  private var isActivityInForeground = true
28
28
  private var pendingDismissRunnable: Runnable? = null
29
+ private var isInitialized = false
29
30
 
30
31
  /**
31
32
  * Start observing fragment lifecycle events.
@@ -53,6 +54,9 @@ class RNScreensFragmentObserver(
53
54
  // Ignore if app is resuming from background
54
55
  if (!isActivityInForeground) return
55
56
 
57
+ // Ignore initial fragment attachments during app startup (cold start deep links)
58
+ if (!isInitialized) return
59
+
56
60
  if (isModalFragment(f) && !activeModalFragments.contains(f)) {
57
61
  // Cancel any pending dismiss since a modal is being presented
58
62
  cancelPendingDismiss()
@@ -95,6 +99,11 @@ class RNScreensFragmentObserver(
95
99
  }
96
100
 
97
101
  fragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallback!!, true)
102
+
103
+ // Mark as initialized after a frame to ignore initial fragment attachments during cold start
104
+ activity.window?.decorView?.post {
105
+ isInitialized = true
106
+ }
98
107
  }
99
108
 
100
109
  /**
@@ -18,16 +18,16 @@ object TrueSheetStackManager {
18
18
  */
19
19
  private fun getParentSheetAt(index: Int, rootContainer: ViewGroup?): TrueSheetView? {
20
20
  if (index <= 0) return null
21
- return presentedSheetStack[index - 1].takeIf { !it.viewController.wasHiddenByModal && it.rootContainerView == rootContainer }
21
+ return presentedSheetStack[index - 1].takeIf { it.rootContainerView == rootContainer }
22
22
  }
23
23
 
24
24
  /**
25
- * Returns the topmost presented and visible sheet that is not hidden by modal.
25
+ * Returns the topmost presented and visible sheet.
26
26
  * Must be called within synchronized block.
27
27
  */
28
28
  private fun findTopmostSheet(): TrueSheetView? =
29
29
  presentedSheetStack.lastOrNull {
30
- it.viewController.isPresented && it.viewController.isSheetVisible && !it.viewController.wasHiddenByModal
30
+ it.viewController.isPresented && it.viewController.isSheetVisible
31
31
  }
32
32
 
33
33
  /**
@@ -19,7 +19,6 @@
19
19
  #import "events/TrueSheetLifecycleEvents.h"
20
20
  #import "events/TrueSheetStateEvents.h"
21
21
  #import "utils/LayoutUtil.h"
22
- #import "utils/WindowUtil.h"
23
22
 
24
23
  #import <react/renderer/components/TrueSheetSpec/EventEmitters.h>
25
24
  #import <react/renderer/components/TrueSheetSpec/Props.h>
@@ -91,8 +90,16 @@ using namespace facebook::react;
91
90
  }
92
91
 
93
92
  if (_initialDetentIndex >= 0 && !_didInitiallyPresent) {
94
- _didInitiallyPresent = YES;
95
- [self presentAtIndex:_initialDetentIndex animated:_initialDetentAnimated completion:nil];
93
+ UIViewController *vc = [self findPresentingViewController];
94
+
95
+ // Only present if the view controller is in the same window and not being dismissed
96
+ if (vc && vc.view.window == self.window && !vc.isBeingDismissed) {
97
+ _didInitiallyPresent = YES;
98
+ [self presentAtIndex:_initialDetentIndex animated:_initialDetentAnimated completion:nil];
99
+ } else {
100
+ // Animate next time when sheet finally moves to the correct window
101
+ _initialDetentAnimated = YES;
102
+ }
96
103
  }
97
104
  }
98
105
 
@@ -106,6 +113,8 @@ using namespace facebook::react;
106
113
  [root dismissViewControllerAnimated:YES completion:nil];
107
114
  }
108
115
 
116
+ _didInitiallyPresent = NO;
117
+
109
118
  _controller.delegate = nil;
110
119
  _controller = nil;
111
120
 
@@ -551,11 +560,10 @@ using namespace facebook::react;
551
560
  #pragma mark - Private Helpers
552
561
 
553
562
  - (UIViewController *)findPresentingViewController {
554
- UIWindow *keyWindow = [WindowUtil keyWindow];
555
- if (!keyWindow)
563
+ if (!self.window)
556
564
  return nil;
557
565
 
558
- UIViewController *rootViewController = keyWindow.rootViewController;
566
+ UIViewController *rootViewController = self.window.rootViewController;
559
567
  if (!rootViewController)
560
568
  return nil;
561
569
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodev09/react-native-true-sheet",
3
- "version": "3.7.1",
3
+ "version": "3.7.3",
4
4
  "description": "The true native bottom sheet experience for your React Native Apps.",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./lib/module/index.js",