Skip to content

Commit 0dc52a0

Browse files
committed
ref(android-nav3): Prepare back stack changes
1 parent 8996266 commit 0dc52a0

1 file changed

Lines changed: 45 additions & 33 deletions

File tree

‎sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackObserver.kt‎

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import io.sentry.SpanStatus
1414
import io.sentry.TransactionContext
1515
import io.sentry.TransactionOptions
1616
import io.sentry.TypeCheckHint
17+
import io.sentry.compose.navigation3.PreparedChange.BackStackHasNewTop
18+
import io.sentry.compose.navigation3.PreparedChange.BackStackHasSameTop
19+
import io.sentry.compose.navigation3.PreparedChange.BackStackIsEmpty
1720
import io.sentry.protocol.App
1821
import io.sentry.protocol.TransactionNameSource
1922
import io.sentry.util.ExceptionUtils
@@ -88,18 +91,8 @@ internal class BackStackObserver<T : Any>(
8891
*/
8992
internal fun onBackStackChanged(backStack: List<T>) {
9093
guard("onBackStackChanged") {
91-
val topEntry = backStack.lastOrNull()
92-
93-
val status =
94-
when {
95-
topEntry == null -> BackStackStatus.EMPTY
96-
topEntry === previousTopEntry?.get() -> BackStackStatus.SAME_TOP
97-
else -> BackStackStatus.NEW_TOP
98-
}
99-
100-
scopes.configureScope { scope ->
101-
applyBackStackChange(scope, status, backStack)
102-
}
94+
val change = prepareChange(backStack)
95+
scopes.configureScope { scope -> applyPreparedChange(scope, change) }
10396
}
10497
}
10598

@@ -124,24 +117,29 @@ internal class BackStackObserver<T : Any>(
124117
}
125118
}
126119

127-
private fun applyBackStackChange(
128-
scope: IScope,
129-
status: BackStackStatus,
130-
backStack: List<T>,
131-
) {
132-
when (status) {
133-
BackStackStatus.EMPTY -> handleEmptyBackStack(scope)
120+
private fun prepareChange(backStack: List<T>): PreparedChange<T> {
121+
val topEntry = backStack.lastOrNull() ?: return BackStackIsEmpty
122+
val data = backStack.extractData()
123+
124+
return if (topEntry === previousTopEntry?.get()) {
125+
BackStackHasSameTop(data)
126+
} else {
127+
BackStackHasNewTop(previousTopRoute, data)
128+
}
129+
}
130+
131+
private fun applyPreparedChange(scope: IScope, change: PreparedChange<T>) {
132+
when (change) {
133+
is BackStackIsEmpty -> handleEmptyBackStack(scope)
134134

135-
BackStackStatus.NEW_TOP -> {
136-
val data = backStack.extractData()
137-
handleNewTop(scope, previousTopRoute, data)
138-
storeAsPreviousTop(data.topEntry, data.topRoute)
135+
is BackStackHasNewTop -> {
136+
handleNewTop(scope, change.previousTopRoute, change.data)
137+
storeAsPreviousTop(change.data.topEntry, change.data.topRoute)
139138
}
140139

141-
BackStackStatus.SAME_TOP -> {
142-
val data = backStack.extractData()
143-
handleSameTop(scope, data)
144-
storeAsPreviousTop(data.topEntry, data.topRoute)
140+
is BackStackHasSameTop -> {
141+
handleSameTop(scope, change.data)
142+
storeAsPreviousTop(change.data.topEntry, change.data.topRoute)
145143
}
146144
}
147145
}
@@ -319,15 +317,29 @@ internal class BackStackObserver<T : Any>(
319317
}
320318
}
321319

322-
private enum class BackStackStatus {
323-
EMPTY,
320+
/**
321+
* A model for applying one back stack update.
322+
*
323+
* Lets us separate change preparation from its application so that the [IScopes.configureScope]
324+
* callback in charge of application can use already-computed navigation state. Otherwise, any
325+
* exceptions thrown during state computation would be swallowed by `configureScope`'s over-broad
326+
* `catch` clause.
327+
*/
328+
private sealed interface PreparedChange<out T : Any> {
329+
330+
/** The incoming back stack is empty. */
331+
data object BackStackIsEmpty : PreparedChange<Nothing>
332+
324333
/**
325-
* The top of the back stack has changed, and one or more entries below it may have been updated
326-
* as well.
334+
* The top of the back stack has changed, and one or more entries below it may have been updated.
327335
*/
328-
NEW_TOP,
336+
data class BackStackHasNewTop<T : Any>(
337+
val previousTopRoute: Route?,
338+
val data: BackStackData<T>,
339+
) : PreparedChange<T>
340+
329341
/** The top of the back stack is unchanged, but one or more entries below it have been updated. */
330-
SAME_TOP,
342+
data class BackStackHasSameTop<T : Any>(val data: BackStackData<T>) : PreparedChange<T>
331343
}
332344

333345
/** Info extracted from the host app's back stack in a form suitable for Sentry data. */

0 commit comments

Comments
 (0)