@@ -23,6 +23,7 @@ import androidx.compose.material3.CardDefaults
2323import androidx.compose.material3.ExperimentalMaterial3Api
2424import androidx.compose.material3.MaterialTheme
2525import androidx.compose.material3.ModalBottomSheet
26+ import androidx.compose.material3.Surface
2627import androidx.compose.material3.Text
2728import androidx.compose.material3.TextButton
2829import androidx.compose.runtime.Composable
@@ -123,127 +124,129 @@ internal fun Nav2ComposeApp(
123124 routeWorkOptions = routeWorkOptions,
124125 )
125126
126- Column (modifier = Modifier .fillMaxSize().background(MaterialTheme .colorScheme.background)) {
127- NavHost (
128- navController = navController,
129- startDestination = Home .route,
130- modifier = Modifier .weight(1f ),
131- ) {
132- composable(Home .route) {
133- TracedNav2ComposeRoute (Home .routeName) {
134- Nav2ComposeHomeRoute (routeSpec = Nav2RouteSpecs .home) { navigateTo(ProductList ) }
127+ Surface (modifier = Modifier .fillMaxSize(), color = MaterialTheme .colorScheme.background) {
128+ Column (modifier = Modifier .fillMaxSize()) {
129+ NavHost (
130+ navController = navController,
131+ startDestination = Home .route,
132+ modifier = Modifier .weight(1f ),
133+ ) {
134+ composable(Home .route) {
135+ TracedNav2ComposeRoute (Home .routeName) {
136+ Nav2ComposeHomeRoute (routeSpec = Nav2RouteSpecs .home) { navigateTo(ProductList ) }
137+ }
135138 }
136- }
137139
138- composable(ProductList .route) {
139- TracedNav2ComposeRoute (ProductList .routeName) {
140- Nav2ComposeProductListRoute (
141- routeSpec = Nav2RouteSpecs .productList,
142- onOpenProduct42 = {
143- navigateTo(
144- ProductDetail (
145- productId = " 42" ,
146- source = " product-list" ,
147- campaign = " summer-sale" ,
140+ composable(ProductList .route) {
141+ TracedNav2ComposeRoute (ProductList .routeName) {
142+ Nav2ComposeProductListRoute (
143+ routeSpec = Nav2RouteSpecs .productList,
144+ onOpenProduct42 = {
145+ navigateTo(
146+ ProductDetail (
147+ productId = " 42" ,
148+ source = " product-list" ,
149+ campaign = " summer-sale" ,
150+ )
148151 )
149- )
150- },
151- onOpenProduct7 = {
152- navigateTo( ProductDetail (productId = " 7 " , source = " product-list " ))
153- },
154- )
152+ },
153+ onOpenProduct7 = {
154+ navigateTo( ProductDetail (productId = " 7 " , source = " product-list " ))
155+ },
156+ )
157+ }
155158 }
156- }
157159
158- composable(
159- route = Nav2ComposeDestination .PRODUCT_DETAIL_ROUTE ,
160- arguments =
161- listOf (
162- navArgument(Nav2Args .PRODUCT_ID ) { type = NavType .StringType },
163- navArgument(Nav2Args .SOURCE ) { type = NavType .StringType },
164- navArgument(Nav2Args .CAMPAIGN ) {
165- type = NavType .StringType
166- defaultValue = " "
167- },
168- ),
169- ) { entry ->
170- val productId = entry.arguments?.getString(Nav2Args .PRODUCT_ID ).orEmpty()
171- val source = entry.arguments?.getString(Nav2Args .SOURCE ).orEmpty()
172- val campaign = entry.arguments?.getString(Nav2Args .CAMPAIGN ).orEmpty()
173- TracedNav2ComposeRoute (Nav2RouteNames .PRODUCT_DETAIL ) {
174- Nav2ComposeProductDetailRoute (
175- routeSpec = Nav2RouteSpecs .productDetail,
176- productId = productId,
177- source = source,
178- campaign = campaign,
179- onShowPromoDialog = {
180- navigateTo(PromoDialog (" detail-$productId " ))
181- },
182- onOpenShareSheet = { openShareSheet(productId) },
183- onCheckout = { navigateTo(Checkout (productId)) },
184- )
160+ composable(
161+ route = Nav2ComposeDestination .PRODUCT_DETAIL_ROUTE ,
162+ arguments =
163+ listOf (
164+ navArgument(Nav2Args .PRODUCT_ID ) { type = NavType .StringType },
165+ navArgument(Nav2Args .SOURCE ) { type = NavType .StringType },
166+ navArgument(Nav2Args .CAMPAIGN ) {
167+ type = NavType .StringType
168+ defaultValue = " "
169+ },
170+ ),
171+ ) { entry ->
172+ val productId = entry.arguments?.getString(Nav2Args .PRODUCT_ID ).orEmpty()
173+ val source = entry.arguments?.getString(Nav2Args .SOURCE ).orEmpty()
174+ val campaign = entry.arguments?.getString(Nav2Args .CAMPAIGN ).orEmpty()
175+ TracedNav2ComposeRoute (Nav2RouteNames .PRODUCT_DETAIL ) {
176+ Nav2ComposeProductDetailRoute (
177+ routeSpec = Nav2RouteSpecs .productDetail,
178+ productId = productId,
179+ source = source,
180+ campaign = campaign,
181+ onShowPromoDialog = {
182+ navigateTo(PromoDialog (" detail-$productId " ))
183+ },
184+ onOpenShareSheet = { openShareSheet(productId) },
185+ onCheckout = { navigateTo(Checkout (productId)) },
186+ )
187+ }
185188 }
186- }
187189
188- composable(
189- route = Nav2ComposeDestination .CHECKOUT_ROUTE ,
190- arguments = listOf (navArgument(Nav2Args .PRODUCT_ID ) { type = NavType .StringType }),
191- ) { entry ->
192- val productId = entry.arguments?.getString(Nav2Args .PRODUCT_ID ).orEmpty()
193- TracedNav2ComposeRoute (Nav2RouteNames .CHECKOUT ) {
194- Nav2ComposeCheckoutRoute (
195- routeSpec = Nav2RouteSpecs .checkout,
196- productId = productId,
197- onCompleteOrder = {
198- navigateTo(Confirmation (orderId = " order-$productId " ))
199- },
200- )
190+ composable(
191+ route = Nav2ComposeDestination .CHECKOUT_ROUTE ,
192+ arguments = listOf (navArgument(Nav2Args .PRODUCT_ID ) { type = NavType .StringType }),
193+ ) { entry ->
194+ val productId = entry.arguments?.getString(Nav2Args .PRODUCT_ID ).orEmpty()
195+ TracedNav2ComposeRoute (Nav2RouteNames .CHECKOUT ) {
196+ Nav2ComposeCheckoutRoute (
197+ routeSpec = Nav2RouteSpecs .checkout,
198+ productId = productId,
199+ onCompleteOrder = {
200+ navigateTo(Confirmation (orderId = " order-$productId " ))
201+ },
202+ )
203+ }
201204 }
202- }
203205
204- composable(
205- route = Nav2ComposeDestination .CONFIRMATION_ROUTE ,
206- arguments = listOf (navArgument(Nav2Args .ORDER_ID ) { type = NavType .StringType }),
207- ) { entry ->
208- TracedNav2ComposeRoute (Nav2RouteNames .CONFIRMATION ) {
209- Nav2ComposeConfirmationRoute (
210- routeSpec = Nav2RouteSpecs .confirmation,
211- orderId = entry.arguments?.getString(Nav2Args .ORDER_ID ).orEmpty(),
212- onResetBackStack = { resetToHome() },
213- )
206+ composable(
207+ route = Nav2ComposeDestination .CONFIRMATION_ROUTE ,
208+ arguments = listOf (navArgument(Nav2Args .ORDER_ID ) { type = NavType .StringType }),
209+ ) { entry ->
210+ TracedNav2ComposeRoute (Nav2RouteNames .CONFIRMATION ) {
211+ Nav2ComposeConfirmationRoute (
212+ routeSpec = Nav2RouteSpecs .confirmation,
213+ orderId = entry.arguments?.getString(Nav2Args .ORDER_ID ).orEmpty(),
214+ onResetBackStack = { resetToHome() },
215+ )
216+ }
214217 }
215- }
216218
217- dialog(
218- route = Nav2ComposeDestination .PROMO_DIALOG_ROUTE ,
219- arguments = listOf (navArgument(Nav2Args .PROMO_ID ) { type = NavType .StringType }),
220- ) { entry ->
221- // This dialog is a real Nav destination, so it participates in Nav2 the same way as the
222- // rest of the route graph. Compare it with the share sheet overlay below when inspecting
223- // Sentry's Nav2 breadcrumbs, destination arguments, and route transactions.
224- TracedNav2ComposeRoute (Nav2RouteNames .PROMO_DIALOG ) {
225- Nav2ComposePromoDialogRoute (
226- routeSpec = Nav2RouteSpecs .promoDialog,
227- promoId = entry.arguments?.getString(Nav2Args .PROMO_ID ).orEmpty(),
228- onCaptureException = onCaptureException,
229- onCrashApp = onCrashApp,
230- onDismiss = { navigateBack() },
231- )
219+ dialog(
220+ route = Nav2ComposeDestination .PROMO_DIALOG_ROUTE ,
221+ arguments = listOf (navArgument(Nav2Args .PROMO_ID ) { type = NavType .StringType }),
222+ ) { entry ->
223+ // This dialog is a real Nav destination, so it participates in Nav2 the same way as the
224+ // rest of the route graph. Compare it with the share sheet overlay below when inspecting
225+ // Sentry's Nav2 breadcrumbs, destination arguments, and route transactions.
226+ TracedNav2ComposeRoute (Nav2RouteNames .PROMO_DIALOG ) {
227+ Nav2ComposePromoDialogRoute (
228+ routeSpec = Nav2RouteSpecs .promoDialog,
229+ promoId = entry.arguments?.getString(Nav2Args .PROMO_ID ).orEmpty(),
230+ onCaptureException = onCaptureException,
231+ onCrashApp = onCrashApp,
232+ onDismiss = { navigateBack() },
233+ )
234+ }
232235 }
233236 }
234- }
235237
236- shareSheetProductId.value?.let { productId ->
237- // This share sheet is intentionally just a screen overlay, not a Nav destination. It lets
238- // the sample compare how Sentry's Nav2 integration behaves for proper Nav destinations vs.
239- // UI layered on top of the current route.
240- Nav2ComposeShareSheetRoute (
241- routeSpec = Nav2RouteSpecs .shareSheet,
242- productId = productId,
243- onCaptureException = onCaptureException,
244- onCrashApp = onCrashApp,
245- onDone = ::dismissShareSheet,
246- )
238+ shareSheetProductId.value?.let { productId ->
239+ // This share sheet is intentionally just a screen overlay, not a Nav destination. It lets
240+ // the sample compare how Sentry's Nav2 integration behaves for proper Nav destinations vs.
241+ // UI layered on top of the current route.
242+ Nav2ComposeShareSheetRoute (
243+ routeSpec = Nav2RouteSpecs .shareSheet,
244+ productId = productId,
245+ onCaptureException = onCaptureException,
246+ onCrashApp = onCrashApp,
247+ onDone = ::dismissShareSheet,
248+ )
249+ }
247250 }
248251 }
249252}
@@ -528,30 +531,33 @@ private fun Nav2ComposeRouteScaffold(
528531 cardContent : (@Composable ColumnScope .() -> Unit )? = null,
529532 content : (@Composable ColumnScope .() -> Unit )? = null,
530533) {
531- Column (
532- modifier = Modifier .fillMaxSize().verticalScroll(rememberScrollState()).padding(16 .dp),
533- verticalArrangement = Arrangement .spacedBy(12 .dp),
534- ) {
535- Text (
536- routeSpec.title,
537- style = MaterialTheme .typography.headlineMedium,
538- fontWeight = FontWeight .Bold ,
539- )
540- routeSpec.description?.let { Text (it, style = MaterialTheme .typography.bodyMedium) }
541- if (cardContent != null ) {
542- Card (
543- colors = CardDefaults .cardColors(containerColor = MaterialTheme .colorScheme.surfaceVariant),
544- modifier = Modifier .fillMaxWidth(),
545- ) {
546- Column (
547- modifier = Modifier .padding(16 .dp),
548- verticalArrangement = Arrangement .spacedBy(8 .dp),
534+ Surface (modifier = Modifier .fillMaxSize(), color = MaterialTheme .colorScheme.background) {
535+ Column (
536+ modifier = Modifier .verticalScroll(rememberScrollState()).padding(16 .dp),
537+ verticalArrangement = Arrangement .spacedBy(12 .dp),
538+ ) {
539+ Text (
540+ routeSpec.title,
541+ style = MaterialTheme .typography.headlineMedium,
542+ fontWeight = FontWeight .Bold ,
543+ )
544+ routeSpec.description?.let { Text (it, style = MaterialTheme .typography.bodyMedium) }
545+ if (cardContent != null ) {
546+ Card (
547+ colors =
548+ CardDefaults .cardColors(containerColor = MaterialTheme .colorScheme.surfaceVariant),
549+ modifier = Modifier .fillMaxWidth(),
549550 ) {
550- cardContent()
551+ Column (
552+ modifier = Modifier .padding(16 .dp),
553+ verticalArrangement = Arrangement .spacedBy(8 .dp),
554+ ) {
555+ cardContent()
556+ }
551557 }
552558 }
559+ content?.invoke(this )
553560 }
554- content?.invoke(this )
555561 }
556562}
557563
@@ -599,16 +605,19 @@ private const val PRODUCT_LIST_ITEM_COUNT = 20
599605
600606@Composable
601607private fun Nav2ComposeRouteInfo (label : String , value : String ) {
602- Row (
603- modifier =
604- Modifier .fillMaxWidth()
605- .background(MaterialTheme .colorScheme.surface, RoundedCornerShape (8 .dp))
606- .padding(12 .dp),
607- horizontalArrangement = Arrangement .SpaceBetween ,
608+ Surface (
609+ color = MaterialTheme .colorScheme.surface,
610+ shape = RoundedCornerShape (8 .dp),
611+ modifier = Modifier .fillMaxWidth(),
608612 ) {
609- Text (label, fontWeight = FontWeight .Bold )
610- Spacer (Modifier .size(12 .dp))
611- Text (value, maxLines = 1 , overflow = TextOverflow .Ellipsis )
613+ Row (
614+ modifier = Modifier .padding(12 .dp),
615+ horizontalArrangement = Arrangement .SpaceBetween ,
616+ ) {
617+ Text (label, fontWeight = FontWeight .Bold )
618+ Spacer (Modifier .size(12 .dp))
619+ Text (value, maxLines = 1 , overflow = TextOverflow .Ellipsis )
620+ }
612621 }
613622}
614623
0 commit comments