diff --git a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2Activity.kt b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2Activity.kt index 2067e4e8d1..70fb0fe0f3 100644 --- a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2Activity.kt +++ b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2Activity.kt @@ -20,7 +20,6 @@ import android.widget.LinearLayout import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy @@ -195,11 +194,10 @@ class Nav2Activity : AppCompatActivity() { private fun createComposeNavHostView(): ComposeView = ComposeView(this).apply { - setBackgroundColor(color(android.R.color.white)) setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { - MaterialTheme { + Nav2SampleTheme { Nav2ComposeApp( navListener = sentryNavigationListener, routeWorkOptions = routeWorkOptions.value, @@ -256,11 +254,10 @@ class Nav2Activity : AppCompatActivity() { private fun createPerformanceView(): ComposeView = ComposeView(this).apply { - setBackgroundColor(color(android.R.color.white)) setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { - MaterialTheme { + Nav2SampleTheme { NavigationPerformancePanel( title = "Performance", description = @@ -287,7 +284,7 @@ class Nav2Activity : AppCompatActivity() { setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { - MaterialTheme { + Nav2SampleTheme { if (showTransactionHistorySheet.value) { Nav2TransactionHistorySheet( transactions = transactionHistory.transactions, diff --git a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2ComposeRoutes.kt b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2ComposeRoutes.kt index c2e2a73040..ba61a6bb2e 100644 --- a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2ComposeRoutes.kt +++ b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2ComposeRoutes.kt @@ -23,6 +23,7 @@ import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable @@ -123,127 +124,129 @@ internal fun Nav2ComposeApp( routeWorkOptions = routeWorkOptions, ) - Column(modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)) { - NavHost( - navController = navController, - startDestination = Home.route, - modifier = Modifier.weight(1f), - ) { - composable(Home.route) { - TracedNav2ComposeRoute(Home.routeName) { - Nav2ComposeHomeRoute(routeSpec = Nav2RouteSpecs.home) { navigateTo(ProductList) } + Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { + Column(modifier = Modifier.fillMaxSize()) { + NavHost( + navController = navController, + startDestination = Home.route, + modifier = Modifier.weight(1f), + ) { + composable(Home.route) { + TracedNav2ComposeRoute(Home.routeName) { + Nav2ComposeHomeRoute(routeSpec = Nav2RouteSpecs.home) { navigateTo(ProductList) } + } } - } - composable(ProductList.route) { - TracedNav2ComposeRoute(ProductList.routeName) { - Nav2ComposeProductListRoute( - routeSpec = Nav2RouteSpecs.productList, - onOpenProduct42 = { - navigateTo( - ProductDetail( - productId = "42", - source = "product-list", - campaign = "summer-sale", + composable(ProductList.route) { + TracedNav2ComposeRoute(ProductList.routeName) { + Nav2ComposeProductListRoute( + routeSpec = Nav2RouteSpecs.productList, + onOpenProduct42 = { + navigateTo( + ProductDetail( + productId = "42", + source = "product-list", + campaign = "summer-sale", + ) ) - ) - }, - onOpenProduct7 = { - navigateTo(ProductDetail(productId = "7", source = "product-list")) - }, - ) + }, + onOpenProduct7 = { + navigateTo(ProductDetail(productId = "7", source = "product-list")) + }, + ) + } } - } - composable( - route = Nav2ComposeDestination.PRODUCT_DETAIL_ROUTE, - arguments = - listOf( - navArgument(Nav2Args.PRODUCT_ID) { type = NavType.StringType }, - navArgument(Nav2Args.SOURCE) { type = NavType.StringType }, - navArgument(Nav2Args.CAMPAIGN) { - type = NavType.StringType - defaultValue = "" - }, - ), - ) { entry -> - val productId = entry.arguments?.getString(Nav2Args.PRODUCT_ID).orEmpty() - val source = entry.arguments?.getString(Nav2Args.SOURCE).orEmpty() - val campaign = entry.arguments?.getString(Nav2Args.CAMPAIGN).orEmpty() - TracedNav2ComposeRoute(Nav2RouteNames.PRODUCT_DETAIL) { - Nav2ComposeProductDetailRoute( - routeSpec = Nav2RouteSpecs.productDetail, - productId = productId, - source = source, - campaign = campaign, - onShowPromoDialog = { - navigateTo(PromoDialog("detail-$productId")) - }, - onOpenShareSheet = { openShareSheet(productId) }, - onCheckout = { navigateTo(Checkout(productId)) }, - ) + composable( + route = Nav2ComposeDestination.PRODUCT_DETAIL_ROUTE, + arguments = + listOf( + navArgument(Nav2Args.PRODUCT_ID) { type = NavType.StringType }, + navArgument(Nav2Args.SOURCE) { type = NavType.StringType }, + navArgument(Nav2Args.CAMPAIGN) { + type = NavType.StringType + defaultValue = "" + }, + ), + ) { entry -> + val productId = entry.arguments?.getString(Nav2Args.PRODUCT_ID).orEmpty() + val source = entry.arguments?.getString(Nav2Args.SOURCE).orEmpty() + val campaign = entry.arguments?.getString(Nav2Args.CAMPAIGN).orEmpty() + TracedNav2ComposeRoute(Nav2RouteNames.PRODUCT_DETAIL) { + Nav2ComposeProductDetailRoute( + routeSpec = Nav2RouteSpecs.productDetail, + productId = productId, + source = source, + campaign = campaign, + onShowPromoDialog = { + navigateTo(PromoDialog("detail-$productId")) + }, + onOpenShareSheet = { openShareSheet(productId) }, + onCheckout = { navigateTo(Checkout(productId)) }, + ) + } } - } - composable( - route = Nav2ComposeDestination.CHECKOUT_ROUTE, - arguments = listOf(navArgument(Nav2Args.PRODUCT_ID) { type = NavType.StringType }), - ) { entry -> - val productId = entry.arguments?.getString(Nav2Args.PRODUCT_ID).orEmpty() - TracedNav2ComposeRoute(Nav2RouteNames.CHECKOUT) { - Nav2ComposeCheckoutRoute( - routeSpec = Nav2RouteSpecs.checkout, - productId = productId, - onCompleteOrder = { - navigateTo(Confirmation(orderId = "order-$productId")) - }, - ) + composable( + route = Nav2ComposeDestination.CHECKOUT_ROUTE, + arguments = listOf(navArgument(Nav2Args.PRODUCT_ID) { type = NavType.StringType }), + ) { entry -> + val productId = entry.arguments?.getString(Nav2Args.PRODUCT_ID).orEmpty() + TracedNav2ComposeRoute(Nav2RouteNames.CHECKOUT) { + Nav2ComposeCheckoutRoute( + routeSpec = Nav2RouteSpecs.checkout, + productId = productId, + onCompleteOrder = { + navigateTo(Confirmation(orderId = "order-$productId")) + }, + ) + } } - } - composable( - route = Nav2ComposeDestination.CONFIRMATION_ROUTE, - arguments = listOf(navArgument(Nav2Args.ORDER_ID) { type = NavType.StringType }), - ) { entry -> - TracedNav2ComposeRoute(Nav2RouteNames.CONFIRMATION) { - Nav2ComposeConfirmationRoute( - routeSpec = Nav2RouteSpecs.confirmation, - orderId = entry.arguments?.getString(Nav2Args.ORDER_ID).orEmpty(), - onResetBackStack = { resetToHome() }, - ) + composable( + route = Nav2ComposeDestination.CONFIRMATION_ROUTE, + arguments = listOf(navArgument(Nav2Args.ORDER_ID) { type = NavType.StringType }), + ) { entry -> + TracedNav2ComposeRoute(Nav2RouteNames.CONFIRMATION) { + Nav2ComposeConfirmationRoute( + routeSpec = Nav2RouteSpecs.confirmation, + orderId = entry.arguments?.getString(Nav2Args.ORDER_ID).orEmpty(), + onResetBackStack = { resetToHome() }, + ) + } } - } - dialog( - route = Nav2ComposeDestination.PROMO_DIALOG_ROUTE, - arguments = listOf(navArgument(Nav2Args.PROMO_ID) { type = NavType.StringType }), - ) { entry -> - // This dialog is a real Nav destination, so it participates in Nav2 the same way as the - // rest of the route graph. Compare it with the share sheet overlay below when inspecting - // Sentry's Nav2 breadcrumbs, destination arguments, and route transactions. - TracedNav2ComposeRoute(Nav2RouteNames.PROMO_DIALOG) { - Nav2ComposePromoDialogRoute( - routeSpec = Nav2RouteSpecs.promoDialog, - promoId = entry.arguments?.getString(Nav2Args.PROMO_ID).orEmpty(), - onCaptureException = onCaptureException, - onCrashApp = onCrashApp, - onDismiss = { navigateBack() }, - ) + dialog( + route = Nav2ComposeDestination.PROMO_DIALOG_ROUTE, + arguments = listOf(navArgument(Nav2Args.PROMO_ID) { type = NavType.StringType }), + ) { entry -> + // This dialog is a real Nav destination, so it participates in Nav2 the same way as the + // rest of the route graph. Compare it with the share sheet overlay below when inspecting + // Sentry's Nav2 breadcrumbs, destination arguments, and route transactions. + TracedNav2ComposeRoute(Nav2RouteNames.PROMO_DIALOG) { + Nav2ComposePromoDialogRoute( + routeSpec = Nav2RouteSpecs.promoDialog, + promoId = entry.arguments?.getString(Nav2Args.PROMO_ID).orEmpty(), + onCaptureException = onCaptureException, + onCrashApp = onCrashApp, + onDismiss = { navigateBack() }, + ) + } } } - } - shareSheetProductId.value?.let { productId -> - // This share sheet is intentionally just a screen overlay, not a Nav destination. It lets - // the sample compare how Sentry's Nav2 integration behaves for proper Nav destinations vs. - // UI layered on top of the current route. - Nav2ComposeShareSheetRoute( - routeSpec = Nav2RouteSpecs.shareSheet, - productId = productId, - onCaptureException = onCaptureException, - onCrashApp = onCrashApp, - onDone = ::dismissShareSheet, - ) + shareSheetProductId.value?.let { productId -> + // This share sheet is intentionally just a screen overlay, not a Nav destination. It lets + // the sample compare how Sentry's Nav2 integration behaves for proper Nav destinations vs. + // UI layered on top of the current route. + Nav2ComposeShareSheetRoute( + routeSpec = Nav2RouteSpecs.shareSheet, + productId = productId, + onCaptureException = onCaptureException, + onCrashApp = onCrashApp, + onDone = ::dismissShareSheet, + ) + } } } } @@ -528,30 +531,33 @@ private fun Nav2ComposeRouteScaffold( cardContent: (@Composable ColumnScope.() -> Unit)? = null, content: (@Composable ColumnScope.() -> Unit)? = null, ) { - Column( - modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(16.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - ) { - Text( - routeSpec.title, - style = MaterialTheme.typography.headlineMedium, - fontWeight = FontWeight.Bold, - ) - routeSpec.description?.let { Text(it, style = MaterialTheme.typography.bodyMedium) } - if (cardContent != null) { - Card( - colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant), - modifier = Modifier.fillMaxWidth(), - ) { - Column( - modifier = Modifier.padding(16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp), + Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { + Column( + modifier = Modifier.verticalScroll(rememberScrollState()).padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + Text( + routeSpec.title, + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold, + ) + routeSpec.description?.let { Text(it, style = MaterialTheme.typography.bodyMedium) } + if (cardContent != null) { + Card( + colors = + CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant), + modifier = Modifier.fillMaxWidth(), ) { - cardContent() + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + cardContent() + } } } + content?.invoke(this) } - content?.invoke(this) } } @@ -599,16 +605,19 @@ private const val PRODUCT_LIST_ITEM_COUNT = 20 @Composable private fun Nav2ComposeRouteInfo(label: String, value: String) { - Row( - modifier = - Modifier.fillMaxWidth() - .background(MaterialTheme.colorScheme.surface, RoundedCornerShape(8.dp)) - .padding(12.dp), - horizontalArrangement = Arrangement.SpaceBetween, + Surface( + color = MaterialTheme.colorScheme.surface, + shape = RoundedCornerShape(8.dp), + modifier = Modifier.fillMaxWidth(), ) { - Text(label, fontWeight = FontWeight.Bold) - Spacer(Modifier.size(12.dp)) - Text(value, maxLines = 1, overflow = TextOverflow.Ellipsis) + Row( + modifier = Modifier.padding(12.dp), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Text(label, fontWeight = FontWeight.Bold) + Spacer(Modifier.size(12.dp)) + Text(value, maxLines = 1, overflow = TextOverflow.Ellipsis) + } } } diff --git a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2ModalFragments.kt b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2ModalFragments.kt index b4f1326204..a06df9ae62 100644 --- a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2ModalFragments.kt +++ b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2ModalFragments.kt @@ -158,7 +158,7 @@ private fun titleText(context: Context, textValue: String): TextView = text = textValue textSize = 26f setTypeface(null, Typeface.BOLD) - setTextColor(color(context, android.R.color.black)) + setTextColor(context.themeColor(android.R.attr.textColorPrimary)) setPadding(0, 0, 0, 8.dp(context)) } @@ -166,7 +166,7 @@ private fun bodyText(context: Context, textValue: String): TextView = TextView(context).apply { text = textValue textSize = 15f - setTextColor(0xFF5E5873.toInt()) + setTextColor(context.themeColor(android.R.attr.textColorSecondary)) setLineSpacing(0f, 1.12f) setPadding(0, 0, 0, 14.dp(context)) } @@ -214,14 +214,14 @@ private fun quietButton(context: Context, id: Int, label: String, onClick: () -> this.id = id text = label isAllCaps = false - setTextColor(0xFF756E89.toInt()) + setTextColor(context.themeColor(android.R.attr.textColorSecondary)) setOnClickListener { onClick() } } private fun roundedSurface(context: Context, topCornersOnly: Boolean): GradientDrawable { return GradientDrawable().apply { shape = GradientDrawable.RECTANGLE - setColor(color(context, android.R.color.white)) + setColor(context.themeColor(android.R.attr.colorBackgroundFloating)) val radius = 28.dp(context).toFloat() if (topCornersOnly) { cornerRadii = floatArrayOf(radius, radius, radius, radius, 0f, 0f, 0f, 0f) diff --git a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2RouteFragment.kt b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2RouteFragment.kt index 50796b4f6c..5fb4ef1bdd 100644 --- a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2RouteFragment.kt +++ b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2RouteFragment.kt @@ -182,7 +182,7 @@ class Nav2RouteFragment : Fragment() { LinearLayout(context).apply { orientation = LinearLayout.VERTICAL setPadding(16.dp) - setBackgroundColor(color(android.R.color.darker_gray)) + setBackgroundColor(context.themeColor(android.R.attr.colorBackgroundFloating)) info.forEach { (label, value) -> addView(infoRow(label, value)) } buttons.forEach { button -> addView(routeButton(button)) } } @@ -286,7 +286,7 @@ class Nav2RouteFragment : Fragment() { LinearLayout(requireContext()).apply { orientation = LinearLayout.HORIZONTAL setPadding(12.dp) - setBackgroundColor(color(android.R.color.white)) + setBackgroundColor(context.themeColor(android.R.attr.colorBackgroundFloating)) addView( TextView(context).apply { text = "Product #$itemNumber" @@ -308,7 +308,7 @@ class Nav2RouteFragment : Fragment() { text = textValue textSize = 26f setTypeface(null, Typeface.BOLD) - setTextColor(color(android.R.color.black)) + setTextColor(context.themeColor(android.R.attr.textColorPrimary)) setPadding(0, 0, 0, 12.dp) } @@ -316,7 +316,7 @@ class Nav2RouteFragment : Fragment() { TextView(requireContext()).apply { text = textValue textSize = 15f - setTextColor(color(android.R.color.black)) + setTextColor(context.themeColor(android.R.attr.textColorSecondary)) setPadding(0, 0, 0, 16.dp) } diff --git a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2RouteWorkDialog.kt b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2RouteWorkDialog.kt index f6cb37aefa..31b7e39f77 100644 --- a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2RouteWorkDialog.kt +++ b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2RouteWorkDialog.kt @@ -39,14 +39,14 @@ private fun routeWorkDialogTitle(context: Context): View = text = "Route work" textSize = 20f setTypeface(null, Typeface.BOLD) - setTextColor(context.getColor(android.R.color.black)) + setTextColor(context.themeColor(android.R.attr.textColorPrimary)) } ) addView( TextView(context).apply { text = "Enable/disable the generation of spans by navigation destinations." textSize = 14f - setTextColor(0xFF756E89.toInt()) + setTextColor(context.themeColor(android.R.attr.textColorSecondary)) setPadding(0, context.dp(8), 0, 0) } ) diff --git a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2SampleTheme.kt b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2SampleTheme.kt new file mode 100644 index 0000000000..f6d1876734 --- /dev/null +++ b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2SampleTheme.kt @@ -0,0 +1,26 @@ +package io.sentry.samples.android.navigation + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.core.content.ContextCompat +import io.sentry.samples.android.R + +@Composable +internal fun Nav2SampleTheme(content: @Composable () -> Unit) { + val context = LocalContext.current + val primaryColor = Color(ContextCompat.getColor(context, R.color.colorPrimary)) + val accentColor = Color(ContextCompat.getColor(context, R.color.colorAccent)) + val colorScheme = + if (isSystemInDarkTheme()) { + darkColorScheme(primary = primaryColor, secondary = accentColor, tertiary = primaryColor) + } else { + lightColorScheme(primary = primaryColor, secondary = accentColor, tertiary = primaryColor) + } + + MaterialTheme(colorScheme = colorScheme, content = content) +} diff --git a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2SetupActivity.kt b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2SetupActivity.kt index 70810b4014..cdd0c35f40 100644 --- a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2SetupActivity.kt +++ b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2SetupActivity.kt @@ -67,7 +67,7 @@ class Nav2SetupActivity : AppCompatActivity() { super.onCreate(savedInstanceState) configuration = savedInstanceState?.nav2SampleConfiguration() ?: configuration setContent { - MaterialTheme { + Nav2SampleTheme { Nav2SetupScreen( configuration = configuration, onConfigurationChanged = { updatedConfiguration -> diff --git a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2ThemeColors.kt b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2ThemeColors.kt new file mode 100644 index 0000000000..6f5d99b536 --- /dev/null +++ b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2ThemeColors.kt @@ -0,0 +1,13 @@ +package io.sentry.samples.android.navigation + +import android.content.Context +import androidx.annotation.AttrRes + +internal fun Context.themeColor(@AttrRes attrId: Int): Int { + val attributes = obtainStyledAttributes(intArrayOf(attrId)) + return try { + attributes.getColor(0, 0) + } finally { + attributes.recycle() + } +} diff --git a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2TopBar.kt b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2TopBar.kt index e740e97c06..c21cebf6b3 100644 --- a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2TopBar.kt +++ b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/Nav2TopBar.kt @@ -14,7 +14,6 @@ import androidx.compose.material.icons.filled.Settings import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy @@ -97,11 +96,13 @@ internal class Nav2TopBar( tabViews.forEach { (tabScenario, tabView) -> val selected = tabScenario == scenario tabView.label.setTextColor( - color(if (selected) R.color.colorPrimary else android.R.color.black) + if (selected) context.themeColor(androidx.appcompat.R.attr.colorPrimary) + else tabView.defaultTextColor ) tabView.label.setTypeface(null, if (selected) Typeface.BOLD else Typeface.NORMAL) tabView.indicator.setBackgroundColor( - color(if (selected) R.color.colorPrimary else android.R.color.transparent) + if (selected) context.themeColor(androidx.appcompat.R.attr.colorPrimary) + else color(android.R.color.transparent) ) } } @@ -118,7 +119,7 @@ internal class Nav2TopBar( TextView(context).apply { text = "Navigation 2" textSize = 20f - setTextColor(color(android.R.color.black)) + setTextColor(context.themeColor(android.R.attr.textColorPrimary)) layoutParams = LinearLayout.LayoutParams(0, WRAP_CONTENT, 1f) } ) @@ -156,6 +157,7 @@ internal class Nav2TopBar( textSize = 14f gravity = Gravity.CENTER setPadding(18.dp, 14.dp, 18.dp, 10.dp) + setTextColor(context.themeColor(android.R.attr.textColorPrimary)) } val indicator = View(context).apply { @@ -164,7 +166,7 @@ internal class Nav2TopBar( } tabContainer.addView(textView) tabContainer.addView(indicator) - tabViews[scenario] = Nav2TabView(textView, indicator) + tabViews[scenario] = Nav2TabView(textView, indicator, textView.currentTextColor) tabRow.addView(tabContainer) } @@ -187,7 +189,7 @@ internal class Nav2TopBar( private fun bodyText(): TextView = TextView(context).apply { textSize = 12f - setTextColor(color(android.R.color.black)) + setTextColor(context.themeColor(android.R.attr.textColorSecondary)) maxLines = 1 setHorizontallyScrolling(true) } @@ -225,12 +227,12 @@ internal class Nav2TopBar( this.id = id setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { - MaterialTheme { + Nav2SampleTheme { IconButton(onClick = onClick) { Icon( imageVector = imageVector, contentDescription = contentDescription, - tint = Color.Black, + tint = MaterialTheme.colorScheme.onSurface, ) } } @@ -245,4 +247,4 @@ internal class Nav2TopBar( private data class Nav2TopBarState(val currentRoute: String, val backStack: String) -private data class Nav2TabView(val label: TextView, val indicator: View) +private data class Nav2TabView(val label: TextView, val indicator: View, val defaultTextColor: Int) diff --git a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/NavigationPerformanceControls.kt b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/NavigationPerformanceControls.kt index 271530e6a3..54ae586566 100644 --- a/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/NavigationPerformanceControls.kt +++ b/sentry-samples/sentry-samples-android/src/main/java/io/sentry/samples/android/navigation/NavigationPerformanceControls.kt @@ -1,7 +1,6 @@ package io.sentry.samples.android.navigation import android.os.Trace -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope @@ -20,6 +19,7 @@ import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -114,60 +114,62 @@ internal fun NavigationPerformancePanel( } } - Column( - modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(16.dp), - verticalArrangement = Arrangement.spacedBy(12.dp), - ) { - Text(title, style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold) - Text(description, style = MaterialTheme.typography.bodyMedium) + Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { + Column( + modifier = Modifier.verticalScroll(rememberScrollState()).padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + Text(title, style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold) + Text(description, style = MaterialTheme.typography.bodyMedium) - PerfCard(title = "Current State") { - PerfInfoRow("Current route", currentRoute) - PerfInfoRow("Tracked stack", backStack) - } + PerfCard(title = "Current State") { + PerfInfoRow("Current route", currentRoute) + PerfInfoRow("Tracked stack", backStack) + } - PerfCard(title = "Stress Controls") { - PerfStepper( - label = "Stack depth", - value = state.stackDepth, - onDecrement = { state.stackDepth = (state.stackDepth - 1).coerceAtLeast(1) }, - onIncrement = { state.stackDepth = (state.stackDepth + 1).coerceAtMost(100) }, - ) + PerfCard(title = "Stress Controls") { + PerfStepper( + label = "Stack depth", + value = state.stackDepth, + onDecrement = { state.stackDepth = (state.stackDepth - 1).coerceAtLeast(1) }, + onIncrement = { state.stackDepth = (state.stackDepth + 1).coerceAtMost(100) }, + ) - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { - Button(onClick = onBuildStack, modifier = Modifier.weight(1f)) { Text("Build Stack") } - Button(onClick = onReplaceTop, modifier = Modifier.weight(1f)) { Text("Replace Top") } - } + Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + Button(onClick = onBuildStack, modifier = Modifier.weight(1f)) { Text("Build Stack") } + Button(onClick = onReplaceTop, modifier = Modifier.weight(1f)) { Text("Replace Top") } + } - Button( - onClick = { state.markRecompositionRequest() }, - modifier = Modifier.fillMaxWidth(), - ) { - Text("Force Unrelated Recomposition") - } + Button( + onClick = { state.markRecompositionRequest() }, + modifier = Modifier.fillMaxWidth(), + ) { + Text("Force Unrelated Recomposition") + } - Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { - PerfToggleButton( - selected = state.autoRecompose, - label = if (state.autoRecompose) "Stop Recompose" else "Auto Recompose", - onClick = { state.autoRecompose = !state.autoRecompose }, - modifier = Modifier.weight(1f), - ) - PerfToggleButton( - selected = state.autoNavigate, - label = if (state.autoNavigate) "Stop Navigate" else "Auto Navigate", - onClick = { state.autoNavigate = !state.autoNavigate }, - modifier = Modifier.weight(1f), - ) + Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + PerfToggleButton( + selected = state.autoRecompose, + label = if (state.autoRecompose) "Stop Recompose" else "Auto Recompose", + onClick = { state.autoRecompose = !state.autoRecompose }, + modifier = Modifier.weight(1f), + ) + PerfToggleButton( + selected = state.autoNavigate, + label = if (state.autoNavigate) "Stop Navigate" else "Auto Navigate", + onClick = { state.autoNavigate = !state.autoNavigate }, + modifier = Modifier.weight(1f), + ) + } } - } - PerfCard(title = "Counters") { - PerfInfoRow("Recomposition requests", state.recompositionRequests.toString()) - PerfInfoRow("Navigation mutations", state.navigationMutations.toString()) - PerfInfoRow("Destination changes", state.destinationChanges.toString()) - Button(onClick = { state.resetCounters() }, modifier = Modifier.fillMaxWidth()) { - Text("Reset Counters") + PerfCard(title = "Counters") { + PerfInfoRow("Recomposition requests", state.recompositionRequests.toString()) + PerfInfoRow("Navigation mutations", state.navigationMutations.toString()) + PerfInfoRow("Destination changes", state.destinationChanges.toString()) + Button(onClick = { state.resetCounters() }, modifier = Modifier.fillMaxWidth()) { + Text("Reset Counters") + } } } } @@ -191,17 +193,20 @@ private fun PerfCard(title: String, content: @Composable ColumnScope.() -> Unit) @Composable private fun PerfInfoRow(label: String, value: String) { - Row( - modifier = - Modifier.fillMaxWidth() - .background(MaterialTheme.colorScheme.surface, RoundedCornerShape(8.dp)) - .padding(12.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, + Surface( + color = MaterialTheme.colorScheme.surface, + shape = RoundedCornerShape(8.dp), + modifier = Modifier.fillMaxWidth(), ) { - Text(label, fontWeight = FontWeight.Bold, modifier = Modifier.weight(1f)) - Spacer(Modifier.size(12.dp)) - Text(value, modifier = Modifier.weight(1f)) + Row( + modifier = Modifier.padding(12.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + Text(label, fontWeight = FontWeight.Bold, modifier = Modifier.weight(1f)) + Spacer(Modifier.size(12.dp)) + Text(value, modifier = Modifier.weight(1f)) + } } }