@lodev09/react-native-true-sheet 3.5.1-beta.5 → 3.5.2

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.
@@ -309,13 +309,15 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
309
309
  // ==================== Sheet Stack Translation ====================
310
310
 
311
311
  /**
312
- * Updates this sheet's translation based on its child sheet's position.
313
- * When a child sheet is presented, parent sheets slide down to create a stacked appearance.
312
+ * Updates this sheet's translation and disables dragging when a child sheet is presented.
313
+ * Parent sheets slide down to create a stacked appearance.
314
314
  * Propagates additional translation to parent so the entire stack stays visually consistent.
315
315
  */
316
316
  fun updateTranslationForChild(childSheetTop: Int) {
317
317
  if (!viewController.isSheetVisible || viewController.isExpanded) return
318
318
 
319
+ viewController.sheetView?.behavior?.isDraggable = false
320
+
319
321
  val mySheetTop = viewController.detentCalculator.getSheetTopForDetentIndex(viewController.currentDetentIndex)
320
322
  val newTranslation = maxOf(0, childSheetTop - mySheetTop)
321
323
  val additionalTranslation = newTranslation - viewController.currentTranslationY
@@ -332,17 +334,18 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
332
334
  * Recursively adds translation to this sheet and all parent sheets.
333
335
  */
334
336
  private fun addTranslation(amount: Int) {
335
- if (!viewController.isSheetVisible || viewController.isExpanded) return
337
+ if (viewController.isExpanded) return
336
338
 
337
339
  viewController.translateSheet(viewController.currentTranslationY + amount)
338
340
  TrueSheetStackManager.getParentSheet(this)?.addTranslation(amount)
339
341
  }
340
342
 
341
343
  /**
342
- * Resets this sheet's translation and updates parent sheets.
343
- * This sheet resets to 0 (it's now topmost), but parent recalculates based on this sheet's position.
344
+ * Resets this sheet's translation and restores dragging when it becomes topmost.
345
+ * Parent recalculates its translation based on this sheet's position.
344
346
  */
345
347
  fun resetTranslation() {
348
+ viewController.sheetView?.behavior?.isDraggable = viewController.draggable
346
349
  viewController.translateSheet(0)
347
350
 
348
351
  // Parent should recalculate its translation based on this sheet's position
@@ -534,24 +534,25 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
534
534
  }
535
535
 
536
536
  private fun hideForModal() {
537
- isSheetVisible = false
538
- wasHiddenByModal = true
539
-
540
537
  val sheet = sheetView ?: run {
541
- setSheetVisibility(false)
542
- parentSheetView?.viewController?.hideForModal()
538
+ RNLog.e(reactContext, "TrueSheet: sheetView is null in hideForModal")
543
539
  return
544
540
  }
545
541
 
542
+ isSheetVisible = false
543
+ wasHiddenByModal = true
544
+
546
545
  dimViews.forEach { it.animate().alpha(0f).setDuration(MODAL_FADE_DURATION).start() }
547
546
  sheet.animate()
548
547
  .alpha(0f)
549
548
  .setDuration(MODAL_FADE_DURATION)
550
549
  .withEndAction {
551
550
  setSheetVisibility(false)
552
- parentSheetView?.viewController?.hideForModal()
553
551
  }
554
552
  .start()
553
+
554
+ // This will hide parent sheets first
555
+ parentSheetView?.viewController?.hideForModal()
555
556
  }
556
557
 
557
558
  private fun showAfterModal() {
@@ -24,6 +24,7 @@ class RNScreensFragmentObserver(
24
24
  private var activityLifecycleObserver: DefaultLifecycleObserver? = null
25
25
  private val activeModalFragments: MutableSet<Fragment> = mutableSetOf()
26
26
  private var isActivityInForeground = true
27
+ private var pendingDismissRunnable: Runnable? = null
27
28
 
28
29
  /**
29
30
  * Start observing fragment lifecycle events.
@@ -52,6 +53,9 @@ class RNScreensFragmentObserver(
52
53
  if (!isActivityInForeground) return
53
54
 
54
55
  if (isModalFragment(f) && !activeModalFragments.contains(f)) {
56
+ // Cancel any pending dismiss since a modal is being presented
57
+ cancelPendingDismiss()
58
+
55
59
  activeModalFragments.add(f)
56
60
 
57
61
  if (activeModalFragments.size == 1) {
@@ -71,7 +75,8 @@ class RNScreensFragmentObserver(
71
75
  activeModalFragments.remove(f)
72
76
 
73
77
  if (activeModalFragments.isEmpty()) {
74
- onModalWillDismiss()
78
+ // Post dismiss to allow fragment attach to cancel if navigation is happening
79
+ schedulePendingDismiss()
75
80
  }
76
81
  }
77
82
  }
@@ -79,7 +84,7 @@ class RNScreensFragmentObserver(
79
84
  override fun onFragmentDestroyed(fm: FragmentManager, f: Fragment) {
80
85
  super.onFragmentDestroyed(fm, f)
81
86
 
82
- if (activeModalFragments.isEmpty()) {
87
+ if (activeModalFragments.isEmpty() && pendingDismissRunnable == null) {
83
88
  onModalDidDismiss()
84
89
  }
85
90
  }
@@ -94,6 +99,8 @@ class RNScreensFragmentObserver(
94
99
  fun stop() {
95
100
  val activity = reactContext.currentActivity as? AppCompatActivity
96
101
 
102
+ cancelPendingDismiss()
103
+
97
104
  fragmentLifecycleCallback?.let { callback ->
98
105
  activity?.supportFragmentManager?.unregisterFragmentLifecycleCallbacks(callback)
99
106
  }
@@ -107,6 +114,31 @@ class RNScreensFragmentObserver(
107
114
  activeModalFragments.clear()
108
115
  }
109
116
 
117
+ private fun schedulePendingDismiss() {
118
+ val activity = reactContext.currentActivity ?: return
119
+ val decorView = activity.window?.decorView ?: return
120
+
121
+ cancelPendingDismiss()
122
+
123
+ pendingDismissRunnable = Runnable {
124
+ pendingDismissRunnable = null
125
+ if (activeModalFragments.isEmpty()) {
126
+ onModalWillDismiss()
127
+ }
128
+ }
129
+ decorView.post(pendingDismissRunnable)
130
+ }
131
+
132
+ private fun cancelPendingDismiss() {
133
+ val activity = reactContext.currentActivity ?: return
134
+ val decorView = activity.window?.decorView ?: return
135
+
136
+ pendingDismissRunnable?.let {
137
+ decorView.removeCallbacks(it)
138
+ pendingDismissRunnable = null
139
+ }
140
+ }
141
+
110
142
  companion object {
111
143
  /**
112
144
  * Check if fragment is from react-native-screens.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodev09/react-native-true-sheet",
3
- "version": "3.5.1-beta.5",
3
+ "version": "3.5.2",
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",