@@ -14,6 +14,9 @@ import io.sentry.SpanStatus
1414import io.sentry.TransactionContext
1515import io.sentry.TransactionOptions
1616import 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
1720import io.sentry.protocol.App
1821import io.sentry.protocol.TransactionNameSource
1922import 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