Skip to content

Commit

Permalink
Merge pull request #5 from sunildhiman90/using_decompose_navigation
Browse files Browse the repository at this point in the history
Using decompose for navigation
  • Loading branch information
sunildhiman90 authored May 5, 2024
2 parents 51b5e12 + 0aaa5fa commit a58d6f7
Show file tree
Hide file tree
Showing 12 changed files with 381 additions and 26 deletions.
11 changes: 10 additions & 1 deletion composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsCompose)

kotlin("plugin.serialization") version "1.9.21"
kotlin("plugin.serialization") version "1.9.21" //decompose step2
}

kotlin {
Expand Down Expand Up @@ -52,6 +52,11 @@ kotlin {
androidMain.dependencies {
implementation(libs.compose.ui.tooling.preview)
implementation(libs.androidx.activity.compose)

//decompose step3
implementation("com.arkivanov.decompose:decompose:2.2.2-compose-experimental")
implementation("com.arkivanov.decompose:extensions-compose-jetbrains:2.2.2-compose-experimental")

}
commonMain.dependencies {
implementation(compose.runtime)
Expand All @@ -73,6 +78,10 @@ kotlin {

api(libs.image.loader)


implementation("com.arkivanov.decompose:decompose:2.2.2-compose-experimental")
implementation("com.arkivanov.decompose:extensions-compose-jetbrains:2.2.2-compose-experimental")
//decompose step1
}
desktopMain.dependencies {
implementation(compose.desktop.currentOs)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,36 @@
package com.codingambitions.kmpapp2

import App
import HomeViewModel
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.arkivanov.decompose.defaultComponentContext
import com.seiko.imageloader.ImageLoader
import com.seiko.imageloader.LocalImageLoader
import com.seiko.imageloader.cache.memory.maxSizePercent
import com.seiko.imageloader.component.setupDefaultComponents
import com.seiko.imageloader.defaultImageResultMemoryCache
import com.seiko.imageloader.option.androidContext
import okio.Path.Companion.toOkioPath
import root.DefaultRootComponent
import root.RootContent

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContent {

CompositionLocalProvider(
LocalImageLoader provides remember { generateImageLoader() },
) {
App()
val homeViewModel = HomeViewModel()
val root = DefaultRootComponent(defaultComponentContext(), homeViewModel)
RootContent(root, modifier = Modifier)
}
}
}
Expand Down Expand Up @@ -57,5 +62,5 @@ class MainActivity : ComponentActivity() {
@Preview
@Composable
fun AppAndroidPreview() {
App()
//App()
}
33 changes: 16 additions & 17 deletions composeApp/src/commonMain/kotlin/App.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
Expand Down Expand Up @@ -30,6 +31,7 @@ import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.SearchBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
Expand All @@ -38,22 +40,15 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.seiko.imageloader.rememberImagePainter
import data.Product
import kotlinx.coroutines.launch
import list.ListComponent
import org.jetbrains.compose.resources.ExperimentalResourceApi

@OptIn(ExperimentalResourceApi::class)
@Composable
fun App() {
MaterialTheme {
AppContent(homeViewModel = HomeViewModel())
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppContent(homeViewModel: HomeViewModel) {

val products = homeViewModel.products.collectAsState()
fun AppContent(products: State<ListComponent.Model>, onItemClicked: (Product) -> Unit) {

BoxWithConstraints {
val scope = this
Expand All @@ -79,11 +74,13 @@ fun AppContent(homeViewModel: HomeViewModel) {
columns = GridCells.Fixed(cols),
state = scrollState,
contentPadding = PaddingValues(16.dp),
modifier = Modifier.draggable(orientation = Orientation.Vertical, state = rememberDraggableState { delta ->
coroutineScope.launch {
scrollState.scrollBy(-delta)
}
})
modifier = Modifier.draggable(
orientation = Orientation.Vertical,
state = rememberDraggableState { delta ->
coroutineScope.launch {
scrollState.scrollBy(-delta)
}
})
) {

item(span = { GridItemSpan(cols) }) {
Expand All @@ -110,12 +107,14 @@ fun AppContent(homeViewModel: HomeViewModel) {


items(
items = products.value,
items = products.value.items,
key = { product -> product.id.toString() }) { product ->

Card(
shape = RoundedCornerShape(15.dp),
modifier = Modifier.padding(8.dp).fillMaxWidth(),
modifier = Modifier.padding(8.dp).fillMaxWidth().clickable {
onItemClicked(product)
},
elevation = 2.dp
) {
Column(
Expand Down
43 changes: 43 additions & 0 deletions composeApp/src/commonMain/kotlin/detail/DetailComponent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package detail

import HomeViewModel
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.value.MutableValue
import com.arkivanov.decompose.value.Value
import data.Product
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import list.ListComponent

interface DetailComponent {
val model: Value<Model>

fun onBackPressed()

data class Model(
val item: Product
)
}

class DefaultDetailComponent(
private val componentContext: ComponentContext,
private val item: Product,
private val onBack: () -> Unit,
) : DetailComponent, ComponentContext by componentContext {

private val _model = MutableValue(DetailComponent.Model(item = item))
override val model: Value<DetailComponent.Model> = _model
override fun onBackPressed() {
onBack()
}

init {
CoroutineScope(Dispatchers.Default).launch {
//IF we need to call api in Detail Component, call here
}
}


}
65 changes: 65 additions & 0 deletions composeApp/src/commonMain/kotlin/detail/DetailContent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package detail

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Build
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.Key.Companion.P
import androidx.compose.ui.unit.dp
import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState


@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DetailContent(
component: DetailComponent
) {

val product = component.model.subscribeAsState()

Scaffold(
modifier = Modifier,
containerColor = MaterialTheme.colorScheme.surface,
topBar = {
TopAppBar(
modifier = Modifier.windowInsetsPadding(WindowInsets(0.dp)),
title = { Text("Product Detail") },
navigationIcon = {
IconButton(onClick = {
component.onBackPressed()
}) {
Icon(Icons.Default.ArrowBack, contentDescription = "Go Back")
}
}
)
}
) {

Column(
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxHeight().fillMaxWidth().padding(16.dp)
) {
Text("Product title: ${product.value.item.title}")
Text("Product Desc: ${product.value.item.description}")
}
}
}
44 changes: 44 additions & 0 deletions composeApp/src/commonMain/kotlin/list/ListComponent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package list

import HomeViewModel
import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.value.MutableValue
import com.arkivanov.decompose.value.Value
import data.Product
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

interface ListComponent {
val model: Value<Model>

fun onItemClicked(item: Product)

data class Model(
val items: List<Product>
)
}

class DefaultListComponent(
private val componentContext: ComponentContext,
private val homeViewModel: HomeViewModel,
private val onItemSelected: (item: Product) -> Unit
) : ListComponent, ComponentContext by componentContext {

private val _model = MutableValue<ListComponent.Model>(ListComponent.Model(items = emptyList()))
override val model: Value<ListComponent.Model> = _model
override fun onItemClicked(item: Product) {
onItemSelected(item)
}

init {
CoroutineScope(Dispatchers.Default).launch {
homeViewModel.products.collect {
_model.value = ListComponent.Model(items = it)
}
}
}


}
18 changes: 18 additions & 0 deletions composeApp/src/commonMain/kotlin/list/ListContent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package list

import AppContent
import androidx.compose.runtime.Composable
import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState


@Composable
fun ListContent(
component: ListComponent
) {
val products = component.model.subscribeAsState()

AppContent(products) {
component.onItemClicked(it)
}

}
Loading

0 comments on commit a58d6f7

Please sign in to comment.