Skip to content

Commit e50cea7

Browse files
committed
fix(ui/navigation): prevent any recomposition on fully expanded sheet state
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent e490125 commit e50cea7

2 files changed

Lines changed: 27 additions & 13 deletions

File tree

ui/navigation/src/main/kotlin/com/getcode/navigation/core/BottomSheetNavigator.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ class BottomSheetNavigator @InternalVoyagerApi constructor(
139139
private val coroutineScope: CoroutineScope
140140
) : Stack<Screen> by navigator {
141141

142+
private var _isSheetActive by mutableStateOf(false)
143+
val isSheetActive: Boolean get() = _isSheetActive
144+
142145
val isVisible: Boolean
143146
get() = sheetState.isVisible
144147

@@ -162,6 +165,7 @@ class BottomSheetNavigator @InternalVoyagerApi constructor(
162165
replaceAll(screen)
163166
// setup stack
164167
sheetStacks.push(screen)
168+
_isSheetActive = true
165169
sheetState.show()
166170
} else {
167171
hideAndShow(screen)
@@ -177,6 +181,7 @@ class BottomSheetNavigator @InternalVoyagerApi constructor(
177181
val firstScreen = items.first()
178182
val remainingScreens = items.drop(1)
179183
sheetStacks.push(firstScreen to remainingScreens)
184+
_isSheetActive = true
180185
sheetState.show()
181186
} else {
182187
hideAndShow(screens)
@@ -189,12 +194,14 @@ class BottomSheetNavigator @InternalVoyagerApi constructor(
189194
sheetStacks.pop()
190195
// animate sheet out
191196
sheetState.hide()
197+
_isSheetActive = false
192198
// replacing w/ dummy sheet
193199
replaceAll(HiddenBottomSheetScreen)
194200
// push new stack
195201
sheetStacks.push(screen)
196202
// show new sheet
197203
replaceAll(screen)
204+
_isSheetActive = true
198205
sheetState.show()
199206
} else {
200207
Timber.e("shouldn't get here; but ensuring a sheet is shown when requested.")
@@ -208,6 +215,7 @@ class BottomSheetNavigator @InternalVoyagerApi constructor(
208215
sheetStacks.pop()
209216
// animate sheet out
210217
sheetState.hide()
218+
_isSheetActive = false
211219
// replacing w/ dummy sheet
212220
replaceAll(HiddenBottomSheetScreen)
213221
// push new stack
@@ -216,6 +224,7 @@ class BottomSheetNavigator @InternalVoyagerApi constructor(
216224
sheetStacks.push(firstScreen to remainingScreens)
217225
// show new sheet
218226
replaceAll(screens)
227+
_isSheetActive = true
219228
sheetState.show()
220229
} else {
221230
Timber.e("shouldn't get here; but ensuring a sheet is shown when requested.")
@@ -230,11 +239,13 @@ class BottomSheetNavigator @InternalVoyagerApi constructor(
230239
if (isVisible) {
231240
sheetStacks.pop()
232241
sheetState.hide()
242+
_isSheetActive = false
233243
replaceAll(HiddenBottomSheetScreen)
234244
showPreviousSheet()
235245
} else if (sheetState.targetValue == ModalBottomSheetValue.Hidden) {
236246
// Swipe down - sheetState is already hidden here so `isVisible` is false
237247
replaceAll(HiddenBottomSheetScreen)
248+
_isSheetActive = false
238249
}
239250
}
240251
}

ui/navigation/src/main/kotlin/com/getcode/navigation/core/CombinedNavigator.kt

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,22 @@ class CombinedNavigator(
2424
override var screensNavigator: Navigator? = null
2525
override var tabsNavigator: TabNavigator? = null
2626

27+
private val isSheetActive: Boolean
28+
get() = sheetNavigator.isSheetActive
29+
2730
override val lastItem: Screen?
28-
get() = if (isVisible) sheetNavigator.lastItemOrNull else screensNavigator?.lastItemOrNull
31+
get() = if (isSheetActive) sheetNavigator.lastItemOrNull else screensNavigator?.lastItemOrNull
32+
33+
override val lastEvent: StackEvent
34+
get() = if (isSheetActive) sheetNavigator.lastEvent else screensNavigator?.lastEvent
35+
?: StackEvent.Idle
2936

3037
override val lastModalItem: Screen?
3138
get() = sheetNavigator.lastItemOrNull
3239

3340
override val sheetStackRoot: Screen?
3441
get() = sheetNavigator.sheetStacks.lastItemOrNull?.first
3542

36-
override val lastEvent: StackEvent
37-
get() = if (isVisible) sheetNavigator.lastEvent else screensNavigator?.lastEvent
38-
?: StackEvent.Idle
39-
4043
override val isVisible: Boolean
4144
get() = sheetNavigator.isVisible
4245

@@ -90,7 +93,7 @@ class CombinedNavigator(
9093
trace(message = "navigating to ${item::class.java.simpleName}")
9194
launch {
9295
delay(delay)
93-
if (isVisible) {
96+
if (isSheetActive) {
9497
sheetNavigator.push(item)
9598
} else {
9699
screensNavigator?.push(item)
@@ -100,7 +103,7 @@ class CombinedNavigator(
100103

101104
override fun push(items: List<Screen>) {
102105
trace(message = "navigating to ${items.joinToString { it::class.java.simpleName }}")
103-
if (isVisible) {
106+
if (isSheetActive) {
104107
sheetNavigator.push(items)
105108
} else {
106109
screensNavigator?.push(items)
@@ -126,7 +129,7 @@ class CombinedNavigator(
126129
}
127130

128131
override fun isAtRoot(): Boolean {
129-
return if (isVisible) {
132+
return if (isSheetActive) {
130133
sheetNavigator.items.count() == 1
131134
} else {
132135
screensNavigator?.items?.count() == 1
@@ -135,15 +138,15 @@ class CombinedNavigator(
135138

136139
override fun pop(): Boolean {
137140
trace(message = "popping from back stack")
138-
return if (isVisible) {
141+
return if (isSheetActive) {
139142
sheetNavigator.pop()
140143
} else {
141144
screensNavigator?.pop() ?: false
142145
}
143146
}
144147

145148
override fun <T> popWithResult(result: T): Boolean {
146-
return if (isVisible) {
149+
return if (isSheetActive) {
147150
with(sheetNavigator) {
148151
val prev = if (size < 2) null else items[items.size - 2] as? AppScreen
149152
prev?.onResult(result)
@@ -170,15 +173,15 @@ class CombinedNavigator(
170173

171174
override fun popAll() {
172175
trace(message = "popping all from back stack")
173-
if (isVisible) {
176+
if (isSheetActive) {
174177
sheetNavigator.popAll()
175178
} else {
176179
screensNavigator?.popAll()
177180
}
178181
}
179182

180183
override fun popUntil(predicate: (Screen) -> Boolean): Boolean {
181-
return if (isVisible) {
184+
return if (isSheetActive) {
182185
sheetNavigator.popUntil(predicate)
183186
} else {
184187
screensNavigator?.popUntil(predicate) == true
@@ -191,7 +194,7 @@ class CombinedNavigator(
191194
screen: Screen?,
192195
content: @Composable () -> Unit
193196
) {
194-
if (isVisible) {
197+
if (isSheetActive) {
195198
sheetNavigator.saveableState(key, screen = screen, content = content)
196199
} else {
197200
val lastScreen by remember(screen) {

0 commit comments

Comments
 (0)