diff --git a/commonApp/src/commonMain/kotlin/com/stslex/atten/host/DefaultRootComponent.kt b/commonApp/src/commonMain/kotlin/com/stslex/atten/host/DefaultRootComponent.kt index 9323eea..e6955bf 100644 --- a/commonApp/src/commonMain/kotlin/com/stslex/atten/host/DefaultRootComponent.kt +++ b/commonApp/src/commonMain/kotlin/com/stslex/atten/host/DefaultRootComponent.kt @@ -9,6 +9,7 @@ import com.arkivanov.decompose.router.stack.navigate import com.arkivanov.decompose.router.stack.pop import com.arkivanov.decompose.value.Value import com.stslex.atten.core.ui.navigation.Config +import com.stslex.atten.core.ui.navigation.Router import com.stslex.atten.feature.details.ui.mvi.DetailsComponent import com.stslex.atten.feature.home.ui.mvi.HomeComponent import com.stslex.atten.host.RootComponent.Child @@ -37,21 +38,8 @@ class DefaultRootComponent( config: Config, context: ComponentContext ): Child = when (config) { - is Config.Home -> Child.Home( - HomeComponent.create( - popBack = ::popBack, - navTo = ::navigateTo, - componentContext = context - ) - ) - - is Config.Detail -> Child.Details( - DetailsComponent.create( - popBack = ::popBack, - componentContext = context, - uuid = config.uuid - ) - ) + is Config.Home -> Child.Home(HomeComponent.create(context.router)) + is Config.Detail -> Child.Details(DetailsComponent.create(context.router, config.uuid)) } @OptIn(DelicateDecomposeApi::class) @@ -68,4 +56,16 @@ class DefaultRootComponent( private fun popBack() { navigation.pop() } + + private val ComponentContext.router: Router + get() = object : Router, ComponentContext by this { + + override fun navTo(config: Config) { + navigateTo(config) + } + + override fun popBack() { + this@DefaultRootComponent.popBack() + } + } } diff --git a/commonApp/src/commonMain/kotlin/com/stslex/atten/host/RootComponent.kt b/commonApp/src/commonMain/kotlin/com/stslex/atten/host/RootComponent.kt index 9644bae..72027d9 100644 --- a/commonApp/src/commonMain/kotlin/com/stslex/atten/host/RootComponent.kt +++ b/commonApp/src/commonMain/kotlin/com/stslex/atten/host/RootComponent.kt @@ -20,4 +20,4 @@ interface RootComponent { data class Details(val component: DetailsComponent) : Child } -} \ No newline at end of file +} diff --git a/core/ui/navigation/src/commonMain/kotlin/com/stslex/atten/core/ui/navigation/Config.kt b/core/ui/navigation/src/commonMain/kotlin/com/stslex/atten/core/ui/navigation/Config.kt index bd00d19..a8bd5e6 100644 --- a/core/ui/navigation/src/commonMain/kotlin/com/stslex/atten/core/ui/navigation/Config.kt +++ b/core/ui/navigation/src/commonMain/kotlin/com/stslex/atten/core/ui/navigation/Config.kt @@ -10,11 +10,13 @@ sealed interface Config { val isBackAllow: Boolean get() = true + @Serializable data object Home : Config { override val isBackAllow: Boolean = false } + @Serializable data class Detail( val uuid: String ) : Config diff --git a/core/ui/navigation/src/commonMain/kotlin/com/stslex/atten/core/ui/navigation/Router.kt b/core/ui/navigation/src/commonMain/kotlin/com/stslex/atten/core/ui/navigation/Router.kt new file mode 100644 index 0000000..265f3d1 --- /dev/null +++ b/core/ui/navigation/src/commonMain/kotlin/com/stslex/atten/core/ui/navigation/Router.kt @@ -0,0 +1,11 @@ +package com.stslex.atten.core.ui.navigation + +import com.arkivanov.decompose.ComponentContext + +interface Router : ComponentContext { + + fun navTo(config: Config) + + fun popBack() + +} \ No newline at end of file diff --git a/core/ui/navigation/src/commonMain/kotlin/com/stslex/atten/core/ui/navigation/Target.kt b/core/ui/navigation/src/commonMain/kotlin/com/stslex/atten/core/ui/navigation/Target.kt index b0173cd..d009a84 100644 --- a/core/ui/navigation/src/commonMain/kotlin/com/stslex/atten/core/ui/navigation/Target.kt +++ b/core/ui/navigation/src/commonMain/kotlin/com/stslex/atten/core/ui/navigation/Target.kt @@ -1,3 +1,3 @@ -package com.stslex.wizard.core.navigation +package com.stslex.atten.core.ui.navigation interface Target \ No newline at end of file diff --git a/feature/details/src/commonMain/kotlin/com.stslex.atten.feature.details/ui/mvi/DetailsComponent.kt b/feature/details/src/commonMain/kotlin/com.stslex.atten.feature.details/ui/mvi/DetailsComponent.kt index 0a8ab5f..bf2ff44 100644 --- a/feature/details/src/commonMain/kotlin/com.stslex.atten.feature.details/ui/mvi/DetailsComponent.kt +++ b/feature/details/src/commonMain/kotlin/com.stslex.atten.feature.details/ui/mvi/DetailsComponent.kt @@ -1,10 +1,10 @@ package com.stslex.atten.feature.details.ui.mvi -import com.arkivanov.decompose.ComponentContext +import com.stslex.atten.core.ui.mvi.handler.Handler import com.stslex.atten.core.ui.navigation.Component +import com.stslex.atten.core.ui.navigation.Router import com.stslex.atten.feature.details.ui.mvi.DetailsStore.Action import com.stslex.atten.feature.details.ui.mvi.handlers.DetailsComponentImpl -import com.stslex.atten.core.ui.mvi.handler.Handler interface DetailsComponent : Component, Handler { @@ -13,13 +13,8 @@ interface DetailsComponent : Component, Handler Unit, + router: Router, uuid: String, - componentContext: ComponentContext - ): DetailsComponent = DetailsComponentImpl( - componentContext = componentContext, - popBack = popBack, - uuid = uuid - ) + ): DetailsComponent = DetailsComponentImpl(router, uuid) } } \ No newline at end of file diff --git a/feature/details/src/commonMain/kotlin/com.stslex.atten.feature.details/ui/mvi/handlers/DetailsComponentImpl.kt b/feature/details/src/commonMain/kotlin/com.stslex.atten.feature.details/ui/mvi/handlers/DetailsComponentImpl.kt index caef102..21f90f2 100644 --- a/feature/details/src/commonMain/kotlin/com.stslex.atten.feature.details/ui/mvi/handlers/DetailsComponentImpl.kt +++ b/feature/details/src/commonMain/kotlin/com.stslex.atten.feature.details/ui/mvi/handlers/DetailsComponentImpl.kt @@ -1,19 +1,19 @@ package com.stslex.atten.feature.details.ui.mvi.handlers import com.arkivanov.decompose.ComponentContext +import com.stslex.atten.core.ui.navigation.Router import com.stslex.atten.feature.details.ui.mvi.DetailsComponent import com.stslex.atten.feature.details.ui.mvi.DetailsHandlerStore -import com.stslex.atten.feature.details.ui.mvi.DetailsStore +import com.stslex.atten.feature.details.ui.mvi.DetailsStore.Action internal class DetailsComponentImpl( - componentContext: ComponentContext, - private val popBack: () -> Unit, + private val router: Router, override val uuid: String -) : DetailsComponent, ComponentContext by componentContext { +) : DetailsComponent, ComponentContext by router { - override fun DetailsHandlerStore.invoke(action: DetailsStore.Action.Navigation) { + override fun DetailsHandlerStore.invoke(action: Action.Navigation) { when (action) { - DetailsStore.Action.Navigation.Back -> popBack() + Action.Navigation.Back -> router.popBack() } } } \ No newline at end of file diff --git a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/HomeScreen.kt b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/HomeScreen.kt index 712ac27..b214bf2 100644 --- a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/HomeScreen.kt +++ b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/HomeScreen.kt @@ -1,5 +1,6 @@ package com.stslex.atten.feature.home.ui +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback @@ -13,12 +14,12 @@ import com.stslex.atten.feature.home.ui.mvi.HomeStore.Action fun HomeScreen(component: HomeComponent) { NavComponentScreen(HomeFeature, component) { processor -> val hapticFeedback = LocalHapticFeedback.current - + val lazyListState = rememberLazyListState() processor.handle { event -> when (event) { - is HomeStore.Event.Snackbar -> { + is HomeStore.Event.Snackbar -> Unit - } + is HomeStore.Event.List.ScrollTop -> lazyListState.requestScrollToItem(0) HomeStore.Event.Haptic.Click -> { hapticFeedback.performHapticFeedback(HapticFeedbackType.TextHandleMove) @@ -40,6 +41,7 @@ fun HomeScreen(component: HomeComponent) { HomeWidget( state = processor.state.value, + lazyListState = lazyListState, onItemClicked = { id -> processor.consume(Action.Click.OnItemClicked(id)) }, diff --git a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/HomeWidget.kt b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/HomeWidget.kt index c8cf53d..f6c2418 100644 --- a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/HomeWidget.kt +++ b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/HomeWidget.kt @@ -18,6 +18,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Create import androidx.compose.material.icons.filled.Delete @@ -45,6 +47,7 @@ import org.jetbrains.compose.ui.tooling.preview.Preview @Composable internal fun HomeWidget( state: State, + lazyListState: LazyListState = rememberLazyListState(), onItemLongCLick: (id: String) -> Unit, onItemClicked: (id: String) -> Unit, onLoadNext: () -> Unit, @@ -64,6 +67,7 @@ internal fun HomeWidget( .padding( horizontal = AppDimension.Padding.medium, ), + state = lazyListState, pagingState = state.paging, onLoadNext = onLoadNext ) { diff --git a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/HomeComponent.kt b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/HomeComponent.kt index 6fbce5b..abd7464 100644 --- a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/HomeComponent.kt +++ b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/HomeComponent.kt @@ -1,24 +1,15 @@ package com.stslex.atten.feature.home.ui.mvi -import com.arkivanov.decompose.ComponentContext +import com.stslex.atten.core.ui.mvi.handler.Handler import com.stslex.atten.core.ui.navigation.Component -import com.stslex.atten.core.ui.navigation.Config +import com.stslex.atten.core.ui.navigation.Router import com.stslex.atten.feature.home.ui.mvi.HomeStore.Action import com.stslex.atten.feature.home.ui.mvi.handlers.HomeComponentImpl -import com.stslex.atten.core.ui.mvi.handler.Handler interface HomeComponent : Component, Handler { companion object { - fun create( - popBack: () -> Unit, - navTo: (config: Config) -> Unit, - componentContext: ComponentContext - ): HomeComponent = HomeComponentImpl( - popBack = popBack, - navTo = navTo, - componentContext = componentContext - ) + fun create(router: Router): HomeComponent = HomeComponentImpl(router) } } \ No newline at end of file diff --git a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/HomeStore.kt b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/HomeStore.kt index 06a9a5f..fef8c81 100644 --- a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/HomeStore.kt +++ b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/HomeStore.kt @@ -46,6 +46,12 @@ interface HomeStore : Store { val snackbar: CommonEvents.Snackbar ) : Event + @Stable + sealed interface List : Event { + + data object ScrollTop : List + } + sealed interface Haptic : Event { data object Click : Haptic diff --git a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/handlers/HomeComponentImpl.kt b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/handlers/HomeComponentImpl.kt index 5fb6953..a361dc5 100644 --- a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/handlers/HomeComponentImpl.kt +++ b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/handlers/HomeComponentImpl.kt @@ -2,20 +2,19 @@ package com.stslex.atten.feature.home.ui.mvi.handlers import com.arkivanov.decompose.ComponentContext import com.stslex.atten.core.ui.navigation.Config +import com.stslex.atten.core.ui.navigation.Router import com.stslex.atten.feature.home.ui.mvi.HomeComponent import com.stslex.atten.feature.home.ui.mvi.HomeHandlerStore import com.stslex.atten.feature.home.ui.mvi.HomeStore.Action internal class HomeComponentImpl( - private val popBack: () -> Unit, - private val navTo: (config: Config) -> Unit, - componentContext: ComponentContext -) : HomeComponent, ComponentContext by componentContext { + private val router: Router, +) : HomeComponent, ComponentContext by router { override fun HomeHandlerStore.invoke(action: Action.Navigation) { when (action) { - is Action.Navigation.Back -> popBack() - is Action.Navigation.NavigateToDetail -> navTo(Config.Detail(action.id)) + is Action.Navigation.Back -> router.popBack() + is Action.Navigation.NavigateToDetail -> router.navTo(Config.Detail(action.id)) } } } \ No newline at end of file diff --git a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/handlers/PagingHandler.kt b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/handlers/PagingHandler.kt index 16926b2..d00c193 100644 --- a/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/handlers/PagingHandler.kt +++ b/feature/home/src/commonMain/kotlin/com.stslex.atten.feature.home/ui/mvi/handlers/PagingHandler.kt @@ -5,6 +5,7 @@ import com.stslex.atten.core.paging.states.PagerLoadState import com.stslex.atten.core.paging.states.pagingMap import com.stslex.atten.core.paging.states.toUi import com.stslex.atten.core.ui.mvi.CommonEvents +import com.stslex.atten.core.ui.mvi.handler.Handler import com.stslex.atten.feature.home.di.HomeScope import com.stslex.atten.feature.home.domain.interactor.HomeScreenInteractor import com.stslex.atten.feature.home.ui.model.toUi @@ -12,7 +13,6 @@ import com.stslex.atten.feature.home.ui.mvi.HomeHandlerStore import com.stslex.atten.feature.home.ui.mvi.HomeStore.Action import com.stslex.atten.feature.home.ui.mvi.HomeStore.Event import com.stslex.atten.feature.home.ui.mvi.toUi -import com.stslex.atten.core.ui.mvi.handler.Handler import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map @@ -37,6 +37,7 @@ internal class PagingHandler( } private fun HomeHandlerStore.actionInit() { + sendEvent(Event.List.ScrollTop) interactor.pagingState .map { pagingState -> pagingState.pagingMap { it.toUi() }