diff --git a/demo-app/build.gradle.kts b/demo-app/build.gradle.kts
index 75b3eeaca..1f2f1f20e 100644
--- a/demo-app/build.gradle.kts
+++ b/demo-app/build.gradle.kts
@@ -65,6 +65,7 @@ dependencies {
implementation(libs.androidx.navigation.fragment.ktx)
implementation(libs.androidx.navigation.ui.ktx)
implementation(libs.opentelemetry.api.incubator)
+ implementation(libs.androidx.navigation.compose)
coreLibraryDesugaring(libs.desugarJdkLibs)
diff --git a/demo-app/gradle/libs.versions.toml b/demo-app/gradle/libs.versions.toml
index ea8041f42..8786f1288 100644
--- a/demo-app/gradle/libs.versions.toml
+++ b/demo-app/gradle/libs.versions.toml
@@ -4,6 +4,7 @@ opentelemetry-alpha = "1.39.0-alpha"
junit = "5.10.3"
spotless = "6.25.0"
kotlin = "2.0.0"
+navigation-compose = "2.7.7"
[libraries]
androidx-appcompat = "androidx.appcompat:appcompat:1.7.0"
@@ -35,8 +36,9 @@ androidx-constraintlayout = { group = "androidx.constraintlayout", name = "const
material = { group = "com.google.android.material", name = "material", version = "1.12.0" }
androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version = "2.8.4" }
androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version = "2.8.4" }
-androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navigation-fragment-ktx", version = "2.7.7" }
-androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version = "2.7.7" }
+androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "navigation-compose" }
+androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigation-compose" }
+androidx-navigation-compose = {group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation-compose"}
[bundles]
junit = ["junit-jupiter-api", "junit-jupiter-engine", "junit-vintage-engine"]
diff --git a/demo-app/src/main/AndroidManifest.xml b/demo-app/src/main/AndroidManifest.xml
index c04a07e76..1046456dd 100644
--- a/demo-app/src/main/AndroidManifest.xml
+++ b/demo-app/src/main/AndroidManifest.xml
@@ -18,7 +18,7 @@
android:usesCleartextTraffic="true"
tools:targetApi="31">
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/AstronomyShopActivity.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/AstronomyShopActivity.kt
deleted file mode 100644
index f031cb71b..000000000
--- a/demo-app/src/main/java/io/opentelemetry/android/demo/AstronomyShopActivity.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.android.demo
-
-import android.content.Intent
-import android.os.Bundle
-import android.util.Log
-import android.view.MenuItem
-import androidx.appcompat.app.AppCompatActivity
-import androidx.navigation.findNavController
-import androidx.navigation.ui.AppBarConfiguration
-import androidx.navigation.ui.setupActionBarWithNavController
-import androidx.navigation.ui.setupWithNavController
-import com.google.android.material.bottomnavigation.BottomNavigationView
-import io.opentelemetry.android.demo.databinding.ActivityAstronomyShopBinding
-
-class AstronomyShopActivity : AppCompatActivity() {
- private lateinit var binding: ActivityAstronomyShopBinding
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- binding = ActivityAstronomyShopBinding.inflate(layoutInflater)
- setContentView(binding.root)
-
- val navView: BottomNavigationView = binding.navView
-
- val navController = findNavController(R.id.nav_host_fragment_activity_astronomy_shop)
- // Passing each menu ID as a set of Ids because each
- // menu should be considered as top level destinations.
- val appBarConfiguration =
- AppBarConfiguration(
- setOf(
- R.id.navigation_home,
- R.id.navigation_dashboard,
- R.id.navigation_cart,
- ),
- )
- setupActionBarWithNavController(navController, appBarConfiguration)
- navView.setupWithNavController(navController)
- }
-
- fun onExitToMainClicked(item: MenuItem) {
- Log.d(TAG, "Exiting shop back to main activity")
- startActivity(Intent(this@AstronomyShopActivity, MainActivity::class.java))
- }
-}
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/MainActivity.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/MainActivity.kt
index 96ee2730d..6e5c2a36e 100644
--- a/demo-app/src/main/java/io/opentelemetry/android/demo/MainActivity.kt
+++ b/demo-app/src/main/java/io/opentelemetry/android/demo/MainActivity.kt
@@ -29,6 +29,7 @@ import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import io.opentelemetry.android.demo.theme.DemoAppTheme
+import io.opentelemetry.android.demo.ui.shop.AstronomyShopActivity
class MainActivity : ComponentActivity() {
private val viewModel by viewModels()
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/cart/CartFragment.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/cart/CartFragment.kt
deleted file mode 100644
index 2e039c40c..000000000
--- a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/cart/CartFragment.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.android.demo.ui.cart
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.ViewModelProvider
-import io.opentelemetry.android.demo.databinding.FragmentNotificationsBinding
-
-class CartFragment : Fragment() {
- // Renamed from _binding (default) due to ktlint problem below
- private var binding: FragmentNotificationsBinding? = null
-
- // This property is only valid between onCreateView and onDestroyView.
- // Currently failing ktlint due to
- // https://github.com/pinterest/ktlint/issues/2448
- // which hasn't hit the aging gradle spotless plugin yet
-// private val binding get() = _binding!!
- private fun getBinding(): FragmentNotificationsBinding {
- return binding!!
- }
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?,
- ): View {
- val cartViewModel =
- ViewModelProvider(this).get(CartViewModel::class.java)
-
- binding = FragmentNotificationsBinding.inflate(inflater, container, false)
- val root: View = getBinding().root
-
- val textView: TextView = getBinding().textNotifications
- cartViewModel.text.observe(viewLifecycleOwner) {
- textView.text = it
- }
- return root
- }
-
- override fun onDestroyView() {
- super.onDestroyView()
- binding = null
- }
-}
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/cart/CartViewModel.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/cart/CartViewModel.kt
deleted file mode 100644
index b2c5a207b..000000000
--- a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/cart/CartViewModel.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.android.demo.ui.cart
-
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.ViewModel
-
-class CartViewModel : ViewModel() {
- private val _text =
- MutableLiveData().apply {
- value = "This is cart Fragment"
- }
- val text: LiveData = _text
-}
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/dashboard/DashboardFragment.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/dashboard/DashboardFragment.kt
deleted file mode 100644
index 9a4481934..000000000
--- a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/dashboard/DashboardFragment.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.android.demo.ui.dashboard
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.ViewModelProvider
-import io.opentelemetry.android.demo.databinding.FragmentDashboardBinding
-
-class DashboardFragment : Fragment() {
- // Renamed from _binding (default) due to ktlint problem below
- private var binding: FragmentDashboardBinding? = null
-
- // This property is only valid between onCreateView and onDestroyView.
- // Currently failing ktlint due to
- // https://github.com/pinterest/ktlint/issues/2448
- // which hasn't hit the aging gradle spotless plugin yet
-// private val binding get() = _binding!!
- fun getBinding(): FragmentDashboardBinding {
- return binding!!
- }
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?,
- ): View {
- val dashboardViewModel =
- ViewModelProvider(this).get(DashboardViewModel::class.java)
-
- binding = FragmentDashboardBinding.inflate(inflater, container, false)
- val root: View = getBinding().root
-
- val textView: TextView = getBinding().textDashboard
- dashboardViewModel.text.observe(viewLifecycleOwner) {
- textView.text = it
- }
- return root
- }
-
- override fun onDestroyView() {
- super.onDestroyView()
- binding = null
- }
-}
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/dashboard/DashboardViewModel.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/dashboard/DashboardViewModel.kt
deleted file mode 100644
index af4464db2..000000000
--- a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/dashboard/DashboardViewModel.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.android.demo.ui.dashboard
-
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.ViewModel
-
-class DashboardViewModel : ViewModel() {
- private val _text =
- MutableLiveData().apply {
- value = "This is dashboard Fragment"
- }
- val text: LiveData = _text
-}
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/AstronomyShopActivity.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/AstronomyShopActivity.kt
new file mode 100644
index 000000000..feb6edee1
--- /dev/null
+++ b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/AstronomyShopActivity.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.android.demo.ui.shop
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.compose.setContent
+import androidx.appcompat.app.AppCompatActivity
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.navigation.compose.NavHost
+import androidx.navigation.compose.composable
+import io.opentelemetry.android.demo.MainActivity
+import io.opentelemetry.android.demo.clients.ProductCatalogClient
+import io.opentelemetry.android.demo.theme.DemoAppTheme
+import io.opentelemetry.android.demo.ui.shop.cart.CartScreen
+import io.opentelemetry.android.demo.ui.shop.products.ProductDetails
+import io.opentelemetry.android.demo.ui.shop.products.ProductList
+
+class AstronomyShopActivity : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContent {
+ AstronomyShopScreen()
+ }
+ }
+}
+
+@Composable
+fun AstronomyShopScreen() {
+ val productsClient = ProductCatalogClient(LocalContext.current)
+ val products by remember { mutableStateOf(productsClient.get()) }
+ val context = LocalContext.current
+ val astronomyShopNavController = rememberAstronomyShopNavController()
+
+ DemoAppTheme {
+ Surface(
+ modifier = Modifier.fillMaxSize(),
+ color = MaterialTheme.colorScheme.background
+ ) {
+ Scaffold(
+ bottomBar = {
+ BottomNavigationBar(
+ items = listOf(BottomNavItem.Exit, BottomNavItem.List, BottomNavItem.Cart),
+ currentRoute = astronomyShopNavController.currentRoute,
+ onItemClicked = { route ->
+ astronomyShopNavController.navController.navigate(route) {
+ popUpTo(astronomyShopNavController.navController.graph.startDestinationId)
+ launchSingleTop = true
+ }
+ },
+ onExitClicked = {
+ val intent = Intent(context, MainActivity::class.java)
+ context.startActivity(intent)
+ (context as? Activity)?.finish()
+ }
+ )
+ }
+ ) { innerPadding ->
+ NavHost(
+ navController = astronomyShopNavController.navController,
+ startDestination = MainDestinations.HOME_ROUTE,
+ Modifier.padding(innerPadding)
+ ) {
+ composable(BottomNavItem.List.route) {
+ ProductList(products = products) { productId ->
+ astronomyShopNavController.navigateToProductDetail(productId)
+ }
+ }
+ composable(BottomNavItem.Cart.route) {
+ CartScreen()
+ }
+ composable("${MainDestinations.PRODUCT_DETAIL_ROUTE}/{${MainDestinations.PRODUCT_ID_KEY}}") { backStackEntry ->
+ val productId = backStackEntry.arguments?.getString(MainDestinations.PRODUCT_ID_KEY)
+ val product = products.find { it.id == productId }
+ product?.let { ProductDetails(product = it) }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/Navigation.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/Navigation.kt
new file mode 100644
index 000000000..76942e2e8
--- /dev/null
+++ b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/Navigation.kt
@@ -0,0 +1,80 @@
+package io.opentelemetry.android.demo.ui.shop
+
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.filled.ExitToApp
+import androidx.compose.material.icons.automirrored.filled.List
+import androidx.compose.material.icons.filled.ShoppingCart
+import androidx.compose.material3.Icon
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Stable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.lifecycle.Lifecycle
+import androidx.navigation.NavBackStackEntry
+import androidx.navigation.NavDestination
+import androidx.navigation.NavGraph
+import androidx.navigation.NavHostController
+import androidx.navigation.compose.rememberNavController
+import androidx.compose.material3.*
+
+
+sealed class BottomNavItem(val route: String, val icon: ImageVector, val label: String) {
+ data object Exit : BottomNavItem("home", Icons.AutoMirrored.Filled.ExitToApp, "Exit")
+ data object List : BottomNavItem("prod-list", Icons.AutoMirrored.Filled.List, "List")
+ data object Cart : BottomNavItem("cart", Icons.Filled.ShoppingCart, "Cart")
+}
+
+object MainDestinations {
+ const val HOME_ROUTE = "prod-list"
+ const val PRODUCT_DETAIL_ROUTE = "product"
+ const val PRODUCT_ID_KEY = "productId"
+}
+
+@Composable
+fun rememberAstronomyShopNavController(navController: NavHostController = rememberNavController())
+: AstronomyShopNavController = remember(navController)
+{
+ AstronomyShopNavController(navController)
+}
+
+@Stable
+class AstronomyShopNavController(
+ val navController: NavHostController,
+) {
+ val currentRoute: String?
+ get() = navController.currentDestination?.route
+
+ fun upPress() {
+ navController.navigateUp()
+ }
+
+ fun navigateToProductDetail(productId: String) {
+ navController.navigate("${MainDestinations.PRODUCT_DETAIL_ROUTE}/$productId")
+ }
+
+}
+
+@Composable
+fun BottomNavigationBar(
+ items: List,
+ currentRoute: String?,
+ onItemClicked: (String) -> Unit,
+ onExitClicked: () -> Unit
+) {
+ NavigationBar {
+ items.forEach { item ->
+ NavigationBarItem(
+ selected = currentRoute == item.route,
+ onClick = {
+ if (item.route == BottomNavItem.Exit.route) {
+ onExitClicked()
+ } else {
+ onItemClicked(item.route)
+ }
+ },
+ icon = { Icon(item.icon, contentDescription = item.label) },
+ label = { Text(item.label) }
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/ShopFragment.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/ShopFragment.kt
deleted file mode 100644
index b5ea4294c..000000000
--- a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/ShopFragment.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.android.demo.ui.shop
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Surface
-import androidx.compose.material3.Text
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.ComposeView
-import androidx.fragment.app.Fragment
-import io.opentelemetry.android.demo.clients.ProductCatalogClient
-import io.opentelemetry.android.demo.theme.DemoAppTheme
-
-class ShopFragment : Fragment() {
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?,
- ): View {
-
- val productsClient = ProductCatalogClient(requireContext())
- val products = productsClient.get()
- val productState = mutableStateOf(products)
-
- return ComposeView(requireContext()).apply {
- setContent {
- DemoAppTheme {
- // A surface container using the 'background' color from the theme
- Surface(
- modifier = Modifier.fillMaxSize(),
- color = MaterialTheme.colorScheme.background,
- ) {
- ProductList(productState)
- }
- }
- }
- }
- }
-
-}
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/cart/Cart.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/cart/Cart.kt
new file mode 100644
index 000000000..a0781e841
--- /dev/null
+++ b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/cart/Cart.kt
@@ -0,0 +1,62 @@
+package io.opentelemetry.android.demo.ui.shop.cart
+
+import androidx.compose.material3.Scaffold
+import androidx.compose.runtime.Composable
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.material3.Button
+import androidx.compose.material3.Text
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import io.opentelemetry.android.demo.model.Product
+
+
+@Composable
+fun CartScreen() {
+ val products : List = listOf()
+ Scaffold(
+ content = { innerPadding ->
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(innerPadding),
+ verticalArrangement = Arrangement.SpaceBetween
+ ) {
+ LazyColumn(
+ modifier = Modifier.weight(1f)
+ ) {
+ items(products.size) { index -> CartItem(products[index]) }
+ }
+ CheckoutButton(totalPrice = products.sumOf { it.priceValue() })
+ }
+ }
+ )
+}
+
+@Composable
+fun CartItem(product: Product) {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(vertical = 8.dp),
+ horizontalArrangement = Arrangement.SpaceBetween,
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Text(text = product.name, fontSize = 20.sp)
+ Text(text = "$${product.priceUsd}", fontSize = 20.sp)
+ }
+}
+
+@Composable
+fun CheckoutButton(totalPrice: Double) {
+ Button(
+ onClick = { /* TODO: Add checkout logic */ },
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(vertical = 16.dp)
+ ) {
+ Text(text = "Checkout ($${String.format("%.2f", totalPrice)})")
+ }
+}
\ No newline at end of file
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/ProductCard.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/products/ProductCard.kt
similarity index 72%
rename from demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/ProductCard.kt
rename to demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/products/ProductCard.kt
index 0da990da4..e5100efa9 100644
--- a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/ProductCard.kt
+++ b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/products/ProductCard.kt
@@ -1,7 +1,6 @@
-package io.opentelemetry.android.demo.ui.shop
+package io.opentelemetry.android.demo.ui.shop.products
import android.graphics.Bitmap
-import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -15,7 +14,6 @@ import androidx.compose.material3.CardColors
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
@@ -24,33 +22,33 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import io.opentelemetry.android.demo.TAG
import io.opentelemetry.android.demo.clients.ImageLoader
import io.opentelemetry.android.demo.gothamFont
import io.opentelemetry.android.demo.model.Product
@Composable
-fun ProductCard(product: Product) {
+fun ProductCard(product: Product, onClick: (String) -> Unit) {
val imageLoader = ImageLoader(LocalContext.current)
val sourceProductImage = imageLoader.load(product.picture)
Bitmap.createScaledBitmap(sourceProductImage, 120, 120, false)
-// Bitmap.createBitmap()
val cardColors = CardColors(
containerColor = Color.White, contentColor = Color.Black,
disabledContentColor = Color.Black, disabledContainerColor = Color.Black
)
- Card(elevation = CardDefaults.cardElevation(defaultElevation = 10.dp),
+ Card(
+ elevation = CardDefaults.cardElevation(defaultElevation = 10.dp),
colors = cardColors,
- modifier = Modifier.fillMaxSize()
- .height(200.dp)
- .wrapContentHeight()
- .padding(20.dp),
- onClick = {
- Log.d(TAG, "TODO: Implement me!")
- }
+ modifier = Modifier
+ .fillMaxSize()
+ .height(200.dp)
+ .wrapContentHeight()
+ .padding(20.dp),
+ onClick = { onClick(product.id) }
) {
- Row(modifier = Modifier.fillMaxSize().padding(20.dp)) {
+ Row(modifier = Modifier
+ .fillMaxSize()
+ .padding(20.dp)) {
Row(modifier = Modifier.fillMaxWidth()) {
Column {
Image(
@@ -59,14 +57,17 @@ fun ProductCard(product: Product) {
)
}
Column(modifier = Modifier.fillMaxWidth()) {
- Text(product.name + "\n\n$" + product.priceValue(), fontFamily = gothamFont,
+ Text(
+ product.name + "\n\n$" + product.priceValue(),
+ fontFamily = gothamFont,
style = TextStyle.Default.copy(textAlign = TextAlign.Right),
fontSize = 18.sp,
- modifier = Modifier.padding(start = 15.dp, top = 25.dp).fillMaxWidth()
+ modifier = Modifier
+ .padding(start = 15.dp, top = 25.dp)
+ .fillMaxWidth()
)
-
}
}
}
}
-}
\ No newline at end of file
+}
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/products/ProductDetails.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/products/ProductDetails.kt
new file mode 100644
index 000000000..5b0a30e20
--- /dev/null
+++ b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/products/ProductDetails.kt
@@ -0,0 +1,73 @@
+package io.opentelemetry.android.demo.ui.shop.products
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.*
+import androidx.compose.runtime.*
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.asImageBitmap
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import io.opentelemetry.android.demo.clients.ImageLoader
+import io.opentelemetry.android.demo.gothamFont
+import io.opentelemetry.android.demo.model.Product
+
+@Composable
+fun ProductDetails(product:Product){
+ val imageLoader = ImageLoader(LocalContext.current)
+ val sourceProductImage = imageLoader.load(product.picture)
+
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(16.dp)
+ .verticalScroll(rememberScrollState())
+ ) {
+ Image(
+ bitmap = sourceProductImage.asImageBitmap(),
+ contentDescription = product.name,
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(300.dp)
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ Text(
+ text = product.name,
+ fontFamily = gothamFont,
+ fontSize = 24.sp,
+ modifier = Modifier.fillMaxWidth(),
+ textAlign = TextAlign.Center
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ Text(
+ text = product.description,
+ color = Color.Gray,
+ textAlign = TextAlign.Justify,
+ fontFamily = gothamFont,
+ fontSize = 16.sp,
+ modifier = Modifier.fillMaxWidth()
+ )
+ Spacer(modifier = Modifier.height(16.dp))
+ Text(
+ text = "$${product.priceValue()}",
+ fontFamily = gothamFont,
+ fontSize = 24.sp,
+ modifier = Modifier.fillMaxWidth(),
+ textAlign = TextAlign.Center
+ )
+ Spacer(modifier = Modifier.height(32.dp))
+ Button(
+ onClick = { /* TODO: Handle add to cart */ },
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp)
+ ) {
+ Text(text = "Add to Cart")
+ }
+ }
+}
diff --git a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/ProductList.kt b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/products/ProductList.kt
similarity index 69%
rename from demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/ProductList.kt
rename to demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/products/ProductList.kt
index 04de9d82e..8c26bd1f9 100644
--- a/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/ProductList.kt
+++ b/demo-app/src/main/java/io/opentelemetry/android/demo/ui/shop/products/ProductList.kt
@@ -1,4 +1,4 @@
-package io.opentelemetry.android.demo.ui.shop
+package io.opentelemetry.android.demo.ui.shop.products
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
@@ -6,17 +6,16 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import io.opentelemetry.android.demo.model.Product
@Composable
-fun ProductList(products: State>) {
+fun ProductList(products: List, onProductClick: (String) -> Unit) {
LazyColumn(modifier = Modifier.fillMaxSize()) {
- items(products.value.size) { index ->
- Row() {
- ProductCard(products.value[index])
+ items(products.size) { index ->
+ Row {
+ ProductCard(products[index], onClick = onProductClick)
}
}
item {
@@ -25,4 +24,4 @@ fun ProductList(products: State>) {
)
}
}
-}
\ No newline at end of file
+}
diff --git a/demo-app/src/main/res/layout/activity_astronomy_shop.xml b/demo-app/src/main/res/layout/activity_astronomy_shop.xml
index 87f9dba2c..cd1f2df91 100644
--- a/demo-app/src/main/res/layout/activity_astronomy_shop.xml
+++ b/demo-app/src/main/res/layout/activity_astronomy_shop.xml
@@ -4,30 +4,4 @@
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingTop="?attr/actionBarSize">
-
-
-
-
-
-
\ No newline at end of file
+ android:paddingTop="?attr/actionBarSize"/>
\ No newline at end of file
diff --git a/demo-app/src/main/res/layout/fragment_dashboard.xml b/demo-app/src/main/res/layout/fragment_dashboard.xml
deleted file mode 100644
index 166ab0e9e..000000000
--- a/demo-app/src/main/res/layout/fragment_dashboard.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/demo-app/src/main/res/layout/fragment_home.xml b/demo-app/src/main/res/layout/fragment_home.xml
deleted file mode 100644
index 5778483d8..000000000
--- a/demo-app/src/main/res/layout/fragment_home.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/demo-app/src/main/res/navigation/mobile_navigation.xml b/demo-app/src/main/res/navigation/mobile_navigation.xml
deleted file mode 100644
index da4972c97..000000000
--- a/demo-app/src/main/res/navigation/mobile_navigation.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file