diff --git a/biz/detail/src/main/AndroidManifest.xml b/biz/detail/src/main/AndroidManifest.xml
index 990c4aa05..08fddbef7 100644
--- a/biz/detail/src/main/AndroidManifest.xml
+++ b/biz/detail/src/main/AndroidManifest.xml
@@ -2,7 +2,9 @@
-
+
diff --git a/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/Color.kt b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/Color.kt
new file mode 100644
index 000000000..12d3ee839
--- /dev/null
+++ b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/Color.kt
@@ -0,0 +1,10 @@
+@file:Suppress("MagicNumber")
+
+package io.goooler.demoapp.detail.ui
+
+import androidx.compose.ui.graphics.Color
+
+val Navy = Color(0xFF073042)
+val Blue = Color(0xFF4285F4)
+val LightBlue = Color(0xFFD7EFFE)
+val Chartreuse = Color(0xFFEFF7CF)
diff --git a/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/DetailPage.kt b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/DetailPage.kt
deleted file mode 100644
index bdc359e41..000000000
--- a/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/DetailPage.kt
+++ /dev/null
@@ -1,131 +0,0 @@
-package io.goooler.demoapp.detail.ui
-
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.rememberScrollState
-import androidx.compose.foundation.verticalScroll
-import androidx.compose.material.Button
-import androidx.compose.material.ButtonDefaults
-import androidx.compose.material.ExperimentalMaterialApi
-import androidx.compose.material.Icon
-import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Text
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Share
-import androidx.compose.material.icons.filled.Star
-import androidx.compose.material.pullrefresh.PullRefreshIndicator
-import androidx.compose.material.pullrefresh.pullRefresh
-import androidx.compose.material.pullrefresh.rememberPullRefreshState
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import io.goooler.demoapp.common.util.getQuantityString
-import io.goooler.demoapp.common.util.showToast
-import io.goooler.demoapp.detail.R
-import io.goooler.demoapp.detail.model.RepoDetailModel
-
-@OptIn(ExperimentalMaterialApi::class)
-@Composable
-fun DetailPageWithSwipeRefresh(
- isRefreshing: Boolean,
- onRefresh: () -> Unit,
- model: RepoDetailModel,
- modifier: Modifier = Modifier,
- onForkClick: () -> Unit,
-) {
- val refreshState = rememberPullRefreshState(refreshing = isRefreshing, onRefresh = onRefresh)
-
- MaterialTheme {
- Box(modifier = Modifier.pullRefresh(state = refreshState)) {
- DetailPage(model = model, onForkClick = onForkClick)
- PullRefreshIndicator(isRefreshing, refreshState, Modifier.align(Alignment.TopCenter))
- }
- }
-}
-
-@Composable
-fun DetailPage(
- model: RepoDetailModel,
- modifier: Modifier = Modifier,
- onForkClick: () -> Unit,
-) {
- var isDescExpanded by remember { mutableStateOf(false) }
-
- Column(
- modifier = Modifier
- .padding(8.dp)
- .fillMaxSize()
- .verticalScroll(rememberScrollState()),
- ) {
- Text(
- text = model.fullName,
- style = MaterialTheme.typography.h5,
- maxLines = 1,
- )
- Spacer(modifier = Modifier.height(5.dp))
- Text(
- text = model.description,
- style = MaterialTheme.typography.body1,
- maxLines = if (isDescExpanded) Int.MAX_VALUE else 2,
- modifier = Modifier.clickable {
- isDescExpanded = !isDescExpanded
- },
- )
- Spacer(modifier = Modifier.height(5.dp))
- Row {
- Button(onClick = {
- R.plurals.detail_star_count_tip.getQuantityString(model.starsCount)?.showToast()
- }) {
- Icon(
- Icons.Filled.Star,
- contentDescription = "Star",
- modifier = Modifier.size(ButtonDefaults.IconSize),
- )
- Spacer(Modifier.size(ButtonDefaults.IconSpacing))
- Text(model.starsCount.toString())
- }
- Spacer(modifier = Modifier.width(20.dp))
- Button(onClick = onForkClick) {
- Icon(
- Icons.Filled.Share,
- contentDescription = "Fork",
- modifier = Modifier.size(ButtonDefaults.IconSize),
- )
- Spacer(Modifier.size(ButtonDefaults.IconSpacing))
- Text(model.forksCount.toString())
- }
- }
- Spacer(modifier = Modifier.height(5.dp))
- }
-}
-
-@Preview
-@Composable
-private fun DetailPagePreview() {
- @Suppress("MagicNumber")
- val model = RepoDetailModel(
- "Compose/Demo",
- "Jetpack Compose is Android’s modern toolkit for building native UI. " +
- "It simplifies and accelerates UI development on Android. " +
- "Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.",
- "Apache",
- 99,
- 1,
- 2,
- )
- DetailPage(model) {}
-}
diff --git a/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/DetailScreen.kt b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/DetailScreen.kt
new file mode 100644
index 000000000..2faeff51b
--- /dev/null
+++ b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/DetailScreen.kt
@@ -0,0 +1,185 @@
+package io.goooler.demoapp.detail.ui
+
+import androidx.compose.animation.animateContentSize
+import androidx.compose.animation.core.Spring
+import androidx.compose.animation.core.spring
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Share
+import androidx.compose.material.icons.filled.Star
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Card
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.material3.pulltorefresh.PullToRefreshContainer
+import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.nestedscroll.nestedScroll
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.viewmodel.compose.viewModel
+import io.goooler.demoapp.common.util.getQuantityString
+import io.goooler.demoapp.common.util.showToast
+import io.goooler.demoapp.detail.R
+import io.goooler.demoapp.detail.model.RepoDetailModel
+import io.goooler.demoapp.detail.vm.DetailViewModel
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun DetailScreenWithSwipeRefresh(
+ modifier: Modifier = Modifier,
+ vm: DetailViewModel = viewModel(),
+) {
+ val model by vm.repoDetailModel.collectAsState()
+ val isRefreshing by vm.isRefreshing.collectAsState()
+ val refreshState = rememberPullToRefreshState()
+
+ if (refreshState.isRefreshing) {
+ LaunchedEffect(true) {
+ // fetch something
+ vm.refresh()
+ if (!isRefreshing) {
+ refreshState.endRefresh()
+ }
+ }
+ }
+
+ Surface(
+ color = MaterialTheme.colorScheme.surface,
+ modifier = modifier.padding(horizontal = 10.dp),
+ ) {
+ Box(Modifier.nestedScroll(refreshState.nestedScrollConnection)) {
+ DetailList(model, vm::fork)
+
+ PullToRefreshContainer(
+ modifier = Modifier.align(Alignment.TopCenter),
+ state = refreshState,
+ )
+ }
+ }
+}
+
+@Composable
+private fun DetailList(
+ model: RepoDetailModel,
+ onForkClick: () -> Unit = {},
+) {
+ LazyColumn {
+ @Suppress("MagicNumber")
+ val models = List(10) { model }
+ items(models) { model ->
+ DetailCard(model = model, onForkClick = onForkClick)
+ }
+ }
+}
+
+@Composable
+private fun DetailCard(
+ model: RepoDetailModel,
+ modifier: Modifier = Modifier,
+ onForkClick: () -> Unit = {},
+) {
+ var isDescExpanded by rememberSaveable { mutableStateOf(false) }
+
+ Card(
+ modifier = modifier.padding(8.dp),
+ ) {
+ Column(
+ modifier = Modifier
+ .padding(12.dp)
+ .animateContentSize(
+ animationSpec = spring(
+ dampingRatio = Spring.DampingRatioMediumBouncy,
+ stiffness = Spring.StiffnessLow,
+ ),
+ ),
+ ) {
+ Text(
+ text = model.fullName,
+ style = MaterialTheme.typography.titleLarge.copy(
+ fontWeight = FontWeight.SemiBold,
+ ),
+ maxLines = 1,
+ )
+ Spacer(modifier = Modifier.height(5.dp))
+ Text(
+ text = model.description,
+ style = MaterialTheme.typography.bodyLarge,
+ maxLines = if (isDescExpanded) Int.MAX_VALUE else 1,
+ modifier = Modifier.clickable {
+ isDescExpanded = !isDescExpanded
+ },
+ )
+ Spacer(modifier = Modifier.height(5.dp))
+ Row {
+ Button(
+ modifier = Modifier.weight(1f),
+ onClick = {
+ R.plurals.detail_star_count_tip.getQuantityString(model.starsCount)?.showToast()
+ },
+ ) {
+ Icon(
+ Icons.Filled.Star,
+ contentDescription = "Star",
+ modifier = Modifier.size(ButtonDefaults.IconSize),
+ )
+ Spacer(Modifier.size(ButtonDefaults.IconSpacing))
+ Text(model.starsCount.toString())
+ }
+ Spacer(modifier = Modifier.width(20.dp))
+ Button(
+ modifier = Modifier.weight(1f),
+ onClick = onForkClick,
+ ) {
+ Icon(
+ Icons.Filled.Share,
+ contentDescription = "Fork",
+ modifier = Modifier.size(ButtonDefaults.IconSize),
+ )
+ Spacer(Modifier.size(ButtonDefaults.IconSpacing))
+ Text(model.forksCount.toString())
+ }
+ }
+ Spacer(modifier = Modifier.height(5.dp))
+ }
+ }
+}
+
+@PreviewDemo
+@Composable
+private fun DetailListPreview() {
+ @Suppress("MagicNumber")
+ val model = RepoDetailModel(
+ "Compose/Demo",
+ "Jetpack Compose is Android’s modern toolkit for building native UI. " +
+ "It simplifies and accelerates UI development on Android. " +
+ "Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.",
+ "Apache",
+ 99,
+ 1,
+ 2,
+ )
+ DetailList(model)
+}
diff --git a/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt
index 5d6efed7b..53288750c 100644
--- a/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt
+++ b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/RepoDetailActivity.kt
@@ -3,8 +3,8 @@ package io.goooler.demoapp.detail.ui
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.activity.viewModels
-import androidx.compose.runtime.collectAsState
-import androidx.compose.runtime.getValue
+import androidx.compose.foundation.layout.padding
+import androidx.compose.ui.Modifier
import io.goooler.demoapp.base.core.BaseActivity
import io.goooler.demoapp.detail.vm.DetailViewModel
@@ -15,15 +15,15 @@ class RepoDetailActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- intent.getStringExtra(FULL_NAME)?.let {
- vm.fullName = it
- vm.refresh()
- }
+ vm.fullName = intent.getStringExtra(FULL_NAME) ?: "Goooler/DemoApp"
+ vm.refresh()
setContent {
- val model by vm.repoDetailModel.collectAsState()
- val isRefreshing by vm.isRefreshing.collectAsState()
- DetailPageWithSwipeRefresh(isRefreshing, vm::refresh, model, onForkClick = vm::fork)
+ DemoScaffold { innerPadding ->
+ DetailScreenWithSwipeRefresh(
+ modifier = Modifier.padding(innerPadding),
+ )
+ }
}
}
diff --git a/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/Theme.kt b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/Theme.kt
new file mode 100644
index 000000000..2a503cde1
--- /dev/null
+++ b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/Theme.kt
@@ -0,0 +1,115 @@
+package io.goooler.demoapp.detail.ui
+
+import android.app.Activity
+import android.content.res.Configuration.UI_MODE_NIGHT_YES
+import android.os.Build
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.calculateEndPadding
+import androidx.compose.foundation.layout.calculateStartPadding
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.material3.lightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.SideEffect
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.platform.LocalView
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.core.view.WindowCompat
+
+private val DarkColorScheme = darkColorScheme(
+ surface = Blue,
+ onSurface = Navy,
+ primary = Navy,
+ onPrimary = Chartreuse,
+)
+
+private val LightColorScheme = lightColorScheme(
+ surface = Blue,
+ onSurface = Color.White,
+ primary = LightBlue,
+ onPrimary = Navy,
+)
+
+@Composable
+fun DemoTheme(
+ darkTheme: Boolean = isSystemInDarkTheme(),
+ // Dynamic color is available on Android 12+
+ dynamicColor: Boolean = true,
+ content: @Composable () -> Unit,
+) {
+ val colorScheme = when {
+ dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
+ val context = LocalContext.current
+ if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
+ }
+
+ darkTheme -> DarkColorScheme
+ else -> LightColorScheme
+ }
+
+ val view = LocalView.current
+ if (!view.isInEditMode) {
+ SideEffect {
+ val window = (view.context as Activity).window
+ window.statusBarColor = colorScheme.primary.toArgb()
+ WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
+ }
+ }
+
+ MaterialTheme(
+ colorScheme = colorScheme,
+ typography = Typography,
+ content = content,
+ )
+}
+
+@Preview(
+ name = "Light",
+ showSystemUi = true,
+ showBackground = true,
+)
+@Preview(
+ name = "Dark",
+ showSystemUi = true,
+ showBackground = true,
+ uiMode = UI_MODE_NIGHT_YES,
+)
+annotation class PreviewDemo
+
+@Composable
+fun DemoScaffold(
+ modifier: Modifier = Modifier,
+ content: @Composable (PaddingValues) -> Unit,
+) {
+ DemoTheme {
+ Scaffold(
+ modifier = modifier.fillMaxSize(),
+ content = content,
+ )
+ }
+}
+
+@Composable
+fun PaddingValues.copy(
+ layoutDirection: LayoutDirection = LocalLayoutDirection.current,
+ start: Dp = calculateStartPadding(layoutDirection),
+ top: Dp = calculateTopPadding(),
+ end: Dp = calculateEndPadding(layoutDirection),
+ bottom: Dp = calculateBottomPadding(),
+) = PaddingValues(
+ start = start,
+ top = top,
+ end = end,
+ bottom = bottom,
+)
diff --git a/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/Type.kt b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/Type.kt
new file mode 100644
index 000000000..ad5aa5934
--- /dev/null
+++ b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/ui/Type.kt
@@ -0,0 +1,34 @@
+package io.goooler.demoapp.detail.ui
+
+import androidx.compose.material3.Typography
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.sp
+
+// Set of Material typography styles to start with
+val Typography = Typography(
+ bodyLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ letterSpacing = 0.5.sp,
+ ),
+ /* Other default text styles to override
+ titleLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 22.sp,
+ lineHeight = 28.sp,
+ letterSpacing = 0.sp
+ ),
+ labelSmall = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Medium,
+ fontSize = 11.sp,
+ lineHeight = 16.sp,
+ letterSpacing = 0.5.sp
+ )
+ */
+)
diff --git a/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/vm/DetailViewModel.kt b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/vm/DetailViewModel.kt
index 442ac95ca..e3cd1cebb 100644
--- a/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/vm/DetailViewModel.kt
+++ b/biz/detail/src/main/kotlin/io/goooler/demoapp/detail/vm/DetailViewModel.kt
@@ -20,14 +20,12 @@ class DetailViewModel : BaseViewModel() {
lateinit var fullName: String
- val repoDetailModel: StateFlow
- get() = _repoDetailModel.asStateFlow()
- val isRefreshing: StateFlow
- get() = _isRefreshing.asStateFlow()
+ val repoDetailModel: StateFlow = _repoDetailModel.asStateFlow()
+ val isRefreshing: StateFlow = _isRefreshing.asStateFlow()
fun refresh() {
viewModelScope.launch {
- _isRefreshing.emit(true)
+ _isRefreshing.value = true
repository.getRepoDetail(fullName).let {
repoDetail = RepoDetailModel(
it.fullName,
@@ -39,7 +37,7 @@ class DetailViewModel : BaseViewModel() {
)
}
_repoDetailModel.value = repoDetail
- _isRefreshing.emit(false)
+ _isRefreshing.value = false
}
}
diff --git a/biz/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt b/biz/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt
index 78f796794..4dc90187c 100644
--- a/biz/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt
+++ b/biz/main/src/main/kotlin/io/goooler/demoapp/main/vm/MainHomeViewModel.kt
@@ -16,6 +16,7 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onCompletion
@@ -26,7 +27,7 @@ class MainHomeViewModel : BaseViewModel() {
private val repository = MainCommonRepository()
private val _title = MutableStateFlow("")
- val title: StateFlow = _title
+ val title: StateFlow = _title.asStateFlow()
private var countdownJob: Job? = null
diff --git a/detekt.yml b/detekt.yml
index ea5074944..b5ad4386c 100644
--- a/detekt.yml
+++ b/detekt.yml
@@ -128,7 +128,7 @@ complexity:
threshold: 600
LongMethod:
active: true
- threshold: 60
+ threshold: 70
LongParameterList:
active: true
functionThreshold: 6
@@ -740,7 +740,7 @@ style:
UnusedPrivateMember:
active: true
allowedNames: ''
- ignoreAnnotated: [ 'Preview' ]
+ ignoreAnnotated: [ 'Preview*' ]
UnusedPrivateProperty:
active: true
allowedNames: '_|ignored|expected|serialVersionUID'
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 87d0d8da1..7771da54a 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -36,7 +36,7 @@ androidX-compose-bom = "androidx.compose:compose-bom:2024.06.00"
androidX-compose-ui = { module = "androidx.compose.ui:ui" }
androidX-compose-tooling = { module = "androidx.compose.ui:ui-tooling" }
androidX-compose-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
-androidX-compose-material = { module = "androidx.compose.material:material" }
+androidX-compose-material3 = { module = "androidx.compose.material3:material3" }
androidX-compose-foundation = { module = "androidx.compose.foundation:foundation" }
androidX-compose-icons-core = { module = "androidx.compose.material:material-icons-core" }
androidX-compose-icons-extended = { module = "androidx.compose.material:material-icons-extended" }
@@ -53,7 +53,8 @@ androidX-coordinatorLayout = "androidx.coordinatorlayout:coordinatorlayout:1.2.0
androidX-core = "androidx.core:core-ktx:1.13.1"
androidX-fragment = "androidx.fragment:fragment-ktx:1.8.1"
androidX-lifecycle-service = { module = "androidx.lifecycle:lifecycle-service", version.ref = "androidX-lifecycle" }
-androidX-lifecycle-viewModel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidX-lifecycle" }
+androidX-lifecycle-viewModel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidX-lifecycle" }
+androidX-lifecycle-viewModel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidX-lifecycle" }
androidX-paging = "androidx.paging:paging-runtime:3.3.0"
androidX-recyclerView = "androidx.recyclerview:recyclerview:1.3.2"
androidX-room-compiler = { module = "androidx.room:room-compiler", version.ref = "androidX-room" }
@@ -98,13 +99,14 @@ composeRules = "io.nlopez.compose.rules:detekt:0.4.5"
androidX-compose = [
"androidX-compose-ui",
"androidX-compose-tooling-preview",
- "androidX-compose-material",
+ "androidX-compose-material3",
"androidX-compose-foundation",
"androidX-compose-icons-core",
- "androidX-compose-icons-extended"
+ "androidX-compose-icons-extended",
+ "androidX-lifecycle-viewModel-compose",
]
androidX-lifecycle = [
- "androidX-lifecycle-viewModel",
+ "androidX-lifecycle-viewModel-ktx",
"androidX-lifecycle-service"
]
androidX-room = [